chartist 1.2.0 → 1.3.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.
package/dist/index.js CHANGED
@@ -243,12 +243,13 @@ function extend() {
243
243
  * @return The same value that was provided to the n parameter
244
244
  */ const noop = (n)=>n
245
245
  ;
246
- /**
247
- * Functional style helper to produce array with given length initialized with undefined values
248
- */ const times = (length)=>Array.from({
246
+ function times(length, filler) {
247
+ return Array.from({
249
248
  length
250
- })
251
- ;
249
+ }, filler ? (_, i)=>filler(i)
250
+ : ()=>void 0
251
+ );
252
+ }
252
253
  /**
253
254
  * Sum helper to be used in reduce functions
254
255
  */ const sum = (previous, current)=>previous + (current ? current : 0)
@@ -267,7 +268,7 @@ function extend() {
267
268
  * // 2. call arguments: (2, undefined, undefined)
268
269
  * ```
269
270
  */ const serialMap = (array, callback)=>times(Math.max(...array.map((element)=>element.length
270
- ))).map((_inner, index)=>callback(...array.map((element)=>element[index]
271
+ )), (index)=>callback(...array.map((element)=>element[index]
271
272
  ))
272
273
  )
273
274
  ;
@@ -294,6 +295,14 @@ function getNumberOrUndefined(value) {
294
295
  }
295
296
  return data.every(Array.isArray);
296
297
  }
298
+ /**
299
+ * Loop over array.
300
+ */ function each(list, callback) {
301
+ let reverse = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : false;
302
+ let index = 0;
303
+ list[reverse ? "reduceRight" : "reduce"]((_, item, itemIndex)=>callback(item, index++, itemIndex)
304
+ , void 0);
305
+ }
297
306
 
298
307
  /**
299
308
  * Get meta data of a specific value in a series.
@@ -398,22 +407,25 @@ function normalizeData(data) {
398
407
  let reverse = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : false, multi = arguments.length > 2 ? arguments[2] : void 0, distributed = arguments.length > 3 ? arguments[3] : void 0;
399
408
  let labelCount;
400
409
  const normalized = {
401
- labels: [],
410
+ labels: (data.labels || []).slice(),
402
411
  series: normalizeSeries(data.series, multi, distributed)
403
412
  };
413
+ const inputLabelCount = normalized.labels.length;
404
414
  // If all elements of the normalized data array are arrays we're dealing with
405
415
  // multi series data and we need to find the largest series if they are un-even
406
416
  if (isArrayOfArrays(normalized.series)) {
407
417
  // Getting the series with the the most elements
408
- labelCount = Math.max(...normalized.series.map((series)=>series.length
418
+ labelCount = Math.max(inputLabelCount, ...normalized.series.map((series)=>series.length
409
419
  ));
420
+ normalized.series.forEach((series)=>{
421
+ series.push(...times(Math.max(0, labelCount - series.length)));
422
+ });
410
423
  } else {
411
424
  // We're dealing with Pie data so we just take the normalized array length
412
425
  labelCount = normalized.series.length;
413
426
  }
414
- normalized.labels = (data.labels || []).slice();
415
427
  // Padding the labels to labelCount with empty strings
416
- normalized.labels.push(...times(Math.max(0, labelCount - normalized.labels.length)).map(()=>""
428
+ normalized.labels.push(...times(Math.max(0, labelCount - inputLabelCount), ()=>""
417
429
  ));
418
430
  if (reverse) {
419
431
  reverseData(normalized);
@@ -2387,7 +2399,7 @@ class FixedScaleAxis extends Axis {
2387
2399
  constructor(axisUnit, data, chartRect, options){
2388
2400
  const highLow = options.highLow || getHighLow(data, options, axisUnit.pos);
2389
2401
  const divisor = options.divisor || 1;
2390
- const ticks = (options.ticks || times(divisor).map((_value, index)=>highLow.low + (highLow.high - highLow.low) / divisor * index
2402
+ const ticks = (options.ticks || times(divisor, (index)=>highLow.low + (highLow.high - highLow.low) / divisor * index
2391
2403
  )).sort((a, b)=>Number(a) - Number(b)
2392
2404
  );
2393
2405
  const range = {
@@ -2561,7 +2573,7 @@ class LineChart extends BaseChart {
2561
2573
  createGridBackground(gridGroup, chartRect, options.classNames.gridBackground, this.eventEmitter);
2562
2574
  }
2563
2575
  // Draw the series
2564
- data.series.forEach((series, seriesIndex)=>{
2576
+ each(data.series, (series, seriesIndex)=>{
2565
2577
  const seriesElement = seriesGroup.elem("g");
2566
2578
  const seriesName = safeHasProperty(series, "name") && series.name;
2567
2579
  const seriesClassName = safeHasProperty(series, "className") && series.className;
@@ -2721,7 +2733,7 @@ class LineChart extends BaseChart {
2721
2733
  });
2722
2734
  });
2723
2735
  }
2724
- });
2736
+ }, options.reverseData);
2725
2737
  this.eventEmitter.emit("created", {
2726
2738
  chartRect,
2727
2739
  axisX,
@@ -2903,8 +2915,9 @@ function getSerialSums(series) {
2903
2915
  seriesBarDistance: 15,
2904
2916
  // If set to true this property will cause the series bars to be stacked. Check the `stackMode` option for further stacking options.
2905
2917
  stackBars: false,
2906
- // If set to 'overlap' this property will force the stacked bars to draw from the zero line.
2918
+ // If set to true this property will force the stacked bars to draw from the zero line.
2907
2919
  // If set to 'accumulate' this property will form a total for each series point. This will also influence the y-axis and the overall bounds of the chart. In stacked mode the seriesBarDistance property will have no effect.
2920
+ // If set to 'accumulate-relative' positive and negative values will be handled separately.
2908
2921
  stackMode: "accumulate",
2909
2922
  // Inverts the axes of the bar chart in order to draw a horizontal bar chart. Be aware that you also need to invert your axis settings as the Y Axis will now display the labels and the X Axis the values.
2910
2923
  horizontalBars: false,
@@ -3013,15 +3026,19 @@ class BarChart extends BaseChart {
3013
3026
  }
3014
3027
  // Projected 0 point
3015
3028
  const zeroPoint = options.horizontalBars ? chartRect.x1 + valueAxis.projectValue(0) : chartRect.y1 - valueAxis.projectValue(0);
3029
+ const isAccumulateStackMode = options.stackMode === "accumulate";
3030
+ const isAccumulateRelativeStackMode = options.stackMode === "accumulate-relative";
3016
3031
  // Used to track the screen coordinates of stacked bars
3017
- const stackedBarValues = [];
3032
+ const posStackedBarValues = [];
3033
+ const negStackedBarValues = [];
3034
+ let stackedBarValues = posStackedBarValues;
3018
3035
  labelAxis.createGridAndLabels(gridGroup, labelGroup, options, this.eventEmitter);
3019
3036
  valueAxis.createGridAndLabels(gridGroup, labelGroup, options, this.eventEmitter);
3020
3037
  if (options.showGridBackground) {
3021
3038
  createGridBackground(gridGroup, chartRect, options.classNames.gridBackground, this.eventEmitter);
3022
3039
  }
3023
3040
  // Draw the series
3024
- data.series.forEach((series, seriesIndex)=>{
3041
+ each(data.series, (series, seriesIndex)=>{
3025
3042
  // Calculating bi-polar value of index for seriesOffset. For i = 0..4 biPol will be -1.5, -0.5, 0.5, 1.5 etc.
3026
3043
  const biPol = seriesIndex - (data.series.length - 1) / 2;
3027
3044
  // Half of the period width between vertical grid lines used to position bars
@@ -3061,6 +3078,8 @@ class BarChart extends BaseChart {
3061
3078
  seriesClassName || "".concat(options.classNames.series, "-").concat(alphaNumerate(seriesIndex))
3062
3079
  ].join(" "));
3063
3080
  normalizedData.series[seriesIndex].forEach((value, valueIndex)=>{
3081
+ const valueX = safeHasProperty(value, "x") && value.x;
3082
+ const valueY = safeHasProperty(value, "y") && value.y;
3064
3083
  let labelAxisValueIndex;
3065
3084
  // We need to set labelAxisValueIndex based on some options combinations
3066
3085
  if (options.distributeSeries && !options.stackBars) {
@@ -3079,13 +3098,13 @@ class BarChart extends BaseChart {
3079
3098
  // We need to transform coordinates differently based on the chart layout
3080
3099
  if (options.horizontalBars) {
3081
3100
  projected = {
3082
- x: chartRect.x1 + valueAxis.projectValue(safeHasProperty(value, "x") ? value.x : 0, valueIndex, normalizedData.series[seriesIndex]),
3083
- y: chartRect.y1 - labelAxis.projectValue(safeHasProperty(value, "y") ? value.y : 0, labelAxisValueIndex, normalizedData.series[seriesIndex])
3101
+ x: chartRect.x1 + valueAxis.projectValue(valueX || 0, valueIndex, normalizedData.series[seriesIndex]),
3102
+ y: chartRect.y1 - labelAxis.projectValue(valueY || 0, labelAxisValueIndex, normalizedData.series[seriesIndex])
3084
3103
  };
3085
3104
  } else {
3086
3105
  projected = {
3087
- x: chartRect.x1 + labelAxis.projectValue(safeHasProperty(value, "x") ? value.x : 0, labelAxisValueIndex, normalizedData.series[seriesIndex]),
3088
- y: chartRect.y1 - valueAxis.projectValue(safeHasProperty(value, "y") ? value.y : 0, valueIndex, normalizedData.series[seriesIndex])
3106
+ x: chartRect.x1 + labelAxis.projectValue(valueX || 0, labelAxisValueIndex, normalizedData.series[seriesIndex]),
3107
+ y: chartRect.y1 - valueAxis.projectValue(valueY || 0, valueIndex, normalizedData.series[seriesIndex])
3089
3108
  };
3090
3109
  }
3091
3110
  // If the label axis is a step based axis we will offset the bar into the middle of between two steps using
@@ -3100,6 +3119,10 @@ class BarChart extends BaseChart {
3100
3119
  // Using bi-polar offset for multiple series if no stacked bars or series distribution is used
3101
3120
  projected[labelAxis.units.pos] += options.stackBars || options.distributeSeries ? 0 : biPol * options.seriesBarDistance * (options.horizontalBars ? -1 : 1);
3102
3121
  }
3122
+ // distinguish between positive and negative values in relative stack mode
3123
+ if (isAccumulateRelativeStackMode) {
3124
+ stackedBarValues = valueY >= 0 || valueX >= 0 ? posStackedBarValues : negStackedBarValues;
3125
+ }
3103
3126
  // Enter value in stacked bar values used to remember previous screen value for stacking up bars
3104
3127
  const previousStack = stackedBarValues[valueIndex] || zeroPoint;
3105
3128
  stackedBarValues[valueIndex] = previousStack - (zeroPoint - projected[labelAxis.counterUnits.pos]);
@@ -3111,7 +3134,7 @@ class BarChart extends BaseChart {
3111
3134
  ["".concat(labelAxis.units.pos, "1")]: projected[labelAxis.units.pos],
3112
3135
  ["".concat(labelAxis.units.pos, "2")]: projected[labelAxis.units.pos]
3113
3136
  };
3114
- if (options.stackBars && (options.stackMode === "accumulate" || !options.stackMode)) {
3137
+ if (options.stackBars && (isAccumulateStackMode || isAccumulateRelativeStackMode || !options.stackMode)) {
3115
3138
  // Stack mode: accumulate (default)
3116
3139
  // If bars are stacked we use the stackedBarValues reference and otherwise base all bars off the zero line
3117
3140
  // We want backwards compatibility, so the expected fallback without the 'stackMode' option
@@ -3133,8 +3156,8 @@ class BarChart extends BaseChart {
3133
3156
  // Create bar element
3134
3157
  const bar = seriesElement.elem("line", positions, options.classNames.bar).attr({
3135
3158
  "ct:value": [
3136
- safeHasProperty(value, "x") && value.x,
3137
- safeHasProperty(value, "y") && value.y
3159
+ valueX,
3160
+ valueY
3138
3161
  ].filter(isNumeric).join(","),
3139
3162
  "ct:meta": serialize(metaData)
3140
3163
  });
@@ -3153,7 +3176,7 @@ class BarChart extends BaseChart {
3153
3176
  ...positions
3154
3177
  });
3155
3178
  });
3156
- });
3179
+ }, options.reverseData);
3157
3180
  this.eventEmitter.emit("created", {
3158
3181
  chartRect,
3159
3182
  axisX,
@@ -3242,8 +3265,6 @@ class BarChart extends BaseChart {
3242
3265
  labelInterpolationFnc: noop,
3243
3266
  // Label direction can be 'neutral', 'explode' or 'implode'. The labels anchor will be positioned based on those settings as well as the fact if the labels are on the right or left side of the center of the chart. Usually explode is useful when labels are positioned far away from the center.
3244
3267
  labelDirection: "neutral",
3245
- // If true the whole data is reversed including labels, the series order as well as the whole series data arrays.
3246
- reverseData: false,
3247
3268
  // If true empty values will be ignored to avoid drawing unnecessary slices and labels
3248
3269
  ignoreEmptyValues: false
3249
3270
  };
@@ -3521,5 +3542,5 @@ class PieChart extends BaseChart {
3521
3542
  }
3522
3543
  }
3523
3544
 
3524
- export { AutoScaleAxis, Axis, BarChart, BaseChart, EPSILON, EventEmitter, FixedScaleAxis, index as Interpolation, LineChart, PieChart, StepAxis, Svg, SvgList, SvgPath, alphaNumerate, axisUnits, createChartRect, createGrid, createGridBackground, createLabel, createSvg, deserialize, determineAnchorPosition, easings, ensureUnit, escapingMap, extend, getBounds, getHighLow, getMetaData, getMultiValue, getNumberOrUndefined, getSeriesOption, isArrayOfArrays, isArrayOfSeries, isDataHoleValue, isFalseyButZero, isMultiValue, isNumeric, namespaces, noop, normalizeData, normalizePadding, optionsProvider, orderOfMagnitude, polarToCartesian, precision, projectLength, quantity, rho, roundWithPrecision, safeHasProperty, serialMap, serialize, splitIntoSegments, sum, times };
3545
+ export { AutoScaleAxis, Axis, BarChart, BaseChart, EPSILON, EventEmitter, FixedScaleAxis, index as Interpolation, LineChart, PieChart, StepAxis, Svg, SvgList, SvgPath, alphaNumerate, axisUnits, createChartRect, createGrid, createGridBackground, createLabel, createSvg, deserialize, determineAnchorPosition, each, easings, ensureUnit, escapingMap, extend, getBounds, getHighLow, getMetaData, getMultiValue, getNumberOrUndefined, getSeriesOption, isArrayOfArrays, isArrayOfSeries, isDataHoleValue, isFalseyButZero, isMultiValue, isNumeric, namespaces, noop, normalizeData, normalizePadding, optionsProvider, orderOfMagnitude, polarToCartesian, precision, projectLength, quantity, rho, roundWithPrecision, safeHasProperty, serialMap, serialize, splitIntoSegments, sum, times };
3525
3546
  //# sourceMappingURL=index.js.map