From 1c97152533c92108472a5385903cca67f8fe0eaf Mon Sep 17 00:00:00 2001 From: Andrew Nicolaou Date: Sun, 8 Sep 2019 18:57:57 +0200 Subject: [PATCH] EditableInput component --- .../modules/IDE/components/EditableInput.jsx | 92 +++++++++++++++++++ client/styles/components/_editable-input.scss | 37 ++++++++ client/styles/main.scss | 1 + 3 files changed, 130 insertions(+) create mode 100644 client/modules/IDE/components/EditableInput.jsx create mode 100644 client/styles/components/_editable-input.scss diff --git a/client/modules/IDE/components/EditableInput.jsx b/client/modules/IDE/components/EditableInput.jsx new file mode 100644 index 00000000..6315839e --- /dev/null +++ b/client/modules/IDE/components/EditableInput.jsx @@ -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 ; +} + +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 ( + + + + + + ); +} + +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; diff --git a/client/styles/components/_editable-input.scss b/client/styles/components/_editable-input.scss new file mode 100644 index 00000000..c7239d35 --- /dev/null +++ b/client/styles/components/_editable-input.scss @@ -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; +} diff --git a/client/styles/main.scss b/client/styles/main.scss index decb6aba..853fe0f0 100644 --- a/client/styles/main.scss +++ b/client/styles/main.scss @@ -47,6 +47,7 @@ @import 'components/uploader'; @import 'components/tabs'; @import 'components/dashboard-header'; +@import 'components/editable-input'; @import 'layout/dashboard'; @import 'layout/ide';