UNPKG

@drivy/cobalt

Version:

Opinionated design system for Drivy's projects.

108 lines (105 loc) 4.99 kB
import React, { PureComponent } from 'react'; import cx from 'classnames'; import { withFieldLabelAndHint } from './field.js'; import DefaultButton from '../Buttons/DefaultButton/index.js'; import '../Icon/index.js'; import MinusIcon from '../Icon/__generated__/MinusIcon.js'; import PlusIcon from '../Icon/__generated__/PlusIcon.js'; const AUTO_CHANGE_TIMEOUT_IN_MS = 750; const AUTO_CHANGE_INTERVAL_IN_MS = 150; const enforceInRange = (value, min, max) => { let enforcedValue = value; if (typeof max !== "undefined") { enforcedValue = Math.min(enforcedValue, max); } if (typeof min !== "undefined") { enforcedValue = Math.max(enforcedValue, min); } return enforcedValue; }; class Stepper extends PureComponent { constructor(props) { super(props); this.timeout = null; this.interval = null; this.onDecrement = () => { (this.props.min !== null || this.state.value > this.props.min) && this.changeValue(parseFloat((this.state.value - this.props.step).toFixed(10))); }; this.onIncrement = () => { (this.props.max !== null || this.state.value < this.props.max) && this.changeValue(parseFloat((this.state.value + this.props.step).toFixed(10))); }; this.onPointerDown = (callback) => { callback(); this.timeout && clearTimeout(this.timeout); this.timeout = setTimeout(() => { this.interval && clearInterval(this.interval); this.interval = setInterval(callback, AUTO_CHANGE_INTERVAL_IN_MS); }, AUTO_CHANGE_TIMEOUT_IN_MS); }; this.onPointerUp = () => { if (this.interval) { clearInterval(this.interval); this.interval = null; } this.timeout && clearTimeout(this.timeout); }; this.changeValue = (value) => { this.setState({ value: enforceInRange(value, this.props.min, this.props.max), }, () => { this.props.onChange && this.props.onChange(this.state.value); }); }; if (props.step < 0) throw new Error("Incorrect step value. Can't be below zero"); this.onDecrement = this.onDecrement.bind(this); this.onIncrement = this.onIncrement.bind(this); this.changeValue = this.changeValue.bind(this); this.onPointerDown = this.onPointerDown.bind(this); this.onPointerUp = this.onPointerUp.bind(this); this.state = { value: enforceInRange(props.value, props.min, props.max), }; } componentDidUpdate(_prevProps, prevState) { if (prevState.value !== this.state.value) { this.changeValue(this.state.value); } else if (this.props.value !== this.state.value) { this.changeValue(this.props.value); } } render() { const { name, status, disabled, min, max, children } = this.props; return (React.createElement("div", { className: cx("cobalt-Stepper", { "cobalt-Stepper--disabled": disabled, "cobalt-Stepper--success": status === "success", "cobalt-Stepper--error": status === "error", }) }, React.createElement("div", { className: "cobalt-Stepper__Wrapper" }, React.createElement(DefaultButton, { className: "cobalt-Stepper__ActionButton", disabled: disabled || this.state.value === min, ...(!disabled && { onPointerDown: () => this.onPointerDown(this.onDecrement), onPointerUp: this.onPointerUp, onPointerLeave: this.onPointerUp, }), type: "button", "data-label": "stepper-minus" }, React.createElement(MinusIcon, null)), React.createElement("div", { className: "cobalt-Stepper__ContentWrapper" }, children ? children(this.state.value) : this.state.value, React.createElement("input", { type: "hidden", name: name, value: this.state.value })), React.createElement(DefaultButton, { className: "cobalt-Stepper__ActionButton", disabled: disabled || this.state.value === max, ...(!disabled && { onPointerDown: () => this.onPointerDown(this.onIncrement), onPointerUp: this.onPointerUp, onPointerLeave: this.onPointerUp, }), type: "button", "data-label": "stepper-plus" }, React.createElement(PlusIcon, null))))); } } const wrappedComponent = withFieldLabelAndHint(Stepper); wrappedComponent.displayName = "Stepper"; const StepperMeta = ({ children }) => { return React.createElement("div", { className: "cobalt-Stepper__Meta" }, children); }; export { wrappedComponent as Stepper, StepperMeta }; //# sourceMappingURL=Stepper.js.map