DEV;Add MenuItem new option - onClick
This commit is contained in:
parent
4658595a62
commit
e3b89dabac
7 changed files with 46 additions and 37 deletions
|
@ -6,15 +6,17 @@ import ChevronDownIcon from '@treejs/components/Icons/ChevronDown';
|
|||
import ChevronUpIcon from '@treejs/components/Icons/ChevronUp';
|
||||
import { isNilOrEmpty } from '@treejs/utils';
|
||||
|
||||
import { IMenuItem } from '../types';
|
||||
import { MenuItem } from '../types';
|
||||
|
||||
type IProps = {
|
||||
isChild: boolean;
|
||||
onClick: (href: string, external: boolean) => () => void;
|
||||
} & IMenuItem;
|
||||
item: MenuItem;
|
||||
onClick: (menuItem: MenuItem) => void;
|
||||
};
|
||||
|
||||
export const SidebarMenuItem = (props: IProps) => {
|
||||
const { defaultOpen, href, onClick, isChild, label, external, subMenu } = props;
|
||||
const { onClick, isChild, item } = props;
|
||||
const { defaultOpen, href, label, subMenu } = item;
|
||||
|
||||
const [open, setOpen] = useState(defaultOpen);
|
||||
|
||||
|
@ -24,16 +26,16 @@ export const SidebarMenuItem = (props: IProps) => {
|
|||
|
||||
const handleOnClick = useCallback(() => {
|
||||
if (!isNilOrEmpty(href)) {
|
||||
onClick(href, external)();
|
||||
onClick(item);
|
||||
} else {
|
||||
setOpen(!open);
|
||||
}
|
||||
}, [open, href, external]);
|
||||
}, [open, item]);
|
||||
|
||||
const items = useMemo(() => {
|
||||
if (open && !isNilOrEmpty(subMenu)) {
|
||||
return subMenu.map((menuItem, i) => (
|
||||
<SidebarMenuItem key={i} isChild={true} onClick={onClick} {...menuItem} />
|
||||
return subMenu.map((subMenuItem, i) => (
|
||||
<SidebarMenuItem key={i} isChild={true} item={subMenuItem} onClick={onClick} />
|
||||
));
|
||||
} else {
|
||||
return null;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { isNil } from 'ramda';
|
||||
|
||||
import cx from 'classnames';
|
||||
import { History } from 'history';
|
||||
|
@ -9,7 +10,7 @@ import { isNilOrEmpty } from '@treejs/utils';
|
|||
|
||||
import Modals from '../../Modal/components/Modals';
|
||||
import Toasters from '../../Toaster/components/Toasters';
|
||||
import { IMenuItem } from '../types';
|
||||
import { MenuItem } from '../types';
|
||||
import SidebarMenuItem from './SidebarMenuItem';
|
||||
import UserMenu from './UserMenu';
|
||||
|
||||
|
@ -27,9 +28,9 @@ type IProps = {
|
|||
};
|
||||
history: History;
|
||||
menuItems?: {
|
||||
navigation?: IMenuItem[];
|
||||
sidebar?: IMenuItem[];
|
||||
user?: IMenuItem[];
|
||||
navigation?: MenuItem[];
|
||||
sidebar?: MenuItem[];
|
||||
user?: MenuItem[];
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -61,11 +62,15 @@ const Skeleton: React.FC<IProps> = (props) => {
|
|||
}, [sidebarOpened]);
|
||||
|
||||
const openLink = useCallback(
|
||||
(link: string, external: boolean) => () => {
|
||||
if (external) {
|
||||
window.open(link, '_blank');
|
||||
({ href, external, onClick }: MenuItem) => {
|
||||
if (!isNil(onClick)) {
|
||||
onClick();
|
||||
} else {
|
||||
history.push(link);
|
||||
if (external) {
|
||||
window.open(href, '_blank');
|
||||
} else {
|
||||
history.push(href);
|
||||
}
|
||||
}
|
||||
setSidebarOpened(false);
|
||||
},
|
||||
|
@ -75,7 +80,7 @@ const Skeleton: React.FC<IProps> = (props) => {
|
|||
const sidebarItems = useMemo(() => {
|
||||
if (!isNilOrEmpty(menuItems.sidebar)) {
|
||||
return menuItems.sidebar.map((menuItem, i) => (
|
||||
<SidebarMenuItem key={i} isChild={false} onClick={openLink} {...menuItem} />
|
||||
<SidebarMenuItem key={i} isChild={false} onClick={openLink} item={menuItem} />
|
||||
));
|
||||
} else {
|
||||
return null;
|
||||
|
@ -84,9 +89,10 @@ const Skeleton: React.FC<IProps> = (props) => {
|
|||
|
||||
const navigationItems = useMemo(() => {
|
||||
if (!isNilOrEmpty(menuItems.navigation)) {
|
||||
return menuItems.navigation.map(({ label, href, external }, i) => (
|
||||
<div key={i} className="navigation-item" onClick={openLink(href, external)}>
|
||||
{label}
|
||||
return menuItems.navigation.map((menuItem, i) => (
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
<div key={i} className="navigation-item" onClick={() => openLink(menuItem)}>
|
||||
{menuItem.label}
|
||||
</div>
|
||||
));
|
||||
} else {
|
||||
|
|
|
@ -2,24 +2,22 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|||
|
||||
import { isNilOrEmpty } from '@treejs/utils';
|
||||
|
||||
import { IMenuItem } from '../types';
|
||||
import { MenuItem } from '../types';
|
||||
|
||||
type IProps = {
|
||||
children: React.ReactElement;
|
||||
items: IMenuItem[];
|
||||
onClick: (href: string, external: boolean) => () => void;
|
||||
items: MenuItem[];
|
||||
onClick: (menuItem: MenuItem) => void;
|
||||
};
|
||||
|
||||
export const UserMenu = (props: IProps) => {
|
||||
const { items, onClick, children } = props;
|
||||
|
||||
export const UserMenu: React.FC<IProps> = ({ items, onClick, children }) => {
|
||||
const divRef = useRef<HTMLDivElement>();
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleClick = useCallback(
|
||||
(href: string, external: boolean) => () => {
|
||||
onClick(href, external)();
|
||||
(item: MenuItem) => () => {
|
||||
onClick(item);
|
||||
setOpen(false);
|
||||
},
|
||||
[onClick]
|
||||
|
@ -37,9 +35,9 @@ export const UserMenu = (props: IProps) => {
|
|||
|
||||
const userItems = useMemo(() => {
|
||||
if (!isNilOrEmpty(items)) {
|
||||
return items.map(({ label, href, external }, i) => (
|
||||
<div key={i} className="user-item" onClick={handleClick(href, external)}>
|
||||
{label}
|
||||
return items.map((menuItem, i) => (
|
||||
<div key={i} className="user-item" onClick={handleClick(menuItem)}>
|
||||
{menuItem.label}
|
||||
</div>
|
||||
));
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
export interface IMenuItem {
|
||||
export type MenuItem = {
|
||||
defaultOpen?: boolean;
|
||||
external?: boolean;
|
||||
href?: string;
|
||||
label: string;
|
||||
subMenu?: IMenuItem[];
|
||||
}
|
||||
onClick?: () => void;
|
||||
subMenu?: MenuItem[];
|
||||
};
|
||||
|
|
|
@ -41,10 +41,11 @@ export const Template = (args) => (
|
|||
{ label: 'Menu External', href: 'https://treejs.romanjaros.dev', external: true },
|
||||
],
|
||||
sidebar: [{ label: 'Menu 1' }, { label: 'Menu 2' }],
|
||||
user: [{ label: 'Menu 1' }, { label: 'Menu 2', href: '/r3' }],
|
||||
user: [{ label: 'Menu 1', href: '/ru1' }, { label: 'Menu 2', href: '/ru2' }],
|
||||
},
|
||||
enabledMenu: {
|
||||
user: true,
|
||||
navigation: true,
|
||||
sidebar: true,
|
||||
},
|
||||
}}
|
||||
|
|
|
@ -7,7 +7,8 @@ const Router = () => (
|
|||
<Route path="/" element={<div>Main</div>} />
|
||||
<Route path="/r1" element={<div>Conten 1</div>} />
|
||||
<Route path="/r2" element={<div>Conten 2</div>} />
|
||||
<Route path="/r3" element={<div>User content 2</div>} />
|
||||
<Route path="/ru1" element={<div>User content 1</div>} />
|
||||
<Route path="/ru2" element={<div>User content 2</div>} />
|
||||
</Routes>
|
||||
);
|
||||
|
||||
|
|
|
@ -24,6 +24,6 @@ const composeSetup = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
|
|||
const store = createStore(mainReducer, composeSetup(applyMiddleware(thunk)));
|
||||
|
||||
// eslint-disable-next-line react/display-name
|
||||
const StoreProvider: React.FC = ({ children }) => <Provider store={store}>{children}</Provider>;
|
||||
const StoreProvider: React.FC = ({ children }: any) => <Provider store={store}>{children}</Provider>;
|
||||
|
||||
export default StoreProvider;
|
||||
|
|
Loading…
Add table
Reference in a new issue