From 73f3929b4ff7375012cefa55256a1e89a163047e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=AB=E9=9B=A8=E6=B0=B4=E8=BF=87=E6=BB=A4=E7=9A=84?= =?UTF-8?q?=E7=A9=BA=E6=B0=94-Rairn?= <958414905@qq.com> Date: Sun, 25 Jun 2023 19:18:22 +0800 Subject: [PATCH] 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 7991d1c569629a6f458a4d5145a8df3f581bb27d. * chore: ignore types check to avoid build error --- .../schema-initializer/SchemaInitializer.tsx | 71 ++++++++++--------- .../src/schema-settings/SchemaSettings.tsx | 48 ++++++++----- 2 files changed, 68 insertions(+), 51 deletions(-) diff --git a/packages/core/client/src/schema-initializer/SchemaInitializer.tsx b/packages/core/client/src/schema-initializer/SchemaInitializer.tsx index b0c298620..b410ebdce 100644 --- a/packages/core/client/src/schema-initializer/SchemaInitializer.tsx +++ b/packages/core/client/src/schema-initializer/SchemaInitializer.tsx @@ -3,7 +3,8 @@ import { ISchema, observer, useForm } from '@formily/react'; import { error, isString } from '@nocobase/utils/client'; import { Button, Dropdown, MenuProps, Switch } from 'antd'; 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 { Icon } from '../icon'; import { SchemaComponent, useActionContext } from '../schema-component'; @@ -22,6 +23,12 @@ const overlayClassName = css` overflow: auto; } `; +/** + * 用于去除菜单的消失动画,优化操作体验 + */ +const hidden = css` + display: none; +`; const defaultWrap = (s: ISchema) => s; @@ -56,42 +63,36 @@ SchemaInitializer.Button = observer( const { insertAdjacent, findComponent, designable } = useDesignable(); const [visible, setVisible] = useState(false); const { Component: CollectionComponent, getMenuItem, clean } = useMenuItem(); - const [shouldRender, setShouldRender] = useState(false); const [searchValue, setSearchValue] = useState(''); + const [isPending, startTransition] = useTransition(); + const menuItems = useRef([]); + + const changeMenu = (v: boolean) => { + startTransition(() => { + setVisible(v); + }); + }; if (!designable && props.designable !== true) { return null; } - const buttonDom = ( -
{ - setShouldRender(true); - setVisible(true); + const buttonDom = component ? ( + component + ) : ( + - )} -
+ {compile(props.children || props.title)} + ); - if (!shouldRender || !items.length) { - return buttonDom; - } const insertSchema = (schema) => { if (insert) { @@ -169,12 +170,14 @@ SchemaInitializer.Button = observer( }); }; - clean(); - const menuItems = renderItems(items); + if (visible) { + clean(); + menuItems.current = renderItems(items); + } return ( - + {visible ? : null} { // 如果不清空输入框的值,那么下次打开的时候会出现上次输入的值 setSearchValue(''); - setShouldRender(false); - setVisible(false); + changeMenu(!visible); }} menu={{ style: { maxHeight: '60vh', overflowY: 'auto', }, - items: menuItems, + className: classNames({ [hidden]: !visible }), + items: menuItems.current, }} {...dropdown} > diff --git a/packages/core/client/src/schema-settings/SchemaSettings.tsx b/packages/core/client/src/schema-settings/SchemaSettings.tsx index ddc73fc81..c0108a4d5 100644 --- a/packages/core/client/src/schema-settings/SchemaSettings.tsx +++ b/packages/core/client/src/schema-settings/SchemaSettings.tsx @@ -20,7 +20,17 @@ import { } from 'antd'; import classNames from 'classnames'; 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 { useTranslation } from 'react-i18next'; import { @@ -75,6 +85,13 @@ interface SchemaSettingsContextProps { const SchemaSettingsContext = createContext(null); +/** + * 用于去除菜单的消失动画,优化操作体验 + */ +const hidden = css` + display: none; +`; + export const useSchemaSettings = () => { return useContext(SchemaSettingsContext); }; @@ -131,31 +148,28 @@ export const SchemaSettings: React.FC & SchemaSettingsNeste const { title, dn, ...others } = props; const [visible, setVisible] = useState(false); const { Component, getMenuItems } = useMenuItem(); - const [shouldRender, setShouldRender] = useState(false); + const menuItems = useRef([]); + const [isPending, startTransition] = useReactTransition(); - if (!shouldRender) { - return ( -
{ - setShouldRender(true); - setVisible(true); - }} - > - {typeof title === 'string' ? {title} : title} -
- ); + const changeMenu = (v: boolean) => { + startTransition(() => { + setVisible(v); + }); + }; + + if (visible) { + menuItems.current = getMenuItems(() => props.children); } const dropdownMenu = () => ( <> - + {visible ? : null} { - setShouldRender(false); - setVisible(false); + changeMenu(!visible); }} - menu={{ items: getMenuItems(() => props.children) }} + menu={{ items: menuItems.current, className: classNames({ [hidden]: !visible }) }} overlayClassName={overlayClassName} > {typeof title === 'string' ? {title} : title}