@axdspub/axiom-charts 0.0.18 → 0.0.20

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.
@@ -757,10 +757,225 @@ class AxiomScatter extends AxiomPlotRoot {
757
757
  }
758
758
  }
759
759
 
760
+ class AxiomBar extends AxiomPlotRoot {
761
+ constructor(props) {
762
+ super(props);
763
+ this.legendHeight = 12;
764
+ this.legendPaddingTop = 8;
765
+ const chart = this.chart;
766
+ const chartElements = chart.getChartElements();
767
+ if ((chartElements === null || chartElements === void 0 ? void 0 : chartElements.svg) !== undefined) {
768
+ chartElements.svg.style('z-index', 20);
769
+ // TODO find better way ^. Doing this so that svg can get events.
770
+ }
771
+ }
772
+ draw() {
773
+ var _a, _b, _c, _d, _e;
774
+ return __awaiter(this, void 0, void 0, function* () {
775
+ const dataResponse = yield this.getData();
776
+ const parsedData = (_a = dataResponse === null || dataResponse === void 0 ? void 0 : dataResponse.parsed) === null || _a === void 0 ? void 0 : _a.data;
777
+ if (parsedData === undefined)
778
+ return;
779
+ const xAccessor = this.getAccessorAtAxis('x');
780
+ const yAccessor = (_b = dataResponse.parsed) === null || _b === void 0 ? void 0 : _b.accessors.y;
781
+ if (xAccessor === undefined || yAccessor === undefined)
782
+ return;
783
+ const y2Accessor = (_c = dataResponse.parsed) === null || _c === void 0 ? void 0 : _c.accessors.y2;
784
+ const yGroups = this.dimensions;
785
+ const yKey = yGroups.y.property;
786
+ const yLabel = yGroups.y.label;
787
+ const y2Key = this.dimensions.y2.property;
788
+ const y2Label = this.dimensions.y2.label;
789
+ const chart = this.chart;
790
+ const chartElements = chart.getChartElements();
791
+ if (chartElements === undefined || chartElements.svg === null || yKey === undefined || yLabel === undefined)
792
+ return undefined;
793
+ if (chartElements.svg.select('g') !== undefined)
794
+ chartElements.svg.select('g').remove();
795
+ let { width, height } = chart.settings;
796
+ width = Number(width);
797
+ height = Number(height);
798
+ const oneOrZero = y2Key === undefined ? 0 : 1; // Used to add in space for y2 if exists.
799
+ const xAxisHeight = 48; // HOW TO GET DYNAMICALLY?
800
+ const yAxisWidth = 36; // HOW TO GET DYNAMICALLY?
801
+ const y2AxisWidth = yAxisWidth * oneOrZero;
802
+ const chartPaddingTop = 4;
803
+ const yLabelWidth = 24;
804
+ const y1TotalWidth = yAxisWidth + yLabelWidth;
805
+ const y2LabelWidth = yLabelWidth * oneOrZero;
806
+ const y2TotalWidth = y2AxisWidth * oneOrZero + y2LabelWidth;
807
+ const plotHeight = height - xAxisHeight - this.legendHeight - this.legendPaddingTop - chartPaddingTop;
808
+ const plotWidth = width - yAxisWidth - yLabelWidth - y2TotalWidth;
809
+ const plotXStart = width - plotWidth - y2TotalWidth;
810
+ const plotXEnd = width - y2TotalWidth;
811
+ const groups = parsedData.map(d => xAccessor(d));
812
+ const subgroups = [yKey];
813
+ if (y2Key !== undefined && y2Accessor !== undefined)
814
+ subgroups.push(y2Key);
815
+ // Colors
816
+ const fillColors = (_e = (_d = this.style) === null || _d === void 0 ? void 0 : _d.colors) !== null && _e !== void 0 ? _e : d3.schemeTableau10;
817
+ const color = d3.scaleOrdinal(fillColors).domain(subgroups);
818
+ // TODO use real data
819
+ // @ts-expect-error just for testing
820
+ this.emitDataLoad(parsedData, color);
821
+ const svg = chartElements.svg;
822
+ const g = svg.insert('g');
823
+ const x = this.getXScale(plotXStart, plotXEnd, groups);
824
+ const y = this.getYScale(plotHeight, chartPaddingTop, parsedData, yAccessor);
825
+ const y2 = this.getY2Scale(plotHeight, chartPaddingTop, parsedData, y2Accessor);
826
+ const subgroupScales = this.getSubgroupScales(yKey, y, y2Key, y2);
827
+ const xSubgroup = d3.scaleBand()
828
+ .domain(subgroups)
829
+ .range([0, x.bandwidth()])
830
+ .padding(0.05);
831
+ const onMouseEnterOrMove = (event, data) => {
832
+ if (this.chart.onScrub === undefined)
833
+ return;
834
+ const scrubPositions = {
835
+ [this.id]: {
836
+ xPosition: event.offsetX,
837
+ xValue: null,
838
+ yPosition: event.offsetY,
839
+ yValue: data.value
840
+ }
841
+ };
842
+ this.chart.onScrub(scrubPositions);
843
+ };
844
+ const onMouseLeave = () => {
845
+ if (this.chart.onScrubEnd === undefined)
846
+ return;
847
+ this.chart.onScrubEnd();
848
+ };
849
+ // Make Bar Groups
850
+ g.append('g')
851
+ .attr('width', plotWidth)
852
+ .attr('height', plotHeight)
853
+ .selectAll('g')
854
+ .data(parsedData)
855
+ .enter()
856
+ .append('g')
857
+ .attr('transform', d => `translate(${Number(x(xAccessor(d)))}, 0)`)
858
+ .selectAll('rect')
859
+ .data(d => Object.keys(this.dimensions).filter(key => key !== 'x').map((key) => {
860
+ var _a, _b, _c;
861
+ return {
862
+ label: (_a = this.dimensions[key].label) !== null && _a !== void 0 ? _a : key,
863
+ key: (_b = this.dimensions[key].property) !== null && _b !== void 0 ? _b : '',
864
+ value: d[(_c = this.dimensions[key].property) !== null && _c !== void 0 ? _c : '']
865
+ };
866
+ }))
867
+ .enter()
868
+ .append('rect')
869
+ .attr('x', d => Number(xSubgroup(d.key)))
870
+ .attr('y', d => Number(subgroupScales[d.key](d.value)))
871
+ .attr('width', xSubgroup.bandwidth())
872
+ .attr('height', d => plotHeight - Number(subgroupScales[d.key](d.value)))
873
+ .attr('fill', d => color(d.key))
874
+ .classed('bar', true)
875
+ .on('mouseover', onMouseEnterOrMove)
876
+ .on('mousemove', onMouseEnterOrMove)
877
+ .on('mouseleave', onMouseLeave);
878
+ // X Axis
879
+ const xAxis = g.append('g')
880
+ .attr('transform', `translate(0, ${plotHeight})`)
881
+ .call(d3.axisBottom(x));
882
+ // X Labels
883
+ xAxis.selectAll('text')
884
+ .attr('text-anchor', 'end')
885
+ .attr('transform', 'rotate(-45)translate(-10, 0)');
886
+ // Y Axis
887
+ g.append('g')
888
+ .call(d3.axisLeft(y))
889
+ .attr('transform', `translate(${y1TotalWidth}, 0)`);
890
+ if (y2 !== undefined) {
891
+ // Y2 Axis
892
+ g.append('g')
893
+ .call(d3.axisRight(y2))
894
+ .attr('transform', `translate(${width - y2TotalWidth}, 0)`);
895
+ }
896
+ // Y Label
897
+ g.append('text')
898
+ .attr('text-anchor', 'middle')
899
+ .attr('transform', 'rotate(-90)')
900
+ .attr('x', -1 * plotHeight / 2)
901
+ .attr('y', yLabelWidth)
902
+ .attr('font-weight', 800)
903
+ .text(yLabel);
904
+ if (y2Label !== undefined) {
905
+ // Y2 Label
906
+ g.append('text')
907
+ .attr('text-anchor', 'middle')
908
+ .attr('transform', 'rotate(90)')
909
+ .attr('x', 1 * plotHeight / 2)
910
+ .attr('y', -1 * (width - y2LabelWidth))
911
+ .attr('font-weight', 800)
912
+ .text(y2Label);
913
+ }
914
+ });
915
+ }
916
+ getXScale(plotXStart, plotXEnd, groups) {
917
+ return d3.scaleBand()
918
+ .domain(groups)
919
+ .range([plotXStart, plotXEnd])
920
+ .padding(0.25);
921
+ }
922
+ getYScale(plotHeight, chartPaddingTop, data, yAccessor) {
923
+ return d3.scaleLinear()
924
+ .domain([
925
+ 0,
926
+ Number(d3.max(data, d => yAccessor(d)))
927
+ ])
928
+ .range([plotHeight, chartPaddingTop]);
929
+ }
930
+ getY2Scale(plotHeight, chartPaddingTop, data, y2Accessor) {
931
+ if (y2Accessor === undefined)
932
+ return undefined;
933
+ return this.getYScale(plotHeight, chartPaddingTop, data, y2Accessor);
934
+ }
935
+ /**
936
+ *
937
+ * Returns a map from Y key to Y scale. E.g.
938
+ * {
939
+ * "frequency": Y,
940
+ * "proportion": Y2
941
+ * }
942
+ */
943
+ getSubgroupScales(yKey, y, y2Key, y2) {
944
+ const subgroupScales = {
945
+ [yKey]: y
946
+ };
947
+ if (y2Key !== undefined && y2 !== undefined) {
948
+ subgroupScales[y2Key] = y2;
949
+ }
950
+ return subgroupScales;
951
+ }
952
+ getScrubPosition(mouseX) { return undefined; }
953
+ drawScrubbing(mouseX) { }
954
+ emitDataLoad(data, color) {
955
+ if (this.onDataLoad !== undefined) {
956
+ const legend = Object.keys(this.dimensions).filter(key => key !== 'x').map(key => {
957
+ var _a, _b;
958
+ return ({
959
+ key,
960
+ label: (_a = this.dimensions[key].label) !== null && _a !== void 0 ? _a : key,
961
+ color: color((_b = this.dimensions[key].property) !== null && _b !== void 0 ? _b : '')
962
+ });
963
+ });
964
+ const barPlotLoadEvent = {
965
+ plotId: this.id,
966
+ data,
967
+ properties: { legend }
968
+ };
969
+ this.onDataLoad(barPlotLoadEvent);
970
+ }
971
+ }
972
+ }
973
+
760
974
  const chartTypes = {
761
975
  Line: AxiomLine,
762
976
  Area: AxiomArea,
763
- Scatter: AxiomScatter
977
+ Scatter: AxiomScatter,
978
+ Bar: AxiomBar
764
979
  };
765
980
 
766
981
  function styleInject(css, ref) {
@@ -1029,6 +1244,9 @@ class AxiomChart extends ChartRoot {
1029
1244
  else if (plot.type === EPlotTypes.scatter) {
1030
1245
  return new chartTypes.Scatter(props);
1031
1246
  }
1247
+ else if (plot.type === EPlotTypes.bar) {
1248
+ return new chartTypes.Bar(props);
1249
+ }
1032
1250
  return new PlotRoot(props);
1033
1251
  }
1034
1252
  clearCanvas() {
@@ -1762,14 +1980,20 @@ function calculateWindRoseProportions(data) {
1762
1980
 
1763
1981
  /* eslint-disable @typescript-eslint/ban-ts-comment */
1764
1982
  class AxiomWindrose extends AxiomPlotRoot {
1765
- constructor() {
1766
- super(...arguments);
1983
+ constructor(props) {
1984
+ super(props);
1767
1985
  this.Y_DOMAIN_TYPE = 'frequency';
1768
1986
  this.raw = {
1769
1987
  direction: [],
1770
1988
  speed: []
1771
1989
  };
1772
1990
  this.columns = DEFAULT_COLUMNS;
1991
+ const chart = this.chart;
1992
+ const chartElements = chart.getChartElements();
1993
+ if ((chartElements === null || chartElements === void 0 ? void 0 : chartElements.svg) !== undefined) {
1994
+ chartElements.svg.style('z-index', 20);
1995
+ // TODO find better way ^. Doing this so that svg can get events.
1996
+ }
1773
1997
  }
1774
1998
  initializeData() {
1775
1999
  if (this.Y_DOMAIN_TYPE === 'frequency') {
@@ -1780,7 +2004,7 @@ class AxiomWindrose extends AxiomPlotRoot {
1780
2004
  }
1781
2005
  }
1782
2006
  draw() {
1783
- var _a, _b, _c;
2007
+ var _a, _b, _c, _d, _e;
1784
2008
  return __awaiter(this, void 0, void 0, function* () {
1785
2009
  const chart = this.chart;
1786
2010
  const chartElements = chart.getChartElements();
@@ -1822,25 +2046,16 @@ class AxiomWindrose extends AxiomPlotRoot {
1822
2046
  const y = d3
1823
2047
  .scaleLinear() // you can try scaleRadial but it scales differently
1824
2048
  .range([innerRadius, outerRadius]);
2049
+ const fillColors = (_b = (_a = this.style) === null || _a === void 0 ? void 0 : _a.colors) !== null && _b !== void 0 ? _b : d3.schemeTableau10;
1825
2050
  const z = d3
1826
2051
  .scaleOrdinal()
1827
- .range([
1828
- '#8e44ad',
1829
- '#4242f4',
1830
- '#42c5f4',
1831
- '#42f4ce',
1832
- '#42f456',
1833
- '#adf442',
1834
- '#f4e242',
1835
- '#f4a142',
1836
- '#f44242'
1837
- ]);
2052
+ .range(fillColors);
1838
2053
  x.domain(data.map((d) => String(d.angle)));
1839
2054
  if (this.Y_DOMAIN_TYPE === 'frequency') {
1840
2055
  y.domain([
1841
2056
  0,
1842
- ((_a = d3.max(data, (d) => d.total)) !== null && _a !== void 0 ? _a : 0) > 1
1843
- ? (_b = d3.max(data, (d) => d.total)) !== null && _b !== void 0 ? _b : 0
2057
+ ((_c = d3.max(data, (d) => d.total)) !== null && _c !== void 0 ? _c : 0) > 1
2058
+ ? (_d = d3.max(data, (d) => d.total)) !== null && _d !== void 0 ? _d : 0
1844
2059
  : 1
1845
2060
  ]);
1846
2061
  }
@@ -1849,7 +2064,7 @@ class AxiomWindrose extends AxiomPlotRoot {
1849
2064
  }
1850
2065
  z.domain(this.columns.slice(1));
1851
2066
  // Extend the domain slightly to match the range of [0, 2π].
1852
- angle.domain([0, (_c = d3.max(data, (_, i) => i + 1)) !== null && _c !== void 0 ? _c : 0]);
2067
+ angle.domain([0, (_e = d3.max(data, (_, i) => i + 1)) !== null && _e !== void 0 ? _e : 0]);
1853
2068
  // radius.domain([0, d3.max(data, (): number => 0) || 0])
1854
2069
  radius.domain([0, 0]);
1855
2070
  // radius.domain([innerRadius, outerRadius]);
@@ -1891,7 +2106,10 @@ class AxiomWindrose extends AxiomPlotRoot {
1891
2106
  arc
1892
2107
  // @ts-expect-error
1893
2108
  .attr('d', arcVal)
1894
- .attr('transform', `rotate(${angleOffset})`);
2109
+ .attr('transform', `rotate(${angleOffset})`)
2110
+ .on('mouseover', (event, data) => { this.onMouseEnterOrMove(event, data); })
2111
+ .on('mousemove', (event, data) => { this.onMouseEnterOrMove(event, data); })
2112
+ .on('mouseleave', () => { this.onMouseLeave(); });
1895
2113
  const label = g
1896
2114
  .append('g')
1897
2115
  .selectAll('g')
@@ -1974,6 +2192,25 @@ class AxiomWindrose extends AxiomPlotRoot {
1974
2192
  }
1975
2193
  drawScrubbing(mouseX) {
1976
2194
  }
2195
+ onMouseEnterOrMove(event, data) {
2196
+ if (this.chart.onScrub === undefined)
2197
+ return;
2198
+ const scrubPositions = {
2199
+ [this.id]: {
2200
+ xPosition: event.offsetX,
2201
+ xValue: data.data.angle,
2202
+ yPosition: event.offsetY,
2203
+ yValue: data[1] - data[0],
2204
+ properties: Object.assign({}, data)
2205
+ }
2206
+ };
2207
+ this.chart.onScrub(scrubPositions);
2208
+ }
2209
+ onMouseLeave() {
2210
+ if (this.chart.onScrubEnd === undefined)
2211
+ return;
2212
+ this.chart.onScrubEnd();
2213
+ }
1977
2214
  }
1978
2215
 
1979
2216
  class AxiomWindroseChart extends AxiomChart {