@genome-spy/core 0.55.0 → 0.56.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle/index.es.js +3653 -3545
- package/dist/bundle/index.js +90 -83
- package/dist/schema.json +4 -0
- package/dist/src/gl/glslScaleGenerator.d.ts +1 -0
- package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
- package/dist/src/gl/glslScaleGenerator.js +3 -10
- package/dist/src/gl/includes/common.glsl.js +1 -1
- package/dist/src/gl/webGLHelper.d.ts +8 -0
- package/dist/src/gl/webGLHelper.d.ts.map +1 -1
- package/dist/src/gl/webGLHelper.js +40 -0
- package/dist/src/marks/mark.d.ts +8 -0
- package/dist/src/marks/mark.d.ts.map +1 -1
- package/dist/src/marks/mark.js +86 -19
- package/dist/src/marks/rule.d.ts.map +1 -1
- package/dist/src/marks/rule.js +23 -22
- package/dist/src/selection/selection.d.ts +24 -0
- package/dist/src/selection/selection.d.ts.map +1 -1
- package/dist/src/selection/selection.js +78 -2
- package/dist/src/spec/parameter.d.ts +6 -2
- package/dist/src/types/selectionTypes.d.ts +2 -2
- package/dist/src/view/paramMediator.d.ts.map +1 -1
- package/dist/src/view/paramMediator.js +14 -8
- package/dist/src/view/unitView.d.ts.map +1 -1
- package/dist/src/view/unitView.js +56 -20
- package/package.json +2 -2
package/dist/schema.json
CHANGED
|
@@ -4512,6 +4512,10 @@
|
|
|
4512
4512
|
],
|
|
4513
4513
|
"type": "string"
|
|
4514
4514
|
},
|
|
4515
|
+
"toggle": {
|
|
4516
|
+
"description": "Controls whether data values should be toggled (inserted or removed from a point selection) when clicking with the shift key pressed.\n\n- `true` -- additional values can be selected by shift-clicking.\n- `false` -- only a single value can be selected at a time.\n\n__Default value:__ `true`",
|
|
4517
|
+
"type": "boolean"
|
|
4518
|
+
},
|
|
4515
4519
|
"type": {
|
|
4516
4520
|
"const": "point",
|
|
4517
4521
|
"description": "Determines the default event processing and data query for the selection. Vega-Lite currently supports two selection types:\n\n- `\"point\"` -- to select multiple discrete data values; the first value is selected on `click` and additional values toggled on shift-click.\n- `\"interval\"` -- to select a continuous range of data values on `drag`.",
|
|
@@ -141,6 +141,7 @@ export const SCALE_FUNCTION_PREFIX: "scale_";
|
|
|
141
141
|
export const SCALED_FUNCTION_PREFIX: "getScaled_";
|
|
142
142
|
export const RANGE_TEXTURE_PREFIX: "uRangeTexture_";
|
|
143
143
|
export const PARAM_PREFIX: "uParam_";
|
|
144
|
+
export const SELECTION_CHECKER_PREFIX: "checkSelection_";
|
|
144
145
|
export function getRangeForGlsl(scale: any, channel: Channel): number[];
|
|
145
146
|
export type Channel = import("../spec/channel.js").Channel;
|
|
146
147
|
export type AccessorParts = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glslScaleGenerator.d.ts","sourceRoot":"","sources":["../../../src/gl/glslScaleGenerator.js"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"glslScaleGenerator.d.ts","sourceRoot":"","sources":["../../../src/gl/glslScaleGenerator.js"],"names":[],"mappings":";AAsDA;;;;;GAKG;AACH,kDAJW,OAAO,mBACP,MAAM,GACJ,MAAM,CAIlB;AAED;;;;;;;;;;GAUG;AAEH;;;;;;;GAOG;AACH,mDALW,OAAO,mBACP,MAAM,SACN,MAAM,GAAG,MAAM,EAAE,GAAG,MAAM,GAAG,OAAO,GAClC,aAAa,CA4CzB;AAED;;;;;;;GAOG;AACH,4DAJW,OAAO,mBACP,MAAM,GACJ,aAAa,CAkCzB;AAED;;;;;;GAMG;AACH,0CANW,OAAO,SACP,GAAG,mBACH,MAAM,+BACN,OAAO,EAAE,GACP,aAAa,CA+BzB;AACD;;;;;GAKG;AACH,qDALW,OAAO,SACP,GAAG,mBACH,MAAM,GACJ,aAAa,CAyBzB;AAED;;;;;GAKG;AAEH,2CALW,OAAO,SACP,GAAG,cACH,OAAO,oBAAoB,EAAE,UAAU;;;;;;EAwQjD;AAED;;;;GAIG;AACH,wDAHW,OAAO,aACP,OAAO,qBAAqB,EAAE,QAAQ,EAAE,UA+BlD;AAmED;;GAEG;AACH,qDAFW,OAAO,6BAQjB;AA+CD;;;;GAIG;AACH,iDAHW,OAAO,qBAAqB,EAAE,SAAS,WACvC,OAAO,oBAAoB,EAAE,OAAO;mBAQjB,MAAM;sBAAoB,sBAAsB,GAAG,sBAAsB,GAAG,uBAAuB;;;;;;EAkBhI;AAED;;;;GAIG;AACH,2CAFW,MAAM,WAIhB;AAED;;;;GAIG;AACH,sCAFW,MAAM,EAAE,WAIlB;AAMD;;;GAGG;AACH,sCAHW,MAAM,QACN,MAAM,EAAE,YAYlB;AAED;;;GAGG;AACH,2CAHW,MAAM,QACN,MAAM,EAAE,YAUlB;AAYD;;GAEG;AACH,qDAFW,MAAM,EAAE,YAIlB;AAED;;GAEG;AAEH;;;;;GAKG;AACH,+CAFW,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CAAC,+DA4BtG;AAED;;GAEG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,GAAG,OAAO,oBAAoB,EAAE,OAAO,EAAE,UAIvF;AAwBD;;;;GAIG;AACH,uCAJW,MAAM,EAAE,cACR,MAAM,EAAE,GACN,MAAM,CAgClB;AA90BD,uCAAwC;AACxC,uCAAwC;AACxC,oCAAqC;AACrC,mDAAoD;AACpD,6CAA8C;AAC9C,kDAAmD;AACnD,oDAAqD;AACrD,qCAAsC;AACtC,yDAA0D;AA2xBnD,uCAJI,GAAG,WACH,OAAO,GACL,MAAM,EAAE,CAQF;sBA3xBN,OAAO,oBAAoB,EAAE,OAAO;;aA+BvC,OAAO;kBACP,MAAM;0BACN,MAAM;oBACN,MAAM;oBACN,MAAM;kBACN,MAAM;kBACN,MAAM;eACN,CAAC,CAAC,EAAE,GAAG,KAAK,GAAG;;;;;8BAqfZ,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE;;;;uBAgMhD,CAAC,MAAM,EAAE,OAAO,CAAC;0BA7uBJ,WAAW"}
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "../encoder/encoder.js";
|
|
17
17
|
import { asArray, peek } from "../utils/arrayUtils.js";
|
|
18
18
|
import { InternMap } from "internmap";
|
|
19
|
-
import { isExprRef
|
|
19
|
+
import { isExprRef } from "../view/paramMediator.js";
|
|
20
20
|
import scaleNull from "../utils/scaleNull.js";
|
|
21
21
|
|
|
22
22
|
export const ATTRIBUTE_PREFIX = "attr_";
|
|
@@ -27,6 +27,7 @@ export const SCALE_FUNCTION_PREFIX = "scale_";
|
|
|
27
27
|
export const SCALED_FUNCTION_PREFIX = "getScaled_";
|
|
28
28
|
export const RANGE_TEXTURE_PREFIX = "uRangeTexture_";
|
|
29
29
|
export const PARAM_PREFIX = "uParam_";
|
|
30
|
+
export const SELECTION_CHECKER_PREFIX = "checkSelection_";
|
|
30
31
|
|
|
31
32
|
// https://stackoverflow.com/a/47543127
|
|
32
33
|
const FLT_MAX = 3.402823466e38;
|
|
@@ -523,16 +524,8 @@ export function generateConditionalEncoderGlsl(channel, accessors) {
|
|
|
523
524
|
const accessorFunctionName = makeAccessorFunctionName(channel, i);
|
|
524
525
|
const { param, empty } = accessor.predicate;
|
|
525
526
|
|
|
526
|
-
const paramUniform = PARAM_PREFIX + validateParameterName(param);
|
|
527
|
-
const idAttribute = ATTRIBUTE_PREFIX + "uniqueId";
|
|
528
|
-
|
|
529
|
-
// Hardcoded condition for single point selection ... for now.
|
|
530
527
|
conditions.push(
|
|
531
|
-
param
|
|
532
|
-
? `${idAttribute} == ${paramUniform}${
|
|
533
|
-
empty ? ` || ${paramUniform} == uint(0)` : ""
|
|
534
|
-
}`
|
|
535
|
-
: null
|
|
528
|
+
param ? `${SELECTION_CHECKER_PREFIX}${param}(${!!empty})` : null
|
|
536
529
|
);
|
|
537
530
|
|
|
538
531
|
statements.push(
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "#define PI 3.141593\nuniform View{mediump vec2 uViewOffset;mediump vec2 uViewScale;mediump vec2 uViewportSize;lowp float uDevicePixelRatio;lowp float uViewOpacity;bool uPickingEnabled;};/***Maps a coordinate on the unit scale to a normalized device coordinate.*(0,0)is at the bottom left corner.*/vec4 unitToNdc(vec2 coord){return vec4((coord*uViewScale+uViewOffset)*2.0-1.0,0.0,1.0);}vec4 unitToNdc(float x,float y){return unitToNdc(vec2(x,y));}vec4 pixelsToNdc(vec2 coord){return unitToNdc(coord/uViewportSize);}vec4 pixelsToNdc(float x,float y){return pixelsToNdc(vec2(x,y));}float linearstep(float edge0,float edge1,float x){return clamp((x-edge0)/(edge1-edge0),0.0,1.0);}/***Calculates a gamma for antialiasing opacity based on the color.*/float getGammaForColor(vec3 rgb){return mix(1.25,0.75,smoothstep(0.0,1.0,dot(rgb,vec3(0.299,0.587,0.114))));}/***Specialized linearstep for doing antialiasing*/float distanceToRatio(float d){return clamp(d*uDevicePixelRatio+0.5,0.0,1.0);}vec4 distanceToColor(float d,vec4 fill,vec4 stroke,float halfStrokeWidth){if(halfStrokeWidth>0.0){float sd=abs(d)-halfStrokeWidth;return mix(stroke,d<=0.0 ? fill : vec4(0.0),distanceToRatio(sd));}else{return fill*distanceToRatio(-d);}}";
|
|
1
|
+
const shader = "#define PI 3.141593\nuniform View{mediump vec2 uViewOffset;mediump vec2 uViewScale;mediump vec2 uViewportSize;lowp float uDevicePixelRatio;lowp float uViewOpacity;bool uPickingEnabled;};/***Maps a coordinate on the unit scale to a normalized device coordinate.*(0,0)is at the bottom left corner.*/vec4 unitToNdc(vec2 coord){return vec4((coord*uViewScale+uViewOffset)*2.0-1.0,0.0,1.0);}vec4 unitToNdc(float x,float y){return unitToNdc(vec2(x,y));}vec4 pixelsToNdc(vec2 coord){return unitToNdc(coord/uViewportSize);}vec4 pixelsToNdc(float x,float y){return pixelsToNdc(vec2(x,y));}float linearstep(float edge0,float edge1,float x){return clamp((x-edge0)/(edge1-edge0),0.0,1.0);}bool isEmptyBinarySearchTexture(highp usampler2D s){return textureSize(s,0).x==1&&texelFetch(s,ivec2(0,0),0).r==0u;}bool binarySearchTexture(highp usampler2D s,uint value){int texSize=textureSize(s,0).x;int left=0;int right=texSize-1;while(left<=right){int mid=left+(right-left)/2;uint midValue=texelFetch(s,ivec2(mid,0),0).r;if(midValue==value){return true;}if(midValue<value){left=mid+1;}else{right=mid-1;}}return false;}/***Calculates a gamma for antialiasing opacity based on the color.*/float getGammaForColor(vec3 rgb){return mix(1.25,0.75,smoothstep(0.0,1.0,dot(rgb,vec3(0.299,0.587,0.114))));}/***Specialized linearstep for doing antialiasing*/float distanceToRatio(float d){return clamp(d*uDevicePixelRatio+0.5,0.0,1.0);}vec4 distanceToColor(float d,vec4 fill,vec4 stroke,float halfStrokeWidth){if(halfStrokeWidth>0.0){float sd=abs(d)-halfStrokeWidth;return mix(stroke,d<=0.0 ? fill : vec4(0.0),distanceToRatio(sd));}else{return fill*distanceToRatio(-d);}}";
|
|
2
2
|
export default shader;
|
|
@@ -40,6 +40,10 @@ export default class WebGLHelper {
|
|
|
40
40
|
_shaderCache: Map<string, WebGLShader>;
|
|
41
41
|
/** @type {WeakMap<import("../view/scaleResolution.js").default, WebGLTexture>} */
|
|
42
42
|
rangeTextures: WeakMap<import("../view/scaleResolution.js").default, WebGLTexture>;
|
|
43
|
+
/**
|
|
44
|
+
* @type {WeakMap<import("../types/selectionTypes.js").MultiPointSelection, WebGLTexture>}
|
|
45
|
+
*/
|
|
46
|
+
selectionTextures: WeakMap<import("../types/selectionTypes.js").MultiPointSelection, WebGLTexture>;
|
|
43
47
|
canvas: HTMLCanvasElement;
|
|
44
48
|
gl: WebGL2RenderingContext;
|
|
45
49
|
/** @type {import("twgl.js").AttachmentOptions[]} */
|
|
@@ -100,5 +104,9 @@ export default class WebGLHelper {
|
|
|
100
104
|
* @param {boolean} update Update the texture if it exists already.
|
|
101
105
|
*/
|
|
102
106
|
createRangeTexture(resolution: import("../view/scaleResolution.js").default, update?: boolean): void;
|
|
107
|
+
/**
|
|
108
|
+
* @param {import("../types/selectionTypes.js").MultiPointSelection} selection
|
|
109
|
+
*/
|
|
110
|
+
createSelectionTexture(selection: import("../types/selectionTypes.js").MultiPointSelection, update?: boolean): void;
|
|
103
111
|
}
|
|
104
112
|
//# sourceMappingURL=webGLHelper.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webGLHelper.d.ts","sourceRoot":"","sources":["../../../src/gl/webGLHelper.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"webGLHelper.d.ts","sourceRoot":"","sources":["../../../src/gl/webGLHelper.js"],"names":[],"mappings":"AA2cA;;;;GAIG;AACH,kCAJW,sBAAsB,gBACtB,WAAW,kBACX,WAAW;;;;;;EA8CrB;AAED;;;;;GAKG;AACH,0CALW,qBAAqB,WACrB,KAAK,OAAO,SAAS,EAAE,cAAc,EAAE,KAAK,CAAC,OAC7C,MAAM,EAAE,GAAG,eAAe,YAC1B,YAAY,gBAYtB;AA/eD;IACI;;;;;;;;OAQG;IACH,uBAPW,WAAW,eACX,MAAM;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,eAGrC,MAAM,2BACN,sBAAsB,EA8FhC;IAtFG,wBAA2B;IAC3B;;;MAKO;IAEP,uCAAuC;IACvC,cADW,IAAI,MAAM,EAAE,WAAW,CAAC,CACN;IAE7B,kFAAkF;IAClF,eADW,QAAQ,OAAO,4BAA4B,EAAE,OAAO,EAAE,YAAY,CAAC,CAC5C;IAElC;;OAEG;IACH,mBAFU,QAAQ,OAAO,4BAA4B,EAAE,mBAAmB,EAAE,YAAY,CAAC,CAEnD;IAwCtC,0BAAoB;IACpB,2BAAY;IAGZ,oDAAoD;IACpD,2BADW,OAAO,SAAS,EAAE,iBAAiB,EAAE,CAQ/C;IACD,sDAGC;IAOD,+CAA+C;IAC/C,aADW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CACZ;IAOnC,uBAIC;IAHG;;;MAAmC;IAKvC,mBAEC;IADG,YAAkC;IAGtC;;;;;OAKG;IACH,oBAHW,MAAM,QACN,MAAM,GAAG,MAAM,EAAE,eA2B3B;IAED,iBAcC;IAED,iBAEC;IAED;;;;OAIG;IACH,oCAFW;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;;;MAQ3C;IAED;;OAEG;IACH;;;MAuBC;IAED;;;;OAIG;IACH,oBAHW,MAAM,KACN,MAAM,cAwBhB;IAED,iBAOC;IAED;;;;;;;;;OASG;IACH,+BAHW,OAAO,4BAA4B,EAAE,OAAO,WAC5C,OAAO,QA0GjB;IAED;;OAEG;IACH,kCAFW,OAAO,4BAA4B,EAAE,mBAAmB,0BA+BlE;CACJ"}
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
isDiscreteChannel,
|
|
28
28
|
} from "../encoder/encoder.js";
|
|
29
29
|
import { color } from "d3-color";
|
|
30
|
+
import { isMultiPointSelection } from "../selection/selection.js";
|
|
30
31
|
|
|
31
32
|
export default class WebGLHelper {
|
|
32
33
|
/**
|
|
@@ -58,6 +59,11 @@ export default class WebGLHelper {
|
|
|
58
59
|
/** @type {WeakMap<import("../view/scaleResolution.js").default, WebGLTexture>} */
|
|
59
60
|
this.rangeTextures = new WeakMap();
|
|
60
61
|
|
|
62
|
+
/**
|
|
63
|
+
* @type {WeakMap<import("../types/selectionTypes.js").MultiPointSelection, WebGLTexture>}
|
|
64
|
+
*/
|
|
65
|
+
this.selectionTextures = new WeakMap();
|
|
66
|
+
|
|
61
67
|
// --------------------------------------------------------
|
|
62
68
|
|
|
63
69
|
const canvas = document.createElement("canvas");
|
|
@@ -384,6 +390,40 @@ export default class WebGLHelper {
|
|
|
384
390
|
}
|
|
385
391
|
}
|
|
386
392
|
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* @param {import("../types/selectionTypes.js").MultiPointSelection} selection
|
|
396
|
+
*/
|
|
397
|
+
createSelectionTexture(selection, update = true) {
|
|
398
|
+
if (!isMultiPointSelection(selection)) {
|
|
399
|
+
throw new Error(
|
|
400
|
+
"Not a multi-point selection, cannot create texture"
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const keys = Array.from(selection.data.keys());
|
|
405
|
+
// Zero is a special value for no selection. The minimum texture size is 1.
|
|
406
|
+
const uniqueIds = keys.length > 0 ? keys.sort((a, b) => a - b) : [0];
|
|
407
|
+
|
|
408
|
+
const existingTexture = this.selectionTextures.get(selection);
|
|
409
|
+
|
|
410
|
+
const gl = this.gl;
|
|
411
|
+
const texture = createOrUpdateTexture(
|
|
412
|
+
this.gl,
|
|
413
|
+
{
|
|
414
|
+
level: 0,
|
|
415
|
+
minMag: gl.NEAREST,
|
|
416
|
+
format: gl.RED_INTEGER,
|
|
417
|
+
internalFormat: gl.R32UI,
|
|
418
|
+
height: 1,
|
|
419
|
+
width: uniqueIds.length,
|
|
420
|
+
},
|
|
421
|
+
new Uint32Array(uniqueIds),
|
|
422
|
+
update ? existingTexture : false
|
|
423
|
+
);
|
|
424
|
+
|
|
425
|
+
this.selectionTextures.set(selection, texture);
|
|
426
|
+
}
|
|
387
427
|
}
|
|
388
428
|
|
|
389
429
|
/**
|
package/dist/src/marks/mark.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="external-typings/internmap.js" />
|
|
2
2
|
export const SAMPLE_FACET_UNIFORM: "SAMPLE_FACET_UNIFORM";
|
|
3
3
|
export const SAMPLE_FACET_TEXTURE: "SAMPLE_FACET_TEXTURE";
|
|
4
|
+
export const SELECTION_TEXTURE_PREFIX: "uSelectionTexture_";
|
|
4
5
|
/**
|
|
5
6
|
*
|
|
6
7
|
* @typedef {import("../types/rendering.js").RenderingOptions} RenderingOptions
|
|
@@ -69,6 +70,13 @@ export default class Mark<P extends import("../spec/mark.js").MarkProps = import
|
|
|
69
70
|
* @protected
|
|
70
71
|
*/
|
|
71
72
|
protected markUniformsAltered: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Functions that set textures for multi-selection parameters.
|
|
75
|
+
*
|
|
76
|
+
* @type {(() => void)[]}
|
|
77
|
+
* @private
|
|
78
|
+
*/
|
|
79
|
+
private selectionTextureOps;
|
|
72
80
|
/** @type {RangeMap<any>} keep track of facet locations within the vertex array */
|
|
73
81
|
rangeMap: RangeMap<any>;
|
|
74
82
|
defaultProperties: P;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":"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"}
|
package/dist/src/marks/mark.js
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
generateConditionalEncoderGlsl,
|
|
35
35
|
PARAM_PREFIX,
|
|
36
36
|
ATTRIBUTE_PREFIX,
|
|
37
|
+
SELECTION_CHECKER_PREFIX,
|
|
37
38
|
} from "../gl/glslScaleGenerator.js";
|
|
38
39
|
import GLSL_COMMON from "../gl/includes/common.glsl.js";
|
|
39
40
|
import GLSL_SCALES from "../gl/includes/scales.glsl.js";
|
|
@@ -48,11 +49,16 @@ import { InternMap } from "internmap";
|
|
|
48
49
|
import ViewError from "../view/viewError.js";
|
|
49
50
|
import { isExprRef, validateParameterName } from "../view/paramMediator.js";
|
|
50
51
|
import { UNIQUE_ID_KEY } from "../data/transforms/identifier.js";
|
|
51
|
-
import {
|
|
52
|
+
import {
|
|
53
|
+
isMultiPointSelection,
|
|
54
|
+
isSinglePointSelection,
|
|
55
|
+
} from "../selection/selection.js";
|
|
52
56
|
|
|
53
57
|
export const SAMPLE_FACET_UNIFORM = "SAMPLE_FACET_UNIFORM";
|
|
54
58
|
export const SAMPLE_FACET_TEXTURE = "SAMPLE_FACET_TEXTURE";
|
|
55
59
|
|
|
60
|
+
export const SELECTION_TEXTURE_PREFIX = "uSelectionTexture_";
|
|
61
|
+
|
|
56
62
|
/**
|
|
57
63
|
*
|
|
58
64
|
* @typedef {import("../types/rendering.js").RenderingOptions} RenderingOptions
|
|
@@ -146,6 +152,14 @@ export default class Mark {
|
|
|
146
152
|
*/
|
|
147
153
|
this.markUniformsAltered = true;
|
|
148
154
|
|
|
155
|
+
/**
|
|
156
|
+
* Functions that set textures for multi-selection parameters.
|
|
157
|
+
*
|
|
158
|
+
* @type {(() => void)[]}
|
|
159
|
+
* @private
|
|
160
|
+
*/
|
|
161
|
+
this.selectionTextureOps = [];
|
|
162
|
+
|
|
149
163
|
/** @type {RangeMap<any>} keep track of facet locations within the vertex array */
|
|
150
164
|
this.rangeMap = new RangeMap();
|
|
151
165
|
|
|
@@ -456,7 +470,8 @@ export default class Mark {
|
|
|
456
470
|
|
|
457
471
|
for (const predicate of paramPredicates) {
|
|
458
472
|
const param = predicate.param;
|
|
459
|
-
const
|
|
473
|
+
const paramMediator = this.unitView.paramMediator;
|
|
474
|
+
const selection = paramMediator.getValue(param);
|
|
460
475
|
|
|
461
476
|
// The selection is supposed to have an empty value at this point
|
|
462
477
|
// so that we can figure out the type of the selection.
|
|
@@ -466,6 +481,8 @@ export default class Mark {
|
|
|
466
481
|
);
|
|
467
482
|
}
|
|
468
483
|
|
|
484
|
+
const uniqueIdAttr = ATTRIBUTE_PREFIX + "uniqueId";
|
|
485
|
+
|
|
469
486
|
if (isSinglePointSelection(selection)) {
|
|
470
487
|
// Register a mark uniform for each param. The uniform will have
|
|
471
488
|
// the value of uniqueId of the selected datum.
|
|
@@ -487,13 +504,63 @@ export default class Mark {
|
|
|
487
504
|
) => selection.uniqueId ?? 0
|
|
488
505
|
);
|
|
489
506
|
});
|
|
507
|
+
scaleCode.push(
|
|
508
|
+
`bool ${SELECTION_CHECKER_PREFIX}${param}(bool empty) {\n` +
|
|
509
|
+
` return ${PARAM_PREFIX}${param} == ${uniqueIdAttr} || (empty && ${PARAM_PREFIX}${param} == 0u);\n` +
|
|
510
|
+
`}`
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
} else if (isMultiPointSelection(selection)) {
|
|
514
|
+
// We need a texture for each multi-selection parameter.
|
|
515
|
+
// The texture contains the uniqueIds of the selected data objects sorted
|
|
516
|
+
// in ascending order, which allows for binary search.
|
|
517
|
+
if (!selectionParameterUniforms.has(param)) {
|
|
518
|
+
selectionParameterUniforms.set(param, "multi");
|
|
519
|
+
|
|
520
|
+
const uniformName =
|
|
521
|
+
SELECTION_TEXTURE_PREFIX + validateParameterName(param);
|
|
522
|
+
scaleCode.push(
|
|
523
|
+
`// Selection texture\nuniform highp usampler2D ${uniformName};`
|
|
524
|
+
);
|
|
525
|
+
|
|
526
|
+
const glHelper = this.getContext().glHelper;
|
|
527
|
+
const selectionTextures = glHelper.selectionTextures;
|
|
528
|
+
|
|
529
|
+
this.selectionTextureOps.push(() => {
|
|
530
|
+
// Texture is set in the prepareRender method
|
|
531
|
+
const selection = paramMediator.getValue(param);
|
|
532
|
+
const texture = selectionTextures.get(selection);
|
|
533
|
+
if (!texture) {
|
|
534
|
+
throw new Error(
|
|
535
|
+
`Bug: no selection texture found for "${param}"!`
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
setUniforms(this.programInfo, {
|
|
540
|
+
[uniformName]: texture,
|
|
541
|
+
});
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
const texName = SELECTION_TEXTURE_PREFIX + param;
|
|
545
|
+
scaleCode.push(
|
|
546
|
+
`bool ${SELECTION_CHECKER_PREFIX}${param}(bool empty) {\n` +
|
|
547
|
+
` return binarySearchTexture(${texName}, ${uniqueIdAttr}) || (empty && isEmptyBinarySearchTexture(${texName}));\n` +
|
|
548
|
+
`}`
|
|
549
|
+
);
|
|
550
|
+
|
|
551
|
+
// Create the initial texture
|
|
552
|
+
glHelper.createSelectionTexture(selection);
|
|
553
|
+
|
|
554
|
+
const fn = paramMediator.createExpression(param);
|
|
555
|
+
fn.addListener(() => {
|
|
556
|
+
const selection =
|
|
557
|
+
/** @type {import("../types/selectionTypes.js").MultiPointSelection} */ (
|
|
558
|
+
fn(null)
|
|
559
|
+
);
|
|
560
|
+
glHelper.createSelectionTexture(selection);
|
|
561
|
+
this.getContext().animator.requestRender();
|
|
562
|
+
});
|
|
490
563
|
}
|
|
491
|
-
} else {
|
|
492
|
-
throw new Error(
|
|
493
|
-
`Unsupported selection (${param}) in condition: ${JSON.stringify(
|
|
494
|
-
selection
|
|
495
|
-
)}`
|
|
496
|
-
);
|
|
497
564
|
}
|
|
498
565
|
}
|
|
499
566
|
|
|
@@ -686,18 +753,16 @@ export default class Mark {
|
|
|
686
753
|
}
|
|
687
754
|
|
|
688
755
|
// Generate a function that checks if the datum is subject to any point selection
|
|
689
|
-
const conditions = [...selectionParameterUniforms.
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
`${PARAM_PREFIX}${param} == ${ATTRIBUTE_PREFIX}uniqueId`
|
|
694
|
-
);
|
|
756
|
+
const conditions = [...selectionParameterUniforms.keys()].map(
|
|
757
|
+
(param) => `${SELECTION_CHECKER_PREFIX}${param}(false)`
|
|
758
|
+
);
|
|
759
|
+
|
|
695
760
|
scaleCode.push(
|
|
696
|
-
"bool isPointSelected() {"
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
761
|
+
"bool isPointSelected() {\n" +
|
|
762
|
+
(this.encoders.uniqueId && conditions.length > 0
|
|
763
|
+
? ` return ${conditions.join(" || ")};`
|
|
764
|
+
: " return false;") +
|
|
765
|
+
"\n}"
|
|
701
766
|
);
|
|
702
767
|
|
|
703
768
|
const vertexPrecision = "precision highp float;\nprecision highp int;";
|
|
@@ -1046,6 +1111,8 @@ export default class Mark {
|
|
|
1046
1111
|
}
|
|
1047
1112
|
}
|
|
1048
1113
|
|
|
1114
|
+
ops.push(...this.selectionTextureOps);
|
|
1115
|
+
|
|
1049
1116
|
if (this.getSampleFacetMode() == SAMPLE_FACET_TEXTURE) {
|
|
1050
1117
|
ops.push(() => {
|
|
1051
1118
|
/** @type {WebGLTexture} */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule.d.ts","sourceRoot":"","sources":["../../../src/marks/rule.js"],"names":[],"mappings":"AAcA;;GAEG;AACH;IACI;;OAEG;IACH,sBAFW,OAAO,qBAAqB,EAAE,OAAO,EAoB/C;IAfG,wBAAwB;
|
|
1
|
+
{"version":3,"file":"rule.d.ts","sourceRoot":"","sources":["../../../src/marks/rule.js"],"names":[],"mappings":"AAcA;;GAEG;AACH;IACI;;OAEG;IACH,sBAFW,OAAO,qBAAqB,EAAE,OAAO,EAoB/C;IAfG,wBAAwB;IAyGxB,0BAQE;CA+FT;iBAxOgB,WAAW"}
|
package/dist/src/marks/rule.js
CHANGED
|
@@ -125,21 +125,18 @@ export default class RuleMark extends Mark {
|
|
|
125
125
|
async initializeGraphics() {
|
|
126
126
|
await super.initializeGraphics();
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
});
|
|
141
|
-
this.dashTextureSize = textureData.length; // Not needed with WebGL2
|
|
142
|
-
}
|
|
128
|
+
const gl = this.gl;
|
|
129
|
+
const textureData = createDashTextureArray(this.properties.strokeDash);
|
|
130
|
+
this.dashTexture = createTexture(gl, {
|
|
131
|
+
level: 0,
|
|
132
|
+
mag: gl.NEAREST,
|
|
133
|
+
min: gl.NEAREST,
|
|
134
|
+
internalFormat: gl.R8,
|
|
135
|
+
format: gl.RED,
|
|
136
|
+
src: textureData,
|
|
137
|
+
height: 1,
|
|
138
|
+
});
|
|
139
|
+
this.dashTextureSize = textureData.length; // Not needed with WebGL2
|
|
143
140
|
|
|
144
141
|
this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER, [
|
|
145
142
|
COMMON_SHADER,
|
|
@@ -196,13 +193,13 @@ export default class RuleMark extends Mark {
|
|
|
196
193
|
|
|
197
194
|
ops.push(() => this.bindOrSetMarkUniformBlock());
|
|
198
195
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
)
|
|
205
|
-
|
|
196
|
+
ops.push(() =>
|
|
197
|
+
// Dash texture must be set always. Otherwise the texture unit may have
|
|
198
|
+
// an incompatible texture from an earlier program.
|
|
199
|
+
setUniforms(this.programInfo, {
|
|
200
|
+
uDashTexture: this.dashTexture,
|
|
201
|
+
})
|
|
202
|
+
);
|
|
206
203
|
|
|
207
204
|
ops.push(() =>
|
|
208
205
|
setBuffersAndAttributes(
|
|
@@ -240,6 +237,10 @@ export default class RuleMark extends Mark {
|
|
|
240
237
|
* @param {number[]} pattern
|
|
241
238
|
*/
|
|
242
239
|
function createDashTextureArray(pattern) {
|
|
240
|
+
if (!pattern) {
|
|
241
|
+
return new Uint8Array(0);
|
|
242
|
+
}
|
|
243
|
+
|
|
243
244
|
if (
|
|
244
245
|
pattern.length == 0 ||
|
|
245
246
|
pattern.length % 2 ||
|
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
* @returns {import("../types/selectionTypes.js").SinglePointSelection}
|
|
4
4
|
*/
|
|
5
5
|
export function createSinglePointSelection(datum: import("../data/flowNode.js").Datum): import("../types/selectionTypes.js").SinglePointSelection;
|
|
6
|
+
/**
|
|
7
|
+
* @param {import("../data/flowNode.js").Datum[]} [data]
|
|
8
|
+
* @returns {import("../types/selectionTypes.js").MultiPointSelection}
|
|
9
|
+
*/
|
|
10
|
+
export function createMultiPointSelection(data?: import("../data/flowNode.js").Datum[]): import("../types/selectionTypes.js").MultiPointSelection;
|
|
11
|
+
/**
|
|
12
|
+
* Updates the backing data and returns a new instance of the selection object.
|
|
13
|
+
* A new instance is required to trigger reactivity in parameters.
|
|
14
|
+
*
|
|
15
|
+
* @param {import("../types/selectionTypes.js").MultiPointSelection} selection
|
|
16
|
+
* @param {Partial<Record<"add" | "remove" | "toggle", Iterable<import("../data/flowNode.js").Datum>>>} update
|
|
17
|
+
* @returns {import("../types/selectionTypes.js").MultiPointSelection}
|
|
18
|
+
*/
|
|
19
|
+
export function updateMultiPointSelection(selection: import("../types/selectionTypes.js").MultiPointSelection, { add, remove, toggle }: Partial<Record<"add" | "remove" | "toggle", Iterable<import("../data/flowNode.js").Datum>>>): import("../types/selectionTypes.js").MultiPointSelection;
|
|
6
20
|
/**
|
|
7
21
|
* @param {import("../types/selectionTypes.js").Selection} selection
|
|
8
22
|
* @param {import("../data/flowNode.js").Datum} datum
|
|
@@ -36,4 +50,14 @@ export function isMultiPointSelection(selection: import("../types/selectionTypes
|
|
|
36
50
|
* @returns {selection is import("../types/selectionTypes.js").ProjectedSelection}
|
|
37
51
|
*/
|
|
38
52
|
export function isProjectedSelection(selection: import("../types/selectionTypes.js").Selection): selection is import("../types/selectionTypes.js").ProjectedSelection;
|
|
53
|
+
/**
|
|
54
|
+
* @param {import("../spec/parameter.js").SelectionTypeOrConfig} typeOrConfig
|
|
55
|
+
* @returns {import("../spec/parameter.js").SelectionConfig}
|
|
56
|
+
*/
|
|
57
|
+
export function asSelectionConfig(typeOrConfig: import("../spec/parameter.js").SelectionTypeOrConfig): import("../spec/parameter.js").SelectionConfig;
|
|
58
|
+
/**
|
|
59
|
+
* @param {import("../spec/parameter.js").SelectionConfig} config
|
|
60
|
+
* @returns {config is import("../spec/parameter.js").PointSelectionConfig}
|
|
61
|
+
*/
|
|
62
|
+
export function isPointSelectionConfig(config: import("../spec/parameter.js").SelectionConfig): config is import("../spec/parameter.js").PointSelectionConfig;
|
|
39
63
|
//# sourceMappingURL=selection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/selection/selection.js"],"names":[],"mappings":"AAGA;;;GAGG;AACH,kDAHW,OAAO,qBAAqB,EAAE,KAAK,GACjC,OAAO,4BAA4B,EAAE,oBAAoB,CAQrE;AAED;;;;GAIG;AACH,yCAJW,OAAO,4BAA4B,EAAE,SAAS,SAC9C,OAAO,qBAAqB,EAAE,KAAK,UACnC,OAAO,WAkBjB;AAED;;GAEG;AACH,oDAFW;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAC,UAM1C;AAED;;;GAGG;AACH,4CAHW,OAAO,4BAA4B,EAAE,SAAS,oEAKxD;AAED;;;GAGG;AACH,kDAHW,OAAO,4BAA4B,EAAE,SAAS,0EAKxD;AAED;;;GAGG;AACH,iDAHW,OAAO,4BAA4B,EAAE,SAAS,yEAKxD;AAED;;;GAGG;AACH,gDAHW,OAAO,4BAA4B,EAAE,SAAS,wEAKxD"}
|
|
1
|
+
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/selection/selection.js"],"names":[],"mappings":"AAGA;;;GAGG;AACH,kDAHW,OAAO,qBAAqB,EAAE,KAAK,GACjC,OAAO,4BAA4B,EAAE,oBAAoB,CAQrE;AAED;;;GAGG;AACH,iDAHW,OAAO,qBAAqB,EAAE,KAAK,EAAE,GACnC,OAAO,4BAA4B,EAAE,mBAAmB,CAQpE;AAED;;;;;;;GAOG;AACH,qDAJW,OAAO,4BAA4B,EAAE,mBAAmB,2BACxD,QAAQ,OAAO,KAAK,GAAG,QAAQ,GAAG,QAAQ,EAAE,SAAS,OAAO,qBAAqB,EAAE,KAAK,CAAC,CAAC,CAAC,GACzF,OAAO,4BAA4B,EAAE,mBAAmB,CA2BpE;AAED;;;;GAIG;AACH,yCAJW,OAAO,4BAA4B,EAAE,SAAS,SAC9C,OAAO,qBAAqB,EAAE,KAAK,UACnC,OAAO,WAkBjB;AAED;;GAEG;AACH,oDAFW;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAC,UAM1C;AAED;;;GAGG;AACH,4CAHW,OAAO,4BAA4B,EAAE,SAAS,oEAKxD;AAED;;;GAGG;AACH,kDAHW,OAAO,4BAA4B,EAAE,SAAS,0EAKxD;AAED;;;GAGG;AACH,iDAHW,OAAO,4BAA4B,EAAE,SAAS,yEAKxD;AAED;;;GAGG;AACH,gDAHW,OAAO,4BAA4B,EAAE,SAAS,wEAKxD;AAED;;;GAGG;AACH,gDAHW,OAAO,sBAAsB,EAAE,qBAAqB,GAClD,OAAO,sBAAsB,EAAE,eAAe,CAiB1D;AAED;;;GAGG;AACH,+CAHW,OAAO,sBAAsB,EAAE,eAAe,iEAKxD"}
|
|
@@ -13,6 +13,53 @@ export function createSinglePointSelection(datum) {
|
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @param {import("../data/flowNode.js").Datum[]} [data]
|
|
18
|
+
* @returns {import("../types/selectionTypes.js").MultiPointSelection}
|
|
19
|
+
*/
|
|
20
|
+
export function createMultiPointSelection(data) {
|
|
21
|
+
data ??= [];
|
|
22
|
+
return {
|
|
23
|
+
type: "multi",
|
|
24
|
+
data: new Map(data.map((d) => [d[UNIQUE_ID_KEY], d])),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Updates the backing data and returns a new instance of the selection object.
|
|
30
|
+
* A new instance is required to trigger reactivity in parameters.
|
|
31
|
+
*
|
|
32
|
+
* @param {import("../types/selectionTypes.js").MultiPointSelection} selection
|
|
33
|
+
* @param {Partial<Record<"add" | "remove" | "toggle", Iterable<import("../data/flowNode.js").Datum>>>} update
|
|
34
|
+
* @returns {import("../types/selectionTypes.js").MultiPointSelection}
|
|
35
|
+
*/
|
|
36
|
+
export function updateMultiPointSelection(selection, { add, remove, toggle }) {
|
|
37
|
+
const data = selection.data;
|
|
38
|
+
|
|
39
|
+
for (const d of add ?? []) {
|
|
40
|
+
data.set(d[UNIQUE_ID_KEY], d);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
for (const d of remove ?? []) {
|
|
44
|
+
data.delete(d[UNIQUE_ID_KEY]);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
for (const d of toggle ?? []) {
|
|
48
|
+
const id = d[UNIQUE_ID_KEY];
|
|
49
|
+
if (data.has(id)) {
|
|
50
|
+
data.delete(id);
|
|
51
|
+
} else {
|
|
52
|
+
data.set(id, d);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
type: "multi",
|
|
58
|
+
// Note, the data map is reused for performance reasons.
|
|
59
|
+
data,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
16
63
|
/**
|
|
17
64
|
* @param {import("../types/selectionTypes.js").Selection} selection
|
|
18
65
|
* @param {import("../data/flowNode.js").Datum} datum
|
|
@@ -28,9 +75,9 @@ export function selectionTest(selection, datum, empty = true) {
|
|
|
28
75
|
? empty
|
|
29
76
|
: selection.uniqueId === datum[UNIQUE_ID_KEY];
|
|
30
77
|
} else if (isMultiPointSelection(selection)) {
|
|
31
|
-
return selection.
|
|
78
|
+
return selection.data.size == 0
|
|
32
79
|
? empty
|
|
33
|
-
: selection.
|
|
80
|
+
: selection.data.has(datum[UNIQUE_ID_KEY]); // TODO: Binary search
|
|
34
81
|
} else {
|
|
35
82
|
throw new Error("Not a selection: " + JSON.stringify(selection));
|
|
36
83
|
}
|
|
@@ -76,3 +123,32 @@ export function isMultiPointSelection(selection) {
|
|
|
76
123
|
export function isProjectedSelection(selection) {
|
|
77
124
|
return selection.type === "projected";
|
|
78
125
|
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @param {import("../spec/parameter.js").SelectionTypeOrConfig} typeOrConfig
|
|
129
|
+
* @returns {import("../spec/parameter.js").SelectionConfig}
|
|
130
|
+
*/
|
|
131
|
+
export function asSelectionConfig(typeOrConfig) {
|
|
132
|
+
const config =
|
|
133
|
+
typeof typeOrConfig === "string"
|
|
134
|
+
? { type: typeOrConfig }
|
|
135
|
+
: typeOrConfig;
|
|
136
|
+
|
|
137
|
+
// Set some default
|
|
138
|
+
if (isPointSelectionConfig(config)) {
|
|
139
|
+
config.on ??= "click";
|
|
140
|
+
if (config.on === "click") {
|
|
141
|
+
config.toggle = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return config;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @param {import("../spec/parameter.js").SelectionConfig} config
|
|
150
|
+
* @returns {config is import("../spec/parameter.js").PointSelectionConfig}
|
|
151
|
+
*/
|
|
152
|
+
export function isPointSelectionConfig(config) {
|
|
153
|
+
return config && config.type == "point";
|
|
154
|
+
}
|
|
@@ -196,6 +196,8 @@ export interface BaseSelectionConfig<T extends SelectionType = SelectionType> {
|
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
export interface PointSelectionConfig extends BaseSelectionConfig<"point"> {
|
|
199
|
+
type: "point";
|
|
200
|
+
|
|
199
201
|
/**
|
|
200
202
|
* Controls whether data values should be toggled (inserted or removed from a point selection)
|
|
201
203
|
* when clicking with the shift key pressed.
|
|
@@ -205,8 +207,7 @@ export interface PointSelectionConfig extends BaseSelectionConfig<"point"> {
|
|
|
205
207
|
*
|
|
206
208
|
* __Default value:__ `true`
|
|
207
209
|
*/
|
|
208
|
-
|
|
209
|
-
//toggle?: boolean;
|
|
210
|
+
toggle?: boolean;
|
|
210
211
|
/**
|
|
211
212
|
* A set of fields that uniquely identify a tuple. Used for bookmarking point selections
|
|
212
213
|
* in the GenomeSpy App. Still work in progress.
|
|
@@ -252,4 +253,7 @@ export interface SelectionParameter<T extends SelectionType = SelectionType>
|
|
|
252
253
|
*/
|
|
253
254
|
}
|
|
254
255
|
|
|
256
|
+
export type SelectionConfig = PointSelectionConfig | IntervalSelectionConfig;
|
|
257
|
+
export type SelectionTypeOrConfig = SelectionType | SelectionConfig;
|
|
258
|
+
|
|
255
259
|
export type Parameter = VariableParameter | SelectionParameter;
|
|
@@ -33,8 +33,8 @@ export interface SinglePointSelection extends SelectionBase {
|
|
|
33
33
|
export interface MultiPointSelection extends SelectionBase {
|
|
34
34
|
type: "multi";
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
/** Maps unique id to datum */
|
|
37
|
+
data: Map<number, Datum>;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export type Selection =
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paramMediator.d.ts","sourceRoot":"","sources":["../../../src/view/paramMediator.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"paramMediator.d.ts","sourceRoot":"","sources":["../../../src/view/paramMediator.js"],"names":[],"mappings":"AA0UA;;;GAGG;AACH,6BAHW,GAAG,+CAKb;AAED;;;;;;;GAOG;AACH,oFASC;AAED;;;GAGG;AACH,gJAEC;AAED;;;GAGG;AACH,gMAEC;AAED;;;;;;;;;;GAUG;AACH,mFANW,aAAa,+CAEW,IAAI,KAwCtC;AAED;;;;;;GAMG;AACH,4CAHW,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;GAOG;AACH,2CAHW,GAAG,GACD,eAAe,CAW3B;AA/bD;;;;;;;;GAQG;AACH;IA2BI;;;;;OAKG;IACH,2BALW,MAAM,aAAa,EAU7B;IA7BD;;;OAGG;IACH,0BAHU,IAAI,MAAM,EAAE,IAAI,MAAM,IAAI,CAAC,CAAC,CAGvB;IA2Bf;;;OAGG;IACH,wEAzCqB,GAAG,KAAK,IAAI,CAoGhC;IAED;;;;;;;OAOG;IACH,6BANW,MAAM,6BAEN,OAAO,iBACS,IAAI,CAgC9B;IAED;;;OAGG;IACH,qBAFW,MAAM,WAnIc,GAAG,KAAK,IAAI,CA2I1C;IAED;;;OAGG;IACH,oBAFW,MAAM,OAIhB;IAED;;;OAGG;IACH,qBAFW,MAAM,OAKhB;IAED;;OAEG;IACH,kFAIC;IAED;;;;OAIG;IACH,gCAHW,MAAM,GACJ,aAAa,CAQzB;IAID;;;;OAIG;IACH,uBAFW,MAAM,mBA4EhB;IAED;;;;OAIG;IACH,qBAFW,MAAM,OAKhB;IAED;;;;;OAKG;IACH,sBAFa,OAAO,CAiBnB;;CACJ;;;;;;;;8BAxTY,OAAO,wBAAwB,EAAE,kBAAkB,GAAG;IAAE,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,IAAI,CAAC;IAAC,UAAU,EAAE,MAAM,MAAM,CAAA;CAAC"}
|