import { Collapse, createStyles, Flex, Stack, Text } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; import { IconChevronDown, IconGripVertical } from '@tabler/icons'; import { Reorder, useDragControls } from 'framer-motion'; import { FC, ReactNode, useEffect, useRef } from 'react'; import { IDraggableListInputValue } from '../../../../widgets/widgets'; const useStyles = createStyles((theme) => ({ container: { display: 'flex', flexDirection: 'column', borderRadius: theme.radius.md, border: `1px solid ${ theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[2] }`, backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.white, marginBottom: theme.spacing.xs, }, row: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '12px 16px', gap: theme.spacing.sm, }, middle: { flexGrow: 1, }, symbol: { fontSize: 16, }, clickableIcons: { color: theme.colorScheme === 'dark' ? theme.colors.dark[1] : theme.colors.gray[6], cursor: 'pointer', userSelect: 'none', transition: 'transform .3s ease-in-out', }, rotate: { transform: 'rotate(180deg)', }, collapseContent: { padding: '12px 16px', }, })); type DraggableListParams = { value: IDraggableListInputValue['defaultValue']; onChange: (value: IDraggableListInputValue['defaultValue']) => void; labels: Record; children?: Record; }; export const DraggableList: FC = (props) => { const keys = props.value.map((v) => v.key); return (
props.onChange(order.map((key) => props.value.find((v) => v.key === key)!)) } as="div" > {props.value.map((item) => ( {props.children?.[item.key]} ))}
); }; const ListItem: FC<{ item: IDraggableListInputValue['defaultValue'][number]; label: string; }> = (props) => { const { classes, cx } = useStyles(); const controls = useDragControls(); const [opened, handlers] = useDisclosure(false); const hasContent = props.children != null && Object.keys(props.children).length !== 0; // Workaround for mobile drag controls not working // https://github.com/framer/motion/issues/1597#issuecomment-1235026724 const dragRef = useRef(null); useEffect(() => { const touchHandler: EventListener = (e) => e.preventDefault(); const dragItem = dragRef.current; if (dragItem) { dragItem.addEventListener('touchstart', touchHandler, { passive: false }); return () => { dragItem.removeEventListener('touchstart', touchHandler); }; } return undefined; }, [dragRef]); return (
controls.start(e)}>
{props.label}
{hasContent && ( handlers.toggle()} size={18} stroke={1.5} /> )}
{hasContent && ( {props.children} )}
); };