vega-selections
Advanced tools
Comparing version 5.4.0 to 5.4.1
@@ -11,19 +11,26 @@ (function (global, factory) { | ||
function descending(a, b) { | ||
return a == null || b == null ? NaN : b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; | ||
} | ||
function bisector(f) { | ||
let delta = f; | ||
let compare1 = f; | ||
let compare2 = f; | ||
let compare1, compare2, delta; | ||
// If an accessor is specified, promote it to a comparator. In this case we | ||
// can test whether the search value is (self-) comparable. We can’t do this | ||
// for a comparator (except for specific, known comparators) because we can’t | ||
// tell if the comparator is symmetric, and an asymmetric comparator can’t be | ||
// used to test whether a single value is comparable. | ||
if (f.length !== 2) { | ||
delta = (d, x) => f(d) - x; | ||
compare1 = ascending; | ||
compare2 = (d, x) => ascending(f(d), x); | ||
delta = (d, x) => f(d) - x; | ||
} else { | ||
compare1 = f === ascending || f === descending ? f : zero; | ||
compare2 = f; | ||
delta = f; | ||
} | ||
function left(a, x, lo = 0, hi = a.length) { | ||
if (lo < hi) { | ||
if (compare1(x, x) !== 0) return hi; | ||
do { | ||
@@ -34,10 +41,7 @@ const mid = lo + hi >>> 1; | ||
} | ||
return lo; | ||
} | ||
function right(a, x, lo = 0, hi = a.length) { | ||
if (lo < hi) { | ||
if (compare1(x, x) !== 0) return hi; | ||
do { | ||
@@ -48,6 +52,4 @@ const mid = lo + hi >>> 1; | ||
} | ||
return lo; | ||
} | ||
function center(a, x, lo = 0, hi = a.length) { | ||
@@ -57,3 +59,2 @@ const i = left(a, x, lo, hi - 1); | ||
} | ||
return { | ||
@@ -65,2 +66,5 @@ left, | ||
} | ||
function zero() { | ||
return 0; | ||
} | ||
@@ -80,17 +84,12 @@ class InternSet extends Set { | ||
} | ||
has(value) { | ||
return super.has(intern_get(this, value)); | ||
} | ||
add(value) { | ||
return super.add(intern_set(this, value)); | ||
} | ||
delete(value) { | ||
return super.delete(intern_delete(this, value)); | ||
} | ||
} | ||
function intern_get({ | ||
@@ -101,6 +100,4 @@ _intern, | ||
const key = _key(value); | ||
return _intern.has(key) ? _intern.get(key) : value; | ||
} | ||
function intern_set({ | ||
@@ -111,10 +108,6 @@ _intern, | ||
const key = _key(value); | ||
if (_intern.has(key)) return _intern.get(key); | ||
_intern.set(key, value); | ||
return value; | ||
} | ||
function intern_delete({ | ||
@@ -125,12 +118,8 @@ _intern, | ||
const key = _key(value); | ||
if (_intern.has(key)) { | ||
value = _intern.get(key); | ||
_intern.delete(key); | ||
} | ||
return value; | ||
} | ||
function keyof(value) { | ||
@@ -143,3 +132,2 @@ return value !== null && typeof value === "object" ? value.valueOf() : value; | ||
others = others.map(set); | ||
out: for (const value of values) { | ||
@@ -153,6 +141,4 @@ for (const other of others) { | ||
} | ||
return values; | ||
} | ||
function set(values) { | ||
@@ -164,3 +150,2 @@ return values instanceof InternSet ? values : new InternSet(values); | ||
const set = new InternSet(); | ||
for (const other of others) { | ||
@@ -171,3 +156,2 @@ for (const o of other) { | ||
} | ||
return set; | ||
@@ -186,16 +170,16 @@ } | ||
const TYPE_ENUM = 'E', | ||
TYPE_RANGE_INC = 'R', | ||
TYPE_RANGE_EXC = 'R-E', | ||
TYPE_RANGE_LE = 'R-LE', | ||
TYPE_RANGE_RE = 'R-RE', | ||
UNIT_INDEX = 'index:unit'; // TODO: revisit date coercion? | ||
TYPE_RANGE_INC = 'R', | ||
TYPE_RANGE_EXC = 'R-E', | ||
TYPE_RANGE_LE = 'R-LE', | ||
TYPE_RANGE_RE = 'R-RE', | ||
UNIT_INDEX = 'index:unit'; | ||
// TODO: revisit date coercion? | ||
function testPoint(datum, entry) { | ||
var fields = entry.fields, | ||
values = entry.values, | ||
n = fields.length, | ||
i = 0, | ||
dval, | ||
f; | ||
values = entry.values, | ||
n = fields.length, | ||
i = 0, | ||
dval, | ||
f; | ||
for (; i < n; ++i) { | ||
@@ -208,3 +192,2 @@ f = fields[i]; | ||
if (vegaUtil.isDate(values[i][0])) values[i] = values[i].map(vegaUtil.toNumber); | ||
if (f.type === TYPE_ENUM) { | ||
@@ -230,5 +213,5 @@ // Enumerated fields can either specify individual values (single/multi selections) | ||
} | ||
return true; | ||
} | ||
/** | ||
@@ -248,58 +231,56 @@ * Tests if a tuple is contained within an interactive selection. | ||
*/ | ||
function selectionTest(name, datum, op) { | ||
var data = this.context.data[name], | ||
entries = data ? data.values.value : [], | ||
unitIdx = data ? data[UNIT_INDEX] && data[UNIT_INDEX].value : undefined, | ||
intersect = op === Intersect, | ||
n = entries.length, | ||
i = 0, | ||
entry, | ||
miss, | ||
count, | ||
unit, | ||
b; | ||
entries = data ? data.values.value : [], | ||
unitIdx = data ? data[UNIT_INDEX] && data[UNIT_INDEX].value : undefined, | ||
intersect = op === Intersect, | ||
n = entries.length, | ||
i = 0, | ||
entry, | ||
miss, | ||
count, | ||
unit, | ||
b; | ||
for (; i < n; ++i) { | ||
entry = entries[i]; | ||
if (unitIdx && intersect) { | ||
// multi selections union within the same unit and intersect across units. | ||
miss = miss || {}; | ||
count = miss[unit = entry.unit] || 0; // if we've already matched this unit, skip. | ||
count = miss[unit = entry.unit] || 0; | ||
// if we've already matched this unit, skip. | ||
if (count === -1) continue; | ||
b = testPoint(datum, entry); | ||
miss[unit] = b ? -1 : ++count; // if we match and there are no other units return true | ||
miss[unit] = b ? -1 : ++count; | ||
// if we match and there are no other units return true | ||
// if we've missed against all tuples in this unit return false | ||
if (b && unitIdx.size === 1) return true; | ||
if (!b && count === unitIdx.get(unit).count) return false; | ||
} else { | ||
b = testPoint(datum, entry); // if we find a miss and we do require intersection return false | ||
b = testPoint(datum, entry); | ||
// if we find a miss and we do require intersection return false | ||
// if we find a match and we don't require intersection return true | ||
if (intersect ^ b) return b; | ||
} | ||
} // if intersecting and we made it here, then we saw no misses | ||
} | ||
// if intersecting and we made it here, then we saw no misses | ||
// if not intersecting, then we saw no matches | ||
// if no active selections, return false | ||
return n && intersect; | ||
} | ||
const bisect = bisector($selectionId), | ||
bisectLeft = bisect.left, | ||
bisectRight = bisect.right; | ||
bisectLeft = bisect.left, | ||
bisectRight = bisect.right; | ||
function selectionIdTest(name, datum, op) { | ||
const data = this.context.data[name], | ||
entries = data ? data.values.value : [], | ||
unitIdx = data ? data[UNIT_INDEX] && data[UNIT_INDEX].value : undefined, | ||
intersect = op === Intersect, | ||
value = $selectionId(datum), | ||
index = bisectLeft(entries, value); | ||
entries = data ? data.values.value : [], | ||
unitIdx = data ? data[UNIT_INDEX] && data[UNIT_INDEX].value : undefined, | ||
intersect = op === Intersect, | ||
value = $selectionId(datum), | ||
index = bisectLeft(entries, value); | ||
if (index === entries.length) return false; | ||
if ($selectionId(entries[index]) !== value) return false; | ||
if (unitIdx && intersect) { | ||
@@ -309,3 +290,2 @@ if (unitIdx.size === 1) return true; | ||
} | ||
return true; | ||
@@ -321,3 +301,2 @@ } | ||
*/ | ||
function selectionTuples(array, base) { | ||
@@ -344,24 +323,24 @@ return array.map(x => vegaUtil.extend(base.fields ? { | ||
*/ | ||
function selectionResolve(name, op, isMulti, vl5) { | ||
var data = this.context.data[name], | ||
entries = data ? data.values.value : [], | ||
resolved = {}, | ||
multiRes = {}, | ||
types = {}, | ||
entry, | ||
fields, | ||
values, | ||
unit, | ||
field, | ||
value, | ||
res, | ||
resUnit, | ||
type, | ||
union, | ||
n = entries.length, | ||
i = 0, | ||
j, | ||
m; // First union all entries within the same unit. | ||
entries = data ? data.values.value : [], | ||
resolved = {}, | ||
multiRes = {}, | ||
types = {}, | ||
entry, | ||
fields, | ||
values, | ||
unit, | ||
field, | ||
value, | ||
res, | ||
resUnit, | ||
type, | ||
union, | ||
n = entries.length, | ||
i = 0, | ||
j, | ||
m; | ||
// First union all entries within the same unit. | ||
for (; i < n; ++i) { | ||
@@ -372,3 +351,2 @@ entry = entries[i]; | ||
values = entry.values; | ||
if (fields && values) { | ||
@@ -383,3 +361,5 @@ // Intentional selection stores | ||
res[unit] = union(resUnit, vegaUtil.array(values[j])); | ||
} // If the same multi-selection is repeated over views and projected over | ||
} | ||
// If the same multi-selection is repeated over views and projected over | ||
// an encoding, it may operate over different fields making it especially | ||
@@ -390,4 +370,2 @@ // tricky to reliably resolve it. At best, we can de-dupe identical entries | ||
// a more human-friendly one. | ||
if (isMulti) { | ||
@@ -404,3 +382,2 @@ resUnit = multiRes[unit] || (multiRes[unit] = []); | ||
resUnit.push(value); | ||
if (isMulti) { | ||
@@ -413,7 +390,6 @@ resUnit = multiRes[unit] || (multiRes[unit] = []); | ||
} | ||
} // Then resolve fields across units as per the op. | ||
} | ||
// Then resolve fields across units as per the op. | ||
op = op || Union; | ||
if (resolved[SelectionId]) { | ||
@@ -426,5 +402,3 @@ resolved[SelectionId] = ops[`${SelectionId}_${op}`](...Object.values(resolved[SelectionId])); | ||
} | ||
entries = Object.keys(multiRes); | ||
if (isMulti && entries.length) { | ||
@@ -440,3 +414,2 @@ const key = vl5 ? VlPoint : VlMulti; | ||
} | ||
return resolved; | ||
@@ -450,6 +423,4 @@ } | ||
var i = 0, | ||
n = value.length; | ||
n = value.length; | ||
for (; i < n; ++i) if (base.indexOf(value[i]) < 0) base.push(value[i]); | ||
return base; | ||
@@ -462,4 +433,3 @@ }, | ||
var lo = vegaUtil.toNumber(value[0]), | ||
hi = vegaUtil.toNumber(value[1]); | ||
hi = vegaUtil.toNumber(value[1]); | ||
if (lo > hi) { | ||
@@ -469,3 +439,2 @@ lo = value[1]; | ||
} | ||
if (!base.length) return [lo, hi]; | ||
@@ -478,4 +447,3 @@ if (base[0] > lo) base[0] = lo; | ||
var lo = vegaUtil.toNumber(value[0]), | ||
hi = vegaUtil.toNumber(value[1]); | ||
hi = vegaUtil.toNumber(value[1]); | ||
if (lo > hi) { | ||
@@ -485,5 +453,3 @@ lo = value[1]; | ||
} | ||
if (!base.length) return [lo, hi]; | ||
if (hi < base[0] || base[1] < lo) { | ||
@@ -495,3 +461,2 @@ return []; | ||
} | ||
return base; | ||
@@ -502,16 +467,17 @@ } | ||
const DataPrefix = ':', | ||
IndexPrefix = '@'; | ||
IndexPrefix = '@'; | ||
function selectionVisitor(name, args, scope, params) { | ||
if (args[0].type !== vegaExpression.Literal) vegaUtil.error('First argument to selection functions must be a string literal.'); | ||
const data = args[0].value, | ||
op = args.length >= 2 && vegaUtil.peek(args).value, | ||
field = 'unit', | ||
indexName = IndexPrefix + field, | ||
dataName = DataPrefix + data; // eslint-disable-next-line no-prototype-builtins | ||
op = args.length >= 2 && vegaUtil.peek(args).value, | ||
field = 'unit', | ||
indexName = IndexPrefix + field, | ||
dataName = DataPrefix + data; | ||
// eslint-disable-next-line no-prototype-builtins | ||
if (op === Intersect && !vegaUtil.hasOwnProperty(params, indexName)) { | ||
params[indexName] = scope.getData(data).indataRef(scope, field); | ||
} // eslint-disable-next-line no-prototype-builtins | ||
} | ||
// eslint-disable-next-line no-prototype-builtins | ||
if (!vegaUtil.hasOwnProperty(params, dataName)) { | ||
@@ -528,4 +494,2 @@ params[dataName] = scope.getData(data).tuplesRef(); | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
})); |
@@ -1,2 +0,2 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vega-util"),require("vega-expression")):"function"==typeof define&&define.amd?define(["exports","vega-util","vega-expression"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).vega={},e.vega,e.vega)}(this,(function(e,t,n){"use strict";function r(e,t){return null==e||null==t?NaN:e<t?-1:e>t?1:e>=t?0:NaN}class i extends Set{constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:u;if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:t}}),null!=e)for(const t of e)this.add(t)}has(e){return super.has(function(e,t){let{_intern:n,_key:r}=e;const i=r(t);return n.has(i)?n.get(i):t}(this,e))}add(e){return super.add(function(e,t){let{_intern:n,_key:r}=e;const i=r(t);return n.has(i)?n.get(i):(n.set(i,t),t)}(this,e))}delete(e){return super.delete(function(e,t){let{_intern:n,_key:r}=e;const i=r(t);n.has(i)&&(t=n.get(i),n.delete(i));return t}(this,e))}}function u(e){return null!==e&&"object"==typeof e?e.valueOf():e}function o(e){return e instanceof i?e:new i(e)}const l="intersect",s="union",f="_vgsid_",a=t.field(f),c="index:unit";function d(e,n){for(var r,i,u=n.fields,o=n.values,l=u.length,s=0;s<l;++s)if((i=u[s]).getter=t.field.getter||t.field(i.field),r=i.getter(e),t.isDate(r)&&(r=t.toNumber(r)),t.isDate(o[s])&&(o[s]=t.toNumber(o[s])),t.isDate(o[s][0])&&(o[s]=o[s].map(t.toNumber)),"E"===i.type){if(t.isArray(o[s])?o[s].indexOf(r)<0:r!==o[s])return!1}else if("R"===i.type){if(!t.inrange(r,o[s]))return!1}else if("R-RE"===i.type){if(!t.inrange(r,o[s],!0,!1))return!1}else if("R-E"===i.type){if(!t.inrange(r,o[s],!1,!1))return!1}else if("R-LE"===i.type&&!t.inrange(r,o[s],!1,!0))return!1;return!0}const g=function(e){let t=e,n=e,i=e;function u(e,t){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,u=arguments.length>3&&void 0!==arguments[3]?arguments[3]:e.length;if(r<u){if(0!==n(t,t))return u;do{const n=r+u>>>1;i(e[n],t)<0?r=n+1:u=n}while(r<u)}return r}return 2!==e.length&&(t=(t,n)=>e(t)-n,n=r,i=(t,n)=>r(e(t),n)),{left:u,center:function(e,n){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:e.length;const o=u(e,n,r,i-1);return o>r&&t(e[o-1],n)>-t(e[o],n)?o-1:o},right:function(e,t){let r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,u=arguments.length>3&&void 0!==arguments[3]?arguments[3]:e.length;if(r<u){if(0!==n(t,t))return u;do{const n=r+u>>>1;i(e[n],t)<=0?r=n+1:u=n}while(r<u)}return r}}}(a),h=g.left,v=g.right;var p={["".concat(f,"_union")]:function(){const e=new i;for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];for(const t of n)for(const n of t)e.add(n);return e},["".concat(f,"_intersect")]:function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];e=new i(e),n=n.map(o);e:for(const t of e)for(const r of n)if(!r.has(t)){e.delete(t);continue e}return e},E_union:function(e,t){if(!e.length)return t;for(var n=0,r=t.length;n<r;++n)e.indexOf(t[n])<0&&e.push(t[n]);return e},E_intersect:function(e,t){return e.length?e.filter((e=>t.indexOf(e)>=0)):t},R_union:function(e,n){var r=t.toNumber(n[0]),i=t.toNumber(n[1]);return r>i&&(r=n[1],i=n[0]),e.length?(e[0]>r&&(e[0]=r),e[1]<i&&(e[1]=i),e):[r,i]},R_intersect:function(e,n){var r=t.toNumber(n[0]),i=t.toNumber(n[1]);return r>i&&(r=n[1],i=n[0]),e.length?i<e[0]||e[1]<r?[]:(e[0]<r&&(e[0]=r),e[1]>i&&(e[1]=i),e):[r,i]}};e.selectionIdTest=function(e,t,n){const r=this.context.data[e],i=r?r.values.value:[],u=r?r[c]&&r[c].value:void 0,o=n===l,s=a(t),f=h(i,s);if(f===i.length)return!1;if(a(i[f])!==s)return!1;if(u&&o){if(1===u.size)return!0;if(v(i,s)-f<u.size)return!1}return!0},e.selectionResolve=function(e,n,r,i){for(var u,o,l,c,d,g,h,v,y,_,m,b,x=this.context.data[e],O=x?x.values.value:[],N={},w={},R={},j=O.length,k=0;k<j;++k)if(c=(u=O[k]).unit,o=u.fields,l=u.values,o&&l){for(m=0,b=o.length;m<b;++m)d=o[m],v=(h=N[d.field]||(N[d.field]={}))[c]||(h[c]=[]),R[d.field]=y=d.type.charAt(0),_=p["".concat(y,"_union")],h[c]=_(v,t.array(l[m]));r&&(v=w[c]||(w[c]=[])).push(t.array(l).reduce(((e,t,n)=>(e[o[n].field]=t,e)),{}))}else d=f,g=a(u),(v=(h=N[d]||(N[d]={}))[c]||(h[c]=[])).push(g),r&&(v=w[c]||(w[c]=[])).push({[f]:g});if(n=n||s,N._vgsid_?N._vgsid_=p["".concat(f,"_").concat(n)](...Object.values(N._vgsid_)):Object.keys(N).forEach((e=>{N[e]=Object.keys(N[e]).map((t=>N[e][t])).reduce(((t,r)=>void 0===t?r:p["".concat(R[e],"_").concat(n)](t,r)))})),O=Object.keys(w),r&&O.length){N[i?"vlPoint":"vlMulti"]=n===s?{or:O.reduce(((e,t)=>(e.push(...w[t]),e)),[])}:{and:O.map((e=>({or:w[e]})))}}return N},e.selectionTest=function(e,t,n){for(var r,i,u,o,s,f=this.context.data[e],a=f?f.values.value:[],g=f?f[c]&&f[c].value:void 0,h=n===l,v=a.length,p=0;p<v;++p)if(r=a[p],g&&h){if(-1===(u=(i=i||{})[o=r.unit]||0))continue;if(s=d(t,r),i[o]=s?-1:++u,s&&1===g.size)return!0;if(!s&&u===g.get(o).count)return!1}else if(h^(s=d(t,r)))return s;return v&&h},e.selectionTuples=function(e,n){return e.map((e=>t.extend(n.fields?{values:n.fields.map((n=>(n.getter||(n.getter=t.field(n.field)))(e.datum)))}:{[f]:a(e.datum)},n)))},e.selectionVisitor=function(e,r,i,u){r[0].type!==n.Literal&&t.error("First argument to selection functions must be a string literal.");const o=r[0].value,s="unit",f="@unit",a=":"+o;(r.length>=2&&t.peek(r).value)!==l||t.hasOwnProperty(u,f)||(u["@unit"]=i.getData(o).indataRef(i,s)),t.hasOwnProperty(u,a)||(u[a]=i.getData(o).tuplesRef())},Object.defineProperty(e,"__esModule",{value:!0})})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vega-util"),require("vega-expression")):"function"==typeof define&&define.amd?define(["exports","vega-util","vega-expression"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).vega={},e.vega,e.vega)}(this,(function(e,t,n){"use strict";function r(e,t){return null==e||null==t?NaN:e<t?-1:e>t?1:e>=t?0:NaN}function i(e,t){return null==e||null==t?NaN:t<e?-1:t>e?1:t>=e?0:NaN}function u(){return 0}class o extends Set{constructor(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:l;if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:t}}),null!=e)for(const t of e)this.add(t)}has(e){return super.has(function(e,t){let{_intern:n,_key:r}=e;const i=r(t);return n.has(i)?n.get(i):t}(this,e))}add(e){return super.add(function(e,t){let{_intern:n,_key:r}=e;const i=r(t);return n.has(i)?n.get(i):(n.set(i,t),t)}(this,e))}delete(e){return super.delete(function(e,t){let{_intern:n,_key:r}=e;const i=r(t);n.has(i)&&(t=n.get(i),n.delete(i));return t}(this,e))}}function l(e){return null!==e&&"object"==typeof e?e.valueOf():e}function f(e){return e instanceof o?e:new o(e)}const s="intersect",a="union",c="vlMulti",d="vlPoint",h="or",g="and",v="_vgsid_",p=t.field(v),y="E",m="R",_="R-E",b="R-LE",N="R-RE",x="index:unit";function O(e,n){for(var r,i,u=n.fields,o=n.values,l=u.length,f=0;f<l;++f)if((i=u[f]).getter=t.field.getter||t.field(i.field),r=i.getter(e),t.isDate(r)&&(r=t.toNumber(r)),t.isDate(o[f])&&(o[f]=t.toNumber(o[f])),t.isDate(o[f][0])&&(o[f]=o[f].map(t.toNumber)),i.type===y){if(t.isArray(o[f])?o[f].indexOf(r)<0:r!==o[f])return!1}else if(i.type===m){if(!t.inrange(r,o[f]))return!1}else if(i.type===N){if(!t.inrange(r,o[f],!0,!1))return!1}else if(i.type===_){if(!t.inrange(r,o[f],!1,!1))return!1}else if(i.type===b&&!t.inrange(r,o[f],!1,!0))return!1;return!0}const w=function(e){let t,n,o;function l(e,r){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,u=arguments.length>3&&void 0!==arguments[3]?arguments[3]:e.length;if(i<u){if(0!==t(r,r))return u;do{const t=i+u>>>1;n(e[t],r)<0?i=t+1:u=t}while(i<u)}return i}return 2!==e.length?(t=r,n=(t,n)=>r(e(t),n),o=(t,n)=>e(t)-n):(t=e===r||e===i?e:u,n=e,o=e),{left:l,center:function(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;const r=l(e,t,n,(arguments.length>3&&void 0!==arguments[3]?arguments[3]:e.length)-1);return r>n&&o(e[r-1],t)>-o(e[r],t)?r-1:r},right:function(e,r){let i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,u=arguments.length>3&&void 0!==arguments[3]?arguments[3]:e.length;if(i<u){if(0!==t(r,r))return u;do{const t=i+u>>>1;n(e[t],r)<=0?i=t+1:u=t}while(i<u)}return i}}}(p),R=w.left,k=w.right;var j={[`${v}_union`]:function(){const e=new o;for(var t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];for(const t of n)for(const n of t)e.add(n);return e},[`${v}_intersect`]:function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];e=new o(e),n=n.map(f);e:for(const t of e)for(const r of n)if(!r.has(t)){e.delete(t);continue e}return e},E_union:function(e,t){if(!e.length)return t;for(var n=0,r=t.length;n<r;++n)e.indexOf(t[n])<0&&e.push(t[n]);return e},E_intersect:function(e,t){return e.length?e.filter((e=>t.indexOf(e)>=0)):t},R_union:function(e,n){var r=t.toNumber(n[0]),i=t.toNumber(n[1]);return r>i&&(r=n[1],i=n[0]),e.length?(e[0]>r&&(e[0]=r),e[1]<i&&(e[1]=i),e):[r,i]},R_intersect:function(e,n){var r=t.toNumber(n[0]),i=t.toNumber(n[1]);return r>i&&(r=n[1],i=n[0]),e.length?i<e[0]||e[1]<r?[]:(e[0]<r&&(e[0]=r),e[1]>i&&(e[1]=i),e):[r,i]}};const E=":",$="@";e.selectionIdTest=function(e,t,n){const r=this.context.data[e],i=r?r.values.value:[],u=r?r[x]&&r[x].value:void 0,o=n===s,l=p(t),f=R(i,l);if(f===i.length)return!1;if(p(i[f])!==l)return!1;if(u&&o){if(1===u.size)return!0;if(k(i,l)-f<u.size)return!1}return!0},e.selectionResolve=function(e,n,r,i){for(var u,o,l,f,s,y,m,_,b,N,x,O,w=this.context.data[e],R=w?w.values.value:[],k={},E={},$={},D=R.length,T=0;T<D;++T)if(f=(u=R[T]).unit,o=u.fields,l=u.values,o&&l){for(x=0,O=o.length;x<O;++x)s=o[x],_=(m=k[s.field]||(k[s.field]={}))[f]||(m[f]=[]),$[s.field]=b=s.type.charAt(0),N=j[`${b}_union`],m[f]=N(_,t.array(l[x]));r&&(_=E[f]||(E[f]=[])).push(t.array(l).reduce(((e,t,n)=>(e[o[n].field]=t,e)),{}))}else s=v,y=p(u),(_=(m=k[s]||(k[s]={}))[f]||(m[f]=[])).push(y),r&&(_=E[f]||(E[f]=[])).push({[v]:y});if(n=n||a,k[v]?k[v]=j[`${v}_${n}`](...Object.values(k[v])):Object.keys(k).forEach((e=>{k[e]=Object.keys(k[e]).map((t=>k[e][t])).reduce(((t,r)=>void 0===t?r:j[`${$[e]}_${n}`](t,r)))})),R=Object.keys(E),r&&R.length){k[i?d:c]=n===a?{[h]:R.reduce(((e,t)=>(e.push(...E[t]),e)),[])}:{[g]:R.map((e=>({[h]:E[e]})))}}return k},e.selectionTest=function(e,t,n){for(var r,i,u,o,l,f=this.context.data[e],a=f?f.values.value:[],c=f?f[x]&&f[x].value:void 0,d=n===s,h=a.length,g=0;g<h;++g)if(r=a[g],c&&d){if(-1===(u=(i=i||{})[o=r.unit]||0))continue;if(l=O(t,r),i[o]=l?-1:++u,l&&1===c.size)return!0;if(!l&&u===c.get(o).count)return!1}else if(d^(l=O(t,r)))return l;return h&&d},e.selectionTuples=function(e,n){return e.map((e=>t.extend(n.fields?{values:n.fields.map((n=>(n.getter||(n.getter=t.field(n.field)))(e.datum)))}:{[v]:p(e.datum)},n)))},e.selectionVisitor=function(e,r,i,u){r[0].type!==n.Literal&&t.error("First argument to selection functions must be a string literal.");const o=r[0].value,l=r.length>=2&&t.peek(r).value,f="unit",a=$+f,c=E+o;l!==s||t.hasOwnProperty(u,a)||(u[a]=i.getData(o).indataRef(i,f)),t.hasOwnProperty(u,c)||(u[c]=i.getData(o).tuplesRef())}})); | ||
//# sourceMappingURL=vega-selection.min.js.map |
@@ -15,16 +15,16 @@ import { bisector, union, intersection } from 'd3-array'; | ||
const TYPE_ENUM = 'E', | ||
TYPE_RANGE_INC = 'R', | ||
TYPE_RANGE_EXC = 'R-E', | ||
TYPE_RANGE_LE = 'R-LE', | ||
TYPE_RANGE_RE = 'R-RE', | ||
UNIT_INDEX = 'index:unit'; // TODO: revisit date coercion? | ||
TYPE_RANGE_INC = 'R', | ||
TYPE_RANGE_EXC = 'R-E', | ||
TYPE_RANGE_LE = 'R-LE', | ||
TYPE_RANGE_RE = 'R-RE', | ||
UNIT_INDEX = 'index:unit'; | ||
// TODO: revisit date coercion? | ||
function testPoint(datum, entry) { | ||
var fields = entry.fields, | ||
values = entry.values, | ||
n = fields.length, | ||
i = 0, | ||
dval, | ||
f; | ||
values = entry.values, | ||
n = fields.length, | ||
i = 0, | ||
dval, | ||
f; | ||
for (; i < n; ++i) { | ||
@@ -37,3 +37,2 @@ f = fields[i]; | ||
if (isDate(values[i][0])) values[i] = values[i].map(toNumber); | ||
if (f.type === TYPE_ENUM) { | ||
@@ -59,5 +58,5 @@ // Enumerated fields can either specify individual values (single/multi selections) | ||
} | ||
return true; | ||
} | ||
/** | ||
@@ -77,58 +76,56 @@ * Tests if a tuple is contained within an interactive selection. | ||
*/ | ||
function selectionTest(name, datum, op) { | ||
var data = this.context.data[name], | ||
entries = data ? data.values.value : [], | ||
unitIdx = data ? data[UNIT_INDEX] && data[UNIT_INDEX].value : undefined, | ||
intersect = op === Intersect, | ||
n = entries.length, | ||
i = 0, | ||
entry, | ||
miss, | ||
count, | ||
unit, | ||
b; | ||
entries = data ? data.values.value : [], | ||
unitIdx = data ? data[UNIT_INDEX] && data[UNIT_INDEX].value : undefined, | ||
intersect = op === Intersect, | ||
n = entries.length, | ||
i = 0, | ||
entry, | ||
miss, | ||
count, | ||
unit, | ||
b; | ||
for (; i < n; ++i) { | ||
entry = entries[i]; | ||
if (unitIdx && intersect) { | ||
// multi selections union within the same unit and intersect across units. | ||
miss = miss || {}; | ||
count = miss[unit = entry.unit] || 0; // if we've already matched this unit, skip. | ||
count = miss[unit = entry.unit] || 0; | ||
// if we've already matched this unit, skip. | ||
if (count === -1) continue; | ||
b = testPoint(datum, entry); | ||
miss[unit] = b ? -1 : ++count; // if we match and there are no other units return true | ||
miss[unit] = b ? -1 : ++count; | ||
// if we match and there are no other units return true | ||
// if we've missed against all tuples in this unit return false | ||
if (b && unitIdx.size === 1) return true; | ||
if (!b && count === unitIdx.get(unit).count) return false; | ||
} else { | ||
b = testPoint(datum, entry); // if we find a miss and we do require intersection return false | ||
b = testPoint(datum, entry); | ||
// if we find a miss and we do require intersection return false | ||
// if we find a match and we don't require intersection return true | ||
if (intersect ^ b) return b; | ||
} | ||
} // if intersecting and we made it here, then we saw no misses | ||
} | ||
// if intersecting and we made it here, then we saw no misses | ||
// if not intersecting, then we saw no matches | ||
// if no active selections, return false | ||
return n && intersect; | ||
} | ||
const bisect = bisector($selectionId), | ||
bisectLeft = bisect.left, | ||
bisectRight = bisect.right; | ||
bisectLeft = bisect.left, | ||
bisectRight = bisect.right; | ||
function selectionIdTest(name, datum, op) { | ||
const data = this.context.data[name], | ||
entries = data ? data.values.value : [], | ||
unitIdx = data ? data[UNIT_INDEX] && data[UNIT_INDEX].value : undefined, | ||
intersect = op === Intersect, | ||
value = $selectionId(datum), | ||
index = bisectLeft(entries, value); | ||
entries = data ? data.values.value : [], | ||
unitIdx = data ? data[UNIT_INDEX] && data[UNIT_INDEX].value : undefined, | ||
intersect = op === Intersect, | ||
value = $selectionId(datum), | ||
index = bisectLeft(entries, value); | ||
if (index === entries.length) return false; | ||
if ($selectionId(entries[index]) !== value) return false; | ||
if (unitIdx && intersect) { | ||
@@ -138,3 +135,2 @@ if (unitIdx.size === 1) return true; | ||
} | ||
return true; | ||
@@ -150,3 +146,2 @@ } | ||
*/ | ||
function selectionTuples(array, base) { | ||
@@ -173,24 +168,24 @@ return array.map(x => extend(base.fields ? { | ||
*/ | ||
function selectionResolve(name, op, isMulti, vl5) { | ||
var data = this.context.data[name], | ||
entries = data ? data.values.value : [], | ||
resolved = {}, | ||
multiRes = {}, | ||
types = {}, | ||
entry, | ||
fields, | ||
values, | ||
unit, | ||
field, | ||
value, | ||
res, | ||
resUnit, | ||
type, | ||
union, | ||
n = entries.length, | ||
i = 0, | ||
j, | ||
m; // First union all entries within the same unit. | ||
entries = data ? data.values.value : [], | ||
resolved = {}, | ||
multiRes = {}, | ||
types = {}, | ||
entry, | ||
fields, | ||
values, | ||
unit, | ||
field, | ||
value, | ||
res, | ||
resUnit, | ||
type, | ||
union, | ||
n = entries.length, | ||
i = 0, | ||
j, | ||
m; | ||
// First union all entries within the same unit. | ||
for (; i < n; ++i) { | ||
@@ -201,3 +196,2 @@ entry = entries[i]; | ||
values = entry.values; | ||
if (fields && values) { | ||
@@ -210,5 +204,7 @@ // Intentional selection stores | ||
types[field.field] = type = field.type.charAt(0); | ||
union = ops["".concat(type, "_union")]; | ||
union = ops[`${type}_union`]; | ||
res[unit] = union(resUnit, array(values[j])); | ||
} // If the same multi-selection is repeated over views and projected over | ||
} | ||
// If the same multi-selection is repeated over views and projected over | ||
// an encoding, it may operate over different fields making it especially | ||
@@ -219,4 +215,2 @@ // tricky to reliably resolve it. At best, we can de-dupe identical entries | ||
// a more human-friendly one. | ||
if (isMulti) { | ||
@@ -233,3 +227,2 @@ resUnit = multiRes[unit] || (multiRes[unit] = []); | ||
resUnit.push(value); | ||
if (isMulti) { | ||
@@ -242,17 +235,14 @@ resUnit = multiRes[unit] || (multiRes[unit] = []); | ||
} | ||
} // Then resolve fields across units as per the op. | ||
} | ||
// Then resolve fields across units as per the op. | ||
op = op || Union; | ||
if (resolved[SelectionId]) { | ||
resolved[SelectionId] = ops["".concat(SelectionId, "_").concat(op)](...Object.values(resolved[SelectionId])); | ||
resolved[SelectionId] = ops[`${SelectionId}_${op}`](...Object.values(resolved[SelectionId])); | ||
} else { | ||
Object.keys(resolved).forEach(field => { | ||
resolved[field] = Object.keys(resolved[field]).map(unit => resolved[field][unit]).reduce((acc, curr) => acc === undefined ? curr : ops["".concat(types[field], "_").concat(op)](acc, curr)); | ||
resolved[field] = Object.keys(resolved[field]).map(unit => resolved[field][unit]).reduce((acc, curr) => acc === undefined ? curr : ops[`${types[field]}_${op}`](acc, curr)); | ||
}); | ||
} | ||
entries = Object.keys(multiRes); | ||
if (isMulti && entries.length) { | ||
@@ -268,15 +258,12 @@ const key = vl5 ? VlPoint : VlMulti; | ||
} | ||
return resolved; | ||
} | ||
var ops = { | ||
["".concat(SelectionId, "_union")]: union, | ||
["".concat(SelectionId, "_intersect")]: intersection, | ||
[`${SelectionId}_union`]: union, | ||
[`${SelectionId}_intersect`]: intersection, | ||
E_union: function (base, value) { | ||
if (!base.length) return value; | ||
var i = 0, | ||
n = value.length; | ||
n = value.length; | ||
for (; i < n; ++i) if (base.indexOf(value[i]) < 0) base.push(value[i]); | ||
return base; | ||
@@ -289,4 +276,3 @@ }, | ||
var lo = toNumber(value[0]), | ||
hi = toNumber(value[1]); | ||
hi = toNumber(value[1]); | ||
if (lo > hi) { | ||
@@ -296,3 +282,2 @@ lo = value[1]; | ||
} | ||
if (!base.length) return [lo, hi]; | ||
@@ -305,4 +290,3 @@ if (base[0] > lo) base[0] = lo; | ||
var lo = toNumber(value[0]), | ||
hi = toNumber(value[1]); | ||
hi = toNumber(value[1]); | ||
if (lo > hi) { | ||
@@ -312,5 +296,3 @@ lo = value[1]; | ||
} | ||
if (!base.length) return [lo, hi]; | ||
if (hi < base[0] || base[1] < lo) { | ||
@@ -322,3 +304,2 @@ return []; | ||
} | ||
return base; | ||
@@ -329,16 +310,17 @@ } | ||
const DataPrefix = ':', | ||
IndexPrefix = '@'; | ||
IndexPrefix = '@'; | ||
function selectionVisitor(name, args, scope, params) { | ||
if (args[0].type !== Literal) error('First argument to selection functions must be a string literal.'); | ||
const data = args[0].value, | ||
op = args.length >= 2 && peek(args).value, | ||
field = 'unit', | ||
indexName = IndexPrefix + field, | ||
dataName = DataPrefix + data; // eslint-disable-next-line no-prototype-builtins | ||
op = args.length >= 2 && peek(args).value, | ||
field = 'unit', | ||
indexName = IndexPrefix + field, | ||
dataName = DataPrefix + data; | ||
// eslint-disable-next-line no-prototype-builtins | ||
if (op === Intersect && !hasOwnProperty(params, indexName)) { | ||
params[indexName] = scope.getData(data).indataRef(scope, field); | ||
} // eslint-disable-next-line no-prototype-builtins | ||
} | ||
// eslint-disable-next-line no-prototype-builtins | ||
if (!hasOwnProperty(params, dataName)) { | ||
@@ -345,0 +327,0 @@ params[dataName] = scope.getData(data).tuplesRef(); |
{ | ||
"name": "vega-selections", | ||
"version": "5.4.0", | ||
"version": "5.4.1", | ||
"description": "Vega expression functions for Vega-Lite selections.", | ||
@@ -18,3 +18,3 @@ "keywords": [ | ||
"prebuild": "rimraf build", | ||
"build": "rollup -c", | ||
"build": "rollup -c rollup.config.mjs", | ||
"pretest": "yarn build --config-test", | ||
@@ -25,7 +25,7 @@ "test": "tape 'test/**/*-test.js'", | ||
"dependencies": { | ||
"d3-array": "3.1.1", | ||
"vega-expression": "^5.0.0", | ||
"vega-util": "^1.16.0" | ||
"d3-array": "3.2.2", | ||
"vega-expression": "^5.0.1", | ||
"vega-util": "^1.17.1" | ||
}, | ||
"gitHead": "9a3faca4395cade9ecdfde90af98f1c53e9916b2" | ||
"gitHead": "fb1092f6b931d450f9c210b67ae4752bd3dd461b" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
72032
1032
+ Addedd3-array@3.2.2(transitive)
- Removedd3-array@3.1.1(transitive)
Updatedd3-array@3.2.2
Updatedvega-expression@^5.0.1
Updatedvega-util@^1.17.1