UNPKG

saagie-ui

Version:

Saagie UI from Saagie Design System

129 lines (111 loc) 3.25 kB
/* eslint prefer-const: 0 */ import React, { useState, useMemo } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; const propTypes = { /** * The component used for the root node. * Either a string to use a DOM element or a component. */ tag: PropTypes.elementType, className: PropTypes.string, defaultClassName: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]), isDanger: PropTypes.bool, isDisabled: PropTypes.bool, isPrimary: PropTypes.bool, isSuccess: PropTypes.bool, isWarning: PropTypes.bool, min: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), max: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), onChange: PropTypes.func, formatLabel: PropTypes.func, }; const defaultProps = { tag: 'input', className: '', defaultClassName: 'sui-a-form-range', isDanger: false, isDisabled: false, isPrimary: false, isSuccess: false, isWarning: false, min: 0, max: 100, value: 0, onChange: () => {}, formatLabel: (value) => value, }; const SLIDER_THUMB_WIDTH = 25; const FULL_WIDTH_PERCENTAGE = 100; const HALF_WIDTH_PERCENTAGE = 50; export const FormRange = (props) => { let { tag: Tag, defaultClassName, className, isDanger, isDisabled, isPrimary, isSuccess, isWarning, min, max, value, onChange, formatLabel, ...attributes } = props; const defaultValue = value || min; const [currentValue, setCurrentValue] = useState(defaultValue); const classes = classnames( defaultClassName, className, { 'as--danger': isDanger, 'as--primary': isPrimary, 'as--success': isSuccess, 'as--warning': isWarning, }, ); const valueLeft = useMemo( () => (currentValue / max) * FULL_WIDTH_PERCENTAGE, [currentValue, max]); const handleChange = (event) => { const { value: newValue } = (event.target || {}); setCurrentValue(newValue); onChange(newValue); }; return ( <div className={classes}> <div className="sui-a-form-range__label as--before">{formatLabel(min)}</div> <div className="sui-a-form-range__container"> <Tag type="range" disabled={isDisabled} min={min} max={max} defaultValue={defaultValue} onChange={handleChange} {...attributes} /> <div className="sui-a-form-range__wrapper" style={{ transform: `translateX(calc(${valueLeft}% ${valueLeft > HALF_WIDTH_PERCENTAGE ? `- ${((valueLeft - HALF_WIDTH_PERCENTAGE) / FULL_WIDTH_PERCENTAGE) * SLIDER_THUMB_WIDTH}` : `+ ${((HALF_WIDTH_PERCENTAGE - valueLeft) / FULL_WIDTH_PERCENTAGE) * SLIDER_THUMB_WIDTH}`}px))`, }} > <div className="sui-a-form-range__value as--position-dynamic" > {formatLabel(currentValue)} </div> </div> </div> <div className="sui-a-form-range__label as--after">{formatLabel(max)}</div> </div> ); }; FormRange.propTypes = propTypes; FormRange.defaultProps = defaultProps;