@drivy/cobalt
Version:
Opinionated design system for Drivy's projects.
108 lines (105 loc) • 4.99 kB
JavaScript
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