react-beautiful-dnd#Droppable TypeScript Examples
The following examples show how to use
react-beautiful-dnd#Droppable.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: FlowList.tsx From Protoman with MIT License | 6 votes |
FlowList: React.FunctionComponent<Props> = ({ collectionName }) => {
const dispatch = useDispatch();
const collection = useSelector((s: AppState) => getByKey(s.collections, collectionName));
const flowNames = useSelector((s: AppState) => collection?.flows?.map(([n]) => n));
const isCurrentCollection = useSelector((s: AppState) => s.currentCollection === collectionName);
const currentFlow = useSelector((s: AppState) => s.currentFlow);
function handleSelection(flowName: string): void {
dispatch(selectFlow(collectionName, flowName));
}
function validateFlowName(flowName: string): boolean {
return !collection?.flows?.map(([n]) => n)?.includes(flowName);
}
function handleDelete(flowName: string): void {
const flowCount = collection?.flows?.length || 0;
if (flowCount > 1) {
dispatch(deleteFlow(collectionName, flowName));
} else {
message.error("Can't delete the last request");
}
}
function handleClone(originalFlowName: string): void {
//check if this clone already exists
const tmpName = originalFlowName.concat('_clone');
let tmpNameIdx = 1;
while (!validateFlowName(`${tmpName}${tmpNameIdx}`)) tmpNameIdx++;
dispatch(cloneFlow(collectionName, originalFlowName, `${tmpName}${tmpNameIdx}`));
}
function handleDragEnd(result: DropResult): void {
console.log(result);
if (!result.destination || result.source.droppableId != result.destination.droppableId) return;
const src = result.source.index;
const dst = result.destination.index;
dispatch(reorderFlow(collectionName, src, dst));
}
return (
<DragDropContext onDragEnd={handleDragEnd}>
<Droppable droppableId={collectionName}>
{(provided): React.ReactElement => (
<div {...provided.droppableProps} ref={provided.innerRef}>
<List
dataSource={flowNames}
rowKey={(name): string => name}
renderItem={(flowName, idx): React.ReactNode => (
<FlowCell
idx={idx}
flowName={flowName}
emphasize={isCurrentCollection && currentFlow === flowName}
handleSelection={handleSelection}
handleDelete={handleDelete}
handleClone={handleClone}
/>
)}
/>
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
);
}
Example #2
Source File: DragndropPostList.tsx From clearflask with Apache License 2.0 | 6 votes |
DragndropPostList = React.memo((props: {
droppable?: boolean;
droppableId: string;
dragSelectedTourAnchorProps?: React.ComponentProps<typeof TourAnchor>;
} & React.ComponentProps<typeof PostList>) => {
const { droppable, droppableId, ...PostListProps } = props;
return (
<Droppable droppableId={droppableId} isDropDisabled={!droppable}>
{(providedDroppable, snapshotDroppable) => (
<>
<DragndropPostListDroppableInner
providedDroppableInnerRef={providedDroppable.innerRef}
PostListProps={PostListProps}
DroppableProvidedProps={providedDroppable.droppableProps}
dragSelectedTourAnchorProps={props.dragSelectedTourAnchorProps}
/>
{providedDroppable.placeholder && (<div style={{ display: 'none' }}>{providedDroppable.placeholder}</div>)}
</>
)}
</Droppable>
);
}, customReactMemoEquals({ nested: new Set(['dragSelectedTourAnchorProps', 'PostListProps', 'DroppableProvidedProps']) }))
Example #3
Source File: AddButtonMappingDialog.tsx From Pi-Tool with GNU General Public License v3.0 | 6 votes |
ButtonActionCreator: React.FC<{ buttonDuration: ButtonPress }> = ({ buttonDuration }) => {
const draggableId = uuidv4();
return (
<Droppable droppableId="PALETTE" direction="horizontal" isDropDisabled={true}>
{(provided, _snapshot) => (
<div ref={provided.innerRef} {...provided.droppableProps}>
<Box width={1} style={{ display: 'inline-flex', verticalAlign: 'middle', alignItems: 'center' }}>
<Draggable key={draggableId} draggableId={draggableId} index={buttonDuration as number}>
{(provided, snapshot) => (
<Box style={{ width: 50, height: 50 }}>
<div
style={{ width: 50, height: 50 }}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}>
<ButtonPressIcon press={buttonDuration} isButton={true} />
</div>
{snapshot.isDragging &&
<ButtonPressIcon press={buttonDuration} isButton={true} />
}
</Box>
)}
</Draggable>
<Typography>
{buttonDuration === ButtonPress.Short ? "Short button press" : "Long button press"}
</Typography>
</Box>
</div>
)}
</Droppable>
);
}
Example #4
Source File: next-item-list.tsx From wikitrivia with MIT License | 6 votes |
export default function NextItemList(props: NextItemListProps) {
const { next } = props;
return (
<div className={styles.container}>
<Droppable droppableId="next" direction="horizontal">
{(provided) => (
<div className={styles.wrapper}>
<div
ref={provided.innerRef}
{...provided.droppableProps}
className={styles.list}
>
{next && (
<ItemCard draggable index={0} item={next} key={next.id} />
)}
{provided.placeholder}
</div>
</div>
)}
</Droppable>
</div>
);
}
Example #5
Source File: SearchSidebar.tsx From peterportal-client with MIT License | 6 votes |
SearchSidebar = () => {
const dispatch = useAppDispatch();
return (
<div className="search-sidebar" >
{isMobile && <div><CloseButton className='close-icon' onClick={() => { dispatch(setShowSearch(false)) }} /></div>}
<div className='search-body'>
<Droppable droppableId="search" type="COURSE">
{(provided) => {
return (
<div
ref={provided.innerRef}
style={{ height: "100%" }}
{...provided.droppableProps}
>
<div className='search-sidebar-content'>
<div className='search-sidebar-search-module'>
<SearchModule index='courses' />
</div>
<SearchHitContainer index='courses' CourseHitItem={CourseHitItem} />
</div>
{provided.placeholder}
</div>
);
}}
</Droppable>
</div>
</div>
);
}
Example #6
Source File: TaskList.tsx From knboard with MIT License | 6 votes |
TaskList = ({ columnId, listType, tasks: tasks, index }: Props) => (
<Droppable droppableId={columnId.toString()} type={listType}>
{(
dropProvided: DroppableProvided,
dropSnapshot: DroppableStateSnapshot
) => (
<Wrapper
isDraggingOver={dropSnapshot.isDraggingOver}
isDraggingFrom={Boolean(dropSnapshot.draggingFromThisWith)}
{...dropProvided.droppableProps}
>
<InnerList
columnId={columnId}
tasks={tasks}
dropProvided={dropProvided}
index={index}
/>
</Wrapper>
)}
</Droppable>
)
Example #7
Source File: bodywrapper.tsx From gant-design with MIT License | 6 votes |
BodyWrapper = ({ children, ...props }) => {
const { onDragEnd } = useContext(TableBodyWrapperContext)
return (
<DragDropContext onDragEnd={onDragEnd} >
<Droppable droppableId='droppable'>
{
(provided, snapshot) => {
return (
<tbody {...props} ref={provided.innerRef} {...provided.droppableProps}>
{children}
{provided.placeholder}
</tbody>
)
}
}
</Droppable>
</DragDropContext>
)
}
Example #8
Source File: index.tsx From S2 with MIT License | 5 votes |
Dimension: React.FC<DimensionProps> = React.memo((props) => {
const {
fieldType,
crossRows,
expandable,
expandText = i18n('展开子项'),
allowEmpty,
items,
droppableType,
...rest
} = props;
const [expandChildren, setExpandChildren] = React.useState(true);
const SWITCHER_CONFIG = React.useMemo(getSwitcherConfig, []);
const onUpdateExpand = (event: CheckboxChangeEvent) => {
setExpandChildren(event.target.checked);
};
// 开启不允许为空后,如果当前有且仅有一个item时,需要禁用拖动
const isDragDisabled = !allowEmpty && items.length === 1;
const { text, icon: Icon } = SWITCHER_CONFIG[fieldType];
return (
<div
className={cx(getSwitcherClassName(CLASS_NAME_PREFIX), {
'long-dimension': crossRows,
})}
>
<div className={getSwitcherClassName(CLASS_NAME_PREFIX, 'header')}>
<div className="title">
<Icon /> <span>{text}</span>
</div>
{expandable && (
<div className={'expand-option'}>
<Checkbox checked={expandChildren} onChange={onUpdateExpand} />
<span className="description">{expandText}</span>
</div>
)}
</div>
<Droppable droppableId={fieldType} type={droppableType}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.droppableProps}
className={cx(getSwitcherClassName(CLASS_NAME_PREFIX, 'items'), {
[getSwitcherClassName(CLASS_NAME_PREFIX, 'items-highlight')]:
snapshot.isDraggingOver,
[getSwitcherClassName(CLASS_NAME_PREFIX, 'long-items')]:
crossRows,
})}
>
{items.map((item: SwitcherItem, index: number) => (
<DimensionItem
key={item.id}
index={index}
fieldType={fieldType}
item={item}
expandable={expandable}
expandChildren={expandChildren}
isDragDisabled={isDragDisabled}
{...rest}
/>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</div>
);
})
Example #9
Source File: BoardColumn.tsx From projectboard with MIT License | 5 votes |
IssueCol = ({ title, status, tasks }: Props) => {
let statusIcon = <StatusIcon status={status} />;
let tasksItems = (tasks || []).map((task, idx) => <BoardItem task={task} index={idx} />);
const history = useHistory();
const match = useRouteMatch<MatchParams>();
const onAddClick = () => {
history.push(`/projects/${match.params.projectId}/create-task`, {
status
});
};
return (
<div className="flex flex-col flex-shrink-0 mr-3 select-none w-90">
<div className="flex items-center justify-between pb-3 text-sm">
{/* left info */}
<div className="flex items-center">
{statusIcon}
<span className="ml-3 mr-3 font-medium">{title}</span>
<span className="mr-3 font-normal text-gray-400">{tasks?.length || 0}</span>
</div>
{/* action buttons */}
<div className="flex items-center">
<button
onClick={onAddClick}
className="flex items-center justify-center border-none rounded h-7 w-7 hover:bg-gray-200 focus:outline-none"
>
<AddIcon className="w-3.5 text-gray-400 hover:text-gray-700" />
</button>
</div>
</div>
<Droppable droppableId={status} key={status} type="category">
{(provided: DroppableProvided) => {
return (
<div
ref={provided.innerRef}
{...provided.droppableProps}
className="flex flex-col flex-1 w-full overflow-y-auto border-gray-200 pt-0.5"
>
{React.Children.toArray(tasksItems)}
{provided.placeholder}
</div>
);
}}
</Droppable>
</div>
);
}
Example #10
Source File: DashboardQuickActions.tsx From clearflask with Apache License 2.0 | 5 votes |
QuickActionArea = (props: {
droppableId: string;
isDragging: boolean;
feedback?: FeedbackInstance | null;
enabled?: boolean;
onClick?: (droppableId: string) => Promise<any>;
color?: string;
title?: string;
}) => {
const { t } = useTranslation('app');
const theme = useTheme();
const classes = useStyles();
const [autoDragging, setAutoDragging] = useState<boolean>(false);
return (
<RenderControl freezeInitialRender={props.isDragging}>
<HoverArea>
{(hoverAreaProps, isHovering, isHoverDown) => (
<Droppable
droppableId={props.droppableId}
ignoreContainerClipping
isDropDisabled={!props.enabled || (!isHovering && !autoDragging)}
>
{(provided, snapshot) => (
<CardActionArea
{...hoverAreaProps}
ref={provided.innerRef}
{...provided.droppableProps}
disabled={!props.enabled}
className={classNames(
classes.postAction,
!props.enabled && classes.postActionDisabled,
)}
style={!props.enabled ? {
color: theme.palette.text.disabled,
} : {
color: props.color,
borderColor: props.color || fade(theme.palette.common.black, 0.54),
background: !snapshot.isDraggingOver ? undefined : fade(props.color || theme.palette.common.black, 0.1),
}}
onClick={async e => {
if (!props.enabled || !props.onClick) return;
setAutoDragging(true);
try {
await props.onClick(props.droppableId);
} finally {
setAutoDragging(false);
}
}}
>
{provided.placeholder && (<div style={{ display: 'none' }}>{provided.placeholder}</div>)}
{props.title && (
<Typography>{t(props.title as any)}</Typography>
)}
</CardActionArea>
)}
</Droppable>
)}
</HoverArea>
</RenderControl>
);
}
Example #11
Source File: index.tsx From nextjs-hasura-fullstack with MIT License | 5 votes |
ListBoard: React.FC<ListBoardProps> = ({ list, index }) => {
return (
<Draggable draggableId={`${list.id}`} index={index} key={list.id}>
{({ innerRef, dragHandleProps, draggableProps }, { isDragging }) => {
return (
<div
ref={innerRef}
{...draggableProps}
className={`flex flex-col mx-4`}
>
<Card
className={`w-72 bg-white flex flex-col ${
isDragging && `border-purple-600`
}`}
>
<CardHeader
action={<ActionDropdown list={list} />}
{...dragHandleProps}
className={`hover:bg-purple-50`}
>
<ListHeader list={list} />
</CardHeader>
<Droppable
type="CARD"
direction="vertical"
key={list.id}
droppableId={`${list.id}`}
>
{(
{ innerRef, droppableProps, placeholder },
{ isDraggingOver },
) => (
<CardBody
ref={innerRef}
{...droppableProps}
className={`${isDraggingOver && `bg-purple-400 border-2`}`}
>
{list.cards.map((card, index) => (
<CardTask key={card.id} card={card} index={index} />
))}
{placeholder}
</CardBody>
)}
</Droppable>
<CardFooter className={`h-14`}>
<NewCard
lastCard={list.cards[list.cards.length - 1]}
list={list}
/>
</CardFooter>
</Card>
</div>
)
}}
</Draggable>
)
}
Example #12
Source File: Column.tsx From gant-design with MIT License | 5 votes |
Column = (props) => {
const {
column,
tasks,
index,
hideQuickAdd,
isColumnDragDisabled,
isTaskDropDisabled,
...nextProps
} = props
const { prefixCls, renderHeader, renderExtra, handleAddBtn, idKey, titleKey } = useContext(TaskBoardContext)
return <Draggable
index={index}
draggableId={column[idKey]}
isDragDisabled={isColumnDragDisabled}
>
{(provided, snapshot) => (
<div
className={prefixCls + '-column-wrapper'}
ref={provided.innerRef}
{...provided.draggableProps}
>
<div
className={prefixCls + '-column-container'}
style={{
boxShadow: `${snapshot.isDragging ? 'rgba(0, 0, 0, 0.2) 2px 2px 1px' : ''}`,
}}
>
<div {...provided.dragHandleProps}>
{renderHeader === null ? null :
renderHeader ? renderHeader(column) :
<div className={prefixCls + '-column-header-wrapper'}>
<Tooltip title={column[titleKey]} mouseEnterDelay={0.3} placement="topLeft">
<div className={prefixCls + '-column-header-title'}>
{column[titleKey]}{tasks && tasks.length > 0 ? `(${tasks.length})` : null}
</div>
</Tooltip>
<div className={prefixCls + '-column-header-extra'}>
{renderExtra && renderExtra(column)}
</div>
</div>
}
</div>
<Droppable
droppableId={column[idKey]}
type='task'
isDropDisabled={isTaskDropDisabled}
>
{(provided, snapshot) => (
<div
className={prefixCls + '-task-drop-inner'}
ref={provided.innerRef}
{...provided.droppableProps}
>
<TaskList tasks={tasks} column={column} {...nextProps} />
{provided.placeholder}
{!hideQuickAdd && <div
className={prefixCls + '-quick-add'}
onClick={(e) => {
e.stopPropagation()
handleAddBtn && handleAddBtn(column)
}}>
<Icon type="plus" />
</div>}
</div>
)}
</Droppable>
</div>
</div>
)}
</Draggable>
}
Example #13
Source File: SidePanel.tsx From TabMerger with GNU General Public License v3.0 | 5 votes |
export default function SidePanel(): JSX.Element {
const { available } = useSelector((state) => state.groups.present);
const { inputValue, filterChoice } = useSelector((state) => state.header);
const { dragType, isDragging } = useSelector((state) => state.dnd);
const { filteredGroups, nonEmptyGroups } = useFilter();
const groupSearch = inputValue !== "" && filterChoice === "group";
const tabSearch = inputValue !== "" && filterChoice === "tab";
const currentGroups = groupSearch ? filteredGroups : tabSearch ? nonEmptyGroups : available;
const groupDrag = isGroupDrag(dragType);
const groupsContainerRef = useRef<HTMLDivElement | null>(null);
const containerHeight = useContainerHeight(groupsContainerRef);
return (
<Container>
{currentGroups.map((group) => group.id).includes(available[0].id) && <Group {...available[0]} />}
<div ref={groupsContainerRef}>
<Droppable droppableId="sidePanel" isCombineEnabled={!groupDrag}>
{(provider) => (
<DraggableContainer
ref={provider.innerRef}
{...provider.droppableProps}
$height={containerHeight}
$dragging={isDragging && groupDrag}
>
{currentGroups
.filter((group) => group.id !== available[0].id)
.map((data, i) => (
<Draggable
key={data.id + i + 1}
draggableId={`group-${i + 1}`}
index={i + 1}
isDragDisabled={groupSearch}
>
{(provided, dragSnapshot) => (
<div ref={provided.innerRef} {...provided.draggableProps}>
<Group {...data} snapshot={dragSnapshot} dragHandleProps={provided.dragHandleProps} />
</div>
)}
</Draggable>
))}
{provider.placeholder}
</DraggableContainer>
)}
</Droppable>
</div>
</Container>
);
}
Example #14
Source File: TabContainer.tsx From yana with MIT License | 5 votes |
TabContainer: React.FC<{}> = props => {
const theme = useTheme();
const mainContent = useMainContentContext();
return (
<DragDropContext
onDragEnd={(result, provided) => {
if (result.destination?.index !== undefined) {
mainContent.reorderTab(result.source.index, result.destination.index);
}
}}
>
<Droppable droppableId="tabs-droppable" direction="horizontal">
{(provided, snapshot) => (
<div className={styles.tabsContainer} ref={provided.innerRef} {...provided.droppableProps}>
{mainContent.tabs.map((tab, idx) => {
const id = tab.dataItem?.id ?? tab.page ?? 'unknown';
const name = tab.dataItem?.name ?? (tab.page ? pages[tab.page]?.title : 'Unknown name');
return (
<Draggable key={id} draggableId={id} index={idx} disableInteractiveElementBlocking={true}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
className={cx(
styles.tab,
snapshot.isDragging && styles.draggingTab,
cxs({
color:
mainContent.openTabId === idx
? 'white'
: Color(theme.topBarColor).mix(Color('#ffffff'), 0.5).toString(),
borderBottom: mainContent.openTabId === idx ? `4px solid ${theme.primaryColor}` : undefined,
fontWeight: mainContent.openTabId === idx ? 'bold' : 'normal',
backgroundColor: theme.topBarColor,
':hover': {
borderBottom: mainContent.openTabId !== idx ? `4px solid white` : undefined,
},
})
)}
onClick={() => mainContent.activateTab(idx)}
>
{name.substr(0, 12)}
{name.length > 12 ? '...' : ''}
<div
className={cx(
styles.closeContainer,
cxs({
backgroundColor: theme.topBarColor,
})
)}
onClick={e => {
e.stopPropagation();
mainContent.closeTab(idx);
}}
>
<Icon icon={'cross'} />
</div>
</div>
)}
</Draggable>
);
})}
</div>
)}
</Droppable>
</DragDropContext>
);
}
Example #15
Source File: Form.demo.dnd.tsx From mantine with MIT License | 5 votes |
function Demo() {
const form = useForm({
initialValues: {
employees: formList([
{ name: 'John Doe', email: '[email protected]' },
{ name: 'Bill Love', email: '[email protected]' },
{ name: 'Nancy Eagle', email: '[email protected]' },
{ name: 'Lim Notch', email: '[email protected]' },
{ name: 'Susan Seven', email: '[email protected]' },
]),
},
});
const fields = form.values.employees.map((_, index) => (
<Draggable key={index} index={index} draggableId={index.toString()}>
{(provided) => (
<Group ref={provided.innerRef} mt="xs" {...provided.draggableProps}>
<Center {...provided.dragHandleProps}>
<GripVertical size={18} />
</Center>
<TextInput
placeholder="John Doe"
{...form.getListInputProps('employees', index, 'name')}
/>
<TextInput
placeholder="[email protected]"
{...form.getListInputProps('employees', index, 'email')}
/>
</Group>
)}
</Draggable>
));
return (
<Box sx={{ maxWidth: 500 }} mx="auto">
<DragDropContext
onDragEnd={({ destination, source }) =>
form.reorderListItem('employees', { from: source.index, to: destination.index })
}
>
<Droppable droppableId="dnd-list" direction="vertical">
{(provided) => (
<div {...provided.droppableProps} ref={provided.innerRef}>
{fields}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
<Group position="center" mt="md">
<Button onClick={() => form.addListItem('employees', { name: '', email: '' })}>
Add employee
</Button>
</Group>
<Text size="sm" weight={500} mt="md">
Form values:
</Text>
<Code block>{JSON.stringify(form.values, null, 2)}</Code>
</Box>
);
}
Example #16
Source File: Todos.tsx From max-todos with MIT License | 5 votes |
Todos = () => {
const { todos, moveTodo } = useContext(MainContext)!;
const [deleteSnackOpen, setDeleteSnackOpen] = useState(false);
const [editSnackOpen, setEditSnackOpen] = useState(false);
const [dragging, setDragging] = useState(false);
const onDragEnd = (x: DropResult) => {
if (!x.destination) return console.log(x);
moveTodo(x.source.index, x.destination.index);
setTimeout(() => setDragging(false), 200);
};
return (
<>
<DragDropContext
onBeforeDragStart={() => setDragging(true)}
onDragEnd={onDragEnd}
>
<Droppable droppableId="0">
{(p) => (
<div {...p.droppableProps} ref={p.innerRef}>
<FlipMove disableAllAnimations={dragging}>
{todos.map((todo, i) => {
return (
<Todo
todo={todo}
key={todo.id}
onDelete={() => setDeleteSnackOpen(true)}
index={i}
onEdit={() => setEditSnackOpen(true)}
/>
);
})}
</FlipMove>
{p.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
<Snackbar
open={deleteSnackOpen}
autoHideDuration={4000}
onClose={() => setDeleteSnackOpen(false)}
anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
>
<Alert
elevation={6}
variant="filled"
onClose={() => setDeleteSnackOpen(false)}
severity="success"
>
Successfully deleted item!
</Alert>
</Snackbar>
<Snackbar
open={editSnackOpen}
autoHideDuration={4000}
onClose={() => setEditSnackOpen(false)}
anchorOrigin={{ vertical: "bottom", horizontal: "right" }}
>
<Alert
elevation={6}
variant="filled"
onClose={() => setEditSnackOpen(false)}
severity="success"
>
Successfully edited item!
</Alert>
</Snackbar>
</>
);
}
Example #17
Source File: Tree.tsx From react-beautiful-tree with Apache License 2.0 | 5 votes |
render() {
const {
isNestingEnabled,
isVirtualizationEnabled,
virtualItemHeight,
} = this.props
const { flattenedTree } = this.state
const renderedItems = this.renderItems()
return (
<DragDropContext
onDragStart={this.onDragStart}
onDragEnd={this.onDragEnd}
onDragUpdate={this.onDragUpdate}
>
<Droppable
droppableId="tree"
isCombineEnabled={isNestingEnabled}
ignoreContainerClipping
mode={isVirtualizationEnabled ? 'virtual' : 'standard'}
renderClone={
isVirtualizationEnabled
? (provided, snapshot, rubric) =>
this.renderVirtualItem({
provided,
snapshot,
flatItem: flattenedTree[rubric.source.index],
})
: undefined
}
>
{(provided: DroppableProvided) => {
const finalProvided: DroppableProvided = this.patchDroppableProvided(
provided
)
return isVirtualizationEnabled ? (
<AutoSizer defaultHeight={1} defaultWidth={1}>
{({ height, width }: { height: number; width: number }) => (
<FixedSizeList
height={height}
itemCount={flattenedTree.length}
itemSize={virtualItemHeight}
width={width}
outerRef={provided.innerRef}
itemData={flattenedTree}
>
{this.renderVirtualRow}
</FixedSizeList>
)}
</AutoSizer>
) : (
<div
ref={finalProvided.innerRef}
style={{ pointerEvents: 'auto' }}
onTouchMove={this.onPointerMove}
onMouseMove={this.onPointerMove}
{...finalProvided.droppableProps}
>
{renderedItems}
{provided.placeholder}
</div>
)
}}
</Droppable>
</DragDropContext>
)
}
Example #18
Source File: StatOptionList.tsx From slippi-stats with MIT License | 5 votes |
StatOptionList: React.FC<StatOptionListProps> = (props) => {
const statOptions = props.value;
const onDragEnd = (result: any) => {
const { destination, source } = result;
if (!destination) {
return;
}
if (destination.droppableId === source.droppableId && destination.index === source.index) {
return;
}
const newArray = reorder(props.value, source.index, destination.index);
props.onChange(newArray);
};
const toggle = (statId: string) => {
const optionIndex = statOptions.findIndex((o) => o.statId === statId);
if (optionIndex === -1) {
return;
}
const newOptions = Array.from(statOptions);
const option = newOptions[optionIndex];
option.enabled = !option.enabled;
props.onChange(newOptions);
};
return (
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="stat-option-list">
{(provided) => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{statOptions.map((option, i) => {
return (
<StatOptionItem
key={option.statId}
index={i}
id={option.statId}
checked={option.enabled}
onChange={() => toggle(option.statId)}
/>
);
})}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
);
}
Example #19
Source File: DraggableTags.tsx From nebula-studio with Apache License 2.0 | 5 votes |
render() {
const list = this.props.data.map(item => ({
id: `field-${item}`,
content: (
<Tag className={styles.dragItem} closable={true} onClose={() => this.props.removeData(item)}>
{item}
</Tag>
),
}));
return (
<DragDropContext onDragEnd={this.onDragEnd}>
<Droppable droppableId="droppable" direction="horizontal">
{(provided, _snapshot) => (
<div
{...provided.droppableProps}
ref={provided.innerRef}
style={{
display: 'flex',
overflow: 'auto',
flexWrap: 'wrap',
}}
>
{list.map((item, index) => (
<Draggable key={item.id} draggableId={item.id} index={index}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={getItemStyle(
snapshot.isDragging,
provided.draggableProps.style,
)}
>
{item.content}
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
);
}
Example #20
Source File: AddButtonMappingDialog.tsx From Pi-Tool with GNU General Public License v3.0 | 5 votes |
ButtonActionGrid: React.FC<{ buttonPresses: ButtonPressItems }> = ({ buttonPresses }) => {
const classes = useStyles();
return (
<Paper className={classes.buttonActionGrid} variant="outlined">
<Droppable
droppableId="GRID"
direction="horizontal"
isDropDisabled={buttonPresses.length >= 8}>
{(provided, snapshot) => (
<div
className={classes.buttonActionDroppable}
ref={provided.innerRef}
style={{ display: 'inline-flex', verticalAlign: 'middle', alignItems: 'center' }}
{...provided.droppableProps}>
<Box display="flex" flexDirection="row">
{buttonPresses.map((item, index) => (
<Draggable key={item.id} draggableId={item.id} index={index}>
{(provided, snapshot) => (
<div
style={getStyle(provided.draggableProps.style, snapshot)}
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}>
<ButtonPressIcon press={item.press} isButton={true} />
</div>
)}
</Draggable>
))}
</Box>
{provided.placeholder}
{/* && (buttonPresses.length == 0 && <Typography> Drag your your sequence here.</Typography>)} */}
</div>
)}
</Droppable>
</Paper>
);
}
Example #21
Source File: index.tsx From Tiquet with MIT License | 5 votes |
List = ({ id, title, tasks, onDelete, editListTitle }: IProps): JSX.Element => {
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
const handleDelete = (callback) => {
onDelete()
setDeleteModalOpen(false);
trackEvent({
category: 'Lists',
action: 'Deleted',
value: id
});
callback();
};
const getListStyles = () => ({
width: '100%',
minHeight: 5,
maxHeight: 350,
overflowY: 'auto',
overflowX: 'hidden',
display: 'flex',
flexDirection: 'column',
});
const handleEditTitle = (value, callback) => {
editListTitle(id, value);
trackEvent({
category: 'Lists',
action: 'Title edited',
value: id
});
callback();
}
return (
<div className="list">
{onDelete && (
<Fragment>
<ConfirmationModal
isOpen={deleteModalOpen}
title="DELETE LIST"
description="Are you sure you want to delete this list?. All tasks will be lost."
onSuccess={handleDelete}
onCancel={() => setDeleteModalOpen(false)}
/>
<i
onClick={() => setDeleteModalOpen(true)}
className="far fa-sm fa-trash-alt list__delete-icon"></i>
</Fragment>
)}
<div className="list__header">
<EditableText
text={title}
textClassName="list__header-title"
tag="h5"
onSuccess={handleEditTitle}
/>
</div>
<div className="list__body">
<Droppable droppableId={new Number(id).toString()} key={`${title}_${id}`}>
{(provided) => (
<div
{...provided.droppableProps}
ref={provided.innerRef}
style={getListStyles()}
>
{tasks.map((task: ITask, index: number) => (
<Task key={task.uid} {...task} index={index} />
))}
{provided.placeholder}
</div>
)}
</Droppable>
</div>
<div className="list__footer">
<CreateTask listId={id} />
</div>
</div>
);
}
Example #22
Source File: index.tsx From calories-in with MIT License | 5 votes |
function MealsList({
mealsForms,
selectedVariantFormIndex,
selectedVariantFormFieldId,
headerHeight,
onAddMeal,
...rest
}: Props) {
const getMealNameInputRefById = useGetRefForId<HTMLInputElement>()
const scrollTargetRef = useRef<HTMLDivElement>(null)
const { onScrollToMeal } = useScrollToAndFocusMeal({
scrollTargetRef,
getMealNameInputRefById,
})
const dietFormActions = useDietFormActions()
return (
<Droppable droppableId="mealsList" type="mealsList">
{(provided, snapshot) => (
<Flex ref={provided.innerRef} flexDirection="column" {...rest}>
{mealsForms.length > 0 ? (
mealsForms.map((mealForm, index) => (
<MealItem
key={mealForm.fieldId}
variantIndex={selectedVariantFormIndex}
getMealNameInputRefById={getMealNameInputRefById}
index={index}
onRemove={dietFormActions.removeMealForm}
mealForm={mealForm}
onFirstAppear={onScrollToMeal}
selectedVariantFormFieldId={selectedVariantFormFieldId}
mb={5}
isDragging={snapshot.isDraggingOver}
/>
))
) : (
<EmptyList onAddMeal={onAddMeal} />
)}
{provided.placeholder}
{mealsForms.length > 0 && (
<>
<MealsControls mealsForms={mealsForms} onAddMeal={onAddMeal} />
<Box ref={scrollTargetRef} />
</>
)}
</Flex>
)}
</Droppable>
)
}
Example #23
Source File: played-item-list.tsx From wikitrivia with MIT License | 5 votes |
export default function PlayedItemList(props: PlayedItemListProps) {
const { badlyPlacedIndex, isDragging, items } = props;
const [flippedId, setFlippedId] = React.useState<null | string>(null);
React.useEffect(() => {
if (isDragging && flippedId !== null) {
setFlippedId(null);
}
}, [flippedId, isDragging]);
return (
<div className={styles.wrapper}>
<div className={styles.listContainer}>
<Droppable droppableId="played" direction="horizontal">
{(provided) => (
<div
ref={provided.innerRef}
{...provided.droppableProps}
className={styles.list}
>
<div className={styles.timelineContainer}>
<div className={styles.timeline}></div>
</div>
<div className={styles.items}>
{items.map((item, index) => (
<ItemCard
draggable={badlyPlacedIndex !== null}
flippedId={flippedId}
index={index}
item={item}
key={item.id}
setFlippedId={setFlippedId}
/>
))}
</div>
{provided.placeholder}
</div>
)}
</Droppable>
</div>
</div>
);
}
Example #24
Source File: NetworksDnd.tsx From devex with GNU General Public License v3.0 | 5 votes |
NetworksDnd: React.FC<IProps> = ({ cards, setCards, deleteNode, editNode }) => {
const onDragEnd = (result: any) => {
if (!result.destination) {
return
}
const reorderedCards = reorder(
cards,
result.source.index,
result.destination.index
)
setCards(reorderedCards)
}
return <Container>
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="droppable">
{(provided, snapshot) => (
<div
className='dnd'
{...provided.droppableProps}
ref={provided.innerRef}
style={getListStyle(snapshot.isDraggingOver)}
>
{cards.map((card, index) => (
<Draggable key={card.id} draggableId={card.id.toString()} index={index}>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={getItemStyle(
snapshot.isDragging,
provided.draggableProps.style
)}
>
<NetworkCard
key={card.url}
url={card.url}
name={card.name}
deleteNode={deleteNode}
editNode={editNode}
/>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
</Container>
}
Example #25
Source File: designers.tsx From ali-react-table with MIT License | 5 votes |
export function CheckedDimList({ style, className, pivot }: CheckDimListProps) {
const dimMap = new Map(pivot.allDimensions.map((dim) => [dim.code, dim]))
return (
<CheckedDimListDiv style={style} className={className}>
<DragDropContext
onDragEnd={(result) => {
if (!result.destination) {
return
}
const i = result.source.index
const j = result.destination.index
const nextCodes = pivot.dimCodes.slice()
const [code] = nextCodes.splice(i, 1)
nextCodes.splice(j, 0, code)
pivot.changeDimCodes(nextCodes)
}}
>
<Droppable droppableId="dimension-list" direction="horizontal">
{(dropProvided, snapshot) => (
<div className="tag-list" ref={dropProvided.innerRef}>
{pivot.dimCodes.map((dimCode, index) => {
const allValues = pivot.dimValues[dimCode]
const values = pivot.filters[dimCode]
return (
<Draggable key={dimCode} draggableId={dimCode} index={index}>
{(dragProvided, snapshot) => (
<Overlay.Popup
key={dimCode}
trigger={
<div
key={dimCode}
ref={dragProvided.innerRef}
{...dragProvided.draggableProps}
{...dragProvided.dragHandleProps}
className={cx('tag', {
active: values.length < allValues.length,
empty: allValues.length > 0 && values.length === 0,
})}
>
{dimMap.get(dimCode).name}
<Filter16 className="filter-icon" />
</div>
}
triggerType="click"
>
<CheckedDimFilterPopup pivot={pivot} allValues={allValues} values={values} dimCode={dimCode} />
</Overlay.Popup>
)}
</Draggable>
)
})}
{dropProvided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
</CheckedDimListDiv>
)
}
Example #26
Source File: DataModelBranch.tsx From datart with Apache License 2.0 | 4 votes |
DataModelBranch: FC<{
node: Column;
onNodeTypeChange: (type: any, name: string) => void;
onMoveToHierarchy: (node: Column) => void;
onEditBranch;
onDelete: (node: Column) => void;
onDeleteFromHierarchy: (parent: Column) => (node: Column) => void;
}> = memo(
({
node,
onNodeTypeChange,
onMoveToHierarchy,
onEditBranch,
onDelete,
onDeleteFromHierarchy,
}) => {
const t = useI18NPrefix('view.model');
const [isHover, setIsHover] = useState(false);
const renderNode = (node, isDragging) => {
let icon = (
<FolderOpenOutlined style={{ alignSelf: 'center', color: YELLOW }} />
);
return (
<>
<div
className="content"
onMouseEnter={() => {
setIsHover(true);
}}
onMouseLeave={() => {
setIsHover(false);
}}
>
<IW fontSize={FONT_SIZE_HEADING}>{icon}</IW>
<span>{node.name}</span>
<div className="action">
{isHover && !isDragging && (
<Tooltip title={t('rename')}>
<Button
type="link"
onClick={() => onEditBranch(node)}
icon={<EditOutlined />}
/>
</Tooltip>
)}
{isHover && !isDragging && (
<Tooltip title={t('delete')}>
<Button
type="link"
onClick={() => onDelete(node)}
icon={<DeleteOutlined />}
/>
</Tooltip>
)}
</div>
</div>
<div className="children">
{node?.children?.map(childNode => (
<DataModelNode
className="in-hierarchy"
node={childNode}
key={childNode.name}
onMoveToHierarchy={onMoveToHierarchy}
onNodeTypeChange={onNodeTypeChange}
onDeleteFromHierarchy={onDeleteFromHierarchy(node)}
/>
))}
</div>
</>
);
};
return (
<Draggable
key={node?.name}
draggableId={node?.name}
index={node?.index}
isDragDisabled={true}
>
{(draggableProvided, draggableSnapshot) => {
return (
<StyledDataModelBranch
ref={draggableProvided.innerRef}
{...draggableProvided.draggableProps}
{...draggableProvided.dragHandleProps}
>
<Droppable
droppableId={node?.name}
type={TreeNodeHierarchy.Branch}
isCombineEnabled={false}
>
{(droppableProvided, droppableSnapshot) => (
<div ref={droppableProvided.innerRef}>
{renderNode(node, draggableSnapshot.isDragging)}
{droppableProvided.placeholder}
</div>
)}
</Droppable>
</StyledDataModelBranch>
);
}}
</Draggable>
);
},
)
Example #27
Source File: index.tsx From nanolooker with MIT License | 4 votes |
CryptocurrencyPreferences: React.FC<Props> = ({ isDetailed }) => {
const { t } = useTranslation();
const {
cryptocurrency,
addCryptocurrency,
removeCryptocurrency,
reorderCryptocurrency,
} = React.useContext(PreferencesContext);
const [search, setSearch] = React.useState<string>("");
const onSearch = (value: string) => {
setSearch(value);
};
const onSelect = (value: string) => {
const { symbol = "" } = dataSource.find(({ name }) => name === value) || {};
addCryptocurrency(symbol);
setSearch("");
};
const options = dataSource.map(({ name, symbol }) => (
<Option
key={name}
value={name}
symbol={symbol}
disabled={cryptocurrency.includes(symbol) || symbol === "nano"}
>
<img
src={`/cryptocurrencies/logo/${symbol}.png`}
alt={name}
width="16px"
height="16px"
style={{ marginRight: "6px" }}
/>
{name}
</Option>
));
const reorder = (list: string[], startIndex: number, endIndex: number) => {
const result = Array.from(list);
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
return result;
};
const onDragEnd = (result: any) => {
const items = reorder(
cryptocurrency,
result.source?.index || 0,
result.destination?.index || 0,
);
reorderCryptocurrency(items);
};
return (
<Row>
<Col xs={24}>
<Text
className={isDetailed ? "preference-detailed-title" : ""}
style={{
display: "block",
marginBottom: "6px",
}}
>
{t("preferences.watch")}
</Text>
</Col>
{isDetailed ? (
<Col xs={24} style={{ marginBottom: "6px" }}>
<Text>{t("preferences.watchDetailed")}</Text>
</Col>
) : null}
<Col xs={24} md={isDetailed ? 12 : 24}>
<AutoComplete
value={search}
style={{ width: "100%" }}
filterOption={(value = "", option) => {
const { value: name, symbol } = option as any;
return (
name.toLowerCase().includes(value.toLowerCase()) ||
symbol.toLowerCase().includes(value.toLowerCase())
);
}}
onSearch={onSearch}
onSelect={onSelect}
placeholder={t("preferences.watchSearch")}
>
{options}
</AutoComplete>
{cryptocurrency.length ? (
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId={`hello${isDetailed ? "-detailed" : ""}`}>
{(provided, snapshot) => (
<ul
style={{
margin: 0,
padding: "6px",
marginTop: "6px",
backgroundColor: snapshot.isDraggingOver
? "#1890ff24"
: "#f6f6f6",
listStyle: "none",
}}
ref={provided.innerRef}
{...provided.droppableProps}
>
{cryptocurrency.map((symbol, index) => {
const { name = "" } =
dataSource.find(
({ symbol: sourceSymbol }) => sourceSymbol === symbol,
) || {};
return (
<Draggable draggableId={name} index={index} key={name}>
{provided => {
// https://github.com/atlassian/react-beautiful-dnd/issues/1662#issuecomment-708538811
if (
typeof provided.draggableProps.onTransitionEnd ===
"function"
) {
window?.requestAnimationFrame(() =>
// @ts-ignore
provided?.draggableProps?.onTransitionEnd?.({
propertyName: "transform",
}),
);
}
return (
<li
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
width: "100%",
padding: "6px",
marginTop: "-1px",
backgroundColor: "#fff",
border: "1px solid #d9d9d9",
...(index !== cryptocurrency.length - 1
? { marginBottom: "6px" }
: { marginBottom: "-1px" }),
}}
>
<span>
<img
src={`/cryptocurrencies/logo/${symbol}.png`}
alt={name}
width="16px"
height="16px"
style={{ marginRight: "6px" }}
/>
{name}
</span>
<DeleteButton
onClick={(e: Event) => {
e.stopPropagation();
removeCryptocurrency(symbol);
}}
/>
</div>
</li>
);
}}
</Draggable>
);
})}
{provided.placeholder}
</ul>
)}
</Droppable>
</DragDropContext>
) : null}
</Col>
</Row>
);
}
Example #28
Source File: index.tsx From nextjs-hasura-fullstack with MIT License | 4 votes |
BoardPage: React.FC = () => {
const router = useRouter()
const { setLastPosition } = useLastPositionNumber()
const { data, loading } = useBoardQuery({
variables: {
id: Number(router.query.boardId),
},
skip: !router.query.boardId,
})
const [updateList] = useUpdateListMutation()
const [updateCard] = useUpdateCardMutation()
const [moveCard] = useMoveCardMutation()
const renderLists = React.useMemo(() => {
return data?.boards_by_pk?.lists || []
}, [data])
React.useEffect(() => {
setLastPosition(renderLists[renderLists.length - 1]?.position || 1)
}, [renderLists])
const onDragEnd = async (result: DropResult, provided: ResponderProvided) => {
const { source, destination, type } = result
// dropped outside the list
if (!destination) {
return
}
if (
source.droppableId === destination.droppableId &&
source.index === destination.index
) {
return
}
// DragDrop a "List"
if (type === 'LIST') {
const updatedPosition = getUpdatePositionReorder(
renderLists,
source.index,
destination.index,
)
const sourceList = renderLists[source.index]
updateList({
variables: {
id: sourceList.id,
name: sourceList.name,
position: updatedPosition,
},
update: (cache, { data }) => {
if (data?.update_lists_by_pk) {
const cacheId = cache.identify({
__typename: 'boards',
id: sourceList.board_id,
})
if (cacheId) {
cache.modify({
id: cacheId,
fields: {
lists(existingListRefs = []) {
return reorder(
existingListRefs,
source.index,
destination.index,
)
},
},
})
}
}
},
optimisticResponse: (variables) => {
return {
__typename: 'mutation_root',
update_lists_by_pk: {
...sourceList,
position: updatedPosition,
},
}
},
})
}
if (type === 'CARD') {
/* same list: reorder card */
if (source.droppableId === destination.droppableId) {
const listCards = renderLists.find(
(item) => item.id === Number(source.droppableId),
)?.cards
if (!listCards) {
return
}
const updatedPosition = getUpdatePositionReorder(
listCards,
source.index,
destination.index,
)
const sourceCard = listCards[source.index]
await updateCard({
variables: {
id: sourceCard.id,
title: sourceCard.title,
position: updatedPosition,
},
update: (cache, { data }) => {
if (data?.update_cards_by_pk) {
const cacheId = cache.identify({
__typename: 'lists',
id: sourceCard.list_id,
})
if (cacheId) {
cache.modify({
id: cacheId,
fields: {
cards(existingCardRefs = []) {
return reorder(
existingCardRefs,
source.index,
destination.index,
)
},
},
})
}
}
},
optimisticResponse: (variables) => {
return {
__typename: 'mutation_root',
update_cards_by_pk: {
...sourceCard,
position: updatedPosition,
},
}
},
})
} else {
/**
* Diferent list: move card
*/
const sourceListCards = renderLists.find(
(item) => item.id === Number(source.droppableId),
)?.cards
const destinationListCards = renderLists.find(
(item) => item.id === Number(destination.droppableId),
)?.cards
if (!sourceListCards || !destinationListCards) {
return
}
const updatedPosition = getUpdatePositionMove(
sourceListCards,
destinationListCards,
source.index,
destination.index,
)
const sourceCard = sourceListCards[source.index]
await moveCard({
variables: {
id: sourceCard.id,
list_id: Number(destination.droppableId),
title: sourceCard.title,
position: updatedPosition,
},
update: (cache, { data }) => {
if (data?.update_cards_by_pk) {
const cardCacheId = cache.identify(data.update_cards_by_pk)
if (!cardCacheId) {
return
}
const cacheId = cache.identify({
__typename: 'lists',
id: source.droppableId,
})
if (cacheId) {
cache.modify({
id: cacheId,
fields: {
cards(existingRefs = []) {
const next = existingRefs.filter(
(listRef: { __ref: string }) =>
listRef.__ref !== cardCacheId,
)
return next
},
},
})
}
const cacheIdDestination = cache.identify({
__typename: 'lists',
id: destination.droppableId,
})
if (cacheIdDestination) {
cache.modify({
id: cacheIdDestination,
fields: {
cards(existingCardRefs = [], { toReference }) {
const moveRef = toReference(cardCacheId)
if (moveRef) {
const next = produce(
existingCardRefs as any[],
(draftState) => {
draftState.splice(destination.index, 0, moveRef)
},
)
return next
}
},
},
})
}
}
},
optimisticResponse: () => ({
__typename: 'mutation_root',
update_cards_by_pk: {
...sourceCard,
position: updatedPosition,
},
}),
})
}
}
}
let listRender
if (loading) {
listRender = (
<div className={`flex flex-no-wrap min-w-max-content`}>
{[...Array(3)].map((item, idx) => (
<div
key={idx}
className="flex flex-col max-w-sm p-4 mx-4 space-y-3 border border-gray-300 rounded-md shadow w-72"
>
<div className="flex space-x-4 animate-pulse">
<div className="flex-1 py-1 space-y-4">
<div className="w-3/4 h-4 bg-gray-400 rounded"></div>
{/* <div className="space-y-2">
<div className="h-4 bg-gray-400 rounded"></div>
<div className="w-5/6 h-4 bg-gray-400 rounded"></div>
</div> */}
</div>
</div>
{[...Array(4)].map((item, index) => (
<div
key={index}
className="flex flex-col max-w-sm p-4 border border-gray-300 rounded-md shadow"
>
<div className="flex space-x-4 animate-pulse">
<div className="flex-1 py-1 space-y-2">
<div className="h-4 bg-gray-400 rounded"></div>
<div className="w-5/6 h-4 bg-gray-400 rounded"></div>
</div>
</div>
</div>
))}
<div className="flex flex-col max-w-sm border-t border-gray-300 rounded-md shadow">
<div className="flex space-x-4 animate-pulse">
<div className="flex-1 py-1 space-y-2">
<div className="h-4 bg-gray-400 rounded"></div>
</div>
</div>
</div>
</div>
))}
{/* */}
</div>
)
} else {
listRender = (
<div className={`flex flex-no-wrap h-screen w-max-content`}>
<DragDropContext
onDragStart={(source) => {
console.log(`?? [LOG]: source`, source)
}}
// onDragUpdate={onDragUpdate}
onDragEnd={onDragEnd}
>
{/* List */}
<Droppable
droppableId="board"
type="LIST"
direction="horizontal"
// ignoreContainerClipping={true}
>
{(
{ innerRef, droppableProps, placeholder },
{ isDraggingOver },
) => {
return (
<div
ref={innerRef}
{...droppableProps}
className={`inline-flex ${isDraggingOver && ``}`}
style={{
overflowAnchor: 'none',
}}
>
{renderLists.map((list, index) => (
<ListBoard list={list} index={index} key={index} />
))}
{placeholder}
</div>
)
}}
</Droppable>
</DragDropContext>
<div className={``}>
<NewList lastId={renderLists[renderLists.length - 1]?.id || 0} />
</div>
</div>
)
}
return (
<div className={`h-screen space-x-2 -mt-14`}>
<Scrollbar noScrollY className={``}>
<div className={`pt-14`}>
<div className={`mt-4 mb-8`}>
<h2
className={`text-3xl font-semibold text-center text-cool-gray-100`}
>
{data?.boards_by_pk?.icon} {data?.boards_by_pk?.name}
</h2>
</div>
{listRender}
</div>
</Scrollbar>
</div>
)
}
Example #29
Source File: index.tsx From calories-in with MIT License | 4 votes |
function VariantsList({
onVariantFormSelect,
onVariantFormCopy,
forwardedRef = createRef(),
}: Props) {
const scrollNodeRef = useRef<HTMLDivElement>(null)
const screenSize = useScreenSize()
const isPhone = screenSize <= ScreenSize.Small
const nameModalDisclosure = useDisclosure()
const detailsModalDisclosure = useDisclosure()
const variantFormEvents = useVariantFormEvents({
onVariantFormSelect,
onVariantFormCopy,
nameModalDisclosure,
detailsModalDisclosure,
})
const dietForm = useDietForm()
const getVariantItemRefById = useGetRefForId<HTMLDivElement>()
const scrollState = useScrollState()
return (
<Flex py={6}>
<AddVariantButton onClick={variantFormEvents.onAppend} />
{!isPhone && (
<VariantsMenuOrDrawer onVariantFormSelect={onVariantFormSelect} />
)}
<Droppable
droppableId="variantsList"
type="variantsList"
direction="horizontal"
>
{provided => (
<HFadeScroll
onScrollStateChange={scrollState.onScrollStateChange}
ref={mergeRefs([provided.innerRef, scrollNodeRef, forwardedRef])}
>
{dietForm.variantsForms.map((variantForm, index) => {
return (
<VariantItem
canRemove={dietForm.variantsForms.length > 1}
mr={2}
index={index}
onDelete={variantFormEvents.onRemove}
onEditName={variantFormEvents.onRename}
onClone={variantFormEvents.onCopy}
onViewDetails={variantFormEvents.onViewDetails}
key={variantForm.fieldId}
variantForm={variantForm}
isSelected={index === dietForm.selectedVariantFormIndex}
onSelect={variantFormEvents.onSelect}
ref={getVariantItemRefById(variantForm.fieldId)}
>
{variantForm.name}
</VariantItem>
)
})}
{provided.placeholder}
</HFadeScroll>
)}
</Droppable>
{isPhone ? (
<VariantsMenuOrDrawer onVariantFormSelect={onVariantFormSelect} />
) : (
<ScrollButtons
scrollNodeRef={scrollNodeRef}
showsButtons={scrollState.showsScrollButtons}
canScrollLeft={scrollState.canScrollLeft}
canScrollRight={scrollState.canScrollRight}
/>
)}
<VariantNameModal
isOpen={nameModalDisclosure.isOpen}
onClose={nameModalDisclosure.onClose}
variantFormIndex={variantFormEvents.variantFormIndex}
/>
{variantFormEvents.variantForm && (
<VariantsDetailsModal
isOpen={detailsModalDisclosure.isOpen}
onClose={detailsModalDisclosure.onClose}
initialVariantForm={variantFormEvents.variantForm}
/>
)}
</Flex>
)
}