Convert SearchBox to TS
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>pull/21833/head
							parent
							
								
									ac0ba2d597
								
							
						
					
					
						commit
						4673e1aa49
					
				|  | @ -16,7 +16,6 @@ limitations under the License. | |||
| */ | ||||
| 
 | ||||
| import React, { createRef } from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { Key } from '../../Keyboard'; | ||||
| import dis from '../../dispatcher/dispatcher'; | ||||
| import { throttle } from 'lodash'; | ||||
|  | @ -24,106 +23,116 @@ import AccessibleButton from '../../components/views/elements/AccessibleButton'; | |||
| import classNames from 'classnames'; | ||||
| import { replaceableComponent } from "../../utils/replaceableComponent"; | ||||
| 
 | ||||
| interface IProps { | ||||
|     onSearch?: (query: string) => void; | ||||
|     onCleared?: (source?: string) => void; | ||||
|     onKeyDown?: (ev: React.KeyboardEvent) => void; | ||||
|     onFocus?: (ev: React.FocusEvent) => void; | ||||
|     onBlur?: (ev: React.FocusEvent) => void; | ||||
|     className?: string; | ||||
|     placeholder: string; | ||||
|     blurredPlaceholder?: string; | ||||
|     autoFocus?: boolean; | ||||
|     initialValue?: string; | ||||
|     collapsed?: boolean; | ||||
| 
 | ||||
|     // If true, the search box will focus and clear itself
 | ||||
|     // on room search focus action (it would be nicer to take
 | ||||
|     // this functionality out, but not obvious how that would work)
 | ||||
|     enableRoomSearchFocus?: boolean; | ||||
| } | ||||
| 
 | ||||
| interface IState { | ||||
|     searchTerm: string; | ||||
|     blurred: boolean; | ||||
| } | ||||
| 
 | ||||
| @replaceableComponent("structures.SearchBox") | ||||
| export default class SearchBox extends React.Component { | ||||
|     static propTypes = { | ||||
|         onSearch: PropTypes.func, | ||||
|         onCleared: PropTypes.func, | ||||
|         onKeyDown: PropTypes.func, | ||||
|         className: PropTypes.string, | ||||
|         placeholder: PropTypes.string.isRequired, | ||||
|         autoFocus: PropTypes.bool, | ||||
|         initialValue: PropTypes.string, | ||||
| export default class SearchBox extends React.Component<IProps, IState> { | ||||
|     private dispatcherRef: string; | ||||
|     private search = createRef<HTMLInputElement>(); | ||||
| 
 | ||||
|         // If true, the search box will focus and clear itself
 | ||||
|         // on room search focus action (it would be nicer to take
 | ||||
|         // this functionality out, but not obvious how that would work)
 | ||||
|         enableRoomSearchFocus: PropTypes.bool, | ||||
|     }; | ||||
| 
 | ||||
|     static defaultProps = { | ||||
|     static defaultProps: Partial<IProps> = { | ||||
|         enableRoomSearchFocus: false, | ||||
|     }; | ||||
| 
 | ||||
|     constructor(props) { | ||||
|     constructor(props: IProps) { | ||||
|         super(props); | ||||
| 
 | ||||
|         this._search = createRef(); | ||||
| 
 | ||||
|         this.state = { | ||||
|             searchTerm: this.props.initialValue || "", | ||||
|             searchTerm: props.initialValue || "", | ||||
|             blurred: true, | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|     componentDidMount() { | ||||
|     public componentDidMount(): void { | ||||
|         this.dispatcherRef = dis.register(this.onAction); | ||||
|     } | ||||
| 
 | ||||
|     componentWillUnmount() { | ||||
|     public componentWillUnmount(): void { | ||||
|         dis.unregister(this.dispatcherRef); | ||||
|     } | ||||
| 
 | ||||
|     onAction = payload => { | ||||
|     private onAction = (payload): void => { | ||||
|         if (!this.props.enableRoomSearchFocus) return; | ||||
| 
 | ||||
|         switch (payload.action) { | ||||
|             case 'view_room': | ||||
|                 if (this._search.current && payload.clear_search) { | ||||
|                     this._clearSearch(); | ||||
|                 if (this.search.current && payload.clear_search) { | ||||
|                     this.clearSearch(); | ||||
|                 } | ||||
|                 break; | ||||
|             case 'focus_room_filter': | ||||
|                 if (this._search.current) { | ||||
|                     this._search.current.focus(); | ||||
|                 if (this.search.current) { | ||||
|                     this.search.current.focus(); | ||||
|                 } | ||||
|                 break; | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     onChange = () => { | ||||
|         if (!this._search.current) return; | ||||
|         this.setState({ searchTerm: this._search.current.value }); | ||||
|     private onChange = (): void => { | ||||
|         if (!this.search.current) return; | ||||
|         this.setState({ searchTerm: this.search.current.value }); | ||||
|         this.onSearch(); | ||||
|     }; | ||||
| 
 | ||||
|     onSearch = throttle(() => { | ||||
|         this.props.onSearch(this._search.current.value); | ||||
|     private onSearch = throttle((): void => { | ||||
|         this.props.onSearch(this.search.current.value); | ||||
|     }, 200, { trailing: true, leading: true }); | ||||
| 
 | ||||
|     _onKeyDown = ev => { | ||||
|     private onKeyDown = (ev: React.KeyboardEvent): void => { | ||||
|         switch (ev.key) { | ||||
|             case Key.ESCAPE: | ||||
|                 this._clearSearch("keyboard"); | ||||
|                 this.clearSearch("keyboard"); | ||||
|                 break; | ||||
|         } | ||||
|         if (this.props.onKeyDown) this.props.onKeyDown(ev); | ||||
|     }; | ||||
| 
 | ||||
|     _onFocus = ev => { | ||||
|     private onFocus = (ev: React.FocusEvent): void => { | ||||
|         this.setState({ blurred: false }); | ||||
|         ev.target.select(); | ||||
|         (ev.target as HTMLInputElement).select(); | ||||
|         if (this.props.onFocus) { | ||||
|             this.props.onFocus(ev); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     _onBlur = ev => { | ||||
|     private onBlur = (ev: React.FocusEvent): void => { | ||||
|         this.setState({ blurred: true }); | ||||
|         if (this.props.onBlur) { | ||||
|             this.props.onBlur(ev); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     _clearSearch(source) { | ||||
|         this._search.current.value = ""; | ||||
|     private clearSearch(source?: string): void { | ||||
|         this.search.current.value = ""; | ||||
|         this.onChange(); | ||||
|         if (this.props.onCleared) { | ||||
|             this.props.onCleared(source); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     render() { | ||||
|     public render(): JSX.Element { | ||||
|         // check for collapsed here and
 | ||||
|         // not at parent so we keep
 | ||||
|         // searchTerm in our state
 | ||||
|  | @ -136,7 +145,7 @@ export default class SearchBox extends React.Component { | |||
|                 key="button" | ||||
|                 tabIndex={-1} | ||||
|                 className="mx_SearchBox_closeButton" | ||||
|                 onClick={() => {this._clearSearch("button"); }} | ||||
|                 onClick={() => {this.clearSearch("button"); }} | ||||
|             />) : undefined; | ||||
| 
 | ||||
|         // show a shorter placeholder when blurred, if requested
 | ||||
|  | @ -151,13 +160,13 @@ export default class SearchBox extends React.Component { | |||
|                 <input | ||||
|                     key="searchfield" | ||||
|                     type="text" | ||||
|                     ref={this._search} | ||||
|                     ref={this.search} | ||||
|                     className={"mx_textinput_icon mx_textinput_search " + className} | ||||
|                     value={this.state.searchTerm} | ||||
|                     onFocus={this._onFocus} | ||||
|                     onFocus={this.onFocus} | ||||
|                     onChange={this.onChange} | ||||
|                     onKeyDown={this._onKeyDown} | ||||
|                     onBlur={this._onBlur} | ||||
|                     onKeyDown={this.onKeyDown} | ||||
|                     onBlur={this.onBlur} | ||||
|                     placeholder={placeholder} | ||||
|                     autoComplete="off" | ||||
|                     autoFocus={this.props.autoFocus} | ||||
|  | @ -258,7 +258,6 @@ export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({ | |||
|             className="mx_textinput_icon mx_textinput_search" | ||||
|             placeholder={filterPlaceholder} | ||||
|             onSearch={setQuery} | ||||
|             autoComplete={true} | ||||
|             autoFocus={true} | ||||
|         /> | ||||
|         <AutoHideScrollbar className="mx_AddExistingToSpace_content"> | ||||
|  |  | |||
|  | @ -243,7 +243,6 @@ const ForwardDialog: React.FC<IProps> = ({ matrixClient: cli, event, permalinkCr | |||
|                 className="mx_textinput_icon mx_textinput_search" | ||||
|                 placeholder={_t("Search for rooms or people")} | ||||
|                 onSearch={setQuery} | ||||
|                 autoComplete={true} | ||||
|                 autoFocus={true} | ||||
|             /> | ||||
|             <AutoHideScrollbar className="mx_ForwardList_content"> | ||||
|  |  | |||
|  | @ -57,7 +57,6 @@ const SpaceChildPicker = ({ filterPlaceholder, rooms, selected, onChange }) => { | |||
|             className="mx_textinput_icon mx_textinput_search" | ||||
|             placeholder={filterPlaceholder} | ||||
|             onSearch={setQuery} | ||||
|             autoComplete={true} | ||||
|             autoFocus={true} | ||||
|         /> | ||||
|         <AutoHideScrollbar className="mx_LeaveSpaceDialog_content"> | ||||
|  |  | |||
|  | @ -126,7 +126,6 @@ const ManageRestrictedJoinRuleDialog: React.FC<IProps> = ({ room, selected = [], | |||
|                 className="mx_textinput_icon mx_textinput_search" | ||||
|                 placeholder={_t("Search spaces")} | ||||
|                 onSearch={setQuery} | ||||
|                 autoComplete={true} | ||||
|                 autoFocus={true} | ||||
|             /> | ||||
|             <AutoHideScrollbar className="mx_ManageRestrictedJoinRuleDialog_content"> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Šimon Brandner
						Šimon Brandner