@genome-spy/core 0.44.0 → 0.46.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 (129) hide show
  1. package/dist/bundle/{index-lmJu1tfP.js → index-BtRKzKhM.js} +6 -6
  2. package/dist/bundle/{index--cKb-dKG.js → index-BwFvhduA.js} +5 -5
  3. package/dist/bundle/{index-1QVesMzU.js → index-C8lYPtq_.js} +1 -1
  4. package/dist/bundle/{index-Pv3tKJ1W.js → index-CkI3Kd2P.js} +3 -3
  5. package/dist/bundle/{index-Y-LdHNIz.js → index-CmBp-spD.js} +1 -1
  6. package/dist/bundle/{index-z4Cs62EO.js → index-Dixm7K89.js} +4 -4
  7. package/dist/bundle/{index-noY1e-G6.js → index-Sk-Wtwdn.js} +5 -5
  8. package/dist/bundle/{index-UyrC0vvF.js → index-Z7JiNsFI.js} +4 -4
  9. package/dist/bundle/{index-LD6yPc3X.js → index-mihmTLo-.js} +1 -1
  10. package/dist/bundle/index.es.js +6339 -5615
  11. package/dist/bundle/index.js +222 -150
  12. package/dist/bundle/{long-Veu0zKh9.js → long-CYrAUkxh.js} +2 -2
  13. package/dist/bundle/{remoteFile-Ur-gRKsH.js → remoteFile-1_eCK3VV.js} +1 -1
  14. package/dist/schema.json +481 -90
  15. package/dist/src/data/collector.d.ts +1 -0
  16. package/dist/src/data/collector.d.ts.map +1 -1
  17. package/dist/src/data/collector.js +23 -5
  18. package/dist/src/data/flow.test.js +4 -0
  19. package/dist/src/data/flowNode.d.ts +10 -8
  20. package/dist/src/data/flowNode.d.ts.map +1 -1
  21. package/dist/src/data/flowNode.js +25 -15
  22. package/dist/src/data/flowOptimizer.test.js +12 -3
  23. package/dist/src/data/sources/dataSource.d.ts +17 -0
  24. package/dist/src/data/sources/dataSource.d.ts.map +1 -1
  25. package/dist/src/data/sources/dataSource.js +34 -0
  26. package/dist/src/data/sources/dataUtils.d.ts.map +1 -1
  27. package/dist/src/data/sources/dataUtils.js +3 -1
  28. package/dist/src/data/sources/inlineSource.js +1 -1
  29. package/dist/src/data/sources/lazy/bigBedSource.d.ts +1 -1
  30. package/dist/src/data/sources/lazy/bigBedSource.d.ts.map +1 -1
  31. package/dist/src/data/sources/lazy/bigBedSource.js +58 -20
  32. package/dist/src/data/sources/lazy/bigWigSource.d.ts +0 -1
  33. package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
  34. package/dist/src/data/sources/lazy/bigWigSource.js +58 -19
  35. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +0 -8
  36. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  37. package/dist/src/data/sources/lazy/singleAxisLazySource.js +1 -15
  38. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts +6 -2
  39. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  40. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +41 -23
  41. package/dist/src/data/sources/namedSource.js +1 -1
  42. package/dist/src/data/sources/sequenceSource.d.ts.map +1 -1
  43. package/dist/src/data/sources/sequenceSource.js +16 -6
  44. package/dist/src/data/sources/sequenceSource.test.js +23 -5
  45. package/dist/src/data/sources/urlSource.d.ts.map +1 -1
  46. package/dist/src/data/sources/urlSource.js +24 -7
  47. package/dist/src/data/transforms/aggregate.d.ts.map +1 -1
  48. package/dist/src/data/transforms/aggregate.js +5 -2
  49. package/dist/src/data/transforms/filter.d.ts +2 -2
  50. package/dist/src/data/transforms/filter.d.ts.map +1 -1
  51. package/dist/src/data/transforms/filter.js +3 -6
  52. package/dist/src/data/transforms/filter.test.js +6 -0
  53. package/dist/src/data/transforms/formula.d.ts +2 -2
  54. package/dist/src/data/transforms/formula.d.ts.map +1 -1
  55. package/dist/src/data/transforms/formula.js +3 -3
  56. package/dist/src/data/transforms/formula.test.js +7 -1
  57. package/dist/src/encoder/encoder.d.ts +2 -4
  58. package/dist/src/encoder/encoder.d.ts.map +1 -1
  59. package/dist/src/encoder/encoder.js +8 -8
  60. package/dist/src/encoder/encoder.test.js +3 -0
  61. package/dist/src/genomeSpy.d.ts +12 -7
  62. package/dist/src/genomeSpy.d.ts.map +1 -1
  63. package/dist/src/genomeSpy.js +132 -139
  64. package/dist/src/gl/glslScaleGenerator.js +1 -1
  65. package/dist/src/index.d.ts +1 -1
  66. package/dist/src/index.d.ts.map +1 -1
  67. package/dist/src/index.js +1 -1
  68. package/dist/src/marks/mark.d.ts +8 -5
  69. package/dist/src/marks/mark.d.ts.map +1 -1
  70. package/dist/src/marks/mark.js +67 -12
  71. package/dist/src/marks/point.common.glsl.js +1 -1
  72. package/dist/src/marks/point.d.ts +1 -4
  73. package/dist/src/marks/point.d.ts.map +1 -1
  74. package/dist/src/marks/point.js +31 -23
  75. package/dist/src/marks/point.vertex.glsl.js +1 -1
  76. package/dist/src/marks/text.d.ts.map +1 -1
  77. package/dist/src/marks/text.js +15 -7
  78. package/dist/src/spec/data.d.ts +11 -10
  79. package/dist/src/spec/mark.d.ts +11 -21
  80. package/dist/src/spec/parameter.d.ts +11 -7
  81. package/dist/src/spec/root.d.ts +0 -8
  82. package/dist/src/spec/title.d.ts +5 -4
  83. package/dist/src/spec/view.d.ts +64 -6
  84. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  85. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  86. package/dist/src/styles/genome-spy.css.js +56 -5
  87. package/dist/src/styles/genome-spy.scss +68 -10
  88. package/dist/src/styles/update.sh +6 -0
  89. package/dist/src/tooltip/dataTooltipHandler.js +1 -1
  90. package/dist/src/tooltip/refseqGeneTooltipHandler.js +1 -1
  91. package/dist/src/tooltip/tooltipHandler.d.ts +1 -1
  92. package/dist/src/tooltip/tooltipHandler.d.ts.map +1 -1
  93. package/dist/src/tooltip/tooltipHandler.ts +1 -1
  94. package/dist/src/types/embedApi.d.ts +6 -0
  95. package/dist/src/types/viewContext.d.ts +11 -5
  96. package/dist/src/utils/debounce.d.ts +2 -2
  97. package/dist/src/utils/debounce.d.ts.map +1 -1
  98. package/dist/src/utils/debounce.js +5 -2
  99. package/dist/src/utils/expression.d.ts +2 -2
  100. package/dist/src/utils/expression.d.ts.map +1 -1
  101. package/dist/src/utils/expression.js +2 -2
  102. package/dist/src/utils/formatObject.d.ts +2 -2
  103. package/dist/src/utils/formatObject.d.ts.map +1 -1
  104. package/dist/src/utils/formatObject.js +2 -2
  105. package/dist/src/utils/inputBinding.d.ts +5 -0
  106. package/dist/src/utils/inputBinding.d.ts.map +1 -0
  107. package/dist/src/utils/inputBinding.js +115 -0
  108. package/dist/src/utils/ui/tooltip.js +1 -1
  109. package/dist/src/view/paramMediator.d.ts +109 -0
  110. package/dist/src/view/paramMediator.d.ts.map +1 -0
  111. package/dist/src/view/paramMediator.js +338 -0
  112. package/dist/src/view/paramMediator.test.js +224 -0
  113. package/dist/src/view/scaleResolution.d.ts.map +1 -1
  114. package/dist/src/view/scaleResolution.js +11 -6
  115. package/dist/src/view/view.d.ts +4 -1
  116. package/dist/src/view/view.d.ts.map +1 -1
  117. package/dist/src/view/view.js +19 -5
  118. package/dist/src/view/viewFactory.d.ts +4 -1
  119. package/dist/src/view/viewFactory.d.ts.map +1 -1
  120. package/dist/src/view/viewFactory.js +86 -13
  121. package/dist/src/view/viewUtils.d.ts +7 -8
  122. package/dist/src/view/viewUtils.d.ts.map +1 -1
  123. package/dist/src/view/viewUtils.js +30 -34
  124. package/package.json +16 -17
  125. package/dist/src/paramBroker.d.ts +0 -46
  126. package/dist/src/paramBroker.d.ts.map +0 -1
  127. package/dist/src/paramBroker.js +0 -118
  128. /package/dist/bundle/{__vite-browser-external-ENoMJThg.js → __vite-browser-external-C--ziKoh.js} +0 -0
  129. /package/dist/bundle/{_commonjsHelpers-QtkX90xp.js → _commonjsHelpers-BIiJCwQW.js} +0 -0
@@ -16,7 +16,7 @@ import { appendToBaseUrl } from "../utils/url.js";
16
16
  import { isDiscrete, bandSpace } from "vega-scale";
17
17
  import { peek } from "../utils/arrayUtils.js";
18
18
  import ViewError from "./viewError.js";
19
- import { isExprRef } from "../marks/mark.js";
19
+ import ParamMediator, { isExprRef } from "./paramMediator.js";
20
20
 
21
21
  // TODO: View classes have too many responsibilities. Come up with a way
22
22
  // to separate the concerns. However, most concerns are tightly tied to
@@ -128,6 +128,17 @@ export default class View {
128
128
  * @type {Record<import("../spec/channel.js").PrimaryPositionalChannel, boolean>}
129
129
  */
130
130
  this.needsAxes = { x: false, y: false };
131
+
132
+ /** @type {ParamMediator} */
133
+ this.paramMediator = new ParamMediator(
134
+ () => this.dataParent?.paramMediator
135
+ );
136
+
137
+ if (spec.params) {
138
+ for (const param of spec.params) {
139
+ this.paramMediator.registerParam(param);
140
+ }
141
+ }
131
142
  }
132
143
 
133
144
  getPadding() {
@@ -631,7 +642,11 @@ export default class View {
631
642
  getTitleText() {
632
643
  const title = this.spec.title;
633
644
  if (title) {
634
- return isString(title) ? title : title.text;
645
+ return isString(title)
646
+ ? title
647
+ : isExprRef(title.text)
648
+ ? this.paramMediator.evaluateAndGet(title.text.expr)
649
+ : title.text;
635
650
  }
636
651
  }
637
652
 
@@ -736,9 +751,8 @@ function createViewOpacityFunction(view) {
736
751
  return interpolate(unitsPerPixel) * parentOpacity;
737
752
  };
738
753
  } else if (isExprRef(opacityDef)) {
739
- const fn = view.context.paramBroker.createExpression(
740
- opacityDef.expr
741
- );
754
+ const fn = view.paramMediator.createExpression(opacityDef.expr);
755
+ fn.addListener(() => view.context.animator.requestRender());
742
756
  return (parentOpacity) => fn(null) * parentOpacity;
743
757
  }
744
758
  }
@@ -55,7 +55,7 @@ export function isSampleSpec(spec: import("../spec/view.js").ViewSpec): spec is
55
55
  export const VIEW_ROOT_NAME: "viewRoot";
56
56
  /**
57
57
  * @typedef {object} ViewFactoryOptions
58
- * @property {boolean} [allowImport]
58
+ * @property {boolean} [allowImport] allows imports from urls
59
59
  * @property {boolean} [wrapRoot]
60
60
  */
61
61
  /**
@@ -102,6 +102,9 @@ export class ViewFactory {
102
102
  #private;
103
103
  }
104
104
  export type ViewFactoryOptions = {
105
+ /**
106
+ * allows imports from urls
107
+ */
105
108
  allowImport?: boolean;
106
109
  wrapRoot?: boolean;
107
110
  };
@@ -1 +1 @@
1
- {"version":3,"file":"viewFactory.d.ts","sourceRoot":"","sources":["../../../src/view/viewFactory.js"],"names":[],"mappings":"AAuMA;;;;GAIG;AACH,iHAEC;AAED;;;;GAIG;AACH,mHAEC;AAED;;;;GAIG;AACH,mHAOC;AAED;;;;GAIG;AACH,yIAMC;AAED;;;;GAIG;AACH,mCAHW,MAAM,gDAKhB;AAED;;;;GAIG;AACH,uHAEC;AAED;;;;GAIG;AACH,6FAEC;AAED;;;;GAIG;AACH,qHAEC;AAED;;;;GAIG;AACH,2HAOC;AAzRD,wCAAyC;AAEzC;;;;GAIG;AAEH;;GAEG;AACH;IAiBI;;OAEG;IACH,sBAFW,kBAAkB,EAoC5B;IAjCG,2CAA2C;IAC3C,SADW,SAAS,kBAAkB,CAAC,CAKtC;IA8BL;;;OAGG;IACH,qEAlDiC,OAAO,yHAC2B,OAAO,oBAAoB,EAAE,OAAO,eAAe,OAAO,WAAW,EAAE,OAAO,gBAAgB,MAAM,KAAK,IAAI,QAmD/K;IAED;;;;;;OAMG;IACH,wHAJW,OAAO,oBAAoB,EAAE,OAAO,eACpC,OAAO,WAAW,EAAE,OAAO,gBAC3B,MAAM,QAmBhB;IAED;;;;OAIG;IACH,iGAQC;IAED;;;;;;;;;;OAUG;IACH,uKALW,OAAO,oBAAoB,EAAE,OAAO,eACpC,OAAO,WAAW,EAAE,OAAO,gBAC3B,MAAM,4DACc,IAAI,iBA4DlC;;CACJ;;kBAtLa,OAAO;eACP,OAAO;;iBAfJ,WAAW"}
1
+ {"version":3,"file":"viewFactory.d.ts","sourceRoot":"","sources":["../../../src/view/viewFactory.js"],"names":[],"mappings":"AAgRA;;;;GAIG;AACH,iHAEC;AAED;;;;GAIG;AACH,mHAEC;AAED;;;;GAIG;AACH,mHAOC;AAED;;;;GAIG;AACH,yIAMC;AAED;;;;GAIG;AACH,mCAHW,MAAM,gDAKhB;AAED;;;;GAIG;AACH,uHAEC;AAED;;;;GAIG;AACH,6FAEC;AAED;;;;GAIG;AACH,qHAEC;AAED;;;;GAIG;AACH,2HAOC;AAlWD,wCAAyC;AAEzC;;;;GAIG;AAEH;;GAEG;AACH;IAiBI;;OAEG;IACH,sBAFW,kBAAkB,EAoC5B;IAjCG,2CAA2C;IAC3C,SADW,SAAS,kBAAkB,CAAC,CAKtC;IA8BL;;;OAGG;IACH,qEAlDiC,OAAO,yHAC2B,OAAO,oBAAoB,EAAE,OAAO,eAAe,OAAO,WAAW,EAAE,OAAO,gBAAgB,MAAM,KAAK,IAAI,QAmD/K;IAED;;;;;;OAMG;IACH,wHAJW,OAAO,oBAAoB,EAAE,OAAO,eACpC,OAAO,WAAW,EAAE,OAAO,gBAC3B,MAAM,QAmBhB;IAED;;;;OAIG;IACH,iGAQC;IAED;;;;;;;;;;OAUG;IACH,uKALW,OAAO,oBAAoB,EAAE,OAAO,eACpC,OAAO,WAAW,EAAE,OAAO,gBAC3B,MAAM,4DACc,IAAI,iBAuElC;;CACJ;;;;;kBAjMa,OAAO;eACP,OAAO;;iBAfJ,WAAW"}
@@ -13,7 +13,7 @@ export const VIEW_ROOT_NAME = "viewRoot";
13
13
 
14
14
  /**
15
15
  * @typedef {object} ViewFactoryOptions
16
- * @property {boolean} [allowImport]
16
+ * @property {boolean} [allowImport] allows imports from urls
17
17
  * @property {boolean} [wrapRoot]
18
18
  */
19
19
 
@@ -148,22 +148,33 @@ export class ViewFactory {
148
148
  let viewSpec;
149
149
 
150
150
  if (isImportSpec(spec)) {
151
- if (this.options.allowImport) {
152
- viewSpec = await loadExternalViewSpec(
153
- spec,
154
- dataParent.getBaseUrl(),
155
- context
156
- );
151
+ /** @type {ViewSpec} */
152
+ let importedSpec;
157
153
 
158
- if (validator) {
159
- validator(viewSpec);
154
+ if ("url" in spec.import) {
155
+ if (this.options.allowImport) {
156
+ importedSpec = await loadExternalViewSpec(
157
+ spec,
158
+ dataParent.getBaseUrl(),
159
+ context
160
+ );
161
+ } else {
162
+ throw new ViewError(
163
+ "Importing views is not allowed!",
164
+ layoutParent
165
+ );
160
166
  }
167
+ } else if ("template" in spec.import) {
168
+ importedSpec = findTemplate(spec.import.template, dataParent);
161
169
  } else {
162
- throw new ViewError(
163
- "Importing views is not allowed!",
164
- layoutParent
165
- );
170
+ throw new Error("Invalid import: " + JSON.stringify(spec));
166
171
  }
172
+
173
+ validator?.(importedSpec);
174
+
175
+ applyParamsToImportedSpec(importedSpec, spec);
176
+
177
+ viewSpec = importedSpec;
167
178
  } else {
168
179
  viewSpec = spec;
169
180
  }
@@ -197,6 +208,68 @@ export class ViewFactory {
197
208
  }
198
209
  }
199
210
 
211
+ /**
212
+ * @param {string} name
213
+ * @param {View} view Start searching from this view, then search within its parent, etc.
214
+ */
215
+ function findTemplate(name, view) {
216
+ const template = view.spec?.templates?.[name];
217
+ if (template) {
218
+ // Ensure that the template is not altered
219
+ return structuredClone(template);
220
+ }
221
+
222
+ if (view.dataParent) {
223
+ return findTemplate(name, view.dataParent);
224
+ } else {
225
+ throw new Error(
226
+ `Cannot find template "${name}" in current view or its ancestors!`
227
+ );
228
+ }
229
+ }
230
+
231
+ /**
232
+ * @param {ViewSpec} importedSpec
233
+ * @param {import("../spec/view.js").ImportSpec} importSpec
234
+ */
235
+ function applyParamsToImportedSpec(importedSpec, importSpec) {
236
+ if (importSpec.name != null) {
237
+ importedSpec.name = importSpec.name;
238
+ }
239
+
240
+ const params = isArray(importSpec.params)
241
+ ? importSpec.params
242
+ : isObject(importSpec.params)
243
+ ? Object.entries(importSpec.params).map(([name, value]) => ({
244
+ name,
245
+ value,
246
+ }))
247
+ : [];
248
+
249
+ if (!params.length) {
250
+ return;
251
+ }
252
+
253
+ importedSpec.params ??= [];
254
+
255
+ // Replace overridden parameters
256
+ for (const param of params) {
257
+ const index = importedSpec.params.findIndex(
258
+ (p) => p.name == param.name
259
+ );
260
+ if (index >= 0) {
261
+ importedSpec.params[index] = param;
262
+ }
263
+ }
264
+
265
+ // Add missing parameters
266
+ for (const param of params) {
267
+ if (!importedSpec.params.some((p) => p.name == param.name)) {
268
+ importedSpec.params.push(param);
269
+ }
270
+ }
271
+ }
272
+
200
273
  /**
201
274
  *
202
275
  * @param {ViewSpec} spec
@@ -10,12 +10,6 @@ export function isFacetFieldDef(def: import("../spec/channel.js").ChannelDef | i
10
10
  * @returns {spec is FacetMapping}
11
11
  */
12
12
  export function isFacetMapping(def: import("../spec/channel.js").FacetFieldDef | import("../spec/view.js").FacetMapping): spec is FacetMapping;
13
- /**
14
- *
15
- * @param {object} config
16
- * @returns {config is ImportConfig}
17
- */
18
- export function isImportConfig(config: object): config is ImportConfig;
19
13
  /**
20
14
  * Returns all marks in the order (DFS) they are rendered
21
15
  * @param {View} root
@@ -60,8 +54,9 @@ export function findEncodedFields(view: View): {
60
54
  * @param {import("../spec/view.js").ImportSpec} spec
61
55
  * @param {string} baseUrl
62
56
  * @param {import("../types/viewContext.js").default} viewContext
57
+ * @returns {Promise<import("../spec/view.js").ViewSpec>}
63
58
  */
64
- export function loadExternalViewSpec(spec: import("../spec/view.js").ImportSpec, baseUrl: string, viewContext: import("../types/viewContext.js").default): Promise<any>;
59
+ export function loadExternalViewSpec(spec: import("../spec/view.js").ImportSpec, baseUrl: string, viewContext: import("../types/viewContext.js").default): Promise<import("../spec/view.js").ViewSpec>;
65
60
  /**
66
61
  * @param {function(View, View[]):void} visitor
67
62
  */
@@ -82,7 +77,11 @@ export function findUniqueViewNames(root: View): Set<string>;
82
77
  /**
83
78
  * @param {View} viewRoot
84
79
  */
85
- export function calculateCanvasSize(viewRoot: View): {
80
+ export function calculateViewRootSize(viewRoot: View): import("./layout/flexLayout.js").FlexDimensions;
81
+ /**
82
+ * @param {import("./layout/flexLayout.js").FlexDimensions} viewRootSize
83
+ */
84
+ export function calculateCanvasSize(viewRootSize: import("./layout/flexLayout.js").FlexDimensions): {
86
85
  width: number;
87
86
  height: number;
88
87
  };
@@ -1 +1 @@
1
- {"version":3,"file":"viewUtils.d.ts","sourceRoot":"","sources":["../../../src/view/viewUtils.js"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,qCAHW,OAAO,oBAAoB,EAAE,UAAU,GAAG,OAAO,iBAAiB,EAAE,YAAY,yBAK1F;AAED;;;;GAIG;AACH,oCAHW,OAAO,oBAAoB,EAAE,aAAa,GAAG,OAAO,iBAAiB,EAAE,YAAY,wBAQ7F;AAED;;;;GAIG;AACH,uCAHW,MAAM,0BAKhB;AAED;;;GAGG;AACH,+BAFW,IAAI,wCAMd;AAED;;;;GAIG;AACH,wCAFW,IAAI,UASd;AAED;;GAEG;AACH,kDAFW,IAAI,QAiBd;AAED;;;;;;;GAOG;AACH,4CAFW,IAAI,QAUd;AAED;;;;GAIG;AACH,qCAJW,IAAI,iBACJ,OAAO,qBAAqB,EAAE,OAAO,CAAC,IAAI,CAAC,wDAcrD;AAED;;;GAGG;AACH,wCAFW,IAAI;UAGO,QAAQ;aAAW,OAAO,oBAAoB,EAAE,OAAO;WAAS,OAAO,oBAAoB,EAAE,KAAK;UAAQ,OAAO,oBAAoB,EAAE,IAAI;IAqBhK;AAED;;;;GAIG;AACH,2CAJW,OAAO,iBAAiB,EAAE,UAAU,WACpC,MAAM,eACN,OAAO,yBAAyB,EAAE,OAAO,gBA8BnD;AAED;;GAEG;AACH,gDAFoB,IAAI,QAAE,IAAI,EAAE,KAAE,IAAI,+BAkBrC;AAED;;;;;;GAMG;AACH,4CAJW,IAAI,QACJ,MAAM,GACJ,IAAI,EAAE,CAalB;AAED;;;GAGG;AACH,0CAFW,IAAI,eAqBd;AAOD;;GAEG;AACH,8CAFW,IAAI;;;EAgBd;AAnBM,uCAFI,MAAM,WAE0D;iBAxP9B,WAAW;qBAFnC,eAAe"}
1
+ {"version":3,"file":"viewUtils.d.ts","sourceRoot":"","sources":["../../../src/view/viewUtils.js"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,qCAHW,OAAO,oBAAoB,EAAE,UAAU,GAAG,OAAO,iBAAiB,EAAE,YAAY,yBAK1F;AAED;;;;GAIG;AACH,oCAHW,OAAO,oBAAoB,EAAE,aAAa,GAAG,OAAO,iBAAiB,EAAE,YAAY,wBAQ7F;AAED;;;GAGG;AACH,+BAFW,IAAI,wCAMd;AAED;;;;GAIG;AACH,wCAFW,IAAI,UASd;AAED;;GAEG;AACH,kDAFW,IAAI,QAiBd;AAED;;;;;;;GAOG;AACH,4CAFW,IAAI,QAUd;AAED;;;;GAIG;AACH,qCAJW,IAAI,iBACJ,OAAO,qBAAqB,EAAE,OAAO,CAAC,IAAI,CAAC,wDAcrD;AAED;;;GAGG;AACH,wCAFW,IAAI;UAGO,QAAQ;aAAW,OAAO,oBAAoB,EAAE,OAAO;WAAS,OAAO,oBAAoB,EAAE,KAAK;UAAQ,OAAO,oBAAoB,EAAE,IAAI;IAqBhK;AAED;;;;;GAKG;AACH,2CALW,OAAO,iBAAiB,EAAE,UAAU,WACpC,MAAM,eACN,OAAO,yBAAyB,EAAE,OAAO,GACvC,QAAQ,OAAO,iBAAiB,EAAE,QAAQ,CAAC,CA6BvD;AAED;;GAEG;AACH,gDAFoB,IAAI,QAAE,IAAI,EAAE,KAAE,IAAI,+BAkBrC;AAED;;;;;;GAMG;AACH,4CAJW,IAAI,QACJ,MAAM,GACJ,IAAI,EAAE,CAalB;AAED;;;GAGG;AACH,0CAFW,IAAI,eAqBd;AAOD;;GAEG;AACH,gDAFW,IAAI,mDAId;AAED;;GAEG;AACH,kDAFW,OAAO,wBAAwB,EAAE,cAAc;;;EAczD;AAxBM,uCAFI,MAAM,WAE0D;iBA/O9B,WAAW;qBAFnC,eAAe"}
@@ -30,15 +30,6 @@ export function isFacetMapping(def) {
30
30
  );
31
31
  }
32
32
 
33
- /**
34
- *
35
- * @param {object} config
36
- * @returns {config is ImportConfig}
37
- */
38
- export function isImportConfig(config) {
39
- return "name" in config || "url" in config;
40
- }
41
-
42
33
  /**
43
34
  * Returns all marks in the order (DFS) they are rendered
44
35
  * @param {View} root
@@ -151,34 +142,34 @@ export function findEncodedFields(view) {
151
142
  * @param {import("../spec/view.js").ImportSpec} spec
152
143
  * @param {string} baseUrl
153
144
  * @param {import("../types/viewContext.js").default} viewContext
145
+ * @returns {Promise<import("../spec/view.js").ViewSpec>}
154
146
  */
155
147
  export async function loadExternalViewSpec(spec, baseUrl, viewContext) {
156
- if (!spec.import.url) {
157
- throw new Error(
158
- "Cannot import, not an import spec: " + JSON.stringify(spec)
159
- );
160
- }
148
+ const importParam = spec.import;
149
+ if ("url" in importParam) {
150
+ const loader = vegaLoader({ baseURL: baseUrl });
151
+ const url = importParam.url;
161
152
 
162
- const loader = vegaLoader({ baseURL: baseUrl });
163
- const url = spec.import.url;
153
+ const importedSpec = JSON.parse(
154
+ await loader.load(url).catch((/** @type {Error} */ e) => {
155
+ throw new Error(
156
+ `Could not load imported view spec: ${url} \nReason: ${e.message}`
157
+ );
158
+ })
159
+ );
164
160
 
165
- const importedSpec = JSON.parse(
166
- await loader.load(url).catch((/** @type {Error} */ e) => {
161
+ if (viewContext.isViewSpec(importedSpec)) {
162
+ importedSpec.baseUrl = url.match(/^[^?#]*\//)?.[0];
163
+ return importedSpec;
164
+ } else {
167
165
  throw new Error(
168
- `Could not load imported view spec: ${url} \nReason: ${e.message}`
166
+ `The imported spec "${url}" is not a view spec: ${JSON.stringify(
167
+ spec
168
+ )}`
169
169
  );
170
- })
171
- );
172
-
173
- if (viewContext.isViewSpec(importedSpec)) {
174
- importedSpec.baseUrl = url.match(/^[^?#]*\//)?.[0];
175
- return importedSpec;
170
+ }
176
171
  } else {
177
- throw new Error(
178
- `The imported spec "${url}" is not a view spec: ${JSON.stringify(
179
- spec
180
- )}`
181
- );
172
+ throw new Error("Not an url import: " + JSON.stringify(importParam));
182
173
  }
183
174
  }
184
175
 
@@ -256,9 +247,14 @@ export const isCustomViewName = (name) => !/^(layer|concat)\d+$/.test(name);
256
247
  /**
257
248
  * @param {View} viewRoot
258
249
  */
259
- export function calculateCanvasSize(viewRoot) {
260
- const size = viewRoot.getSize().addPadding(viewRoot.getOverhang());
250
+ export function calculateViewRootSize(viewRoot) {
251
+ return viewRoot.getSize().addPadding(viewRoot.getOverhang());
252
+ }
261
253
 
254
+ /**
255
+ * @param {import("./layout/flexLayout.js").FlexDimensions} viewRootSize
256
+ */
257
+ export function calculateCanvasSize(viewRootSize) {
262
258
  // If a dimension has an absolutely specified size (in pixels), use it for the canvas size.
263
259
  // However, if the dimension has a growing component, the canvas should be fit to the
264
260
  // container.
@@ -267,7 +263,7 @@ export function calculateCanvasSize(viewRoot) {
267
263
  /** @param {import("./layout/flexLayout.js").SizeDef} dim */
268
264
  const f = (dim) => (dim.grow > 0 ? undefined : dim.px);
269
265
  return {
270
- width: f(size.width),
271
- height: f(size.height),
266
+ width: f(viewRootSize.width),
267
+ height: f(viewRootSize.height),
272
268
  };
273
269
  }
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "contributors": [],
9
9
  "license": "MIT",
10
- "version": "0.44.0",
10
+ "version": "0.46.0",
11
11
  "jsdelivr": "dist/bundle/index.js",
12
12
  "unpkg": "dist/bundle/index.js",
13
13
  "browser": "dist/bundle/index.js",
@@ -43,27 +43,26 @@
43
43
  "@gmod/gff": "^1.3.0",
44
44
  "@gmod/indexedfasta": "^2.0.4",
45
45
  "@gmod/tabix": "^1.5.13",
46
- "@types/d3-array": "^3.0.2",
47
- "@types/d3-dsv": "^3.0.0",
48
- "@types/d3-ease": "^3.0.0",
49
- "@types/d3-format": "^3.0.1",
50
- "@types/d3-interpolate": "^3.0.1",
51
- "@types/d3-scale": "^4.0.2",
46
+ "@types/d3-array": "^3.2.1",
47
+ "@types/d3-dsv": "^3.0.7",
48
+ "@types/d3-ease": "^3.0.2",
49
+ "@types/d3-format": "^3.0.4",
50
+ "@types/d3-interpolate": "^3.0.4",
51
+ "@types/d3-scale": "^4.0.8",
52
52
  "buffer": "^6.0.3",
53
- "d3-array": "^3.1.1",
54
- "d3-color": "^3.0.1",
53
+ "d3-array": "^3.2.4",
54
+ "d3-color": "^3.1.0",
55
55
  "d3-ease": "^3.0.1",
56
- "d3-format": "^3.0.1",
56
+ "d3-format": "^3.1.0",
57
57
  "events": "^3.3.0",
58
58
  "flatqueue": "^2.0.3",
59
59
  "internmap": "^2.0.3",
60
- "lit": "^3.1.0",
61
- "lit-html": "^3.0.2",
60
+ "lit": "^3.1.2",
62
61
  "twgl.js": "^4.19.1",
63
- "vega-expression": "^5.0.0",
64
- "vega-loader": "^4.4.0",
65
- "vega-scale": "^7.1.1",
66
- "vega-util": "^1.16.0"
62
+ "vega-expression": "^5.1.0",
63
+ "vega-loader": "^4.5.1",
64
+ "vega-scale": "^7.3.1",
65
+ "vega-util": "^1.17.2"
67
66
  },
68
- "gitHead": "87fe1d80557bb9f1c721f9ce142b437e956204f9"
67
+ "gitHead": "cb5df0a9b0ea35b7325e148d34d0184a6384da85"
69
68
  }
@@ -1,46 +0,0 @@
1
- /**
2
- * A class that manages parameters and expressions. Still a work in progress.
3
- *
4
- * TODO: Write tests for this class.
5
- *
6
- * This should eventually handle the following:
7
- * - Parameter registration
8
- * - Dependency tracking
9
- * - Calling observers when a parameter changes
10
- * - Somehow saving parameter "state" (in bookmarks)
11
- * - Maybe something else
12
- *
13
- * @typedef {import("./utils/expression.js").ExpressionFunction & { addListener: (listener: () => void) => void, invalidate: () => void}} ExprRefFunction
14
- */
15
- export default class ParamBroker {
16
- /**
17
- *
18
- * @param {string} paramName
19
- * @returns {(value: any) => void}
20
- */
21
- allocateSetter(paramName: string): (value: any) => void;
22
- /**
23
- * Parse expr and return a function that returns the value of the parameter.
24
- *
25
- * @param {string} expr
26
- */
27
- createExpression(expr: string): ExprRefFunction;
28
- #private;
29
- }
30
- /**
31
- * A class that manages parameters and expressions. Still a work in progress.
32
- *
33
- * TODO: Write tests for this class.
34
- *
35
- * This should eventually handle the following:
36
- * - Parameter registration
37
- * - Dependency tracking
38
- * - Calling observers when a parameter changes
39
- * - Somehow saving parameter "state" (in bookmarks)
40
- * - Maybe something else
41
- */
42
- export type ExprRefFunction = ((datum: object) => any) & import("./utils/expression.js").ExpressionProps & {
43
- addListener: (listener: () => void) => void;
44
- invalidate: () => void;
45
- };
46
- //# sourceMappingURL=paramBroker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"paramBroker.d.ts","sourceRoot":"","sources":["../../src/paramBroker.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;GAaG;AACH;IAyBI;;;;OAIG;IACH,0BAHW,MAAM,WACI,GAAG,KAAK,IAAI,CAqBhC;IAID;;;;OAIG;IACH,uBAFW,MAAM,mBA2ChB;;CACJ;;;;;;;;;;;;;;4BAtG2F,MAAM,IAAI,KAAK,IAAI;gBAAc,MAAM,IAAI"}
@@ -1,118 +0,0 @@
1
- import { isString } from "vega-util";
2
- import createFunction from "./utils/expression.js";
3
-
4
- /**
5
- * A class that manages parameters and expressions. Still a work in progress.
6
- *
7
- * TODO: Write tests for this class.
8
- *
9
- * This should eventually handle the following:
10
- * - Parameter registration
11
- * - Dependency tracking
12
- * - Calling observers when a parameter changes
13
- * - Somehow saving parameter "state" (in bookmarks)
14
- * - Maybe something else
15
- *
16
- * @typedef {import("./utils/expression.js").ExpressionFunction & { addListener: (listener: () => void) => void, invalidate: () => void}} ExprRefFunction
17
- */
18
- export default class ParamBroker {
19
- /** @type {Map<string, any>} */
20
- #params;
21
-
22
- /** @type {Set<string>} */
23
- #allocatedSetters;
24
-
25
- /** @type {Record<string, any>} */
26
- #proxy;
27
-
28
- /** @type {Map<string, Set<() => void>>} */
29
- #paramListeners;
30
-
31
- constructor() {
32
- this.#params = new Map();
33
- this.#allocatedSetters = new Set();
34
- this.#paramListeners = new Map();
35
-
36
- this.#proxy = new Proxy(this.#params, {
37
- get(target, prop) {
38
- return isString(prop) ? target.get(prop) : undefined;
39
- },
40
- });
41
- }
42
-
43
- /**
44
- *
45
- * @param {string} paramName
46
- * @returns {(value: any) => void}
47
- */
48
- allocateSetter(paramName) {
49
- if (this.#allocatedSetters.has(paramName)) {
50
- throw new Error(
51
- "Setter already allocated for parameter: " + paramName
52
- );
53
- }
54
-
55
- this.#allocatedSetters.add(paramName);
56
-
57
- return (value) => {
58
- this.#params.set(paramName, value);
59
-
60
- const listeners = this.#paramListeners.get(paramName);
61
- if (listeners) {
62
- for (const listener of listeners) {
63
- listener();
64
- }
65
- }
66
- };
67
- }
68
-
69
- // TODO: deallocateSetter
70
-
71
- /**
72
- * Parse expr and return a function that returns the value of the parameter.
73
- *
74
- * @param {string} expr
75
- */
76
- createExpression(expr) {
77
- /** @type {ExprRefFunction} */
78
- const fn = /** @type {any} */ (createFunction(expr, this.#proxy));
79
-
80
- for (const g of fn.globals) {
81
- if (!this.#allocatedSetters.has(g)) {
82
- throw new Error(
83
- `Unknown variable "${g}" in expression: ${expr}`
84
- );
85
- }
86
- }
87
-
88
- // Keep track of them so that they can be detached later
89
- const myListeners = new Set();
90
-
91
- /**
92
- *
93
- * @param {() => void} listener
94
- */
95
- fn.addListener = (listener) => {
96
- for (const g of fn.globals) {
97
- const listeners = this.#paramListeners.get(g) ?? new Set();
98
- this.#paramListeners.set(g, listeners);
99
- listeners.add(listener);
100
- myListeners.add(listener);
101
- }
102
- };
103
-
104
- /**
105
- * Detach listeners. This must be called if the expression is no longer used.
106
- */
107
- fn.invalidate = () => {
108
- for (const g of fn.globals) {
109
- const listeners = this.#paramListeners.get(g);
110
- for (const listener of myListeners) {
111
- listeners.delete(listener);
112
- }
113
- }
114
- };
115
-
116
- return fn;
117
- }
118
- }