@fr0st/ui-sortable 2.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 elusivecodes
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # FrostUI Sortable
2
+
3
+ **FrostUI Sortable** is a free, open-source Sortable component for *JavaScript*.
4
+
5
+ It is built on top of the [FrostUI](https://github.com/elusivecodes/FrostUI) library.
6
+
7
+
8
+ ## Table Of Contents
9
+ - [Installation](#installation)
10
+ - [Usage](#usage)
11
+
12
+
13
+
14
+ ## Installation
15
+
16
+ **Dependencies**
17
+
18
+ - [fQuery](https://github.com/elusivecodes/fQuery)
19
+ - [FrostUI](https://github.com/elusivecodes/FrostUI)
20
+
21
+ **CSS**
22
+
23
+ ```html
24
+ <link rel="stylesheet" href="/path/to/frost-ui.min.css" />
25
+ ```
26
+
27
+ **JS**
28
+
29
+ ```html
30
+ <script type="text/javascript" src="/path/to/frost-ui-bundle.min.js"></script>
31
+ <script type="text/javascript" src="/path/to/frost-ui-sortable.min.js"></script>
32
+ ```
33
+
34
+
35
+ ## Usage
36
+
37
+ Check the demo folder for examples. Full documentation and website coming soon™.
@@ -0,0 +1,327 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fr0st/ui'), require('@fr0st/query')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', '@fr0st/ui', '@fr0st/query'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.UI = global.UI || {}, global.UI, global.fQuery));
5
+ })(this, (function (exports, ui, $) { 'use strict';
6
+
7
+ /**
8
+ * Sortable Class
9
+ * @class
10
+ */
11
+ class Sortable extends ui.BaseComponent {
12
+ /**
13
+ * New Sortable constructor.
14
+ * @param {HTMLElement} node The input node.
15
+ * @param {object} [options] The options to create the Sortable with.
16
+ */
17
+ constructor(node, options) {
18
+ super(node, options);
19
+
20
+ this._selector = this._options.items;
21
+ if (this._options.handle) {
22
+ this._selector += ' ' + this._options.handle;
23
+ }
24
+
25
+ this._enabled = !this._options.disabled;
26
+
27
+ this._refreshCursors();
28
+ this._events();
29
+ }
30
+
31
+ /**
32
+ * Disable the Sortable.
33
+ */
34
+ disable() {
35
+ this._enabled = false;
36
+ }
37
+
38
+ /**
39
+ * Dispose the Sortable.
40
+ */
41
+ dispose() {
42
+ $.removeEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable');
43
+ $.removeEvent(this._node, 'receive.ui.sortable');
44
+
45
+ this._target = null;
46
+ this._currentSortable = null;
47
+
48
+ super.dispose();
49
+ }
50
+
51
+ /**
52
+ * Enable the Sortable.
53
+ */
54
+ enable() {
55
+ this._enabled = true;
56
+ }
57
+
58
+ /**
59
+ * Get the Sortable item elements.
60
+ * @return {array} The Sortable item elements.
61
+ */
62
+ items() {
63
+ return $.find(this._options.items, this._node);
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Attach events for the Sortable.
69
+ */
70
+ function _events() {
71
+ const downEvent = (e) => {
72
+ if (
73
+ e.button ||
74
+ !this._enabled ||
75
+ $.is(e.currentTarget, this._options.cancel) ||
76
+ $.getDataset(this._node, 'uiDragging')
77
+ ) {
78
+ return false;
79
+ }
80
+
81
+ if (e.type === 'mousedown') {
82
+ e.preventDefault();
83
+ }
84
+
85
+ this._target = this._options.handle ?
86
+ this.items().find((node) => $.hasDescendent(node, e.currentTarget)) :
87
+ e.currentTarget;
88
+ };
89
+
90
+ const moveEvent = (e) => {
91
+ this._pos = ui.getPosition(e);
92
+
93
+ if (!$.getDataset(this._node, 'uiDragging')) {
94
+ $.setDataset(this._node, { uiDragging: true });
95
+
96
+ this._startIndex = $.index(this._target);
97
+ this._currentIndex = this._startIndex;
98
+
99
+ $.triggerEvent(this._node, 'sort.ui.sortable', {
100
+ detail: {
101
+ target: this._target,
102
+ },
103
+ });
104
+
105
+ if (this._options.helperClass) {
106
+ $.addClass(this._target, this._options.helperClass);
107
+ }
108
+
109
+ this._currentSortable = this._node;
110
+
111
+ if (this._options.scroll) {
112
+ this._checkScroll();
113
+ }
114
+ }
115
+
116
+ let nearestSortable = this._node;
117
+
118
+ if (this._options.connectWith) {
119
+ const connected = $.find(this._options.connectWith)
120
+ .filter((node) => {
121
+ const sortable = this.constructor.init(node);
122
+
123
+ return sortable._options.dropOnEmpty || sortable.items().length;
124
+ });
125
+
126
+ if (connected.length) {
127
+ nearestSortable = $.nearestTo([this._node, ...connected], this._pos.x, this._pos.y, { offset: true });
128
+ }
129
+ }
130
+
131
+ const nearestItems = $.isSame(this._node, nearestSortable) ?
132
+ this.items() :
133
+ this.constructor.init(nearestSortable).items();
134
+
135
+ const nearestItem = $.nearestTo(nearestItems, this._pos.x, this._pos.y, { offset: true });
136
+
137
+ if (!nearestItem) {
138
+ return;
139
+ }
140
+
141
+ this._updateTarget(nearestItem, this._pos.x, this._pos.y);
142
+
143
+ const newIndex = $.index(this._target);
144
+
145
+ if (!$.isSame(nearestSortable, this._currentSortable)) {
146
+ $.triggerEvent(this._currentSortable, 'send.ui.sortable', {
147
+ detail: {
148
+ target: this._target,
149
+ },
150
+ });
151
+
152
+ $.triggerEvent(nearestSortable, 'receive.ui.sortable', {
153
+ detail: {
154
+ target: this._target,
155
+ },
156
+ });
157
+ } else if (this._currentIndex !== newIndex) {
158
+ $.triggerEvent(nearestSortable, 'sorting.ui.sortable', {
159
+ detail: {
160
+ target: this._target,
161
+ },
162
+ });
163
+ }
164
+
165
+ this._currentIndex = newIndex;
166
+ this._currentSortable = nearestSortable;
167
+ };
168
+
169
+ const upEvent = (e) => {
170
+ if (!$.getDataset(this._node, 'uiDragging')) {
171
+ this._target = null;
172
+ return;
173
+ }
174
+
175
+ if (e.type === 'mouseup') {
176
+ e.preventDefault();
177
+ }
178
+
179
+ $.triggerEvent(this._currentSortable, 'sorted.ui.sortable', {
180
+ detail: {
181
+ target: this._target,
182
+ },
183
+ });
184
+
185
+ if (this._options.helperClass) {
186
+ $.removeClass(this._target, this._options.helperClass);
187
+ }
188
+
189
+ if (this._currentIndex !== this._startIndex || !$.isSame(this._currentSortable, this._node)) {
190
+ $.triggerEvent(this._currentSortable, 'update.ui.sortable', {
191
+ detail: {
192
+ target: this._target,
193
+ },
194
+ });
195
+ }
196
+
197
+ $.removeDataset(this._node, 'uiDragging');
198
+
199
+ if (this._checkScrollTimer) {
200
+ clearTimeout(this._checkScrollTimer);
201
+ this._checkScrollTimer = null;
202
+ }
203
+
204
+ this._target = null;
205
+ this._currentSortable = null;
206
+ this._currentIndex = null;
207
+ this._startIndex = null;
208
+ };
209
+
210
+ const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);
211
+
212
+ $.addEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable', this._selector, dragEvent);
213
+
214
+ $.addEvent(this._node, 'receive.ui.sortable', (_) => {
215
+ this._refreshCursors();
216
+ });
217
+ }
218
+
219
+ /**
220
+ * Check for window scroll.
221
+ */
222
+ function _checkScroll() {
223
+ $.hide(this._target);
224
+
225
+ const originalX = $.getScrollX(window);
226
+ const originalY = $.getScrollY(window);
227
+
228
+ let offsetX = originalX;
229
+ let offsetY = originalY;
230
+
231
+ if (this._pos.y < originalY + this._options.scrollSensitivity) {
232
+ offsetY = Math.max(0, originalY - this._options.scrollSpeed);
233
+ } else if (this._pos.y > originalY + $.height(window) - this._options.scrollSensitivity) {
234
+ const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });
235
+ offsetY = Math.min(docHeight, originalY + this._options.scrollSpeed);
236
+ }
237
+
238
+ if (this._pos.x < originalX + this._options.scrollSensitivity) {
239
+ offsetX = Math.max(0, originalX - this._options.scrollSpeed);
240
+ } else if (this._pos.x > originalX + $.width(window) - this._options.scrollSensitivity) {
241
+ const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });
242
+ offsetX = Math.min(docWidth, originalX + this._options.scrollSpeed);
243
+ }
244
+
245
+ if (offsetX !== originalX || offsetY !== originalY) {
246
+ $.setStyle(':root', { scrollBehavior: 'initial' });
247
+ $.setScroll(document, offsetX, offsetY);
248
+ $.setStyle(':root', { scrollBehavior: '' });
249
+
250
+ this._pos.x += offsetX - originalX;
251
+ this._pos.y += offsetY - originalY;
252
+ }
253
+
254
+ $.show(this._target);
255
+
256
+ this._checkScrollTimer = setTimeout((_) => {
257
+ this._checkScroll();
258
+ }, 0);
259
+ }
260
+ /**
261
+ * Refresh Sortable item cursors.
262
+ */
263
+ function _refreshCursors() {
264
+ const elements = $.find(this._selector, this._node);
265
+
266
+ $.setStyle(elements, { cursor: this._options.cursor });
267
+ }
268
+ /**
269
+ * Update the target element.
270
+ * @param {HTMLElement} nearestItem The current nearest item.
271
+ * @param {number} x The mouse X position.
272
+ * @param {number} y The mouse Y position.
273
+ */
274
+ function _updateTarget(nearestItem, x, y) {
275
+ const nearestCenter = $.center(nearestItem, { offset: true });
276
+ const targetCenter = $.center(this._target, { offset: true });
277
+
278
+ let method;
279
+ if (this._options.axis === 'y' || nearestCenter.x === targetCenter.x) {
280
+ method = y < nearestCenter.y ?
281
+ 'before' :
282
+ 'after';
283
+ } else if (this._options.axis === 'x' || nearestCenter.y === targetCenter.y) {
284
+ method = x < nearestCenter.x ?
285
+ 'before' :
286
+ 'after';
287
+ } else {
288
+ method = x < nearestCenter.x && y < nearestCenter.y ?
289
+ 'before' :
290
+ 'after';
291
+ }
292
+
293
+ $[method](nearestItem, this._target);
294
+ }
295
+
296
+ // Sortable default options
297
+ Sortable.defaults = {
298
+ appendTo: 'body',
299
+ axis: null,
300
+ cancel: 'input, textarea, button, select, option',
301
+ connectWith: null,
302
+ cursor: 'auto',
303
+ disabled: false,
304
+ dropOnEmpty: true,
305
+ handle: null,
306
+ helperClass: 'bg-body-tertiary',
307
+ items: ':scope > li',
308
+ scroll: true,
309
+ scrollSensitivity: 20,
310
+ scrollSpeed: 5,
311
+ };
312
+
313
+ // Sortable prototype
314
+ const proto = Sortable.prototype;
315
+
316
+ proto._checkScroll = _checkScroll;
317
+ proto._events = _events;
318
+ proto._refreshCursors = _refreshCursors;
319
+ proto._updateTarget = _updateTarget;
320
+
321
+ // Sortable init
322
+ ui.initComponent('sortable', Sortable);
323
+
324
+ exports.Sortable = Sortable;
325
+
326
+ }));
327
+ //# sourceMappingURL=frost-ui-sortable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frost-ui-sortable.js","sources":["../src/sortable.js","../src/prototype/events.js","../src/prototype/helpers.js","../src/index.js"],"sourcesContent":["import $ from '@fr0st/query';\nimport { BaseComponent } from '@fr0st/ui';\n\n/**\n * Sortable Class\n * @class\n */\nexport default class Sortable extends BaseComponent {\n /**\n * New Sortable constructor.\n * @param {HTMLElement} node The input node.\n * @param {object} [options] The options to create the Sortable with.\n */\n constructor(node, options) {\n super(node, options);\n\n this._selector = this._options.items;\n if (this._options.handle) {\n this._selector += ' ' + this._options.handle;\n }\n\n this._enabled = !this._options.disabled;\n\n this._refreshCursors();\n this._events();\n }\n\n /**\n * Disable the Sortable.\n */\n disable() {\n this._enabled = false;\n }\n\n /**\n * Dispose the Sortable.\n */\n dispose() {\n $.removeEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable');\n $.removeEvent(this._node, 'receive.ui.sortable');\n\n this._target = null;\n this._currentSortable = null;\n\n super.dispose();\n }\n\n /**\n * Enable the Sortable.\n */\n enable() {\n this._enabled = true;\n }\n\n /**\n * Get the Sortable item elements.\n * @return {array} The Sortable item elements.\n */\n items() {\n return $.find(this._options.items, this._node);\n }\n}\n","import $ from '@fr0st/query';\nimport { getPosition } from '@fr0st/ui';\n\n/**\n * Attach events for the Sortable.\n */\nexport function _events() {\n const downEvent = (e) => {\n if (\n e.button ||\n !this._enabled ||\n $.is(e.currentTarget, this._options.cancel) ||\n $.getDataset(this._node, 'uiDragging')\n ) {\n return false;\n }\n\n if (e.type === 'mousedown') {\n e.preventDefault();\n }\n\n this._target = this._options.handle ?\n this.items().find((node) => $.hasDescendent(node, e.currentTarget)) :\n e.currentTarget;\n };\n\n const moveEvent = (e) => {\n this._pos = getPosition(e);\n\n if (!$.getDataset(this._node, 'uiDragging')) {\n $.setDataset(this._node, { uiDragging: true });\n\n this._startIndex = $.index(this._target);\n this._currentIndex = this._startIndex;\n\n $.triggerEvent(this._node, 'sort.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n\n if (this._options.helperClass) {\n $.addClass(this._target, this._options.helperClass);\n }\n\n this._currentSortable = this._node;\n\n if (this._options.scroll) {\n this._checkScroll();\n }\n }\n\n let nearestSortable = this._node;\n\n if (this._options.connectWith) {\n const connected = $.find(this._options.connectWith)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable._options.dropOnEmpty || sortable.items().length;\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo([this._node, ...connected], this._pos.x, this._pos.y, { offset: true });\n }\n }\n\n const nearestItems = $.isSame(this._node, nearestSortable) ?\n this.items() :\n this.constructor.init(nearestSortable).items();\n\n const nearestItem = $.nearestTo(nearestItems, this._pos.x, this._pos.y, { offset: true });\n\n if (!nearestItem) {\n return;\n }\n\n this._updateTarget(nearestItem, this._pos.x, this._pos.y);\n\n const newIndex = $.index(this._target);\n\n if (!$.isSame(nearestSortable, this._currentSortable)) {\n $.triggerEvent(this._currentSortable, 'send.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n\n $.triggerEvent(nearestSortable, 'receive.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n } else if (this._currentIndex !== newIndex) {\n $.triggerEvent(nearestSortable, 'sorting.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n }\n\n this._currentIndex = newIndex;\n this._currentSortable = nearestSortable;\n };\n\n const upEvent = (e) => {\n if (!$.getDataset(this._node, 'uiDragging')) {\n this._target = null;\n return;\n }\n\n if (e.type === 'mouseup') {\n e.preventDefault();\n }\n\n $.triggerEvent(this._currentSortable, 'sorted.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n\n if (this._options.helperClass) {\n $.removeClass(this._target, this._options.helperClass);\n }\n\n if (this._currentIndex !== this._startIndex || !$.isSame(this._currentSortable, this._node)) {\n $.triggerEvent(this._currentSortable, 'update.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n }\n\n $.removeDataset(this._node, 'uiDragging');\n\n if (this._checkScrollTimer) {\n clearTimeout(this._checkScrollTimer);\n this._checkScrollTimer = null;\n }\n\n this._target = null;\n this._currentSortable = null;\n this._currentIndex = null;\n this._startIndex = null;\n };\n\n const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);\n\n $.addEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable', this._selector, dragEvent);\n\n $.addEvent(this._node, 'receive.ui.sortable', (_) => {\n this._refreshCursors();\n });\n};\n","import $ from '@fr0st/query';\n\n/**\n * Check for window scroll.\n */\nexport function _checkScroll() {\n $.hide(this._target);\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n\n let offsetX = originalX;\n let offsetY = originalY;\n\n if (this._pos.y < originalY + this._options.scrollSensitivity) {\n offsetY = Math.max(0, originalY - this._options.scrollSpeed);\n } else if (this._pos.y > originalY + $.height(window) - this._options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n offsetY = Math.min(docHeight, originalY + this._options.scrollSpeed);\n }\n\n if (this._pos.x < originalX + this._options.scrollSensitivity) {\n offsetX = Math.max(0, originalX - this._options.scrollSpeed);\n } else if (this._pos.x > originalX + $.width(window) - this._options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n offsetX = Math.min(docWidth, originalX + this._options.scrollSpeed);\n }\n\n if (offsetX !== originalX || offsetY !== originalY) {\n $.setStyle(':root', { scrollBehavior: 'initial' });\n $.setScroll(document, offsetX, offsetY);\n $.setStyle(':root', { scrollBehavior: '' });\n\n this._pos.x += offsetX - originalX;\n this._pos.y += offsetY - originalY;\n }\n\n $.show(this._target);\n\n this._checkScrollTimer = setTimeout((_) => {\n this._checkScroll();\n }, 0);\n};\n\n/**\n * Refresh Sortable item cursors.\n */\nexport function _refreshCursors() {\n const elements = $.find(this._selector, this._node);\n\n $.setStyle(elements, { cursor: this._options.cursor });\n};\n\n/**\n * Update the target element.\n * @param {HTMLElement} nearestItem The current nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n */\nexport function _updateTarget(nearestItem, x, y) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const targetCenter = $.center(this._target, { offset: true });\n\n let method;\n if (this._options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n method = y < nearestCenter.y ?\n 'before' :\n 'after';\n } else if (this._options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n method = x < nearestCenter.x ?\n 'before' :\n 'after';\n } else {\n method = x < nearestCenter.x && y < nearestCenter.y ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this._target);\n};\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\nimport { _events } from './prototype/events.js';\nimport { _checkScroll, _refreshCursors, _updateTarget } from './prototype/helpers.js';\n\n// Sortable default options\nSortable.defaults = {\n appendTo: 'body',\n axis: null,\n cancel: 'input, textarea, button, select, option',\n connectWith: null,\n cursor: 'auto',\n disabled: false,\n dropOnEmpty: true,\n handle: null,\n helperClass: 'bg-body-tertiary',\n items: ':scope > li',\n scroll: true,\n scrollSensitivity: 20,\n scrollSpeed: 5,\n};\n\n// Sortable prototype\nconst proto = Sortable.prototype;\n\nproto._checkScroll = _checkScroll;\nproto._events = _events;\nproto._refreshCursors = _refreshCursors;\nproto._updateTarget = _updateTarget;\n\n// Sortable init\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"names":["BaseComponent","getPosition","initComponent"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("@fr0st/ui"),require("@fr0st/query")):"function"==typeof define&&define.amd?define(["exports","@fr0st/ui","@fr0st/query"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).UI=t.UI||{},t.UI,t.fQuery)}(this,(function(t,e,s){"use strict";class i extends e.BaseComponent{constructor(t,e){super(t,e),this._selector=this._options.items,this._options.handle&&(this._selector+=" "+this._options.handle),this._enabled=!this._options.disabled,this._refreshCursors(),this._events()}disable(){this._enabled=!1}dispose(){s.removeEventDelegate(this._node,"mousedown.ui.sortable touchstart.ui.sortable"),s.removeEvent(this._node,"receive.ui.sortable"),this._target=null,this._currentSortable=null,super.dispose()}enable(){this._enabled=!0}items(){return s.find(this._options.items,this._node)}}i.defaults={appendTo:"body",axis:null,cancel:"input, textarea, button, select, option",connectWith:null,cursor:"auto",disabled:!1,dropOnEmpty:!0,handle:null,helperClass:"bg-body-tertiary",items:":scope > li",scroll:!0,scrollSensitivity:20,scrollSpeed:5};const o=i.prototype;o._checkScroll=function(){s.hide(this._target);const t=s.getScrollX(window),e=s.getScrollY(window);let i=t,o=e;if(this._pos.y<e+this._options.scrollSensitivity)o=Math.max(0,e-this._options.scrollSpeed);else if(this._pos.y>e+s.height(window)-this._options.scrollSensitivity){const t=s.height(document,{boxSize:s.SCROLL_BOX});o=Math.min(t,e+this._options.scrollSpeed)}if(this._pos.x<t+this._options.scrollSensitivity)i=Math.max(0,t-this._options.scrollSpeed);else if(this._pos.x>t+s.width(window)-this._options.scrollSensitivity){const e=s.width(document,{boxSize:s.SCROLL_BOX});i=Math.min(e,t+this._options.scrollSpeed)}i===t&&o===e||(s.setStyle(":root",{scrollBehavior:"initial"}),s.setScroll(document,i,o),s.setStyle(":root",{scrollBehavior:""}),this._pos.x+=i-t,this._pos.y+=o-e),s.show(this._target),this._checkScrollTimer=setTimeout((t=>{this._checkScroll()}),0)},o._events=function(){const t=s.mouseDragFactory((t=>{if(t.button||!this._enabled||s.is(t.currentTarget,this._options.cancel)||s.getDataset(this._node,"uiDragging"))return!1;"mousedown"===t.type&&t.preventDefault(),this._target=this._options.handle?this.items().find((e=>s.hasDescendent(e,t.currentTarget))):t.currentTarget}),(t=>{this._pos=e.getPosition(t),s.getDataset(this._node,"uiDragging")||(s.setDataset(this._node,{uiDragging:!0}),this._startIndex=s.index(this._target),this._currentIndex=this._startIndex,s.triggerEvent(this._node,"sort.ui.sortable",{detail:{target:this._target}}),this._options.helperClass&&s.addClass(this._target,this._options.helperClass),this._currentSortable=this._node,this._options.scroll&&this._checkScroll());let i=this._node;if(this._options.connectWith){const t=s.find(this._options.connectWith).filter((t=>{const e=this.constructor.init(t);return e._options.dropOnEmpty||e.items().length}));t.length&&(i=s.nearestTo([this._node,...t],this._pos.x,this._pos.y,{offset:!0}))}const o=s.isSame(this._node,i)?this.items():this.constructor.init(i).items(),r=s.nearestTo(o,this._pos.x,this._pos.y,{offset:!0});if(!r)return;this._updateTarget(r,this._pos.x,this._pos.y);const n=s.index(this._target);s.isSame(i,this._currentSortable)?this._currentIndex!==n&&s.triggerEvent(i,"sorting.ui.sortable",{detail:{target:this._target}}):(s.triggerEvent(this._currentSortable,"send.ui.sortable",{detail:{target:this._target}}),s.triggerEvent(i,"receive.ui.sortable",{detail:{target:this._target}})),this._currentIndex=n,this._currentSortable=i}),(t=>{s.getDataset(this._node,"uiDragging")?("mouseup"===t.type&&t.preventDefault(),s.triggerEvent(this._currentSortable,"sorted.ui.sortable",{detail:{target:this._target}}),this._options.helperClass&&s.removeClass(this._target,this._options.helperClass),this._currentIndex===this._startIndex&&s.isSame(this._currentSortable,this._node)||s.triggerEvent(this._currentSortable,"update.ui.sortable",{detail:{target:this._target}}),s.removeDataset(this._node,"uiDragging"),this._checkScrollTimer&&(clearTimeout(this._checkScrollTimer),this._checkScrollTimer=null),this._target=null,this._currentSortable=null,this._currentIndex=null,this._startIndex=null):this._target=null}));s.addEventDelegate(this._node,"mousedown.ui.sortable touchstart.ui.sortable",this._selector,t),s.addEvent(this._node,"receive.ui.sortable",(t=>{this._refreshCursors()}))},o._refreshCursors=function(){const t=s.find(this._selector,this._node);s.setStyle(t,{cursor:this._options.cursor})},o._updateTarget=function(t,e,i){const o=s.center(t,{offset:!0}),r=s.center(this._target,{offset:!0});let n;n="y"===this._options.axis||o.x===r.x?i<o.y?"before":"after":"x"===this._options.axis||o.y===r.y?e<o.x?"before":"after":e<o.x&&i<o.y?"before":"after",s[n](t,this._target)},e.initComponent("sortable",i),t.Sortable=i}));
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Sortable","BaseComponent","constructor","node","options","super","this","_selector","_options","items","handle","_enabled","disabled","_refreshCursors","_events","disable","dispose","$","removeEventDelegate","_node","removeEvent","_target","_currentSortable","enable","find","defaults","appendTo","axis","cancel","connectWith","cursor","dropOnEmpty","helperClass","scroll","scrollSensitivity","scrollSpeed","proto","prototype","_checkScroll","hide","originalX","getScrollX","window","originalY","getScrollY","offsetX","offsetY","_pos","y","Math","max","height","docHeight","document","boxSize","SCROLL_BOX","min","x","width","docWidth","setStyle","scrollBehavior","setScroll","show","_checkScrollTimer","setTimeout","_","dragEvent","mouseDragFactory","e","button","is","currentTarget","getDataset","type","preventDefault","hasDescendent","getPosition","setDataset","uiDragging","_startIndex","index","_currentIndex","triggerEvent","detail","target","addClass","nearestSortable","connected","filter","sortable","init","length","nearestTo","offset","nearestItems","isSame","nearestItem","_updateTarget","newIndex","removeClass","removeDataset","clearTimeout","addEventDelegate","addEvent","elements","nearestCenter","center","targetCenter","method","initComponent"],"sources":["../src/sortable.js","../src/index.js","../src/prototype/helpers.js","../src/prototype/events.js"],"sourcesContent":["import $ from '@fr0st/query';\nimport { BaseComponent } from '@fr0st/ui';\n\n/**\n * Sortable Class\n * @class\n */\nexport default class Sortable extends BaseComponent {\n /**\n * New Sortable constructor.\n * @param {HTMLElement} node The input node.\n * @param {object} [options] The options to create the Sortable with.\n */\n constructor(node, options) {\n super(node, options);\n\n this._selector = this._options.items;\n if (this._options.handle) {\n this._selector += ' ' + this._options.handle;\n }\n\n this._enabled = !this._options.disabled;\n\n this._refreshCursors();\n this._events();\n }\n\n /**\n * Disable the Sortable.\n */\n disable() {\n this._enabled = false;\n }\n\n /**\n * Dispose the Sortable.\n */\n dispose() {\n $.removeEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable');\n $.removeEvent(this._node, 'receive.ui.sortable');\n\n this._target = null;\n this._currentSortable = null;\n\n super.dispose();\n }\n\n /**\n * Enable the Sortable.\n */\n enable() {\n this._enabled = true;\n }\n\n /**\n * Get the Sortable item elements.\n * @return {array} The Sortable item elements.\n */\n items() {\n return $.find(this._options.items, this._node);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\nimport { _events } from './prototype/events.js';\nimport { _checkScroll, _refreshCursors, _updateTarget } from './prototype/helpers.js';\n\n// Sortable default options\nSortable.defaults = {\n appendTo: 'body',\n axis: null,\n cancel: 'input, textarea, button, select, option',\n connectWith: null,\n cursor: 'auto',\n disabled: false,\n dropOnEmpty: true,\n handle: null,\n helperClass: 'bg-body-tertiary',\n items: ':scope > li',\n scroll: true,\n scrollSensitivity: 20,\n scrollSpeed: 5,\n};\n\n// Sortable prototype\nconst proto = Sortable.prototype;\n\nproto._checkScroll = _checkScroll;\nproto._events = _events;\nproto._refreshCursors = _refreshCursors;\nproto._updateTarget = _updateTarget;\n\n// Sortable init\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n","import $ from '@fr0st/query';\n\n/**\n * Check for window scroll.\n */\nexport function _checkScroll() {\n $.hide(this._target);\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n\n let offsetX = originalX;\n let offsetY = originalY;\n\n if (this._pos.y < originalY + this._options.scrollSensitivity) {\n offsetY = Math.max(0, originalY - this._options.scrollSpeed);\n } else if (this._pos.y > originalY + $.height(window) - this._options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n offsetY = Math.min(docHeight, originalY + this._options.scrollSpeed);\n }\n\n if (this._pos.x < originalX + this._options.scrollSensitivity) {\n offsetX = Math.max(0, originalX - this._options.scrollSpeed);\n } else if (this._pos.x > originalX + $.width(window) - this._options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n offsetX = Math.min(docWidth, originalX + this._options.scrollSpeed);\n }\n\n if (offsetX !== originalX || offsetY !== originalY) {\n $.setStyle(':root', { scrollBehavior: 'initial' });\n $.setScroll(document, offsetX, offsetY);\n $.setStyle(':root', { scrollBehavior: '' });\n\n this._pos.x += offsetX - originalX;\n this._pos.y += offsetY - originalY;\n }\n\n $.show(this._target);\n\n this._checkScrollTimer = setTimeout((_) => {\n this._checkScroll();\n }, 0);\n};\n\n/**\n * Refresh Sortable item cursors.\n */\nexport function _refreshCursors() {\n const elements = $.find(this._selector, this._node);\n\n $.setStyle(elements, { cursor: this._options.cursor });\n};\n\n/**\n * Update the target element.\n * @param {HTMLElement} nearestItem The current nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n */\nexport function _updateTarget(nearestItem, x, y) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const targetCenter = $.center(this._target, { offset: true });\n\n let method;\n if (this._options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n method = y < nearestCenter.y ?\n 'before' :\n 'after';\n } else if (this._options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n method = x < nearestCenter.x ?\n 'before' :\n 'after';\n } else {\n method = x < nearestCenter.x && y < nearestCenter.y ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this._target);\n};\n","import $ from '@fr0st/query';\nimport { getPosition } from '@fr0st/ui';\n\n/**\n * Attach events for the Sortable.\n */\nexport function _events() {\n const downEvent = (e) => {\n if (\n e.button ||\n !this._enabled ||\n $.is(e.currentTarget, this._options.cancel) ||\n $.getDataset(this._node, 'uiDragging')\n ) {\n return false;\n }\n\n if (e.type === 'mousedown') {\n e.preventDefault();\n }\n\n this._target = this._options.handle ?\n this.items().find((node) => $.hasDescendent(node, e.currentTarget)) :\n e.currentTarget;\n };\n\n const moveEvent = (e) => {\n this._pos = getPosition(e);\n\n if (!$.getDataset(this._node, 'uiDragging')) {\n $.setDataset(this._node, { uiDragging: true });\n\n this._startIndex = $.index(this._target);\n this._currentIndex = this._startIndex;\n\n $.triggerEvent(this._node, 'sort.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n\n if (this._options.helperClass) {\n $.addClass(this._target, this._options.helperClass);\n }\n\n this._currentSortable = this._node;\n\n if (this._options.scroll) {\n this._checkScroll();\n }\n }\n\n let nearestSortable = this._node;\n\n if (this._options.connectWith) {\n const connected = $.find(this._options.connectWith)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable._options.dropOnEmpty || sortable.items().length;\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo([this._node, ...connected], this._pos.x, this._pos.y, { offset: true });\n }\n }\n\n const nearestItems = $.isSame(this._node, nearestSortable) ?\n this.items() :\n this.constructor.init(nearestSortable).items();\n\n const nearestItem = $.nearestTo(nearestItems, this._pos.x, this._pos.y, { offset: true });\n\n if (!nearestItem) {\n return;\n }\n\n this._updateTarget(nearestItem, this._pos.x, this._pos.y);\n\n const newIndex = $.index(this._target);\n\n if (!$.isSame(nearestSortable, this._currentSortable)) {\n $.triggerEvent(this._currentSortable, 'send.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n\n $.triggerEvent(nearestSortable, 'receive.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n } else if (this._currentIndex !== newIndex) {\n $.triggerEvent(nearestSortable, 'sorting.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n }\n\n this._currentIndex = newIndex;\n this._currentSortable = nearestSortable;\n };\n\n const upEvent = (e) => {\n if (!$.getDataset(this._node, 'uiDragging')) {\n this._target = null;\n return;\n }\n\n if (e.type === 'mouseup') {\n e.preventDefault();\n }\n\n $.triggerEvent(this._currentSortable, 'sorted.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n\n if (this._options.helperClass) {\n $.removeClass(this._target, this._options.helperClass);\n }\n\n if (this._currentIndex !== this._startIndex || !$.isSame(this._currentSortable, this._node)) {\n $.triggerEvent(this._currentSortable, 'update.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n }\n\n $.removeDataset(this._node, 'uiDragging');\n\n if (this._checkScrollTimer) {\n clearTimeout(this._checkScrollTimer);\n this._checkScrollTimer = null;\n }\n\n this._target = null;\n this._currentSortable = null;\n this._currentIndex = null;\n this._startIndex = null;\n };\n\n const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);\n\n $.addEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable', this._selector, dragEvent);\n\n $.addEvent(this._node, 'receive.ui.sortable', (_) => {\n this._refreshCursors();\n });\n};\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "@fr0st/ui-sortable",
3
+ "version": "2.0.0",
4
+ "description": "FrostUI-Sortable is a free, open-source Sortable component for Javascript.",
5
+ "keywords": [
6
+ "ui",
7
+ "component",
8
+ "sortable",
9
+ "front-end",
10
+ "web"
11
+ ],
12
+ "homepage": "https://github.com/elusivecodes/FrostUI-Sortable",
13
+ "bugs": {
14
+ "url": "https://github.com/elusivecodes/FrostUI-Sortable/issues",
15
+ "email": "elusivecodes@gmail.com"
16
+ },
17
+ "main": "src/index.js",
18
+ "type": "module",
19
+ "files": [
20
+ "dist",
21
+ "/LICENSE",
22
+ "/README.md",
23
+ "src"
24
+ ],
25
+ "scripts": {
26
+ "build": "npm run js-compile && npm run js-minify",
27
+ "js-compile": "rollup --config",
28
+ "js-lint": "eslint --ext .js .",
29
+ "js-minify": "terser --compress passes=2 --mangle --source-map \"content=dist/frost-ui-sortable.js.map\" --output dist/frost-ui-sortable.min.js dist/frost-ui-sortable.js"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/elusivecodes/FrostUI-Sortable.git"
34
+ },
35
+ "author": "Elusive",
36
+ "license": "MIT",
37
+ "devDependencies": {
38
+ "@rollup/plugin-node-resolve": "^15.0.2",
39
+ "eslint": "^8.41.0",
40
+ "eslint-config-google": "^0.14.0",
41
+ "rollup": "^3.23.0",
42
+ "terser": "^5.17.6"
43
+ }
44
+ }
package/src/index.js ADDED
@@ -0,0 +1,34 @@
1
+ import { initComponent } from '@fr0st/ui';
2
+ import Sortable from './sortable.js';
3
+ import { _events } from './prototype/events.js';
4
+ import { _checkScroll, _refreshCursors, _updateTarget } from './prototype/helpers.js';
5
+
6
+ // Sortable default options
7
+ Sortable.defaults = {
8
+ appendTo: 'body',
9
+ axis: null,
10
+ cancel: 'input, textarea, button, select, option',
11
+ connectWith: null,
12
+ cursor: 'auto',
13
+ disabled: false,
14
+ dropOnEmpty: true,
15
+ handle: null,
16
+ helperClass: 'bg-body-tertiary',
17
+ items: ':scope > li',
18
+ scroll: true,
19
+ scrollSensitivity: 20,
20
+ scrollSpeed: 5,
21
+ };
22
+
23
+ // Sortable prototype
24
+ const proto = Sortable.prototype;
25
+
26
+ proto._checkScroll = _checkScroll;
27
+ proto._events = _events;
28
+ proto._refreshCursors = _refreshCursors;
29
+ proto._updateTarget = _updateTarget;
30
+
31
+ // Sortable init
32
+ initComponent('sortable', Sortable);
33
+
34
+ export default Sortable;
@@ -0,0 +1,154 @@
1
+ import $ from '@fr0st/query';
2
+ import { getPosition } from '@fr0st/ui';
3
+
4
+ /**
5
+ * Attach events for the Sortable.
6
+ */
7
+ export function _events() {
8
+ const downEvent = (e) => {
9
+ if (
10
+ e.button ||
11
+ !this._enabled ||
12
+ $.is(e.currentTarget, this._options.cancel) ||
13
+ $.getDataset(this._node, 'uiDragging')
14
+ ) {
15
+ return false;
16
+ }
17
+
18
+ if (e.type === 'mousedown') {
19
+ e.preventDefault();
20
+ }
21
+
22
+ this._target = this._options.handle ?
23
+ this.items().find((node) => $.hasDescendent(node, e.currentTarget)) :
24
+ e.currentTarget;
25
+ };
26
+
27
+ const moveEvent = (e) => {
28
+ this._pos = getPosition(e);
29
+
30
+ if (!$.getDataset(this._node, 'uiDragging')) {
31
+ $.setDataset(this._node, { uiDragging: true });
32
+
33
+ this._startIndex = $.index(this._target);
34
+ this._currentIndex = this._startIndex;
35
+
36
+ $.triggerEvent(this._node, 'sort.ui.sortable', {
37
+ detail: {
38
+ target: this._target,
39
+ },
40
+ });
41
+
42
+ if (this._options.helperClass) {
43
+ $.addClass(this._target, this._options.helperClass);
44
+ }
45
+
46
+ this._currentSortable = this._node;
47
+
48
+ if (this._options.scroll) {
49
+ this._checkScroll();
50
+ }
51
+ }
52
+
53
+ let nearestSortable = this._node;
54
+
55
+ if (this._options.connectWith) {
56
+ const connected = $.find(this._options.connectWith)
57
+ .filter((node) => {
58
+ const sortable = this.constructor.init(node);
59
+
60
+ return sortable._options.dropOnEmpty || sortable.items().length;
61
+ });
62
+
63
+ if (connected.length) {
64
+ nearestSortable = $.nearestTo([this._node, ...connected], this._pos.x, this._pos.y, { offset: true });
65
+ }
66
+ }
67
+
68
+ const nearestItems = $.isSame(this._node, nearestSortable) ?
69
+ this.items() :
70
+ this.constructor.init(nearestSortable).items();
71
+
72
+ const nearestItem = $.nearestTo(nearestItems, this._pos.x, this._pos.y, { offset: true });
73
+
74
+ if (!nearestItem) {
75
+ return;
76
+ }
77
+
78
+ this._updateTarget(nearestItem, this._pos.x, this._pos.y);
79
+
80
+ const newIndex = $.index(this._target);
81
+
82
+ if (!$.isSame(nearestSortable, this._currentSortable)) {
83
+ $.triggerEvent(this._currentSortable, 'send.ui.sortable', {
84
+ detail: {
85
+ target: this._target,
86
+ },
87
+ });
88
+
89
+ $.triggerEvent(nearestSortable, 'receive.ui.sortable', {
90
+ detail: {
91
+ target: this._target,
92
+ },
93
+ });
94
+ } else if (this._currentIndex !== newIndex) {
95
+ $.triggerEvent(nearestSortable, 'sorting.ui.sortable', {
96
+ detail: {
97
+ target: this._target,
98
+ },
99
+ });
100
+ }
101
+
102
+ this._currentIndex = newIndex;
103
+ this._currentSortable = nearestSortable;
104
+ };
105
+
106
+ const upEvent = (e) => {
107
+ if (!$.getDataset(this._node, 'uiDragging')) {
108
+ this._target = null;
109
+ return;
110
+ }
111
+
112
+ if (e.type === 'mouseup') {
113
+ e.preventDefault();
114
+ }
115
+
116
+ $.triggerEvent(this._currentSortable, 'sorted.ui.sortable', {
117
+ detail: {
118
+ target: this._target,
119
+ },
120
+ });
121
+
122
+ if (this._options.helperClass) {
123
+ $.removeClass(this._target, this._options.helperClass);
124
+ }
125
+
126
+ if (this._currentIndex !== this._startIndex || !$.isSame(this._currentSortable, this._node)) {
127
+ $.triggerEvent(this._currentSortable, 'update.ui.sortable', {
128
+ detail: {
129
+ target: this._target,
130
+ },
131
+ });
132
+ }
133
+
134
+ $.removeDataset(this._node, 'uiDragging');
135
+
136
+ if (this._checkScrollTimer) {
137
+ clearTimeout(this._checkScrollTimer);
138
+ this._checkScrollTimer = null;
139
+ }
140
+
141
+ this._target = null;
142
+ this._currentSortable = null;
143
+ this._currentIndex = null;
144
+ this._startIndex = null;
145
+ };
146
+
147
+ const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);
148
+
149
+ $.addEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable', this._selector, dragEvent);
150
+
151
+ $.addEvent(this._node, 'receive.ui.sortable', (_) => {
152
+ this._refreshCursors();
153
+ });
154
+ };
@@ -0,0 +1,80 @@
1
+ import $ from '@fr0st/query';
2
+
3
+ /**
4
+ * Check for window scroll.
5
+ */
6
+ export function _checkScroll() {
7
+ $.hide(this._target);
8
+
9
+ const originalX = $.getScrollX(window);
10
+ const originalY = $.getScrollY(window);
11
+
12
+ let offsetX = originalX;
13
+ let offsetY = originalY;
14
+
15
+ if (this._pos.y < originalY + this._options.scrollSensitivity) {
16
+ offsetY = Math.max(0, originalY - this._options.scrollSpeed);
17
+ } else if (this._pos.y > originalY + $.height(window) - this._options.scrollSensitivity) {
18
+ const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });
19
+ offsetY = Math.min(docHeight, originalY + this._options.scrollSpeed);
20
+ }
21
+
22
+ if (this._pos.x < originalX + this._options.scrollSensitivity) {
23
+ offsetX = Math.max(0, originalX - this._options.scrollSpeed);
24
+ } else if (this._pos.x > originalX + $.width(window) - this._options.scrollSensitivity) {
25
+ const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });
26
+ offsetX = Math.min(docWidth, originalX + this._options.scrollSpeed);
27
+ }
28
+
29
+ if (offsetX !== originalX || offsetY !== originalY) {
30
+ $.setStyle(':root', { scrollBehavior: 'initial' });
31
+ $.setScroll(document, offsetX, offsetY);
32
+ $.setStyle(':root', { scrollBehavior: '' });
33
+
34
+ this._pos.x += offsetX - originalX;
35
+ this._pos.y += offsetY - originalY;
36
+ }
37
+
38
+ $.show(this._target);
39
+
40
+ this._checkScrollTimer = setTimeout((_) => {
41
+ this._checkScroll();
42
+ }, 0);
43
+ };
44
+
45
+ /**
46
+ * Refresh Sortable item cursors.
47
+ */
48
+ export function _refreshCursors() {
49
+ const elements = $.find(this._selector, this._node);
50
+
51
+ $.setStyle(elements, { cursor: this._options.cursor });
52
+ };
53
+
54
+ /**
55
+ * Update the target element.
56
+ * @param {HTMLElement} nearestItem The current nearest item.
57
+ * @param {number} x The mouse X position.
58
+ * @param {number} y The mouse Y position.
59
+ */
60
+ export function _updateTarget(nearestItem, x, y) {
61
+ const nearestCenter = $.center(nearestItem, { offset: true });
62
+ const targetCenter = $.center(this._target, { offset: true });
63
+
64
+ let method;
65
+ if (this._options.axis === 'y' || nearestCenter.x === targetCenter.x) {
66
+ method = y < nearestCenter.y ?
67
+ 'before' :
68
+ 'after';
69
+ } else if (this._options.axis === 'x' || nearestCenter.y === targetCenter.y) {
70
+ method = x < nearestCenter.x ?
71
+ 'before' :
72
+ 'after';
73
+ } else {
74
+ method = x < nearestCenter.x && y < nearestCenter.y ?
75
+ 'before' :
76
+ 'after';
77
+ }
78
+
79
+ $[method](nearestItem, this._target);
80
+ };
@@ -0,0 +1,62 @@
1
+ import $ from '@fr0st/query';
2
+ import { BaseComponent } from '@fr0st/ui';
3
+
4
+ /**
5
+ * Sortable Class
6
+ * @class
7
+ */
8
+ export default class Sortable extends BaseComponent {
9
+ /**
10
+ * New Sortable constructor.
11
+ * @param {HTMLElement} node The input node.
12
+ * @param {object} [options] The options to create the Sortable with.
13
+ */
14
+ constructor(node, options) {
15
+ super(node, options);
16
+
17
+ this._selector = this._options.items;
18
+ if (this._options.handle) {
19
+ this._selector += ' ' + this._options.handle;
20
+ }
21
+
22
+ this._enabled = !this._options.disabled;
23
+
24
+ this._refreshCursors();
25
+ this._events();
26
+ }
27
+
28
+ /**
29
+ * Disable the Sortable.
30
+ */
31
+ disable() {
32
+ this._enabled = false;
33
+ }
34
+
35
+ /**
36
+ * Dispose the Sortable.
37
+ */
38
+ dispose() {
39
+ $.removeEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable');
40
+ $.removeEvent(this._node, 'receive.ui.sortable');
41
+
42
+ this._target = null;
43
+ this._currentSortable = null;
44
+
45
+ super.dispose();
46
+ }
47
+
48
+ /**
49
+ * Enable the Sortable.
50
+ */
51
+ enable() {
52
+ this._enabled = true;
53
+ }
54
+
55
+ /**
56
+ * Get the Sortable item elements.
57
+ * @return {array} The Sortable item elements.
58
+ */
59
+ items() {
60
+ return $.find(this._options.items, this._node);
61
+ }
62
+ }
package/src/wrapper.js ADDED
@@ -0,0 +1,3 @@
1
+ import Sortable from './index.js';
2
+
3
+ export { Sortable };