{"version":3,"file":"selection.min.mjs","sources":["../src/utils/css.ts","../src/utils/events.ts","../src/utils/intersects.ts","../src/utils/removeElement.ts","../src/utils/selectAll.ts","../src/utils/constants.ts","../src/index.ts","../src/EventEmitter.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\r\nimport {Properties} from 'csstype';\r\n\r\nconst unitify = (val: string | number, unit = 'px'): string => {\r\n    return typeof val === 'number' ? val + unit : val;\r\n};\r\n\r\n/**\r\n * Add css to a DOM-Element or returns the current\r\n * value of a property.\r\n *\r\n * @param el The Element.\r\n * @param attr The attribute or a object which holds css key-properties.\r\n * @param val The value for a single attribute.\r\n * @returns {*}\r\n */\r\nexport function css(\r\n    {style}: HTMLElement,\r\n    attr: Partial<Record<keyof Properties, string | number>> | keyof Properties,\r\n    val?: string | number\r\n): void {\r\n    if (typeof attr === 'object') {\r\n\r\n        for (const [key, value] of Object.entries(attr)) {\r\n            style[key as any] = unitify(value as string | number);\r\n        }\r\n\r\n    } else if (val !== undefined) {\r\n        style[attr as any] = unitify(val);\r\n    }\r\n}\r\n\r\n\r\n","/* eslint-disable @typescript-eslint/explicit-module-boundary-types */\r\n/* eslint-disable @typescript-eslint/no-explicit-any */\r\ntype Method = 'addEventListener' | 'removeEventListener';\r\ntype AnyFunction = (...arg: any) => any;\r\n\r\nexport type EventBindingArgs = [\r\n        EventTarget | Array<EventTarget>,\r\n        string | Array<string>,\r\n    AnyFunction,\r\n    Record<string, unknown>?\r\n];\r\n\r\ninterface EventBinding {\r\n    (\r\n        elements: EventTarget | Array<EventTarget>,\r\n        events: string | Array<string>,\r\n        fn: AnyFunction,\r\n        options?: Record<string, unknown>\r\n    ): EventBindingArgs;\r\n}\r\n\r\n/* eslint-disable prefer-rest-params */\r\nfunction eventListener(method: Method): EventBinding {\r\n    return (\r\n        items: EventTarget | Array<EventTarget>,\r\n        events: string | Array<string>,\r\n        fn: AnyFunction, options = {}\r\n    ): EventBindingArgs => {\r\n\r\n        // Normalize array\r\n        if (items instanceof HTMLCollection || items instanceof NodeList) {\r\n            items = Array.from(items);\r\n        } else if (!Array.isArray(items)) {\r\n            items = [items];\r\n        }\r\n\r\n        if (!Array.isArray(events)) {\r\n            events = [events];\r\n        }\r\n\r\n        for (const el of items) {\r\n            for (const ev of events) {\r\n                el[method](ev, fn as EventListener, {capture: false, ...options});\r\n            }\r\n        }\r\n\r\n        return [items, events, fn, options];\r\n    };\r\n}\r\n\r\n/**\r\n * Add event(s) to element(s).\r\n * @param elements DOM-Elements\r\n * @param events Event names\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const on = eventListener('addEventListener');\r\n\r\n/**\r\n * Remove event(s) from element(s).\r\n * @param elements DOM-Elements\r\n * @param events Event names\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const off = eventListener('removeEventListener');\r\n\r\n/**\r\n * Simplifies a touch / mouse-event\r\n * @param evt\r\n */\r\nexport const simplifyEvent = (evt: any): {\r\n    tap: MouseEvent | Touch;\r\n    x: number;\r\n    y: number;\r\n    target: HTMLElement;\r\n} => {\r\n    const tap = (evt.touches && evt.touches[0] || evt);\r\n    return {\r\n        tap,\r\n        x: tap.clientX,\r\n        y: tap.clientY,\r\n        target: tap.target\r\n    };\r\n};\r\n\r\n/**\r\n * Polyfill for safari & firefox for the eventPath event property.\r\n * @param evt The event object.\r\n * @return [String] event path.\r\n */\r\nexport function eventPath(evt: any): Array<EventTarget> {\r\n    let path: Array<EventTarget> = evt.path || (evt.composedPath && evt.composedPath());\r\n    if (path) {\r\n        return path;\r\n    }\r\n\r\n    let el = evt.target.parentElement;\r\n    path = [evt.target, el];\r\n    while (el = el.parentElement) {\r\n        path.push(el);\r\n    }\r\n\r\n    path.push(document, window);\r\n    return path;\r\n}\r\n\r\n","export type Intersection = 'center' | 'cover' | 'touch'\r\n\r\n/**\r\n * Check if two DOM-Elements intersects each other.\r\n * @param a BoundingClientRect of the first element.\r\n * @param b BoundingClientRect of the second element.\r\n * @param mode Options are center, cover or touch.\r\n * @returns {boolean} If both elements intersects each other.\r\n */\r\nexport function intersects(a: DOMRect, b: DOMRect, mode: Intersection = 'touch'): boolean {\r\n    switch (mode) {\r\n        case 'center': {\r\n            const bxc = b.left + b.width / 2;\r\n            const byc = b.top + b.height / 2;\r\n\r\n            return bxc >= a.left &&\r\n                bxc <= a.right &&\r\n                byc >= a.top &&\r\n                byc <= a.bottom;\r\n        }\r\n        case 'cover': {\r\n            return b.left >= a.left &&\r\n                b.top >= a.top &&\r\n                b.right <= a.right &&\r\n                b.bottom <= a.bottom;\r\n        }\r\n        case 'touch': {\r\n            return a.right >= b.left &&\r\n                a.left <= b.right &&\r\n                a.bottom >= b.top &&\r\n                a.top <= b.bottom;\r\n        }\r\n        default: {\r\n            throw new Error(`Unkown intersection mode: ${mode}`);\r\n        }\r\n    }\r\n}\r\n","/**\r\n * Removes an element from an Array.\r\n */\r\nexport function removeElement<T>(arr: T[], el: T): void {\r\n    const index = arr.indexOf(el);\r\n\r\n    if (~index) {\r\n        arr.splice(index, 1);\r\n    }\r\n}\r\n","export type SelectAllSelectors = readonly (string | Element)[] | string | Element;\r\n\r\n/**\r\n * Takes a selector (or array of selectors) and returns the matched nodes.\r\n * @param selector The selector or an Array of selectors.\r\n * @param doc\r\n * @returns {Array} Array of DOM-Nodes.\r\n */\r\nexport function selectAll(selector: SelectAllSelectors, doc: Document = document): Array<Element> {\r\n    const list = !Array.isArray(selector) ? [selector] : selector;\r\n\r\n    const nodes = [];\r\n    for (let i = 0, l = list.length; i < l; i++) {\r\n        const item = list[i];\r\n\r\n        if (typeof item === 'string') {\r\n            nodes.push(...Array.from(doc.querySelectorAll(item)));\r\n        } else if (item instanceof HTMLElement) {\r\n            nodes.push(item);\r\n        }\r\n    }\r\n\r\n    return nodes;\r\n}\r\n","// Determines if the device's primary input supports touch\r\n// See this article: https://css-tricks.com/touch-devices-not-judged-size/\r\nexport const isTouchDevice = window.matchMedia('(hover: none), (pointer: coarse)').matches;\r\n","import {css, eventPath, intersects, isTouchDevice, off, on, removeElement, selectAll, SelectAllSelectors, simplifyEvent} from '@utils';\r\nimport {EventTarget} from './EventEmitter';\r\nimport {AreaLocation, Coordinates, ScrollEvent, SelectionEvents, SelectionOptions, SelectionStore} from './types';\r\n\r\n// Re-export types\r\nexport * from './types';\r\n\r\n// Some var shorting for better compression and readability\r\nconst {abs, max, min, ceil} = Math;\r\n\r\nexport default class SelectionArea extends EventTarget<SelectionEvents> {\r\n    public static version = VERSION;\r\n\r\n    // Options\r\n    private readonly _options: SelectionOptions;\r\n\r\n    // Selection store\r\n    private _selection: SelectionStore = {\r\n        touched: [],\r\n        stored: [],\r\n        selected: [],\r\n        changed: {\r\n            added: [], // Added elements since last selection\r\n            removed: [] // Removed elements since last selection\r\n        }\r\n    };\r\n\r\n    // Area element and clipping element\r\n    private readonly _area: HTMLElement;\r\n    private readonly _clippingElement: HTMLElement;\r\n\r\n    // Target container (element) and boundary (cached)\r\n    private _targetElement?: Element;\r\n    private _targetRect?: DOMRect;\r\n    private _selectables: Array<Element> = [];\r\n\r\n    // Caches the position of the selection-area\r\n    private readonly _areaRect = new DOMRect();\r\n\r\n    // Dynamically constructed area rect\r\n    private _areaLocation: AreaLocation = {y1: 0, x2: 0, y2: 0, x1: 0};\r\n\r\n    // If a single click is being performed.\r\n    // It's a single-click until the user dragged the mouse.\r\n    private _singleClick = true;\r\n\r\n    // Is getting set on movement. Varied.\r\n    private _scrollAvailable = true;\r\n    private _scrollSpeed: Coordinates = {x: 0, y: 0};\r\n    private _scrollDelta: Coordinates = {x: 0, y: 0};\r\n\r\n    constructor(opt: Partial<SelectionOptions>) {\r\n        super();\r\n\r\n        this._options = Object.assign({\r\n            class: 'selection-area',\r\n            document: window.document,\r\n            intersect: 'touch',\r\n            startThreshold: 10,\r\n            singleClick: true,\r\n            allowTouch: true,\r\n            overlap: 'invert',\r\n            selectables: [],\r\n\r\n            singleTap: {\r\n                allow: true,\r\n                intersect: 'native'\r\n            },\r\n\r\n            scrolling: {\r\n                speedDivider: 10,\r\n                manualSpeed: 750\r\n            },\r\n\r\n            startareas: ['html'],\r\n            boundaries: ['html'],\r\n            container: 'body'\r\n        }, opt);\r\n\r\n        // Bind locale functions to instance\r\n        /* eslint-disable @typescript-eslint/no-explicit-any */\r\n        for (const key of Object.getOwnPropertyNames(Object.getPrototypeOf(this))) {\r\n            if (typeof (this as any)[key] === 'function') {\r\n                (this as any)[key] = (this as any)[key].bind(this);\r\n            }\r\n        }\r\n\r\n        const {document} = this._options;\r\n        this._area = document.createElement('div');\r\n        this._clippingElement = document.createElement('div');\r\n        this._clippingElement.appendChild(this._area);\r\n\r\n        // Add class to the area element\r\n        this._area.classList.add(this._options.class);\r\n\r\n        // Apply basic styles to the area element\r\n        css(this._area, {\r\n            willChange: 'top, left, bottom, right, width, height',\r\n            top: 0,\r\n            left: 0,\r\n            position: 'fixed'\r\n        });\r\n\r\n        css(this._clippingElement, {\r\n            overflow: 'hidden',\r\n            position: 'fixed',\r\n            transform: 'translate3d(0, 0, 0)', // https://stackoverflow.com/a/38268846\r\n            pointerEvents: 'none',\r\n            zIndex: '1'\r\n        });\r\n\r\n        this.enable();\r\n    }\r\n\r\n    _bindStartEvents(activate = true): void {\r\n        const {document, allowTouch} = this._options;\r\n        const fn = activate ? on : off;\r\n\r\n        fn(document, 'mousedown', this._onTapStart);\r\n        allowTouch && fn(document, 'touchstart', this._onTapStart, {\r\n            passive: false\r\n        });\r\n    }\r\n\r\n    _onTapStart(evt: MouseEvent | TouchEvent, silent = false): void {\r\n        const {x, y, target} = simplifyEvent(evt);\r\n        const {_options} = this;\r\n        const {document} = this._options;\r\n        const targetBoundingClientRect = target.getBoundingClientRect();\r\n\r\n        // Find start-areas and boundaries\r\n        const startAreas = selectAll(_options.startareas, _options.document);\r\n        const resolvedBoundaries = selectAll(_options.boundaries, _options.document);\r\n\r\n        // Check in which container the user currently acts\r\n        this._targetElement = resolvedBoundaries.find(el =>\r\n            intersects(el.getBoundingClientRect(), targetBoundingClientRect)\r\n        );\r\n\r\n        // Check if area starts in one of the start areas / boundaries\r\n        const evtpath = eventPath(evt);\r\n        if (!this._targetElement ||\r\n            !startAreas.find(el => evtpath.includes(el)) ||\r\n            !resolvedBoundaries.find(el => evtpath.includes(el))) {\r\n            return;\r\n        }\r\n\r\n        if (!silent && this._emitEvent('beforestart', evt) === false) {\r\n            return;\r\n        }\r\n\r\n        // Area rect\r\n        this._areaLocation = {x1: x, y1: y, x2: 0, y2: 0};\r\n\r\n        // Lock scrolling in target container\r\n        // Solution to preventing scrolling taken fr\r\n        const scrollElement = document.scrollingElement || document.body;\r\n        this._scrollDelta = {x: scrollElement.scrollLeft, y: scrollElement.scrollTop};\r\n\r\n        // To detect single-click\r\n        this._singleClick = true;\r\n        this.clearSelection(false);\r\n\r\n        // Add listener\r\n        on(document, ['touchmove', 'mousemove'], this._delayedTapMove, {passive: false});\r\n        on(document, ['mouseup', 'touchcancel', 'touchend'], this._onTapStop);\r\n        on(document, 'scroll', this._onScroll);\r\n    }\r\n\r\n    _onSingleTap(evt: MouseEvent | TouchEvent): void {\r\n        const {intersect} = this._options.singleTap;\r\n        const spl = simplifyEvent(evt);\r\n        let target = null;\r\n\r\n        if (intersect === 'native') {\r\n            target = spl.target;\r\n        } else if (intersect === 'touch') {\r\n            this.resolveSelectables();\r\n\r\n            const {x, y} = spl;\r\n            target = this._selectables.find(v => {\r\n                const {right, left, top, bottom} = v.getBoundingClientRect();\r\n                return x < right && x > left && y < bottom && y > top;\r\n            });\r\n        }\r\n\r\n        if (!target) {\r\n            return;\r\n        }\r\n\r\n        /**\r\n         * Resolve selectables again.\r\n         * If the user starded in a scrollable area they will be reduced\r\n         * to the current area. Prevent the exclusion of these if a range-selection\r\n         * gets performed.\r\n         */\r\n        this.resolveSelectables();\r\n\r\n        // Traverse dom upwards to check if target is selectable\r\n        while (!this._selectables.includes(target)) {\r\n            if (!target.parentElement) {\r\n                return;\r\n            }\r\n\r\n            target = target.parentElement;\r\n        }\r\n\r\n        // Grab current store first in case it gets resetted\r\n        const {stored} = this._selection;\r\n\r\n        // Emit event and process element\r\n        this._emitEvent('start', evt);\r\n        if (evt.shiftKey && stored.length) {\r\n            const reference = stored[stored.length - 1];\r\n\r\n            // Resolve correct range\r\n            const [preceding, following] = reference.compareDocumentPosition(target) & 4 ?\r\n                [target, reference] : [reference, target];\r\n\r\n            const rangeItems = [...this._selectables.filter(el =>\r\n                (el.compareDocumentPosition(preceding) & 4) &&\r\n                (el.compareDocumentPosition(following) & 2)\r\n            ), target, preceding, following];\r\n\r\n            this.select(rangeItems);\r\n        } else if (stored.includes(target) && (stored.length === 1 || evt.ctrlKey)) {\r\n            this.deselect(target);\r\n        } else {\r\n            this.select(target);\r\n        }\r\n\r\n        this._emitEvent('stop', evt);\r\n    }\r\n\r\n    _delayedTapMove(evt: MouseEvent | TouchEvent): void {\r\n        const {startThreshold, container, document, allowTouch} = this._options;\r\n        const {x1, y1} = this._areaLocation; // Coordinates of first \"tap\"\r\n        const {x, y} = simplifyEvent(evt);\r\n\r\n        // Check pixel threshold\r\n        const thresholdType = typeof startThreshold;\r\n        if (\r\n\r\n            // Single number\r\n            (thresholdType === 'number' && abs((x + y) - (x1 + y1)) >= startThreshold) ||\r\n\r\n            // Different x and y threshold\r\n            (thresholdType === 'object' && abs(x - x1) >= (startThreshold as Coordinates).x || abs(y - y1) >= (startThreshold as Coordinates).y)\r\n        ) {\r\n            off(document, ['mousemove', 'touchmove'], this._delayedTapMove, {passive: false});\r\n            on(document, ['mousemove', 'touchmove'], this._onTapMove, {passive: false});\r\n\r\n            // Make area element visible\r\n            css(this._area, 'display', 'block');\r\n\r\n            // Apppend selection-area to the dom\r\n            selectAll(container, document)[0].appendChild(this._clippingElement);\r\n\r\n            // Now after the threshold is reached resolve all selectables\r\n            this.resolveSelectables();\r\n\r\n            // An action is recognized as single-select until the user performed a mutli-selection\r\n            this._singleClick = false;\r\n\r\n            // Just saving the boundaries of this container for later\r\n            this._targetRect = this._targetElement!.getBoundingClientRect();\r\n\r\n            // Find container and check if it's scrollable\r\n            this._scrollAvailable =\r\n                this._targetElement!.scrollHeight !== this._targetElement!.clientHeight ||\r\n                this._targetElement!.scrollWidth !== this._targetElement!.clientWidth;\r\n\r\n            if (this._scrollAvailable) {\r\n\r\n                // Detect mouse scrolling\r\n                on(document, 'wheel', this._manualScroll, {passive: false});\r\n\r\n                /**\r\n                 * The selection-area will also cover other element which are\r\n                 * out of the current scrollable parent. So find all elements\r\n                 * which are in the current scrollable element. Later these are\r\n                 * the only selectables instead of all.\r\n                 */\r\n                this._selectables = this._selectables.filter(s => this._targetElement!.contains(s));\r\n            }\r\n\r\n            // Trigger recalc and fire event\r\n            this._prepareSelectionArea();\r\n            this._emitEvent('start', evt);\r\n            this._onTapMove(evt);\r\n        }\r\n\r\n        if (allowTouch && isTouchDevice) {\r\n            evt.preventDefault(); // Prevent swipe-down refresh\r\n        }\r\n    }\r\n\r\n    _prepareSelectionArea(): void {\r\n        const {_clippingElement, _targetElement, _area} = this;\r\n        const tr = this._targetRect = _targetElement!.getBoundingClientRect();\r\n\r\n        if (this._scrollAvailable) {\r\n\r\n            /**\r\n             * To clip the area, the selection area has a parent\r\n             * which has exact the same dimensions as the scrollable elemeent.\r\n             * Now if the area exeeds these boundaries it will be cropped.\r\n             */\r\n            css(_clippingElement, {\r\n                top: tr.top,\r\n                left: tr.left,\r\n                width: tr.width,\r\n                height: tr.height\r\n            });\r\n\r\n            /**\r\n             * The area element is relative to the clipping element,\r\n             * but when this is moved or transformed we need to correct\r\n             * the positions via a negative margin.\r\n             */\r\n            css(_area, {\r\n                marginTop: -tr.top,\r\n                marginLeft: -tr.left\r\n            });\r\n        } else {\r\n\r\n            /**\r\n             * Reset margin and clipping element dimensions.\r\n             */\r\n            css(_clippingElement, {\r\n                top: 0,\r\n                left: 0,\r\n                width: '100%',\r\n                height: '100%'\r\n            });\r\n\r\n            css(_area, {\r\n                marginTop: 0,\r\n                marginLeft: 0\r\n            });\r\n        }\r\n    }\r\n\r\n    _onTapMove(evt: MouseEvent | TouchEvent): void {\r\n        const {x, y} = simplifyEvent(evt);\r\n        const {_scrollSpeed, _areaLocation, _options} = this;\r\n        const {allowTouch} = _options;\r\n        const {speedDivider} = _options.scrolling;\r\n        const scon = this._targetElement as Element;\r\n\r\n        _areaLocation.x2 = x;\r\n        _areaLocation.y2 = y;\r\n\r\n        if (this._scrollAvailable && (_scrollSpeed.y || _scrollSpeed.x)) {\r\n            const scroll = () => {\r\n                if (!_scrollSpeed.x && !_scrollSpeed.y) {\r\n                    return;\r\n                }\r\n\r\n                /**\r\n                 * If the value exeeds the scrollable area it will\r\n                 * be set to the max / min value. So change only\r\n                 */\r\n                const {scrollTop, scrollLeft} = scon;\r\n\r\n                // Reduce velocity, use ceil in both directions to scroll at least 1px per frame\r\n                if (_scrollSpeed.y) {\r\n                    scon.scrollTop += ceil(_scrollSpeed.y / speedDivider);\r\n                    _areaLocation.y1 -= scon.scrollTop - scrollTop;\r\n                }\r\n\r\n                if (_scrollSpeed.x) {\r\n                    scon.scrollLeft += ceil(_scrollSpeed.x / speedDivider);\r\n                    _areaLocation.x1 -= scon.scrollLeft - scrollLeft;\r\n                }\r\n\r\n                /**\r\n                 * We changed the start coordinates -> redraw the selectiona area\r\n                 * We changed the dimensions of the area element -> re-calc selected elements\r\n                 * The selected elements array has been changed -> fire event\r\n                 */\r\n                this._recalculateSelectionAreaRect();\r\n                this._updateElementSelection();\r\n                this._emitEvent('move', evt);\r\n                this._redrawSelectionArea();\r\n\r\n                // Keep scrolling even if the user stops to move his pointer\r\n                requestAnimationFrame(scroll);\r\n            };\r\n\r\n            // Continous scrolling\r\n            requestAnimationFrame(scroll);\r\n        } else {\r\n\r\n            /**\r\n             * Perform redraw only if scrolling is not active.\r\n             * If scrolling is active this area is getting re-dragwed by the\r\n             * anonymized scroll function.\r\n             */\r\n            this._recalculateSelectionAreaRect();\r\n            this._updateElementSelection();\r\n            this._emitEvent('move', evt);\r\n            this._redrawSelectionArea();\r\n        }\r\n\r\n        if (allowTouch && isTouchDevice) {\r\n            evt.preventDefault(); // Prevent swipe-down refresh\r\n        }\r\n    }\r\n\r\n    _onScroll(): void {\r\n        const {_scrollDelta, _options: {document}} = this;\r\n\r\n        // Resolve scrolling offsets\r\n        const {scrollTop, scrollLeft} = document.scrollingElement || document.body;\r\n\r\n        // Adjust area start location\r\n        this._areaLocation.x1 += _scrollDelta.x - scrollLeft;\r\n        this._areaLocation.y1 += _scrollDelta.y - scrollTop;\r\n        _scrollDelta.x = scrollLeft;\r\n        _scrollDelta.y = scrollTop;\r\n\r\n        // The area needs to be resetted as the target-container has changed in its position\r\n        this._prepareSelectionArea();\r\n        this._recalculateSelectionAreaRect();\r\n        this._updateElementSelection();\r\n        this._emitEvent('move', null);\r\n        this._redrawSelectionArea();\r\n    }\r\n\r\n    _manualScroll(evt: ScrollEvent): void {\r\n        const {manualSpeed} = this._options.scrolling;\r\n\r\n        // Consistent scrolling speed on all browsers\r\n        const deltaY = evt.deltaY ? (evt.deltaY > 0 ? 1 : -1) : 0;\r\n        const deltaX = evt.deltaX ? (evt.deltaX > 0 ? 1 : -1) : 0;\r\n        this._scrollSpeed.y += deltaY * manualSpeed;\r\n        this._scrollSpeed.x += deltaX * manualSpeed;\r\n        this._onTapMove(evt);\r\n\r\n        // Prevent defaul scrolling behaviour, eg. page scrolling\r\n        evt.preventDefault();\r\n    }\r\n\r\n    _recalculateSelectionAreaRect(): void {\r\n        const {_scrollSpeed, _areaLocation, _areaRect, _targetElement, _targetRect} = this;\r\n        const {scrollTop, scrollHeight, clientHeight, scrollLeft, scrollWidth, clientWidth} = _targetElement as Element;\r\n        const brect = _targetRect as DOMRect;\r\n        let {x1, y1, x2, y2} = _areaLocation;\r\n\r\n        if (x2 < brect.left) {\r\n            _scrollSpeed.x = scrollLeft ? -abs(brect.left - x2) : 0;\r\n            x2 = brect.left;\r\n        } else if (x2 > brect.right) {\r\n            _scrollSpeed.x = scrollWidth - scrollLeft - clientWidth ? abs(brect.left + brect.width - x2) : 0;\r\n            x2 = brect.right;\r\n        } else {\r\n            _scrollSpeed.x = 0;\r\n        }\r\n\r\n        if (y2 < brect.top) {\r\n            _scrollSpeed.y = scrollTop ? -abs(brect.top - y2) : 0;\r\n            y2 = brect.top;\r\n        } else if (y2 > brect.bottom) {\r\n            _scrollSpeed.y = scrollHeight - scrollTop - clientHeight ? abs(brect.top + brect.height - y2) : 0;\r\n            y2 = brect.bottom;\r\n        } else {\r\n            _scrollSpeed.y = 0;\r\n        }\r\n\r\n        const x3 = min(x1, x2);\r\n        const y3 = min(y1, y2);\r\n        const x4 = max(x1, x2);\r\n        const y4 = max(y1, y2);\r\n\r\n        _areaRect.x = x3;\r\n        _areaRect.y = y3;\r\n        _areaRect.width = x4 - x3;\r\n        _areaRect.height = y4 - y3;\r\n    }\r\n\r\n    _redrawSelectionArea(): void {\r\n        const {x, y, width, height} = this._areaRect;\r\n        const {style} = this._area;\r\n\r\n        // Using transform will make the area's borders look blurry\r\n        style.left = `${x}px`;\r\n        style.top = `${y}px`;\r\n        style.width = `${width}px`;\r\n        style.height = `${height}px`;\r\n    }\r\n\r\n    _onTapStop(evt: MouseEvent | TouchEvent | null, silent: boolean): void {\r\n        const {document, singleTap} = this._options;\r\n        const {_singleClick} = this;\r\n\r\n        // Remove event handlers\r\n        off(document, ['mousemove', 'touchmove'], this._delayedTapMove);\r\n        off(document, ['touchmove', 'mousemove'], this._onTapMove);\r\n        off(document, ['mouseup', 'touchcancel', 'touchend'], this._onTapStop);\r\n        off(document, 'scroll', this._onScroll);\r\n\r\n        if (evt && _singleClick && singleTap.allow) {\r\n            this._onSingleTap(evt);\r\n        } else if (!_singleClick && !silent) {\r\n            this._updateElementSelection();\r\n            this._emitEvent('stop', evt);\r\n        }\r\n\r\n        // Reset scroll speed\r\n        this._scrollSpeed.x = 0;\r\n        this._scrollSpeed.y = 0;\r\n\r\n        // Unbind mouse scrolling listener\r\n        this._scrollAvailable && off(document, 'wheel', this._manualScroll, {passive: true});\r\n\r\n        // Remove selection-area from dom\r\n        this._clippingElement.remove();\r\n\r\n        // Hide selection area\r\n        css(this._area, 'display', 'none');\r\n    }\r\n\r\n    _updateElementSelection(): void {\r\n        const {_selectables, _options, _selection, _areaRect} = this;\r\n        const {stored, selected, touched} = _selection;\r\n        const {intersect, overlap} = _options;\r\n\r\n        // Update\r\n        const newlyTouched = [];\r\n        const added = [];\r\n        const removed = [];\r\n\r\n        // Itreate over the selectable elements\r\n        for (let i = 0; i < _selectables.length; i++) {\r\n            const node = _selectables[i];\r\n\r\n            // Check if area intersects element\r\n            if (intersects(_areaRect, node.getBoundingClientRect(), intersect)) {\r\n\r\n                // Check if the element wasn't present in the last selection.\r\n                if (!selected.includes(node)) {\r\n\r\n                    // Check if user wants to invert the selection for already selected elements\r\n                    if (overlap === 'invert' && stored.includes(node)) {\r\n                        removed.push(node);\r\n                        continue;\r\n                    } else {\r\n                        added.push(node);\r\n                    }\r\n                } else if (stored.includes(node) && !touched.includes(node)) {\r\n                    touched.push(node);\r\n                }\r\n\r\n                newlyTouched.push(node);\r\n            }\r\n        }\r\n\r\n        // Re-select elements which were previously stored\r\n        if (overlap === 'invert') {\r\n            added.push(...stored.filter(v => !selected.includes(v)));\r\n        }\r\n\r\n        // Check which elements where removed since last selection\r\n        for (let i = 0; i < selected.length; i++) {\r\n            const node = selected[i];\r\n\r\n            if (!newlyTouched.includes(node) && !(\r\n\r\n                // Check if user wants to keep previously selected elements, e.g.\r\n                // not make them part of the current selection as soon as they're touched.\r\n                overlap === 'keep' && stored.includes(node)\r\n            )) {\r\n                removed.push(node);\r\n            }\r\n        }\r\n\r\n        // Save\r\n        _selection.selected = newlyTouched;\r\n        _selection.changed = {added, removed};\r\n    }\r\n\r\n    _emitEvent(name: keyof SelectionEvents, evt: MouseEvent | TouchEvent | null): unknown {\r\n        return this.emit(name, {\r\n            event: evt,\r\n            store: this._selection\r\n        });\r\n    }\r\n\r\n    /**\r\n     * Manually triggers the start of a selection\r\n     * @param evt A MouseEvent / TouchEvent -like object\r\n     * @param silent If beforestart should be fired,\r\n     */\r\n    trigger(evt: MouseEvent | TouchEvent, silent = true): void {\r\n        this._onTapStart(evt, silent);\r\n    }\r\n\r\n    /**\r\n     * Can be used if during a selection elements have been added.\r\n     * Will update everything which can be selected.\r\n     */\r\n    resolveSelectables(): void {\r\n\r\n        // Resolve selectors\r\n        this._selectables = selectAll(this._options.selectables, this._options.document);\r\n    }\r\n\r\n    /**\r\n     * Saves the current selection for the next selecion.\r\n     * Allows multiple selections.\r\n     */\r\n    keepSelection(): void {\r\n        const {_options, _selection} = this;\r\n        const {selected, changed, touched, stored} = _selection;\r\n\r\n        // Newly added elements\r\n        const addedElements = selected.filter(el => !stored.includes(el));\r\n\r\n        switch (_options.overlap) {\r\n            case 'drop': {\r\n                _selection.stored = addedElements.concat(\r\n\r\n                    // Elements not touched\r\n                    stored.filter(el => !touched.includes(el))\r\n                );\r\n                break;\r\n            }\r\n            case 'invert': {\r\n                _selection.stored = addedElements.concat(\r\n\r\n                    // Elements not removed from selection\r\n                    stored.filter(el => !changed.removed.includes(el))\r\n                );\r\n                break;\r\n            }\r\n            case 'keep': {\r\n                _selection.stored = stored.concat(\r\n\r\n                    // Newly added\r\n                    selected.filter(el => !stored.includes(el))\r\n                );\r\n                break;\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Clear the elements which where saved by 'keepSelection()'.\r\n     * @param store If the store should also get cleared\r\n     */\r\n    clearSelection(store = true): void {\r\n        this._selection = {\r\n            stored: store ? [] : this._selection.stored,\r\n            selected: [],\r\n            touched: [],\r\n            changed: {\r\n                added: [],\r\n                removed: []\r\n            }\r\n        };\r\n    }\r\n\r\n    /**\r\n     * @returns {Array} Selected elements\r\n     */\r\n    getSelection(): Array<Element> {\r\n        return this._selection.stored;\r\n    }\r\n\r\n    /**\r\n     * @returns {HTMLElement} The selection area element\r\n     */\r\n    getSelectionArea(): HTMLElement {\r\n        return this._area;\r\n    }\r\n\r\n    /**\r\n     * Cancel the current selection process.\r\n     * @param keepEvent {boolean} true to fire the onStop listener after cancel.\r\n     */\r\n    cancel(keepEvent = false): void {\r\n        this._onTapStop(null, !keepEvent);\r\n    }\r\n\r\n    /**\r\n     * Unbinds all events and removes the area-element.\r\n     */\r\n    destroy(): void {\r\n        this.cancel();\r\n        this.disable();\r\n        this._clippingElement.remove();\r\n        super.unbindAllListeners();\r\n    }\r\n\r\n    /**\r\n     * Disable the selection functinality.\r\n     */\r\n    /* eslint-disable no-invalid-this */\r\n    disable = this._bindStartEvents.bind(this, false);\r\n\r\n    /**\r\n     * Disable the selection functinality.\r\n     */\r\n    /* eslint-disable no-invalid-this */\r\n    enable = this._bindStartEvents;\r\n\r\n    /**\r\n     * Adds elements to the selection\r\n     * @param query - CSS Query, can be an array of queries\r\n     * @param quiet - If this should not trigger the move event\r\n     */\r\n    select(query: SelectAllSelectors, quiet = false): Array<Element> {\r\n        const {changed, selected, stored} = this._selection;\r\n        const elements = selectAll(query, this._options.document).filter(el =>\r\n            !selected.includes(el) &&\r\n            !stored.includes(el)\r\n        );\r\n\r\n        // Update stores\r\n        selected.push(...elements);\r\n        changed.added.push(...elements);\r\n\r\n        !quiet && this._emitEvent('move', null);\r\n        return elements;\r\n    }\r\n\r\n    /**\r\n     * Removes an particular element from the selection.\r\n     * @param el - Element to remove.\r\n     * @param quiet - If this should not trigger the move event\r\n     * @returns boolean - true if the element was successfully removed\r\n     */\r\n    deselect(el: Element, quiet = false): boolean {\r\n        const {selected, stored, changed} = this._selection;\r\n\r\n        if (\r\n            selected.includes(el) ||\r\n            stored.includes(el)\r\n        ) {\r\n            changed.removed.push(el);\r\n            removeElement(stored, el);\r\n            removeElement(selected, el);\r\n\r\n            // Fire event\r\n            !quiet && this._emitEvent('move', null);\r\n            return true;\r\n        }\r\n\r\n        return false;\r\n    }\r\n}\r\n","\r\n/* eslint-disable @typescript-eslint/no-explicit-any */\r\ntype AnyFunction = (...args: any[]) => any;\r\ntype EventMap = Record<string, AnyFunction>;\r\n\r\nexport class EventTarget<Events extends EventMap> {\r\n    private readonly _listeners = new Map<keyof Events, Set<AnyFunction>>();\r\n\r\n    public addEventListener<K extends keyof Events>(event: K, cb: Events[K]): this {\r\n        const set = this._listeners.get(event) || new Set();\r\n        this._listeners.set(event, set);\r\n        set.add(cb as AnyFunction);\r\n        return this;\r\n    }\r\n\r\n    public removeEventListener<K extends keyof Events>(event: K, cb: Events[K]): this {\r\n        this._listeners.get(event)?.delete(cb as AnyFunction);\r\n        return this;\r\n    }\r\n\r\n    public dispatchEvent<K extends keyof Events>(event: K, ...data: Parameters<Events[K]>): unknown {\r\n        let ok = true;\r\n        for (const cb of (this._listeners.get(event) || [])) {\r\n            ok = (cb(...data) !== false) && ok;\r\n        }\r\n\r\n        return ok;\r\n    }\r\n\r\n    public unbindAllListeners(): void {\r\n        this._listeners.clear();\r\n    }\r\n\r\n    // Let's also support on, off and emit like node\r\n    /* eslint-disable no-invalid-this */\r\n    public on = this.addEventListener;\r\n    public off = this.removeEventListener;\r\n    public emit = this.dispatchEvent;\r\n}\r\n"],"names":["unitify","val","unit","css","style","attr","key","value","Object","entries","undefined","eventListener","method","items","events","fn","options","HTMLCollection","NodeList","Array","from","isArray","el","ev","capture","on","off","simplifyEvent","evt","tap","touches","x","clientX","y","clientY","target","eventPath","path","composedPath","parentElement","push","document","window","intersects","a","b","mode","bxc","left","width","byc","top","height","right","bottom","Error","removeElement","arr","index","indexOf","splice","selectAll","selector","doc","list","nodes","i","l","length","item","querySelectorAll","HTMLElement","isTouchDevice","matchMedia","matches","abs","max","min","ceil","Math","SelectionArea","[object Object]","this","Map","addEventListener","removeEventListener","dispatchEvent","event","cb","set","_listeners","get","Set","add","delete","data","ok","clear","opt","super","touched","stored","selected","changed","added","removed","DOMRect","y1","x2","y2","x1","_bindStartEvents","bind","_options","assign","class","intersect","startThreshold","singleClick","allowTouch","overlap","selectables","singleTap","allow","scrolling","speedDivider","manualSpeed","startareas","boundaries","container","getOwnPropertyNames","getPrototypeOf","_area","createElement","_clippingElement","appendChild","classList","willChange","position","overflow","transform","pointerEvents","zIndex","enable","activate","_onTapStart","passive","silent","_","targetBoundingClientRect","getBoundingClientRect","startAreas","resolvedBoundaries","_targetElement","find","evtpath","includes","_emitEvent","_areaLocation","scrollElement","scrollingElement","body","_scrollDelta","scrollLeft","scrollTop","_singleClick","clearSelection","_delayedTapMove","_onTapStop","_onScroll","spl","resolveSelectables","_selectables","v","_selection","shiftKey","reference","preceding","following","compareDocumentPosition","rangeItems","filter","select","ctrlKey","deselect","thresholdType","_onTapMove","_targetRect","_scrollAvailable","scrollHeight","clientHeight","scrollWidth","clientWidth","_manualScroll","s","contains","_prepareSelectionArea","preventDefault","T","L","S","tr","marginTop","marginLeft","m","_scrollSpeed","scon","scroll","_recalculateSelectionAreaRect","_updateElementSelection","_redrawSelectionArea","requestAnimationFrame","deltaY","deltaX","h","_areaRect","C","brect","x3","y3","x4","y4","u","_onSingleTap","remove","o","newlyTouched","node","name","emit","store","addedElements","concat","keepEvent","cancel","disable","unbindAllListeners","query","quiet","elements"],"mappings":"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"}