@genome-spy/core 0.74.0 → 0.75.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 +4660 -4468
- package/dist/bundle/index.js +81 -81
- package/dist/schema.json +220 -12
- package/dist/src/data/sources/dataUtils.d.ts +25 -0
- package/dist/src/data/sources/dataUtils.d.ts.map +1 -1
- package/dist/src/data/sources/dataUtils.js +23 -0
- package/dist/src/data/sources/inlineSource.js +2 -2
- package/dist/src/data/sources/urlSource.d.ts.map +1 -1
- package/dist/src/data/sources/urlSource.js +8 -3
- package/dist/src/encoder/encoder.d.ts +2 -2
- package/dist/src/encoder/encoder.d.ts.map +1 -1
- package/dist/src/genome/scaleLocus.d.ts.map +1 -1
- package/dist/src/genome/scaleLocus.js +8 -3
- package/dist/src/genomeSpy/interactionController.d.ts.map +1 -1
- package/dist/src/genomeSpy/interactionController.js +91 -51
- package/dist/src/gl/dataToVertices.d.ts +12 -14
- package/dist/src/gl/dataToVertices.d.ts.map +1 -1
- package/dist/src/gl/dataToVertices.js +116 -95
- package/dist/src/gl/glslScaleGenerator.d.ts +3 -0
- package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
- package/dist/src/gl/glslScaleGenerator.js +10 -8
- package/dist/src/gl/vertexRangeIndex.d.ts +23 -0
- package/dist/src/gl/vertexRangeIndex.d.ts.map +1 -0
- package/dist/src/gl/vertexRangeIndex.js +150 -0
- package/dist/src/marks/mark.d.ts +1 -1
- package/dist/src/paramRuntime/expressionCompiler.d.ts +2 -1
- package/dist/src/paramRuntime/expressionCompiler.d.ts.map +1 -1
- package/dist/src/paramRuntime/expressionCompiler.js +3 -2
- package/dist/src/paramRuntime/expressionRef.d.ts +4 -1
- package/dist/src/paramRuntime/expressionRef.d.ts.map +1 -1
- package/dist/src/paramRuntime/expressionRef.js +10 -3
- package/dist/src/paramRuntime/graphRuntime.d.ts.map +1 -1
- package/dist/src/paramRuntime/graphRuntime.js +15 -6
- package/dist/src/paramRuntime/paramRuntime.d.ts +8 -2
- package/dist/src/paramRuntime/paramRuntime.d.ts.map +1 -1
- package/dist/src/paramRuntime/paramRuntime.js +10 -5
- package/dist/src/paramRuntime/types.d.ts +1 -0
- package/dist/src/paramRuntime/types.d.ts.map +1 -1
- package/dist/src/paramRuntime/types.js +1 -0
- package/dist/src/paramRuntime/viewParamRuntime.d.ts +5 -4
- package/dist/src/paramRuntime/viewParamRuntime.d.ts.map +1 -1
- package/dist/src/paramRuntime/viewParamRuntime.js +17 -6
- package/dist/src/scale/scale.d.ts.map +1 -1
- package/dist/src/scale/scale.js +1 -0
- package/dist/src/scales/domainPlanner.d.ts +57 -11
- package/dist/src/scales/domainPlanner.d.ts.map +1 -1
- package/dist/src/scales/domainPlanner.js +182 -83
- package/dist/src/scales/scaleInstanceManager.d.ts.map +1 -1
- package/dist/src/scales/scaleInstanceManager.js +7 -2
- package/dist/src/scales/scalePropsResolver.d.ts +3 -3
- package/dist/src/scales/scalePropsResolver.d.ts.map +1 -1
- package/dist/src/scales/scalePropsResolver.js +28 -5
- package/dist/src/scales/scaleResolution.d.ts +12 -1
- package/dist/src/scales/scaleResolution.d.ts.map +1 -1
- package/dist/src/scales/scaleResolution.js +171 -18
- package/dist/src/screenshotExport.d.ts +23 -0
- package/dist/src/screenshotExport.d.ts.map +1 -0
- package/dist/src/screenshotExport.js +44 -0
- package/dist/src/screenshotHarness.d.ts.map +1 -1
- package/dist/src/screenshotHarness.js +26 -24
- package/dist/src/spec/axis.d.ts +2 -2
- package/dist/src/spec/channel.d.ts +4 -4
- package/dist/src/spec/data.d.ts +12 -0
- package/dist/src/spec/scale.d.ts +13 -1
- package/dist/src/utils/expression.d.ts +16 -8
- package/dist/src/utils/expression.d.ts.map +1 -1
- package/dist/src/utils/expression.js +291 -11
- package/dist/src/view/flowBuilder.d.ts +1 -1
- package/dist/src/view/flowBuilder.d.ts.map +1 -1
- package/dist/src/view/flowBuilder.js +11 -7
- package/dist/src/view/resolutionPlanner.d.ts +9 -0
- package/dist/src/view/resolutionPlanner.d.ts.map +1 -0
- package/dist/src/view/resolutionPlanner.js +302 -0
- package/dist/src/view/unitView.d.ts +1 -1
- package/dist/src/view/unitView.d.ts.map +1 -1
- package/dist/src/view/unitView.js +5 -152
- package/dist/src/view/view.d.ts.map +1 -1
- package/dist/src/view/view.js +2 -1
- package/package.json +2 -2
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
resolveIntervalSelectionBinding,
|
|
12
12
|
} from "./selectionDomainUtils.js";
|
|
13
13
|
import createDomain from "../utils/domainArray.js";
|
|
14
|
+
import { isExprRef } from "../paramRuntime/paramUtils.js";
|
|
14
15
|
import { getAccessorDomainKey, isScaleAccessor } from "../encoder/accessor.js";
|
|
15
16
|
import { getEncoderAccessors, getPrimaryChannel } from "../encoder/encoder.js";
|
|
16
17
|
import {
|
|
@@ -18,12 +19,45 @@ import {
|
|
|
18
19
|
isChromosomalLocusInterval,
|
|
19
20
|
} from "../genome/genome.js";
|
|
20
21
|
|
|
22
|
+
/*
|
|
23
|
+
* Domain planning decides what domain a shared scale should use before the
|
|
24
|
+
* scale instance is configured.
|
|
25
|
+
*
|
|
26
|
+
* "Planning" means collecting the participating members, separating literal
|
|
27
|
+
* configured domains from selection-driven domains, validating that the shared
|
|
28
|
+
* scale is not asked to mix incompatible sources, and producing the final union
|
|
29
|
+
* that will be applied to the scale.
|
|
30
|
+
*/
|
|
31
|
+
|
|
21
32
|
/**
|
|
22
33
|
* @typedef {import("../utils/domainArray.js").DomainArray} DomainArray
|
|
23
34
|
* @typedef {import("../spec/scale.js").ComplexDomain} ComplexDomain
|
|
24
35
|
* @typedef {import("../spec/scale.js").ScalarDomain} ScalarDomain
|
|
25
36
|
* @typedef {import("../spec/scale.js").SelectionDomainRef} SelectionDomainRef
|
|
37
|
+
* @typedef {import("../spec/parameter.js").ExprRef} ExprRef
|
|
26
38
|
* @typedef {import("./scaleResolution.js").ScaleResolutionMember} ScaleResolutionMember
|
|
39
|
+
* @typedef {() => Set<ScaleResolutionMember>} ScaleMembersGetter
|
|
40
|
+
* @typedef {(interval: ScalarDomain | ComplexDomain) => number[]} FromComplexInterval
|
|
41
|
+
* @typedef {(assembly: import("../spec/scale.js").Scale["assembly"] | undefined) => number[]} GetLocusExtent
|
|
42
|
+
* @typedef {{
|
|
43
|
+
* domains: DomainArray[],
|
|
44
|
+
* selectionRef: SelectionDomainLinkInfo | undefined,
|
|
45
|
+
* selectionRuntime: any,
|
|
46
|
+
* selectionDescription: string | undefined,
|
|
47
|
+
* hasLiteralDomain: boolean,
|
|
48
|
+
* }} ConfiguredDomainResolutionState
|
|
49
|
+
* @typedef {{
|
|
50
|
+
* kind: "literal",
|
|
51
|
+
* domain: DomainArray,
|
|
52
|
+
* } | {
|
|
53
|
+
* kind: "selection",
|
|
54
|
+
* domain: DomainArray | undefined,
|
|
55
|
+
* description: string,
|
|
56
|
+
* param: string,
|
|
57
|
+
* encoding: "x" | "y",
|
|
58
|
+
* hasInitial: boolean,
|
|
59
|
+
* runtime: any,
|
|
60
|
+
* }} ConfiguredDomainMemberResolution
|
|
27
61
|
* @typedef {{
|
|
28
62
|
* param: string,
|
|
29
63
|
* encoding: "x" | "y",
|
|
@@ -33,22 +67,22 @@ import {
|
|
|
33
67
|
*/
|
|
34
68
|
|
|
35
69
|
export default class DomainPlanner {
|
|
36
|
-
/** @type {
|
|
37
|
-
#
|
|
70
|
+
/** @type {ScaleMembersGetter} */
|
|
71
|
+
#getActiveMembers;
|
|
38
72
|
|
|
39
|
-
/** @type {
|
|
73
|
+
/** @type {ScaleMembersGetter} */
|
|
40
74
|
#getAllMembers;
|
|
41
75
|
|
|
42
|
-
/** @type {
|
|
76
|
+
/** @type {ScaleMembersGetter} */
|
|
43
77
|
#getDataMembers;
|
|
44
78
|
|
|
45
79
|
/** @type {() => import("../spec/channel.js").Type} */
|
|
46
80
|
#getType;
|
|
47
81
|
|
|
48
|
-
/** @type {
|
|
82
|
+
/** @type {GetLocusExtent} */
|
|
49
83
|
#getLocusExtent;
|
|
50
84
|
|
|
51
|
-
/** @type {
|
|
85
|
+
/** @type {FromComplexInterval} */
|
|
52
86
|
#fromComplexInterval;
|
|
53
87
|
|
|
54
88
|
/** @type {any[]} */
|
|
@@ -67,24 +101,24 @@ export default class DomainPlanner {
|
|
|
67
101
|
|
|
68
102
|
/**
|
|
69
103
|
* @param {object} options
|
|
70
|
-
* @param {
|
|
71
|
-
* @param {
|
|
72
|
-
* @param {
|
|
104
|
+
* @param {ScaleMembersGetter} options.getActiveMembers Active shared-scale members used for configured domain planning.
|
|
105
|
+
* @param {ScaleMembersGetter} [options.getAllMembers] All members, including inactive ones, used for conflict validation.
|
|
106
|
+
* @param {ScaleMembersGetter} [options.getDataMembers] Members used for data-domain extraction; defaults to `getActiveMembers`.
|
|
73
107
|
* @param {() => import("../spec/channel.js").Type} options.getType
|
|
74
|
-
* @param {
|
|
75
|
-
* @param {
|
|
108
|
+
* @param {GetLocusExtent} options.getLocusExtent
|
|
109
|
+
* @param {FromComplexInterval} options.fromComplexInterval
|
|
76
110
|
*/
|
|
77
111
|
constructor({
|
|
78
|
-
|
|
112
|
+
getActiveMembers,
|
|
79
113
|
getAllMembers,
|
|
80
114
|
getDataMembers,
|
|
81
115
|
getType,
|
|
82
116
|
getLocusExtent,
|
|
83
117
|
fromComplexInterval,
|
|
84
118
|
}) {
|
|
85
|
-
this.#
|
|
86
|
-
this.#getAllMembers = getAllMembers ??
|
|
87
|
-
this.#getDataMembers = getDataMembers ??
|
|
119
|
+
this.#getActiveMembers = getActiveMembers;
|
|
120
|
+
this.#getAllMembers = getAllMembers ?? getActiveMembers;
|
|
121
|
+
this.#getDataMembers = getDataMembers ?? getActiveMembers;
|
|
88
122
|
this.#getType = getType;
|
|
89
123
|
this.#getLocusExtent = getLocusExtent;
|
|
90
124
|
this.#fromComplexInterval = fromComplexInterval;
|
|
@@ -147,10 +181,13 @@ export default class DomainPlanner {
|
|
|
147
181
|
* @returns {any[]}
|
|
148
182
|
*/
|
|
149
183
|
getDefaultDomain(extractDataDomain = false, locusAssembly) {
|
|
184
|
+
const type = this.#getType();
|
|
150
185
|
return resolveDefaultDomain(
|
|
151
|
-
|
|
186
|
+
type,
|
|
152
187
|
this.#getLocusExtent,
|
|
153
|
-
extractDataDomain
|
|
188
|
+
extractDataDomain && type !== LOCUS
|
|
189
|
+
? this.getDataDomain()
|
|
190
|
+
: undefined,
|
|
154
191
|
locusAssembly
|
|
155
192
|
);
|
|
156
193
|
}
|
|
@@ -194,7 +231,7 @@ export default class DomainPlanner {
|
|
|
194
231
|
}
|
|
195
232
|
|
|
196
233
|
const configuredDomain = resolveConfiguredDomain(
|
|
197
|
-
this.#
|
|
234
|
+
this.#getActiveMembers(),
|
|
198
235
|
this.#fromComplexInterval,
|
|
199
236
|
includeSelectionInitial
|
|
200
237
|
);
|
|
@@ -298,91 +335,153 @@ function resolveConfiguredDomain(
|
|
|
298
335
|
.filter((member) => member.contributesToDomain)
|
|
299
336
|
.filter((member) => member.channelDef.scale?.domain);
|
|
300
337
|
|
|
301
|
-
/** @type {
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
let selectionRef = undefined;
|
|
310
|
-
let hasLiteralDomain = false;
|
|
338
|
+
/** @type {ConfiguredDomainResolutionState} */
|
|
339
|
+
const state = {
|
|
340
|
+
domains: [],
|
|
341
|
+
selectionRef: undefined,
|
|
342
|
+
selectionRuntime: undefined,
|
|
343
|
+
selectionDescription: undefined,
|
|
344
|
+
hasLiteralDomain: false,
|
|
345
|
+
};
|
|
311
346
|
|
|
312
347
|
for (const member of domainMembers) {
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
348
|
+
const resolved = resolveConfiguredDomainMember(
|
|
349
|
+
member,
|
|
350
|
+
fromComplexInterval,
|
|
351
|
+
includeSelectionInitial
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
if (resolved.kind === "selection") {
|
|
355
|
+
mergeSelectionConfiguredDomain(state, resolved);
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
320
358
|
|
|
321
|
-
|
|
359
|
+
mergeLiteralConfiguredDomain(state, resolved);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return finishConfiguredDomainResolution(state);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* @param {ScaleResolutionMember} member
|
|
367
|
+
* @param {(interval: ScalarDomain | ComplexDomain) => number[]} fromComplexInterval
|
|
368
|
+
* @param {boolean} includeSelectionInitial
|
|
369
|
+
* @returns {ConfiguredDomainMemberResolution}
|
|
370
|
+
*/
|
|
371
|
+
function resolveConfiguredDomainMember(
|
|
372
|
+
member,
|
|
373
|
+
fromComplexInterval,
|
|
374
|
+
includeSelectionInitial
|
|
375
|
+
) {
|
|
376
|
+
const domainDef = member.channelDef.scale.domain;
|
|
377
|
+
if (isSelectionDomainRef(domainDef)) {
|
|
378
|
+
return {
|
|
379
|
+
kind: "selection",
|
|
380
|
+
...resolveSelectionDomain(
|
|
322
381
|
member,
|
|
323
382
|
domainDef,
|
|
324
383
|
fromComplexInterval,
|
|
325
384
|
includeSelectionInitial
|
|
326
|
-
)
|
|
385
|
+
),
|
|
386
|
+
};
|
|
387
|
+
}
|
|
327
388
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
resolved.description +
|
|
339
|
-
"."
|
|
340
|
-
);
|
|
341
|
-
}
|
|
389
|
+
if (isExprRef(domainDef)) {
|
|
390
|
+
return {
|
|
391
|
+
kind: "literal",
|
|
392
|
+
domain: resolveConfiguredIntervalDomain(
|
|
393
|
+
member.channelDef.type,
|
|
394
|
+
member.view.paramRuntime.createExpression(domainDef.expr)(),
|
|
395
|
+
fromComplexInterval
|
|
396
|
+
),
|
|
397
|
+
};
|
|
398
|
+
}
|
|
342
399
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
if (resolved.domain) {
|
|
354
|
-
domains.push(resolved.domain);
|
|
355
|
-
}
|
|
356
|
-
continue;
|
|
357
|
-
}
|
|
400
|
+
return {
|
|
401
|
+
kind: "literal",
|
|
402
|
+
domain: resolveConfiguredIntervalDomain(
|
|
403
|
+
member.channelDef.type,
|
|
404
|
+
domainDef,
|
|
405
|
+
fromComplexInterval
|
|
406
|
+
),
|
|
407
|
+
};
|
|
408
|
+
}
|
|
358
409
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
410
|
+
/**
|
|
411
|
+
* @param {ConfiguredDomainResolutionState} state
|
|
412
|
+
* @param {Extract<ConfiguredDomainMemberResolution, { kind: "selection" }>} resolved
|
|
413
|
+
*/
|
|
414
|
+
function mergeSelectionConfiguredDomain(state, resolved) {
|
|
415
|
+
if (state.hasLiteralDomain) {
|
|
416
|
+
throw new Error(
|
|
417
|
+
"Cannot mix selection-driven and literal configured domains on a shared scale."
|
|
418
|
+
);
|
|
419
|
+
}
|
|
364
420
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
421
|
+
if (
|
|
422
|
+
state.selectionRef &&
|
|
423
|
+
(state.selectionRef.runtime !== resolved.runtime ||
|
|
424
|
+
state.selectionRef.param !== resolved.param ||
|
|
425
|
+
state.selectionRef.encoding !== resolved.encoding)
|
|
426
|
+
) {
|
|
427
|
+
throw new Error(
|
|
428
|
+
"Conflicting selection domain references on a shared scale: " +
|
|
429
|
+
state.selectionDescription +
|
|
430
|
+
" vs " +
|
|
431
|
+
resolved.description +
|
|
432
|
+
"."
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
state.selectionRuntime = resolved.runtime;
|
|
437
|
+
state.selectionDescription = resolved.description;
|
|
438
|
+
state.selectionRef = {
|
|
439
|
+
param: resolved.param,
|
|
440
|
+
encoding: resolved.encoding,
|
|
441
|
+
hasInitial:
|
|
442
|
+
(state.selectionRef?.hasInitial ?? false) || resolved.hasInitial,
|
|
443
|
+
runtime: resolved.runtime,
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
if (resolved.domain) {
|
|
447
|
+
state.domains.push(resolved.domain);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* @param {ConfiguredDomainResolutionState} state
|
|
453
|
+
* @param {Extract<ConfiguredDomainMemberResolution, { kind: "literal" }>} resolved
|
|
454
|
+
*/
|
|
455
|
+
function mergeLiteralConfiguredDomain(state, resolved) {
|
|
456
|
+
if (state.selectionRuntime) {
|
|
457
|
+
throw new Error(
|
|
458
|
+
"Cannot mix literal configured domains with selection-driven domains on a shared scale."
|
|
372
459
|
);
|
|
373
460
|
}
|
|
374
461
|
|
|
375
|
-
|
|
462
|
+
state.hasLiteralDomain = true;
|
|
463
|
+
state.domains.push(resolved.domain);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* @param {ConfiguredDomainResolutionState} state
|
|
468
|
+
* @returns {{
|
|
469
|
+
* domain: DomainArray | undefined,
|
|
470
|
+
* selectionRef: SelectionDomainLinkInfo | undefined,
|
|
471
|
+
* }}
|
|
472
|
+
*/
|
|
473
|
+
function finishConfiguredDomainResolution(state) {
|
|
474
|
+
if (state.domains.length > 0) {
|
|
376
475
|
return {
|
|
377
|
-
domain: domains.reduce((acc, curr) => acc.extendAll(curr)),
|
|
378
|
-
selectionRef,
|
|
476
|
+
domain: state.domains.reduce((acc, curr) => acc.extendAll(curr)),
|
|
477
|
+
selectionRef: state.selectionRef,
|
|
379
478
|
};
|
|
380
479
|
}
|
|
381
480
|
|
|
382
|
-
if (
|
|
481
|
+
if (state.selectionRuntime) {
|
|
383
482
|
// Selection refs are still the source of truth even when the
|
|
384
483
|
// selection interval currently resolves to no domain.
|
|
385
|
-
return { domain: undefined, selectionRef };
|
|
484
|
+
return { domain: undefined, selectionRef: state.selectionRef };
|
|
386
485
|
}
|
|
387
486
|
|
|
388
487
|
return { domain: undefined, selectionRef: undefined };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaleInstanceManager.d.ts","sourceRoot":"","sources":["../../../src/scales/scaleInstanceManager.js"],"names":[],"mappings":"AAMA;IA0BI;;;;;;OAMG;IACH,iFALG;QAAkH,eAAe,EAAzH,MAAM;YAAE,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,0BAA0B,EAAE,eAAe,CAAA;SAAE;QAC5E,aAAa,EAAjC,MAAM,IAAI;QACW,cAAc,GAAnC,MAAM,IAAI;QAC6D,cAAc,GAArF,MAAM,OAAO,0BAA0B,EAAE,OAAO,GAAG,SAAS;KAA0B,EAYhG;IAED;eA1CkC,OAAO,kBAAkB,EAAE,KAAK;MA4CjE;IAED;;;OAGG;IACH,0BAHW,OAAO,kBAAkB,EAAE,KAAK,CAAC,UAAU,CAAC,GAC1C,OAAO,qBAAqB,EAAE,OAAO,CAajD;IAED;;;OAGG;IACH,mBAHW,OAAO,kBAAkB,EAAE,KAAK;eAhET,OAAO,kBAAkB,EAAE,KAAK;MAqFjE;IAcD;;OAEG;IACH,wBAFW,OAAO,kBAAkB,EAAE,KAAK,QAc1C;IAED;;;OAGG;IACH,4CAHW,MAAM,IAAI,GACR,IAAI,CAShB;
|
|
1
|
+
{"version":3,"file":"scaleInstanceManager.d.ts","sourceRoot":"","sources":["../../../src/scales/scaleInstanceManager.js"],"names":[],"mappings":"AAMA;IA0BI;;;;;;OAMG;IACH,iFALG;QAAkH,eAAe,EAAzH,MAAM;YAAE,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,0BAA0B,EAAE,eAAe,CAAA;SAAE;QAC5E,aAAa,EAAjC,MAAM,IAAI;QACW,cAAc,GAAnC,MAAM,IAAI;QAC6D,cAAc,GAArF,MAAM,OAAO,0BAA0B,EAAE,OAAO,GAAG,SAAS;KAA0B,EAYhG;IAED;eA1CkC,OAAO,kBAAkB,EAAE,KAAK;MA4CjE;IAED;;;OAGG;IACH,0BAHW,OAAO,kBAAkB,EAAE,KAAK,CAAC,UAAU,CAAC,GAC1C,OAAO,qBAAqB,EAAE,OAAO,CAajD;IAED;;;OAGG;IACH,mBAHW,OAAO,kBAAkB,EAAE,KAAK;eAhET,OAAO,kBAAkB,EAAE,KAAK;MAqFjE;IAcD;;OAEG;IACH,wBAFW,OAAO,kBAAkB,EAAE,KAAK,QAc1C;IAED;;;OAGG;IACH,4CAHW,MAAM,IAAI,GACR,IAAI,CAShB;IAwFD,gBAGC;;CACJ"}
|
|
@@ -147,10 +147,12 @@ export default class ScaleInstanceManager {
|
|
|
147
147
|
const {
|
|
148
148
|
assembly: _assembly,
|
|
149
149
|
domainIndexer: _domainIndexer,
|
|
150
|
+
__rangeExprScope: _rangeExprScope,
|
|
150
151
|
...rest
|
|
151
152
|
} = propsAny;
|
|
152
153
|
void _assembly;
|
|
153
154
|
void _domainIndexer;
|
|
155
|
+
void _rangeExprScope;
|
|
154
156
|
return rest;
|
|
155
157
|
}
|
|
156
158
|
|
|
@@ -168,11 +170,14 @@ export default class ScaleInstanceManager {
|
|
|
168
170
|
this.#rangeExprRefListeners.forEach((fn) => fn.invalidate());
|
|
169
171
|
this.#rangeExprRefListeners.clear();
|
|
170
172
|
|
|
173
|
+
const rangeExprScope = /** @type {any} */ (props).__rangeExprScope;
|
|
174
|
+
const paramRuntime =
|
|
175
|
+
rangeExprScope?.paramRuntime ?? this.#getParamRuntime();
|
|
176
|
+
|
|
171
177
|
const resolved = resolveRange({
|
|
172
178
|
range: props.range,
|
|
173
179
|
reverse: props.reverse,
|
|
174
|
-
createExpression: (expr) =>
|
|
175
|
-
this.#getParamRuntime().createExpression(expr),
|
|
180
|
+
createExpression: (expr) => paramRuntime.createExpression(expr),
|
|
176
181
|
registerExpr: (fn) => this.#rangeExprRefListeners.add(fn),
|
|
177
182
|
});
|
|
178
183
|
|
|
@@ -7,15 +7,15 @@
|
|
|
7
7
|
* @param {object} options
|
|
8
8
|
* @param {Channel} options.channel
|
|
9
9
|
* @param {import("../spec/channel.js").Type} options.dataType
|
|
10
|
-
* @param {
|
|
10
|
+
* @param {ScaleResolutionMember[]} options.orderedMembers
|
|
11
11
|
* @param {boolean} options.isExplicitDomain
|
|
12
12
|
* @param {import("../spec/config.js").GenomeSpyConfig[]} options.configScopes
|
|
13
13
|
* @returns {Scale}
|
|
14
14
|
*/
|
|
15
|
-
export function resolveScalePropsBase({ channel, dataType,
|
|
15
|
+
export function resolveScalePropsBase({ channel, dataType, orderedMembers, isExplicitDomain, configScopes, }: {
|
|
16
16
|
channel: Channel;
|
|
17
17
|
dataType: import("../spec/channel.js").Type;
|
|
18
|
-
|
|
18
|
+
orderedMembers: ScaleResolutionMember[];
|
|
19
19
|
isExplicitDomain: boolean;
|
|
20
20
|
configScopes: import("../spec/config.js").GenomeSpyConfig[];
|
|
21
21
|
}): Scale;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scalePropsResolver.d.ts","sourceRoot":"","sources":["../../../src/scales/scalePropsResolver.js"],"names":[],"mappings":"AAcA;;;;GAIG;AAEH;;;;;;;;GAQG;AACH,
|
|
1
|
+
{"version":3,"file":"scalePropsResolver.d.ts","sourceRoot":"","sources":["../../../src/scales/scalePropsResolver.js"],"names":[],"mappings":"AAcA;;;;GAIG;AAEH;;;;;;;;GAQG;AACH,8GAPG;IAAyB,OAAO,EAAxB,OAAO;IACoC,QAAQ,EAAnD,OAAO,oBAAoB,EAAE,IAAI;IACA,cAAc,EAA/C,qBAAqB,EAAE;IACN,gBAAgB,EAAjC,OAAO;IACgD,YAAY,EAAnE,OAAO,mBAAmB,EAAE,eAAe,EAAE;CACrD,GAAU,KAAK,CA6IjB;sBAzJY,OAAO,oBAAoB,EAAE,OAAO;oBACpC,OAAO,kBAAkB,EAAE,KAAK;oCAChC,OAAO,sBAAsB,EAAE,qBAAqB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isDiscrete } from "vega-scale";
|
|
2
2
|
import { isColorChannel } from "../encoder/encoder.js";
|
|
3
|
+
import { isExprRef } from "../paramRuntime/paramUtils.js";
|
|
3
4
|
|
|
4
5
|
import mergeObjects from "../utils/mergeObjects.js";
|
|
5
6
|
import {
|
|
@@ -10,7 +11,6 @@ import {
|
|
|
10
11
|
} from "../config/scaleConfig.js";
|
|
11
12
|
import { applyLockedProperties, getDefaultScaleType } from "./scaleRules.js";
|
|
12
13
|
import { INDEX, LOCUS } from "./scaleResolutionConstants.js";
|
|
13
|
-
import { orderResolutionMembers } from "./resolutionMemberOrder.js";
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* @typedef {import("../spec/channel.js").Channel} Channel
|
|
@@ -22,7 +22,7 @@ import { orderResolutionMembers } from "./resolutionMemberOrder.js";
|
|
|
22
22
|
* @param {object} options
|
|
23
23
|
* @param {Channel} options.channel
|
|
24
24
|
* @param {import("../spec/channel.js").Type} options.dataType
|
|
25
|
-
* @param {
|
|
25
|
+
* @param {ScaleResolutionMember[]} options.orderedMembers
|
|
26
26
|
* @param {boolean} options.isExplicitDomain
|
|
27
27
|
* @param {import("../spec/config.js").GenomeSpyConfig[]} options.configScopes
|
|
28
28
|
* @returns {Scale}
|
|
@@ -30,11 +30,13 @@ import { orderResolutionMembers } from "./resolutionMemberOrder.js";
|
|
|
30
30
|
export function resolveScalePropsBase({
|
|
31
31
|
channel,
|
|
32
32
|
dataType,
|
|
33
|
-
|
|
33
|
+
orderedMembers,
|
|
34
34
|
isExplicitDomain,
|
|
35
35
|
configScopes,
|
|
36
36
|
}) {
|
|
37
|
-
const
|
|
37
|
+
const memberList = orderedMembers;
|
|
38
|
+
|
|
39
|
+
const markTypes = memberList
|
|
38
40
|
.map((member) =>
|
|
39
41
|
typeof member.view.getMarkType == "function"
|
|
40
42
|
? member.view.getMarkType()
|
|
@@ -42,7 +44,7 @@ export function resolveScalePropsBase({
|
|
|
42
44
|
)
|
|
43
45
|
.filter((markType) => !!markType);
|
|
44
46
|
|
|
45
|
-
const propArray =
|
|
47
|
+
const propArray = memberList
|
|
46
48
|
.map((member) => member.channelDef.scale)
|
|
47
49
|
.filter((props) => props !== undefined);
|
|
48
50
|
|
|
@@ -129,6 +131,27 @@ export function resolveScalePropsBase({
|
|
|
129
131
|
// TODO: Props should be set more intelligently
|
|
130
132
|
}
|
|
131
133
|
|
|
134
|
+
if (props.domainTransition === undefined) {
|
|
135
|
+
const hasExprDrivenDomain = memberList.some((member) =>
|
|
136
|
+
isExprRef(member.channelDef.scale?.domain)
|
|
137
|
+
);
|
|
138
|
+
props.domainTransition = !hasExprDrivenDomain;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (
|
|
142
|
+
Array.isArray(props.range) &&
|
|
143
|
+
props.range.some(isExprRef) &&
|
|
144
|
+
memberList.length > 0
|
|
145
|
+
) {
|
|
146
|
+
const rangeOwner = memberList.find(
|
|
147
|
+
(member) => member.channelDef.scale?.range !== undefined
|
|
148
|
+
)?.view;
|
|
149
|
+
if (rangeOwner) {
|
|
150
|
+
/** @type {any} */
|
|
151
|
+
(props).__rangeExprScope = rangeOwner;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
132
155
|
// By default, index and locus scales are zoomable, others are not.
|
|
133
156
|
// Config can override this baseline via scale.zoom.
|
|
134
157
|
if (!("zoom" in props)) {
|
|
@@ -27,10 +27,21 @@
|
|
|
27
27
|
* @implements {ScaleResolutionApi}
|
|
28
28
|
*/
|
|
29
29
|
export default class ScaleResolution implements ScaleResolutionApi {
|
|
30
|
+
/**
|
|
31
|
+
* Executes a group of member registrations without refreshing derived
|
|
32
|
+
* membership state until the callback completes.
|
|
33
|
+
*
|
|
34
|
+
* @template T
|
|
35
|
+
* @param {Iterable<ScaleResolution>} resolutions
|
|
36
|
+
* @param {() => T} callback
|
|
37
|
+
* @returns {T}
|
|
38
|
+
*/
|
|
39
|
+
static registerInBatch<T>(resolutions: Iterable<ScaleResolution>, callback: () => T): T;
|
|
30
40
|
/**
|
|
31
41
|
* @param {Channel} channel
|
|
42
|
+
* @param {import("../view/view.js").default} [hostView]
|
|
32
43
|
*/
|
|
33
|
-
constructor(channel: import("../spec/channel.js").Channel);
|
|
44
|
+
constructor(channel: import("../spec/channel.js").Channel, hostView?: import("../view/view.js").default);
|
|
34
45
|
channel: import("../spec/channel.js").Channel;
|
|
35
46
|
/** @type {import("../spec/channel.js").Type} Data type (quantitative, nominal, etc...) */
|
|
36
47
|
type: import("../spec/channel.js").Type;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaleResolution.d.ts","sourceRoot":"","sources":["../../../src/scales/scaleResolution.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scaleResolution.d.ts","sourceRoot":"","sources":["../../../src/scales/scaleResolution.js"],"names":[],"mappings":"AAoDA;;;;;;;;GAQG;AACH;;;;;;;;;;;;;;;;;;GAkBG;AACH;IAucI;;;;;;;;OAQG;IACH,uBALa,CAAC,eACH,QAAQ,CAAC,eAAe,CAAC,YACzB,MAAM,CAAC,GACL,CAAC,CAqBb;IA5ZD;;;OAGG;IACH,sEAFW,OAAO,iBAAiB,EAAE,OAAO,EAsC3C;IAnCG,8CAAsB;IACtB,0FAA0F;IAC1F,MADW,OAAO,oBAAoB,EAAE,IAAI,CAC5B;IAEhB,iEAAiE;IACjE,MADW,MAAM,CACI;IA0EzB,2BASC;IAwBD;;;;;;;OAOG;IACH,4KAEC;IAED;;;OAGG;IACH,+KAEC;IAiCD,sCA0CC;IA4MD;;;OAGG;IACH,uBAHW,qBAAqB,GACnB,MAAM,OAAO,CAazB;IAED,gBAMC;IAoFD;;;;OAIG;IACH,0CAJW,OAAO,sBAAsB,EAAE,OAAO,aACtC,QAAQ,CAAC,OAAO,qBAAqB,EAAE,aAAa,CAAC,GACnD,MAAM,IAAI,CAkCtB;IAED;;OAEG;IACH,qCAEC;IAED,+BAiBC;IAuED;;;;;;;;;;;OAWG;IACH,0BALa;QACR,QAAQ,EAAE,OAAO,kBAAkB,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC;QACnE,oBAAoB,EAAE,OAAO,CAAA;KAC9B,CAeH;IAED;;;;;;;OAOG;IACH,wBAFa,OAAO,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,SAAS,CAShE;IAgGD;;;;;OAKG;IACH,oBAYC;IAED;;;;;OAKG;IACH,0BA0BC;IAoID;;OAEG;IACH;eA5gCkC,OAAO,kBAAkB,EAAE,KAAK;MAmhCjE;IAED;;;;;;OAMG;IACH;eA5hCkC,OAAO,kBAAkB,EAAE,KAAK;MAmiCjE;IAED;;;;OAIG;IACH;eA1iCkC,OAAO,kBAAkB,EAAE,KAAK;MAmjCjE;IAED,mBASC;IAED;;;;OAIG;IACH,+DAEC;IAED;;OAEG;IACH,oBAFa,mFAA6B,CASzC;IAED;;OAEG;IACH;;;;MAqBC;IAED;;;;OAIG;IACH,oBAEC;IAED;;OAEG;IACH,sBASC;IAED;;;;;;;OAOG;IACH,kBALW,MAAM,eACN,MAAM,OACN,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;OAMG;IACH,eAJW,mFAA6B,aAC7B,OAAO,GAAG,MAAM,iBAK1B;IAED;;;;OAIG;IACH,qBAEC;IAED;;;;;OAKG;IACH,uBAEC;IAED;;;;;;;OAOG;IACH,wBAoBC;IAED;;;;;OAKG;IACH,uBAFW,MAAM,yDAUhB;IAED;;OAEG;IACH,iBAFW,MAAM,yDAIhB;IAED;;;OAGG;IACH,qBAHW,MAAM,+CAAmB,GACvB,MAAM,CAIlB;IAED;;;OAGG;IACH,8BAHW,kFAA4B,GAC1B,MAAM,EAAE,CAOpB;;CACJ;kCAjyC+B,CAAC,SAApB,6CAAkB;;;;UAGrB,OAAO,qBAAqB,EAAE,OAAO;aACrC,CAAC;gBACD,OAAO,oBAAoB,EAAE,mBAAmB;yBAChD,OAAO;;sBApCV,+BAA+B;sBAA/B,+BAA+B;wBAA/B,+BAA+B;wBAA/B,+BAA+B;6BAA/B,+BAA+B"}
|