function resolveXLabelsForValues()

in src/XAxisLabels.js [25:99]


function resolveXLabelsForValues(
  scale,
  values,
  formats = [],
  style,
  force = true,
) {
  // given a set of values to label, and a list of formatters to try,
  // find the first formatter that produces a set of labels
  // which are A) distinct and B) fit on the axis without colliding with each other
  // returns the formatter and the generated labels

  let labels;
  const attempts = [];

  const goodFormat = formats.find(format => {
    const testLabels = values.map((value, i) => {
      return MeasuredValueLabel.getLabel({
        value,
        format,
        style: defaults(
          getValue(style.labelStyle, { value }, i),
          style.defaultStyle,
        ),
      });
    });

    const areLabelsDistinct = checkLabelsDistinct(testLabels);
    if (!areLabelsDistinct) {
      attempts.push({ labels: testLabels, format, areLabelsDistinct });
      return false;
    }

    const labelXRanges = testLabels.map(label =>
      getLabelXRange(scale, label, style.textAnchor || 'middle'),
    );
    const collisionCount = countRangeOverlaps(labelXRanges);
    if (collisionCount) {
      // console.log(`labels do not fit on X axis, ${collisionCount} collisions`, _.map(testLabels, 'text'));
      attempts.push({
        labels: testLabels,
        format,
        areLabelsDistinct,
        collisionCount,
      });
      return false;
    }

    labels = testLabels;
    return true;
  });

  if (!isUndefined(goodFormat)) {
    // found labels which work, return them
    return {
      labels,
      format: goodFormat,
      areLabelsDistinct: true,
      collisionCount: 0,
    };
  }
  // none of the sets of labels are good
  if (!force)
    // if we're not forced to decide, return all the labels we tried (let someone else decide)
    return { attempts };

  // forced to decide, choose the least bad option
  // todo warn that we couldn't find good labels
  const distinctAttempts = attempts.filter(
    attempt => attempt.areLabelsDistinct,
  );
  return distinctAttempts.length === 0
    ? last(attempts)
    : minBy(distinctAttempts, 'collisionCount');
}