@get-set/gs-sortable 0.0.36 → 0.0.37
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 +99 -1
- package/actions/afterAllImagesLoad.ts +36 -0
- package/actions/calculate.ts +155 -0
- package/actions/calculateOnSort.ts +270 -0
- package/actions/checkItemInContainer.ts +22 -0
- package/actions/destroy.ts +30 -0
- package/actions/general.ts +72 -0
- package/actions/getCurrentParams.ts +32 -0
- package/actions/init.ts +31 -0
- package/actions/initDraggable.ts +85 -0
- package/actions/initMouseMove.ts +120 -0
- package/actions/initScroll.ts +21 -0
- package/actions/initSortEnd.ts +87 -0
- package/components/GSSortable.tsx +160 -0
- package/components/styles/GSSortable.css +39 -0
- package/components/styles/GSSortable.scss +38 -0
- package/components/styles/GSSortableCSS.ts +41 -0
- package/constants/constParams.ts +5 -0
- package/constants/defaultParams.ts +20 -0
- package/constants/types.ts +7 -0
- package/dist/GSSortable.d.ts +2 -0
- package/dist/actions/afterAllImagesLoad.d.ts +4 -0
- package/dist/actions/afterAllImagesLoad.d.ts.map +1 -0
- package/dist/actions/afterAllImagesLoad.js +35 -0
- package/dist/actions/afterAllImagesLoad.js.map +1 -0
- package/dist/actions/calculate.d.ts +3 -2
- package/dist/actions/calculate.d.ts.map +1 -0
- package/dist/actions/calculate.js +13 -18
- package/dist/actions/calculate.js.map +1 -1
- package/dist/actions/calculateOnSort.d.ts +3 -2
- package/dist/actions/calculateOnSort.d.ts.map +1 -0
- package/dist/actions/calculateOnSort.js +51 -70
- package/dist/actions/calculateOnSort.js.map +1 -1
- package/dist/actions/checkItemInContainer.d.ts +1 -0
- package/dist/actions/checkItemInContainer.d.ts.map +1 -0
- package/dist/actions/checkItemInContainer.js +8 -17
- package/dist/actions/checkItemInContainer.js.map +1 -1
- package/dist/actions/destroy.d.ts +3 -8
- package/dist/actions/destroy.d.ts.map +1 -0
- package/dist/actions/destroy.js +7 -9
- package/dist/actions/destroy.js.map +1 -1
- package/dist/actions/general.d.ts +1 -0
- package/dist/actions/general.d.ts.map +1 -0
- package/dist/actions/general.js +5 -12
- package/dist/actions/general.js.map +1 -1
- package/dist/actions/getCurrentParams.d.ts +4 -9
- package/dist/actions/getCurrentParams.d.ts.map +1 -0
- package/dist/actions/getCurrentParams.js +15 -18
- package/dist/actions/getCurrentParams.js.map +1 -1
- package/dist/actions/init.d.ts +3 -2
- package/dist/actions/init.d.ts.map +1 -0
- package/dist/actions/init.js +13 -16
- package/dist/actions/init.js.map +1 -1
- package/dist/actions/initDraggable.d.ts +3 -2
- package/dist/actions/initDraggable.d.ts.map +1 -0
- package/dist/actions/initDraggable.js +14 -22
- package/dist/actions/initDraggable.js.map +1 -1
- package/dist/actions/initMouseMove.d.ts +1 -0
- package/dist/actions/initMouseMove.d.ts.map +1 -0
- package/dist/actions/initMouseMove.js +40 -53
- package/dist/actions/initMouseMove.js.map +1 -1
- package/dist/actions/initScroll.d.ts +1 -0
- package/dist/actions/initScroll.d.ts.map +1 -0
- package/dist/actions/initScroll.js +7 -15
- package/dist/actions/initScroll.js.map +1 -1
- package/dist/actions/initSortEnd.d.ts +2 -1
- package/dist/actions/initSortEnd.d.ts.map +1 -0
- package/dist/actions/initSortEnd.js +62 -71
- package/dist/actions/initSortEnd.js.map +1 -1
- package/dist/components/GSSortable.d.ts +4 -19
- package/dist/components/GSSortable.d.ts.map +1 -0
- package/dist/components/GSSortable.js +72 -105
- package/dist/components/GSSortable.js.map +1 -1
- package/dist/components/styles/GSSortableCSS.d.ts +2 -1
- package/dist/components/styles/GSSortableCSS.d.ts.map +1 -0
- package/dist/components/styles/GSSortableCSS.js +3 -4
- package/dist/components/styles/GSSortableCSS.js.map +1 -1
- package/dist/constants/constParams.d.ts +4 -3
- package/dist/constants/constParams.d.ts.map +1 -0
- package/dist/constants/constParams.js +2 -4
- package/dist/constants/constParams.js.map +1 -1
- package/dist/constants/defaultParams.d.ts +3 -2
- package/dist/constants/defaultParams.d.ts.map +1 -0
- package/dist/constants/defaultParams.js +3 -8
- package/dist/constants/defaultParams.js.map +1 -1
- package/dist/constants/types.d.ts +1 -0
- package/dist/constants/types.d.ts.map +1 -0
- package/dist/constants/types.js +1 -3
- package/dist/constants/types.js.map +1 -1
- package/dist/helpers/uihelpers.d.ts +2 -1
- package/dist/helpers/uihelpers.d.ts.map +1 -0
- package/dist/helpers/uihelpers.js +9 -23
- package/dist/helpers/uihelpers.js.map +1 -1
- package/dist/types/params.d.ts +23 -0
- package/dist/types/params.d.ts.map +1 -0
- package/dist/types/params.js +2 -0
- package/dist/types/params.js.map +1 -0
- package/dist/types/ref.d.ts +41 -0
- package/dist/types/ref.d.ts.map +1 -0
- package/dist/types/ref.js +2 -0
- package/dist/types/ref.js.map +1 -0
- package/dist-js/bundle.js +1181 -0
- package/helpers/uihelpers.ts +44 -0
- package/package.json +71 -43
- package/styles/GSSortable.css +39 -0
- package/styles/GSSortable.scss +38 -0
- package/types/global.d.ts +19 -0
- package/types/params.ts +24 -0
- package/types/ref.ts +41 -0
- package/index.js +0 -3
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import _defaultParams from '../constants/defaultParams';
|
|
2
|
+
import { Params } from '../types/params';
|
|
3
|
+
|
|
4
|
+
const getCurrentParams = (params: Params): Params => {
|
|
5
|
+
const defaultParams: Params = { ..._defaultParams };
|
|
6
|
+
let finalParams: Params = {
|
|
7
|
+
...defaultParams,
|
|
8
|
+
...params,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
if (finalParams.responsive && finalParams.responsive.length > 0) {
|
|
12
|
+
finalParams.responsive.sort((a, b) => b.windowSize - a.windowSize);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (finalParams.responsive && finalParams.responsive.length > 0) {
|
|
16
|
+
const windowSize = window.innerWidth;
|
|
17
|
+
const availableResponsives = finalParams.responsive.filter(
|
|
18
|
+
(resp) => resp.windowSize >= windowSize,
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
availableResponsives.forEach((resp) => {
|
|
22
|
+
finalParams = {
|
|
23
|
+
...finalParams,
|
|
24
|
+
...resp.params,
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return finalParams;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default getCurrentParams;
|
package/actions/init.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import constParams from '../constants/constParams';
|
|
2
|
+
import calculate from './calculate';
|
|
3
|
+
import initDraggable from './initDraggable';
|
|
4
|
+
import { Ref } from '../types/ref';
|
|
5
|
+
|
|
6
|
+
const init = (ref: Ref): void => {
|
|
7
|
+
const transition = `left ${constParams.animationSpeed}ms, top ${constParams.animationSpeed}ms, transform ${constParams.animationSpeed}ms`;
|
|
8
|
+
|
|
9
|
+
ref.grid.classList.add('gs-sortable-instance');
|
|
10
|
+
ref.grid.classList.add(`gs-sortable-${ref.currentParams.type}`);
|
|
11
|
+
|
|
12
|
+
// Disconnect any observers from a previous init/refresh cycle
|
|
13
|
+
ref.itemResizeObservers?.forEach((obs) => obs.disconnect());
|
|
14
|
+
ref.itemResizeObservers = [];
|
|
15
|
+
|
|
16
|
+
Array.from(ref.grid.children).forEach((el) => {
|
|
17
|
+
const element = el as HTMLElement;
|
|
18
|
+
element.classList.add('gs-sortable-item');
|
|
19
|
+
element.style.transition = transition;
|
|
20
|
+
element.style.position = 'absolute';
|
|
21
|
+
|
|
22
|
+
const obs = new ResizeObserver(() => calculate(ref));
|
|
23
|
+
obs.observe(element);
|
|
24
|
+
ref.itemResizeObservers!.push(obs);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
ref.count = ref.grid.children.length;
|
|
28
|
+
initDraggable(ref);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default init;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import constParams from '../constants/constParams';
|
|
2
|
+
import { getOffsetFromWindow } from './general';
|
|
3
|
+
import { Ref } from '../types/ref';
|
|
4
|
+
|
|
5
|
+
const initDraggable = (ref: Ref): void => {
|
|
6
|
+
const params = ref.currentParams;
|
|
7
|
+
const $items = Array.from(ref.grid.children) as HTMLElement[];
|
|
8
|
+
|
|
9
|
+
$items.forEach(($el, index) => {
|
|
10
|
+
$el.onmousedown = null;
|
|
11
|
+
const handler = params.handler
|
|
12
|
+
? $el.querySelector<HTMLElement>(params.handler)
|
|
13
|
+
: $el;
|
|
14
|
+
|
|
15
|
+
if (handler instanceof HTMLElement) {
|
|
16
|
+
handler.style.cursor = 'move';
|
|
17
|
+
handler.onmousedown = (e: MouseEvent) => {
|
|
18
|
+
if (!ref.isAdjusting) {
|
|
19
|
+
window.GSSortableConfigue!.overInItemRef = ref;
|
|
20
|
+
window.GSSortableConfigue!.takeFrom = ref;
|
|
21
|
+
|
|
22
|
+
const container = ref.grid;
|
|
23
|
+
const elStyles = getComputedStyle($el);
|
|
24
|
+
const containerStyles = getComputedStyle(container);
|
|
25
|
+
const paddingTop = parseFloat(containerStyles.paddingTop);
|
|
26
|
+
const paddingLeft = parseFloat(containerStyles.paddingLeft);
|
|
27
|
+
const top = parseFloat(elStyles.top);
|
|
28
|
+
const left = parseFloat(elStyles.left);
|
|
29
|
+
let $draggableEl = $el;
|
|
30
|
+
let placeholder: HTMLElement | undefined;
|
|
31
|
+
|
|
32
|
+
if (!params.takeClone) {
|
|
33
|
+
placeholder = document.createElement('div');
|
|
34
|
+
placeholder.classList.add('gs-sortable-placeholder');
|
|
35
|
+
placeholder.style.position = elStyles.position;
|
|
36
|
+
placeholder.style.transition = `left ${constParams.animationSpeed}ms, top ${constParams.animationSpeed}ms, transform ${constParams.animationSpeed}ms, opacity ${constParams.animationSpeed}ms`;
|
|
37
|
+
placeholder.style.width = `${$el.offsetWidth}px`;
|
|
38
|
+
placeholder.style.height = `${$el.offsetHeight}px`;
|
|
39
|
+
placeholder.style.top = `${top}px`;
|
|
40
|
+
placeholder.style.left = `${left}px`;
|
|
41
|
+
placeholder.style.border = elStyles.border;
|
|
42
|
+
placeholder.style.borderRadius = elStyles.borderRadius;
|
|
43
|
+
ref.grid.append(placeholder);
|
|
44
|
+
} else {
|
|
45
|
+
const $cloneEl = $el.cloneNode(true) as HTMLElement;
|
|
46
|
+
ref.grid.append($cloneEl);
|
|
47
|
+
$draggableEl = $cloneEl;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const elOffsetWindow = getOffsetFromWindow($el);
|
|
51
|
+
let translateX = !isNaN(left) ? left : 0;
|
|
52
|
+
let translateY = !isNaN(top) ? top : 0;
|
|
53
|
+
|
|
54
|
+
$draggableEl.style.transform = `translate(${translateX - paddingLeft}px, ${translateY - paddingTop}px)`;
|
|
55
|
+
$draggableEl.style.top = `${paddingTop}px`;
|
|
56
|
+
$draggableEl.style.left = `${paddingLeft}px`;
|
|
57
|
+
|
|
58
|
+
window.GSSortableConfigue!.draggableInfo = {
|
|
59
|
+
moved: false,
|
|
60
|
+
ref,
|
|
61
|
+
index,
|
|
62
|
+
$el: $draggableEl,
|
|
63
|
+
clientX: e.clientX,
|
|
64
|
+
clientY: e.clientY,
|
|
65
|
+
placeholder,
|
|
66
|
+
newLeft: left,
|
|
67
|
+
newTop: top,
|
|
68
|
+
fromLeft: (e.clientX - elOffsetWindow.left) / $el.offsetWidth,
|
|
69
|
+
fromTop: (e.clientY - elOffsetWindow.top) / $el.offsetHeight,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
$draggableEl.classList.add('gs-sortable-item-inmove');
|
|
73
|
+
ref.grid.classList.add('gs-sortable-active');
|
|
74
|
+
|
|
75
|
+
const closestItem = ref.grid.closest('.gs-sortable-item');
|
|
76
|
+
if (closestItem) {
|
|
77
|
+
closestItem.classList.add('gs-sortable-item-active-parent');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export default initDraggable;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { getOffsetFromWindow, getTranslateCoord } from './general';
|
|
2
|
+
import checkItemInContainer from './checkItemInContainer';
|
|
3
|
+
import calculate from './calculate';
|
|
4
|
+
import constParams from '../constants/constParams';
|
|
5
|
+
import calculateOnSort from './calculateOnSort';
|
|
6
|
+
import { Ref, DraggableInfo } from '../types/ref';
|
|
7
|
+
|
|
8
|
+
const initMouseMove = (event: MouseEvent): void => {
|
|
9
|
+
const info = window.GSSortableConfigue?.draggableInfo as DraggableInfo | undefined;
|
|
10
|
+
|
|
11
|
+
if (info !== undefined) {
|
|
12
|
+
info.moved = true;
|
|
13
|
+
|
|
14
|
+
const allRefs: Ref[] = [];
|
|
15
|
+
if (window.GSSortableConfigue!.takeFrom !== undefined) {
|
|
16
|
+
allRefs.push(window.GSSortableConfigue!.takeFrom);
|
|
17
|
+
}
|
|
18
|
+
window.GSSortableConfigue!.references.forEach((item) => {
|
|
19
|
+
if (
|
|
20
|
+
item.ref.currentParams.acceptFrom!.includes(
|
|
21
|
+
window.GSSortableConfigue!.takeFrom!.currentParams.reference,
|
|
22
|
+
)
|
|
23
|
+
) {
|
|
24
|
+
allRefs.push(item.ref);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
let findedRef = '';
|
|
29
|
+
allRefs.forEach((item) => {
|
|
30
|
+
if (checkItemInContainer(item.grid as HTMLElement, info.$el)) {
|
|
31
|
+
findedRef = item.currentParams.reference;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
if (findedRef !== '') {
|
|
36
|
+
const newRef = window.GSSortableConfigue!.instance(findedRef);
|
|
37
|
+
if (
|
|
38
|
+
newRef !== undefined &&
|
|
39
|
+
info.ref.currentParams.reference !== newRef.currentParams.reference
|
|
40
|
+
) {
|
|
41
|
+
const placeholder = document.querySelector('.gs-sortable-placeholder');
|
|
42
|
+
if (placeholder != null) {
|
|
43
|
+
placeholder.remove();
|
|
44
|
+
calculate(window.GSSortableConfigue!.overInItemRef as Ref);
|
|
45
|
+
}
|
|
46
|
+
window.GSSortableConfigue!.overInItemRef = newRef;
|
|
47
|
+
info.$el.style.width = window.GSSortableConfigue!.overInItemRef.itemWidth!;
|
|
48
|
+
|
|
49
|
+
const newWidth = info.$el.clientWidth;
|
|
50
|
+
const newHeight = info.$el.clientHeight;
|
|
51
|
+
const newContainerOffset = getOffsetFromWindow(
|
|
52
|
+
window.GSSortableConfigue!.takeFrom!.grid as HTMLElement,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const translateY = event.clientY - newContainerOffset.top - newHeight * info.fromTop;
|
|
56
|
+
const translateX = event.clientX - newContainerOffset.left - newWidth * info.fromLeft;
|
|
57
|
+
|
|
58
|
+
const elStyles = getComputedStyle(info.$el);
|
|
59
|
+
const top = parseFloat(elStyles.top);
|
|
60
|
+
const left = parseFloat(elStyles.left);
|
|
61
|
+
|
|
62
|
+
if (!window.GSSortableConfigue!.overInItemRef.currentParams.takeClone) {
|
|
63
|
+
const newPlaceholder = document.createElement('div');
|
|
64
|
+
newPlaceholder.classList.add('gs-sortable-placeholder');
|
|
65
|
+
newPlaceholder.style.position = elStyles.position;
|
|
66
|
+
info.$el.style.transform = `translate(${translateX}px, ${translateY}px)`;
|
|
67
|
+
newPlaceholder.style.transition = `left ${constParams.animationSpeed}ms, top ${constParams.animationSpeed}ms, transform ${constParams.animationSpeed}ms, opacity ${constParams.animationSpeed}ms`;
|
|
68
|
+
newPlaceholder.style.top = `${top}px`;
|
|
69
|
+
newPlaceholder.style.left = `${left}px`;
|
|
70
|
+
newPlaceholder.style.border = elStyles.border;
|
|
71
|
+
newPlaceholder.style.borderRadius = elStyles.borderRadius;
|
|
72
|
+
info.placeholder = newPlaceholder;
|
|
73
|
+
info.ref = newRef;
|
|
74
|
+
newPlaceholder.style.width = `${info.$el.offsetWidth}px`;
|
|
75
|
+
newPlaceholder.style.height = `${info.$el.offsetHeight}px`;
|
|
76
|
+
newRef.grid.append(newPlaceholder);
|
|
77
|
+
calculate(newRef);
|
|
78
|
+
return;
|
|
79
|
+
} else {
|
|
80
|
+
info.ref = newRef;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const params = info.ref.currentParams;
|
|
86
|
+
const $el = info.$el;
|
|
87
|
+
const containerStyles = getComputedStyle(info.ref.grid);
|
|
88
|
+
const paddingLeft = parseFloat(containerStyles.paddingLeft);
|
|
89
|
+
const paddingTop = parseFloat(containerStyles.paddingTop);
|
|
90
|
+
const paddingRight = parseFloat(containerStyles.paddingRight);
|
|
91
|
+
const paddingBottom = parseFloat(containerStyles.paddingBottom);
|
|
92
|
+
const containerInnerHeight = info.ref.grid.clientHeight - paddingTop - paddingBottom;
|
|
93
|
+
const containerInnerWidth = info.ref.grid.clientWidth - paddingLeft - paddingRight;
|
|
94
|
+
|
|
95
|
+
const moveX = event.clientX - info.clientX;
|
|
96
|
+
const moveY = event.clientY - info.clientY;
|
|
97
|
+
const coord = getTranslateCoord($el);
|
|
98
|
+
info.clientX = event.clientX;
|
|
99
|
+
info.clientY = event.clientY;
|
|
100
|
+
|
|
101
|
+
let translateX = moveX + coord.x;
|
|
102
|
+
let translateY = moveY + coord.y;
|
|
103
|
+
|
|
104
|
+
if (!params.allowOutOfBox) {
|
|
105
|
+
translateX = Math.min(Math.max(translateX, 0), containerInnerWidth - $el.offsetWidth);
|
|
106
|
+
translateY = Math.min(Math.max(translateY, 0), containerInnerHeight - $el.offsetHeight);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
$el.style.transform = `translate(${translateX}px, ${translateY}px)`;
|
|
110
|
+
|
|
111
|
+
if (findedRef !== '') {
|
|
112
|
+
calculateOnSort(window.GSSortableConfigue!.overInItemRef as Ref);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
window.scrollY = document.documentElement.scrollTop;
|
|
117
|
+
window.scrollX = document.documentElement.scrollLeft;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export default initMouseMove;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { getTranslateCoord } from './general';
|
|
2
|
+
|
|
3
|
+
const initScroll = (): void => {
|
|
4
|
+
const info = window.GSSortableConfigue?.draggableInfo;
|
|
5
|
+
|
|
6
|
+
if (info !== undefined) {
|
|
7
|
+
const coord = getTranslateCoord(info.$el);
|
|
8
|
+
const scrollY = document.documentElement.scrollTop;
|
|
9
|
+
const scrollX = document.documentElement.scrollLeft;
|
|
10
|
+
|
|
11
|
+
const translateX = coord.x + (scrollX - (window.scrollX || 0));
|
|
12
|
+
const translateY = coord.y + (scrollY - (window.scrollY || 0));
|
|
13
|
+
|
|
14
|
+
window.scrollY = scrollY;
|
|
15
|
+
window.scrollX = scrollX;
|
|
16
|
+
|
|
17
|
+
info.$el.style.transform = `translate(${translateX}px, ${translateY}px)`;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default initScroll;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import constParams from '../constants/constParams';
|
|
2
|
+
import calculate from './calculate';
|
|
3
|
+
import { getOffsetFromBody, moveChildToIndex } from './general';
|
|
4
|
+
import { Ref } from '../types/ref';
|
|
5
|
+
|
|
6
|
+
const initSortEnd = (_event: MouseEvent): void => {
|
|
7
|
+
if (window.GSSortableConfigue?.draggableInfo === undefined) return;
|
|
8
|
+
|
|
9
|
+
// Capture all needed values before clearing the global — prevents a second
|
|
10
|
+
// mousedown during the animation from reading stale isAdjusting state.
|
|
11
|
+
const draggableInfo = window.GSSortableConfigue.draggableInfo;
|
|
12
|
+
const { $el, ref, placeholder, moved, newTop, newLeft, index } = draggableInfo;
|
|
13
|
+
const takeFrom = window.GSSortableConfigue.takeFrom!;
|
|
14
|
+
|
|
15
|
+
// Clear global immediately so new drags are not blocked
|
|
16
|
+
window.GSSortableConfigue.draggableInfo = undefined;
|
|
17
|
+
|
|
18
|
+
if (moved) {
|
|
19
|
+
let containerDifX = 0;
|
|
20
|
+
let containerDifY = 0;
|
|
21
|
+
|
|
22
|
+
if (ref.currentParams.reference !== takeFrom.currentParams.reference) {
|
|
23
|
+
const fromCoord = getOffsetFromBody(takeFrom.grid as HTMLElement);
|
|
24
|
+
const toCoord = getOffsetFromBody(ref.grid as HTMLElement);
|
|
25
|
+
containerDifY = toCoord.top - fromCoord.top;
|
|
26
|
+
containerDifX = toCoord.left - fromCoord.left;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
ref.isAdjusting = true;
|
|
30
|
+
|
|
31
|
+
$el.classList.remove('gs-sortable-item-inmove');
|
|
32
|
+
ref.grid.classList.remove('gs-sortable-active');
|
|
33
|
+
|
|
34
|
+
const activeParent = ref.grid.closest('.gs-sortable-item-active-parent');
|
|
35
|
+
if (activeParent) {
|
|
36
|
+
activeParent.classList.remove('gs-sortable-item-active-parent');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
$el.classList.add('gs-sortable-item-adjusting');
|
|
40
|
+
|
|
41
|
+
$el.style.top = `${newTop + containerDifY}px`;
|
|
42
|
+
$el.style.left = `${newLeft + containerDifX}px`;
|
|
43
|
+
$el.style.removeProperty('transform');
|
|
44
|
+
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
$el.classList.remove('gs-sortable-item-adjusting');
|
|
47
|
+
|
|
48
|
+
if (
|
|
49
|
+
ref.currentParams.reference === takeFrom.currentParams.reference &&
|
|
50
|
+
takeFrom.currentParams.takeClone
|
|
51
|
+
) {
|
|
52
|
+
$el.remove();
|
|
53
|
+
} else {
|
|
54
|
+
if (index !== undefined) {
|
|
55
|
+
moveChildToIndex(ref.grid as HTMLElement, $el, index);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
placeholder?.remove();
|
|
60
|
+
|
|
61
|
+
if (ref.currentParams.reference !== takeFrom.currentParams.reference) {
|
|
62
|
+
takeFrom.currentParams.afterSort?.(
|
|
63
|
+
takeFrom.grid.querySelectorAll('.gs-sortable-item'),
|
|
64
|
+
);
|
|
65
|
+
ref.currentParams.afterSort?.(
|
|
66
|
+
ref.grid.querySelectorAll('.gs-sortable-item'),
|
|
67
|
+
);
|
|
68
|
+
takeFrom.refresh();
|
|
69
|
+
ref.refresh();
|
|
70
|
+
} else {
|
|
71
|
+
calculate(ref);
|
|
72
|
+
ref.currentParams.afterSort?.(
|
|
73
|
+
ref.grid.querySelectorAll('.gs-sortable-item'),
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
ref.isAdjusting = false;
|
|
78
|
+
}, constParams.animationSpeed);
|
|
79
|
+
} else {
|
|
80
|
+
$el.style.top = `${newTop}px`;
|
|
81
|
+
$el.style.left = `${newLeft}px`;
|
|
82
|
+
$el.style.removeProperty('transform');
|
|
83
|
+
placeholder?.remove();
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export default initSortEnd;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState, ReactNode, CSSProperties } from 'react';
|
|
2
|
+
import getCurrentParams from '../actions/getCurrentParams';
|
|
3
|
+
import init from '../actions/init';
|
|
4
|
+
import destroy from '../actions/destroy';
|
|
5
|
+
import afterAllImagesLoad from '../actions/afterAllImagesLoad';
|
|
6
|
+
import defaultParams from '../constants/defaultParams';
|
|
7
|
+
import initMouseMove from '../actions/initMouseMove';
|
|
8
|
+
import initSortEnd from '../actions/initSortEnd';
|
|
9
|
+
import initScroll from '../actions/initScroll';
|
|
10
|
+
import {
|
|
11
|
+
NewGuid,
|
|
12
|
+
convertScssToCss,
|
|
13
|
+
injectCssToHead,
|
|
14
|
+
removeCssFromHead,
|
|
15
|
+
} from '../helpers/uihelpers';
|
|
16
|
+
import cssContent from './styles/GSSortableCSS';
|
|
17
|
+
import { Params } from '../types/params';
|
|
18
|
+
import { Ref } from '../types/ref';
|
|
19
|
+
|
|
20
|
+
export interface GSSortableProps extends Params {
|
|
21
|
+
children?: ReactNode;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const GSSortable: React.FC<GSSortableProps> = ({ children, ...rest }) => {
|
|
25
|
+
const params: Partial<Params> = { ...rest };
|
|
26
|
+
const [componentKey, setComponentKey] = useState<string | null>(null);
|
|
27
|
+
const gridRef = useRef<HTMLDivElement | null>(null);
|
|
28
|
+
const initializedRef = useRef(false);
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (componentKey != null) {
|
|
32
|
+
// Inject CSS once — no external import needed by the consumer
|
|
33
|
+
const styleId = 'gs-sortable-styles';
|
|
34
|
+
if (!document.getElementById(styleId)) {
|
|
35
|
+
const style = document.createElement('style');
|
|
36
|
+
style.id = styleId;
|
|
37
|
+
style.textContent = cssContent;
|
|
38
|
+
document.head.appendChild(style);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Initialise global registry and window event listeners once
|
|
42
|
+
if (typeof window.GSSortableConfigue === 'undefined') {
|
|
43
|
+
window.GSSortableConfigue = {
|
|
44
|
+
references: [],
|
|
45
|
+
instance: (ref: string) => {
|
|
46
|
+
if (ref) {
|
|
47
|
+
const instance = window.GSSortableConfigue?.references.find(
|
|
48
|
+
(x) => x.key === ref,
|
|
49
|
+
);
|
|
50
|
+
if (instance) return instance.ref;
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
window.addEventListener('mousemove', (e) => initMouseMove(e));
|
|
55
|
+
window.addEventListener('mouseup', (e) => initSortEnd(e));
|
|
56
|
+
window.addEventListener('scroll', () => initScroll());
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (
|
|
60
|
+
window.GSSortableConfigue.references.find(
|
|
61
|
+
(x) => x.key === componentKey,
|
|
62
|
+
) === undefined
|
|
63
|
+
) {
|
|
64
|
+
const currentParams = getCurrentParams({
|
|
65
|
+
...params,
|
|
66
|
+
reference: componentKey,
|
|
67
|
+
} as Params);
|
|
68
|
+
|
|
69
|
+
window.GSSortableConfigue.references.push({
|
|
70
|
+
key: componentKey,
|
|
71
|
+
ref: {
|
|
72
|
+
isAdjusting: false,
|
|
73
|
+
grid: gridRef.current!,
|
|
74
|
+
currentParams: { ...currentParams, reference: componentKey },
|
|
75
|
+
itemResizeObservers: [],
|
|
76
|
+
destroy: () => {
|
|
77
|
+
destroy(window.GSSortableConfigue?.instance(componentKey)!);
|
|
78
|
+
},
|
|
79
|
+
refresh: () => {
|
|
80
|
+
const ref = window.GSSortableConfigue?.instance(componentKey)!;
|
|
81
|
+
destroy(ref);
|
|
82
|
+
init(ref);
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const currentRef = window.GSSortableConfigue.references.find(
|
|
88
|
+
(x) => x.key === componentKey,
|
|
89
|
+
)?.ref;
|
|
90
|
+
|
|
91
|
+
if (params.gsx && currentRef) {
|
|
92
|
+
const scss: Record<string, CSSProperties> = {};
|
|
93
|
+
scss[`[data-key='${componentKey}']`] = { ...params.gsx };
|
|
94
|
+
const style = convertScssToCss(scss);
|
|
95
|
+
injectCssToHead(style, componentKey);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (currentRef) {
|
|
99
|
+
init(currentRef);
|
|
100
|
+
afterAllImagesLoad(currentRef);
|
|
101
|
+
initializedRef.current = true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return () => {
|
|
106
|
+
const ref = window.GSSortableConfigue?.instance(componentKey);
|
|
107
|
+
if (ref) {
|
|
108
|
+
ref.itemResizeObservers?.forEach((obs) => obs.disconnect());
|
|
109
|
+
ref.itemResizeObservers = [];
|
|
110
|
+
}
|
|
111
|
+
if (window.GSSortableConfigue) {
|
|
112
|
+
window.GSSortableConfigue.references =
|
|
113
|
+
window.GSSortableConfigue.references.filter(
|
|
114
|
+
(x) => x.key !== componentKey,
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
removeCssFromHead(componentKey);
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}, [componentKey]);
|
|
121
|
+
|
|
122
|
+
// Re-init when children change (items added/removed) — but only after first init
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
if (componentKey != null && initializedRef.current) {
|
|
125
|
+
const ref = window.GSSortableConfigue?.instance(componentKey);
|
|
126
|
+
if (ref) {
|
|
127
|
+
destroy(ref);
|
|
128
|
+
init(ref);
|
|
129
|
+
afterAllImagesLoad(ref);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}, [children]);
|
|
133
|
+
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
setComponentKey(params.reference || NewGuid());
|
|
136
|
+
}, []);
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<>
|
|
140
|
+
{componentKey != null ? (
|
|
141
|
+
<div
|
|
142
|
+
className={`gs-sortable-instance gs-sortable-${params.type ?? 'column'} ${
|
|
143
|
+
rest.className || ''
|
|
144
|
+
}`}
|
|
145
|
+
ref={gridRef}
|
|
146
|
+
data-key={componentKey}
|
|
147
|
+
{...Object.fromEntries(
|
|
148
|
+
Object.entries(rest).filter(([key]) => !(key in defaultParams)),
|
|
149
|
+
)}
|
|
150
|
+
>
|
|
151
|
+
{children}
|
|
152
|
+
</div>
|
|
153
|
+
) : null}
|
|
154
|
+
</>
|
|
155
|
+
);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
GSSortable.displayName = 'GSSortable';
|
|
159
|
+
|
|
160
|
+
export default GSSortable;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
.gs-sortable-instance {
|
|
2
|
+
box-sizing: border-box;
|
|
3
|
+
-webkit-user-select: none !important;
|
|
4
|
+
-moz-user-select: none !important;
|
|
5
|
+
user-select: none !important;
|
|
6
|
+
transition: 0.4s;
|
|
7
|
+
z-index: 1;
|
|
8
|
+
}
|
|
9
|
+
.gs-sortable-instance.gs-sortable-active {
|
|
10
|
+
z-index: 2;
|
|
11
|
+
}
|
|
12
|
+
.gs-sortable-instance * {
|
|
13
|
+
-webkit-user-select: none !important;
|
|
14
|
+
-moz-user-select: none !important;
|
|
15
|
+
user-select: none !important;
|
|
16
|
+
}
|
|
17
|
+
.gs-sortable-instance .gs-sortable-placeholder {
|
|
18
|
+
position: absolute;
|
|
19
|
+
background-color: #f1f1f1;
|
|
20
|
+
border: 1px solid;
|
|
21
|
+
z-index: 1;
|
|
22
|
+
}
|
|
23
|
+
.gs-sortable-instance .gs-sortable-item {
|
|
24
|
+
z-index: 2;
|
|
25
|
+
}
|
|
26
|
+
.gs-sortable-instance .gs-sortable-item.gs-sortable-item-active-parent {
|
|
27
|
+
z-index: 3;
|
|
28
|
+
}
|
|
29
|
+
.gs-sortable-instance .gs-sortable-item-inmove {
|
|
30
|
+
transition: none !important;
|
|
31
|
+
z-index: 99999;
|
|
32
|
+
}
|
|
33
|
+
.gs-sortable-instance .gs-sortable-item-addjusting {
|
|
34
|
+
z-index: 99999;
|
|
35
|
+
}
|
|
36
|
+
.gs-sortable-instance.gs-sortable-row .gs-sortable-item {
|
|
37
|
+
width: -moz-max-content;
|
|
38
|
+
width: max-content;
|
|
39
|
+
}/*# sourceMappingURL=GSSortable.css.map */
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
.gs-sortable-instance {
|
|
2
|
+
box-sizing: border-box;
|
|
3
|
+
user-select: none !important;
|
|
4
|
+
transition: 0.4s;
|
|
5
|
+
z-index: 1;
|
|
6
|
+
&.gs-sortable-active {
|
|
7
|
+
z-index: 2;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
* {
|
|
11
|
+
user-select: none !important;
|
|
12
|
+
}
|
|
13
|
+
.gs-sortable-placeholder {
|
|
14
|
+
position: absolute;
|
|
15
|
+
background-color: #f1f1f1;
|
|
16
|
+
border: 1px solid;
|
|
17
|
+
z-index: 1;
|
|
18
|
+
}
|
|
19
|
+
.gs-sortable-item {
|
|
20
|
+
z-index: 2;
|
|
21
|
+
&.gs-sortable-item-active-parent {
|
|
22
|
+
z-index: 3;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
.gs-sortable-item-inmove {
|
|
26
|
+
//transition: width 0.2s, height 0.2s !important;
|
|
27
|
+
transition: none !important;
|
|
28
|
+
z-index: 99999;
|
|
29
|
+
}
|
|
30
|
+
.gs-sortable-item-addjusting {
|
|
31
|
+
z-index: 99999;
|
|
32
|
+
}
|
|
33
|
+
&.gs-sortable-row {
|
|
34
|
+
.gs-sortable-item {
|
|
35
|
+
width: max-content;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export default `
|
|
2
|
+
.gs-sortable-instance {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
-webkit-user-select: none !important;
|
|
5
|
+
-moz-user-select: none !important;
|
|
6
|
+
user-select: none !important;
|
|
7
|
+
transition: 0.4s;
|
|
8
|
+
z-index: 1;
|
|
9
|
+
}
|
|
10
|
+
.gs-sortable-instance.gs-sortable-active {
|
|
11
|
+
z-index: 2;
|
|
12
|
+
}
|
|
13
|
+
.gs-sortable-instance * {
|
|
14
|
+
-webkit-user-select: none !important;
|
|
15
|
+
-moz-user-select: none !important;
|
|
16
|
+
user-select: none !important;
|
|
17
|
+
}
|
|
18
|
+
.gs-sortable-instance .gs-sortable-placeholder {
|
|
19
|
+
position: absolute;
|
|
20
|
+
background-color: #f1f1f1;
|
|
21
|
+
border: 1px solid;
|
|
22
|
+
z-index: 1;
|
|
23
|
+
}
|
|
24
|
+
.gs-sortable-instance .gs-sortable-item {
|
|
25
|
+
z-index: 2;
|
|
26
|
+
}
|
|
27
|
+
.gs-sortable-instance .gs-sortable-item.gs-sortable-item-active-parent {
|
|
28
|
+
z-index: 3;
|
|
29
|
+
}
|
|
30
|
+
.gs-sortable-instance .gs-sortable-item-inmove {
|
|
31
|
+
transition: none !important;
|
|
32
|
+
z-index: 99999;
|
|
33
|
+
}
|
|
34
|
+
.gs-sortable-instance .gs-sortable-item-addjusting {
|
|
35
|
+
z-index: 99999;
|
|
36
|
+
}
|
|
37
|
+
.gs-sortable-instance.gs-sortable-row .gs-sortable-item {
|
|
38
|
+
width: -moz-max-content;
|
|
39
|
+
width: max-content;
|
|
40
|
+
}/*# sourceMappingURL=GSSortable.css.map */
|
|
41
|
+
`;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import types from './types';
|
|
2
|
+
import { Params } from '../types/params';
|
|
3
|
+
|
|
4
|
+
const defaultParams: Params = {
|
|
5
|
+
acceptFrom: [],
|
|
6
|
+
className: '',
|
|
7
|
+
takeClone: false,
|
|
8
|
+
reference: '',
|
|
9
|
+
count: 3,
|
|
10
|
+
gap: '',
|
|
11
|
+
gsx: undefined,
|
|
12
|
+
handler: '',
|
|
13
|
+
width: 'auto',
|
|
14
|
+
type: types.column,
|
|
15
|
+
allowOutOfBox: true,
|
|
16
|
+
responsive: [],
|
|
17
|
+
afterSort: () => {},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default Object.freeze(defaultParams);
|