@fr0st/ui-sortable 3.0.1 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -92,15 +92,15 @@ var Sortable = class extends BaseComponent {
92
92
  swapThreshold: .25
93
93
  };
94
94
  #currentIndex;
95
- #currentSortable;
95
+ #currentSortable = null;
96
96
  #dragging;
97
97
  #enabled;
98
98
  #initialCursorNodes = [];
99
- #pos;
100
- #scrollFrame;
99
+ #pos = null;
100
+ #scrollFrame = null;
101
101
  #selector;
102
102
  #startIndex;
103
- #target;
103
+ #target = null;
104
104
  /**
105
105
  * Creates a Sortable.
106
106
  * @param {HTMLElement} node The sortable container.
@@ -130,8 +130,6 @@ var Sortable = class extends BaseComponent {
130
130
  /** @inheritdoc */
131
131
  dispose() {
132
132
  if (!this.node) return;
133
- $.removeEventDelegate(this.node, "mousedown.ui.sortable touchstart.ui.sortable");
134
- $.removeEvent(this.node, "receive.ui.sortable");
135
133
  resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));
136
134
  if (this.#target && this.options.helperClass) $.removeClass(this.#target, this.options.helperClass);
137
135
  this.#resetDrag();
@@ -192,13 +190,13 @@ var Sortable = class extends BaseComponent {
192
190
  * Attaches events for the Sortable.
193
191
  */
194
192
  #events() {
195
- const downEvent = (event) => {
193
+ const downHandler = (event) => {
196
194
  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
195
  if (event.button || !this.#enabled || cancelled || $.getDataset(this.node, "uiDragging")) return false;
198
196
  this.#target = this.options.handle ? this.items().find((node) => $.hasDescendent(node, event.currentTarget)) : event.currentTarget;
199
197
  if (!this.#target) return false;
200
198
  };
201
- const moveEvent = (event) => {
199
+ const moveHandler = (event) => {
202
200
  if (!this.node || !this.#target) return;
203
201
  const previousPos = this.#pos;
204
202
  this.#pos = getPosition(event);
@@ -225,7 +223,7 @@ var Sortable = class extends BaseComponent {
225
223
  this.#updatePlacement(deltaX, deltaY);
226
224
  this.#scheduleScroll();
227
225
  };
228
- const upEvent = (event) => {
226
+ const upHandler = (event) => {
229
227
  if (!this.node) return;
230
228
  if (!this.#dragging) {
231
229
  this.#target = null;
@@ -251,9 +249,9 @@ var Sortable = class extends BaseComponent {
251
249
  } else if (this.#currentIndex !== this.#startIndex) triggerSortableEvent(destination, "update", eventData);
252
250
  if (this.node) this.#resetDrag();
253
251
  };
254
- const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);
255
- $.addEventDelegate(this.node, "mousedown.ui.sortable touchstart.ui.sortable", this.#selector, dragEvent);
256
- $.addEvent(this.node, "receive.ui.sortable", () => {
252
+ const dragHandler = $.mouseDragFactory(downHandler, moveHandler, upHandler);
253
+ this.listen(this.node, "mousedown.ui.sortable touchstart.ui.sortable", dragHandler, { delegate: this.#selector });
254
+ this.listen(this.node, "receive.ui.sortable", () => {
257
255
  setCursor($.find(this.#selector, this.node), this.options.cursor);
258
256
  });
259
257
  }
@@ -261,7 +259,7 @@ var Sortable = class extends BaseComponent {
261
259
  * Resets the active drag state.
262
260
  */
263
261
  #resetDrag() {
264
- if (this.#scrollFrame !== null && this.#scrollFrame !== void 0) window.cancelAnimationFrame(this.#scrollFrame);
262
+ if (this.#scrollFrame !== null) window.cancelAnimationFrame(this.#scrollFrame);
265
263
  if (this.#dragging && this.node) $.removeDataset(this.node, "uiDragging");
266
264
  this.#currentIndex = null;
267
265
  this.#currentSortable = null;
@@ -275,7 +273,7 @@ var Sortable = class extends BaseComponent {
275
273
  * Schedules the next auto-scroll update.
276
274
  */
277
275
  #scheduleScroll() {
278
- if (!this.node || !this.options.scroll || !this.#dragging || this.#scrollFrame !== null && this.#scrollFrame !== void 0) return;
276
+ if (!this.node || !this.options.scroll || !this.#dragging || this.#scrollFrame !== null) return;
279
277
  this.#scrollFrame = window.requestAnimationFrame(() => {
280
278
  this.#checkScroll();
281
279
  });
@@ -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&&(r.removeEventDelegate(this.node,`mousedown.ui.sortable touchstart.ui.sortable`),r.removeEvent(this.node,`receive.ui.sortable`),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())});r.addEventDelegate(this.node,`mousedown.ui.sortable touchstart.ui.sortable`,this.#s,e),r.addEvent(this.node,`receive.ui.sortable`,()=>{o(r.find(this.#s,this.node),this.options.cursor)})}#f(){this.#o!==null&&this.#o!==void 0&&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===void 0)&&(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};
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":"0GAIA,IAAMC,kBAAc,IAAI,QAMxB,SAAgBC,EAAY,EAAO,CAC/B,IAAK,IAAMC,KAAQC,EAAO,CACtB,IAAMC,EAAUJ,EAAY,IAAIE,CAAI,EAE/BE,IAILA,EAAQ,EACRJ,EAAY,OAAOE,CAAI,EAC3B,CACJ,CAOA,SAAgBG,EAAU,EAAO,EAAQ,CACrC,IAAK,IAAMH,KAAQC,EACXH,EAAY,IAAIE,CAAI,EACpBH,EAAE,SAASG,EAAM,CAAE,QAAO,CAAC,EAE3BF,EAAY,IAAIE,EAAMH,EAAE,aAAaG,EAAM,SAAUI,CAAM,CAAC,CAGxE,CAQA,SAAgBC,EAAqB,EAAM,EAAM,EAAM,CACnDR,EAAE,aAAaG,EAAM,GAAGM,EAAK,cAAe,CACxC,OACA,OAAQ,CACJ,OAAQC,EAAK,KACb,GAAGA,CACP,CACJ,CAAC,CACL,CChDA,IAAMC,EAAWX,EAAE,WAAW,EACxBY,EAASZ,EAAE,UAAU,EAkCNa,EAArB,cAAsCC,CAAc,CAEhD,OAAO,SAAW,CACd,KAAM,KACN,OAAQ,0CACR,YAAa,KACb,OAAQ,OACR,SAAU,GACV,YAAa,GACb,OAAQ,KACR,YAAa,mBACb,MAAO,cACP,OAAQ,GACR,kBAAmB,GACnB,YAAa,EACb,cAAe,GACnB,EAEA,GACA,GACA,GACA,GACA,GAAsB,CAAC,EACvB,GACA,GACA,GACA,GACA,GAOA,YAAY,EAAM,EAAS,CACvB,MAAMX,EAAMY,CAAO,EAEnB,GAAI,CACA,KAAKC,GAAY,KAAK,QAAQ,OAC1B,OAAO,KAAK,QAAQ,MAAM,QAAQ,KAAK,QAAQ,OAAO,GACtD,KAAK,QAAQ,MAEjB,KAAKC,GAAY,GACjB,KAAKC,GAAW,CAAC,KAAK,QAAQ,SAE9B,KAAKC,GAAsBnB,EAAE,KAAK,KAAKgB,GAAW,KAAK,IAAI,EAC3DV,EAAU,KAAKa,GAAqB,KAAK,QAAQ,MAAM,EACvD,KAAKC,GAAQ,EACb,KAAKD,GAAsB,IAC/B,OAASE,EAAO,CAEZ,MADA,KAAK,QAAQ,EACPA,CACV,CACJ,CAKA,SAAU,CACN,KAAKH,GAAW,EACpB,CAGA,SAAU,CACD,KAAK,OAIVlB,EAAE,oBAAoB,KAAK,KAAM,8CAA8C,EAC/EA,EAAE,YAAY,KAAK,KAAM,qBAAqB,EAC9CE,EAAY,KAAKiB,IAAuBnB,EAAE,KAAK,KAAKgB,GAAW,KAAK,IAAI,CAAC,EAErE,KAAKM,IAAW,KAAK,QAAQ,aAC7BtB,EAAE,YAAY,KAAKsB,GAAS,KAAK,QAAQ,WAAW,EAGxD,KAAKC,GAAW,EAEhB,KAAKJ,GAAsB,KAE3B,MAAM,QAAQ,EAClB,CAKA,QAAS,CACL,KAAKD,GAAW,EACpB,CAMA,OAAQ,CACJ,OAAOlB,EAAE,KAAK,KAAK,QAAQ,MAAO,KAAK,IAAI,CAC/C,CAKA,IAAe,CAGX,GAFA,KAAKwB,GAAe,KAEhB,CAAC,KAAK,MAAQ,CAAC,KAAKP,IAAa,CAAC,KAAKK,IAAW,CAAC,KAAKG,GACxD,OAGJ,IAAMC,EAAY1B,EAAE,WAAWY,CAAM,EAC/Be,EAAY3B,EAAE,WAAWY,CAAM,EAC/BgB,EAAe5B,EAAE,OAAOY,CAAM,EAC9BiB,EAAc7B,EAAE,MAAMY,CAAM,EAE9BkB,EAAUJ,EACVK,EAAUJ,EAEd,GAAI,KAAKF,GAAK,EAAIE,EAAY,KAAK,QAAQ,kBACvC,EAAU,KAAK,IAAI,EAAGA,EAAY,KAAK,QAAQ,WAAW,OACvD,GAAI,KAAKF,GAAK,EAAIE,EAAYC,EAAe,KAAK,QAAQ,kBAAmB,CAChF,IAAMI,EAAYhC,EAAE,OAAOW,EAAU,CAAE,QAASX,EAAE,UAAW,CAAC,EACxDiC,EAAO,KAAK,IAAI,EAAGD,EAAYJ,CAAY,EACjD,EAAU,KAAK,IAAIK,EAAMN,EAAY,KAAK,QAAQ,WAAW,CACjE,CAEA,GAAI,KAAKF,GAAK,EAAIC,EAAY,KAAK,QAAQ,kBACvC,EAAU,KAAK,IAAI,EAAGA,EAAY,KAAK,QAAQ,WAAW,OACvD,GAAI,KAAKD,GAAK,EAAIC,EAAYG,EAAc,KAAK,QAAQ,kBAAmB,CAC/E,IAAMK,EAAWlC,EAAE,MAAMW,EAAU,CAAE,QAASX,EAAE,UAAW,CAAC,EACtDmC,EAAO,KAAK,IAAI,EAAGD,EAAWL,CAAW,EAC/C,EAAU,KAAK,IAAIM,EAAMT,EAAY,KAAK,QAAQ,WAAW,CACjE,CAEA,GAAII,IAAYJ,GAAaK,IAAYJ,EACrC,OAGJf,EAAO,SAAS,CACZ,KAAMkB,EACN,IAAKC,EACL,SAAU,SACd,CAAC,EAED,IAAMK,EAASN,EAAUJ,EACnBW,EAASN,EAAUJ,EAEzB,KAAKF,GAAK,GAAKW,EACf,KAAKX,GAAK,GAAKY,EAEf,KAAKC,GAAiBF,EAAQC,CAAM,EACpC,KAAKE,GAAgB,CACzB,CAKA,IAAU,CA2HN,IAAMC,EAAYxC,EAAE,iBA1HD,GAAU,CACzB,IAAMyC,EAAY,KAAK,QAAQ,SAEvBzC,EAAE,GAAG0C,EAAM,OAAQ,KAAK,QAAQ,MAAM,GACtC1C,EAAE,GAAG0C,EAAM,cAAe,KAAK,QAAQ,MAAM,GAC7C1C,EAAE,QAAQ0C,EAAM,OAAQ,KAAK,QAAQ,OAAQ,KAAK,IAAI,CAAC,CAAC,QAgBhE,GAZIA,EAAM,QACN,CAAC,KAAKxB,IACNuB,GACAzC,EAAE,WAAW,KAAK,KAAM,YAAY,IAKxC,KAAKsB,GAAU,KAAK,QAAQ,OACxB,KAAK,MAAM,CAAC,CAAC,KAAM,GAAStB,EAAE,cAAcG,EAAMuC,EAAM,aAAa,CAAC,EACtEA,EAAM,cAEN,CAAC,KAAKpB,IACN,MAAO,EAEf,EAEmB,GAAU,CACzB,GAAI,CAAC,KAAK,MAAQ,CAAC,KAAKA,GACpB,OAGJ,IAAMqB,EAAc,KAAKlB,GACzB,KAAKA,GAAOmB,EAAYF,CAAK,EAC7B,IAAMN,EAASO,EACX,KAAKlB,GAAK,EAAIkB,EAAY,EAC1B,EACEN,EAASM,EACX,KAAKlB,GAAK,EAAIkB,EAAY,EAC1B,EAEJ,GAAI,CAAC,KAAK1B,GAAW,CACjB,KAAKA,GAAY,GACjB,KAAK4B,GAAmB,KAAK,KAC7B,KAAKC,GAAc,KAAK,MAAM,CAAC,CAAC,QAAQ,KAAKxB,EAAO,EACpD,KAAKyB,GAAgB,KAAKD,GAE1B9C,EAAE,WAAW,KAAK,KAAM,CAAE,WAAY,EAAK,CAAC,EAG5C,IAAMgD,EAAY,CACd,KAAM,KAAK1B,GACX,KAAM,KAAK,KACX,GAAI,KAAK,KACT,SAAU,KAAKwB,GACf,SAAU,KAAKA,EACnB,EAIA,GAFAtC,EAAqB,KAAK,KAAM,OAAQwC,CAAS,EAE7C,CAAC,KAAK,KACN,OAGA,KAAK,QAAQ,aACbhD,EAAE,SAAS,KAAKsB,GAAS,KAAK,QAAQ,WAAW,CAEzD,CAEA,KAAKgB,GAAiBF,EAAQC,CAAM,EACpC,KAAKE,GAAgB,CACzB,EAEiB,GAAU,CACvB,GAAI,CAAC,KAAK,KACN,OAGJ,GAAI,CAAC,KAAKtB,GAAW,CACjB,KAAKK,GAAU,KACf,MACJ,CAEIoB,EAAM,OAAS,WACfA,EAAM,eAAe,EAGzB,IAAMO,EAAS,KAAK,KACdC,EAAc,KAAKL,GAEnBG,EAAY,CACd,KAAM,KAAK1B,GACX,KAAM2B,EACN,GAAIC,EACJ,SAAU,KAAKJ,GACf,SAAU,KAAKC,EACnB,EAEAvC,EAAqB0C,EAAa,SAAUF,CAAS,EAEhD,KAAK,OAIN,KAAK,QAAQ,aACbhD,EAAE,YAAY,KAAKsB,GAAS,KAAK,QAAQ,WAAW,EAGpD2B,IAAWC,EAMJ,KAAKH,KAAkB,KAAKD,IACnCtC,EAAqB0C,EAAa,SAAUF,CAAS,GANrDxC,EAAqByC,EAAQ,SAAUD,CAAS,EAE5C,KAAK,MACLxC,EAAqB0C,EAAa,SAAUF,CAAS,GAMzD,KAAK,MACL,KAAKzB,GAAW,EAExB,CAEkE,EAElEvB,EAAE,iBACE,KAAK,KACL,+CACA,KAAKgB,GACLwB,CACJ,EAEAxC,EAAE,SAAS,KAAK,KAAM,0BAA6B,CAC/CM,EAAUN,EAAE,KAAK,KAAKgB,GAAW,KAAK,IAAI,EAAG,KAAK,QAAQ,MAAM,CACpE,CAAC,CACL,CAKA,IAAa,CACL,KAAKQ,KAAiB,MAAQ,KAAKA,KAAiB,IAAA,IACpDZ,EAAO,qBAAqB,KAAKY,EAAY,EAG7C,KAAKP,IAAa,KAAK,MACvBjB,EAAE,cAAc,KAAK,KAAM,YAAY,EAG3C,KAAK+C,GAAgB,KACrB,KAAKF,GAAmB,KACxB,KAAK5B,GAAY,GACjB,KAAKQ,GAAO,KACZ,KAAKD,GAAe,KACpB,KAAKsB,GAAc,KACnB,KAAKxB,GAAU,IACnB,CAKA,IAAkB,CAET,KAAK,MACL,KAAK,QAAQ,QACb,KAAKL,KACN,KAAKO,KAAiB,MAAQ,KAAKA,KAAiB,IAAA,MAKxD,KAAKA,GAAeZ,EAAO,0BAA4B,CACnD,KAAKuC,GAAa,CACtB,CAAC,EACL,CAOA,GAAiB,EAAQ,EAAQ,CAC7B,IAAIC,EAAkB,KAAK,KAE3B,GAAI,KAAK,QAAQ,YAAa,CAC1B,IAAMC,EAAYrD,EAAE,KAAK,KAAK,QAAQ,WAAW,CAAC,CAC7C,OAAQ,GAASG,IAAS,KAAK,IAAI,CAAC,CACpC,OAAQ,GAAS,CACd,IAAMmD,EAAW,KAAK,YAAY,KAAKnD,CAAI,EAE3C,OAAOmD,EAASpC,KACXoC,EAAS,QAAQ,aAAeA,EAAS,MAAM,CAAC,CAAC,OAC1D,CAAC,EAEDD,EAAU,SACV,EAAkBrD,EAAE,UAChB,CAAC,KAAK,KAAM,GAAGqD,CAAS,EACxB,KAAK5B,GAAK,EACV,KAAKA,GAAK,EACV,CAAE,OAAQ,EAAK,CACnB,EAER,CAEA,IAAM8B,EAAkB,KAAK,YAAY,KAAKH,CAAe,EACvDI,EAAeD,EAAgB,MAAM,CAAC,CACvC,OAAQ,GAASpD,IAAS,KAAKmB,EAAO,EACrCmC,EAAczD,EAAE,UAClBwD,EACA,KAAK/B,GAAK,EACV,KAAKA,GAAK,EACV,CAAE,OAAQ,EAAK,CACnB,EAEA,GAAIgC,EACA,KAAKC,GACDD,EACA,KAAKhC,GAAK,EACV,KAAKA,GAAK,EACVW,EACAC,CACJ,OACG,GAAIe,IAAoB,KAAKP,GAChC7C,EAAE,OAAOoD,EAAiB,KAAK9B,EAAO,OAEtC,OAGJ,IAAMqC,EAAWJ,EAAgB,MAAM,CAAC,CAAC,QAAQ,KAAKjC,EAAO,EAE7D,GAAI8B,IAAoB,KAAKP,GAAkB,CAC3C,IAAMe,EAAmB,KAAKf,GAExB,CAAE,UADiB,KAAK,YAAY,KAAKe,CACb,CAAC,CAAC,QAEpC1D,EAAY2D,EACR7D,EAAE,KAAK6D,EAAQ,KAAKvC,EAAO,EAC3B,CAAC,KAAKA,EAAO,CAAC,EAGlB,IAAM0B,EAAY,CACd,KAAM,KAAK1B,GACX,KAAMsC,EACN,GAAIR,EACJ,SAAU,KAAKL,GACf,UACJ,EAIA,GAFAvC,EAAqBoD,EAAkB,OAAQZ,CAAS,EAEpD,CAAC,KAAK,KACN,OAGJxC,EAAqB4C,EAAiB,UAAWJ,CAAS,CAC9D,MAAO,GAAI,KAAKD,KAAkBY,EAAU,CAExC,IAAMX,EAAY,CACd,KAAM,KAAK1B,GACX,KAAM8B,EACN,GAAIA,EACJ,SAAU,KAAKL,GACf,UACJ,EAEAvC,EAAqB4C,EAAiB,UAAWJ,CAAS,CAC9D,CAEK,KAAK,OAIV,KAAKD,GAAgBY,EACrB,KAAKd,GAAmBO,EAC5B,CAUA,GAAc,EAAa,EAAG,EAAG,EAAQ,EAAQ,CAC7C,IAAMU,EAAgB9D,EAAE,OAAOyD,EAAa,CAAE,OAAQ,EAAK,CAAC,EACtDM,EAAc/D,EAAE,KAAKyD,EAAa,CAAE,OAAQ,EAAK,CAAC,EAClDO,EAAehE,EAAE,OAAO,KAAKsB,GAAS,CAAE,OAAQ,EAAK,CAAC,EACtD2C,EAAY,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,KAAK,QAAQ,aAAa,CAAC,EACjEC,EAAa,GACbC,EAAa,GAEb/B,IACA,EAAaA,EAAS,EAClB6B,EACA,EAAIA,GAGR5B,IACA,EAAaA,EAAS,EAClB4B,EACA,EAAIA,GAGZ,IAAIG,EACJ,GAAI,KAAK,QAAQ,OAAS,KAAON,EAAc,IAAME,EAAa,EAE9D,EAASK,EADKN,EAAY,IAAMA,EAAY,OAASI,EAEjD,SACA,aACD,GAAI,KAAK,QAAQ,OAAS,KAAOL,EAAc,IAAME,EAAa,EAErE,EAASM,EADKP,EAAY,KAAOA,EAAY,MAAQG,EAEjD,SACA,YACD,CACH,IAAMK,EAAQR,EAAY,KAAOA,EAAY,MAAQG,EAC/CM,EAAQT,EAAY,IAAMA,EAAY,OAASI,EACrD,EAASG,EAAIC,GAASF,EAAIG,EACtB,SACA,OACR,CAEAxE,EAAEoE,EAAO,CAACX,EAAa,KAAKnC,EAAO,CACvC,CACJ,ECpgBAmD,EAAc,WAAY5D,CAAQ,EAElC,IAAA6D,EAAe7D"}
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":"A,0GAIA,IAAMC,kBAAc,IAAI,QAMxB,SAAgBC,EAAY,EAAO,CAC/B,IAAK,IAAMC,KAAQC,EAAO,CACtB,IAAMC,EAAUJ,EAAY,IAAIE,CAAI,EAE/BE,IAILA,EAAQ,EACRJ,EAAY,OAAOE,CAAI,EAC3B,CACJ,CAOA,SAAgBG,EAAU,EAAO,EAAQ,CACrC,IAAK,IAAMH,KAAQC,EACXH,EAAY,IAAIE,CAAI,EACpBH,EAAE,SAASG,EAAM,CAAE,QAAO,CAAC,EAE3BF,EAAY,IAAIE,EAAMH,EAAE,aAAaG,EAAM,SAAUI,CAAM,CAAC,CAGxE,CAQA,SAAgBC,EAAqB,EAAM,EAAM,EAAM,CACnDR,EAAE,aAAaG,EAAM,GAAGM,EAAK,cAAe,CACxC,OACA,OAAQ,CACJ,OAAQC,EAAK,KACb,GAAGA,CACP,CACJ,CAAC,CACL,CChDA,IAAMC,EAAWX,EAAE,WAAW,EACxBY,EAASZ,EAAE,UAAU,EAkCNa,EAArB,cAAsCC,CAAc,CAEhD,OAAO,SAAW,CACd,KAAM,KACN,OAAQ,0CACR,YAAa,KACb,OAAQ,OACR,SAAU,GACV,YAAa,GACb,OAAQ,KACR,YAAa,mBACb,MAAO,cACP,OAAQ,GACR,kBAAmB,GACnB,YAAa,EACb,cAAe,GACnB,EAEA,GACA,GAAmB,KACnB,GACA,GACA,GAAsB,CAAC,EACvB,GAAO,KACP,GAAe,KACf,GACA,GACA,GAAU,KAOV,YAAY,EAAM,EAAS,CACvB,MAAMX,EAAMY,CAAO,EAEnB,GAAI,CACA,KAAKC,GAAY,KAAK,QAAQ,OAC1B,OAAO,KAAK,QAAQ,MAAM,QAAQ,KAAK,QAAQ,OAAO,GACtD,KAAK,QAAQ,MAEjB,KAAKC,GAAY,GACjB,KAAKC,GAAW,CAAC,KAAK,QAAQ,SAE9B,KAAKC,GAAsBnB,EAAE,KAAK,KAAKgB,GAAW,KAAK,IAAI,EAC3DV,EAAU,KAAKa,GAAqB,KAAK,QAAQ,MAAM,EACvD,KAAKC,GAAQ,EACb,KAAKD,GAAsB,IAC/B,OAASE,EAAO,CAEZ,MADA,KAAK,QAAQ,EACPA,CACV,CACJ,CAKA,SAAU,CACN,KAAKH,GAAW,EACpB,CAGA,SAAU,CACD,KAAK,OAIVhB,EAAY,KAAKiB,IAAuBnB,EAAE,KAAK,KAAKgB,GAAW,KAAK,IAAI,CAAC,EAErE,KAAKM,IAAW,KAAK,QAAQ,aAC7BtB,EAAE,YAAY,KAAKsB,GAAS,KAAK,QAAQ,WAAW,EAGxD,KAAKC,GAAW,EAEhB,KAAKJ,GAAsB,KAE3B,MAAM,QAAQ,EAClB,CAKA,QAAS,CACL,KAAKD,GAAW,EACpB,CAMA,OAAQ,CACJ,OAAOlB,EAAE,KAAK,KAAK,QAAQ,MAAO,KAAK,IAAI,CAC/C,CAKA,IAAe,CAGX,GAFA,KAAKwB,GAAe,KAEhB,CAAC,KAAK,MAAQ,CAAC,KAAKP,IAAa,CAAC,KAAKK,IAAW,CAAC,KAAKG,GACxD,OAGJ,IAAMC,EAAY1B,EAAE,WAAWY,CAAM,EAC/Be,EAAY3B,EAAE,WAAWY,CAAM,EAC/BgB,EAAe5B,EAAE,OAAOY,CAAM,EAC9BiB,EAAc7B,EAAE,MAAMY,CAAM,EAE9BkB,EAAUJ,EACVK,EAAUJ,EAEd,GAAI,KAAKF,GAAK,EAAIE,EAAY,KAAK,QAAQ,kBACvC,EAAU,KAAK,IAAI,EAAGA,EAAY,KAAK,QAAQ,WAAW,OACvD,GAAI,KAAKF,GAAK,EAAIE,EAAYC,EAAe,KAAK,QAAQ,kBAAmB,CAChF,IAAMI,EAAYhC,EAAE,OAAOW,EAAU,CAAE,QAASX,EAAE,UAAW,CAAC,EACxDiC,EAAO,KAAK,IAAI,EAAGD,EAAYJ,CAAY,EACjD,EAAU,KAAK,IAAIK,EAAMN,EAAY,KAAK,QAAQ,WAAW,CACjE,CAEA,GAAI,KAAKF,GAAK,EAAIC,EAAY,KAAK,QAAQ,kBACvC,EAAU,KAAK,IAAI,EAAGA,EAAY,KAAK,QAAQ,WAAW,OACvD,GAAI,KAAKD,GAAK,EAAIC,EAAYG,EAAc,KAAK,QAAQ,kBAAmB,CAC/E,IAAMK,EAAWlC,EAAE,MAAMW,EAAU,CAAE,QAASX,EAAE,UAAW,CAAC,EACtDmC,EAAO,KAAK,IAAI,EAAGD,EAAWL,CAAW,EAC/C,EAAU,KAAK,IAAIM,EAAMT,EAAY,KAAK,QAAQ,WAAW,CACjE,CAEA,GAAII,IAAYJ,GAAaK,IAAYJ,EACrC,OAGJf,EAAO,SAAS,CACZ,KAAMkB,EACN,IAAKC,EACL,SAAU,SACd,CAAC,EAED,IAAMK,EAASN,EAAUJ,EACnBW,EAASN,EAAUJ,EAEzB,KAAKF,GAAK,GAAKW,EACf,KAAKX,GAAK,GAAKY,EAEf,KAAKC,GAAiBF,EAAQC,CAAM,EACpC,KAAKE,GAAgB,CACzB,CAKA,IAAU,CA2HN,IAAMC,EAAcxC,EAAE,iBA1HD,GAAU,CAC3B,IAAMyC,EAAY,KAAK,QAAQ,SAEvBzC,EAAE,GAAG0C,EAAM,OAAQ,KAAK,QAAQ,MAAM,GACtC1C,EAAE,GAAG0C,EAAM,cAAe,KAAK,QAAQ,MAAM,GAC7C1C,EAAE,QAAQ0C,EAAM,OAAQ,KAAK,QAAQ,OAAQ,KAAK,IAAI,CAAC,CAAC,QAgBhE,GAZIA,EAAM,QACN,CAAC,KAAKxB,IACNuB,GACAzC,EAAE,WAAW,KAAK,KAAM,YAAY,IAKxC,KAAKsB,GAAU,KAAK,QAAQ,OACxB,KAAK,MAAM,CAAC,CAAC,KAAM,GAAStB,EAAE,cAAcG,EAAMuC,EAAM,aAAa,CAAC,EACtEA,EAAM,cAEN,CAAC,KAAKpB,IACN,MAAO,EAEf,EAEqB,GAAU,CAC3B,GAAI,CAAC,KAAK,MAAQ,CAAC,KAAKA,GACpB,OAGJ,IAAMqB,EAAc,KAAKlB,GACzB,KAAKA,GAAOmB,EAAYF,CAAK,EAC7B,IAAMN,EAASO,EACX,KAAKlB,GAAK,EAAIkB,EAAY,EAC1B,EACEN,EAASM,EACX,KAAKlB,GAAK,EAAIkB,EAAY,EAC1B,EAEJ,GAAI,CAAC,KAAK1B,GAAW,CACjB,KAAKA,GAAY,GACjB,KAAK4B,GAAmB,KAAK,KAC7B,KAAKC,GAAc,KAAK,MAAM,CAAC,CAAC,QAAQ,KAAKxB,EAAO,EACpD,KAAKyB,GAAgB,KAAKD,GAE1B9C,EAAE,WAAW,KAAK,KAAM,CAAE,WAAY,EAAK,CAAC,EAG5C,IAAMgD,EAAY,CACd,KAAM,KAAK1B,GACX,KAAM,KAAK,KACX,GAAI,KAAK,KACT,SAAU,KAAKwB,GACf,SAAU,KAAKA,EACnB,EAIA,GAFAtC,EAAqB,KAAK,KAAM,OAAQwC,CAAS,EAE7C,CAAC,KAAK,KACN,OAGA,KAAK,QAAQ,aACbhD,EAAE,SAAS,KAAKsB,GAAS,KAAK,QAAQ,WAAW,CAEzD,CAEA,KAAKgB,GAAiBF,EAAQC,CAAM,EACpC,KAAKE,GAAgB,CACzB,EAEmB,GAAU,CACzB,GAAI,CAAC,KAAK,KACN,OAGJ,GAAI,CAAC,KAAKtB,GAAW,CACjB,KAAKK,GAAU,KACf,MACJ,CAEIoB,EAAM,OAAS,WACfA,EAAM,eAAe,EAGzB,IAAMO,EAAS,KAAK,KACdC,EAAc,KAAKL,GAEnBG,EAAY,CACd,KAAM,KAAK1B,GACX,KAAM2B,EACN,GAAIC,EACJ,SAAU,KAAKJ,GACf,SAAU,KAAKC,EACnB,EAEAvC,EAAqB0C,EAAa,SAAUF,CAAS,EAEhD,KAAK,OAIN,KAAK,QAAQ,aACbhD,EAAE,YAAY,KAAKsB,GAAS,KAAK,QAAQ,WAAW,EAGpD2B,IAAWC,EAMJ,KAAKH,KAAkB,KAAKD,IACnCtC,EAAqB0C,EAAa,SAAUF,CAAS,GANrDxC,EAAqByC,EAAQ,SAAUD,CAAS,EAE5C,KAAK,MACLxC,EAAqB0C,EAAa,SAAUF,CAAS,GAMzD,KAAK,MACL,KAAKzB,GAAW,EAExB,CAE0E,EAE1E,KAAK,OACD,KAAK,KACL,+CACAiB,EACA,CAAE,SAAU,KAAKxB,EAAU,CAC/B,EAEA,KAAK,OAAO,KAAK,KAAM,0BAA6B,CAChDV,EAAUN,EAAE,KAAK,KAAKgB,GAAW,KAAK,IAAI,EAAG,KAAK,QAAQ,MAAM,CACpE,CAAC,CACL,CAKA,IAAa,CACL,KAAKQ,KAAiB,MACtBZ,EAAO,qBAAqB,KAAKY,EAAY,EAG7C,KAAKP,IAAa,KAAK,MACvBjB,EAAE,cAAc,KAAK,KAAM,YAAY,EAG3C,KAAK+C,GAAgB,KACrB,KAAKF,GAAmB,KACxB,KAAK5B,GAAY,GACjB,KAAKQ,GAAO,KACZ,KAAKD,GAAe,KACpB,KAAKsB,GAAc,KACnB,KAAKxB,GAAU,IACnB,CAKA,IAAkB,CAET,KAAK,MACL,KAAK,QAAQ,QACb,KAAKL,IACN,KAAKO,KAAiB,OAK1B,KAAKA,GAAeZ,EAAO,0BAA4B,CACnD,KAAKuC,GAAa,CACtB,CAAC,EACL,CAOA,GAAiB,EAAQ,EAAQ,CAC7B,IAAIC,EAAkB,KAAK,KAE3B,GAAI,KAAK,QAAQ,YAAa,CAC1B,IAAMC,EAAYrD,EAAE,KAAK,KAAK,QAAQ,WAAW,CAAC,CAC7C,OAAQ,GAASG,IAAS,KAAK,IAAI,CAAC,CACpC,OAAQ,GAAS,CACd,IAAMmD,EAAW,KAAK,YAAY,KAAKnD,CAAI,EAE3C,OAAOmD,EAASpC,KACXoC,EAAS,QAAQ,aAAeA,EAAS,MAAM,CAAC,CAAC,OAC1D,CAAC,EAEDD,EAAU,SACV,EAAkBrD,EAAE,UAChB,CAAC,KAAK,KAAM,GAAGqD,CAAS,EACxB,KAAK5B,GAAK,EACV,KAAKA,GAAK,EACV,CAAE,OAAQ,EAAK,CACnB,EAER,CAEA,IAAM8B,EAAkB,KAAK,YAAY,KAAKH,CAAe,EACvDI,EAAeD,EAAgB,MAAM,CAAC,CACvC,OAAQ,GAASpD,IAAS,KAAKmB,EAAO,EACrCmC,EAAczD,EAAE,UAClBwD,EACA,KAAK/B,GAAK,EACV,KAAKA,GAAK,EACV,CAAE,OAAQ,EAAK,CACnB,EAEA,GAAIgC,EACA,KAAKC,GACDD,EACA,KAAKhC,GAAK,EACV,KAAKA,GAAK,EACVW,EACAC,CACJ,OACG,GAAIe,IAAoB,KAAKP,GAChC7C,EAAE,OAAOoD,EAAiB,KAAK9B,EAAO,OAEtC,OAGJ,IAAMqC,EAAWJ,EAAgB,MAAM,CAAC,CAAC,QAAQ,KAAKjC,EAAO,EAE7D,GAAI8B,IAAoB,KAAKP,GAAkB,CAC3C,IAAMe,EAAmB,KAAKf,GAExB,CAAE,UADiB,KAAK,YAAY,KAAKe,CACb,CAAC,CAAC,QAEpC1D,EAAY2D,EACR7D,EAAE,KAAK6D,EAAQ,KAAKvC,EAAO,EAC3B,CAAC,KAAKA,EAAO,CAAC,EAGlB,IAAM0B,EAAY,CACd,KAAM,KAAK1B,GACX,KAAMsC,EACN,GAAIR,EACJ,SAAU,KAAKL,GACf,UACJ,EAIA,GAFAvC,EAAqBoD,EAAkB,OAAQZ,CAAS,EAEpD,CAAC,KAAK,KACN,OAGJxC,EAAqB4C,EAAiB,UAAWJ,CAAS,CAC9D,MAAO,GAAI,KAAKD,KAAkBY,EAAU,CAExC,IAAMX,EAAY,CACd,KAAM,KAAK1B,GACX,KAAM8B,EACN,GAAIA,EACJ,SAAU,KAAKL,GACf,UACJ,EAEAvC,EAAqB4C,EAAiB,UAAWJ,CAAS,CAC9D,CAEK,KAAK,OAIV,KAAKD,GAAgBY,EACrB,KAAKd,GAAmBO,EAC5B,CAUA,GAAc,EAAa,EAAG,EAAG,EAAQ,EAAQ,CAC7C,IAAMU,EAAgB9D,EAAE,OAAOyD,EAAa,CAAE,OAAQ,EAAK,CAAC,EACtDM,EAAc/D,EAAE,KAAKyD,EAAa,CAAE,OAAQ,EAAK,CAAC,EAClDO,EAAehE,EAAE,OAAO,KAAKsB,GAAS,CAAE,OAAQ,EAAK,CAAC,EACtD2C,EAAY,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,KAAK,QAAQ,aAAa,CAAC,EACjEC,EAAa,GACbC,EAAa,GAEb/B,IACA,EAAaA,EAAS,EAClB6B,EACA,EAAIA,GAGR5B,IACA,EAAaA,EAAS,EAClB4B,EACA,EAAIA,GAGZ,IAAIG,EACJ,GAAI,KAAK,QAAQ,OAAS,KAAON,EAAc,IAAME,EAAa,EAE9D,EAASK,EADKN,EAAY,IAAMA,EAAY,OAASI,EAEjD,SACA,aACD,GAAI,KAAK,QAAQ,OAAS,KAAOL,EAAc,IAAME,EAAa,EAErE,EAASM,EADKP,EAAY,KAAOA,EAAY,MAAQG,EAEjD,SACA,YACD,CACH,IAAMK,EAAQR,EAAY,KAAOA,EAAY,MAAQG,EAC/CM,EAAQT,EAAY,IAAMA,EAAY,OAASI,EACrD,EAASG,EAAIC,GAASF,EAAIG,EACtB,SACA,OACR,CAEAxE,EAAEoE,EAAO,CAACX,EAAa,KAAKnC,EAAO,CACvC,CACJ,EClgBAmD,EAAc,WAAY5D,CAAQ,EAElC,IAAA6D,EAAe7D,E"}
@@ -1,6 +1,6 @@
1
1
  (function(global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fr0st/ui'), require('@fr0st/query')) :
3
- typeof define === 'function' && define.amd ? define(['exports', '@fr0st/ui', '@fr0st/query'], factory) :
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' });
@@ -124,15 +124,15 @@ _fr0st_query = __toESM(_fr0st_query, 1);
124
124
  swapThreshold: .25
125
125
  };
126
126
  #currentIndex;
127
- #currentSortable;
127
+ #currentSortable = null;
128
128
  #dragging;
129
129
  #enabled;
130
130
  #initialCursorNodes = [];
131
- #pos;
132
- #scrollFrame;
131
+ #pos = null;
132
+ #scrollFrame = null;
133
133
  #selector;
134
134
  #startIndex;
135
- #target;
135
+ #target = null;
136
136
  /**
137
137
  * Creates a Sortable.
138
138
  * @param {HTMLElement} node The sortable container.
@@ -162,8 +162,6 @@ _fr0st_query = __toESM(_fr0st_query, 1);
162
162
  /** @inheritdoc */
163
163
  dispose() {
164
164
  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
165
  resetCursor(this.#initialCursorNodes ?? _fr0st_query.default.find(this.#selector, this.node));
168
166
  if (this.#target && this.options.helperClass) _fr0st_query.default.removeClass(this.#target, this.options.helperClass);
169
167
  this.#resetDrag();
@@ -224,13 +222,13 @@ _fr0st_query = __toESM(_fr0st_query, 1);
224
222
  * Attaches events for the Sortable.
225
223
  */
226
224
  #events() {
227
- const downEvent = (event) => {
225
+ const downHandler = (event) => {
228
226
  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
227
  if (event.button || !this.#enabled || cancelled || _fr0st_query.default.getDataset(this.node, "uiDragging")) return false;
230
228
  this.#target = this.options.handle ? this.items().find((node) => _fr0st_query.default.hasDescendent(node, event.currentTarget)) : event.currentTarget;
231
229
  if (!this.#target) return false;
232
230
  };
233
- const moveEvent = (event) => {
231
+ const moveHandler = (event) => {
234
232
  if (!this.node || !this.#target) return;
235
233
  const previousPos = this.#pos;
236
234
  this.#pos = (0, _fr0st_ui.getPosition)(event);
@@ -257,7 +255,7 @@ _fr0st_query = __toESM(_fr0st_query, 1);
257
255
  this.#updatePlacement(deltaX, deltaY);
258
256
  this.#scheduleScroll();
259
257
  };
260
- const upEvent = (event) => {
258
+ const upHandler = (event) => {
261
259
  if (!this.node) return;
262
260
  if (!this.#dragging) {
263
261
  this.#target = null;
@@ -283,9 +281,9 @@ _fr0st_query = __toESM(_fr0st_query, 1);
283
281
  } else if (this.#currentIndex !== this.#startIndex) triggerSortableEvent(destination, "update", eventData);
284
282
  if (this.node) this.#resetDrag();
285
283
  };
286
- const dragEvent = _fr0st_query.default.mouseDragFactory(downEvent, moveEvent, upEvent);
287
- _fr0st_query.default.addEventDelegate(this.node, "mousedown.ui.sortable touchstart.ui.sortable", this.#selector, dragEvent);
288
- _fr0st_query.default.addEvent(this.node, "receive.ui.sortable", () => {
284
+ const dragHandler = _fr0st_query.default.mouseDragFactory(downHandler, moveHandler, upHandler);
285
+ this.listen(this.node, "mousedown.ui.sortable touchstart.ui.sortable", dragHandler, { delegate: this.#selector });
286
+ this.listen(this.node, "receive.ui.sortable", () => {
289
287
  setCursor(_fr0st_query.default.find(this.#selector, this.node), this.options.cursor);
290
288
  });
291
289
  }
@@ -293,7 +291,7 @@ _fr0st_query = __toESM(_fr0st_query, 1);
293
291
  * Resets the active drag state.
294
292
  */
295
293
  #resetDrag() {
296
- if (this.#scrollFrame !== null && this.#scrollFrame !== void 0) window.cancelAnimationFrame(this.#scrollFrame);
294
+ if (this.#scrollFrame !== null) window.cancelAnimationFrame(this.#scrollFrame);
297
295
  if (this.#dragging && this.node) _fr0st_query.default.removeDataset(this.node, "uiDragging");
298
296
  this.#currentIndex = null;
299
297
  this.#currentSortable = null;
@@ -307,7 +305,7 @@ _fr0st_query = __toESM(_fr0st_query, 1);
307
305
  * Schedules the next auto-scroll update.
308
306
  */
309
307
  #scheduleScroll() {
310
- if (!this.node || !this.options.scroll || !this.#dragging || this.#scrollFrame !== null && this.#scrollFrame !== void 0) return;
308
+ if (!this.node || !this.options.scroll || !this.#dragging || this.#scrollFrame !== null) return;
311
309
  this.#scrollFrame = window.requestAnimationFrame(() => {
312
310
  this.#checkScroll();
313
311
  });
@@ -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(t||!e||!e.__esModule||!c.call(e,`default`)?i(n,`default`,{value:e,enumerable:!0}):n,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;#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=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&&(n.default.removeEventDelegate(this.node,`mousedown.ui.sortable touchstart.ui.sortable`),n.default.removeEvent(this.node,`receive.ui.sortable`),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())});n.default.addEventDelegate(this.node,`mousedown.ui.sortable touchstart.ui.sortable`,this.#s,e),n.default.addEvent(this.node,`receive.ui.sortable`,()=>{f(n.default.find(this.#s,this.node),this.options.cursor)})}#f(){this.#o!==null&&this.#o!==void 0&&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===void 0)&&(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});
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":"C,uzBAIA,IAAM0B,kBAAc,IAAI,QAMxB,SAAgBC,EAAY,EAAO,CAC/B,IAAK,IAAMC,KAAQC,EAAO,CACtB,IAAMC,EAAUJ,EAAY,IAAIE,CAAI,EAE/BE,IAILA,EAAQ,EACRJ,EAAY,OAAOE,CAAI,EAC3B,CACJ,CAOA,SAAgBG,EAAU,EAAO,EAAQ,CACrC,IAAK,IAAMH,KAAQC,EACXH,EAAY,IAAIE,CAAI,EACpBH,EAAA,QAAE,SAASG,EAAM,CAAE,QAAO,CAAC,EAE3BF,EAAY,IAAIE,EAAM5B,EAAAA,QAAE,aAAa4B,EAAM,SAAUI,CAAM,CAAC,CAGxE,CAQA,SAAgBC,EAAqB,EAAM,EAAM,EAAM,CACnDR,EAAA,QAAE,aAAaG,EAAM,GAAGM,EAAK,cAAe,CACxC,OACA,OAAQ,CACJ,OAAQC,EAAK,KACb,GAAGA,CACP,CACJ,CAAC,CACL,CChDA,IAAMC,EAAWnC,EAAAA,QAAE,WAAW,EACxBoC,EAASpC,EAAAA,QAAE,UAAU,EAkCNqC,EAArB,cAAsCpC,EAAAA,aAAc,CAEhD,OAAO,SAAW,CACd,KAAM,KACN,OAAQ,0CACR,YAAa,KACb,OAAQ,OACR,SAAU,GACV,YAAa,GACb,OAAQ,KACR,YAAa,mBACb,MAAO,cACP,OAAQ,GACR,kBAAmB,GACnB,YAAa,EACb,cAAe,GACnB,EAEA,GACA,GAAmB,KACnB,GACA,GACA,GAAsB,CAAC,EACvB,GAAO,KACP,GAAe,KACf,GACA,GACA,GAAU,KAOV,YAAY,EAAM,EAAS,CACvB,MAAM0B,EAAMY,CAAO,EAEnB,GAAI,CACA,KAAKC,GAAY,KAAK,QAAQ,OAC1B,OAAO,KAAK,QAAQ,MAAM,QAAQ,KAAK,QAAQ,OAAO,GACtD,KAAK,QAAQ,MAEjB,KAAKC,GAAY,GACjB,KAAKC,GAAW,CAAC,KAAK,QAAQ,SAE9B,KAAKC,GAAsB3C,EAAAA,QAAE,KAAK,KAAKwC,GAAW,KAAK,IAAI,EAC3DV,EAAU,KAAKa,GAAqB,KAAK,QAAQ,MAAM,EACvD,KAAKC,GAAQ,EACb,KAAKD,GAAsB,IAC/B,OAASE,EAAO,CAEZ,MADA,KAAK,QAAQ,EACPA,CACV,CACJ,CAKA,SAAU,CACN,KAAKH,GAAW,EACpB,CAGA,SAAU,CACD,KAAK,OAIVhB,EAAY,KAAKiB,IAAuB3C,EAAAA,QAAE,KAAK,KAAKwC,GAAW,KAAK,IAAI,CAAC,EAErE,KAAKM,IAAW,KAAK,QAAQ,aAC7BtB,EAAA,QAAE,YAAY,KAAKsB,GAAS,KAAK,QAAQ,WAAW,EAGxD,KAAKC,GAAW,EAEhB,KAAKJ,GAAsB,KAE3B,MAAM,QAAQ,EAClB,CAKA,QAAS,CACL,KAAKD,GAAW,EACpB,CAMA,OAAQ,CACJ,OAAO1C,EAAAA,QAAE,KAAK,KAAK,QAAQ,MAAO,KAAK,IAAI,CAC/C,CAKA,IAAe,CAGX,GAFA,KAAKgD,GAAe,KAEhB,CAAC,KAAK,MAAQ,CAAC,KAAKP,IAAa,CAAC,KAAKK,IAAW,CAAC,KAAKG,GACxD,OAGJ,IAAMC,EAAYlD,EAAAA,QAAE,WAAWoC,CAAM,EAC/Be,EAAYnD,EAAAA,QAAE,WAAWoC,CAAM,EAC/BgB,EAAepD,EAAAA,QAAE,OAAOoC,CAAM,EAC9BiB,EAAcrD,EAAAA,QAAE,MAAMoC,CAAM,EAE9BkB,EAAUJ,EACVK,EAAUJ,EAEd,GAAI,KAAKF,GAAK,EAAIE,EAAY,KAAK,QAAQ,kBACvC,EAAU,KAAK,IAAI,EAAGA,EAAY,KAAK,QAAQ,WAAW,OACvD,GAAI,KAAKF,GAAK,EAAIE,EAAYC,EAAe,KAAK,QAAQ,kBAAmB,CAChF,IAAMI,EAAYxD,EAAAA,QAAE,OAAOmC,EAAU,CAAE,QAASnC,EAAAA,QAAE,UAAW,CAAC,EACxDyD,EAAO,KAAK,IAAI,EAAGD,EAAYJ,CAAY,EACjD,EAAU,KAAK,IAAIK,EAAMN,EAAY,KAAK,QAAQ,WAAW,CACjE,CAEA,GAAI,KAAKF,GAAK,EAAIC,EAAY,KAAK,QAAQ,kBACvC,EAAU,KAAK,IAAI,EAAGA,EAAY,KAAK,QAAQ,WAAW,OACvD,GAAI,KAAKD,GAAK,EAAIC,EAAYG,EAAc,KAAK,QAAQ,kBAAmB,CAC/E,IAAMK,EAAW1D,EAAAA,QAAE,MAAMmC,EAAU,CAAE,QAASnC,EAAAA,QAAE,UAAW,CAAC,EACtD2D,EAAO,KAAK,IAAI,EAAGD,EAAWL,CAAW,EAC/C,EAAU,KAAK,IAAIM,EAAMT,EAAY,KAAK,QAAQ,WAAW,CACjE,CAEA,GAAII,IAAYJ,GAAaK,IAAYJ,EACrC,OAGJf,EAAO,SAAS,CACZ,KAAMkB,EACN,IAAKC,EACL,SAAU,SACd,CAAC,EAED,IAAMK,EAASN,EAAUJ,EACnBW,EAASN,EAAUJ,EAEzB,KAAKF,GAAK,GAAKW,EACf,KAAKX,GAAK,GAAKY,EAEf,KAAKC,GAAiBF,EAAQC,CAAM,EACpC,KAAKE,GAAgB,CACzB,CAKA,IAAU,CA2HN,IAAMC,EAAchE,EAAAA,QAAE,iBA1HD,GAAU,CAC3B,IAAMiE,EAAY,KAAK,QAAQ,SAEvBjE,EAAAA,QAAE,GAAGkE,EAAM,OAAQ,KAAK,QAAQ,MAAM,GACtClE,EAAAA,QAAE,GAAGkE,EAAM,cAAe,KAAK,QAAQ,MAAM,GAC7ClE,EAAAA,QAAE,QAAQkE,EAAM,OAAQ,KAAK,QAAQ,OAAQ,KAAK,IAAI,CAAC,CAAC,QAgBhE,GAZIA,EAAM,QACN,CAAC,KAAKxB,IACNuB,GACAjE,EAAAA,QAAE,WAAW,KAAK,KAAM,YAAY,IAKxC,KAAK8C,GAAU,KAAK,QAAQ,OACxB,KAAK,MAAM,CAAC,CAAC,KAAM,GAAS9C,EAAAA,QAAE,cAAc2B,EAAMuC,EAAM,aAAa,CAAC,EACtEA,EAAM,cAEN,CAAC,KAAKpB,IACN,MAAO,EAEf,EAEqB,GAAU,CAC3B,GAAI,CAAC,KAAK,MAAQ,CAAC,KAAKA,GACpB,OAGJ,IAAMqB,EAAc,KAAKlB,GACzB,KAAKA,IAAA,EAAO/C,EAAAA,YAAAA,CAAYgE,CAAK,EAC7B,IAAMN,EAASO,EACX,KAAKlB,GAAK,EAAIkB,EAAY,EAC1B,EACEN,EAASM,EACX,KAAKlB,GAAK,EAAIkB,EAAY,EAC1B,EAEJ,GAAI,CAAC,KAAK1B,GAAW,CACjB,KAAKA,GAAY,GACjB,KAAK2B,GAAmB,KAAK,KAC7B,KAAKC,GAAc,KAAK,MAAM,CAAC,CAAC,QAAQ,KAAKvB,EAAO,EACpD,KAAKwB,GAAgB,KAAKD,GAE1B7C,EAAA,QAAE,WAAW,KAAK,KAAM,CAAE,WAAY,EAAK,CAAC,EAG5C,IAAM+C,EAAY,CACd,KAAM,KAAKzB,GACX,KAAM,KAAK,KACX,GAAI,KAAK,KACT,SAAU,KAAKuB,GACf,SAAU,KAAKA,EACnB,EAIA,GAFArC,EAAqB,KAAK,KAAM,OAAQuC,CAAS,EAE7C,CAAC,KAAK,KACN,OAGA,KAAK,QAAQ,aACb/C,EAAA,QAAE,SAAS,KAAKsB,GAAS,KAAK,QAAQ,WAAW,CAEzD,CAEA,KAAKgB,GAAiBF,EAAQC,CAAM,EACpC,KAAKE,GAAgB,CACzB,EAEmB,GAAU,CACzB,GAAI,CAAC,KAAK,KACN,OAGJ,GAAI,CAAC,KAAKtB,GAAW,CACjB,KAAKK,GAAU,KACf,MACJ,CAEIoB,EAAM,OAAS,WACfA,EAAM,eAAe,EAGzB,IAAMM,EAAS,KAAK,KACdC,EAAc,KAAKL,GAEnBG,EAAY,CACd,KAAM,KAAKzB,GACX,KAAM0B,EACN,GAAIC,EACJ,SAAU,KAAKJ,GACf,SAAU,KAAKC,EACnB,EAEAtC,EAAqByC,EAAa,SAAUF,CAAS,EAEhD,KAAK,OAIN,KAAK,QAAQ,aACb/C,EAAA,QAAE,YAAY,KAAKsB,GAAS,KAAK,QAAQ,WAAW,EAGpD0B,IAAWC,EAMJ,KAAKH,KAAkB,KAAKD,IACnCrC,EAAqByC,EAAa,SAAUF,CAAS,GANrDvC,EAAqBwC,EAAQ,SAAUD,CAAS,EAE5C,KAAK,MACLvC,EAAqByC,EAAa,SAAUF,CAAS,GAMzD,KAAK,MACL,KAAKxB,GAAW,EAExB,CAE0E,EAE1E,KAAK,OACD,KAAK,KACL,+CACAiB,EACA,CAAE,SAAU,KAAKxB,EAAU,CAC/B,EAEA,KAAK,OAAO,KAAK,KAAM,0BAA6B,CAChDV,EAAU9B,EAAAA,QAAE,KAAK,KAAKwC,GAAW,KAAK,IAAI,EAAG,KAAK,QAAQ,MAAM,CACpE,CAAC,CACL,CAKA,IAAa,CACL,KAAKQ,KAAiB,MACtBZ,EAAO,qBAAqB,KAAKY,EAAY,EAG7C,KAAKP,IAAa,KAAK,MACvBjB,EAAA,QAAE,cAAc,KAAK,KAAM,YAAY,EAG3C,KAAK8C,GAAgB,KACrB,KAAKF,GAAmB,KACxB,KAAK3B,GAAY,GACjB,KAAKQ,GAAO,KACZ,KAAKD,GAAe,KACpB,KAAKqB,GAAc,KACnB,KAAKvB,GAAU,IACnB,CAKA,IAAkB,CAET,KAAK,MACL,KAAK,QAAQ,QACb,KAAKL,IACN,KAAKO,KAAiB,OAK1B,KAAKA,GAAeZ,EAAO,0BAA4B,CACnD,KAAKsC,GAAa,CACtB,CAAC,EACL,CAOA,GAAiB,EAAQ,EAAQ,CAC7B,IAAIC,EAAkB,KAAK,KAE3B,GAAI,KAAK,QAAQ,YAAa,CAC1B,IAAMC,EAAY5E,EAAAA,QAAE,KAAK,KAAK,QAAQ,WAAW,CAAC,CAC7C,OAAQ,GAAS2B,IAAS,KAAK,IAAI,CAAC,CACpC,OAAQ,GAAS,CACd,IAAMkD,EAAW,KAAK,YAAY,KAAKlD,CAAI,EAE3C,OAAOkD,EAASnC,KACXmC,EAAS,QAAQ,aAAeA,EAAS,MAAM,CAAC,CAAC,OAC1D,CAAC,EAEDD,EAAU,SACV,EAAkB5E,EAAAA,QAAE,UAChB,CAAC,KAAK,KAAM,GAAG4E,CAAS,EACxB,KAAK3B,GAAK,EACV,KAAKA,GAAK,EACV,CAAE,OAAQ,EAAK,CACnB,EAER,CAEA,IAAM6B,EAAkB,KAAK,YAAY,KAAKH,CAAe,EACvDI,EAAeD,EAAgB,MAAM,CAAC,CACvC,OAAQ,GAASnD,IAAS,KAAKmB,EAAO,EACrCkC,EAAchF,EAAAA,QAAE,UAClB+E,EACA,KAAK9B,GAAK,EACV,KAAKA,GAAK,EACV,CAAE,OAAQ,EAAK,CACnB,EAEA,GAAI+B,EACA,KAAKC,GACDD,EACA,KAAK/B,GAAK,EACV,KAAKA,GAAK,EACVW,EACAC,CACJ,OACG,GAAIc,IAAoB,KAAKP,GAChC5C,EAAA,QAAE,OAAOmD,EAAiB,KAAK7B,EAAO,OAEtC,OAGJ,IAAMoC,EAAWJ,EAAgB,MAAM,CAAC,CAAC,QAAQ,KAAKhC,EAAO,EAE7D,GAAI6B,IAAoB,KAAKP,GAAkB,CAC3C,IAAMe,EAAmB,KAAKf,GAExB,CAAE,UADiB,KAAK,YAAY,KAAKe,CACb,CAAC,CAAC,QAEpCzD,EAAY0D,EACRpF,EAAAA,QAAE,KAAKoF,EAAQ,KAAKtC,EAAO,EAC3B,CAAC,KAAKA,EAAO,CAAC,EAGlB,IAAMyB,EAAY,CACd,KAAM,KAAKzB,GACX,KAAMqC,EACN,GAAIR,EACJ,SAAU,KAAKL,GACf,UACJ,EAIA,GAFAtC,EAAqBmD,EAAkB,OAAQZ,CAAS,EAEpD,CAAC,KAAK,KACN,OAGJvC,EAAqB2C,EAAiB,UAAWJ,CAAS,CAC9D,MAAO,GAAI,KAAKD,KAAkBY,EAAU,CAExC,IAAMX,EAAY,CACd,KAAM,KAAKzB,GACX,KAAM6B,EACN,GAAIA,EACJ,SAAU,KAAKL,GACf,UACJ,EAEAtC,EAAqB2C,EAAiB,UAAWJ,CAAS,CAC9D,CAEK,KAAK,OAIV,KAAKD,GAAgBY,EACrB,KAAKd,GAAmBO,EAC5B,CAUA,GAAc,EAAa,EAAG,EAAG,EAAQ,EAAQ,CAC7C,IAAMU,EAAgBrF,EAAAA,QAAE,OAAOgF,EAAa,CAAE,OAAQ,EAAK,CAAC,EACtDM,EAActF,EAAAA,QAAE,KAAKgF,EAAa,CAAE,OAAQ,EAAK,CAAC,EAClDO,EAAevF,EAAAA,QAAE,OAAO,KAAK8C,GAAS,CAAE,OAAQ,EAAK,CAAC,EACtD0C,EAAY,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,KAAK,QAAQ,aAAa,CAAC,EACjEC,EAAa,GACbC,EAAa,GAEb9B,IACA,EAAaA,EAAS,EAClB4B,EACA,EAAIA,GAGR3B,IACA,EAAaA,EAAS,EAClB2B,EACA,EAAIA,GAGZ,IAAIG,EACJ,GAAI,KAAK,QAAQ,OAAS,KAAON,EAAc,IAAME,EAAa,EAE9D,EAASK,EADKN,EAAY,IAAMA,EAAY,OAASI,EAEjD,SACA,aACD,GAAI,KAAK,QAAQ,OAAS,KAAOL,EAAc,IAAME,EAAa,EAErE,EAASM,EADKP,EAAY,KAAOA,EAAY,MAAQG,EAEjD,SACA,YACD,CACH,IAAMK,EAAQR,EAAY,KAAOA,EAAY,MAAQG,EAC/CM,EAAQT,EAAY,IAAMA,EAAY,OAASI,EACrD,EAASG,EAAIC,GAASF,EAAIG,EACtB,SACA,OACR,CAEAvE,EAAA,QAAEmE,EAAO,CAACX,EAAa,KAAKlC,EAAO,CACvC,CACJ,GClgBA,EAAAR,EAAA,cAAA,CAAc,WAAYD,CAAQ,E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fr0st/ui-sortable",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
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": [
@@ -57,11 +57,11 @@
57
57
  "devDependencies": {
58
58
  "@fr0st/eslint-config": "^6.0.1",
59
59
  "@fr0st/query": "^5.0.1",
60
- "@fr0st/ui": "^4.0.1",
61
- "@playwright/test": "^1.63.0",
62
- "eslint": "^10.11.0",
60
+ "@fr0st/ui": "^4.0.2",
61
+ "@playwright/test": "^1.64.1",
62
+ "eslint": "^10.13.0",
63
63
  "monocart-reporter": "^2.14.0",
64
- "vite": "^8.3.1"
64
+ "vite": "^8.3.4"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "@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 downEvent = (event) => {
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 moveEvent = (event) => {
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 upEvent = (event) => {
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 dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);
316
+ const dragHandler = $.mouseDragFactory(downHandler, moveHandler, upHandler);
319
317
 
320
- $.addEventDelegate(
318
+ this.listen(
321
319
  this.node,
322
320
  'mousedown.ui.sortable touchstart.ui.sortable',
323
- this.#selector,
324
- dragEvent,
321
+ dragHandler,
322
+ { delegate: this.#selector },
325
323
  );
326
324
 
327
- $.addEvent(this.node, 'receive.ui.sortable', () => {
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 && this.#scrollFrame !== undefined) {
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 && this.#scrollFrame !== undefined
359
+ this.#scrollFrame !== null
362
360
  ) {
363
361
  return;
364
362
  }