@momentum-ui/react
Version:
Cisco Momentum UI framework for ReactJs applications
197 lines (175 loc) • 4.63 kB
JavaScript
/** @component editable-textfield */
import React from 'react';
import PropTypes from 'prop-types';
import omit from 'lodash/omit';
import { Input } from '@momentum-ui/react';
class EditableTextfield extends React.Component {
static displayName = 'EditableTextfield';
state = {
isEditing: false,
inputText: this.props.inputText,
};
componentDidUpdate = () => {
if (this.state.isEditing && this.editText) {
this.editText.focus();
}
}
handleEnter = (e, value) => {
const { allowEmpty, handleDoneEditing } = this.props;
e.persist();
if(!allowEmpty && (!value || !value.replace(/\s/g, ''))) {
this.setState(
{
isEditing: false
},
() => handleDoneEditing && handleDoneEditing(e, {value})
);
} else {
this.setState(
{
isEditing: false,
inputText: value,
},
() => handleDoneEditing && handleDoneEditing(e, {value})
);
}
e.nativeEvent.stopImmediatePropagation();
}
handleBlur = (e, value) => {
const { allowEmpty, handleDoneEditing } = this.props;
e.persist();
if(!allowEmpty && (!value || !value.replace(/\s/g, ''))) {
this.setState(
{
isEditing: false
},
() => handleDoneEditing && handleDoneEditing(e, {value})
);
} else {
this.setState(
{
isEditing: false,
inputText: value,
},
() => handleDoneEditing && handleDoneEditing(e, {value})
);
}
}
handleEsc = e => {
this.setState(
{
isEditing: false
}
);
e.nativeEvent.stopImmediatePropagation();
}
handleClick = () => {
const { disabled } = this.props;
if(disabled) {
return;
} else {
this.setState({
isEditing: true,
});
}
}
handleKey = () => {
const { disabled } = this.props;
if(disabled) {
return;
} else {
this.setState({
isEditing: true
});
}
}
handleDoneKeyDown = e => {
if (e.keyCode === 27) {
this.handleEsc(e);
} else if (e.keyCode === 13){
this.handleEnter(e, e.target.value);
}
}
render() {
const {
alignment,
buttonClassName,
buttonProps,
className,
...props
} = this.props;
const { isEditing, inputText } = this.state;
const inputProps = omit({...props}, [
'allowEmpty',
'disabled',
'handleDoneEditing',
'inputText',
]);
return(
<span
className={
'md-editable-textfield' +
`${alignment && ` md-editable-textfield--${alignment}` || ''}`
}
>
{isEditing &&
<Input
className={
'md-editable-textfield__editing' +
`${className && ` ${className}` || ''}`
}
inputRef={(input) => { this.editText = input; }}
onDoneEditing={this.handleBlur}
onKeyDown={this.handleDoneKeyDown}
value={inputText}
{...inputProps}
/>
}
{!isEditing &&
<div
role='button'
tabIndex={0}
className={
'md-editable-textfield__button' +
`${buttonClassName && ` ${buttonClassName}` || ''}`
}
onClick={this.handleClick}
onKeyPress={this.handleKey}
{...buttonProps}
>
{inputText || '\u00a0'}
</div>
}
</span>
);
}
}
EditableTextfield.propTypes = {
/** @prop Alignment css modifier | 'left' */
alignment: PropTypes.oneOf(['center', 'left', 'right']),
/** @prop Optional prop that prevents input from having null value | true */
allowEmpty: PropTypes.bool,
/** @prop Optional css class name for internal button | null */
buttonClassName: PropTypes.string,
/** @prop Optional props for internal button | '' */
buttonProps: PropTypes.shape({}),
/** @prop Optional css class string | '' */
className: PropTypes.string,
/** @prop Sets the disable attribute for EditableTextField | false */
disabled: PropTypes.bool,
/** @prop Optional function for blur | null */
handleDoneEditing: PropTypes.func,
/** @prop Text to be shown within input field | null */
inputText: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};
EditableTextfield.defaultProps = {
alignment: 'left',
allowEmpty: true,
buttonClassName: '',
buttonProps: null,
className: '',
disabled: false,
handleDoneEditing: null,
inputText: '',
};
export default EditableTextfield;