UNPKG

shinkansen-cogs

Version:
202 lines (184 loc) 4.19 kB
/** * @typedef {CogsTypes.OnEventType} OnEventType * @typedef {CogsTypes.Components.Field.ValueProps} ValueProps * @typedef {CogsTypes.Components.Field.Select.SelectProps} SelectProps */ /** * SelectField component */ import React from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' import { ValueField, toInputValue } from '#cogs/components/field' /** * @type {OnEventType} */ function DEFAULT_HANDLE_EVENT () { // } /** * @param {HTMLOptionElement[]} selectedOptions * @returns {string[]} */ function fromSelectedOptions (selectedOptions) { return ( Array.from(selectedOptions) .map(({ value, text }) => (value || text) ?? '') ) } /** * @param {{ target: { selectedOptions: HTMLOptionElement[] } }} event * @returns {string[]} */ function getSelectedValues ({ target: { selectedOptions } }) { return ( fromSelectedOptions(selectedOptions) ) } /** * @param {{ target: { value?: string } }} event * @returns {string} */ function getSelectedValue ({ target: { value } }) { return value ?? '' } /** * @extends {ValueField<ValueProps & SelectProps>} */ export default class SelectField extends ValueField { getClassName () { return classnames(super.getClassName(), 'select') } /** * @param {SelectProps} props * @returns {boolean} */ shouldComponentUpdate (props) { const { multiple, children, ...superProps } = props return ( super.shouldComponentUpdate(superProps) || // , state || (multiple !== this.props.multiple) || (children !== this.props.children) ) } /** * @overload * @param {{ target: { selectedOptions: { value?: string, text?: string }[] } }} event * @returns {void} * * @overload * @param {{ target: { value?: string } }} event * @returns {void} * * @param {any} event * @returns {void} */ handleChange = (event) => { const { multiple = false, onChange = DEFAULT_HANDLE_EVENT, name } = this.props if (multiple) { onChange(name, getSelectedValues(event)) } else { onChange(name, getSelectedValue(event)) } } render () { const { name, id, defaultValue, required = false, disabled = false, readOnly = false, tabIndex, accessKey, multiple = false, children, fieldRef } = this.props const className = this.getClassName() if (defaultValue === undefined) { const { value } = this.props return ( <select name={name} id={id} value={( multiple ? Array.isArray(value) ? value : [toInputValue(value)] : toInputValue(value) )} required={required} disabled={disabled} // @ts-ignore readOnly={readOnly} tabIndex={tabIndex} accessKey={accessKey} multiple={multiple} onChange={this.handleChange} className={className} ref={fieldRef}> {children} </select> ) } return ( <select name={name} id={id} defaultValue={( multiple ? Array.isArray(defaultValue) ? defaultValue : [String(defaultValue)] : String(defaultValue) )} required={required} disabled={disabled} // @ts-ignore readOnly={readOnly} tabIndex={tabIndex} accessKey={accessKey} multiple={multiple} onChange={this.handleChange} className={className} ref={fieldRef}> {children} </select> ) } } SelectField.propTypes = { ...ValueField.propTypes, multiple: PropTypes.bool, value: PropTypes.oneOfType([ PropTypes.string, PropTypes.arrayOf( PropTypes.string ) ]), defaultValue: PropTypes.oneOfType([ PropTypes.string, PropTypes.arrayOf( PropTypes.string ) ]), children: PropTypes.oneOfType([ PropTypes.node, PropTypes.arrayOf( PropTypes.node ) ]) }