@genome-spy/core 0.43.3 → 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.
Files changed (124) hide show
  1. package/dist/bundle/index.es.js +5231 -4324
  2. package/dist/bundle/index.js +197 -85
  3. package/dist/schema.json +723 -104
  4. package/dist/src/data/collector.d.ts.map +1 -1
  5. package/dist/src/data/collector.js +4 -2
  6. package/dist/src/data/flowOptimizer.test.js +12 -3
  7. package/dist/src/data/sources/dataUtils.d.ts.map +1 -1
  8. package/dist/src/data/sources/dataUtils.js +3 -1
  9. package/dist/src/data/sources/lazy/axisTickSource.d.ts +1 -1
  10. package/dist/src/data/sources/lazy/axisTickSource.d.ts.map +1 -1
  11. package/dist/src/data/sources/lazy/axisTickSource.js +2 -2
  12. package/dist/src/data/sources/lazy/bigBedSource.d.ts +1 -1
  13. package/dist/src/data/sources/lazy/bigBedSource.d.ts.map +1 -1
  14. package/dist/src/data/sources/lazy/bigBedSource.js +52 -20
  15. package/dist/src/data/sources/lazy/bigWigSource.d.ts +6 -1
  16. package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
  17. package/dist/src/data/sources/lazy/bigWigSource.js +33 -9
  18. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +1 -1
  19. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  20. package/dist/src/data/sources/lazy/singleAxisLazySource.js +1 -3
  21. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts +13 -14
  22. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  23. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +70 -48
  24. package/dist/src/data/sources/sequenceSource.d.ts.map +1 -1
  25. package/dist/src/data/sources/sequenceSource.js +14 -5
  26. package/dist/src/data/sources/sequenceSource.test.js +23 -5
  27. package/dist/src/data/sources/urlSource.d.ts.map +1 -1
  28. package/dist/src/data/sources/urlSource.js +15 -2
  29. package/dist/src/data/transforms/aggregate.d.ts.map +1 -1
  30. package/dist/src/data/transforms/aggregate.js +5 -2
  31. package/dist/src/data/transforms/filterScoredLabels.js +1 -1
  32. package/dist/src/encoder/encoder.d.ts +2 -4
  33. package/dist/src/encoder/encoder.d.ts.map +1 -1
  34. package/dist/src/encoder/encoder.js +20 -10
  35. package/dist/src/encoder/encoder.test.js +3 -0
  36. package/dist/src/genomeSpy.d.ts +8 -5
  37. package/dist/src/genomeSpy.d.ts.map +1 -1
  38. package/dist/src/genomeSpy.js +121 -42
  39. package/dist/src/gl/glslScaleGenerator.d.ts +23 -3
  40. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
  41. package/dist/src/gl/glslScaleGenerator.js +137 -42
  42. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  43. package/dist/src/gl/webGLHelper.js +5 -7
  44. package/dist/src/index.d.ts +1 -1
  45. package/dist/src/index.d.ts.map +1 -1
  46. package/dist/src/index.js +1 -1
  47. package/dist/src/marks/link.common.glsl.js +2 -0
  48. package/dist/src/marks/link.d.ts.map +1 -1
  49. package/dist/src/marks/link.js +19 -9
  50. package/dist/src/marks/link.vertex.glsl.js +1 -1
  51. package/dist/src/marks/mark.d.ts +25 -20
  52. package/dist/src/marks/mark.d.ts.map +1 -1
  53. package/dist/src/marks/mark.js +234 -129
  54. package/dist/src/marks/point.common.glsl.js +1 -1
  55. package/dist/src/marks/point.d.ts +1 -4
  56. package/dist/src/marks/point.d.ts.map +1 -1
  57. package/dist/src/marks/point.js +31 -23
  58. package/dist/src/marks/point.vertex.glsl.js +1 -1
  59. package/dist/src/marks/rect.common.glsl.js +2 -0
  60. package/dist/src/marks/rect.d.ts.map +1 -1
  61. package/dist/src/marks/rect.js +12 -12
  62. package/dist/src/marks/rect.vertex.glsl.js +1 -1
  63. package/dist/src/marks/rule.common.glsl.js +1 -1
  64. package/dist/src/marks/rule.js +2 -2
  65. package/dist/src/marks/text.common.glsl.js +1 -1
  66. package/dist/src/marks/text.d.ts.map +1 -1
  67. package/dist/src/marks/text.js +17 -9
  68. package/dist/src/spec/channel.d.ts +4 -3
  69. package/dist/src/spec/data.d.ts +11 -10
  70. package/dist/src/spec/mark.d.ts +28 -46
  71. package/dist/src/spec/parameter.d.ts +127 -0
  72. package/dist/src/spec/root.d.ts +1 -0
  73. package/dist/src/spec/scale.d.ts +2 -1
  74. package/dist/src/spec/title.d.ts +5 -4
  75. package/dist/src/spec/view.d.ts +20 -5
  76. package/dist/src/styles/genome-spy.css.d.ts +1 -1
  77. package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
  78. package/dist/src/styles/genome-spy.css.js +52 -5
  79. package/dist/src/styles/genome-spy.scss +63 -10
  80. package/dist/src/styles/update.sh +6 -0
  81. package/dist/src/tooltip/dataTooltipHandler.js +1 -1
  82. package/dist/src/tooltip/refseqGeneTooltipHandler.js +1 -1
  83. package/dist/src/tooltip/tooltipHandler.d.ts +1 -1
  84. package/dist/src/tooltip/tooltipHandler.d.ts.map +1 -1
  85. package/dist/src/tooltip/tooltipHandler.ts +1 -1
  86. package/dist/src/types/embedApi.d.ts +6 -0
  87. package/dist/src/types/scaleResolutionApi.d.ts +7 -3
  88. package/dist/src/types/viewContext.d.ts +2 -3
  89. package/dist/src/utils/debounce.d.ts +2 -2
  90. package/dist/src/utils/debounce.d.ts.map +1 -1
  91. package/dist/src/utils/debounce.js +5 -2
  92. package/dist/src/utils/expression.d.ts +2 -2
  93. package/dist/src/utils/expression.d.ts.map +1 -1
  94. package/dist/src/utils/expression.js +3 -3
  95. package/dist/src/utils/formatObject.d.ts +2 -2
  96. package/dist/src/utils/formatObject.d.ts.map +1 -1
  97. package/dist/src/utils/formatObject.js +2 -2
  98. package/dist/src/utils/inputBinding.d.ts +5 -0
  99. package/dist/src/utils/inputBinding.d.ts.map +1 -0
  100. package/dist/src/utils/inputBinding.js +115 -0
  101. package/dist/src/utils/ui/tooltip.js +1 -1
  102. package/dist/src/view/axisView.js +3 -3
  103. package/dist/src/view/paramMediator.d.ts +108 -0
  104. package/dist/src/view/paramMediator.d.ts.map +1 -0
  105. package/dist/src/view/paramMediator.js +337 -0
  106. package/dist/src/view/paramMediator.test.js +211 -0
  107. package/dist/src/view/scaleResolution.d.ts +8 -18
  108. package/dist/src/view/scaleResolution.d.ts.map +1 -1
  109. package/dist/src/view/scaleResolution.js +225 -126
  110. package/dist/src/view/scaleResolution.test.js +7 -7
  111. package/dist/src/view/unitView.d.ts.map +1 -1
  112. package/dist/src/view/unitView.js +10 -3
  113. package/dist/src/view/view.d.ts +4 -1
  114. package/dist/src/view/view.d.ts.map +1 -1
  115. package/dist/src/view/view.js +21 -7
  116. package/dist/src/view/viewFactory.d.ts.map +1 -1
  117. package/dist/src/view/viewFactory.js +45 -0
  118. package/dist/src/view/viewUtils.d.ts +5 -1
  119. package/dist/src/view/viewUtils.d.ts.map +1 -1
  120. package/dist/src/view/viewUtils.js +9 -4
  121. package/package.json +16 -17
  122. package/dist/src/paramBroker.d.ts +0 -30
  123. package/dist/src/paramBroker.d.ts.map +0 -1
  124. package/dist/src/paramBroker.js +0 -102
@@ -1,2 +1,2 @@
1
- const shader = "out float vRadius;out float vRadiusWithPadding;out lowp vec4 vFillColor;out lowp vec4 vStrokeColor;out lowp float vShape;out lowp float vHalfStrokeWidth;out mat2 vRotationMatrix;const float CIRCLE=0.0;const float SQUARE=1.0;const float CROSS=2.0;const float DIAMOND=3.0;const float TRIANGLE_UP=4.0;const float TRIANGLE_RIGHT=5.0;const float TRIANGLE_DOWN=6.0;const float TRIANGLE_LEFT=7.0;const float TICK_UP=8.0;const float TICK_RIGHT=9.0;const float TICK_DOWN=10.0;const float TICK_LEFT=11.0;float computeSemanticThresholdFactor(){return getScaled_semanticScore()>=uSemanticThreshold ? 1.0 : 0.0;}/***Computes a scaling factor for the points in a sample-faceted view.*/float getDownscaleFactor(vec2 pos){if(!isFacetedSamples()){return 1.0;}float sampleFacetHeight=getSampleFacetHeight(pos);float maxPointDiameter=sqrt(uMaxPointSize);float factor=sampleFacetHeight*uViewportSize.y*uMaxRelativePointDiameter;return clamp(0.0,maxPointDiameter,factor)/maxPointDiameter;}vec2 getDxDy(){\n#if defined(dx_DEFINED) || defined(dy_DEFINED)\nreturn vec2(getScaled_dx(),getScaled_dy())/uViewportSize;\n#else\nreturn vec2(0.0,0.0);\n#endif\n}void main(void){float shapeAngle=0.0;float semanticThresholdFactor=computeSemanticThresholdFactor();if(semanticThresholdFactor<=0.0){gl_PointSize=0.0;gl_Position=vec4(100.0,0.0,0.0,0.0);return;}float size=getScaled_size();vec2 pos=vec2(getScaled_x(),getScaled_y())+getDxDy();gl_Position=unitToNdc(applySampleFacet(pos));float strokeWidth=getScaled_strokeWidth();float diameter=sqrt(size)*uScaleFactor*semanticThresholdFactor*getDownscaleFactor(pos);float opacity=uViewOpacity;if(strokeWidth<=0.0||uInwardStroke){float minDiameter=1.0/uDevicePixelRatio;if(diameter<minDiameter){opacity*=pow(diameter/minDiameter,2.5);diameter=minDiameter;}}float fillOpa=getScaled_fillOpacity()*opacity;float strokeOpa=getScaled_strokeOpacity()*opacity;vShape=getScaled_shape();bool circle=vShape==0.0;if(vShape>TICK_UP&&vShape<=TICK_LEFT){shapeAngle=(vShape-TICK_UP)*90.0;vShape=TICK_UP;}else if(vShape>TRIANGLE_UP&&vShape<=TRIANGLE_LEFT){shapeAngle=(vShape-TRIANGLE_UP)*90.0;vShape=TRIANGLE_UP;}float angleInDegrees=getScaled_angle();float angle=-(shapeAngle+angleInDegrees)*PI/180.0;float sinTheta=sin(angle);float cosTheta=cos(angle);vRotationMatrix=mat2(cosTheta,sinTheta,-sinTheta,cosTheta);float roomForRotation=circle ? 1.0 : sin(mod(angle,PI/2.0)+PI/4.0)/sin(PI/4.0);float aaPadding=1.0/uDevicePixelRatio;float rotationPadding=(diameter*roomForRotation)-diameter;float strokePadding=uInwardStroke ? 0.0 : strokeWidth*(circle ? 1.0 : sqrt(3.0));float padding=rotationPadding+strokePadding+aaPadding;gl_PointSize=(diameter+padding)*uDevicePixelRatio;vRadius=diameter/2.0;vRadiusWithPadding=vRadius+padding/2.0;vHalfStrokeWidth=strokeWidth/2.0;vFillColor=vec4(getScaled_fill()*fillOpa,fillOpa);vStrokeColor=vec4(getScaled_stroke()*strokeOpa,strokeOpa);setupPicking();}";
1
+ const shader = "out float vRadius;out float vRadiusWithPadding;out lowp vec4 vFillColor;out lowp vec4 vStrokeColor;out lowp float vShape;out lowp float vHalfStrokeWidth;out mat2 vRotationMatrix;const float CIRCLE=0.0;const float SQUARE=1.0;const float CROSS=2.0;const float DIAMOND=3.0;const float TRIANGLE_UP=4.0;const float TRIANGLE_RIGHT=5.0;const float TRIANGLE_DOWN=6.0;const float TRIANGLE_LEFT=7.0;const float TICK_UP=8.0;const float TICK_RIGHT=9.0;const float TICK_DOWN=10.0;const float TICK_LEFT=11.0;float computeSemanticThresholdFactor(){return getScaled_semanticScore()>=uSemanticThreshold ? 1.0 : 0.0;}vec2 getDxDy(){\n#if defined(dx_DEFINED) || defined(dy_DEFINED)\nreturn vec2(getScaled_dx(),getScaled_dy())/uViewportSize;\n#else\nreturn vec2(0.0,0.0);\n#endif\n}void main(void){float shapeAngle=0.0;float semanticThresholdFactor=computeSemanticThresholdFactor();if(semanticThresholdFactor<=0.0){gl_PointSize=0.0;gl_Position=vec4(100.0,0.0,0.0,0.0);return;}float size=getScaled_size();vec2 pos=vec2(getScaled_x(),getScaled_y())+getDxDy();gl_Position=unitToNdc(applySampleFacet(pos));float strokeWidth=getScaled_strokeWidth();float diameter=sqrt(size)*uScaleFactor*semanticThresholdFactor;float opacity=uViewOpacity;if(strokeWidth<=0.0||uInwardStroke){float minDiameter=1.0/uDevicePixelRatio;if(diameter<minDiameter){opacity*=pow(diameter/minDiameter,2.5);diameter=minDiameter;}}float fillOpa=getScaled_fillOpacity()*opacity;float strokeOpa=getScaled_strokeOpacity()*opacity;vShape=getScaled_shape();bool circle=vShape==0.0;if(vShape>TICK_UP&&vShape<=TICK_LEFT){shapeAngle=(vShape-TICK_UP)*90.0;vShape=TICK_UP;}else if(vShape>TRIANGLE_UP&&vShape<=TRIANGLE_LEFT){shapeAngle=(vShape-TRIANGLE_UP)*90.0;vShape=TRIANGLE_UP;}float angleInDegrees=getScaled_angle();float angle=-(shapeAngle+angleInDegrees)*PI/180.0;float sinTheta=sin(angle);float cosTheta=cos(angle);vRotationMatrix=mat2(cosTheta,sinTheta,-sinTheta,cosTheta);float roomForRotation=circle ? 1.0 : sin(mod(angle,PI/2.0)+PI/4.0)/sin(PI/4.0);float aaPadding=1.0/uDevicePixelRatio;float rotationPadding=(diameter*roomForRotation)-diameter;float strokePadding=uInwardStroke ? 0.0 : strokeWidth*(circle ? 1.0 : sqrt(3.0));float padding=rotationPadding+strokePadding+aaPadding;gl_PointSize=(diameter+padding)*uDevicePixelRatio;vRadius=diameter/2.0;vRadiusWithPadding=vRadius+padding/2.0;vHalfStrokeWidth=strokeWidth/2.0;vFillColor=vec4(getScaled_fill()*fillOpa,fillOpa);vStrokeColor=vec4(getScaled_stroke()*strokeOpa,strokeOpa);setupPicking();}";
2
2
  export default shader;
@@ -0,0 +1,2 @@
1
+ const shader = "layout(std140)uniform Mark{uniform float uMinWidth;uniform float uMinHeight;uniform float uMinOpacity;uniform float uCornerRadiusTopRight;uniform float uCornerRadiusBottomRight;uniform float uCornerRadiusTopLeft;uniform float uCornerRadiusBottomLeft;\n#pragma markUniforms\n};";
2
+ export default shader;
@@ -1 +1 @@
1
- {"version":3,"file":"rect.d.ts","sourceRoot":"","sources":["../../../src/marks/rect.js"],"names":[],"mappings":"AAYA;IA0NI;;;;;;;;;;OAUG;IACH,8BALW,GAAG,KACH,OAAO,oBAAoB,EAAE,MAAM,GACjC,GAAG,CAyBf;;CACJ;iBAnQgB,WAAW"}
1
+ {"version":3,"file":"rect.d.ts","sourceRoot":"","sources":["../../../src/marks/rect.js"],"names":[],"mappings":"AAaA;IAyNI;;;;;;;;;;OAUG;IACH,8BALW,GAAG,KACH,OAAO,oBAAoB,EAAE,MAAM,GACjC,GAAG,CAyBf;;CACJ;iBAlQgB,WAAW"}
@@ -1,6 +1,7 @@
1
1
  import { drawBufferInfo, setBuffersAndAttributes } from "twgl.js";
2
2
  import VERTEX_SHADER from "./rect.vertex.glsl.js";
3
3
  import FRAGMENT_SHADER from "./rect.fragment.glsl.js";
4
+ import COMMON_SHADER from "./rect.common.glsl.js";
4
5
  import { RectVertexBuilder } from "../gl/dataToVertices.js";
5
6
 
6
7
  import Mark from "./mark.js";
@@ -140,11 +141,10 @@ export default class RectMark extends Mark {
140
141
  defines.push("STROKED");
141
142
  }
142
143
 
143
- this.createAndLinkShaders(
144
- VERTEX_SHADER,
145
- FRAGMENT_SHADER,
146
- defines.map((d) => "#define " + d)
147
- );
144
+ this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER, [
145
+ COMMON_SHADER,
146
+ ...defines.map((d) => "#define " + d),
147
+ ]);
148
148
  }
149
149
 
150
150
  finalizeGraphicsInitialization() {
@@ -154,22 +154,22 @@ export default class RectMark extends Mark {
154
154
 
155
155
  const props = this.properties;
156
156
 
157
- this.registerMarkUniform("uMinWidth", props.minWidth);
158
- this.registerMarkUniform("uMinHeight", props.minHeight);
159
- this.registerMarkUniform("uMinOpacity", props.minOpacity);
160
- this.registerMarkUniform(
157
+ this.registerMarkUniformValue("uMinWidth", props.minWidth);
158
+ this.registerMarkUniformValue("uMinHeight", props.minHeight);
159
+ this.registerMarkUniformValue("uMinOpacity", props.minOpacity);
160
+ this.registerMarkUniformValue(
161
161
  "uCornerRadiusTopRight",
162
162
  props.cornerRadiusTopRight ?? props.cornerRadius ?? 0
163
163
  );
164
- this.registerMarkUniform(
164
+ this.registerMarkUniformValue(
165
165
  "uCornerRadiusBottomRight",
166
166
  props.cornerRadiusBottomRight ?? props.cornerRadius ?? 0
167
167
  );
168
- this.registerMarkUniform(
168
+ this.registerMarkUniformValue(
169
169
  "uCornerRadiusTopLeft",
170
170
  props.cornerRadiusTopLeft ?? props.cornerRadius ?? 0
171
171
  );
172
- this.registerMarkUniform(
172
+ this.registerMarkUniformValue(
173
173
  "uCornerRadiusBottomLeft",
174
174
  props.cornerRadiusBottomLeft ?? props.cornerRadius ?? 0
175
175
  );
@@ -1,2 +1,2 @@
1
- const shader = "uniform Mark{uniform float uMinWidth;uniform float uMinHeight;uniform float uMinOpacity;uniform float uCornerRadiusTopRight;uniform float uCornerRadiusBottomRight;uniform float uCornerRadiusTopLeft;uniform float uCornerRadiusBottomLeft;};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,uCornerRadiusBottomLeft,uCornerRadiusTopLeft);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)\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,uCornerRadiusBottomLeft,uCornerRadiusTopLeft);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();}";
2
2
  export default shader;
@@ -1,2 +1,2 @@
1
- const shader = "uniform Mark{uniform mediump float uMinLength;uniform mediump float uDashTextureSize;uniform lowp int uStrokeCap;uniform mediump float uStrokeDashOffset;};";
1
+ const shader = "layout(std140)uniform Mark{uniform mediump float uMinLength;uniform mediump float uDashTextureSize;uniform lowp int uStrokeCap;uniform mediump float uStrokeDashOffset;\n#pragma markUniforms\n};";
2
2
  export default shader;
@@ -150,8 +150,8 @@ export default class RuleMark extends Mark {
150
150
 
151
151
  const props = this.properties;
152
152
 
153
- this.registerMarkUniform("uMinLength", props.minLength);
154
- this.registerMarkUniform(
153
+ this.registerMarkUniformValue("uMinLength", props.minLength);
154
+ this.registerMarkUniformValue(
155
155
  "uStrokeCap",
156
156
  props.strokeCap ?? "butt",
157
157
  (cap) => ["butt", "square", "round"].indexOf(cap)
@@ -1,2 +1,2 @@
1
- const shader = "uniform Mark{uniform mediump float uSdfNumerator;uniform mediump vec2 uD;uniform mediump vec4 uViewportEdgeFadeWidth;uniform mediump vec4 uViewportEdgeFadeDistance;uniform bool uSqueeze;uniform bool uLogoLetter;uniform lowp ivec2 uAlign;uniform mediump float uPaddingX;uniform bool uFlushX;uniform mediump float uPaddingY;uniform bool uFlushY;};";
1
+ const shader = "layout(std140)uniform Mark{uniform mediump float uSdfNumerator;uniform mediump vec2 uD;uniform mediump vec4 uViewportEdgeFadeWidth;uniform mediump vec4 uViewportEdgeFadeDistance;uniform bool uSqueeze;uniform bool uLogoLetter;uniform lowp ivec2 uAlign;uniform mediump float uPaddingX;uniform bool uFlushX;uniform mediump float uPaddingY;uniform bool uFlushY;\n#pragma markUniforms\n};";
2
2
  export default shader;
@@ -1 +1 @@
1
- {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/marks/text.js"],"names":[],"mappings":"AAgCA;;;;;;;GAOG;AACH;IAsDQ,oDAMmD;CAgM1D;iBAvRgB,WAAW"}
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/marks/text.js"],"names":[],"mappings":"AAgCA;;;;;;;GAOG;AACH;IAyDQ,oDAMmD;CAqM1D;iBA/RgB,WAAW"}
@@ -39,6 +39,9 @@ const baselines = {
39
39
  * - Google's web fonts as SDFs: https://github.com/etiennepinchon/aframe-fonts
40
40
  */
41
41
  export default class TextMark extends Mark {
42
+ /**
43
+ * @typedef {import("../spec/mark.js").MarkProps} MarkProps
44
+ */
42
45
  /**
43
46
  * @param {import("../view/unitView.js").default} unitView
44
47
  */
@@ -99,6 +102,12 @@ export default class TextMark extends Mark {
99
102
  this.properties.fontWeight
100
103
  )
101
104
  : unitView.context.fontManager.getDefaultFont();
105
+
106
+ this.setupExprRefsNeedingGraphicsUpdate([
107
+ "text",
108
+ "fitToBand",
109
+ "logoLetters",
110
+ ]);
102
111
  }
103
112
 
104
113
  getAttributes() {
@@ -160,9 +169,9 @@ export default class TextMark extends Mark {
160
169
 
161
170
  const props = this.properties;
162
171
 
163
- this.registerMarkUniform(
172
+ this.registerMarkUniformValue(
164
173
  "uSdfNumerator",
165
- /** @type {import("../spec/mark.js").ExprRef | number} */
174
+ /** @type {import("../spec/parameter.js").ExprRef | number} */
166
175
  ({ expr: "devicePixelRatio" }),
167
176
  (dpr) => {
168
177
  let q = 0.35; // TODO: Ensure that this makes sense. Now chosen by trial & error
@@ -176,19 +185,18 @@ export default class TextMark extends Mark {
176
185
  }
177
186
  );
178
187
 
179
- // TODO: Use uniform block.
180
- setBlockUniforms(this.markUniformInfo, {
181
- uPaddingX: props.paddingX,
182
- uPaddingY: props.paddingY,
183
- uFlushX: !!props.flushX,
184
- uFlushY: !!props.flushY,
188
+ this.registerMarkUniformValue("uPaddingX", props.paddingX);
189
+ this.registerMarkUniformValue("uPaddingY", props.paddingY);
190
+ this.registerMarkUniformValue("uFlushX", props.flushX, (x) => !!x);
191
+ this.registerMarkUniformValue("uFlushY", props.flushY, (x) => !!x);
192
+ this.registerMarkUniformValue("uSqueeze", props.squeeze, (x) => !!x);
185
193
 
194
+ setBlockUniforms(this.markUniformInfo, {
186
195
  uAlign: [alignments[props.align], baselines[props.baseline]],
187
196
 
188
197
  uD: [props.dx, -props.dy],
189
198
 
190
199
  uLogoLetter: !!props.logoLetters,
191
- uSqueeze: !!props.squeeze,
192
200
 
193
201
  uViewportEdgeFadeWidth: [
194
202
  props.viewportEdgeFadeWidthTop,
@@ -8,11 +8,12 @@
8
8
  * BSD-3-Clause License: https://github.com/vega/vega-lite/blob/master/LICENSE
9
9
  */
10
10
 
11
+ import { ExprRef } from "./parameter.js";
11
12
  import { Scale } from "./scale.js";
12
13
  import { GenomeAxis } from "./axis.js";
13
14
 
14
15
  export type Scalar = string | number | boolean;
15
- export type Value = Scalar | null;
16
+ export type Value = Scalar | ExprRef | null;
16
17
 
17
18
  export type FieldName = string;
18
19
  export type Field = FieldName;
@@ -149,7 +150,7 @@ export interface ValueDefBase<V extends Value = Scalar> {
149
150
  /**
150
151
  * A constant value in visual domain (e.g., `"red"` / `"#0099ff"`, values between `0` to `1` for opacity).
151
152
  */
152
- value: V;
153
+ value: V | ExprRef;
153
154
  }
154
155
 
155
156
  export type ValueDef<V extends Value = Scalar> = ValueDefBase<V> & TitleMixins;
@@ -158,7 +159,7 @@ export interface DatumDefBase {
158
159
  /**
159
160
  * A constant value in data domain.
160
161
  */
161
- datum?: Scalar;
162
+ datum?: Scalar | ExprRef;
162
163
  }
163
164
 
164
165
  export type DatumDef = DatumDefBase & TitleMixins;
@@ -13,6 +13,7 @@
13
13
  */
14
14
  import { Axis } from "./axis.js";
15
15
  import { FieldName, PrimaryPositionalChannel } from "./channel.js";
16
+ import { ExprRef } from "./parameter.js";
16
17
 
17
18
  export type ParseValue =
18
19
  | null
@@ -123,7 +124,7 @@ export interface UrlData extends DataBase {
123
124
  * An URL or an array of URLs from which to load the data set.
124
125
  * Use the `format.type` property to ensure the loaded data is correctly parsed.
125
126
  */
126
- url: string | string[];
127
+ url: string | string[] | ExprRef;
127
128
  }
128
129
 
129
130
  export interface InlineData extends DataBase {
@@ -169,24 +170,24 @@ export interface SequenceParams {
169
170
  /**
170
171
  * The starting value of the sequence (inclusive).
171
172
  */
172
- start: number;
173
+ start: number | ExprRef;
173
174
  /**
174
175
  * The ending value of the sequence (exclusive).
175
176
  */
176
- stop: number;
177
+ stop: number | ExprRef;
177
178
  /**
178
179
  * The step value between sequence entries.
179
180
  *
180
181
  * __Default value:__ `1`
181
182
  */
182
- step?: number;
183
+ step?: number | ExprRef;
183
184
 
184
185
  /**
185
186
  * The name of the generated sequence field.
186
187
  *
187
188
  * __Default value:__ `"data"`
188
189
  */
189
- as?: FieldName;
190
+ as?: FieldName | ExprRef;
190
191
  }
191
192
 
192
193
  export interface LazyData {
@@ -209,7 +210,7 @@ export interface DebouncedData {
209
210
  *
210
211
  * __Default value:__ `200`
211
212
  */
212
- debounce?: number;
213
+ debounce?: number | ExprRef;
213
214
 
214
215
  /**
215
216
  * The debounce mode for data updates. If set to `"domain"`, domain change
@@ -286,14 +287,14 @@ export interface BigWigData extends DebouncedData {
286
287
  /**
287
288
  * URL of the BigWig file.
288
289
  */
289
- url: string;
290
+ url: string | ExprRef;
290
291
 
291
292
  /**
292
293
  * The approximate minimum width of each data bin, in pixels.
293
294
  *
294
295
  * __Default value:__ `2`
295
296
  */
296
- pixelsPerBin?: number;
297
+ pixelsPerBin?: number | ExprRef;
297
298
  }
298
299
 
299
300
  export interface BigBedData extends DebouncedData {
@@ -309,7 +310,7 @@ export interface BigBedData extends DebouncedData {
309
310
  /**
310
311
  * URL of the BigBed file.
311
312
  */
312
- url: string;
313
+ url: string | ExprRef;
313
314
 
314
315
  /**
315
316
  * Size of each chunk when fetching the BigBed file. Data is only fetched
@@ -317,7 +318,7 @@ export interface BigBedData extends DebouncedData {
317
318
  *
318
319
  * __Default value:__ `1000000`
319
320
  */
320
- windowSize?: number;
321
+ windowSize?: number | ExprRef;
321
322
  }
322
323
 
323
324
  export interface BamData extends DebouncedData {
@@ -1,35 +1,27 @@
1
1
  import { Scalar } from "./channel.js";
2
+ import { ExprRef } from "./parameter.js";
2
3
  import { Align, Baseline, FontStyle, FontWeight } from "./font.js";
3
4
  import { Tooltip } from "./tooltip.js";
4
5
 
5
- // TODO: This may not be the best place for this type.
6
- // Also, this is now similar to the ExprDef type in channel.d.ts
7
- export interface ExprRef {
8
- /**
9
- * The expression string.
10
- */
11
- expr: string;
12
- }
13
-
14
6
  export type MarkType = "rect" | "point" | "rule" | "text" | "link";
15
7
 
16
8
  export interface FillAndStrokeProps {
17
9
  /** The fill color */
18
- fill?: string;
10
+ fill?: string | ExprRef;
19
11
 
20
12
  /** The fill opacity. Value between [0, 1]. */
21
- fillOpacity?: number;
13
+ fillOpacity?: number | ExprRef;
22
14
 
23
15
  /** The stroke color */
24
- stroke?: string;
16
+ stroke?: string | ExprRef;
25
17
 
26
18
  /** The stroke opacity. Value between [0, 1]. */
27
- strokeOpacity?: number;
19
+ strokeOpacity?: number | ExprRef;
28
20
  }
29
21
 
30
22
  export interface SecondaryPositionProps {
31
- x2?: number;
32
- y2?: number;
23
+ x2?: number | ExprRef;
24
+ y2?: number | ExprRef;
33
25
  }
34
26
 
35
27
  export interface AngleProps {
@@ -38,7 +30,7 @@ export interface AngleProps {
38
30
  *
39
31
  * **Default value:** `0`
40
32
  */
41
- angle?: number;
33
+ angle?: number | ExprRef;
42
34
  }
43
35
 
44
36
  /**
@@ -170,14 +162,14 @@ export interface TextProps
170
162
  *
171
163
  * **Default value:** `""`
172
164
  */
173
- text?: Scalar;
165
+ text?: Scalar | ExprRef;
174
166
 
175
167
  /**
176
168
  * The font size in pixels.
177
169
  *
178
170
  * **Default value:** `11`
179
171
  */
180
- size?: number;
172
+ size?: number | ExprRef;
181
173
 
182
174
  /**
183
175
  * The font typeface. GenomeSpy uses [SDF](https://github.com/Chlumsky/msdfgen)
@@ -242,33 +234,33 @@ export interface TextProps
242
234
  *
243
235
  * **Default value:** `false`
244
236
  */
245
- fitToBand?: boolean;
237
+ fitToBand?: boolean | ExprRef;
246
238
 
247
239
  /**
248
240
  * The horizontal padding, in pixels, when the `x2` channel is used for ranged text.
249
241
  *
250
242
  * **Default value:** `0`
251
243
  */
252
- paddingX?: number;
244
+ paddingX?: number | ExprRef;
253
245
 
254
246
  /**
255
247
  * The vertical padding, in pixels, when the `y2` channel is used for ranged text.
256
248
  *
257
249
  * **Default value:** `0`
258
250
  */
259
- paddingY?: number;
251
+ paddingY?: number | ExprRef;
260
252
 
261
253
  /**
262
254
  * If true, the text is kept inside the viewport when the range of `x` and `x2`
263
255
  * intersect the viewport.
264
256
  */
265
- flushX?: boolean;
257
+ flushX?: boolean | ExprRef;
266
258
 
267
259
  /**
268
260
  * If true, the text is kept inside the viewport when the range of `y` and `y2`
269
261
  * intersect the viewport.
270
262
  */
271
- flushY?: boolean;
263
+ flushY?: boolean | ExprRef;
272
264
 
273
265
  /**
274
266
  * If the `squeeze` property is true and secondary positional channels (`x2` and/or `y2`)
@@ -276,12 +268,12 @@ export interface TextProps
276
268
  *
277
269
  * **Default value:** `true`
278
270
  */
279
- squeeze?: boolean;
271
+ squeeze?: boolean | ExprRef;
280
272
 
281
273
  /**
282
274
  * Stretch letters so that they can be used with [sequence logos](https://en.wikipedia.org/wiki/Sequence_logo), etc...
283
275
  */
284
- logoLetters?: boolean;
276
+ logoLetters?: boolean | ExprRef;
285
277
  }
286
278
 
287
279
  export interface PointProps extends AngleProps {
@@ -300,7 +292,7 @@ export interface PointProps extends AngleProps {
300
292
  *
301
293
  * **Default value:** `false`
302
294
  */
303
- inwardStroke?: boolean;
295
+ inwardStroke?: boolean | ExprRef;
304
296
 
305
297
  /**
306
298
  * Gradient strength controls the amount of the gradient eye-candy effect in the fill color.
@@ -308,24 +300,14 @@ export interface PointProps extends AngleProps {
308
300
  *
309
301
  * **Default value:** `0`
310
302
  */
311
- fillGradientStrength?: number;
312
-
313
- /**
314
- * Padding between sample facet's upper/lower edge and the maximum point size. This property
315
- * controls how tightly points are squeezed when facet's height is smaller than the maximum
316
- * point size. The unit is a proportion of facet's height. The value must be between `0`
317
- * and `0.5`. This property has no effect when sample faceting is not used.
318
- *
319
- * **Default value:** `0.1`
320
- */
321
- sampleFacetPadding?: number;
303
+ fillGradientStrength?: number | ExprRef;
322
304
 
323
305
  /**
324
306
  * TODO
325
307
  *
326
308
  * **Default value:** `0.02`
327
309
  */
328
- semanticZoomFraction?: number;
310
+ semanticZoomFraction?: number | ExprRef;
329
311
 
330
312
  /**
331
313
  * Enables geometric zooming. The value is the base two logarithmic zoom level where the maximum
@@ -414,7 +396,7 @@ export interface LinkProps extends SecondaryPositionProps {
414
396
  }
415
397
 
416
398
  // TODO: Mark-specific configs
417
- export interface MarkConfig
399
+ export interface MarkProps
418
400
  extends PointProps,
419
401
  RectProps,
420
402
  TextProps,
@@ -422,11 +404,11 @@ export interface MarkConfig
422
404
  LinkProps,
423
405
  FillAndStrokeProps {
424
406
  // Channels.
425
- x?: number;
426
- y?: number;
427
- color?: string;
428
- opacity?: number;
429
- size?: number;
407
+ x?: number | ExprRef;
408
+ y?: number | ExprRef;
409
+ color?: string | ExprRef;
410
+ opacity?: number | ExprRef;
411
+ size?: number | ExprRef;
430
412
 
431
413
  /**
432
414
  * Whether the `color` represents the `fill` color (`true`) or the `stroke` color (`false`).
@@ -463,7 +445,7 @@ export interface MarkConfig
463
445
  /**
464
446
  * The stroke width in pixels.
465
447
  */
466
- strokeWidth?: number;
448
+ strokeWidth?: number | ExprRef;
467
449
 
468
450
  /**
469
451
  * Minimum size for WebGL buffers (number of data items).
@@ -474,6 +456,6 @@ export interface MarkConfig
474
456
  minBufferSize?: number;
475
457
  }
476
458
 
477
- export interface MarkConfigAndType extends MarkConfig {
459
+ export interface MarkConfigAndType extends MarkProps {
478
460
  type: MarkType;
479
461
  }
@@ -0,0 +1,127 @@
1
+ export interface ExprRef {
2
+ /**
3
+ * The expression string.
4
+ */
5
+ expr: string;
6
+ }
7
+
8
+ // Adapted from: https://github.com/vega/vega-lite/blob/main/src/parameter.ts
9
+
10
+ export interface VariableParameter {
11
+ /**
12
+ * A unique name for the variable parameter. Parameter names should be valid
13
+ * JavaScript identifiers: they should contain only alphanumeric characters
14
+ * (or "$", or "_") and may not start with a digit. Reserved keywords that
15
+ * may not be used as parameter names are: "datum".
16
+ */
17
+ name: string;
18
+
19
+ /**
20
+ * The [initial value](http://vega.github.io/vega-lite/docs/value.html) of the parameter.
21
+ *
22
+ * __Default value:__ `undefined`
23
+ */
24
+ value?: any;
25
+
26
+ /**
27
+ * An expression for the value of the parameter. This expression may include other parameters,
28
+ * in which case the parameter will automatically update in response to upstream parameter changes.
29
+ */
30
+ expr?: string;
31
+
32
+ /**
33
+ * Binds the parameter to an external input element such as a slider, selection list or radio button group.
34
+ */
35
+ bind?: Binding;
36
+ }
37
+
38
+ // ----------------------------------------------------------------------------
39
+ // Adapted from: https://github.com/vega/vega/blob/main/packages/vega-typings/types/spec/bind.d.ts
40
+
41
+ export type Element = string;
42
+
43
+ export interface BindBase {
44
+ /**
45
+ * If defined, delays event handling until the specified milliseconds have
46
+ * elapsed since the last event was fired.
47
+ */
48
+ debounce?: number;
49
+
50
+ /**
51
+ * By default, the parameter name is used to label input elements.
52
+ * This `name` property can be used instead to specify a custom
53
+ * label for the bound parameter.
54
+ */
55
+ name?: string;
56
+
57
+ /**
58
+ * An optional description or help text that is shown below the input element.
59
+ */
60
+ description?: string;
61
+ }
62
+
63
+ export interface BindCheckbox extends BindBase {
64
+ input: "checkbox";
65
+ }
66
+
67
+ export interface BindRadioSelect extends BindBase {
68
+ input: "radio" | "select";
69
+ /**
70
+ * An array of options to select from.
71
+ */
72
+ options: any[];
73
+
74
+ /**
75
+ * An array of label strings to represent the `options` values. If
76
+ * unspecified, the `options` value will be coerced to a string and
77
+ * used as the label.
78
+ */
79
+ labels?: string[];
80
+ }
81
+
82
+ export interface BindRange extends BindBase {
83
+ input: "range";
84
+
85
+ /**
86
+ * Sets the minimum slider value. Defaults to the smaller of the signal value and `0`.
87
+ */
88
+ min?: number;
89
+
90
+ /**
91
+ * Sets the maximum slider value. Defaults to the larger of the signal value and `100`.
92
+ */
93
+ max?: number;
94
+
95
+ /**
96
+ * Sets the minimum slider increment. If undefined, the step size will be
97
+ * automatically determined based on the `min` and `max` values.
98
+ */
99
+ step?: number;
100
+ }
101
+
102
+ export interface BindDirect {
103
+ /**
104
+ * An input element that exposes a _value_ property and supports the
105
+ * [EventTarget](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget)
106
+ * interface, or a CSS selector string to such an element. When the element
107
+ * updates and dispatches an event, the _value_ property will be used as the
108
+ * new, bound signal value. When the signal updates independent of the
109
+ * element, the _value_ property will be set to the signal value and a new
110
+ * event will be dispatched on the element.
111
+ */
112
+ element: Element | EventTarget;
113
+
114
+ /**
115
+ * The event (default `"input"`) to listen for to track changes on the
116
+ * external element.
117
+ */
118
+ event?: string;
119
+
120
+ /**
121
+ * If defined, delays event handling until the specified milliseconds have
122
+ * elapsed since the last event was fired.
123
+ */
124
+ debounce?: number;
125
+ }
126
+
127
+ export type Binding = BindCheckbox | BindRadioSelect | BindRange;
@@ -1,4 +1,5 @@
1
1
  import { GenomeConfig } from "./genome.js";
2
+ import { VariableParameter } from "./parameter.js";
2
3
  import { ViewSpec } from "./view.js";
3
4
 
4
5
  interface RootConfig {
@@ -9,6 +9,7 @@
9
9
  */
10
10
 
11
11
  import { ChromosomalLocus } from "./genome.js";
12
+ import { ExprRef } from "./parameter.js";
12
13
 
13
14
  export type ScaleType =
14
15
  | "null"
@@ -94,7 +95,7 @@ export interface Scale {
94
95
  *
95
96
  * 2) Any directly specified `range` for `x` and `y` channels will be ignored. Range can be customized via the view's corresponding [size](https://vega.github.io/vega-lite/docs/size.html) (`width` and `height`).
96
97
  */
97
- range?: number[] | string[] | string;
98
+ range?: number[] | string[] | string | ExprRef[];
98
99
 
99
100
  // ordinal
100
101