{"version":3,"file":"index.js","sources":["../../../../src/packages/core/sorter/sorter.controller.ts","../../../../src/packages/core/sorter/replacement-resolver-as-grid.function.ts"],"sourcesContent":["import { isWithinRect } from '@umbraco-cms/backoffice/utils';\r\nimport { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';\r\nimport type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';\r\n\r\nconst autoScrollSensitivity = 50;\r\nconst autoScrollSpeed = 16;\r\n\r\n/**\r\n *\r\n * @param el\r\n * @param includeSelf\r\n */\r\nfunction getParentScrollElement(el: Element, includeSelf: boolean) {\r\n\tif (!el || !el.getBoundingClientRect) return null;\r\n\r\n\tlet elem = el;\r\n\tlet gotSelf = false;\r\n\r\n\twhile (elem) {\r\n\t\t// we don't need to get elem css if it isn't even overflowing in the first place (performance)\r\n\t\tif (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) {\r\n\t\t\tconst elemCSS = getComputedStyle(elem);\r\n\r\n\t\t\tif (\r\n\t\t\t\t(elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')) ||\r\n\t\t\t\t(elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll'))\r\n\t\t\t) {\r\n\t\t\t\tif (!elem.getBoundingClientRect || elem === document.body) return null;\r\n\t\t\t\tif (gotSelf || includeSelf) return elem;\r\n\t\t\t\tgotSelf = true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (elem.parentNode === document) {\r\n\t\t\treturn null;\r\n\t\t} else if (elem.parentNode instanceof ShadowRoot) {\r\n\t\t\telem = elem.parentNode.host;\r\n\t\t} else {\r\n\t\t\telem = elem.parentNode as Element;\r\n\t\t}\r\n\t}\r\n\r\n\treturn null;\r\n}\r\n\r\n/**\r\n *\r\n * @param element\r\n * @param ignorerSelectors\r\n */\r\nfunction setupIgnorerElements(element: HTMLElement, ignorerSelectors: string) {\r\n\tconst selectors = ignorerSelectors.split(',');\r\n\tselectors.push('[draggable=\"false\"]');\r\n\tselectors.forEach(function (criteria) {\r\n\t\telement.querySelectorAll(criteria.trim()).forEach(setupPreventEvent);\r\n\t});\r\n}\r\n/**\r\n *\r\n * @param element\r\n * @param ignorerSelectors\r\n */\r\nfunction destroyIgnorerElements(element: HTMLElement, ignorerSelectors: string) {\r\n\tconst selectors = ignorerSelectors.split(',');\r\n\tselectors.push('[draggable=\"false\"]');\r\n\tselectors.forEach(function (criteria: string) {\r\n\t\telement.querySelectorAll(criteria.trim()).forEach(destroyPreventEvent);\r\n\t});\r\n}\r\n/**\r\n *\r\n * @param element\r\n */\r\nfunction setupPreventEvent(element: Element) {\r\n\tconsole.log('prevent on', element);\r\n\t(element as HTMLElement).draggable = false;\r\n\t//(element as HTMLElement).setAttribute('draggable', 'false');\r\n}\r\n/**\r\n *\r\n * @param element\r\n */\r\nfunction destroyPreventEvent(element: Element) {\r\n\t(element as HTMLElement).draggable = false;\r\n\t//element.removeAttribute('draggable');\r\n}\r\n\r\nexport type UmbSorterResolvePlacementReturn =\r\n\t| boolean\r\n\t| null\r\n\t| {\r\n\t\t\tplaceAfter: boolean;\r\n\t\t\tverticalDirection?: boolean;\r\n\t };\r\n\r\nexport type UmbSorterResolvePlacementArgs = {\r\n\tcontainerElement: Element;\r\n\tcontainerRect: DOMRect;\r\n\titem: T;\r\n\titemIndex: number | null;\r\n\telement: ElementType;\r\n\telementRect: DOMRect;\r\n\trelatedElement: ElementType;\r\n\trelatedModel: T;\r\n\trelatedRect: DOMRect;\r\n\trelatedIndex: number | null;\r\n\tplaceholderIsInThisRow: boolean;\r\n\thorizontalPlaceAfter: boolean;\r\n\tpointerX: number;\r\n\tpointerY: number;\r\n};\r\n\r\n/**\r\n * @deprecated will be removed in v.17, use `UmbSorterResolvePlacementArgs`\r\n */\r\nexport type resolvePlacementArgs = UmbSorterResolvePlacementArgs<\r\n\tT,\r\n\tElementType\r\n>;\r\n\r\ntype UniqueType = string | symbol | number;\r\n\r\n/**\r\n * Internal type, which is adjusted to become the public one.\r\n @internal */\r\ntype INTERNAL_UmbSorterConfig = {\r\n\t/**\r\n\t * Define how to retrive the unique identifier of an element. If this method returns undefined, the move will be cancelled.\r\n\t */\r\n\tgetUniqueOfElement: (element: ElementType) => UniqueType | null | undefined;\r\n\tgetUniqueOfModel: (modeEntry: T) => UniqueType | null | undefined;\r\n\t/**\r\n\t * Optionally define a unique identifier for each sorter experience, all Sorters that uses the same identifier to connect with other sorters.\r\n\t */\r\n\tidentifier: UniqueType;\r\n\t/**\r\n\t * A query selector for the item element.\r\n\t */\r\n\titemSelector: string;\r\n\tdisabledItemSelector?: string;\r\n\t/**\r\n\t * A selector for the container element, if not defined the host element will be used as container.\r\n\t */\r\n\tcontainerSelector: string;\r\n\t/**\r\n\t * A selector for elements to ignore, elements that should not be draggable when within an draggable item, This defaults to links, images & iframes.\r\n\t */\r\n\tignorerSelector: string;\r\n\t/**\r\n\t * An class to set on the placeholder element.\r\n\t */\r\n\tplaceholderClass?: string;\r\n\t/**\r\n\t * An attribute to set on the placeholder element.\r\n\t */\r\n\tplaceholderAttr?: string;\r\n\t/**\r\n\t * The selector to find the draggable element within the item.\r\n\t */\r\n\tdraggableSelector?: string;\r\n\t/**\r\n\t * The selector to define the interactive element within the item, this element will then become the only interactive part, the item can only be dragged by mouse when interacting with this element.\r\n\t */\r\n\thandleSelector?: string;\r\n\r\n\t//boundarySelector?: string;\r\n\tdataTransferResolver?: (dataTransfer: DataTransfer | null, currentItem: T) => void;\r\n\tonStart?: (argument: { item: T; element: ElementType }) => void;\r\n\t/**\r\n\t * This callback is executed every time where is a change to this model, this could be a move, insert or remove.\r\n\t * But notice its not called if a more specific callback is provided, such would be the performItemMove, performItemInsert or performItemRemove or performItemRemove.\r\n\t */\r\n\tonChange?: (argument: { item: T; model: Array }) => void;\r\n\t/**\r\n\t * This callback is executed when an item is moved from another container to this container.\r\n\t */\r\n\tonContainerChange?: (argument: { item: T; model: Array; from: UmbSorterController }) => void;\r\n\tonEnd?: (argument: { item: T; element: ElementType }) => void;\r\n\titemHasNestedContainersResolver?: (element: HTMLElement) => boolean;\r\n\t/**\r\n\t * Callback when a item move is disallowed.\r\n\t * This should make a visual indication for the user to understand that the move is not allowed.\r\n\t */\r\n\tonDisallowed?: (argument: { item: T; element: ElementType }) => void;\r\n\t/**\r\n\t * Callback when a item move is allowed.\r\n\t * This should remove any visual indication of the disallowing, reverting the work of the onDisallowed callback.\r\n\t */\r\n\tonAllowed?: (argument: { item: T; element: ElementType }) => void;\r\n\t/**\r\n\t * Callback when user tries to move an item from another Sorter to this Sorter, return true or false to allow or disallow the move.\r\n\t */\r\n\tonRequestMove?: (argument: { item: T }) => boolean;\r\n\t/**\r\n\t * This callback is executed when an item is hovered within this container.\r\n\t * The callback should return true if the item should be placed after the hovered item, or false if it should be placed before the hovered item.\r\n\t * In this way the callback can control the placement of the item.\r\n\t * If it returns null the placement will be prevented.\r\n\t * @example\r\n\t * This is equivalent to the default behavior:\r\n\t * ```ts\r\n\t * resolvePlacement: (argument) => {\r\n\t * \tif(argument.pointerY > argument.relatedRect.top + argument.relatedRect.height * 0.5) {\r\n\t * \t\treturn true; // Place after\r\n\t * \t} else {\r\n\t * \t\treturn false; // Place before\r\n\t * \t}\r\n\t * }\r\n\t */\r\n\tresolvePlacement?: (argument: UmbSorterResolvePlacementArgs) => UmbSorterResolvePlacementReturn;\r\n\t/**\r\n\t * This callback is executed when an item is moved within this container.\r\n\t */\r\n\tperformItemMove?: (argument: { item: T; newIndex: number; oldIndex: number }) => Promise | boolean;\r\n\t/**\r\n\t * This callback is executed when an item should be inserted into this container.\r\n\t */\r\n\tperformItemInsert?: (argument: { item: T; newIndex: number }) => Promise | boolean;\r\n\t/**\r\n\t * This callback is executed when an item should be removed from this container.\r\n\t */\r\n\tperformItemRemove?: (argument: { item: T }) => Promise | boolean;\r\n};\r\n\r\n// External type with some properties optional, as they have fallback values:\r\nexport type UmbSorterConfig = Omit<\r\n\tINTERNAL_UmbSorterConfig,\r\n\t'ignorerSelector' | 'containerSelector' | 'identifier'\r\n> &\r\n\tPartial, 'ignorerSelector' | 'containerSelector' | 'identifier'>>;\r\n\r\n/**\r\n\r\n * @class UmbSorterController\r\n * @implements {UmbControllerInterface}\r\n * @description This controller can make user able to sort items.\r\n * @example\r\n *\r\n * This example shows how to setup a sorter controller with no special needs.\r\n * Assuming your declaring this on a Umbraco Element(UmbControllerHostElement):\r\n *\r\n * ```ts\r\n * const sorter = new UmbSorterController(this, {\r\n * \titemSelector: '.item',\r\n * \tcontainerSelector: '.container',\r\n * \tgetUniqueOfElement: (element) => element.dataset.id,\r\n * \tgetUniqueOfModel: (model) => model.id\r\n * });\r\n * ```\r\n */\r\nexport class UmbSorterController extends UmbControllerBase {\r\n\t//\r\n\t// The sorter who last indicated that it was okay or not okay to drop here:\r\n\tstatic lastIndicationSorter?: UmbSorterController;\r\n\r\n\t// A sorter that is requested to become the next sorter:\r\n\tstatic originalSorter?: UmbSorterController;\r\n\tstatic originalIndex?: number;\r\n\r\n\t// A sorter that is requested to become the next sorter:\r\n\tstatic dropSorter?: UmbSorterController;\r\n\r\n\t// The sorter of which the element is located within:\r\n\tstatic activeSorter?: UmbSorterController;\r\n\r\n\t// Information about the current dragged item/element:\r\n\tstatic activeIndex?: number;\r\n\tstatic activeItem?: any;\r\n\tstatic activeElement?: HTMLElement;\r\n\tstatic activeDragElement?: HTMLElement;\r\n\r\n\t#host;\r\n\t#isConnected = false;\r\n\t#config: INTERNAL_UmbSorterConfig;\r\n\t#observer;\r\n\r\n\t#model: Array = [];\r\n\tstatic rqaId?: number;\r\n\r\n\t#containerElement!: HTMLElement;\r\n\t#useContainerShadowRoot?: boolean;\r\n\r\n\t#scrollElement?: Element | null;\r\n\r\n\t#enabled = true;\r\n\r\n\t#dragX = 0;\r\n\t#dragY = 0;\r\n\r\n\t#elements = Array();\r\n\r\n\tpublic get identifier() {\r\n\t\treturn this.#config.identifier;\r\n\t}\r\n\tpublic set identifier(identifier: UniqueType) {\r\n\t\tthis.#config.identifier = identifier;\r\n\t}\r\n\t#isActiveIdentifier() {\r\n\t\treturn UmbSorterController.activeSorter?.identifier === this.identifier;\r\n\t}\r\n\r\n\tconstructor(host: UmbControllerHostElement, config: UmbSorterConfig) {\r\n\t\tsuper(host);\r\n\t\tthis.#host = host;\r\n\r\n\t\t// Set defaults:\r\n\t\tconfig.identifier ??= Symbol();\r\n\t\tconfig.ignorerSelector ??= 'a,img,iframe,input,textarea,select,option';\r\n\t\tif (!config.placeholderClass && !config.placeholderAttr) {\r\n\t\t\tconfig.placeholderAttr = 'drag-placeholder';\r\n\t\t}\r\n\r\n\t\tthis.#config = config as INTERNAL_UmbSorterConfig;\r\n\t\thost.addUmbController(this);\r\n\r\n\t\tthis.#observer = new MutationObserver((mutations) => {\r\n\t\t\tmutations.forEach((mutation) => {\r\n\t\t\t\tmutation.addedNodes.forEach((addedNode) => {\r\n\t\t\t\t\tif ((addedNode as HTMLElement).matches && (addedNode as HTMLElement).matches(this.#config.itemSelector)) {\r\n\t\t\t\t\t\tthis.setupItem(addedNode as ElementType);\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t\tmutation.removedNodes.forEach((removedNode) => {\r\n\t\t\t\t\tif ((removedNode as HTMLElement).matches && (removedNode as HTMLElement).matches(this.#config.itemSelector)) {\r\n\t\t\t\t\t\tthis.destroyItem(removedNode as ElementType);\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t});\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Enables the sorter, this will allow sorting to happen.\r\n\t * @returns {*} {void}\r\n\t * @memberof UmbSorterController\r\n\t */\r\n\tenable(): void {\r\n\t\tif (this.#enabled) return;\r\n\t\tthis.#enabled = true;\r\n\t\tif (this.#isConnected) {\r\n\t\t\tthis.#initialize();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Disables the sorter, this will prevent any sorting to happen.\r\n\t * @returns {*} {void}\r\n\t * @memberof UmbSorterController\r\n\t */\r\n\tdisable(): void {\r\n\t\tif (!this.#enabled) return;\r\n\t\tthis.#enabled = false;\r\n\t\tif (this.#isConnected) {\r\n\t\t\tthis.#uninitialize();\r\n\t\t}\r\n\t}\r\n\r\n\tsetModel(model: Array | undefined): void {\r\n\t\tthis.#model = model ?? [];\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the model of the sorter.\r\n\t * @returns {Array}\r\n\t * @memberof UmbSorterController\r\n\t */\r\n\tgetModel(): Array {\r\n\t\treturn this.#model;\r\n\t}\r\n\r\n\thasItem(unique: UniqueType) {\r\n\t\treturn this.#model.find((x) => this.#config.getUniqueOfModel(x) === unique) !== undefined;\r\n\t}\r\n\r\n\tgetItem(unique: UniqueType) {\r\n\t\treturn this.#model.find((x) => this.#config.getUniqueOfModel(x) === unique);\r\n\t}\r\n\r\n\toverride hostConnected() {\r\n\t\tthis.#isConnected = true;\r\n\t\tif (this.#enabled) {\r\n\t\t\trequestAnimationFrame(this.#initialize);\r\n\t\t}\r\n\t}\r\n\r\n\toverride hostDisconnected() {\r\n\t\tthis.#isConnected = false;\r\n\t\tif (this.#enabled) {\r\n\t\t\tthis.#uninitialize();\r\n\t\t}\r\n\t}\r\n\r\n\t#initialize = () => {\r\n\t\tif (this.#isConnected === false) return;\r\n\r\n\t\tconst containerEl =\r\n\t\t\t(this.#config.containerSelector\r\n\t\t\t\t? this.#host.shadowRoot!.querySelector(this.#config.containerSelector)\r\n\t\t\t\t: this.#host) ?? this.#host;\r\n\r\n\t\tthis.#containerElement = containerEl as HTMLElement;\r\n\t\tthis.#useContainerShadowRoot = this.#containerElement === this.#host;\r\n\r\n\t\t// Only look at the shadowRoot if the containerElement is host.\r\n\t\tconst containerElement = this.#useContainerShadowRoot\r\n\t\t\t? (this.#containerElement.shadowRoot ?? this.#containerElement)\r\n\t\t\t: this.#containerElement;\r\n\t\tcontainerElement.addEventListener('dragover', this.#itemDraggedOver as unknown as EventListener);\r\n\r\n\t\tthis.#observer.disconnect();\r\n\r\n\t\tcontainerElement.querySelectorAll(this.#config.itemSelector).forEach((child) => {\r\n\t\t\tif (child.matches && child.matches(this.#config.itemSelector)) {\r\n\t\t\t\tthis.setupItem(child as ElementType);\r\n\t\t\t}\r\n\t\t});\r\n\t\tthis.#observer.observe(containerElement, {\r\n\t\t\tchildList: true,\r\n\t\t\tsubtree: false,\r\n\t\t});\r\n\t};\r\n\r\n\t#uninitialize() {\r\n\t\t// TODO: Is there more clean up to do??\r\n\t\tthis.#observer.disconnect();\r\n\t\tif (this.#containerElement) {\r\n\t\t\t// Only look at the shadowRoot if the containerElement is host.\r\n\t\t\tconst containerElement = this.#useContainerShadowRoot\r\n\t\t\t\t? (this.#containerElement.shadowRoot ?? this.#containerElement)\r\n\t\t\t\t: this.#containerElement;\r\n\r\n\t\t\tcontainerElement.removeEventListener('dragover', this.#itemDraggedOver as unknown as EventListener);\r\n\t\t\t(this.#containerElement as unknown) = undefined;\r\n\t\t}\r\n\r\n\t\tthis.#elements.forEach((item) => this.destroyItem(item));\r\n\t}\r\n\r\n\t#itemDraggedOver = (e: DragEvent) => {\r\n\t\t//if(UmbSorterController.activeSorter === this) return;\r\n\t\tconst dropSorter = UmbSorterController.dropSorter as unknown as UmbSorterController;\r\n\t\tif (!dropSorter || dropSorter.identifier !== this.identifier) return;\r\n\r\n\t\tif (dropSorter === this) {\r\n\t\t\te.preventDefault();\r\n\t\t\tif (e.dataTransfer) {\r\n\t\t\t\te.dataTransfer.dropEffect = 'move';\r\n\t\t\t}\r\n\r\n\t\t\t// Do nothing as we are the active sorter.\r\n\t\t\tthis.#handleDragMove(e);\r\n\r\n\t\t\t// Maybe we need to stop the event in this case.\r\n\r\n\t\t\t// Do not bubble up to parent sorters:\r\n\t\t\te.stopPropagation();\r\n\r\n\t\t\treturn;\r\n\t\t} else {\r\n\t\t\t// Indication if drop is good:\r\n\t\t\tif (this.updateAllowIndication(UmbSorterController.activeItem) === false) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\t// If so lets set the approaching sorter:\r\n\t\t\tUmbSorterController.dropSorter = this as unknown as UmbSorterController;\r\n\r\n\t\t\t// Do not bubble up to parent sorters:\r\n\t\t\te.stopPropagation();\r\n\t\t}\r\n\t};\r\n\r\n\t#getDraggableElement(element: HTMLElement) {\r\n\t\tif (this.#config.draggableSelector) {\r\n\t\t\t// Concept for enabling getting element within ShadowRoot: (But it might need to be configurable, so its still possible to get light dom element(slotted), despite the host is a web-component with shadow-dom.) [NL]\r\n\t\t\tconst queryFromEl = element.shadowRoot ?? element;\r\n\t\t\treturn (queryFromEl.querySelector(this.#config.draggableSelector) as HTMLElement | undefined) ?? element;\r\n\t\t}\r\n\t\treturn element;\r\n\t}\r\n\r\n\t#getHandleElement(element: HTMLElement) {\r\n\t\tif (this.#config.handleSelector) {\r\n\t\t\t// Concept for enabling getting element within ShadowRoot: (But it might need to be configurable, so its still possible to get light dom element(slotted), despite the host is a web-component with shadow-dom.) [NL]\r\n\t\t\tconst queryFromEl = element.shadowRoot ?? element;\r\n\t\t\treturn (queryFromEl.querySelector(this.#config.handleSelector) as HTMLElement | undefined) ?? element;\r\n\t\t}\r\n\t\treturn element;\r\n\t}\r\n\r\n\t#getElement(innerElement: HTMLElement): HTMLElement | null {\r\n\t\tlet source = innerElement;\r\n\t\tlet element: HTMLElement | null = null;\r\n\t\twhile (!element) {\r\n\t\t\telement = source.closest(this.#config.itemSelector);\r\n\t\t\tif (!element) {\r\n\t\t\t\tconst containingElement = (source.getRootNode() as ShadowRoot).host;\r\n\t\t\t\tconst newSource =\r\n\t\t\t\t\tsource === containingElement\r\n\t\t\t\t\t\t? ((source.parentElement?.getRootNode() as ShadowRoot | undefined)?.host as HTMLElement | undefined)\r\n\t\t\t\t\t\t: (containingElement as HTMLElement);\r\n\t\t\t\tif (newSource) {\r\n\t\t\t\t\tsource = newSource;\r\n\t\t\t\t} else {\r\n\t\t\t\t\treturn null;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn element;\r\n\t}\r\n\r\n\tsetupItem(element: ElementType) {\r\n\t\tif (this.#config.ignorerSelector) {\r\n\t\t\tsetupIgnorerElements(element, this.#config.ignorerSelector);\r\n\t\t}\r\n\r\n\t\tif (!this.#config.disabledItemSelector || !element.matches(this.#config.disabledItemSelector)) {\r\n\t\t\t// Idea: to make sure on does not get initialized twice: if ((element as HTMLElement).draggable === true) return;\r\n\t\t\tconst draggableElement = this.#getDraggableElement(element);\r\n\t\t\tconst handleElement = this.#getHandleElement(element);\r\n\t\t\thandleElement.addEventListener('mousedown', this.#handleHandleMouseDown);\r\n\t\t\t// Will be set to true by the 'mousedown' event if approved:\r\n\t\t\t(draggableElement as HTMLElement).draggable = false;\r\n\t\t\tdraggableElement.addEventListener('dragstart', this.#handleDragStart);\r\n\t\t\tdraggableElement.addEventListener('dragend', this.#handleDragEnd);\r\n\t\t}\r\n\r\n\t\t// If we have a currentItem and the element matches, we should set the currentElement to this element.\r\n\t\tif (UmbSorterController.activeItem && this.#isActiveIdentifier()) {\r\n\t\t\tconst elUnique = this.#config.getUniqueOfElement(element);\r\n\t\t\tconst modelUnique = this.#config.getUniqueOfModel(UmbSorterController.activeItem);\r\n\t\t\tif (elUnique === modelUnique && elUnique !== undefined) {\r\n\t\t\t\tif (UmbSorterController.activeElement !== element) {\r\n\t\t\t\t\tthis.#setCurrentElement(element);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.#elements.push(element);\r\n\t\tthis.#elements = Array.from(new Set(this.#elements));\r\n\t}\r\n\r\n\tdestroyItem(element: HTMLElement) {\r\n\t\tif (this.#config.ignorerSelector) {\r\n\t\t\tdestroyIgnorerElements(element, this.#config.ignorerSelector);\r\n\t\t}\r\n\r\n\t\tconst draggableElement = this.#getDraggableElement(element);\r\n\t\tdraggableElement.removeEventListener('dragstart', this.#handleDragStart);\r\n\t\tdraggableElement.removeEventListener('dragend', this.#handleDragEnd);\r\n\r\n\t\tconst handleElement = this.#getHandleElement(element);\r\n\t\thandleElement.removeEventListener('mousedown', this.#handleHandleMouseDown);\r\n\r\n\t\t(draggableElement as HTMLElement).draggable = false;\r\n\r\n\t\tthis.#elements = this.#elements.filter((x) => x !== element);\r\n\t}\r\n\r\n\t#setupPlaceholderStyle() {\r\n\t\tif (this.#config.placeholderClass) {\r\n\t\t\tUmbSorterController.activeElement?.classList.add(this.#config.placeholderClass);\r\n\t\t}\r\n\t\tif (this.#config.placeholderAttr) {\r\n\t\t\tUmbSorterController.activeElement?.setAttribute(this.#config.placeholderAttr, '');\r\n\t\t}\r\n\t}\r\n\t#removePlaceholderStyle() {\r\n\t\tif (this.#config.placeholderClass) {\r\n\t\t\tUmbSorterController.activeElement?.classList.remove(this.#config.placeholderClass);\r\n\t\t}\r\n\t\tif (this.#config.placeholderAttr) {\r\n\t\t\tUmbSorterController.activeElement?.removeAttribute(this.#config.placeholderAttr);\r\n\t\t}\r\n\t}\r\n\r\n\t#setCurrentElement(element: ElementType) {\r\n\t\tUmbSorterController.activeElement = element;\r\n\r\n\t\tUmbSorterController.activeDragElement = this.#getDraggableElement(element);\r\n\r\n\t\tif (!UmbSorterController.activeDragElement) {\r\n\t\t\tthrow new Error(\r\n\t\t\t\t'Could not find drag element, query was made with the `draggableSelector` of \"' +\r\n\t\t\t\t\tthis.#config.draggableSelector +\r\n\t\t\t\t\t'\"',\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tthis.#setupPlaceholderStyle();\r\n\t}\r\n\r\n\t#handleHandleMouseDown = (event: MouseEvent) => {\r\n\t\tconst target = event.target as HTMLElement;\r\n\t\tconst composedPath = event.composedPath();\r\n\r\n\t\t// Test for a match with the ignore selectors:\r\n\t\tif (this.#config.ignorerSelector) {\r\n\t\t\tif (target.matches(this.#config.ignorerSelector)) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\t// filter composedPath for only elements descending from the event.target:\r\n\t\t\tconst index = composedPath.indexOf(target);\r\n\t\t\tconst composedPathBelowTarget = index !== -1 ? composedPath.slice(0, index) : undefined;\r\n\r\n\t\t\tif (composedPathBelowTarget) {\r\n\t\t\t\tconst ignoreThis = composedPathBelowTarget.some((x) =>\r\n\t\t\t\t\t(x as HTMLElement).matches?.('[draggable=\"false\"],' + this.#config.ignorerSelector),\r\n\t\t\t\t);\r\n\t\t\t\tif (ignoreThis) {\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (event.target && event.button === 0) {\r\n\t\t\tconst element = this.#getElement(event.target as HTMLElement);\r\n\t\t\tif (!element) return;\r\n\t\t\tconst dragElement = this.#getDraggableElement(element);\r\n\t\t\tif (!dragElement) return;\r\n\r\n\t\t\tdragElement.addEventListener('mouseup', this.#handleDragElementMouseUp);\r\n\t\t\tdragElement.draggable = true;\r\n\t\t}\r\n\t};\r\n\r\n\t#handleDragElementMouseUp = (event: MouseEvent) => {\r\n\t\tconst target = event.target as HTMLElement | null;\r\n\t\tif (target) {\r\n\t\t\ttarget.removeEventListener('mouseup', this.#handleDragElementMouseUp);\r\n\t\t\ttarget.draggable = false;\r\n\t\t}\r\n\t};\r\n\r\n\t#handleDragStart = (event: DragEvent) => {\r\n\t\tconst element = (event.target as HTMLElement).closest(this.#config.itemSelector) as HTMLElement | null;\r\n\t\tif (!element) return;\r\n\r\n\t\tif (UmbSorterController.activeElement && UmbSorterController.activeElement !== element) {\r\n\t\t\t// TODO: Remove this console log at one point.\r\n\t\t\tconsole.error('drag start ws cancelled due to another drag was still active');\r\n\t\t\tthis.#handleDragEnd();\r\n\t\t}\r\n\r\n\t\tevent.stopPropagation();\r\n\t\tif (event.dataTransfer) {\r\n\t\t\tconst dragElement = UmbSorterController.activeDragElement ?? element;\r\n\t\t\tconst activeDragRect = dragElement.getBoundingClientRect();\r\n\t\t\tevent.dataTransfer.setDragImage(dragElement, event.clientX - activeDragRect.x, event.clientY - activeDragRect.y);\r\n\t\t\tevent.dataTransfer.dropEffect = 'move';\r\n\t\t\tevent.dataTransfer.effectAllowed = 'all'; // copyMove when we enhance the drag with clipboard data.// defaults to 'all'\r\n\t\t}\r\n\r\n\t\tif (!this.#scrollElement) {\r\n\t\t\tthis.#scrollElement = getParentScrollElement(this.#containerElement, true);\r\n\t\t}\r\n\r\n\t\tthis.#setCurrentElement(element as ElementType);\r\n\r\n\t\tUmbSorterController.activeDragElement?.addEventListener('dragend', this.#handleDragEnd);\r\n\t\twindow.addEventListener('mouseup', this.#handleMouseUp);\r\n\t\twindow.addEventListener('mouseout', this.#handleMouseUp);\r\n\t\twindow.addEventListener('mouseleave', this.#handleMouseUp);\r\n\t\twindow.addEventListener('mousemove', this.#handleMouseMove);\r\n\r\n\t\tUmbSorterController.activeItem = this.getItemOfElement(UmbSorterController.activeElement! as ElementType);\r\n\r\n\t\tUmbSorterController.originalSorter = this as unknown as UmbSorterController;\r\n\t\t// Notice, it is acceptable here to get index via object reference, but only cause there has been no change at this stage, otherwise we cannot trust the object instance is represented in the model — it could have mutated or been cloned [NL]\r\n\t\tUmbSorterController.originalIndex = this.#model.indexOf(UmbSorterController.activeItem);\r\n\r\n\t\tif (!UmbSorterController.activeItem) {\r\n\t\t\tconsole.error('Could not find item related to this element.', UmbSorterController.activeElement);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t// Get the current index of the item:\r\n\t\tUmbSorterController.activeIndex = UmbSorterController.originalIndex;\r\n\t\tUmbSorterController.activeDragElement!.style.transform = 'translateZ(0)'; // Solves problem with FireFox and ShadowDom in the drag-image.\r\n\r\n\t\tif (this.#config.dataTransferResolver) {\r\n\t\t\tthis.#config.dataTransferResolver(event.dataTransfer, UmbSorterController.activeItem as T);\r\n\t\t}\r\n\r\n\t\tif (this.#config.onStart) {\r\n\t\t\tthis.#config.onStart({\r\n\t\t\t\titem: UmbSorterController.activeItem,\r\n\t\t\t\telement: UmbSorterController.activeElement! as ElementType,\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\t// Assuming we can only drag one thing at the time.\r\n\t\tUmbSorterController.activeSorter = this as unknown as UmbSorterController;\r\n\t\tUmbSorterController.dropSorter = this as unknown as UmbSorterController;\r\n\r\n\t\t// We must wait one frame before changing the look of the block.\r\n\t\tUmbSorterController.rqaId = requestAnimationFrame(() => {\r\n\t\t\t// It should be okay to use the same rqaId, as the move does not, or is okay not, to happen on first frame/drag-move.\r\n\t\t\tUmbSorterController.rqaId = undefined;\r\n\t\t\tif (UmbSorterController.activeDragElement) {\r\n\t\t\t\tUmbSorterController.activeDragElement.style.transform = '';\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\treturn true;\r\n\t};\r\n\r\n\t#handleDragEnd = (event?: DragEvent) => {\r\n\t\t// If browser thinks this was a cancelled move, we should revert the move. (based on dropEffect === 'none') [NL]\r\n\t\t// But notice, this also count when releasing the mouse outside the sorters element, this i'm not sure if I agree on, would be ideal only to revert if ESC was pressed. [NL]\r\n\t\tif (UmbSorterController.originalSorter && event?.dataTransfer != null && event.dataTransfer.dropEffect === 'none') {\r\n\t\t\t// Revert move, to start position.\r\n\t\t\tUmbSorterController.originalSorter.moveItemInModel(\r\n\t\t\t\tUmbSorterController.originalIndex ?? 0,\r\n\t\t\t\tUmbSorterController.activeSorter!,\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tthis.#handleMoveEnd();\r\n\t};\r\n\r\n\t/**\r\n\t * Listen to mouse move, to check if the mouse is still down.\r\n\t * This event does not happen while dragging, so its a indication that the drag is over.\r\n\t */\r\n\t#handleMouseMove = (event: MouseEvent) => {\r\n\t\t// buttons should reprensent which buttons are held, and 0 => represents no button is pressed. [NL]\r\n\t\tif (event.buttons === 0) {\r\n\t\t\tthis.#handleMoveEnd();\r\n\t\t}\r\n\t};\r\n\r\n\t// eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n\t#handleMouseUp = (event?: MouseEvent) => {\r\n\t\tthis.#handleMoveEnd();\r\n\t};\r\n\r\n\t#handleMoveEnd() {\r\n\t\tif (!UmbSorterController.activeElement || !UmbSorterController.activeItem) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst element = UmbSorterController.activeElement;\r\n\r\n\t\tif (UmbSorterController.activeDragElement) {\r\n\t\t\tUmbSorterController.activeDragElement.style.transform = '';\r\n\t\t\tUmbSorterController.activeDragElement.draggable = false;\r\n\t\t\tUmbSorterController.activeDragElement.removeEventListener('dragend', this.#handleDragEnd);\r\n\t\t}\r\n\r\n\t\twindow.removeEventListener('mouseup', this.#handleMouseUp);\r\n\t\twindow.removeEventListener('mouseout', this.#handleMouseUp);\r\n\t\twindow.removeEventListener('mouseleave', this.#handleMouseUp);\r\n\t\twindow.removeEventListener('mousemove', this.#handleMouseMove);\r\n\r\n\t\tthis.#removePlaceholderStyle();\r\n\t\tthis.#stopAutoScroll();\r\n\t\tthis.removeAllowIndication();\r\n\r\n\t\tif (this.#config.onEnd) {\r\n\t\t\tthis.#config.onEnd({\r\n\t\t\t\titem: UmbSorterController.activeItem,\r\n\t\t\t\telement: element as ElementType,\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\tif (UmbSorterController.rqaId) {\r\n\t\t\tcancelAnimationFrame(UmbSorterController.rqaId);\r\n\t\t\tUmbSorterController.rqaId = undefined;\r\n\t\t}\r\n\r\n\t\tUmbSorterController.activeItem = undefined;\r\n\t\tUmbSorterController.activeElement = undefined;\r\n\t\tUmbSorterController.activeDragElement = undefined;\r\n\t\tUmbSorterController.activeSorter = undefined;\r\n\t\tUmbSorterController.dropSorter = undefined;\r\n\t\tUmbSorterController.originalIndex = undefined;\r\n\t\tUmbSorterController.originalSorter = undefined;\r\n\t\tthis.#dragX = 0;\r\n\t\tthis.#dragY = 0;\r\n\t}\r\n\r\n\t#handleDragMove(event: DragEvent) {\r\n\t\tif (!UmbSorterController.activeElement) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst clientX = (event as unknown as TouchEvent).touches\r\n\t\t\t? (event as unknown as TouchEvent).touches[0].clientX\r\n\t\t\t: event.clientX;\r\n\t\tconst clientY = (event as unknown as TouchEvent).touches\r\n\t\t\t? (event as unknown as TouchEvent).touches[0].clientY\r\n\t\t\t: event.clientY;\r\n\t\tif (clientX !== 0 && clientY !== 0) {\r\n\t\t\tif (this.#dragX === clientX && this.#dragY === clientY) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\tthis.#dragX = clientX;\r\n\t\t\tthis.#dragY = clientY;\r\n\r\n\t\t\tthis.handleAutoScroll(this.#dragX, this.#dragY);\r\n\r\n\t\t\tconst activeDragRect = UmbSorterController.activeDragElement!.getBoundingClientRect();\r\n\t\t\tconst insideCurrentRect = isWithinRect(this.#dragX, this.#dragY, activeDragRect);\r\n\t\t\tif (!insideCurrentRect) {\r\n\t\t\t\tif (UmbSorterController.rqaId === undefined) {\r\n\t\t\t\t\tUmbSorterController.rqaId = requestAnimationFrame(this.#updateDragMove);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t#updateDragMove = () => {\r\n\t\tUmbSorterController.rqaId = undefined;\r\n\t\tif (!UmbSorterController.activeElement || !UmbSorterController.activeItem) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif ((UmbSorterController.dropSorter as any) !== this) {\r\n\t\t\tthrow new Error('Drop sorter is not this sorter');\r\n\t\t}\r\n\r\n\t\t// Maybe no need to check this twice, like we do it before the RAF an inside it, I think its fine to choose one of them.\r\n\t\tconst currentElementRect = UmbSorterController.activeElement.getBoundingClientRect();\r\n\t\tconst insideCurrentRect = isWithinRect(this.#dragX, this.#dragY, currentElementRect);\r\n\t\tif (insideCurrentRect) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst containerElement = this.#useContainerShadowRoot\r\n\t\t\t? (this.#containerElement.shadowRoot ?? this.#containerElement)\r\n\t\t\t: this.#containerElement;\r\n\r\n\t\t// We want to retrieve the children of the container, every time to ensure we got the right order and index\r\n\t\tconst orderedContainerElements = Array.from(containerElement.querySelectorAll(this.#config.itemSelector));\r\n\r\n\t\tconst currentContainerRect = this.#containerElement.getBoundingClientRect();\r\n\r\n\t\t// gather elements on the same row.\r\n\t\tconst elementsInSameRow = [];\r\n\t\tlet placeholderIsInThisRow = false;\r\n\t\tfor (const el of orderedContainerElements) {\r\n\t\t\tconst elRect = el.getBoundingClientRect();\r\n\t\t\t// gather elements on the same row.\r\n\t\t\tif (this.#dragY >= elRect.top && this.#dragY <= elRect.bottom) {\r\n\t\t\t\tconst dragElement = this.#getDraggableElement(el as unknown as HTMLElement);\r\n\t\t\t\tif (dragElement) {\r\n\t\t\t\t\tconst dragElementRect = dragElement.getBoundingClientRect();\r\n\t\t\t\t\tif (el !== UmbSorterController.activeElement) {\r\n\t\t\t\t\t\telementsInSameRow.push({ el: el, dragRect: dragElementRect });\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tplaceholderIsInThisRow = true;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tlet lastDistance = Infinity;\r\n\t\tlet foundEl: HTMLElement | undefined = undefined;\r\n\t\tlet foundElDragRect!: DOMRect;\r\n\t\tlet placeAfter = false;\r\n\t\telementsInSameRow.forEach((sameRow) => {\r\n\t\t\tconst centerX = sameRow.dragRect.left + sameRow.dragRect.width * 0.5;\r\n\t\t\tconst distance = Math.abs(this.#dragX - centerX);\r\n\t\t\t/*const distance = Math.min(\r\n\t\t\t\tMath.abs(this.#dragX - sameRow.dragRect.left),\r\n\t\t\t\tMath.abs(this.#dragX - sameRow.dragRect.right),\r\n\t\t\t);*/\r\n\t\t\tif (distance < lastDistance) {\r\n\t\t\t\tfoundEl = sameRow.el as HTMLElement;\r\n\t\t\t\tfoundElDragRect = sameRow.dragRect;\r\n\t\t\t\tlastDistance = distance;\r\n\t\t\t\tplaceAfter = this.#dragX > centerX;\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\tlet activeIndex: number | null = this.#model.indexOf(UmbSorterController.activeItem);\r\n\t\tif (activeIndex === -1) {\r\n\t\t\tactiveIndex = null;\r\n\t\t}\r\n\r\n\t\tif (foundEl) {\r\n\t\t\t// If we are on top or closest to our self, we should not do anything.\r\n\t\t\tif (foundEl === UmbSorterController.activeElement) {\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tconst foundModel = this.getItemOfElement(foundEl);\r\n\t\t\tif (!foundModel) {\r\n\t\t\t\tthrow new Error('Could not find model of found element');\r\n\t\t\t}\r\n\r\n\t\t\tlet relatedIndex: number | null = this.#model.indexOf(foundModel);\r\n\t\t\tif (relatedIndex === -1) {\r\n\t\t\t\trelatedIndex = null;\r\n\t\t\t}\r\n\r\n\t\t\tif (activeIndex !== null && relatedIndex !== null) {\r\n\t\t\t\t// We have both indexes, aka. both elements are in this list.\r\n\t\t\t\tconst widthDiff = Math.max(foundElDragRect.width - currentElementRect.width, 0);\r\n\t\t\t\tif (activeIndex < relatedIndex && foundElDragRect.left + widthDiff < this.#dragX) {\r\n\t\t\t\t\t// If we are located before and we are just enough over to get located after, then lets do it already.\r\n\t\t\t\t\tplaceAfter = true;\r\n\t\t\t\t} else if (activeIndex > relatedIndex && foundElDragRect.right - widthDiff > this.#dragX) {\r\n\t\t\t\t\t// If we are located after and we are just enough over to get located before, then lets do it already.\r\n\t\t\t\t\tplaceAfter = false;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tconst placementResult: UmbSorterResolvePlacementReturn = this.#config.resolvePlacement\r\n\t\t\t\t? this.#config.resolvePlacement({\r\n\t\t\t\t\t\tcontainerElement: this.#containerElement,\r\n\t\t\t\t\t\tcontainerRect: currentContainerRect,\r\n\t\t\t\t\t\titem: UmbSorterController.activeItem,\r\n\t\t\t\t\t\titemIndex: activeIndex,\r\n\t\t\t\t\t\telement: UmbSorterController.activeElement as ElementType,\r\n\t\t\t\t\t\telementRect: currentElementRect,\r\n\t\t\t\t\t\trelatedElement: foundEl,\r\n\t\t\t\t\t\trelatedModel: foundModel,\r\n\t\t\t\t\t\trelatedRect: foundElDragRect,\r\n\t\t\t\t\t\trelatedIndex: relatedIndex,\r\n\t\t\t\t\t\tplaceholderIsInThisRow: placeholderIsInThisRow,\r\n\t\t\t\t\t\thorizontalPlaceAfter: placeAfter,\r\n\t\t\t\t\t\tpointerX: this.#dragX,\r\n\t\t\t\t\t\tpointerY: this.#dragY,\r\n\t\t\t\t\t})\r\n\t\t\t\t: true;\r\n\r\n\t\t\tif (placementResult === null) {\r\n\t\t\t\t// The resolvePlacement method has chosen to back out of this move.\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\r\n\t\t\tlet verticalDirection = true;\r\n\t\t\tif (typeof placementResult === 'object') {\r\n\t\t\t\tverticalDirection = placementResult.verticalDirection ?? false;\r\n\t\t\t\tplaceAfter = placementResult.placeAfter;\r\n\t\t\t} else {\r\n\t\t\t\tverticalDirection = placementResult ?? false;\r\n\t\t\t\tif (verticalDirection === true) {\r\n\t\t\t\t\t// Lets check if we should place after or before, based on a vertical algortihm.\r\n\t\t\t\t\tplaceAfter = this.#dragY > foundElDragRect.top + foundElDragRect.height * 0.5;\r\n\r\n\t\t\t\t\t// There is room for improvements, if we are in the same model:\r\n\t\t\t\t\tif (activeIndex !== null && relatedIndex !== null) {\r\n\t\t\t\t\t\t// We have both indexes, aka. both elements are in this list.\r\n\t\t\t\t\t\tconst heightDiff = Math.max(foundElDragRect.height - currentElementRect.height, 0);\r\n\t\t\t\t\t\tif (activeIndex < relatedIndex && this.#dragY > foundElDragRect.top + heightDiff) {\r\n\t\t\t\t\t\t\t// If active is located above and we are just enough above to get located after, then lets do it already.\r\n\t\t\t\t\t\t\tplaceAfter = true;\r\n\t\t\t\t\t\t} else if (activeIndex > relatedIndex && this.#dragY < foundElDragRect.bottom - heightDiff) {\r\n\t\t\t\t\t\t\t// If active is located below and we are just enough above to get located before, then lets do it already.\r\n\t\t\t\t\t\t\tplaceAfter = false;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (verticalDirection === true) {\r\n\t\t\t\tlet el;\r\n\t\t\t\tif (placeAfter === false) {\r\n\t\t\t\t\tlet lastLeft = foundElDragRect.left;\r\n\t\t\t\t\telementsInSameRow.map((x) => {\r\n\t\t\t\t\t\tif (x.dragRect.left < lastLeft) {\r\n\t\t\t\t\t\t\tlastLeft = x.dragRect.left;\r\n\t\t\t\t\t\t\tel = x.el;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t});\r\n\t\t\t\t} else {\r\n\t\t\t\t\tlet lastRight = foundElDragRect.right;\r\n\t\t\t\t\telementsInSameRow.map((x) => {\r\n\t\t\t\t\t\tif (x.dragRect.right > lastRight) {\r\n\t\t\t\t\t\t\tlastRight = x.dragRect.right;\r\n\t\t\t\t\t\t\tel = x.el;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t});\r\n\t\t\t\t}\r\n\t\t\t\tif (el) {\r\n\t\t\t\t\tfoundEl = el;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tconst foundElIndex = orderedContainerElements.indexOf(foundEl);\r\n\t\t\tconst newIndex = placeAfter ? foundElIndex + 1 : foundElIndex;\r\n\t\t\tthis.#moveElementTo(newIndex);\r\n\r\n\t\t\treturn;\r\n\t\t}\r\n\t\t// We skipped the above part cause we are above or below container, or within an empty container, or in a blank space:\r\n\r\n\t\t// Indication if drop is good:\r\n\t\tif (this.updateAllowIndication(UmbSorterController.activeItem) === false) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (this.#model.length === 0) {\r\n\t\t\t// Here is no items, so we should just move into the top of the container.\r\n\t\t\tthis.#moveElementTo(0);\r\n\t\t} else if (this.#dragY < currentContainerRect.top) {\r\n\t\t\tthis.#moveElementTo(0);\r\n\t\t} else if (this.#dragY > currentContainerRect.bottom) {\r\n\t\t\tthis.#moveElementTo(-1);\r\n\t\t} else {\r\n\t\t\t// There was no target, but we are still inside. aka. in a vertical gap/gutter/blankspace.\r\n\t\t\tif (this.#model.length > 1 && activeIndex !== null) {\r\n\t\t\t\tconst belowActive = this.#dragY > currentElementRect.bottom;\r\n\r\n\t\t\t\tconst foundTarget =\r\n\t\t\t\t\tbelowActive === false\r\n\t\t\t\t\t\t? this.#findIndexToMoveTo(0, activeIndex)\r\n\t\t\t\t\t\t: this.#findIndexToMoveTo(activeIndex, this.#model.length);\r\n\r\n\t\t\t\tif (foundTarget) {\r\n\t\t\t\t\tthis.#moveElementTo(foundTarget);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t};\r\n\r\n\t#findIndexToMoveTo(a: number, b: number): number | undefined {\r\n\t\tif (a === b) {\r\n\t\t\treturn a;\r\n\t\t}\r\n\t\tconst halfWay = a + Math.round((b - a) * 0.5);\r\n\r\n\t\t// if we hit one of the points, then lets just move to the other point.\r\n\t\tif (halfWay === a || halfWay === b) {\r\n\t\t\treturn b;\r\n\t\t}\r\n\r\n\t\tconst belowHalf = this.#isPointerBelowTargetElement(halfWay);\r\n\t\tif (belowHalf === null) {\r\n\t\t\tthrow new Error('Could not determine if below target');\r\n\t\t}\r\n\r\n\t\tif (belowHalf) {\r\n\t\t\treturn this.#findIndexToMoveTo(halfWay, b);\r\n\t\t} else {\r\n\t\t\treturn this.#findIndexToMoveTo(a, halfWay);\r\n\t\t}\r\n\t}\r\n\r\n\t#isPointerBelowTargetElement(targetIndex: number) {\r\n\t\tif (targetIndex > 0 && targetIndex < this.#model.length) {\r\n\t\t\tconst element = this.getElementOfItem(this.#model[targetIndex]);\r\n\t\t\tif (element) {\r\n\t\t\t\t// Below this one == true, otherwise false.\r\n\t\t\t\treturn this.#dragY > element?.getBoundingClientRect().bottom;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn null;\r\n\t}\r\n\r\n\t//\r\n\tasync #moveElementTo(newIndex: number) {\r\n\t\tif (!UmbSorterController.activeElement || !UmbSorterController.activeSorter) {\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tconst requestingSorter = UmbSorterController.dropSorter;\r\n\t\tif (!requestingSorter) {\r\n\t\t\tthrow new Error('Could not find requestingSorter');\r\n\t\t}\r\n\t\tif ((requestingSorter as any) !== this) {\r\n\t\t\tthrow new Error('Requesting sorter is not this sorter');\r\n\t\t}\r\n\r\n\t\t// If same container and same index, do nothing:\r\n\t\tif (requestingSorter === UmbSorterController.activeSorter && UmbSorterController.activeIndex === newIndex) return;\r\n\r\n\t\tawait requestingSorter.moveItemInModel(newIndex, UmbSorterController.activeSorter);\r\n\t}\r\n\r\n\t/** Management methods: */\r\n\r\n\tpublic getItemOfElement(element: ElementType) {\r\n\t\tif (!element) {\r\n\t\t\tthrow new Error('Element was not defined');\r\n\t\t}\r\n\t\tconst elementUnique = this.#config.getUniqueOfElement(element);\r\n\t\tif (elementUnique === undefined) {\r\n\t\t\tconsole.error('Could not find unique of element', element);\r\n\t\t\treturn undefined;\r\n\t\t}\r\n\t\treturn this.#model.find((entry: T) => elementUnique === this.#config.getUniqueOfModel(entry));\r\n\t}\r\n\r\n\tpublic getElementOfItem(item: T) {\r\n\t\tconst unique = this.#config.getUniqueOfModel(item);\r\n\t\tif (unique === undefined) {\r\n\t\t\tconsole.error('Sorter could not find unique of item', item);\r\n\t\t\t//throw new Error('Sorter could not find unique of item');\r\n\t\t\treturn;\r\n\t\t}\r\n\t\treturn this.#elements.find((element) => unique === this.#config.getUniqueOfElement(element));\r\n\t}\r\n\r\n\tpublic async removeItem(item: T) {\r\n\t\tif (!item) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tif (this.#config.performItemRemove) {\r\n\t\t\treturn (await this.#config.performItemRemove({ item })) ?? false;\r\n\t\t} else {\r\n\t\t\tconst oldIndex = this.#model.indexOf(item);\r\n\t\t\tif (oldIndex !== -1) {\r\n\t\t\t\tconst newModel = [...this.#model];\r\n\t\t\t\tnewModel.splice(oldIndex, 1);\r\n\t\t\t\tthis.#model = newModel;\r\n\t\t\t\tthis.#config.onChange?.({ model: newModel, item });\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\r\n\tpublic hasOtherItemsThan(item: T) {\r\n\t\treturn this.#model.filter((x) => x !== item).length > 0;\r\n\t}\r\n\r\n\tpublic async moveItemInModel(newIndex: number, fromCtrl: UmbSorterController) {\r\n\t\tif (!UmbSorterController.activeItem) {\r\n\t\t\tconsole.error('There is no active item to move');\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tconst itemUnique = this.#config.getUniqueOfModel(UmbSorterController.activeItem);\r\n\t\tif (!itemUnique) {\r\n\t\t\tconsole.error('Failed to retrieve active item unique');\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\t// We use the getItem method to find the current item/object of this entry, as we cannot trust the object instance(activeItem) to be the same as in the model. [NL]\r\n\t\t// So notice, item in this method is the real modal entry reference, where in many other cases we use the activeItem which might not be up to date with the real entry of the model. [NL]\r\n\t\tconst item = fromCtrl.getItem(itemUnique);\r\n\t\tif (!item) {\r\n\t\t\tconsole.error('Could not find item of model to move', itemUnique, this.#model);\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tif (this.notifyRequestDrop({ item }) === false) {\r\n\t\t\treturn false;\r\n\t\t}\r\n\r\n\t\tconst localMove = fromCtrl === (this as any);\r\n\r\n\t\tif (!localMove) {\r\n\t\t\t// Not a local move, so we have to switch container to continue:\r\n\r\n\t\t\tif ((await fromCtrl.removeItem(item)) !== true) {\r\n\t\t\t\tconsole.error('Sync could not remove item when moving to a new container');\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.#config.performItemInsert) {\r\n\t\t\t\tconst result = await this.#config.performItemInsert({ item, newIndex });\r\n\t\t\t\tif (result === false) {\r\n\t\t\t\t\tconsole.error('Sync could not insert after a move a new container');\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tconst newModel = [...this.#model];\r\n\t\t\t\tnewModel.splice(newIndex, 0, item);\r\n\t\t\t\tthis.#model = newModel;\r\n\r\n\t\t\t\tthis.#config.onContainerChange?.({\r\n\t\t\t\t\tmodel: newModel,\r\n\t\t\t\t\titem,\r\n\t\t\t\t\tfrom: fromCtrl as unknown as UmbSorterController,\r\n\t\t\t\t});\r\n\t\t\t\tthis.#config.onChange?.({ model: newModel, item });\r\n\r\n\t\t\t\t// If everything went well, we can set the new activeSorter (and dropSorter) to this, as we are switching container. [NL]\r\n\t\t\t\tUmbSorterController.activeSorter = this as unknown as UmbSorterController;\r\n\t\t\t\tUmbSorterController.dropSorter = this as unknown as UmbSorterController;\r\n\t\t\t\tUmbSorterController.activeIndex = newIndex;\r\n\t\t\t}\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tif (localMove) {\r\n\t\t\t// Local move:\r\n\r\n\t\t\tconst oldIndex = this.#model.indexOf(item);\r\n\t\t\tif (oldIndex === -1) {\r\n\t\t\t\tconsole.error('Could not find item in model when performing internal move', this.getHostElement(), this.#model);\r\n\t\t\t\treturn false;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.#config.performItemMove) {\r\n\t\t\t\tconst result = await this.#config.performItemMove({ item, newIndex, oldIndex });\r\n\t\t\t\tif (result === false) {\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tconst newModel = [...this.#model];\r\n\t\t\t\tnewModel.splice(oldIndex, 1);\r\n\t\t\t\tif (oldIndex <= newIndex) {\r\n\t\t\t\t\tnewIndex--;\r\n\t\t\t\t}\r\n\t\t\t\tnewModel.splice(newIndex, 0, item);\r\n\t\t\t\tthis.#model = newModel;\r\n\t\t\t\tthis.#config.onChange?.({ model: newModel, item });\r\n\t\t\t}\r\n\r\n\t\t\tUmbSorterController.activeIndex = newIndex;\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t}\r\n\r\n\tupdateAllowIndication(item: T) {\r\n\t\t// Remove old indication:\r\n\t\tif (UmbSorterController.lastIndicationSorter && UmbSorterController.lastIndicationSorter !== (this as unknown)) {\r\n\t\t\tUmbSorterController.lastIndicationSorter.notifyAllowed();\r\n\t\t}\r\n\t\tUmbSorterController.lastIndicationSorter = this as unknown as UmbSorterController;\r\n\r\n\t\tif (this.notifyRequestDrop({ item: item }) === true) {\r\n\t\t\tthis.notifyAllowed();\r\n\t\t\treturn true;\r\n\t\t}\r\n\r\n\t\tthis.notifyDisallowed(); // This block is not accepted to we will indicate that its not allowed.\r\n\t\treturn false;\r\n\t}\r\n\tremoveAllowIndication() {\r\n\t\t// Remove old indication:\r\n\t\tif (UmbSorterController.lastIndicationSorter) {\r\n\t\t\tUmbSorterController.lastIndicationSorter.notifyAllowed();\r\n\t\t}\r\n\t\tUmbSorterController.lastIndicationSorter = undefined;\r\n\t}\r\n\r\n\t// TODO: Move auto scroll into its own class?\r\n\t#autoScrollRAF: number | null = null;\r\n\t#autoScrollEl = document.scrollingElement || document.documentElement;\r\n\tprivate autoScrollX = 0;\r\n\tprivate autoScrollY = 0;\r\n\r\n\tprivate handleAutoScroll(clientX: number, clientY: number) {\r\n\t\tlet scrollRect: DOMRect | null = null;\r\n\t\tif (this.#scrollElement) {\r\n\t\t\tthis.#autoScrollEl = this.#scrollElement;\r\n\t\t\tscrollRect = this.#autoScrollEl.getBoundingClientRect();\r\n\t\t} else {\r\n\t\t\tthis.#autoScrollEl = document.scrollingElement || document.documentElement;\r\n\t\t\tscrollRect = {\r\n\t\t\t\ttop: 0,\r\n\t\t\t\tleft: 0,\r\n\t\t\t\tbottom: window.innerHeight,\r\n\t\t\t\tright: window.innerWidth,\r\n\t\t\t\theight: window.innerHeight,\r\n\t\t\t\twidth: window.innerWidth,\r\n\t\t\t} as DOMRect;\r\n\t\t}\r\n\r\n\t\tconst scrollWidth = this.#autoScrollEl.scrollWidth;\r\n\t\tconst scrollHeight = this.#autoScrollEl.scrollHeight;\r\n\t\tconst canScrollX = scrollRect.width < scrollWidth;\r\n\t\tconst canScrollY = scrollRect.height < scrollHeight;\r\n\t\tconst scrollPosX = this.#autoScrollEl.scrollLeft;\r\n\t\tconst scrollPosY = this.#autoScrollEl.scrollTop;\r\n\r\n\t\tcancelAnimationFrame(this.#autoScrollRAF!);\r\n\r\n\t\tif (canScrollX || canScrollY) {\r\n\t\t\tthis.autoScrollX =\r\n\t\t\t\tMath.abs(scrollRect.right - clientX) <= autoScrollSensitivity && scrollPosX + scrollRect.width < scrollWidth\r\n\t\t\t\t\t? 1\r\n\t\t\t\t\t: Math.abs(scrollRect.left - clientX) <= autoScrollSensitivity && !!scrollPosX\r\n\t\t\t\t\t\t? -1\r\n\t\t\t\t\t\t: 0;\r\n\r\n\t\t\tthis.autoScrollY =\r\n\t\t\t\tMath.abs(scrollRect.bottom - clientY) <= autoScrollSensitivity && scrollPosY + scrollRect.height < scrollHeight\r\n\t\t\t\t\t? 1\r\n\t\t\t\t\t: Math.abs(scrollRect.top - clientY) <= autoScrollSensitivity && !!scrollPosY\r\n\t\t\t\t\t\t? -1\r\n\t\t\t\t\t\t: 0;\r\n\r\n\t\t\tthis.#autoScrollRAF = requestAnimationFrame(this.#performAutoScroll);\r\n\t\t}\r\n\t}\r\n\t#performAutoScroll = () => {\r\n\t\tthis.#autoScrollEl!.scrollLeft += this.autoScrollX * autoScrollSpeed;\r\n\t\tthis.#autoScrollEl!.scrollTop += this.autoScrollY * autoScrollSpeed;\r\n\t\tthis.#autoScrollRAF = requestAnimationFrame(this.#performAutoScroll);\r\n\t};\r\n\t#stopAutoScroll() {\r\n\t\tcancelAnimationFrame(this.#autoScrollRAF!);\r\n\t\tthis.#autoScrollRAF = null;\r\n\t}\r\n\r\n\tpublic notifyDisallowed() {\r\n\t\tif (this.#config.onDisallowed) {\r\n\t\t\tthis.#config.onDisallowed({\r\n\t\t\t\titem: UmbSorterController.activeItem,\r\n\t\t\t\telement: UmbSorterController.activeElement! as ElementType,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\tpublic notifyAllowed() {\r\n\t\tif (this.#config.onAllowed) {\r\n\t\t\tthis.#config.onAllowed({\r\n\t\t\t\titem: UmbSorterController.activeItem,\r\n\t\t\t\telement: UmbSorterController.activeElement! as ElementType,\r\n\t\t\t});\r\n\t\t}\r\n\t}\r\n\tpublic notifyRequestDrop(data: any) {\r\n\t\tif (this.#config.onRequestMove) {\r\n\t\t\treturn this.#config.onRequestMove(data) || false;\r\n\t\t}\r\n\t\treturn true;\r\n\t}\r\n\r\n\toverride destroy() {\r\n\t\tsuper.destroy();\r\n\r\n\t\t// Do something when host element is destroyed.\r\n\t\tif (UmbSorterController.activeElement) {\r\n\t\t\tthis.#handleDragEnd();\r\n\t\t}\r\n\r\n\t\tUmbSorterController.lastIndicationSorter = undefined;\r\n\r\n\t\t// TODO: Clean up items??\r\n\t\tthis.#observer.disconnect();\r\n\r\n\t\t// For auto scroller:\r\n\t\tthis.#scrollElement = null;\r\n\t}\r\n}\r\n","import type { UmbSorterResolvePlacementArgs } from './sorter.controller.js';\r\n\r\n/**\r\n * This function is used to resolve the placement of an item in a simple grid layout.\r\n * @param args\r\n * @returns { null | true }\r\n */\r\nexport function UmbSorterResolvePlacementAsGrid(args: UmbSorterResolvePlacementArgs) {\r\n\t// If we are part of the same Sorter model\r\n\tif (args.itemIndex !== null && args.relatedIndex !== null) {\r\n\t\t// and the pointer is within the related rect\r\n\t\tif (args.relatedRect.left < args.pointerX && args.relatedRect.right > args.pointerX) {\r\n\t\t\t// Then we control the placeAfter property, making the active-drag-element allow to be placed at a spot already when just hovering that spot. (This only works when items have the same size)\r\n\t\t\treturn {\r\n\t\t\t\tplaceAfter: args.itemIndex < args.relatedIndex,\r\n\t\t\t};\r\n\t\t}\r\n\t}\r\n\treturn false;\r\n}\r\n"],"names":["autoScrollSensitivity","autoScrollSpeed","getParentScrollElement","el","includeSelf","elem","elemCSS","setupIgnorerElements","element","ignorerSelectors","selectors","criteria","setupPreventEvent","destroyIgnorerElements","destroyPreventEvent","UmbSorterController","UmbControllerBase","host","config","#isConnected","#model","#enabled","#dragX","#dragY","#elements","#initialize","containerEl","#config","#host","#containerElement","#useContainerShadowRoot","containerElement","#itemDraggedOver","#observer","child","e","dropSorter","#handleDragMove","#handleHandleMouseDown","event","target","composedPath","index","composedPathBelowTarget","x","#getElement","dragElement","#getDraggableElement","#handleDragElementMouseUp","#handleDragStart","#handleDragEnd","activeDragRect","#scrollElement","#setCurrentElement","#handleMouseUp","#handleMouseMove","#handleMoveEnd","#updateDragMove","currentElementRect","isWithinRect","orderedContainerElements","currentContainerRect","elementsInSameRow","placeholderIsInThisRow","elRect","dragElementRect","lastDistance","foundEl","foundElDragRect","placeAfter","sameRow","centerX","distance","activeIndex","foundModel","relatedIndex","widthDiff","placementResult","verticalDirection","heightDiff","lastLeft","lastRight","foundElIndex","newIndex","#moveElementTo","foundTarget","#findIndexToMoveTo","#autoScrollRAF","#autoScrollEl","#performAutoScroll","mutations","mutation","addedNode","removedNode","identifier","#isActiveIdentifier","#uninitialize","model","unique","item","#getHandleElement","innerElement","source","containingElement","newSource","draggableElement","elUnique","modelUnique","#setupPlaceholderStyle","#removePlaceholderStyle","#stopAutoScroll","clientX","clientY","a","b","halfWay","belowHalf","#isPointerBelowTargetElement","targetIndex","requestingSorter","elementUnique","entry","oldIndex","newModel","fromCtrl","itemUnique","localMove","scrollRect","scrollWidth","scrollHeight","canScrollX","canScrollY","scrollPosX","scrollPosY","data","UmbSorterResolvePlacementAsGrid","args"],"mappings":"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"}