Skip to content

Commit

Permalink
Add isDragging and isDropping attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
clauderic committed Feb 3, 2025
1 parent 4cc79ec commit c9716cf
Show file tree
Hide file tree
Showing 18 changed files with 100 additions and 44 deletions.
6 changes: 6 additions & 0 deletions .changeset/is-drag-source.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@dnd-kit/abstract': patch
'@dnd-kit/dom': patch
---

Added `isDragging` and `isDropping` properties to `draggable` and `sortable` instances.
4 changes: 2 additions & 2 deletions apps/docs/react/guides/multiple-sortable-lists.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ export const SortableItem = `import React from 'react';
import {useSortable} from '@dnd-kit/react/sortable';

export function Item({id, index, column}) {
const {ref, isDragSource} = useSortable({
const {ref, isDragging} = useSortable({
id,
index,
type: 'item',
Expand All @@ -367,7 +367,7 @@ export function Item({id, index, column}) {
});

return (
<button className="Item" ref={ref} data-dragging={isDragSource}>
<button className="Item" ref={ref} data-dragging={isDragging}>
{id}
</button>
);
Expand Down
10 changes: 9 additions & 1 deletion apps/docs/react/hooks/use-draggable.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,15 @@ The `useDraggable` hook returns an object containing the following properties:
</ResponseField>

<ResponseField name="isDragSource" type="boolean">
A boolean value that indicates whether the element is currently being dragged.
A boolean value that indicates whether the draggable is the source of the drag operation that is in progress.
</ResponseField>

<ResponseField name="isDragging" type="boolean">
A boolean value that indicates whether the draggable is currently being dragged.
</ResponseField>

<ResponseField name="isDropping" type="boolean">
A boolean value that indicates whether the draggable is being dropped. This can be used to style the draggable element differently during the drop animation.
</ResponseField>

<ResponseField name="draggable" type="Draggable">
Expand Down
10 changes: 9 additions & 1 deletion apps/docs/react/hooks/use-sortable.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -149,5 +149,13 @@ The `useSortable` hook returns an object containing the following properties:
</ParamField>

<ParamField path="isDragSource" type="boolean">
A boolean value that indicates whether the sortable element is currently being dragged.
A boolean value that indicates whether the sortable is the source of the drag operation that is in progress.
</ParamField>

<ResponseField name="isDragging" type="boolean">
A boolean value that indicates whether the sortable is currently being dragged.
</ResponseField>

<ResponseField name="isDropping" type="boolean">
A boolean value that indicates whether the sortable is being dropped. This can be used to style the sortable element differently during the drop animation.
</ResponseField>
4 changes: 2 additions & 2 deletions apps/stories/stories/react/Draggable/DraggableExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function Draggable({
const [element, setElement] = useState<Element | null>(null);
const handleRef = useRef<HTMLButtonElement | null>(null);

const {isDragSource} = useDraggable({
const {isDragging} = useDraggable({
id,
modifiers,
element,
Expand All @@ -64,7 +64,7 @@ export function Draggable({
return (
<Button
ref={setElement}
shadow={isDragSource}
shadow={isDragging}
actions={handle ? <Handle ref={handleRef} variant="dark" /> : undefined}
style={style}
>
Expand Down
4 changes: 2 additions & 2 deletions apps/stories/stories/react/Droppable/DroppableExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@ interface DraggableProps {
function Draggable({id}: DraggableProps) {
const [element, setElement] = useState<Element | null>(null);

const {isDragSource} = useDraggable({
const {isDragging} = useDraggable({
id,
element,
});

return (
<Button ref={setElement} shadow={isDragSource}>
<Button ref={setElement} shadow={isDragging}>
<DraggableIcon />
</Button>
);
Expand Down
4 changes: 1 addition & 3 deletions apps/stories/stories/react/Sortable/Iframe/IframeExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,7 @@ export function IframeLists({
</AutoFrame>
</div>
<DragOverlay>
{(source) => (
<Item shadow={source.status == 'dragging'}>{source.id}</Item>
)}
{(source) => <Item shadow={source.isDragging}>{source.id}</Item>}
</DragOverlay>
</DragDropProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ function SortableItem({
onRemove,
}: PropsWithChildren<SortableItemProps>) {
const group = column;
const {handleRef, ref, isDragSource} = useSortable({
const {handleRef, ref, isDragging} = useSortable({
id,
group,
accept: 'item',
Expand All @@ -178,14 +178,14 @@ function SortableItem({
ref={ref}
actions={
<Actions>
{onRemove && !isDragSource ? (
{onRemove && !isDragging ? (
<Remove onClick={() => onRemove(id, column)} />
) : null}
<Handle ref={handleRef} />
</Actions>
}
accentColor={COLORS[column]}
shadow={isDragSource}
shadow={isDragging}
style={style}
transitionId={`sortable-${column}-${id}`}
>
Expand All @@ -210,7 +210,7 @@ function SortableColumn({
scrollable,
style,
}: PropsWithChildren<SortableColumnProps>) {
const {handleRef, isDragSource, ref} = useSortable({
const {handleRef, isDragging, ref} = useSortable({
id,
accept: ['column', 'item'],
collisionPriority: CollisionPriority.Low,
Expand All @@ -228,7 +228,7 @@ function SortableColumn({
</Actions>
}
columns={columns}
shadow={isDragSource}
shadow={isDragging}
scrollable={scrollable}
transitionId={`sortable-column-${id}`}
style={style}
Expand Down
4 changes: 2 additions & 2 deletions apps/stories/stories/react/Sortable/SortableExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function SortableItem({
}: PropsWithChildren<SortableProps>) {
const [element, setElement] = useState<Element | null>(null);
const handleRef = useRef<HTMLButtonElement | null>(null);
const {isDragSource} = useSortable({
const {isDragging} = useSortable({
id,
index,
element,
Expand All @@ -117,7 +117,7 @@ function SortableItem({
<Item
ref={setElement}
actions={dragHandle ? <Handle ref={handleRef} /> : null}
shadow={isDragSource}
shadow={isDragging}
style={style}
>
{id}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ interface SortableProps {
}

function Sortable({id, index, style}: SortableProps) {
const {isDragSource, ref, handleRef} = useSortable({
const {isDragging, ref, handleRef} = useSortable({
id,
index,
});
Expand All @@ -68,7 +68,7 @@ function Sortable({id, index, style}: SortableProps) {
<Item
actions={<Handle ref={handleRef} />}
data-index={index}
shadow={isDragSource}
shadow={isDragging}
>
{id}
</Item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ const Sortable = forwardRef<Element, PropsWithChildren<SortableProps>>(
const [element, setElement] = useState<Element | null>(null);
const handleRef = useRef<HTMLButtonElement | null>(null);

const {isDragSource} = useSortable({
const {isDragging} = useSortable({
id,
index,
element,
Expand All @@ -119,7 +119,7 @@ const Sortable = forwardRef<Element, PropsWithChildren<SortableProps>>(
}}
actions={<Handle ref={handleRef} />}
data-index={index}
shadow={isDragSource}
shadow={isDragging}
>
{id}
</Item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ interface SortableProps {
}

function Sortable({id, index, style}: SortableProps) {
const {isDragSource, ref, handleRef} = useSortable({
const {isDragging, ref, handleRef} = useSortable({
id,
index,
});
Expand All @@ -80,7 +80,7 @@ function Sortable({id, index, style}: SortableProps) {
<Item
actions={<Handle ref={handleRef} />}
data-index={index}
shadow={isDragSource}
shadow={isDragging}
>
{id}
</Item>
Expand Down
4 changes: 1 addition & 3 deletions apps/stories/stories/vanilla/Draggable/DraggableExample.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ export const DraggableExample = createVanillaStory(() => {
element: draggableElement,
effects: () => [
() => {
const {status} = manager.dragOperation;

if (draggable.isDragSource && (status.dragging || status.dropped)) {
if (draggable.isDragging) {
draggableElement.setAttribute('data-shadow', 'true');

return () => {
Expand Down
16 changes: 16 additions & 0 deletions packages/abstract/src/core/entities/draggable/draggable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ export class Draggable<
@reactive
public accessor status: DraggableStatus = 'idle';

/**
* A boolean indicating whether the draggable item is being dropped.
*/
@derived
public get isDropping() {
return this.status === 'dropping' && this.isDragSource;
}

/**
* A boolean indicating whether the draggable item is being dropped.
*/
@derived
public get isDragging() {
return this.status === 'dragging' && this.isDragSource;
}

/**
* A boolean indicating whether the draggable item is the source of a drag operation.
*/
Expand Down
14 changes: 14 additions & 0 deletions packages/dom/src/sortable/sortable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,20 @@ export class Sortable<T extends Data = Data> {
return this.draggable.isDragSource;
}

/**
* A boolean indicating whether the sortable item is being dragged.
*/
public get isDragging() {
return this.draggable.isDragging;
}

/**
* A boolean indicating whether the sortable item is being dropped.
*/
public get isDropping() {
return this.draggable.isDropping;
}

public get status() {
return this.draggable.status;
}
Expand Down
16 changes: 10 additions & 6 deletions packages/react/src/core/draggable/useDraggable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
useComputed,
useOnValueChange,
useOnElementChange,
useDeepSignal,
} from '@dnd-kit/react/hooks';
import {currentValue, type RefOrValue} from '@dnd-kit/react/utilities';

Expand All @@ -33,7 +34,7 @@ export function useDraggable<T extends Data = Data>(
manager
)
);
const isDragSource = useComputed(() => draggable.isDragSource, [draggable]);
const trackedDraggable = useDeepSignal(draggable);
const status = useComputed(() => draggable.status, [draggable]);

useOnValueChange(id, () => (draggable.id = id));
Expand All @@ -54,12 +55,15 @@ export function useDraggable<T extends Data = Data>(
);

return {
draggable,
get isDragSource() {
return isDragSource.value;
draggable: trackedDraggable,
get isDragging() {
return trackedDraggable.isDragging;
},
get isDropping() {
return trackedDraggable.isDropping;
},
get status() {
return status.value;
get isDragSource() {
return trackedDraggable.isDragSource;
},
handleRef: useCallback(
(element: Element | null) => {
Expand Down
7 changes: 4 additions & 3 deletions packages/react/src/core/droppable/useDroppable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
useComputed,
useOnValueChange,
useOnElementChange,
useDeepSignal,
} from '@dnd-kit/react/hooks';
import {currentValue, type RefOrValue} from '@dnd-kit/react/utilities';

Expand All @@ -31,7 +32,7 @@ export function useDroppable<T extends Data = Data>(
manager
)
);
const isDropTarget = useComputed(() => droppable.isDropTarget, [droppable]);
const trackedDroppalbe = useDeepSignal(droppable);

useOnValueChange(id, () => (droppable.id = id));
useOnElementChange(element, (element) => (droppable.element = element));
Expand All @@ -42,8 +43,9 @@ export function useDroppable<T extends Data = Data>(
useOnValueChange(type, () => (droppable.id = id));

return {
droppable: trackedDroppalbe,
get isDropTarget() {
return isDropTarget.value;
return trackedDroppalbe.isDropTarget;
},
ref: useCallback(
(element: Element | null) => {
Expand All @@ -59,6 +61,5 @@ export function useDroppable<T extends Data = Data>(
},
[droppable]
),
droppable,
};
}
19 changes: 11 additions & 8 deletions packages/react/src/sortable/useSortable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
useIsomorphicLayoutEffect,
useOnValueChange,
useOnElementChange,
useDeepSignal,
} from '@dnd-kit/react/hooks';
import {currentValue, type RefOrValue} from '@dnd-kit/react/utilities';

Expand Down Expand Up @@ -52,9 +53,7 @@ export function useSortable<T extends Data = Data>(input: UseSortableInput<T>) {
);
});

const isDropTarget = useComputed(() => sortable.isDropTarget, [sortable]);
const isDragSource = useComputed(() => sortable.isDragSource, [sortable]);
const status = useComputed(() => sortable.status, [sortable]);
const trackedSortable = useDeepSignal(sortable);

useOnValueChange(id, () => (sortable.id = id));

Expand Down Expand Up @@ -105,14 +104,18 @@ export function useSortable<T extends Data = Data>(input: UseSortableInput<T>) {
);

return {
sortable: trackedSortable,
get isDragging() {
return trackedSortable.isDragging;
},
get isDropping() {
return trackedSortable.isDropping;
},
get isDragSource() {
return isDragSource.value;
return trackedSortable.isDragSource;
},
get isDropTarget() {
return isDropTarget.value;
},
get status() {
return status.value;
return trackedSortable.isDropTarget;
},
handleRef: useCallback(
(element: Element | null) => {
Expand Down

0 comments on commit c9716cf

Please sign in to comment.