UNPKG

fluid-dnd

Version:

An agnostic drag and drop library to sort all kind of lists. With current support for vue, react and svelte

108 lines (107 loc) 4.29 kB
import { VERTICAL } from '.'; import useDroppable from './useDroppable'; import ConfigHandler from './config/configHandler'; import { isTempElement, observeMutation } from './utils/observer'; import { addClass } from './utils/dom/classList'; import { DRAGGABLE_CLASS, DROPPABLE_CLASS } from './utils/classes'; const getConfig = (listCondig, config) => { const onRemoveAtEvent = (index, sync) => { return listCondig.removeAtEvent(index, sync); }; const onInsertEvent = (index, value, sync) => { return listCondig.insertEvent(index, value, sync); }; const onGetLegth = () => { return listCondig.getLength(); }; const onGetValue = (index) => { return listCondig.getValue(index); }; const defaultMapFrom = (object) => { return object; }; return { direction: config?.direction ?? VERTICAL, handlerSelector: config?.handlerSelector ?? DRAGGABLE_CLASS, draggingClass: config?.draggingClass ?? 'dragging', droppableClass: config?.droppableClass ?? 'droppable-hover', isDraggable: config?.isDraggable ?? (() => true), onDragStart: config?.onDragStart ?? (() => { }), onDragEnd: config?.onDragEnd ?? (() => { }), onDragOver: config?.onDragOver ?? (() => { }), droppableGroup: config?.droppableGroup, onRemoveAtEvent, onInsertEvent, onGetLegth, onGetValue, animationDuration: config?.animationDuration ?? 200, removingClass: config?.removingClass ?? 'removing', insertingFromClass: config?.insertingFromClass ?? 'from-inserting', delayBeforeRemove: config?.delayBeforeRemove ?? 200, delayBeforeInsert: config?.delayBeforeInsert ?? 200, mapFrom: config?.mapFrom ?? defaultMapFrom, delayBeforeTouchMoveEvent: config?.delayBeforeTouchMoveEvent ?? 150, coordinateTransform: config?.coordinateTransform ?? [(coordinate) => coordinate], }; }; export default function dragAndDrop(listCondig, handlerPublisher, config, indexAttr = 'index') { let removeAtFromElements = []; let insertAtFromElements = []; let currentObserver; const coreConfig = getConfig(listCondig, config); const removeAt = (index) => { for (const removeAtFromElement of removeAtFromElements) { removeAtFromElement(index); } }; const insertAt = (index, value) => { const listLegth = coreConfig.onGetLegth(); if (listLegth === 0) { listCondig.insertToListEmpty(coreConfig, index, value); } else { for (const insertAtFromElement of insertAtFromElements) { insertAtFromElement(index, value); } } }; const makeChildrensDraggable = (parent) => { const [removeAtFromElementList, insertAtFromElementList] = useDroppable(coreConfig, handlerPublisher, parent, indexAttr); removeAtFromElements = removeAtFromElementList; insertAtFromElements = insertAtFromElementList; }; const childrenMutationFilter = (mutation) => { const addedNodes = Array.from(mutation.addedNodes ?? []) .values() .filter((element) => !isTempElement(element)) .toArray(); const removedNodes = Array.from(mutation.removedNodes ?? []) .values() .filter((element) => !isTempElement(element)) .toArray(); return addedNodes.length > 0 || removedNodes.length > 0; }; const observeChildrens = (parent) => { currentObserver = observeMutation(() => { makeChildrensDraggable(parent); }, parent, { childList: true }, childrenMutationFilter); }; const makeDroppable = (parent) => { addClass(parent, DROPPABLE_CLASS); }; const addConfigHandler = (parent) => { ConfigHandler.addConfig(parent, coreConfig); }; const onChangeParent = (parent) => { if (!parent) { return; } makeDroppable(parent); addConfigHandler(parent); observeChildrens(parent); makeChildrensDraggable(parent); ConfigHandler.removeObsoleteConfigs(); return currentObserver; }; return [removeAt, insertAt, onChangeParent]; }