@get-set/gs-sortable 0.0.1 → 0.0.2

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.
@@ -0,0 +1,43 @@
1
+ import calculate from "./calculate";
2
+
3
+ const afterAllImagesLoad = (ref) => {
4
+ const $images = [...ref.grid.querySelectorAll("img")];
5
+ const count = $images.length;
6
+
7
+ if (count > 0) {
8
+ let alreadyLoaded = 0;
9
+ $images.map((img) => {
10
+ if (img.complete) {
11
+ alreadyLoaded++;
12
+ if (alreadyLoaded === count) {
13
+ setTimeout(() => {
14
+ calculate(ref);
15
+ }, 500);
16
+ }
17
+ } else {
18
+ img.onload = () => {
19
+ alreadyLoaded++;
20
+ if (alreadyLoaded === count) {
21
+ setTimeout(() => {
22
+ calculate(ref);
23
+ }, 500);
24
+ }
25
+ };
26
+ img.onerror = () => {
27
+ alreadyLoaded++;
28
+ if (alreadyLoaded === count) {
29
+ setTimeout(() => {
30
+ calculate(ref);
31
+ }, 500);
32
+ }
33
+ };
34
+ }
35
+ });
36
+ } else {
37
+ setTimeout(() => {
38
+ calculate(ref);
39
+ }, 500);
40
+ }
41
+ };
42
+
43
+ export default afterAllImagesLoad;
@@ -0,0 +1,142 @@
1
+ import constParams from "../constants/constParams";
2
+ import types from "../constants/types";
3
+
4
+ const calculate = (ref) => {
5
+ console.log("calculate");
6
+ const params = ref.currentParams;
7
+ if (typeof ref.currentParams.beforeInit === "function") {
8
+ ref.currentParams.beforeInit();
9
+ }
10
+ const $items = [...ref.grid.children].filter(
11
+ (x) => !x.classList.contains("gs-sortable-item-inmove")
12
+ );
13
+ const itemsCount = $items.length;
14
+
15
+ ref.grid.style.position = "relative";
16
+ if (params.gap != "") {
17
+ ref.grid.style.gap = params.gap;
18
+ }
19
+ const gridStyles = getComputedStyle(ref.grid);
20
+ const cssGap = gridStyles.gap;
21
+ let gapX = 0;
22
+ let gapY = 0;
23
+ if (typeof cssGap !== "undefined" && cssGap !== null) {
24
+ const cssGapYValue = cssGap.includes(" ") ? cssGap.split(" ")[0] : cssGap;
25
+ const cssGapXValue = cssGap.includes(" ") ? cssGap.split(" ")[1] : cssGap;
26
+
27
+ const gapYSize = parseInt(cssGapYValue);
28
+ const gapXSize = parseInt(cssGapXValue);
29
+ if (!Number.isNaN(gapYSize)) {
30
+ gapY = gapYSize;
31
+ }
32
+ if (!Number.isNaN(gapXSize)) {
33
+ gapX = gapXSize;
34
+ }
35
+ }
36
+ const borderBottomWidth = parseFloat(gridStyles.borderBottomWidth);
37
+ const borderTopWidth = parseFloat(gridStyles.borderTopWidth);
38
+ const borderLeftWidth = parseFloat(gridStyles.borderLeftWidth);
39
+ const borderRightWidth = parseFloat(gridStyles.borderRightWidth);
40
+ const containerPT = parseFloat(gridStyles.paddingTop);
41
+ const containerPR = parseFloat(gridStyles.paddingRight);
42
+ const containerPB = parseFloat(gridStyles.paddingBottom);
43
+ const containerPL = parseFloat(gridStyles.paddingLeft);
44
+
45
+ const containerWidth = ref.grid.clientWidth - containerPR - containerPL;
46
+ let itemWidth = 0;
47
+ if (params.type == types.grid) {
48
+ itemWidth = (containerWidth - (params.count - 1) * gapX) / params.count;
49
+ }
50
+
51
+ const transition = `left ${constParams.animateionSpeed}ms, top ${constParams.animateionSpeed}ms, transform ${constParams.animateionSpeed}ms`;
52
+
53
+ let currentLeft = containerPL;
54
+ let currentTop = containerPT;
55
+ let currentHeight =
56
+ containerPT + containerPB + borderBottomWidth + borderTopWidth; //ref.grid.offsetHeight;
57
+ let currentWidth =
58
+ containerPL + containerPR + borderLeftWidth + borderRightWidth;
59
+ let maxHeight = 0;
60
+ $items.map((el) => {
61
+ el.style.position = "absolute";
62
+ if (params.type == types.column) {
63
+ el.style.width = `${containerWidth}px`;
64
+ } else if (params.type == types.grid) {
65
+ el.style.width = `${itemWidth}px`;
66
+ }
67
+ el.style.transition = transition;
68
+ });
69
+ ref.uiData = {
70
+ containerPT,
71
+ containerPR,
72
+ containerPB,
73
+ containerPL,
74
+ containerWidth,
75
+ currentHeight,
76
+ currentWidth,
77
+ itemWidth,
78
+ gapX,
79
+ gapY,
80
+ };
81
+ let colHeight = 0;
82
+ $items.map((el, index) => {
83
+ const height = el.offsetHeight;
84
+ const width = el.offsetWidth;
85
+ if (params.type == types.column) {
86
+ el.style.left = `${containerPL}px`;
87
+ if (currentTop == containerPT) {
88
+ el.style.top = `${containerPT}px`;
89
+ currentTop = containerPT + height;
90
+ currentHeight = currentHeight + height;
91
+ } else {
92
+ el.style.top = `${currentTop + gapY}px`;
93
+ currentTop = currentTop + gapY + height;
94
+ currentHeight = currentHeight + height + gapY;
95
+ }
96
+ } else if (params.type == types.row) {
97
+ el.style.top = `${containerPT}px`;
98
+ if (currentLeft == containerPL) {
99
+ el.style.left = `${containerPL}px`;
100
+ currentLeft = containerPL + width;
101
+ currentWidth = currentWidth + width;
102
+ } else {
103
+ el.style.left = `${currentLeft + gapX}px`;
104
+ currentLeft = currentLeft + gapX + width;
105
+ currentWidth = currentWidth + width + gapX;
106
+ }
107
+ if (height > maxHeight) {
108
+ maxHeight = height;
109
+ }
110
+ } else if (params.type == types.grid) {
111
+ const left =
112
+ index % params.count == 0
113
+ ? containerPL
114
+ : containerPL + (index % params.count) * (itemWidth + gapX);
115
+ const top = currentTop;
116
+ if (height > colHeight) {
117
+ colHeight = height;
118
+ }
119
+ if (
120
+ index % params.count === params.count - 1 ||
121
+ index === itemsCount - 1
122
+ ) {
123
+ if (top === containerPT) {
124
+ currentHeight = currentHeight + colHeight;
125
+ } else {
126
+ currentHeight = currentHeight + colHeight + gapY;
127
+ }
128
+ currentTop = currentTop + colHeight + gapY;
129
+ colHeight = 0;
130
+ }
131
+ el.style.left = `${left}px`;
132
+ el.style.top = `${top}px`;
133
+ }
134
+ });
135
+ ref.grid.style.height = `${currentHeight}px`;
136
+ if (params.type == types.row) {
137
+ ref.grid.style.height = `${currentHeight + maxHeight}px`;
138
+ ref.grid.style.width = `${currentWidth}px`;
139
+ }
140
+ };
141
+
142
+ export default calculate;
@@ -0,0 +1,282 @@
1
+ import types from "../constants/types";
2
+ import { getOffsetFromWindow, getTranslateCoord } from "./general";
3
+
4
+ const calculateOnSort = (ref) => {
5
+ const params = ref.currentParams;
6
+ const $items = [...ref.grid.children];
7
+ const itemsCount = $items.filter(
8
+ (x) => !x.classList.contains("gs-sortable-item-inmove")
9
+ ).length;
10
+ const info = window.GSSortableConfigue.draggableInfo;
11
+ let {
12
+ containerPT,
13
+ containerPR,
14
+ containerPB,
15
+ containerPL,
16
+ containerWidth,
17
+ currentHeight,
18
+ currentWidth,
19
+ itemWidth,
20
+ gapX,
21
+ gapY,
22
+ } = ref.uiData;
23
+
24
+ let currentLeft = containerPL;
25
+ let currentTop = containerPT;
26
+ let maxHeight = 0;
27
+ let maxWidth = 0;
28
+
29
+ let placeholderSeted = info === undefined;
30
+ let inProcessEl = undefined;
31
+ const containerCoord = getOffsetFromWindow(info.ref.grid);
32
+ if (info !== undefined) {
33
+ const $el = info.$el;
34
+ const elCoord = getOffsetFromWindow($el);
35
+ //const coord = getTranslateCoord($el);
36
+ inProcessEl = {
37
+ height: $el.offsetHeight,
38
+ width: $el.offsetWidth,
39
+ top: elCoord.top - containerCoord.top,
40
+ left: elCoord.left - containerCoord.left,
41
+ };
42
+ }
43
+ let plIndex = info.index;
44
+ let colHeight = 0;
45
+
46
+ let itIndex = 0;
47
+
48
+ $items.map((el) => {
49
+ if (!el.classList.contains("gs-sortable-item-inmove")) {
50
+ const height = el.offsetHeight;
51
+ const width = el.offsetWidth;
52
+ if (params.type == types.column) {
53
+ if (!placeholderSeted) {
54
+ let placeholderTop =
55
+ currentTop == containerPT ? containerPT : currentTop + gapY;
56
+ let placeholderLeft = containerPL;
57
+
58
+ if (
59
+ Math.abs(placeholderTop - inProcessEl.top) <
60
+ inProcessEl.height / 2 &&
61
+ Math.abs(placeholderLeft - inProcessEl.left) < inProcessEl.width / 2
62
+ ) {
63
+ info.newTop = placeholderTop;
64
+ info.newLeft = placeholderLeft;
65
+ placeholderSeted = true;
66
+ plIndex = itIndex;
67
+ }
68
+ }
69
+ if (!el.classList.contains("gs-sortable-placeholder")) {
70
+ if (currentTop == containerPT) {
71
+ currentTop = containerPT + height;
72
+ currentHeight = currentHeight + height;
73
+ } else {
74
+ currentTop = currentTop + gapY + height;
75
+ currentHeight = currentHeight + height + gapY;
76
+ }
77
+ }
78
+ } else if (params.type == types.row) {
79
+ if (!placeholderSeted) {
80
+ let placeholderLeft =
81
+ currentLeft == containerPL ? containerPL : currentLeft + gapX;
82
+ let placeholderTop = containerPT;
83
+ if (
84
+ Math.abs(placeholderTop - inProcessEl.top) <
85
+ inProcessEl.height / 2 &&
86
+ Math.abs(placeholderLeft - inProcessEl.left) < inProcessEl.width / 2
87
+ ) {
88
+ info.newTop = placeholderTop;
89
+ info.newLeft = placeholderLeft;
90
+ placeholderSeted = true;
91
+ plIndex = itIndex;
92
+ }
93
+ }
94
+ if (!el.classList.contains("gs-sortable-placeholder")) {
95
+ if (currentLeft == containerPL) {
96
+ currentLeft = containerPL + width;
97
+ currentWidth = currentWidth + width;
98
+ } else {
99
+ currentLeft = currentLeft + gapX + width;
100
+ currentWidth = currentWidth + width + gapX;
101
+ }
102
+ if (height > maxHeight) {
103
+ maxHeight = height;
104
+ }
105
+ }
106
+ } else if (params.type == types.grid) {
107
+ const placeholderLeft =
108
+ itIndex % params.count == 0
109
+ ? containerPL
110
+ : containerPL + (itIndex % params.count) * (itemWidth + gapX);
111
+ const placeholderTop = currentTop;
112
+ if (
113
+ Math.abs(placeholderTop - inProcessEl.top) < inProcessEl.height / 2 &&
114
+ Math.abs(placeholderLeft - inProcessEl.left) < inProcessEl.width / 2
115
+ ) {
116
+ info.newTop = placeholderTop;
117
+ info.newLeft = placeholderLeft;
118
+ placeholderSeted = true;
119
+ plIndex = itIndex;
120
+ }
121
+ if (!el.classList.contains("gs-sortable-placeholder")) {
122
+ const top = currentTop;
123
+ if (height > colHeight) {
124
+ colHeight = height;
125
+ }
126
+ if (
127
+ itIndex % params.count === params.count - 1 ||
128
+ itIndex === itemsCount - 1
129
+ ) {
130
+ if (top === containerPT) {
131
+ currentHeight = currentHeight + colHeight;
132
+ } else {
133
+ currentHeight = currentHeight + colHeight + gapY;
134
+ }
135
+ currentTop = currentTop + colHeight + gapY;
136
+ colHeight = 0;
137
+ }
138
+ }
139
+ }
140
+ itIndex += 1;
141
+ }
142
+ });
143
+ //'if (plIndex != info.index) {
144
+ if (true) {
145
+ info.index = plIndex;
146
+ let {
147
+ containerPT,
148
+ containerPR,
149
+ containerPB,
150
+ containerPL,
151
+ containerWidth,
152
+ currentHeight,
153
+ currentWidth,
154
+ itemWidth,
155
+ gapX,
156
+ gapY,
157
+ } = ref.uiData;
158
+
159
+ currentLeft = containerPL;
160
+ currentTop = containerPT;
161
+ itIndex = 0;
162
+ $items.map((el) => {
163
+ if (!el.classList.contains("gs-sortable-item-inmove")) {
164
+ const height = el.offsetHeight;
165
+ const width = el.offsetWidth;
166
+ if (params.type == types.column) {
167
+ if (itIndex == plIndex) {
168
+ info.placeholder.style.left = `${containerPL}px`;
169
+ info.newLeft = containerPL;
170
+ if (currentTop == containerPT) {
171
+ info.newTop = containerPT;
172
+ info.placeholder.style.top = `${containerPT}px`;
173
+ currentTop = containerPT + inProcessEl.height;
174
+ } else {
175
+ info.newTop = currentTop + gapY;
176
+ info.placeholder.style.top = `${currentTop + gapY}px`;
177
+ currentTop = currentTop + gapY + inProcessEl.height;
178
+ }
179
+ }
180
+ if (!el.classList.contains("gs-sortable-placeholder")) {
181
+ el.style.left = `${containerPL}px`;
182
+ if (currentTop == containerPT) {
183
+ el.style.top = `${containerPT}px`;
184
+ currentTop = containerPT + height;
185
+ currentHeight = currentHeight + height;
186
+ } else {
187
+ el.style.top = `${currentTop + gapY}px`;
188
+ currentTop = currentTop + gapY + height;
189
+ currentHeight = currentHeight + height + gapY;
190
+ }
191
+ }
192
+ } else if (params.type == types.row) {
193
+ if (itIndex == plIndex) {
194
+ info.placeholder.style.top = `${containerPT}px`;
195
+ info.newTop = containerPT;
196
+ if (currentLeft == containerPL) {
197
+ info.newLeft = containerPL;
198
+ info.placeholder.style.left = `${containerPL}px`;
199
+ currentLeft = containerPL + inProcessEl.width;
200
+ } else {
201
+ info.newLeft = currentLeft + gapX;
202
+ info.placeholder.style.left = `${currentLeft + gapX}px`;
203
+ currentLeft = currentLeft + gapX + inProcessEl.width;
204
+ }
205
+ }
206
+ if (!el.classList.contains("gs-sortable-placeholder")) {
207
+ el.style.top = `${containerPT}px`;
208
+ if (currentLeft == containerPL) {
209
+ el.style.left = `${containerPL}px`;
210
+ currentLeft = containerPL + width;
211
+ currentWidth = currentWidth + width;
212
+ } else {
213
+ el.style.left = `${currentLeft + gapX}px`;
214
+ currentLeft = currentLeft + gapX + width;
215
+ currentWidth = currentWidth + width + gapX;
216
+ }
217
+ }
218
+ if (height > maxHeight) {
219
+ maxHeight = height;
220
+ }
221
+ } else if (params.type == types.grid) {
222
+ if (itIndex == plIndex) {
223
+ const left =
224
+ itIndex % params.count == 0
225
+ ? containerPL
226
+ : containerPL + (itIndex % params.count) * (itemWidth + gapX);
227
+ const top = currentTop;
228
+ if (inProcessEl.height > colHeight) {
229
+ colHeight = inProcessEl.height;
230
+ }
231
+ if (
232
+ itIndex % params.count === params.count - 1 ||
233
+ itIndex === itemsCount - 1
234
+ ) {
235
+ if (top === containerPT) {
236
+ currentHeight = currentHeight + colHeight;
237
+ } else {
238
+ currentHeight = currentHeight + colHeight + gapY;
239
+ }
240
+ currentTop = currentTop + colHeight + gapY;
241
+ colHeight = 0;
242
+ ref.grid.style.height = `${currentHeight}px`;
243
+ }
244
+ itIndex += 1;
245
+ info.newTop = top;
246
+ info.newLeft = left;
247
+ info.placeholder.style.left = `${left}px`;
248
+ info.placeholder.style.top = `${top}px`;
249
+ }
250
+ if (!el.classList.contains("gs-sortable-placeholder")) {
251
+ const left =
252
+ itIndex % params.count == 0
253
+ ? containerPL
254
+ : containerPL + (itIndex % params.count) * (itemWidth + gapX);
255
+ const top = currentTop;
256
+ if (height > colHeight) {
257
+ colHeight = height;
258
+ }
259
+ if (
260
+ itIndex % params.count === params.count - 1 ||
261
+ itIndex === itemsCount - 1
262
+ ) {
263
+ if (top === containerPT) {
264
+ currentHeight = currentHeight + colHeight;
265
+ } else {
266
+ currentHeight = currentHeight + colHeight + gapY;
267
+ }
268
+ currentTop = currentTop + colHeight + gapY;
269
+ colHeight = 0;
270
+ ref.grid.style.height = `${currentHeight}px`;
271
+ }
272
+ el.style.left = `${left}px`;
273
+ el.style.top = `${top}px`;
274
+ }
275
+ }
276
+ itIndex += 1;
277
+ }
278
+ });
279
+ }
280
+ };
281
+
282
+ export default calculateOnSort;
@@ -0,0 +1,28 @@
1
+ import { getOffsetFromWindow } from './general';
2
+
3
+ const checkItemInContainer = (grid, el) => {
4
+ const gridOffset = getOffsetFromWindow(grid);
5
+ const elOffset = getOffsetFromWindow(el);
6
+ const gridTop = gridOffset.top;
7
+ const gridLeft = gridOffset.left;
8
+ const elTop = elOffset.top;
9
+ const elLeft = elOffset.left;
10
+
11
+ const offsetTopFromGrid = elTop - gridTop;
12
+ const offsetLeftFromGrid = elLeft - gridLeft;
13
+ const elHeight = el.offsetHeight;
14
+ const elWidth = el.offsetWidth;
15
+ const gridHeight = grid.offsetHeight;
16
+ const gridWidth = grid.offsetWidth;
17
+ if (
18
+ offsetTopFromGrid >= (-1 * elHeight) / 2 &&
19
+ offsetLeftFromGrid >= (-1 * elWidth) / 2 &&
20
+ offsetTopFromGrid <= gridHeight - elHeight / 2 &&
21
+ offsetLeftFromGrid <= gridWidth - elWidth / 2
22
+ ) {
23
+ return true;
24
+ }
25
+ return false;
26
+ };
27
+
28
+ export default checkItemInContainer;
@@ -0,0 +1,19 @@
1
+ const destroy = (ref) => {
2
+ ref.grid.classList.remove('gs-sortable-instance');
3
+ ref.grid.classList.remove(`gs-sortable-${ref.currentParams.type}`);
4
+ ref.grid.style.removeProperty('position');
5
+ ref.grid.style.removeProperty('gap');
6
+ ref.grid.style.removeProperty('height');
7
+ ref.grid.style.removeProperty('width');
8
+ [...ref.grid.children].map((el) => {
9
+ el.classList.remove('gs-sortable-item');
10
+ el.style.removeProperty('position');
11
+ el.style.removeProperty('width');
12
+ el.style.removeProperty('left');
13
+ el.style.removeProperty('top');
14
+ el.style.removeProperty('transition');
15
+ });
16
+ ref.count = ref.grid.children.length;
17
+ };
18
+
19
+ export default destroy;
@@ -0,0 +1,81 @@
1
+ export const getTranslateCoord = (element) => {
2
+ const style = window.getComputedStyle(element);
3
+ // eslint-disable-next-line no-undef
4
+ const matrix = new WebKitCSSMatrix(style.transform);
5
+ return {
6
+ x: matrix.e,
7
+ y: matrix.f,
8
+ };
9
+ };
10
+ export const getOffsetFromBody = (el) => {
11
+ let top = 0,
12
+ left = 0;
13
+
14
+ // Loop through every parent element
15
+ while (el && el !== document.body) {
16
+ top += el.offsetTop || 0;
17
+ left += el.offsetLeft || 0;
18
+
19
+ // Handle transformations (i.e., translate, scale)
20
+ const transform = window.getComputedStyle(el).transform;
21
+ if (transform !== 'none') {
22
+ const matrix = new DOMMatrix(transform);
23
+ top += matrix.m42 || 0;
24
+ left += matrix.m41 || 0;
25
+ }
26
+
27
+ // If there's a positioned parent, move up the tree
28
+ el = el.offsetParent;
29
+ }
30
+
31
+ // Add scroll offsets for body, in case of page scrolling
32
+ top += document.body.scrollTop || document.documentElement.scrollTop || 0;
33
+ left += document.body.scrollLeft || document.documentElement.scrollLeft || 0;
34
+
35
+ return { top, left };
36
+ };
37
+ export const getOffsetFromWindow = (el) => {
38
+ let top = 0,
39
+ left = 0;
40
+
41
+ // Loop through each parent, accumulating the offset relative to the viewport
42
+ while (el) {
43
+ top += el.offsetTop || 0;
44
+ left += el.offsetLeft || 0;
45
+
46
+ // Handle transforms (translate, scale, etc.)
47
+ const transform = window.getComputedStyle(el).transform;
48
+ if (transform !== 'none') {
49
+ const matrix = new DOMMatrix(transform);
50
+ top += matrix.m42 || 0;
51
+ left += matrix.m41 || 0;
52
+ }
53
+
54
+ // Move to the next parent element
55
+ el = el.offsetParent;
56
+ }
57
+
58
+ // Subtract scroll position from the window (not the document)
59
+ top -= window.scrollY || 0;
60
+ left -= window.scrollX || 0;
61
+
62
+ return { top, left };
63
+ };
64
+ export const moveChildToIndex = (parent, child, newIndex) => {
65
+ let children = Array.from(parent.children);
66
+ let oldIndex = children.indexOf(child);
67
+ if (oldIndex !== newIndex) {
68
+ if (oldIndex === newIndex) return; // If not found or same position, do nothing
69
+
70
+ // Ensure the new index is within valid bounds
71
+ newIndex = Math.max(0, Math.min(newIndex, children.length - 1));
72
+
73
+ if (newIndex > oldIndex && oldIndex != -1) {
74
+ // Moving forward, so insert after the target index
75
+ parent.insertBefore(child, children[newIndex].nextSibling);
76
+ } else {
77
+ // Moving backward, insert before the target index
78
+ parent.insertBefore(child, children[newIndex]);
79
+ }
80
+ }
81
+ };
@@ -0,0 +1,32 @@
1
+ import _defaultParams from "../constants/defaultParams";
2
+
3
+ const getCurrentParams = (params) => {
4
+ const defaultParams = { ..._defaultParams };
5
+ let finalParams = {
6
+ ...defaultParams,
7
+ ...params,
8
+ };
9
+
10
+ if (finalParams.responsive.length > 0) {
11
+ finalParams.responsive.sort((a, b) => b.windowSize - a.windowSize);
12
+ }
13
+
14
+ if (finalParams.responsive.length > 0) {
15
+ const windowSize = window.innerWidth;
16
+ const availableResponsives = finalParams.responsive.filter(
17
+ (resp) => resp.windowSize >= windowSize
18
+ );
19
+
20
+ availableResponsives.map((resp) => {
21
+ finalParams = {
22
+ ...finalParams,
23
+ ...resp.params,
24
+ };
25
+ return resp;
26
+ });
27
+ }
28
+
29
+ return finalParams;
30
+ };
31
+
32
+ export default getCurrentParams;
@@ -0,0 +1,20 @@
1
+ import calculate from './calculate';
2
+ import initDraggable from './initDraggable';
3
+
4
+ const init = (ref) => {
5
+ ref.grid.classList.add('gs-sortable-instance');
6
+ ref.grid.classList.add(`gs-sortable-${ref.currentParams.type}`);
7
+ [...ref.grid.children].map((el) => {
8
+ el.classList.add('gs-sortable-item');
9
+
10
+ let resizeObserver = new ResizeObserver(() => {
11
+ calculate(ref);
12
+ });
13
+ resizeObserver.observe(el);
14
+ });
15
+ ref.count = ref.grid.children.length;
16
+
17
+ initDraggable(ref);
18
+ };
19
+
20
+ export default init;
@@ -0,0 +1,73 @@
1
+ import constParams from '../constants/constParams';
2
+
3
+ const initDraggable = (ref) => {
4
+ const params = ref.currentParams;
5
+
6
+ const $items = [...ref.grid.children];
7
+ $items.map(($el, index) => {
8
+ $el.onmousedown = null;
9
+ const handler =
10
+ params.handler != '' ? $el.querySelector(params.handler) : $el;
11
+ if (handler != null) {
12
+ handler.style.cursor = 'move';
13
+ handler.onmousedown = (e) => {
14
+ if (!ref.isAddjusting) {
15
+ window.GSSortableConfigue.overInItemRef = ref;
16
+ window.GSSortableConfigue.takeFrom = ref;
17
+ const container = ref.grid;
18
+ const elStyles = getComputedStyle($el);
19
+ const containerStyles = getComputedStyle(container);
20
+ const paddingTop = parseFloat(containerStyles.paddingTop);
21
+ const paddingLeft = parseFloat(containerStyles.paddingLeft);
22
+ const placeholder = document.createElement('div');
23
+ const top = parseFloat(elStyles.top);
24
+ const left = parseFloat(elStyles.left);
25
+ placeholder.classList.add('gs-sortable-placeholder');
26
+ placeholder.style.position = elStyles.position;
27
+ placeholder.style.transition = `left ${constParams.animateionSpeed}ms, top ${constParams.animateionSpeed}ms, transform ${constParams.animateionSpeed}ms, opacity ${constParams.animateionSpeed}ms, opacity ${constParams.animateionSpeed}ms`;
28
+ placeholder.style.width = `${$el.offsetWidth}px`;
29
+ placeholder.style.height = `${$el.offsetHeight}px`;
30
+ placeholder.style.top = `${top}px`;
31
+ placeholder.style.left = `${left}px`;
32
+ placeholder.style.border = elStyles.border;
33
+ placeholder.style.borderRadius = elStyles.borderRadius;
34
+ ref.grid.append(placeholder);
35
+ let translateX = 0;
36
+ let translateY = 0;
37
+ if (!isNaN(parseFloat(top))) {
38
+ translateY = parseFloat(top);
39
+ }
40
+ if (!isNaN(parseFloat(left))) {
41
+ translateX = parseFloat(left);
42
+ }
43
+ $el.style.transform = ` translate(${translateX - paddingLeft}px, ${
44
+ translateY - paddingTop
45
+ }px)`;
46
+ $el.style.top = `${paddingTop}px`;
47
+ $el.style.left = `${paddingLeft}px`;
48
+
49
+ window.GSSortableConfigue.draggableInfo = {
50
+ moved: false,
51
+ ref: ref,
52
+ index,
53
+ $el,
54
+ clientX: e.clientX,
55
+ clientY: e.clientY,
56
+ placeholder,
57
+ newLeft: left,
58
+ newTop: top,
59
+ };
60
+ $el.classList.add('gs-sortable-item-inmove');
61
+ ref.grid.classList.add('gs-sortable-active');
62
+ if (ref.grid.closest('.gs-sortable-item') != null) {
63
+ ref.grid
64
+ .closest('.gs-sortable-item')
65
+ .classList.add('gs-sortable-item-active-parent');
66
+ }
67
+ }
68
+ };
69
+ }
70
+ });
71
+ };
72
+
73
+ export default initDraggable;
@@ -0,0 +1,105 @@
1
+ import { getTranslateCoord } from './general';
2
+ import getItemPositionToContainer from './checkItemInContainer';
3
+ import checkItemInContainer from './checkItemInContainer';
4
+ import calculate from './calculate';
5
+ import constParams from '../constants/constParams';
6
+ import calculateOnSort from './calculateOnSort';
7
+
8
+ const initMouseMove = (event) => {
9
+ const info = window.GSSortableConfigue.draggableInfo;
10
+
11
+ if (info != undefined) {
12
+ info.moved = true;
13
+ const allRefs = [window.GSSortableConfigue.takeFrom];
14
+ window.GSSortableConfigue.references.map((item) => {
15
+ if (
16
+ item.ref.currentParams.acceptFrom.includes(
17
+ window.GSSortableConfigue.takeFrom.currentParams.reference
18
+ )
19
+ ) {
20
+ allRefs.push(item.ref);
21
+ }
22
+ });
23
+ let findedRef = '';
24
+ allRefs.map((item) => {
25
+ if (checkItemInContainer(item.grid, info.$el)) {
26
+ findedRef = item.currentParams.reference;
27
+ }
28
+ });
29
+ if (findedRef !== '') {
30
+ //if (window.GSSortableConfigue.overInItemRef == undefined) {
31
+ const newRef = window.GSSortableConfigue.instance(findedRef);
32
+ if (
33
+ newRef != undefined &&
34
+ info.ref.currentParams.reference !== newRef.currentParams.reference
35
+ ) {
36
+ if (document.querySelector('.gs-sortable-placeholder') != null) {
37
+ document.querySelector('.gs-sortable-placeholder').remove();
38
+ calculate(window.GSSortableConfigue.overInItemRef);
39
+ }
40
+
41
+ window.GSSortableConfigue.overInItemRef = newRef;
42
+ const elStyles = getComputedStyle(info.$el);
43
+ const placeholder = document.createElement('div');
44
+ const top = parseFloat(elStyles.top);
45
+ const left = parseFloat(elStyles.left);
46
+ placeholder.classList.add('gs-sortable-placeholder');
47
+ placeholder.style.position = elStyles.position;
48
+ placeholder.style.transition = `left ${constParams.animateionSpeed}ms, top ${constParams.animateionSpeed}ms, transform ${constParams.animateionSpeed}ms, opacity ${constParams.animateionSpeed}ms, opacity ${constParams.animateionSpeed}ms`;
49
+ placeholder.style.width = `${info.$el.offsetWidth}px`;
50
+ placeholder.style.height = `${info.$el.offsetHeight}px`;
51
+ placeholder.style.top = `${top}px`;
52
+ placeholder.style.left = `${left}px`;
53
+ placeholder.style.border = elStyles.border;
54
+ placeholder.style.borderRadius = elStyles.borderRadius;
55
+ newRef.grid.append(placeholder);
56
+ info.placeholder = placeholder;
57
+ info.ref = newRef;
58
+ calculate(newRef);
59
+ return;
60
+ }
61
+ // } else {
62
+ // }
63
+ }
64
+ //if (window.GSSortableConfigue.overInItemRef != undefined) {
65
+ const params = info.ref.currentParams;
66
+ const clientX = event.clientX;
67
+ const clientY = event.clientY;
68
+ const $el = info.$el;
69
+ const containerStyles = getComputedStyle(info.ref.grid);
70
+ const paddingLeft = parseFloat(containerStyles.paddingLeft);
71
+ const paddingTop = parseFloat(containerStyles.paddingTop);
72
+ const paddingRight = parseFloat(containerStyles.paddingRight);
73
+ const paddingBottom = parseFloat(containerStyles.paddingBottom);
74
+ const containerInnerHeight =
75
+ info.ref.grid.clientHeight - paddingTop - paddingBottom;
76
+ const containerInnerWidth =
77
+ info.ref.grid.clientWidth - paddingLeft - paddingRight;
78
+ const moveX = clientX - info.clientX;
79
+ const moveY = clientY - info.clientY;
80
+ const coord = getTranslateCoord($el);
81
+ info.clientX = clientX;
82
+ info.clientY = clientY;
83
+ let tranlateX = moveX + coord.x;
84
+ let tranlateY = moveY + coord.y;
85
+ if (!params.allowOutOfBox) {
86
+ const minY = 0;
87
+ const minX = 0;
88
+ const maxY = containerInnerHeight - $el.offsetHeight;
89
+ const maxX = containerInnerWidth - $el.offsetWidth;
90
+ tranlateX = Math.min(Math.max(tranlateX, minX), maxX);
91
+ tranlateY = Math.min(Math.max(tranlateY, minY), maxY);
92
+ }
93
+ $el.style.transform = `translate(${tranlateX}px, ${tranlateY}px)`;
94
+
95
+ if (findedRef != '') {
96
+ console.log('calculateOnSort');
97
+ calculateOnSort(window.GSSortableConfigue.overInItemRef);
98
+ }
99
+ //}
100
+ }
101
+ window.scrollY = document.documentElement.scrollTop;
102
+ window.scrollX = document.documentElement.scrollLeft;
103
+ };
104
+
105
+ export default initMouseMove;
@@ -0,0 +1,23 @@
1
+ import { getTranslateCoord } from './general';
2
+
3
+ const initScroll = () => {
4
+ const info = window.GSSortableConfigue.draggableInfo;
5
+
6
+ if (info != undefined) {
7
+ const $el = info.$el;
8
+ const coord = getTranslateCoord(info.$el);
9
+ let translateX = coord.x;
10
+ let translateY = coord.y;
11
+ const scrollY = document.documentElement.scrollTop;
12
+ const scrollX = document.documentElement.scrollLeft;
13
+ const scrollYDist = scrollY - window.scrollY;
14
+ const scrollXDist = scrollX - window.scrollX;
15
+ translateX = translateX + scrollXDist;
16
+ translateY = translateY + scrollYDist;
17
+ window.scrollY = scrollY;
18
+ window.scrollX = scrollX;
19
+ info.$el.style.transform = `translate(${translateX}px, ${translateY}px)`;
20
+ }
21
+ };
22
+
23
+ export default initScroll;
@@ -0,0 +1,75 @@
1
+ import constParams from '../constants/constParams';
2
+ import calculate from './calculate';
3
+ import { getOffsetFromBody, moveChildToIndex } from './general';
4
+
5
+ const initSortEnd = (event) => {
6
+ const info = { ...window.GSSortableConfigue.draggableInfo };
7
+ if (window.GSSortableConfigue.draggableInfo != undefined) {
8
+ if (info.moved) {
9
+ let containerDifX = 0;
10
+ let containerDifY = 0;
11
+ if (
12
+ info.ref.currentParams.reference !==
13
+ window.GSSortableConfigue.takeFrom.currentParams.reference
14
+ ) {
15
+ const fromCoord = getOffsetFromBody(
16
+ window.GSSortableConfigue.takeFrom.grid
17
+ );
18
+ const toCoord = getOffsetFromBody(info.ref.grid);
19
+ containerDifY = toCoord.top - fromCoord.top;
20
+ containerDifX = toCoord.left - fromCoord.left;
21
+ }
22
+ info.ref.isAddjusting = true;
23
+ const $el = info.$el;
24
+ const placeholder = info.placeholder;
25
+ info.$el.classList.remove('gs-sortable-item-inmove');
26
+ info.ref.grid.classList.remove('gs-sortable-active');
27
+ if (info.ref.grid.closest('.gs-sortable-item-active-parent') != null) {
28
+ info.ref.grid
29
+ .closest('.gs-sortable-item-active-parent')
30
+ .classList.remove('gs-sortable-item-active-parent');
31
+ }
32
+ info.$el.classList.add('gs-sortable-item-addjusting');
33
+ window.GSSortableConfigue.draggableInfo = undefined;
34
+ info.$el.style.top = `${info.newTop + containerDifY}px`;
35
+ info.$el.style.left = `${info.newLeft + containerDifX}px`;
36
+ info.$el.style.removeProperty('transform');
37
+ setTimeout(() => {
38
+ $el.classList.remove('gs-sortable-item-addjusting');
39
+ // if (
40
+ // info.ref.currentParams.reference ===
41
+ // window.GSSortableConfigue.takeFrom.currentParams.reference
42
+ // ) {
43
+ if (info.index != undefined) {
44
+ moveChildToIndex(info.ref.grid, info.$el, info.index);
45
+ }
46
+ // }
47
+ // else{
48
+ // if (info.index != undefined) {
49
+ // moveChildToIndex(info.ref.grid, info.$el, info.index);
50
+ // }
51
+ // }
52
+ placeholder.remove();
53
+ if (
54
+ info.ref.currentParams.reference !==
55
+ window.GSSortableConfigue.takeFrom.currentParams.reference
56
+ ) {
57
+ window.GSSortableConfigue.takeFrom.refresh();
58
+ info.ref.refresh();
59
+ } else {
60
+ calculate(info.ref);
61
+ }
62
+ info.ref.isAddjusting = false;
63
+ }, constParams.animateionSpeed);
64
+ } else {
65
+ const placeholder = info.placeholder;
66
+ info.$el.style.top = `${info.newTop}px`;
67
+ info.$el.style.left = `${info.newLeft}px`;
68
+ info.$el.style.removeProperty('transform');
69
+ placeholder.remove();
70
+ window.GSSortableConfigue.draggableInfo = undefined;
71
+ }
72
+ }
73
+ };
74
+
75
+ export default initSortEnd;
@@ -0,0 +1,145 @@
1
+ import { useEffect, useRef, useState } from 'react';
2
+ import NewGuid from '../helpers/uihelpers';
3
+ import getCurrentParams from '../actions/getCurrentParams';
4
+ import init from './actions/init';
5
+ import destroy from './actions/destroy';
6
+ import PropTypes from 'prop-types';
7
+ import init from '../actions/init';
8
+ import defaultParams from '../constants/defaultParams';
9
+ import initMouseMove from "./actions/initMouseMove";
10
+ import initSortEnd from "./actions/initSortEnd";
11
+ import initScroll from "./actions/initScroll";
12
+
13
+ const params = {
14
+ reference: PropTypes.string,
15
+ gap: PropTypes.string,
16
+ count: PropTypes.number,
17
+ resetSortHandler: PropTypes.number,
18
+ resetFilterHandler: PropTypes.number,
19
+ };
20
+
21
+ /**
22
+ * GSSortable component to display a customizable sortable.
23
+ *
24
+ * @component
25
+ * @param {Object} props - The props object.
26
+ * @param {string} props.gap - Allows set gap among elements.
27
+ * @param {number} props.count - Shows items count per row.
28
+ * @param {Object} props.resetSortHandler - This is the ref of that element which should reset order.
29
+ * @param {Object} props.resetFilterHandler - This is the ref of that element which should reset filter.
30
+ * @param {Array<Object>} [props.sortByOptions] - Array of sort options.
31
+ * @param {number} props.sortByOptions[].handler - This is the ref of that element which should change order.
32
+ * @param {string} props.sortByOptions[].prop - this is the name of data attribute of element like data-[prop].
33
+ * @param {'number' | 'string'} props.sortByOptions[].type - this is the type of prop.
34
+ * @param {Array<Object>} [props.filterByOptions] - Array of filter options.
35
+ * @param {number} props.filterByOptions[].handler - This is the ref of that element which should change filter.
36
+ * @param {string} props.filterByOptions[].prop - This is the name of data attribute of element like data-[prop].
37
+ * @param {'number' | 'string'} props.filterByOptions[].value - This is the value of prop for element.
38
+ * @param {Array<Object>} [props.responsive] - Array of responsive configurations based on window size.
39
+ * @param {number} props.responsive[].windowSize - Minimum window size for this configuration.
40
+ * @param {Object} props.responsive[].params - The responsive configuration for the grid.
41
+ * @returns {JSX.Element} The rendered sortable component.
42
+ */
43
+
44
+ const GSSortable = ({ children, ...rest }) => {
45
+ const params = { ...rest };
46
+ const [componentKey, setComponentKey] = useState(null);
47
+ const gridRef = useRef(null);
48
+
49
+ useEffect(() => {
50
+ if (componentKey != null) {
51
+ if (typeof window.GSSortableConfigue === 'undefined') {
52
+ window.GSSortableConfigue = {
53
+ references: [],
54
+ instance: ref => {
55
+ if (ref != undefined && ref != '') {
56
+ const instance = window.GSSortableConfigue.references.find(
57
+ x => x.key === ref,
58
+ );
59
+ if (instance != undefined) {
60
+ return instance.ref;
61
+ }
62
+ }
63
+ },
64
+ };
65
+
66
+ window.addEventListener("mousemove", (e) => {
67
+ initMouseMove(e);
68
+ });
69
+ window.addEventListener("mouseup", (e) => {
70
+ initSortEnd(e);
71
+ });
72
+ window.addEventListener("scroll", () => {
73
+ initScroll();
74
+ });
75
+ }
76
+ if (
77
+ window.GSSortableConfigue.references.find(
78
+ x => x.key === componentKey,
79
+ ) === undefined
80
+ ) {
81
+ const currentParams = getCurrentParams(params);
82
+
83
+ window.GSSortableConfigue.references.push({
84
+ key: componentKey,
85
+ ref: {
86
+ isAddjusting: false,
87
+ grid: gridRef.current,
88
+ currentParams,
89
+ destroy: () => {
90
+ destroy(window.GSSortableConfigue.instance(_key));
91
+ },
92
+ refresh: () => {
93
+ destroy(window.GSSortableConfigue.instance(_key));
94
+ init(window.GSSortableConfigue.instance(_key));
95
+ },
96
+ },
97
+ });
98
+
99
+ const currentRef = window.GSSortableConfigue.references.find(
100
+ x => x.key === componentKey,
101
+ ).ref;
102
+ init(currentRef);
103
+ }
104
+ return () => {
105
+ if (window.GSCarouselConfigue != undefined) {
106
+ window.GSCarouselConfigue.references =
107
+ window.GSCarouselConfigue.references.filter(
108
+ x => x.key !== componentKey,
109
+ );
110
+ }
111
+ };
112
+ }
113
+ }, [componentKey]);
114
+
115
+ useEffect(() => {
116
+ setComponentKey(
117
+ params.reference != undefined ? params.reference : NewGuid(),
118
+ );
119
+ }, []);
120
+
121
+ return (
122
+ <div
123
+ className={`gs-sortable-instance gs-sortable-${params.type}`}
124
+ ref={gridRef}
125
+ {...Object.fromEntries(
126
+ Object.entries({ ...rest }).filter(([key]) => !(key in defaultParams)),
127
+ )}>
128
+ {children}
129
+ </div>
130
+ );
131
+ };
132
+
133
+ GSSortable.propTypes = {
134
+ ...params,
135
+ responsive: PropTypes.arrayOf(
136
+ PropTypes.shape({
137
+ windowSize: PropTypes.number,
138
+ params: PropTypes.shape({
139
+ ...params,
140
+ }),
141
+ }),
142
+ ),
143
+ };
144
+
145
+ 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 @@
1
+ {"version":3,"sources":["GSSortable.scss","GSSortable.css"],"names":[],"mappings":"AAAA;EACE,sBAAA;EACA,oCAAA;KAAA,iCAAA;UAAA,4BAAA;EACA,gBAAA;EACA,UAAA;ACCF;ADAE;EACE,UAAA;ACEJ;ADCE;EACE,oCAAA;KAAA,iCAAA;UAAA,4BAAA;ACCJ;ADCE;EACE,kBAAA;EACA,yBAAA;EACA,iBAAA;EACA,UAAA;ACCJ;ADCE;EACE,UAAA;ACCJ;ADAI;EACE,UAAA;ACEN;ADCE;EACE,2BAAA;EACA,cAAA;ACCJ;ADCE;EACE,cAAA;ACCJ;ADEI;EACE,uBAAA;EAAA,kBAAA;ACAN","file":"GSSortable.css"}
@@ -0,0 +1,37 @@
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: none !important;
27
+ z-index: 99999;
28
+ }
29
+ .gs-sortable-item-addjusting {
30
+ z-index: 99999;
31
+ }
32
+ &.gs-sortable-row {
33
+ .gs-sortable-item {
34
+ width: max-content;
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,5 @@
1
+ const constParams = {
2
+ animateionSpeed: 400,
3
+ };
4
+
5
+ export default Object.freeze(constParams);
@@ -0,0 +1,15 @@
1
+ import types from './types';
2
+
3
+ const defaultParams = {
4
+ acceptFrom: [],
5
+ reference: '',
6
+ count: 3,
7
+ gap: '',
8
+ handler: '',
9
+ width: 'auto',
10
+ type: types.column,
11
+ allowOutOfBox: true,
12
+ responsive: [],
13
+ };
14
+
15
+ export default Object.freeze(defaultParams);
@@ -0,0 +1,7 @@
1
+ const types = {
2
+ row: 'row',
3
+ column: 'column',
4
+ grid: 'grid',
5
+ };
6
+
7
+ export default Object.freeze(types);
@@ -0,0 +1,9 @@
1
+ const NewGuid = () => {
2
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
3
+ const r = (Math.random() * 16) | 0,
4
+ v = c == 'x' ? r : (r & 0x3) | 0x8;
5
+ return v.toString(16);
6
+ });
7
+ };
8
+
9
+ export default NewGuid;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@get-set/gs-sortable",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "Get-Set Sortable",
5
5
  "main": "index.js",
6
6
  "author": "Get-Set",