Compare commits
1 Commits
sriram/SQL
...
fastfrwrd/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b86c42d82a |
@@ -3,9 +3,11 @@ import * as React from 'react';
|
||||
|
||||
import { ContextMenu } from '../ContextMenu/ContextMenu';
|
||||
|
||||
export type OpenMenuFunction = <E extends HTMLElement>(e: React.KeyboardEvent<E> | React.MouseEvent<E>) => void;
|
||||
|
||||
export interface WithContextMenuProps {
|
||||
/** Menu item trigger that accepts openMenu prop */
|
||||
children: (props: { openMenu: React.MouseEventHandler<HTMLElement> }) => JSX.Element;
|
||||
children: (props: { openMenu: OpenMenuFunction }) => JSX.Element;
|
||||
/** A function that returns an array of menu items */
|
||||
renderMenuItems: () => React.ReactNode;
|
||||
/** On menu open focus the first element */
|
||||
@@ -19,11 +21,19 @@ export const WithContextMenu = ({ children, renderMenuItems, focusOnOpen = true
|
||||
<>
|
||||
{children({
|
||||
openMenu: (e) => {
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
if ('pageX' in e) {
|
||||
x = e.pageX;
|
||||
y = e.pageY - window.scrollY;
|
||||
} else if ('currentTarget' in e) {
|
||||
const target = e.currentTarget;
|
||||
const rect = target.getBoundingClientRect();
|
||||
x = rect.left + rect.width / 2 + window.scrollX;
|
||||
y = rect.top + rect.height / 2 + window.scrollY;
|
||||
}
|
||||
setIsMenuOpen(true);
|
||||
setMenuPosition({
|
||||
x: e.pageX,
|
||||
y: e.pageY - window.scrollY,
|
||||
});
|
||||
setMenuPosition({ x, y });
|
||||
},
|
||||
})}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
import { DataLinksContextMenu } from './DataLinksContextMenu';
|
||||
|
||||
const fakeAriaLabel = 'fake aria label';
|
||||
|
||||
describe('DataLinksContextMenu', () => {
|
||||
it('renders context menu when there are more than one data links', () => {
|
||||
render(
|
||||
@@ -24,9 +26,7 @@ describe('DataLinksContextMenu', () => {
|
||||
},
|
||||
]}
|
||||
>
|
||||
{() => {
|
||||
return <div aria-label="fake aria label" />;
|
||||
}}
|
||||
{() => <div aria-label={fakeAriaLabel} />}
|
||||
</DataLinksContextMenu>
|
||||
);
|
||||
|
||||
@@ -46,13 +46,76 @@ describe('DataLinksContextMenu', () => {
|
||||
},
|
||||
]}
|
||||
>
|
||||
{() => {
|
||||
return <div aria-label="fake aria label" />;
|
||||
}}
|
||||
{() => <div aria-label={fakeAriaLabel} />}
|
||||
</DataLinksContextMenu>
|
||||
);
|
||||
|
||||
expect(screen.getByLabelText(fakeAriaLabel)).toBeInTheDocument();
|
||||
expect(screen.getByTestId(selectors.components.DataLinksContextMenu.singleLink)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not render anything when there are no data links', () => {
|
||||
render(<DataLinksContextMenu links={() => []}>{() => <div aria-label={fakeAriaLabel} />}</DataLinksContextMenu>);
|
||||
|
||||
expect(screen.getByLabelText(fakeAriaLabel)).toBeInTheDocument();
|
||||
expect(screen.queryByTestId(selectors.components.DataLinksContextMenu.singleLink)).not.toBeInTheDocument();
|
||||
expect(screen.queryByLabelText(selectors.components.Menu.MenuComponent('Context'))).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('openMenu function', () => {
|
||||
it('accepts mouse event', async () => {
|
||||
render(
|
||||
<DataLinksContextMenu
|
||||
links={() => [
|
||||
{
|
||||
href: '/link1',
|
||||
title: 'Link1',
|
||||
target: '_blank',
|
||||
origin: {},
|
||||
},
|
||||
{
|
||||
href: '/link2',
|
||||
title: 'Link2',
|
||||
target: '_blank',
|
||||
origin: {},
|
||||
},
|
||||
]}
|
||||
>
|
||||
{({ openMenu }) => <div aria-label={fakeAriaLabel} onClick={openMenu} />}
|
||||
</DataLinksContextMenu>
|
||||
);
|
||||
|
||||
await userEvent.click(screen.getByLabelText(fakeAriaLabel));
|
||||
|
||||
expect(screen.getByLabelText(selectors.components.Menu.MenuComponent('Context'))).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('accepts keyboard event', async () => {
|
||||
render(
|
||||
<DataLinksContextMenu
|
||||
links={() => [
|
||||
{
|
||||
href: '/link1',
|
||||
title: 'Link1',
|
||||
target: '_blank',
|
||||
origin: {},
|
||||
},
|
||||
{
|
||||
href: '/link2',
|
||||
title: 'Link2',
|
||||
target: '_blank',
|
||||
origin: {},
|
||||
},
|
||||
]}
|
||||
>
|
||||
{({ openMenu }) => <div tabIndex={0} aria-label={fakeAriaLabel} onKeyDown={openMenu} />}
|
||||
</DataLinksContextMenu>
|
||||
);
|
||||
|
||||
await userEvent.click(screen.getByLabelText(fakeAriaLabel));
|
||||
await userEvent.keyboard('Enter');
|
||||
|
||||
expect(screen.getByLabelText(selectors.components.Menu.MenuComponent('Context'))).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { CSSProperties, type JSX } from 'react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { ActionModel, GrafanaTheme2, LinkModel } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
import { useStyles2 } from '../../themes/ThemeContext';
|
||||
import { linkModelToContextMenuItems } from '../../utils/dataLinks';
|
||||
import { WithContextMenu } from '../ContextMenu/WithContextMenu';
|
||||
import { WithContextMenu, OpenMenuFunction } from '../ContextMenu/WithContextMenu';
|
||||
import { MenuGroup, MenuItemsGroup } from '../Menu/MenuGroup';
|
||||
import { MenuItem } from '../Menu/MenuItem';
|
||||
|
||||
@@ -22,7 +21,7 @@ export interface DataLinksContextMenuProps {
|
||||
}
|
||||
|
||||
export interface DataLinksContextMenuApi {
|
||||
openMenu?: React.MouseEventHandler<HTMLOrSVGElement>;
|
||||
openMenu?: OpenMenuFunction;
|
||||
targetClassName?: string;
|
||||
}
|
||||
|
||||
@@ -66,7 +65,7 @@ export const DataLinksContextMenu = ({ children, links, style }: DataLinksContex
|
||||
}}
|
||||
</WithContextMenu>
|
||||
);
|
||||
} else {
|
||||
} else if (linksCounter === 1) {
|
||||
const linkModel = links()[0];
|
||||
return (
|
||||
<a
|
||||
@@ -80,6 +79,8 @@ export const DataLinksContextMenu = ({ children, links, style }: DataLinksContex
|
||||
{children({})}
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
return <>{children({})}</>;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user