@genome-spy/core 0.44.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle/index.es.js +6123 -5482
- package/dist/bundle/index.js +211 -148
- package/dist/schema.json +329 -79
- package/dist/src/data/collector.d.ts.map +1 -1
- package/dist/src/data/collector.js +4 -2
- package/dist/src/data/flowOptimizer.test.js +12 -3
- package/dist/src/data/sources/dataUtils.d.ts.map +1 -1
- package/dist/src/data/sources/dataUtils.js +3 -1
- package/dist/src/data/sources/lazy/bigBedSource.d.ts +1 -1
- package/dist/src/data/sources/lazy/bigBedSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/bigBedSource.js +52 -20
- package/dist/src/data/sources/lazy/bigWigSource.d.ts +0 -1
- package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/bigWigSource.js +30 -4
- package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/singleAxisLazySource.js +0 -2
- package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts +6 -2
- package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +38 -20
- package/dist/src/data/sources/sequenceSource.d.ts.map +1 -1
- package/dist/src/data/sources/sequenceSource.js +14 -5
- package/dist/src/data/sources/sequenceSource.test.js +23 -5
- package/dist/src/data/sources/urlSource.d.ts.map +1 -1
- package/dist/src/data/sources/urlSource.js +15 -2
- package/dist/src/data/transforms/aggregate.d.ts.map +1 -1
- package/dist/src/data/transforms/aggregate.js +5 -2
- package/dist/src/encoder/encoder.d.ts +2 -4
- package/dist/src/encoder/encoder.d.ts.map +1 -1
- package/dist/src/encoder/encoder.js +8 -8
- package/dist/src/encoder/encoder.test.js +3 -0
- package/dist/src/genomeSpy.d.ts +7 -5
- package/dist/src/genomeSpy.d.ts.map +1 -1
- package/dist/src/genomeSpy.js +109 -132
- package/dist/src/gl/glslScaleGenerator.js +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/marks/mark.d.ts +8 -5
- package/dist/src/marks/mark.d.ts.map +1 -1
- package/dist/src/marks/mark.js +56 -12
- package/dist/src/marks/point.common.glsl.js +1 -1
- package/dist/src/marks/point.d.ts +1 -4
- package/dist/src/marks/point.d.ts.map +1 -1
- package/dist/src/marks/point.js +31 -23
- package/dist/src/marks/point.vertex.glsl.js +1 -1
- package/dist/src/marks/text.d.ts.map +1 -1
- package/dist/src/marks/text.js +15 -7
- package/dist/src/spec/data.d.ts +11 -10
- package/dist/src/spec/mark.d.ts +11 -21
- package/dist/src/spec/parameter.d.ts +11 -7
- package/dist/src/spec/root.d.ts +0 -8
- package/dist/src/spec/title.d.ts +5 -4
- package/dist/src/spec/view.d.ts +19 -4
- package/dist/src/styles/genome-spy.css.d.ts +1 -1
- package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
- package/dist/src/styles/genome-spy.css.js +52 -5
- package/dist/src/styles/genome-spy.scss +63 -10
- package/dist/src/styles/update.sh +6 -0
- package/dist/src/tooltip/dataTooltipHandler.js +1 -1
- package/dist/src/tooltip/refseqGeneTooltipHandler.js +1 -1
- package/dist/src/tooltip/tooltipHandler.d.ts +1 -1
- package/dist/src/tooltip/tooltipHandler.d.ts.map +1 -1
- package/dist/src/tooltip/tooltipHandler.ts +1 -1
- package/dist/src/types/embedApi.d.ts +6 -0
- package/dist/src/types/viewContext.d.ts +2 -3
- package/dist/src/utils/debounce.d.ts +2 -2
- package/dist/src/utils/debounce.d.ts.map +1 -1
- package/dist/src/utils/debounce.js +5 -2
- package/dist/src/utils/expression.d.ts +2 -2
- package/dist/src/utils/expression.d.ts.map +1 -1
- package/dist/src/utils/expression.js +1 -1
- package/dist/src/utils/formatObject.d.ts +2 -2
- package/dist/src/utils/formatObject.d.ts.map +1 -1
- package/dist/src/utils/formatObject.js +2 -2
- package/dist/src/utils/inputBinding.d.ts +5 -0
- package/dist/src/utils/inputBinding.d.ts.map +1 -0
- package/dist/src/utils/inputBinding.js +115 -0
- package/dist/src/utils/ui/tooltip.js +1 -1
- package/dist/src/view/paramMediator.d.ts +108 -0
- package/dist/src/view/paramMediator.d.ts.map +1 -0
- package/dist/src/view/paramMediator.js +337 -0
- package/dist/src/view/paramMediator.test.js +211 -0
- package/dist/src/view/scaleResolution.d.ts.map +1 -1
- package/dist/src/view/scaleResolution.js +11 -6
- package/dist/src/view/view.d.ts +4 -1
- package/dist/src/view/view.d.ts.map +1 -1
- package/dist/src/view/view.js +19 -5
- package/dist/src/view/viewFactory.d.ts.map +1 -1
- package/dist/src/view/viewFactory.js +45 -0
- package/dist/src/view/viewUtils.d.ts +5 -1
- package/dist/src/view/viewUtils.d.ts.map +1 -1
- package/dist/src/view/viewUtils.js +9 -4
- package/package.json +16 -17
- package/dist/src/paramBroker.d.ts +0 -46
- package/dist/src/paramBroker.d.ts.map +0 -1
- package/dist/src/paramBroker.js +0 -118
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
const css =
|
|
1
|
+
const css = `
|
|
2
|
+
.genome-spy {
|
|
2
3
|
font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
|
3
4
|
position: relative;
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
}
|
|
8
|
+
.genome-spy .canvas-wrapper {
|
|
9
|
+
position: relative;
|
|
10
|
+
flex-grow: 1;
|
|
11
|
+
overflow: hidden;
|
|
4
12
|
}
|
|
5
13
|
.genome-spy canvas {
|
|
6
14
|
transform: scale(1, 1);
|
|
@@ -19,14 +27,14 @@ const css = `.genome-spy {
|
|
|
19
27
|
opacity: 0;
|
|
20
28
|
transition: opacity 0.7s;
|
|
21
29
|
}
|
|
22
|
-
.genome-spy.loading canvas {
|
|
30
|
+
.genome-spy .loading > canvas {
|
|
23
31
|
transform: scale(0.95, 0.95);
|
|
24
32
|
opacity: 0;
|
|
25
33
|
}
|
|
26
|
-
.genome-spy.loading .loading-message .message {
|
|
34
|
+
.genome-spy .loading > .loading-message .message {
|
|
27
35
|
opacity: 1;
|
|
28
36
|
}
|
|
29
|
-
.genome-spy.loading .ellipsis {
|
|
37
|
+
.genome-spy .loading > .loading-message .message .ellipsis {
|
|
30
38
|
animation: blinker 1s linear infinite;
|
|
31
39
|
}
|
|
32
40
|
@keyframes blinker {
|
|
@@ -138,6 +146,45 @@ const css = `.genome-spy {
|
|
|
138
146
|
border: 1px solid red;
|
|
139
147
|
padding: 10px;
|
|
140
148
|
background: #fff0f0;
|
|
141
|
-
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.gs-input-binding {
|
|
152
|
+
display: grid;
|
|
153
|
+
grid-template-columns: max-content max-content;
|
|
154
|
+
column-gap: 1em;
|
|
155
|
+
row-gap: 0.3em;
|
|
156
|
+
justify-items: start;
|
|
157
|
+
}
|
|
158
|
+
.gs-input-binding > select,
|
|
159
|
+
.gs-input-binding > input:not([type=checkbox]) {
|
|
160
|
+
width: 100%;
|
|
161
|
+
}
|
|
162
|
+
.gs-input-binding input[type=range] + span {
|
|
163
|
+
display: inline-block;
|
|
164
|
+
margin-left: 0.3em;
|
|
165
|
+
min-width: 2.2em;
|
|
166
|
+
font-variant-numeric: tabular-nums;
|
|
167
|
+
}
|
|
168
|
+
.gs-input-binding input[type=range],
|
|
169
|
+
.gs-input-binding input[type=radio] {
|
|
170
|
+
vertical-align: text-bottom;
|
|
171
|
+
}
|
|
172
|
+
.gs-input-binding .radio-group {
|
|
173
|
+
display: flex;
|
|
174
|
+
align-items: center;
|
|
175
|
+
}
|
|
176
|
+
.gs-input-binding .description {
|
|
177
|
+
max-width: 26em;
|
|
178
|
+
grid-column: 1/-1;
|
|
179
|
+
color: #777;
|
|
180
|
+
font-size: 90%;
|
|
181
|
+
margin-top: -0.5em;
|
|
182
|
+
}
|
|
142
183
|
|
|
184
|
+
.gs-input-bindings {
|
|
185
|
+
flex-basis: content;
|
|
186
|
+
font-size: 14px;
|
|
187
|
+
padding: 10px;
|
|
188
|
+
}
|
|
189
|
+
`;
|
|
143
190
|
export default css;
|
|
@@ -10,6 +10,15 @@ $font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
|
|
|
10
10
|
|
|
11
11
|
position: relative;
|
|
12
12
|
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
|
|
16
|
+
.canvas-wrapper {
|
|
17
|
+
position: relative;
|
|
18
|
+
flex-grow: 1;
|
|
19
|
+
overflow: hidden;
|
|
20
|
+
}
|
|
21
|
+
|
|
13
22
|
canvas {
|
|
14
23
|
transform: scale(1, 1);
|
|
15
24
|
opacity: 1;
|
|
@@ -31,23 +40,23 @@ $font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
|
|
|
31
40
|
}
|
|
32
41
|
}
|
|
33
42
|
|
|
34
|
-
|
|
35
|
-
canvas {
|
|
43
|
+
.loading {
|
|
44
|
+
> canvas {
|
|
36
45
|
transform: scale(0.95, 0.95);
|
|
37
46
|
opacity: 0;
|
|
38
47
|
}
|
|
39
48
|
|
|
40
|
-
.loading-message .message {
|
|
49
|
+
> .loading-message .message {
|
|
41
50
|
opacity: 1;
|
|
42
|
-
}
|
|
43
51
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
.ellipsis {
|
|
53
|
+
animation: blinker 1s linear infinite;
|
|
54
|
+
}
|
|
47
55
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
56
|
+
@keyframes blinker {
|
|
57
|
+
50% {
|
|
58
|
+
opacity: 0;
|
|
59
|
+
}
|
|
51
60
|
}
|
|
52
61
|
}
|
|
53
62
|
}
|
|
@@ -187,3 +196,47 @@ $font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
|
|
|
187
196
|
}
|
|
188
197
|
}
|
|
189
198
|
}
|
|
199
|
+
|
|
200
|
+
.gs-input-binding {
|
|
201
|
+
display: grid;
|
|
202
|
+
grid-template-columns: max-content max-content;
|
|
203
|
+
column-gap: 1em;
|
|
204
|
+
row-gap: 0.3em;
|
|
205
|
+
justify-items: start;
|
|
206
|
+
|
|
207
|
+
> select,
|
|
208
|
+
> input:not([type="checkbox"]) {
|
|
209
|
+
width: 100%;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
input[type="range"] + span {
|
|
213
|
+
display: inline-block;
|
|
214
|
+
margin-left: 0.3em;
|
|
215
|
+
min-width: 2.2em;
|
|
216
|
+
font-variant-numeric: tabular-nums;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
input[type="range"],
|
|
220
|
+
input[type="radio"] {
|
|
221
|
+
vertical-align: text-bottom;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.radio-group {
|
|
225
|
+
display: flex;
|
|
226
|
+
align-items: center;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.description {
|
|
230
|
+
max-width: 26em;
|
|
231
|
+
grid-column: 1 / -1;
|
|
232
|
+
color: #777;
|
|
233
|
+
font-size: 90%;
|
|
234
|
+
margin-top: -0.5em;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.gs-input-bindings {
|
|
239
|
+
flex-basis: content;
|
|
240
|
+
font-size: 14px;
|
|
241
|
+
padding: $basic-spacing;
|
|
242
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltipHandler.d.ts","sourceRoot":"","sources":["../../../src/tooltip/tooltipHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"tooltipHandler.d.ts","sourceRoot":"","sources":["../../../src/tooltip/tooltipHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,KAAK,CAAC;AACrC,OAAO,IAAI,MAAM,kBAAkB,CAAC;AAEpC;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1B,IAAI,EAAE,IAAI;AACV,sDAAsD;AACtD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAC3B,OAAO,CAAC,MAAM,GAAG,cAAc,GAAG,WAAW,CAAC,CAAC"}
|
|
@@ -27,6 +27,12 @@ export interface EmbedOptions {
|
|
|
27
27
|
* Custom tooltip handlers. Use `"default"` to override the default handler
|
|
28
28
|
*/
|
|
29
29
|
tooltipHandlers?: Record<string, TooltipHandler>;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Where to put the input binding elements. The default is `"default"`, which means that
|
|
33
|
+
* the input binding elements are placed in the same container as the GenomeSpy instance.
|
|
34
|
+
*/
|
|
35
|
+
inputBindingContainer?: HTMLElement | "none" | "default";
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TemplateResult } from "lit
|
|
1
|
+
import { TemplateResult } from "lit";
|
|
2
2
|
import View, { BroadcastMessage } from "../view/view.js";
|
|
3
3
|
import DataFlow from "../data/dataFlow.js";
|
|
4
4
|
import AccessorFactory from "../encoder/accessor.js";
|
|
@@ -11,7 +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
|
|
14
|
+
import ParamMediator from "../view/paramMediator.js";
|
|
15
15
|
|
|
16
16
|
export interface Hover {
|
|
17
17
|
mark: Mark;
|
|
@@ -29,7 +29,6 @@ export default interface ViewContext {
|
|
|
29
29
|
genomeStore?: GenomeStore;
|
|
30
30
|
fontManager: BmFontManager;
|
|
31
31
|
|
|
32
|
-
paramBroker: ParamBroker;
|
|
33
32
|
devicePixelRatio: number;
|
|
34
33
|
|
|
35
34
|
requestLayoutReflow: () => void;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @param {(...args:T) => R} func
|
|
3
|
-
* @param {number} wait
|
|
3
|
+
* @param {number | (() => number)} wait
|
|
4
4
|
* @template {any[]} T
|
|
5
5
|
* @template R
|
|
6
6
|
*/
|
|
7
|
-
export function debounce<T extends any[], R>(func: (...args: T) => R, wait: number, rejectOnDebounce?: boolean): (...args: T) => Promise<R>;
|
|
7
|
+
export function debounce<T extends any[], R>(func: (...args: T) => R, wait: number | (() => number), rejectOnDebounce?: boolean): (...args: T) => Promise<R>;
|
|
8
8
|
//# sourceMappingURL=debounce.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../../src/utils/debounce.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,4EAJW,MAAM,
|
|
1
|
+
{"version":3,"file":"debounce.d.ts","sourceRoot":"","sources":["../../../src/utils/debounce.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,4EAJW,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,0DAqCjC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @param {(...args:T) => R} func
|
|
3
|
-
* @param {number} wait
|
|
3
|
+
* @param {number | (() => number)} wait
|
|
4
4
|
* @template {any[]} T
|
|
5
5
|
* @template R
|
|
6
6
|
*/
|
|
@@ -29,7 +29,10 @@ export function debounce(func, wait, rejectOnDebounce = true) {
|
|
|
29
29
|
clearTimeout(timeout);
|
|
30
30
|
|
|
31
31
|
rejectPrevious = reject;
|
|
32
|
-
timeout = window.setTimeout(
|
|
32
|
+
timeout = window.setTimeout(
|
|
33
|
+
later,
|
|
34
|
+
typeof wait == "function" ? wait() : wait
|
|
35
|
+
);
|
|
33
36
|
});
|
|
34
37
|
};
|
|
35
38
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @prop { string[] } globals
|
|
5
5
|
* @prop { string } code
|
|
6
6
|
*
|
|
7
|
-
* @typedef { ((datum
|
|
7
|
+
* @typedef { ((datum?: object) => any) & ExpressionProps } ExpressionFunction
|
|
8
8
|
*
|
|
9
9
|
* @param {string} expr
|
|
10
10
|
* @returns {ExpressionFunction}
|
|
@@ -15,5 +15,5 @@ export type ExpressionProps = {
|
|
|
15
15
|
globals: string[];
|
|
16
16
|
code: string;
|
|
17
17
|
};
|
|
18
|
-
export type ExpressionFunction = ((datum
|
|
18
|
+
export type ExpressionFunction = ((datum?: object) => any) & ExpressionProps;
|
|
19
19
|
//# sourceMappingURL=expression.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../../src/utils/expression.js"],"names":[],"mappings":"AAyDA;;;;;;;;;;GAUG;AACH,6CAHW,MAAM,sBACJ,kBAAkB,CAyB9B;;YAhCU,MAAM,EAAE;aACR,MAAM,EAAE;UACR,MAAM;;
|
|
1
|
+
{"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../../src/utils/expression.js"],"names":[],"mappings":"AAyDA;;;;;;;;;;GAUG;AACH,6CAHW,MAAM,sBACJ,kBAAkB,CAyB9B;;YAhCU,MAAM,EAAE;aACR,MAAM,EAAE;UACR,MAAM;;2CAEO,MAAM,KAAK,GAAG"}
|
|
@@ -61,7 +61,7 @@ const cg = codegenExpression({
|
|
|
61
61
|
* @prop { string[] } globals
|
|
62
62
|
* @prop { string } code
|
|
63
63
|
*
|
|
64
|
-
* @typedef { ((datum
|
|
64
|
+
* @typedef { ((datum?: object) => any) & ExpressionProps } ExpressionFunction
|
|
65
65
|
*
|
|
66
66
|
* @param {string} expr
|
|
67
67
|
* @returns {ExpressionFunction}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
*
|
|
3
3
|
* @param {any} object Object to format
|
|
4
|
-
* @returns {string | import("lit
|
|
4
|
+
* @returns {string | import("lit").TemplateResult}
|
|
5
5
|
*/
|
|
6
|
-
export default function formatObject(object: any): string | import("lit
|
|
6
|
+
export default function formatObject(object: any): string | import("lit").TemplateResult;
|
|
7
7
|
//# sourceMappingURL=formatObject.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatObject.d.ts","sourceRoot":"","sources":["../../../src/utils/formatObject.js"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,6CAHW,GAAG,GACD,MAAM,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"formatObject.d.ts","sourceRoot":"","sources":["../../../src/utils/formatObject.js"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,6CAHW,GAAG,GACD,MAAM,GAAG,OAAO,KAAK,EAAE,cAAc,CA0BjD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isNumber, isString, isBoolean, isArray } from "vega-util";
|
|
2
2
|
import { format as d3format } from "d3-format";
|
|
3
|
-
import { html, nothing } from "lit
|
|
3
|
+
import { html, nothing } from "lit";
|
|
4
4
|
|
|
5
5
|
const numberFormat = d3format(".4~r");
|
|
6
6
|
const exponentNumberFormat = d3format(".4~e");
|
|
@@ -8,7 +8,7 @@ const exponentNumberFormat = d3format(".4~e");
|
|
|
8
8
|
/**
|
|
9
9
|
*
|
|
10
10
|
* @param {any} object Object to format
|
|
11
|
-
* @returns {string | import("lit
|
|
11
|
+
* @returns {string | import("lit").TemplateResult}
|
|
12
12
|
*/
|
|
13
13
|
export default function formatObject(object) {
|
|
14
14
|
if (object === null || object === undefined) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inputBinding.d.ts","sourceRoot":"","sources":["../../../src/utils/inputBinding.js"],"names":[],"mappings":"AAIA;;GAEG;AACH,sDAFW,OAAO,0BAA0B,EAAE,OAAO,8CA6GpD"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { html } from "lit";
|
|
2
|
+
import { debounce } from "./debounce.js";
|
|
3
|
+
import { tickStep } from "d3-array";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {import("../view/paramMediator.js").default} mediator
|
|
7
|
+
*/
|
|
8
|
+
export default function createBindingInputs(mediator) {
|
|
9
|
+
const random = Math.floor(Math.random() * 0xffffff).toString(16);
|
|
10
|
+
|
|
11
|
+
/** @type {import("lit").TemplateResult[]} */
|
|
12
|
+
const inputs = [];
|
|
13
|
+
|
|
14
|
+
for (const param of mediator.paramConfigs.values()) {
|
|
15
|
+
const bind = param.bind;
|
|
16
|
+
if (!bind || !("input" in bind)) {
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const name = param.name;
|
|
21
|
+
const setter = mediator.getSetter(name);
|
|
22
|
+
const value = mediator.getValue(name);
|
|
23
|
+
const label = bind.name ?? name;
|
|
24
|
+
|
|
25
|
+
// TODO: Implement two-way data binding, e.g. when an external agent changes
|
|
26
|
+
// the parameter value, the UI components should be updated.
|
|
27
|
+
|
|
28
|
+
const debouncedSetter = bind.debounce
|
|
29
|
+
? debounce(setter, bind.debounce, false)
|
|
30
|
+
: setter;
|
|
31
|
+
|
|
32
|
+
const id = `${random}-param-${name}`;
|
|
33
|
+
|
|
34
|
+
if (bind.input == "range") {
|
|
35
|
+
// TODO: Show the value next to the slider
|
|
36
|
+
inputs.push(
|
|
37
|
+
html`<label for=${id}>${label}</label>
|
|
38
|
+
<div>
|
|
39
|
+
<input
|
|
40
|
+
id=${id}
|
|
41
|
+
type="range"
|
|
42
|
+
min=${bind.min ?? 0}
|
|
43
|
+
max=${bind.max ?? 100}
|
|
44
|
+
step=${bind.step ??
|
|
45
|
+
tickStep(bind.min, bind.max, 100)}
|
|
46
|
+
.value=${value}
|
|
47
|
+
@input=${(/** @type {any} */ e) => {
|
|
48
|
+
debouncedSetter(e.target.valueAsNumber);
|
|
49
|
+
e.target.nextElementSibling.textContent =
|
|
50
|
+
e.target.valueAsNumber;
|
|
51
|
+
}}
|
|
52
|
+
/><span>${value}</span>
|
|
53
|
+
</div>`
|
|
54
|
+
);
|
|
55
|
+
} else if (bind.input == "checkbox") {
|
|
56
|
+
inputs.push(
|
|
57
|
+
html`<label for=${id}>${label}</label>
|
|
58
|
+
<input
|
|
59
|
+
id=${id}
|
|
60
|
+
type="checkbox"
|
|
61
|
+
?checked=${value}
|
|
62
|
+
@input=${(/** @type {any} */ e) =>
|
|
63
|
+
debouncedSetter(e.target.checked)}
|
|
64
|
+
/>`
|
|
65
|
+
);
|
|
66
|
+
} else if (bind.input == "radio") {
|
|
67
|
+
inputs.push(
|
|
68
|
+
html`<span class="label">${label}</span>
|
|
69
|
+
<div class="radio-group">
|
|
70
|
+
${bind.options.map(
|
|
71
|
+
(option, i) => html`<label>
|
|
72
|
+
<input
|
|
73
|
+
type="radio"
|
|
74
|
+
name=${name}
|
|
75
|
+
value=${option}
|
|
76
|
+
.checked=${value == option}
|
|
77
|
+
@input=${(/** @type {any} */ e) =>
|
|
78
|
+
debouncedSetter(e.target.value)}
|
|
79
|
+
/>${bind.labels?.[i] ?? option}</label
|
|
80
|
+
>`
|
|
81
|
+
)}
|
|
82
|
+
</div>`
|
|
83
|
+
);
|
|
84
|
+
} else if (bind.input == "select") {
|
|
85
|
+
inputs.push(
|
|
86
|
+
html`<label for=${id}>${label}</label>
|
|
87
|
+
<select
|
|
88
|
+
id=${id}
|
|
89
|
+
@input=${(/** @type {any} */ e) =>
|
|
90
|
+
debouncedSetter(e.target.value)}
|
|
91
|
+
>
|
|
92
|
+
${bind.options.map(
|
|
93
|
+
(option, i) => html`<option
|
|
94
|
+
value=${option}
|
|
95
|
+
?selected=${value == option}
|
|
96
|
+
>
|
|
97
|
+
${bind.labels?.[i] ?? option}
|
|
98
|
+
</option>`
|
|
99
|
+
)}
|
|
100
|
+
</select> `
|
|
101
|
+
);
|
|
102
|
+
} else {
|
|
103
|
+
// TODO: Support other types: "text", "number", "color".
|
|
104
|
+
throw new Error("Unsupported input type: " + bind.input);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (bind.description) {
|
|
108
|
+
inputs.push(
|
|
109
|
+
html`<div class="description">${bind.description}</div>`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return inputs;
|
|
115
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {any} x
|
|
3
|
+
* @returns {x is import("../spec/parameter.js").ExprRef}
|
|
4
|
+
*/
|
|
5
|
+
export function isExprRef(x: any): x is import("../spec/parameter.js").ExprRef;
|
|
6
|
+
/**
|
|
7
|
+
* Removes ExprRef from the type and checks that the value is not an ExprRef.
|
|
8
|
+
* This is designed to be used with `activateExprRefProps`.
|
|
9
|
+
*
|
|
10
|
+
* @param {T | import("../spec/parameter.js").ExprRef} x
|
|
11
|
+
* @template T
|
|
12
|
+
* @returns {T}
|
|
13
|
+
*/
|
|
14
|
+
export function withoutExprRef<T>(x: T | import("../spec/parameter.js").ExprRef): T;
|
|
15
|
+
/**
|
|
16
|
+
* Takes a record of properties that may have ExprRefs as values. Converts the
|
|
17
|
+
* ExprRefs to getters and setups a listener that is called when any of the
|
|
18
|
+
* expressions (upstream parameters) change.
|
|
19
|
+
*
|
|
20
|
+
* @param {ParamMediator} paramMediator
|
|
21
|
+
* @param {T} props The properties object
|
|
22
|
+
* @param {(props: (keyof T)[]) => void} [listener] Listener to be called when any of the expressions change
|
|
23
|
+
* @returns T
|
|
24
|
+
* @template {Record<string, any | import("../spec/parameter.js").ExprRef>} T
|
|
25
|
+
*/
|
|
26
|
+
export function activateExprRefProps<T extends Record<string, any>>(paramMediator: ParamMediator, props: T, listener?: (props: (keyof T)[]) => void): T;
|
|
27
|
+
/**
|
|
28
|
+
* A class that manages parameters and expressions.
|
|
29
|
+
* Supports nesting and scoped parameters.
|
|
30
|
+
*
|
|
31
|
+
* @typedef {import("../utils/expression.js").ExpressionFunction & { addListener: (listener: () => void) => void, invalidate: () => void, identifier: () => string}} ExprRefFunction
|
|
32
|
+
*/
|
|
33
|
+
export default class ParamMediator {
|
|
34
|
+
/**
|
|
35
|
+
* @param {() => ParamMediator} [parentFinder]
|
|
36
|
+
* An optional function that returns the parent mediator.
|
|
37
|
+
* N.B. The function must always return the same mediator for the same parent,
|
|
38
|
+
* i.e., the changing the structure of the hierarchy is NOT supported.
|
|
39
|
+
*/
|
|
40
|
+
constructor(parentFinder?: () => ParamMediator);
|
|
41
|
+
/**
|
|
42
|
+
* @type {Map<string, Set<() => void>>}
|
|
43
|
+
* @protected
|
|
44
|
+
*/
|
|
45
|
+
protected paramListeners: Map<string, Set<() => void>>;
|
|
46
|
+
/**
|
|
47
|
+
* @param {VariableParameter} param
|
|
48
|
+
* @returns {ParameterSetter}
|
|
49
|
+
*/
|
|
50
|
+
registerParam(param: import("../spec/parameter.js").VariableParameter): (value: any) => void;
|
|
51
|
+
/**
|
|
52
|
+
*
|
|
53
|
+
* @param {string} paramName
|
|
54
|
+
* @param {T} initialValue
|
|
55
|
+
* @returns {(value: T) => void}
|
|
56
|
+
* @template T
|
|
57
|
+
*/
|
|
58
|
+
allocateSetter<T>(paramName: string, initialValue: T): (value: T) => void;
|
|
59
|
+
/**
|
|
60
|
+
* Gets an existing setter for a parameter. Throws if the setter is not found.
|
|
61
|
+
* @param {string} paramName
|
|
62
|
+
*/
|
|
63
|
+
getSetter(paramName: string): (value: any) => void;
|
|
64
|
+
/**
|
|
65
|
+
* Get the value of a parameter from this mediator.
|
|
66
|
+
* @param {string} paramName
|
|
67
|
+
*/
|
|
68
|
+
getValue(paramName: string): any;
|
|
69
|
+
/**
|
|
70
|
+
* Get the value of a parameter from this mediator or the ancestors.
|
|
71
|
+
* @param {string} paramName
|
|
72
|
+
*/
|
|
73
|
+
findValue(paramName: string): any;
|
|
74
|
+
/**
|
|
75
|
+
* Returns configs for all parameters that have been registered using `registerParam`.
|
|
76
|
+
*/
|
|
77
|
+
get paramConfigs(): ReadonlyMap<string, import("../spec/parameter.js").VariableParameter>;
|
|
78
|
+
/**
|
|
79
|
+
*
|
|
80
|
+
* @param {string} paramName
|
|
81
|
+
* @returns {ParamMediator}
|
|
82
|
+
* @protected
|
|
83
|
+
*/
|
|
84
|
+
protected findMediatorForParam(paramName: string): ParamMediator;
|
|
85
|
+
/**
|
|
86
|
+
* Parse expr and return a function that returns the value of the parameter.
|
|
87
|
+
*
|
|
88
|
+
* @param {string} expr
|
|
89
|
+
*/
|
|
90
|
+
createExpression(expr: string): ExprRefFunction;
|
|
91
|
+
/**
|
|
92
|
+
* A convenience method for evaluating an expression.
|
|
93
|
+
*
|
|
94
|
+
* @param {string} expr
|
|
95
|
+
*/
|
|
96
|
+
evaluateAndGet(expr: string): any;
|
|
97
|
+
#private;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* A class that manages parameters and expressions.
|
|
101
|
+
* Supports nesting and scoped parameters.
|
|
102
|
+
*/
|
|
103
|
+
export type ExprRefFunction = ((datum?: object) => any) & import("../utils/expression.js").ExpressionProps & {
|
|
104
|
+
addListener: (listener: () => void) => void;
|
|
105
|
+
invalidate: () => void;
|
|
106
|
+
identifier: () => string;
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=paramMediator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paramMediator.d.ts","sourceRoot":"","sources":["../../../src/view/paramMediator.js"],"names":[],"mappings":"AAsQA;;;GAGG;AACH,6BAHW,GAAG,+CAKb;AAED;;;;;;;GAOG;AACH,oFASC;AAED;;;;;;;;;;GAUG;AACH,mFANW,aAAa,+CAEW,IAAI,KAwCtC;AA7UD;;;;;GAKG;AACH;IA2BI;;;;;OAKG;IACH,2BALW,MAAM,aAAa,EAU7B;IA7BD;;;OAGG;IACH,0BAHU,IAAI,MAAM,EAAE,IAAI,MAAM,IAAI,CAAC,CAAC,CAGvB;IA2Bf;;;OAGG;IACH,gFAzCqB,GAAG,KAAK,IAAI,CAkEhC;IAED;;;;;;OAMG;IACH,6BALW,MAAM,kCAEU,IAAI,CA8B9B;IAED;;;OAGG;IACH,qBAFW,MAAM,WA9Fc,GAAG,KAAK,IAAI,CAsG1C;IAED;;;OAGG;IACH,oBAFW,MAAM,OAIhB;IAED;;;OAGG;IACH,qBAFW,MAAM,OAKhB;IAED;;OAEG;IACH,0FAIC;IAED;;;;;OAKG;IACH,0CAJW,MAAM,GACJ,aAAa,CASzB;IAID;;;;OAIG;IACH,uBAFW,MAAM,mBA4EhB;IAED;;;;OAIG;IACH,qBAFW,MAAM,OAKhB;;CACJ;;;;;;4BA7P4F,MAAM,IAAI,KAAK,IAAI;gBAAc,MAAM,IAAI;gBAAc,MAAM,MAAM"}
|