{"version":3,"file":"react-ranger.min.mjs","sources":["../src/index.js"],"sourcesContent":["import React from 'react'\n\nconst getBoundingClientRect = element => {\n  const rect = element.getBoundingClientRect()\n  return {\n    left: Math.ceil(rect.left),\n    width: Math.ceil(rect.width),\n  }\n}\n\nconst sortNumList = arr => [...arr].sort((a, b) => Number(a) - Number(b))\n\nconst useGetLatest = val => {\n  const ref = React.useRef(val)\n  ref.current = val\n  return React.useCallback(() => ref.current, [])\n}\n\nconst linearInterpolator = {\n  getPercentageForValue: (val, min, max) => {\n    return Math.max(0, Math.min(100, ((val - min) / (max - min)) * 100))\n  },\n  getValueForClientX: (clientX, trackDims, min, max) => {\n    const { left, width } = trackDims\n    const percentageValue = (clientX - left) / width\n    const value = (max - min) * percentageValue\n    return value + min\n  },\n}\n\nexport function useRanger({\n  interpolator = linearInterpolator,\n  tickSize = 10,\n  values,\n  min,\n  max,\n  ticks: controlledTicks,\n  steps,\n  onChange,\n  onDrag,\n  stepSize,\n}) {\n  const [activeHandleIndex, setActiveHandleIndex] = React.useState(null)\n  const [tempValues, setTempValues] = React.useState()\n\n  const getLatest = useGetLatest({\n    activeHandleIndex,\n    onChange,\n    onDrag,\n    values,\n    tempValues,\n  })\n\n  const trackElRef = React.useRef()\n\n  const getValueForClientX = React.useCallback(\n    clientX => {\n      const trackDims = getBoundingClientRect(trackElRef.current)\n      return interpolator.getValueForClientX(clientX, trackDims, min, max)\n    },\n    [interpolator, max, min]\n  )\n\n  const getNextStep = React.useCallback(\n    (val, direction) => {\n      if (steps) {\n        let currIndex = steps.indexOf(val)\n        let nextIndex = currIndex + direction\n        if (nextIndex >= 0 && nextIndex < steps.length) {\n          return steps[nextIndex]\n        } else {\n          return val\n        }\n      } else {\n        if (process.env.NODE_ENV !== 'production') {\n          if (typeof stepSize === 'undefined') {\n            throw new Error(\n              'Warning: The option `stepSize` is expected in `useRanger`, but its value is `undefined`'\n            )\n          }\n        }\n        let nextVal = val + stepSize * direction\n        if (nextVal >= min && nextVal <= max) {\n          return nextVal\n        } else {\n          return val\n        }\n      }\n    },\n    [max, min, stepSize, steps]\n  )\n\n  const roundToStep = React.useCallback(\n    val => {\n      let left = min\n      let right = max\n      if (steps) {\n        steps.forEach(step => {\n          if (step <= val && step > left) {\n            left = step\n          }\n          if (step >= val && step < right) {\n            right = step\n          }\n        })\n      } else {\n        if (process.env.NODE_ENV !== 'production') {\n          if (typeof stepSize === 'undefined') {\n            throw new Error(\n              'Warning: The option `stepSize` is expected in `useRanger`, but its value is `undefined`'\n            )\n          }\n        }\n        while (left < val && left + stepSize < val) {\n          left += stepSize\n        }\n\n        right = Math.min(left + stepSize, max)\n      }\n\n      if (val - left < right - val) {\n        return left\n      }\n      return right\n    },\n    [max, min, stepSize, steps]\n  )\n\n  const handleDrag = React.useCallback(\n    e => {\n      const { activeHandleIndex, onDrag } = getLatest()\n      const clientX =\n        e.type === 'touchmove' ? e.changedTouches[0].clientX : e.clientX\n      const newValue = getValueForClientX(clientX)\n      const newRoundedValue = roundToStep(newValue)\n\n      const newValues = [\n        ...values.slice(0, activeHandleIndex),\n        newRoundedValue,\n        ...values.slice(activeHandleIndex + 1),\n      ]\n\n      if (onDrag) {\n        onDrag(newValues)\n      } else {\n        setTempValues(newValues)\n      }\n    },\n    [getLatest, getValueForClientX, roundToStep, values]\n  )\n\n  const handleKeyDown = React.useCallback(\n    (e, i) => {\n      const { values, onChange = () => {} } = getLatest()\n      // Left Arrow || Right Arrow\n      if (e.keyCode === 37 || e.keyCode === 39) {\n        setActiveHandleIndex(i)\n        const direction = e.keyCode === 37 ? -1 : 1\n        const newValue = getNextStep(values[i], direction)\n        const newValues = [\n          ...values.slice(0, i),\n          newValue,\n          ...values.slice(i + 1),\n        ]\n        const sortedValues = sortNumList(newValues)\n        onChange(sortedValues)\n      }\n    },\n    [getLatest, getNextStep]\n  )\n\n  const handlePress = React.useCallback(\n    (e, i) => {\n      setActiveHandleIndex(i)\n\n      const handleRelease = e => {\n        const {\n          tempValues,\n          values,\n          onChange = () => {},\n          onDrag = () => {},\n        } = getLatest()\n\n        document.removeEventListener('mousemove', handleDrag)\n        document.removeEventListener('touchmove', handleDrag)\n        document.removeEventListener('mouseup', handleRelease)\n        document.removeEventListener('touchend', handleRelease)\n        const sortedValues = sortNumList(tempValues || values)\n        onChange(sortedValues)\n        onDrag(sortedValues)\n        setActiveHandleIndex(null)\n        setTempValues()\n      }\n\n      document.addEventListener('mousemove', handleDrag)\n      document.addEventListener('touchmove', handleDrag)\n      document.addEventListener('mouseup', handleRelease)\n      document.addEventListener('touchend', handleRelease)\n    },\n    [getLatest, handleDrag]\n  )\n\n  const getPercentageForValue = React.useCallback(\n    val => interpolator.getPercentageForValue(val, min, max),\n    [interpolator, max, min]\n  )\n\n  // Build the ticks\n  const ticks = React.useMemo(() => {\n    let ticks = controlledTicks || steps\n\n    if (!ticks) {\n      ticks = [min]\n      while (ticks[ticks.length - 1] < max - tickSize) {\n        ticks.push(ticks[ticks.length - 1] + tickSize)\n      }\n      ticks.push(max)\n    }\n\n    return ticks.map((value, i) => ({\n      value,\n      getTickProps: ({ key = i, style = {}, ...rest } = {}) => ({\n        key,\n        style: {\n          position: 'absolute',\n          width: 0,\n          left: `${getPercentageForValue(value)}%`,\n          transform: `translateX(-50%)`,\n          ...style,\n        },\n        ...rest,\n      }),\n    }))\n  }, [controlledTicks, getPercentageForValue, max, min, steps, tickSize])\n\n  const segments = React.useMemo(() => {\n    const sortedValues = sortNumList(tempValues || values)\n\n    return [...sortedValues, max].map((value, i) => ({\n      value,\n      getSegmentProps: ({ key = i, style = {}, ...rest } = {}) => {\n        const left = getPercentageForValue(\n          sortedValues[i - 1] ? sortedValues[i - 1] : min\n        )\n        const width = getPercentageForValue(value) - left\n        return {\n          key,\n          style: {\n            position: 'absolute',\n            left: `${left}%`,\n            width: `${width}%`,\n            ...style,\n          },\n          ...rest,\n        }\n      },\n    }))\n  }, [getPercentageForValue, max, min, tempValues, values])\n\n  const handles = React.useMemo(\n    () =>\n      (tempValues || values).map((value, i) => ({\n        value,\n        active: i === activeHandleIndex,\n        getHandleProps: ({\n          key = i,\n          ref,\n          innerRef = () => {},\n          onKeyDown,\n          onMouseDown,\n          onTouchStart,\n          style = {},\n          ...rest\n        } = {}) => ({\n          key,\n          onKeyDown: e => {\n            e.persist()\n            handleKeyDown(e, i)\n            if (onKeyDown) onKeyDown(e)\n          },\n          onMouseDown: e => {\n            e.persist()\n            handlePress(e, i)\n            if (onMouseDown) onMouseDown(e)\n          },\n          onTouchStart: e => {\n            e.persist()\n            handlePress(e, i)\n            if (onTouchStart) onTouchStart(e)\n          },\n          role: 'slider',\n          'aria-valuemin': min,\n          'aria-valuemax': max,\n          'aria-valuenow': value,\n          style: {\n            position: 'absolute',\n            top: '50%',\n            left: `${getPercentageForValue(value)}%`,\n            zIndex: i === activeHandleIndex ? '1' : '0',\n            transform: 'translate(-50%, -50%)',\n            ...style,\n          },\n          ...rest,\n        }),\n      })),\n    [\n      activeHandleIndex,\n      getPercentageForValue,\n      handleKeyDown,\n      handlePress,\n      min,\n      max,\n      tempValues,\n      values,\n    ]\n  )\n\n  const getTrackProps = ({ style = {}, ref, ...rest } = {}) => {\n    return {\n      ref: el => {\n        trackElRef.current = el\n        if (ref) {\n          if (typeof ref === 'function') {\n            ref(el)\n          } else {\n            ref.current = el\n          }\n        }\n      },\n      style: {\n        position: 'relative',\n        userSelect: 'none',\n        ...style,\n      },\n      ...rest,\n    }\n  }\n\n  return {\n    activeHandleIndex,\n    getTrackProps,\n    ticks,\n    segments,\n    handles,\n  }\n}\n"],"names":["sortNumList","arr","sort","a","b","Number","linearInterpolator","getPercentageForValue","val","min","max","Math","getValueForClientX","clientX","trackDims","left","width","useRanger","ref","interpolator","tickSize","values","controlledTicks","ticks","steps","onChange","onDrag","stepSize","React","useState","activeHandleIndex","setActiveHandleIndex","tempValues","setTempValues","getLatest","useRef","current","useCallback","trackElRef","element","rect","getBoundingClientRect","ceil","getNextStep","direction","nextIndex","indexOf","length","process","env","NODE_ENV","Error","nextVal","roundToStep","right","forEach","step","handleDrag","e","type","changedTouches","newValue","newRoundedValue","newValues","slice","handleKeyDown","i","keyCode","handlePress","handleRelease","document","removeEventListener","sortedValues","addEventListener","useMemo","push","map","value","getTickProps","key","style","rest","position","transform","segments","getSegmentProps","handles","active","getHandleProps","onKeyDown","innerRef","onMouseDown","onTouchStart","persist","role","top","zIndex","getTrackProps","el","userSelect"],"mappings":"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"}