@fr0st/ui-sortable 3.0.1 → 3.0.3
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/dist/frost-ui-sortable.esm.js +15 -20
- package/dist/frost-ui-sortable.esm.js.map +1 -1
- package/dist/frost-ui-sortable.esm.min.js +1 -1
- package/dist/frost-ui-sortable.esm.min.js.map +1 -1
- package/dist/frost-ui-sortable.js +18 -24
- package/dist/frost-ui-sortable.js.map +1 -1
- package/dist/frost-ui-sortable.min.js +1 -1
- package/dist/frost-ui-sortable.min.js.map +1 -1
- package/package.json +12 -7
- package/src/sortable.js +14 -16
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseComponent, getPosition, initComponent } from "@fr0st/ui";
|
|
2
2
|
import $ from "@fr0st/query";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
// src/helpers.js
|
|
5
5
|
/** @import { SortableEventData } from './sortable.js'; */
|
|
6
6
|
var cursorLocks = /* @__PURE__ */ new WeakMap();
|
|
7
7
|
/**
|
|
@@ -41,8 +41,7 @@ function triggerSortableEvent(node, name, data) {
|
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
//#region src/sortable.js
|
|
44
|
+
// src/sortable.js
|
|
46
45
|
var document = $.getContext();
|
|
47
46
|
var window = $.getWindow();
|
|
48
47
|
/** @typedef {'x'|'y'} SortableAxis */
|
|
@@ -92,15 +91,15 @@ var Sortable = class extends BaseComponent {
|
|
|
92
91
|
swapThreshold: .25
|
|
93
92
|
};
|
|
94
93
|
#currentIndex;
|
|
95
|
-
#currentSortable;
|
|
94
|
+
#currentSortable = null;
|
|
96
95
|
#dragging;
|
|
97
96
|
#enabled;
|
|
98
97
|
#initialCursorNodes = [];
|
|
99
|
-
#pos;
|
|
100
|
-
#scrollFrame;
|
|
98
|
+
#pos = null;
|
|
99
|
+
#scrollFrame = null;
|
|
101
100
|
#selector;
|
|
102
101
|
#startIndex;
|
|
103
|
-
#target;
|
|
102
|
+
#target = null;
|
|
104
103
|
/**
|
|
105
104
|
* Creates a Sortable.
|
|
106
105
|
* @param {HTMLElement} node The sortable container.
|
|
@@ -130,8 +129,6 @@ var Sortable = class extends BaseComponent {
|
|
|
130
129
|
/** @inheritdoc */
|
|
131
130
|
dispose() {
|
|
132
131
|
if (!this.node) return;
|
|
133
|
-
$.removeEventDelegate(this.node, "mousedown.ui.sortable touchstart.ui.sortable");
|
|
134
|
-
$.removeEvent(this.node, "receive.ui.sortable");
|
|
135
132
|
resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));
|
|
136
133
|
if (this.#target && this.options.helperClass) $.removeClass(this.#target, this.options.helperClass);
|
|
137
134
|
this.#resetDrag();
|
|
@@ -192,13 +189,13 @@ var Sortable = class extends BaseComponent {
|
|
|
192
189
|
* Attaches events for the Sortable.
|
|
193
190
|
*/
|
|
194
191
|
#events() {
|
|
195
|
-
const
|
|
192
|
+
const downHandler = (event) => {
|
|
196
193
|
const cancelled = this.options.cancel && ($.is(event.target, this.options.cancel) || $.is(event.currentTarget, this.options.cancel) || $.closest(event.target, this.options.cancel, this.node).length);
|
|
197
194
|
if (event.button || !this.#enabled || cancelled || $.getDataset(this.node, "uiDragging")) return false;
|
|
198
195
|
this.#target = this.options.handle ? this.items().find((node) => $.hasDescendent(node, event.currentTarget)) : event.currentTarget;
|
|
199
196
|
if (!this.#target) return false;
|
|
200
197
|
};
|
|
201
|
-
const
|
|
198
|
+
const moveHandler = (event) => {
|
|
202
199
|
if (!this.node || !this.#target) return;
|
|
203
200
|
const previousPos = this.#pos;
|
|
204
201
|
this.#pos = getPosition(event);
|
|
@@ -225,7 +222,7 @@ var Sortable = class extends BaseComponent {
|
|
|
225
222
|
this.#updatePlacement(deltaX, deltaY);
|
|
226
223
|
this.#scheduleScroll();
|
|
227
224
|
};
|
|
228
|
-
const
|
|
225
|
+
const upHandler = (event) => {
|
|
229
226
|
if (!this.node) return;
|
|
230
227
|
if (!this.#dragging) {
|
|
231
228
|
this.#target = null;
|
|
@@ -251,9 +248,9 @@ var Sortable = class extends BaseComponent {
|
|
|
251
248
|
} else if (this.#currentIndex !== this.#startIndex) triggerSortableEvent(destination, "update", eventData);
|
|
252
249
|
if (this.node) this.#resetDrag();
|
|
253
250
|
};
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
251
|
+
const dragHandler = $.mouseDragFactory(downHandler, moveHandler, upHandler);
|
|
252
|
+
this.listen(this.node, "mousedown.ui.sortable touchstart.ui.sortable", dragHandler, { delegate: this.#selector });
|
|
253
|
+
this.listen(this.node, "receive.ui.sortable", () => {
|
|
257
254
|
setCursor($.find(this.#selector, this.node), this.options.cursor);
|
|
258
255
|
});
|
|
259
256
|
}
|
|
@@ -261,7 +258,7 @@ var Sortable = class extends BaseComponent {
|
|
|
261
258
|
* Resets the active drag state.
|
|
262
259
|
*/
|
|
263
260
|
#resetDrag() {
|
|
264
|
-
if (this.#scrollFrame !== null
|
|
261
|
+
if (this.#scrollFrame !== null) window.cancelAnimationFrame(this.#scrollFrame);
|
|
265
262
|
if (this.#dragging && this.node) $.removeDataset(this.node, "uiDragging");
|
|
266
263
|
this.#currentIndex = null;
|
|
267
264
|
this.#currentSortable = null;
|
|
@@ -275,7 +272,7 @@ var Sortable = class extends BaseComponent {
|
|
|
275
272
|
* Schedules the next auto-scroll update.
|
|
276
273
|
*/
|
|
277
274
|
#scheduleScroll() {
|
|
278
|
-
if (!this.node || !this.options.scroll || !this.#dragging || this.#scrollFrame !== null
|
|
275
|
+
if (!this.node || !this.options.scroll || !this.#dragging || this.#scrollFrame !== null) return;
|
|
279
276
|
this.#scrollFrame = window.requestAnimationFrame(() => {
|
|
280
277
|
this.#checkScroll();
|
|
281
278
|
});
|
|
@@ -360,11 +357,9 @@ var Sortable = class extends BaseComponent {
|
|
|
360
357
|
}
|
|
361
358
|
};
|
|
362
359
|
|
|
363
|
-
|
|
364
|
-
//#region src/index.js
|
|
360
|
+
// src/index.js
|
|
365
361
|
initComponent("sortable", Sortable);
|
|
366
362
|
var src_default = Sortable;
|
|
367
363
|
|
|
368
|
-
//#endregion
|
|
369
364
|
export { src_default as default };
|
|
370
365
|
//# sourceMappingURL=frost-ui-sortable.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frost-ui-sortable.esm.js","names":[],"sources":["../src/helpers.js","../src/sortable.js","../src/index.js"],"sourcesContent":["/** @import { SortableEventData } from './sortable.js'; */\n\nimport $ from '@fr0st/query';\n\nconst cursorLocks = new WeakMap();\n\n/**\n * Resets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to restore.\n */\nexport function resetCursor(nodes) {\n for (const node of nodes) {\n const release = cursorLocks.get(node);\n\n if (!release) {\n continue;\n }\n\n release();\n cursorLocks.delete(node);\n }\n}\n\n/**\n * Sets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to update.\n * @param {string} cursor The cursor style.\n */\nexport function setCursor(nodes, cursor) {\n for (const node of nodes) {\n if (cursorLocks.has(node)) {\n $.setStyle(node, { cursor });\n } else {\n cursorLocks.set(node, $.setStyleLock(node, 'cursor', cursor));\n }\n }\n}\n\n/**\n * Triggers a Sortable event with its data and detail payloads.\n * @param {HTMLElement} node The event target.\n * @param {string} name The event name without its namespace.\n * @param {SortableEventData} data The sorting event data.\n */\nexport function triggerSortableEvent(node, name, data) {\n $.triggerEvent(node, `${name}.ui.sortable`, {\n data,\n detail: {\n target: data.item,\n ...data,\n },\n });\n}\n","import $ from '@fr0st/query';\nimport { BaseComponent, getPosition } from '@fr0st/ui';\nimport { resetCursor, setCursor, triggerSortableEvent } from './helpers.js';\n\nconst document = $.getContext();\nconst window = $.getWindow();\n\n/** @typedef {'x'|'y'} SortableAxis */\n\n/**\n * @typedef {object} SortableOptions\n * @property {SortableAxis|null} [axis=null] The axis used to determine item placement.\n * @property {string} [cancel='input, textarea, button, select, option'] The selector for elements that cannot start a sort.\n * @property {string|null} [connectWith=null] The selector for connected Sortable containers.\n * @property {string} [cursor='auto'] The cursor applied to sortable items or handles.\n * @property {boolean} [disabled=false] Whether sorting is initially disabled.\n * @property {boolean} [dropOnEmpty=true] Whether connected empty containers accept items.\n * @property {string|null} [handle=null] The handle selector within each sortable item.\n * @property {string|null} [helperClass='bg-body-tertiary'] The class applied to an item while it is being sorted.\n * @property {string} [items=':scope > li'] The selector for sortable items.\n * @property {boolean} [scroll=true] Whether to scroll the window while sorting near an edge.\n * @property {number} [scrollSensitivity=20] The distance from a window edge that starts scrolling, in pixels.\n * @property {number} [scrollSpeed=5] The scroll distance applied per animation frame, in pixels.\n * @property {number} [swapThreshold=0.25] The fraction of an item crossed before swapping, from `0` to `1`.\n */\n\n/**\n * @typedef {object} SortableEventData\n * @property {HTMLElement} item The item being sorted.\n * @property {HTMLElement} from The previous or original Sortable container.\n * @property {HTMLElement} to The next or final Sortable container.\n * @property {number} oldIndex The previous or original item index.\n * @property {number} newIndex The next or final item index.\n */\n\n/**\n * Controls a sortable collection of elements.\n * @augments {BaseComponent<SortableOptions>}\n */\nexport default class Sortable extends BaseComponent {\n /** @type {SortableOptions} */\n static defaults = {\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 swapThreshold: 0.25,\n };\n\n #currentIndex;\n #currentSortable;\n #dragging;\n #enabled;\n #initialCursorNodes = [];\n #pos;\n #scrollFrame;\n #selector;\n #startIndex;\n #target;\n\n /**\n * Creates a Sortable.\n * @param {HTMLElement} node The sortable container.\n * @param {SortableOptions} [options] The Sortable options.\n */\n constructor(node, options) {\n super(node, options);\n\n try {\n this.#selector = this.options.handle ?\n `:is(${this.options.items}) :is(${this.options.handle})` :\n this.options.items;\n\n this.#dragging = false;\n this.#enabled = !this.options.disabled;\n\n this.#initialCursorNodes = $.find(this.#selector, this.node);\n setCursor(this.#initialCursorNodes, this.options.cursor);\n this.#events();\n this.#initialCursorNodes = null;\n } catch (error) {\n this.dispose();\n throw error;\n }\n }\n\n /**\n * Disables the Sortable.\n */\n disable() {\n this.#enabled = false;\n }\n\n /** @inheritdoc */\n dispose() {\n if (!this.node) {\n return;\n }\n\n $.removeEventDelegate(this.node, 'mousedown.ui.sortable touchstart.ui.sortable');\n $.removeEvent(this.node, 'receive.ui.sortable');\n resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));\n\n if (this.#target && this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n this.#resetDrag();\n\n this.#initialCursorNodes = null;\n\n super.dispose();\n }\n\n /**\n * Enables the Sortable.\n */\n enable() {\n this.#enabled = true;\n }\n\n /**\n * Gets the Sortable item elements.\n * @returns {HTMLElement[]} The Sortable item elements.\n */\n items() {\n return $.find(this.options.items, this.node);\n }\n\n /**\n * Checks whether the window should scroll while sorting.\n */\n #checkScroll() {\n this.#scrollFrame = null;\n\n if (!this.node || !this.#dragging || !this.#target || !this.#pos) {\n return;\n }\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n const windowHeight = $.height(window);\n const windowWidth = $.width(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 + windowHeight - this.options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n const maxY = Math.max(0, docHeight - windowHeight);\n offsetY = Math.min(maxY, 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 + windowWidth - this.options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n const maxX = Math.max(0, docWidth - windowWidth);\n offsetX = Math.min(maxX, originalX + this.options.scrollSpeed);\n }\n\n if (offsetX === originalX && offsetY === originalY) {\n return;\n }\n\n window.scrollTo({\n left: offsetX,\n top: offsetY,\n behavior: 'instant',\n });\n\n const deltaX = offsetX - originalX;\n const deltaY = offsetY - originalY;\n\n this.#pos.x += deltaX;\n this.#pos.y += deltaY;\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n }\n\n /**\n * Attaches events for the Sortable.\n */\n #events() {\n const downEvent = (event) => {\n const cancelled = this.options.cancel &&\n (\n $.is(event.target, this.options.cancel) ||\n $.is(event.currentTarget, this.options.cancel) ||\n $.closest(event.target, this.options.cancel, this.node).length\n );\n\n if (\n event.button ||\n !this.#enabled ||\n cancelled ||\n $.getDataset(this.node, 'uiDragging')\n ) {\n return false;\n }\n\n this.#target = this.options.handle ?\n this.items().find((node) => $.hasDescendent(node, event.currentTarget)) :\n event.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveEvent = (event) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(event);\n const deltaX = previousPos ?\n this.#pos.x - previousPos.x :\n 0;\n const deltaY = previousPos ?\n this.#pos.y - previousPos.y :\n 0;\n\n if (!this.#dragging) {\n this.#dragging = true;\n this.#currentSortable = this.node;\n this.#startIndex = this.items().indexOf(this.#target);\n this.#currentIndex = this.#startIndex;\n\n $.setDataset(this.node, { uiDragging: true });\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: this.node,\n to: this.node,\n oldIndex: this.#startIndex,\n newIndex: this.#startIndex,\n };\n\n triggerSortableEvent(this.node, 'sort', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.addClass(this.#target, this.options.helperClass);\n }\n }\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n };\n\n const upEvent = (event) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (event.type === 'mouseup') {\n event.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);\n\n $.addEventDelegate(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n this.#selector,\n dragEvent,\n );\n\n $.addEvent(this.node, 'receive.ui.sortable', () => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null && this.#scrollFrame !== undefined) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null && this.#scrollFrame !== undefined\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame(() => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"frost-ui-sortable.esm.js","names":[],"sources":["../src/helpers.js","../src/sortable.js","../src/index.js"],"sourcesContent":["/** @import { SortableEventData } from './sortable.js'; */\n\nimport $ from '@fr0st/query';\n\nconst cursorLocks = new WeakMap();\n\n/**\n * Resets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to restore.\n */\nexport function resetCursor(nodes) {\n for (const node of nodes) {\n const release = cursorLocks.get(node);\n\n if (!release) {\n continue;\n }\n\n release();\n cursorLocks.delete(node);\n }\n}\n\n/**\n * Sets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to update.\n * @param {string} cursor The cursor style.\n */\nexport function setCursor(nodes, cursor) {\n for (const node of nodes) {\n if (cursorLocks.has(node)) {\n $.setStyle(node, { cursor });\n } else {\n cursorLocks.set(node, $.setStyleLock(node, 'cursor', cursor));\n }\n }\n}\n\n/**\n * Triggers a Sortable event with its data and detail payloads.\n * @param {HTMLElement} node The event target.\n * @param {string} name The event name without its namespace.\n * @param {SortableEventData} data The sorting event data.\n */\nexport function triggerSortableEvent(node, name, data) {\n $.triggerEvent(node, `${name}.ui.sortable`, {\n data,\n detail: {\n target: data.item,\n ...data,\n },\n });\n}\n","import $ from '@fr0st/query';\nimport { BaseComponent, getPosition } from '@fr0st/ui';\nimport { resetCursor, setCursor, triggerSortableEvent } from './helpers.js';\n\nconst document = $.getContext();\nconst window = $.getWindow();\n\n/** @typedef {'x'|'y'} SortableAxis */\n\n/**\n * @typedef {object} SortableOptions\n * @property {SortableAxis|null} [axis=null] The axis used to determine item placement.\n * @property {string} [cancel='input, textarea, button, select, option'] The selector for elements that cannot start a sort.\n * @property {string|null} [connectWith=null] The selector for connected Sortable containers.\n * @property {string} [cursor='auto'] The cursor applied to sortable items or handles.\n * @property {boolean} [disabled=false] Whether sorting is initially disabled.\n * @property {boolean} [dropOnEmpty=true] Whether connected empty containers accept items.\n * @property {string|null} [handle=null] The handle selector within each sortable item.\n * @property {string|null} [helperClass='bg-body-tertiary'] The class applied to an item while it is being sorted.\n * @property {string} [items=':scope > li'] The selector for sortable items.\n * @property {boolean} [scroll=true] Whether to scroll the window while sorting near an edge.\n * @property {number} [scrollSensitivity=20] The distance from a window edge that starts scrolling, in pixels.\n * @property {number} [scrollSpeed=5] The scroll distance applied per animation frame, in pixels.\n * @property {number} [swapThreshold=0.25] The fraction of an item crossed before swapping, from `0` to `1`.\n */\n\n/**\n * @typedef {object} SortableEventData\n * @property {HTMLElement} item The item being sorted.\n * @property {HTMLElement} from The previous or original Sortable container.\n * @property {HTMLElement} to The next or final Sortable container.\n * @property {number} oldIndex The previous or original item index.\n * @property {number} newIndex The next or final item index.\n */\n\n/**\n * Controls a sortable collection of elements.\n * @augments {BaseComponent<SortableOptions>}\n */\nexport default class Sortable extends BaseComponent {\n /** @type {SortableOptions} */\n static defaults = {\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 swapThreshold: 0.25,\n };\n\n #currentIndex;\n #currentSortable = null;\n #dragging;\n #enabled;\n #initialCursorNodes = [];\n #pos = null;\n #scrollFrame = null;\n #selector;\n #startIndex;\n #target = null;\n\n /**\n * Creates a Sortable.\n * @param {HTMLElement} node The sortable container.\n * @param {SortableOptions} [options] The Sortable options.\n */\n constructor(node, options) {\n super(node, options);\n\n try {\n this.#selector = this.options.handle ?\n `:is(${this.options.items}) :is(${this.options.handle})` :\n this.options.items;\n\n this.#dragging = false;\n this.#enabled = !this.options.disabled;\n\n this.#initialCursorNodes = $.find(this.#selector, this.node);\n setCursor(this.#initialCursorNodes, this.options.cursor);\n this.#events();\n this.#initialCursorNodes = null;\n } catch (error) {\n this.dispose();\n throw error;\n }\n }\n\n /**\n * Disables the Sortable.\n */\n disable() {\n this.#enabled = false;\n }\n\n /** @inheritdoc */\n dispose() {\n if (!this.node) {\n return;\n }\n\n resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));\n\n if (this.#target && this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n this.#resetDrag();\n\n this.#initialCursorNodes = null;\n\n super.dispose();\n }\n\n /**\n * Enables the Sortable.\n */\n enable() {\n this.#enabled = true;\n }\n\n /**\n * Gets the Sortable item elements.\n * @returns {HTMLElement[]} The Sortable item elements.\n */\n items() {\n return $.find(this.options.items, this.node);\n }\n\n /**\n * Checks whether the window should scroll while sorting.\n */\n #checkScroll() {\n this.#scrollFrame = null;\n\n if (!this.node || !this.#dragging || !this.#target || !this.#pos) {\n return;\n }\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n const windowHeight = $.height(window);\n const windowWidth = $.width(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 + windowHeight - this.options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n const maxY = Math.max(0, docHeight - windowHeight);\n offsetY = Math.min(maxY, 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 + windowWidth - this.options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n const maxX = Math.max(0, docWidth - windowWidth);\n offsetX = Math.min(maxX, originalX + this.options.scrollSpeed);\n }\n\n if (offsetX === originalX && offsetY === originalY) {\n return;\n }\n\n window.scrollTo({\n left: offsetX,\n top: offsetY,\n behavior: 'instant',\n });\n\n const deltaX = offsetX - originalX;\n const deltaY = offsetY - originalY;\n\n this.#pos.x += deltaX;\n this.#pos.y += deltaY;\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n }\n\n /**\n * Attaches events for the Sortable.\n */\n #events() {\n const downHandler = (event) => {\n const cancelled = this.options.cancel &&\n (\n $.is(event.target, this.options.cancel) ||\n $.is(event.currentTarget, this.options.cancel) ||\n $.closest(event.target, this.options.cancel, this.node).length\n );\n\n if (\n event.button ||\n !this.#enabled ||\n cancelled ||\n $.getDataset(this.node, 'uiDragging')\n ) {\n return false;\n }\n\n this.#target = this.options.handle ?\n this.items().find((node) => $.hasDescendent(node, event.currentTarget)) :\n event.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveHandler = (event) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(event);\n const deltaX = previousPos ?\n this.#pos.x - previousPos.x :\n 0;\n const deltaY = previousPos ?\n this.#pos.y - previousPos.y :\n 0;\n\n if (!this.#dragging) {\n this.#dragging = true;\n this.#currentSortable = this.node;\n this.#startIndex = this.items().indexOf(this.#target);\n this.#currentIndex = this.#startIndex;\n\n $.setDataset(this.node, { uiDragging: true });\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: this.node,\n to: this.node,\n oldIndex: this.#startIndex,\n newIndex: this.#startIndex,\n };\n\n triggerSortableEvent(this.node, 'sort', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.addClass(this.#target, this.options.helperClass);\n }\n }\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n };\n\n const upHandler = (event) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (event.type === 'mouseup') {\n event.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragHandler = $.mouseDragFactory(downHandler, moveHandler, upHandler);\n\n this.listen(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n dragHandler,\n { delegate: this.#selector },\n );\n\n this.listen(this.node, 'receive.ui.sortable', () => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame(() => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{BaseComponent as e,getPosition as t,initComponent as n}from"@fr0st/ui";import r from"@fr0st/query";var i=/* @__PURE__ */ new WeakMap;function a(e){for(let t of e){let e=i.get(t);e&&(e(),i.delete(t))}}function o(e,t){for(let n of e)i.has(n)?r.setStyle(n,{cursor:t}):i.set(n,r.setStyleLock(n,`cursor`,t))}function s(e,t,n){r.triggerEvent(e,`${t}.ui.sortable`,{data:n,detail:{target:n.item,...n}})}var c=r.getContext(),l=r.getWindow(),u=class extends e{static defaults={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,swapThreshold:.25};#e;#t;#n;#r;#i=[];#a;#o;#s;#c;#l;constructor(e,t){super(e,t);try{this.#s=this.options.handle?`:is(${this.options.items}) :is(${this.options.handle})`:this.options.items,this.#n=!1,this.#r=!this.options.disabled,this.#i=r.find(this.#s,this.node),o(this.#i,this.options.cursor),this.#d(),this.#i=null}catch(e){throw this.dispose(),e}}disable(){this.#r=!1}dispose(){this.node&&(
|
|
1
|
+
import{BaseComponent as e,getPosition as t,initComponent as n}from"@fr0st/ui";import r from"@fr0st/query";var i=/* @__PURE__ */ new WeakMap;function a(e){for(let t of e){let e=i.get(t);e&&(e(),i.delete(t))}}function o(e,t){for(let n of e)i.has(n)?r.setStyle(n,{cursor:t}):i.set(n,r.setStyleLock(n,`cursor`,t))}function s(e,t,n){r.triggerEvent(e,`${t}.ui.sortable`,{data:n,detail:{target:n.item,...n}})}var c=r.getContext(),l=r.getWindow(),u=class extends e{static defaults={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,swapThreshold:.25};#e;#t=null;#n;#r;#i=[];#a=null;#o=null;#s;#c;#l=null;constructor(e,t){super(e,t);try{this.#s=this.options.handle?`:is(${this.options.items}) :is(${this.options.handle})`:this.options.items,this.#n=!1,this.#r=!this.options.disabled,this.#i=r.find(this.#s,this.node),o(this.#i,this.options.cursor),this.#d(),this.#i=null}catch(e){throw this.dispose(),e}}disable(){this.#r=!1}dispose(){this.node&&(a(this.#i??r.find(this.#s,this.node)),this.#l&&this.options.helperClass&&r.removeClass(this.#l,this.options.helperClass),this.#f(),this.#i=null,super.dispose())}enable(){this.#r=!0}items(){return r.find(this.options.items,this.node)}#u(){if(this.#o=null,!this.node||!this.#n||!this.#l||!this.#a)return;let e=r.getScrollX(l),t=r.getScrollY(l),n=r.height(l),i=r.width(l),a=e,o=t;if(this.#a.y<t+this.options.scrollSensitivity)o=Math.max(0,t-this.options.scrollSpeed);else if(this.#a.y>t+n-this.options.scrollSensitivity){let e=r.height(c,{boxSize:r.SCROLL_BOX}),i=Math.max(0,e-n);o=Math.min(i,t+this.options.scrollSpeed)}if(this.#a.x<e+this.options.scrollSensitivity)a=Math.max(0,e-this.options.scrollSpeed);else if(this.#a.x>e+i-this.options.scrollSensitivity){let t=r.width(c,{boxSize:r.SCROLL_BOX}),n=Math.max(0,t-i);a=Math.min(n,e+this.options.scrollSpeed)}if(a===e&&o===t)return;l.scrollTo({left:a,top:o,behavior:`instant`});let s=a-e,u=o-t;this.#a.x+=s,this.#a.y+=u,this.#m(s,u),this.#p()}#d(){let e=r.mouseDragFactory(e=>{let t=this.options.cancel&&(r.is(e.target,this.options.cancel)||r.is(e.currentTarget,this.options.cancel)||r.closest(e.target,this.options.cancel,this.node).length);if(e.button||!this.#r||t||r.getDataset(this.node,`uiDragging`)||(this.#l=this.options.handle?this.items().find(t=>r.hasDescendent(t,e.currentTarget)):e.currentTarget,!this.#l))return!1},e=>{if(!this.node||!this.#l)return;let n=this.#a;this.#a=t(e);let i=n?this.#a.x-n.x:0,a=n?this.#a.y-n.y:0;if(!this.#n){this.#n=!0,this.#t=this.node,this.#c=this.items().indexOf(this.#l),this.#e=this.#c,r.setDataset(this.node,{uiDragging:!0});let e={item:this.#l,from:this.node,to:this.node,oldIndex:this.#c,newIndex:this.#c};if(s(this.node,`sort`,e),!this.node)return;this.options.helperClass&&r.addClass(this.#l,this.options.helperClass)}this.#m(i,a),this.#p()},e=>{if(!this.node)return;if(!this.#n){this.#l=null;return}e.type===`mouseup`&&e.preventDefault();let t=this.node,n=this.#t,i={item:this.#l,from:t,to:n,oldIndex:this.#c,newIndex:this.#e};s(n,`sorted`,i),this.node&&(this.options.helperClass&&r.removeClass(this.#l,this.options.helperClass),t===n?this.#e!==this.#c&&s(n,`update`,i):(s(t,`update`,i),this.node&&s(n,`update`,i)),this.node&&this.#f())});this.listen(this.node,`mousedown.ui.sortable touchstart.ui.sortable`,e,{delegate:this.#s}),this.listen(this.node,`receive.ui.sortable`,()=>{o(r.find(this.#s,this.node),this.options.cursor)})}#f(){this.#o!==null&&l.cancelAnimationFrame(this.#o),this.#n&&this.node&&r.removeDataset(this.node,`uiDragging`),this.#e=null,this.#t=null,this.#n=!1,this.#a=null,this.#o=null,this.#c=null,this.#l=null}#p(){this.node&&this.options.scroll&&this.#n&&this.#o===null&&(this.#o=l.requestAnimationFrame(()=>{this.#u()}))}#m(e,t){let n=this.node;if(this.options.connectWith){let e=r.find(this.options.connectWith).filter(e=>e!==this.node).filter(e=>{let t=this.constructor.init(e);return t.#r&&(t.options.dropOnEmpty||t.items().length)});e.length&&(n=r.nearestTo([this.node,...e],this.#a.x,this.#a.y,{offset:!0}))}let i=this.constructor.init(n),o=i.items().filter(e=>e!==this.#l),c=r.nearestTo(o,this.#a.x,this.#a.y,{offset:!0});if(c)this.#h(c,this.#a.x,this.#a.y,e,t);else if(n!==this.#t)r.append(n,this.#l);else return;let l=i.items().indexOf(this.#l);if(n!==this.#t){let e=this.#t,{handle:t}=this.constructor.init(e).options;a(t?r.find(t,this.#l):[this.#l]);let i={item:this.#l,from:e,to:n,oldIndex:this.#e,newIndex:l};if(s(e,`send`,i),!this.node)return;s(n,`receive`,i)}else if(this.#e!==l){let e={item:this.#l,from:n,to:n,oldIndex:this.#e,newIndex:l};s(n,`sorting`,e)}this.node&&(this.#e=l,this.#t=n)}#h(e,t,n,i,a){let o=r.center(e,{offset:!0}),s=r.rect(e,{offset:!0}),c=r.center(this.#l,{offset:!0}),l=Math.min(1,Math.max(0,this.options.swapThreshold)),u=.5,d=.5;i&&(u=i>0?l:1-l),a&&(d=a>0?l:1-l);let f;if(this.options.axis===`y`||o.x===c.x)f=n<s.top+s.height*d?`before`:`after`;else if(this.options.axis===`x`||o.y===c.y)f=t<s.left+s.width*u?`before`:`after`;else{let e=s.left+s.width*u,r=s.top+s.height*d;f=t<e&&n<r?`before`:`after`}r[f](e,this.#l)}};n(`sortable`,u);var d=u;export{d as default};
|
|
2
2
|
//# sourceMappingURL=frost-ui-sortable.esm.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frost-ui-sortable.esm.min.js","names":["$","cursorLocks","resetCursor","node","nodes","release","setCursor","cursor","triggerSortableEvent","name","data","document","window","Sortable","BaseComponent","options","#selector","#dragging","#enabled","#initialCursorNodes","#events","error","#target","#resetDrag","#scrollFrame","#pos","originalX","originalY","windowHeight","windowWidth","offsetX","offsetY","docHeight","maxY","docWidth","maxX","deltaX","deltaY","#updatePlacement","#scheduleScroll","dragEvent","cancelled","event","previousPos","getPosition","#currentSortable","#startIndex","#currentIndex","eventData","source","destination","#checkScroll","nearestSortable","connected","sortable","nearestInstance","nearestItems","nearestItem","#updateTarget","newIndex","previousSortable","handle","nearestCenter","nearestRect","targetCenter","threshold","thresholdX","thresholdY","method","y","x","swapX","swapY","initComponent","src_default"],"sources":["../src/helpers.js","../src/sortable.js","../src/index.js"],"sourcesContent":["/** @import { SortableEventData } from './sortable.js'; */\n\nimport $ from '@fr0st/query';\n\nconst cursorLocks = new WeakMap();\n\n/**\n * Resets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to restore.\n */\nexport function resetCursor(nodes) {\n for (const node of nodes) {\n const release = cursorLocks.get(node);\n\n if (!release) {\n continue;\n }\n\n release();\n cursorLocks.delete(node);\n }\n}\n\n/**\n * Sets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to update.\n * @param {string} cursor The cursor style.\n */\nexport function setCursor(nodes, cursor) {\n for (const node of nodes) {\n if (cursorLocks.has(node)) {\n $.setStyle(node, { cursor });\n } else {\n cursorLocks.set(node, $.setStyleLock(node, 'cursor', cursor));\n }\n }\n}\n\n/**\n * Triggers a Sortable event with its data and detail payloads.\n * @param {HTMLElement} node The event target.\n * @param {string} name The event name without its namespace.\n * @param {SortableEventData} data The sorting event data.\n */\nexport function triggerSortableEvent(node, name, data) {\n $.triggerEvent(node, `${name}.ui.sortable`, {\n data,\n detail: {\n target: data.item,\n ...data,\n },\n });\n}\n","import $ from '@fr0st/query';\nimport { BaseComponent, getPosition } from '@fr0st/ui';\nimport { resetCursor, setCursor, triggerSortableEvent } from './helpers.js';\n\nconst document = $.getContext();\nconst window = $.getWindow();\n\n/** @typedef {'x'|'y'} SortableAxis */\n\n/**\n * @typedef {object} SortableOptions\n * @property {SortableAxis|null} [axis=null] The axis used to determine item placement.\n * @property {string} [cancel='input, textarea, button, select, option'] The selector for elements that cannot start a sort.\n * @property {string|null} [connectWith=null] The selector for connected Sortable containers.\n * @property {string} [cursor='auto'] The cursor applied to sortable items or handles.\n * @property {boolean} [disabled=false] Whether sorting is initially disabled.\n * @property {boolean} [dropOnEmpty=true] Whether connected empty containers accept items.\n * @property {string|null} [handle=null] The handle selector within each sortable item.\n * @property {string|null} [helperClass='bg-body-tertiary'] The class applied to an item while it is being sorted.\n * @property {string} [items=':scope > li'] The selector for sortable items.\n * @property {boolean} [scroll=true] Whether to scroll the window while sorting near an edge.\n * @property {number} [scrollSensitivity=20] The distance from a window edge that starts scrolling, in pixels.\n * @property {number} [scrollSpeed=5] The scroll distance applied per animation frame, in pixels.\n * @property {number} [swapThreshold=0.25] The fraction of an item crossed before swapping, from `0` to `1`.\n */\n\n/**\n * @typedef {object} SortableEventData\n * @property {HTMLElement} item The item being sorted.\n * @property {HTMLElement} from The previous or original Sortable container.\n * @property {HTMLElement} to The next or final Sortable container.\n * @property {number} oldIndex The previous or original item index.\n * @property {number} newIndex The next or final item index.\n */\n\n/**\n * Controls a sortable collection of elements.\n * @augments {BaseComponent<SortableOptions>}\n */\nexport default class Sortable extends BaseComponent {\n /** @type {SortableOptions} */\n static defaults = {\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 swapThreshold: 0.25,\n };\n\n #currentIndex;\n #currentSortable;\n #dragging;\n #enabled;\n #initialCursorNodes = [];\n #pos;\n #scrollFrame;\n #selector;\n #startIndex;\n #target;\n\n /**\n * Creates a Sortable.\n * @param {HTMLElement} node The sortable container.\n * @param {SortableOptions} [options] The Sortable options.\n */\n constructor(node, options) {\n super(node, options);\n\n try {\n this.#selector = this.options.handle ?\n `:is(${this.options.items}) :is(${this.options.handle})` :\n this.options.items;\n\n this.#dragging = false;\n this.#enabled = !this.options.disabled;\n\n this.#initialCursorNodes = $.find(this.#selector, this.node);\n setCursor(this.#initialCursorNodes, this.options.cursor);\n this.#events();\n this.#initialCursorNodes = null;\n } catch (error) {\n this.dispose();\n throw error;\n }\n }\n\n /**\n * Disables the Sortable.\n */\n disable() {\n this.#enabled = false;\n }\n\n /** @inheritdoc */\n dispose() {\n if (!this.node) {\n return;\n }\n\n $.removeEventDelegate(this.node, 'mousedown.ui.sortable touchstart.ui.sortable');\n $.removeEvent(this.node, 'receive.ui.sortable');\n resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));\n\n if (this.#target && this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n this.#resetDrag();\n\n this.#initialCursorNodes = null;\n\n super.dispose();\n }\n\n /**\n * Enables the Sortable.\n */\n enable() {\n this.#enabled = true;\n }\n\n /**\n * Gets the Sortable item elements.\n * @returns {HTMLElement[]} The Sortable item elements.\n */\n items() {\n return $.find(this.options.items, this.node);\n }\n\n /**\n * Checks whether the window should scroll while sorting.\n */\n #checkScroll() {\n this.#scrollFrame = null;\n\n if (!this.node || !this.#dragging || !this.#target || !this.#pos) {\n return;\n }\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n const windowHeight = $.height(window);\n const windowWidth = $.width(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 + windowHeight - this.options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n const maxY = Math.max(0, docHeight - windowHeight);\n offsetY = Math.min(maxY, 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 + windowWidth - this.options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n const maxX = Math.max(0, docWidth - windowWidth);\n offsetX = Math.min(maxX, originalX + this.options.scrollSpeed);\n }\n\n if (offsetX === originalX && offsetY === originalY) {\n return;\n }\n\n window.scrollTo({\n left: offsetX,\n top: offsetY,\n behavior: 'instant',\n });\n\n const deltaX = offsetX - originalX;\n const deltaY = offsetY - originalY;\n\n this.#pos.x += deltaX;\n this.#pos.y += deltaY;\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n }\n\n /**\n * Attaches events for the Sortable.\n */\n #events() {\n const downEvent = (event) => {\n const cancelled = this.options.cancel &&\n (\n $.is(event.target, this.options.cancel) ||\n $.is(event.currentTarget, this.options.cancel) ||\n $.closest(event.target, this.options.cancel, this.node).length\n );\n\n if (\n event.button ||\n !this.#enabled ||\n cancelled ||\n $.getDataset(this.node, 'uiDragging')\n ) {\n return false;\n }\n\n this.#target = this.options.handle ?\n this.items().find((node) => $.hasDescendent(node, event.currentTarget)) :\n event.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveEvent = (event) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(event);\n const deltaX = previousPos ?\n this.#pos.x - previousPos.x :\n 0;\n const deltaY = previousPos ?\n this.#pos.y - previousPos.y :\n 0;\n\n if (!this.#dragging) {\n this.#dragging = true;\n this.#currentSortable = this.node;\n this.#startIndex = this.items().indexOf(this.#target);\n this.#currentIndex = this.#startIndex;\n\n $.setDataset(this.node, { uiDragging: true });\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: this.node,\n to: this.node,\n oldIndex: this.#startIndex,\n newIndex: this.#startIndex,\n };\n\n triggerSortableEvent(this.node, 'sort', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.addClass(this.#target, this.options.helperClass);\n }\n }\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n };\n\n const upEvent = (event) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (event.type === 'mouseup') {\n event.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);\n\n $.addEventDelegate(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n this.#selector,\n dragEvent,\n );\n\n $.addEvent(this.node, 'receive.ui.sortable', () => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null && this.#scrollFrame !== undefined) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null && this.#scrollFrame !== undefined\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame(() => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"frost-ui-sortable.esm.min.js","names":["$","cursorLocks","resetCursor","node","nodes","release","setCursor","cursor","triggerSortableEvent","name","data","document","window","Sortable","BaseComponent","options","#selector","#dragging","#enabled","#initialCursorNodes","#events","error","#target","#resetDrag","#scrollFrame","#pos","originalX","originalY","windowHeight","windowWidth","offsetX","offsetY","docHeight","maxY","docWidth","maxX","deltaX","deltaY","#updatePlacement","#scheduleScroll","dragHandler","cancelled","event","previousPos","getPosition","#currentSortable","#startIndex","#currentIndex","eventData","source","destination","#checkScroll","nearestSortable","connected","sortable","nearestInstance","nearestItems","nearestItem","#updateTarget","newIndex","previousSortable","handle","nearestCenter","nearestRect","targetCenter","threshold","thresholdX","thresholdY","method","y","x","swapX","swapY","initComponent","src_default"],"sources":["../src/helpers.js","../src/sortable.js","../src/index.js"],"sourcesContent":["/** @import { SortableEventData } from './sortable.js'; */\n\nimport $ from '@fr0st/query';\n\nconst cursorLocks = new WeakMap();\n\n/**\n * Resets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to restore.\n */\nexport function resetCursor(nodes) {\n for (const node of nodes) {\n const release = cursorLocks.get(node);\n\n if (!release) {\n continue;\n }\n\n release();\n cursorLocks.delete(node);\n }\n}\n\n/**\n * Sets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to update.\n * @param {string} cursor The cursor style.\n */\nexport function setCursor(nodes, cursor) {\n for (const node of nodes) {\n if (cursorLocks.has(node)) {\n $.setStyle(node, { cursor });\n } else {\n cursorLocks.set(node, $.setStyleLock(node, 'cursor', cursor));\n }\n }\n}\n\n/**\n * Triggers a Sortable event with its data and detail payloads.\n * @param {HTMLElement} node The event target.\n * @param {string} name The event name without its namespace.\n * @param {SortableEventData} data The sorting event data.\n */\nexport function triggerSortableEvent(node, name, data) {\n $.triggerEvent(node, `${name}.ui.sortable`, {\n data,\n detail: {\n target: data.item,\n ...data,\n },\n });\n}\n","import $ from '@fr0st/query';\nimport { BaseComponent, getPosition } from '@fr0st/ui';\nimport { resetCursor, setCursor, triggerSortableEvent } from './helpers.js';\n\nconst document = $.getContext();\nconst window = $.getWindow();\n\n/** @typedef {'x'|'y'} SortableAxis */\n\n/**\n * @typedef {object} SortableOptions\n * @property {SortableAxis|null} [axis=null] The axis used to determine item placement.\n * @property {string} [cancel='input, textarea, button, select, option'] The selector for elements that cannot start a sort.\n * @property {string|null} [connectWith=null] The selector for connected Sortable containers.\n * @property {string} [cursor='auto'] The cursor applied to sortable items or handles.\n * @property {boolean} [disabled=false] Whether sorting is initially disabled.\n * @property {boolean} [dropOnEmpty=true] Whether connected empty containers accept items.\n * @property {string|null} [handle=null] The handle selector within each sortable item.\n * @property {string|null} [helperClass='bg-body-tertiary'] The class applied to an item while it is being sorted.\n * @property {string} [items=':scope > li'] The selector for sortable items.\n * @property {boolean} [scroll=true] Whether to scroll the window while sorting near an edge.\n * @property {number} [scrollSensitivity=20] The distance from a window edge that starts scrolling, in pixels.\n * @property {number} [scrollSpeed=5] The scroll distance applied per animation frame, in pixels.\n * @property {number} [swapThreshold=0.25] The fraction of an item crossed before swapping, from `0` to `1`.\n */\n\n/**\n * @typedef {object} SortableEventData\n * @property {HTMLElement} item The item being sorted.\n * @property {HTMLElement} from The previous or original Sortable container.\n * @property {HTMLElement} to The next or final Sortable container.\n * @property {number} oldIndex The previous or original item index.\n * @property {number} newIndex The next or final item index.\n */\n\n/**\n * Controls a sortable collection of elements.\n * @augments {BaseComponent<SortableOptions>}\n */\nexport default class Sortable extends BaseComponent {\n /** @type {SortableOptions} */\n static defaults = {\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 swapThreshold: 0.25,\n };\n\n #currentIndex;\n #currentSortable = null;\n #dragging;\n #enabled;\n #initialCursorNodes = [];\n #pos = null;\n #scrollFrame = null;\n #selector;\n #startIndex;\n #target = null;\n\n /**\n * Creates a Sortable.\n * @param {HTMLElement} node The sortable container.\n * @param {SortableOptions} [options] The Sortable options.\n */\n constructor(node, options) {\n super(node, options);\n\n try {\n this.#selector = this.options.handle ?\n `:is(${this.options.items}) :is(${this.options.handle})` :\n this.options.items;\n\n this.#dragging = false;\n this.#enabled = !this.options.disabled;\n\n this.#initialCursorNodes = $.find(this.#selector, this.node);\n setCursor(this.#initialCursorNodes, this.options.cursor);\n this.#events();\n this.#initialCursorNodes = null;\n } catch (error) {\n this.dispose();\n throw error;\n }\n }\n\n /**\n * Disables the Sortable.\n */\n disable() {\n this.#enabled = false;\n }\n\n /** @inheritdoc */\n dispose() {\n if (!this.node) {\n return;\n }\n\n resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));\n\n if (this.#target && this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n this.#resetDrag();\n\n this.#initialCursorNodes = null;\n\n super.dispose();\n }\n\n /**\n * Enables the Sortable.\n */\n enable() {\n this.#enabled = true;\n }\n\n /**\n * Gets the Sortable item elements.\n * @returns {HTMLElement[]} The Sortable item elements.\n */\n items() {\n return $.find(this.options.items, this.node);\n }\n\n /**\n * Checks whether the window should scroll while sorting.\n */\n #checkScroll() {\n this.#scrollFrame = null;\n\n if (!this.node || !this.#dragging || !this.#target || !this.#pos) {\n return;\n }\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n const windowHeight = $.height(window);\n const windowWidth = $.width(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 + windowHeight - this.options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n const maxY = Math.max(0, docHeight - windowHeight);\n offsetY = Math.min(maxY, 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 + windowWidth - this.options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n const maxX = Math.max(0, docWidth - windowWidth);\n offsetX = Math.min(maxX, originalX + this.options.scrollSpeed);\n }\n\n if (offsetX === originalX && offsetY === originalY) {\n return;\n }\n\n window.scrollTo({\n left: offsetX,\n top: offsetY,\n behavior: 'instant',\n });\n\n const deltaX = offsetX - originalX;\n const deltaY = offsetY - originalY;\n\n this.#pos.x += deltaX;\n this.#pos.y += deltaY;\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n }\n\n /**\n * Attaches events for the Sortable.\n */\n #events() {\n const downHandler = (event) => {\n const cancelled = this.options.cancel &&\n (\n $.is(event.target, this.options.cancel) ||\n $.is(event.currentTarget, this.options.cancel) ||\n $.closest(event.target, this.options.cancel, this.node).length\n );\n\n if (\n event.button ||\n !this.#enabled ||\n cancelled ||\n $.getDataset(this.node, 'uiDragging')\n ) {\n return false;\n }\n\n this.#target = this.options.handle ?\n this.items().find((node) => $.hasDescendent(node, event.currentTarget)) :\n event.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveHandler = (event) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(event);\n const deltaX = previousPos ?\n this.#pos.x - previousPos.x :\n 0;\n const deltaY = previousPos ?\n this.#pos.y - previousPos.y :\n 0;\n\n if (!this.#dragging) {\n this.#dragging = true;\n this.#currentSortable = this.node;\n this.#startIndex = this.items().indexOf(this.#target);\n this.#currentIndex = this.#startIndex;\n\n $.setDataset(this.node, { uiDragging: true });\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: this.node,\n to: this.node,\n oldIndex: this.#startIndex,\n newIndex: this.#startIndex,\n };\n\n triggerSortableEvent(this.node, 'sort', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.addClass(this.#target, this.options.helperClass);\n }\n }\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n };\n\n const upHandler = (event) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (event.type === 'mouseup') {\n event.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragHandler = $.mouseDragFactory(downHandler, moveHandler, upHandler);\n\n this.listen(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n dragHandler,\n { delegate: this.#selector },\n );\n\n this.listen(this.node, 'receive.ui.sortable', () => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame(() => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
(function(global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require(
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports',
|
|
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
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.UI = global.UI || {}), global.UI,global.fQuery));
|
|
5
5
|
})(this, function(exports, _fr0st_ui, _fr0st_query) {
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
7
|
-
|
|
7
|
+
// \0rolldown/runtime.js
|
|
8
8
|
var __create = Object.create;
|
|
9
9
|
var __defProp = Object.defineProperty;
|
|
10
10
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -30,10 +30,9 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
30
30
|
enumerable: true
|
|
31
31
|
}) : target, mod));
|
|
32
32
|
|
|
33
|
-
//#endregion
|
|
34
33
|
_fr0st_query = __toESM(_fr0st_query, 1);
|
|
35
34
|
|
|
36
|
-
|
|
35
|
+
// src/helpers.js
|
|
37
36
|
/** @import { SortableEventData } from './sortable.js'; */
|
|
38
37
|
var cursorLocks = /* @__PURE__ */ new WeakMap();
|
|
39
38
|
/**
|
|
@@ -73,8 +72,7 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
73
72
|
});
|
|
74
73
|
}
|
|
75
74
|
|
|
76
|
-
|
|
77
|
-
//#region src/sortable.js
|
|
75
|
+
// src/sortable.js
|
|
78
76
|
var document = _fr0st_query.default.getContext();
|
|
79
77
|
var window = _fr0st_query.default.getWindow();
|
|
80
78
|
/** @typedef {'x'|'y'} SortableAxis */
|
|
@@ -124,15 +122,15 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
124
122
|
swapThreshold: .25
|
|
125
123
|
};
|
|
126
124
|
#currentIndex;
|
|
127
|
-
#currentSortable;
|
|
125
|
+
#currentSortable = null;
|
|
128
126
|
#dragging;
|
|
129
127
|
#enabled;
|
|
130
128
|
#initialCursorNodes = [];
|
|
131
|
-
#pos;
|
|
132
|
-
#scrollFrame;
|
|
129
|
+
#pos = null;
|
|
130
|
+
#scrollFrame = null;
|
|
133
131
|
#selector;
|
|
134
132
|
#startIndex;
|
|
135
|
-
#target;
|
|
133
|
+
#target = null;
|
|
136
134
|
/**
|
|
137
135
|
* Creates a Sortable.
|
|
138
136
|
* @param {HTMLElement} node The sortable container.
|
|
@@ -162,8 +160,6 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
162
160
|
/** @inheritdoc */
|
|
163
161
|
dispose() {
|
|
164
162
|
if (!this.node) return;
|
|
165
|
-
_fr0st_query.default.removeEventDelegate(this.node, "mousedown.ui.sortable touchstart.ui.sortable");
|
|
166
|
-
_fr0st_query.default.removeEvent(this.node, "receive.ui.sortable");
|
|
167
163
|
resetCursor(this.#initialCursorNodes ?? _fr0st_query.default.find(this.#selector, this.node));
|
|
168
164
|
if (this.#target && this.options.helperClass) _fr0st_query.default.removeClass(this.#target, this.options.helperClass);
|
|
169
165
|
this.#resetDrag();
|
|
@@ -224,13 +220,13 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
224
220
|
* Attaches events for the Sortable.
|
|
225
221
|
*/
|
|
226
222
|
#events() {
|
|
227
|
-
const
|
|
223
|
+
const downHandler = (event) => {
|
|
228
224
|
const cancelled = this.options.cancel && (_fr0st_query.default.is(event.target, this.options.cancel) || _fr0st_query.default.is(event.currentTarget, this.options.cancel) || _fr0st_query.default.closest(event.target, this.options.cancel, this.node).length);
|
|
229
225
|
if (event.button || !this.#enabled || cancelled || _fr0st_query.default.getDataset(this.node, "uiDragging")) return false;
|
|
230
226
|
this.#target = this.options.handle ? this.items().find((node) => _fr0st_query.default.hasDescendent(node, event.currentTarget)) : event.currentTarget;
|
|
231
227
|
if (!this.#target) return false;
|
|
232
228
|
};
|
|
233
|
-
const
|
|
229
|
+
const moveHandler = (event) => {
|
|
234
230
|
if (!this.node || !this.#target) return;
|
|
235
231
|
const previousPos = this.#pos;
|
|
236
232
|
this.#pos = (0, _fr0st_ui.getPosition)(event);
|
|
@@ -257,7 +253,7 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
257
253
|
this.#updatePlacement(deltaX, deltaY);
|
|
258
254
|
this.#scheduleScroll();
|
|
259
255
|
};
|
|
260
|
-
const
|
|
256
|
+
const upHandler = (event) => {
|
|
261
257
|
if (!this.node) return;
|
|
262
258
|
if (!this.#dragging) {
|
|
263
259
|
this.#target = null;
|
|
@@ -283,9 +279,9 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
283
279
|
} else if (this.#currentIndex !== this.#startIndex) triggerSortableEvent(destination, "update", eventData);
|
|
284
280
|
if (this.node) this.#resetDrag();
|
|
285
281
|
};
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
282
|
+
const dragHandler = _fr0st_query.default.mouseDragFactory(downHandler, moveHandler, upHandler);
|
|
283
|
+
this.listen(this.node, "mousedown.ui.sortable touchstart.ui.sortable", dragHandler, { delegate: this.#selector });
|
|
284
|
+
this.listen(this.node, "receive.ui.sortable", () => {
|
|
289
285
|
setCursor(_fr0st_query.default.find(this.#selector, this.node), this.options.cursor);
|
|
290
286
|
});
|
|
291
287
|
}
|
|
@@ -293,7 +289,7 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
293
289
|
* Resets the active drag state.
|
|
294
290
|
*/
|
|
295
291
|
#resetDrag() {
|
|
296
|
-
if (this.#scrollFrame !== null
|
|
292
|
+
if (this.#scrollFrame !== null) window.cancelAnimationFrame(this.#scrollFrame);
|
|
297
293
|
if (this.#dragging && this.node) _fr0st_query.default.removeDataset(this.node, "uiDragging");
|
|
298
294
|
this.#currentIndex = null;
|
|
299
295
|
this.#currentSortable = null;
|
|
@@ -307,7 +303,7 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
307
303
|
* Schedules the next auto-scroll update.
|
|
308
304
|
*/
|
|
309
305
|
#scheduleScroll() {
|
|
310
|
-
if (!this.node || !this.options.scroll || !this.#dragging || this.#scrollFrame !== null
|
|
306
|
+
if (!this.node || !this.options.scroll || !this.#dragging || this.#scrollFrame !== null) return;
|
|
311
307
|
this.#scrollFrame = window.requestAnimationFrame(() => {
|
|
312
308
|
this.#checkScroll();
|
|
313
309
|
});
|
|
@@ -392,12 +388,10 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
392
388
|
}
|
|
393
389
|
};
|
|
394
390
|
|
|
395
|
-
|
|
396
|
-
//#region src/index.js
|
|
391
|
+
// src/index.js
|
|
397
392
|
(0, _fr0st_ui.initComponent)("sortable", Sortable);
|
|
398
393
|
var src_default = Sortable;
|
|
399
394
|
|
|
400
|
-
//#endregion
|
|
401
395
|
exports.Sortable = src_default;
|
|
402
396
|
});
|
|
403
397
|
//# sourceMappingURL=frost-ui-sortable.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frost-ui-sortable.js","names":["$","$","BaseComponent","getPosition"],"sources":["../src/helpers.js","../src/sortable.js","../src/index.js"],"sourcesContent":["/** @import { SortableEventData } from './sortable.js'; */\n\nimport $ from '@fr0st/query';\n\nconst cursorLocks = new WeakMap();\n\n/**\n * Resets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to restore.\n */\nexport function resetCursor(nodes) {\n for (const node of nodes) {\n const release = cursorLocks.get(node);\n\n if (!release) {\n continue;\n }\n\n release();\n cursorLocks.delete(node);\n }\n}\n\n/**\n * Sets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to update.\n * @param {string} cursor The cursor style.\n */\nexport function setCursor(nodes, cursor) {\n for (const node of nodes) {\n if (cursorLocks.has(node)) {\n $.setStyle(node, { cursor });\n } else {\n cursorLocks.set(node, $.setStyleLock(node, 'cursor', cursor));\n }\n }\n}\n\n/**\n * Triggers a Sortable event with its data and detail payloads.\n * @param {HTMLElement} node The event target.\n * @param {string} name The event name without its namespace.\n * @param {SortableEventData} data The sorting event data.\n */\nexport function triggerSortableEvent(node, name, data) {\n $.triggerEvent(node, `${name}.ui.sortable`, {\n data,\n detail: {\n target: data.item,\n ...data,\n },\n });\n}\n","import $ from '@fr0st/query';\nimport { BaseComponent, getPosition } from '@fr0st/ui';\nimport { resetCursor, setCursor, triggerSortableEvent } from './helpers.js';\n\nconst document = $.getContext();\nconst window = $.getWindow();\n\n/** @typedef {'x'|'y'} SortableAxis */\n\n/**\n * @typedef {object} SortableOptions\n * @property {SortableAxis|null} [axis=null] The axis used to determine item placement.\n * @property {string} [cancel='input, textarea, button, select, option'] The selector for elements that cannot start a sort.\n * @property {string|null} [connectWith=null] The selector for connected Sortable containers.\n * @property {string} [cursor='auto'] The cursor applied to sortable items or handles.\n * @property {boolean} [disabled=false] Whether sorting is initially disabled.\n * @property {boolean} [dropOnEmpty=true] Whether connected empty containers accept items.\n * @property {string|null} [handle=null] The handle selector within each sortable item.\n * @property {string|null} [helperClass='bg-body-tertiary'] The class applied to an item while it is being sorted.\n * @property {string} [items=':scope > li'] The selector for sortable items.\n * @property {boolean} [scroll=true] Whether to scroll the window while sorting near an edge.\n * @property {number} [scrollSensitivity=20] The distance from a window edge that starts scrolling, in pixels.\n * @property {number} [scrollSpeed=5] The scroll distance applied per animation frame, in pixels.\n * @property {number} [swapThreshold=0.25] The fraction of an item crossed before swapping, from `0` to `1`.\n */\n\n/**\n * @typedef {object} SortableEventData\n * @property {HTMLElement} item The item being sorted.\n * @property {HTMLElement} from The previous or original Sortable container.\n * @property {HTMLElement} to The next or final Sortable container.\n * @property {number} oldIndex The previous or original item index.\n * @property {number} newIndex The next or final item index.\n */\n\n/**\n * Controls a sortable collection of elements.\n * @augments {BaseComponent<SortableOptions>}\n */\nexport default class Sortable extends BaseComponent {\n /** @type {SortableOptions} */\n static defaults = {\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 swapThreshold: 0.25,\n };\n\n #currentIndex;\n #currentSortable;\n #dragging;\n #enabled;\n #initialCursorNodes = [];\n #pos;\n #scrollFrame;\n #selector;\n #startIndex;\n #target;\n\n /**\n * Creates a Sortable.\n * @param {HTMLElement} node The sortable container.\n * @param {SortableOptions} [options] The Sortable options.\n */\n constructor(node, options) {\n super(node, options);\n\n try {\n this.#selector = this.options.handle ?\n `:is(${this.options.items}) :is(${this.options.handle})` :\n this.options.items;\n\n this.#dragging = false;\n this.#enabled = !this.options.disabled;\n\n this.#initialCursorNodes = $.find(this.#selector, this.node);\n setCursor(this.#initialCursorNodes, this.options.cursor);\n this.#events();\n this.#initialCursorNodes = null;\n } catch (error) {\n this.dispose();\n throw error;\n }\n }\n\n /**\n * Disables the Sortable.\n */\n disable() {\n this.#enabled = false;\n }\n\n /** @inheritdoc */\n dispose() {\n if (!this.node) {\n return;\n }\n\n $.removeEventDelegate(this.node, 'mousedown.ui.sortable touchstart.ui.sortable');\n $.removeEvent(this.node, 'receive.ui.sortable');\n resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));\n\n if (this.#target && this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n this.#resetDrag();\n\n this.#initialCursorNodes = null;\n\n super.dispose();\n }\n\n /**\n * Enables the Sortable.\n */\n enable() {\n this.#enabled = true;\n }\n\n /**\n * Gets the Sortable item elements.\n * @returns {HTMLElement[]} The Sortable item elements.\n */\n items() {\n return $.find(this.options.items, this.node);\n }\n\n /**\n * Checks whether the window should scroll while sorting.\n */\n #checkScroll() {\n this.#scrollFrame = null;\n\n if (!this.node || !this.#dragging || !this.#target || !this.#pos) {\n return;\n }\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n const windowHeight = $.height(window);\n const windowWidth = $.width(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 + windowHeight - this.options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n const maxY = Math.max(0, docHeight - windowHeight);\n offsetY = Math.min(maxY, 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 + windowWidth - this.options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n const maxX = Math.max(0, docWidth - windowWidth);\n offsetX = Math.min(maxX, originalX + this.options.scrollSpeed);\n }\n\n if (offsetX === originalX && offsetY === originalY) {\n return;\n }\n\n window.scrollTo({\n left: offsetX,\n top: offsetY,\n behavior: 'instant',\n });\n\n const deltaX = offsetX - originalX;\n const deltaY = offsetY - originalY;\n\n this.#pos.x += deltaX;\n this.#pos.y += deltaY;\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n }\n\n /**\n * Attaches events for the Sortable.\n */\n #events() {\n const downEvent = (event) => {\n const cancelled = this.options.cancel &&\n (\n $.is(event.target, this.options.cancel) ||\n $.is(event.currentTarget, this.options.cancel) ||\n $.closest(event.target, this.options.cancel, this.node).length\n );\n\n if (\n event.button ||\n !this.#enabled ||\n cancelled ||\n $.getDataset(this.node, 'uiDragging')\n ) {\n return false;\n }\n\n this.#target = this.options.handle ?\n this.items().find((node) => $.hasDescendent(node, event.currentTarget)) :\n event.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveEvent = (event) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(event);\n const deltaX = previousPos ?\n this.#pos.x - previousPos.x :\n 0;\n const deltaY = previousPos ?\n this.#pos.y - previousPos.y :\n 0;\n\n if (!this.#dragging) {\n this.#dragging = true;\n this.#currentSortable = this.node;\n this.#startIndex = this.items().indexOf(this.#target);\n this.#currentIndex = this.#startIndex;\n\n $.setDataset(this.node, { uiDragging: true });\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: this.node,\n to: this.node,\n oldIndex: this.#startIndex,\n newIndex: this.#startIndex,\n };\n\n triggerSortableEvent(this.node, 'sort', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.addClass(this.#target, this.options.helperClass);\n }\n }\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n };\n\n const upEvent = (event) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (event.type === 'mouseup') {\n event.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);\n\n $.addEventDelegate(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n this.#selector,\n dragEvent,\n );\n\n $.addEvent(this.node, 'receive.ui.sortable', () => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null && this.#scrollFrame !== undefined) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null && this.#scrollFrame !== undefined\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame(() => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"frost-ui-sortable.js","names":["$","$","BaseComponent","getPosition"],"sources":["../src/helpers.js","../src/sortable.js","../src/index.js"],"sourcesContent":["/** @import { SortableEventData } from './sortable.js'; */\n\nimport $ from '@fr0st/query';\n\nconst cursorLocks = new WeakMap();\n\n/**\n * Resets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to restore.\n */\nexport function resetCursor(nodes) {\n for (const node of nodes) {\n const release = cursorLocks.get(node);\n\n if (!release) {\n continue;\n }\n\n release();\n cursorLocks.delete(node);\n }\n}\n\n/**\n * Sets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to update.\n * @param {string} cursor The cursor style.\n */\nexport function setCursor(nodes, cursor) {\n for (const node of nodes) {\n if (cursorLocks.has(node)) {\n $.setStyle(node, { cursor });\n } else {\n cursorLocks.set(node, $.setStyleLock(node, 'cursor', cursor));\n }\n }\n}\n\n/**\n * Triggers a Sortable event with its data and detail payloads.\n * @param {HTMLElement} node The event target.\n * @param {string} name The event name without its namespace.\n * @param {SortableEventData} data The sorting event data.\n */\nexport function triggerSortableEvent(node, name, data) {\n $.triggerEvent(node, `${name}.ui.sortable`, {\n data,\n detail: {\n target: data.item,\n ...data,\n },\n });\n}\n","import $ from '@fr0st/query';\nimport { BaseComponent, getPosition } from '@fr0st/ui';\nimport { resetCursor, setCursor, triggerSortableEvent } from './helpers.js';\n\nconst document = $.getContext();\nconst window = $.getWindow();\n\n/** @typedef {'x'|'y'} SortableAxis */\n\n/**\n * @typedef {object} SortableOptions\n * @property {SortableAxis|null} [axis=null] The axis used to determine item placement.\n * @property {string} [cancel='input, textarea, button, select, option'] The selector for elements that cannot start a sort.\n * @property {string|null} [connectWith=null] The selector for connected Sortable containers.\n * @property {string} [cursor='auto'] The cursor applied to sortable items or handles.\n * @property {boolean} [disabled=false] Whether sorting is initially disabled.\n * @property {boolean} [dropOnEmpty=true] Whether connected empty containers accept items.\n * @property {string|null} [handle=null] The handle selector within each sortable item.\n * @property {string|null} [helperClass='bg-body-tertiary'] The class applied to an item while it is being sorted.\n * @property {string} [items=':scope > li'] The selector for sortable items.\n * @property {boolean} [scroll=true] Whether to scroll the window while sorting near an edge.\n * @property {number} [scrollSensitivity=20] The distance from a window edge that starts scrolling, in pixels.\n * @property {number} [scrollSpeed=5] The scroll distance applied per animation frame, in pixels.\n * @property {number} [swapThreshold=0.25] The fraction of an item crossed before swapping, from `0` to `1`.\n */\n\n/**\n * @typedef {object} SortableEventData\n * @property {HTMLElement} item The item being sorted.\n * @property {HTMLElement} from The previous or original Sortable container.\n * @property {HTMLElement} to The next or final Sortable container.\n * @property {number} oldIndex The previous or original item index.\n * @property {number} newIndex The next or final item index.\n */\n\n/**\n * Controls a sortable collection of elements.\n * @augments {BaseComponent<SortableOptions>}\n */\nexport default class Sortable extends BaseComponent {\n /** @type {SortableOptions} */\n static defaults = {\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 swapThreshold: 0.25,\n };\n\n #currentIndex;\n #currentSortable = null;\n #dragging;\n #enabled;\n #initialCursorNodes = [];\n #pos = null;\n #scrollFrame = null;\n #selector;\n #startIndex;\n #target = null;\n\n /**\n * Creates a Sortable.\n * @param {HTMLElement} node The sortable container.\n * @param {SortableOptions} [options] The Sortable options.\n */\n constructor(node, options) {\n super(node, options);\n\n try {\n this.#selector = this.options.handle ?\n `:is(${this.options.items}) :is(${this.options.handle})` :\n this.options.items;\n\n this.#dragging = false;\n this.#enabled = !this.options.disabled;\n\n this.#initialCursorNodes = $.find(this.#selector, this.node);\n setCursor(this.#initialCursorNodes, this.options.cursor);\n this.#events();\n this.#initialCursorNodes = null;\n } catch (error) {\n this.dispose();\n throw error;\n }\n }\n\n /**\n * Disables the Sortable.\n */\n disable() {\n this.#enabled = false;\n }\n\n /** @inheritdoc */\n dispose() {\n if (!this.node) {\n return;\n }\n\n resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));\n\n if (this.#target && this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n this.#resetDrag();\n\n this.#initialCursorNodes = null;\n\n super.dispose();\n }\n\n /**\n * Enables the Sortable.\n */\n enable() {\n this.#enabled = true;\n }\n\n /**\n * Gets the Sortable item elements.\n * @returns {HTMLElement[]} The Sortable item elements.\n */\n items() {\n return $.find(this.options.items, this.node);\n }\n\n /**\n * Checks whether the window should scroll while sorting.\n */\n #checkScroll() {\n this.#scrollFrame = null;\n\n if (!this.node || !this.#dragging || !this.#target || !this.#pos) {\n return;\n }\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n const windowHeight = $.height(window);\n const windowWidth = $.width(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 + windowHeight - this.options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n const maxY = Math.max(0, docHeight - windowHeight);\n offsetY = Math.min(maxY, 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 + windowWidth - this.options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n const maxX = Math.max(0, docWidth - windowWidth);\n offsetX = Math.min(maxX, originalX + this.options.scrollSpeed);\n }\n\n if (offsetX === originalX && offsetY === originalY) {\n return;\n }\n\n window.scrollTo({\n left: offsetX,\n top: offsetY,\n behavior: 'instant',\n });\n\n const deltaX = offsetX - originalX;\n const deltaY = offsetY - originalY;\n\n this.#pos.x += deltaX;\n this.#pos.y += deltaY;\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n }\n\n /**\n * Attaches events for the Sortable.\n */\n #events() {\n const downHandler = (event) => {\n const cancelled = this.options.cancel &&\n (\n $.is(event.target, this.options.cancel) ||\n $.is(event.currentTarget, this.options.cancel) ||\n $.closest(event.target, this.options.cancel, this.node).length\n );\n\n if (\n event.button ||\n !this.#enabled ||\n cancelled ||\n $.getDataset(this.node, 'uiDragging')\n ) {\n return false;\n }\n\n this.#target = this.options.handle ?\n this.items().find((node) => $.hasDescendent(node, event.currentTarget)) :\n event.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveHandler = (event) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(event);\n const deltaX = previousPos ?\n this.#pos.x - previousPos.x :\n 0;\n const deltaY = previousPos ?\n this.#pos.y - previousPos.y :\n 0;\n\n if (!this.#dragging) {\n this.#dragging = true;\n this.#currentSortable = this.node;\n this.#startIndex = this.items().indexOf(this.#target);\n this.#currentIndex = this.#startIndex;\n\n $.setDataset(this.node, { uiDragging: true });\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: this.node,\n to: this.node,\n oldIndex: this.#startIndex,\n newIndex: this.#startIndex,\n };\n\n triggerSortableEvent(this.node, 'sort', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.addClass(this.#target, this.options.helperClass);\n }\n }\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n };\n\n const upHandler = (event) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (event.type === 'mouseup') {\n event.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragHandler = $.mouseDragFactory(downHandler, moveHandler, upHandler);\n\n this.listen(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n dragHandler,\n { delegate: this.#selector },\n );\n\n this.listen(this.node, 'receive.ui.sortable', () => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame(() => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("@fr0st/ui"),require("@fr0st/query")):typeof define==`function`&&define.amd?define([`exports`,`@fr0st/ui`,`@fr0st/query`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.UI=e.UI||{},e.UI,e.fQuery))})(this,function(e,t,n){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var s=o(t),l=0,u=s.length,d;l<u;l++)d=s[l],!c.call(e,d)&&d!==n&&i(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=a(t,d))||r.enumerable});return e};n=((e,t,n)=>(n=e==null?{}:r(s(e)),l(
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("@fr0st/ui"),require("@fr0st/query")):typeof define==`function`&&define.amd?define([`exports`,`@fr0st/ui`,`@fr0st/query`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.UI=e.UI||{},e.UI,e.fQuery))})(this,function(e,t,n){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var s=o(t),l=0,u=s.length,d;l<u;l++)d=s[l],!c.call(e,d)&&d!==n&&i(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=a(t,d))||r.enumerable});return e};n=((e,t,n)=>(n=e==null?{}:r(s(e)),l(i(n,`default`,{value:e,enumerable:!0}),e)))(n,1);var u=/* @__PURE__ */ new WeakMap;function d(e){for(let t of e){let e=u.get(t);e&&(e(),u.delete(t))}}function f(e,t){for(let r of e)u.has(r)?n.default.setStyle(r,{cursor:t}):u.set(r,n.default.setStyleLock(r,`cursor`,t))}function p(e,t,r){n.default.triggerEvent(e,`${t}.ui.sortable`,{data:r,detail:{target:r.item,...r}})}var m=n.default.getContext(),h=n.default.getWindow(),g=class extends t.BaseComponent{static defaults={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,swapThreshold:.25};#e;#t=null;#n;#r;#i=[];#a=null;#o=null;#s;#c;#l=null;constructor(e,t){super(e,t);try{this.#s=this.options.handle?`:is(${this.options.items}) :is(${this.options.handle})`:this.options.items,this.#n=!1,this.#r=!this.options.disabled,this.#i=n.default.find(this.#s,this.node),f(this.#i,this.options.cursor),this.#d(),this.#i=null}catch(e){throw this.dispose(),e}}disable(){this.#r=!1}dispose(){this.node&&(d(this.#i??n.default.find(this.#s,this.node)),this.#l&&this.options.helperClass&&n.default.removeClass(this.#l,this.options.helperClass),this.#f(),this.#i=null,super.dispose())}enable(){this.#r=!0}items(){return n.default.find(this.options.items,this.node)}#u(){if(this.#o=null,!this.node||!this.#n||!this.#l||!this.#a)return;let e=n.default.getScrollX(h),t=n.default.getScrollY(h),r=n.default.height(h),i=n.default.width(h),a=e,o=t;if(this.#a.y<t+this.options.scrollSensitivity)o=Math.max(0,t-this.options.scrollSpeed);else if(this.#a.y>t+r-this.options.scrollSensitivity){let e=n.default.height(m,{boxSize:n.default.SCROLL_BOX}),i=Math.max(0,e-r);o=Math.min(i,t+this.options.scrollSpeed)}if(this.#a.x<e+this.options.scrollSensitivity)a=Math.max(0,e-this.options.scrollSpeed);else if(this.#a.x>e+i-this.options.scrollSensitivity){let t=n.default.width(m,{boxSize:n.default.SCROLL_BOX}),r=Math.max(0,t-i);a=Math.min(r,e+this.options.scrollSpeed)}if(a===e&&o===t)return;h.scrollTo({left:a,top:o,behavior:`instant`});let s=a-e,c=o-t;this.#a.x+=s,this.#a.y+=c,this.#m(s,c),this.#p()}#d(){let e=n.default.mouseDragFactory(e=>{let t=this.options.cancel&&(n.default.is(e.target,this.options.cancel)||n.default.is(e.currentTarget,this.options.cancel)||n.default.closest(e.target,this.options.cancel,this.node).length);if(e.button||!this.#r||t||n.default.getDataset(this.node,`uiDragging`)||(this.#l=this.options.handle?this.items().find(t=>n.default.hasDescendent(t,e.currentTarget)):e.currentTarget,!this.#l))return!1},e=>{if(!this.node||!this.#l)return;let r=this.#a;this.#a=(0,t.getPosition)(e);let i=r?this.#a.x-r.x:0,a=r?this.#a.y-r.y:0;if(!this.#n){this.#n=!0,this.#t=this.node,this.#c=this.items().indexOf(this.#l),this.#e=this.#c,n.default.setDataset(this.node,{uiDragging:!0});let e={item:this.#l,from:this.node,to:this.node,oldIndex:this.#c,newIndex:this.#c};if(p(this.node,`sort`,e),!this.node)return;this.options.helperClass&&n.default.addClass(this.#l,this.options.helperClass)}this.#m(i,a),this.#p()},e=>{if(!this.node)return;if(!this.#n){this.#l=null;return}e.type===`mouseup`&&e.preventDefault();let t=this.node,r=this.#t,i={item:this.#l,from:t,to:r,oldIndex:this.#c,newIndex:this.#e};p(r,`sorted`,i),this.node&&(this.options.helperClass&&n.default.removeClass(this.#l,this.options.helperClass),t===r?this.#e!==this.#c&&p(r,`update`,i):(p(t,`update`,i),this.node&&p(r,`update`,i)),this.node&&this.#f())});this.listen(this.node,`mousedown.ui.sortable touchstart.ui.sortable`,e,{delegate:this.#s}),this.listen(this.node,`receive.ui.sortable`,()=>{f(n.default.find(this.#s,this.node),this.options.cursor)})}#f(){this.#o!==null&&h.cancelAnimationFrame(this.#o),this.#n&&this.node&&n.default.removeDataset(this.node,`uiDragging`),this.#e=null,this.#t=null,this.#n=!1,this.#a=null,this.#o=null,this.#c=null,this.#l=null}#p(){this.node&&this.options.scroll&&this.#n&&this.#o===null&&(this.#o=h.requestAnimationFrame(()=>{this.#u()}))}#m(e,t){let r=this.node;if(this.options.connectWith){let e=n.default.find(this.options.connectWith).filter(e=>e!==this.node).filter(e=>{let t=this.constructor.init(e);return t.#r&&(t.options.dropOnEmpty||t.items().length)});e.length&&(r=n.default.nearestTo([this.node,...e],this.#a.x,this.#a.y,{offset:!0}))}let i=this.constructor.init(r),a=i.items().filter(e=>e!==this.#l),o=n.default.nearestTo(a,this.#a.x,this.#a.y,{offset:!0});if(o)this.#h(o,this.#a.x,this.#a.y,e,t);else if(r!==this.#t)n.default.append(r,this.#l);else return;let s=i.items().indexOf(this.#l);if(r!==this.#t){let e=this.#t,{handle:t}=this.constructor.init(e).options;d(t?n.default.find(t,this.#l):[this.#l]);let i={item:this.#l,from:e,to:r,oldIndex:this.#e,newIndex:s};if(p(e,`send`,i),!this.node)return;p(r,`receive`,i)}else if(this.#e!==s){let e={item:this.#l,from:r,to:r,oldIndex:this.#e,newIndex:s};p(r,`sorting`,e)}this.node&&(this.#e=s,this.#t=r)}#h(e,t,r,i,a){let o=n.default.center(e,{offset:!0}),s=n.default.rect(e,{offset:!0}),c=n.default.center(this.#l,{offset:!0}),l=Math.min(1,Math.max(0,this.options.swapThreshold)),u=.5,d=.5;i&&(u=i>0?l:1-l),a&&(d=a>0?l:1-l);let f;if(this.options.axis===`y`||o.x===c.x)f=r<s.top+s.height*d?`before`:`after`;else if(this.options.axis===`x`||o.y===c.y)f=t<s.left+s.width*u?`before`:`after`;else{let e=s.left+s.width*u,n=s.top+s.height*d;f=t<e&&r<n?`before`:`after`}n.default[f](e,this.#l)}};(0,t.initComponent)(`sortable`,g),e.Sortable=g});
|
|
2
2
|
//# sourceMappingURL=frost-ui-sortable.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frost-ui-sortable.min.js","names":["$","$","BaseComponent","getPosition","factory","global","exports","__create","__defProp","__getOwnPropDesc","__getOwnPropNames","__getProtoOf","__hasOwnProp","__copyProps","from","keys","i","n","key","to","except","k","desc","mod","isNodeMode","target","_fr0st_query","cursorLocks","resetCursor","node","nodes","release","setCursor","cursor","triggerSortableEvent","name","data","document","window","Sortable","_fr0st_ui","options","#selector","#dragging","#enabled","#initialCursorNodes","#events","error","#target","#resetDrag","#scrollFrame","#pos","originalX","originalY","windowHeight","windowWidth","offsetX","offsetY","docHeight","maxY","docWidth","maxX","deltaX","deltaY","#updatePlacement","#scheduleScroll","dragEvent","cancelled","event","previousPos","#currentSortable","#startIndex","#currentIndex","eventData","source","destination","#checkScroll","nearestSortable","connected","sortable","nearestInstance","nearestItems","nearestItem","#updateTarget","newIndex","previousSortable","handle","nearestCenter","nearestRect","targetCenter","threshold","thresholdX","thresholdY","method","y","x","swapX","swapY","src_default"],"sources":["../src/helpers.js","../src/sortable.js","../src/index.js"],"sourcesContent":["/** @import { SortableEventData } from './sortable.js'; */\n\nimport $ from '@fr0st/query';\n\nconst cursorLocks = new WeakMap();\n\n/**\n * Resets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to restore.\n */\nexport function resetCursor(nodes) {\n for (const node of nodes) {\n const release = cursorLocks.get(node);\n\n if (!release) {\n continue;\n }\n\n release();\n cursorLocks.delete(node);\n }\n}\n\n/**\n * Sets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to update.\n * @param {string} cursor The cursor style.\n */\nexport function setCursor(nodes, cursor) {\n for (const node of nodes) {\n if (cursorLocks.has(node)) {\n $.setStyle(node, { cursor });\n } else {\n cursorLocks.set(node, $.setStyleLock(node, 'cursor', cursor));\n }\n }\n}\n\n/**\n * Triggers a Sortable event with its data and detail payloads.\n * @param {HTMLElement} node The event target.\n * @param {string} name The event name without its namespace.\n * @param {SortableEventData} data The sorting event data.\n */\nexport function triggerSortableEvent(node, name, data) {\n $.triggerEvent(node, `${name}.ui.sortable`, {\n data,\n detail: {\n target: data.item,\n ...data,\n },\n });\n}\n","import $ from '@fr0st/query';\nimport { BaseComponent, getPosition } from '@fr0st/ui';\nimport { resetCursor, setCursor, triggerSortableEvent } from './helpers.js';\n\nconst document = $.getContext();\nconst window = $.getWindow();\n\n/** @typedef {'x'|'y'} SortableAxis */\n\n/**\n * @typedef {object} SortableOptions\n * @property {SortableAxis|null} [axis=null] The axis used to determine item placement.\n * @property {string} [cancel='input, textarea, button, select, option'] The selector for elements that cannot start a sort.\n * @property {string|null} [connectWith=null] The selector for connected Sortable containers.\n * @property {string} [cursor='auto'] The cursor applied to sortable items or handles.\n * @property {boolean} [disabled=false] Whether sorting is initially disabled.\n * @property {boolean} [dropOnEmpty=true] Whether connected empty containers accept items.\n * @property {string|null} [handle=null] The handle selector within each sortable item.\n * @property {string|null} [helperClass='bg-body-tertiary'] The class applied to an item while it is being sorted.\n * @property {string} [items=':scope > li'] The selector for sortable items.\n * @property {boolean} [scroll=true] Whether to scroll the window while sorting near an edge.\n * @property {number} [scrollSensitivity=20] The distance from a window edge that starts scrolling, in pixels.\n * @property {number} [scrollSpeed=5] The scroll distance applied per animation frame, in pixels.\n * @property {number} [swapThreshold=0.25] The fraction of an item crossed before swapping, from `0` to `1`.\n */\n\n/**\n * @typedef {object} SortableEventData\n * @property {HTMLElement} item The item being sorted.\n * @property {HTMLElement} from The previous or original Sortable container.\n * @property {HTMLElement} to The next or final Sortable container.\n * @property {number} oldIndex The previous or original item index.\n * @property {number} newIndex The next or final item index.\n */\n\n/**\n * Controls a sortable collection of elements.\n * @augments {BaseComponent<SortableOptions>}\n */\nexport default class Sortable extends BaseComponent {\n /** @type {SortableOptions} */\n static defaults = {\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 swapThreshold: 0.25,\n };\n\n #currentIndex;\n #currentSortable;\n #dragging;\n #enabled;\n #initialCursorNodes = [];\n #pos;\n #scrollFrame;\n #selector;\n #startIndex;\n #target;\n\n /**\n * Creates a Sortable.\n * @param {HTMLElement} node The sortable container.\n * @param {SortableOptions} [options] The Sortable options.\n */\n constructor(node, options) {\n super(node, options);\n\n try {\n this.#selector = this.options.handle ?\n `:is(${this.options.items}) :is(${this.options.handle})` :\n this.options.items;\n\n this.#dragging = false;\n this.#enabled = !this.options.disabled;\n\n this.#initialCursorNodes = $.find(this.#selector, this.node);\n setCursor(this.#initialCursorNodes, this.options.cursor);\n this.#events();\n this.#initialCursorNodes = null;\n } catch (error) {\n this.dispose();\n throw error;\n }\n }\n\n /**\n * Disables the Sortable.\n */\n disable() {\n this.#enabled = false;\n }\n\n /** @inheritdoc */\n dispose() {\n if (!this.node) {\n return;\n }\n\n $.removeEventDelegate(this.node, 'mousedown.ui.sortable touchstart.ui.sortable');\n $.removeEvent(this.node, 'receive.ui.sortable');\n resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));\n\n if (this.#target && this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n this.#resetDrag();\n\n this.#initialCursorNodes = null;\n\n super.dispose();\n }\n\n /**\n * Enables the Sortable.\n */\n enable() {\n this.#enabled = true;\n }\n\n /**\n * Gets the Sortable item elements.\n * @returns {HTMLElement[]} The Sortable item elements.\n */\n items() {\n return $.find(this.options.items, this.node);\n }\n\n /**\n * Checks whether the window should scroll while sorting.\n */\n #checkScroll() {\n this.#scrollFrame = null;\n\n if (!this.node || !this.#dragging || !this.#target || !this.#pos) {\n return;\n }\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n const windowHeight = $.height(window);\n const windowWidth = $.width(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 + windowHeight - this.options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n const maxY = Math.max(0, docHeight - windowHeight);\n offsetY = Math.min(maxY, 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 + windowWidth - this.options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n const maxX = Math.max(0, docWidth - windowWidth);\n offsetX = Math.min(maxX, originalX + this.options.scrollSpeed);\n }\n\n if (offsetX === originalX && offsetY === originalY) {\n return;\n }\n\n window.scrollTo({\n left: offsetX,\n top: offsetY,\n behavior: 'instant',\n });\n\n const deltaX = offsetX - originalX;\n const deltaY = offsetY - originalY;\n\n this.#pos.x += deltaX;\n this.#pos.y += deltaY;\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n }\n\n /**\n * Attaches events for the Sortable.\n */\n #events() {\n const downEvent = (event) => {\n const cancelled = this.options.cancel &&\n (\n $.is(event.target, this.options.cancel) ||\n $.is(event.currentTarget, this.options.cancel) ||\n $.closest(event.target, this.options.cancel, this.node).length\n );\n\n if (\n event.button ||\n !this.#enabled ||\n cancelled ||\n $.getDataset(this.node, 'uiDragging')\n ) {\n return false;\n }\n\n this.#target = this.options.handle ?\n this.items().find((node) => $.hasDescendent(node, event.currentTarget)) :\n event.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveEvent = (event) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(event);\n const deltaX = previousPos ?\n this.#pos.x - previousPos.x :\n 0;\n const deltaY = previousPos ?\n this.#pos.y - previousPos.y :\n 0;\n\n if (!this.#dragging) {\n this.#dragging = true;\n this.#currentSortable = this.node;\n this.#startIndex = this.items().indexOf(this.#target);\n this.#currentIndex = this.#startIndex;\n\n $.setDataset(this.node, { uiDragging: true });\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: this.node,\n to: this.node,\n oldIndex: this.#startIndex,\n newIndex: this.#startIndex,\n };\n\n triggerSortableEvent(this.node, 'sort', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.addClass(this.#target, this.options.helperClass);\n }\n }\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n };\n\n const upEvent = (event) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (event.type === 'mouseup') {\n event.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);\n\n $.addEventDelegate(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n this.#selector,\n dragEvent,\n );\n\n $.addEvent(this.node, 'receive.ui.sortable', () => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null && this.#scrollFrame !== undefined) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null && this.#scrollFrame !== undefined\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame(() => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"frost-ui-sortable.min.js","names":["$","$","BaseComponent","getPosition","factory","global","exports","__create","__defProp","__getOwnPropDesc","__getOwnPropNames","__getProtoOf","__hasOwnProp","__copyProps","from","keys","i","n","key","to","except","k","desc","mod","target","_fr0st_query","cursorLocks","resetCursor","node","nodes","release","setCursor","cursor","triggerSortableEvent","name","data","document","window","Sortable","_fr0st_ui","options","#selector","#dragging","#enabled","#initialCursorNodes","#events","error","#target","#resetDrag","#scrollFrame","#pos","originalX","originalY","windowHeight","windowWidth","offsetX","offsetY","docHeight","maxY","docWidth","maxX","deltaX","deltaY","#updatePlacement","#scheduleScroll","dragHandler","cancelled","event","previousPos","#currentSortable","#startIndex","#currentIndex","eventData","source","destination","#checkScroll","nearestSortable","connected","sortable","nearestInstance","nearestItems","nearestItem","#updateTarget","newIndex","previousSortable","handle","nearestCenter","nearestRect","targetCenter","threshold","thresholdX","thresholdY","method","y","x","swapX","swapY","src_default"],"sources":["../src/helpers.js","../src/sortable.js","../src/index.js"],"sourcesContent":["/** @import { SortableEventData } from './sortable.js'; */\n\nimport $ from '@fr0st/query';\n\nconst cursorLocks = new WeakMap();\n\n/**\n * Resets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to restore.\n */\nexport function resetCursor(nodes) {\n for (const node of nodes) {\n const release = cursorLocks.get(node);\n\n if (!release) {\n continue;\n }\n\n release();\n cursorLocks.delete(node);\n }\n}\n\n/**\n * Sets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to update.\n * @param {string} cursor The cursor style.\n */\nexport function setCursor(nodes, cursor) {\n for (const node of nodes) {\n if (cursorLocks.has(node)) {\n $.setStyle(node, { cursor });\n } else {\n cursorLocks.set(node, $.setStyleLock(node, 'cursor', cursor));\n }\n }\n}\n\n/**\n * Triggers a Sortable event with its data and detail payloads.\n * @param {HTMLElement} node The event target.\n * @param {string} name The event name without its namespace.\n * @param {SortableEventData} data The sorting event data.\n */\nexport function triggerSortableEvent(node, name, data) {\n $.triggerEvent(node, `${name}.ui.sortable`, {\n data,\n detail: {\n target: data.item,\n ...data,\n },\n });\n}\n","import $ from '@fr0st/query';\nimport { BaseComponent, getPosition } from '@fr0st/ui';\nimport { resetCursor, setCursor, triggerSortableEvent } from './helpers.js';\n\nconst document = $.getContext();\nconst window = $.getWindow();\n\n/** @typedef {'x'|'y'} SortableAxis */\n\n/**\n * @typedef {object} SortableOptions\n * @property {SortableAxis|null} [axis=null] The axis used to determine item placement.\n * @property {string} [cancel='input, textarea, button, select, option'] The selector for elements that cannot start a sort.\n * @property {string|null} [connectWith=null] The selector for connected Sortable containers.\n * @property {string} [cursor='auto'] The cursor applied to sortable items or handles.\n * @property {boolean} [disabled=false] Whether sorting is initially disabled.\n * @property {boolean} [dropOnEmpty=true] Whether connected empty containers accept items.\n * @property {string|null} [handle=null] The handle selector within each sortable item.\n * @property {string|null} [helperClass='bg-body-tertiary'] The class applied to an item while it is being sorted.\n * @property {string} [items=':scope > li'] The selector for sortable items.\n * @property {boolean} [scroll=true] Whether to scroll the window while sorting near an edge.\n * @property {number} [scrollSensitivity=20] The distance from a window edge that starts scrolling, in pixels.\n * @property {number} [scrollSpeed=5] The scroll distance applied per animation frame, in pixels.\n * @property {number} [swapThreshold=0.25] The fraction of an item crossed before swapping, from `0` to `1`.\n */\n\n/**\n * @typedef {object} SortableEventData\n * @property {HTMLElement} item The item being sorted.\n * @property {HTMLElement} from The previous or original Sortable container.\n * @property {HTMLElement} to The next or final Sortable container.\n * @property {number} oldIndex The previous or original item index.\n * @property {number} newIndex The next or final item index.\n */\n\n/**\n * Controls a sortable collection of elements.\n * @augments {BaseComponent<SortableOptions>}\n */\nexport default class Sortable extends BaseComponent {\n /** @type {SortableOptions} */\n static defaults = {\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 swapThreshold: 0.25,\n };\n\n #currentIndex;\n #currentSortable = null;\n #dragging;\n #enabled;\n #initialCursorNodes = [];\n #pos = null;\n #scrollFrame = null;\n #selector;\n #startIndex;\n #target = null;\n\n /**\n * Creates a Sortable.\n * @param {HTMLElement} node The sortable container.\n * @param {SortableOptions} [options] The Sortable options.\n */\n constructor(node, options) {\n super(node, options);\n\n try {\n this.#selector = this.options.handle ?\n `:is(${this.options.items}) :is(${this.options.handle})` :\n this.options.items;\n\n this.#dragging = false;\n this.#enabled = !this.options.disabled;\n\n this.#initialCursorNodes = $.find(this.#selector, this.node);\n setCursor(this.#initialCursorNodes, this.options.cursor);\n this.#events();\n this.#initialCursorNodes = null;\n } catch (error) {\n this.dispose();\n throw error;\n }\n }\n\n /**\n * Disables the Sortable.\n */\n disable() {\n this.#enabled = false;\n }\n\n /** @inheritdoc */\n dispose() {\n if (!this.node) {\n return;\n }\n\n resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));\n\n if (this.#target && this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n this.#resetDrag();\n\n this.#initialCursorNodes = null;\n\n super.dispose();\n }\n\n /**\n * Enables the Sortable.\n */\n enable() {\n this.#enabled = true;\n }\n\n /**\n * Gets the Sortable item elements.\n * @returns {HTMLElement[]} The Sortable item elements.\n */\n items() {\n return $.find(this.options.items, this.node);\n }\n\n /**\n * Checks whether the window should scroll while sorting.\n */\n #checkScroll() {\n this.#scrollFrame = null;\n\n if (!this.node || !this.#dragging || !this.#target || !this.#pos) {\n return;\n }\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n const windowHeight = $.height(window);\n const windowWidth = $.width(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 + windowHeight - this.options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n const maxY = Math.max(0, docHeight - windowHeight);\n offsetY = Math.min(maxY, 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 + windowWidth - this.options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n const maxX = Math.max(0, docWidth - windowWidth);\n offsetX = Math.min(maxX, originalX + this.options.scrollSpeed);\n }\n\n if (offsetX === originalX && offsetY === originalY) {\n return;\n }\n\n window.scrollTo({\n left: offsetX,\n top: offsetY,\n behavior: 'instant',\n });\n\n const deltaX = offsetX - originalX;\n const deltaY = offsetY - originalY;\n\n this.#pos.x += deltaX;\n this.#pos.y += deltaY;\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n }\n\n /**\n * Attaches events for the Sortable.\n */\n #events() {\n const downHandler = (event) => {\n const cancelled = this.options.cancel &&\n (\n $.is(event.target, this.options.cancel) ||\n $.is(event.currentTarget, this.options.cancel) ||\n $.closest(event.target, this.options.cancel, this.node).length\n );\n\n if (\n event.button ||\n !this.#enabled ||\n cancelled ||\n $.getDataset(this.node, 'uiDragging')\n ) {\n return false;\n }\n\n this.#target = this.options.handle ?\n this.items().find((node) => $.hasDescendent(node, event.currentTarget)) :\n event.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveHandler = (event) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(event);\n const deltaX = previousPos ?\n this.#pos.x - previousPos.x :\n 0;\n const deltaY = previousPos ?\n this.#pos.y - previousPos.y :\n 0;\n\n if (!this.#dragging) {\n this.#dragging = true;\n this.#currentSortable = this.node;\n this.#startIndex = this.items().indexOf(this.#target);\n this.#currentIndex = this.#startIndex;\n\n $.setDataset(this.node, { uiDragging: true });\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: this.node,\n to: this.node,\n oldIndex: this.#startIndex,\n newIndex: this.#startIndex,\n };\n\n triggerSortableEvent(this.node, 'sort', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.addClass(this.#target, this.options.helperClass);\n }\n }\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n };\n\n const upHandler = (event) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (event.type === 'mouseup') {\n event.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragHandler = $.mouseDragFactory(downHandler, moveHandler, upHandler);\n\n this.listen(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n dragHandler,\n { delegate: this.#selector },\n );\n\n this.listen(this.node, 'receive.ui.sortable', () => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame(() => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fr0st/ui-sortable",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Drag-and-drop sortable lists for Frost UI with handles, connected containers, axis control, and automatic scrolling.",
|
|
6
6
|
"keywords": [
|
|
@@ -56,12 +56,17 @@
|
|
|
56
56
|
],
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@fr0st/eslint-config": "^6.0.1",
|
|
59
|
-
"@fr0st/query": "^5.0.
|
|
60
|
-
"@fr0st/ui": "^4.0.
|
|
61
|
-
"@playwright/test": "^1.
|
|
62
|
-
"eslint": "^10.
|
|
63
|
-
"monocart-reporter": "
|
|
64
|
-
"vite": "^8.3.
|
|
59
|
+
"@fr0st/query": "^5.0.2",
|
|
60
|
+
"@fr0st/ui": "^4.0.3",
|
|
61
|
+
"@playwright/test": "^1.64.1",
|
|
62
|
+
"eslint": "^10.13.0",
|
|
63
|
+
"monocart-reporter": "2.14.0",
|
|
64
|
+
"vite": "^8.3.5"
|
|
65
|
+
},
|
|
66
|
+
"overrides": {
|
|
67
|
+
"monocart-reporter": {
|
|
68
|
+
"monocart-coverage-reports": "2.13.0"
|
|
69
|
+
}
|
|
65
70
|
},
|
|
66
71
|
"peerDependencies": {
|
|
67
72
|
"@fr0st/query": "^5.0.0",
|
package/src/sortable.js
CHANGED
|
@@ -56,15 +56,15 @@ export default class Sortable extends BaseComponent {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
#currentIndex;
|
|
59
|
-
#currentSortable;
|
|
59
|
+
#currentSortable = null;
|
|
60
60
|
#dragging;
|
|
61
61
|
#enabled;
|
|
62
62
|
#initialCursorNodes = [];
|
|
63
|
-
#pos;
|
|
64
|
-
#scrollFrame;
|
|
63
|
+
#pos = null;
|
|
64
|
+
#scrollFrame = null;
|
|
65
65
|
#selector;
|
|
66
66
|
#startIndex;
|
|
67
|
-
#target;
|
|
67
|
+
#target = null;
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
70
|
* Creates a Sortable.
|
|
@@ -105,8 +105,6 @@ export default class Sortable extends BaseComponent {
|
|
|
105
105
|
return;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
$.removeEventDelegate(this.node, 'mousedown.ui.sortable touchstart.ui.sortable');
|
|
109
|
-
$.removeEvent(this.node, 'receive.ui.sortable');
|
|
110
108
|
resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));
|
|
111
109
|
|
|
112
110
|
if (this.#target && this.options.helperClass) {
|
|
@@ -193,7 +191,7 @@ export default class Sortable extends BaseComponent {
|
|
|
193
191
|
* Attaches events for the Sortable.
|
|
194
192
|
*/
|
|
195
193
|
#events() {
|
|
196
|
-
const
|
|
194
|
+
const downHandler = (event) => {
|
|
197
195
|
const cancelled = this.options.cancel &&
|
|
198
196
|
(
|
|
199
197
|
$.is(event.target, this.options.cancel) ||
|
|
@@ -219,7 +217,7 @@ export default class Sortable extends BaseComponent {
|
|
|
219
217
|
}
|
|
220
218
|
};
|
|
221
219
|
|
|
222
|
-
const
|
|
220
|
+
const moveHandler = (event) => {
|
|
223
221
|
if (!this.node || !this.#target) {
|
|
224
222
|
return;
|
|
225
223
|
}
|
|
@@ -265,7 +263,7 @@ export default class Sortable extends BaseComponent {
|
|
|
265
263
|
this.#scheduleScroll();
|
|
266
264
|
};
|
|
267
265
|
|
|
268
|
-
const
|
|
266
|
+
const upHandler = (event) => {
|
|
269
267
|
if (!this.node) {
|
|
270
268
|
return;
|
|
271
269
|
}
|
|
@@ -315,16 +313,16 @@ export default class Sortable extends BaseComponent {
|
|
|
315
313
|
}
|
|
316
314
|
};
|
|
317
315
|
|
|
318
|
-
const
|
|
316
|
+
const dragHandler = $.mouseDragFactory(downHandler, moveHandler, upHandler);
|
|
319
317
|
|
|
320
|
-
|
|
318
|
+
this.listen(
|
|
321
319
|
this.node,
|
|
322
320
|
'mousedown.ui.sortable touchstart.ui.sortable',
|
|
323
|
-
|
|
324
|
-
|
|
321
|
+
dragHandler,
|
|
322
|
+
{ delegate: this.#selector },
|
|
325
323
|
);
|
|
326
324
|
|
|
327
|
-
|
|
325
|
+
this.listen(this.node, 'receive.ui.sortable', () => {
|
|
328
326
|
setCursor($.find(this.#selector, this.node), this.options.cursor);
|
|
329
327
|
});
|
|
330
328
|
}
|
|
@@ -333,7 +331,7 @@ export default class Sortable extends BaseComponent {
|
|
|
333
331
|
* Resets the active drag state.
|
|
334
332
|
*/
|
|
335
333
|
#resetDrag() {
|
|
336
|
-
if (this.#scrollFrame !== null
|
|
334
|
+
if (this.#scrollFrame !== null) {
|
|
337
335
|
window.cancelAnimationFrame(this.#scrollFrame);
|
|
338
336
|
}
|
|
339
337
|
|
|
@@ -358,7 +356,7 @@ export default class Sortable extends BaseComponent {
|
|
|
358
356
|
!this.node ||
|
|
359
357
|
!this.options.scroll ||
|
|
360
358
|
!this.#dragging ||
|
|
361
|
-
this.#scrollFrame !== null
|
|
359
|
+
this.#scrollFrame !== null
|
|
362
360
|
) {
|
|
363
361
|
return;
|
|
364
362
|
}
|