lucid-ui
Version:
A UI component library from Xandr.
155 lines • 5.84 kB
JavaScript
/* eslint-disable react/prop-types */
import _ from 'lodash';
import React, { createElement } from 'react';
import PropTypes from 'prop-types';
import { lucidClassNames } from '../../util/style-helpers';
import { getFirst } 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';
/** TODO: Remove the nonPassThroughs when the component is converted to a functional component */
const nonPassThroughs = [
'onChange',
'onChangeDebounced',
'debounceLevel',
'onSubmit',
'value',
'isValid',
'isDisabled',
'placeholder',
'className',
'Icon',
'TextField',
'initialState',
'callbackId',
];
class SearchField extends React.Component {
constructor() {
super(...arguments);
this.textFieldElement = React.createRef();
this.focus = (options) => {
this.textFieldElement.current &&
this.textFieldElement.current.focus(options);
};
}
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, { ref: this.textFieldElement, ...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", { ..._.omit(passThroughs, nonPassThroughs), className: cx('&', className) },
textFieldElement,
React.createElement("div", { className: cx('&-Icon-container', {
'&-Icon-is-disabled': isDisabled,
}) }, icon)));
}
}
SearchField.displayName = 'SearchField';
SearchField.TextField = SearchFieldTextField;
SearchField.Icon = SearchFieldIcon;
SearchField.peek = {
description: `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 = {
/**
Fires an event every time the user types text into the TextField.
Signature: \`(value, { event, props }) => {}\`
*/
onChange: func,
/**
Fires an event, debounced by \`debounceLevel\`, when the user types text
into the TextField. Signature: \`(value, { event, props }) => {}\`
*/
onChangeDebounced: func,
/**
Number of milliseconds to debounce the \`onChangeDebounced\` callback.
Only useful if you provide an \`onChangeDebounced\` handler.
*/
debounceLevel: number,
/**
Fires an event when the user hits "enter" from the SearchField.
Signature: \`(value, { event, props }) => {}\`
*/
onSubmit: func,
/**
Set the value of the input.
*/
value: oneOfType([number, string]),
/**
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.
*/
isValid: bool,
/**
Disables the SearchField by greying it out.
*/
isDisabled: bool,
/**
placeholder value
*/
placeholder: string,
/**
Appended to the component-specific class names set on the root element.
*/
className: string,
Icon: node /**
Icon this is displayed on the right side of the SearchField. Any of the
lucid \`*Icon\` components should work.
*/,
/**
The TextField that Searchfield is composed of.
*/
TextField: node,
};
SearchField.defaultProps = {
isDisabled: false,
onChange: _.noop,
onChangeDebounced: _.noop,
debounceLevel: 500,
onSubmit: _.noop,
value: '',
};
export default buildModernHybridComponent(SearchField, { reducers });
export { SearchField as SearchFieldDumb };
//# sourceMappingURL=SearchField.js.map