EditableInput component
This commit is contained in:
parent
c57ead4c62
commit
521e117d95
3 changed files with 130 additions and 0 deletions
92
client/modules/IDE/components/EditableInput.jsx
Normal file
92
client/modules/IDE/components/EditableInput.jsx
Normal file
|
@ -0,0 +1,92 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import InlineSVG from 'react-inlinesvg';
|
||||
|
||||
const editIconUrl = require('../../../images/pencil.svg');
|
||||
|
||||
function EditIcon() {
|
||||
return <InlineSVG className="editable-input__icon" src={editIconUrl} alt="Edit" />;
|
||||
}
|
||||
|
||||
function EditableInput({
|
||||
validate, value, emptyPlaceholder, InputComponent, inputProps, onChange
|
||||
}) {
|
||||
const [isEditing, setIsEditing] = React.useState(false);
|
||||
const [currentValue, setCurrentValue] = React.useState(value || '');
|
||||
const displayValue = currentValue || emptyPlaceholder;
|
||||
const classes = `editable-input editable-input--${isEditing ? 'is-editing' : 'is-not-editing'}`;
|
||||
const inputRef = React.createRef();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isEditing) {
|
||||
inputRef.current.focus();
|
||||
}
|
||||
}, [isEditing]);
|
||||
|
||||
function beginEditing() {
|
||||
setIsEditing(true);
|
||||
}
|
||||
|
||||
function doneEditing() {
|
||||
setIsEditing(false);
|
||||
|
||||
const isValid = typeof validate === 'function' && validate(currentValue);
|
||||
|
||||
if (isValid) {
|
||||
onChange(currentValue);
|
||||
} else {
|
||||
setCurrentValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
function updateValue(event) {
|
||||
setCurrentValue(event.target.value);
|
||||
}
|
||||
|
||||
function checkForKeyAction(event) {
|
||||
if (event.key === 'Enter') {
|
||||
doneEditing();
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={classes}>
|
||||
<button className="editable-input__label" onClick={beginEditing}>
|
||||
<span>{displayValue}</span>
|
||||
<EditIcon />
|
||||
</button>
|
||||
|
||||
<InputComponent
|
||||
className="editable-input__input"
|
||||
type="text"
|
||||
{...inputProps}
|
||||
disabled={!isEditing}
|
||||
onBlur={doneEditing}
|
||||
onChange={updateValue}
|
||||
onKeyPress={checkForKeyAction}
|
||||
ref={inputRef}
|
||||
value={currentValue}
|
||||
/>
|
||||
</span >
|
||||
);
|
||||
}
|
||||
|
||||
EditableInput.defaultProps = {
|
||||
emptyPlaceholder: 'No value',
|
||||
InputComponent: 'input',
|
||||
inputProps: {},
|
||||
validate: () => true,
|
||||
value: '',
|
||||
};
|
||||
|
||||
EditableInput.propTypes = {
|
||||
emptyPlaceholder: PropTypes.string,
|
||||
InputComponent: PropTypes.elementType,
|
||||
// eslint-disable-next-line react/forbid-prop-types
|
||||
inputProps: PropTypes.object,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
validate: PropTypes.func,
|
||||
value: PropTypes.string,
|
||||
};
|
||||
|
||||
export default EditableInput;
|
37
client/styles/components/_editable-input.scss
Normal file
37
client/styles/components/_editable-input.scss
Normal file
|
@ -0,0 +1,37 @@
|
|||
.editable-input {
|
||||
height: 70%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.editable-input__label {
|
||||
@include themify() {
|
||||
color: getThemifyVariable('inactive-text-color');
|
||||
&:hover {
|
||||
color: getThemifyVariable('primary-text-color');
|
||||
& .editable-input__icon path {
|
||||
fill: getThemifyVariable('primary-text-color');
|
||||
}
|
||||
}
|
||||
}
|
||||
cursor: pointer;
|
||||
line-height: #{18 / $base-font-size}rem;
|
||||
|
||||
font-size: unset;
|
||||
font-weight: unset;
|
||||
}
|
||||
|
||||
.editable-input__icon svg {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
}
|
||||
|
||||
.editable-input--is-not-editing .editable-input__input,
|
||||
.editable-input--is-editing .editable-input__label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.editable-input--is-editing .editable-input__input,
|
||||
.editable-input--is-not-editing .editable-input__label {
|
||||
display: block;
|
||||
}
|
|
@ -48,6 +48,7 @@
|
|||
@import 'components/uploader';
|
||||
@import 'components/tabs';
|
||||
@import 'components/dashboard-header';
|
||||
@import 'components/editable-input';
|
||||
|
||||
@import 'layout/dashboard';
|
||||
@import 'layout/ide';
|
||||
|
|
Loading…
Reference in a new issue