UNPKG

lucid-ui

Version:

A UI component library from AppNexus.

127 lines (126 loc) 5.01 kB
/* eslint-disable react/prop-types */ import _ from 'lodash'; import React, { createElement } from 'react'; import PropTypes from 'react-peek/prop-types'; import { lucidClassNames } from '../../util/style-helpers'; import { getFirst, omitProps, } from '../../util/component-types'; import { buildModernHybridComponent } from '../../util/state-management'; import TextField from '../TextField/TextField'; import SearchIcon from '../Icon/SearchIcon/SearchIcon'; import reducers from './SearchField.reducers'; const cx = lucidClassNames.bind('&-SearchField'); const { bool, func, node, number, oneOfType, string } = PropTypes; const SearchFieldIcon = (_props) => null; SearchFieldIcon.peek = { description: ` Icon this is displayed on the right side of the SearchField. Any of the lucid \`*Icon\` components should work. `, }; SearchFieldIcon.displayName = 'SearchField.Icon'; SearchFieldIcon.propName = 'Icon'; const SearchFieldTextField = (_props) => null; SearchFieldTextField.peek = { description: ` Icon this is displayed on the right side of the SearchField. Any of the lucid \`*Icon\` components should work. `, }; SearchFieldTextField.displayName = 'SearchField.TextField'; SearchFieldTextField.propName = 'TextField'; class SearchField extends React.Component { render() { const { props, props: { className, isDisabled, isValid, onChange, onChangeDebounced, debounceLevel, onSubmit, placeholder, value, autoComplete, ...passThroughs }, } = this; const { Icon } = SearchField; const textFieldProps = _.get(getFirst(props, SearchField.TextField), 'props') || { isDisabled, onChange, onChangeDebounced, debounceLevel, onSubmit, placeholder, isMultiLine: false, value, autoComplete, }; const textFieldElement = React.createElement(TextField, Object.assign({}, textFieldProps)); const isIconActive = _.isUndefined(isValid) ? !_.isEmpty(_.get(textFieldElement, 'props.value')) : isValid; const defaultIcon = (React.createElement(SearchIcon, { size: 12, className: cx('&-Icon', { '&-Icon-active': isIconActive }) })); const iconElement = getFirst(props, Icon); const iconChildren = _.get(iconElement, 'props.children'); const icon = iconChildren ? createElement(iconChildren.type, { ...iconChildren.props, className: cx('&-Icon', { '&-Icon-active': isIconActive }, iconChildren.props.className), }) : defaultIcon; return (React.createElement("div", Object.assign({}, omitProps(passThroughs, undefined, _.keys(SearchField.propTypes)), { className: cx('&', className) }), textFieldElement, React.createElement("div", { className: cx('&-Icon-container') }, icon))); } } SearchField.displayName = 'SearchField'; SearchField.TextField = SearchFieldTextField; SearchField.Icon = SearchFieldIcon; SearchField.peek = { description: ` This is a wrapper around TextField that styles it for a search use-case. The icon and TextField are customizable through child components. `, categories: ['controls', 'text'], madeFrom: ['TextField', 'SearchIcon'], }; SearchField.reducers = reducers; SearchField.propTypes = { onChange: func ` Fires an event every time the user types text into the TextField. Signature: \`(value, { event, props }) => {}\` `, onChangeDebounced: func ` Fires an event, debounced by \`debounceLevel\`, when the user types text into the TextField. Signature: \`(value, { event, props }) => {}\` `, debounceLevel: number ` Number of milliseconds to debounce the \`onChangeDebounced\` callback. Only useful if you provide an \`onChangeDebounced\` handler. `, onSubmit: func ` Fires an event when the user hits "enter" from the SearchField. Signature: \`(value, { event, props }) => {}\` `, value: oneOfType([number, string]) ` Set the value of the input. `, isValid: bool ` Controls the highlighting of the search icon. Should be passed \`true\` when the search text is valid, e.g. contains enough characters to perform a search. `, isDisabled: bool ` Disables the SearchField by greying it out. `, placeholder: string ` placeholder value `, className: string ` Appended to the component-specific class names set on the root element. `, Icon: node ` Icon this is displayed on the right side of the SearchField. Any of the lucid \`*Icon\` components should work. `, TextField: node ` The TextField that Searchfield is composed of. `, }; SearchField.defaultProps = { isDisabled: false, onChange: _.noop, onChangeDebounced: _.noop, debounceLevel: 500, onSubmit: _.noop, value: '', }; export default buildModernHybridComponent(SearchField, { reducers }); export { SearchField as SearchFieldDumb };