Shared:Components:ContextMenuButton: rewrite to typescript

This commit is contained in:
Timofey Boyko 2023-12-18 15:01:02 +03:00
parent 32902c49f7
commit 8fa274a9f6
43 changed files with 717 additions and 733 deletions

View File

@ -1,72 +0,0 @@
import React, { useState } from "react";
// @ts-expect-error TS(2307): Cannot find module 'PUBLIC_DIR/images/vertical-dot... Remove this comment to see the full error message
import VerticalDotsReactSvgUrl from "PUBLIC_DIR/images/vertical-dots.react.svg?url";
import ContextMenuButton from "./";
export default {
title: "Components/ContextMenuButton",
component: ContextMenuButton,
argTypes: {
clickColor: { control: "color" },
color: { control: "color" },
getData: { required: true },
hoverColor: { control: "color" },
onClickLabel: { action: "onClickLabel", table: { disable: true } },
onMouseLeave: { action: "onMouseLeave" },
onMouseEnter: { action: "onMouseEnter" },
onMouseOver: { action: "onMouseOver" },
onMouseOut: { action: "onMouseOut" },
},
parameters: {
docs: {
description: {
component: `ContextMenuButton is used for displaying context menu actions on a list's item`,
},
},
},
};
const Template = (args: any) => {
const [isOpen, setIsOpen] = useState(args.opened);
const getData = () => {
return [
{
key: "key1",
label: "label1",
onClick: () => args.onClickLabel("label1"),
},
{
key: "key2",
label: "label2",
onClick: () => args.onClickLabel("label2"),
},
];
};
const onClickHandler = () => {
setIsOpen(!isOpen);
args.onClickLabel();
};
return (
<div style={{ height: "100px" }}>
<ContextMenuButton
{...args}
opened={isOpen}
getData={getData}
isDisabled={false}
onClick={onClickHandler}
/>
</div>
);
};
export const Default = Template.bind({});
// @ts-expect-error TS(2339): Property 'args' does not exist on type '(args: any... Remove this comment to see the full error message
Default.args = {
title: "Actions",
displayType: "dropdown",
iconName: VerticalDotsReactSvgUrl,
size: 16,
directionX: "left",
isDisabled: false,
};

View File

@ -1,225 +0,0 @@
import React from "react";
// @ts-expect-error TS(7016): Could not find a declaration file for module 'enzy... Remove this comment to see the full error message
import { mount, shallow } from "enzyme";
import ContextMenuButton from ".";
// @ts-expect-error TS(2307): Cannot find module 'PUBLIC_DIR/images/vertical-dot... Remove this comment to see the full error message
import VerticalDotsReactSvgUrl from "PUBLIC_DIR/images/vertical-dots.react.svg?url";
const baseData = () => [
{
key: "key",
label: "label",
// @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
onClick: () => jest.fn(),
},
];
const baseProps = {
title: "Actions",
iconName: VerticalDotsReactSvgUrl,
size: 16,
color: "#A3A9AE",
getData: baseData,
isDisabled: false,
};
// @ts-expect-error TS(2582): Cannot find name 'describe'. Do you need to instal... Remove this comment to see the full error message
describe("<ContextMenuButton />", () => {
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("renders without error", () => {
const wrapper = mount(<ContextMenuButton {...baseProps} />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper).toExist();
});
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("render with full custom props", () => {
const wrapper = mount(
<ContextMenuButton
// @ts-expect-error TS(2322): Type '{ color: string; hoverColor: string; clickCo... Remove this comment to see the full error message
color="red"
hoverColor="red"
clickColor="red"
size={20}
iconName="CatalogFolderIcon"
iconHoverName="CatalogFolderIcon"
iconClickName="CatalogFolderIcon"
isFill={true}
isDisabled={true}
// @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
onClick={() => jest.fn()}
// @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
onMouseEnter={() => jest.fn()}
// @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
onMouseLeave={() => jest.fn()}
// @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
onMouseOver={() => jest.fn()}
// @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
onMouseOut={() => jest.fn()}
getData={() => [
{
key: "key",
icon: "CatalogFolderIcon",
// @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
onClick: () => jest.fn(),
},
{
label: "CatalogFolderIcon",
// @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
onClick: () => jest.fn(),
},
{},
]}
directionX="right"
opened={true}
/>
);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper).toExist();
});
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("disabled", () => {
const wrapper = mount(
// @ts-expect-error TS(2322): Type '{ isDisabled: boolean; title: string; iconNa... Remove this comment to see the full error message
<ContextMenuButton {...baseProps} isDisabled={true} />
);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.prop("isDisabled")).toEqual(true);
});
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("not re-render", () => {
const wrapper = shallow(<ContextMenuButton {...baseProps} />).instance();
const shouldUpdate = wrapper.shouldComponentUpdate(
wrapper.props,
wrapper.state
);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(shouldUpdate).toBe(false);
});
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("re-render", () => {
const wrapper = shallow(<ContextMenuButton {...baseProps} />).instance();
const shouldUpdate = wrapper.shouldComponentUpdate(
{ opened: true },
wrapper.state
);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(shouldUpdate).toBe(true);
});
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("causes function onDropDownItemClick()", () => {
// @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
const onClick = jest.fn();
const wrapper = shallow(
// @ts-expect-error TS(2322): Type '{ opened: boolean; onClick: any; title: stri... Remove this comment to see the full error message
<ContextMenuButton {...baseProps} opened={true} onClick={onClick} />
);
const instance = wrapper.instance();
instance.onDropDownItemClick({
key: "key",
label: "label",
onClick: onClick,
});
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.state("isOpen")).toBe(false);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(onClick).toHaveBeenCalled();
});
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("causes function onIconButtonClick()", () => {
const wrapper = shallow(
// @ts-expect-error TS(2322): Type '{ isDisabled: boolean; opened: boolean; titl... Remove this comment to see the full error message
<ContextMenuButton {...baseProps} isDisabled={false} opened={true} />
);
const instance = wrapper.instance();
instance.onIconButtonClick();
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.state("isOpen")).toBe(false);
});
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("causes function onIconButtonClick() with isDisabled prop", () => {
const wrapper = shallow(
// @ts-expect-error TS(2322): Type '{ isDisabled: boolean; opened: boolean; titl... Remove this comment to see the full error message
<ContextMenuButton {...baseProps} isDisabled={true} opened={true} />
);
const instance = wrapper.instance();
instance.onIconButtonClick();
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.state("isOpen")).toBe(true);
});
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("componentDidUpdate() state lifecycle test", () => {
const wrapper = shallow(<ContextMenuButton {...baseProps} />);
const instance = wrapper.instance();
wrapper.setState({ isOpen: false });
instance.componentDidUpdate(wrapper.props(), wrapper.state());
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.state()).toBe(wrapper.state());
});
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("componentDidUpdate() props lifecycle test", () => {
const wrapper = shallow(<ContextMenuButton {...baseProps} />);
const instance = wrapper.instance();
instance.componentDidUpdate({ opened: true }, wrapper.state());
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.props()).toBe(wrapper.props());
});
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("accepts id", () => {
// @ts-expect-error TS(2322): Type '{ id: string; title: string; iconName: any; ... Remove this comment to see the full error message
const wrapper = mount(<ContextMenuButton {...baseProps} id="testId" />);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.prop("id")).toEqual("testId");
});
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("accepts className", () => {
const wrapper = mount(
// @ts-expect-error TS(2322): Type '{ className: string; title: string; iconName... Remove this comment to see the full error message
<ContextMenuButton {...baseProps} className="test" />
);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.prop("className")).toEqual("test");
});
// @ts-expect-error TS(2582): Cannot find name 'it'. Do you need to install type... Remove this comment to see the full error message
it("accepts style", () => {
const wrapper = mount(
// @ts-expect-error TS(2322): Type '{ style: { color: string; }; title: string; ... Remove this comment to see the full error message
<ContextMenuButton {...baseProps} style={{ color: "red" }} />
);
// @ts-expect-error TS(2304): Cannot find name 'expect'.
expect(wrapper.getDOMNode().style).toHaveProperty("color", "red");
});
});

View File

@ -1,427 +0,0 @@
import React from "react";
import throttle from "lodash/throttle";
import PropTypes from "prop-types";
import DropDownItem from "../drop-down-item";
import DropDown from "../drop-down";
import IconButton from "../icon-button";
import Backdrop from "../backdrop";
import Aside from "../aside";
import Heading from "../heading";
import Link from "../link";
import { desktop, isTablet, isMobile } from "../utils/device";
import { isTablet as Tablet } from "react-device-detect";
import {
StyledBodyContent,
StyledHeaderContent,
StyledContent,
StyledOuter,
} from "./styled-context-menu-button";
// @ts-expect-error TS(2307): Cannot find module 'PUBLIC_DIR/images/vertical-dot... Remove this comment to see the full error message
import VerticalDotsReactSvgUrl from "PUBLIC_DIR/images/vertical-dots.react.svg?url";
class ContextMenuButton extends React.Component {
ref: any;
throttledResize: any;
constructor(props: any) {
super(props);
this.ref = React.createRef();
const displayType =
props.displayType === "auto" ? this.getTypeByWidth() : props.displayType;
this.state = {
isOpen: props.opened,
data: props.data,
displayType,
};
this.throttledResize = throttle(this.resize, 300);
}
getTypeByWidth = () => {
// @ts-expect-error TS(2339): Property 'displayType' does not exist on type 'Rea... Remove this comment to see the full error message
if (this.props.displayType !== "auto") return this.props.displayType;
// @ts-expect-error TS(2365): Operator '<' cannot be applied to types 'number' a... Remove this comment to see the full error message
return window.innerWidth < desktop.match(/\d+/)[0] ? "aside" : "dropdown";
};
resize = () => {
// @ts-expect-error TS(2339): Property 'displayType' does not exist on type 'Rea... Remove this comment to see the full error message
if (this.props.displayType !== "auto") return;
const type = this.getTypeByWidth();
// @ts-expect-error TS(2339): Property 'displayType' does not exist on type 'Rea... Remove this comment to see the full error message
if (type === this.state.displayType) return;
this.setState({ displayType: type });
};
popstate = () => {
window.removeEventListener("popstate", this.popstate, false);
this.onClose();
window.history.go(1);
};
componentDidMount() {
window.addEventListener("resize", this.throttledResize);
}
componentWillUnmount() {
window.removeEventListener("resize", this.throttledResize);
window.removeEventListener("popstate", this.popstate, false);
this.throttledResize.cancel();
}
stopAction = (e: any) => e.preventDefault();
toggle = (isOpen: any) => this.setState({ isOpen: isOpen });
onClose = () => {
// @ts-expect-error TS(2339): Property 'isOpen' does not exist on type 'Readonly... Remove this comment to see the full error message
this.setState({ isOpen: !this.state.isOpen });
// @ts-expect-error TS(2339): Property 'onClose' does not exist on type 'Readonl... Remove this comment to see the full error message
this.props.onClose && this.props.onClose();
};
componentDidUpdate(prevProps: any) {
// @ts-expect-error TS(2339): Property 'opened' does not exist on type 'Readonly... Remove this comment to see the full error message
if (this.props.opened !== prevProps.opened) {
// @ts-expect-error TS(2339): Property 'opened' does not exist on type 'Readonly... Remove this comment to see the full error message
this.toggle(this.props.opened);
}
// @ts-expect-error TS(2339): Property 'opened' does not exist on type 'Readonly... Remove this comment to see the full error message
if (this.props.opened && this.state.displayType === "aside") {
window.addEventListener("popstate", this.popstate, false);
}
// @ts-expect-error TS(2339): Property 'displayType' does not exist on type 'Rea... Remove this comment to see the full error message
if (this.props.displayType !== prevProps.displayType) {
this.setState({ displayType: this.getTypeByWidth() });
}
}
onIconButtonClick = (e: any) => {
// @ts-expect-error TS(2339): Property 'isDisabled' does not exist on type 'Read... Remove this comment to see the full error message
if (this.props.isDisabled || this.state.displayType === "toggle") {
this.stopAction;
return;
}
this.setState(
{
// @ts-expect-error TS(2339): Property 'getData' does not exist on type 'Readonl... Remove this comment to see the full error message
data: this.props.getData(),
// @ts-expect-error TS(2339): Property 'isOpen' does not exist on type 'Readonly... Remove this comment to see the full error message
isOpen: !this.state.isOpen,
},
() =>
// @ts-expect-error TS(2339): Property 'isDisabled' does not exist on type 'Read... Remove this comment to see the full error message
!this.props.isDisabled &&
// @ts-expect-error TS(2339): Property 'isOpen' does not exist on type 'Readonly... Remove this comment to see the full error message
this.state.isOpen &&
// @ts-expect-error TS(2339): Property 'onClick' does not exist on type 'Readonl... Remove this comment to see the full error message
this.props.onClick &&
// @ts-expect-error TS(2339): Property 'onClick' does not exist on type 'Readonl... Remove this comment to see the full error message
this.props.onClick(e)
); // eslint-disable-line react/prop-types
};
clickOutsideAction = (e: any) => {
const path = e.path || (e.composedPath && e.composedPath());
const dropDownItem = path ? path.find((x: any) => x === this.ref.current) : null;
if (dropDownItem) return;
this.onClose();
};
onDropDownItemClick = (item: any, e: any) => {
// @ts-expect-error TS(2339): Property 'displayType' does not exist on type 'Rea... Remove this comment to see the full error message
const open = this.state.displayType === "dropdown";
item.onClick && item.onClick(e, open, item);
// @ts-expect-error TS(2339): Property 'isOpen' does not exist on type 'Readonly... Remove this comment to see the full error message
this.toggle(!this.state.isOpen);
};
shouldComponentUpdate(nextProps: any, nextState: any) {
if (
// @ts-expect-error TS(2339): Property 'opened' does not exist on type 'Readonly... Remove this comment to see the full error message
this.props.opened === nextProps.opened &&
// @ts-expect-error TS(2339): Property 'isOpen' does not exist on type 'Readonly... Remove this comment to see the full error message
this.state.isOpen === nextState.isOpen &&
// @ts-expect-error TS(2339): Property 'displayType' does not exist on type 'Rea... Remove this comment to see the full error message
this.props.displayType === nextProps.displayType &&
// @ts-expect-error TS(2339): Property 'isDisabled' does not exist on type 'Read... Remove this comment to see the full error message
this.props.isDisabled === nextProps.isDisabled
) {
return false;
}
return true;
}
callNewMenu = (e: any) => {
// @ts-expect-error TS(2339): Property 'isDisabled' does not exist on type 'Read... Remove this comment to see the full error message
if (this.props.isDisabled || this.state.displayType !== "toggle") {
this.stopAction;
return;
}
this.setState(
{
// @ts-expect-error TS(2339): Property 'getData' does not exist on type 'Readonl... Remove this comment to see the full error message
data: this.props.getData(),
},
// @ts-expect-error TS(2339): Property 'onClick' does not exist on type 'Readonl... Remove this comment to see the full error message
() => this.props.onClick(e)
);
};
render() {
//console.log("ContextMenuButton render", this.props);
const {
// @ts-expect-error TS(2339): Property 'className' does not exist on type 'Reado... Remove this comment to see the full error message
className,
// @ts-expect-error TS(2339): Property 'clickColor' does not exist on type 'Read... Remove this comment to see the full error message
clickColor,
// @ts-expect-error TS(2339): Property 'color' does not exist on type 'Readonly<... Remove this comment to see the full error message
color,
// @ts-expect-error TS(2339): Property 'columnCount' does not exist on type 'Rea... Remove this comment to see the full error message
columnCount,
// @ts-expect-error TS(2339): Property 'directionX' does not exist on type 'Read... Remove this comment to see the full error message
directionX,
// @ts-expect-error TS(2339): Property 'directionY' does not exist on type 'Read... Remove this comment to see the full error message
directionY,
// @ts-expect-error TS(2339): Property 'hoverColor' does not exist on type 'Read... Remove this comment to see the full error message
hoverColor,
// @ts-expect-error TS(2339): Property 'iconClickName' does not exist on type 'R... Remove this comment to see the full error message
iconClickName,
// @ts-expect-error TS(2339): Property 'iconHoverName' does not exist on type 'R... Remove this comment to see the full error message
iconHoverName,
// @ts-expect-error TS(2339): Property 'iconName' does not exist on type 'Readon... Remove this comment to see the full error message
iconName,
// @ts-expect-error TS(2339): Property 'iconOpenName' does not exist on type 'Re... Remove this comment to see the full error message
iconOpenName,
// @ts-expect-error TS(2339): Property 'id' does not exist on type 'Readonly<{}>... Remove this comment to see the full error message
id,
// @ts-expect-error TS(2339): Property 'isDisabled' does not exist on type 'Read... Remove this comment to see the full error message
isDisabled,
// @ts-expect-error TS(2339): Property 'onMouseEnter' does not exist on type 'Re... Remove this comment to see the full error message
onMouseEnter,
// @ts-expect-error TS(2339): Property 'onMouseLeave' does not exist on type 'Re... Remove this comment to see the full error message
onMouseLeave,
// @ts-expect-error TS(2339): Property 'onMouseOut' does not exist on type 'Read... Remove this comment to see the full error message
onMouseOut,
// @ts-expect-error TS(2339): Property 'onMouseOver' does not exist on type 'Rea... Remove this comment to see the full error message
onMouseOver,
// @ts-expect-error TS(2339): Property 'size' does not exist on type 'Readonly<{... Remove this comment to see the full error message
size,
// @ts-expect-error TS(2339): Property 'style' does not exist on type 'Readonly<... Remove this comment to see the full error message
style,
// @ts-expect-error TS(2339): Property 'isFill' does not exist on type 'Readonly... Remove this comment to see the full error message
isFill, // eslint-disable-line react/prop-types
// @ts-expect-error TS(2339): Property 'asideHeader' does not exist on type 'Rea... Remove this comment to see the full error message
asideHeader, // eslint-disable-line react/prop-types
// @ts-expect-error TS(2339): Property 'title' does not exist on type 'Readonly<... Remove this comment to see the full error message
title,
// @ts-expect-error TS(2339): Property 'zIndex' does not exist on type 'Readonly... Remove this comment to see the full error message
zIndex,
// @ts-expect-error TS(2339): Property 'usePortal' does not exist on type 'Reado... Remove this comment to see the full error message
usePortal,
// @ts-expect-error TS(2339): Property 'dropDownClassName' does not exist on typ... Remove this comment to see the full error message
dropDownClassName,
// @ts-expect-error TS(2339): Property 'iconClassName' does not exist on type 'R... Remove this comment to see the full error message
iconClassName,
// @ts-expect-error TS(2339): Property 'displayIconBorder' does not exist on typ... Remove this comment to see the full error message
displayIconBorder,
} = this.props;
// @ts-expect-error TS(2339): Property 'isOpen' does not exist on type 'Readonly... Remove this comment to see the full error message
const { isOpen, displayType, offsetX, offsetY } = this.state;
const iconButtonName = isOpen && iconOpenName ? iconOpenName : iconName;
return (
<StyledOuter
ref={this.ref}
className={className}
id={id}
style={style}
onClick={this.callNewMenu}
// @ts-expect-error TS(2769): No overload matches this call.
displayIconBorder={displayIconBorder}
>
<IconButton
// @ts-expect-error TS(2322): Type '{ className: any; color: any; hoverColor: an... Remove this comment to see the full error message
className={iconClassName}
color={color}
hoverColor={hoverColor}
clickColor={clickColor}
size={size}
iconName={iconButtonName}
iconHoverName={iconHoverName}
iconClickName={iconClickName}
isFill={isFill}
isDisabled={isDisabled}
onClick={this.onIconButtonClick}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onMouseOver={onMouseOver}
onMouseOut={onMouseOut}
title={title}
/>
{displayType === "dropdown" ? (
// @ts-expect-error TS(2769): No overload matches this call.
<DropDown
className={dropDownClassName}
directionX={directionX}
directionY={directionY}
open={isOpen}
forwardedRef={this.ref}
clickOutsideAction={this.clickOutsideAction}
columnCount={columnCount}
withBackdrop={isTablet() || isMobile() || Tablet}
zIndex={zIndex}
isDefaultMode={usePortal}
>
// @ts-expect-error TS(2339): Property 'data' does not exist on type 'Readonly<{... Remove this comment to see the full error message
{this.state.data?.map(
(item: any, index: any) =>
item &&
(item.label || item.icon || item.key) && (
<DropDownItem
{...item}
id={item.id}
key={item.key || index}
onClick={this.onDropDownItemClick.bind(this, item)}
/>
)
)}
</DropDown>
) : (
displayType === "aside" && (
<>
<Backdrop
// @ts-expect-error TS(2322): Type '{ onClick: () => void; visible: any; zIndex:... Remove this comment to see the full error message
onClick={this.onClose}
visible={isOpen}
zIndex={310}
isAside={true}
/>
<Aside
visible={isOpen}
scale={false}
zIndex={310}
onClose={this.onClose}
>
<StyledContent>
<StyledHeaderContent>
// @ts-expect-error TS(2322): Type '{ children: any; className: string; size: st... Remove this comment to see the full error message
<Heading className="header" size="medium" truncate={true}>
{asideHeader}
</Heading>
</StyledHeaderContent>
<StyledBodyContent>
// @ts-expect-error TS(2339): Property 'data' does not exist on type 'Readonly<{... Remove this comment to see the full error message
{this.state.data.map(
(item: any, index: any) =>
item &&
(item.label || item.icon || item.key) && (
<Link
className={`context-menu-button_link${
item.isHeader ? "-header" : ""
}`}
key={item.key || index}
fontSize={item.isHeader ? "15px" : "13px"}
noHover={item.isHeader}
fontWeight={600}
onClick={this.onDropDownItemClick.bind(this, item)}
>
{item.label}
</Link>
)
)}
</StyledBodyContent>
</StyledContent>
</Aside>
</>
)
)}
</StyledOuter>
);
}
}
// @ts-expect-error TS(2339): Property 'propTypes' does not exist on type 'typeo... Remove this comment to see the full error message
ContextMenuButton.propTypes = {
/** Sets the button to present an opened state */
opened: PropTypes.bool,
/** Array of options for display */
data: PropTypes.array,
/** Function for converting to inner data */
getData: PropTypes.func.isRequired,
/** Specifies the icon title */
title: PropTypes.string,
/** Specifies the icon name */
iconName: PropTypes.string,
/** Specifies the icon size */
size: PropTypes.number,
/** Specifies the icon color */
color: PropTypes.string,
/** Sets the button to present a disabled state */
isDisabled: PropTypes.bool,
/** Specifies the icon hover color */
hoverColor: PropTypes.string,
/** Specifies the icon click color */
clickColor: PropTypes.string,
/** Specifies the icon hover name */
iconHoverName: PropTypes.string,
/** Specifies the icon click name */
iconClickName: PropTypes.string,
/** Specifies the icon open name */
iconOpenName: PropTypes.string,
/** Triggers a callback function when the mouse enters the button borders */
onMouseEnter: PropTypes.func,
/** Triggers a callback function when the mouse leaves the button borders */
onMouseLeave: PropTypes.func,
/** Triggers a callback function when the mouse moves over the button borders */
onMouseOver: PropTypes.func,
/** Triggers a callback function when the mouse moves out of the button borders */
onMouseOut: PropTypes.func,
/** Direction X */
directionX: PropTypes.string,
/** Direction Y */
directionY: PropTypes.string,
/** Accepts class */
className: PropTypes.string,
/** Accepts id */
id: PropTypes.string,
/** Accepts css style */
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
/** Sets the number of columns */
columnCount: PropTypes.number,
/** Sets the display type */
displayType: PropTypes.oneOf(["dropdown", "toggle", "aside", "auto"]),
/** Closing event */
onClose: PropTypes.func,
/** Sets the drop down open with the portal */
usePortal: PropTypes.bool,
/** Sets the class of the drop down element */
dropDownClassName: PropTypes.string,
/** Sets the class of the icon button */
iconClassName: PropTypes.string,
/** Enables displaying the icon borders */
displayIconBorder: PropTypes.bool,
};
// @ts-expect-error TS(2339): Property 'defaultProps' does not exist on type 'ty... Remove this comment to see the full error message
ContextMenuButton.defaultProps = {
opened: false,
data: [],
title: "",
iconName: VerticalDotsReactSvgUrl,
size: 16,
isDisabled: false,
directionX: "left",
isFill: false,
displayType: "dropdown",
usePortal: true,
displayIconBorder: false,
};
export default ContextMenuButton;

View File

@ -0,0 +1,6 @@
export const enum ContextMenuButtonDisplayType {
dropdown = "dropdown",
toggle = "toggle",
aside = "aside",
auto = "auto",
}

View File

@ -0,0 +1,79 @@
import React, { useState } from "react";
import { Meta, StoryObj } from "@storybook/react";
import VerticalDotsReactSvgUrl from "PUBLIC_DIR/images/vertical-dots.react.svg?url";
import { ContextMenuButton } from "./ContextMenuButton";
import { ContextMenuButtonProps } from "./ContextMenuButton.types";
import { ContextMenuButtonDisplayType } from "./ContextMenuButton.enums";
const meta = {
title: "Components/ContextMenuButton",
component: ContextMenuButton,
argTypes: {
clickColor: { control: "color" },
color: { control: "color" },
getData: { required: true },
hoverColor: { control: "color" },
// onClickLabel: { action: "onClickLabel", table: { disable: true } },
onMouseLeave: { action: "onMouseLeave" },
onMouseEnter: { action: "onMouseEnter" },
onMouseOver: { action: "onMouseOver" },
onMouseOut: { action: "onMouseOut" },
},
parameters: {
docs: {
description: {
component: `ContextMenuButton is used for displaying context menu actions on a list's item`,
},
},
},
} satisfies Meta<typeof ContextMenuButton>;
type Story = StoryObj<typeof meta>;
export default meta;
const Template = (args: ContextMenuButtonProps) => {
const [isOpen, setIsOpen] = useState(false);
const onClickHandler = () => {
setIsOpen(!isOpen);
};
return (
<div style={{ height: "100px" }}>
<ContextMenuButton
{...args}
opened={isOpen}
isDisabled={false}
onClick={onClickHandler}
/>
</div>
);
};
const getData = () => {
return [
{
key: "key1",
label: "label1",
},
{
key: "key2",
label: "label2",
},
];
};
export const Default: Story = {
render: (args) => <Template {...args} />,
args: {
title: "Actions",
displayType: ContextMenuButtonDisplayType.dropdown,
iconName: VerticalDotsReactSvgUrl,
size: 16,
directionX: "left",
isDisabled: false,
data: [],
getData,
},
};

View File

@ -1,17 +1,17 @@
import styled, { css } from "styled-components";
import Base from "../themes/base";
const StyledOuter = styled.div`
import { Base } from "../../themes";
const StyledOuter = styled.div<{ displayIconBorder?: boolean }>`
display: inline-block;
position: relative;
cursor: pointer;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
${(props) =>
// @ts-expect-error TS(2339): Property 'displayIconBorder' does not exist on typ... Remove this comment to see the full error message
props.displayIconBorder &&
css`
border: ${(props) => props.theme.comboBox.button.border};
border: ${props.theme.comboBox.button.border};
width: 32px;
height: 32px;
box-sizing: border-box;
@ -21,8 +21,7 @@ const StyledOuter = styled.div`
padding: 6px 7px;
}
:hover {
border-color: ${(props) =>
props.theme.comboBox.button.hoverBorderColor};
border-color: ${props.theme.comboBox.button.hoverBorderColor};
}
`}
`;

View File

@ -0,0 +1,216 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import VerticalDotsReactSvgUrl from "PUBLIC_DIR/images/vertical-dots.react.svg?url";
import { ContextMenuButton } from "./ContextMenuButton";
import { ContextMenuButtonDisplayType } from "./ContextMenuButton.enums";
const baseData = () => [
{
key: "key",
label: "label",
onClick: jest.fn(),
},
];
const baseProps = {
title: "Actions",
iconName: VerticalDotsReactSvgUrl,
size: 16,
color: "#A3A9AE",
getData: baseData,
isDisabled: false,
};
describe("<ContextMenuButton />", () => {
it("renders without error", () => {
render(
<ContextMenuButton
displayType={ContextMenuButtonDisplayType.dropdown}
{...baseProps}
/>,
);
expect(screen.getByTestId("context-menu-button")).toBeInTheDocument();
});
// it("render with full custom props", () => {
// const wrapper = mount(
// <ContextMenuButton
// // @ts-expect-error TS(2322): Type '{ color: string; hoverColor: string; clickCo... Remove this comment to see the full error message
// color="red"
// hoverColor="red"
// clickColor="red"
// size={20}
// iconName="CatalogFolderIcon"
// iconHoverName="CatalogFolderIcon"
// iconClickName="CatalogFolderIcon"
// isFill={true}
// isDisabled={true}
// // @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
// onClick={() => jest.fn()}
// // @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
// onMouseEnter={() => jest.fn()}
// // @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
// onMouseLeave={() => jest.fn()}
// // @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
// onMouseOver={() => jest.fn()}
// // @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
// onMouseOut={() => jest.fn()}
// getData={() => [
// {
// key: "key",
// icon: "CatalogFolderIcon",
// // @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
// onClick: () => jest.fn(),
// },
// {
// label: "CatalogFolderIcon",
// // @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
// onClick: () => jest.fn(),
// },
// {},
// ]}
// directionX="right"
// opened={true}
// />,
// );
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(wrapper).toExist();
// });
// it("disabled", () => {
// const wrapper = mount(
// // @ts-expect-error TS(2322): Type '{ isDisabled: boolean; title: string; iconNa... Remove this comment to see the full error message
// <ContextMenuButton {...baseProps} isDisabled={true} />,
// );
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(wrapper.prop("isDisabled")).toEqual(true);
// });
// it("not re-render", () => {
// const wrapper = shallow(<ContextMenuButton {...baseProps} />).instance();
// const shouldUpdate = wrapper.shouldComponentUpdate(
// wrapper.props,
// wrapper.state,
// );
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(shouldUpdate).toBe(false);
// });
// it("re-render", () => {
// const wrapper = shallow(<ContextMenuButton {...baseProps} />).instance();
// const shouldUpdate = wrapper.shouldComponentUpdate(
// { opened: true },
// wrapper.state,
// );
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(shouldUpdate).toBe(true);
// });
// it("causes function onDropDownItemClick()", () => {
// // @ts-expect-error TS(2708): Cannot use namespace 'jest' as a value.
// const onClick = jest.fn();
// const wrapper = shallow(
// // @ts-expect-error TS(2322): Type '{ opened: boolean; onClick: any; title: stri... Remove this comment to see the full error message
// <ContextMenuButton {...baseProps} opened={true} onClick={onClick} />,
// );
// const instance = wrapper.instance();
// instance.onDropDownItemClick({
// key: "key",
// label: "label",
// onClick: onClick,
// });
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(wrapper.state("isOpen")).toBe(false);
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(onClick).toHaveBeenCalled();
// });
// it("causes function onIconButtonClick()", () => {
// const wrapper = shallow(
// // @ts-expect-error TS(2322): Type '{ isDisabled: boolean; opened: boolean; titl... Remove this comment to see the full error message
// <ContextMenuButton {...baseProps} isDisabled={false} opened={true} />,
// );
// const instance = wrapper.instance();
// instance.onIconButtonClick();
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(wrapper.state("isOpen")).toBe(false);
// });
// it("causes function onIconButtonClick() with isDisabled prop", () => {
// const wrapper = shallow(
// // @ts-expect-error TS(2322): Type '{ isDisabled: boolean; opened: boolean; titl... Remove this comment to see the full error message
// <ContextMenuButton {...baseProps} isDisabled={true} opened={true} />,
// );
// const instance = wrapper.instance();
// instance.onIconButtonClick();
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(wrapper.state("isOpen")).toBe(true);
// });
// it("componentDidUpdate() state lifecycle test", () => {
// const wrapper = shallow(<ContextMenuButton {...baseProps} />);
// const instance = wrapper.instance();
// wrapper.setState({ isOpen: false });
// instance.componentDidUpdate(wrapper.props(), wrapper.state());
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(wrapper.state()).toBe(wrapper.state());
// });
// it("componentDidUpdate() props lifecycle test", () => {
// const wrapper = shallow(<ContextMenuButton {...baseProps} />);
// const instance = wrapper.instance();
// instance.componentDidUpdate({ opened: true }, wrapper.state());
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(wrapper.props()).toBe(wrapper.props());
// });
// it("accepts id", () => {
// // @ts-expect-error TS(2322): Type '{ id: string; title: string; iconName: any; ... Remove this comment to see the full error message
// const wrapper = mount(<ContextMenuButton {...baseProps} id="testId" />);
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(wrapper.prop("id")).toEqual("testId");
// });
// it("accepts className", () => {
// const wrapper = mount(
// // @ts-expect-error TS(2322): Type '{ className: string; title: string; iconName... Remove this comment to see the full error message
// <ContextMenuButton {...baseProps} className="test" />,
// );
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(wrapper.prop("className")).toEqual("test");
// });
// it("accepts style", () => {
// const wrapper = mount(
// // @ts-expect-error TS(2322): Type '{ style: { color: string; }; title: string; ... Remove this comment to see the full error message
// <ContextMenuButton {...baseProps} style={{ color: "red" }} />,
// );
// // @ts-expect-error TS(2304): Cannot find name 'expect'.
// expect(wrapper.getDOMNode().style).toHaveProperty("color", "red");
// });
});

View File

@ -0,0 +1,335 @@
import React from "react";
import { DebouncedFunc } from "lodash";
import throttle from "lodash/throttle";
import { isTablet as Tablet } from "react-device-detect";
import VerticalDotsReactSvgUrl from "PUBLIC_DIR/images/vertical-dots.react.svg?url";
import { desktop, isTablet, isMobile } from "../../utils";
import { DropDownItem } from "../drop-down-item";
import { DropDown } from "../drop-down";
import { IconButton } from "../icon-button";
import { Backdrop } from "../backdrop";
import { Aside } from "../aside";
import { Heading, HeadingSize } from "../heading";
import { Link } from "../link";
import { ContextMenuModel } from "../context-menu";
import {
StyledBodyContent,
StyledHeaderContent,
StyledContent,
StyledOuter,
} from "./ContextMenuButton.styled";
import { ContextMenuButtonProps } from "./ContextMenuButton.types";
import { ContextMenuButtonDisplayType } from "./ContextMenuButton.enums";
const ContextMenuButtonPure = ({
opened,
data,
displayType,
onClose,
isDisabled,
getData,
onClick,
className,
iconOpenName,
id,
style,
displayIconBorder,
iconClassName,
color,
hoverColor,
clickColor,
size,
iconHoverName,
iconClickName,
isFill,
onMouseEnter,
onMouseLeave,
onMouseOut,
onMouseOver,
title,
dropDownClassName,
directionX,
directionY,
columnCount,
zIndex,
usePortal,
asideHeader,
iconName = VerticalDotsReactSvgUrl,
}: ContextMenuButtonProps) => {
const ref = React.useRef<HTMLDivElement | null>(null);
const throttledResize = React.useRef<null | DebouncedFunc<() => void>>(null);
const [state, setState] = React.useState({
isOpen: opened,
data,
displayType: ContextMenuButtonDisplayType.dropdown,
offsetX: 0,
offsetY: 0,
});
const getTypeByWidth = React.useCallback(() => {
if (displayType !== "auto") return displayType;
const desktopSize = desktop.match(/\d+/)?.[0] as number | undefined;
if (typeof desktopSize !== "undefined" && window.innerWidth < desktopSize) {
return ContextMenuButtonDisplayType.aside;
}
return ContextMenuButtonDisplayType.dropdown;
}, [displayType]);
React.useEffect(() => {
const type = displayType === "auto" ? getTypeByWidth() : displayType;
setState((s) => ({ ...s, displayType: type }));
}, [displayType, getTypeByWidth]);
const resize = React.useCallback(() => {
if (displayType !== "auto") return;
const type = getTypeByWidth();
if (type === state.displayType) return;
setState((s) => ({ ...s, displayType: type }));
}, [displayType, getTypeByWidth, state.displayType]);
React.useEffect(() => {
throttledResize.current = throttle(resize, 300);
window.addEventListener("resize", throttledResize.current);
return () => {
if (throttledResize.current) {
window.removeEventListener("resize", throttledResize.current);
throttledResize.current.cancel();
}
};
}, [resize]);
const stopAction = React.useCallback(
(e: React.MouseEvent) => e.preventDefault(),
[],
);
const toggle = (isOpen: boolean) => setState((s) => ({ ...s, isOpen }));
const onCloseAction = React.useCallback(() => {
setState((s) => ({ ...s, isOpen: !s.isOpen }));
onClose?.();
}, [onClose]);
const popstate = React.useCallback(() => {
window.removeEventListener("popstate", popstate, false);
onCloseAction();
window.history.go(1);
}, [onCloseAction]);
React.useEffect(() => {
return () => {
window.removeEventListener("popstate", popstate, false);
};
}, [popstate]);
React.useEffect(() => {
toggle(opened || false);
}, [opened]);
React.useEffect(() => {
if (opened && state.displayType === "aside") {
window.addEventListener("popstate", popstate, false);
}
}, [opened, popstate, state.displayType]);
React.useEffect(() => {
setState((s) => ({ ...s, displayType: getTypeByWidth() }));
}, [displayType, getTypeByWidth]);
const onIconButtonClick = (e: React.MouseEvent) => {
if (isDisabled || state.displayType === "toggle") {
stopAction(e);
return;
}
setState((s) => ({ ...s, data: getData(), isOpen: !state.isOpen }));
if (!isDisabled && state.isOpen) onClick?.(e);
};
const clickOutsideAction = (e: Event) => {
const path = e.composedPath();
const dropDownItem = path
? path.find((x: EventTarget) => x === ref.current)
: null;
if (dropDownItem) return;
onCloseAction();
};
const onDropDownItemClick = (
item: ContextMenuModel,
e: React.MouseEvent | React.ChangeEvent<HTMLInputElement>,
) => {
if ("onClick" in item) {
const open = state.displayType === "dropdown";
item.onClick?.({ originalEvent: e, action: open, item });
toggle(!state.isOpen);
}
};
const callNewMenu = (e: React.MouseEvent) => {
if (isDisabled || state.displayType !== "toggle") {
stopAction(e);
return;
}
setState((s) => ({ ...s, data: getData() }));
onClick?.(e);
};
const iconButtonName = state.isOpen && iconOpenName ? iconOpenName : iconName;
return (
<StyledOuter
ref={ref}
className={className}
id={id}
style={style}
onClick={callNewMenu}
displayIconBorder={displayIconBorder}
data-testid="context-menu-button"
>
<IconButton
className={iconClassName}
color={color}
hoverColor={hoverColor}
clickColor={clickColor}
size={size}
iconName={iconButtonName}
iconHoverName={iconHoverName}
iconClickName={iconClickName}
isFill={isFill}
isDisabled={isDisabled}
onClick={onIconButtonClick}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
onMouseDown={onMouseOver}
onMouseUp={onMouseOut}
title={title}
/>
{displayType === "dropdown" ? (
<DropDown
className={dropDownClassName}
directionX={directionX}
directionY={directionY}
open={state.isOpen}
forwardedRef={ref}
clickOutsideAction={clickOutsideAction}
columnCount={columnCount}
withBackdrop={isTablet() || isMobile() || Tablet}
zIndex={zIndex}
isDefaultMode={usePortal}
>
{state.data?.map(
(item: ContextMenuModel, index: number) =>
item && (
<DropDownItem
{...item}
id={item.id}
key={item.key || index}
label={"label" in item ? item.label : ""}
onClick={(
e: React.MouseEvent | React.ChangeEvent<HTMLInputElement>,
) => onDropDownItemClick(item, e)}
/>
),
)}
</DropDown>
) : (
displayType === "aside" && (
<>
<Backdrop
onClick={onCloseAction}
visible={state.isOpen}
zIndex={310}
isAside
/>
<Aside
visible={state.isOpen || false}
scale={false}
zIndex={310}
onClose={onCloseAction}
>
<StyledContent>
<StyledHeaderContent>
<Heading
className="header"
size={HeadingSize.medium}
truncate
>
{asideHeader}
</Heading>
</StyledHeaderContent>
<StyledBodyContent>
{state.data.map(
(item: ContextMenuModel, index: number) =>
item && (
<Link
className={`context-menu-button_link${
"isHeader" in item && item.isHeader ? "-header" : ""
}`}
key={item.key || index}
fontSize={
"isHeader" in item && item.isHeader
? "15px"
: "13px"
}
noHover={"isHeader" in item ? item.isHeader : false}
fontWeight={600}
onClick={(e) => onDropDownItemClick(item, e)}
>
{"label" in item ? item.label : ""}
</Link>
),
)}
</StyledBodyContent>
</StyledContent>
</Aside>
</>
)
)}
</StyledOuter>
);
};
ContextMenuButtonPure.defaultProps = {
opened: false,
data: [],
title: "",
size: 16,
isDisabled: false,
directionX: "left",
isFill: false,
usePortal: true,
displayIconBorder: false,
};
export { ContextMenuButtonPure };
const compare = (
prevProps: ContextMenuButtonProps,
nextProps: ContextMenuButtonProps,
) => {
if (
prevProps.opened === nextProps.opened &&
prevProps.displayType === nextProps.displayType &&
prevProps.isDisabled === nextProps.isDisabled
) {
return false;
}
return true;
};
export const ContextMenuButton = React.memo(ContextMenuButtonPure, compare);

View File

@ -0,0 +1,68 @@
import { TDirectionX, TDirectionY } from "../../types";
import { ContextMenuModel } from "../context-menu";
import { ContextMenuButtonDisplayType } from "./ContextMenuButton.enums";
export interface ContextMenuButtonProps {
/** Sets the button to present an opened state */
opened?: boolean;
/** Array of options for display */
data: ContextMenuModel[];
/** Function for converting to inner data */
getData: () => ContextMenuModel[];
/** Specifies the icon title */
title?: string;
/** Specifies the icon name */
iconName?: string;
/** Specifies the icon size */
size?: number;
/** Specifies the icon color */
color?: string;
/** Sets the button to present a disabled state */
isDisabled?: boolean;
/** Specifies the icon hover color */
hoverColor?: string;
/** Specifies the icon click color */
clickColor?: string;
/** Specifies the icon hover name */
iconHoverName?: string;
/** Specifies the icon click name */
iconClickName?: string;
/** Specifies the icon open name */
iconOpenName?: string;
/** Triggers a callback function when the mouse enters the button borders */
onMouseEnter?: (e: React.MouseEvent) => void;
/** Triggers a callback function when the mouse leaves the button borders */
onMouseLeave?: (e: React.MouseEvent) => void;
/** Triggers a callback function when the mouse moves over the button borders */
onMouseOver?: (e: React.MouseEvent) => void;
/** Triggers a callback function when the mouse moves out of the button borders */
onMouseOut?: (e: React.MouseEvent) => void;
onClick?: (e: React.MouseEvent) => void;
/** Direction X */
directionX?: TDirectionX;
/** Direction Y */
directionY?: TDirectionY;
/** Accepts class */
className?: string;
/** Accepts id */
id?: string;
/** Accepts css style */
style?: React.CSSProperties;
/** Sets the number of columns */
columnCount?: number;
/** Sets the display type */
displayType: ContextMenuButtonDisplayType;
/** Closing event */
onClose?: () => void;
/** Sets the drop down open with the portal */
usePortal?: boolean;
/** Sets the class of the drop down element */
dropDownClassName?: string;
/** Sets the class of the icon button */
iconClassName?: string;
/** Enables displaying the icon borders */
displayIconBorder?: boolean;
isFill?: boolean;
zIndex?: number;
asideHeader?: React.ReactNode;
}

View File

@ -5,7 +5,7 @@ ContextMenuButton is used for displaying context menu actions on a list's item
### Usage
```js
import ContextMenuButton from "@docspace/components/context-menu-button";
import { ContextMenuButton } from "@docspace/shared/components";
import VerticalDotsReactSvgUrl from "PUBLIC_DIR/images/vertical-dots.react.svg?url";
```

View File

@ -10,7 +10,7 @@ export type ContextMenuType = {
item,
}: {
originalEvent: React.MouseEvent | React.ChangeEvent<HTMLInputElement>;
action?: string;
action?: string | boolean;
item: ContextMenuType;
}) => VoidFunction;
isSeparator?: undefined;
@ -22,6 +22,7 @@ export type ContextMenuType = {
style?: React.CSSProperties;
target?: string;
isLoader?: boolean;
isHeader?: boolean;
onLoad?: () => Promise<ContextMenuModel[]>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
template?: any;
@ -31,6 +32,7 @@ export type ContextMenuType = {
};
export type SeparatorType = {
id?: string;
key: string | number;
isSeparator: boolean;
disabled?: boolean;

View File

@ -10,7 +10,7 @@ export interface DropDownItemProps {
/** Accepts tab-index */
tabIndex?: number;
/** Dropdown item text */
label?: string;
label?: string | React.ReactNode;
/** Sets the dropdown item to display as disabled */
disabled?: boolean;
/** Dropdown item icon */

View File

@ -34,6 +34,7 @@ const DropDown = ({
enableKeyboardEvents,
appendTo,
eventTypes,
zIndex,
clickOutsideAction,
}: DropDownProps) => {
const theme = useTheme();
@ -378,6 +379,7 @@ const DropDown = ({
directionXStylesDisabled={directionXStylesDisabled}
isDropdownReady={state.isDropdownReady}
open={open}
zIndex={zIndex}
>
<VirtualList
Row={Row}

View File

@ -57,6 +57,7 @@ export interface DropDownProps {
eventTypes?: string[];
forceCloseClickOutside?: boolean;
withoutBackground?: boolean;
zIndex?: number;
}
export interface VirtualListProps {