# All files / src/utils nearest.ts

100% Statements 45/45
100% Branches 5/5
100% Functions 1/1
100% Lines 45/45

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    461x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    42x
    42x
    2x
    2x
    40x
    40x
    40x
    40x
    40x
    40x
    40x
    40x
    40x
    33x
    42x
    42x
    42x
    42x
    42x
    42x
    42x
     /**
     * @internal
     * @remarks \@since 6.0.0
     */
    export interface NearestOptions {
      min: number;
      max: number;
      steps: number;
      value: number;

      /** @defaultValue `max - min` */
      range?: number;
    }

    /**
     * Rounds a number to the nearest step within a min/max range.
     *
     * @see https://stackoverflow.com/a/13635455
     * @returns the value rounded to the nearest step in the min/max range
     * @remarks
     * \@since 2.5.0 Added the `range` param
     * \@since 6.0.0 Converted to using an object instead of multiple arguments.
     */
    export function nearest(options: NearestOptions): number {
      const { min, max, steps, value, range = max - min } = options;
      if (min === max) {
        return max;
      }

      const rounded = Math.round(((value - min) * steps) / range) / steps;
      const zeroToOne = Math.min(Math.max(rounded, 0), 1);

      // have to calculate the number of allowed decimal places since decimal
      // precision gets weird:
      // 0.28 * 100 === 28.000000000000004
      const step = range / steps;
      const decimals = Number.isInteger(step)
        ? range % steps
        : `${step}`.split(".")[1].length;

      return Math.min(
        max,
        Math.max(min, parseFloat((zeroToOne * range + min).toFixed(decimals)))
      );
    }