forked from WikiEducationFoundation/WikiEduDashboard
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: text_input.jsx to functional component
- Loading branch information
1 parent
09f6a53
commit 8c0a472
Showing
1 changed file
with
121 additions
and
99 deletions.
There are no files selected for viewing
220 changes: 121 additions & 99 deletions
220
app/assets/javascripts/components/common/text_input.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,116 +1,138 @@ | ||
import React from 'react'; | ||
import createReactClass from 'create-react-class'; | ||
import React, { useRef } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import InputHOC from '../high_order/input_hoc.jsx'; | ||
import Conditional from '../high_order/conditional.jsx'; | ||
|
||
const TextInput = createReactClass({ | ||
displayName: 'TextInput', | ||
const TextInput = ({ | ||
value, | ||
value_key, | ||
editable, | ||
label, | ||
placeholder, | ||
spacer, | ||
valueClass, | ||
p_tag_classname, | ||
inline, | ||
type, | ||
max, | ||
maxLength, | ||
focus, | ||
onBlur, | ||
onClick, | ||
append, | ||
onKeyDown, | ||
_value, | ||
invalid, | ||
onChange, | ||
onFocus, | ||
id, | ||
children | ||
}) => { | ||
const inputRef = useRef(null); | ||
|
||
propTypes: { | ||
value: PropTypes.any, | ||
value_key: PropTypes.string, | ||
editable: PropTypes.bool, | ||
label: PropTypes.string, | ||
placeholder: PropTypes.string, | ||
spacer: PropTypes.string, | ||
valueClass: PropTypes.string, | ||
p_tag_classname: PropTypes.string, | ||
inline: PropTypes.bool, | ||
type: PropTypes.string, | ||
max: PropTypes.string, | ||
maxLength: PropTypes.string, | ||
focus: PropTypes.func, | ||
onBlur: PropTypes.func, | ||
onClick: PropTypes.func, | ||
append: PropTypes.node, | ||
onKeyDown: PropTypes.func, | ||
_value: PropTypes.any, | ||
// validation: Regex used by Conditional | ||
// required: bool used by Conditional | ||
}, | ||
const onKeyDownHandler = (e) => { | ||
if (!onKeyDown) return; | ||
onKeyDown(e.keyCode, inputRef.current); | ||
}; | ||
|
||
onKeyDown(e) { | ||
if (!this.props.onKeyDown) { return; } | ||
this.props.onKeyDown(e.keyCode, this.refs.inputbox); | ||
}, | ||
let labelContent; | ||
const usedSpacer = spacer || ': '; | ||
|
||
dateChange(date) { | ||
const value = date ? date.format('YYYY-MM-DD') : ''; | ||
return this.props.onChange({ target: { value } }); | ||
}, | ||
if (label) { | ||
labelContent = label + usedSpacer; | ||
} | ||
|
||
render() { | ||
let label; | ||
const spacer = this.props.spacer || ': '; | ||
let usedValueClass = 'text-input-component__value '; | ||
if (valueClass) { | ||
usedValueClass += valueClass; | ||
} | ||
|
||
if (this.props.label) { | ||
label = this.props.label + spacer; | ||
if (editable) { | ||
let labelClass = ''; | ||
let inputClass = inline ? 'inline' : ''; | ||
if (invalid) { | ||
labelClass += 'red'; | ||
inputClass += ' invalid'; | ||
} | ||
|
||
const value = this.props.value; | ||
|
||
let valueClass = 'text-input-component__value '; | ||
if (this.props.valueClass) { valueClass += this.props.valueClass; } | ||
|
||
if (this.props.editable) { | ||
let labelClass = ''; | ||
let inputClass = this.props.inline ? 'inline' : ''; | ||
if (this.props.invalid) { | ||
labelClass += 'red'; | ||
inputClass += ' invalid'; | ||
} | ||
let title; | ||
if (type === 'number') { | ||
title = I18n.t('accessibility.number_field'); | ||
} | ||
|
||
let title; | ||
if (this.props.type === 'number') { | ||
title = I18n.t('accessibility.number_field'); | ||
} | ||
const className = `${inputClass} ${value_key}`; | ||
|
||
const className = `${inputClass} ${this.props.value_key}`; | ||
// The default maximum length of 75 ensures that the slug field | ||
// of a course, which combines three TextInput values, will not exceed | ||
// the maximum string size of 255. | ||
const maxLength = this.props.maxLength || '75'; | ||
const input = ( | ||
<input | ||
className={className} | ||
id={this.props.id} | ||
value={this.props._value !== undefined ? this.props._value : this.props.value || ''} | ||
onChange={this.props.onChange} | ||
autoFocus={this.props.focus} | ||
onFocus={this.props.onFocus} | ||
onBlur={this.props.onBlur} | ||
onKeyDown={this.onKeyDown} | ||
type={this.props.type || 'text'} | ||
max={this.props.max} | ||
maxLength={maxLength} | ||
placeholder={this.props.placeholder} | ||
title={title} | ||
min={0} | ||
ref="inputbox" | ||
aria-labelledby={`${this.props.id}-label`} | ||
/> | ||
); | ||
// The default maximum length of 75 ensures that the slug field | ||
// of a course, which combines three TextInput values, will not exceed | ||
// the maximum string size of 255. | ||
const usedMaxLength = maxLength || '75'; | ||
const inputElement = ( | ||
<input | ||
id={id} | ||
className={className} | ||
value={_value !== undefined ? _value : value || ''} | ||
onChange={onChange} | ||
autoFocus={focus} | ||
onFocus={onFocus} | ||
onBlur={onBlur} | ||
onKeyDown={onKeyDownHandler} | ||
type={type || 'text'} | ||
max={max} | ||
maxLength={usedMaxLength} | ||
placeholder={placeholder} | ||
title={title} | ||
min={0} | ||
ref={inputRef} | ||
aria-labelledby={`${id}-label`} | ||
/> | ||
); | ||
|
||
return ( | ||
<div className="form-group"> | ||
<label id={`${this.props.id}-label`} htmlFor={this.props.id} className={labelClass}>{label}</label> | ||
{input} | ||
{this.props.children} | ||
</div> | ||
); | ||
} else if (this.props.label) { | ||
return ( | ||
<p className={this.props.p_tag_classname}> | ||
<span className="text-input-component__label"><strong>{label}</strong></span> | ||
<span onBlur={this.props.onBlur} onClick={this.props.onClick} className={valueClass}>{value}</span> | ||
{this.props.append} | ||
</p> | ||
); | ||
} | ||
return <span>{value}</span>; | ||
return ( | ||
<div className="form-group"> | ||
<label id={`${id}-label`} htmlFor={id} className={labelClass}> | ||
{labelContent} | ||
</label> | ||
{inputElement} | ||
{children} | ||
</div> | ||
); | ||
} else if (label) { | ||
return ( | ||
<p className={p_tag_classname}> | ||
<span className="text-input-component__label"> | ||
<strong>{labelContent}</strong> | ||
</span> | ||
<span onBlur={onBlur} onClick={onClick} className={usedValueClass}> | ||
{value} | ||
</span> | ||
{append} | ||
</p> | ||
); | ||
} | ||
} | ||
); | ||
return <span>{value}</span>; | ||
}; | ||
|
||
TextInput.propTypes = { | ||
value: PropTypes.any, | ||
value_key: PropTypes.string, | ||
editable: PropTypes.bool, | ||
label: PropTypes.string, | ||
placeholder: PropTypes.string, | ||
spacer: PropTypes.string, | ||
valueClass: PropTypes.string, | ||
p_tag_classname: PropTypes.string, | ||
inline: PropTypes.bool, | ||
type: PropTypes.string, | ||
max: PropTypes.string, | ||
maxLength: PropTypes.string, | ||
focus: PropTypes.func, | ||
onBlur: PropTypes.func, | ||
onClick: PropTypes.func, | ||
append: PropTypes.node, | ||
onKeyDown: PropTypes.func, | ||
_value: PropTypes.any, | ||
// validation: Regex used by Conditional | ||
// required: bool used by Conditional | ||
}; | ||
|
||
export default Conditional(InputHOC(TextInput)); |