@vizabi/bubblechart 5.5.2 → 5.5.4

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.
@@ -1,4 +1,4 @@
1
- // https://github.com/vizabi/bubblechart#readme v5.5.2 build 1765875954936 Copyright 2025 Gapminder Foundation and contributors
1
+ // https://github.com/vizabi/bubblechart#readme v5.5.4 build 1773941847513 Copyright 2026 Gapminder Foundation and contributors
2
2
  (function (global, factory) {
3
3
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@vizabi/shared-components'), require('d3'), require('mobx'), require('@deck.gl/core'), require('@deck.gl/layers')) :
4
4
  typeof define === 'function' && define.amd ? define(['exports', '@vizabi/shared-components', 'd3', 'mobx', '@deck.gl/core', '@deck.gl/layers'], factory) :
@@ -1423,8 +1423,10 @@ in float instanceSizes;
1423
1423
  in float instanceAngles;
1424
1424
  in vec2 instancePixelOffsets;
1425
1425
  in float instanceLineWidths;
1426
+ in float instanceGlowWidths;
1426
1427
  in vec4 instanceFillColors;
1427
1428
  in vec4 instanceLineColors;
1429
+ in vec4 instanceGlowColors;
1428
1430
  in vec3 instancePickingColors;
1429
1431
  in float instanceDragged;
1430
1432
 
@@ -1437,9 +1439,11 @@ uniform vec4 padding;
1437
1439
  uniform int sizeUnits;
1438
1440
  uniform float edgeMaxCoord;
1439
1441
 
1442
+ out vec4 vGlowColor;
1440
1443
  out vec4 vFillColor;
1441
1444
  out vec4 vLineColor;
1442
1445
  out float vLineWidth;
1446
+ out float vGlowWidth;
1443
1447
  out vec2 uv;
1444
1448
  out vec2 dimensions;
1445
1449
 
@@ -1457,6 +1461,8 @@ void main(void) {
1457
1461
  geometry.pickingColor = instancePickingColors;
1458
1462
  uv = positions;
1459
1463
  vLineWidth = instanceLineWidths;
1464
+ vGlowWidth = instanceGlowWidths;
1465
+ vec4 glowPadding = padding + vec4(instanceGlowWidths);
1460
1466
 
1461
1467
  // convert size in meters to pixels, then scaled and clamp
1462
1468
 
@@ -1466,9 +1472,9 @@ void main(void) {
1466
1472
  sizeMinPixels, sizeMaxPixels
1467
1473
  );
1468
1474
 
1469
- dimensions = instanceRects.zw * sizePixels + padding.xy + padding.zw;
1475
+ dimensions = instanceRects.zw * sizePixels + glowPadding.xy + glowPadding.zw;
1470
1476
 
1471
- vec2 pixelOffset = (positions * instanceRects.zw + instanceRects.xy) * sizePixels + mix(-padding.xy, padding.zw, positions);
1477
+ vec2 pixelOffset = (positions * instanceRects.zw + instanceRects.xy) * sizePixels + mix(-glowPadding.xy, glowPadding.zw, positions);
1472
1478
  pixelOffset = rotate_by_angle(pixelOffset, instanceAngles);
1473
1479
  pixelOffset += instancePixelOffsets;
1474
1480
  pixelOffset.y *= -1.0;
@@ -1481,6 +1487,7 @@ void main(void) {
1481
1487
  gl_Position.xy += project_pixel_size_to_clipspace(offset.xy);
1482
1488
 
1483
1489
  vec2 clip_dimensions = project_pixel_size_to_clipspace(dimensions);
1490
+ vec2 clip_glow = project_pixel_size_to_clipspace(vec2(vGlowWidth));
1484
1491
 
1485
1492
  //default pos switch on edge
1486
1493
  if (instanceDragged < 0.5) {
@@ -1490,8 +1497,8 @@ void main(void) {
1490
1497
  }
1491
1498
 
1492
1499
  //edge check
1493
- vec2 a = clamp(gl_Position.xy, vec2(-edgeMaxCoord), vec2(edgeMaxCoord) - clip_dimensions);
1494
- vec2 b = clamp(gl_Position.xy, clip_dimensions - edgeMaxCoord, vec2(edgeMaxCoord));
1500
+ vec2 a = clamp(gl_Position.xy, vec2(-edgeMaxCoord) - clip_glow, vec2(edgeMaxCoord) - clip_dimensions + clip_glow);
1501
+ vec2 b = clamp(gl_Position.xy, clip_dimensions - edgeMaxCoord - clip_glow, vec2(edgeMaxCoord) + clip_glow);
1495
1502
  //flip y
1496
1503
  gl_Position.xy = mix(a, b, vec2(positions.x, 1.0 - positions.y));
1497
1504
 
@@ -1507,6 +1514,8 @@ void main(void) {
1507
1514
  DECKGL_FILTER_COLOR(vFillColor, geometry);
1508
1515
  vLineColor = vec4(instanceLineColors.rgb, instanceLineColors.a * opacity);
1509
1516
  DECKGL_FILTER_COLOR(vLineColor, geometry);
1517
+ vGlowColor = vec4(instanceGlowColors.rgb, instanceGlowColors.a * opacity);
1518
+ DECKGL_FILTER_COLOR(vGlowColor, geometry);
1510
1519
  }
1511
1520
  `;
1512
1521
 
@@ -1522,8 +1531,10 @@ uniform float cornerRadius;
1522
1531
  in vec4 vFillColor;
1523
1532
  in vec4 vLineColor;
1524
1533
  in float vLineWidth;
1534
+ in float vGlowWidth;
1525
1535
  in vec2 uv;
1526
1536
  in vec2 dimensions;
1537
+ in vec4 vGlowColor;
1527
1538
 
1528
1539
  out vec4 fragColor;
1529
1540
 
@@ -1539,17 +1550,24 @@ void main()
1539
1550
 
1540
1551
  vec2 pixelPosition = uv * dimensions;
1541
1552
 
1553
+ float fDist = RectSDF(pixelPosition-dimensions/2.0, dimensions/2.0 - vLineWidth/2.0-1.0 - vGlowWidth, cornerRadius);
1554
+ vec4 v4ToColor = (fDist < 0.0) ? vFillColor : vec4(0.0);
1555
+
1542
1556
  if (stroked) {
1543
- float fDist = RectSDF(pixelPosition-dimensions/2.0, dimensions/2.0 - vLineWidth/2.0-1.0, cornerRadius);
1544
1557
  float fBlendAmount = smoothstep(-1.0, 1.0, abs(fDist) - vLineWidth / 2.0);
1545
1558
 
1546
1559
  vec4 v4FromColor = vLineColor;
1547
- vec4 v4ToColor = (fDist < 0.0) ? vFillColor : vec4(0.0);
1548
1560
  fragColor = mix(v4FromColor, v4ToColor, fBlendAmount);
1549
1561
  } else {
1550
- fragColor = vFillColor;
1562
+ fragColor = v4ToColor;
1551
1563
  }
1552
1564
 
1565
+ // Outer glow
1566
+ if (vGlowWidth > 0.0) {
1567
+ float glowFactor = (1.0 - smoothstep(0.3*vGlowWidth, vGlowWidth*1.3, fDist - vLineWidth/2.0));
1568
+ fragColor = fragColor + vec4(vGlowColor.rgb, vGlowColor.a * glowFactor) * (1.0 - fragColor.a);
1569
+ }
1570
+
1553
1571
  DECKGL_FILTER_COLOR(fragColor, geometry);
1554
1572
  }
1555
1573
  `;
@@ -1557,6 +1575,8 @@ void main()
1557
1575
  class LabelBackgroundLayer extends layers._TextBackgroundLayer {
1558
1576
  static defaultProps = {
1559
1577
  getDragged: {type: 'accessor', value: 0.0},
1578
+ getGlowColor: {type: 'accessor', value: [0, 0, 0, 255]},
1579
+ getGlowWidth: {type: 'accessor', value: 0.0},
1560
1580
  };
1561
1581
 
1562
1582
  initializeState() {
@@ -1571,6 +1591,19 @@ void main()
1571
1591
  // return this.parent.props.getDragged(object, info);
1572
1592
  //}
1573
1593
  },
1594
+ instanceGlowColors: {
1595
+ size: 4,
1596
+ transition: true,
1597
+ type: 'unorm8',
1598
+ accessor: 'getGlowColor',
1599
+ defaultValue: [0, 0, 0, 255]
1600
+ },
1601
+ instanceGlowWidths: {
1602
+ size: 1,
1603
+ transition: false,
1604
+ accessor: "getGlowWidth",
1605
+ defaultValue: 0.0
1606
+ },
1574
1607
  });
1575
1608
  }
1576
1609
 
@@ -1817,6 +1850,8 @@ void main(void) {
1817
1850
  getLineSourceFillOffset: {type: 'accessor', value: 0},
1818
1851
  getRadius: {type: 'accessor', value: 0},
1819
1852
  getDragged: {type: 'accessor', value: 0.0},
1853
+ getGlowColor: {type: 'accessor', value: [0, 0, 0, 255]},
1854
+ getGlowWidth: {type: 'accessor', value: 0.0}
1820
1855
  }
1821
1856
 
1822
1857
  getPickingInfo(e) {
@@ -1895,6 +1930,55 @@ void main(void) {
1895
1930
  }
1896
1931
  ),
1897
1932
  //...layers,
1933
+ this.props.glow && new LabelBackgroundLayer(
1934
+ this.getSubLayerProps({
1935
+ id: 'glow',
1936
+ updateTriggers: {
1937
+ //getColor: [activeObject],
1938
+ getDragged: this.props.updateTriggers.getDragged,
1939
+ getPixelOffset: this.props.updateTriggers.getPixelOffset,
1940
+ getPosition: this.props.updateTriggers.getPosition,
1941
+ getSize: this.props.updateTriggers.getSize,
1942
+ getGlowWidth: this.props.updateTriggers.getGlowWidth,
1943
+ }
1944
+ }), {
1945
+ data: this.props.data,
1946
+ getPosition: (d, { index, data }) => {
1947
+ const pos = this.props.getPosition(d, { index, data });
1948
+ return index == (data.length - 1) ? pos : [...pos.slice(0, 2), -10];
1949
+ },
1950
+ getBoundingRect: this.getBoundingRect,
1951
+ getPixelOffset: this.props.getPixelOffset,
1952
+ getSize: this.props.getSize,
1953
+ getFillColor: (_, { index, data }) => {
1954
+ const alpha = index == (data.length - 1) ? 255 : 0;
1955
+ return [255, 255, 255, alpha];
1956
+ },
1957
+ getLineColor: (d, { index, data }) => {
1958
+ const alpha = index == (data.length - 1) ? 255: 0;
1959
+ return [...(typeof this.props.getBorderColor == "function" ? this.props.getBorderColor(d) : this.props.getBorderColor).slice(0,3), alpha];
1960
+ },
1961
+ getLineWidth: (_, { index, data }) => {
1962
+ return index == (data.length - 1) ? 1: 0;
1963
+ },
1964
+ getGlowColor: this.props.getGlowColor,
1965
+ getGlowWidth: (d, { index, data }) => {
1966
+ return index == (data.length - 1) ? this.props.getGlowWidth(d) : 0;
1967
+ },
1968
+ getDragged: this.props.getDragged,
1969
+ padding: this.props.backgroundPadding,
1970
+ edgeMaxCoord: this.props.edgeMaxCoord,
1971
+ cornerRadius: 5,
1972
+ transitions: {
1973
+ getPosition: this.props.transitions?.getPosition,
1974
+ getPixelOffset: this.props.transitions?.getPosition,
1975
+ getSize: this.props.transitions?.getSize,
1976
+ getFillColor: this.props.transitions?.getBackgroundColor,
1977
+ getLineColor: this.props.transitions?.getBorderColor,
1978
+ getLineWidth: this.props.transitions?.getBorderWidth,
1979
+ getGlowColor: this.props.transitions?.getGlowColor,
1980
+ }
1981
+ }),
1898
1982
  ...super.renderLayers(),
1899
1983
  this.state.closeData?.length && new LabelCloseButtonLayer(
1900
1984
  this.getSubLayerProps({
@@ -2156,6 +2240,7 @@ void main(void) {
2156
2240
  this.dragX;
2157
2241
  this.dragY;
2158
2242
  this.redrawUpdateTrigger = 0;
2243
+ this.lastLineRedrawUpdateTrigger = 0;
2159
2244
  this.opacityUpdateTrigger = 0;
2160
2245
  }
2161
2246
 
@@ -2695,7 +2780,7 @@ void main(void) {
2695
2780
  //requestAnimationFrame(() => {
2696
2781
  this.deckBubble.setProps({layers: this.getBubbleLayers(this.__oldData, false, 0, undefined, this.__lastLineTrailData)});
2697
2782
  requestAnimationFrame(() => {
2698
- this.redrawUpdateTrigger++;
2783
+ this.lastLineRedrawUpdateTrigger++;
2699
2784
  this.deckBubble.setProps({layers: this.getBubbleLayers(this.__oldData, true, 0.001, undefined, this.__lastLineTrailData)});
2700
2785
  requestAnimationFrame(() => {
2701
2786
  this.redrawUpdateTrigger++;
@@ -2788,8 +2873,6 @@ void main(void) {
2788
2873
  return true;
2789
2874
  });
2790
2875
 
2791
- this.labelZScale = d3.scaleLinear([0, selectedData.size - 1],[-0.09, -0.05]);
2792
-
2793
2876
  if (newTrailsData.length) {
2794
2877
  newTrailsData.forEach(d => {
2795
2878
  if (!d[TRAIL_KEY]) return;
@@ -2855,8 +2938,16 @@ void main(void) {
2855
2938
  } = this.profileConstants;
2856
2939
 
2857
2940
  //transfer min max radius to size dialog via root ui observable (probably a cleaner way is possible)
2858
- this.root.ui.minMaxRadius = {min: minRadiusPx, max: maxRadiusPx};
2859
-
2941
+ if (this.root.ui.minMaxRadius) {
2942
+ this.root.ui.minMaxRadius.min = minRadiusPx;
2943
+ this.root.ui.minMaxRadius.max = maxRadiusPx;
2944
+ } else {
2945
+ this.root.ui.minMaxRadius = {
2946
+ min: minRadiusPx,
2947
+ max: maxRadiusPx
2948
+ };
2949
+ }
2950
+
2860
2951
  const extent = this.MDL.size.scale.extent || [0, 1];
2861
2952
 
2862
2953
  let minArea = sharedComponents.LegacyUtils.radiusToArea(Math.max(maxRadiusPx * extent[0], minRadiusPx));
@@ -2888,6 +2979,16 @@ void main(void) {
2888
2979
  const activeObject = this.__highlightedMarkers.size == 1 ? Object.assign({}, this.model.dataMap.get(this.__highlightedMarkers.keys().next().value)) : null;
2889
2980
  this.activeObject = activeObject?.[REQUIRED_KEY] ? null : activeObject;
2890
2981
  this.activeObjectData = this.activeObject ? [this.activeObject] : [];
2982
+ this.labelGlow = false;
2983
+ if (this.activeObject && this.__someSelected) {
2984
+ const index = this.__selectedKeys.indexOf(this.activeObject[TRAIL_KEY] || this.activeObject[KEY]);
2985
+ if (index > -1) {
2986
+ this.__selectedKeys.push(this.__selectedKeys.splice(index, 1)[0]);
2987
+ const data = this.__labelData.splice(index, 1);
2988
+ this.__labelData = [...this.__labelData, ...data];
2989
+ this.labelGlow = true;
2990
+ }
2991
+ }
2891
2992
  this.opacityUpdateTrigger++;
2892
2993
  this.deckBubble.setProps({layers: this.getBubbleLayers(undefined, false)});
2893
2994
  }
@@ -2899,6 +3000,7 @@ void main(void) {
2899
3000
  this.__selectedMarkers = new Map(selectedFilter.markers);
2900
3001
  this.__selectedKeys = [...this.__selectedMarkers.keys()];
2901
3002
 
3003
+ this.labelZScale = d3.scaleLinear([0, this.__selectedKeys.length - 1],[-0.09, -0.05]);
2902
3004
 
2903
3005
  Object.keys(this.labelOffset).forEach(key => {
2904
3006
  if (!this.__selectedMarkers.has(key)) delete this.labelOffset[key];
@@ -3337,6 +3439,19 @@ void main(void) {
3337
3439
  const key = d[TRAIL_KEY] || d[KEY];
3338
3440
  return this.labelDragged[key];
3339
3441
  },
3442
+ getGlowWidth: (d) => {
3443
+ if (!d) return 0;
3444
+ return this.activeObject && ((d[TRAIL_KEY] || d[KEY]) === (this.activeObject[TRAIL_KEY ] || this.activeObject[KEY])) ? 5 : 0;
3445
+ },
3446
+ getGlowColor: (d, { target }) => {
3447
+ if (!d) return;
3448
+ const c = d3.color(this.__getColor(d[TRAIL_KEY] || d[KEY], d.color)).formatRgb().slice(4, -1).split(",").map(v=>+v);
3449
+ target[0] = c[0];
3450
+ target[1] = c[1];
3451
+ target[2] = c[2];
3452
+ target[3] = 200;
3453
+ return target;
3454
+ },
3340
3455
  onLabelDragStart: ({ object:d, x, y, coordinate, sourceLayer, viewport }, evt) => {
3341
3456
  console.log("onLabelDragStart", d, x, y, coordinate, viewport, sourceLayer);
3342
3457
  if (!d) return;
@@ -3653,7 +3768,7 @@ void main(void) {
3653
3768
  getWidth: this.props.getLastTrailLineWidth,
3654
3769
  updateTriggers: {
3655
3770
  getColor: [this.activeObject, this.opacityUpdateTrigger],
3656
- getTargetPosition: [this.redrawUpdateTrigger]
3771
+ getTargetPosition: [this.redrawUpdateTrigger, this.lastLineRedrawUpdateTrigger]
3657
3772
  },
3658
3773
  transitions: t ? {
3659
3774
  getTargetPosition: {
@@ -3863,6 +3978,9 @@ void main(void) {
3863
3978
  //smoothing: 0.1
3864
3979
  } : { sdf: false },
3865
3980
  //fontWeight: '500',
3981
+ glow: this.labelGlow,
3982
+ getGlowColor: this.props.getGlowColor,
3983
+ getGlowWidth: this.props.getGlowWidth,
3866
3984
  getPosition: this.props.getLabelPositionZ,
3867
3985
  getPixelOffset: this.props.getPixelOffset,
3868
3986
  getText: this.props.getLabelText,
@@ -3893,7 +4011,8 @@ void main(void) {
3893
4011
  updateTriggers: {
3894
4012
  getPixelOffset: [this.dragX, this.dragY, this.redrawUpdateTrigger],
3895
4013
  getDragged: [this.dragX0, this.dragY0],
3896
- getPosition: [this.redrawUpdateTrigger]
4014
+ getPosition: [this.redrawUpdateTrigger],
4015
+ getGlowWidth: [this.activeObject],
3897
4016
  },
3898
4017
  transitions: t ? {
3899
4018
  getPosition: {
@@ -4248,7 +4367,7 @@ void main(void) {
4248
4367
  },
4249
4368
  };
4250
4369
 
4251
- BubbleChart.versionInfo = { version: "5.5.2", build: 1765875954936, package: {"homepage":"https://github.com/vizabi/bubblechart#readme","name":"@vizabi/bubblechart","description":"Vizabi bubble chart"}, sharedComponents: sharedComponents.versionInfo};
4370
+ BubbleChart.versionInfo = { version: "5.5.4", build: 1773941847513, package: {"homepage":"https://github.com/vizabi/bubblechart#readme","name":"@vizabi/bubblechart","description":"Vizabi bubble chart"}, sharedComponents: sharedComponents.versionInfo};
4252
4371
 
4253
4372
  exports.Base = BubbleChart;
4254
4373