Skip to content

Commit

Permalink
Fix local modifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
clauderic committed Jul 11, 2024
1 parent d47bdf8 commit e9be505
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 29 deletions.
5 changes: 5 additions & 0 deletions .changeset/fix-local-modifiers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@dnd-kit/abstract': patch
---

Fix lifecycle of local modifiers now that it's possible to initialize a Draggable instance without a manager instance.
28 changes: 2 additions & 26 deletions packages/abstract/src/core/entities/draggable/draggable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ import {derived, reactive} from '@dnd-kit/state';

import {Entity} from '../entity/index.ts';
import type {EntityInput, Data, Type} from '../entity/index.ts';
import {Modifier} from '../../modifiers/index.ts';
import type {Modifiers} from '../../modifiers/index.ts';
import type {DragDropManager} from '../../manager/index.ts';
import {descriptor} from '../../plugins/index.ts';
import type {Sensors} from '../../sensors/sensor.ts';

export interface Input<T extends Data = Data> extends EntityInput<T> {
Expand Down Expand Up @@ -33,24 +31,8 @@ export class Draggable<

public sensors: Sensors | undefined;

#modifiers: Modifier[] | undefined;

public set modifiers(modifiers: Modifiers | undefined) {
const {manager} = this;

this.#modifiers?.forEach((modifier) => modifier.destroy());

if (!manager) return;
this.#modifiers = modifiers?.map((modifier) => {
const {plugin, options} = descriptor(modifier);

return new plugin(manager, options);
});
}

public get modifiers(): Modifier[] | undefined {
return this.#modifiers;
}
@reactive
public accessor modifiers: Modifiers | undefined;

@reactive
public accessor type: Type | undefined;
Expand All @@ -65,10 +47,4 @@ export class Draggable<
public get isDragSource() {
return this.manager?.dragOperation.source?.id === this.id;
}

public destroy() {
super.destroy();

this.modifiers?.forEach((modifier) => modifier.destroy());
}
}
32 changes: 29 additions & 3 deletions packages/abstract/src/core/manager/dragOperation.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import {Position, type Shape} from '@dnd-kit/geometry';
import type {Coordinates} from '@dnd-kit/geometry';
import {batch, computed, signal} from '@dnd-kit/state';
import {batch, computed, effect, signal} from '@dnd-kit/state';

import type {
Draggable,
Droppable,
UniqueIdentifier,
} from '../entities/index.ts';
import type {Modifier} from '../modifiers/index.ts';
import {descriptor} from '../plugins/index.ts';

import type {DragDropManager} from './manager.ts';
import {defaultPreventable} from './events.ts';
Expand Down Expand Up @@ -100,9 +102,24 @@ export function DragOperationManager<
return identifier != null ? droppables.get(identifier) ?? null : null;
});

const modifiers = signal<Modifier[]>([]);

effect(() => {
const currentModifiers = modifiers.peek();

if (currentModifiers !== manager.modifiers) {
currentModifiers.forEach((modifier) => modifier.destroy());
}

modifiers.value =
source.value?.modifiers?.map((modifier) => {
const {plugin, options} = descriptor(modifier);
return new plugin(manager, options);
}) ?? manager.modifiers;
});

const transform = computed(() => {
const {x, y} = position.delta;
const modifiers = source?.value?.modifiers ?? manager.modifiers;

let transform = {x, y};
const initialShape = shape.initial.peek();
Expand All @@ -128,7 +145,7 @@ export function DragOperationManager<
position,
};

for (const modifier of modifiers) {
for (const modifier of modifiers.value) {
transform = modifier.apply({...operation, transform});
}

Expand Down Expand Up @@ -204,6 +221,7 @@ export function DragOperationManager<
shape.current.value = null;
shape.initial.value = null;
position.reset({x: 0, y: 0});
modifiers.value = [];
});
};

Expand Down Expand Up @@ -236,6 +254,14 @@ export function DragOperationManager<
return manager.renderer.rendering;
},
start({event, coordinates}: {event: Event; coordinates: Coordinates}) {
const sourceInstance = source.peek();

if (!sourceInstance) {
throw new Error(
'Cannot start a drag operation without a drag source'
);
}

batch(() => {
dragended.value = false;
canceled.value = false;
Expand Down

0 comments on commit e9be505

Please sign in to comment.