client: FilesystemBrowserTextbox, TagSelect: use more precise detection of out-of-view click

This commit is contained in:
Jesse Chan
2020-10-27 02:21:55 +08:00
parent 7825ef0a6c
commit c5d6caef63
4 changed files with 38 additions and 28 deletions
@@ -26,9 +26,8 @@ interface FilesystemBrowserTextboxStates {
class FilesystemBrowserTextbox extends React.Component<FilesystemBrowserTextboxProps, FilesystemBrowserTextboxStates> {
contextMenuInstanceRef: ContextMenu | null = null;
contextMenuNodeRef: HTMLDivElement | null = null;
formRowRef = React.createRef<HTMLDivElement>();
textboxRef: HTMLInputElement | null = null;
constructor(props: FilesystemBrowserTextboxProps) {
@@ -114,8 +113,10 @@ class FilesystemBrowserTextbox extends React.Component<FilesystemBrowserTextboxP
this.setState({destination, isDirectoryListOpen: isDirectory});
};
handleDocumentClick = () => {
this.closeDirectoryList();
handleDocumentClick = (e: Event) => {
if (!this.formRowRef.current?.contains((e.target as unknown) as Node)) {
this.closeDirectoryList();
}
};
handleModalDismiss = () => {
@@ -167,7 +168,7 @@ class FilesystemBrowserTextbox extends React.Component<FilesystemBrowserTextboxP
}
return (
<FormRowGroup>
<FormRowGroup ref={this.formRowRef}>
<FormRow>
<Textbox
addonPlacement="after"
@@ -21,8 +21,8 @@ interface TagSelectStates {
}
export default class TagSelect extends Component<TagSelectProps, TagSelectStates> {
formRowRef = React.createRef<HTMLDivElement>();
menuRef: HTMLDivElement | null = null;
textboxRef: HTMLInputElement | null = null;
tagMenuItems = Object.keys(TorrentFilterStore.taxonomy.tagCounts).reduce((accumulator: React.ReactNodeArray, tag) => {
@@ -66,13 +66,13 @@ export default class TagSelect extends Component<TagSelectProps, TagSelectStates
window.addEventListener('scroll', this.handleWindowScroll, {
capture: true,
});
document.addEventListener('click', this.toggleOpenState);
document.addEventListener('click', this.handleDocumentClick);
} else if (!isOpen && prevState.isOpen) {
window.addEventListener('keydown', this.handleKeyDown);
window.removeEventListener('scroll', this.handleWindowScroll, {
capture: true,
});
document.removeEventListener('click', this.toggleOpenState);
document.removeEventListener('click', this.handleDocumentClick);
}
}
@@ -97,6 +97,12 @@ export default class TagSelect extends Component<TagSelectProps, TagSelectStates
}, []);
}
handleDocumentClick = (e: Event) => {
if (!this.formRowRef.current?.contains((e.target as unknown) as Node)) {
this.toggleOpenState();
}
};
handleItemClick = (tag: string) => {
let {selectedTags} = this.state;
@@ -147,7 +153,7 @@ export default class TagSelect extends Component<TagSelectProps, TagSelectStates
});
return (
<FormRowItem>
<FormRowItem ref={this.formRowRef}>
<label className="form__element__label">{label}</label>
<div className={classes}>
<Textbox
@@ -4,8 +4,12 @@ interface FormRowGroupProps {
children: React.ReactNode;
}
const FormRowGroup: React.FC<FormRowGroupProps> = ({children}: FormRowGroupProps) => {
return <div className="form__row form__row--group">{children}</div>;
};
const FormRowGroup = React.forwardRef<HTMLDivElement, FormRowGroupProps>(({children}: FormRowGroupProps, ref) => {
return (
<div className="form__row form__row--group" ref={ref}>
{children}
</div>
);
});
export default FormRowGroup;
@@ -20,23 +20,22 @@ export interface FormRowItemProps {
| 'seven-eighths';
}
const FormRowItem: React.FC<FormRowItemProps> = ({
children,
className,
type,
width,
grow,
shrink,
}: FormRowItemProps) => {
const classes = classnames('form__row__item', className, {
[`form__row__item--${width}`]: width,
'form__row__item--grow': grow,
'form__row__item--shrink': shrink,
'form__row__item--error': type === 'error',
});
const FormRowItem = React.forwardRef<HTMLDivElement, FormRowItemProps>(
({children, className, type, width, grow, shrink}: FormRowItemProps, ref) => {
const classes = classnames('form__row__item', className, {
[`form__row__item--${width}`]: width,
'form__row__item--grow': grow,
'form__row__item--shrink': shrink,
'form__row__item--error': type === 'error',
});
return <div className={classes}>{children}</div>;
};
return (
<div className={classes} ref={ref}>
{children}
</div>
);
},
);
FormRowItem.defaultProps = {
grow: true,