@genome-spy/core 0.40.0 → 0.42.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.
Files changed (104) hide show
  1. package/dist/bundle/index--cKb-dKG.js +615 -0
  2. package/dist/bundle/{index-gn8bhQ8w.js → index-d7k3kkin.js} +365 -366
  3. package/dist/bundle/index.es.js +4260 -3928
  4. package/dist/bundle/index.js +115 -80
  5. package/dist/schema.json +254 -52
  6. package/dist/src/data/sources/dynamic/axisGenomeSource.js +1 -1
  7. package/dist/src/data/sources/dynamic/axisTickSource.js +3 -3
  8. package/dist/src/data/sources/dynamic/bamSource.d.ts +3 -21
  9. package/dist/src/data/sources/dynamic/bamSource.d.ts.map +1 -1
  10. package/dist/src/data/sources/dynamic/bamSource.js +38 -55
  11. package/dist/src/data/sources/dynamic/bigBedSource.d.ts +2 -38
  12. package/dist/src/data/sources/dynamic/bigBedSource.d.ts.map +1 -1
  13. package/dist/src/data/sources/dynamic/bigBedSource.js +14 -71
  14. package/dist/src/data/sources/dynamic/bigWigSource.d.ts +4 -42
  15. package/dist/src/data/sources/dynamic/bigWigSource.d.ts.map +1 -1
  16. package/dist/src/data/sources/dynamic/bigWigSource.js +23 -60
  17. package/dist/src/data/sources/dynamic/gff3Source.d.ts.map +1 -1
  18. package/dist/src/data/sources/dynamic/gff3Source.js +1 -0
  19. package/dist/src/data/sources/dynamic/indexedFastaSource.d.ts +2 -20
  20. package/dist/src/data/sources/dynamic/indexedFastaSource.d.ts.map +1 -1
  21. package/dist/src/data/sources/dynamic/indexedFastaSource.js +23 -41
  22. package/dist/src/data/sources/dynamic/singleAxisLazySource.d.ts +23 -4
  23. package/dist/src/data/sources/dynamic/singleAxisLazySource.d.ts.map +1 -1
  24. package/dist/src/data/sources/dynamic/singleAxisLazySource.js +29 -4
  25. package/dist/src/data/sources/dynamic/singleAxisWindowedSource.d.ts +60 -0
  26. package/dist/src/data/sources/dynamic/singleAxisWindowedSource.d.ts.map +1 -0
  27. package/dist/src/data/sources/dynamic/singleAxisWindowedSource.js +152 -0
  28. package/dist/src/data/sources/dynamic/tabixSource.d.ts +6 -40
  29. package/dist/src/data/sources/dynamic/tabixSource.d.ts.map +1 -1
  30. package/dist/src/data/sources/dynamic/tabixSource.js +29 -78
  31. package/dist/src/data/transforms/regexFold.d.ts.map +1 -1
  32. package/dist/src/data/transforms/regexFold.js +8 -0
  33. package/dist/src/data/transforms/regexFold.test.js +28 -0
  34. package/dist/src/encoder/accessor.js +4 -2
  35. package/dist/src/genomeSpy.d.ts +16 -0
  36. package/dist/src/genomeSpy.d.ts.map +1 -1
  37. package/dist/src/genomeSpy.js +119 -8
  38. package/dist/src/gl/link.vertex.glsl.js +1 -1
  39. package/dist/src/gl/point.common.glsl.js +2 -0
  40. package/dist/src/gl/point.fragment.glsl.js +1 -1
  41. package/dist/src/gl/point.vertex.glsl.js +1 -1
  42. package/dist/src/gl/rect.vertex.glsl.js +1 -1
  43. package/dist/src/gl/rule.common.glsl.js +2 -0
  44. package/dist/src/gl/rule.fragment.glsl.js +1 -1
  45. package/dist/src/gl/rule.vertex.glsl.js +1 -1
  46. package/dist/src/gl/text.common.glsl.js +2 -0
  47. package/dist/src/gl/text.fragment.glsl.js +1 -1
  48. package/dist/src/gl/text.vertex.glsl.js +1 -1
  49. package/dist/src/gl/webGLHelper.d.ts +6 -21
  50. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  51. package/dist/src/gl/webGLHelper.js +7 -38
  52. package/dist/src/img/90-ring-with-bg.svg +1 -0
  53. package/dist/src/img/README.md +5 -0
  54. package/dist/src/marks/link.d.ts +7 -0
  55. package/dist/src/marks/link.d.ts.map +1 -1
  56. package/dist/src/marks/link.js +99 -50
  57. package/dist/src/marks/mark.d.ts +34 -0
  58. package/dist/src/marks/mark.d.ts.map +1 -1
  59. package/dist/src/marks/mark.js +83 -1
  60. package/dist/src/marks/pointMark.d.ts.map +1 -1
  61. package/dist/src/marks/pointMark.js +21 -9
  62. package/dist/src/marks/rectMark.d.ts +1 -2
  63. package/dist/src/marks/rectMark.d.ts.map +1 -1
  64. package/dist/src/marks/rectMark.js +28 -17
  65. package/dist/src/marks/rule.d.ts.map +1 -1
  66. package/dist/src/marks/rule.js +17 -6
  67. package/dist/src/marks/text.d.ts.map +1 -1
  68. package/dist/src/marks/text.js +32 -18
  69. package/dist/src/paramBroker.d.ts +30 -0
  70. package/dist/src/paramBroker.d.ts.map +1 -0
  71. package/dist/src/paramBroker.js +102 -0
  72. package/dist/src/spec/data.d.ts +28 -13
  73. package/dist/src/spec/mark.d.ts +27 -26
  74. package/dist/src/spec/view.d.ts +2 -1
  75. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  76. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  77. package/dist/src/styles/genome-spy.css.js +33 -4
  78. package/dist/src/styles/genome-spy.scss +40 -4
  79. package/dist/src/types/viewContext.d.ts +11 -0
  80. package/dist/src/utils/binnedIndex.d.ts +2 -0
  81. package/dist/src/utils/binnedIndex.d.ts.map +1 -1
  82. package/dist/src/utils/binnedIndex.js +59 -10
  83. package/dist/src/utils/binnedIndex.test.js +46 -0
  84. package/dist/src/utils/expression.d.ts +12 -2
  85. package/dist/src/utils/expression.d.ts.map +1 -1
  86. package/dist/src/utils/expression.js +68 -9
  87. package/dist/src/utils/linearstep.d.ts +7 -0
  88. package/dist/src/utils/linearstep.d.ts.map +1 -0
  89. package/dist/src/utils/linearstep.js +10 -0
  90. package/dist/src/view/gridView.d.ts.map +1 -1
  91. package/dist/src/view/gridView.js +2 -0
  92. package/dist/src/view/layerView.d.ts.map +1 -1
  93. package/dist/src/view/layerView.js +2 -0
  94. package/dist/src/view/unitView.d.ts +0 -6
  95. package/dist/src/view/unitView.d.ts.map +1 -1
  96. package/dist/src/view/unitView.js +2 -9
  97. package/dist/src/view/view.d.ts +6 -0
  98. package/dist/src/view/view.d.ts.map +1 -1
  99. package/dist/src/view/view.js +17 -0
  100. package/package.json +3 -3
  101. package/dist/bundle/index-Cbz74kpR.js +0 -638
  102. package/dist/src/data/sources/dynamic/windowedMixin.d.ts +0 -32
  103. package/dist/src/data/sources/dynamic/windowedMixin.d.ts.map +0 -1
  104. package/dist/src/data/sources/dynamic/windowedMixin.js +0 -53
@@ -1,8 +1,14 @@
1
1
  import { isString } from "vega-util";
2
2
  import { format } from "d3-format";
3
- import { drawBufferInfo, setBuffersAndAttributes, setUniforms } from "twgl.js";
3
+ import {
4
+ drawBufferInfo,
5
+ setBlockUniforms,
6
+ setBuffersAndAttributes,
7
+ setUniforms,
8
+ } from "twgl.js";
4
9
  import VERTEX_SHADER from "../gl/text.vertex.glsl.js";
5
10
  import FRAGMENT_SHADER from "../gl/text.fragment.glsl.js";
11
+ import COMMON_SHADER from "../gl/text.common.glsl.js";
6
12
  import { TextVertexBuilder } from "../gl/dataToVertices.js";
7
13
 
8
14
  import Mark from "./mark.js";
@@ -142,7 +148,9 @@ export default class TextMark extends Mark {
142
148
 
143
149
  async initializeGraphics() {
144
150
  await super.initializeGraphics();
145
- this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER);
151
+ this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER, [
152
+ COMMON_SHADER,
153
+ ]);
146
154
  }
147
155
 
148
156
  finalizeGraphicsInitialization() {
@@ -152,8 +160,24 @@ export default class TextMark extends Mark {
152
160
 
153
161
  const props = this.properties;
154
162
 
163
+ this.registerMarkUniform(
164
+ "uSdfNumerator",
165
+ /** @type {import("../spec/mark.js").ExprRef | number} */
166
+ ({ expr: "devicePixelRatio" }),
167
+ (dpr) => {
168
+ let q = 0.35; // TODO: Ensure that this makes sense. Now chosen by trial & error
169
+ if (this.properties.logoLetters) {
170
+ // Adjust to make stretched letters a bit less blurry
171
+ // A proper solution would probably be to compute gradients in the fragment shader
172
+ // to find a suitable divisor.
173
+ q /= 2;
174
+ }
175
+ return this.font.metrics.common.base / (dpr / q);
176
+ }
177
+ );
178
+
155
179
  // TODO: Use uniform block.
156
- setUniforms(this.programInfo, {
180
+ setBlockUniforms(this.markUniformInfo, {
157
181
  uPaddingX: props.paddingX,
158
182
  uPaddingY: props.paddingY,
159
183
  uFlushX: !!props.flushX,
@@ -229,23 +253,13 @@ export default class TextMark extends Mark {
229
253
  prepareRender(options) {
230
254
  const ops = super.prepareRender(options);
231
255
 
232
- let q = 0.35; // TODO: Ensure that this makes sense. Now chosen by trial & error
233
- if (this.properties.logoLetters) {
234
- // Adjust to make stretched letters a bit less blurry
235
- // A proper solution would probably be to compute gradients in the fragment shader
236
- // to find a suitable divisor.
237
- q /= 2;
238
- }
239
- const uSdfNumerator =
240
- this.font.metrics.common.base /
241
- (this.unitView.context.devicePixelRatio / q);
242
-
243
- ops.push(() =>
256
+ ops.push(() => {
244
257
  setUniforms(this.programInfo, {
245
258
  uTexture: this.font.texture,
246
- uSdfNumerator,
247
- })
248
- );
259
+ });
260
+ });
261
+
262
+ ops.push(() => this.bindOrSetMarkUniformBlock());
249
263
 
250
264
  ops.push(() =>
251
265
  setBuffersAndAttributes(
@@ -0,0 +1,30 @@
1
+ /**
2
+ * A class that manages parameters and expressions. Still a work in progress.
3
+ *
4
+ * TODO: Write tests for this class.
5
+ *
6
+ * This should eventually handle the following:
7
+ * - Parameter registration
8
+ * - Dependency tracking
9
+ * - Calling observers when a parameter changes
10
+ * - Somehow saving parameter "state" (in bookmarks)
11
+ * - Maybe something else
12
+ */
13
+ export default class ParamBroker {
14
+ /**
15
+ *
16
+ * @param {string} paramName
17
+ * @returns {(value: any) => void}
18
+ */
19
+ allocateSetter(paramName: string): (value: any) => void;
20
+ /**
21
+ * Parse expr and return a function that returns the value of the parameter.
22
+ *
23
+ * @param {string} expr
24
+ */
25
+ createExpression(expr: string): ((x: object) => any) & import("./utils/expression.js").ExpressionProps & {
26
+ addListener: (listener: () => void) => void;
27
+ };
28
+ #private;
29
+ }
30
+ //# sourceMappingURL=paramBroker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paramBroker.d.ts","sourceRoot":"","sources":["../../src/paramBroker.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH;IAyBI;;;;OAIG;IACH,0BAHW,MAAM,WACI,GAAG,KAAK,IAAI,CAqBhC;IAID;;;;OAIG;IACH,uBAFW,MAAM;gCAG6E,MAAM,IAAI,KAAK,IAAI;MA0BhH;;CACJ"}
@@ -0,0 +1,102 @@
1
+ import { isString } from "vega-util";
2
+ import createFunction from "./utils/expression.js";
3
+
4
+ /**
5
+ * A class that manages parameters and expressions. Still a work in progress.
6
+ *
7
+ * TODO: Write tests for this class.
8
+ *
9
+ * This should eventually handle the following:
10
+ * - Parameter registration
11
+ * - Dependency tracking
12
+ * - Calling observers when a parameter changes
13
+ * - Somehow saving parameter "state" (in bookmarks)
14
+ * - Maybe something else
15
+ */
16
+ export default class ParamBroker {
17
+ /** @type {Map<string, any>} */
18
+ #params;
19
+
20
+ /** @type {Set<string>} */
21
+ #allocatedSetters;
22
+
23
+ /** @type {Record<string, any>} */
24
+ #proxy;
25
+
26
+ /** @type {Map<string, Set<() => void>>} */
27
+ #paramListeners;
28
+
29
+ constructor() {
30
+ this.#params = new Map();
31
+ this.#allocatedSetters = new Set();
32
+ this.#paramListeners = new Map();
33
+
34
+ this.#proxy = new Proxy(this.#params, {
35
+ get(target, prop) {
36
+ return isString(prop) ? target.get(prop) : undefined;
37
+ },
38
+ });
39
+ }
40
+
41
+ /**
42
+ *
43
+ * @param {string} paramName
44
+ * @returns {(value: any) => void}
45
+ */
46
+ allocateSetter(paramName) {
47
+ if (this.#allocatedSetters.has(paramName)) {
48
+ throw new Error(
49
+ "Setter already allocated for parameter: " + paramName
50
+ );
51
+ }
52
+
53
+ this.#allocatedSetters.add(paramName);
54
+
55
+ return (value) => {
56
+ this.#params.set(paramName, value);
57
+
58
+ const listeners = this.#paramListeners.get(paramName);
59
+ if (listeners) {
60
+ for (const listener of listeners) {
61
+ listener();
62
+ }
63
+ }
64
+ };
65
+ }
66
+
67
+ // TODO: deallocateSetter
68
+
69
+ /**
70
+ * Parse expr and return a function that returns the value of the parameter.
71
+ *
72
+ * @param {string} expr
73
+ */
74
+ createExpression(expr) {
75
+ /** @type {import("./utils/expression.js").ExpressionFunction & { addListener: (listener: () => void) => void}} */
76
+ const fn = /** @type {any} */ (createFunction(expr, this.#proxy));
77
+
78
+ for (const g of fn.globals) {
79
+ if (!this.#allocatedSetters.has(g)) {
80
+ throw new Error(
81
+ `Unknown variable "${g}" in expression: ${expr}`
82
+ );
83
+ }
84
+ }
85
+
86
+ /**
87
+ *
88
+ * @param {() => void} listener
89
+ */
90
+ fn.addListener = (listener) => {
91
+ for (const g of fn.globals) {
92
+ const listeners = this.#paramListeners.get(g) ?? new Set();
93
+ this.#paramListeners.set(g, listeners);
94
+ listeners.add(listener);
95
+ }
96
+ };
97
+
98
+ // TODO: remove listener
99
+
100
+ return fn;
101
+ }
102
+ }
@@ -202,6 +202,29 @@ export type LazyDataParams =
202
202
  | BamData
203
203
  | Gff3Data;
204
204
 
205
+ export interface DebouncedData {
206
+ /**
207
+ * Debounce time for data updates, in milliseconds. Debouncing prevents
208
+ * excessive data updates when the user is zooming or panning around.
209
+ *
210
+ * __Default value:__ `200`
211
+ */
212
+ debounce?: number;
213
+
214
+ /**
215
+ * The debounce mode for data updates. If set to `"domain"`, domain change
216
+ * events (panning and zooming) will be debounced. If set to `"window"`,
217
+ * the data fetches initiated by the changes to the visible window (or tile)
218
+ * will be debounced. If your data is small, the `"window"` is better as
219
+ * it will start fetching data while the user is still panning around,
220
+ * resulting in a shorter perceived latency.
221
+ *
222
+ * __Default value:__ `"window"`
223
+ *
224
+ */
225
+ debounceMode?: "domain" | "window";
226
+ }
227
+
205
228
  export interface AxisTicksData {
206
229
  type: "axisTicks";
207
230
 
@@ -219,7 +242,7 @@ export interface AxisGenomeData {
219
242
  channel: PrimaryPositionalChannel;
220
243
  }
221
244
 
222
- export interface IndexedFastaData {
245
+ export interface IndexedFastaData extends DebouncedData {
223
246
  type: "indexedFasta";
224
247
 
225
248
  /**
@@ -250,7 +273,7 @@ export interface IndexedFastaData {
250
273
  windowSize?: number;
251
274
  }
252
275
 
253
- export interface BigWigData {
276
+ export interface BigWigData extends DebouncedData {
254
277
  type: "bigwig";
255
278
 
256
279
  /**
@@ -273,7 +296,7 @@ export interface BigWigData {
273
296
  pixelsPerBin?: number;
274
297
  }
275
298
 
276
- export interface BigBedData {
299
+ export interface BigBedData extends DebouncedData {
277
300
  type: "bigbed";
278
301
 
279
302
  /**
@@ -297,7 +320,7 @@ export interface BigBedData {
297
320
  windowSize?: number;
298
321
  }
299
322
 
300
- export interface BamData {
323
+ export interface BamData extends DebouncedData {
301
324
  type: "bam";
302
325
 
303
326
  /**
@@ -328,7 +351,7 @@ export interface BamData {
328
351
  windowSize?: number;
329
352
  }
330
353
 
331
- export interface TabixData {
354
+ export interface TabixData extends DebouncedData {
332
355
  /**
333
356
  * Which channel's scale domain to monitor.
334
357
  *
@@ -355,14 +378,6 @@ export interface TabixData {
355
378
  * __Default value:__ `30000000`
356
379
  */
357
380
  windowSize?: number;
358
-
359
- /**
360
- * The debounce time for domain changes, in milliseconds. Debouncing prevents
361
- * data fetches while the user is still panning around.
362
- *
363
- * __Default value:__ `200`
364
- */
365
- debounceDomainChange?: number;
366
381
  }
367
382
 
368
383
  export interface Gff3Data extends TabixData {
@@ -2,6 +2,15 @@ import { Scalar } from "./channel.js";
2
2
  import { Align, Baseline, FontStyle, FontWeight } from "./font.js";
3
3
  import { Tooltip } from "./tooltip.js";
4
4
 
5
+ // TODO: This may not be the best place for this type.
6
+ // Also, this is now similar to the ExprDef type in channel.d.ts
7
+ export interface ExprRef {
8
+ /**
9
+ * The expression string.
10
+ */
11
+ expr: string;
12
+ }
13
+
5
14
  export type MarkType = "rect" | "point" | "rule" | "text" | "link";
6
15
 
7
16
  export interface FillAndStrokeProps {
@@ -63,7 +72,7 @@ export interface RectProps extends SecondaryPositionProps {
63
72
  * **Default value:** `0`
64
73
  */
65
74
  // TODO: Rename to minCompensatedOpacity or something like that
66
- minOpacity?: number;
75
+ minOpacity?: number | ExprRef;
67
76
 
68
77
  /**
69
78
  * The minimum width of a rectangle in pixels. The property clamps rectangles'
@@ -74,49 +83,49 @@ export interface RectProps extends SecondaryPositionProps {
74
83
  *
75
84
  * **Default value:** `1`
76
85
  */
77
- minWidth?: number;
86
+ minWidth?: number | ExprRef;
78
87
 
79
88
  /**
80
89
  * The minimum height of a rectangle in pixels. The property clamps rectangles' heights.
81
90
  *
82
91
  * **Default value:** `0`
83
92
  */
84
- minHeight?: number;
93
+ minHeight?: number | ExprRef;
85
94
 
86
95
  /**
87
96
  * Radius of the rounded corners.
88
97
  *
89
98
  * **Default value:** `0`
90
99
  */
91
- cornerRadius?: number;
100
+ cornerRadius?: number | ExprRef;
92
101
 
93
102
  /**
94
103
  * Radius of the top left rounded corner. Has higher precedence than `cornerRadius`.
95
104
  *
96
105
  * **Default value:** (None)
97
106
  */
98
- cornerRadiusTopLeft?: number;
107
+ cornerRadiusTopLeft?: number | ExprRef;
99
108
 
100
109
  /**
101
110
  * Radius of the top right rounded corner. Has higher precedence than `cornerRadius`.
102
111
  *
103
112
  * **Default value:** (None)
104
113
  */
105
- cornerRadiusTopRight?: number;
114
+ cornerRadiusTopRight?: number | ExprRef;
106
115
 
107
116
  /**
108
117
  * Radius of the bottom left rounded corner. Has higher precedence than `cornerRadius`.
109
118
  *
110
119
  * **Default value:** (None)
111
120
  */
112
- cornerRadiusBottomLeft?: number;
121
+ cornerRadiusBottomLeft?: number | ExprRef;
113
122
 
114
123
  /**
115
124
  * Radius of the bottom right rounded corner. Has higher precedence than `cornerRadius`.
116
125
  *
117
126
  * **Default value:** (None)
118
127
  */
119
- cornerRadiusBottomRight?: number;
128
+ cornerRadiusBottomRight?: number | ExprRef;
120
129
  }
121
130
 
122
131
  export interface RuleProps extends SecondaryPositionProps {
@@ -126,7 +135,7 @@ export interface RuleProps extends SecondaryPositionProps {
126
135
  *
127
136
  * **Default value:** `0`
128
137
  */
129
- minLength?: number;
138
+ minLength?: number | ExprRef;
130
139
 
131
140
  /**
132
141
  * An array of of alternating stroke and gap lengths or `null` for solid strokes.
@@ -147,7 +156,7 @@ export interface RuleProps extends SecondaryPositionProps {
147
156
  *
148
157
  * **Default value:** `"butt"`
149
158
  */
150
- strokeCap?: "butt" | "square" | "round";
159
+ strokeCap?: "butt" | "square" | "round" | ExprRef;
151
160
  }
152
161
 
153
162
  export interface TextProps
@@ -333,7 +342,7 @@ export interface LinkProps extends SecondaryPositionProps {
333
342
  *
334
343
  * **Default value:** `"arc"`
335
344
  */
336
- linkShape?: "arc" | "diagonal" | "line" | "dome";
345
+ linkShape?: "arc" | "diagonal" | "line" | "dome" | ExprRef;
337
346
 
338
347
  /**
339
348
  * The orientation of the link path. Either `"vertical"` or `"horizontal"`.
@@ -341,7 +350,7 @@ export interface LinkProps extends SecondaryPositionProps {
341
350
  *
342
351
  * **Default value:** `"vertical"`
343
352
  */
344
- orient?: "vertical" | "horizontal";
353
+ orient?: "vertical" | "horizontal" | ExprRef;
345
354
 
346
355
  /**
347
356
  * Whether the apex of the `"dome"` shape is clamped to the viewport edge. When over a
@@ -350,7 +359,7 @@ export interface LinkProps extends SecondaryPositionProps {
350
359
  *
351
360
  * **Default value:** `false`
352
361
  */
353
- clampApex?: boolean;
362
+ clampApex?: boolean | ExprRef;
354
363
 
355
364
  /**
356
365
  * The number of segments in the bézier curve. Affects the rendering quality and performance.
@@ -365,14 +374,14 @@ export interface LinkProps extends SecondaryPositionProps {
365
374
  *
366
375
  * **Default value:** `1.0`
367
376
  */
368
- arcHeightFactor?: number;
377
+ arcHeightFactor?: number | ExprRef;
369
378
 
370
379
  /**
371
380
  * The minimum height of an `"arc"` shape. Makes very short links more clearly visible.
372
381
  *
373
382
  * **Default value:** `1.5`
374
383
  */
375
- minArcHeight?: number;
384
+ minArcHeight?: number | ExprRef;
376
385
 
377
386
  /**
378
387
  * The maximum length of `"arc"` shape's chord in pixels. The chord is the line segment
@@ -383,7 +392,7 @@ export interface LinkProps extends SecondaryPositionProps {
383
392
  *
384
393
  * **Default value:** `50000`
385
394
  */
386
- maxChordLength?: number;
395
+ maxChordLength?: number | ExprRef;
387
396
 
388
397
  /**
389
398
  * The range of the `"arc"` shape's fading distance in pixels. This property allows for
@@ -393,7 +402,7 @@ export interface LinkProps extends SecondaryPositionProps {
393
402
  *
394
403
  * **Default value:** `false`
395
404
  */
396
- arcFadingDistance?: [number, number] | false;
405
+ arcFadingDistance?: [number, number] | false | ExprRef;
397
406
 
398
407
  /**
399
408
  * The minimum stroke width of the links when pointing with the mouse cursor.
@@ -401,7 +410,7 @@ export interface LinkProps extends SecondaryPositionProps {
401
410
  *
402
411
  * **Default value:** `3.0`
403
412
  */
404
- minPickingSize?: number;
413
+ minPickingSize?: number | ExprRef;
405
414
  }
406
415
 
407
416
  // TODO: Mark-specific configs
@@ -463,14 +472,6 @@ export interface MarkConfig
463
472
  * This property is intended for internal use.
464
473
  */
465
474
  minBufferSize?: number;
466
-
467
- /**
468
- * Builds and index for efficient rendering of subsets of the data.
469
- * The data must be sorted by the x coordinate.
470
- *
471
- * TODO: This should be enabled automatically if the data are sorted.
472
- */
473
- buildIndex?: boolean;
474
475
  }
475
476
 
476
477
  export interface MarkConfigAndType extends MarkConfig {
@@ -7,6 +7,7 @@ import {
7
7
  PrimaryPositionalChannel,
8
8
  } from "./channel.js";
9
9
  import {
10
+ ExprRef,
10
11
  FillAndStrokeProps,
11
12
  MarkConfigAndType,
12
13
  MarkType,
@@ -43,7 +44,7 @@ export interface DynamicOpacity {
43
44
  values: number[];
44
45
  }
45
46
 
46
- export type ViewOpacityDef = number | DynamicOpacity;
47
+ export type ViewOpacityDef = number | DynamicOpacity | ExprRef;
47
48
 
48
49
  export interface Step {
49
50
  step: number;
@@ -1,3 +1,3 @@
1
1
  export default css;
2
- declare const css: ".genome-spy {\n font-family: system-ui, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n position: relative;\n}\n.genome-spy canvas {\n transform: scale(1, 1);\n opacity: 1;\n transition: transform 0.6s, opacity 0.6s;\n}\n.genome-spy .loading-message {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n right: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.genome-spy .loading-message .message {\n color: #666;\n opacity: 0;\n transition: opacity 0.7s;\n}\n.genome-spy.loading canvas {\n transform: scale(0.95, 0.95);\n opacity: 0;\n}\n.genome-spy.loading .loading-message .message {\n opacity: 1;\n}\n.genome-spy.loading .ellipsis {\n animation: blinker 1s linear infinite;\n}\n@keyframes blinker {\n 50% {\n opacity: 0;\n }\n}\n.genome-spy .tooltip {\n position: absolute;\n max-width: 450px;\n overflow: hidden;\n background: #f6f6f6;\n padding: 10px;\n font-size: 13px;\n box-shadow: 0px 3px 15px 0px rgba(0, 0, 0, 0.21);\n pointer-events: none;\n z-index: 100;\n}\n.genome-spy .tooltip > :last-child {\n margin-bottom: 0;\n}\n.genome-spy .tooltip > .title {\n padding-bottom: 5px;\n margin-bottom: 5px;\n border-bottom: 1px dashed #b6b6b6;\n}\n.genome-spy .tooltip .summary {\n font-size: 12px;\n}\n.genome-spy .tooltip table {\n border-collapse: collapse;\n}\n.genome-spy .tooltip table:first-child {\n margin-top: 0;\n}\n.genome-spy .tooltip table th,\n.genome-spy .tooltip table td {\n padding: 2px 0.4em;\n vertical-align: top;\n}\n.genome-spy .tooltip table th:first-child,\n.genome-spy .tooltip table td:first-child {\n padding-left: 0;\n}\n.genome-spy .tooltip table th {\n text-align: left;\n font-weight: bold;\n}\n.genome-spy .tooltip .color-legend {\n display: inline-block;\n width: 0.8em;\n height: 0.8em;\n margin-left: 0.4em;\n box-shadow: 0px 0px 3px 1px white;\n}\n.genome-spy .tooltip .attributes .hovered {\n background-color: #e0e0e0;\n}\n.genome-spy .tooltip .na {\n color: #aaa;\n font-style: italic;\n font-size: 80%;\n}\n.genome-spy .gene-track-tooltip .summary {\n font-size: 90%;\n}\n.genome-spy .message-box {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n top: 0;\n height: 100%;\n width: 100%;\n}\n.genome-spy .message-box > div {\n border: 1px solid red;\n padding: 10px;\n background: #fff0f0;\n}";
2
+ declare const css: ".genome-spy {\n font-family: system-ui, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n position: relative;\n}\n.genome-spy canvas {\n transform: scale(1, 1);\n opacity: 1;\n transition: transform 0.6s, opacity 0.6s;\n}\n.genome-spy .loading-message {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.genome-spy .loading-message .message {\n color: #666;\n opacity: 0;\n transition: opacity 0.7s;\n}\n.genome-spy.loading canvas {\n transform: scale(0.95, 0.95);\n opacity: 0;\n}\n.genome-spy.loading .loading-message .message {\n opacity: 1;\n}\n.genome-spy.loading .ellipsis {\n animation: blinker 1s linear infinite;\n}\n@keyframes blinker {\n 50% {\n opacity: 0;\n }\n}\n.genome-spy .loading-indicators {\n position: absolute;\n inset: 0;\n user-select: none;\n pointer-events: none;\n}\n.genome-spy .loading-indicators div {\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.genome-spy .loading-indicators div > div {\n font-size: 11px;\n transition: opacity 0.2s;\n background: white;\n padding: 2px 5px;\n display: flex;\n border-radius: 3px;\n gap: 0.5em;\n opacity: 0;\n}\n.genome-spy .loading-indicators div > div.loading {\n opacity: 0.5;\n}\n.genome-spy .loading-indicators div > div > * {\n display: block;\n}\n.genome-spy .loading-indicators div > div img {\n width: 1.5em;\n height: 1.5em;\n}\n.genome-spy .tooltip {\n position: absolute;\n max-width: 450px;\n overflow: hidden;\n background: #f6f6f6;\n padding: 10px;\n font-size: 13px;\n box-shadow: 0px 3px 15px 0px rgba(0, 0, 0, 0.21);\n pointer-events: none;\n z-index: 100;\n}\n.genome-spy .tooltip > :last-child {\n margin-bottom: 0;\n}\n.genome-spy .tooltip > .title {\n padding-bottom: 5px;\n margin-bottom: 5px;\n border-bottom: 1px dashed #b6b6b6;\n}\n.genome-spy .tooltip .summary {\n font-size: 12px;\n}\n.genome-spy .tooltip table {\n border-collapse: collapse;\n}\n.genome-spy .tooltip table:first-child {\n margin-top: 0;\n}\n.genome-spy .tooltip table th,\n.genome-spy .tooltip table td {\n padding: 2px 0.4em;\n vertical-align: top;\n}\n.genome-spy .tooltip table th:first-child,\n.genome-spy .tooltip table td:first-child {\n padding-left: 0;\n}\n.genome-spy .tooltip table th {\n text-align: left;\n font-weight: bold;\n}\n.genome-spy .tooltip .color-legend {\n display: inline-block;\n width: 0.8em;\n height: 0.8em;\n margin-left: 0.4em;\n box-shadow: 0px 0px 3px 1px white;\n}\n.genome-spy .tooltip .attributes .hovered {\n background-color: #e0e0e0;\n}\n.genome-spy .tooltip .na {\n color: #aaa;\n font-style: italic;\n font-size: 80%;\n}\n.genome-spy .gene-track-tooltip .summary {\n font-size: 90%;\n}\n.genome-spy .message-box {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n top: 0;\n height: 100%;\n width: 100%;\n}\n.genome-spy .message-box > div {\n border: 1px solid red;\n padding: 10px;\n background: #fff0f0;\n}";
3
3
  //# sourceMappingURL=genome-spy.css.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"genome-spy.css.d.ts","sourceRoot":"","sources":["../../../src/styles/genome-spy.css.js"],"names":[],"mappings":";AAAA,q6EA+GG"}
1
+ {"version":3,"file":"genome-spy.css.d.ts","sourceRoot":"","sources":["../../../src/styles/genome-spy.css.js"],"names":[],"mappings":";AAAA,0jGA4IG"}
@@ -9,10 +9,7 @@ const css = `.genome-spy {
9
9
  }
10
10
  .genome-spy .loading-message {
11
11
  position: absolute;
12
- top: 0;
13
- bottom: 0;
14
- left: 0;
15
- right: 0;
12
+ inset: 0;
16
13
  display: flex;
17
14
  align-items: center;
18
15
  justify-content: center;
@@ -37,6 +34,38 @@ const css = `.genome-spy {
37
34
  opacity: 0;
38
35
  }
39
36
  }
37
+ .genome-spy .loading-indicators {
38
+ position: absolute;
39
+ inset: 0;
40
+ user-select: none;
41
+ pointer-events: none;
42
+ }
43
+ .genome-spy .loading-indicators div {
44
+ position: absolute;
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ }
49
+ .genome-spy .loading-indicators div > div {
50
+ font-size: 11px;
51
+ transition: opacity 0.2s;
52
+ background: white;
53
+ padding: 2px 5px;
54
+ display: flex;
55
+ border-radius: 3px;
56
+ gap: 0.5em;
57
+ opacity: 0;
58
+ }
59
+ .genome-spy .loading-indicators div > div.loading {
60
+ opacity: 0.5;
61
+ }
62
+ .genome-spy .loading-indicators div > div > * {
63
+ display: block;
64
+ }
65
+ .genome-spy .loading-indicators div > div img {
66
+ width: 1.5em;
67
+ height: 1.5em;
68
+ }
40
69
  .genome-spy .tooltip {
41
70
  position: absolute;
42
71
  max-width: 450px;
@@ -18,10 +18,7 @@ $font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
18
18
 
19
19
  .loading-message {
20
20
  position: absolute;
21
- top: 0;
22
- bottom: 0;
23
- left: 0;
24
- right: 0;
21
+ inset: 0;
25
22
  display: flex;
26
23
 
27
24
  align-items: center;
@@ -55,6 +52,45 @@ $font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
55
52
  }
56
53
  }
57
54
 
55
+ .loading-indicators {
56
+ position: absolute;
57
+ inset: 0;
58
+
59
+ user-select: none;
60
+ pointer-events: none;
61
+
62
+ div {
63
+ position: absolute;
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: center;
67
+
68
+ > div {
69
+ font-size: 11px;
70
+ transition: opacity 0.2s;
71
+ background: white;
72
+ padding: 2px 5px;
73
+ display: flex;
74
+ border-radius: 3px;
75
+ gap: 0.5em;
76
+ opacity: 0;
77
+
78
+ &.loading {
79
+ opacity: 0.5;
80
+ }
81
+
82
+ > * {
83
+ display: block;
84
+ }
85
+
86
+ img {
87
+ width: 1.5em;
88
+ height: 1.5em;
89
+ }
90
+ }
91
+ }
92
+ }
93
+
58
94
  .tooltip {
59
95
  position: absolute;
60
96
 
@@ -11,6 +11,7 @@ import { Datum } from "../data/flowNode.js";
11
11
  import { ImportSpec, ViewSpec } from "../spec/view.js";
12
12
  import ContainerView from "./containerView.js";
13
13
  import { BroadcastEventType } from "../genomeSpy.js";
14
+ import ParamBroker from "../paramBroker.js";
14
15
 
15
16
  export interface Hover {
16
17
  mark: Mark;
@@ -28,6 +29,7 @@ export default interface ViewContext {
28
29
  genomeStore?: GenomeStore;
29
30
  fontManager: BmFontManager;
30
31
 
32
+ paramBroker: ParamBroker;
31
33
  devicePixelRatio: number;
32
34
 
33
35
  requestLayoutReflow: () => void;
@@ -68,6 +70,15 @@ export default interface ViewContext {
68
70
 
69
71
  getNamedDataFromProvider: (name: string) => any[];
70
72
 
73
+ /**
74
+ * Allows lazy data sources to signal that they are loading data.
75
+ * The status is shown in the UI somewhere within or near the view.
76
+ *
77
+ * @param view The view where the data source is located.
78
+ * @param status true if loading, false if not loading.
79
+ */
80
+ setDataLoadingStatus: (view: View, status: boolean) => void;
81
+
71
82
  /**
72
83
  * Returns true if the view is configured to be visible.
73
84
  * N.B. This does NOT consider ancestors' visibility.
@@ -9,6 +9,8 @@
9
9
  * A binned index for (overlapping) ranges that are sorted by their start position.
10
10
  * Each indexed range is associated with respective vertex indices.
11
11
  *
12
+ * The indexing scheme is somewhat similar to Tabix (https://academic.oup.com/bioinformatics/article/27/5/718/262743).
13
+ *
12
14
  * @param {number} size Number of bins
13
15
  * @param {[number, number]} domain Domain of positions
14
16
  * @param {(datum: T) => number} accessor Accessor for range's start position
@@ -1 +1 @@
1
- {"version":3,"file":"binnedIndex.d.ts","sourceRoot":"","sources":["../../../src/utils/binnedIndex.js"],"names":[],"mappings":"AAKA;;;;;;GAMG;AAEH;;;;;;;;;GASG;AACH,mDANW,MAAM,UACN,CAAC,MAAM,EAAE,MAAM,CAAC,0BACF,MAAM,4BACN,MAAM;iCAyChB,MAAM,kBACN,MAAM;;EAwGpB;6BA/JU,MAAM,OACN,MAAM,QACN,CAAC,MAAM,EAAE,MAAM,CAAC,KACd,CAAC,MAAM,EAAE,MAAM,CAAC"}
1
+ {"version":3,"file":"binnedIndex.d.ts","sourceRoot":"","sources":["../../../src/utils/binnedIndex.js"],"names":[],"mappings":"AAKA;;;;;;GAMG;AAEH;;;;;;;;;;;GAWG;AACH,mDANW,MAAM,UACN,CAAC,MAAM,EAAE,MAAM,CAAC,0BACF,MAAM,4BACN,MAAM;iCA2ChB,MAAM,kBACN,MAAM;oBAsHJ,MAAM;EA+BtB;6BAhNU,MAAM,OACN,MAAM,QACN,CAAC,MAAM,EAAE,MAAM,CAAC,KACd,CAAC,MAAM,EAAE,MAAM,CAAC"}