@genome-spy/core 0.58.1 → 0.60.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 (117) hide show
  1. package/dist/bundle/{index-DwLfOHEk.js → index-5ajWdKly.js} +1 -1
  2. package/dist/bundle/{index-vgGDWUPz.js → index-B03-Om4z.js} +1 -1
  3. package/dist/bundle/index-Bg7C4Xat.js +2750 -0
  4. package/dist/bundle/{index-CalimFw3.js → index-C3QR8Lv6.js} +79 -79
  5. package/dist/bundle/{index-DKe9Bhvi.js → index-g8iXgW0W.js} +1 -1
  6. package/dist/bundle/index.es.js +6554 -6011
  7. package/dist/bundle/index.js +189 -164
  8. package/dist/bundle/{long-BviWyoZx.js → long-B-FASCSo.js} +45 -45
  9. package/dist/schema.json +312 -25
  10. package/dist/src/data/collector.d.ts.map +1 -1
  11. package/dist/src/data/collector.js +1 -0
  12. package/dist/src/data/flowNode.d.ts.map +1 -1
  13. package/dist/src/data/sources/dataSource.d.ts.map +1 -1
  14. package/dist/src/data/sources/dataUtils.d.ts +2 -1
  15. package/dist/src/data/sources/dataUtils.d.ts.map +1 -1
  16. package/dist/src/data/sources/dataUtils.js +3 -4
  17. package/dist/src/data/sources/inlineSource.d.ts +8 -0
  18. package/dist/src/data/sources/inlineSource.d.ts.map +1 -1
  19. package/dist/src/data/sources/inlineSource.js +17 -1
  20. package/dist/src/data/sources/urlSource.d.ts +1 -0
  21. package/dist/src/data/sources/urlSource.d.ts.map +1 -1
  22. package/dist/src/data/sources/urlSource.js +33 -4
  23. package/dist/src/data/transforms/identifier.d.ts.map +1 -1
  24. package/dist/src/data/transforms/measureText.js +1 -1
  25. package/dist/src/data/transforms/regexFold.d.ts.map +1 -1
  26. package/dist/src/data/transforms/regexFold.js +10 -0
  27. package/dist/src/data/transforms/regexFold.test.js +13 -0
  28. package/dist/src/encoder/encoder.d.ts +1 -1
  29. package/dist/src/fonts/bmFontManager.js +2 -2
  30. package/dist/src/fonts/bmFontMetrics.d.ts.map +1 -1
  31. package/dist/src/genomeSpy.d.ts.map +1 -1
  32. package/dist/src/genomeSpy.js +39 -19
  33. package/dist/src/gl/arrayBuilder.d.ts.map +1 -1
  34. package/dist/src/gl/colorUtils.d.ts +4 -0
  35. package/dist/src/gl/colorUtils.d.ts.map +1 -1
  36. package/dist/src/gl/colorUtils.js +8 -0
  37. package/dist/src/gl/glslScaleGenerator.d.ts +1 -1
  38. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
  39. package/dist/src/gl/glslScaleGenerator.js +1 -9
  40. package/dist/src/gl/includes/common.glsl.js +1 -1
  41. package/dist/src/gl/webGLHelper.d.ts +1 -1
  42. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  43. package/dist/src/marks/link.d.ts.map +1 -1
  44. package/dist/src/marks/link.js +9 -1
  45. package/dist/src/marks/mark.d.ts +8 -0
  46. package/dist/src/marks/mark.d.ts.map +1 -1
  47. package/dist/src/marks/mark.js +101 -3
  48. package/dist/src/marks/point.d.ts +1 -1
  49. package/dist/src/marks/point.d.ts.map +1 -1
  50. package/dist/src/marks/point.fragment.glsl.js +1 -1
  51. package/dist/src/marks/point.vertex.glsl.js +1 -1
  52. package/dist/src/marks/rect.common.glsl.js +1 -1
  53. package/dist/src/marks/rect.d.ts.map +1 -1
  54. package/dist/src/marks/rect.fragment.glsl.js +1 -1
  55. package/dist/src/marks/rect.js +41 -0
  56. package/dist/src/marks/rect.vertex.glsl.js +1 -1
  57. package/dist/src/selection/selection.d.ts +27 -2
  58. package/dist/src/selection/selection.d.ts.map +1 -1
  59. package/dist/src/selection/selection.js +53 -3
  60. package/dist/src/spec/data.d.ts +18 -1
  61. package/dist/src/spec/mark.d.ts +58 -1
  62. package/dist/src/spec/parameter.d.ts +71 -31
  63. package/dist/src/spec/sampleView.d.ts +12 -1
  64. package/dist/src/spec/view.d.ts +9 -2
  65. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  66. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  67. package/dist/src/styles/genome-spy.css.js +12 -1
  68. package/dist/src/styles/genome-spy.scss +19 -1
  69. package/dist/src/types/selectionTypes.d.ts +4 -7
  70. package/dist/src/types/viewContext.d.ts +0 -15
  71. package/dist/src/utils/expression.d.ts.map +1 -1
  72. package/dist/src/utils/expression.js +4 -0
  73. package/dist/src/utils/indexer.d.ts +0 -2
  74. package/dist/src/utils/indexer.d.ts.map +1 -1
  75. package/dist/src/utils/reservationMap.d.ts +4 -4
  76. package/dist/src/utils/reservationMap.d.ts.map +1 -1
  77. package/dist/src/utils/scaleNull.d.ts +0 -2
  78. package/dist/src/utils/scaleNull.d.ts.map +1 -1
  79. package/dist/src/utils/trees.d.ts +2 -2
  80. package/dist/src/utils/ui/tooltip.d.ts +6 -10
  81. package/dist/src/utils/ui/tooltip.d.ts.map +1 -1
  82. package/dist/src/utils/ui/tooltip.js +74 -42
  83. package/dist/src/view/concatView.d.ts +1 -1
  84. package/dist/src/view/concatView.d.ts.map +1 -1
  85. package/dist/src/view/concatView.js +1 -1
  86. package/dist/src/view/gridView/gridChild.d.ts +53 -0
  87. package/dist/src/view/gridView/gridChild.d.ts.map +1 -0
  88. package/dist/src/view/gridView/gridChild.js +753 -0
  89. package/dist/src/view/gridView/gridView.d.ts +64 -0
  90. package/dist/src/view/gridView/gridView.d.ts.map +1 -0
  91. package/dist/src/view/{gridView.js → gridView/gridView.js} +40 -595
  92. package/dist/src/view/gridView/scrollbar.d.ts +32 -0
  93. package/dist/src/view/gridView/scrollbar.d.ts.map +1 -0
  94. package/dist/src/view/gridView/scrollbar.js +186 -0
  95. package/dist/src/view/gridView/selectionRect.d.ts +10 -0
  96. package/dist/src/view/gridView/selectionRect.d.ts.map +1 -0
  97. package/dist/src/view/gridView/selectionRect.js +182 -0
  98. package/dist/src/view/layout/rectangle.d.ts +11 -1
  99. package/dist/src/view/layout/rectangle.d.ts.map +1 -1
  100. package/dist/src/view/layout/rectangle.js +22 -2
  101. package/dist/src/view/layout/rectangle.test.js +12 -0
  102. package/dist/src/view/paramMediator.d.ts.map +1 -1
  103. package/dist/src/view/paramMediator.js +11 -2
  104. package/dist/src/view/scaleResolution.d.ts +1 -0
  105. package/dist/src/view/scaleResolution.d.ts.map +1 -1
  106. package/dist/src/view/scaleResolution.js +43 -33
  107. package/dist/src/view/testUtils.d.ts.map +1 -1
  108. package/dist/src/view/testUtils.js +0 -4
  109. package/dist/src/view/view.d.ts +6 -0
  110. package/dist/src/view/view.d.ts.map +1 -1
  111. package/dist/src/view/view.js +19 -0
  112. package/dist/src/view/viewFactory.d.ts.map +1 -1
  113. package/dist/src/view/viewFactory.js +13 -1
  114. package/package.json +2 -2
  115. package/dist/bundle/index-DS2hvLgl.js +0 -3425
  116. package/dist/src/view/gridView.d.ts +0 -135
  117. package/dist/src/view/gridView.d.ts.map +0 -1
@@ -10,6 +10,20 @@ import { asArray } from "../utils/arrayUtils.js";
10
10
  import { isValueDef } from "../encoder/encoder.js";
11
11
  import { getCachedOrCall } from "../utils/propertyCacher.js";
12
12
  import { isDiscrete } from "vega-scale";
13
+ import { cssColorToArray } from "../gl/colorUtils.js";
14
+
15
+ const hatchPatterns = [
16
+ "none",
17
+ "diagonal",
18
+ "antiDiagonal",
19
+ "cross",
20
+ "vertical",
21
+ "horizontal",
22
+ "grid",
23
+ "dots",
24
+ "rings",
25
+ "ringsLarge",
26
+ ];
13
27
 
14
28
  /**
15
29
  * @extends {Mark<import("../spec/mark.js").RectProps>}
@@ -79,6 +93,7 @@ export default class RectMark extends Mark {
79
93
  () =>
80
94
  !this.#isRoundedCorners() &&
81
95
  !this.#isStroked() &&
96
+ !this.properties.shadowOpacity &&
82
97
  isValueDef(this.encoding.fillOpacity) &&
83
98
  this.encoding.fillOpacity.value == 1.0 &&
84
99
  this.properties.minOpacity == 1.0
@@ -141,6 +156,9 @@ export default class RectMark extends Mark {
141
156
  if (this.#isStroked()) {
142
157
  defines.push("STROKED");
143
158
  }
159
+ if (this.properties.shadowOpacity) {
160
+ defines.push("SHADOW");
161
+ }
144
162
 
145
163
  this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER, [
146
164
  COMMON_SHADER,
@@ -174,6 +192,29 @@ export default class RectMark extends Mark {
174
192
  "uCornerRadiusBottomLeft",
175
193
  props.cornerRadiusBottomLeft ?? props.cornerRadius ?? 0
176
194
  );
195
+
196
+ this.registerMarkUniformValue("uHatchPattern", props.hatch, (x) =>
197
+ Math.max(0, hatchPatterns.indexOf(x ?? "none"))
198
+ );
199
+
200
+ this.registerMarkUniformValue("uShadowBlur", props.shadowBlur ?? 0);
201
+ this.registerMarkUniformValue(
202
+ "uShadowOpacity",
203
+ props.shadowOpacity ?? 0
204
+ );
205
+ this.registerMarkUniformValue(
206
+ "uShadowOffsetX",
207
+ props.shadowOffsetX ?? 0
208
+ );
209
+ this.registerMarkUniformValue(
210
+ "uShadowOffsetY",
211
+ props.shadowOffsetY ?? 0
212
+ );
213
+ this.registerMarkUniformValue(
214
+ "uShadowColor",
215
+ props.shadowColor ?? "black",
216
+ cssColorToArray
217
+ );
177
218
  }
178
219
 
179
220
  updateGraphicsData() {
@@ -1,2 +1,2 @@
1
- const shader = "out lowp vec4 vFillColor;out lowp vec4 vStrokeColor;out float vHalfStrokeWidth;out vec4 vCornerRadii;\n#if defined(ROUNDED_CORNERS) || defined(STROKED)\nout vec2 vPosInPixels;\n#endif\nout vec2 vHalfSizeInPixels;/***Clamps the minimumSize and returns an opacity that reflects the amount of clamping.*/float clampMinSize(inout float pos,float frac,float size,float minSize){if(minSize>0.0&&abs(size)<minSize){pos+=(frac-0.5)*(minSize*sign(size)-size);return abs(size)/minSize;}return 1.0;}void sort(inout float a,inout float b){if(a>b){float tmp=b;b=a;a=tmp;}}/***The vertex position wrt the rectangle specified by(x,x2,y,y2).*[0,0]=[x,y],[1,1]=[x2,y2].*The x or y component may contain fractional values if the rectangle*have been tessellated.*/vec2 getVertexPos(){int index=gl_VertexID % 6;return vec2(index==0||index==1||index==3 ? 0.0 : 1.0,index==0||index==1||index==2 ? 0.0 : 1.0);}void main(void){vec2 frac=getVertexPos();vec2 normalizedMinSize=vec2(uMinWidth,uMinHeight)/uViewportSize;vec4 cornerRadii=vec4(uCornerRadiusTopRight,uCornerRadiusBottomRight,uCornerRadiusTopLeft,uCornerRadiusBottomLeft);float x=getScaled_x();float x2=getScaled_x2();float y=getScaled_y();float y2=getScaled_y2();sort(x,x2);sort(y,y2);float clampMargin=1.0;vec2 pos1=vec2(clamp(x,0.0-clampMargin,1.0+clampMargin),y);vec2 pos2=vec2(clamp(x2,0.0-clampMargin,1.0+clampMargin),y2);vec2 size=pos2-pos1;if(size.x<=0.0||size.y<=0.0){gl_Position=vec4(0.0,0.0,0.0,1.0);return;}vec2 pos=pos1+frac*size;size.y*=getSampleFacetHeight(pos);float opaFactor=uViewOpacity*max(uMinOpacity,clampMinSize(pos.x,frac.x,size.x,normalizedMinSize.x)*clampMinSize(pos.y,frac.y,size.y,normalizedMinSize.y));pos=applySampleFacet(pos);\n#if defined(ROUNDED_CORNERS) || defined(STROKED)\nfloat aaPadding=1.0/uDevicePixelRatio;float strokeWidth=getScaled_strokeWidth();float strokeOpacity=getScaled_strokeOpacity()*opaFactor;vec2 centeredFrac=frac-0.5;vec2 expand=centeredFrac*(strokeWidth+aaPadding)/uViewportSize;pos+=expand;vec2 sizeInPixels=size*uViewportSize;vPosInPixels=(centeredFrac+expand/size)*sizeInPixels;vHalfSizeInPixels=sizeInPixels/2.0;vCornerRadii=min(cornerRadii,min(vHalfSizeInPixels.x,vHalfSizeInPixels.y));vHalfStrokeWidth=strokeWidth/2.0;vStrokeColor=vec4(getScaled_stroke()*strokeOpacity,strokeOpacity);\n#endif\ngl_Position=unitToNdc(pos);float fillOpacity=getScaled_fillOpacity()*opaFactor;vFillColor=vec4(getScaled_fill()*fillOpacity,fillOpacity);setupPicking();}";
1
+ const shader = "out lowp vec4 vFillColor;out lowp vec4 vStrokeColor;out float vHalfStrokeWidth;out vec4 vCornerRadii;\n#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\nout vec2 vPosInPixels;\n#endif\nout vec2 vHalfSizeInPixels;/***Clamps the minimumSize and returns an opacity that reflects the amount of clamping.*/float clampMinSize(inout float pos,float frac,float size,float minSize){if(minSize>0.0&&abs(size)<minSize){pos+=(frac-0.5)*(minSize*sign(size)-size);return abs(size)/minSize;}return 1.0;}void sort(inout float a,inout float b){if(a>b){float tmp=b;b=a;a=tmp;}}/***The vertex position wrt the rectangle specified by(x,x2,y,y2).*[0,0]=[x,y],[1,1]=[x2,y2].*The x or y component may contain fractional values if the rectangle*have been tessellated.*/vec2 getVertexPos(){int index=gl_VertexID % 6;return vec2(index==0||index==1||index==3 ? 0.0 : 1.0,index==0||index==1||index==2 ? 0.0 : 1.0);}void main(void){vec2 frac=getVertexPos();vec2 normalizedMinSize=vec2(uMinWidth,uMinHeight)/uViewportSize;vec4 cornerRadii=vec4(uCornerRadiusTopRight,uCornerRadiusBottomRight,uCornerRadiusTopLeft,uCornerRadiusBottomLeft);float x=getScaled_x();float x2=getScaled_x2();float y=getScaled_y();float y2=getScaled_y2();sort(x,x2);sort(y,y2);float clampMargin=1.0;vec2 pos1=vec2(clamp(x,0.0-clampMargin,1.0+clampMargin),y);vec2 pos2=vec2(clamp(x2,0.0-clampMargin,1.0+clampMargin),y2);vec2 size=pos2-pos1;if(size.x<=0.0||size.y<=0.0){gl_Position=vec4(0.0,0.0,0.0,1.0);return;}vec2 pos=pos1+frac*size;size.y*=getSampleFacetHeight(pos);float opaFactor=uViewOpacity*max(uMinOpacity,clampMinSize(pos.x,frac.x,size.x,normalizedMinSize.x)*clampMinSize(pos.y,frac.y,size.y,normalizedMinSize.y));pos=applySampleFacet(pos);\n#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\nfloat aaPadding=1.0/uDevicePixelRatio;float shadowPadding=uShadowBlur+max(abs(uShadowOffsetX),abs(uShadowOffsetY));float strokeWidth=getScaled_strokeWidth();float strokeOpacity=getScaled_strokeOpacity()*opaFactor;vec2 centeredFrac=frac-0.5;vec2 expand=centeredFrac*(strokeWidth+aaPadding+shadowPadding*2.0)/uViewportSize;pos+=expand;vec2 sizeInPixels=size*uViewportSize;vPosInPixels=(centeredFrac+expand/size)*sizeInPixels;vHalfSizeInPixels=sizeInPixels/2.0;vCornerRadii=min(cornerRadii,min(vHalfSizeInPixels.x,vHalfSizeInPixels.y));vHalfStrokeWidth=strokeWidth/2.0;vStrokeColor=vec4(getScaled_stroke()*strokeOpacity,strokeOpacity);\n#endif\ngl_Position=unitToNdc(pos);float fillOpacity=getScaled_fillOpacity()*opaFactor;vFillColor=vec4(getScaled_fill()*fillOpacity,fillOpacity);setupPicking();}";
2
2
  export default shader;
@@ -8,6 +8,12 @@ export function createSinglePointSelection(datum: import("../data/flowNode.js").
8
8
  * @returns {import("../types/selectionTypes.js").MultiPointSelection}
9
9
  */
10
10
  export function createMultiPointSelection(data?: import("../data/flowNode.js").Datum[]): import("../types/selectionTypes.js").MultiPointSelection;
11
+ /**
12
+ *
13
+ * @param {import("../spec/channel.js").ChannelWithScale[]} channels
14
+ * @returns {import("../types/selectionTypes.js").IntervalSelection}
15
+ */
16
+ export function createIntervalSelection(channels: import("../spec/channel.js").ChannelWithScale[]): import("../types/selectionTypes.js").IntervalSelection;
11
17
  /**
12
18
  * Updates the backing data and returns a new instance of the selection object.
13
19
  * A new instance is required to trigger reactivity in parameters.
@@ -32,9 +38,9 @@ export function makeSelectionTestExpression(params: {
32
38
  }): string;
33
39
  /**
34
40
  * @param {import("../types/selectionTypes.js").Selection} selection
35
- * @returns {selection is import("../types/selectionTypes.js").RangeSelection}
41
+ * @returns {selection is import("../types/selectionTypes.js").IntervalSelection}
36
42
  */
37
- export function isRangeSelection(selection: import("../types/selectionTypes.js").Selection): selection is import("../types/selectionTypes.js").RangeSelection;
43
+ export function isIntervalSelection(selection: import("../types/selectionTypes.js").Selection): selection is import("../types/selectionTypes.js").IntervalSelection;
38
44
  /**
39
45
  * @param {import("../types/selectionTypes.js").Selection} selection
40
46
  * @returns {selection is import("../types/selectionTypes.js").SinglePointSelection}
@@ -60,4 +66,23 @@ export function asSelectionConfig(typeOrConfig: import("../spec/parameter.js").S
60
66
  * @returns {config is import("../spec/parameter.js").PointSelectionConfig}
61
67
  */
62
68
  export function isPointSelectionConfig(config: import("../spec/parameter.js").SelectionConfig): config is import("../spec/parameter.js").PointSelectionConfig;
69
+ /**
70
+ *
71
+ * @param {import("../spec/parameter.js").SelectionConfig} config
72
+ * @returns {config is import("../spec/parameter.js").IntervalSelectionConfig}
73
+ */
74
+ export function isIntervalSelectionConfig(config: import("../spec/parameter.js").SelectionConfig): config is import("../spec/parameter.js").IntervalSelectionConfig;
75
+ /**
76
+ * @param {import("../types/selectionTypes.js").IntervalSelection} selection
77
+ */
78
+ export function isActiveIntervalSelection(selection: import("../types/selectionTypes.js").IntervalSelection): boolean;
79
+ /**
80
+ * @typedef {import("../types/selectionTypes.js").IntervalSelection} IntervalSelection
81
+ * @typedef {Partial<Record<keyof IntervalSelection["intervals"], number>>} IntervalPoint
82
+ * @param {IntervalSelection} selection
83
+ * @param {IntervalPoint} point
84
+ */
85
+ export function selectionContainsPoint(selection: IntervalSelection, point: IntervalPoint): boolean;
86
+ export type IntervalSelection = import("../types/selectionTypes.js").IntervalSelection;
87
+ export type IntervalPoint = Partial<Record<keyof IntervalSelection["intervals"], number>>;
63
88
  //# sourceMappingURL=selection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/selection/selection.js"],"names":[],"mappings":"AAGA;;;GAGG;AACH,kDAHW,OAAO,qBAAqB,EAAE,KAAK,GACjC,OAAO,4BAA4B,EAAE,oBAAoB,CAQrE;AAED;;;GAGG;AACH,iDAHW,OAAO,qBAAqB,EAAE,KAAK,EAAE,GACnC,OAAO,4BAA4B,EAAE,mBAAmB,CAQpE;AAED;;;;;;;GAOG;AACH,qDAJW,OAAO,4BAA4B,EAAE,mBAAmB,2BACxD,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,QAAQ,GAAG,QAAQ,EAAE,QAAQ,CAAC,OAAO,qBAAqB,EAAE,KAAK,CAAC,CAAC,CAAC,GACzF,OAAO,4BAA4B,EAAE,mBAAmB,CA2BpE;AAED;;;;GAIG;AACH,yCAJW,OAAO,4BAA4B,EAAE,SAAS,SAC9C,OAAO,qBAAqB,EAAE,KAAK,UACnC,OAAO,WAkBjB;AAED;;GAEG;AACH,oDAFW;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAC,UAM1C;AAED;;;GAGG;AACH,4CAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,cAAc,CAI5E;AAED;;;GAGG;AACH,kDAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,oBAAoB,CAIlF;AAED;;;GAGG;AACH,iDAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,mBAAmB,CAIjF;AAED;;;GAGG;AACH,gDAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,kBAAkB,CAIhF;AAED;;;GAGG;AACH,gDAHW,OAAO,sBAAsB,EAAE,qBAAqB,GAClD,OAAO,sBAAsB,EAAE,eAAe,CAiB1D;AAED;;;GAGG;AACH,+CAHW,OAAO,sBAAsB,EAAE,eAAe,GAC5C,MAAM,IAAI,OAAO,sBAAsB,EAAE,oBAAoB,CAIzE"}
1
+ {"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/selection/selection.js"],"names":[],"mappings":"AAGA;;;GAGG;AACH,kDAHW,OAAO,qBAAqB,EAAE,KAAK,GACjC,OAAO,4BAA4B,EAAE,oBAAoB,CAQrE;AAED;;;GAGG;AACH,iDAHW,OAAO,qBAAqB,EAAE,KAAK,EAAE,GACnC,OAAO,4BAA4B,EAAE,mBAAmB,CAQpE;AAED;;;;GAIG;AACH,kDAHW,OAAO,oBAAoB,EAAE,gBAAgB,EAAE,GAC7C,OAAO,4BAA4B,EAAE,iBAAiB,CASlE;AAED;;;;;;;GAOG;AACH,qDAJW,OAAO,4BAA4B,EAAE,mBAAmB,2BACxD,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,QAAQ,GAAG,QAAQ,EAAE,QAAQ,CAAC,OAAO,qBAAqB,EAAE,KAAK,CAAC,CAAC,CAAC,GACzF,OAAO,4BAA4B,EAAE,mBAAmB,CA2BpE;AAED;;;;GAIG;AACH,yCAJW,OAAO,4BAA4B,EAAE,SAAS,SAC9C,OAAO,qBAAqB,EAAE,KAAK,UACnC,OAAO,WAoBjB;AAED;;GAEG;AACH,oDAFW;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAC,UAM1C;AAED;;;GAGG;AACH,+CAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,iBAAiB,CAI/E;AAED;;;GAGG;AACH,kDAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,oBAAoB,CAIlF;AAED;;;GAGG;AACH,iDAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,mBAAmB,CAIjF;AAED;;;GAGG;AACH,gDAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,kBAAkB,CAIhF;AAED;;;GAGG;AACH,gDAHW,OAAO,sBAAsB,EAAE,qBAAqB,GAClD,OAAO,sBAAsB,EAAE,eAAe,CAiB1D;AAED;;;GAGG;AACH,+CAHW,OAAO,sBAAsB,EAAE,eAAe,GAC5C,MAAM,IAAI,OAAO,sBAAsB,EAAE,oBAAoB,CAIzE;AAED;;;;GAIG;AACH,kDAHW,OAAO,sBAAsB,EAAE,eAAe,GAC5C,MAAM,IAAI,OAAO,sBAAsB,EAAE,uBAAuB,CAI5E;AAED;;GAEG;AACH,qDAFW,OAAO,4BAA4B,EAAE,iBAAiB,WAMhE;AAED;;;;;GAKG;AACH,kDAHW,iBAAiB,SACjB,aAAa,WAUvB;gCAbY,OAAO,4BAA4B,EAAE,iBAAiB;4BACtD,OAAO,CAAC,MAAM,CAAC,MAAM,iBAAiB,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC"}
@@ -25,6 +25,20 @@ export function createMultiPointSelection(data) {
25
25
  };
26
26
  }
27
27
 
28
+ /**
29
+ *
30
+ * @param {import("../spec/channel.js").ChannelWithScale[]} channels
31
+ * @returns {import("../types/selectionTypes.js").IntervalSelection}
32
+ */
33
+ export function createIntervalSelection(channels) {
34
+ return {
35
+ type: "interval",
36
+ intervals: Object.fromEntries(
37
+ channels.map((c) => [c, /** @type {number[]} */ (null)])
38
+ ),
39
+ };
40
+ }
41
+
28
42
  /**
29
43
  * Updates the backing data and returns a new instance of the selection object.
30
44
  * A new instance is required to trigger reactivity in parameters.
@@ -78,6 +92,8 @@ export function selectionTest(selection, datum, empty = true) {
78
92
  return selection.data.size == 0
79
93
  ? empty
80
94
  : selection.data.has(datum[UNIQUE_ID_KEY]); // TODO: Binary search
95
+ } else if (isIntervalSelection(selection)) {
96
+ throw new Error("TODO: Implement interval selection test");
81
97
  } else {
82
98
  throw new Error("Not a selection: " + JSON.stringify(selection));
83
99
  }
@@ -94,10 +110,10 @@ export function makeSelectionTestExpression(params) {
94
110
 
95
111
  /**
96
112
  * @param {import("../types/selectionTypes.js").Selection} selection
97
- * @returns {selection is import("../types/selectionTypes.js").RangeSelection}
113
+ * @returns {selection is import("../types/selectionTypes.js").IntervalSelection}
98
114
  */
99
- export function isRangeSelection(selection) {
100
- return selection.type === "range";
115
+ export function isIntervalSelection(selection) {
116
+ return selection.type === "interval";
101
117
  }
102
118
 
103
119
  /**
@@ -152,3 +168,37 @@ export function asSelectionConfig(typeOrConfig) {
152
168
  export function isPointSelectionConfig(config) {
153
169
  return config && config.type == "point";
154
170
  }
171
+
172
+ /**
173
+ *
174
+ * @param {import("../spec/parameter.js").SelectionConfig} config
175
+ * @returns {config is import("../spec/parameter.js").IntervalSelectionConfig}
176
+ */
177
+ export function isIntervalSelectionConfig(config) {
178
+ return config && config.type == "interval";
179
+ }
180
+
181
+ /**
182
+ * @param {import("../types/selectionTypes.js").IntervalSelection} selection
183
+ */
184
+ export function isActiveIntervalSelection(selection) {
185
+ return Object.values(selection.intervals).some(
186
+ (interval) => interval && interval.length === 2
187
+ );
188
+ }
189
+
190
+ /**
191
+ * @typedef {import("../types/selectionTypes.js").IntervalSelection} IntervalSelection
192
+ * @typedef {Partial<Record<keyof IntervalSelection["intervals"], number>>} IntervalPoint
193
+ * @param {IntervalSelection} selection
194
+ * @param {IntervalPoint} point
195
+ */
196
+ export function selectionContainsPoint(selection, point) {
197
+ return Object.entries(selection.intervals).every(
198
+ ([channel, interval]) =>
199
+ (channel == "x" || channel == "y") &&
200
+ interval &&
201
+ interval[0] <= point[channel] &&
202
+ interval[1] >= point[channel]
203
+ );
204
+ }
@@ -119,12 +119,29 @@ export interface DataBase {
119
119
  name?: string;
120
120
  }
121
121
 
122
+ export interface UrlList {
123
+ /**
124
+ * A URL that returns a list of URLs to load the data set.
125
+ * The URLs in the list can be absolute or relative to the URL of the list.
126
+ */
127
+ urlsFromFile: string;
128
+
129
+ /**
130
+ * The format of the data in the list.
131
+ * If the type is `"json"`, the list is expected to be an array of strings.
132
+ * If the type is `"csv"` or `"tsv"`, the list is expected to be a table with a single column named `file`.
133
+ *
134
+ * __Default value:__ `"txt"`
135
+ */
136
+ type?: "json" | "csv" | "tsv";
137
+ }
138
+
122
139
  export interface UrlData extends DataBase {
123
140
  /**
124
141
  * An URL or an array of URLs from which to load the data set.
125
142
  * Use the `format.type` property to ensure the loaded data is correctly parsed.
126
143
  */
127
- url: string | string[] | ExprRef;
144
+ url: string | string[] | ExprRef | UrlList;
128
145
  }
129
146
 
130
147
  export interface InlineData extends DataBase {
@@ -110,6 +110,43 @@ export interface FillAndStrokeProps {
110
110
  strokeOpacity?: number | ExprRef;
111
111
  }
112
112
 
113
+ export interface ShadowProps {
114
+ /**
115
+ * The color of the drop shadow. Any valid CSS color string is allowed.
116
+ *
117
+ * **Default value:** `"black"`
118
+ */
119
+ shadowColor?: string | ExprRef;
120
+
121
+ /**
122
+ * The opacity of the drop shadow. Value between `0` (fully transparent) and `1` (fully opaque).
123
+ *
124
+ * **Default value:** `0` (disabled)
125
+ */
126
+ shadowOpacity?: number | ExprRef;
127
+
128
+ /**
129
+ * The horizontal offset of the drop shadow in pixels. Positive values move the shadow to the right.
130
+ *
131
+ * **Default value:** `0`
132
+ */
133
+ shadowOffsetX?: number | ExprRef;
134
+
135
+ /**
136
+ * The vertical offset of the drop shadow in pixels. Positive values move the shadow downward.
137
+ *
138
+ * **Default value:** `0`
139
+ */
140
+ shadowOffsetY?: number | ExprRef;
141
+
142
+ /**
143
+ * The blur radius of the drop shadow in pixels. Higher values produce a more diffuse shadow.
144
+ *
145
+ * **Default value:** `0`
146
+ */
147
+ shadowBlur?: number | ExprRef;
148
+ }
149
+
113
150
  export interface SecondaryPositionProps {
114
151
  /**
115
152
  * The secondary position on the x axis.
@@ -161,7 +198,8 @@ export interface ViewportEdgeFadeProps {
161
198
  export interface RectProps
162
199
  extends MarkPropsBase,
163
200
  SecondaryPositionProps,
164
- FillAndStrokeProps {
201
+ FillAndStrokeProps,
202
+ ShadowProps {
165
203
  type: "rect";
166
204
 
167
205
  /**
@@ -232,6 +270,25 @@ export interface RectProps
232
270
  * **Default value:** (None)
233
271
  */
234
272
  cornerRadiusBottomRight?: number | ExprRef;
273
+
274
+ /**
275
+ * A hatch pattern drawn inside the mark using the stroke width, color, and opacity.
276
+ * The pattern is aligned in screen space and scaled by the stroke width.
277
+ *
278
+ * **Default value:** `"none"`
279
+ */
280
+ hatch?:
281
+ | "none"
282
+ | "diagonal"
283
+ | "antiDiagonal"
284
+ | "cross"
285
+ | "vertical"
286
+ | "horizontal"
287
+ | "grid"
288
+ | "dots"
289
+ | "rings"
290
+ | "ringsLarge"
291
+ | ExprRef;
235
292
  }
236
293
 
237
294
  export interface RuleProps
@@ -1,4 +1,5 @@
1
- import { ChannelWithScale, Scalar } from "./channel.js";
1
+ import { PrimaryPositionalChannel, Scalar } from "./channel.js";
2
+ import { ShadowProps } from "./mark.js";
2
3
 
3
4
  export interface ExprRef {
4
5
  /**
@@ -177,22 +178,6 @@ export interface BaseSelectionConfig<T extends SelectionType = SelectionType> {
177
178
  /**
178
179
  */
179
180
  on?: "click" | "mouseover" | "pointerover";
180
-
181
- /**
182
- * An array of encoding channels. The corresponding data field values
183
- * must match for a data tuple to fall within the selection.
184
- *
185
- * __See also:__ The [projection with `encodings` and `fields` section](https://vega.github.io/vega-lite/docs/selection.html#project) in the documentation.
186
- */
187
- encodings?: ChannelWithScale[];
188
-
189
- /**
190
- * An array of field names whose values must match for a data tuple to
191
- * fall within the selection.
192
- *
193
- * __See also:__ The [projection with `encodings` and `fields` section](https://vega.github.io/vega-lite/docs/selection.html#project) in the documentation.
194
- */
195
- fields?: string[];
196
181
  }
197
182
 
198
183
  export interface PointSelectionConfig extends BaseSelectionConfig<"point"> {
@@ -219,7 +204,67 @@ export interface PointSelectionConfig extends BaseSelectionConfig<"point"> {
219
204
 
220
205
  export interface IntervalSelectionConfig
221
206
  extends BaseSelectionConfig<"interval"> {
222
- // TODO
207
+ type: "interval";
208
+
209
+ /**
210
+ * An array of encoding channels that define the interval selection.
211
+ */
212
+ encodings?: PrimaryPositionalChannel[];
213
+
214
+ /**
215
+ * Interval selections display a rectangle mark to show the selected range.
216
+ * Use the `mark` property to adjust the appearance of this rectangle.
217
+ */
218
+ mark?: BrushConfig;
219
+ }
220
+
221
+ export interface BrushConfig extends ShadowProps {
222
+ /**
223
+ * The fill color of the interval mark.
224
+ *
225
+ * __Default value:__ `"#808080"`
226
+ *
227
+ */
228
+ fill?: string;
229
+
230
+ /**
231
+ * The fill opacity of the interval mark (a value between `0` and `1`).
232
+ *
233
+ * __Default value:__ `0.05`
234
+ */
235
+ fillOpacity?: number;
236
+
237
+ /**
238
+ * The stroke color of the interval mark.
239
+ *
240
+ * __Default value:__ `"black"`
241
+ */
242
+ stroke?: string;
243
+
244
+ /**
245
+ * The stroke opacity of the interval mark (a value between `0` and `1`).
246
+ *
247
+ * __Default value:__ `0.2`
248
+ */
249
+ strokeOpacity?: number;
250
+
251
+ /**
252
+ * The stroke width of the interval mark.
253
+ *
254
+ * __Default value:__ `1`
255
+ */
256
+ strokeWidth?: number;
257
+
258
+ /**
259
+ * Where to display the measurement text (e.g., number of base pairs) for the interval selection.
260
+ *
261
+ * - `"none"` -- do not show the measurement.
262
+ * - `"inside"` -- show inside the brush rectangle.
263
+ * - `"outside"` -- show outside the brush rectangle.
264
+ *
265
+ * __Default value:__ `"none"`
266
+ */
267
+ measure?: "none" | "inside" | "outside";
223
268
  }
224
269
 
225
270
  export interface SelectionParameter<T extends SelectionType = SelectionType>
@@ -238,21 +283,16 @@ export interface SelectionParameter<T extends SelectionType = SelectionType>
238
283
  ? IntervalSelectionConfig
239
284
  : never);
240
285
 
241
- /*
242
- * Initialize the selection with a mapping between [projected channels or field names](https://vega.github.io/vega-lite/docs/selection.html#project) and initial values.
243
- *
244
- * __See also:__ [`init`](https://vega.github.io/vega-lite/docs/value.html) documentation.
245
- */
246
- /*
247
- // TODO TODO TODO TODO TODO TODO TODO TODO
248
- value?: T extends "point"
249
- ? SelectionInit | SelectionInitMapping[]
250
- : T extends "interval"
251
- ? SelectionInitIntervalMapping
252
- : never;
253
- */
286
+ /**
287
+ * Initial value for the selection.
288
+ */
289
+ value?: T extends "interval" ? SelectionInitIntervalMapping : never;
254
290
  }
255
291
 
292
+ export type SelectionInitIntervalMapping = Partial<
293
+ Record<PrimaryPositionalChannel, [number, number]>
294
+ >;
295
+
256
296
  export type SelectionConfig = PointSelectionConfig | IntervalSelectionConfig;
257
297
  export type SelectionTypeOrConfig = SelectionType | SelectionConfig;
258
298
 
@@ -35,7 +35,7 @@ export interface SampleAttributeDef {
35
35
  /**
36
36
  * The attribute type. One of `"nominal"`, `"ordinal"`, or `"quantitative"`.
37
37
  */
38
- type: Type; // TODO: Omit index/locus from available types
38
+ type?: Type; // TODO: Omit index/locus from available types
39
39
 
40
40
  /**
41
41
  * Scale definition for the (default) color channel
@@ -57,6 +57,11 @@ export interface SampleAttributeDef {
57
57
  * Whether the attribute is visible by default.
58
58
  */
59
59
  visible?: boolean;
60
+
61
+ /**
62
+ * The title of the attribute. Defaults to attribute name.
63
+ */
64
+ title?: string;
60
65
  }
61
66
 
62
67
  export interface SampleDef {
@@ -65,6 +70,12 @@ export interface SampleDef {
65
70
  */
66
71
  data?: Data;
67
72
 
73
+ /**
74
+ * If attributes form a hierarchy, specify the separator character to
75
+ * split the attribute names into paths.
76
+ */
77
+ attributeGroupSeparator?: string;
78
+
68
79
  /**
69
80
  * Explicitly specify the sample attributes.
70
81
  */
@@ -6,7 +6,13 @@ import {
6
6
  FacetFieldDef,
7
7
  PrimaryPositionalChannel,
8
8
  } from "./channel.js";
9
- import { FillAndStrokeProps, MarkProps, MarkType, RectProps } from "./mark.js";
9
+ import {
10
+ FillAndStrokeProps,
11
+ MarkProps,
12
+ MarkType,
13
+ RectProps,
14
+ ShadowProps,
15
+ } from "./mark.js";
10
16
  import { ExprRef } from "./parameter.js";
11
17
  import { Title } from "./title.js";
12
18
  import { SampleSpec } from "./sampleView.js";
@@ -74,7 +80,8 @@ interface CompleteViewBackground extends RectProps, FillAndStrokeProps {
74
80
  export type ViewBackground = Pick<
75
81
  CompleteViewBackground,
76
82
  "fill" | "fillOpacity" | "stroke" | "strokeWidth" | "strokeOpacity"
77
- >;
83
+ > &
84
+ ShadowProps;
78
85
 
79
86
  export interface ViewSpecBase extends ResolveSpec {
80
87
  /**
@@ -1,3 +1,3 @@
1
1
  export default css;
2
- declare const css: "\n.genome-spy {\n font-family: system-ui, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n position: relative;\n display: flex;\n flex-direction: column;\n}\n.genome-spy .canvas-wrapper {\n position: relative;\n flex-grow: 1;\n overflow: hidden;\n}\n.genome-spy canvas {\n display: block;\n transform: scale(1, 1);\n opacity: 1;\n transition: transform 0.6s, opacity 0.6s;\n}\n.genome-spy .loading-message {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.genome-spy .loading-message .message {\n color: #666;\n opacity: 0;\n transition: opacity 0.7s;\n}\n.genome-spy .loading > canvas {\n transform: scale(0.95, 0.95);\n opacity: 0;\n}\n.genome-spy .loading > .loading-message .message {\n opacity: 1;\n}\n.genome-spy .loading > .loading-message .message .ellipsis {\n animation: blinker 1s linear infinite;\n}\n@keyframes blinker {\n 50% {\n opacity: 0;\n }\n}\n.genome-spy .loading-indicators {\n position: absolute;\n inset: 0;\n user-select: none;\n pointer-events: none;\n}\n.genome-spy .loading-indicators div {\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.genome-spy .loading-indicators div > div {\n font-size: 11px;\n transition: opacity 0.2s;\n background: white;\n padding: 2px 5px;\n display: flex;\n border-radius: 3px;\n gap: 0.5em;\n opacity: 0;\n}\n.genome-spy .loading-indicators div > div.loading {\n opacity: 0.5;\n}\n.genome-spy .loading-indicators div > div.error {\n opacity: 0.8;\n color: firebrick;\n}\n.genome-spy .loading-indicators div > div > * {\n display: block;\n}\n.genome-spy .loading-indicators div > div img {\n width: 1.5em;\n height: 1.5em;\n}\n.genome-spy .tooltip {\n position: absolute;\n max-width: 450px;\n overflow: hidden;\n background: #f6f6f6;\n padding: 10px;\n font-size: 12px;\n box-shadow: 0px 3px 15px 0px rgba(0, 0, 0, 0.21);\n pointer-events: none;\n z-index: 100;\n}\n.genome-spy .tooltip > :last-child {\n margin-bottom: 0;\n}\n.genome-spy .tooltip > .title {\n padding-bottom: 5px;\n margin-bottom: 5px;\n border-bottom: 1px dashed #b6b6b6;\n}\n.genome-spy .tooltip .summary {\n font-size: 12px;\n}\n.genome-spy .tooltip table {\n border-collapse: collapse;\n}\n.genome-spy .tooltip table:first-child {\n margin-top: 0;\n}\n.genome-spy .tooltip table th,\n.genome-spy .tooltip table td {\n padding: 2px 0.4em;\n vertical-align: top;\n}\n.genome-spy .tooltip table th:first-child,\n.genome-spy .tooltip table td:first-child {\n padding-left: 0;\n}\n.genome-spy .tooltip table th {\n text-align: left;\n font-weight: bold;\n}\n.genome-spy .tooltip .color-legend {\n display: inline-block;\n width: 0.8em;\n height: 0.8em;\n margin-left: 0.4em;\n box-shadow: 0px 0px 3px 1px white;\n}\n.genome-spy .tooltip .attributes .hovered {\n background-color: #e0e0e0;\n}\n.genome-spy .tooltip .na {\n color: #aaa;\n font-style: italic;\n font-size: 80%;\n}\n.genome-spy .gene-track-tooltip .summary {\n font-size: 90%;\n}\n.genome-spy .message-box {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n top: 0;\n height: 100%;\n width: 100%;\n}\n.genome-spy .message-box > div {\n border: 1px solid red;\n padding: 10px;\n background: #fff0f0;\n}\n\n.gs-input-binding {\n display: grid;\n grid-template-columns: max-content max-content;\n column-gap: 1em;\n row-gap: 0.3em;\n justify-items: start;\n}\n.gs-input-binding > select,\n.gs-input-binding > input:not([type=checkbox]) {\n width: 100%;\n}\n.gs-input-binding input[type=range] + span {\n display: inline-block;\n margin-left: 0.3em;\n min-width: 2.2em;\n font-variant-numeric: tabular-nums;\n}\n.gs-input-binding input[type=range],\n.gs-input-binding input[type=radio] {\n vertical-align: text-bottom;\n}\n.gs-input-binding .radio-group {\n display: flex;\n align-items: center;\n}\n.gs-input-binding .description {\n max-width: 26em;\n grid-column: 1/-1;\n color: #777;\n font-size: 90%;\n margin-top: -0.5em;\n}\n\n.gs-input-bindings {\n flex-basis: content;\n font-size: 14px;\n padding: 10px;\n}\n";
2
+ declare const css: "\n.genome-spy {\n font-family: system-ui, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n position: relative;\n display: flex;\n flex-direction: column;\n}\n.genome-spy .canvas-wrapper {\n position: relative;\n flex-grow: 1;\n overflow: hidden;\n}\n.genome-spy canvas {\n display: block;\n transform: scale(1, 1);\n opacity: 1;\n transition: transform 0.6s, opacity 0.6s;\n}\n.genome-spy canvas:focus, .genome-spy canvas:focus-visible {\n outline: none;\n}\n.genome-spy .loading-message {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.genome-spy .loading-message .message {\n color: #666;\n opacity: 0;\n transition: opacity 0.7s;\n}\n.genome-spy .loading > canvas {\n transform: scale(0.95, 0.95);\n opacity: 0;\n}\n.genome-spy .loading > .loading-message .message {\n opacity: 1;\n}\n.genome-spy .loading > .loading-message .message .ellipsis {\n animation: blinker 1s linear infinite;\n}\n@keyframes blinker {\n 50% {\n opacity: 0;\n }\n}\n.genome-spy .loading-indicators {\n position: absolute;\n inset: 0;\n user-select: none;\n pointer-events: none;\n}\n.genome-spy .loading-indicators div {\n position: absolute;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.genome-spy .loading-indicators div > div {\n font-size: 11px;\n transition: opacity 0.2s;\n background: white;\n padding: 2px 5px;\n display: flex;\n border-radius: 3px;\n gap: 0.5em;\n opacity: 0;\n}\n.genome-spy .loading-indicators div > div.loading {\n opacity: 0.5;\n}\n.genome-spy .loading-indicators div > div.error {\n opacity: 0.8;\n color: firebrick;\n}\n.genome-spy .loading-indicators div > div > * {\n display: block;\n}\n.genome-spy .loading-indicators div > div img {\n width: 1.5em;\n height: 1.5em;\n}\n.genome-spy .tooltip {\n position: absolute;\n max-width: 450px;\n overflow: hidden;\n background: #f6f6f6;\n padding: 10px;\n font-size: 12px;\n box-shadow: 0px 3px 15px 0px rgba(0, 0, 0, 0.21);\n transition: outline-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;\n outline: 0px solid transparent;\n z-index: 100;\n}\n.genome-spy .tooltip:not(.sticky) {\n pointer-events: none;\n}\n.genome-spy .tooltip.sticky {\n outline: 2px solid black;\n box-shadow: 0px 3px 18px 0px rgba(0, 0, 0, 0.3);\n}\n.genome-spy .tooltip > :last-child {\n margin-bottom: 0;\n}\n.genome-spy .tooltip > .title {\n padding-bottom: 5px;\n margin-bottom: 5px;\n border-bottom: 1px dashed #b6b6b6;\n}\n.genome-spy .tooltip .summary {\n font-size: 12px;\n}\n.genome-spy .tooltip table {\n border-collapse: collapse;\n}\n.genome-spy .tooltip table:first-child {\n margin-top: 0;\n}\n.genome-spy .tooltip table th,\n.genome-spy .tooltip table td {\n padding: 2px 0.4em;\n vertical-align: top;\n}\n.genome-spy .tooltip table th:first-child,\n.genome-spy .tooltip table td:first-child {\n padding-left: 0;\n}\n.genome-spy .tooltip table th {\n text-align: left;\n font-weight: bold;\n}\n.genome-spy .tooltip .color-legend {\n display: inline-block;\n width: 0.8em;\n height: 0.8em;\n margin-left: 0.4em;\n box-shadow: 0px 0px 3px 1px white;\n}\n.genome-spy .tooltip .attributes .hovered {\n background-color: #e0e0e0;\n}\n.genome-spy .tooltip .na {\n color: #aaa;\n font-style: italic;\n font-size: 80%;\n}\n.genome-spy .gene-track-tooltip .summary {\n font-size: 90%;\n}\n.genome-spy .message-box {\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n top: 0;\n height: 100%;\n width: 100%;\n}\n.genome-spy .message-box > div {\n border: 1px solid red;\n padding: 10px;\n background: #fff0f0;\n}\n\n.gs-input-binding {\n display: grid;\n grid-template-columns: max-content max-content;\n column-gap: 1em;\n row-gap: 0.3em;\n justify-items: start;\n}\n.gs-input-binding > select,\n.gs-input-binding > input:not([type=checkbox]) {\n width: 100%;\n}\n.gs-input-binding input[type=range] + span {\n display: inline-block;\n margin-left: 0.3em;\n min-width: 2.2em;\n font-variant-numeric: tabular-nums;\n}\n.gs-input-binding input[type=range],\n.gs-input-binding input[type=radio] {\n vertical-align: text-bottom;\n}\n.gs-input-binding .radio-group {\n display: flex;\n align-items: center;\n}\n.gs-input-binding .description {\n max-width: 26em;\n grid-column: 1/-1;\n color: #777;\n font-size: 90%;\n margin-top: -0.5em;\n}\n\n.gs-input-bindings {\n flex-basis: content;\n font-size: 14px;\n padding: 10px;\n}\n";
3
3
  //# sourceMappingURL=genome-spy.css.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"genome-spy.css.d.ts","sourceRoot":"","sources":["../../../src/styles/genome-spy.css.js"],"names":[],"mappings":";AAAA,4pIAiME"}
1
+ {"version":3,"file":"genome-spy.css.d.ts","sourceRoot":"","sources":["../../../src/styles/genome-spy.css.js"],"names":[],"mappings":";AAAA,y/IA4ME"}
@@ -16,6 +16,9 @@ const css = `
16
16
  opacity: 1;
17
17
  transition: transform 0.6s, opacity 0.6s;
18
18
  }
19
+ .genome-spy canvas:focus, .genome-spy canvas:focus-visible {
20
+ outline: none;
21
+ }
19
22
  .genome-spy .loading-message {
20
23
  position: absolute;
21
24
  inset: 0;
@@ -87,9 +90,17 @@ const css = `
87
90
  padding: 10px;
88
91
  font-size: 12px;
89
92
  box-shadow: 0px 3px 15px 0px rgba(0, 0, 0, 0.21);
90
- pointer-events: none;
93
+ transition: outline-color 0.3s ease-in-out, box-shadow 0.3s ease-in-out;
94
+ outline: 0px solid transparent;
91
95
  z-index: 100;
92
96
  }
97
+ .genome-spy .tooltip:not(.sticky) {
98
+ pointer-events: none;
99
+ }
100
+ .genome-spy .tooltip.sticky {
101
+ outline: 2px solid black;
102
+ box-shadow: 0px 3px 18px 0px rgba(0, 0, 0, 0.3);
103
+ }
93
104
  .genome-spy .tooltip > :last-child {
94
105
  margin-bottom: 0;
95
106
  }
@@ -26,6 +26,11 @@ $font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
26
26
  transition:
27
27
  transform 0.6s,
28
28
  opacity 0.6s;
29
+
30
+ &:focus,
31
+ &:focus-visible {
32
+ outline: none;
33
+ }
29
34
  }
30
35
 
31
36
  .loading-message {
@@ -121,7 +126,20 @@ $font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
121
126
 
122
127
  box-shadow: 0px 3px 15px 0px rgba(0, 0, 0, 0.21);
123
128
 
124
- pointer-events: none;
129
+ &:not(.sticky) {
130
+ pointer-events: none;
131
+ }
132
+
133
+ transition:
134
+ outline-color 0.3s ease-in-out,
135
+ box-shadow 0.3s ease-in-out;
136
+
137
+ outline: 0px solid transparent;
138
+ &.sticky {
139
+ outline: 2px solid black;
140
+ box-shadow: 0px 3px 18px 0px rgba(0, 0, 0, 0.3);
141
+ }
142
+
125
143
  z-index: 100;
126
144
 
127
145
  > :last-child {
@@ -5,13 +5,10 @@ export interface SelectionBase {
5
5
  type: string;
6
6
  }
7
7
 
8
- export interface RangeSelection extends SelectionBase {
9
- type: "range";
8
+ export interface IntervalSelection extends SelectionBase {
9
+ type: "interval";
10
10
 
11
- fields?: string[];
12
- channels?: ChannelWithScale[];
13
-
14
- ranges: number[][];
11
+ intervals: Partial<Record<ChannelWithScale, number[] | null>>;
15
12
  }
16
13
 
17
14
  export interface ProjectedSelection extends SelectionBase {
@@ -38,7 +35,7 @@ export interface MultiPointSelection extends SelectionBase {
38
35
  }
39
36
 
40
37
  export type Selection =
41
- | RangeSelection
38
+ | IntervalSelection
42
39
  | ProjectedSelection
43
40
  | SinglePointSelection
44
41
  | MultiPointSelection;
@@ -98,21 +98,6 @@ export default interface ViewContext {
98
98
 
99
99
  isViewSpec: (spec: any) => boolean;
100
100
 
101
- /**
102
- * @deprecated Use createOrImportView instead.
103
- * @param spec
104
- * @param layoutParent
105
- * @param dataParent
106
- * @param defaultName
107
- * @returns
108
- */
109
- createView: (
110
- spec: ViewSpec,
111
- layoutParent?: ContainerView,
112
- dataParent?: View,
113
- defaultName?: string
114
- ) => View;
115
-
116
101
  /**
117
102
  *
118
103
  * @param spec
@@ -1 +1 @@
1
- {"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../../src/utils/expression.js"],"names":[],"mappings":"AAkEA;;;;;;;;;;GAUG;AACH,6CAHW,MAAM,sBACJ,kBAAkB,CAgC9B;;YAvCU,MAAM,EAAE;aACR,MAAM,EAAE;UACR,MAAM;;iCAEH,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,qBAAqB,EAAE,KAAK,KAAK,GAAG,CAAC,GAAG,eAAe"}
1
+ {"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../../../src/utils/expression.js"],"names":[],"mappings":"AAsEA;;;;;;;;;;GAUG;AACH,6CAHW,MAAM,sBACJ,kBAAkB,CAgC9B;;YAvCU,MAAM,EAAE;aACR,MAAM,EAAE;UACR,MAAM;;iCAEH,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,qBAAqB,EAAE,KAAK,KAAK,GAAG,CAAC,GAAG,eAAe"}