mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 10:26:45 +00:00
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:
parent
55b3681bba
commit
73f3929b4f
@ -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}
|
||||||
>
|
>
|
||||||
|
@ -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}
|
||||||
|
Loading…
Reference in New Issue
Block a user