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
+ ) : (
+ : icon}
>
- {component ? (
- component
- ) : (
- : icon}
- >
- {compile(props.children || props.title)}
-
- )}
-
+ {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}