@genome-spy/core 0.62.2 → 0.64.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 +4568 -4301
- package/dist/bundle/index.js +371 -297
- package/dist/schema.json +84 -12
- package/dist/src/genomeSpy.d.ts +11 -0
- package/dist/src/genomeSpy.d.ts.map +1 -1
- package/dist/src/genomeSpy.js +98 -20
- package/dist/src/gl/includes/common.glsl.js +1 -1
- package/dist/src/gl/webGLHelper.d.ts +18 -14
- package/dist/src/gl/webGLHelper.d.ts.map +1 -1
- package/dist/src/gl/webGLHelper.js +65 -64
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/marks/link.fragment.glsl.js +1 -1
- package/dist/src/marks/link.vertex.glsl.js +1 -1
- package/dist/src/marks/mark.d.ts +6 -1
- package/dist/src/marks/mark.d.ts.map +1 -1
- package/dist/src/marks/mark.js +10 -16
- package/dist/src/marks/point.fragment.glsl.js +1 -1
- package/dist/src/marks/point.vertex.glsl.js +1 -1
- package/dist/src/marks/rect.fragment.glsl.js +1 -1
- package/dist/src/marks/rect.vertex.glsl.js +1 -1
- package/dist/src/marks/rule.fragment.glsl.js +1 -1
- package/dist/src/marks/rule.vertex.glsl.js +1 -1
- package/dist/src/marks/text.d.ts.map +1 -1
- package/dist/src/marks/text.fragment.glsl.js +1 -1
- package/dist/src/marks/text.js +7 -15
- package/dist/src/marks/text.vertex.glsl.js +1 -1
- package/dist/src/selection/selection.d.ts +5 -0
- package/dist/src/selection/selection.d.ts.map +1 -1
- package/dist/src/selection/selection.js +43 -6
- package/dist/src/selection/selection.test.d.ts +2 -0
- package/dist/src/selection/selection.test.d.ts.map +1 -0
- package/dist/src/selection/selection.test.js +14 -0
- package/dist/src/spec/parameter.d.ts +28 -2
- package/dist/src/styles/{genome-spy.scss → genome-spy.css} +25 -21
- package/dist/src/styles/genome-spy.css.d.ts +1 -1
- package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
- package/dist/src/styles/genome-spy.css.js +264 -195
- package/dist/src/styles/update.sh +14 -4
- package/dist/src/types/embedApi.d.ts +16 -0
- package/dist/src/types/viewContext.d.ts +0 -2
- package/dist/src/utils/expression.d.ts +5 -0
- package/dist/src/utils/expression.d.ts.map +1 -1
- package/dist/src/utils/expression.js +37 -0
- package/dist/src/utils/interactionEvent.d.ts +18 -1
- package/dist/src/utils/interactionEvent.d.ts.map +1 -1
- package/dist/src/utils/interactionEvent.js +101 -1
- package/dist/src/utils/interactionEvent.test.d.ts +2 -0
- package/dist/src/utils/interactionEvent.test.d.ts.map +1 -0
- package/dist/src/utils/interactionEvent.test.js +35 -0
- package/dist/src/view/facetView.d.ts +1 -1
- package/dist/src/view/facetView.d.ts.map +1 -1
- package/dist/src/view/gridView/gridView.js +1 -1
- package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts +32 -17
- package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts.map +1 -1
- package/dist/src/view/renderingContext/bufferedViewRenderingContext.js +85 -39
- package/dist/src/view/renderingContext/simpleViewRenderingContext.d.ts.map +1 -1
- package/dist/src/view/renderingContext/simpleViewRenderingContext.js +5 -1
- package/dist/src/view/renderingContext/viewRenderingContext.d.ts +1 -0
- package/dist/src/view/renderingContext/viewRenderingContext.d.ts.map +1 -1
- package/dist/src/view/renderingContext/viewRenderingContext.js +4 -0
- package/dist/src/view/unitView.d.ts.map +1 -1
- package/dist/src/view/unitView.js +45 -2
- package/package.json +8 -8
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* as in the DOM.
|
|
5
5
|
*/
|
|
6
6
|
export default class InteractionEvent {
|
|
7
|
+
/** @type {MouseEvent} */
|
|
8
|
+
#primitiveMouseEventProxy;
|
|
9
|
+
|
|
7
10
|
/**
|
|
8
|
-
*
|
|
9
11
|
* @param {import("../view/layout/point.js").default} point Event coordinates
|
|
10
12
|
* inside the visualization canvas.
|
|
11
13
|
* @param {UIEvent} uiEvent The event to be wrapped
|
|
@@ -27,10 +29,27 @@ export default class InteractionEvent {
|
|
|
27
29
|
this.stopped = true;
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
/**
|
|
33
|
+
* The event type string of the underlying UI event (e.g. "click", "keydown").
|
|
34
|
+
*
|
|
35
|
+
* This getter proxies and returns the `type` property from the internal `UIEvent` instance (`this.uiEvent`).
|
|
36
|
+
*
|
|
37
|
+
* @returns {string} The UI event type.
|
|
38
|
+
*/
|
|
30
39
|
get type() {
|
|
31
40
|
return this.uiEvent.type;
|
|
32
41
|
}
|
|
33
42
|
|
|
43
|
+
get proxiedMouseEvent() {
|
|
44
|
+
if (!this.#primitiveMouseEventProxy) {
|
|
45
|
+
this.#primitiveMouseEventProxy = createPrimitiveEventProxy(
|
|
46
|
+
this.mouseEvent
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return this.#primitiveMouseEventProxy;
|
|
51
|
+
}
|
|
52
|
+
|
|
34
53
|
get mouseEvent() {
|
|
35
54
|
if (this.uiEvent instanceof MouseEvent) {
|
|
36
55
|
return this.uiEvent;
|
|
@@ -39,3 +58,84 @@ export default class InteractionEvent {
|
|
|
39
58
|
}
|
|
40
59
|
}
|
|
41
60
|
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Create a safe proxy for an event-like object that exposes only primitive
|
|
64
|
+
* (string, number, boolean, bigint, symbol, undefined) properties and null.
|
|
65
|
+
*
|
|
66
|
+
* @param {T} target The event-like object to wrap.
|
|
67
|
+
* @returns {T} A proxy exposing only primitive properties.
|
|
68
|
+
* @template T
|
|
69
|
+
*/
|
|
70
|
+
export function createPrimitiveEventProxy(target) {
|
|
71
|
+
/**
|
|
72
|
+
* @param {any} v
|
|
73
|
+
* @returns {boolean}
|
|
74
|
+
*/
|
|
75
|
+
const isPrimitiveOrNull = (v) =>
|
|
76
|
+
v === null || (typeof v !== "object" && typeof v !== "function");
|
|
77
|
+
|
|
78
|
+
/** @type {ProxyHandler<any>} */
|
|
79
|
+
const handler = {
|
|
80
|
+
/**
|
|
81
|
+
* @param {any} target
|
|
82
|
+
* @param {PropertyKey} prop
|
|
83
|
+
* @param {any} receiver
|
|
84
|
+
*/
|
|
85
|
+
get(target, prop, receiver) {
|
|
86
|
+
const value = Reflect.get(target, prop, target);
|
|
87
|
+
if (!isPrimitiveOrNull(value)) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`Access to non-primitive property "${String(prop)}" is not allowed.`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
return value;
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
getPrototypeOf() {
|
|
96
|
+
return null;
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @param {any} target
|
|
101
|
+
* @returns {ArrayLike<string|symbol>}
|
|
102
|
+
*/
|
|
103
|
+
ownKeys(target) {
|
|
104
|
+
const keys = Reflect.ownKeys(target).filter((k) =>
|
|
105
|
+
isPrimitiveOrNull(target[k])
|
|
106
|
+
);
|
|
107
|
+
return keys.map((k) => (typeof k === "symbol" ? k : String(k)));
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @param {any} target
|
|
112
|
+
* @param {PropertyKey} prop
|
|
113
|
+
* @returns {PropertyDescriptor|undefined}
|
|
114
|
+
*/
|
|
115
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
116
|
+
const desc = Reflect.getOwnPropertyDescriptor(target, prop);
|
|
117
|
+
if (!desc) return undefined;
|
|
118
|
+
// hide accessor properties (getters/setters)
|
|
119
|
+
if ("get" in desc || "set" in desc) return undefined;
|
|
120
|
+
if (!isPrimitiveOrNull(desc.value)) return undefined;
|
|
121
|
+
// Preserve configurability/enumerability/writability to satisfy proxy invariants
|
|
122
|
+
return {
|
|
123
|
+
value: desc.value,
|
|
124
|
+
writable: !!desc.writable,
|
|
125
|
+
enumerable: !!desc.enumerable,
|
|
126
|
+
configurable: !!desc.configurable,
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* @param {any} target
|
|
132
|
+
* @param {PropertyKey} prop
|
|
133
|
+
* @returns {boolean} */
|
|
134
|
+
has(target, prop) {
|
|
135
|
+
if (!(prop in target)) return false;
|
|
136
|
+
return isPrimitiveOrNull(target[prop]);
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
return new Proxy(target, handler);
|
|
141
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interactionEvent.test.d.ts","sourceRoot":"","sources":["../../../src/utils/interactionEvent.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { createPrimitiveEventProxy } from "./interactionEvent.js";
|
|
3
|
+
|
|
4
|
+
describe("createPrimitiveEventProxy", () => {
|
|
5
|
+
it("exposes primitive properties and hides non-primitives", () => {
|
|
6
|
+
const mock = {
|
|
7
|
+
type: "click",
|
|
8
|
+
clientX: 42,
|
|
9
|
+
meta: { foo: "bar" },
|
|
10
|
+
nested: { a: 1 },
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/** @type {any} */
|
|
14
|
+
const proxy = createPrimitiveEventProxy(mock);
|
|
15
|
+
|
|
16
|
+
// allowed primitives
|
|
17
|
+
expect(proxy.type).toBe("click");
|
|
18
|
+
expect(proxy.clientX).toBe(42);
|
|
19
|
+
|
|
20
|
+
// non-primitive access throws
|
|
21
|
+
expect(() => proxy.meta).toThrow(/non-primitive/);
|
|
22
|
+
|
|
23
|
+
// keys enumeration hides non-primitives
|
|
24
|
+
const keys = Object.keys(proxy);
|
|
25
|
+
expect(keys).toContain("type");
|
|
26
|
+
expect(keys).not.toContain("meta");
|
|
27
|
+
|
|
28
|
+
// `in` operator respects the policy
|
|
29
|
+
expect("type" in proxy).toBe(true);
|
|
30
|
+
expect("meta" in proxy).toBe(false);
|
|
31
|
+
|
|
32
|
+
// prototype is hidden
|
|
33
|
+
expect(Object.getPrototypeOf(proxy)).toBeNull();
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -48,7 +48,7 @@ export default class FacetView extends ContainerView {
|
|
|
48
48
|
getAccessor(channel: "row" | "column"): any;
|
|
49
49
|
updateFacets(): void;
|
|
50
50
|
updateLabels(): void;
|
|
51
|
-
getFacetGroups():
|
|
51
|
+
getFacetGroups(): string[] | number[] | boolean[];
|
|
52
52
|
/**
|
|
53
53
|
* @param {import("./renderingContext/viewRenderingContext.js").default} context
|
|
54
54
|
* @param {import("./layout/rectangle.js").default} coords
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"facetView.d.ts","sourceRoot":"","sources":["../../../src/view/facetView.js"],"names":[],"mappings":"AAmDA;;;;;;;;;;;;;;GAcG;AACH;IACI;;;;;;;OAOG;IACH;;;;;;OAMG;IACH,kBALW,OAAO,gBAAgB,EAAE,SAAS,WAClC,OAAO,gBAAgB,EAAE,WAAW,UACpC,aAAa,QACb,MAAM,EA8BhB;IAzBG,UAAgB;IAEhB,WAEC;IAED;;;;OAIG;IACH,aAFU,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAYvC;IAED,oDAAoD;IACpD,kBADY,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,CACa;IA2BjE,sBAIC;IAED;;;OAGG;IACH,qBAFW,KAAK,GAAG,QAAQ,OAwB1B;IAED,qBAyCC;IAED,qBASC;IA6BD,
|
|
1
|
+
{"version":3,"file":"facetView.d.ts","sourceRoot":"","sources":["../../../src/view/facetView.js"],"names":[],"mappings":"AAmDA;;;;;;;;;;;;;;GAcG;AACH;IACI;;;;;;;OAOG;IACH;;;;;;OAMG;IACH,kBALW,OAAO,gBAAgB,EAAE,SAAS,WAClC,OAAO,gBAAgB,EAAE,WAAW,UACpC,aAAa,QACb,MAAM,EA8BhB;IAzBG,UAAgB;IAEhB,WAEC;IAED;;;;OAIG;IACH,aAFU,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAYvC;IAED,oDAAoD;IACpD,kBADY,MAAM,CAAC,YAAY,EAAE,cAAc,CAAC,CACa;IA2BjE,sBAIC;IAED;;;OAGG;IACH,qBAFW,KAAK,GAAG,QAAQ,OAwB1B;IAED,qBAyCC;IAED,qBASC;IA6BD,kDAgBC;IAOD;;;;OAIG;IACH,gBAJW,OAAO,4CAA4C,EAAE,OAAO,UAC5D,OAAO,uBAAuB,EAAE,OAAO,YACvC,OAAO,WAAW,EAAE,gBAAgB,QA2L9C;IA3KO,wBAA0B;CA4KrC;2BA/bY,QAAQ,GAAG,KAAK;;;;;;aA4CnB,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE;;;0BA1Df,oBAAoB;qBACzB,eAAe"}
|
|
@@ -449,7 +449,7 @@ export default class GridView extends ContainerView {
|
|
|
449
449
|
context.pushView(this, coords);
|
|
450
450
|
|
|
451
451
|
const flexOpts = {
|
|
452
|
-
devicePixelRatio:
|
|
452
|
+
devicePixelRatio: context.getDevicePixelRatio(),
|
|
453
453
|
};
|
|
454
454
|
const columnFlexCoords = mapToPixelCoords(
|
|
455
455
|
this.#makeFlexItems("column"),
|
|
@@ -1,30 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {object} BufferedViewRenderingOptions
|
|
3
|
+
* @prop {import("../../gl/webGLHelper.js").default} webGLHelper
|
|
4
|
+
* @prop {{width: number, height: number}} canvasSize Size of the canvas in logical pixels.
|
|
5
|
+
* @prop {number} devicePixelRatio
|
|
6
|
+
* @prop {import("twgl.js").FramebufferInfo} [framebufferInfo]
|
|
7
|
+
* @prop {string} [clearColor] Clear color for the WebGL context,
|
|
8
|
+
* defaults to transparent black.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* View rendering context that buffers the actual WebGL rendering for
|
|
12
|
+
* efficient animation.
|
|
13
|
+
*/
|
|
1
14
|
export default class BufferedViewRenderingContext extends ViewRenderingContext {
|
|
2
15
|
/**
|
|
3
16
|
* @param {import("../../types/rendering.js").GlobalRenderingOptions} globalOptions
|
|
4
|
-
* @param {
|
|
17
|
+
* @param {BufferedViewRenderingOptions} bufferedOptions
|
|
5
18
|
*/
|
|
6
|
-
constructor(globalOptions: import("../../types/rendering.js").GlobalRenderingOptions,
|
|
7
|
-
webGLHelper: import("../../gl/webGLHelper.js").default;
|
|
8
|
-
/**
|
|
9
|
-
* @type {import("../../types/rendering.js").BufferedRenderingRequest[]}
|
|
10
|
-
*/
|
|
11
|
-
buffer: import("../../types/rendering.js").BufferedRenderingRequest[];
|
|
12
|
-
/** @type {import("../layout/rectangle.js").default} */
|
|
13
|
-
coords: import("../layout/rectangle.js").default;
|
|
14
|
-
/** @type {Set<import("../view.js").default>} */
|
|
15
|
-
views: Set<import("../view.js").default>;
|
|
19
|
+
constructor(globalOptions: import("../../types/rendering.js").GlobalRenderingOptions, bufferedOptions: BufferedViewRenderingOptions);
|
|
16
20
|
/**
|
|
17
21
|
* Renders marks in an optimized order, minimizing the number of WebGL state
|
|
18
22
|
* changes.
|
|
19
23
|
*/
|
|
20
24
|
render(): void;
|
|
21
|
-
|
|
25
|
+
#private;
|
|
26
|
+
}
|
|
27
|
+
export type BufferedViewRenderingOptions = {
|
|
28
|
+
webGLHelper: import("../../gl/webGLHelper.js").default;
|
|
22
29
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* @type {(function():void)[]}
|
|
30
|
+
* Size of the canvas in logical pixels.
|
|
26
31
|
*/
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
canvasSize: {
|
|
33
|
+
width: number;
|
|
34
|
+
height: number;
|
|
35
|
+
};
|
|
36
|
+
devicePixelRatio: number;
|
|
37
|
+
framebufferInfo?: import("twgl.js").FramebufferInfo;
|
|
38
|
+
/**
|
|
39
|
+
* Clear color for the WebGL context,
|
|
40
|
+
* defaults to transparent black.
|
|
41
|
+
*/
|
|
42
|
+
clearColor?: string;
|
|
43
|
+
};
|
|
29
44
|
import ViewRenderingContext from "./viewRenderingContext.js";
|
|
30
45
|
//# sourceMappingURL=bufferedViewRenderingContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bufferedViewRenderingContext.d.ts","sourceRoot":"","sources":["../../../../src/view/renderingContext/bufferedViewRenderingContext.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bufferedViewRenderingContext.d.ts","sourceRoot":"","sources":["../../../../src/view/renderingContext/bufferedViewRenderingContext.js"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AAEH;;;GAGG;AACH;IA2BI;;;OAGG;IACH,2BAHW,OAAO,0BAA0B,EAAE,sBAAsB,mBACzD,4BAA4B,EActC;IAyCD;;;OAGG;IACH,eAmCC;;CA8EJ;;iBArNS,OAAO,yBAAyB,EAAE,OAAO;;;;gBACzC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC;sBAC/B,MAAM;sBACN,OAAO,SAAS,EAAE,eAAe;;;;;iBACjC,MAAM;;iCATiB,2BAA2B"}
|
|
@@ -1,27 +1,69 @@
|
|
|
1
1
|
import { group } from "d3-array";
|
|
2
2
|
|
|
3
3
|
import ViewRenderingContext from "./viewRenderingContext.js";
|
|
4
|
-
|
|
4
|
+
import { color } from "d3-color";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {object} BufferedViewRenderingOptions
|
|
8
|
+
* @prop {import("../../gl/webGLHelper.js").default} webGLHelper
|
|
9
|
+
* @prop {{width: number, height: number}} canvasSize Size of the canvas in logical pixels.
|
|
10
|
+
* @prop {number} devicePixelRatio
|
|
11
|
+
* @prop {import("twgl.js").FramebufferInfo} [framebufferInfo]
|
|
12
|
+
* @prop {string} [clearColor] Clear color for the WebGL context,
|
|
13
|
+
* defaults to transparent black.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* View rendering context that buffers the actual WebGL rendering for
|
|
18
|
+
* efficient animation.
|
|
19
|
+
*/
|
|
5
20
|
export default class BufferedViewRenderingContext extends ViewRenderingContext {
|
|
21
|
+
/** @type {[number, number, number, number]} */
|
|
22
|
+
#clearColor = [0, 0, 0, 0];
|
|
23
|
+
|
|
24
|
+
/** @type {(() => void)[]} */
|
|
25
|
+
#batch;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @type {import("../../types/rendering.js").BufferedRenderingRequest[]}
|
|
29
|
+
*/
|
|
30
|
+
#buffer = [];
|
|
31
|
+
|
|
32
|
+
/** @type {import("twgl.js").FramebufferInfo} */
|
|
33
|
+
#framebufferInfo;
|
|
34
|
+
|
|
35
|
+
/** @type {import("../../gl/webGLHelper.js").default} */
|
|
36
|
+
#webGLHelper;
|
|
37
|
+
|
|
38
|
+
/** @type {Set<import("../view.js").default>} */
|
|
39
|
+
#views = new Set();
|
|
40
|
+
|
|
41
|
+
/** @type {import("../layout/rectangle.js").default} */
|
|
42
|
+
#coords = undefined;
|
|
43
|
+
|
|
44
|
+
#dpr = 1;
|
|
45
|
+
#canvasSize = { width: 0, height: 0 };
|
|
46
|
+
|
|
6
47
|
/**
|
|
7
48
|
* @param {import("../../types/rendering.js").GlobalRenderingOptions} globalOptions
|
|
8
|
-
* @param {
|
|
49
|
+
* @param {BufferedViewRenderingOptions} bufferedOptions
|
|
9
50
|
*/
|
|
10
|
-
constructor(globalOptions,
|
|
51
|
+
constructor(globalOptions, bufferedOptions) {
|
|
11
52
|
super(globalOptions);
|
|
12
53
|
|
|
13
|
-
this
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
*/
|
|
18
|
-
this.buffer = [];
|
|
54
|
+
this.#webGLHelper = bufferedOptions.webGLHelper;
|
|
55
|
+
this.#framebufferInfo = bufferedOptions.framebufferInfo;
|
|
56
|
+
this.#dpr = bufferedOptions.devicePixelRatio;
|
|
57
|
+
this.#canvasSize = bufferedOptions.canvasSize;
|
|
19
58
|
|
|
20
|
-
|
|
21
|
-
|
|
59
|
+
if (bufferedOptions.clearColor) {
|
|
60
|
+
const c = color(bufferedOptions.clearColor).rgb();
|
|
61
|
+
this.#clearColor = [c.r / 255, c.g / 255, c.b / 255, c.opacity];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
22
64
|
|
|
23
|
-
|
|
24
|
-
this
|
|
65
|
+
getDevicePixelRatio() {
|
|
66
|
+
return this.#dpr;
|
|
25
67
|
}
|
|
26
68
|
|
|
27
69
|
/**
|
|
@@ -33,8 +75,8 @@ export default class BufferedViewRenderingContext extends ViewRenderingContext {
|
|
|
33
75
|
* @override
|
|
34
76
|
*/
|
|
35
77
|
pushView(view, coords) {
|
|
36
|
-
this
|
|
37
|
-
this
|
|
78
|
+
this.#views.add(view);
|
|
79
|
+
this.#coords = coords;
|
|
38
80
|
}
|
|
39
81
|
|
|
40
82
|
/**
|
|
@@ -50,10 +92,10 @@ export default class BufferedViewRenderingContext extends ViewRenderingContext {
|
|
|
50
92
|
|
|
51
93
|
const callback = mark.render(options);
|
|
52
94
|
if (callback) {
|
|
53
|
-
this
|
|
95
|
+
this.#buffer.push({
|
|
54
96
|
mark,
|
|
55
97
|
callback,
|
|
56
|
-
coords: this
|
|
98
|
+
coords: this.#coords,
|
|
57
99
|
clipRect: options.clipRect,
|
|
58
100
|
});
|
|
59
101
|
}
|
|
@@ -64,45 +106,47 @@ export default class BufferedViewRenderingContext extends ViewRenderingContext {
|
|
|
64
106
|
* changes.
|
|
65
107
|
*/
|
|
66
108
|
render() {
|
|
67
|
-
if (!this
|
|
68
|
-
this
|
|
109
|
+
if (!this.#batch) {
|
|
110
|
+
this.#buildBatch();
|
|
69
111
|
}
|
|
70
112
|
|
|
71
|
-
if (this
|
|
113
|
+
if (this.#batch.length == 0) {
|
|
72
114
|
return;
|
|
73
115
|
}
|
|
74
116
|
|
|
75
|
-
const gl = this
|
|
76
|
-
const
|
|
117
|
+
const gl = this.#webGLHelper.gl;
|
|
118
|
+
const fbi = this.#framebufferInfo;
|
|
77
119
|
|
|
78
|
-
|
|
79
|
-
gl.FRAMEBUFFER,
|
|
80
|
-
|
|
81
|
-
|
|
120
|
+
if (fbi) {
|
|
121
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, fbi.framebuffer);
|
|
122
|
+
gl.viewport(0, 0, fbi.width, fbi.height);
|
|
123
|
+
} else {
|
|
124
|
+
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
|
125
|
+
}
|
|
82
126
|
|
|
83
|
-
|
|
127
|
+
gl.disable(gl.SCISSOR_TEST);
|
|
128
|
+
gl.clearColor(...this.#clearColor);
|
|
129
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
84
130
|
|
|
85
|
-
for (const view of this
|
|
131
|
+
for (const view of this.#views) {
|
|
86
132
|
view.onBeforeRender();
|
|
87
133
|
}
|
|
88
134
|
|
|
89
135
|
// Execute the batch
|
|
90
|
-
for (const op of this
|
|
136
|
+
for (const op of this.#batch) {
|
|
91
137
|
op();
|
|
92
138
|
}
|
|
93
139
|
|
|
94
|
-
if (
|
|
140
|
+
if (this.#framebufferInfo) {
|
|
95
141
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
96
142
|
}
|
|
97
143
|
}
|
|
98
144
|
|
|
99
|
-
|
|
145
|
+
#buildBatch() {
|
|
100
146
|
/**
|
|
101
147
|
* Store the operations as a sequence of commands for cheap subsequent rendering.
|
|
102
|
-
*
|
|
103
|
-
* @type {(function():void)[]}
|
|
104
148
|
*/
|
|
105
|
-
this
|
|
149
|
+
this.#batch = [];
|
|
106
150
|
|
|
107
151
|
/**
|
|
108
152
|
* Is drawing enabled or not. As an optimization this is toggled off for invisible views.
|
|
@@ -129,7 +173,7 @@ export default class BufferedViewRenderingContext extends ViewRenderingContext {
|
|
|
129
173
|
// Note: by reversing the buffer, we ensure ensure that the last instance
|
|
130
174
|
// of a mark determines the order of the groups.
|
|
131
175
|
const requestByMark = group(
|
|
132
|
-
this
|
|
176
|
+
this.#buffer.reverse(),
|
|
133
177
|
(request) => request.mark
|
|
134
178
|
);
|
|
135
179
|
|
|
@@ -140,11 +184,11 @@ export default class BufferedViewRenderingContext extends ViewRenderingContext {
|
|
|
140
184
|
}
|
|
141
185
|
|
|
142
186
|
// eslint-disable-next-line no-loop-func
|
|
143
|
-
this
|
|
187
|
+
this.#batch.push(() => {
|
|
144
188
|
enabled = mark.unitView.getEffectiveOpacity() > 0;
|
|
145
189
|
});
|
|
146
190
|
// Change program, set common uniforms (mark properties, shared domains)
|
|
147
|
-
this
|
|
191
|
+
this.#batch.push(
|
|
148
192
|
...mark
|
|
149
193
|
.prepareRender(this.globalOptions)
|
|
150
194
|
.map((op) => ifEnabled(op))
|
|
@@ -156,18 +200,20 @@ export default class BufferedViewRenderingContext extends ViewRenderingContext {
|
|
|
156
200
|
const coords = request.coords;
|
|
157
201
|
// Render each facet
|
|
158
202
|
if (!coords.equals(previousCoords)) {
|
|
159
|
-
this
|
|
203
|
+
this.#batch.push(
|
|
160
204
|
// eslint-disable-next-line no-loop-func
|
|
161
205
|
ifEnabled(() => {
|
|
162
206
|
// Suppress rendering if viewport is outside the clipRect
|
|
163
207
|
viewportVisible = mark.setViewport(
|
|
208
|
+
this.#canvasSize,
|
|
209
|
+
this.#dpr,
|
|
164
210
|
coords,
|
|
165
211
|
request.clipRect
|
|
166
212
|
);
|
|
167
213
|
})
|
|
168
214
|
);
|
|
169
215
|
}
|
|
170
|
-
this
|
|
216
|
+
this.#batch.push(ifEnabledAndVisible(request.callback));
|
|
171
217
|
previousCoords = request.coords;
|
|
172
218
|
}
|
|
173
219
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simpleViewRenderingContext.d.ts","sourceRoot":"","sources":["../../../../src/view/renderingContext/simpleViewRenderingContext.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH;IAMQ,uDAAuD;IACvD,QADW,OAAO,wBAAwB,EAAE,OAAO,CAC5B;IAEvB,gDAAgD;IAChD,OADW,GAAG,CAAC,OAAO,YAAY,EAAE,OAAO,CAAC,CACtB;
|
|
1
|
+
{"version":3,"file":"simpleViewRenderingContext.d.ts","sourceRoot":"","sources":["../../../../src/view/renderingContext/simpleViewRenderingContext.js"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH;IAMQ,uDAAuD;IACvD,QADW,OAAO,wBAAwB,EAAE,OAAO,CAC5B;IAEvB,gDAAgD;IAChD,OADW,GAAG,CAAC,OAAO,YAAY,EAAE,OAAO,CAAC,CACtB;CAiD7B;;;;;mBA7DY,OAAO,YAAY,EAAE,OAAO;iCANR,2BAA2B"}
|
|
@@ -58,7 +58,11 @@ export default class SimpleViewRenderingContext extends ViewRenderingContext {
|
|
|
58
58
|
for (const op of mark.prepareRender(this.globalOptions)) {
|
|
59
59
|
op();
|
|
60
60
|
}
|
|
61
|
-
|
|
61
|
+
|
|
62
|
+
const canvasSize = { width: 100, height: 100 }; // Placeholder, should be replaced with actual canvas size
|
|
63
|
+
const dpr = this.getDevicePixelRatio();
|
|
64
|
+
|
|
65
|
+
mark.setViewport(canvasSize, dpr, this.coords, options.clipRect);
|
|
62
66
|
mark.render(options)();
|
|
63
67
|
}
|
|
64
68
|
}
|
|
@@ -28,6 +28,7 @@ export default class ViewRenderingContext {
|
|
|
28
28
|
* @param {import("../../types/rendering.js").RenderingOptions} options
|
|
29
29
|
*/
|
|
30
30
|
renderMark(mark: import("../../marks/mark.js").default, options: import("../../types/rendering.js").RenderingOptions): void;
|
|
31
|
+
getDevicePixelRatio(): number;
|
|
31
32
|
}
|
|
32
33
|
export type View = import("../view.js").default;
|
|
33
34
|
//# sourceMappingURL=viewRenderingContext.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"viewRenderingContext.d.ts","sourceRoot":"","sources":["../../../../src/view/renderingContext/viewRenderingContext.js"],"names":[],"mappings":"AAAA;;GAEG;AACH;IACI;;;OAGG;IACH,2BAFW,OAAO,0BAA0B,EAAE,sBAAsB,EAInE;IADG,yEAAkC;IAGtC;;;;;;OAMG;IACH,eAJW,IAAI,UACJ,OAAO,wBAAwB,EAAE,OAAO,QAKlD;IAED;;;;OAIG;IACH,cAFW,IAAI,QAId;IAED;;;;OAIG;IACH,iBAHW,OAAO,qBAAqB,EAAE,OAAO,WACrC,OAAO,0BAA0B,EAAE,gBAAgB,QAI7D;CACJ;
|
|
1
|
+
{"version":3,"file":"viewRenderingContext.d.ts","sourceRoot":"","sources":["../../../../src/view/renderingContext/viewRenderingContext.js"],"names":[],"mappings":"AAAA;;GAEG;AACH;IACI;;;OAGG;IACH,2BAFW,OAAO,0BAA0B,EAAE,sBAAsB,EAInE;IADG,yEAAkC;IAGtC;;;;;;OAMG;IACH,eAJW,IAAI,UACJ,OAAO,wBAAwB,EAAE,OAAO,QAKlD;IAED;;;;OAIG;IACH,cAFW,IAAI,QAId;IAED;;;;OAIG;IACH,iBAHW,OAAO,qBAAqB,EAAE,OAAO,WACrC,OAAO,0BAA0B,EAAE,gBAAgB,QAI7D;IAED,8BAEC;CACJ;mBA3CY,OAAO,YAAY,EAAE,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unitView.d.ts","sourceRoot":"","sources":["../../../src/view/unitView.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"unitView.d.ts","sourceRoot":"","sources":["../../../src/view/unitView.js"],"names":[],"mappings":"AA6BA;;;;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;IA4JlC,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;iBAhdgB,WAAW"}
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
updateMultiPointSelection,
|
|
26
26
|
} from "../selection/selection.js";
|
|
27
27
|
import { UNIQUE_ID_KEY } from "../data/transforms/identifier.js";
|
|
28
|
+
import { createEventFilterFunction } from "../utils/expression.js";
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
*
|
|
@@ -108,6 +109,16 @@ export default class UnitView extends View {
|
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
const select = asSelectionConfig(param.select);
|
|
112
|
+
// Normalized config has eventConfig in "on"
|
|
113
|
+
const eventConfig =
|
|
114
|
+
/** @type {import("../spec/parameter.js").EventConfig} */ (
|
|
115
|
+
select.on
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const clearEventConfig =
|
|
119
|
+
/** @type {import("../spec/parameter.js").EventConfig} */ (
|
|
120
|
+
select.clear
|
|
121
|
+
);
|
|
111
122
|
|
|
112
123
|
if (isPointSelectionConfig(select)) {
|
|
113
124
|
// Handle projection-free point selections
|
|
@@ -122,10 +133,17 @@ export default class UnitView extends View {
|
|
|
122
133
|
return h?.mark?.unitView === this ? h.datum : null;
|
|
123
134
|
};
|
|
124
135
|
|
|
136
|
+
const eventPredicate = eventConfig.filter
|
|
137
|
+
? createEventFilterFunction(eventConfig.filter)
|
|
138
|
+
: () => true;
|
|
139
|
+
|
|
125
140
|
const listener = (
|
|
126
141
|
/** @type {any} */ _,
|
|
127
142
|
/** @type {import("../utils/interactionEvent.js").default} */ event
|
|
128
143
|
) => {
|
|
144
|
+
if (!eventPredicate(event.proxiedMouseEvent)) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
129
147
|
const datum = getHoveredDatum();
|
|
130
148
|
const id = datum ? datum[UNIQUE_ID_KEY] : none;
|
|
131
149
|
|
|
@@ -164,11 +182,36 @@ export default class UnitView extends View {
|
|
|
164
182
|
};
|
|
165
183
|
|
|
166
184
|
this.addInteractionEventListener(
|
|
167
|
-
["mouseover", "pointerover"].includes(
|
|
185
|
+
["mouseover", "pointerover"].includes(eventConfig.type)
|
|
168
186
|
? "mousemove"
|
|
169
|
-
:
|
|
187
|
+
: eventConfig.type,
|
|
170
188
|
listener
|
|
171
189
|
);
|
|
190
|
+
|
|
191
|
+
if (clearEventConfig) {
|
|
192
|
+
const clearPredicate = clearEventConfig.filter
|
|
193
|
+
? createEventFilterFunction(clearEventConfig.filter)
|
|
194
|
+
: () => true;
|
|
195
|
+
|
|
196
|
+
const clearListener = (
|
|
197
|
+
/** @type {any} */ _,
|
|
198
|
+
/** @type {import("../utils/interactionEvent.js").default} */ event
|
|
199
|
+
) => {
|
|
200
|
+
if (!clearPredicate(event.proxiedMouseEvent)) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
lastId = none;
|
|
204
|
+
const selection = select.toggle
|
|
205
|
+
? createMultiPointSelection()
|
|
206
|
+
: createSinglePointSelection(null);
|
|
207
|
+
setter(selection);
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
this.addInteractionEventListener(
|
|
211
|
+
clearEventConfig.type,
|
|
212
|
+
clearListener
|
|
213
|
+
);
|
|
214
|
+
}
|
|
172
215
|
}
|
|
173
216
|
}
|
|
174
217
|
}
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"contributors": [],
|
|
9
9
|
"license": "MIT",
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.64.0",
|
|
11
11
|
"jsdelivr": "dist/bundle/index.js",
|
|
12
12
|
"unpkg": "dist/bundle/index.js",
|
|
13
13
|
"browser": "dist/bundle/index.js",
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
"@gmod/indexedfasta": "^2.1.1",
|
|
45
45
|
"@gmod/tabix": "^1.6.1",
|
|
46
46
|
"@gmod/vcf": "^6.0.0",
|
|
47
|
-
"@types/d3-array": "^3.2.
|
|
47
|
+
"@types/d3-array": "^3.2.2",
|
|
48
48
|
"@types/d3-dsv": "^3.0.7",
|
|
49
49
|
"@types/d3-ease": "^3.0.2",
|
|
50
50
|
"@types/d3-format": "^3.0.4",
|
|
51
51
|
"@types/d3-interpolate": "^3.0.4",
|
|
52
|
-
"@types/d3-scale": "^4.0.
|
|
52
|
+
"@types/d3-scale": "^4.0.9",
|
|
53
53
|
"d3-array": "^3.2.4",
|
|
54
54
|
"d3-color": "^3.1.0",
|
|
55
55
|
"d3-ease": "^3.0.1",
|
|
@@ -59,13 +59,13 @@
|
|
|
59
59
|
"internmap": "^2.0.3",
|
|
60
60
|
"lit": "^3.3.0",
|
|
61
61
|
"twgl.js": "^4.19.1",
|
|
62
|
-
"vega-expression": "^6.
|
|
63
|
-
"vega-loader": "^5.
|
|
64
|
-
"vega-scale": "^8.
|
|
65
|
-
"vega-util": "^2.
|
|
62
|
+
"vega-expression": "^6.1.0",
|
|
63
|
+
"vega-loader": "^5.1.0",
|
|
64
|
+
"vega-scale": "^8.1.0",
|
|
65
|
+
"vega-util": "^2.1.0"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@types/long": "^4.0.1"
|
|
69
69
|
},
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "a1edb39d7a50b3a2b05c9ee0d860170065fd5ad6"
|
|
71
71
|
}
|