@genome-spy/core 0.60.0 → 0.61.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 (55) hide show
  1. package/dist/bundle/index.es.js +5241 -5068
  2. package/dist/bundle/index.js +112 -112
  3. package/dist/schema.json +1668 -82
  4. package/dist/src/data/sources/lazy/gff3Source.d.ts +1 -3
  5. package/dist/src/data/sources/lazy/gff3Source.d.ts.map +1 -1
  6. package/dist/src/data/sources/lazy/vcfSource.d.ts.map +1 -1
  7. package/dist/src/data/transforms/filter.d.ts.map +1 -1
  8. package/dist/src/data/transforms/filter.js +7 -1
  9. package/dist/src/encoder/accessor.d.ts.map +1 -1
  10. package/dist/src/encoder/accessor.js +6 -1
  11. package/dist/src/encoder/accessor.test.js +2 -1
  12. package/dist/src/encoder/encoder.d.ts +1 -1
  13. package/dist/src/encoder/encoder.d.ts.map +1 -1
  14. package/dist/src/encoder/encoder.js +58 -3
  15. package/dist/src/encoder/encoder.test.js +2 -1
  16. package/dist/src/gl/webGLHelper.d.ts +2 -2
  17. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  18. package/dist/src/gl/webGLHelper.js +4 -4
  19. package/dist/src/marks/mark.d.ts.map +1 -1
  20. package/dist/src/marks/mark.js +8 -20
  21. package/dist/src/marks/markUtils.d.ts.map +1 -1
  22. package/dist/src/marks/markUtils.js +26 -16
  23. package/dist/src/selection/selection.d.ts +4 -10
  24. package/dist/src/selection/selection.d.ts.map +1 -1
  25. package/dist/src/selection/selection.js +63 -23
  26. package/dist/src/spec/transform.d.ts +8 -0
  27. package/dist/src/tooltip/refseqGeneTooltipHandler.js +60 -21
  28. package/dist/src/types/encoder.d.ts +4 -0
  29. package/dist/src/types/selectionTypes.d.ts +6 -2
  30. package/dist/src/utils/binnedIndex.d.ts.map +1 -1
  31. package/dist/src/utils/binnedIndex.js +0 -17
  32. package/dist/src/utils/expression.d.ts.map +1 -1
  33. package/dist/src/utils/expression.js +3 -2
  34. package/dist/src/utils/interactionEvent.d.ts +1 -0
  35. package/dist/src/utils/interactionEvent.d.ts.map +1 -1
  36. package/dist/src/utils/interactionEvent.js +8 -0
  37. package/dist/src/utils/mergeObjects.d.ts +0 -2
  38. package/dist/src/utils/mergeObjects.d.ts.map +1 -1
  39. package/dist/src/utils/mergeObjects.js +5 -3
  40. package/dist/src/utils/throttle.d.ts +1 -1
  41. package/dist/src/utils/throttle.d.ts.map +1 -1
  42. package/dist/src/view/gridView/gridChild.d.ts.map +1 -1
  43. package/dist/src/view/gridView/gridChild.js +8 -5
  44. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -1
  45. package/dist/src/view/gridView/scrollbar.js +2 -3
  46. package/dist/src/view/gridView/selectionRect.d.ts +4 -0
  47. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
  48. package/dist/src/view/gridView/selectionRect.js +11 -13
  49. package/dist/src/view/unitView.d.ts.map +1 -1
  50. package/dist/src/view/unitView.js +31 -10
  51. package/dist/src/view/view.test.js +6 -4
  52. package/dist/src/view/viewFactory.test.js +2 -2
  53. package/dist/src/view/zoom.d.ts.map +1 -1
  54. package/dist/src/view/zoom.js +2 -5
  55. package/package.json +7 -7
@@ -7,18 +7,31 @@ import { html } from "lit";
7
7
  * TODO: Implement tool & email parameters: https://www.ncbi.nlm.nih.gov/books/NBK25497/
8
8
  */
9
9
 
10
- // TODO: Replace with an LRU-cache
11
10
  const symbolSummaryCache = new Map();
12
11
 
12
+ const defaultParams = {
13
+ Organism: "Homo sapiens",
14
+ };
15
+
13
16
  /**
14
17
  * @type {import("./tooltipHandler.js").TooltipHandler}
15
18
  */
16
- export default async function refseqGeneTooltipHandler(datum, mark, params) {
19
+ export default async function refseqGeneTooltipHandler(
20
+ datum,
21
+ mark,
22
+ params = {}
23
+ ) {
17
24
  const symbol = datum.symbol;
18
25
 
26
+ const term = {
27
+ ...defaultParams,
28
+ ...params,
29
+ GENE: symbol,
30
+ };
31
+
19
32
  let summary =
20
33
  symbolSummaryCache.get(symbol) ??
21
- (await debouncedFetchGeneSummary(datum.symbol));
34
+ (await debouncedFetchGeneSummary(term));
22
35
 
23
36
  if (summary) {
24
37
  symbolSummaryCache.set(symbol, summary);
@@ -36,29 +49,43 @@ export default async function refseqGeneTooltipHandler(datum, mark, params) {
36
49
  }
37
50
 
38
51
  /**
39
- * @param {string} symbol
52
+ * @param {Record<string, string>} term
40
53
  */
41
- async function fetchGeneSummary(symbol) {
42
- // TODO: Add more search terms to ensure that we really find genes specific to the current genome
43
-
44
- console.log("Searching: " + symbol);
45
-
54
+ async function fetchGeneSummary(term) {
46
55
  /** @type {RequestInit} */
47
56
  const opts = { mode: "cors" };
48
57
 
49
- const searchResult = await fetch(
50
- `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=gene&term=${symbol}[GENE]&sort=relevance&retmode=json`,
51
- opts
52
- ).then((res) => res.json());
58
+ const url = new URL(
59
+ "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi"
60
+ );
61
+ url.search = new URLSearchParams({
62
+ db: "gene",
63
+ term: termToQuery(term),
64
+ sort: "relevance",
65
+ retmax: "1",
66
+ retmode: "json",
67
+ }).toString();
68
+
69
+ const searchResult = await fetch(url.toString(), opts).then((res) =>
70
+ res.json()
71
+ );
53
72
 
54
73
  // TODO: Handle failed searchs
55
74
  const id = searchResult.esearchresult.idlist[0];
56
75
 
57
76
  if (id) {
58
- const summaryResult = await fetch(
59
- `https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?db=gene&id=${id}&retmode=json`,
60
- opts
61
- ).then((res) => res.json());
77
+ const summaryUrl = new URL(
78
+ "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi"
79
+ );
80
+ summaryUrl.search = new URLSearchParams({
81
+ db: "gene",
82
+ id: id,
83
+ retmode: "json",
84
+ }).toString();
85
+
86
+ const summaryResult = await fetch(summaryUrl.toString(), opts).then(
87
+ (res) => res.json()
88
+ );
62
89
 
63
90
  const summary = summaryResult.result[id];
64
91
  return summary;
@@ -70,9 +97,21 @@ async function fetchGeneSummary(symbol) {
70
97
  const debounced = debounce(fetchGeneSummary, 500);
71
98
 
72
99
  /**
73
- *
74
- * @param {string} symbol
100
+ * @param {Record<string, string>} term
101
+ */
102
+ function debouncedFetchGeneSummary(term) {
103
+ return debounced(term);
104
+ }
105
+
106
+ /**
107
+ * @param {Record<string, string>} term
75
108
  */
76
- function debouncedFetchGeneSummary(symbol) {
77
- return debounced(symbol);
109
+ function termToQuery(term) {
110
+ return (
111
+ Object.entries(term)
112
+ .filter(([_, value]) => value && value.length > 0)
113
+ // TODO: Escape
114
+ .map(([key, value]) => `("${value}"[${key}])`)
115
+ .join(" AND ")
116
+ );
78
117
  }
@@ -82,6 +82,10 @@ export interface Predicate extends ExprRefFunction {
82
82
  * Wraps one or more accessors, uses an optional scale to encode the data.
83
83
  */
84
84
  export interface Encoder {
85
+ /**
86
+ * Returns an encoded value for the given datum.
87
+ * If the encoder has a scale, the value is passed through the scale function.
88
+ */
85
89
  (datum: Datum): Scalar;
86
90
 
87
91
  /**
@@ -1,5 +1,9 @@
1
1
  import { Datum } from "../data/flowNode.js";
2
- import { ChannelWithScale, Scalar } from "../spec/channel.js";
2
+ import {
3
+ ChannelWithScale,
4
+ PositionalChannel,
5
+ Scalar,
6
+ } from "../spec/channel.js";
3
7
 
4
8
  export interface SelectionBase {
5
9
  type: string;
@@ -8,7 +12,7 @@ export interface SelectionBase {
8
12
  export interface IntervalSelection extends SelectionBase {
9
13
  type: "interval";
10
14
 
11
- intervals: Partial<Record<ChannelWithScale, number[] | null>>;
15
+ intervals: Partial<Record<PositionalChannel, number[] | null>>;
12
16
  }
13
17
 
14
18
  export interface ProjectedSelection extends SelectionBase {
@@ -1 +1 @@
1
- {"version":3,"file":"binnedIndex.d.ts","sourceRoot":"","sources":["../../../src/utils/binnedIndex.js"],"names":[],"mappings":"AAKA;;;;;;GAMG;AAEH;;;;;;;;;;;GAWG;AACH,0CAFa,CAAC,QAJH,MAAM,UACN,CAAC,MAAM,EAAE,MAAM,CAAC,YAChB,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,cACpB,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM;YA0ChB,CAAC,oBACD,MAAM,kBACN,MAAM;oBAsHJ,MAAM;EA+BtB;6BAhNU,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,0CAFa,CAAC,QAJH,MAAM,UACN,CAAC,MAAM,EAAE,MAAM,CAAC,YAChB,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,cACpB,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM;YA0ChB,CAAC,oBACD,MAAM,kBACN,MAAM;oBAqGJ,MAAM;EA+BtB;6BA/LU,MAAM,OACN,MAAM,QACN,CAAC,MAAM,EAAE,MAAM,CAAC,KACd,CAAC,MAAM,EAAE,MAAM,CAAC"}
@@ -75,10 +75,6 @@ export function createBinningRangeIndexer(
75
75
  lastIndex = startVertexIndex;
76
76
  } else {
77
77
  unordered = true;
78
- // TODO: Contextual info like view path
79
- console.debug(
80
- "Items are not ordered properly. Disabling binned index."
81
- );
82
78
  return;
83
79
  }
84
80
 
@@ -86,10 +82,6 @@ export function createBinningRangeIndexer(
86
82
 
87
83
  if (value < lastStart) {
88
84
  unordered = true;
89
- // TODO: Contextual info like view path
90
- console.debug(
91
- "Items are not ordered properly. Disabling binned index."
92
- );
93
85
  return;
94
86
  }
95
87
  lastStart = value;
@@ -133,18 +125,9 @@ export function createBinningRangeIndexer(
133
125
 
134
126
  if (start < lastStart) {
135
127
  unordered = true;
136
- // TODO: Contextual info like view path
137
- console.debug(
138
- "Items are not ordered properly. Disabling binned index."
139
- );
140
128
  return;
141
129
  } else if (end < start) {
142
130
  unordered = true;
143
- // TODO: Contextual info like view path
144
- console.debug(
145
- "End index is less than start index. Disabling binned index. Datum: ",
146
- datum
147
- );
148
131
  return;
149
132
  }
150
133
  lastStart = start;
@@ -1 +1 @@
1
- {"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../../src/utils/expression.js"],"names":[],"mappings":"AAsEA;;;;;;;;;;GAUG;AACH,6CAHW,MAAM,sBACJ,kBAAkB,CAgC9B;;YAvCU,MAAM,EAAE;aACR,MAAM,EAAE;UACR,MAAM;;iCAEH,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,qBAAqB,EAAE,KAAK,KAAK,GAAG,CAAC,GAAG,eAAe"}
1
+ {"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../../src/utils/expression.js"],"names":[],"mappings":"AAuEA;;;;;;;;;;GAUG;AACH,6CAHW,MAAM,sBACJ,kBAAkB,CAgC9B;;YAvCU,MAAM,EAAE;aACR,MAAM,EAAE;UACR,MAAM;;iCAEH,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,qBAAqB,EAAE,KAAK,KAAK,GAAG,CAAC,GAAG,eAAe"}
@@ -12,7 +12,6 @@ import { format as d3format } from "d3-format";
12
12
  import smoothstep from "./smoothstep.js";
13
13
  import clamp from "./clamp.js";
14
14
  import linearstep from "./linearstep.js";
15
- import { selectionTest } from "../selection/selection.js";
16
15
 
17
16
  /**
18
17
  * Some bits are adapted from https://github.com/vega/vega/blob/main/packages/vega-functions/src/codegen.js
@@ -22,6 +21,9 @@ const functionContext = {
22
21
  format(/** @type {number} */ value, /** @type {string} */ format) {
23
22
  return d3format(format)(value);
24
23
  },
24
+ mapHasKey(/** @type {Map<any, any>} */ map, /** @type {any} */ key) {
25
+ return map.has(key);
26
+ },
25
27
  isArray,
26
28
  isBoolean,
27
29
  isDefined(/** @type {any} */ _) {
@@ -45,7 +47,6 @@ const functionContext = {
45
47
  return String(str).replace(pattern, replace);
46
48
  },
47
49
  smoothstep,
48
- selectionTest,
49
50
  };
50
51
 
51
52
  /**
@@ -22,5 +22,6 @@ export default class InteractionEvent {
22
22
  target: import("../view/view.js").default;
23
23
  stopPropagation(): void;
24
24
  get type(): string;
25
+ get mouseEvent(): MouseEvent;
25
26
  }
26
27
  //# sourceMappingURL=interactionEvent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interactionEvent.d.ts","sourceRoot":"","sources":["../../../src/utils/interactionEvent.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH;IACI;;;;;OAKG;IACH,mBAJW,OAAO,yBAAyB,EAAE,OAAO,WAEzC,OAAO,EAajB;IAVG,iDAAkB;IAClB,iBAAsB;IACtB,iBAAoB;IAEpB;;;;OAIG;IACH,QAFU,OAAO,iBAAiB,EAAE,OAAO,CAEpB;IAG3B,wBAEC;IAED,mBAEC;CACJ"}
1
+ {"version":3,"file":"interactionEvent.d.ts","sourceRoot":"","sources":["../../../src/utils/interactionEvent.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH;IACI;;;;;OAKG;IACH,mBAJW,OAAO,yBAAyB,EAAE,OAAO,WAEzC,OAAO,EAajB;IAVG,iDAAkB;IAClB,iBAAsB;IACtB,iBAAoB;IAEpB;;;;OAIG;IACH,QAFU,OAAO,iBAAiB,EAAE,OAAO,CAEpB;IAG3B,wBAEC;IAED,mBAEC;IAED,6BAMC;CACJ"}
@@ -30,4 +30,12 @@ export default class InteractionEvent {
30
30
  get type() {
31
31
  return this.uiEvent.type;
32
32
  }
33
+
34
+ get mouseEvent() {
35
+ if (this.uiEvent instanceof MouseEvent) {
36
+ return this.uiEvent;
37
+ } else {
38
+ throw new Error("Not a MouseEvent!");
39
+ }
40
+ }
33
41
  }
@@ -3,8 +3,6 @@
3
3
  *
4
4
  * A boolean true and an object are compatible. The object survives, the boolean is overwritten.
5
5
  *
6
- * TODO: Support arrays. Should accept identical arrays and complain about others.
7
- *
8
6
  * @param {T[]} objects Objects to merge
9
7
  * @param {string} propertyOf What are we merging? Used in warning messages
10
8
  * @param {string[]} [skip] Fields to skip. TODO: Support nested fields.
@@ -1 +1 @@
1
- {"version":3,"file":"mergeObjects.d.ts","sourceRoot":"","sources":["../../../src/utils/mergeObjects.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,qCAFa,CAAC,WAJF,CAAC,EAAE,cACJ,MAAM,SACN,MAAM,EAAE,GACN,CAAC,CA6Eb"}
1
+ {"version":3,"file":"mergeObjects.d.ts","sourceRoot":"","sources":["../../../src/utils/mergeObjects.js"],"names":[],"mappings":"AAGA;;;;;;;;;;GAUG;AACH,qCAFa,CAAC,WAJF,CAAC,EAAE,cACJ,MAAM,SACN,MAAM,EAAE,GACN,CAAC,CAiFb"}
@@ -6,8 +6,6 @@ import { isObject } from "vega-util";
6
6
  *
7
7
  * A boolean true and an object are compatible. The object survives, the boolean is overwritten.
8
8
  *
9
- * TODO: Support arrays. Should accept identical arrays and complain about others.
10
- *
11
9
  * @param {T[]} objects Objects to merge
12
10
  * @param {string} propertyOf What are we merging? Used in warning messages
13
11
  * @param {string[]} [skip] Fields to skip. TODO: Support nested fields.
@@ -34,7 +32,11 @@ export default function mergeObjects(objects, propertyOf, skip) {
34
32
  a === b ||
35
33
  (isPlainObject(a) && isPlainObject(b)) ||
36
34
  (isPlainObject(a) && b === true) ||
37
- (a === true && isObject(b));
35
+ (a === true && isObject(b)) ||
36
+ (Array.isArray(a) &&
37
+ Array.isArray(b) &&
38
+ a.length === b.length &&
39
+ a.every((v, i) => v === b[i]));
38
40
 
39
41
  /** @param {any} obj */
40
42
  const merger = (obj) => {
@@ -4,5 +4,5 @@
4
4
  * @param {function} func
5
5
  * @param {number} limit
6
6
  */
7
- export default function throttle(func: Function, limit: number): (...args: any[]) => void;
7
+ export default function throttle(func: Function, limit: number): () => void;
8
8
  //# sourceMappingURL=throttle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../../src/utils/throttle.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wDAFW,MAAM,4BA8BhB"}
1
+ {"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../../src/utils/throttle.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,wDAFW,MAAM,cA8BhB"}
@@ -1 +1 @@
1
- {"version":3,"file":"gridChild.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/gridChild.js"],"names":[],"mappings":"AA+pBA;;;GAGG;AACH,iDAHW,OAAO,oBAAoB,EAAE,cAAc,GACzC,OAAO,oBAAoB,EAAE,QAAQ,CA8BjD;AAED;;;GAGG;AACH,uDAHW,OAAO,oBAAoB,EAAE,cAAc,GACzC,OAAO,oBAAoB,EAAE,QAAQ,CA6CjD;AA7tBD;IACI;;;;OAIG;IACH,kBAJW,OAAO,YAAY,EAAE,OAAO,gBAC5B,OAAO,qBAAqB,EAAE,OAAO,UACrC,MAAM,EAyFhB;IAtFG,oDAAgC;IAChC,mCAAgB;IAChB,eAAoB;IAEpB,uBAAuB;IACvB,YADW,QAAQ,CACQ;IAE3B,uBAAuB;IACvB,kBADW,QAAQ,CACc;IAEjC,sFAAsF;IACtF,MADW,OAAO,CAAC,MAAM,CAAC,OAAO,oBAAoB,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAC/D;IAEd,+FAA+F;IAC/F,WADW,OAAO,CAAC,MAAM,CAAC,OAAO,oBAAoB,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAC9D;IAEnB,mFAAmF;IACnF,YADW,OAAO,CAAC,MAAM,CAAC,OAAO,gBAAgB,EAAE,eAAe,EAAE,SAAS,CAAC,CAAC,CAC3D;IAEpB,4BAA4B;IAC5B,eADW,aAAa,CACM;IAE9B,uBAAuB;IACvB,OADW,QAAQ,CACG;IAEtB,wBAAwB;IACxB,QADW,SAAS,CACQ;IAiZhC,sEAiBC;IAED;;OAEG;IACH,4BAsKC;IAED,uBAqBC;IAED,iCAEC;;CACJ;qBA9oBoB,gBAAgB;qBANK,gBAAgB;yBADjC,oBAAoB;sBAQvB,gBAAgB;0BACZ,oBAAoB;sBAJxB,wBAAwB;oBAF1B,sBAAsB"}
1
+ {"version":3,"file":"gridChild.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/gridChild.js"],"names":[],"mappings":"AAkqBA;;;GAGG;AACH,iDAHW,OAAO,oBAAoB,EAAE,cAAc,GACzC,OAAO,oBAAoB,EAAE,QAAQ,CA8BjD;AAED;;;GAGG;AACH,uDAHW,OAAO,oBAAoB,EAAE,cAAc,GACzC,OAAO,oBAAoB,EAAE,QAAQ,CA6CjD;AAhuBD;IACI;;;;OAIG;IACH,kBAJW,OAAO,YAAY,EAAE,OAAO,gBAC5B,OAAO,qBAAqB,EAAE,OAAO,UACrC,MAAM,EAyFhB;IAtFG,oDAAgC;IAChC,mCAAgB;IAChB,eAAoB;IAEpB,uBAAuB;IACvB,YADW,QAAQ,CACQ;IAE3B,uBAAuB;IACvB,kBADW,QAAQ,CACc;IAEjC,sFAAsF;IACtF,MADW,OAAO,CAAC,MAAM,CAAC,OAAO,oBAAoB,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAC/D;IAEd,+FAA+F;IAC/F,WADW,OAAO,CAAC,MAAM,CAAC,OAAO,oBAAoB,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAC9D;IAEnB,mFAAmF;IACnF,YADW,OAAO,CAAC,MAAM,CAAC,OAAO,gBAAgB,EAAE,eAAe,EAAE,SAAS,CAAC,CAAC,CAC3D;IAEpB,4BAA4B;IAC5B,eADW,aAAa,CACM;IAE9B,uBAAuB;IACvB,OADW,QAAQ,CACG;IAEtB,wBAAwB;IACxB,QADW,SAAS,CACQ;IAoZhC,sEAiBC;IAED;;OAEG;IACH,4BAsKC;IAED,uBAqBC;IAED,iCAEC;;CACJ;qBAjpBoB,gBAAgB;qBANK,gBAAgB;yBADjC,oBAAoB;sBAQvB,gBAAgB;0BACZ,oBAAoB;sBAJxB,wBAAwB;oBAF1B,sBAAsB"}
@@ -257,7 +257,7 @@ export default class GridChild {
257
257
  };
258
258
 
259
259
  view.addInteractionEventListener("mousedown", (coords, event) => {
260
- if (/** @type {MouseEvent} */ (event.uiEvent).button != 0) {
260
+ if (event.mouseEvent.button != 0) {
261
261
  return;
262
262
  }
263
263
 
@@ -283,8 +283,9 @@ export default class GridChild {
283
283
  preventNextClickPropagation = true;
284
284
  }
285
285
 
286
- if (/** @type {MouseEvent} */ (event.uiEvent).shiftKey) {
287
- // Start brushing a new selection, clear the existing selection
286
+ const startSelection = event.mouseEvent.shiftKey;
287
+
288
+ if (startSelection) {
288
289
  clearSelection();
289
290
  nowBrushing = true;
290
291
  } else if (isActiveIntervalSelection(selectionExpr())) {
@@ -309,6 +310,8 @@ export default class GridChild {
309
310
  };
310
311
  view.addInteractionEventListener("mouseup", listener);
311
312
  return;
313
+ } else {
314
+ return;
312
315
  }
313
316
  }
314
317
 
@@ -317,7 +320,7 @@ export default class GridChild {
317
320
 
318
321
  const start = event.point;
319
322
  const viewOffset = Point.fromMouseEvent(
320
- /** @type {MouseEvent} */ (event.uiEvent)
323
+ event.mouseEvent
321
324
  ).subtract(start);
322
325
 
323
326
  const mouseMoveListener = (/** @type {MouseEvent} */ event) => {
@@ -405,7 +408,7 @@ export default class GridChild {
405
408
  view.addInteractionEventListener(
406
409
  "click",
407
410
  (coords, event) => {
408
- if (/** @type {MouseEvent} */ (event.uiEvent).button == 0) {
411
+ if (event.mouseEvent.button == 0) {
409
412
  if (preventNextClickPropagation) {
410
413
  event.stopPropagation();
411
414
  preventNextClickPropagation = false;
@@ -1 +1 @@
1
- {"version":3,"file":"scrollbar.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/scrollbar.js"],"names":[],"mappings":"AAKA;;GAEG;AACH;IAeI;;;OAGG;IACH,uBAHW,OAAO,gBAAgB,EAAE,OAAO,mBAChC,eAAe,EA4FzB;IAhGD,uBAAmB;IAsCf;;;MAAoB;IAIpB;;;;MAQC;IAgDL,2BAKC;IAWD;;;;OAIG;IACH,gCAHW,SAAS,UACT,SAAS,QA8CnB;;CACJ;8BAnLY,YAAY,GAAG,UAAU;qBAHjB,gBAAgB;sBADf,wBAAwB"}
1
+ {"version":3,"file":"scrollbar.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/scrollbar.js"],"names":[],"mappings":"AAKA;;GAEG;AACH;IAeI;;;OAGG;IACH,uBAHW,OAAO,gBAAgB,EAAE,OAAO,mBAChC,eAAe,EA2FzB;IA/FD,uBAAmB;IAsCf;;;MAAoB;IAIpB;;;;MAQC;IA+CL,2BAKC;IAWD;;;;OAIG;IACH,gCAHW,SAAS,UACT,SAAS,QA8CnB;;CACJ;8BAlLY,YAAY,GAAG,UAAU;qBAHjB,gBAAgB;sBADf,wBAAwB"}
@@ -83,11 +83,10 @@ export default class Scrollbar extends UnitView {
83
83
  ? mouseEvent.clientY
84
84
  : mouseEvent.clientX;
85
85
 
86
- const mouseEvent = /** @type {MouseEvent} */ (event.uiEvent);
87
- mouseEvent.preventDefault();
86
+ event.mouseEvent.preventDefault();
88
87
 
89
88
  const initialScrollOffset = this.scrollOffset;
90
- const initialOffset = getMouseOffset(mouseEvent);
89
+ const initialOffset = getMouseOffset(event.mouseEvent);
91
90
 
92
91
  const onMousemove = /** @param {MouseEvent} moveEvent */ (
93
92
  moveEvent
@@ -1,4 +1,8 @@
1
1
  export default class SelectionRect extends LayerView {
2
+ /**
3
+ * @typedef {import("../../spec/channel.js").PrimaryPositionalChannel} PrimaryPositionalChannel
4
+ * @typedef {import("../../types/selectionTypes.js").IntervalSelection} IntervalSelection
5
+ */
2
6
  /**
3
7
  * @param {import("./gridChild.js").default} gridChild
4
8
  * @param {import("../paramMediator.js").ExprRefFunction} selectionExpr
@@ -1 +1 @@
1
- {"version":3,"file":"selectionRect.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/selectionRect.js"],"names":[],"mappings":"AAEA;IACI;;;;OAIG;IACH,uBAJW,OAAO,gBAAgB,EAAE,OAAO,iBAChC,OAAO,qBAAqB,EAAE,eAAe,gBAC7C,OAAO,yBAAyB,EAAE,WAAW,EAkJvD;CACJ;sBAzJqB,iBAAiB"}
1
+ {"version":3,"file":"selectionRect.d.ts","sourceRoot":"","sources":["../../../../src/view/gridView/selectionRect.js"],"names":[],"mappings":"AAGA;IACI;;;OAGG;IAEH;;;;OAIG;IACH,uBAJW,OAAO,gBAAgB,EAAE,OAAO,iBAChC,OAAO,qBAAqB,EAAE,eAAe,gBAC7C,OAAO,yBAAyB,EAAE,WAAW,EA0IvD;CACJ;sBAtJqB,iBAAiB"}
@@ -1,24 +1,24 @@
1
+ import { primaryPositionalChannels } from "../../encoder/encoder.js";
1
2
  import LayerView from "../layerView.js";
2
3
 
3
4
  export default class SelectionRect extends LayerView {
5
+ /**
6
+ * @typedef {import("../../spec/channel.js").PrimaryPositionalChannel} PrimaryPositionalChannel
7
+ * @typedef {import("../../types/selectionTypes.js").IntervalSelection} IntervalSelection
8
+ */
9
+
4
10
  /**
5
11
  * @param {import("./gridChild.js").default} gridChild
6
12
  * @param {import("../paramMediator.js").ExprRefFunction} selectionExpr
7
13
  * @param {import("../../spec/parameter.js").BrushConfig} [brushConfig]
8
14
  */
9
15
  constructor(gridChild, selectionExpr, brushConfig = {}) {
10
- const initialSelection =
11
- /** @type {import("../../types/selectionTypes.js").IntervalSelection} */ (
12
- selectionExpr()
13
- );
16
+ const initialSelection = /** @type {IntervalSelection} */ (
17
+ selectionExpr()
18
+ );
14
19
  const channels = Object.keys(initialSelection.intervals);
15
20
 
16
- if (
17
- /** @type {import("../../spec/channel.js").ChannelWithScale[]} */ ([
18
- "x",
19
- "y",
20
- ]).every((c) => !channels.includes(c))
21
- ) {
21
+ if (primaryPositionalChannels.every((c) => !channels.includes(c))) {
22
22
  throw new Error(
23
23
  "SelectionRect requires at least one of the channels 'x' or 'y' to be present in the selection."
24
24
  );
@@ -64,9 +64,7 @@ export default class SelectionRect extends LayerView {
64
64
  },
65
65
  });
66
66
 
67
- const makeExpr = (
68
- /** @type {import("../../spec/channel.js").PrimaryPositionalChannel} */ channel
69
- ) => {
67
+ const makeExpr = (/** @type {PrimaryPositionalChannel} */ channel) => {
70
68
  const resolution = gridChild.view.getScaleResolution(channel);
71
69
  return (
72
70
  `format(datum._${channel}2 - datum._${channel}, '.3s')` +
@@ -1 +1 @@
1
- {"version":3,"file":"unitView.d.ts","sourceRoot":"","sources":["../../../src/view/unitView.js"],"names":[],"mappings":"AA2BA;;;;GAIG;AACH,wBAHU,MAAM,CAAC,OAAO,iBAAiB,EAAE,QAAQ,EAAE,cAAc,kBAAkB,EAAE,OAAO,CAAC,CAc7F;AAEF;IAeI;;;;;;;;OAQG;IACH,kBAPW,OAAO,iBAAiB,EAAE,QAAQ,WAClC,OAAO,yBAAyB,EAAE,OAAO,gBACzC,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,WAAW,EAAE,OAAO,QAC3B,MAAM,YACN,OAAO,WAAW,EAAE,WAAW,EAiCzC;IA5BG,yCAAgB;IAIZ,iDAAiD;IACjD,MADW,OAAO,kBAAkB,EAAE,OAAO,CACnB;IAqHlC,2DAIC;IAgBD;;;;;OAKG;IAEH,iEA+FC;IAED;;;;;OAKG;IACH,4IAEC;IAkBD;;OAEG;IACH,uDAEC;IAED;;;;;;;;;;;;;OAaG;IACH,uEAHW,OAAO,oBAAoB,EAAE,IAAI,iDAqB3C;IAED,uBAQC;IAgBD;;;;OAIG;IACH,8BAJW,MAAM,+DAEJ,OAAO,iBAAiB,EAAE,kBAAkB,CAKxD;;CACJ;iBAjZgB,WAAW"}
1
+ {"version":3,"file":"unitView.d.ts","sourceRoot":"","sources":["../../../src/view/unitView.js"],"names":[],"mappings":"AA4BA;;;;GAIG;AACH,wBAHU,MAAM,CAAC,OAAO,iBAAiB,EAAE,QAAQ,EAAE,cAAc,kBAAkB,EAAE,OAAO,CAAC,CAc7F;AAEF;IAeI;;;;;;;;OAQG;IACH,kBAPW,OAAO,iBAAiB,EAAE,QAAQ,WAClC,OAAO,yBAAyB,EAAE,OAAO,gBACzC,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,WAAW,EAAE,OAAO,QAC3B,MAAM,YACN,OAAO,WAAW,EAAE,WAAW,EAiCzC;IA5BG,yCAAgB;IAIZ,iDAAiD;IACjD,MADW,OAAO,kBAAkB,EAAE,OAAO,CACnB;IAkHlC,2DAIC;IAgBD;;;;;OAKG;IAEH,iEAsHC;IAED;;;;;OAKG;IACH,4IAEC;IAkBD;;OAEG;IACH,uDAEC;IAED;;;;;;;;;;;;;OAaG;IACH,uEAHW,OAAO,oBAAoB,EAAE,IAAI,iDAqB3C;IAED,uBAQC;IAgBD;;;;OAIG;IACH,8BAJW,MAAM,+DAEJ,OAAO,iBAAiB,EAAE,kBAAkB,CAKxD;;CACJ;iBAragB,WAAW"}
@@ -12,6 +12,7 @@ import {
12
12
  getPrimaryChannel,
13
13
  isChannelWithScale,
14
14
  isPrimaryPositionalChannel,
15
+ isValueDefWithCondition,
15
16
  } from "../encoder/encoder.js";
16
17
  import createDomain from "../utils/domainArray.js";
17
18
  import AxisResolution from "./axisResolution.js";
@@ -125,9 +126,6 @@ export default class UnitView extends View {
125
126
  /** @type {any} */ _,
126
127
  /** @type {import("../utils/interactionEvent.js").default} */ event
127
128
  ) => {
128
- const mouseEvent = /** @type {MouseEvent} */ (
129
- event.uiEvent
130
- );
131
129
  const datum = getHoveredDatum();
132
130
  const id = datum ? datum[UNIQUE_ID_KEY] : none;
133
131
 
@@ -135,7 +133,7 @@ export default class UnitView extends View {
135
133
  let selection;
136
134
 
137
135
  if (select.toggle) {
138
- const toggle = mouseEvent.shiftKey;
136
+ const toggle = event.mouseEvent.shiftKey;
139
137
 
140
138
  if (toggle) {
141
139
  if (datum) {
@@ -223,6 +221,7 @@ export default class UnitView extends View {
223
221
  if (!type) {
224
222
  this.resolve("scale");
225
223
  this.resolve("axis");
224
+ return;
226
225
  }
227
226
 
228
227
  // TODO: Complain about nonsensical configuration, e.g. shared parent has independent children.
@@ -230,12 +229,34 @@ export default class UnitView extends View {
230
229
  const encoding = this.mark.encoding;
231
230
 
232
231
  for (const [channel, channelDef] of Object.entries(encoding)) {
233
- if (!isChannelDefWithScale(channelDef)) {
232
+ if (!channelDef) {
234
233
  continue;
235
234
  }
236
235
 
236
+ /** @type {import("../spec/channel.js").ChannelDefWithScale} */
237
+ let channelDefWithScale;
238
+
239
+ if (isChannelDefWithScale(channelDef)) {
240
+ channelDefWithScale = channelDef;
241
+ } else {
242
+ if (isValueDefWithCondition(channelDef)) {
243
+ const condition = channelDef.condition;
244
+ if (
245
+ !Array.isArray(condition) &&
246
+ isChannelDefWithScale(condition)
247
+ ) {
248
+ // There's a single condition (maybe) with a scale
249
+ channelDefWithScale = condition;
250
+ } else {
251
+ continue;
252
+ }
253
+ } else {
254
+ continue;
255
+ }
256
+ }
257
+
237
258
  const targetChannel = getPrimaryChannel(
238
- channelDef.resolutionChannel ?? channel
259
+ channelDefWithScale.resolutionChannel ?? channel
239
260
  );
240
261
 
241
262
  if (!isChannelWithScale(targetChannel)) {
@@ -279,7 +300,7 @@ export default class UnitView extends View {
279
300
  view.resolutions[type][targetChannel].addMember({
280
301
  view: this,
281
302
  channel,
282
- channelDef,
303
+ channelDef: channelDefWithScale,
283
304
  });
284
305
  } else if (type == "scale" && isChannelWithScale(channel)) {
285
306
  if (!view.resolutions[type][targetChannel]) {
@@ -301,15 +322,15 @@ export default class UnitView extends View {
301
322
  .some(
302
323
  (view) => !view.options.contributesToScaleDomain
303
324
  ) ||
304
- (isChannelDefWithScale(channelDef) &&
305
- channelDef.contributesToScaleDomain === false)
325
+ (isChannelDefWithScale(channelDefWithScale) &&
326
+ channelDefWithScale.contributesToScaleDomain === false)
306
327
  ? undefined
307
328
  : this.extractDataDomain.bind(this);
308
329
 
309
330
  view.resolutions[type][targetChannel].addMember({
310
331
  view: this,
311
332
  channel,
312
- channelDef,
333
+ channelDef: channelDefWithScale,
313
334
  dataDomainSource,
314
335
  });
315
336
  }
@@ -11,14 +11,16 @@ import LayerView from "./layerView.js";
11
11
  describe("Trivial creations and initializations", () => {
12
12
  test("Fails on empty spec", async () => {
13
13
  // @ts-expect-error
14
- expect(create({}, View)).rejects.toThrow();
14
+ await expect(create({}, View)).rejects.toThrow();
15
15
  });
16
16
 
17
- test("Parses a trivial spec", () => {
18
- expect(create({ mark: "point" }, View)).resolves.toBeInstanceOf(
17
+ test("Parses a trivial spec", async () => {
18
+ await expect(create({ mark: "point" }, View)).resolves.toBeInstanceOf(
19
19
  UnitView
20
20
  );
21
- expect(create({ layer: [] }, View)).resolves.toBeInstanceOf(LayerView);
21
+ await expect(create({ layer: [] }, View)).resolves.toBeInstanceOf(
22
+ LayerView
23
+ );
22
24
  });
23
25
 
24
26
  test("Parses a more comples spec", async () => {
@@ -16,10 +16,10 @@ test("isViewSpec", () => {
16
16
  expect(() => factory.isViewSpec({ mark: "rect", layer: [] })).toThrow();
17
17
  });
18
18
 
19
- test("Throws if importing is not allowed", () => {
19
+ test("Throws if importing is not allowed", async () => {
20
20
  const factory = new ViewFactory({ allowImport: false });
21
21
 
22
- expect(() =>
22
+ await expect(() =>
23
23
  factory.createOrImportView({ import: { url: "" } }, undefined)
24
24
  ).rejects.toThrow();
25
25
  });
@@ -1 +1 @@
1
- {"version":3,"file":"zoom.d.ts","sourceRoot":"","sources":["../../../src/view/zoom.js"],"names":[],"mappings":"AAkBA,0CAGC;AAgBD;;;;;;GAMG;AACH,yCANW,OAAO,8BAA8B,EAAE,OAAO,UAC9C,OAAO,uBAAuB,EAAE,OAAO,cACvC,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,UAC9B,OAAO,yBAAyB,EAAE,KAAK,aACvC,OAAO,sBAAsB,EAAE,OAAO,QAkJhD;;OA1LS,MAAM;OACN,MAAM;YACN,MAAM;YACN,MAAM;YACN,MAAM"}
1
+ {"version":3,"file":"zoom.d.ts","sourceRoot":"","sources":["../../../src/view/zoom.js"],"names":[],"mappings":"AAkBA,0CAGC;AAgBD;;;;;;GAMG;AACH,yCANW,OAAO,8BAA8B,EAAE,OAAO,UAC9C,OAAO,uBAAuB,EAAE,OAAO,cACvC,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,UAC9B,OAAO,yBAAyB,EAAE,KAAK,aACvC,OAAO,sBAAsB,EAAE,OAAO,QA+IhD;;OAvLS,MAAM;OACN,MAAM;YACN,MAAM;YACN,MAAM;YACN,MAAM"}
@@ -96,10 +96,7 @@ export function interactionToZoom(event, coords, handleZoom, hover, animator) {
96
96
  zDelta: 0,
97
97
  });
98
98
  }
99
- } else if (
100
- event.type == "mousedown" &&
101
- /** @type {MouseEvent} */ (event.uiEvent).button === 0
102
- ) {
99
+ } else if (event.type == "mousedown" && event.mouseEvent.button === 0) {
103
100
  if (smoother) {
104
101
  smoother.stop();
105
102
  }
@@ -107,7 +104,7 @@ export function interactionToZoom(event, coords, handleZoom, hover, animator) {
107
104
  /** @type {RingBuffer<{point: Point, timestamp: number}>} */
108
105
  const eventBuffer = new RingBuffer(30);
109
106
 
110
- const mouseEvent = /** @type {MouseEvent} */ (event.uiEvent);
107
+ const mouseEvent = event.mouseEvent;
111
108
  mouseEvent.preventDefault();
112
109
 
113
110
  let prevPoint = Point.fromMouseEvent(mouseEvent);
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "contributors": [],
9
9
  "license": "MIT",
10
- "version": "0.60.0",
10
+ "version": "0.61.0",
11
11
  "jsdelivr": "dist/bundle/index.js",
12
12
  "unpkg": "dist/bundle/index.js",
13
13
  "browser": "dist/bundle/index.js",
@@ -57,15 +57,15 @@
57
57
  "events": "^3.3.0",
58
58
  "flatqueue": "^2.0.3",
59
59
  "internmap": "^2.0.3",
60
- "lit": "^3.1.2",
60
+ "lit": "^3.3.0",
61
61
  "twgl.js": "^4.19.1",
62
- "vega-expression": "^5.1.0",
63
- "vega-loader": "^4.5.1",
64
- "vega-scale": "^7.3.1",
65
- "vega-util": "^1.17.2"
62
+ "vega-expression": "^6.0.0",
63
+ "vega-loader": "^5.0.0",
64
+ "vega-scale": "^8.0.0",
65
+ "vega-util": "^2.0.0"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@types/long": "^4.0.1"
69
69
  },
70
- "gitHead": "82948eadeadfedcb13e669f6664e163dac3a6a92"
70
+ "gitHead": "f26c40a7ed59f89cac52eba84a87bb723a9ef73b"
71
71
  }