Chore: Improve dropdown draggable list (#1738)
* draggable menu item component * Menu item isDragged prop removed * Droppable list component * Draggablee item component * Drag and drop use refactor * lint fix * isDragDisabled check on DraggableItem * revert changes on non visibility items * MenuItemDraggable stroybook * DraggableItem storybook * lint fix * lint fix * BoardColumnMenu css fix * showGrip prop addition * isDragged css fix
This commit is contained in:
@ -24,7 +24,6 @@ import { BoardColumnHotkeyScope } from '../types/BoardColumnHotkeyScope';
|
|||||||
|
|
||||||
import { BoardColumnEditTitleMenu } from './BoardColumnEditTitleMenu';
|
import { BoardColumnEditTitleMenu } from './BoardColumnEditTitleMenu';
|
||||||
const StyledMenuContainer = styled.div`
|
const StyledMenuContainer = styled.div`
|
||||||
left: 26.5px;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: ${({ theme }) => theme.spacing(10)};
|
top: ${({ theme }) => theme.spacing(10)};
|
||||||
width: 200px;
|
width: 200px;
|
||||||
|
|||||||
@ -0,0 +1,53 @@
|
|||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { IconBell } from '@/ui/icon';
|
||||||
|
import { MenuItemDraggable } from '@/ui/menu-item/components/MenuItemDraggable';
|
||||||
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
|
import { DraggableItem } from '../components/DraggableItem';
|
||||||
|
import { DroppableList } from '../components/DroppableList';
|
||||||
|
|
||||||
|
const meta: Meta<typeof DraggableItem> = {
|
||||||
|
title: 'ui/draggable-list/DraggableItem',
|
||||||
|
component: DraggableItem,
|
||||||
|
decorators: [
|
||||||
|
(Story, { parameters }) => (
|
||||||
|
<DroppableList
|
||||||
|
droppableId={parameters.droppableId}
|
||||||
|
onDragEnd={parameters.onDragEnd}
|
||||||
|
draggableItems={<Story />}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
ComponentDecorator,
|
||||||
|
],
|
||||||
|
parameters: {
|
||||||
|
droppableId: 'droppable',
|
||||||
|
onDragEnd: () => console.log('dragged'),
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
draggableId: 'draggable-1',
|
||||||
|
key: 'key-1',
|
||||||
|
index: 0,
|
||||||
|
isDragDisabled: false,
|
||||||
|
itemComponent: (
|
||||||
|
<>
|
||||||
|
<MenuItemDraggable
|
||||||
|
LeftIcon={IconBell}
|
||||||
|
key="key-1"
|
||||||
|
text="Draggable item 1"
|
||||||
|
/>
|
||||||
|
<MenuItemDraggable
|
||||||
|
LeftIcon={IconBell}
|
||||||
|
key="key-2"
|
||||||
|
text="Draggable item 2"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof DraggableItem>;
|
||||||
|
|
||||||
|
export const Default: Story = {};
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useTheme } from '@emotion/react';
|
||||||
|
import { Draggable } from '@hello-pangea/dnd';
|
||||||
|
|
||||||
|
type DraggableItemProps = {
|
||||||
|
key: string;
|
||||||
|
draggableId: string;
|
||||||
|
isDragDisabled?: boolean;
|
||||||
|
index: number;
|
||||||
|
itemComponent: JSX.Element;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DraggableItem = ({
|
||||||
|
key,
|
||||||
|
draggableId,
|
||||||
|
isDragDisabled = false,
|
||||||
|
index,
|
||||||
|
itemComponent,
|
||||||
|
}: DraggableItemProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
return (
|
||||||
|
<Draggable
|
||||||
|
key={key}
|
||||||
|
draggableId={draggableId}
|
||||||
|
index={index}
|
||||||
|
isDragDisabled={isDragDisabled}
|
||||||
|
>
|
||||||
|
{(draggableProvided, draggableSnapshot) => {
|
||||||
|
const draggableStyle = draggableProvided.draggableProps.style;
|
||||||
|
const isDragged = draggableSnapshot.isDragging;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={draggableProvided.innerRef}
|
||||||
|
{...{
|
||||||
|
...draggableProvided.draggableProps,
|
||||||
|
style: {
|
||||||
|
...draggableStyle,
|
||||||
|
left: 'auto',
|
||||||
|
top: 'auto',
|
||||||
|
transform: draggableStyle?.transform?.replace(
|
||||||
|
/\(-?\d+px,/,
|
||||||
|
'(0,',
|
||||||
|
),
|
||||||
|
background: isDragged
|
||||||
|
? theme.background.transparent.light
|
||||||
|
: 'none',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
{...draggableProvided.dragHandleProps}
|
||||||
|
>
|
||||||
|
{itemComponent}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</Draggable>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
import styled from '@emotion/styled';
|
||||||
|
import {
|
||||||
|
DragDropContext,
|
||||||
|
Droppable,
|
||||||
|
OnDragEndResponder,
|
||||||
|
} from '@hello-pangea/dnd';
|
||||||
|
|
||||||
|
type DroppableListProps = {
|
||||||
|
droppableId: string;
|
||||||
|
draggableItems: React.ReactNode;
|
||||||
|
onDragEnd: OnDragEndResponder;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyledDragDropItemsWrapper = styled.div`
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DroppableList = ({
|
||||||
|
droppableId,
|
||||||
|
draggableItems,
|
||||||
|
onDragEnd,
|
||||||
|
}: DroppableListProps) => {
|
||||||
|
return (
|
||||||
|
<DragDropContext onDragEnd={onDragEnd}>
|
||||||
|
<StyledDragDropItemsWrapper>
|
||||||
|
<Droppable droppableId={droppableId}>
|
||||||
|
{(provided) => (
|
||||||
|
<div ref={provided.innerRef} {...provided.droppableProps}>
|
||||||
|
{draggableItems}
|
||||||
|
{provided.placeholder}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Droppable>
|
||||||
|
</StyledDragDropItemsWrapper>
|
||||||
|
</DragDropContext>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,11 +1,13 @@
|
|||||||
import { MouseEvent } from 'react';
|
import { MouseEvent } from 'react';
|
||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
import { FloatingIconButtonGroup } from '@/ui/button/components/FloatingIconButtonGroup';
|
import { FloatingIconButtonGroup } from '@/ui/button/components/FloatingIconButtonGroup';
|
||||||
import { IconComponent } from '@/ui/icon/types/IconComponent';
|
import { IconComponent } from '@/ui/icon/types/IconComponent';
|
||||||
|
|
||||||
import { MenuItemLeftContent } from '../internals/components/MenuItemLeftContent';
|
import { MenuItemLeftContent } from '../internals/components/MenuItemLeftContent';
|
||||||
import { StyledMenuItemBase } from '../internals/components/StyledMenuItemBase';
|
import {
|
||||||
|
StyledHoverableMenuItemBase,
|
||||||
|
StyledMenuItemLeftContent,
|
||||||
|
} from '../internals/components/StyledMenuItemBase';
|
||||||
import { MenuItemAccent } from '../types/MenuItemAccent';
|
import { MenuItemAccent } from '../types/MenuItemAccent';
|
||||||
|
|
||||||
export type MenuItemIconButton = {
|
export type MenuItemIconButton = {
|
||||||
@ -14,7 +16,6 @@ export type MenuItemIconButton = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type MenuItemProps = {
|
export type MenuItemProps = {
|
||||||
isDraggable?: boolean;
|
|
||||||
LeftIcon?: IconComponent | null;
|
LeftIcon?: IconComponent | null;
|
||||||
accent?: MenuItemAccent;
|
accent?: MenuItemAccent;
|
||||||
text: string;
|
text: string;
|
||||||
@ -24,25 +25,7 @@ export type MenuItemProps = {
|
|||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledHoverableMenuItemBase = styled(StyledMenuItemBase)`
|
|
||||||
& .hoverable-buttons {
|
|
||||||
opacity: 0;
|
|
||||||
pointer-events: none;
|
|
||||||
position: fixed;
|
|
||||||
right: ${({ theme }) => theme.spacing(2)};
|
|
||||||
transition: opacity ${({ theme }) => theme.animation.duration.instant}s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
& .hoverable-buttons {
|
|
||||||
opacity: 1;
|
|
||||||
pointer-events: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const MenuItem = ({
|
export const MenuItem = ({
|
||||||
isDraggable,
|
|
||||||
LeftIcon,
|
LeftIcon,
|
||||||
accent = 'default',
|
accent = 'default',
|
||||||
text,
|
text,
|
||||||
@ -60,11 +43,9 @@ export const MenuItem = ({
|
|||||||
className={className}
|
className={className}
|
||||||
accent={accent}
|
accent={accent}
|
||||||
>
|
>
|
||||||
<MenuItemLeftContent
|
<StyledMenuItemLeftContent>
|
||||||
isDraggable={isDraggable ? true : false}
|
<MenuItemLeftContent LeftIcon={LeftIcon ?? undefined} text={text} />
|
||||||
LeftIcon={LeftIcon ?? undefined}
|
</StyledMenuItemLeftContent>
|
||||||
text={text}
|
|
||||||
/>
|
|
||||||
<div className="hoverable-buttons">
|
<div className="hoverable-buttons">
|
||||||
{showIconButtons && (
|
{showIconButtons && (
|
||||||
<FloatingIconButtonGroup iconButtons={iconButtons} />
|
<FloatingIconButtonGroup iconButtons={iconButtons} />
|
||||||
|
|||||||
@ -0,0 +1,52 @@
|
|||||||
|
import { FloatingIconButtonGroup } from '@/ui/button/components/FloatingIconButtonGroup';
|
||||||
|
import { IconComponent } from '@/ui/icon/types/IconComponent';
|
||||||
|
|
||||||
|
import { MenuItemLeftContent } from '../internals/components/MenuItemLeftContent';
|
||||||
|
import { StyledHoverableMenuItemBase } from '../internals/components/StyledMenuItemBase';
|
||||||
|
import { MenuItemAccent } from '../types/MenuItemAccent';
|
||||||
|
|
||||||
|
import { MenuItemIconButton } from './MenuItem';
|
||||||
|
|
||||||
|
export type MenuItemDraggableProps = {
|
||||||
|
key: string;
|
||||||
|
LeftIcon: IconComponent | undefined;
|
||||||
|
accent?: MenuItemAccent;
|
||||||
|
iconButtons?: MenuItemIconButton[];
|
||||||
|
onClick?: () => void;
|
||||||
|
text: string;
|
||||||
|
isDragDisabled?: boolean;
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
export const MenuItemDraggable = ({
|
||||||
|
key,
|
||||||
|
LeftIcon,
|
||||||
|
accent = 'default',
|
||||||
|
iconButtons,
|
||||||
|
onClick,
|
||||||
|
text,
|
||||||
|
isDragDisabled = false,
|
||||||
|
className,
|
||||||
|
}: MenuItemDraggableProps) => {
|
||||||
|
const showIconButtons = Array.isArray(iconButtons) && iconButtons.length > 0;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledHoverableMenuItemBase
|
||||||
|
data-testid={key ?? undefined}
|
||||||
|
onClick={onClick}
|
||||||
|
accent={accent}
|
||||||
|
className={className}
|
||||||
|
>
|
||||||
|
<MenuItemLeftContent
|
||||||
|
LeftIcon={LeftIcon}
|
||||||
|
text={text}
|
||||||
|
key={key}
|
||||||
|
showGrip={!isDragDisabled}
|
||||||
|
/>
|
||||||
|
<div className="hoverable-buttons">
|
||||||
|
{showIconButtons && (
|
||||||
|
<FloatingIconButtonGroup iconButtons={iconButtons} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</StyledHoverableMenuItemBase>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -4,7 +4,10 @@ import { IconChevronRight } from '@/ui/icon';
|
|||||||
import { IconComponent } from '@/ui/icon/types/IconComponent';
|
import { IconComponent } from '@/ui/icon/types/IconComponent';
|
||||||
|
|
||||||
import { MenuItemLeftContent } from '../internals/components/MenuItemLeftContent';
|
import { MenuItemLeftContent } from '../internals/components/MenuItemLeftContent';
|
||||||
import { StyledMenuItemBase } from '../internals/components/StyledMenuItemBase';
|
import {
|
||||||
|
StyledMenuItemBase,
|
||||||
|
StyledMenuItemLeftContent,
|
||||||
|
} from '../internals/components/StyledMenuItemBase';
|
||||||
|
|
||||||
export type MenuItemProps = {
|
export type MenuItemProps = {
|
||||||
LeftIcon?: IconComponent;
|
LeftIcon?: IconComponent;
|
||||||
@ -23,7 +26,9 @@ export const MenuItemNavigate = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledMenuItemBase onClick={onClick} className={className}>
|
<StyledMenuItemBase onClick={onClick} className={className}>
|
||||||
<MenuItemLeftContent LeftIcon={LeftIcon} text={text} />
|
<StyledMenuItemLeftContent>
|
||||||
|
<MenuItemLeftContent LeftIcon={LeftIcon} text={text} />
|
||||||
|
</StyledMenuItemLeftContent>
|
||||||
<IconChevronRight size={theme.icon.size.sm} />
|
<IconChevronRight size={theme.icon.size.sm} />
|
||||||
</StyledMenuItemBase>
|
</StyledMenuItemBase>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -0,0 +1,107 @@
|
|||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { IconBell, IconMinus } from '@/ui/icon';
|
||||||
|
import {
|
||||||
|
CatalogDecorator,
|
||||||
|
CatalogDimension,
|
||||||
|
CatalogOptions,
|
||||||
|
} from '~/testing/decorators/CatalogDecorator';
|
||||||
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
|
import { MenuItemAccent } from '../../types/MenuItemAccent';
|
||||||
|
import { MenuItemDraggable } from '../MenuItemDraggable';
|
||||||
|
|
||||||
|
const meta: Meta<typeof MenuItemDraggable> = {
|
||||||
|
title: 'ui/MenuItem/MenuItemDraggable',
|
||||||
|
component: MenuItemDraggable,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof MenuItemDraggable>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
args: {
|
||||||
|
key: 'key-1',
|
||||||
|
LeftIcon: IconBell,
|
||||||
|
accent: 'default',
|
||||||
|
iconButtons: [{ Icon: IconMinus, onClick: () => console.log('Clicked') }],
|
||||||
|
onClick: () => console.log('Clicked'),
|
||||||
|
text: 'Menu item draggable',
|
||||||
|
isDragDisabled: false,
|
||||||
|
},
|
||||||
|
decorators: [ComponentDecorator],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Catalog: Story = {
|
||||||
|
args: { ...Default.args },
|
||||||
|
argTypes: {
|
||||||
|
accent: { control: false },
|
||||||
|
iconButtons: { control: false },
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
pseudo: { hover: ['.hover'] },
|
||||||
|
catalog: {
|
||||||
|
dimensions: [
|
||||||
|
{
|
||||||
|
name: 'isDragDisabled',
|
||||||
|
values: [true, false],
|
||||||
|
props: (isDragDisabled: boolean) => ({
|
||||||
|
isDragDisabled: isDragDisabled,
|
||||||
|
}),
|
||||||
|
labels: (isDragDisabled: boolean) =>
|
||||||
|
isDragDisabled ? 'Without drag icon' : 'With drag icon',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'accents',
|
||||||
|
values: ['default', 'danger', 'placeholder'] as MenuItemAccent[],
|
||||||
|
props: (accent: MenuItemAccent) => ({ accent }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'states',
|
||||||
|
values: ['default', 'hover'],
|
||||||
|
props: (state: string) => {
|
||||||
|
switch (state) {
|
||||||
|
case 'default':
|
||||||
|
return {};
|
||||||
|
case 'hover':
|
||||||
|
return { className: state };
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'iconButtons',
|
||||||
|
values: ['no icon button', 'minus icon buttons'],
|
||||||
|
props: (choice: string) => {
|
||||||
|
switch (choice) {
|
||||||
|
case 'no icon button': {
|
||||||
|
return {
|
||||||
|
iconButtons: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'minus icon buttons': {
|
||||||
|
return {
|
||||||
|
iconButtons: [
|
||||||
|
{
|
||||||
|
Icon: IconMinus,
|
||||||
|
onClick: () =>
|
||||||
|
console.log('Clicked on minus icon button'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
] as CatalogDimension[],
|
||||||
|
options: {
|
||||||
|
elementContainer: {
|
||||||
|
width: 200,
|
||||||
|
},
|
||||||
|
} as CatalogOptions,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
decorators: [CatalogDecorator],
|
||||||
|
};
|
||||||
@ -10,21 +10,21 @@ import {
|
|||||||
} from './StyledMenuItemBase';
|
} from './StyledMenuItemBase';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
isDraggable?: boolean;
|
|
||||||
LeftIcon: IconComponent | null | undefined;
|
LeftIcon: IconComponent | null | undefined;
|
||||||
|
showGrip?: boolean;
|
||||||
text: string;
|
text: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MenuItemLeftContent = ({
|
export const MenuItemLeftContent = ({
|
||||||
isDraggable,
|
|
||||||
LeftIcon,
|
LeftIcon,
|
||||||
text,
|
text,
|
||||||
|
showGrip = false,
|
||||||
}: OwnProps) => {
|
}: OwnProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledMenuItemLeftContent>
|
<StyledMenuItemLeftContent>
|
||||||
{isDraggable && (
|
{showGrip && (
|
||||||
<IconGripVertical
|
<IconGripVertical
|
||||||
size={theme.icon.size.md}
|
size={theme.icon.size.md}
|
||||||
stroke={theme.icon.stroke.sm}
|
stroke={theme.icon.stroke.sm}
|
||||||
|
|||||||
@ -88,3 +88,20 @@ export const StyledMenuItemRightContent = styled.div`
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const StyledHoverableMenuItemBase = styled(StyledMenuItemBase)`
|
||||||
|
& .hoverable-buttons {
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
position: fixed;
|
||||||
|
right: ${({ theme }) => theme.spacing(2)};
|
||||||
|
transition: opacity ${({ theme }) => theme.animation.duration.instant}s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
& .hoverable-buttons {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|||||||
@ -1,21 +1,20 @@
|
|||||||
import styled from '@emotion/styled';
|
|
||||||
import {
|
import {
|
||||||
DragDropContext,
|
|
||||||
Draggable,
|
|
||||||
Droppable,
|
|
||||||
DropResult,
|
DropResult,
|
||||||
OnDragEndResponder,
|
OnDragEndResponder,
|
||||||
ResponderProvided,
|
ResponderProvided,
|
||||||
} from '@hello-pangea/dnd';
|
} from '@hello-pangea/dnd';
|
||||||
|
|
||||||
|
import { DraggableItem } from '@/ui/draggable-list/components/DraggableItem';
|
||||||
|
import { DroppableList } from '@/ui/draggable-list/components/DroppableList';
|
||||||
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
||||||
import { StyledDropdownMenuSubheader } from '@/ui/dropdown/components/StyledDropdownMenuSubheader';
|
import { StyledDropdownMenuSubheader } from '@/ui/dropdown/components/StyledDropdownMenuSubheader';
|
||||||
import { IconMinus, IconPlus } from '@/ui/icon';
|
import { IconMinus, IconPlus } from '@/ui/icon';
|
||||||
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
|
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
|
||||||
|
import { MenuItemDraggable } from '@/ui/menu-item/components/MenuItemDraggable';
|
||||||
|
|
||||||
import { ViewFieldForVisibility } from '../types/ViewFieldForVisibility';
|
import { ViewFieldForVisibility } from '../types/ViewFieldForVisibility';
|
||||||
|
|
||||||
type OwnProps = {
|
type ViewFieldsVisibilityDropdownSectionProps = {
|
||||||
fields: ViewFieldForVisibility[];
|
fields: ViewFieldForVisibility[];
|
||||||
onVisibilityChange: (field: ViewFieldForVisibility) => void;
|
onVisibilityChange: (field: ViewFieldForVisibility) => void;
|
||||||
title: string;
|
title: string;
|
||||||
@ -23,17 +22,13 @@ type OwnProps = {
|
|||||||
onDragEnd?: OnDragEndResponder;
|
onDragEnd?: OnDragEndResponder;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledDropdownMenuItemWrapper = styled.div`
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const ViewFieldsVisibilityDropdownSection = ({
|
export const ViewFieldsVisibilityDropdownSection = ({
|
||||||
fields,
|
fields,
|
||||||
onVisibilityChange,
|
onVisibilityChange,
|
||||||
title,
|
title,
|
||||||
isDraggable,
|
isDraggable,
|
||||||
onDragEnd,
|
onDragEnd,
|
||||||
}: OwnProps) => {
|
}: ViewFieldsVisibilityDropdownSectionProps) => {
|
||||||
const handleOnDrag = (result: DropResult, provided: ResponderProvided) => {
|
const handleOnDrag = (result: DropResult, provided: ResponderProvided) => {
|
||||||
onDragEnd?.(result, provided);
|
onDragEnd?.(result, provided);
|
||||||
};
|
};
|
||||||
@ -54,57 +49,31 @@ export const ViewFieldsVisibilityDropdownSection = ({
|
|||||||
<StyledDropdownMenuSubheader>{title}</StyledDropdownMenuSubheader>
|
<StyledDropdownMenuSubheader>{title}</StyledDropdownMenuSubheader>
|
||||||
<StyledDropdownMenuItemsContainer>
|
<StyledDropdownMenuItemsContainer>
|
||||||
{isDraggable && (
|
{isDraggable && (
|
||||||
<DragDropContext onDragEnd={handleOnDrag}>
|
<DroppableList
|
||||||
<StyledDropdownMenuItemWrapper>
|
droppableId="droppable"
|
||||||
<Droppable droppableId="droppable">
|
onDragEnd={handleOnDrag}
|
||||||
{(provided) => (
|
draggableItems={
|
||||||
<div ref={provided.innerRef} {...provided.droppableProps}>
|
<>
|
||||||
{fields.map((field, index) => (
|
{fields.map((field, index) => (
|
||||||
<Draggable
|
<DraggableItem
|
||||||
|
key={field.key}
|
||||||
|
draggableId={field.key}
|
||||||
|
index={index}
|
||||||
|
isDragDisabled={index === 0}
|
||||||
|
itemComponent={
|
||||||
|
<MenuItemDraggable
|
||||||
key={field.key}
|
key={field.key}
|
||||||
draggableId={field.key}
|
LeftIcon={field.Icon}
|
||||||
index={index}
|
iconButtons={getIconButtons(index, field)}
|
||||||
|
text={field.name}
|
||||||
isDragDisabled={index === 0}
|
isDragDisabled={index === 0}
|
||||||
>
|
/>
|
||||||
{(draggableProvided) => {
|
}
|
||||||
const draggableStyle =
|
/>
|
||||||
draggableProvided.draggableProps.style;
|
))}
|
||||||
|
</>
|
||||||
return (
|
}
|
||||||
<div
|
/>
|
||||||
ref={draggableProvided.innerRef}
|
|
||||||
{...{
|
|
||||||
...draggableProvided.draggableProps,
|
|
||||||
style: {
|
|
||||||
...draggableStyle,
|
|
||||||
left: 'auto',
|
|
||||||
top: 'auto',
|
|
||||||
transform: draggableStyle?.transform?.replace(
|
|
||||||
/\(-?\d+px,/,
|
|
||||||
'(0,',
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
{...draggableProvided.dragHandleProps}
|
|
||||||
>
|
|
||||||
<MenuItem
|
|
||||||
isDraggable={index !== 0 && isDraggable}
|
|
||||||
key={field.key}
|
|
||||||
LeftIcon={field.Icon}
|
|
||||||
iconButtons={getIconButtons(index, field)}
|
|
||||||
text={field.name}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Draggable>
|
|
||||||
))}
|
|
||||||
{provided.placeholder}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Droppable>
|
|
||||||
</StyledDropdownMenuItemWrapper>
|
|
||||||
</DragDropContext>
|
|
||||||
)}
|
)}
|
||||||
{!isDraggable &&
|
{!isDraggable &&
|
||||||
fields.map((field) => (
|
fields.map((field) => (
|
||||||
|
|||||||
Reference in New Issue
Block a user