mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
fix(plugin-data-spreadsheet-new): CB-994 CB-996 context menu
This commit is contained in:
@@ -32,6 +32,7 @@ export function useMouse<T extends HTMLElement>(options: IOptions): IMouseHook<T
|
||||
|
||||
useEffect(() => {
|
||||
if (!reference.current) {
|
||||
state.mouseEnter = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -57,10 +58,11 @@ export function useMouse<T extends HTMLElement>(options: IOptions): IMouseHook<T
|
||||
element.addEventListener('mouseleave', mouseOutHandler);
|
||||
|
||||
return () => {
|
||||
state.mouseEnter = false;
|
||||
element.removeEventListener('mouseenter', mouseOverHandler);
|
||||
element.removeEventListener('mouseleave', mouseOutHandler);
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
|
||||
return { state, reference };
|
||||
}
|
||||
|
||||
@@ -41,4 +41,6 @@ export type MenuTriggerProps = PropsWithChildren<{
|
||||
style?: Style[];
|
||||
placement?: MenuInitialState['placement'];
|
||||
modal?: boolean;
|
||||
visible?: boolean;
|
||||
onVisibleSwitch?: (visible: boolean) => void;
|
||||
}> & Omit<ButtonHTMLAttributes<any>, 'style'>;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import { observer, useObserver } from 'mobx-react-lite';
|
||||
import {
|
||||
forwardRef, Ref, useCallback
|
||||
forwardRef, Ref, useCallback, useEffect
|
||||
} from 'react';
|
||||
import {
|
||||
MenuButton,
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
} from 'reakit/Menu';
|
||||
import styled, { use } from 'reshadow';
|
||||
|
||||
import { useObjectRef } from '@cloudbeaver/core-blocks';
|
||||
import { useStyles, Style } from '@cloudbeaver/core-theming';
|
||||
|
||||
import type {
|
||||
@@ -32,10 +33,17 @@ export const MenuTrigger: React.FC<MenuTriggerProps> = function MenuTrigger({
|
||||
children,
|
||||
style = [],
|
||||
placement,
|
||||
visible,
|
||||
onVisibleSwitch,
|
||||
modal,
|
||||
...props
|
||||
}) {
|
||||
const menu = useMenuState({ modal, placement });
|
||||
const propsRef = useObjectRef({ onVisibleSwitch, visible }, { onVisibleSwitch });
|
||||
const menu = useMenuState({ modal, placement, visible });
|
||||
|
||||
useEffect(() => {
|
||||
propsRef.onVisibleSwitch?.(menu.visible);
|
||||
}, [menu.visible]);
|
||||
|
||||
return styled(useStyles(menuPanelStyles, ...style))(
|
||||
<>
|
||||
|
||||
+10
-3
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useCallback, useContext, useEffect, useRef } from 'react';
|
||||
import { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
||||
import type { FormatterProps } from 'react-data-grid';
|
||||
import styled from 'reshadow';
|
||||
|
||||
@@ -35,6 +35,7 @@ export const CellFormatter: React.FC<FormatterProps> = observer(function CellFor
|
||||
const formatter = context?.model.source.getAction(context.resultIndex, ResultSetFormatAction);
|
||||
const rawValue = row[column.key];
|
||||
const classes = getClasses(rawValue);
|
||||
const [menuVisible, setMenuVisible] = useState(false);
|
||||
const value = formatter?.toString(rawValue) ?? String(rawValue);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
@@ -68,8 +69,14 @@ export const CellFormatter: React.FC<FormatterProps> = observer(function CellFor
|
||||
<cell-formatter title={value} className={`cell-formatter ${classes}`}>
|
||||
{value}
|
||||
</cell-formatter>
|
||||
{(isCellSelected || cellContext?.mouse.state.mouseEnter) && context && (
|
||||
<CellMenu model={context.model} resultIndex={context.resultIndex} row={rowIdx} column={Number(column.key)} />
|
||||
{(isCellSelected || cellContext?.mouse.state.mouseEnter || menuVisible) && context && (
|
||||
<CellMenu
|
||||
model={context.model}
|
||||
resultIndex={context.resultIndex}
|
||||
row={rowIdx}
|
||||
column={Number(column.key)}
|
||||
onStateSwitch={setMenuVisible}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
+6
-4
@@ -24,14 +24,16 @@ interface Props {
|
||||
resultIndex: number;
|
||||
row: number;
|
||||
column: number;
|
||||
onStateSwitch?: (state: boolean) => void;
|
||||
}
|
||||
|
||||
export const CellMenu = observer(function TreeNodeMenu({
|
||||
export const CellMenu: React.FC<Props> = observer(function TreeNodeMenu({
|
||||
model,
|
||||
resultIndex,
|
||||
row,
|
||||
column,
|
||||
}: Props) {
|
||||
onStateSwitch,
|
||||
}) {
|
||||
const dataGridContextMenuService = useService(DataGridContextMenuService);
|
||||
|
||||
const { panel, hidden } = useMemo(
|
||||
@@ -50,8 +52,8 @@ export const CellMenu = observer(function TreeNodeMenu({
|
||||
}
|
||||
|
||||
return styled(cellMenuStyles)(
|
||||
<cell-menu as='div' onClick={e => e.stopPropagation()}>
|
||||
<MenuTrigger panel={panel}>
|
||||
<cell-menu as='div' onClick={e => e.stopPropagation()} onDoubleClick={e => e.stopPropagation()}>
|
||||
<MenuTrigger panel={panel} onVisibleSwitch={onStateSwitch}>
|
||||
<Icon name="snack" viewBox="0 0 16 10" />
|
||||
</MenuTrigger>
|
||||
</cell-menu>
|
||||
|
||||
Reference in New Issue
Block a user