react-dnd#useDrag TypeScript Examples
The following examples show how to use
react-dnd#useDrag.
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: Box.tsx From jetlinks-ui-antd with MIT License | 6 votes |
Box: React.FC<BoxProps> = ({ name, type, isDropped }) => {
const [{ opacity }, drag] = useDrag({
item: { name, type },
collect: monitor => ({
opacity: monitor.isDragging() ? 0.4 : 1,
}),
})
return (
<div ref={drag} style={{ ...style, opacity }}>
{isDropped ? <s>{name}</s> : name}
</div>
)
}
Example #2
Source File: index.tsx From redux-with-domain with MIT License | 6 votes |
FieldItem: FC<Props> = props => {
const { field } = props
const [_, dragRef] = useDrag({
item: { type: 'FIELD', id: field.id }
})
return (
<div className="item" ref={dragRef}>
<FieldIcon />
<span>{field.name}</span>
</div>
)
}
Example #3
Source File: WorkoutCard.tsx From calendar-hack with MIT License | 6 votes |
WorkoutCard: React.FC<WorkoutCardProps> = ({ dayDetails, date, units, swap }) => {
const [{ isDragging }, drag, preview] = useDrag({
item: { date: date, type: ItemTypes.DAY, dayDetails: dayDetails, units: units },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
canDrag: dayDetails !== undefined,
}),
end: (item: { date: Date } | undefined, monitor: DragSourceMonitor) => {
const dropResult = monitor.getDropResult()
if (item && dropResult) {
}
},
})
return (
<Card>
<Dateline dayDetails={dayDetails} units={units} date={date} />
<DragSource isDragging={isDragging} dayDetails={dayDetails} ref={preview}>
<Preview generator={generateDayPreview} />
<Content>
<div ref={drag}>
<DragHandle viewBox="0 0 32 36" />
</div>
<p>{renderDesc(dayDetails, dayDetails.sourceUnits, units)}</p>
</Content>
</DragSource>
</Card >
);
}
Example #4
Source File: DragItem.tsx From gio-design with Apache License 2.0 | 6 votes |
DragItem: React.FC<DragItemProps> = (props) => {
const { label, value, onMoved, index, disabled, ...rest } = props;
const prefixCls = `${usePrefixCls(PREFIX)}`;
const ref = useRef<HTMLDivElement>(null);
const [{ handlerId }, drop] = useDrop({
accept: 'drag-item',
collect(monitor) {
return {
handlerId: monitor.getHandlerId(),
};
},
hover(item: { index: number; type: string; id: string }, monitor: DropTargetMonitor) {
const dragIndex = item.index;
const hoverIndex = index;
if (dragIndex === hoverIndex) {
return;
}
const hoverBoundingRect = ref.current?.getBoundingClientRect() || { bottom: 0, top: 0 };
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
const clientOffset = monitor.getClientOffset();
const hoverClientY = (clientOffset as XYCoord).y - hoverBoundingRect.top;
// Dragging upwards or downwards
if ((dragIndex < hoverIndex && hoverClientY < hoverMiddleY) || (dragIndex > hoverIndex && hoverClientY > hoverMiddleY)) {
return
};
onMoved?.(dragIndex as number, hoverIndex);
// eslint-disable-next-line no-param-reassign
item.index = hoverIndex;
},
});
const [, drag] = useDrag({
item: { type: 'drag-item', id: value, index },
collect: (monitor: DragSourceMonitor) => ({
isDragging: monitor.isDragging(),
}),
canDrag: !disabled,
});
drag(drop(ref));
return (
<div
className={classNames(`${prefixCls}--item`, `${prefixCls}--item--drag`, {
[`${prefixCls}--item--disabled`]: disabled,
})}
ref={ref}
data-handler-id={handlerId}
>
<DragOutlined
className={classNames(`${prefixCls}--item--drag--icon`, {
[`${prefixCls}--item--drag--icon--disabled`]: disabled,
})}
color="#ADB2C2"
size="14px"
/>
<Item label={label} value={value} disabled={disabled} {...rest} />
</div>
);
}
Example #5
Source File: DateLevelFieldContainer.tsx From datart with Apache License 2.0 | 5 votes |
function DateLevelFieldContainer({
onClearCheckedList,
item,
colName,
}: {
onClearCheckedList?: () => any;
item: {
category: string;
expression: string;
id: string;
type: string;
};
colName: string;
}) {
const t = useI18NPrefix(`viz.workbench.dataview`);
const [, drag] = useDrag(
() => ({
type: CHART_DRAG_ELEMENT_TYPE.DATASET_COLUMN,
canDrag: true,
item: {
colName: `${colName}`,
type: item.type,
category: item.category,
expression: `${item.expression}`,
},
collect: monitor => ({
isDragging: monitor.isDragging(),
}),
end: onClearCheckedList,
}),
[],
);
return (
<ItemWrapper ref={drag}>
<CalendarOutlined style={{ color: INFO }} />
<span>
{colName}({t(item.expression)})
</span>
</ItemWrapper>
);
}
Example #6
Source File: TableOrViewSourceTree.tsx From legend-studio with Apache License 2.0 | 5 votes |
RelationalOperationElementTreeNodeContainer: React.FC<
TreeNodeContainerProps<
TableOrViewTreeNodeData,
{ selectedType?: Type | undefined }
>
> = (props) => {
const { node, level, stepPaddingInRem, onNodeSelect } = props;
const [, dragRef] = useDrag(
() => ({
type: TABLE_ELEMENT_DND_TYPE,
item: new TableOrViewTreeNodeDragSource(node),
}),
[node],
);
const isExpandable = Boolean(node.childrenIds?.length);
const nodeTypeIcon =
node instanceof ColumnNodeData ? (
renderColumnTypeIcon(node.column.type)
) : (
<PURE_DatabaseTableJoinIcon />
);
const selectNode = (): void => onNodeSelect?.(node);
const nodeExpandIcon = isExpandable ? (
node.isOpen ? (
<ChevronDownIcon />
) : (
<ChevronRightIcon />
)
) : (
<div />
);
return (
<div
className="tree-view__node__container"
onClick={selectNode}
ref={dragRef}
style={{
paddingLeft: `${(level - 1) * (stepPaddingInRem ?? 1)}rem`,
display: 'flex',
}}
>
<div className="tree-view__node__icon">
<div className="type-tree__expand-icon">{nodeExpandIcon}</div>
<div className="type-tree__type-icon">{nodeTypeIcon}</div>
</div>
<div className="tree-view__node__label type-tree__node__label">
<button tabIndex={-1} title={`${node.id}`}>
{node.label}
</button>
{node instanceof ColumnNodeData && (
<div className="type-tree__node__type">
<button
className="type-tree__node__type__label"
// TODO: match type
// className={clsx('type-tree__node__type__label', {
// 'type-tree__node__type__label--highlighted':
// primitiveType && primitiveType === selectedType,
// })}
tabIndex={-1}
title={'Column Type'}
>
{generateColumnTypeLabel(guaranteeType(node.column, Column).type)}
</button>
</div>
)}
</div>
</div>
);
}
Example #7
Source File: index.tsx From erda-ui with GNU Affero General Public License v3.0 | 5 votes |
useDragAndDrop = ({ item, index, onBeginDrag, onEndDrag, onMove }: any) => {
const { type, data } = item;
const [position, setPosition] = React.useState('');
const dragRef = React.useRef<HTMLDivElement>(null);
const [{ isDragging }, drag, preview] = useDrag({
item: { type, data, index },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
begin: () => {
onBeginDrag && onBeginDrag({ item, index });
},
end: (_, monitor) => {
const posMap = {
top: -1,
center: 0,
bottom: 1,
};
const result = monitor.getDropResult();
if (onEndDrag) {
onEndDrag({
sourceItem: data,
targetItem: result?.data,
position: result?.position && posMap[result.position],
didDrop: monitor.didDrop(),
});
}
},
});
const [{ isOver, area }, drop] = useDrop({
accept: type,
collect: (monitor) => {
if (monitor.isOver({ shallow: true })) {
// hover 的节点
const hoverBoundingRect = dragRef.current!.getBoundingClientRect();
// hover节点高度
const { height } = hoverBoundingRect;
// 获取 hover 到的区域分界线:上(25%) 中(50%) 下(25%)
const Y_top = hoverBoundingRect.top;
const Y_split1 = hoverBoundingRect.top + height * 0.25;
const Y_split2 = hoverBoundingRect.top + height * 0.75;
const Y_bottom = hoverBoundingRect.bottom;
return {
isOver: monitor.isOver({ shallow: true }),
area: [Y_top, Y_split1, Y_split2, Y_bottom],
};
}
return {
isOver: false,
area: [],
};
},
hover(dragItem: SortItemData, monitor) {
const coordinate = monitor.getClientOffset();
if (coordinate) {
const mouseY = coordinate.y;
const pos = mouseY < area[1] ? 'top' : mouseY < area[2] ? 'center' : 'bottom';
setPosition(pos);
}
// Don't replace items with themselves
if (dragItem.data.id !== data.id) {
onMove &&
onMove({
sourceItem: dragItem,
targetItem: item,
position: dragItem.index < index ? 1 : -1,
});
}
},
drop: () => {
return { data: item.data, position };
},
});
return { drag: drag(dragRef), preview, drop, position, isDragging, isOver };
}
Example #8
Source File: TypeTree.tsx From legend-studio with Apache License 2.0 | 5 votes |
TypeTreeNodeContainer: React.FC<
TreeNodeContainerProps<TypeTreeNodeData, { selectedType?: Type | undefined }>
> = (props) => {
const { node, level, stepPaddingInRem, onNodeSelect, innerProps } = props;
const { selectedType } = innerProps;
const [, dragRef] = useDrag(
() => ({ type: node.dndType, item: new TypeDragSource(node) }),
[node],
);
const isExpandable = Boolean(node.childrenIds?.length);
const nodeTypeIcon = node.type ? (
getClassPropertyIcon(node.type)
) : (
<PURE_EnumValueIcon />
);
const nodeExpandIcon = isExpandable ? (
node.isOpen ? (
<ChevronDownIcon />
) : (
<ChevronRightIcon />
)
) : (
<div />
);
const selectNode = (): void => onNodeSelect?.(node);
return (
<div
className={clsx('tree-view__node__container', {
'type-tree__node__container--highlighted': node.type === selectedType,
})}
onClick={selectNode}
ref={dragRef}
style={{
paddingLeft: `${(level - 1) * (stepPaddingInRem ?? 1)}rem`,
display: 'flex',
}}
>
<div className="tree-view__node__icon type-tree__node__icon">
<div className="type-tree__expand-icon">{nodeExpandIcon}</div>
<div className="type-tree__type-icon">{nodeTypeIcon}</div>
</div>
<div className="tree-view__node__label type-tree__node__label">
<button tabIndex={-1} title={`${node.id}`}>
{node.label}
</button>
{Boolean(node.type) && (
<div className="type-tree__node__type">
<button
className={clsx('type-tree__node__type__label', {
'type-tree__node__type__label--highlighted':
node.type === selectedType,
})}
tabIndex={-1}
title={node.type?.path ?? ''}
>
{node.type?.name ?? 'unknown'}
</button>
</div>
)}
</div>
</div>
);
}
Example #9
Source File: DragSortEditTable.tsx From datart with Apache License 2.0 | 5 votes |
DraggableAndEditableBodyRow = ({
index,
moveRow,
className,
style,
...restProps
}) => {
const [form] = Form.useForm();
const ref = useRef(null);
const [{ isOver, dropClassName }, drop] = useDrop({
accept: type,
collect: monitor => {
const { index: dragIndex } = monitor.getItem<{ index: number }>() || {};
if (dragIndex === index) {
return {};
}
return {
isOver: monitor.isOver(),
dropClassName:
dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
};
},
drop: (item: { index: number }) => {
moveRow(item.index, index);
},
});
const [, drag] = useDrag({
type,
item: { index },
collect: monitor => ({
isDragging: monitor.isDragging(),
}),
});
drop(drag(ref));
return (
<Form form={form} component={false}>
<EditableContext.Provider value={form}>
<tr
ref={ref}
className={`${className}${isOver ? dropClassName : ''}`}
style={{ cursor: 'move', ...style }}
{...restProps}
/>
</EditableContext.Provider>
</Form>
);
}
Example #10
Source File: useInteractive.ts From openchakra with MIT License | 5 votes |
useInteractive = (
component: IComponent,
enableVisualHelper: boolean = false,
) => {
const dispatch = useDispatch()
const showLayout = useSelector(getShowLayout)
const isComponentSelected = useSelector(getIsSelectedComponent(component.id))
const isHovered = useSelector(getIsHovered(component.id))
const focusInput = useSelector(getFocusedComponent(component.id))
const [, drag] = useDrag({
item: { id: component.id, type: component.type, isMoved: true },
})
const ref = useRef<HTMLDivElement>(null)
let props = {
...component.props,
onMouseOver: (event: MouseEvent) => {
event.stopPropagation()
dispatch.components.hover(component.id)
},
onMouseOut: () => {
dispatch.components.unhover()
},
onClick: (event: MouseEvent) => {
event.preventDefault()
event.stopPropagation()
dispatch.components.select(component.id)
},
onDoubleClick: (event: MouseEvent) => {
event.preventDefault()
event.stopPropagation()
if (focusInput === false) {
dispatch.app.toggleInputText()
}
},
}
if (showLayout && enableVisualHelper) {
props = {
...props,
border: `1px dashed #718096`,
padding: props.p || props.padding ? props.p || props.padding : 4,
}
}
if (isHovered || isComponentSelected) {
props = {
...props,
boxShadow: `${focusInput ? '#ffc4c7' : '#4FD1C5'} 0px 0px 0px 2px inset`,
}
}
return { props, ref: drag(ref), drag }
}
Example #11
Source File: QueryBuilderFunctionsExplorerPanel.tsx From legend-studio with Apache License 2.0 | 5 votes |
QueryBuilderFunctionsExplorerListEntry = observer(
(props: {
queryBuilderState: QueryBuilderState;
element: ConcreteFunctionDefinition;
rootPackageName: ROOT_PACKAGE_NAME;
}) => {
const { queryBuilderState, element, rootPackageName } = props;
const node = generateFunctionsExplorerTreeNodeData(
queryBuilderState,
element,
rootPackageName,
);
const functionSignature = generateFunctionSignature(element, true);
const [, dragConnector, dragPreviewConnector] = useDrag(
() => ({
type: QUERY_BUILDER_FUNCTIONS_EXPLORER_TREE_DND_TYPE.FUNCTION,
item: { node: node },
}),
[node],
);
// hide default HTML5 preview image
useEffect(() => {
dragPreviewConnector(getEmptyImage(), { captureDraggingState: true });
}, [dragPreviewConnector]);
return (
<div
className="query-builder__functions-explorer__function"
ref={dragConnector}
>
<div className="query-builder__functions-explorer__function__content">
<div className="query-builder__functions-explorer__function__icon">
<div className="query-builder__functions-explorer__function-icon">
<PURE_FunctionIcon />
</div>
</div>
<div
className="query-builder__functions-explorer__function__label"
title={functionSignature}
>
{functionSignature}
</div>
</div>
<div className="query-builder__functions-explorer__function__actions">
<QueryBuilderFunctionInfoTooltip
element={node.packageableElement as ConcreteFunctionDefinition}
>
<div className="query-builder__functions-explorer__function__action query-builder__functions-explorer__function__node__info">
<InfoCircleIcon />
</div>
</QueryBuilderFunctionInfoTooltip>
</div>
</div>
);
},
)
Example #12
Source File: DragItem.tsx From openchakra with MIT License | 5 votes |
DragItem: React.FC<ComponentItemProps> = ({
type,
soon,
label,
isMeta,
isChild,
rootParentType,
}) => {
const [, drag] = useDrag({
item: { id: type, type, isMeta, rootParentType },
})
let boxProps: any = {
cursor: 'no-drop',
color: 'whiteAlpha.600',
}
if (!soon) {
boxProps = {
ref: drag,
color: 'whiteAlpha.800',
cursor: 'move',
_hover: {
ml: -1,
mr: 1,
bg: 'teal.100',
boxShadow: 'sm',
color: 'teal.800',
},
}
}
if (isChild) {
boxProps = { ...boxProps, ml: 4 }
}
return (
<Box
boxSizing="border-box"
transition="margin 200ms"
my={1}
borderRadius="md"
p={1}
display="flex"
alignItems="center"
{...boxProps}
>
<DragHandleIcon path="" fontSize="xs" mr={2} />
<Text letterSpacing="wide" fontSize="sm" textTransform="capitalize">
{label}
</Text>
{isMeta && (
<Box
ml={2}
borderWidth="1px"
color="teal.300"
borderColor="teal.600"
fontSize="xs"
borderRadius={4}
px={1}
>
preset
</Box>
)}
{soon && (
<Box
ml={2}
borderWidth="1px"
color="whiteAlpha.500"
borderColor="whiteAlpha.300"
fontSize="xs"
borderRadius={4}
px={1}
>
soon
</Box>
)}
</Box>
)
}
Example #13
Source File: QueryBuilderParameterPanel.tsx From legend-studio with Apache License 2.0 | 5 votes |
VariableExpressionViewer = observer(
(props: {
queryBuilderState: QueryBuilderState;
variableExpressionState: QueryParameterState;
}) => {
const { queryBuilderState, variableExpressionState } = props;
const queryParameterState = queryBuilderState.queryParametersState;
const variable = variableExpressionState.parameter;
const name = variable.name;
const variableType = variable.genericType?.value.rawType;
const typeName = variableType?.name;
const editVariable = (): void => {
queryParameterState.setSelectedParameter(variableExpressionState);
};
const deleteVariable = (): void =>
queryParameterState.removeParameter(variableExpressionState);
const [, dragConnector, dragPreviewConnector] = useDrag(
() => ({
type: QUERY_BUILDER_PARAMETER_TREE_DND_TYPE.VARIABLE,
item: { variable: variableExpressionState },
}),
[variableExpressionState],
);
// hide default HTML5 preview image
useEffect(() => {
dragPreviewConnector(getEmptyImage(), { captureDraggingState: true });
}, [dragPreviewConnector]);
return (
<div className="query-builder__parameters__parameter" ref={dragConnector}>
<QueryBuilderParameterDragLayer queryBuilderState={queryBuilderState} />
<div className="query-builder__parameters__parameter__content">
<div className="query-builder__parameters__parameter__icon">
<div className="query-builder__parameters__parameter-icon">
<DollarIcon />
</div>
</div>
<div className="query-builder__parameters__parameter__label">
{name}
<div className="query-builder__parameters__parameter__type">
<div className="query-builder__parameters__parameter__type__label">
{typeName}
</div>
</div>
</div>
</div>
<div className="query-builder__parameters__parameter__actions">
<button
className="query-builder__parameters__parameter__action"
tabIndex={-1}
onClick={editVariable}
title="Edit Parameter"
>
<PencilIcon />
</button>
<button
className="query-builder__parameters__parameter__action"
onClick={deleteVariable}
title="Remove"
>
<TimesIcon />
</button>
</div>
</div>
);
},
)
Example #14
Source File: ElementListItemDraggable.tsx From openchakra with MIT License | 5 votes |
ElementListItemDraggable: React.FC<Props> = ({
type,
id,
onSelect,
moveItem,
index,
onHover,
onUnhover,
name,
}) => {
const ref = useRef<HTMLDivElement>(null)
const [, drop] = useDrop({
accept: ITEM_TYPE,
hover(item: DragObjectWithType, monitor) {
if (!ref.current) {
return
}
// @ts-ignore
const dragIndex = item.index
const hoverIndex = index
if (dragIndex === hoverIndex) {
return
}
const hoverBoundingRect = ref.current.getBoundingClientRect()
const hoverMiddleY =
(hoverBoundingRect.bottom - hoverBoundingRect.top) / 2
const clientOffset = monitor.getClientOffset()
const hoverClientY = (clientOffset as XYCoord).y - hoverBoundingRect.top
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return
}
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return
}
if (moveItem) {
moveItem(dragIndex, hoverIndex)
}
// @ts-ignore
item.index = hoverIndex
},
})
const [{ isDragging }, drag] = useDrag({
item: { type: ITEM_TYPE, id, index },
collect: monitor => ({
isDragging: monitor.isDragging(),
}),
})
const opacity = isDragging ? 0 : 1
drag(drop(ref))
const onSelectElement = () => {
onSelect(id)
}
const onMouseOver = () => {
onHover(id)
}
return (
<ElementListItem
ref={ref}
onSelect={onSelectElement}
opacity={opacity}
onMouseOver={onMouseOver}
onMouseOut={onUnhover}
type={type}
draggable
name={name}
/>
)
}
Example #15
Source File: DataDocGridItem.tsx From querybook with Apache License 2.0 | 5 votes |
DataDocGridItem: React.FunctionComponent<IDataDocGridItemProps> = React.memo(
({ dataDoc, className, url, onRemove }) => {
const [, drag] = useDrag({
type: DataDocDraggableType,
item: {
type: DataDocDraggableType,
itemInfo: dataDoc,
},
});
const handleClick = React.useCallback(() => {
history.push(url);
}, [url]);
const handleRemoveDataDoc = React.useCallback(
(event: React.MouseEvent) => {
if (onRemove) {
event.stopPropagation();
event.preventDefault();
onRemove(dataDoc);
}
},
[onRemove, dataDoc]
);
const { title = '', public: publicDataDoc } = dataDoc;
const privateIcon = !publicDataDoc ? 'Lock' : null;
return (
<div ref={drag} className="DataDocGridItem">
<PopoverHoverWrapper>
{(showPopover, anchorElement) => (
<>
<ListLink
className={className}
onClick={handleClick}
to={url}
icon={privateIcon}
title={title}
isRow
>
{onRemove && (
<IconButton
className="delete-grid-item-button ml8"
noPadding
size={16}
icon="X"
onClick={handleRemoveDataDoc}
/>
)}
</ListLink>
<UrlContextMenu
url={url}
anchorRef={{ current: anchorElement }}
/>
{showPopover && anchorElement && (
<Popover
onHide={NOOP}
anchor={anchorElement}
layout={['right', 'top']}
>
<DataDocHoverContent
docId={dataDoc.id}
title={title}
/>
</Popover>
)}
</>
)}
</PopoverHoverWrapper>
</div>
);
}
)
Example #16
Source File: FlatDataRecordTypeTree.tsx From legend-studio with Apache License 2.0 | 5 votes |
RecordFieldTreeNodeContainer: React.FC<
TreeNodeContainerProps<
FlatDataRecordTypeTreeNodeData,
{ selectedType?: Type | undefined }
>
> = (props) => {
const { node, level, stepPaddingInRem, onNodeSelect, innerProps } = props;
const { selectedType } = innerProps;
const [, dragRef] = useDrag(
() => ({
type: CORE_DND_TYPE.TYPE_TREE_PRIMITIVE,
item: new FlatDataColumnDragSource(node),
}),
[node],
);
const nodeTypeIcon = <PURE_PrimitiveTypeIcon />;
const selectNode = (): void => onNodeSelect?.(node);
const primitiveType = node.field.flatDataDataType._correspondingPrimitiveType;
return (
<div
className="tree-view__node__container"
onClick={selectNode}
ref={dragRef}
style={{
paddingLeft: `${(level - 1) * (stepPaddingInRem ?? 1)}rem`,
display: 'flex',
}}
>
<div className="tree-view__node__icon flat-data-column-tree__node__icon">
<div className="type-tree__type-icon">{nodeTypeIcon}</div>
</div>
<div className="tree-view__node__label type-tree__node__label">
<button tabIndex={-1} title={`${node.id}`}>
{node.label}
</button>
{
<div className="type-tree__node__type">
<button
className={clsx('type-tree__node__type__label', {
'type-tree__node__type__label--highlighted':
primitiveType && primitiveType === selectedType,
})}
tabIndex={-1}
title={'Column Type'}
>
{primitiveType?.path ?? 'RecordType'}
</button>
</div>
}
</div>
</div>
);
}
Example #17
Source File: DayOfWeekHeader.tsx From calendar-hack with MIT License | 5 votes |
DayOfWeekHeader: React.FC<Props> = ({ dow, swapDow, selectDow, hoverDow }) => {
const [{ isOver, canDrop, droppedItem }, drop] = useDrop({
accept: ItemTypes.DOW,
canDrop: () => true,
drop: () => { swapDow(dow, droppedItem.dow); return; },
collect: (monitor) => {
if (monitor.isOver()) {
hoverDow(dow);
}
return {
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
droppedItem: monitor.getItem()
}
},
})
const [{ isDragging }, drag, preview] = useDrag({
item: { type: ItemTypes.DOW, dow: dow },
collect: (monitor) => {
if (monitor.isDragging()) {
selectDow(dow);
}
return {
isDragging: monitor.isDragging(),
};
},
begin: (monitor: DragSourceMonitor) => {
selectDow(dow);
},
end: (item: { dow: dayOfWeek } | undefined, monitor: DragSourceMonitor) => {
const dropResult = monitor.getDropResult()
if (item && dropResult) {
selectDow(undefined);
hoverDow(undefined);
}
},
})
return (
<div style={{
position: 'relative',
width: '100%',
height: '100%',
}}>
<DragSource isDragging={isDragging} dow={dow}>
<DropTarget isOver={isOver} canDrop={canDrop} ref={drop}>
<Preview generator={generateDowPreview} />
<div ref={preview}>
<Root ref={drag}>
<DragHandle viewBox="0 0 32 36" />
<div>{dow}</div>
</Root>
</div>
</DropTarget>
</DragSource>
</div>
)
}
Example #18
Source File: use-hooks.tsx From erda-ui with GNU Affero General Public License v3.0 | 5 votes |
useListDnD = ({ type, index, onMove, collect }: IDragProps) => {
const dragRef = useRef<HTMLDivElement>(null);
const [, drop] = useDrop({
accept: type,
hover(item: DragItem, monitor: DropTargetMonitor) {
if (!dragRef.current) {
return;
}
const dragIndex = item.index;
const hoverIndex = index;
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return;
}
// Determine rectangle on screen
const hoverBoundingRect = dragRef.current!.getBoundingClientRect();
// Get vertical middle
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
// Determine mouse position
const clientOffset = monitor.getClientOffset();
// Get pixels to the top
const hoverClientY = (clientOffset as XYCoord).y - hoverBoundingRect.top;
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return;
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return;
}
// Time to actually perform the action
onMove(dragIndex, hoverIndex);
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
item.index = hoverIndex;
},
});
const [collectedProps, drag, previewRef] = useDrag({
item: { index, type },
collect,
});
drag(drop(dragRef));
return [dragRef, previewRef, collectedProps];
}
Example #19
Source File: EditorBrickAsComponent.spec.tsx From next-core with GNU General Public License v3.0 | 5 votes |
(useDrag as jest.MockedFunction<typeof useDrag>).mockReturnValue([
{ isDragging: false },
jest.fn(),
undefined,
]);
Example #20
Source File: BrickTable.tsx From next-basics with GNU General Public License v3.0 | 5 votes |
DraggableBodyRow = ({
index,
moveRow,
className,
style,
...restProps
}) => {
const ref = React.useRef();
const [{ isOver, dropClassName }, drop] = useDrop({
accept: type,
collect: (monitor) => {
const { index: dragIndex } = monitor.getItem() || {};
if (dragIndex === index) {
return {};
}
return {
isOver: monitor.isOver(),
dropClassName:
dragIndex < index
? `${styles.dropOverDownward}`
: `${styles.dropOverUpward}`,
};
},
drop: (item: any) => {
moveRow(item.index, index);
},
});
const [, drag] = useDrag({
item: { type, index },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
});
drop(drag(ref));
return (
<tr
ref={ref}
className={classNames(className, styles.draggableRow, {
[dropClassName]: isOver,
})}
style={{ cursor: "move", ...style }}
{...restProps}
/>
);
}
Example #21
Source File: WidgetDndHandleMask.tsx From datart with Apache License 2.0 | 5 votes |
WidgetDndHandleMask: React.FC<WidgetDndHandleMaskProps> = memo(
({ widgetId, widgetType }) => {
const dispatch = useDispatch();
interface DropResult {
tabItem: ContainerItem;
parentId: string;
}
const [_, dragRef, dragPreview] = useDrag(() => ({
type: CONTAINER_TAB,
item: { type: widgetType },
end: (item, monitor) => {
const dropResult = monitor.getDropResult<DropResult>();
if (item && dropResult) {
const { tabItem, parentId } = dropResult;
dispatch(
editBoardStackActions.addWidgetToContainerWidget({
parentId,
tabItem: { ...tabItem, childWidgetId: widgetId },
sourceId: widgetId,
}),
);
}
},
collect: monitor => ({
isDragging: monitor.isDragging(),
handlerId: monitor.getHandlerId(),
}),
}));
const ssp = e => {
e.stopPropagation();
};
return (
<>
<div
ref={dragPreview}
className="dragRef2"
onClick={ssp}
onDragStart={ssp}
style={{
position: 'absolute',
top: '0',
cursor: 'grabbing',
width: '100%',
height: '100%',
}}
></div>
<div
ref={dragRef}
// onDragStart={ssp}
onClick={ssp}
className="dragRef1"
style={{
position: 'absolute',
cursor: 'grabbing',
top: '0',
zIndex: LEVEL_10 + 1,
width: '100%',
height: '100%',
}}
></div>
</>
);
},
)
Example #22
Source File: index.tsx From uno-game with MIT License | 5 votes |
DraggableCard: React.FC<CardProps> = (props) => {
const {
card,
index,
style,
className,
onClick,
selected,
isDraggingAnyCard,
onDragEnd,
canBePartOfCurrentCombo,
isMoreThanOneCardBeingDragged,
} = props
const draggableCardRef = useRef(null)
const canCardBeUsed = canBePartOfCurrentCombo || card.canBeUsed
const [{ isDragging }, drag, preview] = useDrag({
item: {
type: CARD_TYPE,
id: card.id,
index,
src: card.src,
name: card.name,
cardType: card.type,
selected,
className,
} as DraggedCardItem,
collect: monitor => ({
isDragging: monitor.isDragging(),
}),
canDrag: canCardBeUsed,
end: onDragEnd,
})
drag(draggableCardRef)
useDidMount(() => {
preview(getEmptyImage(), { captureDraggingState: true })
})
return (
<img
ref={draggableCardRef}
key={card.name}
className={className}
alt={card.name}
src={card.src}
style={{
...style,
opacity: (isDragging || (isDraggingAnyCard && isMoreThanOneCardBeingDragged && selected)) ? 0 : 1,
filter: !canCardBeUsed ? "brightness(0.5)" : "saturate(1.5)",
pointerEvents: canCardBeUsed ? "all" : "none",
...(selected ? {
border: `${Device.isMobile ? "3px" : "5px"} solid #EC0000`,
borderRadius: Device.isMobile ? "8px" : "16px",
} : {}),
}}
onClick={onClick}
/>
)
}
Example #23
Source File: ContextItem.tsx From next-basics with GNU General Public License v3.0 | 5 votes |
export function ContextItem({
index,
data,
canDrag,
highlighted,
handleDropItem,
handleItemClick,
handleItemDelete,
handleItemHover,
}: ContextItemProps): React.ReactElement {
const ref = useRef();
const [{ isOver, dropClassName }, drop] = useDrop({
accept: type,
collect: (monitor) => {
const { index: dragIndex } = monitor.getItem() || {};
if (dragIndex === index) {
return {};
}
return {
isOver: monitor.isOver(),
dropClassName:
dragIndex < index
? `${styles.dropOverDownward}`
: `${styles.dropOverUpward}`,
};
},
drop: (item: any) => {
handleDropItem(item.index, index);
},
});
const [{ isDragging }, drag] = useDrag({
item: { type, index },
canDrag,
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
});
drop(drag(ref));
const handleMouseEnter = (): void => {
handleItemHover(data.name);
};
const handleMouseLeave = (): void => {
handleItemHover();
};
return (
<div
ref={ref}
className={classNames(styles.varItem, {
[dropClassName]: isOver,
[styles.highlighted]: highlighted,
})}
onClick={handleItemClick}
key={data.name}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
{data.resolve ? (
<LinkOutlined style={{ color: "var(--theme-orange-color)" }} />
) : (
<CodeOutlined style={{ color: "var(--theme-green-color)" }} />
)}
<span className={styles.varName}>{data.name}</span>
<Button
type="link"
danger
icon={<DeleteOutlined />}
className={styles.deleteIcon}
onClick={handleItemDelete}
/>
</div>
);
}
Example #24
Source File: DragAndDropTreeComponent.tsx From frontend-sample-showcase with MIT License | 5 votes |
DragAndDropNode: React.FC<TreeNodeRendererProps> = (props) => {
const { treeModelSource, treeNodeLoader, isDragging, setDragging } = React.useContext(dragDropContext)!;
// Make node draggable
const [, dragSourceRef] = useDrag({
item: { type: "tree-node", id: props.node.id },
begin: () => setDragging(true),
end: () => setDragging(false),
});
// Make node accept drop events
const [{ isHovered }, dropTargetRef] = useDrop({
accept: "tree-node",
hover: handleHover,
canDrop: handleCanDrop,
drop: handleDrop,
collect: (monitor) => ({ isHovered: monitor.isOver() }),
});
const [canDrop, setCanDrop] = React.useState(false);
function handleCanDrop(item: NodeDragObject): boolean {
// Do not allow dropping a node in such a way that would create a parent-child relationship cycle
const isDroppingOnSelf = props.node.id === item.id && dropArea === DropArea.Inside;
const newCanDrop = !isDroppingOnSelf && !areNodesRelated(treeModelSource.getModel(), item.id, props.node.id);
setCanDrop(newCanDrop);
return newCanDrop;
}
const elementRef = React.useRef<HTMLDivElement>(null);
const [dropArea, setDropArea] = React.useState<DropArea>(DropArea.Inside);
function handleHover(item: NodeDragObject, monitor: DropTargetMonitor): void {
// Determine which drop area is hovered and whether we can drop the node there
const cursorY = monitor.getClientOffset()?.y;
const dropTargetY = elementRef.current?.getBoundingClientRect().y;
if (cursorY !== undefined && dropTargetY !== undefined) {
setDropArea(determineDropArea(25, 7, cursorY - dropTargetY));
handleCanDrop(item);
}
}
function handleDrop(item: NodeDragObject): void {
// The main entry point for drop event handling
const { parentId, index } = getDropLocation(treeModelSource.getModel(), props.node, dropArea);
moveNode(treeModelSource, treeNodeLoader, item.id, parentId, index)
.catch((error) => {
// eslint-disable-next-line no-console
console.error(error);
});
}
const isDropAreaDisplayed = isHovered && canDrop;
const nodeStyle: React.CSSProperties = {
height: 25,
...(isDropAreaDisplayed && dropArea === DropArea.Inside && { background: "var(--buic-row-hover)" }),
};
return (
<div ref={mergeRefs([dragSourceRef, dropTargetRef, elementRef])}>
<div style={{ height: 0 }}>
{isDropAreaDisplayed && dropArea === DropArea.Above && <NodeInsertMarker topOffset={0} />}
{isDropAreaDisplayed && dropArea === DropArea.Below && <NodeInsertMarker topOffset={25} />}
</div>
<BasicTreeNode style={nodeStyle} isHoverDisabled={isDragging} {...props} />
</div>
);
}
Example #25
Source File: BrickItem.spec.tsx From next-basics with GNU General Public License v3.0 | 5 votes |
jest.mock("react-dnd", () => ({
useDrag: jest.fn(),
}));
Example #26
Source File: index.tsx From ql with MIT License | 5 votes |
DragableBodyRow = ({
index,
moveRow,
className,
style,
...restProps
}: any) => {
const ref = useRef();
const [{ isOver, dropClassName }, drop] = useDrop(
() => ({
accept: type,
collect: (monitor) => {
const { index: dragIndex } = monitor.getItem() || ({} as any);
if (dragIndex === index) {
return {};
}
return {
isOver: monitor.isOver(),
dropClassName:
dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
};
},
drop: (item: any) => {
moveRow(item.index, index);
},
}),
[index],
);
const [, drag, preview] = useDrag(
() => ({
type,
item: { index },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
}),
[index],
);
drop(drag(ref));
return (
<tr
ref={ref}
className={`${className}${isOver ? dropClassName : ''}`}
style={{ cursor: 'move', ...style }}
{...restProps}
>
{restProps.children}
</tr>
);
}
Example #27
Source File: navigator-item-dnd-container.tsx From utopia with MIT License | 5 votes |
NavigatorItemContainer = React.memo((props: NavigatorItemDragAndDropWrapperProps) => {
const [{ isDragging }, drag] = useDrag(
() => ({
type: 'NAVIGATOR_ITEM',
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
item: props,
beginDrag: beginDrag,
}),
[props],
)
const dropRef = React.useRef<HTMLDivElement | null>(null)
const [{ isOver }, drop] = useDrop<
NavigatorItemDragAndDropWrapperProps,
unknown,
DropCollectedProps
>(
() => ({
accept: 'NAVIGATOR_ITEM',
collect: (monitor) => ({
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
}),
hover: (item: NavigatorItemDragAndDropWrapperProps, monitor) => {
onHover(item, props, monitor, dropRef.current)
},
drop: (item: NavigatorItemDragAndDropWrapperProps, monitor) => {
onDrop(item, props, monitor, dropRef.current)
},
}),
[props],
)
const attachDrop = React.useCallback(
(domElement: HTMLDivElement) => {
drop(domElement)
dropRef.current = domElement
},
[drop, dropRef],
)
return (
<div ref={attachDrop}>
<div ref={drag}>
<NavigatorItemDndWrapper {...props} isOver={isOver} isDragging={isDragging} />
</div>
</div>
)
})
Example #28
Source File: useReorderTodo.tsx From remix-hexagonal-architecture with MIT License | 5 votes |
useReorderTodo = (
todoListId: string,
todo: TodoDto,
currentIndex: number,
onPreviewMove: (todoId: string, newIndex: number) => void
) => {
const todosOrder = useFetcher();
const moveTodo = (newIndex: number) => {
const formData = new FormData();
formData.append("todoId", todo.id);
formData.append("newIndex", newIndex.toString());
todosOrder.submit(formData, {
method: "put",
action: `/l/${todoListId}/order`,
});
};
const [{ isDragging }, drag, preview] = useDrag<
DragItem,
DropResult,
CollectedProps
>({
type: DragTypeTodo,
item: { todoId: todo.id },
collect: (monitor) => ({
isDragging: monitor.isDragging(),
}),
end: (item, monitor) => {
const dropResult = monitor.getDropResult();
if (dropResult?.newIndex != null) moveTodo(dropResult.newIndex);
},
});
const [, drop] = useDrop<DragItem, DropResult>({
accept: DragTypeTodo,
hover: (item) => {
onPreviewMove(item.todoId, currentIndex);
},
drop: () => ({
newIndex: currentIndex,
}),
});
return {
isDragging,
ref: (node: HTMLDivElement | null) => drag(drop(node)),
preview,
};
}
Example #29
Source File: draggable-table.tsx From admin with MIT License | 4 votes |
DraggableTable: React.FC<DraggableTableProps> = ({
entities,
setEntities,
onDelete,
columns,
}) => {
const [records, setRecords] = useState(entities)
useEffect(() => {
setRecords(entities)
}, [entities])
useEffect(() => setEntities(records), [records])
const DND_ITEM_TYPE = "row"
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
} = useTable({
columns,
data: records,
})
const moveRow = (dragIndex, hoverIndex) => {
const dragRecord = records[dragIndex]
setRecords(
update(records, {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragRecord],
],
})
)
setEntities(
update(records, {
$splice: [
[dragIndex, 1],
[hoverIndex, 0, dragRecord],
],
})
)
}
const debouncedMoveRow = useMemo(() => debounce(moveRow, 100), [])
useEffect(() => {
return () => {
debouncedMoveRow.cancel()
}
}, [])
const Row = ({ row, index, moveRow }) => {
const dropRef = useRef(null)
const dragRef = useRef(null)
const [_, drop] = useDrop(() => ({
accept: DND_ITEM_TYPE,
hover: (item, monitor) => {
if (!dropRef.current) {
return
}
const dragIndex = item.index
const hoverIndex = index
// Don't replace items with themselves
if (dragIndex === hoverIndex) {
return
}
// return // TODO: fix hover/drop action
// if (latestMoved?.from === dragIndex && latestMoved?.to === hoverIndex) {
// return
// }
// Determine rectangle on screen
const hoverBoundingRect = dropRef.current.getBoundingClientRect()
// Get vertical middle
const hoverMiddleY =
(hoverBoundingRect.bottom - hoverBoundingRect.top) / 2
// Determine mouse position
const clientOffset = monitor.getClientOffset()
// Get pixels to the top
const hoverClientY = clientOffset.y - hoverBoundingRect.top
// Only perform the move when the mouse has crossed half of the items height
// When dragging downwards, only move when the cursor is below 50%
// When dragging upwards, only move when the cursor is above 50%
// Dragging downwards
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return
}
// Dragging upwards
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return
}
// Time to actually perform the action
// setLatestMoved({ from: dragIndex, to: hoverIndex })
moveRow(dragIndex, hoverIndex)
// Note: we're mutating the monitor item here!
// Generally it's better to avoid mutations,
// but it's good here for the sake of performance
// to avoid expensive index searches.
item.index = hoverIndex
},
}))
const [{ isDragging }, drag, preview] = useDrag(() => ({
type: "row",
item: { index },
collect: (monitor) => ({
isDragging: !!monitor.isDragging(),
}),
}))
const opacity = isDragging ? 0 : 1
preview(drop(dropRef))
drag(dragRef)
return (
<Table.Row ref={dropRef} style={{ opacity }}>
<Table.Cell className="medium:w-[72px] small:w-auto">
<Button
ref={dragRef}
variant="ghost"
size="small"
className="h-6 w-6 cursor-grab text-grey-40 mx-6"
>
<GripIcon size={20} />
</Button>
</Table.Cell>
{row.cells.map((cell) => {
return <td {...cell.getCellProps()}>{cell.render("Cell")}</td>
})}
{onDelete && (
<Table.Cell>
<Button
onClick={() => onDelete(row.original)}
variant="ghost"
size="small"
className="p-1 text-grey-40 cursor-pointer mx-6"
>
<TrashIcon size={20} />
</Button>
</Table.Cell>
)}
</Table.Row>
)
}
return (
<div className="w-full h-full">
<DndProvider backend={HTML5Backend}>
<Table {...getTableProps()}>
<Table.Head>
{headerGroups?.map((headerGroup) => (
<Table.HeadRow {...headerGroup.getHeaderGroupProps()}>
<Table.HeadCell> </Table.HeadCell>
{headerGroup.headers.map((col) => (
<Table.HeadCell {...col.getHeaderProps()}>
{col.render("Header")}
</Table.HeadCell>
))}
</Table.HeadRow>
))}
</Table.Head>
<Table.Body {...getTableBodyProps()}>
{rows.map(
(row, index) =>
prepareRow(row) || (
<Row
index={index}
row={row}
moveRow={moveRow}
{...row.getRowProps()}
/>
)
)}
</Table.Body>
</Table>
</DndProvider>
</div>
)
}