(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = global || self, factory(global.vega = {})); }(this, (function (exports) { 'use strict'; function accessor(fn, fields, name) { fn.fields = fields || []; fn.fname = name; return fn; } function accessorName(fn) { return fn == null ? null : fn.fname; } function accessorFields(fn) { return fn == null ? null : fn.fields; } function getter(path) { return path.length === 1 ? get1(path[0]) : getN(path); } const get1 = field => function(obj) { return obj[field]; }; const getN = path => { const len = path.length; return function(obj) { for (let i = 0; i < len; ++i) { obj = obj[path[i]]; } return obj; }; }; function error(message) { throw Error(message); } function splitAccessPath(p) { var path = [], q = null, b = 0, n = p.length, s = '', i, j, c; p = p + ''; function push() { path.push(s + p.substring(i, j)); s = ''; i = j + 1; } for (i=j=0; j i) { push(); } else { i = j + 1; } } else if (c === '[') { if (j > i) push(); b = i = j + 1; } else if (c === ']') { if (!b) error('Access path missing open bracket: ' + p); if (b > 0) push(); b = 0; i = j + 1; } } if (b) error('Access path missing closing bracket: ' + p); if (q) error('Access path missing closing quote: ' + p); if (j > i) { j++; push(); } return path; } function field(field, name, opt) { const path = splitAccessPath(field); field = path.length === 1 ? path[0] : field; return accessor( (opt && opt.get || getter)(path), [field], name || field ); } var empty = []; var id = field('id'); var identity = accessor(function(_) { return _; }, empty, 'identity'); var zero = accessor(function() { return 0; }, empty, 'zero'); var one = accessor(function() { return 1; }, empty, 'one'); var truthy = accessor(function() { return true; }, empty, 'true'); var falsy = accessor(function() { return false; }, empty, 'false'); function log(method, level, input) { var args = [level].concat([].slice.call(input)); console[method].apply(console, args); // eslint-disable-line no-console } var None = 0; var Error$1 = 1; var Warn = 2; var Info = 3; var Debug = 4; function logger(_, method) { var level = _ || None; return { level: function(_) { if (arguments.length) { level = +_; return this; } else { return level; } }, error: function() { if (level >= Error$1) log(method || 'error', 'ERROR', arguments); return this; }, warn: function() { if (level >= Warn) log(method || 'warn', 'WARN', arguments); return this; }, info: function() { if (level >= Info) log(method || 'log', 'INFO', arguments); return this; }, debug: function() { if (level >= Debug) log(method || 'log', 'DEBUG', arguments); return this; } }; } var isArray = Array.isArray; function isObject(_) { return _ === Object(_); } const isLegalKey = key => key !== '__proto__'; function mergeConfig(...configs) { return configs.reduce((out, source) => { for (var key in source) { if (key === 'signals') { // for signals, we merge the signals arrays // source signals take precedence over // existing signals with the same name out.signals = mergeNamed(out.signals, source.signals); } else { // otherwise, merge objects subject to recursion constraints // for legend block, recurse for the layout entry only // for style block, recurse for all properties // otherwise, no recursion: objects overwrite, no merging var r = key === 'legend' ? {layout: 1} : key === 'style' ? true : null; writeConfig(out, key, source[key], r); } } return out; }, {}); } function writeConfig(output, key, value, recurse) { if (!isLegalKey(key)) return; var k, o; if (isObject(value) && !isArray(value)) { o = isObject(output[key]) ? output[key] : (output[key] = {}); for (k in value) { if (recurse && (recurse === true || recurse[k])) { writeConfig(o, k, value[k]); } else if (isLegalKey(k)) { o[k] = value[k]; } } } else { output[key] = value; } } function mergeNamed(a, b) { if (a == null) return b; const map = {}, out = []; function add(_) { if (!map[_.name]) { map[_.name] = 1; out.push(_); } } b.forEach(add); a.forEach(add); return out; } function peek(array) { return array[array.length - 1]; } function toNumber(_) { return _ == null || _ === '' ? null : +_; } function exp(sign) { return function(x) { return sign * Math.exp(x); }; } function log$1(sign) { return function(x) { return Math.log(sign * x); }; } function symlog(c) { return function(x) { return Math.sign(x) * Math.log1p(Math.abs(x / c)); }; } function symexp(c) { return function(x) { return Math.sign(x) * Math.expm1(Math.abs(x)) * c; }; } function pow(exponent) { return function(x) { return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent); }; } function pan(domain, delta, lift, ground) { var d0 = lift(domain[0]), d1 = lift(peek(domain)), dd = (d1 - d0) * delta; return [ ground(d0 - dd), ground(d1 - dd) ]; } function panLinear(domain, delta) { return pan(domain, delta, toNumber, identity); } function panLog(domain, delta) { var sign = Math.sign(domain[0]); return pan(domain, delta, log$1(sign), exp(sign)); } function panPow(domain, delta, exponent) { return pan(domain, delta, pow(exponent), pow(1/exponent)); } function panSymlog(domain, delta, constant) { return pan(domain, delta, symlog(constant), symexp(constant)); } function zoom(domain, anchor, scale, lift, ground) { var d0 = lift(domain[0]), d1 = lift(peek(domain)), da = anchor != null ? lift(anchor) : (d0 + d1) / 2; return [ ground(da + (d0 - da) * scale), ground(da + (d1 - da) * scale) ]; } function zoomLinear(domain, anchor, scale) { return zoom(domain, anchor, scale, toNumber, identity); } function zoomLog(domain, anchor, scale) { var sign = Math.sign(domain[0]); return zoom(domain, anchor, scale, log$1(sign), exp(sign)); } function zoomPow(domain, anchor, scale, exponent) { return zoom(domain, anchor, scale, pow(exponent), pow(1/exponent)); } function zoomSymlog(domain, anchor, scale, constant) { return zoom(domain, anchor, scale, symlog(constant), symexp(constant)); } function quarter(date) { return 1 + ~~(new Date(date).getMonth() / 3); } function utcquarter(date) { return 1 + ~~(new Date(date).getUTCMonth() / 3); } function array(_) { return _ != null ? (isArray(_) ? _ : [_]) : []; } /** * Span-preserving range clamp. If the span of the input range is less * than (max - min) and an endpoint exceeds either the min or max value, * the range is translated such that the span is preserved and one * endpoint touches the boundary of the min/max range. * If the span exceeds (max - min), the range [min, max] is returned. */ function clampRange(range, min, max) { var lo = range[0], hi = range[1], span; if (hi < lo) { span = hi; hi = lo; lo = span; } span = hi - lo; return span >= (max - min) ? [min, max] : [ (lo = Math.min(Math.max(lo, min), max - span)), lo + span ]; } function isFunction(_) { return typeof _ === 'function'; } const DESCENDING = 'descending'; function compare(fields, orders, opt) { opt = opt || {}; orders = array(orders) || []; const ord = [], get = [], fmap = {}, gen = opt.comparator || comparator; array(fields).forEach((f, i) => { if (f == null) return; ord.push(orders[i] === DESCENDING ? -1 : 1); get.push(f = isFunction(f) ? f : field(f, null, opt)); (accessorFields(f) || []).forEach(_ => fmap[_] = 1); }); return get.length === 0 ? null : accessor(gen(get, ord), Object.keys(fmap)); } const compare$1 = (u, v) => (u < v || u == null) && v != null ? -1 : (u > v || v == null) && u != null ? 1 : ((v = v instanceof Date ? +v : v), (u = u instanceof Date ? +u : u)) !== u && v === v ? -1 : v !== v && u === u ? 1 : 0; const comparator = (fields, orders) => fields.length === 1 ? compare1(fields[0], orders[0]) : compareN(fields, orders, fields.length); const compare1 = (field, order) => function(a, b) { return compare$1(field(a), field(b)) * order; }; const compareN = (fields, orders, n) => { orders.push(0); // pad zero for convenient lookup return function(a, b) { let f, c = 0, i = -1; while (c === 0 && ++i < n) { f = fields[i]; c = compare$1(f(a), f(b)); } return c * orders[i]; }; }; function constant(_) { return isFunction(_) ? _ : function() { return _; }; } function debounce(delay, handler) { var tid, evt; function callback() { handler(evt); tid = evt = null; } return function(e) { evt = e; if (tid) clearTimeout(tid); tid = setTimeout(callback, delay); }; } function extend(_) { for (var x, k, i=1, len=arguments.length; i max) max = v; } } } else { // find first valid value for (v = f(array[i]); i < n && (v == null || v !== v); v = f(array[++i])); min = max = v; // visit all other values for (; i max) max = v; } } } } return [min, max]; } function extentIndex(array, f) { var i = -1, n = array.length, a, b, c, u, v; if (f == null) { while (++i < n) { b = array[i]; if (b != null && b >= b) { a = c = b; break; } } if (i === n) return [-1, -1]; u = v = i; while (++i < n) { b = array[i]; if (b != null) { if (a > b) { a = b; u = i; } if (c < b) { c = b; v = i; } } } } else { while (++i < n) { b = f(array[i], i, array); if (b != null && b >= b) { a = c = b; break; } } if (i === n) return [-1, -1]; u = v = i; while (++i < n) { b = f(array[i], i, array); if (b != null) { if (a > b) { a = b; u = i; } if (c < b) { c = b; v = i; } } } } return [u, v]; } const hop = Object.prototype.hasOwnProperty; function has(object, property) { return hop.call(object, property); } var NULL = {}; function fastmap(input) { var obj = {}, map, test; function has$1(key) { return has(obj, key) && obj[key] !== NULL; } map = { size: 0, empty: 0, object: obj, has: has$1, get(key) { return has$1(key) ? obj[key] : undefined; }, set(key, value) { if (!has$1(key)) { ++map.size; if (obj[key] === NULL) --map.empty; } obj[key] = value; return this; }, delete(key) { if (has$1(key)) { --map.size; ++map.empty; obj[key] = NULL; } return this; }, clear() { map.size = map.empty = 0; map.object = obj = {}; }, test(_) { if (arguments.length) { test = _; return map; } else { return test; } }, clean() { var next = {}, size = 0, key, value; for (key in obj) { value = obj[key]; if (value !== NULL && (!test || !test(value))) { next[key] = value; ++size; } } map.size = size; map.empty = 0; map.object = (obj = next); } }; if (input) Object.keys(input).forEach(function(key) { map.set(key, input[key]); }); return map; } function flush(range, value, threshold, left, right, center) { if (!threshold && threshold !== 0) return center; var a = range[0], b = peek(range), t = +threshold, l, r; // swap endpoints if range is reversed if (b < a) { l = a; a = b; b = l; } // compare value to endpoints l = Math.abs(value - a); r = Math.abs(b - value); // adjust if value is within threshold distance of endpoint return l < r && l <= t ? left : r <= t ? right : center; } function inherits(child, parent) { var proto = (child.prototype = Object.create(parent.prototype)); proto.constructor = child; return proto; } /** * Predicate that returns true if the value lies within the span * of the given range. The left and right flags control the use * of inclusive (true) or exclusive (false) comparisons. */ function inrange(value, range, left, right) { var r0 = range[0], r1 = range[range.length-1], t; if (r0 > r1) { t = r0; r0 = r1; r1 = t; } left = left === undefined || left; right = right === undefined || right; return (left ? r0 <= value : r0 < value) && (right ? value <= r1 : value < r1); } function isBoolean(_) { return typeof _ === 'boolean'; } function isDate(_) { return Object.prototype.toString.call(_) === '[object Date]'; } function isNumber(_) { return typeof _ === 'number'; } function isRegExp(_) { return Object.prototype.toString.call(_) === '[object RegExp]'; } function isString(_) { return typeof _ === 'string'; } function key(fields, flat, opt) { if (fields) { fields = flat ? array(fields).map(f => f.replace(/\\(.)/g, '$1')) : array(fields); } const len = fields && fields.length, gen = opt && opt.get || getter, map = f => gen(flat ? [f] : splitAccessPath(f)); let fn; if (!len) { fn = function() { return ''; }; } else if (len === 1) { const get = map(fields[0]); fn = function(_) { return '' + get(_); }; } else { const get = fields.map(map); fn = function(_) { let s = '' + get[0](_), i = 0; while (++i < len) s += '|' + get[i](_); return s; }; } return accessor(fn, fields, 'key'); } function lerp(array, frac) { const lo = array[0], hi = peek(array), f = +frac; return !f ? lo : f === 1 ? hi : lo + f * (hi - lo); } const DEFAULT_MAX_SIZE = 10000; // adapted from https://github.com/dominictarr/hashlru/ (MIT License) function lruCache(maxsize) { maxsize = +maxsize || DEFAULT_MAX_SIZE; let curr, prev, size; const clear = () => { curr = {}; prev = {}; size = 0; }; const update = (key, value) => { if (++size > maxsize) { prev = curr; curr = {}; size = 1; } return (curr[key] = value); }; clear(); return { clear, has: key => has(curr, key) || has(prev, key), get: key => has(curr, key) ? curr[key] : has(prev, key) ? update(key, prev[key]) : undefined, set: (key, value) => has(curr, key) ? (curr[key] = value) : update(key, value) }; } function merge(compare, array0, array1, output) { var n0 = array0.length, n1 = array1.length; if (!n1) return array0; if (!n0) return array1; var merged = output || new array0.constructor(n0 + n1), i0 = 0, i1 = 0, i = 0; for (; i0 0 ? array1[i1++] : array0[i0++]; } for (; i0= 0) s += str; return s; } function pad(str, length, padchar, align) { var c = padchar || ' ', s = str + '', n = length - s.length; return n <= 0 ? s : align === 'left' ? repeat(c, n) + s : align === 'center' ? repeat(c, ~~(n/2)) + s + repeat(c, Math.ceil(n/2)) : s + repeat(c, n); } /** * Return the numerical span of an array: the difference between * the last and first values. */ function span(array) { return array && (peek(array) - array[0]) || 0; } function $(x) { return isArray(x) ? '[' + x.map($) + ']' : isObject(x) || isString(x) ? // Output valid JSON and JS source strings. // See http://timelessrepo.com/json-isnt-a-javascript-subset JSON.stringify(x).replace('\u2028','\\u2028').replace('\u2029', '\\u2029') : x; } function toBoolean(_) { return _ == null || _ === '' ? null : !_ || _ === 'false' || _ === '0' ? false : !!_; } function defaultParser(_) { return isNumber(_) ? _ : isDate(_) ? _ : Date.parse(_); } function toDate(_, parser) { parser = parser || defaultParser; return _ == null || _ === '' ? null : parser(_); } function toString(_) { return _ == null || _ === '' ? null : _ + ''; } function toSet(_) { for (var s={}, i=0, n=_.length; i