@genome-spy/core 0.44.0 → 0.45.0
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 +6123 -5482
- package/dist/bundle/index.js +211 -148
- package/dist/schema.json +329 -79
- package/dist/src/data/collector.d.ts.map +1 -1
- package/dist/src/data/collector.js +4 -2
- package/dist/src/data/flowOptimizer.test.js +12 -3
- package/dist/src/data/sources/dataUtils.d.ts.map +1 -1
- package/dist/src/data/sources/dataUtils.js +3 -1
- package/dist/src/data/sources/lazy/bigBedSource.d.ts +1 -1
- package/dist/src/data/sources/lazy/bigBedSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/bigBedSource.js +52 -20
- package/dist/src/data/sources/lazy/bigWigSource.d.ts +0 -1
- package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/bigWigSource.js +30 -4
- package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/singleAxisLazySource.js +0 -2
- package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts +6 -2
- package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +38 -20
- package/dist/src/data/sources/sequenceSource.d.ts.map +1 -1
- package/dist/src/data/sources/sequenceSource.js +14 -5
- package/dist/src/data/sources/sequenceSource.test.js +23 -5
- package/dist/src/data/sources/urlSource.d.ts.map +1 -1
- package/dist/src/data/sources/urlSource.js +15 -2
- package/dist/src/data/transforms/aggregate.d.ts.map +1 -1
- package/dist/src/data/transforms/aggregate.js +5 -2
- package/dist/src/encoder/encoder.d.ts +2 -4
- package/dist/src/encoder/encoder.d.ts.map +1 -1
- package/dist/src/encoder/encoder.js +8 -8
- package/dist/src/encoder/encoder.test.js +3 -0
- package/dist/src/genomeSpy.d.ts +7 -5
- package/dist/src/genomeSpy.d.ts.map +1 -1
- package/dist/src/genomeSpy.js +109 -132
- package/dist/src/gl/glslScaleGenerator.js +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/marks/mark.d.ts +8 -5
- package/dist/src/marks/mark.d.ts.map +1 -1
- package/dist/src/marks/mark.js +56 -12
- package/dist/src/marks/point.common.glsl.js +1 -1
- package/dist/src/marks/point.d.ts +1 -4
- package/dist/src/marks/point.d.ts.map +1 -1
- package/dist/src/marks/point.js +31 -23
- package/dist/src/marks/point.vertex.glsl.js +1 -1
- package/dist/src/marks/text.d.ts.map +1 -1
- package/dist/src/marks/text.js +15 -7
- package/dist/src/spec/data.d.ts +11 -10
- package/dist/src/spec/mark.d.ts +11 -21
- package/dist/src/spec/parameter.d.ts +11 -7
- package/dist/src/spec/root.d.ts +0 -8
- package/dist/src/spec/title.d.ts +5 -4
- package/dist/src/spec/view.d.ts +19 -4
- package/dist/src/styles/genome-spy.css.d.ts +1 -1
- package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
- package/dist/src/styles/genome-spy.css.js +52 -5
- package/dist/src/styles/genome-spy.scss +63 -10
- package/dist/src/styles/update.sh +6 -0
- package/dist/src/tooltip/dataTooltipHandler.js +1 -1
- package/dist/src/tooltip/refseqGeneTooltipHandler.js +1 -1
- package/dist/src/tooltip/tooltipHandler.d.ts +1 -1
- package/dist/src/tooltip/tooltipHandler.d.ts.map +1 -1
- package/dist/src/tooltip/tooltipHandler.ts +1 -1
- package/dist/src/types/embedApi.d.ts +6 -0
- package/dist/src/types/viewContext.d.ts +2 -3
- package/dist/src/utils/debounce.d.ts +2 -2
- package/dist/src/utils/debounce.d.ts.map +1 -1
- package/dist/src/utils/debounce.js +5 -2
- package/dist/src/utils/expression.d.ts +2 -2
- package/dist/src/utils/expression.d.ts.map +1 -1
- package/dist/src/utils/expression.js +1 -1
- package/dist/src/utils/formatObject.d.ts +2 -2
- package/dist/src/utils/formatObject.d.ts.map +1 -1
- package/dist/src/utils/formatObject.js +2 -2
- package/dist/src/utils/inputBinding.d.ts +5 -0
- package/dist/src/utils/inputBinding.d.ts.map +1 -0
- package/dist/src/utils/inputBinding.js +115 -0
- package/dist/src/utils/ui/tooltip.js +1 -1
- package/dist/src/view/paramMediator.d.ts +108 -0
- package/dist/src/view/paramMediator.d.ts.map +1 -0
- package/dist/src/view/paramMediator.js +337 -0
- package/dist/src/view/paramMediator.test.js +211 -0
- package/dist/src/view/scaleResolution.d.ts.map +1 -1
- package/dist/src/view/scaleResolution.js +11 -6
- package/dist/src/view/view.d.ts +4 -1
- package/dist/src/view/view.d.ts.map +1 -1
- package/dist/src/view/view.js +19 -5
- package/dist/src/view/viewFactory.d.ts.map +1 -1
- package/dist/src/view/viewFactory.js +45 -0
- package/dist/src/view/viewUtils.d.ts +5 -1
- package/dist/src/view/viewUtils.d.ts.map +1 -1
- package/dist/src/view/viewUtils.js +9 -4
- package/package.json +16 -17
- package/dist/src/paramBroker.d.ts +0 -46
- package/dist/src/paramBroker.d.ts.map +0 -1
- package/dist/src/paramBroker.js +0 -118
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { isDiscrete } from "vega-scale";
|
|
2
2
|
import createIndexer from "../utils/indexer.js";
|
|
3
3
|
import scaleNull from "../utils/scaleNull.js";
|
|
4
|
-
import { isExprRef } from "../
|
|
4
|
+
import { isExprRef } from "../view/paramMediator.js";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Creates an object that contains encoders for every channel of a mark
|
|
8
8
|
*
|
|
9
|
-
* TODO: This should actually receive the mark as parameter
|
|
10
|
-
*
|
|
11
9
|
* TODO: This method should have a test. But how to mock Mark...
|
|
12
10
|
*
|
|
13
11
|
* @param {import("../marks/mark.js").default} mark
|
|
@@ -41,6 +39,7 @@ export default function createEncoders(mark, encoding) {
|
|
|
41
39
|
const resolution = mark.unitView.getScaleResolution(channelWithScale);
|
|
42
40
|
|
|
43
41
|
encoders[channel] = createEncoder(
|
|
42
|
+
mark,
|
|
44
43
|
encoding[channel],
|
|
45
44
|
resolution?.scale,
|
|
46
45
|
mark.unitView.getAccessor(channel),
|
|
@@ -52,14 +51,14 @@ export default function createEncoders(mark, encoding) {
|
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
/**
|
|
55
|
-
*
|
|
54
|
+
* @param {import("../marks/mark.js").default} mark
|
|
56
55
|
* @param {import("../spec/channel.js").ChannelDef} channelDef
|
|
57
56
|
* @param {any} scale
|
|
58
57
|
* @param {Accessor} accessor
|
|
59
58
|
* @param {Channel} channel
|
|
60
59
|
* @returns {Encoder}
|
|
61
60
|
*/
|
|
62
|
-
export function createEncoder(channelDef, scale, accessor, channel) {
|
|
61
|
+
export function createEncoder(mark, channelDef, scale, accessor, channel) {
|
|
63
62
|
/**
|
|
64
63
|
* @typedef {import("../spec/channel.js").Channel} Channel
|
|
65
64
|
* @typedef {import("../types/encoder.js").Encoder} Encoder
|
|
@@ -71,9 +70,10 @@ export function createEncoder(channelDef, scale, accessor, channel) {
|
|
|
71
70
|
|
|
72
71
|
if (isValueDef(channelDef)) {
|
|
73
72
|
if (isExprRef(channelDef.value)) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
const fn = mark.unitView.paramMediator.createExpression(
|
|
74
|
+
channelDef.value.expr
|
|
75
|
+
);
|
|
76
|
+
encoder = /** @type {Encoder} */ ((datum) => fn(null));
|
|
77
77
|
encoder.constant = true;
|
|
78
78
|
encoder.constantValue = false;
|
|
79
79
|
encoder.accessor = accessor;
|
|
@@ -29,6 +29,7 @@ describe("Encoder", () => {
|
|
|
29
29
|
const encoders = {};
|
|
30
30
|
for (const [channel, channelDef] of Object.entries(encoding)) {
|
|
31
31
|
encoders[channel] = createEncoder(
|
|
32
|
+
null, // TODO: stub the mark
|
|
32
33
|
channelDef,
|
|
33
34
|
scales[channel],
|
|
34
35
|
accessorFactory.createAccessor(encodingSpecs[channel]),
|
|
@@ -95,4 +96,6 @@ describe("Encoder", () => {
|
|
|
95
96
|
});
|
|
96
97
|
|
|
97
98
|
// TODO: Test indexer
|
|
99
|
+
|
|
100
|
+
// TODO: Text ExprRef
|
|
98
101
|
});
|
package/dist/src/genomeSpy.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export default class GenomeSpy {
|
|
|
13
13
|
*/
|
|
14
14
|
constructor(container: HTMLElement, spec: import("./spec/root.js").RootSpec, options?: import("./types/embedApi.js").EmbedOptions);
|
|
15
15
|
container: HTMLElement;
|
|
16
|
+
options: import("./types/embedApi.js").EmbedOptions;
|
|
16
17
|
/** @type {(() => void)[]} */
|
|
17
18
|
_destructionCallbacks: (() => void)[];
|
|
18
19
|
/** Root level configuration object */
|
|
@@ -69,13 +70,16 @@ export default class GenomeSpy {
|
|
|
69
70
|
tooltipHandlers: Record<string, import("./tooltip/tooltipHandler.js").TooltipHandler>;
|
|
70
71
|
/** @type {View} */
|
|
71
72
|
viewRoot: import("./view/view.js").default;
|
|
72
|
-
_paramBroker: ParamBroker;
|
|
73
73
|
/**
|
|
74
74
|
* Views that are currently loading data using lazy sources.
|
|
75
75
|
*
|
|
76
76
|
* @type {Map<View, boolean>}
|
|
77
77
|
*/
|
|
78
78
|
_loadingViews: Map<import("./view/view.js").default, boolean>;
|
|
79
|
+
/**
|
|
80
|
+
* @type {HTMLElement}
|
|
81
|
+
*/
|
|
82
|
+
_inputBindingContainer: HTMLElement;
|
|
79
83
|
/**
|
|
80
84
|
*
|
|
81
85
|
* @param {(name: string) => any[]} provider
|
|
@@ -103,10 +107,9 @@ export default class GenomeSpy {
|
|
|
103
107
|
* animations with html elements than with WebGL.
|
|
104
108
|
*/
|
|
105
109
|
_updateLoadingIndicators(): void;
|
|
106
|
-
_prepareContainer(): void;
|
|
107
110
|
_glHelper: WebGLHelper;
|
|
108
|
-
loadingMessageElement:
|
|
109
|
-
loadingIndicatorsElement:
|
|
111
|
+
loadingMessageElement: HTMLElement;
|
|
112
|
+
loadingIndicatorsElement: HTMLElement;
|
|
110
113
|
tooltip: Tooltip;
|
|
111
114
|
/**
|
|
112
115
|
* Unregisters all listeners, removes all created dom elements, removes all css classes from the container
|
|
@@ -151,7 +154,6 @@ import Animator from "./utils/animator.js";
|
|
|
151
154
|
import GenomeStore from "./genome/genomeStore.js";
|
|
152
155
|
import BufferedViewRenderingContext from "./view/renderingContext/bufferedViewRenderingContext.js";
|
|
153
156
|
import Inertia from "./utils/inertia.js";
|
|
154
|
-
import ParamBroker from "./paramBroker.js";
|
|
155
157
|
import WebGLHelper from "./gl/webGLHelper.js";
|
|
156
158
|
import Tooltip from "./utils/ui/tooltip.js";
|
|
157
159
|
import UnitView from "./view/unitView.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"genomeSpy.d.ts","sourceRoot":"","sources":["../../src/genomeSpy.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"genomeSpy.d.ts","sourceRoot":"","sources":["../../src/genomeSpy.js"],"names":[],"mappings":"AA8CA;IACI;;;;;OAKG;IAEH;;;;;OAKG;IACH,uBAJW,WAAW,qDAEX,OAAO,qBAAqB,EAAE,YAAY,EA2FpD;IAxFG,uBAA0B;IAC1B,oDAAsB;IAItB,6BAA6B;IAC7B,uBADW,CAAC,MAAM,IAAI,CAAC,EAAE,CACM;IAE/B,sCAAsC;IACtC,wCAAgB;IAEhB,iCAA4C;IAC5C,yBAAoC;IAEpC,4CAA4C;IAC5C,oBADW,QAAU,MAAM,KAAE,MAAM,EAAE,CAAC,EAAE,CACZ;IAE5B,mBAAoD;IAEpD,0BAA0B;IAC1B,aADW,WAAW,CACM;IAE5B;;;;;OAKG;IACH,qEAF0B,OAAO,CAE8B;IAE/D,2CAA2C;IAC3C,mBADW,4BAA4B,CACL;IAClC,2CAA2C;IAC3C,iBADW,4BAA4B,CACP;IAEhC,oDAAoD;IACpD,6BAAgC;IAEhC;;;OAGG;IACH,eAFU;QAAE,IAAI,EAAE,OAAO,iBAAiB,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,oBAAoB,EAAE,KAAK,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAEpF;IAE9B,uBAA+C;IAE/C;;;OAGG;IACH,oBAFU,IAAI,MAAM,EAAE,QAAU,aAAa,KAAE,IAAI,CAAC,EAAE,CAAC,CAEpB;IAEnC;;;;;;OAMG;IACH,yCAFkC,GAAG,KAAK,IAAI,GAEd;IAEhC;;;OAGG;IACH,kDAFkC,GAAG,KAAK,IAAI,GAEL;IAEzC,oFAAoF;IACpF,iBADW,OAAO,MAAM,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC,CAK9E;IAED,mBAAmB;IACnB,2CAAyB;IAEzB;;;;OAIG;IACH,8DAA8B;IAE9B;;OAEG;IACH,wBAFU,WAAW,CAEkB;IA2C3C;;;OAGG;IACH,2CAFkB,MAAM,KAAK,GAAG,EAAE,QAIjC;IAED;;OAEG;IACH,+BAFW,MAAM,YAShB;IAED;;;;OAIG;IACH,sBAHW,MAAM,QACN,GAAG,EAAE,QAaf;IAED;;;;;OAKG;IACH,gBAHW,kBAAkB,YAClB,GAAG,QAQb;IAED;;;OAGG;IACH,iCAyCC;IA0DG,uBAOC;IAGD,mCAGE;IAOF,sCAEE;IAGF,iBAAyC;IAW7C;;OAEG;IACH,gBAuBC;IAED,sCA8MC;IAED;;;OAGG;IACH,UAFa,QAAQ,OAAO,CAAC,CA6B5B;IAED,4BA6IC;IAjIe,iCAAoC;IAmIpD;;;OAGG;IACH,kBAHW,MAAM,KACN,MAAM,QAiEhB;IAED;;;;;;;OAOG;IACH,oDAHuB,QAAQ,MAAM,GAAG,WAAW,GAAG,OAAO,KAAK,EAAE,cAAc,CAAC,QAYlF;IAED,sBAyCC;IAED,kBAIC;IAED,iCAOC;IAED,iCASC;IAED,qFAWC;;CACJ;;;;iCA15BY,eAAe,GAAG,YAAY,GAAG,QAAQ,GAAG,gBAAgB;4BAjC7C,uBAAuB;4BA2BP,uBAAuB;qBAZ9C,qBAAqB;wBAIlB,yBAAyB;yCARR,yDAAyD;oBAYvD,oBAAoB;wBAdvC,qBAAqB;oBAXzB,uBAAuB;qBAStB,oBAAoB"}
|
package/dist/src/genomeSpy.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { formats as vegaFormats } from "vega-loader";
|
|
2
|
-
import { html, render } from "lit
|
|
2
|
+
import { html, render } from "lit";
|
|
3
3
|
import { styleMap } from "lit/directives/style-map.js";
|
|
4
4
|
import SPINNER from "./img/90-ring-with-bg.svg";
|
|
5
5
|
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
checkForDuplicateScaleNames,
|
|
12
12
|
setImplicitScaleNames,
|
|
13
13
|
calculateCanvasSize,
|
|
14
|
+
calculateViewRootSize,
|
|
14
15
|
} from "./view/viewUtils.js";
|
|
15
16
|
import UnitView from "./view/unitView.js";
|
|
16
17
|
|
|
@@ -34,9 +35,7 @@ import dataTooltipHandler from "./tooltip/dataTooltipHandler.js";
|
|
|
34
35
|
import { invalidatePrefix } from "./utils/propertyCacher.js";
|
|
35
36
|
import { VIEW_ROOT_NAME, ViewFactory } from "./view/viewFactory.js";
|
|
36
37
|
import { reconfigureScales } from "./view/scaleResolution.js";
|
|
37
|
-
import
|
|
38
|
-
import { debounce } from "./utils/debounce.js";
|
|
39
|
-
import { tickStep } from "d3-array";
|
|
38
|
+
import createBindingInputs from "./utils/inputBinding.js";
|
|
40
39
|
|
|
41
40
|
/**
|
|
42
41
|
* Events that are broadcasted to all views.
|
|
@@ -61,14 +60,13 @@ export default class GenomeSpy {
|
|
|
61
60
|
*/
|
|
62
61
|
constructor(container, spec, options = {}) {
|
|
63
62
|
this.container = container;
|
|
63
|
+
this.options = options;
|
|
64
|
+
|
|
65
|
+
options.inputBindingContainer ??= "default";
|
|
64
66
|
|
|
65
67
|
/** @type {(() => void)[]} */
|
|
66
68
|
this._destructionCallbacks = [];
|
|
67
69
|
|
|
68
|
-
const styleElement = document.createElement("style");
|
|
69
|
-
styleElement.innerHTML = css;
|
|
70
|
-
container.appendChild(styleElement);
|
|
71
|
-
|
|
72
70
|
/** Root level configuration object */
|
|
73
71
|
this.spec = spec;
|
|
74
72
|
|
|
@@ -138,118 +136,55 @@ export default class GenomeSpy {
|
|
|
138
136
|
/** @type {View} */
|
|
139
137
|
this.viewRoot = undefined;
|
|
140
138
|
|
|
141
|
-
this._paramBroker = new ParamBroker();
|
|
142
|
-
this.#initializeParameters();
|
|
143
|
-
|
|
144
139
|
/**
|
|
145
140
|
* Views that are currently loading data using lazy sources.
|
|
146
141
|
*
|
|
147
142
|
* @type {Map<View, boolean>}
|
|
148
143
|
*/
|
|
149
144
|
this._loadingViews = new Map();
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @type {HTMLElement}
|
|
148
|
+
*/
|
|
149
|
+
this._inputBindingContainer = undefined;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
#
|
|
153
|
-
/** @type {
|
|
154
|
-
|
|
152
|
+
get #canvasWrapper() {
|
|
153
|
+
return /** @type {HTMLElement} */ (
|
|
154
|
+
this.container.querySelector(".canvas-wrapper")
|
|
155
|
+
);
|
|
156
|
+
}
|
|
155
157
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
#initializeParameterBindings() {
|
|
159
|
+
/** @type {import("lit").TemplateResult[]} */
|
|
160
|
+
const inputs = [];
|
|
159
161
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
this.viewRoot.visit((view) => {
|
|
163
|
+
const mediator = view.paramMediator;
|
|
164
|
+
inputs.push(...createBindingInputs(mediator));
|
|
165
|
+
});
|
|
166
|
+
const ibc = this.options.inputBindingContainer;
|
|
163
167
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (bind && "input" in bind) {
|
|
168
|
-
const debouncedSetter = bind.debounce
|
|
169
|
-
? debounce(setter, bind.debounce, false)
|
|
170
|
-
: setter;
|
|
171
|
-
|
|
172
|
-
if (bind.input == "range") {
|
|
173
|
-
// TODO: Show the value next to the slider
|
|
174
|
-
inputs.push(
|
|
175
|
-
html`<label
|
|
176
|
-
>${bind.name ?? name}
|
|
177
|
-
<input
|
|
178
|
-
type="range"
|
|
179
|
-
min=${bind.min ?? 0}
|
|
180
|
-
max=${bind.max ?? 100}
|
|
181
|
-
step=${bind.step ??
|
|
182
|
-
tickStep(bind.min, bind.max, 100)}
|
|
183
|
-
.value=${value}
|
|
184
|
-
@input=${(/** @type {any} */ e) =>
|
|
185
|
-
debouncedSetter(e.target.valueAsNumber)}
|
|
186
|
-
/></label>`
|
|
187
|
-
);
|
|
188
|
-
} else if (bind.input == "checkbox") {
|
|
189
|
-
inputs.push(
|
|
190
|
-
html`<label
|
|
191
|
-
>${bind.name ?? name}
|
|
192
|
-
<input
|
|
193
|
-
type="checkbox"
|
|
194
|
-
?checked=${value}
|
|
195
|
-
@input=${(/** @type {any} */ e) =>
|
|
196
|
-
debouncedSetter(e.target.checked)}
|
|
197
|
-
/></label>`
|
|
198
|
-
);
|
|
199
|
-
} else if (bind.input == "radio") {
|
|
200
|
-
inputs.push(
|
|
201
|
-
html`<span class="label">${bind.name ?? name}</span>
|
|
202
|
-
${bind.options.map(
|
|
203
|
-
(option, i) => html`<label>
|
|
204
|
-
<input
|
|
205
|
-
type="radio"
|
|
206
|
-
name=${name}
|
|
207
|
-
value=${option}
|
|
208
|
-
.checked=${value == option}
|
|
209
|
-
@input=${(/** @type {any} */ e) =>
|
|
210
|
-
debouncedSetter(e.target.value)}
|
|
211
|
-
/>${bind.labels?.[i] ?? option}</label
|
|
212
|
-
>`
|
|
213
|
-
)}`
|
|
214
|
-
);
|
|
215
|
-
} else if (bind.input == "select") {
|
|
216
|
-
inputs.push(
|
|
217
|
-
html`<label
|
|
218
|
-
>${bind.name ?? name}
|
|
219
|
-
<select
|
|
220
|
-
@input=${(/** @type {any} */ e) =>
|
|
221
|
-
debouncedSetter(e.target.value)}
|
|
222
|
-
>
|
|
223
|
-
${bind.options.map(
|
|
224
|
-
(option, i) => html`<option
|
|
225
|
-
value=${option}
|
|
226
|
-
?selected=${value == option}
|
|
227
|
-
>
|
|
228
|
-
${bind.labels?.[i] ?? option}
|
|
229
|
-
</option>`
|
|
230
|
-
)}
|
|
231
|
-
</select></label
|
|
232
|
-
>`
|
|
233
|
-
);
|
|
234
|
-
} else {
|
|
235
|
-
// TODO: Support other types: "text", "number", "color".
|
|
236
|
-
throw new Error("Unsupported input type: " + bind.input);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
168
|
+
if (!ibc || ibc == "none" || !inputs.length) {
|
|
169
|
+
return;
|
|
239
170
|
}
|
|
240
171
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
172
|
+
this._inputBindingContainer = element("div", {
|
|
173
|
+
className: "gs-input-bindings",
|
|
174
|
+
});
|
|
244
175
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
176
|
+
if (ibc == "default") {
|
|
177
|
+
this.container.appendChild(this._inputBindingContainer);
|
|
178
|
+
} else if (ibc instanceof HTMLElement) {
|
|
179
|
+
ibc.appendChild(this._inputBindingContainer);
|
|
180
|
+
} else {
|
|
181
|
+
throw new Error("Invalid inputBindingContainer");
|
|
182
|
+
}
|
|
249
183
|
|
|
184
|
+
if (inputs.length) {
|
|
250
185
|
render(
|
|
251
|
-
html
|
|
252
|
-
|
|
186
|
+
html`<div class="gs-input-binding">${inputs}</div>`,
|
|
187
|
+
this._inputBindingContainer
|
|
253
188
|
);
|
|
254
189
|
}
|
|
255
190
|
}
|
|
@@ -311,7 +246,7 @@ export default class GenomeSpy {
|
|
|
311
246
|
* animations with html elements than with WebGL.
|
|
312
247
|
*/
|
|
313
248
|
_updateLoadingIndicators() {
|
|
314
|
-
/** @type {import("lit
|
|
249
|
+
/** @type {import("lit").TemplateResult[]} */
|
|
315
250
|
const indicators = [];
|
|
316
251
|
|
|
317
252
|
const isSomethingVisible = () =>
|
|
@@ -353,17 +288,10 @@ export default class GenomeSpy {
|
|
|
353
288
|
render(indicators, this.loadingIndicatorsElement);
|
|
354
289
|
}
|
|
355
290
|
|
|
356
|
-
|
|
357
|
-
this.
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
this._glHelper = new WebGLHelper(
|
|
361
|
-
this.container,
|
|
362
|
-
() =>
|
|
363
|
-
this.viewRoot
|
|
364
|
-
? calculateCanvasSize(this.viewRoot)
|
|
365
|
-
: { width: undefined, height: undefined },
|
|
366
|
-
this.spec.background
|
|
291
|
+
#setupDpr() {
|
|
292
|
+
const dprSetter = this.viewRoot.paramMediator.allocateSetter(
|
|
293
|
+
"devicePixelRatio",
|
|
294
|
+
window.devicePixelRatio
|
|
367
295
|
);
|
|
368
296
|
|
|
369
297
|
const resizeCallback = () => {
|
|
@@ -379,9 +307,6 @@ export default class GenomeSpy {
|
|
|
379
307
|
resizeObserver.observe(this.container);
|
|
380
308
|
this._destructionCallbacks.push(() => resizeObserver.disconnect());
|
|
381
309
|
|
|
382
|
-
const dprSetter = this._paramBroker.allocateSetter("devicePixelRatio");
|
|
383
|
-
dprSetter(window.devicePixelRatio);
|
|
384
|
-
|
|
385
310
|
/** @type {() => void} */
|
|
386
311
|
let remove = null;
|
|
387
312
|
|
|
@@ -403,22 +328,48 @@ export default class GenomeSpy {
|
|
|
403
328
|
if (remove) {
|
|
404
329
|
this._destructionCallbacks.push(remove);
|
|
405
330
|
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
#prepareContainer() {
|
|
334
|
+
this.container.classList.add("genome-spy");
|
|
335
|
+
|
|
336
|
+
const styleElement = document.createElement("style");
|
|
337
|
+
styleElement.innerHTML = css;
|
|
338
|
+
this.container.appendChild(styleElement);
|
|
339
|
+
|
|
340
|
+
const canvasWrapper = element("div", {
|
|
341
|
+
class: "canvas-wrapper",
|
|
342
|
+
});
|
|
343
|
+
this.container.appendChild(canvasWrapper);
|
|
344
|
+
|
|
345
|
+
canvasWrapper.classList.add("loading");
|
|
346
|
+
|
|
347
|
+
this._glHelper = new WebGLHelper(
|
|
348
|
+
canvasWrapper,
|
|
349
|
+
() =>
|
|
350
|
+
this.viewRoot
|
|
351
|
+
? calculateCanvasSize(calculateViewRootSize(this.viewRoot))
|
|
352
|
+
: { width: undefined, height: undefined },
|
|
353
|
+
this.spec.background
|
|
354
|
+
);
|
|
406
355
|
|
|
407
356
|
// The initial loading message that is shown until the first frame is rendered
|
|
408
|
-
this.loadingMessageElement =
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
357
|
+
this.loadingMessageElement = element("div", {
|
|
358
|
+
class: "loading-message",
|
|
359
|
+
innerHTML: `<div class="message">Loading<span class="ellipsis">...</span></div>`,
|
|
360
|
+
});
|
|
361
|
+
canvasWrapper.appendChild(this.loadingMessageElement);
|
|
412
362
|
|
|
413
363
|
// A container for loading indicators (for lazy data sources.)
|
|
414
364
|
// These could alternatively be included in the view hierarchy,
|
|
415
365
|
// but it's easier this way – particularly if we want to show
|
|
416
366
|
// some fancy animated spinners.
|
|
417
|
-
this.loadingIndicatorsElement =
|
|
418
|
-
|
|
419
|
-
|
|
367
|
+
this.loadingIndicatorsElement = element("div", {
|
|
368
|
+
class: "loading-indicators",
|
|
369
|
+
});
|
|
370
|
+
canvasWrapper.appendChild(this.loadingIndicatorsElement);
|
|
420
371
|
|
|
421
|
-
this.tooltip = new Tooltip(
|
|
372
|
+
this.tooltip = new Tooltip(canvasWrapper);
|
|
422
373
|
|
|
423
374
|
this.loadingMessageElement
|
|
424
375
|
.querySelector(".message")
|
|
@@ -435,8 +386,10 @@ export default class GenomeSpy {
|
|
|
435
386
|
destroy() {
|
|
436
387
|
// TODO: There's a memory leak somewhere
|
|
437
388
|
|
|
389
|
+
const canvasWrapper = this.#canvasWrapper;
|
|
390
|
+
|
|
438
391
|
this.container.classList.remove("genome-spy");
|
|
439
|
-
|
|
392
|
+
canvasWrapper.classList.remove("loading");
|
|
440
393
|
|
|
441
394
|
for (const [type, listeners] of this._keyboardListeners) {
|
|
442
395
|
for (const listener of listeners) {
|
|
@@ -448,6 +401,8 @@ export default class GenomeSpy {
|
|
|
448
401
|
|
|
449
402
|
this._glHelper.finalize();
|
|
450
403
|
|
|
404
|
+
this._inputBindingContainer?.remove();
|
|
405
|
+
|
|
451
406
|
while (this.container.firstChild) {
|
|
452
407
|
this.container.firstChild.remove();
|
|
453
408
|
}
|
|
@@ -475,8 +430,6 @@ export default class GenomeSpy {
|
|
|
475
430
|
return self._glHelper.dpr;
|
|
476
431
|
},
|
|
477
432
|
|
|
478
|
-
paramBroker: this._paramBroker,
|
|
479
|
-
|
|
480
433
|
requestLayoutReflow: () => {
|
|
481
434
|
// placeholder
|
|
482
435
|
},
|
|
@@ -571,6 +524,11 @@ export default class GenomeSpy {
|
|
|
571
524
|
VIEW_ROOT_NAME
|
|
572
525
|
);
|
|
573
526
|
|
|
527
|
+
this.#canvasWrapper.style.flexGrow =
|
|
528
|
+
calculateViewRootSize(this.viewRoot).height.grow > 0 ? "1" : "0";
|
|
529
|
+
|
|
530
|
+
this.#initializeParameterBindings();
|
|
531
|
+
|
|
574
532
|
checkForDuplicateScaleNames(this.viewRoot);
|
|
575
533
|
|
|
576
534
|
setImplicitScaleNames(this.viewRoot);
|
|
@@ -585,6 +543,7 @@ export default class GenomeSpy {
|
|
|
585
543
|
// We should now have a complete view hierarchy. Let's update the canvas size
|
|
586
544
|
// and ensure that the loading message is visible.
|
|
587
545
|
this._glHelper.invalidateSize();
|
|
546
|
+
this.#setupDpr();
|
|
588
547
|
|
|
589
548
|
// Collect all unit views to a list because they need plenty of initialization
|
|
590
549
|
const unitViews = /** @type {UnitView[]} */ (
|
|
@@ -614,12 +573,14 @@ export default class GenomeSpy {
|
|
|
614
573
|
view.mark.initializeData();
|
|
615
574
|
// Update WebGL buffers
|
|
616
575
|
view.mark.updateGraphicsData();
|
|
576
|
+
context.animator.requestRender();
|
|
617
577
|
}, view);
|
|
618
578
|
}
|
|
619
579
|
|
|
620
580
|
// Have to wait until asynchronous font loading is complete.
|
|
621
581
|
// Text mark's geometry builder needs font metrics before data can be
|
|
622
582
|
// converted into geometries.
|
|
583
|
+
// TODO: Make updateGraphicsData async and await font loading there.
|
|
623
584
|
await context.fontManager.waitUntilReady();
|
|
624
585
|
|
|
625
586
|
// Find all data sources and initiate loading
|
|
@@ -661,7 +622,7 @@ export default class GenomeSpy {
|
|
|
661
622
|
*/
|
|
662
623
|
async launch() {
|
|
663
624
|
try {
|
|
664
|
-
this
|
|
625
|
+
this.#prepareContainer();
|
|
665
626
|
|
|
666
627
|
await this._prepareViewsAndData();
|
|
667
628
|
|
|
@@ -680,7 +641,7 @@ export default class GenomeSpy {
|
|
|
680
641
|
|
|
681
642
|
return false;
|
|
682
643
|
} finally {
|
|
683
|
-
this.
|
|
644
|
+
this.#canvasWrapper.classList.remove("loading");
|
|
684
645
|
// Transition listener doesn't appear to work on observablehq
|
|
685
646
|
window.setTimeout(() => {
|
|
686
647
|
this.loadingMessageElement.style.display = "none";
|
|
@@ -1016,3 +977,19 @@ function createMessageBox(container, message) {
|
|
|
1016
977
|
messageBox.appendChild(messageText);
|
|
1017
978
|
container.appendChild(messageBox);
|
|
1018
979
|
}
|
|
980
|
+
|
|
981
|
+
/**
|
|
982
|
+
* @param {string} tag
|
|
983
|
+
* @param {Record<string, any>} attrs
|
|
984
|
+
*/
|
|
985
|
+
function element(tag, attrs) {
|
|
986
|
+
const el = document.createElement(tag);
|
|
987
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
988
|
+
if (["innerHTML", "innerText", "className"].includes(key)) {
|
|
989
|
+
// @ts-ignore
|
|
990
|
+
el[key] = value;
|
|
991
|
+
}
|
|
992
|
+
el.setAttribute(key, value);
|
|
993
|
+
}
|
|
994
|
+
return el;
|
|
995
|
+
}
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
} from "../encoder/encoder.js";
|
|
19
19
|
import { asArray, peek } from "../utils/arrayUtils.js";
|
|
20
20
|
import { InternMap } from "internmap";
|
|
21
|
-
import { isExprRef } from "../
|
|
21
|
+
import { isExprRef } from "../view/paramMediator.js";
|
|
22
22
|
import scaleNull from "../utils/scaleNull.js";
|
|
23
23
|
|
|
24
24
|
export const ATTRIBUTE_PREFIX = "attr_";
|
package/dist/src/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export function embed(el: string | HTMLElement, spec: string | import("./spec/ro
|
|
|
8
8
|
*/
|
|
9
9
|
export function loadSpec(url: string): Promise<any>;
|
|
10
10
|
import GenomeSpy from "./genomeSpy.js";
|
|
11
|
-
import { html } from "lit
|
|
11
|
+
import { html } from "lit";
|
|
12
12
|
import icon from "./img/bowtie.svg";
|
|
13
13
|
import favIcon from "./img/genomespy-favicon.svg";
|
|
14
14
|
export { GenomeSpy, html, icon, favIcon };
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.js"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.js"],"names":[],"mappings":";AAawB,mMAGnB;AAyFL;;;;;GAKG;AACH,8BAFW,MAAM,gBAmBhB;sBA5HqB,gBAAgB;qBAFjB,KAAK;iBAGT,kBAAkB;oBACf,6BAA6B"}
|
package/dist/src/index.js
CHANGED
package/dist/src/marks/mark.d.ts
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
/// <reference types="external-typings/internmap.js" />
|
|
2
|
-
/**
|
|
3
|
-
* @param {any} x
|
|
4
|
-
* @returns {x is import("../spec/parameter.js").ExprRef}
|
|
5
|
-
*/
|
|
6
|
-
export function isExprRef(x: any): x is import("../spec/parameter.js").ExprRef;
|
|
7
2
|
export const SAMPLE_FACET_UNIFORM: "SAMPLE_FACET_UNIFORM";
|
|
8
3
|
export const SAMPLE_FACET_TEXTURE: "SAMPLE_FACET_TEXTURE";
|
|
9
4
|
/**
|
|
@@ -90,6 +85,14 @@ export default class Mark {
|
|
|
90
85
|
* @returns {Encoding}
|
|
91
86
|
*/
|
|
92
87
|
fixEncoding(encoding: import("../spec/channel.js").Encoding<string>): import("../spec/channel.js").Encoding<string>;
|
|
88
|
+
/**
|
|
89
|
+
* Handles dynamic properties that are not bound to uniforms but need
|
|
90
|
+
* to trigger a graphics update, i.e., rebuild the vertex buffer.
|
|
91
|
+
*
|
|
92
|
+
* @param {(keyof MarkProps)[]} props
|
|
93
|
+
* @protected
|
|
94
|
+
*/
|
|
95
|
+
protected setupExprRefsNeedingGraphicsUpdate(props: (keyof import("../spec/mark.js").MarkProps)[]): void;
|
|
93
96
|
/**
|
|
94
97
|
* Returns the encoding spec supplemented with mark's default encodings
|
|
95
98
|
*
|
|
@@ -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":";AA4CA,0DAA2D;AAC3D,0DAA2D;AAE3D;;;;;;;;;;;;GAYG;AACH;IAgBI;;OAEG;IACH,sBAFW,OAAO,qBAAqB,EAAE,OAAO,EAkF/C;IA/EG,gDAAwB;IAExB,oEAAoE;IACpE,UADW,OAAO,MAAM,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CACvC;IAIzB,0FAA0F;IAC1F,YADW,OAAO,SAAS,EAAE,UAAU,GAAG;QAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,CAC7C;IAE3B,0DAA0D;IAC1D,aADW,OAAO,SAAS,EAAE,WAAW,CACZ;IAE5B,8DAA8D;IAC9D,iBADW,OAAO,SAAS,EAAE,eAAe,CACZ;IAEhC,+DAA+D;IAC/D,mBADW,OAAO,SAAS,EAAE,gBAAgB,CACX;IAElC,+DAA+D;IAC/D,iBADW,OAAO,SAAS,EAAE,gBAAgB,CACb;IAEhC;;;OAGG;IACH,iBAFU,OAAO,SAAS,EAAE,gBAAgB,CAEZ;IAEhC;;;;;OAKG;IACH,uCAA+B;IAE/B,kFAAkF;IAClF,UADW,SAAS,GAAG,CAAC,CACM;IAG9B,wBAAwB;IACxB,uDAqBC;IAED;;;;;;;;OAQG;IACH,kEAKC;IAGL,sBAEC;IAED;;;;;;;OAOG;IACH,iBAFa,MAAM,EAAE,CAKpB;IAED;;OAEG;IACH,+DAWC;IAED;;OAEG;IACH,oEAcC;IAED;;;;;OAKG;IACH,oHAEC;IAED;;;;;;OAMG;IACH,yGAkCC;IAED;;;;OAIG;IACH,8DAiDC;IAED,wDAEC;IAED,8CAEC;IAED,uBAEC;IAED;;;OAGG;IACH,2BAEC;IAED;;OAEG;IACH,oCAEC;IAED;;OAEG;IACH,2BAEC;IAED,sEAeC;IAED;;;;;;OAMG;IAEH,6CANW,MAAM,kBACN,MAAM,iBACN,MAAM,EAAE,QA8NlB;IALG;;;;;;MAIC;IAGL;;;;;;OAMG;IACH,uCA6CC;IAED;;;;;;OAMG;IACH,+CAHW,MAAM,UACK,GAAG,KAAE,IAAI,CAe9B;IAED;;;;;;;;;;OAUG;IACH,mDAJW,MAAM,sFAEsB,GAAG,QA6BzC;IAED;;OAEG;IACH,2BAiBC;IAED;;;OAGG;IACH,6BAFW,GAAG,QAoCb;IAED,yBAAyB;IACzB,uDAEC;IAED,yBAAyB;IACzB,iCAEC;IAED,gCAEC;IAED,+BAEC;IAED,yCAEC;IAED;;;;;OAKG;IACH,gCAcC;IAED;;OAEG;IACH,4CAOC;IAED;;;;;;;;OAQG;IAEH,uBAJW,OAAO,uBAAuB,EAAE,sBAAsB,GACpD,CAAC,MAAM,IAAI,CAAC,EAAE,CAsF1B;IAED;;;;;;OAMG;IACH,qCAJW,oBAAoB,GAClB,OAAO,CAqCnB;IAED;;;;;;;OAOG;IACH,gBAJW,oBAAoB,SACP,IAAI,CAM3B;IAED;;;OAGG;IACH,2BAHW,YAAY,WACZ,OAAO,WAAW,EAAE,oBAAoB,cAiElD;IAED;;;;;;OAMG;IACH,oBAJW,OAAO,6BAA6B,EAAE,OAAO,aAC7C,OAAO,6BAA6B,EAAE,OAAO,GAC3C,OAAO,CAuHnB;IAED;;;;;;;;;OASG;IACH,qBAJW,MAAM,KACN,OAAO,oBAAoB,EAAE,MAAM,GACjC,GAAG,CAIf;;CACJ;+BAznCY,OAAO,uBAAuB,EAAE,gBAAgB;;;;;;wBAEnD,OAAO;;mCAEJ,gBAAgB,GAAG,qBAAqB;oCAG1C,MAAM,SACN,MAAM;AAmnCjB;;;GAGG;AACH;IACI,cAEC;IAkBD;;;OAGG;IACH,2BAFW,IAAI,CAAC,EAAE,OAAO,yBAAyB,EAAE,UAAU,CAAC,QAM9D;CACJ;0BAtqCyB,WAAW"}
|