Skip to content

Commit

Permalink
More bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
clauderic committed Jun 6, 2024
1 parent ac8a9e1 commit 9351ad2
Show file tree
Hide file tree
Showing 15 changed files with 93 additions and 75 deletions.
14 changes: 13 additions & 1 deletion packages/abstract/src/core/entities/entity/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@ import {effects, reactive, type Effect} from '@dnd-kit/state';
import type {DragDropManager} from '../../manager/index.js';
import type {Data, UniqueIdentifier} from './types.js';

interface Options {
/**
* A boolean indicating whether the entity should automatically be registered with the manager.
* @defaultValue true
*/
register?: boolean;
}

export interface Input<T extends Data = Data, U extends Entity<T> = Entity<T>> {
id: UniqueIdentifier;
data?: T | null;
disabled?: boolean;
options?: Options;
effects?(): Effect[];
}

Expand Down Expand Up @@ -34,6 +43,7 @@ export class Entity<T extends Data = Data> {
const {
effects: getEffects = getDefaultEffects,
id,
options,
data = null,
disabled = false,
} = input;
Expand All @@ -45,7 +55,9 @@ export class Entity<T extends Data = Data> {
this.disabled = disabled;

queueMicrotask(() => {
manager.registry.register(this);
if (options?.register !== false) {
manager.registry.register(this);
}

const cleanupEffects = effects(
() => {
Expand Down
9 changes: 5 additions & 4 deletions packages/dom/src/plugins/debug/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class Debug extends Plugin<DragDropManager> {
const collidingIds = topCollisions.map(({id}) => id);

if (draggable && dragOperation.shape) {
const element = draggableElement ?? createDebugElement('dialog');
const element = draggableElement ?? createDebugElement();
const {boundingRectangle} = dragOperation.shape.current;

if (!draggableElement) {
Expand All @@ -40,7 +40,7 @@ export class Debug extends Plugin<DragDropManager> {
}

if (element instanceof HTMLDialogElement) {
element.showModal();
element.showPopover();
}

element.style.top = `${boundingRectangle.top}px`;
Expand Down Expand Up @@ -74,8 +74,8 @@ export class Debug extends Plugin<DragDropManager> {
debugElement.style.backgroundColor = droppable.isDropTarget
? 'rgba(13, 210, 36, 0.6)'
: collidingIds.includes(droppable.id)
? 'rgba(255, 193, 7, 0.5)'
: 'rgba(0, 0, 0, 0.1)';
? 'rgba(255, 193, 7, 0.5)'
: 'rgba(0, 0, 0, 0.1)';

debugElement.style.top = `${boundingRectangle.top}px`;
debugElement.style.left = `${boundingRectangle.left}px`;
Expand All @@ -95,6 +95,7 @@ export class Debug extends Plugin<DragDropManager> {
function createDebugElement(tagName = 'div') {
const element = document.createElement(tagName);

element.setAttribute('popover', '');
element.style.all = 'initial';
element.style.position = 'fixed';
element.style.display = 'flex';
Expand Down
2 changes: 1 addition & 1 deletion packages/dom/src/sortable/OptimisticSortingPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class OptimisticSortingPlugin extends Plugin<DragDropManager> {

if (sortableInstances.has(sortable.index)) {
throw new Error(
'Duplicate sortable index found for same sortable group. Make sure each sortable item has a unique index. Use the `group` attribute to separate sortables into different groups.'
`Duplicate sortable index found for same sortable group: ${sortable.droppable.id} and ${sortableInstances.get(sortable.index)?.droppable.id} have the same index (${sortable.index}). Make sure each sortable item has a unique index. Use the \`group\` attribute to separate sortables into different groups.`
);
}

Expand Down
4 changes: 4 additions & 0 deletions packages/dom/src/sortable/sortable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,10 @@ export class Sortable<T extends Data = Data> {
});
}

public get id() {
return this.droppable.id;
}

public set sensors(value: Sensors | undefined) {
this.draggable.sensors = value;
}
Expand Down
19 changes: 9 additions & 10 deletions packages/react/src/core/context/DragDropProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,7 @@ import {
import {type DragDropEvents} from '@dnd-kit/abstract';
import {DragDropManager, defaultPreset} from '@dnd-kit/dom';
import type {DragDropManagerInput, Draggable, Droppable} from '@dnd-kit/dom';
import {
useConstant,
useEvent,
useLatest,
useOnValueChange,
} from '@dnd-kit/react/hooks';
import {useConstant, useLatest, useOnValueChange} from '@dnd-kit/react/hooks';

import {DragDropContext} from './context.js';
import {useRenderer} from './renderer.js';
Expand Down Expand Up @@ -53,11 +48,11 @@ export const DragDropProvider = forwardRef<DragDropManager, Props>(
});
const {plugins, modifiers} = input;
const handleBeforeDragStart = useLatest(onBeforeDragStart);
const handleDragStart = useEvent(onDragStart);
const handleDragStart = useLatest(onDragStart);
const handleDragOver = useLatest(onDragOver);
const handleDragMove = useLatest(onDragMove);
const handleDragEnd = useLatest(onDragEnd);
const handleCollision = useEvent(onCollision);
const handleCollision = useLatest(onCollision);

useEffect(() => {
const listeners = [
Expand All @@ -71,7 +66,9 @@ export const DragDropProvider = forwardRef<DragDropManager, Props>(
}
}
),
manager.monitor.addEventListener('dragstart', handleDragStart),
manager.monitor.addEventListener('dragstart', (event, manager) =>
handleDragStart.current?.(event, manager)
),
manager.monitor.addEventListener('dragover', (event, manager) => {
const callback = handleDragOver.current;

Expand All @@ -93,7 +90,9 @@ export const DragDropProvider = forwardRef<DragDropManager, Props>(
trackRendering(() => callback(event, manager));
}
}),
manager.monitor.addEventListener('collision', handleCollision),
manager.monitor.addEventListener('collision', (event, manager) =>
handleCollision.current?.(event, manager)
),
];

return () => {
Expand Down
20 changes: 16 additions & 4 deletions packages/react/src/core/draggable/useDraggable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {Data} from '@dnd-kit/abstract';
import {Draggable} from '@dnd-kit/dom';
import type {DraggableInput} from '@dnd-kit/dom';
import {useComputed, useOnValueChange} from '@dnd-kit/react/hooks';
import {getCurrentValue, type RefOrValue} from '@dnd-kit/react/utilities';
import {currentValue, type RefOrValue} from '@dnd-kit/react/utilities';

import {useInstance} from '../hooks/useInstance.js';

Expand All @@ -17,10 +17,22 @@ export function useDraggable<T extends Data = Data>(
input: UseDraggableInput<T>
) {
const {disabled, id, sensors} = input;
const handle = getCurrentValue(input.handle);
const element = getCurrentValue(input.element);
const handle = currentValue(input.handle);
const element = currentValue(input.element);
const draggable = useInstance(
(manager) => new Draggable({...input, handle, element}, manager)
(manager) =>
new Draggable(
{
...input,
handle,
element,
options: {
...input.options,
register: false,
},
},
manager
)
);
const isDragSource = useComputed(() => draggable.isDragSource);

Expand Down
17 changes: 14 additions & 3 deletions packages/react/src/core/droppable/useDroppable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {Droppable} from '@dnd-kit/dom';
import {deepEqual} from '@dnd-kit/state';
import type {DroppableInput} from '@dnd-kit/dom';
import {useComputed, useOnValueChange} from '@dnd-kit/react/hooks';
import {getCurrentValue, type RefOrValue} from '@dnd-kit/react/utilities';
import {currentValue, type RefOrValue} from '@dnd-kit/react/utilities';

import {useInstance} from '../hooks/useInstance.js';

Expand All @@ -17,9 +17,20 @@ export function useDroppable<T extends Data = Data>(
input: UseDroppableInput<T>
) {
const {collisionDetector, disabled, id, accept, type} = input;
const element = getCurrentValue(input.element);
const element = currentValue(input.element);
const droppable = useInstance(
(manager) => new Droppable({...input, element}, manager)
(manager) =>
new Droppable(
{
...input,
element,
options: {
...input.options,
register: false,
},
},
manager
)
);
const isDisabled = useComputed(() => droppable.disabled);
const isDropTarget = useComputed(() => droppable.isDropTarget);
Expand Down
2 changes: 0 additions & 2 deletions packages/react/src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
export {useConstant} from './useConstant.js';
export {useComputed} from './useComputed.js';
export {useEvent} from './useEvent.js';
export {useImmediateEffect} from './useImmediateEffect.js';
export {useIsomorphicLayoutEffect} from './useIsomorphicLayoutEffect.js';
export {useLatest} from './useLatest.js';
export {useOnValueChange} from './useOnValueChange.js';
export {useSignalEffect} from './useSignalEffect.js';
14 changes: 0 additions & 14 deletions packages/react/src/hooks/useEvent.ts

This file was deleted.

5 changes: 3 additions & 2 deletions packages/react/src/hooks/useOnValueChange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ export function useOnValueChange<T>(
effect = useEffect,
compare = Object.is
) {
const tracked = useRef(value);
const tracked = useRef<T>(value);

effect(() => {
const oldValue = tracked.current;
if (!compare(value, tracked.current)) {

if (!compare(value, oldValue)) {
tracked.current = value;
onChange(value, oldValue);
}
Expand Down
6 changes: 0 additions & 6 deletions packages/react/src/hooks/useSignalEffect.ts

This file was deleted.

46 changes: 25 additions & 21 deletions packages/react/src/sortable/useSortable.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {useCallback, useEffect} from 'react';
import {useCallback, useLayoutEffect} from 'react';
import {deepEqual} from '@dnd-kit/state';
import {type Data} from '@dnd-kit/abstract';
import {Sortable, defaultSortableTransition} from '@dnd-kit/dom/sortable';
Expand All @@ -11,7 +11,7 @@ import {
useImmediateEffect as immediateEffect,
useIsomorphicLayoutEffect as layoutEffect,
} from '@dnd-kit/react/hooks';
import {getCurrentValue, type RefOrValue} from '@dnd-kit/react/utilities';
import {currentValue, type RefOrValue} from '@dnd-kit/react/utilities';

export interface UseSortableInput<T extends Data = Data>
extends Omit<SortableInput<T>, 'handle' | 'element'> {
Expand All @@ -27,6 +27,7 @@ export function useSortable<T extends Data = Data>(input: UseSortableInput<T>) {
id,
data,
index,
group,
disabled,
feedback,
sensors,
Expand All @@ -35,44 +36,48 @@ export function useSortable<T extends Data = Data>(input: UseSortableInput<T>) {
} = input;

const manager = useDragDropManager();
const handle = getCurrentValue(input.handle);
const element = getCurrentValue(input.element);
const sortable = useConstant(
() =>
new Sortable(
{
...input,
handle,
element,
feedback,
const handle = currentValue(input.handle);
const element = currentValue(input.element);
const sortable = useConstant(() => {
return new Sortable(
{
...input,
handle,
element,
feedback,
options: {
...input.options,
register: false,
},
manager
),
manager
);
},
manager
);
}, manager);

useEffect(() => {
useLayoutEffect(() => {
manager.registry.register(sortable.draggable);
manager.registry.register(sortable.droppable);

return () => {
manager.registry.unregister(sortable.draggable);
manager.registry.unregister(sortable.droppable);
};
}, [manager]);
}, [sortable, manager]);

const isDisabled = useComputed(() => sortable.disabled);
const isDropTarget = useComputed(() => sortable.isDropTarget);
const isDragSource = useComputed(() => sortable.isDragSource);

useOnValueChange(id, () => (sortable.id = id));
useOnValueChange(index, () => (sortable.index = index), layoutEffect);
useOnValueChange(type, () => (sortable.type = type));
useOnValueChange(group, () => (sortable.group = group));
useOnValueChange(
accept,
() => (sortable.accept = accept),
undefined,
deepEqual
);
useOnValueChange(type, () => (sortable.type = type));
useOnValueChange(id, () => (sortable.id = id));
useOnValueChange(data, () => (sortable.data = data ?? null));
useOnValueChange(
index,
Expand All @@ -83,7 +88,6 @@ export function useSortable<T extends Data = Data>(input: UseSortableInput<T>) {
},
immediateEffect
);
useOnValueChange(index, () => (sortable.index = index), layoutEffect);
useOnValueChange(handle, () => (sortable.handle = handle));
useOnValueChange(element, () => (sortable.element = element));
useOnValueChange(disabled, () => (sortable.disabled = disabled === true));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type RefOrValue<T> =
| null
| undefined;

export function getCurrentValue<T>(
export function currentValue<T>(
value: RefOrValue<T>
): NonNullable<T> | undefined {
if (value == null) {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/utilities/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export {getCurrentValue, type RefOrValue} from './getCurrentValue.js';
export {currentValue, type RefOrValue} from './currentValue.js';
6 changes: 1 addition & 5 deletions packages/state/src/comparators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,7 @@ export function deepEqual<T>(a: T, b: T) {
}

if (Array.isArray(a)) {
if (!Array.isArray(b)) {
return false;
}

if (a.length !== b.length) {
if (!Array.isArray(b) || a.length !== b.length) {
return false;
}

Expand Down

0 comments on commit 9351ad2

Please sign in to comment.