@genome-spy/core 0.19.1 → 0.22.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 (42) hide show
  1. package/dist/index.js +42 -42
  2. package/dist/schema.json +213 -21
  3. package/package.json +3 -3
  4. package/src/genomeSpy.js +16 -11
  5. package/src/gl/dataToVertices.js +43 -46
  6. package/src/gl/includes/common.glsl +12 -12
  7. package/src/gl/includes/picking.fragment.glsl +0 -2
  8. package/src/gl/includes/picking.vertex.glsl +0 -2
  9. package/src/marks/link.js +32 -39
  10. package/src/marks/mark.js +168 -95
  11. package/src/marks/pointMark.js +28 -59
  12. package/src/marks/rectMark.js +38 -33
  13. package/src/marks/rule.js +31 -21
  14. package/src/marks/text.js +18 -14
  15. package/src/spec/mark.d.ts +0 -3
  16. package/src/spec/title.d.ts +102 -0
  17. package/src/spec/view.d.ts +6 -4
  18. package/src/tooltip/dataTooltipHandler.js +3 -2
  19. package/src/utils/binnedIndex.js +147 -0
  20. package/src/utils/binnedIndex.test.js +73 -0
  21. package/src/utils/layout/flexLayout.js +35 -3
  22. package/src/utils/layout/flexLayout.test.js +14 -0
  23. package/src/utils/layout/grid.js +95 -0
  24. package/src/utils/layout/grid.test.js +71 -0
  25. package/src/utils/layout/padding.js +13 -0
  26. package/src/utils/layout/rectangle.js +6 -0
  27. package/src/view/axisView.js +3 -5
  28. package/src/view/concatView.js +24 -275
  29. package/src/view/containerView.js +18 -0
  30. package/src/view/gridView.js +774 -0
  31. package/src/view/implicitRootView.js +14 -0
  32. package/src/view/layerView.js +15 -1
  33. package/src/view/renderingContext/deferredViewRenderingContext.js +3 -1
  34. package/src/view/renderingContext/simpleViewRenderingContext.js +3 -1
  35. package/src/view/title.js +165 -0
  36. package/src/view/unitView.js +9 -5
  37. package/src/view/view.js +35 -14
  38. package/src/view/viewContext.d.ts +6 -1
  39. package/src/view/viewUtils.js +1 -93
  40. package/src/view/zoom.js +89 -0
  41. package/src/utils/binnedRangeIndex.js +0 -83
  42. package/src/view/decoratorView.js +0 -513
package/dist/schema.json CHANGED
@@ -478,6 +478,9 @@
478
478
  "baseUrl": {
479
479
  "type": "string"
480
480
  },
481
+ "columns": {
482
+ "type": "number"
483
+ },
481
484
  "concat": {
482
485
  "items": {
483
486
  "anyOf": [
@@ -575,7 +578,14 @@
575
578
  "type": "number"
576
579
  },
577
580
  "title": {
578
- "type": "string"
581
+ "anyOf": [
582
+ {
583
+ "type": "string"
584
+ },
585
+ {
586
+ "$ref": "#/definitions/Title"
587
+ }
588
+ ]
579
589
  },
580
590
  "transform": {
581
591
  "items": {
@@ -606,7 +616,8 @@
606
616
  }
607
617
  },
608
618
  "required": [
609
- "concat"
619
+ "concat",
620
+ "columns"
610
621
  ],
611
622
  "type": "object"
612
623
  },
@@ -1335,7 +1346,14 @@
1335
1346
  "type": "number"
1336
1347
  },
1337
1348
  "title": {
1338
- "type": "string"
1349
+ "anyOf": [
1350
+ {
1351
+ "type": "string"
1352
+ },
1353
+ {
1354
+ "$ref": "#/definitions/Title"
1355
+ }
1356
+ ]
1339
1357
  },
1340
1358
  "transform": {
1341
1359
  "items": {
@@ -1624,7 +1642,14 @@
1624
1642
  "type": "object"
1625
1643
  },
1626
1644
  "title": {
1627
- "type": "string"
1645
+ "anyOf": [
1646
+ {
1647
+ "type": "string"
1648
+ },
1649
+ {
1650
+ "$ref": "#/definitions/Title"
1651
+ }
1652
+ ]
1628
1653
  },
1629
1654
  "transform": {
1630
1655
  "items": {
@@ -1633,7 +1658,7 @@
1633
1658
  "type": "array"
1634
1659
  },
1635
1660
  "view": {
1636
- "$ref": "#/definitions/ViewConfig"
1661
+ "$ref": "#/definitions/ViewBackground"
1637
1662
  },
1638
1663
  "visible": {
1639
1664
  "description": "Visibility of the view. An invisible view is removed from the layout and not rendered.\n\n**Default:** `true`",
@@ -1791,9 +1816,6 @@
1791
1816
  "description": "The vertical offset between the text and its anchor point, in pixels. Applied after the rotation by `angle`.",
1792
1817
  "type": "number"
1793
1818
  },
1794
- "dynamicData": {
1795
- "type": "boolean"
1796
- },
1797
1819
  "fill": {
1798
1820
  "type": "string"
1799
1821
  },
@@ -2972,7 +2994,14 @@
2972
2994
  "type": "object"
2973
2995
  },
2974
2996
  "title": {
2975
- "type": "string"
2997
+ "anyOf": [
2998
+ {
2999
+ "type": "string"
3000
+ },
3001
+ {
3002
+ "$ref": "#/definitions/Title"
3003
+ }
3004
+ ]
2976
3005
  },
2977
3006
  "transform": {
2978
3007
  "items": {
@@ -2981,7 +3010,7 @@
2981
3010
  "type": "array"
2982
3011
  },
2983
3012
  "view": {
2984
- "$ref": "#/definitions/ViewConfig"
3013
+ "$ref": "#/definitions/ViewBackground"
2985
3014
  },
2986
3015
  "visible": {
2987
3016
  "description": "Visibility of the view. An invisible view is removed from the layout and not rendered.\n\n**Default:** `true`",
@@ -3137,7 +3166,14 @@
3137
3166
  "type": "object"
3138
3167
  },
3139
3168
  "title": {
3140
- "type": "string"
3169
+ "anyOf": [
3170
+ {
3171
+ "type": "string"
3172
+ },
3173
+ {
3174
+ "$ref": "#/definitions/Title"
3175
+ }
3176
+ ]
3141
3177
  },
3142
3178
  "transform": {
3143
3179
  "items": {
@@ -3146,7 +3182,7 @@
3146
3182
  "type": "array"
3147
3183
  },
3148
3184
  "view": {
3149
- "$ref": "#/definitions/ViewConfig"
3185
+ "$ref": "#/definitions/ViewBackground"
3150
3186
  },
3151
3187
  "visible": {
3152
3188
  "description": "Visibility of the view. An invisible view is removed from the layout and not rendered.\n\n**Default:** `true`",
@@ -3292,7 +3328,14 @@
3292
3328
  "type": "boolean"
3293
3329
  },
3294
3330
  "title": {
3295
- "type": "string"
3331
+ "anyOf": [
3332
+ {
3333
+ "type": "string"
3334
+ },
3335
+ {
3336
+ "$ref": "#/definitions/Title"
3337
+ }
3338
+ ]
3296
3339
  },
3297
3340
  "transform": {
3298
3341
  "items": {
@@ -3432,7 +3475,14 @@
3432
3475
  "type": "number"
3433
3476
  },
3434
3477
  "title": {
3435
- "type": "string"
3478
+ "anyOf": [
3479
+ {
3480
+ "type": "string"
3481
+ },
3482
+ {
3483
+ "$ref": "#/definitions/Title"
3484
+ }
3485
+ ]
3436
3486
  },
3437
3487
  "transform": {
3438
3488
  "items": {
@@ -3597,7 +3647,14 @@
3597
3647
  "type": "number"
3598
3648
  },
3599
3649
  "title": {
3600
- "type": "string"
3650
+ "anyOf": [
3651
+ {
3652
+ "type": "string"
3653
+ },
3654
+ {
3655
+ "$ref": "#/definitions/Title"
3656
+ }
3657
+ ]
3601
3658
  },
3602
3659
  "transform": {
3603
3660
  "items": {
@@ -3641,6 +3698,9 @@
3641
3698
  "baseUrl": {
3642
3699
  "type": "string"
3643
3700
  },
3701
+ "columns": {
3702
+ "type": "number"
3703
+ },
3644
3704
  "concat": {
3645
3705
  "items": {
3646
3706
  "anyOf": [
@@ -3749,7 +3809,14 @@
3749
3809
  "type": "number"
3750
3810
  },
3751
3811
  "title": {
3752
- "type": "string"
3812
+ "anyOf": [
3813
+ {
3814
+ "type": "string"
3815
+ },
3816
+ {
3817
+ "$ref": "#/definitions/Title"
3818
+ }
3819
+ ]
3753
3820
  },
3754
3821
  "transform": {
3755
3822
  "items": {
@@ -3780,6 +3847,7 @@
3780
3847
  }
3781
3848
  },
3782
3849
  "required": [
3850
+ "columns",
3783
3851
  "concat"
3784
3852
  ],
3785
3853
  "type": "object"
@@ -3947,7 +4015,14 @@
3947
4015
  "type": "boolean"
3948
4016
  },
3949
4017
  "title": {
3950
- "type": "string"
4018
+ "anyOf": [
4019
+ {
4020
+ "type": "string"
4021
+ },
4022
+ {
4023
+ "$ref": "#/definitions/Title"
4024
+ }
4025
+ ]
3951
4026
  },
3952
4027
  "transform": {
3953
4028
  "items": {
@@ -4498,6 +4573,109 @@
4498
4573
  }
4499
4574
  ]
4500
4575
  },
4576
+ "Title": {
4577
+ "additionalProperties": false,
4578
+ "properties": {
4579
+ "align": {
4580
+ "$ref": "#/definitions/Align",
4581
+ "description": "Horizontal text alignment for title text. One of `\"left\"`, `\"center\"`, or `\"right\"`."
4582
+ },
4583
+ "anchor": {
4584
+ "$ref": "#/definitions/TitleAnchor",
4585
+ "description": "The anchor position for placing the title and subtitle text. One of `\"start\"`, `\"middle\"`, or `\"end\"`. For example, with an orientation of top these anchor positions map to a left-, center-, or right-aligned title."
4586
+ },
4587
+ "angle": {
4588
+ "description": "Angle in degrees of title and subtitle text.",
4589
+ "type": "number"
4590
+ },
4591
+ "baseline": {
4592
+ "$ref": "#/definitions/Baseline",
4593
+ "description": "Vertical text baseline for title and subtitle text. One of `\"alphabetic\"` (default), `\"top\"`, `\"middle\"`, or `\"bottom\"`."
4594
+ },
4595
+ "color": {
4596
+ "description": "Text color for title text.",
4597
+ "type": "string"
4598
+ },
4599
+ "dx": {
4600
+ "description": "Delta offset for title and subtitle text x-coordinate.",
4601
+ "type": "number"
4602
+ },
4603
+ "dy": {
4604
+ "description": "Delta offset for title and subtitle text y-coordinate.",
4605
+ "type": "number"
4606
+ },
4607
+ "font": {
4608
+ "description": "Font name for title text.",
4609
+ "type": "string"
4610
+ },
4611
+ "fontSize": {
4612
+ "description": "Font size in pixels for title text.",
4613
+ "minimum": 0,
4614
+ "type": "number"
4615
+ },
4616
+ "fontStyle": {
4617
+ "$ref": "#/definitions/FontStyle",
4618
+ "description": "Font style for title text."
4619
+ },
4620
+ "fontWeight": {
4621
+ "$ref": "#/definitions/FontWeight",
4622
+ "description": "Font weight for title text. This can be either a string (e.g `\"bold\"`, `\"normal\"`) or a number (`100`, `200`, `300`, ..., `900` where `\"normal\"` = `400` and `\"bold\"` = `700`)."
4623
+ },
4624
+ "frame": {
4625
+ "$ref": "#/definitions/TitleFrame",
4626
+ "description": "The reference frame for the anchor position, one of `\"bounds\"` (to anchor relative to the full bounding box) or `\"group\"` (to anchor relative to the group width or height)."
4627
+ },
4628
+ "offset": {
4629
+ "description": "The orthogonal offset in pixels by which to displace the title group from its position along the edge of the chart.",
4630
+ "type": "number"
4631
+ },
4632
+ "orient": {
4633
+ "$ref": "#/definitions/TitleOrient",
4634
+ "description": "Default title orientation (`\"top\"`, `\"bottom\"`, `\"left\"`, or `\"right\"`)"
4635
+ },
4636
+ "style": {
4637
+ "description": "A mark style property to apply to the title text mark. If not specified, a default style of `\"group-title\"` is applied.",
4638
+ "type": "string"
4639
+ },
4640
+ "text": {
4641
+ "description": "The title text.",
4642
+ "type": "string"
4643
+ }
4644
+ },
4645
+ "required": [
4646
+ "text"
4647
+ ],
4648
+ "type": "object"
4649
+ },
4650
+ "TitleAnchor": {
4651
+ "enum": [
4652
+ null,
4653
+ "start",
4654
+ "middle",
4655
+ "end"
4656
+ ],
4657
+ "type": [
4658
+ "null",
4659
+ "string"
4660
+ ]
4661
+ },
4662
+ "TitleFrame": {
4663
+ "enum": [
4664
+ "bounds",
4665
+ "group"
4666
+ ],
4667
+ "type": "string"
4668
+ },
4669
+ "TitleOrient": {
4670
+ "enum": [
4671
+ "none",
4672
+ "left",
4673
+ "right",
4674
+ "top",
4675
+ "bottom"
4676
+ ],
4677
+ "type": "string"
4678
+ },
4501
4679
  "Tooltip": {
4502
4680
  "anyOf": [
4503
4681
  {
@@ -4696,7 +4874,14 @@
4696
4874
  "type": "object"
4697
4875
  },
4698
4876
  "title": {
4699
- "type": "string"
4877
+ "anyOf": [
4878
+ {
4879
+ "type": "string"
4880
+ },
4881
+ {
4882
+ "$ref": "#/definitions/Title"
4883
+ }
4884
+ ]
4700
4885
  },
4701
4886
  "transform": {
4702
4887
  "items": {
@@ -4705,7 +4890,7 @@
4705
4890
  "type": "array"
4706
4891
  },
4707
4892
  "view": {
4708
- "$ref": "#/definitions/ViewConfig"
4893
+ "$ref": "#/definitions/ViewBackground"
4709
4894
  },
4710
4895
  "visible": {
4711
4896
  "description": "Visibility of the view. An invisible view is removed from the layout and not rendered.\n\n**Default:** `true`",
@@ -4855,7 +5040,14 @@
4855
5040
  "type": "number"
4856
5041
  },
4857
5042
  "title": {
4858
- "type": "string"
5043
+ "anyOf": [
5044
+ {
5045
+ "type": "string"
5046
+ },
5047
+ {
5048
+ "$ref": "#/definitions/Title"
5049
+ }
5050
+ ]
4859
5051
  },
4860
5052
  "transform": {
4861
5053
  "items": {
@@ -4932,7 +5124,7 @@
4932
5124
  ],
4933
5125
  "type": "object"
4934
5126
  },
4935
- "ViewConfig": {
5127
+ "ViewBackground": {
4936
5128
  "additionalProperties": false,
4937
5129
  "properties": {
4938
5130
  "cornerRadius": {
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "contributors": [],
9
9
  "license": "BSD-2-Clause",
10
- "version": "0.19.1",
10
+ "version": "0.22.0",
11
11
  "main": "dist/index.js",
12
12
  "module": "src/index.js",
13
13
  "exports": {
@@ -44,7 +44,7 @@
44
44
  "d3-color": "^3.0.1",
45
45
  "d3-ease": "^3.0.1",
46
46
  "d3-format": "^3.0.1",
47
- "flatqueue": "^1.2.1",
47
+ "flatqueue": "^2.0.3",
48
48
  "internmap": "^2.0.3",
49
49
  "lit-html": "^2.0.2",
50
50
  "twgl.js": "^4.19.1",
@@ -53,5 +53,5 @@
53
53
  "vega-scale": "^7.1.1",
54
54
  "vega-util": "^1.16.0"
55
55
  },
56
- "gitHead": "ca14d08659918a002fb330ffcd325e9c1e122a8c"
56
+ "gitHead": "0584f32e402341b913b2cc43543c95ccbb7b846b"
57
57
  }
package/src/genomeSpy.js CHANGED
@@ -8,7 +8,6 @@ import Tooltip from "./utils/ui/tooltip";
8
8
  import AccessorFactory from "./encoder/accessor";
9
9
  import {
10
10
  resolveScalesAndAxes,
11
- addDecorators,
12
11
  processImports,
13
12
  setImplicitScaleNames,
14
13
  } from "./view/viewUtils";
@@ -17,7 +16,6 @@ import UnitView from "./view/unitView";
17
16
  import WebGLHelper from "./gl/webGLHelper";
18
17
  import Rectangle from "./utils/layout/rectangle";
19
18
  import DeferredViewRenderingContext from "./view/renderingContext/deferredViewRenderingContext";
20
- import LayoutRecorderViewRenderingContext from "./view/renderingContext/layoutRecorderViewRenderingContext";
21
19
  import CompositeViewRenderingContext from "./view/renderingContext/compositeViewRenderingContext";
22
20
  import InteractionEvent from "./utils/interactionEvent";
23
21
  import Point from "./utils/layout/point";
@@ -36,6 +34,8 @@ import refseqGeneTooltipHandler from "./tooltip/refseqGeneTooltipHandler";
36
34
  import dataTooltipHandler from "./tooltip/dataTooltipHandler";
37
35
  import { invalidatePrefix } from "./utils/propertyCacher";
38
36
  import { ViewFactory } from "./view/viewFactory";
37
+ import LayerView from "./view/layerView";
38
+ import ImplicitRootView from "./view/implicitRootView";
39
39
 
40
40
  /**
41
41
  * @typedef {import("./spec/view").UnitSpec} UnitSpec
@@ -166,7 +166,9 @@ export default class GenomeSpy {
166
166
 
167
167
  this._glHelper = new WebGLHelper(this.container, () => {
168
168
  if (this.viewRoot) {
169
- const size = this.viewRoot.getSize();
169
+ const size = this.viewRoot
170
+ .getSize()
171
+ .addPadding(this.viewRoot.getOverhang());
170
172
 
171
173
  // If a dimension has an absolutely specified size (in pixels), use it for the canvas size.
172
174
  // However, if the dimension has a growing component, the canvas should be fit to the
@@ -283,12 +285,19 @@ export default class GenomeSpy {
283
285
  // Replace placeholder ImportViews with actual views.
284
286
  await processImports(this.viewRoot);
285
287
 
288
+ if (
289
+ this.viewRoot instanceof UnitView ||
290
+ this.viewRoot instanceof LayerView
291
+ ) {
292
+ this.viewRoot = new ImplicitRootView(context, this.viewRoot);
293
+ }
294
+
286
295
  // Resolve scales, i.e., if possible, pull them towards the root
287
296
  resolveScalesAndAxes(this.viewRoot);
288
297
  setImplicitScaleNames(this.viewRoot);
289
298
 
290
299
  // Wrap unit or layer views that need axes
291
- this.viewRoot = addDecorators(this.viewRoot);
300
+ //this.viewRoot = addDecorators(this.viewRoot);
292
301
 
293
302
  // We should now have a complete view hierarchy. Let's update the canvas size
294
303
  // and ensure that the loading message is visible.
@@ -424,7 +433,7 @@ export default class GenomeSpy {
424
433
 
425
434
  /** @param {Event} event */
426
435
  const listener = (event) => {
427
- if (this.layout && event instanceof MouseEvent) {
436
+ if (event instanceof MouseEvent) {
428
437
  if (event.type == "mousemove") {
429
438
  this.tooltip.handleMouseMove(event);
430
439
  this._tooltipUpdateRequested = false;
@@ -445,7 +454,7 @@ export default class GenomeSpy {
445
454
  * @param {MouseEvent} event
446
455
  */
447
456
  const dispatchEvent = (event) => {
448
- this.layout.dispatchInteractionEvent(
457
+ this.viewRoot.propagateInteractionEvent(
449
458
  new InteractionEvent(point, event)
450
459
  );
451
460
 
@@ -677,20 +686,16 @@ export default class GenomeSpy {
677
686
  },
678
687
  this._glHelper
679
688
  );
680
- const layoutRecorder = new LayoutRecorderViewRenderingContext({});
681
689
 
682
690
  root.render(
683
691
  new CompositeViewRenderingContext(
684
692
  this._renderingContext,
685
- this._pickingContext,
686
- layoutRecorder
693
+ this._pickingContext
687
694
  ),
688
695
  // Canvas should now be sized based on the root view or the container
689
696
  Rectangle.create(0, 0, canvasSize.width, canvasSize.height)
690
697
  );
691
698
 
692
- this.layout = layoutRecorder.getLayout();
693
-
694
699
  this.broadcast("layoutComputed");
695
700
  }
696
701