diff options
author | kibigo! <marrus-sh@users.noreply.github.com> | 2017-12-26 16:54:28 -0800 |
---|---|---|
committer | kibigo! <marrus-sh@users.noreply.github.com> | 2018-01-04 18:21:59 -0800 |
commit | 3c29f5740447270a4122b334281a907ecbdd4165 (patch) | |
tree | dd3daba631f2eddf0ede5af76b8e29eda8874854 /app/javascript/flavours/glitch/features/drawer/search/index.js | |
parent | 924ffe81d477a8cf890c8117efb94b908760bccc (diff) |
WIP <Compose> Refactor; <Drawer> ed.
Diffstat (limited to 'app/javascript/flavours/glitch/features/drawer/search/index.js')
-rw-r--r-- | app/javascript/flavours/glitch/features/drawer/search/index.js | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/app/javascript/flavours/glitch/features/drawer/search/index.js b/app/javascript/flavours/glitch/features/drawer/search/index.js new file mode 100644 index 000000000..ccb2ba859 --- /dev/null +++ b/app/javascript/flavours/glitch/features/drawer/search/index.js @@ -0,0 +1,149 @@ +// Package imports. +import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { + FormattedMessage, + defineMessages, +} from 'react-intl'; +import Overlay from 'react-overlays/lib/Overlay'; + +// Components. +import Icon from 'flavours/glitch/components/icon'; +import DrawerSearchPopout from './popout'; + +// Utils. +import { focusRoot } from 'flavours/glitch/util/dom_helpers'; +import { + assignHandlers, + hiddenComponent, +} from 'flavours/glitch/util/react_helpers'; + +// Messages. +const messages = defineMessages({ + placeholder: { + defaultMessage: 'Search', + id: 'search.placeholder', + }, +}); + +// Handlers. +const handlers = { + + blur () { + this.setState({ expanded: false }); + }, + + change ({ target: { value } }) { + const { onChange } = this.props; + if (onChange) { + onChange(value); + } + }, + + clear (e) { + const { + onClear, + submitted, + value: { length }, + } = this.props; + e.preventDefault(); // Prevents focus change ?? + if (onClear && (submitted || length)) { + onClear(); + } + }, + + focus () { + const { onShow } = this.props; + this.setState({ expanded: true }); + if (onShow) { + onShow(); + } + }, + + keyUp (e) { + const { onSubmit } = this.props; + switch (e.key) { + case 'Enter': + if (onSubmit) { + onSubmit(); + } + break; + case 'Escape': + focusRoot(); + } + }, +}; + +// The component. +export default class DrawerSearch extends React.PureComponent { + + constructor (props) { + super(props); + assignHandlers(this, handlers); + this.state = { expanded: false }; + } + + render () { + const { + blur, + change, + clear, + focus, + keyUp, + } = this.handlers; + const { + intl, + submitted, + value, + } = this.props; + const { expanded } = this.state; + const computedClass = classNames('drawer--search', { active: value.length || submitted }); + + return ( + <div className={computedClass}> + <label> + <span {...hiddenComponent}> + <FormattedMessage {...messages.placeholder} /> + </span> + <input + type='text' + placeholder={intl.formatMessage(messages.placeholder)} + value={value} + onChange={change} + onKeyUp={keyUp} + onFocus={focus} + onBlur={blur} + /> + </label> + <div + aria-label={intl.formatMessage(messages.placeholder)} + className='icon' + onClick={clear} + role='button' + tabIndex='0' + > + <Icon icon='search' /> + <Icon icon='fa-times-circle' /> + </div> + + <Overlay + placement='bottom' + show={expanded && !value.length && !submitted} + target={this} + ><DrawerSearchPopout /></Overlay> + </div> + ); + } + +} + +DrawerSearch.propTypes = { + value: PropTypes.string, + submitted: PropTypes.bool, + onChange: PropTypes.func, + onSubmit: PropTypes.func, + onClear: PropTypes.func, + onShow: PropTypes.func, + intl: PropTypes.object, +}; |