Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@vizzly/dnd-backend

Package Overview
Dependencies
Maintainers
2
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vizzly/dnd-backend - npm Package Compare versions

Comparing version 0.0.1 to 0.0.2

921

dist/index.js

@@ -1,7 +0,918 @@

import { HTML5BackendImpl } from './HTML5BackendImpl.js';
export { getEmptyImage } from './getEmptyImage.js';
export * as NativeTypes from './NativeTypes.js';
export const HTML5Backend = function createBackend(manager, context, options) {
// cheap lodash replacements
function memoize(fn) {
let result = null;
const memoized = () => {
if (result == null) {
result = fn();
}
return result;
};
return memoized;
}
/**
* drop-in replacement for _.without
*/
function without(items, item) {
return items.filter((i) => i !== item);
}
function union(itemsA, itemsB) {
const set = new Set();
const insertItem = (item) => set.add(item);
itemsA.forEach(insertItem);
itemsB.forEach(insertItem);
const result = [];
set.forEach((key) => result.push(key));
return result;
}
class EnterLeaveCounter {
constructor(isNodeInDocument) {
this.entered = [];
this.isNodeInDocument = isNodeInDocument;
}
enter(enteringNode) {
const previousLength = this.entered.length;
const isNodeEntered = (node) => this.isNodeInDocument(node) &&
(!node.contains || node.contains(enteringNode));
this.entered = union(this.entered.filter(isNodeEntered), [enteringNode]);
return previousLength === 0 && this.entered.length > 0;
}
leave(leavingNode) {
const previousLength = this.entered.length;
this.entered = without(this.entered.filter(this.isNodeInDocument), leavingNode);
return previousLength > 0 && this.entered.length === 0;
}
reset() {
this.entered = [];
}
}
class NativeDragSource {
constructor(config) {
this.config = config;
this.item = {};
this.initializeExposedProperties();
}
initializeExposedProperties() {
Object.keys(this.config.exposeProperties).forEach((property) => {
Object.defineProperty(this.item, property, {
configurable: true, // This is needed to allow redefining it later
enumerable: true,
get() {
// eslint-disable-next-line no-console
console.warn(`Browser doesn't allow reading "${property}" until the drop event.`);
return null;
},
});
});
}
loadDataTransfer(dataTransfer) {
if (dataTransfer) {
const newProperties = {};
Object.keys(this.config.exposeProperties).forEach((property) => {
const propertyFn = this.config.exposeProperties[property];
if (propertyFn != null) {
newProperties[property] = {
value: propertyFn(dataTransfer, this.config.matchesTypes),
configurable: true,
enumerable: true,
};
}
});
Object.defineProperties(this.item, newProperties);
}
}
canDrag() {
return true;
}
beginDrag() {
return this.item;
}
isDragging(monitor, handle) {
return handle === monitor.getSourceId();
}
endDrag() {
// empty
}
}
const FILE = '__NATIVE_FILE__';
const URL = '__NATIVE_URL__';
const TEXT = '__NATIVE_TEXT__';
const HTML = '__NATIVE_HTML__';
var NativeTypes = /*#__PURE__*/Object.freeze({
__proto__: null,
FILE: FILE,
HTML: HTML,
TEXT: TEXT,
URL: URL
});
function getDataFromDataTransfer(dataTransfer, typesToTry, defaultValue) {
const result = typesToTry.reduce((resultSoFar, typeToTry) => resultSoFar || dataTransfer.getData(typeToTry), '');
return result != null ? result : defaultValue;
}
const nativeTypesConfig = {
[FILE]: {
exposeProperties: {
files: (dataTransfer) => Array.prototype.slice.call(dataTransfer.files),
items: (dataTransfer) => dataTransfer.items,
dataTransfer: (dataTransfer) => dataTransfer,
},
matchesTypes: ['Files'],
},
[HTML]: {
exposeProperties: {
html: (dataTransfer, matchesTypes) => getDataFromDataTransfer(dataTransfer, matchesTypes, ''),
dataTransfer: (dataTransfer) => dataTransfer,
},
matchesTypes: ['Html', 'text/html'],
},
[URL]: {
exposeProperties: {
urls: (dataTransfer, matchesTypes) => getDataFromDataTransfer(dataTransfer, matchesTypes, '').split('\n'),
dataTransfer: (dataTransfer) => dataTransfer,
},
matchesTypes: ['Url', 'text/uri-list'],
},
[TEXT]: {
exposeProperties: {
text: (dataTransfer, matchesTypes) => getDataFromDataTransfer(dataTransfer, matchesTypes, ''),
dataTransfer: (dataTransfer) => dataTransfer,
},
matchesTypes: ['Text', 'text/plain'],
},
};
function createNativeDragSource(type, dataTransfer) {
const config = nativeTypesConfig[type];
if (!config) {
throw new Error(`native type ${type} has no configuration`);
}
const result = new NativeDragSource(config);
result.loadDataTransfer(dataTransfer);
return result;
}
function matchNativeItemType(dataTransfer) {
if (!dataTransfer) {
return null;
}
const dataTransferTypes = Array.prototype.slice.call(dataTransfer.types || []);
return (Object.keys(nativeTypesConfig).filter((nativeItemType) => {
const typeConfig = nativeTypesConfig[nativeItemType];
if (!(typeConfig === null || typeConfig === void 0 ? void 0 : typeConfig.matchesTypes)) {
return false;
}
return typeConfig.matchesTypes.some((t) => dataTransferTypes.indexOf(t) > -1);
})[0] || null);
}
const isFirefox = memoize(() => /firefox/i.test(navigator.userAgent));
const isSafari = memoize(() => Boolean(window.safari));
/* eslint-disable @typescript-eslint/no-non-null-assertion */
class MonotonicInterpolant {
constructor(xs, ys) {
const { length } = xs;
// Rearrange xs and ys so that xs is sorted
const indexes = [];
for (let i = 0; i < length; i++) {
indexes.push(i);
}
indexes.sort((a, b) => (xs[a] < xs[b] ? -1 : 1));
const dxs = [];
const ms = [];
let dx;
let dy;
for (let i = 0; i < length - 1; i++) {
dx = xs[i + 1] - xs[i];
dy = ys[i + 1] - ys[i];
dxs.push(dx);
ms.push(dy / dx);
}
// Get degree-1 coefficients
const c1s = [ms[0]];
for (let i = 0; i < dxs.length - 1; i++) {
const m2 = ms[i];
const mNext = ms[i + 1];
if (m2 * mNext <= 0) {
c1s.push(0);
}
else {
dx = dxs[i];
const dxNext = dxs[i + 1];
const common = dx + dxNext;
c1s.push((3 * common) / ((common + dxNext) / m2 + (common + dx) / mNext));
}
}
c1s.push(ms[ms.length - 1]);
// Get degree-2 and degree-3 coefficients
const c2s = [];
const c3s = [];
let m;
for (let i = 0; i < c1s.length - 1; i++) {
m = ms[i];
const c1 = c1s[i];
const invDx = 1 / dxs[i];
const common = c1 + c1s[i + 1] - m - m;
c2s.push((m - c1 - common) * invDx);
c3s.push(common * invDx * invDx);
}
this.xs = xs;
this.ys = ys;
this.c1s = c1s;
this.c2s = c2s;
this.c3s = c3s;
}
interpolate(x) {
const { xs, ys, c1s, c2s, c3s } = this;
// The rightmost point in the dataset should give an exact result
let i = xs.length - 1;
if (x === xs[i]) {
return ys[i];
}
// Search for the interval x is in, returning the corresponding y if x is one of the original xs
let low = 0;
let high = c3s.length - 1;
let mid;
while (low <= high) {
mid = Math.floor(0.5 * (low + high));
const xHere = xs[mid];
if (xHere < x) {
low = mid + 1;
}
else if (xHere > x) {
high = mid - 1;
}
else {
return ys[mid];
}
}
i = Math.max(0, high);
// Interpolate
const diff = x - xs[i];
const diffSq = diff * diff;
return ys[i] + c1s[i] * diff + c2s[i] * diffSq + c3s[i] * diff * diffSq;
}
}
const ELEMENT_NODE = 1;
function getNodeClientOffset(node) {
const el = node.nodeType === ELEMENT_NODE ? node : node.parentElement;
if (!el) {
return null;
}
const { top, left } = el.getBoundingClientRect();
return { x: left, y: top };
}
function getEventClientOffset(e) {
return {
x: e.clientX,
y: e.clientY,
};
}
function isImageNode(node) {
var _a;
return (node.nodeName === 'IMG' &&
(isFirefox() || !((_a = document.documentElement) === null || _a === void 0 ? void 0 : _a.contains(node))));
}
function getDragPreviewSize(isImage, dragPreview, sourceWidth, sourceHeight) {
let dragPreviewWidth = isImage ? dragPreview.width : sourceWidth;
let dragPreviewHeight = isImage ? dragPreview.height : sourceHeight;
// Work around @2x coordinate discrepancies in browsers
if (isSafari() && isImage) {
dragPreviewHeight /= window.devicePixelRatio;
dragPreviewWidth /= window.devicePixelRatio;
}
return { dragPreviewWidth, dragPreviewHeight };
}
function getDragPreviewOffset(sourceNode, dragPreview, clientOffset, anchorPoint, offsetPoint) {
// The browsers will use the image intrinsic size under different conditions.
// Firefox only cares if it's an image, but WebKit also wants it to be detached.
const isImage = isImageNode(dragPreview);
const dragPreviewNode = isImage ? sourceNode : dragPreview;
const dragPreviewNodeOffsetFromClient = getNodeClientOffset(dragPreviewNode);
const offsetFromDragPreview = {
x: clientOffset.x - dragPreviewNodeOffsetFromClient.x,
y: clientOffset.y - dragPreviewNodeOffsetFromClient.y,
};
const { offsetWidth: sourceWidth, offsetHeight: sourceHeight } = sourceNode;
const { anchorX, anchorY } = anchorPoint;
const { dragPreviewWidth, dragPreviewHeight } = getDragPreviewSize(isImage, dragPreview, sourceWidth, sourceHeight);
const calculateYOffset = () => {
const interpolantY = new MonotonicInterpolant([0, 0.5, 1], [
// Dock to the top
offsetFromDragPreview.y,
// Align at the center
(offsetFromDragPreview.y / sourceHeight) * dragPreviewHeight,
// Dock to the bottom
offsetFromDragPreview.y + dragPreviewHeight - sourceHeight,
]);
let y = interpolantY.interpolate(anchorY);
// Work around Safari 8 positioning bug
if (isSafari() && isImage) {
// We'll have to wait for @3x to see if this is entirely correct
y += (window.devicePixelRatio - 1) * dragPreviewHeight;
}
return y;
};
const calculateXOffset = () => {
// Interpolate coordinates depending on anchor point
// If you know a simpler way to do this, let me know
const interpolantX = new MonotonicInterpolant([0, 0.5, 1], [
// Dock to the left
offsetFromDragPreview.x,
// Align at the center
(offsetFromDragPreview.x / sourceWidth) * dragPreviewWidth,
// Dock to the right
offsetFromDragPreview.x + dragPreviewWidth - sourceWidth,
]);
return interpolantX.interpolate(anchorX);
};
// Force offsets if specified in the options.
const { offsetX, offsetY } = offsetPoint;
const isManualOffsetX = offsetX === 0 || offsetX;
const isManualOffsetY = offsetY === 0 || offsetY;
return {
x: isManualOffsetX ? offsetX : calculateXOffset(),
y: isManualOffsetY ? offsetY : calculateYOffset(),
};
}
class OptionsReader {
constructor(globalContext, options) {
this.ownerDocument = null;
this.globalContext = globalContext;
this.optionsArgs = options;
}
get window() {
var _a;
return (_a = this.globalContext) !== null && _a !== void 0 ? _a : (typeof window !== 'undefined' ? window : undefined);
}
get document() {
var _a, _b, _c;
return (_b = (_a = this.globalContext) === null || _a === void 0 ? void 0 : _a.document) !== null && _b !== void 0 ? _b : (_c = this.window) === null || _c === void 0 ? void 0 : _c.document;
}
get rootElement() {
var _a;
return ((_a = this.optionsArgs) === null || _a === void 0 ? void 0 : _a.rootElement) || this.window;
}
}
class HTML5BackendImpl {
constructor(manager, globalContext, options) {
this.sourcePreviewNodes = new Map();
this.sourcePreviewNodeOptions = new Map();
this.sourceNodes = new Map();
this.sourceNodeOptions = new Map();
this.dragStartSourceIds = null;
this.dropTargetIds = [];
this.dragEnterTargetIds = [];
this.currentNativeSource = null;
this.currentNativeHandle = null;
this.currentDragSourceNode = null;
this.altKeyPressed = false;
this.mouseMoveTimeoutTimer = null;
this.asyncEndDragFrameId = null;
this.dragOverTargetIds = null;
this.lastClientOffset = null;
this.hoverRafId = null;
this.getSourceClientOffset = (sourceId) => {
const source = this.sourceNodes.get(sourceId);
return (source && getNodeClientOffset(source)) || null;
};
this.endDragNativeItem = () => {
if (!this.isDraggingNativeItem()) {
return;
}
this.actions.endDrag();
if (this.currentNativeHandle) {
this.registry.removeSource(this.currentNativeHandle);
}
this.currentNativeHandle = null;
this.currentNativeSource = null;
};
this.isNodeInDocument = (node) => {
// Check the node either in the main document or in the current context
return Boolean(node &&
this.document &&
this.document.body &&
this.document.body.contains(node));
};
this.endDragIfSourceWasRemovedFromDOM = () => {
const node = this.currentDragSourceNode;
if (node == null || this.isNodeInDocument(node)) {
return;
}
if (this.clearCurrentDragSourceNode() && this.monitor.isDragging()) {
this.actions.endDrag();
}
this.cancelHover();
};
this.scheduleHover = (dragOverTargetIds) => {
if (this.hoverRafId === null &&
typeof requestAnimationFrame !== "undefined") {
this.hoverRafId = requestAnimationFrame(() => {
if (this.monitor.isDragging()) {
this.actions.hover(dragOverTargetIds || [], {
clientOffset: this.lastClientOffset,
});
}
this.hoverRafId = null;
});
}
};
this.cancelHover = () => {
if (this.hoverRafId !== null &&
typeof cancelAnimationFrame !== "undefined") {
cancelAnimationFrame(this.hoverRafId);
this.hoverRafId = null;
}
};
this.handleTopDragStartCapture = () => {
this.clearCurrentDragSourceNode();
this.dragStartSourceIds = [];
};
this.handleTopDragStart = (e) => {
if (e.defaultPrevented) {
return;
}
const { dragStartSourceIds } = this;
this.dragStartSourceIds = null;
const clientOffset = getEventClientOffset(e);
// Avoid crashing if we missed a drop event or our previous drag died
if (this.monitor.isDragging()) {
this.actions.endDrag();
this.cancelHover();
}
// Don't publish the source just yet (see why below)
this.actions.beginDrag(dragStartSourceIds || [], {
publishSource: false,
getSourceClientOffset: this.getSourceClientOffset,
clientOffset,
});
const { dataTransfer } = e;
const nativeType = matchNativeItemType(dataTransfer);
if (this.monitor.isDragging()) {
if (dataTransfer && typeof dataTransfer.setDragImage === "function") {
// Use custom drag image if user specifies it.
// If child drag source refuses drag but parent agrees,
// use parent's node as drag image. Neither works in IE though.
const sourceId = this.monitor.getSourceId();
const sourceNode = this.sourceNodes.get(sourceId);
const dragPreview = this.sourcePreviewNodes.get(sourceId) || sourceNode;
if (dragPreview) {
const { anchorX, anchorY, offsetX, offsetY } = this.getCurrentSourcePreviewNodeOptions();
const anchorPoint = { anchorX, anchorY };
const offsetPoint = { offsetX, offsetY };
const dragPreviewOffset = getDragPreviewOffset(sourceNode, dragPreview, clientOffset, anchorPoint, offsetPoint);
dataTransfer.setDragImage(dragPreview, dragPreviewOffset.x, dragPreviewOffset.y);
}
}
try {
// Firefox won't drag without setting data
dataTransfer === null || dataTransfer === void 0 ? void 0 : dataTransfer.setData("application/json", {});
}
catch (err) {
// IE doesn't support MIME types in setData
}
// Store drag source node so we can check whether
// it is removed from DOM and trigger endDrag manually.
this.setCurrentDragSourceNode(e.target);
// Now we are ready to publish the drag source.. or are we not?
const { captureDraggingState } = this.getCurrentSourcePreviewNodeOptions();
if (!captureDraggingState) {
// Usually we want to publish it in the next tick so that browser
// is able to screenshot the current (not yet dragging) state.
//
// It also neatly avoids a situation where render() returns null
// in the same tick for the source element, and browser freaks out.
setTimeout(() => this.actions.publishDragSource(), 0);
}
else {
// In some cases the user may want to override this behavior, e.g.
// to work around IE not supporting custom drag previews.
//
// When using a custom drag layer, the only way to prevent
// the default drag preview from drawing in IE is to screenshot
// the dragging state in which the node itself has zero opacity
// and height. In this case, though, returning null from render()
// will abruptly end the dragging, which is not obvious.
//
// This is the reason such behavior is strictly opt-in.
this.actions.publishDragSource();
}
}
else if (nativeType) {
// A native item (such as URL) dragged from inside the document
this.beginDragNativeItem(nativeType);
}
else if (dataTransfer &&
!dataTransfer.types &&
((e.target && !e.target.hasAttribute) ||
!e.target.hasAttribute("draggable"))) {
// Looks like a Safari bug: dataTransfer.types is null, but there was no draggable.
// Just let it drag. It's a native type (URL or text) and will be picked up in
// dragenter handler.
return;
}
else {
// If by this time no drag source reacted, tell browser not to drag.
e.preventDefault();
}
};
this.handleTopDragEndCapture = () => {
if (this.clearCurrentDragSourceNode() && this.monitor.isDragging()) {
// Firefox can dispatch this event in an infinite loop
// if dragend handler does something like showing an alert.
// Only proceed if we have not handled it already.
this.actions.endDrag();
}
this.cancelHover();
};
this.handleTopDragEnterCapture = (e) => {
var _a;
this.dragEnterTargetIds = [];
if (this.isDraggingNativeItem()) {
(_a = this.currentNativeSource) === null || _a === void 0 ? void 0 : _a.loadDataTransfer(e.dataTransfer);
}
const isFirstEnter = this.enterLeaveCounter.enter(e.target);
if (!isFirstEnter || this.monitor.isDragging()) {
return;
}
const { dataTransfer } = e;
const nativeType = matchNativeItemType(dataTransfer);
if (nativeType) {
// A native item (such as file or URL) dragged from outside the document
this.beginDragNativeItem(nativeType, dataTransfer);
}
};
this.handleTopDragEnter = (e) => {
const { dragEnterTargetIds } = this;
this.dragEnterTargetIds = [];
if (!this.monitor.isDragging()) {
// This is probably a native item type we don't understand.
return;
}
this.altKeyPressed = e.altKey;
// If the target changes position as the result of `dragenter`, `dragover` might still
// get dispatched despite target being no longer there. The easy solution is to check
// whether there actually is a target before firing `hover`.
if (dragEnterTargetIds.length > 0) {
this.actions.hover(dragEnterTargetIds, {
clientOffset: getEventClientOffset(e),
});
}
const canDrop = dragEnterTargetIds.some((targetId) => this.monitor.canDropOnTarget(targetId));
if (canDrop) {
// IE requires this to fire dragover events
e.preventDefault();
if (e.dataTransfer) {
e.dataTransfer.dropEffect = this.getCurrentDropEffect();
}
}
};
this.handleTopDragOverCapture = (e) => {
var _a;
this.dragOverTargetIds = [];
if (this.isDraggingNativeItem()) {
(_a = this.currentNativeSource) === null || _a === void 0 ? void 0 : _a.loadDataTransfer(e.dataTransfer);
}
};
this.handleTopDragOver = (e) => {
const { dragOverTargetIds } = this;
this.dragOverTargetIds = [];
if (!this.monitor.isDragging()) {
// This is probably a native item type we don't understand.
// Prevent default "drop and blow away the whole document" action.
e.preventDefault();
if (e.dataTransfer) {
e.dataTransfer.dropEffect = "none";
}
return;
}
this.altKeyPressed = e.altKey;
this.lastClientOffset = getEventClientOffset(e);
this.scheduleHover(dragOverTargetIds);
const canDrop = (dragOverTargetIds || []).some((targetId) => this.monitor.canDropOnTarget(targetId));
if (canDrop) {
// Show user-specified drop effect.
e.preventDefault();
if (e.dataTransfer) {
e.dataTransfer.dropEffect = this.getCurrentDropEffect();
}
}
else if (this.isDraggingNativeItem()) {
// Don't show a nice cursor but still prevent default
// "drop and blow away the whole document" action.
e.preventDefault();
}
else {
e.preventDefault();
if (e.dataTransfer) {
e.dataTransfer.dropEffect = "none";
}
}
};
this.handleTopDragLeaveCapture = (e) => {
if (this.isDraggingNativeItem()) {
e.preventDefault();
}
const isLastLeave = this.enterLeaveCounter.leave(e.target);
if (!isLastLeave) {
return;
}
if (this.isDraggingNativeItem()) {
setTimeout(() => this.endDragNativeItem(), 0);
}
this.cancelHover();
};
this.handleTopDropCapture = (e) => {
var _a;
this.dropTargetIds = [];
if (this.isDraggingNativeItem()) {
e.preventDefault();
(_a = this.currentNativeSource) === null || _a === void 0 ? void 0 : _a.loadDataTransfer(e.dataTransfer);
}
else if (matchNativeItemType(e.dataTransfer)) {
// Dragging some elements, like <a> and <img> may still behave like a native drag event,
// even if the current drag event matches a user-defined type.
// Stop the default behavior when we're not expecting a native item to be dropped.
e.preventDefault();
}
this.enterLeaveCounter.reset();
};
this.handleTopDrop = (e) => {
const { dropTargetIds } = this;
this.dropTargetIds = [];
this.actions.hover(dropTargetIds, {
clientOffset: getEventClientOffset(e),
});
this.actions.drop({ dropEffect: this.getCurrentDropEffect() });
if (this.isDraggingNativeItem()) {
this.endDragNativeItem();
}
else if (this.monitor.isDragging()) {
this.actions.endDrag();
}
this.cancelHover();
};
this.handleSelectStart = (e) => {
const target = e.target;
// Only IE requires us to explicitly say
// we want drag drop operation to start
if (typeof target.dragDrop !== "function") {
return;
}
// Inputs and textareas should be selectable
if (target.tagName === "INPUT" ||
target.tagName === "SELECT" ||
target.tagName === "TEXTAREA" ||
target.isContentEditable) {
return;
}
// For other targets, ask IE
// to enable drag and drop
e.preventDefault();
target.dragDrop();
};
this.options = new OptionsReader(globalContext, options);
this.actions = manager.getActions();
this.monitor = manager.getMonitor();
this.registry = manager.getRegistry();
this.enterLeaveCounter = new EnterLeaveCounter(this.isNodeInDocument);
}
/**
* Generate profiling statistics for the HTML5Backend.
*/
profile() {
var _a, _b;
return {
sourcePreviewNodes: this.sourcePreviewNodes.size,
sourcePreviewNodeOptions: this.sourcePreviewNodeOptions.size,
sourceNodeOptions: this.sourceNodeOptions.size,
sourceNodes: this.sourceNodes.size,
dragStartSourceIds: ((_a = this.dragStartSourceIds) === null || _a === void 0 ? void 0 : _a.length) || 0,
dropTargetIds: this.dropTargetIds.length,
dragEnterTargetIds: this.dragEnterTargetIds.length,
dragOverTargetIds: ((_b = this.dragOverTargetIds) === null || _b === void 0 ? void 0 : _b.length) || 0,
};
}
// public for test
get window() {
return this.options.window;
}
get document() {
return this.options.document;
}
/**
* Get the root element to use for event subscriptions
*/
get rootElement() {
return this.options.rootElement;
}
setup() {
const root = this.rootElement;
if (root === undefined) {
return;
}
if (root.__isReactDndBackendSetUp) {
throw new Error("Cannot have two HTML5 backends at the same time.");
}
root.__isReactDndBackendSetUp = true;
this.addEventListeners(root);
}
teardown() {
var _a;
const root = this.rootElement;
if (root === undefined) {
return;
}
root.__isReactDndBackendSetUp = false;
this.removeEventListeners(this.rootElement);
this.clearCurrentDragSourceNode();
if (this.asyncEndDragFrameId) {
(_a = this.window) === null || _a === void 0 ? void 0 : _a.cancelAnimationFrame(this.asyncEndDragFrameId);
}
}
connectDragPreview(sourceId, node, options) {
this.sourcePreviewNodeOptions.set(sourceId, options);
this.sourcePreviewNodes.set(sourceId, node);
return () => {
this.sourcePreviewNodes.delete(sourceId);
this.sourcePreviewNodeOptions.delete(sourceId);
};
}
connectDragSource(sourceId, node, options) {
this.sourceNodes.set(sourceId, node);
this.sourceNodeOptions.set(sourceId, options);
const handleDragStart = (e) => this.handleDragStart(e, sourceId);
const handleSelectStart = (e) => this.handleSelectStart(e);
node.setAttribute("draggable", "true");
node.addEventListener("dragstart", handleDragStart);
node.addEventListener("selectstart", handleSelectStart);
return () => {
this.sourceNodes.delete(sourceId);
this.sourceNodeOptions.delete(sourceId);
node.removeEventListener("dragstart", handleDragStart);
node.removeEventListener("selectstart", handleSelectStart);
node.setAttribute("draggable", "false");
};
}
connectDropTarget(targetId, node) {
const handleDragEnter = (e) => this.handleDragEnter(e, targetId);
const handleDragOver = (e) => this.handleDragOver(e, targetId);
const handleDrop = (e) => this.handleDrop(e, targetId);
node.addEventListener("dragenter", handleDragEnter);
node.addEventListener("dragover", handleDragOver);
node.addEventListener("drop", handleDrop);
return () => {
node.removeEventListener("dragenter", handleDragEnter);
node.removeEventListener("dragover", handleDragOver);
node.removeEventListener("drop", handleDrop);
};
}
addEventListeners(target) {
// SSR Fix (https://github.com/react-dnd/react-dnd/pull/813
if (!target.addEventListener) {
return;
}
target.addEventListener("dragstart", this.handleTopDragStart);
target.addEventListener("dragstart", this.handleTopDragStartCapture, true);
target.addEventListener("dragend", this.handleTopDragEndCapture, true);
target.addEventListener("dragenter", this.handleTopDragEnter);
target.addEventListener("dragenter", this.handleTopDragEnterCapture, true);
target.addEventListener("dragleave", this.handleTopDragLeaveCapture, true);
target.addEventListener("dragover", this.handleTopDragOver);
target.addEventListener("dragover", this.handleTopDragOverCapture, true);
target.addEventListener("drop", this.handleTopDrop);
target.addEventListener("drop", this.handleTopDropCapture, true);
}
removeEventListeners(target) {
// SSR Fix (https://github.com/react-dnd/react-dnd/pull/813
if (!target.removeEventListener) {
return;
}
target.removeEventListener("dragstart", this.handleTopDragStart);
target.removeEventListener("dragstart", this.handleTopDragStartCapture, true);
target.removeEventListener("dragend", this.handleTopDragEndCapture, true);
target.removeEventListener("dragenter", this.handleTopDragEnter);
target.removeEventListener("dragenter", this.handleTopDragEnterCapture, true);
target.removeEventListener("dragleave", this.handleTopDragLeaveCapture, true);
target.removeEventListener("dragover", this.handleTopDragOver);
target.removeEventListener("dragover", this.handleTopDragOverCapture, true);
target.removeEventListener("drop", this.handleTopDrop);
target.removeEventListener("drop", this.handleTopDropCapture, true);
}
getCurrentSourceNodeOptions() {
const sourceId = this.monitor.getSourceId();
const sourceNodeOptions = this.sourceNodeOptions.get(sourceId);
return Object.assign({ dropEffect: this.altKeyPressed ? "copy" : "move" }, (sourceNodeOptions || {}));
}
getCurrentDropEffect() {
if (this.isDraggingNativeItem()) {
// It makes more sense to default to 'copy' for native resources
return "copy";
}
return this.getCurrentSourceNodeOptions().dropEffect;
}
getCurrentSourcePreviewNodeOptions() {
const sourceId = this.monitor.getSourceId();
const sourcePreviewNodeOptions = this.sourcePreviewNodeOptions.get(sourceId);
return Object.assign({ anchorX: 0.5, anchorY: 0.5, captureDraggingState: false }, (sourcePreviewNodeOptions || {}));
}
isDraggingNativeItem() {
const itemType = this.monitor.getItemType();
return Object.keys(NativeTypes).some((key) => NativeTypes[key] === itemType);
}
beginDragNativeItem(type, dataTransfer) {
this.clearCurrentDragSourceNode();
this.currentNativeSource = createNativeDragSource(type, dataTransfer);
this.currentNativeHandle = this.registry.addSource(type, this.currentNativeSource);
this.actions.beginDrag([this.currentNativeHandle]);
}
setCurrentDragSourceNode(node) {
this.clearCurrentDragSourceNode();
this.currentDragSourceNode = node;
// A timeout of > 0 is necessary to resolve Firefox issue referenced
// See:
// * https://github.com/react-dnd/react-dnd/pull/928
// * https://github.com/react-dnd/react-dnd/issues/869
const MOUSE_MOVE_TIMEOUT = 1000;
// Receiving a mouse event in the middle of a dragging operation
// means it has ended and the drag source node disappeared from DOM,
// so the browser didn't dispatch the dragend event.
//
// We need to wait before we start listening for mousemove events.
// This is needed because the drag preview needs to be drawn or else it fires an 'mousemove' event
// immediately in some browsers.
//
// See:
// * https://github.com/react-dnd/react-dnd/pull/928
// * https://github.com/react-dnd/react-dnd/issues/869
//
this.mouseMoveTimeoutTimer = setTimeout(() => {
var _a;
return (_a = this.rootElement) === null || _a === void 0 ? void 0 : _a.addEventListener("mousemove", this.endDragIfSourceWasRemovedFromDOM, true);
}, MOUSE_MOVE_TIMEOUT);
}
clearCurrentDragSourceNode() {
if (this.currentDragSourceNode) {
this.currentDragSourceNode = null;
if (this.rootElement && this.window) {
if (this.mouseMoveTimeoutTimer !== null) {
if (typeof this.window.clearTimeout === "function") {
this.window.clearTimeout(this.mouseMoveTimeoutTimer);
}
else if (typeof clearTimeout === "function") {
clearTimeout(this.mouseMoveTimeoutTimer);
}
this.mouseMoveTimeoutTimer = null;
}
this.rootElement.removeEventListener("mousemove", this.endDragIfSourceWasRemovedFromDOM, true);
}
return true;
}
return false;
}
handleDragStart(e, sourceId) {
if (e.defaultPrevented) {
return;
}
if (!this.dragStartSourceIds) {
this.dragStartSourceIds = [];
}
this.dragStartSourceIds.unshift(sourceId);
}
handleDragEnter(_e, targetId) {
this.dragEnterTargetIds.unshift(targetId);
}
handleDragOver(_e, targetId) {
if (this.dragOverTargetIds === null) {
this.dragOverTargetIds = [];
}
this.dragOverTargetIds.unshift(targetId);
}
handleDrop(_e, targetId) {
this.dropTargetIds.unshift(targetId);
}
}
let emptyImage;
function getEmptyImage() {
if (!emptyImage) {
emptyImage = new Image();
emptyImage.src =
'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
}
return emptyImage;
}
const HTML5Backend = function createBackend(manager, context, options) {
return new HTML5BackendImpl(manager, context, options);
};
//# sourceMappingURL=index.js.map
export { HTML5Backend, NativeTypes, getEmptyImage };
//# sourceMappingURL=index.js.map

8

package.json
{
"name": "@vizzly/dnd-backend",
"version": "0.0.2",
"description": "HTML5 backend for React DnD",
"type": "module",
"version": "0.0.1",
"description": "HTML5 backend for React DnD",
"main": "./dist/bundle.cjs.js",
"module": "./dist/bundle.esm.js",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",

@@ -9,0 +9,0 @@ "files": [

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc