fix: fix the drop-down menu does not disapper (#2109)

* fix: should delay show menu to avoid the menu not hidden

* fix(mouseEnterDelay): change default value from 100 to 150

* chore: upgrade types for react

* fix: fix the drop-down menu does not disapper

* Revert "chore: upgrade types for react"

This reverts commit 7991d1c569.

* chore: ignore types check to avoid build error
This commit is contained in:
被雨水过滤的空气-Rairn 2023-06-25 19:18:22 +08:00 committed by GitHub
parent 55b3681bba
commit 73f3929b4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 51 deletions

View File

@ -3,7 +3,8 @@ import { ISchema, observer, useForm } from '@formily/react';
import { error, isString } from '@nocobase/utils/client'; import { error, isString } from '@nocobase/utils/client';
import { Button, Dropdown, MenuProps, Switch } from 'antd'; import { Button, Dropdown, MenuProps, Switch } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import React, { createContext, useCallback, useContext, useMemo, useState } from 'react'; // @ts-ignore
import React, { createContext, useCallback, useContext, useMemo, useRef, useState, useTransition } from 'react';
import { useCollectMenuItem, useMenuItem } from '../hooks/useMenuItem'; import { useCollectMenuItem, useMenuItem } from '../hooks/useMenuItem';
import { Icon } from '../icon'; import { Icon } from '../icon';
import { SchemaComponent, useActionContext } from '../schema-component'; import { SchemaComponent, useActionContext } from '../schema-component';
@ -22,6 +23,12 @@ const overlayClassName = css`
overflow: auto; overflow: auto;
} }
`; `;
/**
*
*/
const hidden = css`
display: none;
`;
const defaultWrap = (s: ISchema) => s; const defaultWrap = (s: ISchema) => s;
@ -56,42 +63,36 @@ SchemaInitializer.Button = observer(
const { insertAdjacent, findComponent, designable } = useDesignable(); const { insertAdjacent, findComponent, designable } = useDesignable();
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const { Component: CollectionComponent, getMenuItem, clean } = useMenuItem(); const { Component: CollectionComponent, getMenuItem, clean } = useMenuItem();
const [shouldRender, setShouldRender] = useState(false);
const [searchValue, setSearchValue] = useState(''); const [searchValue, setSearchValue] = useState('');
const [isPending, startTransition] = useTransition();
const menuItems = useRef([]);
const changeMenu = (v: boolean) => {
startTransition(() => {
setVisible(v);
});
};
if (!designable && props.designable !== true) { if (!designable && props.designable !== true) {
return null; return null;
} }
const buttonDom = ( const buttonDom = component ? (
<div component
style={{ display: 'inline-block' }} ) : (
onMouseEnter={() => { <Button
setShouldRender(true); type={'dashed'}
setVisible(true); style={{
borderColor: '#f18b62',
color: '#f18b62',
...style,
}} }}
{...others}
icon={typeof icon === 'string' ? <Icon type={icon as string} /> : icon}
> >
{component ? ( {compile(props.children || props.title)}
component </Button>
) : (
<Button
type={'dashed'}
style={{
borderColor: '#f18b62',
color: '#f18b62',
...style,
}}
{...others}
icon={typeof icon === 'string' ? <Icon type={icon as string} /> : icon}
>
{compile(props.children || props.title)}
</Button>
)}
</div>
); );
if (!shouldRender || !items.length) {
return buttonDom;
}
const insertSchema = (schema) => { const insertSchema = (schema) => {
if (insert) { if (insert) {
@ -169,12 +170,14 @@ SchemaInitializer.Button = observer(
}); });
}; };
clean(); if (visible) {
const menuItems = renderItems(items); clean();
menuItems.current = renderItems(items);
}
return ( return (
<SchemaInitializerButtonContext.Provider value={{ visible, setVisible, searchValue, setSearchValue }}> <SchemaInitializerButtonContext.Provider value={{ visible, setVisible, searchValue, setSearchValue }}>
<CollectionComponent /> {visible ? <CollectionComponent /> : null}
<Dropdown <Dropdown
className={classNames('nb-schema-initializer-button')} className={classNames('nb-schema-initializer-button')}
openClassName={`nb-schema-initializer-button-open`} openClassName={`nb-schema-initializer-button-open`}
@ -183,15 +186,15 @@ SchemaInitializer.Button = observer(
onOpenChange={() => { onOpenChange={() => {
// 如果不清空输入框的值,那么下次打开的时候会出现上次输入的值 // 如果不清空输入框的值,那么下次打开的时候会出现上次输入的值
setSearchValue(''); setSearchValue('');
setShouldRender(false); changeMenu(!visible);
setVisible(false);
}} }}
menu={{ menu={{
style: { style: {
maxHeight: '60vh', maxHeight: '60vh',
overflowY: 'auto', overflowY: 'auto',
}, },
items: menuItems, className: classNames({ [hidden]: !visible }),
items: menuItems.current,
}} }}
{...dropdown} {...dropdown}
> >

View File

@ -20,7 +20,17 @@ import {
} from 'antd'; } from 'antd';
import classNames from 'classnames'; import classNames from 'classnames';
import _, { cloneDeep } from 'lodash'; import _, { cloneDeep } from 'lodash';
import React, { ReactNode, createContext, useCallback, useContext, useMemo, useState } from 'react'; import React, {
ReactNode,
createContext,
useCallback,
useContext,
useMemo,
// @ts-ignore
useTransition as useReactTransition,
useRef,
useState,
} from 'react';
import { createPortal } from 'react-dom'; import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import {
@ -75,6 +85,13 @@ interface SchemaSettingsContextProps {
const SchemaSettingsContext = createContext<SchemaSettingsContextProps>(null); const SchemaSettingsContext = createContext<SchemaSettingsContextProps>(null);
/**
*
*/
const hidden = css`
display: none;
`;
export const useSchemaSettings = () => { export const useSchemaSettings = () => {
return useContext(SchemaSettingsContext); return useContext(SchemaSettingsContext);
}; };
@ -131,31 +148,28 @@ export const SchemaSettings: React.FC<SchemaSettingsProps> & SchemaSettingsNeste
const { title, dn, ...others } = props; const { title, dn, ...others } = props;
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const { Component, getMenuItems } = useMenuItem(); const { Component, getMenuItems } = useMenuItem();
const [shouldRender, setShouldRender] = useState(false); const menuItems = useRef([]);
const [isPending, startTransition] = useReactTransition();
if (!shouldRender) { const changeMenu = (v: boolean) => {
return ( startTransition(() => {
<div setVisible(v);
onMouseEnter={() => { });
setShouldRender(true); };
setVisible(true);
}} if (visible) {
> menuItems.current = getMenuItems(() => props.children);
{typeof title === 'string' ? <span>{title}</span> : title}
</div>
);
} }
const dropdownMenu = () => ( const dropdownMenu = () => (
<> <>
<Component /> {visible ? <Component /> : null}
<Dropdown <Dropdown
open={visible} open={visible}
onOpenChange={() => { onOpenChange={() => {
setShouldRender(false); changeMenu(!visible);
setVisible(false);
}} }}
menu={{ items: getMenuItems(() => props.children) }} menu={{ items: menuItems.current, className: classNames({ [hidden]: !visible }) }}
overlayClassName={overlayClassName} overlayClassName={overlayClassName}
> >
{typeof title === 'string' ? <span>{title}</span> : title} {typeof title === 'string' ? <span>{title}</span> : title}