fluid-dnd 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -9
- package/dist/{HandlerPublisher-C-jTncuG.cjs → HandlerPublisher-CsD6p60X.cjs} +1 -1
- package/dist/{HandlerPublisher-BYI2bw4n.js → HandlerPublisher-LAmM6gCQ.js} +1 -1
- package/dist/core/HandlerPublisher.js +20 -0
- package/dist/core/configHandler.d.ts +2 -3
- package/dist/core/configHandler.js +33 -0
- package/dist/core/dragAndDrop.d.ts +3 -3
- package/dist/core/dragAndDrop.js +62 -0
- package/dist/core/index.d.ts +11 -0
- package/dist/core/index.js +2 -0
- package/dist/core/useDraggable.d.ts +2 -3
- package/dist/core/useDraggable.js +335 -0
- package/dist/core/useDroppable.d.ts +2 -3
- package/dist/core/useDroppable.js +55 -0
- package/dist/core/utils/GetStyles.d.ts +2 -3
- package/dist/core/utils/GetStyles.js +138 -0
- package/dist/core/utils/ParseStyles.d.ts +2 -3
- package/dist/core/utils/ParseStyles.js +40 -0
- package/dist/core/utils/SetStyles.d.ts +1 -2
- package/dist/core/utils/SetStyles.js +192 -0
- package/dist/core/utils/SetTransform.d.ts +2 -3
- package/dist/core/utils/SetTransform.js +148 -0
- package/dist/core/utils/classes.js +9 -0
- package/dist/core/utils/config.d.ts +3 -3
- package/dist/core/utils/config.js +56 -0
- package/dist/core/utils/dom/classList.js +35 -0
- package/dist/core/utils/droppableConfigurator.d.ts +3 -4
- package/dist/core/utils/droppableConfigurator.js +106 -0
- package/dist/core/utils/events/emitEvents.d.ts +5 -6
- package/dist/core/utils/events/emitEvents.js +333 -0
- package/dist/core/utils/index.js +9 -0
- package/dist/core/utils/observer.js +11 -0
- package/dist/core/utils/scroll.d.ts +2 -3
- package/dist/core/utils/scroll.js +17 -0
- package/dist/core/utils/tempChildren.d.ts +1 -2
- package/dist/core/utils/tempChildren.js +146 -0
- package/dist/core/utils/touchDevice.js +3 -0
- package/dist/core/utils/translate/GetTranslateBeforeDropping.d.ts +2 -3
- package/dist/core/utils/translate/GetTranslateBeforeDropping.js +129 -0
- package/dist/core/utils/translate/GetTranslationByDraggingAndEvent.d.ts +2 -3
- package/dist/core/utils/translate/GetTranslationByDraggingAndEvent.js +48 -0
- package/dist/index-DE3X7xW4.cjs +1 -0
- package/dist/index-D_kOy-fH.js +1306 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/index.mjs +1 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.d.ts +1 -2
- package/dist/react/index.js +2 -0
- package/dist/react/index.mjs +2 -2
- package/dist/react/useDragAndDrop.d.ts +2 -3
- package/dist/react/useDragAndDrop.js +28 -0
- package/dist/react/utils/ReactLilstConfig.d.ts +3 -4
- package/dist/react/utils/ReactLilstConfig.js +64 -0
- package/dist/svelte/index.cjs +1 -1
- package/dist/svelte/index.d.ts +1 -2
- package/dist/svelte/index.js +2 -0
- package/dist/svelte/index.mjs +2 -2
- package/dist/svelte/useDragAndDrop.d.ts +1 -2
- package/dist/svelte/useDragAndDrop.js +25 -0
- package/dist/svelte/utils/SvelteListCondig.d.ts +2 -2
- package/dist/svelte/utils/SvelteListCondig.js +36 -0
- package/dist/vue/index.cjs +1 -1
- package/dist/vue/index.d.ts +1 -2
- package/dist/vue/index.js +2 -0
- package/dist/vue/index.mjs +2 -2
- package/dist/vue/useDragAndDrop.d.ts +2 -3
- package/dist/vue/useDragAndDrop.js +23 -0
- package/dist/vue/utils/DropMethods.d.ts +1 -2
- package/dist/vue/utils/DropMethods.js +19 -0
- package/dist/vue/utils/VueListCondig.d.ts +3 -3
- package/dist/vue/utils/VueListCondig.js +28 -0
- package/package.json +2 -5
- package/dist/index-BQUYvZRn.js +0 -1301
- package/dist/index-DNmnvxhi.cjs +0 -1
package/README.md
CHANGED
@@ -11,23 +11,22 @@
|
|
11
11
|
[](https://www.npmjs.com/package/fluid-dnd)
|
12
12
|

|
13
13
|

|
14
|
-
[](https://twitter.com/carlosjorgerc)
|
15
14
|
[](https://codeclimate.com/github/carlosjorger/fluid-dnd/test_coverage)
|
16
15
|
|
17
16
|
</div>
|
18
17
|
|
19
|
-
Fluid DnD is a [**fluid**, **agnostic** and **
|
20
|
-
library for lists with support for Vue
|
18
|
+
Fluid DnD is a [**fluid**, **agnostic** and **versatile** drag and drop
|
19
|
+
library for lists; with support for **Vue**, **React** and **Svelte**](https://fluid-dnd.netlify.app/). It's a **lightweight** tool ~8 Kb (gzip) with no depenencies.
|
21
20
|
|
22
|
-
<img src="https://github.com/user-attachments/assets/
|
21
|
+
<img src="https://github.com/user-attachments/assets/1b7ac5e3-48e9-43f9-a577-e78c6b9eacae" width="100%"/>
|
23
22
|
|
24
23
|
## 🧰 Features
|
25
24
|
|
26
25
|
- ✅ **Fully customizable 🎨**.
|
27
26
|
- ✅ **Zero dependencies 🪶**.
|
28
|
-
- ✅ **
|
27
|
+
- ✅ **Works with horizontal➡️and vertical list⬇️**.
|
29
28
|
- ✅ **Mouse 🐭 and touch 👉📱 (mobile, tablet and so on) support**.
|
30
|
-
- ✅ **
|
29
|
+
- ✅ **Clear documentation 📑 and examples**.
|
31
30
|
- ✅ **Fully tested 🧪, typed and reliable**.
|
32
31
|
|
33
32
|
## ✨ Inspirations
|
@@ -54,8 +53,8 @@ library for lists with support for Vue, react and Svelte](https://fluid-dnd.netl
|
|
54
53
|
3. **Documentation**
|
55
54
|
|
56
55
|
- 📚 Check out all the [docs](https://fluid-dnd.netlify.app/).
|
57
|
-
- 🛠️ Edit
|
58
|
-
- 📘 See
|
56
|
+
- 🛠️ Edit this example [here](https://codesandbox.io/s/nifty-hooks-5plkpl).
|
57
|
+
- 📘 See other examples [here](https://fluid-dnd.netlify.app/vue/example/vertical-list/single-vertical-list/).
|
59
58
|
|
60
59
|
## 📚 Libraries Support
|
61
60
|
- **Vue** >=3.0.0
|
@@ -64,7 +63,7 @@ library for lists with support for Vue, react and Svelte](https://fluid-dnd.netl
|
|
64
63
|
|
65
64
|
## 🤝 Contributing
|
66
65
|
|
67
|
-
If you're interested in contributing to [fluid-dnd](https://github.com/carlosjorger/fluid-dnd), please read our
|
66
|
+
If you're interested in contributing to [fluid-dnd](https://github.com/carlosjorger/fluid-dnd), please read our [CONTRIBUTING GUIDELINES](./CONTRIBUTING.md) before submitting a pull request.
|
68
67
|
|
69
68
|
## 🔑 License
|
70
69
|
|
@@ -1 +1 @@
|
|
1
|
-
"use strict";var d=Object.defineProperty;var n=(e,s,l)=>s in e?d(e,s,{enumerable:!0,configurable:!0,writable:!0,value:l}):e[s]=l;var a=(e,s,l)=>n(e,typeof s!="symbol"?s+"":s,l);const r=require("./index-
|
1
|
+
"use strict";var d=Object.defineProperty;var n=(e,s,l)=>s in e?d(e,s,{enumerable:!0,configurable:!0,writable:!0,value:l}):e[s]=l;var a=(e,s,l)=>n(e,typeof s!="symbol"?s+"":s,l);const r=require("./index-DE3X7xW4.cjs");class h{constructor(){a(this,"handlers");this.handlers=[]}addSubscriber(s){this.handlers.includes(s)||(this.handlers.push(s),r.addClass(s,r.GRAB_CLASS))}toggleGrabClass(s){for(const l of this.handlers)r.toggleClass(l,r.GRAB_CLASS,s)}}exports.HandlerPublisher=h;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
var d = Object.defineProperty;
|
2
2
|
var e = (a, s, l) => s in a ? d(a, s, { enumerable: !0, configurable: !0, writable: !0, value: l }) : a[s] = l;
|
3
3
|
var r = (a, s, l) => e(a, typeof s != "symbol" ? s + "" : s, l);
|
4
|
-
import { a as h, t as n, G as t } from "./index-
|
4
|
+
import { a as h, t as n, G as t } from "./index-D_kOy-fH.js";
|
5
5
|
class c {
|
6
6
|
constructor() {
|
7
7
|
r(this, "handlers");
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { GRAB_CLASS } from "./utils/classes";
|
2
|
+
import { addClass, toggleClass } from "./utils/dom/classList";
|
3
|
+
export default class HandlerPublisher {
|
4
|
+
handlers;
|
5
|
+
constructor() {
|
6
|
+
this.handlers = [];
|
7
|
+
}
|
8
|
+
addSubscriber(subscriber) {
|
9
|
+
if (this.handlers.includes(subscriber)) {
|
10
|
+
return;
|
11
|
+
}
|
12
|
+
this.handlers.push(subscriber);
|
13
|
+
addClass(subscriber, GRAB_CLASS);
|
14
|
+
}
|
15
|
+
toggleGrabClass(force) {
|
16
|
+
for (const handler of this.handlers) {
|
17
|
+
toggleClass(handler, GRAB_CLASS, force);
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import { getScrollElement } from "./utils/GetStyles";
|
2
|
+
import { containstClasses } from "./utils/dom/classList";
|
3
|
+
export default class ConfigHandler {
|
4
|
+
static configs = [];
|
5
|
+
static addConfig(droppable, config) {
|
6
|
+
const configs = ConfigHandler.configs.filter((configHandler) => !configHandler.droppable.isSameNode(droppable));
|
7
|
+
const scroll = getScrollElement(droppable);
|
8
|
+
configs.push({
|
9
|
+
droppable,
|
10
|
+
config,
|
11
|
+
scroll,
|
12
|
+
});
|
13
|
+
ConfigHandler.configs = configs;
|
14
|
+
}
|
15
|
+
static removeObsoleteConfigs = () => {
|
16
|
+
const notObsoltete = ConfigHandler.configs.filter(({ droppable }) => document.contains(droppable));
|
17
|
+
ConfigHandler.configs = notObsoltete;
|
18
|
+
};
|
19
|
+
static updateScrolls(currentDroppable, droppableGroupClass) {
|
20
|
+
for (const configHandler of ConfigHandler.configs) {
|
21
|
+
const { droppable } = configHandler;
|
22
|
+
if ((droppableGroupClass &&
|
23
|
+
containstClasses(droppable, droppableGroupClass)) ||
|
24
|
+
droppable.isSameNode(currentDroppable)) {
|
25
|
+
configHandler.scroll = getScrollElement(droppable);
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
29
|
+
static getConfig(curerntDroppable) {
|
30
|
+
const config = ConfigHandler.configs.find(({ droppable }) => droppable.isSameNode(curerntDroppable));
|
31
|
+
return config;
|
32
|
+
}
|
33
|
+
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { ListCondig
|
2
|
-
import {
|
3
|
-
|
1
|
+
import { ListCondig } from ".";
|
2
|
+
import { Config } from ".";
|
3
|
+
import HandlerPublisher from "./HandlerPublisher";
|
4
4
|
export default function dragAndDrop<T>(listCondig: ListCondig<T>, handlerPublisher: HandlerPublisher, config?: Config<T>, indexAttr?: string): readonly [(index: number) => void, (index: number, value: T) => void, (parent: HTMLElement | null | undefined) => MutationObserver | undefined];
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import { getConfig } from "./utils/config";
|
2
|
+
import useDroppable from "./useDroppable";
|
3
|
+
import ConfigHandler from "./configHandler";
|
4
|
+
import { observeMutation } from "./utils/observer";
|
5
|
+
import { addClass } from "./utils/dom/classList";
|
6
|
+
import { DROPPABLE_CLASS } from "./utils/classes";
|
7
|
+
import { isTempElement } from "./utils/tempChildren";
|
8
|
+
export default function dragAndDrop(listCondig, handlerPublisher, config, indexAttr = 'index') {
|
9
|
+
let removeAtFromElements = [];
|
10
|
+
let insertAtFromElements = [];
|
11
|
+
let currentObserver;
|
12
|
+
const coreConfig = getConfig(listCondig, config);
|
13
|
+
const removeAt = (index) => {
|
14
|
+
for (const removeAtFromElement of removeAtFromElements) {
|
15
|
+
removeAtFromElement(index);
|
16
|
+
}
|
17
|
+
};
|
18
|
+
const insertAt = (index, value) => {
|
19
|
+
const listLegth = coreConfig.onGetLegth();
|
20
|
+
if (listLegth === 0) {
|
21
|
+
listCondig.insertToListEmpty(coreConfig, index, value);
|
22
|
+
}
|
23
|
+
else {
|
24
|
+
for (const insertAtFromElement of insertAtFromElements) {
|
25
|
+
insertAtFromElement(index, value);
|
26
|
+
}
|
27
|
+
}
|
28
|
+
};
|
29
|
+
const makeChildrensDraggable = (parent) => {
|
30
|
+
const [removeAtFromElementList, insertAtFromElementList] = useDroppable(coreConfig, handlerPublisher, parent, indexAttr);
|
31
|
+
removeAtFromElements = removeAtFromElementList;
|
32
|
+
insertAtFromElements = insertAtFromElementList;
|
33
|
+
};
|
34
|
+
const childrenMutationFilter = (mutation) => {
|
35
|
+
const addedNodes = mutation.addedNodes.values().filter((element) => !isTempElement(element)).toArray();
|
36
|
+
const removedNodes = mutation.removedNodes.values().filter((element) => !isTempElement(element)).toArray();
|
37
|
+
return addedNodes.length > 0 || removedNodes.length > 0;
|
38
|
+
};
|
39
|
+
const observeChildrens = (parent) => {
|
40
|
+
currentObserver = observeMutation(() => {
|
41
|
+
makeChildrensDraggable(parent);
|
42
|
+
}, parent, { childList: true }, childrenMutationFilter);
|
43
|
+
};
|
44
|
+
const makeDroppable = (parent) => {
|
45
|
+
addClass(parent, DROPPABLE_CLASS);
|
46
|
+
};
|
47
|
+
const addConfigHandler = (parent) => {
|
48
|
+
ConfigHandler.addConfig(parent, coreConfig);
|
49
|
+
};
|
50
|
+
const onChangeParent = (parent) => {
|
51
|
+
if (!parent) {
|
52
|
+
return;
|
53
|
+
}
|
54
|
+
makeDroppable(parent);
|
55
|
+
addConfigHandler(parent);
|
56
|
+
observeChildrens(parent);
|
57
|
+
makeChildrensDraggable(parent);
|
58
|
+
ConfigHandler.removeObsoleteConfigs();
|
59
|
+
return currentObserver;
|
60
|
+
};
|
61
|
+
return [removeAt, insertAt, onChangeParent];
|
62
|
+
}
|
package/dist/core/index.d.ts
CHANGED
@@ -89,6 +89,10 @@ export interface Config<T> {
|
|
89
89
|
* Map value when is passed from the current list to another.
|
90
90
|
*/
|
91
91
|
mapFrom?: MapFrom<T>;
|
92
|
+
/**
|
93
|
+
* The delay before the touchmove event is fired.
|
94
|
+
*/
|
95
|
+
delayBeforeTouchMoveEvent: number;
|
92
96
|
}
|
93
97
|
/**
|
94
98
|
* onDrop event function.
|
@@ -156,5 +160,12 @@ export type CoreConfig<T> = {
|
|
156
160
|
onInsertEvent: OnInsertEvent<T>;
|
157
161
|
onGetLegth: OnGetLength;
|
158
162
|
onGetValue: OnGetValue<T>;
|
163
|
+
/**
|
164
|
+
* Map value when is passed from the current list to another.
|
165
|
+
*/
|
159
166
|
mapFrom: MapFrom<T>;
|
167
|
+
/**
|
168
|
+
* The delay before the touchmove event is fired.
|
169
|
+
*/
|
170
|
+
delayBeforeTouchMoveEvent: number;
|
160
171
|
};
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import { CoreConfig } from
|
2
|
-
import
|
3
|
-
|
1
|
+
import { CoreConfig } from ".";
|
2
|
+
import HandlerPublisher from "./HandlerPublisher";
|
4
3
|
export default function useDraggable<T>(draggableElement: HTMLElement, index: number, config: CoreConfig<T>, parent: HTMLElement, handlerPublisher: HandlerPublisher): readonly [(targetIndex: number) => void, (targetIndex: number, value: T) => void];
|
@@ -0,0 +1,335 @@
|
|
1
|
+
import { assignDraggingEvent, convetEventToDragMouseTouchEvent, moveTranslate, setCustomFixedSize, setEventWithInterval, setTranistion, } from "./utils/SetStyles";
|
2
|
+
import { useTransform } from "./utils/SetTransform";
|
3
|
+
import useEmitEvents from "./utils/events/emitEvents";
|
4
|
+
import { DRAG_EVENT, draggableTargetTimingFunction, START_DRAG_EVENT, START_DROP_EVENT } from "./utils";
|
5
|
+
import ConfigHandler from "./configHandler";
|
6
|
+
import { IsHTMLElement, isTouchEvent } from "./utils/touchDevice";
|
7
|
+
import { addTempChild, addTempChildOnInsert, removeTempChildrens } from "./utils/tempChildren";
|
8
|
+
import { DroppableConfigurator } from "./utils/droppableConfigurator";
|
9
|
+
import { addClass, containClass, getClassesList, getClassesSelector, removeClass, toggleClass, } from "./utils/dom/classList";
|
10
|
+
import { DRAGGABLE_CLASS, DRAGGING_CLASS, DROPPABLE_CLASS, HANDLER_CLASS } from "./utils/classes";
|
11
|
+
var DraggingState;
|
12
|
+
(function (DraggingState) {
|
13
|
+
DraggingState[DraggingState["NOT_DRAGGING"] = 0] = "NOT_DRAGGING";
|
14
|
+
DraggingState[DraggingState["START_DRAGGING"] = 1] = "START_DRAGGING";
|
15
|
+
DraggingState[DraggingState["DRAGING"] = 2] = "DRAGING";
|
16
|
+
DraggingState[DraggingState["END_DRAGGING"] = 3] = "END_DRAGGING";
|
17
|
+
})(DraggingState || (DraggingState = {}));
|
18
|
+
export default function useDraggable(draggableElement, index, config, parent, handlerPublisher) {
|
19
|
+
const { handlerSelector, isDraggable, droppableGroup, animationDuration, delayBeforeRemove, draggingClass, removingClass, onRemoveAtEvent, droppableClass, onDragStart, delayBeforeTouchMoveEvent } = config;
|
20
|
+
const droppableGroupClass = getClassesList(droppableGroup)
|
21
|
+
.map((classGroup) => `droppable-group-${classGroup}`)
|
22
|
+
.join(" ");
|
23
|
+
let draggingState = DraggingState.NOT_DRAGGING;
|
24
|
+
let windowScroll = {
|
25
|
+
scrollX: 0,
|
26
|
+
scrollY: 0,
|
27
|
+
};
|
28
|
+
let pagePosition = { pageX: 0, pageY: 0 };
|
29
|
+
let delayTimeout;
|
30
|
+
let initialTouch;
|
31
|
+
const [setTransform, updateTransformState] = useTransform(draggableElement);
|
32
|
+
const endDraggingState = () => {
|
33
|
+
draggingState = DraggingState.NOT_DRAGGING;
|
34
|
+
};
|
35
|
+
const [emitEventToSiblings, emitRemoveEventToSiblings, emitInsertEventToSiblings, emitFinishRemoveEventToSiblings, toggleDraggingClass,] = useEmitEvents(config, index, parent, droppableGroupClass, handlerPublisher, endDraggingState);
|
36
|
+
const setDraggable = () => {
|
37
|
+
addClass(draggableElement, DRAGGABLE_CLASS);
|
38
|
+
};
|
39
|
+
const addHandlerClass = (handlerElement) => {
|
40
|
+
addClass(handlerElement, HANDLER_CLASS);
|
41
|
+
handlerPublisher.addSubscriber(handlerElement);
|
42
|
+
};
|
43
|
+
const setHandlerStyles = () => {
|
44
|
+
if (isDraggable(draggableElement)) {
|
45
|
+
const handlerElement = draggableElement.querySelector(handlerSelector);
|
46
|
+
if (handlerElement) {
|
47
|
+
addHandlerClass(handlerElement);
|
48
|
+
}
|
49
|
+
else {
|
50
|
+
addHandlerClass(draggableElement);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
};
|
54
|
+
const setCssStyles = () => {
|
55
|
+
setHandlerStyles();
|
56
|
+
setDraggable();
|
57
|
+
};
|
58
|
+
const getHandler = (element) => {
|
59
|
+
const handler = element?.querySelector(`.${HANDLER_CLASS}`);
|
60
|
+
const handlerParent = handler?.parentElement;
|
61
|
+
if (handler && handlerParent
|
62
|
+
&& containClass(handlerParent, DROPPABLE_CLASS)
|
63
|
+
&& !handlerParent.isSameNode(parent)) {
|
64
|
+
return null;
|
65
|
+
}
|
66
|
+
return handler;
|
67
|
+
};
|
68
|
+
const setSlotRefElementParams = (element) => {
|
69
|
+
const handlerElement = (getHandler(element) ?? element);
|
70
|
+
if (handlerElement && isDraggable(element)) {
|
71
|
+
assignDraggingEvent(handlerElement, "onmousedown", onmousedown("mousemove", "mouseup"));
|
72
|
+
assignDraggingEvent(handlerElement, "ontouchstart", onmousedown("touchmove", "touchend"), (event) => {
|
73
|
+
initialTouch = {
|
74
|
+
x: event.touches[0].clientX,
|
75
|
+
y: event.touches[0].clientY,
|
76
|
+
};
|
77
|
+
});
|
78
|
+
disableMousedownEventFromImages(handlerElement);
|
79
|
+
}
|
80
|
+
if (!element?.isSameNode(handlerElement)) {
|
81
|
+
assignDraggingEvent(element, "onmousedown", mousedownOnDraggablefunction);
|
82
|
+
}
|
83
|
+
addClass(parent, DROPPABLE_CLASS);
|
84
|
+
};
|
85
|
+
const disableMousedownEventFromImages = (handlerElement) => {
|
86
|
+
// Avoid dragging inner images
|
87
|
+
const images = handlerElement.querySelectorAll("img");
|
88
|
+
Array.from(images).forEach((image) => {
|
89
|
+
image.onmousedown = () => false;
|
90
|
+
});
|
91
|
+
};
|
92
|
+
const setTransformDragEvent = () => {
|
93
|
+
if (pagePosition.pageX == 0 && pagePosition.pageY == 0) {
|
94
|
+
return;
|
95
|
+
}
|
96
|
+
if (!droppableConfigurator.current) {
|
97
|
+
return;
|
98
|
+
}
|
99
|
+
const { droppable, config } = droppableConfigurator.current;
|
100
|
+
setTransform(draggableElement, droppable, pagePosition, config.direction);
|
101
|
+
emitEventToSiblings(draggableElement, DRAG_EVENT, windowScroll, droppableConfigurator.current);
|
102
|
+
};
|
103
|
+
const changeDroppable = (newdDroppableConfig, oldDroppableConfig) => {
|
104
|
+
if (oldDroppableConfig &&
|
105
|
+
draggingState == DraggingState.DRAGING &&
|
106
|
+
!newdDroppableConfig?.droppable.isSameNode(oldDroppableConfig.droppable)) {
|
107
|
+
emitEventToSiblings(draggableElement, DRAG_EVENT, windowScroll, oldDroppableConfig);
|
108
|
+
}
|
109
|
+
};
|
110
|
+
const droppableConfigurator = new DroppableConfigurator(draggableElement, droppableGroupClass, parent, setTransformDragEvent, changeDroppable, config.mapFrom);
|
111
|
+
const toggleDroppableClass = (isOutside) => {
|
112
|
+
if (!droppableConfigurator.current) {
|
113
|
+
return;
|
114
|
+
}
|
115
|
+
const droppables = droppableGroupClass ? Array.from(document.querySelectorAll(getClassesSelector(droppableGroupClass))) : [parent];
|
116
|
+
for (const droppable of droppables) {
|
117
|
+
droppable
|
118
|
+
.classList
|
119
|
+
.toggle(droppableClass, !isOutside && droppable.isSameNode(droppableConfigurator.current.droppable));
|
120
|
+
}
|
121
|
+
};
|
122
|
+
const onMove = (event, isTouchEvent = false) => {
|
123
|
+
droppableConfigurator.updateConfig(event);
|
124
|
+
const isOutside = droppableConfigurator.isOutside(event);
|
125
|
+
toggleDroppableClass(isOutside);
|
126
|
+
if (draggingState === DraggingState.START_DRAGGING && !isTouchEvent) {
|
127
|
+
startDragging(event);
|
128
|
+
}
|
129
|
+
else if (draggingState === DraggingState.DRAGING) {
|
130
|
+
updateTempChildren(isOutside);
|
131
|
+
setTransformEvent(event);
|
132
|
+
}
|
133
|
+
};
|
134
|
+
const updateTempChildren = (isOutside = true) => {
|
135
|
+
if (!droppableConfigurator.current) {
|
136
|
+
return;
|
137
|
+
}
|
138
|
+
const { droppable } = droppableConfigurator.current;
|
139
|
+
removeTempChildrens(droppable, parent, droppableGroupClass, animationDuration, isOutside);
|
140
|
+
if (isOutside) {
|
141
|
+
return;
|
142
|
+
}
|
143
|
+
addTempChild(draggableElement, parent, draggingState == DraggingState.START_DRAGGING, droppableConfigurator.current);
|
144
|
+
};
|
145
|
+
const cursorWasNotMoved = (event) => {
|
146
|
+
if (isTouchEvent(event) && initialTouch && draggingState == DraggingState.START_DRAGGING) {
|
147
|
+
const movedX = Math.abs(event.touches[0].clientX - initialTouch.x);
|
148
|
+
const movedY = Math.abs(event.touches[0].clientY - initialTouch.y);
|
149
|
+
if (Math.abs(movedX) > 5 && Math.abs(movedY) > 5) {
|
150
|
+
clearTimeout(delayTimeout);
|
151
|
+
return false;
|
152
|
+
}
|
153
|
+
}
|
154
|
+
return true;
|
155
|
+
};
|
156
|
+
const handleMove = (event) => {
|
157
|
+
clearTimeout(delayTimeout);
|
158
|
+
const eventToDragMouse = convetEventToDragMouseTouchEvent(event);
|
159
|
+
if (isTouchEvent(event) && event.cancelable && draggingState == DraggingState.DRAGING) {
|
160
|
+
event.preventDefault();
|
161
|
+
}
|
162
|
+
if ((isTouchEvent(event) && !event.cancelable)
|
163
|
+
|| !cursorWasNotMoved(event)) {
|
164
|
+
disableDragging("touchmove", event);
|
165
|
+
return;
|
166
|
+
}
|
167
|
+
onMove(eventToDragMouse, isTouchEvent(event));
|
168
|
+
};
|
169
|
+
const addTouchDeviceDelay = (event, callback) => {
|
170
|
+
if (event == "touchmove") {
|
171
|
+
delayTimeout = setTimeout(() => {
|
172
|
+
callback();
|
173
|
+
}, delayBeforeTouchMoveEvent);
|
174
|
+
}
|
175
|
+
else {
|
176
|
+
callback();
|
177
|
+
}
|
178
|
+
};
|
179
|
+
const cursorIsOnChildDraggable = (event, element) => {
|
180
|
+
const { clientX, clientY } = event;
|
181
|
+
const elementBelow = document.elementFromPoint(clientX, clientY);
|
182
|
+
const draggableAncestor = elementBelow?.closest(`.${DRAGGABLE_CLASS}`);
|
183
|
+
return draggableAncestor && element.isSameNode(draggableAncestor);
|
184
|
+
};
|
185
|
+
const getDragStartEventData = (element) => {
|
186
|
+
const value = config.onGetValue(index);
|
187
|
+
return ({ index, element, value });
|
188
|
+
};
|
189
|
+
const startTouchMoveEvent = (event) => {
|
190
|
+
droppableConfigurator.updateConfig(event);
|
191
|
+
toggleDroppableClass(droppableConfigurator.isOutside(event));
|
192
|
+
startDragging(event);
|
193
|
+
};
|
194
|
+
const onmousedown = (moveEvent, onLeaveEvent) => {
|
195
|
+
return (event) => {
|
196
|
+
if (!cursorIsOnChildDraggable(event, draggableElement)) {
|
197
|
+
return;
|
198
|
+
}
|
199
|
+
ConfigHandler.updateScrolls(parent, droppableGroupClass);
|
200
|
+
const { scrollX, scrollY } = window;
|
201
|
+
windowScroll = { scrollX, scrollY };
|
202
|
+
if (draggingState === DraggingState.NOT_DRAGGING) {
|
203
|
+
draggingState = DraggingState.START_DRAGGING;
|
204
|
+
const data = getDragStartEventData(draggableElement);
|
205
|
+
data && onDragStart(data);
|
206
|
+
addTouchDeviceDelay(moveEvent, () => {
|
207
|
+
if (moveEvent == 'touchmove') {
|
208
|
+
startTouchMoveEvent(event);
|
209
|
+
}
|
210
|
+
});
|
211
|
+
document.addEventListener(moveEvent, handleMove, {
|
212
|
+
passive: false,
|
213
|
+
});
|
214
|
+
makeScrollEventOnDroppable(parent);
|
215
|
+
document.addEventListener(onLeaveEvent, onLeave(moveEvent), {
|
216
|
+
once: true,
|
217
|
+
});
|
218
|
+
}
|
219
|
+
};
|
220
|
+
};
|
221
|
+
const mousedownOnDraggablefunction = (event) => {
|
222
|
+
return droppableConfigurator.updateConfig(event);
|
223
|
+
};
|
224
|
+
const onLeave = (moveEvent) => {
|
225
|
+
return (event) => {
|
226
|
+
disableDragging(moveEvent, event);
|
227
|
+
};
|
228
|
+
};
|
229
|
+
const disableDragging = (moveEvent, event) => {
|
230
|
+
toggleDroppableClass(true);
|
231
|
+
const convertedEvent = convetEventToDragMouseTouchEvent(event);
|
232
|
+
onDropDraggingEvent(droppableConfigurator.isOutside(convertedEvent, false));
|
233
|
+
clearTimeout(delayTimeout);
|
234
|
+
document.removeEventListener(moveEvent, handleMove);
|
235
|
+
droppableConfigurator.updateConfig(convertedEvent);
|
236
|
+
const currentConfig = droppableConfigurator.getCurrentConfig(convertedEvent);
|
237
|
+
if (currentConfig) {
|
238
|
+
const { droppable } = currentConfig;
|
239
|
+
removeOnScrollEvents(droppable);
|
240
|
+
}
|
241
|
+
parent.onscroll = null;
|
242
|
+
endDraggingState();
|
243
|
+
};
|
244
|
+
const removeOnScrollEvents = (droppable) => {
|
245
|
+
droppable.onscroll = null;
|
246
|
+
if (!droppableGroupClass) {
|
247
|
+
return;
|
248
|
+
}
|
249
|
+
const droppables = Array.from(document.querySelectorAll(getClassesSelector(droppableGroupClass)));
|
250
|
+
for (const droppable of droppables) {
|
251
|
+
if (IsHTMLElement(droppable)) {
|
252
|
+
droppable.onscroll = null;
|
253
|
+
}
|
254
|
+
}
|
255
|
+
};
|
256
|
+
const startDragging = (event) => {
|
257
|
+
addTempChild(draggableElement, parent, draggingState == DraggingState.START_DRAGGING, droppableConfigurator.current);
|
258
|
+
updateDraggingStateBeforeDragging();
|
259
|
+
emitEventToSiblings(draggableElement, START_DRAG_EVENT, windowScroll, droppableConfigurator.current);
|
260
|
+
setDraggingStyles(draggableElement);
|
261
|
+
updateTransformState(event, draggableElement);
|
262
|
+
};
|
263
|
+
const updateDraggingStateBeforeDragging = () => {
|
264
|
+
draggingState = DraggingState.DRAGING;
|
265
|
+
};
|
266
|
+
const setTransformEvent = (event) => {
|
267
|
+
const { pageX, pageY } = event;
|
268
|
+
pagePosition = { pageX, pageY };
|
269
|
+
setTransformDragEvent();
|
270
|
+
};
|
271
|
+
const makeScrollEventOnDroppable = (droppable) => {
|
272
|
+
return setEventWithInterval(droppable, "onscroll", onScrollEvent);
|
273
|
+
};
|
274
|
+
const onScrollEvent = () => {
|
275
|
+
return setTransformDragEvent();
|
276
|
+
};
|
277
|
+
const onDropDraggingEvent = (isOutsideAllDroppables) => {
|
278
|
+
if (draggingState !== DraggingState.DRAGING && draggingState !== DraggingState.START_DRAGGING) {
|
279
|
+
endDraggingState();
|
280
|
+
return;
|
281
|
+
}
|
282
|
+
draggingState = DraggingState.END_DRAGGING;
|
283
|
+
removeDraggingStyles(draggableElement);
|
284
|
+
if (draggableElement.classList.contains(DRAGGING_CLASS)) {
|
285
|
+
emitEventToSiblings(draggableElement, START_DROP_EVENT, windowScroll, isOutsideAllDroppables ?
|
286
|
+
droppableConfigurator.initial :
|
287
|
+
droppableConfigurator.current, index);
|
288
|
+
}
|
289
|
+
};
|
290
|
+
const removeDraggingStyles = (element) => {
|
291
|
+
setTranistion(element, animationDuration, draggableTargetTimingFunction);
|
292
|
+
moveTranslate(element, 0, 0);
|
293
|
+
};
|
294
|
+
const setDraggingStyles = (element) => {
|
295
|
+
const { height, width } = element.getBoundingClientRect();
|
296
|
+
setCustomFixedSize(element, {
|
297
|
+
fixedHeight: `${height}px`,
|
298
|
+
fixedWidth: `${width}px`
|
299
|
+
});
|
300
|
+
toggleDraggingClass(element, true);
|
301
|
+
toggleClass(element, draggingClass, true);
|
302
|
+
element.style.transition = "";
|
303
|
+
};
|
304
|
+
const removeAfterRemovingClass = (targetIndex, config) => {
|
305
|
+
removeClass(draggableElement, removingClass);
|
306
|
+
addTempChild(draggableElement, parent, draggingState == DraggingState.START_DRAGGING, droppableConfigurator.initial);
|
307
|
+
emitRemoveEventToSiblings(targetIndex, draggableElement, config, (sibling) => {
|
308
|
+
removeDraggingStyles(sibling);
|
309
|
+
emitFinishRemoveEventToSiblings(draggableElement);
|
310
|
+
});
|
311
|
+
onRemoveAtEvent(index, true);
|
312
|
+
};
|
313
|
+
const removeAtFromElement = (targetIndex) => {
|
314
|
+
if (!droppableConfigurator.initial) {
|
315
|
+
return;
|
316
|
+
}
|
317
|
+
const config = droppableConfigurator.initial;
|
318
|
+
if (targetIndex == index) {
|
319
|
+
addClass(draggableElement, removingClass);
|
320
|
+
setTimeout(() => {
|
321
|
+
removeAfterRemovingClass(targetIndex, config);
|
322
|
+
}, delayBeforeRemove);
|
323
|
+
}
|
324
|
+
};
|
325
|
+
const insertAtFromElement = (targetIndex, value) => {
|
326
|
+
if (targetIndex === index || targetIndex === config.onGetLegth() && index === targetIndex - 1) {
|
327
|
+
emitInsertEventToSiblings(targetIndex, draggableElement, parent, value, () => {
|
328
|
+
addTempChildOnInsert(draggableElement, draggingState == DraggingState.START_DRAGGING, droppableConfigurator.initial);
|
329
|
+
});
|
330
|
+
}
|
331
|
+
};
|
332
|
+
setCssStyles();
|
333
|
+
setSlotRefElementParams(draggableElement);
|
334
|
+
return [removeAtFromElement, insertAtFromElement];
|
335
|
+
}
|
@@ -1,4 +1,3 @@
|
|
1
|
-
import { CoreConfig } from
|
2
|
-
import
|
3
|
-
|
1
|
+
import { CoreConfig } from ".";
|
2
|
+
import HandlerPublisher from "./HandlerPublisher";
|
4
3
|
export default function useDroppable<T>(coreConfig: CoreConfig<T>, handlerPublisher: HandlerPublisher, droppable?: HTMLElement, indexAttr?: string): readonly [((targetIndex: number) => void)[], ((targetIndex: number, value: T) => void)[]];
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import { parseIntEmpty } from "./utils/GetStyles";
|
2
|
+
import { addMultipleClasses, getClassesList } from "./utils/dom/classList";
|
3
|
+
import useDraggable from "./useDraggable";
|
4
|
+
import { AddCssStylesToElement } from "./utils/SetStyles";
|
5
|
+
import { DRAGGABLE_CLASS, DRAGGING_CLASS, DRAGGING_HANDLER_CLASS, DROPPING_CLASS, GRAB_CLASS, GRABBING_CLASS, HANDLER_CLASS } from "./utils/classes";
|
6
|
+
const setDroppableGroupClass = (droppableGroupClass, droppable) => {
|
7
|
+
if (droppableGroupClass) {
|
8
|
+
addMultipleClasses(droppable, droppableGroupClass);
|
9
|
+
}
|
10
|
+
};
|
11
|
+
const createDraggableCssStyles = () => {
|
12
|
+
AddCssStylesToElement(document.body, [
|
13
|
+
`.${DRAGGABLE_CLASS}{touch-action:manipulation;user-select:none;box-sizing:border-box!important;-webkit-user-select:none;}`,
|
14
|
+
`.${HANDLER_CLASS}{pointer-events:auto!important;}`,
|
15
|
+
`.${GRAB_CLASS}{cursor:grab;}`,
|
16
|
+
".temp-child{touch-action:none;pointer-events:none;box-sizing:border-box!important;}",
|
17
|
+
`.droppable{box-sizing:border-box!important;}`,
|
18
|
+
`.${DRAGGING_CLASS}{position:fixed;z-index:5000;width:var(--fixedWidth)!important;height:var(--fixedHeight)!important;}`,
|
19
|
+
`.${DRAGGING_HANDLER_CLASS}{pointer-events:none!important;}`,
|
20
|
+
`.${DROPPING_CLASS}{pointer-events:none!important;}`,
|
21
|
+
`.${GRABBING_CLASS}{cursor:grabbing;}`,
|
22
|
+
`.disable-transition{transition:none!important;}`,
|
23
|
+
]);
|
24
|
+
};
|
25
|
+
export default function useDroppable(coreConfig, handlerPublisher, droppable, indexAttr = 'index') {
|
26
|
+
const INDEX_ATTR = indexAttr;
|
27
|
+
let removeAtFromElementList = [];
|
28
|
+
let insertAtFromElementList = [];
|
29
|
+
const { droppableGroup } = coreConfig;
|
30
|
+
if (!droppable) {
|
31
|
+
return [
|
32
|
+
removeAtFromElementList,
|
33
|
+
insertAtFromElementList
|
34
|
+
];
|
35
|
+
}
|
36
|
+
const droppableGroupClass = getClassesList(droppableGroup)
|
37
|
+
.map((classGroup) => `droppable-group-${classGroup}`)
|
38
|
+
.join(" ");
|
39
|
+
createDraggableCssStyles();
|
40
|
+
setDroppableGroupClass(droppableGroupClass, droppable);
|
41
|
+
for (const child of droppable.children) {
|
42
|
+
const index = child.getAttribute(INDEX_ATTR);
|
43
|
+
const numberIndex = parseIntEmpty(index);
|
44
|
+
const childHTMLElement = child;
|
45
|
+
if (childHTMLElement && numberIndex >= 0) {
|
46
|
+
const [removeAtFromElement, insertAtFromElement] = useDraggable(childHTMLElement, numberIndex, coreConfig, droppable, handlerPublisher);
|
47
|
+
removeAtFromElementList.push(removeAtFromElement);
|
48
|
+
insertAtFromElementList.push(insertAtFromElement);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
return [
|
52
|
+
removeAtFromElementList,
|
53
|
+
insertAtFromElementList
|
54
|
+
];
|
55
|
+
}
|
@@ -1,6 +1,5 @@
|
|
1
|
-
import { Direction } from
|
2
|
-
import { BeforeMargin, AfterMargin, BorderWidth, PaddingBefore, Before } from
|
3
|
-
|
1
|
+
import { Direction } from "..";
|
2
|
+
import { BeforeMargin, AfterMargin, BorderWidth, PaddingBefore, Before } from "../../../index";
|
4
3
|
export declare const getWindowScroll: () => {
|
5
4
|
scrollX: number;
|
6
5
|
scrollY: number;
|