UNPKG

@hello-pangea/color-picker

Version:

React color pickers from Sketch, Photoshop, Chrome, Github, Twitter & more

168 lines (142 loc) 4.49 kB
import React, { Component, PureComponent } from "react"; const DEFAULT_ARROW_OFFSET = 1; const UP_KEY_CODE = 38; const DOWN_KEY_CODE = 40; const VALID_KEY_CODES = [UP_KEY_CODE, DOWN_KEY_CODE]; const isValidKeyCode = (keyCode) => VALID_KEY_CODES.indexOf(keyCode) > -1; const getNumberValue = (value) => Number(String(value).replace(/%/g, "")); let idCounter = 1; export class EditableInput extends (PureComponent || Component) { constructor(props) { super(); this.state = { value: String(props.value).toUpperCase(), blurValue: String(props.value).toUpperCase(), }; this.inputId = `rc-editable-input-${idCounter++}`; } componentDidUpdate(prevProps, prevState) { if ( this.props.value !== this.state.value && (prevProps.value !== this.props.value || prevState.value !== this.state.value) ) { if (this.input === document.activeElement) { this.setState({ blurValue: String(this.props.value).toUpperCase() }); } else { this.setState({ value: String(this.props.value).toUpperCase(), blurValue: !this.state.blurValue && String(this.props.value).toUpperCase(), }); } } } componentWillUnmount() { this.unbindEventListeners(); } getValueObjectWithLabel(value) { return { [this.props.label]: value, }; } handleBlur = () => { if (this.state.blurValue) { this.setState({ value: this.state.blurValue, blurValue: null }); } }; handleChange = (e) => { this.setUpdatedValue(e.target.value, e); }; getArrowOffset() { return this.props.arrowOffset || DEFAULT_ARROW_OFFSET; } handleKeyDown = (e) => { // In case `e.target.value` is a percentage remove the `%` character // and update accordingly with a percentage // https://github.com/casesandberg/react-color/issues/383 const value = getNumberValue(e.target.value); if (!isNaN(value) && isValidKeyCode(e.keyCode)) { const offset = this.getArrowOffset(); const updatedValue = e.keyCode === UP_KEY_CODE ? value + offset : value - offset; this.setUpdatedValue(updatedValue, e); } }; setUpdatedValue(value, e) { const onChangeValue = this.props.label ? this.getValueObjectWithLabel(value) : value; this.props.onChange && this.props.onChange(onChangeValue, e); this.setState({ value }); } handleDrag = (e) => { if (this.props.dragLabel) { const newValue = Math.round(this.props.value + e.movementX); if (newValue >= 0 && newValue <= this.props.dragMax) { this.props.onChange && this.props.onChange(this.getValueObjectWithLabel(newValue), e); } } }; handleMouseDown = (e) => { if (this.props.dragLabel) { e.preventDefault(); this.handleDrag(e); window.addEventListener("mousemove", this.handleDrag); window.addEventListener("mouseup", this.handleMouseUp); } }; handleMouseUp = () => { this.unbindEventListeners(); }; unbindEventListeners = () => { window.removeEventListener("mousemove", this.handleDrag); window.removeEventListener("mouseup", this.handleMouseUp); }; render() { const styles = { wrap: { position: "relative", }, input: this.props.style && this.props.style.input ? this.props.style.input : {}, label: { cursor: this.props["dragLabel-true"] ? "ew-resize" : undefined, }, }; if (this.props.style && this.props.style.wrap) { styles.wrap = { ...styles.wrap, ...this.props.style.wrap }; } if (this.props.style && this.props.style.label) { styles.label = { ...styles.label, ...this.props.style.label }; } return ( <div style={styles.wrap}> <input id={this.inputId} style={styles.input} ref={(input) => (this.input = input)} value={this.state.value} onKeyDown={this.handleKeyDown} onChange={this.handleChange} onBlur={this.handleBlur} placeholder={this.props.placeholder} spellCheck="false" /> {this.props.label && !this.props.hideLabel ? ( <label htmlFor={this.inputId} style={styles.label} onMouseDown={this.handleMouseDown} > {this.props.label} </label> ) : null} </div> ); } } export default EditableInput;