import type { Story, Meta } from '@storybook/react'; import { useState } from 'react'; import Button from '@mui/material/Button'; import type { ButtonProps } from '@mui/material/Button'; import { arrayMove } from '../../../utils'; import { DropdownMenu } from '../dropdown-menu'; import { DropDownMenuProps } from '../types'; export default { component: DropdownMenu, title: 'Forms/Dropdown Menu', argTypes: { listItems: { description: 'The items which will be shown in the list.' }, multiple: { description: 'Allow multiple selection. Notice your selection logic should also support multiple selection.' }, showSelectedIcon: { description: 'Whether or not to show selected icon on single selection.' }, search: { description: 'Whether or not to allow searching items inside the menu, notice you must pass `handleSearchChangeCallback` to make it work.' }, searchPlaceholder: { description: 'Place holder for the search field.' }, deletable: { description: 'Whether or not to show the delete icon for menu items, notice you must pass `handleDelete` to make it work.' }, arrowSide: { description: 'On which side to show the menu arrow.', options: ['topLeft', 'topRight'], control: { type: 'select' }, defaultValue: { summary: 'topLeft' } }, anchorElTopAddition: { description: 'Specify top addition to place the menu correctly relative to the anchor component.' }, leftAddition: { description: 'Specify left addition to place the menu correctly relative to the anchor component.' }, width: { description: 'The width of the menu.' }, sortable: { description: 'Whether or not to show the sort icon for menu items, notice you must pass `onSortEnd` to make it work.' }, onSortEnd: { description: 'Callback which is fired on sort end.' }, handleSearchChangeCallback: { description: 'Callback which is fired on search text change.' }, bottomButtonText: { description: 'If passed, a button will appear in the bottom of the menu, pass `bottomButtonClickHandler` to make it work.' }, bottomButtonClickHandler: { description: 'Call back which will be fired on click the bottom button.' }, handleDelete: { description: 'Call back which will be fired on click a delete icon.' }, handleClick: { description: 'Call back which will be fired on clicking a menu item.' }, anchorEl: { description: "A HTML element, or a function that returns it. It's used to set the position of the menu." } } } as Meta; const Template: Story = args => { const { multiple } = args; const [anchorEl, setAnchorEl] = useState<(EventTarget & HTMLButtonElement) | null>(null); const handleClick: ButtonProps['onClick'] = event => { setAnchorEl(event && event.currentTarget); }; const handleClose = () => { setAnchorEl(null); }; const [listItems, setListItems] = useState(args.listItems); const handleMenuClick: NonNullable = value => () => { const newItems = listItems.map(item => { if (multiple && item.name === value) { return { ...item, selected: !item.selected }; } if (!multiple && (item.name === value || item.selected)) { return { ...item, selected: !item.selected }; } return item; }); setListItems(newItems); handleClose(); }; const handleDelete: DropDownMenuProps['handleDelete'] = value => e => { e.stopPropagation(); setListItems(listItems.filter(item => item.name !== value)); }; const onSortEnd: DropDownMenuProps['onSortEnd'] = sortArgs => { const { oldIndex, newIndex } = sortArgs; if (oldIndex !== newIndex) { const newArray = arrayMove(listItems, oldIndex, newIndex); setListItems(newArray); } }; const handleSearchChangeCallback: DropDownMenuProps['handleSearchChangeCallback'] = value => { if (!value) { return setListItems(args.listItems); } return setListItems( args.listItems.filter(item => item.name.toString().toLowerCase().includes(value)) ); }; return ( <> ); }; export const ButtonWithMenu = Template.bind({}); ButtonWithMenu.args = { ariaLabel: 'User Menu Links', listItems: [{ name: 'Profile' }, { name: 'My account' }, { name: 'Logout' }], multiple: false, showSelectedIcon: true, search: false, deletable: false, sortable: false, width: 200, arrowSide: 'topLeft', searchPlaceholder: 'Search placeholder', anchorElTopAddition: 10, leftAddition: -12, bottomButtonText: 'Bottom button' };