fix: escapes react-select events when drawer is open

This commit is contained in:
Jacob Fletcher
2022-12-07 12:40:19 -05:00
parent 5f0227fa80
commit f290cda333
7 changed files with 89 additions and 14 deletions

View File

@@ -62,6 +62,7 @@ export const Drawer: React.FC<Props> = ({
return (
<Modal
trapFocus={false}
slug={modalSlug}
className={[
baseClass,

View File

@@ -0,0 +1,40 @@
import React from 'react';
import { components, ControlProps } from 'react-select';
import { Option } from '../../../forms/field-types/Relationship/types';
export const Control: React.FC<ControlProps<Option, any>> = (props) => {
const {
children,
innerProps,
selectProps: {
selectProps: {
drawerIsOpen,
},
},
} = props;
return (
<components.Control
{...props}
innerProps={{
...innerProps,
onMouseDown: (e) => {
// prevent react-select from hijacking the onMouseDown event while the drawer is open
if (!drawerIsOpen) {
innerProps.onMouseDown(e);
}
},
// react-select has this typed incorrectly
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
onKeyDown: (e) => {
if (drawerIsOpen) {
e.stopPropagation();
}
},
}}
>
{children}
</components.Control>
);
};

View File

@@ -1,4 +1,4 @@
import React, { MouseEventHandler } from 'react';
import React from 'react';
import {
MultiValueProps,
components as SelectComponents,
@@ -18,18 +18,18 @@ export const MultiValue: React.FC<MultiValueProps<OptionType>> = (props) => {
data: {
value,
},
selectProps: {
selectProps,
selectProps: {
drawerIsOpen,
},
},
} = props;
const { attributes, listeners, setNodeRef, transform } = useSortable({
id: value as string,
});
const onMouseDown: MouseEventHandler<HTMLDivElement> = (e) => {
// prevent the dropdown from opening when clicking on the drag handle
e.preventDefault();
e.stopPropagation();
};
const classes = [
baseClass,
className,
@@ -43,7 +43,13 @@ export const MultiValue: React.FC<MultiValueProps<OptionType>> = (props) => {
innerProps={{
...innerProps,
ref: setNodeRef,
onMouseDown,
onMouseDown: (e) => {
if (!drawerIsOpen) {
// prevent the dropdown from opening when clicking on the drag handle but not when the drawer is open
e.preventDefault();
e.stopPropagation();
}
},
style: {
...transform ? {
transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`,
@@ -51,6 +57,7 @@ export const MultiValue: React.FC<MultiValueProps<OptionType>> = (props) => {
},
}}
selectProps={{
...selectProps,
// NOTE: pass the draggable props to the label to act as the draggable handle
draggableProps: {
...attributes,

View File

@@ -1,4 +1,4 @@
import React, { Fragment } from 'react';
import React, { Fragment, useEffect } from 'react';
import { components, MultiValueProps } from 'react-select';
import { useDocumentDrawer } from '../../DocumentDrawer';
import Edit from '../../../icons/Edit';
@@ -14,21 +14,28 @@ export const MultiValueLabel: React.FC<MultiValueProps<Option>> = (props) => {
relationTo,
label,
},
selectProps,
selectProps: {
setDrawerIsOpen,
draggableProps,
},
} = props;
const [DocumentDrawer, DocumentDrawerToggler] = useDocumentDrawer({
const [DocumentDrawer, DocumentDrawerToggler, { isDrawerOpen }] = useDocumentDrawer({
id: value?.toString(),
collectionSlug: relationTo,
});
useEffect(() => {
if (typeof setDrawerIsOpen === 'function') setDrawerIsOpen(isDrawerOpen);
}, [isDrawerOpen, setDrawerIsOpen]);
return (
<div className={baseClass}>
<div className={`${baseClass}__label`}>
<components.MultiValueLabel
{...props}
innerProps={{
...selectProps?.draggableProps || {},
...draggableProps || {},
}}
/>
</div>

View File

@@ -1,4 +1,4 @@
import React, { Fragment } from 'react';
import React, { Fragment, useEffect } from 'react';
import { components, SingleValueProps } from 'react-select';
import { useDocumentDrawer } from '../../DocumentDrawer';
import Edit from '../../../icons/Edit';
@@ -15,13 +15,22 @@ export const SingleValue: React.FC<SingleValueProps<Option>> = (props) => {
label,
},
children,
selectProps: {
selectProps: {
setDrawerIsOpen,
},
},
} = props;
const [DocumentDrawer, DocumentDrawerToggler] = useDocumentDrawer({
const [DocumentDrawer, DocumentDrawerToggler, { isDrawerOpen }] = useDocumentDrawer({
id: value.toString(),
collectionSlug: relationTo,
});
useEffect(() => {
if (typeof setDrawerIsOpen === 'function') setDrawerIsOpen(isDrawerOpen);
}, [isDrawerOpen, setDrawerIsOpen]);
return (
<div className={baseClass}>
<div className={`${baseClass}__label`}>

View File

@@ -24,6 +24,7 @@ import { MultiValue } from './MultiValue';
import { SingleValue } from './SingleValue';
import { ValueContainer } from './ValueContainer';
import { ClearIndicator } from './ClearIndicator';
import { Control } from './Control';
import './index.scss';
const SelectAdapter: React.FC<Props> = (props) => {
@@ -44,8 +45,11 @@ const SelectAdapter: React.FC<Props> = (props) => {
onMenuOpen,
components,
droppableRef,
selectProps,
} = props;
const [drawerIsOpen, setDrawerIsOpen] = React.useState(false);
const classes = [
className,
'react-select',
@@ -69,6 +73,9 @@ const SelectAdapter: React.FC<Props> = (props) => {
filterOption={filterOption}
onMenuOpen={onMenuOpen}
selectProps={{
...selectProps,
drawerIsOpen,
setDrawerIsOpen,
droppableRef,
}}
components={{
@@ -78,6 +85,7 @@ const SelectAdapter: React.FC<Props> = (props) => {
MultiValueLabel,
DropdownIndicator: Chevron,
ClearIndicator,
Control,
...components,
}}
/>

View File

@@ -36,4 +36,7 @@ export type Props = {
components?: {
[key: string]: React.FC<any>
}
selectProps?: {
[key: string]: unknown
}
}