@fr0st/ui-sortable 3.0.0 → 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.
- package/README.md +96 -83
- package/dist/frost-ui-sortable.esm.js +33 -26
- package/dist/frost-ui-sortable.esm.js.map +1 -1
- package/dist/frost-ui-sortable.esm.min.js +1 -1
- package/dist/frost-ui-sortable.esm.min.js.map +1 -1
- package/dist/frost-ui-sortable.js +35 -28
- package/dist/frost-ui-sortable.js.map +1 -1
- package/dist/frost-ui-sortable.min.js +1 -1
- package/dist/frost-ui-sortable.min.js.map +1 -1
- package/package.json +8 -8
- package/src/helpers.js +3 -3
- package/src/sortable.js +44 -36
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frost-ui-sortable.esm.min.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 #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 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 setCursor($.find(this.#selector, this.node), this.options.cursor);\n this.#events();\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($.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 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 = (e) => {\n const cancelled = this.options.cancel &&\n (\n $.is(e.target, this.options.cancel) ||\n $.is(e.currentTarget, this.options.cancel) ||\n $.closest(e.target, this.options.cancel, this.node).length\n );\n\n if (\n e.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, e.currentTarget)) :\n e.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveEvent = (e) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(e);\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 = (e) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (e.type === 'mouseup') {\n e.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,IAAM,EAAc,IAAI,QAMxB,SAAgB,EAAY,EAAO,CAC/B,IAAK,IAAM,KAAQ,EAAO,CACtB,IAAM,EAAU,EAAY,IAAI,CAAI,EAE/B,IAIL,EAAQ,EACR,EAAY,OAAO,CAAI,EAC3B,CACJ,CAOA,SAAgB,EAAU,EAAO,EAAQ,CACrC,IAAK,IAAM,KAAQ,EACX,EAAY,IAAI,CAAI,EACpB,EAAE,SAAS,EAAM,CAAE,QAAO,CAAC,EAE3B,EAAY,IAAI,EAAM,EAAE,aAAa,EAAM,SAAU,CAAM,CAAC,CAGxE,CAQA,SAAgB,EAAqB,EAAM,EAAM,EAAM,CACnD,EAAE,aAAa,EAAM,GAAG,EAAK,cAAe,CACxC,OACA,OAAQ,CACJ,OAAQ,EAAK,KACb,GAAG,CACP,CACJ,CAAC,CACL,CChDA,IAAM,EAAW,EAAE,WAAW,EACxB,EAAS,EAAE,UAAU,EAkCN,EAArB,cAAsC,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,GACA,GACA,GACA,GACA,GAOA,YAAY,EAAM,EAAS,CACvB,MAAM,EAAM,CAAO,EAEnB,KAAK,GAAY,KAAK,QAAQ,OAC1B,OAAO,KAAK,QAAQ,MAAM,QAAQ,KAAK,QAAQ,OAAO,GACtD,KAAK,QAAQ,MAEjB,KAAK,GAAY,GACjB,KAAK,GAAW,CAAC,KAAK,QAAQ,SAE9B,EAAU,EAAE,KAAK,KAAK,GAAW,KAAK,IAAI,EAAG,KAAK,QAAQ,MAAM,EAChE,KAAK,GAAQ,CACjB,CAKA,SAAU,CACN,KAAK,GAAW,EACpB,CAGA,SAAU,CACD,KAAK,OAIV,EAAE,oBAAoB,KAAK,KAAM,8CAA8C,EAC/E,EAAE,YAAY,KAAK,KAAM,qBAAqB,EAC9C,EAAY,EAAE,KAAK,KAAK,GAAW,KAAK,IAAI,CAAC,EAEzC,KAAK,IAAW,KAAK,QAAQ,aAC7B,EAAE,YAAY,KAAK,GAAS,KAAK,QAAQ,WAAW,EAGxD,KAAK,GAAW,EAEhB,MAAM,QAAQ,EAClB,CAKA,QAAS,CACL,KAAK,GAAW,EACpB,CAMA,OAAQ,CACJ,OAAO,EAAE,KAAK,KAAK,QAAQ,MAAO,KAAK,IAAI,CAC/C,CAKA,IAAe,CAGX,GAFA,KAAK,GAAe,KAEhB,CAAC,KAAK,MAAQ,CAAC,KAAK,IAAa,CAAC,KAAK,IAAW,CAAC,KAAK,GACxD,OAGJ,IAAM,EAAY,EAAE,WAAW,CAAM,EAC/B,EAAY,EAAE,WAAW,CAAM,EAC/B,EAAe,EAAE,OAAO,CAAM,EAC9B,EAAc,EAAE,MAAM,CAAM,EAE9B,EAAU,EACV,EAAU,EAEd,GAAI,KAAK,GAAK,EAAI,EAAY,KAAK,QAAQ,kBACvC,EAAU,KAAK,IAAI,EAAG,EAAY,KAAK,QAAQ,WAAW,OACvD,GAAI,KAAK,GAAK,EAAI,EAAY,EAAe,KAAK,QAAQ,kBAAmB,CAChF,IAAM,EAAY,EAAE,OAAO,EAAU,CAAE,QAAS,EAAE,UAAW,CAAC,EACxD,EAAO,KAAK,IAAI,EAAG,EAAY,CAAY,EACjD,EAAU,KAAK,IAAI,EAAM,EAAY,KAAK,QAAQ,WAAW,CACjE,CAEA,GAAI,KAAK,GAAK,EAAI,EAAY,KAAK,QAAQ,kBACvC,EAAU,KAAK,IAAI,EAAG,EAAY,KAAK,QAAQ,WAAW,OACvD,GAAI,KAAK,GAAK,EAAI,EAAY,EAAc,KAAK,QAAQ,kBAAmB,CAC/E,IAAM,EAAW,EAAE,MAAM,EAAU,CAAE,QAAS,EAAE,UAAW,CAAC,EACtD,EAAO,KAAK,IAAI,EAAG,EAAW,CAAW,EAC/C,EAAU,KAAK,IAAI,EAAM,EAAY,KAAK,QAAQ,WAAW,CACjE,CAEA,GAAI,IAAY,GAAa,IAAY,EACrC,OAGJ,EAAO,SAAS,CACZ,KAAM,EACN,IAAK,EACL,SAAU,SACd,CAAC,EAED,IAAM,EAAS,EAAU,EACnB,EAAS,EAAU,EAEzB,KAAK,GAAK,GAAK,EACf,KAAK,GAAK,GAAK,EAEf,KAAK,GAAiB,EAAQ,CAAM,EACpC,KAAK,GAAgB,CACzB,CAKA,IAAU,CA2HN,IAAM,EAAY,EAAE,iBA1HD,GAAM,CACrB,IAAM,EAAY,KAAK,QAAQ,SAEvB,EAAE,GAAG,EAAE,OAAQ,KAAK,QAAQ,MAAM,GAClC,EAAE,GAAG,EAAE,cAAe,KAAK,QAAQ,MAAM,GACzC,EAAE,QAAQ,EAAE,OAAQ,KAAK,QAAQ,OAAQ,KAAK,IAAI,CAAC,CAAC,QAgB5D,GAZI,EAAE,QACF,CAAC,KAAK,IACN,GACA,EAAE,WAAW,KAAK,KAAM,YAAY,IAKxC,KAAK,GAAU,KAAK,QAAQ,OACxB,KAAK,MAAM,CAAC,CAAC,KAAM,GAAS,EAAE,cAAc,EAAM,EAAE,aAAa,CAAC,EAClE,EAAE,cAEF,CAAC,KAAK,IACN,MAAO,EAEf,EAEmB,GAAM,CACrB,GAAI,CAAC,KAAK,MAAQ,CAAC,KAAK,GACpB,OAGJ,IAAM,EAAc,KAAK,GACzB,KAAK,GAAO,EAAY,CAAC,EACzB,IAAM,EAAS,EACX,KAAK,GAAK,EAAI,EAAY,EAC1B,EACE,EAAS,EACX,KAAK,GAAK,EAAI,EAAY,EAC1B,EAEJ,GAAI,CAAC,KAAK,GAAW,CACjB,KAAK,GAAY,GACjB,KAAK,GAAmB,KAAK,KAC7B,KAAK,GAAc,KAAK,MAAM,CAAC,CAAC,QAAQ,KAAK,EAAO,EACpD,KAAK,GAAgB,KAAK,GAE1B,EAAE,WAAW,KAAK,KAAM,CAAE,WAAY,EAAK,CAAC,EAG5C,IAAM,EAAY,CACd,KAAM,KAAK,GACX,KAAM,KAAK,KACX,GAAI,KAAK,KACT,SAAU,KAAK,GACf,SAAU,KAAK,EACnB,EAIA,GAFA,EAAqB,KAAK,KAAM,OAAQ,CAAS,EAE7C,CAAC,KAAK,KACN,OAGA,KAAK,QAAQ,aACb,EAAE,SAAS,KAAK,GAAS,KAAK,QAAQ,WAAW,CAEzD,CAEA,KAAK,GAAiB,EAAQ,CAAM,EACpC,KAAK,GAAgB,CACzB,EAEiB,GAAM,CACnB,GAAI,CAAC,KAAK,KACN,OAGJ,GAAI,CAAC,KAAK,GAAW,CACjB,KAAK,GAAU,KACf,MACJ,CAEI,EAAE,OAAS,WACX,EAAE,eAAe,EAGrB,IAAM,EAAS,KAAK,KACd,EAAc,KAAK,GAEnB,EAAY,CACd,KAAM,KAAK,GACX,KAAM,EACN,GAAI,EACJ,SAAU,KAAK,GACf,SAAU,KAAK,EACnB,EAEA,EAAqB,EAAa,SAAU,CAAS,EAEhD,KAAK,OAIN,KAAK,QAAQ,aACb,EAAE,YAAY,KAAK,GAAS,KAAK,QAAQ,WAAW,EAGpD,IAAW,EAMJ,KAAK,KAAkB,KAAK,IACnC,EAAqB,EAAa,SAAU,CAAS,GANrD,EAAqB,EAAQ,SAAU,CAAS,EAE5C,KAAK,MACL,EAAqB,EAAa,SAAU,CAAS,GAMzD,KAAK,MACL,KAAK,GAAW,EAExB,CAEkE,EAElE,EAAE,iBACE,KAAK,KACL,+CACA,KAAK,GACL,CACJ,EAEA,EAAE,SAAS,KAAK,KAAM,sBAAwB,GAAM,CAChD,EAAU,EAAE,KAAK,KAAK,GAAW,KAAK,IAAI,EAAG,KAAK,QAAQ,MAAM,CACpE,CAAC,CACL,CAKA,IAAa,CACL,KAAK,KAAiB,MAAQ,KAAK,KAAiB,IAAA,IACpD,EAAO,qBAAqB,KAAK,EAAY,EAG7C,KAAK,IAAa,KAAK,MACvB,EAAE,cAAc,KAAK,KAAM,YAAY,EAG3C,KAAK,GAAgB,KACrB,KAAK,GAAmB,KACxB,KAAK,GAAY,GACjB,KAAK,GAAO,KACZ,KAAK,GAAe,KACpB,KAAK,GAAc,KACnB,KAAK,GAAU,IACnB,CAKA,IAAkB,CAEV,CAAC,KAAK,MACN,CAAC,KAAK,QAAQ,QACd,CAAC,KAAK,IACN,KAAK,KAAiB,MAAQ,KAAK,KAAiB,IAAA,KAKxD,KAAK,GAAe,EAAO,sBAAuB,GAAM,CACpD,KAAK,GAAa,CACtB,CAAC,EACL,CAOA,GAAiB,EAAQ,EAAQ,CAC7B,IAAI,EAAkB,KAAK,KAE3B,GAAI,KAAK,QAAQ,YAAa,CAC1B,IAAM,EAAY,EAAE,KAAK,KAAK,QAAQ,WAAW,CAAC,CAC7C,OAAQ,GAAS,IAAS,KAAK,IAAI,CAAC,CACpC,OAAQ,GAAS,CACd,IAAM,EAAW,KAAK,YAAY,KAAK,CAAI,EAE3C,OAAO,EAAS,KACX,EAAS,QAAQ,aAAe,EAAS,MAAM,CAAC,CAAC,OAC1D,CAAC,EAED,EAAU,SACV,EAAkB,EAAE,UAChB,CAAC,KAAK,KAAM,GAAG,CAAS,EACxB,KAAK,GAAK,EACV,KAAK,GAAK,EACV,CAAE,OAAQ,EAAK,CACnB,EAER,CAEA,IAAM,EAAkB,KAAK,YAAY,KAAK,CAAe,EACvD,EAAe,EAAgB,MAAM,CAAC,CACvC,OAAQ,GAAS,IAAS,KAAK,EAAO,EACrC,EAAc,EAAE,UAClB,EACA,KAAK,GAAK,EACV,KAAK,GAAK,EACV,CAAE,OAAQ,EAAK,CACnB,EAEA,GAAI,EACA,KAAK,GACD,EACA,KAAK,GAAK,EACV,KAAK,GAAK,EACV,EACA,CACJ,OACG,GAAI,IAAoB,KAAK,GAChC,EAAE,OAAO,EAAiB,KAAK,EAAO,OAEtC,OAGJ,IAAM,EAAW,EAAgB,MAAM,CAAC,CAAC,QAAQ,KAAK,EAAO,EAE7D,GAAI,IAAoB,KAAK,GAAkB,CAC3C,IAAM,EAAmB,KAAK,GAExB,CAAE,UADiB,KAAK,YAAY,KAAK,CACb,CAAC,CAAC,QAEpC,EAAY,EACR,EAAE,KAAK,EAAQ,KAAK,EAAO,EAC3B,CAAC,KAAK,EAAO,CAAC,EAGlB,IAAM,EAAY,CACd,KAAM,KAAK,GACX,KAAM,EACN,GAAI,EACJ,SAAU,KAAK,GACf,UACJ,EAIA,GAFA,EAAqB,EAAkB,OAAQ,CAAS,EAEpD,CAAC,KAAK,KACN,OAGJ,EAAqB,EAAiB,UAAW,CAAS,CAC9D,MAAO,GAAI,KAAK,KAAkB,EAAU,CAExC,IAAM,EAAY,CACd,KAAM,KAAK,GACX,KAAM,EACN,GAAI,EACJ,SAAU,KAAK,GACf,UACJ,EAEA,EAAqB,EAAiB,UAAW,CAAS,CAC9D,CAEK,KAAK,OAIV,KAAK,GAAgB,EACrB,KAAK,GAAmB,EAC5B,CAUA,GAAc,EAAa,EAAG,EAAG,EAAQ,EAAQ,CAC7C,IAAM,EAAgB,EAAE,OAAO,EAAa,CAAE,OAAQ,EAAK,CAAC,EACtD,EAAc,EAAE,KAAK,EAAa,CAAE,OAAQ,EAAK,CAAC,EAClD,EAAe,EAAE,OAAO,KAAK,GAAS,CAAE,OAAQ,EAAK,CAAC,EACtD,EAAY,KAAK,IAAI,EAAG,KAAK,IAAI,EAAG,KAAK,QAAQ,aAAa,CAAC,EACjE,EAAa,GACb,EAAa,GAEb,IACA,EAAa,EAAS,EAClB,EACA,EAAI,GAGR,IACA,EAAa,EAAS,EAClB,EACA,EAAI,GAGZ,IAAI,EACJ,GAAI,KAAK,QAAQ,OAAS,KAAO,EAAc,IAAM,EAAa,EAE9D,EAAS,EADK,EAAY,IAAM,EAAY,OAAS,EAEjD,SACA,aACD,GAAI,KAAK,QAAQ,OAAS,KAAO,EAAc,IAAM,EAAa,EAErE,EAAS,EADK,EAAY,KAAO,EAAY,MAAQ,EAEjD,SACA,YACD,CACH,IAAM,EAAQ,EAAY,KAAO,EAAY,MAAQ,EAC/C,EAAQ,EAAY,IAAM,EAAY,OAAS,EACrD,EAAS,EAAI,GAAS,EAAI,EACtB,SACA,OACR,CAEA,EAAE,EAAO,CAAC,EAAa,KAAK,EAAO,CACvC,CACJ,EC1fA,EAAc,WAAY,CAAQ,EAElC,IAAA,EAAe"}
|
|
1
|
+
{"version":3,"file":"frost-ui-sortable.esm.min.js","names":["$","cursorLocks","resetCursor","node","nodes","release","setCursor","cursor","triggerSortableEvent","name","data","document","window","Sortable","BaseComponent","options","#selector","#dragging","#enabled","#initialCursorNodes","#events","error","#target","#resetDrag","#scrollFrame","#pos","originalX","originalY","windowHeight","windowWidth","offsetX","offsetY","docHeight","maxY","docWidth","maxX","deltaX","deltaY","#updatePlacement","#scheduleScroll","dragHandler","cancelled","event","previousPos","getPosition","#currentSortable","#startIndex","#currentIndex","eventData","source","destination","#checkScroll","nearestSortable","connected","sortable","nearestInstance","nearestItems","nearestItem","#updateTarget","newIndex","previousSortable","handle","nearestCenter","nearestRect","targetCenter","threshold","thresholdX","thresholdY","method","y","x","swapX","swapY","initComponent","src_default"],"sources":["../src/helpers.js","../src/sortable.js","../src/index.js"],"sourcesContent":["/** @import { SortableEventData } from './sortable.js'; */\n\nimport $ from '@fr0st/query';\n\nconst cursorLocks = new WeakMap();\n\n/**\n * Resets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to restore.\n */\nexport function resetCursor(nodes) {\n for (const node of nodes) {\n const release = cursorLocks.get(node);\n\n if (!release) {\n continue;\n }\n\n release();\n cursorLocks.delete(node);\n }\n}\n\n/**\n * Sets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to update.\n * @param {string} cursor The cursor style.\n */\nexport function setCursor(nodes, cursor) {\n for (const node of nodes) {\n if (cursorLocks.has(node)) {\n $.setStyle(node, { cursor });\n } else {\n cursorLocks.set(node, $.setStyleLock(node, 'cursor', cursor));\n }\n }\n}\n\n/**\n * Triggers a Sortable event with its data and detail payloads.\n * @param {HTMLElement} node The event target.\n * @param {string} name The event name without its namespace.\n * @param {SortableEventData} data The sorting event data.\n */\nexport function triggerSortableEvent(node, name, data) {\n $.triggerEvent(node, `${name}.ui.sortable`, {\n data,\n detail: {\n target: data.item,\n ...data,\n },\n });\n}\n","import $ from '@fr0st/query';\nimport { BaseComponent, getPosition } from '@fr0st/ui';\nimport { resetCursor, setCursor, triggerSortableEvent } from './helpers.js';\n\nconst document = $.getContext();\nconst window = $.getWindow();\n\n/** @typedef {'x'|'y'} SortableAxis */\n\n/**\n * @typedef {object} SortableOptions\n * @property {SortableAxis|null} [axis=null] The axis used to determine item placement.\n * @property {string} [cancel='input, textarea, button, select, option'] The selector for elements that cannot start a sort.\n * @property {string|null} [connectWith=null] The selector for connected Sortable containers.\n * @property {string} [cursor='auto'] The cursor applied to sortable items or handles.\n * @property {boolean} [disabled=false] Whether sorting is initially disabled.\n * @property {boolean} [dropOnEmpty=true] Whether connected empty containers accept items.\n * @property {string|null} [handle=null] The handle selector within each sortable item.\n * @property {string|null} [helperClass='bg-body-tertiary'] The class applied to an item while it is being sorted.\n * @property {string} [items=':scope > li'] The selector for sortable items.\n * @property {boolean} [scroll=true] Whether to scroll the window while sorting near an edge.\n * @property {number} [scrollSensitivity=20] The distance from a window edge that starts scrolling, in pixels.\n * @property {number} [scrollSpeed=5] The scroll distance applied per animation frame, in pixels.\n * @property {number} [swapThreshold=0.25] The fraction of an item crossed before swapping, from `0` to `1`.\n */\n\n/**\n * @typedef {object} SortableEventData\n * @property {HTMLElement} item The item being sorted.\n * @property {HTMLElement} from The previous or original Sortable container.\n * @property {HTMLElement} to The next or final Sortable container.\n * @property {number} oldIndex The previous or original item index.\n * @property {number} newIndex The next or final item index.\n */\n\n/**\n * Controls a sortable collection of elements.\n * @augments {BaseComponent<SortableOptions>}\n */\nexport default class Sortable extends BaseComponent {\n /** @type {SortableOptions} */\n static defaults = {\n axis: null,\n cancel: 'input, textarea, button, select, option',\n connectWith: null,\n cursor: 'auto',\n disabled: false,\n dropOnEmpty: true,\n handle: null,\n helperClass: 'bg-body-tertiary',\n items: ':scope > li',\n scroll: true,\n scrollSensitivity: 20,\n scrollSpeed: 5,\n swapThreshold: 0.25,\n };\n\n #currentIndex;\n #currentSortable = null;\n #dragging;\n #enabled;\n #initialCursorNodes = [];\n #pos = null;\n #scrollFrame = null;\n #selector;\n #startIndex;\n #target = null;\n\n /**\n * Creates a Sortable.\n * @param {HTMLElement} node The sortable container.\n * @param {SortableOptions} [options] The Sortable options.\n */\n constructor(node, options) {\n super(node, options);\n\n try {\n this.#selector = this.options.handle ?\n `:is(${this.options.items}) :is(${this.options.handle})` :\n this.options.items;\n\n this.#dragging = false;\n this.#enabled = !this.options.disabled;\n\n this.#initialCursorNodes = $.find(this.#selector, this.node);\n setCursor(this.#initialCursorNodes, this.options.cursor);\n this.#events();\n this.#initialCursorNodes = null;\n } catch (error) {\n this.dispose();\n throw error;\n }\n }\n\n /**\n * Disables the Sortable.\n */\n disable() {\n this.#enabled = false;\n }\n\n /** @inheritdoc */\n dispose() {\n if (!this.node) {\n return;\n }\n\n resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));\n\n if (this.#target && this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n this.#resetDrag();\n\n this.#initialCursorNodes = null;\n\n super.dispose();\n }\n\n /**\n * Enables the Sortable.\n */\n enable() {\n this.#enabled = true;\n }\n\n /**\n * Gets the Sortable item elements.\n * @returns {HTMLElement[]} The Sortable item elements.\n */\n items() {\n return $.find(this.options.items, this.node);\n }\n\n /**\n * Checks whether the window should scroll while sorting.\n */\n #checkScroll() {\n this.#scrollFrame = null;\n\n if (!this.node || !this.#dragging || !this.#target || !this.#pos) {\n return;\n }\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n const windowHeight = $.height(window);\n const windowWidth = $.width(window);\n\n let offsetX = originalX;\n let offsetY = originalY;\n\n if (this.#pos.y < originalY + this.options.scrollSensitivity) {\n offsetY = Math.max(0, originalY - this.options.scrollSpeed);\n } else if (this.#pos.y > originalY + windowHeight - this.options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n const maxY = Math.max(0, docHeight - windowHeight);\n offsetY = Math.min(maxY, originalY + this.options.scrollSpeed);\n }\n\n if (this.#pos.x < originalX + this.options.scrollSensitivity) {\n offsetX = Math.max(0, originalX - this.options.scrollSpeed);\n } else if (this.#pos.x > originalX + windowWidth - this.options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n const maxX = Math.max(0, docWidth - windowWidth);\n offsetX = Math.min(maxX, originalX + this.options.scrollSpeed);\n }\n\n if (offsetX === originalX && offsetY === originalY) {\n return;\n }\n\n window.scrollTo({\n left: offsetX,\n top: offsetY,\n behavior: 'instant',\n });\n\n const deltaX = offsetX - originalX;\n const deltaY = offsetY - originalY;\n\n this.#pos.x += deltaX;\n this.#pos.y += deltaY;\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n }\n\n /**\n * Attaches events for the Sortable.\n */\n #events() {\n const downHandler = (event) => {\n const cancelled = this.options.cancel &&\n (\n $.is(event.target, this.options.cancel) ||\n $.is(event.currentTarget, this.options.cancel) ||\n $.closest(event.target, this.options.cancel, this.node).length\n );\n\n if (\n event.button ||\n !this.#enabled ||\n cancelled ||\n $.getDataset(this.node, 'uiDragging')\n ) {\n return false;\n }\n\n this.#target = this.options.handle ?\n this.items().find((node) => $.hasDescendent(node, event.currentTarget)) :\n event.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveHandler = (event) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(event);\n const deltaX = previousPos ?\n this.#pos.x - previousPos.x :\n 0;\n const deltaY = previousPos ?\n this.#pos.y - previousPos.y :\n 0;\n\n if (!this.#dragging) {\n this.#dragging = true;\n this.#currentSortable = this.node;\n this.#startIndex = this.items().indexOf(this.#target);\n this.#currentIndex = this.#startIndex;\n\n $.setDataset(this.node, { uiDragging: true });\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: this.node,\n to: this.node,\n oldIndex: this.#startIndex,\n newIndex: this.#startIndex,\n };\n\n triggerSortableEvent(this.node, 'sort', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.addClass(this.#target, this.options.helperClass);\n }\n }\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n };\n\n const upHandler = (event) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (event.type === 'mouseup') {\n event.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragHandler = $.mouseDragFactory(downHandler, moveHandler, upHandler);\n\n this.listen(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n dragHandler,\n { delegate: this.#selector },\n );\n\n this.listen(this.node, 'receive.ui.sortable', () => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame(() => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(function(global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require(
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports',
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require("@fr0st/ui"), require("@fr0st/query")) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', "@fr0st/ui", "@fr0st/query"], factory) :
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.UI = global.UI || {}), global.UI,global.fQuery));
|
|
5
5
|
})(this, function(exports, _fr0st_ui, _fr0st_query) {
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
@@ -124,14 +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
|
-
#
|
|
131
|
-
#
|
|
130
|
+
#initialCursorNodes = [];
|
|
131
|
+
#pos = null;
|
|
132
|
+
#scrollFrame = null;
|
|
132
133
|
#selector;
|
|
133
134
|
#startIndex;
|
|
134
|
-
#target;
|
|
135
|
+
#target = null;
|
|
135
136
|
/**
|
|
136
137
|
* Creates a Sortable.
|
|
137
138
|
* @param {HTMLElement} node The sortable container.
|
|
@@ -139,11 +140,18 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
139
140
|
*/
|
|
140
141
|
constructor(node, options) {
|
|
141
142
|
super(node, options);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
143
|
+
try {
|
|
144
|
+
this.#selector = this.options.handle ? `:is(${this.options.items}) :is(${this.options.handle})` : this.options.items;
|
|
145
|
+
this.#dragging = false;
|
|
146
|
+
this.#enabled = !this.options.disabled;
|
|
147
|
+
this.#initialCursorNodes = _fr0st_query.default.find(this.#selector, this.node);
|
|
148
|
+
setCursor(this.#initialCursorNodes, this.options.cursor);
|
|
149
|
+
this.#events();
|
|
150
|
+
this.#initialCursorNodes = null;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
this.dispose();
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
147
155
|
}
|
|
148
156
|
/**
|
|
149
157
|
* Disables the Sortable.
|
|
@@ -154,11 +162,10 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
154
162
|
/** @inheritdoc */
|
|
155
163
|
dispose() {
|
|
156
164
|
if (!this.node) return;
|
|
157
|
-
_fr0st_query.default.
|
|
158
|
-
_fr0st_query.default.removeEvent(this.node, "receive.ui.sortable");
|
|
159
|
-
resetCursor(_fr0st_query.default.find(this.#selector, this.node));
|
|
165
|
+
resetCursor(this.#initialCursorNodes ?? _fr0st_query.default.find(this.#selector, this.node));
|
|
160
166
|
if (this.#target && this.options.helperClass) _fr0st_query.default.removeClass(this.#target, this.options.helperClass);
|
|
161
167
|
this.#resetDrag();
|
|
168
|
+
this.#initialCursorNodes = null;
|
|
162
169
|
super.dispose();
|
|
163
170
|
}
|
|
164
171
|
/**
|
|
@@ -215,16 +222,16 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
215
222
|
* Attaches events for the Sortable.
|
|
216
223
|
*/
|
|
217
224
|
#events() {
|
|
218
|
-
const
|
|
219
|
-
const cancelled = this.options.cancel && (_fr0st_query.default.is(
|
|
220
|
-
if (
|
|
221
|
-
this.#target = this.options.handle ? this.items().find((node) => _fr0st_query.default.hasDescendent(node,
|
|
225
|
+
const downHandler = (event) => {
|
|
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);
|
|
227
|
+
if (event.button || !this.#enabled || cancelled || _fr0st_query.default.getDataset(this.node, "uiDragging")) return false;
|
|
228
|
+
this.#target = this.options.handle ? this.items().find((node) => _fr0st_query.default.hasDescendent(node, event.currentTarget)) : event.currentTarget;
|
|
222
229
|
if (!this.#target) return false;
|
|
223
230
|
};
|
|
224
|
-
const
|
|
231
|
+
const moveHandler = (event) => {
|
|
225
232
|
if (!this.node || !this.#target) return;
|
|
226
233
|
const previousPos = this.#pos;
|
|
227
|
-
this.#pos = (0, _fr0st_ui.getPosition)(
|
|
234
|
+
this.#pos = (0, _fr0st_ui.getPosition)(event);
|
|
228
235
|
const deltaX = previousPos ? this.#pos.x - previousPos.x : 0;
|
|
229
236
|
const deltaY = previousPos ? this.#pos.y - previousPos.y : 0;
|
|
230
237
|
if (!this.#dragging) {
|
|
@@ -248,13 +255,13 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
248
255
|
this.#updatePlacement(deltaX, deltaY);
|
|
249
256
|
this.#scheduleScroll();
|
|
250
257
|
};
|
|
251
|
-
const
|
|
258
|
+
const upHandler = (event) => {
|
|
252
259
|
if (!this.node) return;
|
|
253
260
|
if (!this.#dragging) {
|
|
254
261
|
this.#target = null;
|
|
255
262
|
return;
|
|
256
263
|
}
|
|
257
|
-
if (
|
|
264
|
+
if (event.type === "mouseup") event.preventDefault();
|
|
258
265
|
const source = this.node;
|
|
259
266
|
const destination = this.#currentSortable;
|
|
260
267
|
/** @type {SortableEventData} */
|
|
@@ -274,9 +281,9 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
274
281
|
} else if (this.#currentIndex !== this.#startIndex) triggerSortableEvent(destination, "update", eventData);
|
|
275
282
|
if (this.node) this.#resetDrag();
|
|
276
283
|
};
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
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", () => {
|
|
280
287
|
setCursor(_fr0st_query.default.find(this.#selector, this.node), this.options.cursor);
|
|
281
288
|
});
|
|
282
289
|
}
|
|
@@ -284,7 +291,7 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
284
291
|
* Resets the active drag state.
|
|
285
292
|
*/
|
|
286
293
|
#resetDrag() {
|
|
287
|
-
if (this.#scrollFrame !== null
|
|
294
|
+
if (this.#scrollFrame !== null) window.cancelAnimationFrame(this.#scrollFrame);
|
|
288
295
|
if (this.#dragging && this.node) _fr0st_query.default.removeDataset(this.node, "uiDragging");
|
|
289
296
|
this.#currentIndex = null;
|
|
290
297
|
this.#currentSortable = null;
|
|
@@ -298,8 +305,8 @@ _fr0st_query = __toESM(_fr0st_query, 1);
|
|
|
298
305
|
* Schedules the next auto-scroll update.
|
|
299
306
|
*/
|
|
300
307
|
#scheduleScroll() {
|
|
301
|
-
if (!this.node || !this.options.scroll || !this.#dragging || this.#scrollFrame !== null
|
|
302
|
-
this.#scrollFrame = window.requestAnimationFrame((
|
|
308
|
+
if (!this.node || !this.options.scroll || !this.#dragging || this.#scrollFrame !== null) return;
|
|
309
|
+
this.#scrollFrame = window.requestAnimationFrame(() => {
|
|
303
310
|
this.#checkScroll();
|
|
304
311
|
});
|
|
305
312
|
}
|
|
@@ -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 #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 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 setCursor($.find(this.#selector, this.node), this.options.cursor);\n this.#events();\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($.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 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 = (e) => {\n const cancelled = this.options.cancel &&\n (\n $.is(e.target, this.options.cancel) ||\n $.is(e.currentTarget, this.options.cancel) ||\n $.closest(e.target, this.options.cancel, this.node).length\n );\n\n if (\n e.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, e.currentTarget)) :\n e.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveEvent = (e) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(e);\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 = (e) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (e.type === 'mouseup') {\n e.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);\n\n $.addEventDelegate(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n this.#selector,\n dragEvent,\n );\n\n $.addEvent(this.node, 'receive.ui.sortable', (_) => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null && this.#scrollFrame !== undefined) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null && this.#scrollFrame !== undefined\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame((_) => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"frost-ui-sortable.js","names":["$","$","BaseComponent","getPosition"],"sources":["../src/helpers.js","../src/sortable.js","../src/index.js"],"sourcesContent":["/** @import { SortableEventData } from './sortable.js'; */\n\nimport $ from '@fr0st/query';\n\nconst cursorLocks = new WeakMap();\n\n/**\n * Resets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to restore.\n */\nexport function resetCursor(nodes) {\n for (const node of nodes) {\n const release = cursorLocks.get(node);\n\n if (!release) {\n continue;\n }\n\n release();\n cursorLocks.delete(node);\n }\n}\n\n/**\n * Sets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to update.\n * @param {string} cursor The cursor style.\n */\nexport function setCursor(nodes, cursor) {\n for (const node of nodes) {\n if (cursorLocks.has(node)) {\n $.setStyle(node, { cursor });\n } else {\n cursorLocks.set(node, $.setStyleLock(node, 'cursor', cursor));\n }\n }\n}\n\n/**\n * Triggers a Sortable event with its data and detail payloads.\n * @param {HTMLElement} node The event target.\n * @param {string} name The event name without its namespace.\n * @param {SortableEventData} data The sorting event data.\n */\nexport function triggerSortableEvent(node, name, data) {\n $.triggerEvent(node, `${name}.ui.sortable`, {\n data,\n detail: {\n target: data.item,\n ...data,\n },\n });\n}\n","import $ from '@fr0st/query';\nimport { BaseComponent, getPosition } from '@fr0st/ui';\nimport { resetCursor, setCursor, triggerSortableEvent } from './helpers.js';\n\nconst document = $.getContext();\nconst window = $.getWindow();\n\n/** @typedef {'x'|'y'} SortableAxis */\n\n/**\n * @typedef {object} SortableOptions\n * @property {SortableAxis|null} [axis=null] The axis used to determine item placement.\n * @property {string} [cancel='input, textarea, button, select, option'] The selector for elements that cannot start a sort.\n * @property {string|null} [connectWith=null] The selector for connected Sortable containers.\n * @property {string} [cursor='auto'] The cursor applied to sortable items or handles.\n * @property {boolean} [disabled=false] Whether sorting is initially disabled.\n * @property {boolean} [dropOnEmpty=true] Whether connected empty containers accept items.\n * @property {string|null} [handle=null] The handle selector within each sortable item.\n * @property {string|null} [helperClass='bg-body-tertiary'] The class applied to an item while it is being sorted.\n * @property {string} [items=':scope > li'] The selector for sortable items.\n * @property {boolean} [scroll=true] Whether to scroll the window while sorting near an edge.\n * @property {number} [scrollSensitivity=20] The distance from a window edge that starts scrolling, in pixels.\n * @property {number} [scrollSpeed=5] The scroll distance applied per animation frame, in pixels.\n * @property {number} [swapThreshold=0.25] The fraction of an item crossed before swapping, from `0` to `1`.\n */\n\n/**\n * @typedef {object} SortableEventData\n * @property {HTMLElement} item The item being sorted.\n * @property {HTMLElement} from The previous or original Sortable container.\n * @property {HTMLElement} to The next or final Sortable container.\n * @property {number} oldIndex The previous or original item index.\n * @property {number} newIndex The next or final item index.\n */\n\n/**\n * Controls a sortable collection of elements.\n * @augments {BaseComponent<SortableOptions>}\n */\nexport default class Sortable extends BaseComponent {\n /** @type {SortableOptions} */\n static defaults = {\n axis: null,\n cancel: 'input, textarea, button, select, option',\n connectWith: null,\n cursor: 'auto',\n disabled: false,\n dropOnEmpty: true,\n handle: null,\n helperClass: 'bg-body-tertiary',\n items: ':scope > li',\n scroll: true,\n scrollSensitivity: 20,\n scrollSpeed: 5,\n swapThreshold: 0.25,\n };\n\n #currentIndex;\n #currentSortable = null;\n #dragging;\n #enabled;\n #initialCursorNodes = [];\n #pos = null;\n #scrollFrame = null;\n #selector;\n #startIndex;\n #target = null;\n\n /**\n * Creates a Sortable.\n * @param {HTMLElement} node The sortable container.\n * @param {SortableOptions} [options] The Sortable options.\n */\n constructor(node, options) {\n super(node, options);\n\n try {\n this.#selector = this.options.handle ?\n `:is(${this.options.items}) :is(${this.options.handle})` :\n this.options.items;\n\n this.#dragging = false;\n this.#enabled = !this.options.disabled;\n\n this.#initialCursorNodes = $.find(this.#selector, this.node);\n setCursor(this.#initialCursorNodes, this.options.cursor);\n this.#events();\n this.#initialCursorNodes = null;\n } catch (error) {\n this.dispose();\n throw error;\n }\n }\n\n /**\n * Disables the Sortable.\n */\n disable() {\n this.#enabled = false;\n }\n\n /** @inheritdoc */\n dispose() {\n if (!this.node) {\n return;\n }\n\n resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));\n\n if (this.#target && this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n this.#resetDrag();\n\n this.#initialCursorNodes = null;\n\n super.dispose();\n }\n\n /**\n * Enables the Sortable.\n */\n enable() {\n this.#enabled = true;\n }\n\n /**\n * Gets the Sortable item elements.\n * @returns {HTMLElement[]} The Sortable item elements.\n */\n items() {\n return $.find(this.options.items, this.node);\n }\n\n /**\n * Checks whether the window should scroll while sorting.\n */\n #checkScroll() {\n this.#scrollFrame = null;\n\n if (!this.node || !this.#dragging || !this.#target || !this.#pos) {\n return;\n }\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n const windowHeight = $.height(window);\n const windowWidth = $.width(window);\n\n let offsetX = originalX;\n let offsetY = originalY;\n\n if (this.#pos.y < originalY + this.options.scrollSensitivity) {\n offsetY = Math.max(0, originalY - this.options.scrollSpeed);\n } else if (this.#pos.y > originalY + windowHeight - this.options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n const maxY = Math.max(0, docHeight - windowHeight);\n offsetY = Math.min(maxY, originalY + this.options.scrollSpeed);\n }\n\n if (this.#pos.x < originalX + this.options.scrollSensitivity) {\n offsetX = Math.max(0, originalX - this.options.scrollSpeed);\n } else if (this.#pos.x > originalX + windowWidth - this.options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n const maxX = Math.max(0, docWidth - windowWidth);\n offsetX = Math.min(maxX, originalX + this.options.scrollSpeed);\n }\n\n if (offsetX === originalX && offsetY === originalY) {\n return;\n }\n\n window.scrollTo({\n left: offsetX,\n top: offsetY,\n behavior: 'instant',\n });\n\n const deltaX = offsetX - originalX;\n const deltaY = offsetY - originalY;\n\n this.#pos.x += deltaX;\n this.#pos.y += deltaY;\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n }\n\n /**\n * Attaches events for the Sortable.\n */\n #events() {\n const downHandler = (event) => {\n const cancelled = this.options.cancel &&\n (\n $.is(event.target, this.options.cancel) ||\n $.is(event.currentTarget, this.options.cancel) ||\n $.closest(event.target, this.options.cancel, this.node).length\n );\n\n if (\n event.button ||\n !this.#enabled ||\n cancelled ||\n $.getDataset(this.node, 'uiDragging')\n ) {\n return false;\n }\n\n this.#target = this.options.handle ?\n this.items().find((node) => $.hasDescendent(node, event.currentTarget)) :\n event.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveHandler = (event) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(event);\n const deltaX = previousPos ?\n this.#pos.x - previousPos.x :\n 0;\n const deltaY = previousPos ?\n this.#pos.y - previousPos.y :\n 0;\n\n if (!this.#dragging) {\n this.#dragging = true;\n this.#currentSortable = this.node;\n this.#startIndex = this.items().indexOf(this.#target);\n this.#currentIndex = this.#startIndex;\n\n $.setDataset(this.node, { uiDragging: true });\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: this.node,\n to: this.node,\n oldIndex: this.#startIndex,\n newIndex: this.#startIndex,\n };\n\n triggerSortableEvent(this.node, 'sort', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.addClass(this.#target, this.options.helperClass);\n }\n }\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n };\n\n const upHandler = (event) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (event.type === 'mouseup') {\n event.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragHandler = $.mouseDragFactory(downHandler, moveHandler, upHandler);\n\n this.listen(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n dragHandler,\n { delegate: this.#selector },\n );\n\n this.listen(this.node, 'receive.ui.sortable', () => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame(() => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("@fr0st/ui"),require("@fr0st/query")):typeof define==`function`&&define.amd?define([`exports`,`@fr0st/ui`,`@fr0st/query`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.UI=e.UI||{},e.UI,e.fQuery))})(this,function(e,t,n){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var s=o(t),l=0,u=s.length,d;l<u;l++)d=s[l],!c.call(e,d)&&d!==n&&i(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=a(t,d))||r.enumerable});return e};n=((e,t,n)=>(n=e==null?{}:r(s(e)),l(
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports,require("@fr0st/ui"),require("@fr0st/query")):typeof define==`function`&&define.amd?define([`exports`,`@fr0st/ui`,`@fr0st/query`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.UI=e.UI||{},e.UI,e.fQuery))})(this,function(e,t,n){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,s=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,n,r)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var s=o(t),l=0,u=s.length,d;l<u;l++)d=s[l],!c.call(e,d)&&d!==n&&i(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(r=a(t,d))||r.enumerable});return e};n=((e,t,n)=>(n=e==null?{}:r(s(e)),l(i(n,`default`,{value:e,enumerable:!0}),e)))(n,1);var u=/* @__PURE__ */ new WeakMap;function d(e){for(let t of e){let e=u.get(t);e&&(e(),u.delete(t))}}function f(e,t){for(let r of e)u.has(r)?n.default.setStyle(r,{cursor:t}):u.set(r,n.default.setStyleLock(r,`cursor`,t))}function p(e,t,r){n.default.triggerEvent(e,`${t}.ui.sortable`,{data:r,detail:{target:r.item,...r}})}var m=n.default.getContext(),h=n.default.getWindow(),g=class extends t.BaseComponent{static defaults={axis:null,cancel:`input, textarea, button, select, option`,connectWith:null,cursor:`auto`,disabled:!1,dropOnEmpty:!0,handle:null,helperClass:`bg-body-tertiary`,items:`:scope > li`,scroll:!0,scrollSensitivity:20,scrollSpeed:5,swapThreshold:.25};#e;#t=null;#n;#r;#i=[];#a=null;#o=null;#s;#c;#l=null;constructor(e,t){super(e,t);try{this.#s=this.options.handle?`:is(${this.options.items}) :is(${this.options.handle})`:this.options.items,this.#n=!1,this.#r=!this.options.disabled,this.#i=n.default.find(this.#s,this.node),f(this.#i,this.options.cursor),this.#d(),this.#i=null}catch(e){throw this.dispose(),e}}disable(){this.#r=!1}dispose(){this.node&&(d(this.#i??n.default.find(this.#s,this.node)),this.#l&&this.options.helperClass&&n.default.removeClass(this.#l,this.options.helperClass),this.#f(),this.#i=null,super.dispose())}enable(){this.#r=!0}items(){return n.default.find(this.options.items,this.node)}#u(){if(this.#o=null,!this.node||!this.#n||!this.#l||!this.#a)return;let e=n.default.getScrollX(h),t=n.default.getScrollY(h),r=n.default.height(h),i=n.default.width(h),a=e,o=t;if(this.#a.y<t+this.options.scrollSensitivity)o=Math.max(0,t-this.options.scrollSpeed);else if(this.#a.y>t+r-this.options.scrollSensitivity){let e=n.default.height(m,{boxSize:n.default.SCROLL_BOX}),i=Math.max(0,e-r);o=Math.min(i,t+this.options.scrollSpeed)}if(this.#a.x<e+this.options.scrollSensitivity)a=Math.max(0,e-this.options.scrollSpeed);else if(this.#a.x>e+i-this.options.scrollSensitivity){let t=n.default.width(m,{boxSize:n.default.SCROLL_BOX}),r=Math.max(0,t-i);a=Math.min(r,e+this.options.scrollSpeed)}if(a===e&&o===t)return;h.scrollTo({left:a,top:o,behavior:`instant`});let s=a-e,c=o-t;this.#a.x+=s,this.#a.y+=c,this.#m(s,c),this.#p()}#d(){let e=n.default.mouseDragFactory(e=>{let t=this.options.cancel&&(n.default.is(e.target,this.options.cancel)||n.default.is(e.currentTarget,this.options.cancel)||n.default.closest(e.target,this.options.cancel,this.node).length);if(e.button||!this.#r||t||n.default.getDataset(this.node,`uiDragging`)||(this.#l=this.options.handle?this.items().find(t=>n.default.hasDescendent(t,e.currentTarget)):e.currentTarget,!this.#l))return!1},e=>{if(!this.node||!this.#l)return;let r=this.#a;this.#a=(0,t.getPosition)(e);let i=r?this.#a.x-r.x:0,a=r?this.#a.y-r.y:0;if(!this.#n){this.#n=!0,this.#t=this.node,this.#c=this.items().indexOf(this.#l),this.#e=this.#c,n.default.setDataset(this.node,{uiDragging:!0});let e={item:this.#l,from:this.node,to:this.node,oldIndex:this.#c,newIndex:this.#c};if(p(this.node,`sort`,e),!this.node)return;this.options.helperClass&&n.default.addClass(this.#l,this.options.helperClass)}this.#m(i,a),this.#p()},e=>{if(!this.node)return;if(!this.#n){this.#l=null;return}e.type===`mouseup`&&e.preventDefault();let t=this.node,r=this.#t,i={item:this.#l,from:t,to:r,oldIndex:this.#c,newIndex:this.#e};p(r,`sorted`,i),this.node&&(this.options.helperClass&&n.default.removeClass(this.#l,this.options.helperClass),t===r?this.#e!==this.#c&&p(r,`update`,i):(p(t,`update`,i),this.node&&p(r,`update`,i)),this.node&&this.#f())});this.listen(this.node,`mousedown.ui.sortable touchstart.ui.sortable`,e,{delegate:this.#s}),this.listen(this.node,`receive.ui.sortable`,()=>{f(n.default.find(this.#s,this.node),this.options.cursor)})}#f(){this.#o!==null&&h.cancelAnimationFrame(this.#o),this.#n&&this.node&&n.default.removeDataset(this.node,`uiDragging`),this.#e=null,this.#t=null,this.#n=!1,this.#a=null,this.#o=null,this.#c=null,this.#l=null}#p(){this.node&&this.options.scroll&&this.#n&&this.#o===null&&(this.#o=h.requestAnimationFrame(()=>{this.#u()}))}#m(e,t){let r=this.node;if(this.options.connectWith){let e=n.default.find(this.options.connectWith).filter(e=>e!==this.node).filter(e=>{let t=this.constructor.init(e);return t.#r&&(t.options.dropOnEmpty||t.items().length)});e.length&&(r=n.default.nearestTo([this.node,...e],this.#a.x,this.#a.y,{offset:!0}))}let i=this.constructor.init(r),a=i.items().filter(e=>e!==this.#l),o=n.default.nearestTo(a,this.#a.x,this.#a.y,{offset:!0});if(o)this.#h(o,this.#a.x,this.#a.y,e,t);else if(r!==this.#t)n.default.append(r,this.#l);else return;let s=i.items().indexOf(this.#l);if(r!==this.#t){let e=this.#t,{handle:t}=this.constructor.init(e).options;d(t?n.default.find(t,this.#l):[this.#l]);let i={item:this.#l,from:e,to:r,oldIndex:this.#e,newIndex:s};if(p(e,`send`,i),!this.node)return;p(r,`receive`,i)}else if(this.#e!==s){let e={item:this.#l,from:r,to:r,oldIndex:this.#e,newIndex:s};p(r,`sorting`,e)}this.node&&(this.#e=s,this.#t=r)}#h(e,t,r,i,a){let o=n.default.center(e,{offset:!0}),s=n.default.rect(e,{offset:!0}),c=n.default.center(this.#l,{offset:!0}),l=Math.min(1,Math.max(0,this.options.swapThreshold)),u=.5,d=.5;i&&(u=i>0?l:1-l),a&&(d=a>0?l:1-l);let f;if(this.options.axis===`y`||o.x===c.x)f=r<s.top+s.height*d?`before`:`after`;else if(this.options.axis===`x`||o.y===c.y)f=t<s.left+s.width*u?`before`:`after`;else{let e=s.left+s.width*u,n=s.top+s.height*d;f=t<e&&r<n?`before`:`after`}n.default[f](e,this.#l)}};(0,t.initComponent)(`sortable`,g),e.Sortable=g});
|
|
2
2
|
//# sourceMappingURL=frost-ui-sortable.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frost-ui-sortable.min.js","names":["$","$","BaseComponent","getPosition"],"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 #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 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 setCursor($.find(this.#selector, this.node), this.options.cursor);\n this.#events();\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($.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 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 = (e) => {\n const cancelled = this.options.cancel &&\n (\n $.is(e.target, this.options.cancel) ||\n $.is(e.currentTarget, this.options.cancel) ||\n $.closest(e.target, this.options.cancel, this.node).length\n );\n\n if (\n e.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, e.currentTarget)) :\n e.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveEvent = (e) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(e);\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 = (e) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (e.type === 'mouseup') {\n e.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);\n\n $.addEventDelegate(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n this.#selector,\n dragEvent,\n );\n\n $.addEvent(this.node, 'receive.ui.sortable', (_) => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null && this.#scrollFrame !== undefined) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null && this.#scrollFrame !== undefined\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame((_) => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"frost-ui-sortable.min.js","names":["$","$","BaseComponent","getPosition","factory","global","exports","__create","__defProp","__getOwnPropDesc","__getOwnPropNames","__getProtoOf","__hasOwnProp","__copyProps","from","keys","i","n","key","to","except","k","desc","mod","target","_fr0st_query","cursorLocks","resetCursor","node","nodes","release","setCursor","cursor","triggerSortableEvent","name","data","document","window","Sortable","_fr0st_ui","options","#selector","#dragging","#enabled","#initialCursorNodes","#events","error","#target","#resetDrag","#scrollFrame","#pos","originalX","originalY","windowHeight","windowWidth","offsetX","offsetY","docHeight","maxY","docWidth","maxX","deltaX","deltaY","#updatePlacement","#scheduleScroll","dragHandler","cancelled","event","previousPos","#currentSortable","#startIndex","#currentIndex","eventData","source","destination","#checkScroll","nearestSortable","connected","sortable","nearestInstance","nearestItems","nearestItem","#updateTarget","newIndex","previousSortable","handle","nearestCenter","nearestRect","targetCenter","threshold","thresholdX","thresholdY","method","y","x","swapX","swapY","src_default"],"sources":["../src/helpers.js","../src/sortable.js","../src/index.js"],"sourcesContent":["/** @import { SortableEventData } from './sortable.js'; */\n\nimport $ from '@fr0st/query';\n\nconst cursorLocks = new WeakMap();\n\n/**\n * Resets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to restore.\n */\nexport function resetCursor(nodes) {\n for (const node of nodes) {\n const release = cursorLocks.get(node);\n\n if (!release) {\n continue;\n }\n\n release();\n cursorLocks.delete(node);\n }\n}\n\n/**\n * Sets the cursor style for a collection of elements.\n * @param {Iterable<HTMLElement>} nodes The elements to update.\n * @param {string} cursor The cursor style.\n */\nexport function setCursor(nodes, cursor) {\n for (const node of nodes) {\n if (cursorLocks.has(node)) {\n $.setStyle(node, { cursor });\n } else {\n cursorLocks.set(node, $.setStyleLock(node, 'cursor', cursor));\n }\n }\n}\n\n/**\n * Triggers a Sortable event with its data and detail payloads.\n * @param {HTMLElement} node The event target.\n * @param {string} name The event name without its namespace.\n * @param {SortableEventData} data The sorting event data.\n */\nexport function triggerSortableEvent(node, name, data) {\n $.triggerEvent(node, `${name}.ui.sortable`, {\n data,\n detail: {\n target: data.item,\n ...data,\n },\n });\n}\n","import $ from '@fr0st/query';\nimport { BaseComponent, getPosition } from '@fr0st/ui';\nimport { resetCursor, setCursor, triggerSortableEvent } from './helpers.js';\n\nconst document = $.getContext();\nconst window = $.getWindow();\n\n/** @typedef {'x'|'y'} SortableAxis */\n\n/**\n * @typedef {object} SortableOptions\n * @property {SortableAxis|null} [axis=null] The axis used to determine item placement.\n * @property {string} [cancel='input, textarea, button, select, option'] The selector for elements that cannot start a sort.\n * @property {string|null} [connectWith=null] The selector for connected Sortable containers.\n * @property {string} [cursor='auto'] The cursor applied to sortable items or handles.\n * @property {boolean} [disabled=false] Whether sorting is initially disabled.\n * @property {boolean} [dropOnEmpty=true] Whether connected empty containers accept items.\n * @property {string|null} [handle=null] The handle selector within each sortable item.\n * @property {string|null} [helperClass='bg-body-tertiary'] The class applied to an item while it is being sorted.\n * @property {string} [items=':scope > li'] The selector for sortable items.\n * @property {boolean} [scroll=true] Whether to scroll the window while sorting near an edge.\n * @property {number} [scrollSensitivity=20] The distance from a window edge that starts scrolling, in pixels.\n * @property {number} [scrollSpeed=5] The scroll distance applied per animation frame, in pixels.\n * @property {number} [swapThreshold=0.25] The fraction of an item crossed before swapping, from `0` to `1`.\n */\n\n/**\n * @typedef {object} SortableEventData\n * @property {HTMLElement} item The item being sorted.\n * @property {HTMLElement} from The previous or original Sortable container.\n * @property {HTMLElement} to The next or final Sortable container.\n * @property {number} oldIndex The previous or original item index.\n * @property {number} newIndex The next or final item index.\n */\n\n/**\n * Controls a sortable collection of elements.\n * @augments {BaseComponent<SortableOptions>}\n */\nexport default class Sortable extends BaseComponent {\n /** @type {SortableOptions} */\n static defaults = {\n axis: null,\n cancel: 'input, textarea, button, select, option',\n connectWith: null,\n cursor: 'auto',\n disabled: false,\n dropOnEmpty: true,\n handle: null,\n helperClass: 'bg-body-tertiary',\n items: ':scope > li',\n scroll: true,\n scrollSensitivity: 20,\n scrollSpeed: 5,\n swapThreshold: 0.25,\n };\n\n #currentIndex;\n #currentSortable = null;\n #dragging;\n #enabled;\n #initialCursorNodes = [];\n #pos = null;\n #scrollFrame = null;\n #selector;\n #startIndex;\n #target = null;\n\n /**\n * Creates a Sortable.\n * @param {HTMLElement} node The sortable container.\n * @param {SortableOptions} [options] The Sortable options.\n */\n constructor(node, options) {\n super(node, options);\n\n try {\n this.#selector = this.options.handle ?\n `:is(${this.options.items}) :is(${this.options.handle})` :\n this.options.items;\n\n this.#dragging = false;\n this.#enabled = !this.options.disabled;\n\n this.#initialCursorNodes = $.find(this.#selector, this.node);\n setCursor(this.#initialCursorNodes, this.options.cursor);\n this.#events();\n this.#initialCursorNodes = null;\n } catch (error) {\n this.dispose();\n throw error;\n }\n }\n\n /**\n * Disables the Sortable.\n */\n disable() {\n this.#enabled = false;\n }\n\n /** @inheritdoc */\n dispose() {\n if (!this.node) {\n return;\n }\n\n resetCursor(this.#initialCursorNodes ?? $.find(this.#selector, this.node));\n\n if (this.#target && this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n this.#resetDrag();\n\n this.#initialCursorNodes = null;\n\n super.dispose();\n }\n\n /**\n * Enables the Sortable.\n */\n enable() {\n this.#enabled = true;\n }\n\n /**\n * Gets the Sortable item elements.\n * @returns {HTMLElement[]} The Sortable item elements.\n */\n items() {\n return $.find(this.options.items, this.node);\n }\n\n /**\n * Checks whether the window should scroll while sorting.\n */\n #checkScroll() {\n this.#scrollFrame = null;\n\n if (!this.node || !this.#dragging || !this.#target || !this.#pos) {\n return;\n }\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n const windowHeight = $.height(window);\n const windowWidth = $.width(window);\n\n let offsetX = originalX;\n let offsetY = originalY;\n\n if (this.#pos.y < originalY + this.options.scrollSensitivity) {\n offsetY = Math.max(0, originalY - this.options.scrollSpeed);\n } else if (this.#pos.y > originalY + windowHeight - this.options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n const maxY = Math.max(0, docHeight - windowHeight);\n offsetY = Math.min(maxY, originalY + this.options.scrollSpeed);\n }\n\n if (this.#pos.x < originalX + this.options.scrollSensitivity) {\n offsetX = Math.max(0, originalX - this.options.scrollSpeed);\n } else if (this.#pos.x > originalX + windowWidth - this.options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n const maxX = Math.max(0, docWidth - windowWidth);\n offsetX = Math.min(maxX, originalX + this.options.scrollSpeed);\n }\n\n if (offsetX === originalX && offsetY === originalY) {\n return;\n }\n\n window.scrollTo({\n left: offsetX,\n top: offsetY,\n behavior: 'instant',\n });\n\n const deltaX = offsetX - originalX;\n const deltaY = offsetY - originalY;\n\n this.#pos.x += deltaX;\n this.#pos.y += deltaY;\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n }\n\n /**\n * Attaches events for the Sortable.\n */\n #events() {\n const downHandler = (event) => {\n const cancelled = this.options.cancel &&\n (\n $.is(event.target, this.options.cancel) ||\n $.is(event.currentTarget, this.options.cancel) ||\n $.closest(event.target, this.options.cancel, this.node).length\n );\n\n if (\n event.button ||\n !this.#enabled ||\n cancelled ||\n $.getDataset(this.node, 'uiDragging')\n ) {\n return false;\n }\n\n this.#target = this.options.handle ?\n this.items().find((node) => $.hasDescendent(node, event.currentTarget)) :\n event.currentTarget;\n\n if (!this.#target) {\n return false;\n }\n };\n\n const moveHandler = (event) => {\n if (!this.node || !this.#target) {\n return;\n }\n\n const previousPos = this.#pos;\n this.#pos = getPosition(event);\n const deltaX = previousPos ?\n this.#pos.x - previousPos.x :\n 0;\n const deltaY = previousPos ?\n this.#pos.y - previousPos.y :\n 0;\n\n if (!this.#dragging) {\n this.#dragging = true;\n this.#currentSortable = this.node;\n this.#startIndex = this.items().indexOf(this.#target);\n this.#currentIndex = this.#startIndex;\n\n $.setDataset(this.node, { uiDragging: true });\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: this.node,\n to: this.node,\n oldIndex: this.#startIndex,\n newIndex: this.#startIndex,\n };\n\n triggerSortableEvent(this.node, 'sort', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.addClass(this.#target, this.options.helperClass);\n }\n }\n\n this.#updatePlacement(deltaX, deltaY);\n this.#scheduleScroll();\n };\n\n const upHandler = (event) => {\n if (!this.node) {\n return;\n }\n\n if (!this.#dragging) {\n this.#target = null;\n return;\n }\n\n if (event.type === 'mouseup') {\n event.preventDefault();\n }\n\n const source = this.node;\n const destination = this.#currentSortable;\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: source,\n to: destination,\n oldIndex: this.#startIndex,\n newIndex: this.#currentIndex,\n };\n\n triggerSortableEvent(destination, 'sorted', eventData);\n\n if (!this.node) {\n return;\n }\n\n if (this.options.helperClass) {\n $.removeClass(this.#target, this.options.helperClass);\n }\n\n if (source !== destination) {\n triggerSortableEvent(source, 'update', eventData);\n\n if (this.node) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n } else if (this.#currentIndex !== this.#startIndex) {\n triggerSortableEvent(destination, 'update', eventData);\n }\n\n if (this.node) {\n this.#resetDrag();\n }\n };\n\n const dragHandler = $.mouseDragFactory(downHandler, moveHandler, upHandler);\n\n this.listen(\n this.node,\n 'mousedown.ui.sortable touchstart.ui.sortable',\n dragHandler,\n { delegate: this.#selector },\n );\n\n this.listen(this.node, 'receive.ui.sortable', () => {\n setCursor($.find(this.#selector, this.node), this.options.cursor);\n });\n }\n\n /**\n * Resets the active drag state.\n */\n #resetDrag() {\n if (this.#scrollFrame !== null) {\n window.cancelAnimationFrame(this.#scrollFrame);\n }\n\n if (this.#dragging && this.node) {\n $.removeDataset(this.node, 'uiDragging');\n }\n\n this.#currentIndex = null;\n this.#currentSortable = null;\n this.#dragging = false;\n this.#pos = null;\n this.#scrollFrame = null;\n this.#startIndex = null;\n this.#target = null;\n }\n\n /**\n * Schedules the next auto-scroll update.\n */\n #scheduleScroll() {\n if (\n !this.node ||\n !this.options.scroll ||\n !this.#dragging ||\n this.#scrollFrame !== null\n ) {\n return;\n }\n\n this.#scrollFrame = window.requestAnimationFrame(() => {\n this.#checkScroll();\n });\n }\n\n /**\n * Updates item placement and sorting events for the current pointer position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updatePlacement(deltaX, deltaY) {\n let nearestSortable = this.node;\n\n if (this.options.connectWith) {\n const connected = $.find(this.options.connectWith)\n .filter((node) => node !== this.node)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable.#enabled &&\n (sortable.options.dropOnEmpty || sortable.items().length);\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo(\n [this.node, ...connected],\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n }\n }\n\n const nearestInstance = this.constructor.init(nearestSortable);\n const nearestItems = nearestInstance.items()\n .filter((node) => node !== this.#target);\n const nearestItem = $.nearestTo(\n nearestItems,\n this.#pos.x,\n this.#pos.y,\n { offset: true },\n );\n\n if (nearestItem) {\n this.#updateTarget(\n nearestItem,\n this.#pos.x,\n this.#pos.y,\n deltaX,\n deltaY,\n );\n } else if (nearestSortable !== this.#currentSortable) {\n $.append(nearestSortable, this.#target);\n } else {\n return;\n }\n\n const newIndex = nearestInstance.items().indexOf(this.#target);\n\n if (nearestSortable !== this.#currentSortable) {\n const previousSortable = this.#currentSortable;\n const previousInstance = this.constructor.init(previousSortable);\n const { handle } = previousInstance.options;\n\n resetCursor(handle ?\n $.find(handle, this.#target) :\n [this.#target]);\n\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: previousSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(previousSortable, 'send', eventData);\n\n if (!this.node) {\n return;\n }\n\n triggerSortableEvent(nearestSortable, 'receive', eventData);\n } else if (this.#currentIndex !== newIndex) {\n /** @type {SortableEventData} */\n const eventData = {\n item: this.#target,\n from: nearestSortable,\n to: nearestSortable,\n oldIndex: this.#currentIndex,\n newIndex,\n };\n\n triggerSortableEvent(nearestSortable, 'sorting', eventData);\n }\n\n if (!this.node) {\n return;\n }\n\n this.#currentIndex = newIndex;\n this.#currentSortable = nearestSortable;\n }\n\n /**\n * Moves the target relative to the nearest item.\n * @param {HTMLElement} nearestItem The nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n * @param {number} deltaX The horizontal pointer movement.\n * @param {number} deltaY The vertical pointer movement.\n */\n #updateTarget(nearestItem, x, y, deltaX, deltaY) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const nearestRect = $.rect(nearestItem, { offset: true });\n const targetCenter = $.center(this.#target, { offset: true });\n const threshold = Math.min(1, Math.max(0, this.options.swapThreshold));\n let thresholdX = 0.5;\n let thresholdY = 0.5;\n\n if (deltaX) {\n thresholdX = deltaX > 0 ?\n threshold :\n 1 - threshold;\n }\n\n if (deltaY) {\n thresholdY = deltaY > 0 ?\n threshold :\n 1 - threshold;\n }\n\n let method;\n if (this.options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = y < swapY ?\n 'before' :\n 'after';\n } else if (this.options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n method = x < swapX ?\n 'before' :\n 'after';\n } else {\n const swapX = nearestRect.left + nearestRect.width * thresholdX;\n const swapY = nearestRect.top + nearestRect.height * thresholdY;\n method = x < swapX && y < swapY ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this.#target);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\n\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fr0st/ui-sortable",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.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": [
|
|
@@ -55,13 +55,13 @@
|
|
|
55
55
|
"baseline newly available"
|
|
56
56
|
],
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@fr0st/eslint-config": "^
|
|
59
|
-
"@fr0st/query": "^5.0.
|
|
60
|
-
"@fr0st/ui": "^4.0.
|
|
61
|
-
"@playwright/test": "^1.
|
|
62
|
-
"eslint": "^10.
|
|
63
|
-
"monocart-reporter": "^2.
|
|
64
|
-
"vite": "^8.3.
|
|
58
|
+
"@fr0st/eslint-config": "^6.0.1",
|
|
59
|
+
"@fr0st/query": "^5.0.1",
|
|
60
|
+
"@fr0st/ui": "^4.0.2",
|
|
61
|
+
"@playwright/test": "^1.64.1",
|
|
62
|
+
"eslint": "^10.13.0",
|
|
63
|
+
"monocart-reporter": "^2.14.0",
|
|
64
|
+
"vite": "^8.3.4"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
67
|
"@fr0st/query": "^5.0.0",
|