You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
5.4 KiB

import wrapConnectorHooks from './wrapConnectorHooks';
import { isRef } from '../utils/isRef';
import { shallowEqual } from '@react-dnd/shallowequal';
export class SourceConnector {
constructor(backend) {
this.hooks = wrapConnectorHooks({
dragSource: (node, options) => {
this.clearDragSource();
this.dragSourceOptions = options || null;
if (isRef(node)) {
this.dragSourceRef = node;
}
else {
this.dragSourceNode = node;
}
this.reconnectDragSource();
},
dragPreview: (node, options) => {
this.clearDragPreview();
this.dragPreviewOptions = options || null;
if (isRef(node)) {
this.dragPreviewRef = node;
}
else {
this.dragPreviewNode = node;
}
this.reconnectDragPreview();
},
});
this.handlerId = null;
// The drop target may either be attached via ref or connect function
this.dragSourceRef = null;
this.dragSourceOptionsInternal = null;
// The drag preview may either be attached via ref or connect function
this.dragPreviewRef = null;
this.dragPreviewOptionsInternal = null;
this.lastConnectedHandlerId = null;
this.lastConnectedDragSource = null;
this.lastConnectedDragSourceOptions = null;
this.lastConnectedDragPreview = null;
this.lastConnectedDragPreviewOptions = null;
this.backend = backend;
}
receiveHandlerId(newHandlerId) {
if (this.handlerId === newHandlerId) {
return;
}
this.handlerId = newHandlerId;
this.reconnect();
}
get connectTarget() {
return this.dragSource;
}
get dragSourceOptions() {
return this.dragSourceOptionsInternal;
}
set dragSourceOptions(options) {
this.dragSourceOptionsInternal = options;
}
get dragPreviewOptions() {
return this.dragPreviewOptionsInternal;
}
set dragPreviewOptions(options) {
this.dragPreviewOptionsInternal = options;
}
reconnect() {
this.reconnectDragSource();
this.reconnectDragPreview();
}
reconnectDragSource() {
const dragSource = this.dragSource;
// if nothing has changed then don't resubscribe
const didChange = this.didHandlerIdChange() ||
this.didConnectedDragSourceChange() ||
this.didDragSourceOptionsChange();
if (didChange) {
this.disconnectDragSource();
}
if (!this.handlerId) {
return;
}
if (!dragSource) {
this.lastConnectedDragSource = dragSource;
return;
}
if (didChange) {
this.lastConnectedHandlerId = this.handlerId;
this.lastConnectedDragSource = dragSource;
this.lastConnectedDragSourceOptions = this.dragSourceOptions;
this.dragSourceUnsubscribe = this.backend.connectDragSource(this.handlerId, dragSource, this.dragSourceOptions);
}
}
reconnectDragPreview() {
const dragPreview = this.dragPreview;
// if nothing has changed then don't resubscribe
const didChange = this.didHandlerIdChange() ||
this.didConnectedDragPreviewChange() ||
this.didDragPreviewOptionsChange();
if (!this.handlerId) {
this.disconnectDragPreview();
}
else if (this.dragPreview && didChange) {
this.lastConnectedHandlerId = this.handlerId;
this.lastConnectedDragPreview = dragPreview;
this.lastConnectedDragPreviewOptions = this.dragPreviewOptions;
this.disconnectDragPreview();
this.dragPreviewUnsubscribe = this.backend.connectDragPreview(this.handlerId, dragPreview, this.dragPreviewOptions);
}
}
didHandlerIdChange() {
return this.lastConnectedHandlerId !== this.handlerId;
}
didConnectedDragSourceChange() {
return this.lastConnectedDragSource !== this.dragSource;
}
didConnectedDragPreviewChange() {
return this.lastConnectedDragPreview !== this.dragPreview;
}
didDragSourceOptionsChange() {
return !shallowEqual(this.lastConnectedDragSourceOptions, this.dragSourceOptions);
}
didDragPreviewOptionsChange() {
return !shallowEqual(this.lastConnectedDragPreviewOptions, this.dragPreviewOptions);
}
disconnectDragSource() {
if (this.dragSourceUnsubscribe) {
this.dragSourceUnsubscribe();
this.dragSourceUnsubscribe = undefined;
}
}
disconnectDragPreview() {
if (this.dragPreviewUnsubscribe) {
this.dragPreviewUnsubscribe();
this.dragPreviewUnsubscribe = undefined;
this.dragPreviewNode = null;
this.dragPreviewRef = null;
}
}
get dragSource() {
return (this.dragSourceNode || (this.dragSourceRef && this.dragSourceRef.current));
}
get dragPreview() {
return (this.dragPreviewNode ||
(this.dragPreviewRef && this.dragPreviewRef.current));
}
clearDragSource() {
this.dragSourceNode = null;
this.dragSourceRef = null;
}
clearDragPreview() {
this.dragPreviewNode = null;
this.dragPreviewRef = null;
}
}