@d3plus/core 3.0.0-alpha.1 → 3.0.0-alpha.3

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,5 +1,5 @@
1
1
  /*
2
- @d3plus/core v3.0.0-alpha.1
2
+ @d3plus/core v3.0.0-alpha.3
3
3
  Data visualization made easy. A javascript library that extends the popular D3.js to enable fast and beautiful visualizations.
4
4
  Copyright (c) 2025 D3plus - https://d3plus.org
5
5
  @license MIT
@@ -574,6 +574,21 @@
574
574
  }
575
575
  }
576
576
 
577
+ /**
578
+ * @param {*} nodeList
579
+ * @param {*} classNames
580
+ * @private
581
+ */ function findLastIndexWithClass(nodeList, classNames) {
582
+ for(let x = 0; x < classNames.length; x++){
583
+ const className = classNames[x];
584
+ for(let i = nodeList.length - 1; i >= 0; i--){
585
+ if (nodeList[i].classList.contains(className)) {
586
+ return i; // Return the index if found
587
+ }
588
+ }
589
+ }
590
+ return 0; // Return -1 if no element is found with the class
591
+ }
577
592
  class Shape extends BaseClass {
578
593
  /**
579
594
  @memberof Shape
@@ -769,16 +784,28 @@
769
784
  this._group.selectAll(`g.d3plus-${this._name}-shape, g.d3plus-${this._name}-image, g.d3plus-${this._name}-text, g.d3plus-${this._name}-hover`).selectAll(".d3plus-Shape, .d3plus-Image, .d3plus-textBox").each(function(d, i) {
770
785
  if (!d) d = {};
771
786
  if (!d.parentNode) d.parentNode = this.parentNode;
787
+ if (!d.dataIndex) d.dataIndex = i;
788
+ const dataIndex = d.dataIndex;
772
789
  const parent = d.parentNode;
773
- if (d3Selection.select(this).classed("d3plus-textBox")) d = d.data;
790
+ const d3plusType = d3Selection.select(this).classed("d3plus-textBox") ? "textBox" : d3Selection.select(this).classed("d3plus-Image") ? "Image" : "Shape";
791
+ if (d3plusType === "textBox") d = d.data;
774
792
  if (d.__d3plusShape__ || d.__d3plus__) {
775
793
  while(d && (d.__d3plusShape__ || d.__d3plus__)){
776
794
  i = d.i;
777
795
  d = d.data;
778
796
  }
779
797
  } else i = that._data.indexOf(d);
780
- const group = !that._hover || typeof that._hover !== "function" || !that._hover(d, i) ? parent : that._hoverGroup.node();
781
- if (group !== this.parentNode) group.appendChild(this);
798
+ const notHovering = !that._hover || typeof that._hover !== "function" || !that._hover(d, i);
799
+ const group = notHovering ? parent : that._hoverGroup.node();
800
+ if (group !== this.parentNode) {
801
+ const offset = d3plusType === "textBox" ? findLastIndexWithClass(group.childNodes, [
802
+ "d3plus-Image",
803
+ "d3plus-Shape"
804
+ ]) : d3plusType === "Image" ? findLastIndexWithClass(group.childNodes, [
805
+ "d3plus-Shape"
806
+ ]) : 0;
807
+ group.insertBefore(this, group.childNodes[offset + dataIndex]);
808
+ }
782
809
  if (this.className.baseVal.includes("d3plus-Shape")) {
783
810
  if (parent === group) d3Selection.select(this).call(that._applyStyle.bind(that));
784
811
  else d3Selection.select(this).call(that._updateStyle.bind(that, d3Selection.select(this), that._hoverStyle));
@@ -6128,7 +6155,7 @@
6128
6155
  /**
6129
6156
  * Creates a reference element for popper.
6130
6157
  * @param {Number[]} position
6131
- * @prrivate
6158
+ * @private
6132
6159
  */ function generateReference(position = [
6133
6160
  0,
6134
6161
  0
@@ -7426,11 +7453,13 @@
7426
7453
 
7427
7454
  /**
7428
7455
  * Default padding logic that will return false if the screen is less than 600 pixels wide.
7456
+ * @private
7429
7457
  */ function defaultPadding() {
7430
7458
  return typeof window !== "undefined" ? window.innerWidth > 600 : true;
7431
7459
  }
7432
7460
  /**
7433
7461
  * Turns an array of values into a list string.
7462
+ * @private
7434
7463
  */ function listify(n) {
7435
7464
  return n.reduce((str, item, i)=>{
7436
7465
  if (!i) str += item;
@@ -7628,6 +7657,7 @@
7628
7657
  /**
7629
7658
  * Applies the threshold algorithm according to the type of chart used.
7630
7659
  * @param {Array} data The data to process.
7660
+ * @private
7631
7661
  */ _thresholdFunction(data) {
7632
7662
  return data;
7633
7663
  }
@@ -9595,15 +9625,15 @@
9595
9625
  const defaultY2Config = y2Exists ? {
9596
9626
  data: y2Data
9597
9627
  } : defaultConfig;
9598
- const showX = this._discrete === "x" && this._width > this._discreteCutoff || this._width > this._xCutoff;
9599
- const showY = this._discrete === "y" && this._height > this._discreteCutoff || this._height > this._yCutoff;
9628
+ const showX = this._discrete === "x" ? this._width > this._discreteCutoff && this._width > this._xCutoff : this._width > this._xCutoff;
9629
+ const showY = this._discrete === "y" ? this._height > this._discreteCutoff && this._height > this._yCutoff : this._height > this._yCutoff;
9600
9630
  const yC = {
9601
9631
  data: yData,
9602
9632
  locale: this._locale,
9603
9633
  rounding: this._yDomain ? "none" : "outside",
9604
9634
  scalePadding: y.padding ? y.padding() : 0
9605
9635
  };
9606
- if (!showX) {
9636
+ if (!showX && showY) {
9607
9637
  yC.barConfig = {
9608
9638
  stroke: "transparent"
9609
9639
  };
@@ -9673,7 +9703,7 @@
9673
9703
  rounding: this._xDomain ? "none" : "outside",
9674
9704
  scalePadding: x.padding ? x.padding() : 0
9675
9705
  };
9676
- if (!showY) {
9706
+ if (!showY && showX) {
9677
9707
  xC.barConfig = {
9678
9708
  stroke: "transparent"
9679
9709
  };
@@ -9693,7 +9723,7 @@
9693
9723
  labelConfig: {
9694
9724
  padding: 0,
9695
9725
  rotate: 0,
9696
- textAnchor: (d)=>d.id === xTicks[0] ? "start" : "end"
9726
+ textAnchor: (d)=>xTicks && d.id === xTicks[0] ? "start" : "end"
9697
9727
  },
9698
9728
  labelRotation: false
9699
9729
  };
@@ -9866,14 +9896,15 @@
9866
9896
  });
9867
9897
  const transform = `translate(${this._margin.left}, ${this._margin.top + x2Height + topOffset})`;
9868
9898
  const x2Transform = `translate(${this._margin.left}, ${this._margin.top + topOffset})`;
9869
- const xGroup = showX && dom.elem("g.d3plus-plot-x-axis", {
9899
+ const xGroup = dom.elem("g.d3plus-plot-x-axis", {
9870
9900
  parent,
9871
9901
  transition,
9872
9902
  enter: {
9873
9903
  transform
9874
9904
  },
9875
9905
  update: {
9876
- transform
9906
+ transform,
9907
+ opacity: showX ? 1 : 0
9877
9908
  }
9878
9909
  });
9879
9910
  const x2Group = x2Exists && dom.elem("g.d3plus-plot-x2-axis", {
@@ -9888,14 +9919,15 @@
9888
9919
  });
9889
9920
  const xTrans = xOffsetLeft > yWidth ? xOffsetLeft - yWidth : 0;
9890
9921
  const yTransform = `translate(${this._margin.left + xTrans}, ${this._margin.top + topOffset})`;
9891
- const yGroup = showY && dom.elem("g.d3plus-plot-y-axis", {
9922
+ const yGroup = dom.elem("g.d3plus-plot-y-axis", {
9892
9923
  parent,
9893
9924
  transition,
9894
9925
  enter: {
9895
9926
  transform: yTransform
9896
9927
  },
9897
9928
  update: {
9898
- transform: yTransform
9929
+ transform: yTransform,
9930
+ opacity: showY ? 1 : 0
9899
9931
  }
9900
9932
  });
9901
9933
  const y2Transform = `translate(-${this._margin.right}, ${this._margin.top + topOffset})`;
@@ -9909,7 +9941,7 @@
9909
9941
  transform: y2Transform
9910
9942
  }
9911
9943
  });
9912
- this._xAxis.domain(xDomain).height(height - (x2Height + topOffset + verticalMargin)).maxSize(height / 2).range(xRange).select(showX ? xGroup.node() : undefined).ticks(xTicks).width(width).config(xC).config(this._xConfig).scale(xConfigScale).render();
9944
+ this._xAxis.domain(xDomain).height(height - (x2Height + topOffset + verticalMargin)).maxSize(height / 2).range(xRange).select(xGroup.node()).ticks(xTicks).width(width).config(xC).config(this._xConfig).scale(xConfigScale).render();
9913
9945
  if (x2Exists) {
9914
9946
  this._x2Axis.domain(x2Domain).height(height - (xHeight + topOffset + verticalMargin)).range(xRange).select(x2Group.node()).ticks(x2Ticks).width(width).config(xC).config(defaultX2Config).config(this._x2Config).scale(x2ConfigScale).render();
9915
9947
  }
@@ -9926,7 +9958,7 @@
9926
9958
  this._xAxis.outerBounds().y + x2Height,
9927
9959
  height - (xHeight + topOffset + verticalMargin)
9928
9960
  ];
9929
- this._yAxis.domain(yDomain).height(height).maxSize(width / 2).range(yRange).select(showY ? yGroup.node() : undefined).ticks(yTicks).width(xRange[xRange.length - 1]).config(yC).config(this._yConfig).scale(yConfigScale).render();
9961
+ this._yAxis.domain(yDomain).height(height).maxSize(width / 2).range(yRange).select(yGroup.node()).ticks(yTicks).width(xRange[xRange.length - 1]).config(yC).config(this._yConfig).scale(yConfigScale).render();
9930
9962
  if (y2Exists) {
9931
9963
  this._y2Axis.config(yC).domain(y2Exists ? y2Domain : yDomain).gridSize(0).height(height).range(yRange).select(y2Group.node()).width(width - d3Array.max([
9932
9964
  0,
@@ -9972,6 +10004,8 @@
9972
10004
  return this._yAxis._getPosition.bind(this._yAxis)(d) - x2Height;
9973
10005
  }
9974
10006
  };
10007
+ let yOffset = this._xAxis.barConfig()["stroke-width"];
10008
+ if (yOffset) yOffset /= 2;
9975
10009
  new Rect().data([
9976
10010
  {}
9977
10011
  ]).select(rectGroup.node()).x(xRange[0] + (xRange[1] - xRange[0]) / 2).width(xRange[1] - xRange[0]).y(this._margin.top + topOffset + yRange[0] + (yRange[1] - yRange[0]) / 2).height(yRange[1] - yRange[0]).config(this._backgroundConfig).render();
@@ -10051,8 +10085,6 @@
10051
10085
  });
10052
10086
  this._previousAnnotations[layer] = annotationShapes;
10053
10087
  });
10054
- let yOffset = this._xAxis.barConfig()["stroke-width"];
10055
- if (yOffset) yOffset /= 2;
10056
10088
  const discrete = this._discrete || "x";
10057
10089
  const shapeConfig = {
10058
10090
  discrete: this._discrete,
@@ -10291,14 +10323,6 @@
10291
10323
  */ confidenceConfig(_) {
10292
10324
  return arguments.length ? (this._confidenceConfig = dom.assign(this._confidenceConfig, _), this) : this._confidenceConfig;
10293
10325
  }
10294
- /**
10295
- @memberof Plot
10296
- @desc Sets the discrete axis to the specified string. If *value* is not specified, returns the current discrete axis.
10297
- @param {String} *value*
10298
- @chainable
10299
- */ discrete(_) {
10300
- return arguments.length ? (this._discrete = _, this) : this._discrete;
10301
- }
10302
10326
  /**
10303
10327
  @memberof Plot
10304
10328
  @desc When the width or height of the chart is less than or equal to this pixel value, the discrete axis will not be shown. This helps produce slick sparklines. Set this value to `0` to disable the behavior entirely.
@@ -10425,8 +10449,8 @@
10425
10449
  }
10426
10450
  /**
10427
10451
  @memberof Plot
10428
- @desc Sets the x accessor to the specified function or number. If *value* is not specified, returns the current x accessor.
10429
- @param {Function|Number} *value*
10452
+ @desc Sets the x accessor to the specified accessor Function or String representing which key in the data to reference. If *value* is not specified, returns the current x accessor.
10453
+ @param {Function|String} *value*
10430
10454
  @chainable
10431
10455
  */ x(_) {
10432
10456
  if (arguments.length) {
@@ -10440,8 +10464,8 @@
10440
10464
  }
10441
10465
  /**
10442
10466
  @memberof Plot
10443
- @desc Sets the x2 accessor to the specified function or number. If *value* is not specified, returns the current x2 accessor.
10444
- @param {Function|Number} *value*
10467
+ @desc Sets the x2 accessor to the specified accessor Function or String representing which key in the data to reference. If *value* is not specified, returns the current x2 accessor.
10468
+ @param {Function|String} *value*
10445
10469
  @chainable
10446
10470
  */ x2(_) {
10447
10471
  if (arguments.length) {
@@ -10511,8 +10535,8 @@
10511
10535
  }
10512
10536
  /**
10513
10537
  @memberof Plot
10514
- @desc Sets the y accessor to the specified function or number. If *value* is not specified, returns the current y accessor.
10515
- @param {Function|Number} *value*
10538
+ @desc Sets the y accessor to the specified accessor Function or String representing which key in the data to reference. If *value* is not specified, returns the current y accessor.
10539
+ @param {Function|String} *value*
10516
10540
  @chainable
10517
10541
  */ y(_) {
10518
10542
  if (arguments.length) {
@@ -10526,8 +10550,8 @@
10526
10550
  }
10527
10551
  /**
10528
10552
  @memberof Plot
10529
- @desc Sets the y2 accessor to the specified function or number. If *value* is not specified, returns the current y2 accessor.
10530
- @param {Function|Number} *value*
10553
+ @desc Sets the y2 accessor to the specified accessor Function or String representing which key in the data to reference. If *value* is not specified, returns the current y2 accessor.
10554
+ @param {Function|String} *value*
10531
10555
  @chainable
10532
10556
  */ y2(_) {
10533
10557
  if (arguments.length) {
@@ -10788,6 +10812,7 @@
10788
10812
  });
10789
10813
  this._x = accessor("x");
10790
10814
  this._xAxis = new AxisBottom().align("end");
10815
+ this._xKey = "x";
10791
10816
  this._xTest = new AxisBottom().align("end").gridSize(0);
10792
10817
  this._xConfig = {
10793
10818
  gridConfig: {
@@ -10808,6 +10833,7 @@
10808
10833
  };
10809
10834
  this._y = accessor("y");
10810
10835
  this._yAxis = new AxisLeft().align("start");
10836
+ this._yKey = "y";
10811
10837
  this._yTest = new AxisLeft().align("start").gridSize(0);
10812
10838
  this._yConfig = {
10813
10839
  gridConfig: {
@@ -10837,7 +10863,6 @@
10837
10863
  this._baseline = 0;
10838
10864
  this._discrete = "x";
10839
10865
  this._shape = constant("Area");
10840
- this.x("x");
10841
10866
  }
10842
10867
  }
10843
10868
 
@@ -10858,7 +10883,6 @@
10858
10883
  return defaultLegend.bind(this)(config, arr);
10859
10884
  };
10860
10885
  this._shape = constant("Bar");
10861
- this.x("x");
10862
10886
  }
10863
10887
  }
10864
10888
 
@@ -10871,7 +10895,6 @@
10871
10895
  super();
10872
10896
  this._discrete = "x";
10873
10897
  this._shape = constant("Box");
10874
- this.x("x");
10875
10898
  this._tooltipConfig = dom.assign(this._tooltipConfig, {
10876
10899
  title: (d, i)=>{
10877
10900
  if (!d) return "";
@@ -10896,7 +10919,6 @@
10896
10919
  super();
10897
10920
  this._discrete = "x";
10898
10921
  this._shape = constant("Line");
10899
- this.x("x");
10900
10922
  this.y2((d)=>this._y(d));
10901
10923
  this.yConfig({
10902
10924
  tickFormat: (val)=>{
@@ -11620,7 +11642,6 @@
11620
11642
  super();
11621
11643
  this._discrete = "x";
11622
11644
  this._shape = constant("Line");
11623
- this.x("x");
11624
11645
  }
11625
11646
  }
11626
11647
 
@@ -12465,13 +12486,13 @@
12465
12486
  ])(d3Hierarchy.hierarchy({
12466
12487
  key: nestedData.key,
12467
12488
  values: nestedData
12468
- }, (d)=>d.values).sum(this._sum).sort(this._sort)).descendants();
12469
- packData.forEach((d, i)=>{
12489
+ }, (d)=>d.values).sum(this._sum).sort(this._sort)).descendants().filter((d, i)=>{
12470
12490
  d.__d3plus__ = true;
12471
12491
  d.i = i;
12472
- d.id = d.parent ? d.parent.data.key : null;
12492
+ d.id = d.parent ? d.parent.data.key : "root";
12473
12493
  d.data.__d3plusOpacity__ = d.height ? this._packOpacity(d.data, i) : 1;
12474
12494
  d.data.__d3plusTooltip__ = !d.height ? true : false;
12495
+ return !d.children || d.children.length > 1;
12475
12496
  });
12476
12497
  this._shapes.push(new Circle().data(packData).select(dom.elem("g.d3plus-Pack", {
12477
12498
  parent: this._select,
@@ -12561,9 +12582,10 @@
12561
12582
  const defaultMouseMoveShape = this._on["mousemove.shape"];
12562
12583
  this._on["mousemove.shape"] = (d, i, x, event)=>{
12563
12584
  if (d.__d3plusTooltip__) defaultMouseMoveShape(d, i, x, event);
12564
- this.hover((h)=>recursionCircles(d, [
12565
- d
12566
- ]).includes(h));
12585
+ const hoverData = recursionCircles(d, [
12586
+ d
12587
+ ]);
12588
+ this.hover((h)=>hoverData.includes(h));
12567
12589
  };
12568
12590
  this._pack = d3Hierarchy.pack();
12569
12591
  this._packOpacity = constant(0.25);