![require(esm) Backported to Node.js 20, Paving the Way for ESM-Only Packages](https://cdn.sanity.io/images/cgdhsj6q/production/be8ab80c8efa5907bc341c6fefe9aa20d239d890-1600x1097.png?w=400&fit=max&auto=format)
Security News
require(esm) Backported to Node.js 20, Paving the Way for ESM-Only Packages
require(esm) backported to Node.js 20, easing the transition to ESM-only packages and reducing complexity for developers as Node 18 nears end-of-life.
react-hook-dragula
Advanced tools
Provides named parameters and strong typing + declarative usage to dragula within React.
Lightweight, strongly typed package with almost no dependencies. It uses
Dragula and React Hooks to smoothly manage the DOM state. It also adds a
context store which allows you to pass the data back and forth between
Dragula
and React
. take a look at the example project or the live
demo of the example project.
yarn add react-hook-dragula
// Typing for data which will be attached to dragula events. Yours will be different.
type Fruit = {
itemId: number;
itemName: string;
}
type DraggableStore = {
fruit: Fruit;
fruits: Fruit[];
setFruits: Dispatch<SetStateAction<Fruit[]>>;
}
const {
Dragula,
DragulaContainer,
Draggable,
DragulaHandle,
useDraggableStore,
useInternalStore,
useDrake,
} = initializeDragula<DraggableStore>();
<Dragula>
<DragulaContainer>
<Draggable>
You can move these elements between these two containers
</Draggable>
</DragulaContainer>
<DragulaContainer>
<Draggable>
There's also the possibility of moving elements around in the
same container, changing their position
</Draggable>
</DragulaContainer>
</Dragula>
<Dragula
options={{ moves: ({ container }) => !!container?.children.length > 1 }}
onDrop={() => console.log('dragula drop event!')}
>
<DragulaContainer>
<Draggable>
You can move these elements between these two containers
</Draggable>
<Draggable>
There's also the possibility of moving elements around in the
same container, changing their position
</Draggable>
<Draggable>
Anyting can be moved around. That includes images, links, or any other
nested elements.
</Draggable>
</DragulaContainer>
<DragulaContainer>
<Draggable>
This element can't be moved until a second one is added into it's container
</Draggable>
</DragulaContainer>
</Dragula>
const [fruits, setFruits] = useState<Fruit[]>([
{ itemId: 1, itemName: 'apples' },
{ itemId: 2, itemName: 'oranges' },
{ itemId: 3, itemName: 'tomatoes' },
]);
<Dragula
onDrop={({ el, source }) => {
setFruits([...source.children].map(
({ draggableStore: { fruit } }) => draggableStore,
))
console.log('Dragual drop event for: ', el.draggableStore.fruit.itemName)
}}
>
<DragulaContainer>
{fruits.map(fruit => (
<Draggable
key={fruit.id}
draggableStore={{
fruit,
fruits,
setFruits,
}}
>
<div>{fruit.itemName} - id: {fruit.id}</div>
</Draggable>
))}
</DragulaContainer>
</Dragula>
<Dragula
options={{ moves: ({ el }) => !!el?.internalStore.isMouseOverHandle }}
>
<DragulaContainer>
<Draggable>
<DragulaHandle>You can only drag this item by clicking on me!</DragulaHandle>
<div>You can move these elements between these two containers</div>
</Draggable>
<Draggable>
This item doesn't have a handle.. so it can't be moved at all!
</Draggable>
</DragulaContainer>
</Dragula>
Each <Draggable/>
node has a draggableStore
and an internalStore
object attached to it:
type InternalStore = {
isMouseOverHandle: boolean;
};
type DraggableStore<T> = T;
type ExtendedDrakeElement<T> = Element & {
draggableStore: DraggableStore<T>;
internalStore: InternalStore;
};
type ExtendedDrakeSource<T> = Element & { children: ExtendedDrakeElement<T>[] };
initializeDragula
- - - returns object
with entries:Dragula: (props: DragulaContainerProps<T>) => <Dragula<T> {...props} />
DragulaContainer: (props: HTMLProps<HTMLDivElement>) => (<DragulaContainer {...props} />)
Draggable: (props: DraggableProps<T>) => <Draggable<T> {...props} />
DragulaHandle: (props: DragulaHandleProps) => <DragulaHandle {...props} />
useDraggableStore: () => useDraggableStore<T>()
useInternalStore: () => useInternalStore()
useDrake: () => useDrake()
OnEventProps<T = typeof DraggableStore> {
clone: ExtendedDrakeElement<T>,
container: Element,
el: ExtendedDrakeElement<T>,
original: ExtendedDrakeElement<T>,
sibling: ExtendedDrakeElement<T>,
source: ExtendedDrakeSource<T>,
target: ExtendedDrakeElement<T>,
type: 'mirror' | 'copy',
}
<Dragula
options={{
isContainer: ({ el }) => false,
moves: ({ el, source, handle, sibling }) => true,
accepts: ({ el, target, source, sibling }) => true,
invalid: ({ el, handle }) => true,
direction: "vertical",
copy: false,
copySortSource: false,
revertOnSpill: false,
removeOnSpill: false,
mirrorContainer: document.body,
ignoreInputTextSelection: true,
slideFactorX: 0,
slideFactorY: 0,
}}
onDrag={({ el, source }) => {}}
onDragEnd={({ el }) => {}}
onDrop={({ el, target, source, sibling }) => {}}
onCancel={({ el, container, source }) => {}}
onRemove={({ el, container, source }) => {}}
onShadow={({ el, container, source }) => {}}
onOver={({ el, container, source }) => {}}
onOut={({ el, container, source }) => {}}
onCloned={({ clone, original, type }) => {}}
dependencyList={[]}
/>
See Dragula configuration for more info
<DragulaContainer {...props} />
HTMLProps<HTMLDivElement>
optional
<div />
element<Draggable
draggableStore={{}}
{...props}
/>
draggableStore
Object, required
<T>
from when you initialized const { Draggable } = initializeDragula<T>()
HTMLProps<HTMLDivElement>
optional
<div />
element<DragulaHandle {...props} />
HTMLProps<HTMLDivElement>
optional
<div />
element useDraggableStore: () => typeof DraggableStore<T>
useInternalStore: () => { isMouseOverHandle: boolean; }
// If Drake type & arrow functions were generic, then it would be this:
// useDrake: <T>() => Drake<ExtendedDrakeElement<T>>;
// Since they're not generic, we wind up with:
useDrake: () => ReturnType<ExtendedDragula<any>>;
Dragula
!FAQs
Provides named parameters and strong typing + declarative usage to dragula within React.
The npm package react-hook-dragula receives a total of 3,219 weekly downloads. As such, react-hook-dragula popularity was classified as popular.
We found that react-hook-dragula demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
require(esm) backported to Node.js 20, easing the transition to ESM-only packages and reducing complexity for developers as Node 18 nears end-of-life.
Security News
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.