,\n })\n\n this.pointers.splice(pointerIndex, 1)\n this.pointerIsDown = false\n }\n\n _updateLatestPointer (pointer: PointerType, event: PointerEventType, eventTarget: Node) {\n this._latestPointer.pointer = pointer\n this._latestPointer.event = event\n this._latestPointer.eventTarget = eventTarget\n }\n\n destroy () {\n this._latestPointer.pointer = null\n this._latestPointer.event = null\n this._latestPointer.eventTarget = null\n }\n\n _createPreparedEvent (\n event: PointerEventType,\n phase: P,\n preEnd?: boolean,\n type?: string,\n ) {\n return new InteractEvent(this, event, this.prepared.name, phase, this.element, preEnd, type)\n }\n\n _fireEvent (iEvent: InteractEvent) {\n this.interactable.fire(iEvent)\n\n if (!this.prevEvent || iEvent.timeStamp >= this.prevEvent.timeStamp) {\n this.prevEvent = iEvent\n }\n }\n\n _doPhase (\n signalArg: Omit, 'iEvent'> & { iEvent?: InteractEvent },\n ) {\n const { event, phase, preEnd, type } = signalArg\n const { rect } = this\n\n if (rect && phase === 'move') {\n // update the rect changes due to pointer move\n rectUtils.addEdges(this.edges, rect, this.coords.delta[this.interactable.options.deltaSource])\n\n rect.width = rect.right - rect.left\n rect.height = rect.bottom - rect.top\n }\n\n const beforeResult = this._scopeFire(`interactions:before-action-${phase}` as any, signalArg)\n\n if (beforeResult === false) {\n return false\n }\n\n const iEvent = (signalArg.iEvent = this._createPreparedEvent(event, phase, preEnd, type))\n\n this._scopeFire(`interactions:action-${phase}` as any, signalArg)\n\n if (phase === 'start') {\n this.prevEvent = iEvent\n }\n\n this._fireEvent(iEvent)\n\n this._scopeFire(`interactions:after-action-${phase}` as any, signalArg)\n\n return true\n }\n\n _now () {\n return Date.now()\n }\n}\n\nexport default Interaction\nexport { PointerInfo }\n","import type Interaction from '@interactjs/core/Interaction'\nimport { _ProxyMethods } from '@interactjs/core/Interaction'\nimport type { Plugin } from '@interactjs/core/scope'\nimport type { Point } from '@interactjs/types/index'\nimport * as rectUtils from '@interactjs/utils/rect'\n\ndeclare module '@interactjs/core/Interaction' {\n interface Interaction {\n offsetBy?: typeof offsetBy\n offset: {\n total: Point\n pending: Point\n }\n }\n\n enum _ProxyMethods {\n offsetBy = '',\n }\n}\n\n;(_ProxyMethods as any).offsetBy = ''\n\nexport function addTotal (interaction: Interaction) {\n if (!interaction.pointerIsDown) {\n return\n }\n\n addToCoords(interaction.coords.cur, interaction.offset.total)\n\n interaction.offset.pending.x = 0\n interaction.offset.pending.y = 0\n}\n\nfunction beforeAction ({ interaction }: { interaction: Interaction }) {\n applyPending(interaction)\n}\n\nfunction beforeEnd ({ interaction }: { interaction: Interaction }): boolean | void {\n const hadPending = applyPending(interaction)\n\n if (!hadPending) return\n\n interaction.move({ offset: true })\n interaction.end()\n\n return false\n}\n\nfunction end ({ interaction }: { interaction: Interaction }) {\n interaction.offset.total.x = 0\n interaction.offset.total.y = 0\n interaction.offset.pending.x = 0\n interaction.offset.pending.y = 0\n}\n\nexport function applyPending (interaction: Interaction) {\n if (!hasPending(interaction)) {\n return false\n }\n\n const { pending } = interaction.offset\n\n addToCoords(interaction.coords.cur, pending)\n addToCoords(interaction.coords.delta, pending)\n rectUtils.addEdges(interaction.edges, interaction.rect, pending)\n\n pending.x = 0\n pending.y = 0\n\n return true\n}\n\nfunction offsetBy (this: Interaction, { x, y }: Point) {\n this.offset.pending.x += x\n this.offset.pending.y += y\n\n this.offset.total.x += x\n this.offset.total.y += y\n}\n\nfunction addToCoords ({ page, client }, { x, y }: Point) {\n page.x += x\n page.y += y\n client.x += x\n client.y += y\n}\n\nfunction hasPending (interaction: Interaction) {\n return !!(interaction.offset.pending.x || interaction.offset.pending.y)\n}\n\nconst offset: Plugin = {\n id: 'offset',\n before: ['modifiers', 'pointer-events', 'actions', 'inertia'],\n install (scope) {\n scope.Interaction.prototype.offsetBy = offsetBy\n },\n listeners: {\n 'interactions:new': ({ interaction }) => {\n interaction.offset = {\n total: { x: 0, y: 0 },\n pending: { x: 0, y: 0 },\n }\n },\n 'interactions:update-pointer': ({ interaction }) => addTotal(interaction),\n 'interactions:before-action-start': beforeAction,\n 'interactions:before-action-move': beforeAction,\n 'interactions:before-action-end': beforeEnd,\n 'interactions:stop': end,\n },\n}\n\nexport default offset\n","import type { Interaction, DoPhaseArg } from '@interactjs/core/Interaction'\nimport type { ActionName, Scope, SignalArgs, Plugin } from '@interactjs/core/scope'\nimport Modification from '@interactjs/modifiers/Modification'\nimport * as modifiers from '@interactjs/modifiers/base'\nimport offset from '@interactjs/offset/plugin'\nimport type { Point, PointerEventType } from '@interactjs/types/index'\nimport * as dom from '@interactjs/utils/domUtils'\nimport hypot from '@interactjs/utils/hypot'\nimport is from '@interactjs/utils/is'\nimport { copyCoords } from '@interactjs/utils/pointerUtils'\nimport raf from '@interactjs/utils/raf'\n\ndeclare module '@interactjs/core/InteractEvent' {\n interface PhaseMap {\n resume?: true\n inertiastart?: true\n }\n}\n\ndeclare module '@interactjs/core/Interaction' {\n interface Interaction {\n inertia?: InertiaState\n }\n}\n\ndeclare module '@interactjs/core/options' {\n interface PerActionDefaults {\n inertia?: {\n enabled?: boolean\n resistance?: number // the lambda in exponential decay\n minSpeed?: number // target speed must be above this for inertia to start\n endSpeed?: number // the speed at which inertia is slow enough to stop\n allowResume?: true // allow resuming an action in inertia phase\n smoothEndDuration?: number // animate to snap/restrict endOnly if there's no inertia\n }\n }\n}\n\ndeclare module '@interactjs/core/scope' {\n interface SignalArgs {\n 'interactions:before-action-inertiastart': Omit, 'iEvent'>\n 'interactions:action-inertiastart': DoPhaseArg\n 'interactions:after-action-inertiastart': DoPhaseArg\n 'interactions:before-action-resume': Omit, 'iEvent'>\n 'interactions:action-resume': DoPhaseArg\n 'interactions:after-action-resume': DoPhaseArg\n }\n}\n\nfunction install (scope: Scope) {\n const { defaults } = scope\n\n scope.usePlugin(offset)\n scope.usePlugin(modifiers.default)\n scope.actions.phases.inertiastart = true\n scope.actions.phases.resume = true\n\n defaults.perAction.inertia = {\n enabled: false,\n resistance: 10, // the lambda in exponential decay\n minSpeed: 100, // target speed must be above this for inertia to start\n endSpeed: 10, // the speed at which inertia is slow enough to stop\n allowResume: true, // allow resuming an action in inertia phase\n smoothEndDuration: 300, // animate to snap/restrict endOnly if there's no inertia\n }\n}\n\nexport class InertiaState {\n active = false\n isModified = false\n smoothEnd = false\n allowResume = false\n\n modification!: Modification\n modifierCount = 0\n modifierArg!: modifiers.ModifierArg\n\n startCoords!: Point\n t0 = 0\n v0 = 0\n\n te = 0\n targetOffset!: Point\n modifiedOffset!: Point\n currentOffset!: Point\n\n lambda_v0? = 0 // eslint-disable-line camelcase\n one_ve_v0? = 0 // eslint-disable-line camelcase\n timeout!: number\n readonly interaction: Interaction\n\n constructor (interaction: Interaction) {\n this.interaction = interaction\n }\n\n start (event: PointerEventType) {\n const { interaction } = this\n const options = getOptions(interaction)\n\n if (!options || !options.enabled) {\n return false\n }\n\n const { client: velocityClient } = interaction.coords.velocity\n const pointerSpeed = hypot(velocityClient.x, velocityClient.y)\n const modification = this.modification || (this.modification = new Modification(interaction))\n\n modification.copyFrom(interaction.modification)\n\n this.t0 = interaction._now()\n this.allowResume = options.allowResume\n this.v0 = pointerSpeed\n this.currentOffset = { x: 0, y: 0 }\n this.startCoords = interaction.coords.cur.page\n\n this.modifierArg = modification.fillArg({\n pageCoords: this.startCoords,\n preEnd: true,\n phase: 'inertiastart',\n })\n\n const thrown =\n this.t0 - interaction.coords.cur.timeStamp < 50 &&\n pointerSpeed > options.minSpeed &&\n pointerSpeed > options.endSpeed\n\n if (thrown) {\n this.startInertia()\n } else {\n modification.result = modification.setAll(this.modifierArg)\n\n if (!modification.result.changed) {\n return false\n }\n\n this.startSmoothEnd()\n }\n\n // force modification change\n interaction.modification.result.rect = null\n\n // bring inertiastart event to the target coords\n interaction.offsetBy(this.targetOffset)\n interaction._doPhase({\n interaction,\n event,\n phase: 'inertiastart',\n })\n interaction.offsetBy({ x: -this.targetOffset.x, y: -this.targetOffset.y })\n // force modification change\n interaction.modification.result.rect = null\n\n this.active = true\n interaction.simulation = this\n\n return true\n }\n\n startInertia () {\n const startVelocity = this.interaction.coords.velocity.client\n const options = getOptions(this.interaction)\n const lambda = options.resistance\n const inertiaDur = -Math.log(options.endSpeed / this.v0) / lambda\n\n this.targetOffset = {\n x: (startVelocity.x - inertiaDur) / lambda,\n y: (startVelocity.y - inertiaDur) / lambda,\n }\n\n this.te = inertiaDur\n this.lambda_v0 = lambda / this.v0\n this.one_ve_v0 = 1 - options.endSpeed / this.v0\n\n const { modification, modifierArg } = this\n\n modifierArg.pageCoords = {\n x: this.startCoords.x + this.targetOffset.x,\n y: this.startCoords.y + this.targetOffset.y,\n }\n\n modification.result = modification.setAll(modifierArg)\n\n if (modification.result.changed) {\n this.isModified = true\n this.modifiedOffset = {\n x: this.targetOffset.x + modification.result.delta.x,\n y: this.targetOffset.y + modification.result.delta.y,\n }\n }\n\n this.onNextFrame(() => this.inertiaTick())\n }\n\n startSmoothEnd () {\n this.smoothEnd = true\n this.isModified = true\n this.targetOffset = {\n x: this.modification.result.delta.x,\n y: this.modification.result.delta.y,\n }\n\n this.onNextFrame(() => this.smoothEndTick())\n }\n\n onNextFrame (tickFn: () => void) {\n this.timeout = raf.request(() => {\n if (this.active) {\n tickFn()\n }\n })\n }\n\n inertiaTick () {\n const { interaction } = this\n const options = getOptions(interaction)\n const lambda = options.resistance\n const t = (interaction._now() - this.t0) / 1000\n\n if (t < this.te) {\n const progress = 1 - (Math.exp(-lambda * t) - this.lambda_v0) / this.one_ve_v0\n let newOffset: Point\n\n if (this.isModified) {\n newOffset = getQuadraticCurvePoint(\n 0,\n 0,\n this.targetOffset.x,\n this.targetOffset.y,\n this.modifiedOffset.x,\n this.modifiedOffset.y,\n progress,\n )\n } else {\n newOffset = {\n x: this.targetOffset.x * progress,\n y: this.targetOffset.y * progress,\n }\n }\n\n const delta = { x: newOffset.x - this.currentOffset.x, y: newOffset.y - this.currentOffset.y }\n\n this.currentOffset.x += delta.x\n this.currentOffset.y += delta.y\n\n interaction.offsetBy(delta)\n interaction.move()\n\n this.onNextFrame(() => this.inertiaTick())\n } else {\n interaction.offsetBy({\n x: this.modifiedOffset.x - this.currentOffset.x,\n y: this.modifiedOffset.y - this.currentOffset.y,\n })\n\n this.end()\n }\n }\n\n smoothEndTick () {\n const { interaction } = this\n const t = interaction._now() - this.t0\n const { smoothEndDuration: duration } = getOptions(interaction)\n\n if (t < duration) {\n const newOffset = {\n x: easeOutQuad(t, 0, this.targetOffset.x, duration),\n y: easeOutQuad(t, 0, this.targetOffset.y, duration),\n }\n const delta = {\n x: newOffset.x - this.currentOffset.x,\n y: newOffset.y - this.currentOffset.y,\n }\n\n this.currentOffset.x += delta.x\n this.currentOffset.y += delta.y\n\n interaction.offsetBy(delta)\n interaction.move({ skipModifiers: this.modifierCount })\n\n this.onNextFrame(() => this.smoothEndTick())\n } else {\n interaction.offsetBy({\n x: this.targetOffset.x - this.currentOffset.x,\n y: this.targetOffset.y - this.currentOffset.y,\n })\n\n this.end()\n }\n }\n\n resume ({ pointer, event, eventTarget }: SignalArgs['interactions:down']) {\n const { interaction } = this\n\n // undo inertia changes to interaction coords\n interaction.offsetBy({\n x: -this.currentOffset.x,\n y: -this.currentOffset.y,\n })\n\n // update pointer at pointer down position\n interaction.updatePointer(pointer, event, eventTarget, true)\n\n // fire resume signals and event\n interaction._doPhase({\n interaction,\n event,\n phase: 'resume',\n })\n copyCoords(interaction.coords.prev, interaction.coords.cur)\n\n this.stop()\n }\n\n end () {\n this.interaction.move()\n this.interaction.end()\n this.stop()\n }\n\n stop () {\n this.active = this.smoothEnd = false\n this.interaction.simulation = null\n raf.cancel(this.timeout)\n }\n}\n\nfunction start ({ interaction, event }: DoPhaseArg) {\n if (!interaction._interacting || interaction.simulation) {\n return null\n }\n\n const started = interaction.inertia.start(event)\n\n // prevent action end if inertia or smoothEnd\n return started ? false : null\n}\n\n// Check if the down event hits the current inertia target\n// control should be return to the user\nfunction resume (arg: SignalArgs['interactions:down']) {\n const { interaction, eventTarget } = arg\n const state = interaction.inertia\n\n if (!state.active) return\n\n let element = eventTarget as Node\n\n // climb up the DOM tree from the event target\n while (is.element(element)) {\n // if interaction element is the current inertia target element\n if (element === interaction.element) {\n state.resume(arg)\n break\n }\n\n element = dom.parentNode(element)\n }\n}\n\nfunction stop ({ interaction }: { interaction: Interaction }) {\n const state = interaction.inertia\n\n if (state.active) {\n state.stop()\n }\n}\n\nfunction getOptions ({ interactable, prepared }: Interaction) {\n return interactable && interactable.options && prepared.name && interactable.options[prepared.name].inertia\n}\n\nconst inertia: Plugin = {\n id: 'inertia',\n before: ['modifiers', 'actions'],\n install,\n listeners: {\n 'interactions:new': ({ interaction }) => {\n interaction.inertia = new InertiaState(interaction)\n },\n\n 'interactions:before-action-end': start,\n 'interactions:down': resume,\n 'interactions:stop': stop,\n\n 'interactions:before-action-resume': (arg) => {\n const { modification } = arg.interaction\n\n modification.stop(arg)\n modification.start(arg, arg.interaction.coords.cur.page)\n modification.applyToInteraction(arg)\n },\n\n 'interactions:before-action-inertiastart': (arg) => arg.interaction.modification.setAndApply(arg),\n 'interactions:action-resume': modifiers.addEventModifiers,\n 'interactions:action-inertiastart': modifiers.addEventModifiers,\n 'interactions:after-action-inertiastart': (arg) =>\n arg.interaction.modification.restoreInteractionCoords(arg),\n 'interactions:after-action-resume': (arg) => arg.interaction.modification.restoreInteractionCoords(arg),\n },\n}\n\n// http://stackoverflow.com/a/5634528/2280888\nfunction _getQBezierValue (t: number, p1: number, p2: number, p3: number) {\n const iT = 1 - t\n return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3\n}\n\nfunction getQuadraticCurvePoint (\n startX: number,\n startY: number,\n cpX: number,\n cpY: number,\n endX: number,\n endY: number,\n position: number,\n) {\n return {\n x: _getQBezierValue(position, startX, cpX, endX),\n y: _getQBezierValue(position, startY, cpY, endY),\n }\n}\n\n// http://gizma.com/easing/\nfunction easeOutQuad (t: number, b: number, c: number, d: number) {\n t /= d\n return -c * t * (t - 2) + b\n}\n\nexport default inertia\n","import type { Listener, ListenersArg, Rect } from '@interactjs/types/index'\nimport * as arr from '@interactjs/utils/arr'\nimport extend from '@interactjs/utils/extend'\nimport type { NormalizedListeners } from '@interactjs/utils/normalizeListeners'\nimport normalize from '@interactjs/utils/normalizeListeners'\n\nfunction fireUntilImmediateStopped (event: any, listeners: Listener[]) {\n for (const listener of listeners) {\n if (event.immediatePropagationStopped) {\n break\n }\n\n listener(event)\n }\n}\n\nexport class Eventable {\n options: any\n types: NormalizedListeners = {}\n propagationStopped = false\n immediatePropagationStopped = false\n global: any\n\n constructor (options?: { [index: string]: any }) {\n this.options = extend({}, options || {})\n }\n\n fire (event: T) {\n let listeners: Listener[]\n const global = this.global\n\n // Interactable#on() listeners\n // tslint:disable no-conditional-assignment\n if ((listeners = this.types[event.type])) {\n fireUntilImmediateStopped(event, listeners)\n }\n\n // interact.on() listeners\n if (!event.propagationStopped && global && (listeners = global[event.type])) {\n fireUntilImmediateStopped(event, listeners)\n }\n }\n\n on (type: string, listener: ListenersArg) {\n const listeners = normalize(type, listener)\n\n for (type in listeners) {\n this.types[type] = arr.merge(this.types[type] || [], listeners[type])\n }\n }\n\n off (type: string, listener: ListenersArg) {\n const listeners = normalize(type, listener)\n\n for (type in listeners) {\n const eventList = this.types[type]\n\n if (!eventList || !eventList.length) {\n continue\n }\n\n for (const subListener of listeners[type]) {\n const index = eventList.indexOf(subListener)\n\n if (index !== -1) {\n eventList.splice(index, 1)\n }\n }\n }\n }\n\n getRect (_element: Element): Rect {\n return null\n }\n}\n","import type { Actions } from '@interactjs/core/scope'\n\nexport default function isNonNativeEvent (type: string, actions: Actions) {\n if (actions.phaselessTypes[type]) {\n return true\n }\n\n for (const name in actions.map) {\n if (type.indexOf(name) === 0 && type.substr(name.length) in actions.phases) {\n return true\n }\n }\n\n return false\n}\n","/** @module interact */\nimport type { Scope, Plugin } from '@interactjs/core/scope'\nimport type { Context, EventTypes, Listener, ListenersArg, Target, Element } from '@interactjs/types/index'\nimport browser from '@interactjs/utils/browser'\nimport * as domUtils from '@interactjs/utils/domUtils'\nimport is from '@interactjs/utils/is'\nimport { warnOnce } from '@interactjs/utils/misc'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\nimport type { Interactable } from './Interactable'\nimport isNonNativeEvent from './isNonNativeEvent'\nimport type { Options } from './options'\n\ndeclare module '@interactjs/core/InteractStatic' {\n export interface InteractStatic {\n (target: Target, options?: Options): Interactable\n getPointerAverage: typeof pointerUtils.pointerAverage\n getTouchBBox: typeof pointerUtils.touchBBox\n getTouchDistance: typeof pointerUtils.touchDistance\n getTouchAngle: typeof pointerUtils.touchAngle\n getElementRect: typeof domUtils.getElementRect\n getElementClientRect: typeof domUtils.getElementClientRect\n matchesSelector: typeof domUtils.matchesSelector\n closest: typeof domUtils.closest\n /** @internal */ globalEvents: any\n version: string\n /** @internal */ scope: Scope\n use(\n plugin: Plugin,\n options?: {\n [key: string]: any\n },\n ): any\n isSet(target: Element, options?: any): boolean\n on(type: string | EventTypes, listener: ListenersArg, options?: object): any\n off(type: EventTypes, listener: any, options?: object): any\n debug(): any\n supportsTouch(): boolean\n supportsPointerEvent(): boolean\n stop(): any\n pointerMoveTolerance(newValue?: number): any\n addDocument(doc: Document, options?: object): void\n removeDocument(doc: Document): void\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/consistent-type-imports\ntype _InteractStatic = import('@interactjs/core/InteractStatic').InteractStatic\n\nexport function createInteractStatic (scope: Scope): _InteractStatic {\n /**\n * ```js\n * interact('#draggable').draggable(true)\n *\n * var rectables = interact('rect')\n * rectables\n * .gesturable(true)\n * .on('gesturemove', function (event) {\n * // ...\n * })\n * ```\n *\n * The methods of this variable can be used to set elements as interactables\n * and also to change various default settings.\n *\n * Calling it as a function and passing an element or a valid CSS selector\n * string returns an Interactable object which has various methods to configure\n * it.\n *\n * @global\n *\n * @param {Element | string} target The HTML or SVG Element to interact with\n * or CSS selector\n * @return {Interactable}\n */\n const interact = ((target: Target, options: Options) => {\n let interactable = scope.interactables.get(target, options)\n\n if (!interactable) {\n interactable = scope.interactables.new(target, options)\n interactable.events.global = interact.globalEvents\n }\n\n return interactable\n }) as _InteractStatic\n\n // expose the functions used to calculate multi-touch properties\n interact.getPointerAverage = pointerUtils.pointerAverage\n interact.getTouchBBox = pointerUtils.touchBBox\n interact.getTouchDistance = pointerUtils.touchDistance\n interact.getTouchAngle = pointerUtils.touchAngle\n\n interact.getElementRect = domUtils.getElementRect\n interact.getElementClientRect = domUtils.getElementClientRect\n interact.matchesSelector = domUtils.matchesSelector\n interact.closest = domUtils.closest\n\n interact.globalEvents = {} as any\n\n // eslint-disable-next-line no-undef\n interact.version = process.env.npm_package_version\n interact.scope = scope\n /**\n * Use a plugin\n *\n * @alias module:interact.use\n *\n */\n interact.use = function (plugin, options) {\n this.scope.usePlugin(plugin, options)\n\n return this\n }\n\n /**\n * Check if an element or selector has been set with the {@link interact}\n * function\n *\n * @alias module:interact.isSet\n *\n * @param {Target} target The Element or string being searched for\n * @param {object} options\n * @return {boolean} Indicates if the element or CSS selector was previously\n * passed to interact\n */\n interact.isSet = function (target: Target, options?: { context?: Context }): boolean {\n return !!this.scope.interactables.get(target, options && options.context)\n }\n\n /**\n * @deprecated\n * Add a global listener for an InteractEvent or adds a DOM event to `document`\n *\n * @alias module:interact.on\n *\n * @param {string | array | object} type The types of events to listen for\n * @param {function} listener The function event (s)\n * @param {object | boolean} [options] object or useCapture flag for\n * addEventListener\n * @return {object} interact\n */\n interact.on = warnOnce(function on (type: string | EventTypes, listener: ListenersArg, options?: object) {\n if (is.string(type) && type.search(' ') !== -1) {\n type = type.trim().split(/ +/)\n }\n\n if (is.array(type)) {\n for (const eventType of type as any[]) {\n this.on(eventType, listener, options)\n }\n\n return this\n }\n\n if (is.object(type)) {\n for (const prop in type) {\n this.on(prop, (type as any)[prop], listener)\n }\n\n return this\n }\n\n // if it is an InteractEvent type, add listener to globalEvents\n if (isNonNativeEvent(type, this.scope.actions)) {\n // if this type of event was never bound\n if (!this.globalEvents[type]) {\n this.globalEvents[type] = [listener]\n } else {\n this.globalEvents[type].push(listener)\n }\n }\n // If non InteractEvent type, addEventListener to document\n else {\n this.scope.events.add(this.scope.document, type, listener as Listener, { options })\n }\n\n return this\n }, 'The interact.on() method is being deprecated')\n\n /**\n * @deprecated\n * Removes a global InteractEvent listener or DOM event from `document`\n *\n * @alias module:interact.off\n *\n * @param {string | array | object} type The types of events that were listened\n * for\n * @param {function} listener The listener function to be removed\n * @param {object | boolean} options [options] object or useCapture flag for\n * removeEventListener\n * @return {object} interact\n */\n interact.off = warnOnce(function off (type: EventTypes, listener: any, options?: object) {\n if (is.string(type) && type.search(' ') !== -1) {\n type = type.trim().split(/ +/)\n }\n\n if (is.array(type)) {\n for (const eventType of type) {\n this.off(eventType, listener, options)\n }\n\n return this\n }\n\n if (is.object(type)) {\n for (const prop in type) {\n this.off(prop, type[prop], listener)\n }\n\n return this\n }\n\n if (isNonNativeEvent(type, this.scope.actions)) {\n let index: number\n\n if (type in this.globalEvents && (index = this.globalEvents[type].indexOf(listener)) !== -1) {\n this.globalEvents[type].splice(index, 1)\n }\n } else {\n this.scope.events.remove(this.scope.document, type, listener, options)\n }\n\n return this\n }, 'The interact.off() method is being deprecated')\n\n interact.debug = function () {\n return this.scope\n }\n\n /**\n * @alias module:interact.supportsTouch\n *\n * @return {boolean} Whether or not the browser supports touch input\n */\n interact.supportsTouch = function () {\n return browser.supportsTouch\n }\n\n /**\n * @alias module:interact.supportsPointerEvent\n *\n * @return {boolean} Whether or not the browser supports PointerEvents\n */\n interact.supportsPointerEvent = function () {\n return browser.supportsPointerEvent\n }\n\n /**\n * Cancels all interactions (end events are not fired)\n *\n * @alias module:interact.stop\n *\n * @return {object} interact\n */\n interact.stop = function () {\n for (const interaction of this.scope.interactions.list) {\n interaction.stop()\n }\n\n return this\n }\n\n /**\n * Returns or sets the distance the pointer must be moved before an action\n * sequence occurs. This also affects tolerance for tap events.\n *\n * @alias module:interact.pointerMoveTolerance\n *\n * @param {number} [newValue] The movement from the start position must be greater than this value\n * @return {interact | number}\n */\n interact.pointerMoveTolerance = function (newValue?: number) {\n if (is.number(newValue)) {\n this.scope.interactions.pointerMoveTolerance = newValue\n\n return this\n }\n\n return this.scope.interactions.pointerMoveTolerance\n }\n\n interact.addDocument = function (doc: Document, options?: object) {\n this.scope.addDocument(doc, options)\n }\n\n interact.removeDocument = function (doc: Document) {\n this.scope.removeDocument(doc)\n }\n\n return interact\n}\n","/* eslint-disable no-dupe-class-members */\nimport type { ActionMap, ActionName, Actions, Scope } from '@interactjs/core/scope'\nimport type {\n Context,\n Element,\n Target,\n Listeners,\n OrBoolean,\n EventTypes,\n ListenersArg,\n ActionMethod,\n} from '@interactjs/types/index'\nimport * as arr from '@interactjs/utils/arr'\nimport browser from '@interactjs/utils/browser'\nimport clone from '@interactjs/utils/clone'\nimport { getElementRect, matchesUpTo, nodeContains, trySelector } from '@interactjs/utils/domUtils'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\nimport normalizeListeners from '@interactjs/utils/normalizeListeners'\nimport { getWindow } from '@interactjs/utils/window'\n\nimport { Eventable } from './Eventable'\nimport isNonNativeEvent from './isNonNativeEvent'\nimport type { ActionDefaults, Defaults, OptionsArg, PerActionDefaults } from './options'\nimport { Options } from './options'\n\ntype IgnoreValue = string | Element | boolean\ntype DeltaSource = 'page' | 'client'\n\n/** */\nexport class Interactable implements Partial {\n /** @internal */ get _defaults (): Defaults {\n return {\n base: {},\n perAction: {},\n actions: {} as ActionDefaults,\n }\n }\n\n readonly options!: Required\n readonly _actions: Actions\n readonly target: Target\n readonly events = new Eventable()\n readonly _context: Context\n readonly _win: Window\n readonly _doc: Document\n readonly _scopeEvents: Scope['events']\n\n /** @internal */ _rectChecker?: typeof Interactable.prototype.getRect\n\n /** */\n constructor (\n target: Target,\n options: any,\n defaultContext: Document | Element,\n scopeEvents: Scope['events'],\n ) {\n this._actions = options.actions\n this.target = target\n this._context = options.context || defaultContext\n this._win = getWindow(trySelector(target) ? this._context : target)\n this._doc = this._win.document\n this._scopeEvents = scopeEvents\n\n this.set(options)\n }\n\n setOnEvents (actionName: ActionName, phases: NonNullable) {\n if (is.func(phases.onstart)) {\n this.on(`${actionName}start`, phases.onstart)\n }\n if (is.func(phases.onmove)) {\n this.on(`${actionName}move`, phases.onmove)\n }\n if (is.func(phases.onend)) {\n this.on(`${actionName}end`, phases.onend)\n }\n if (is.func(phases.oninertiastart)) {\n this.on(`${actionName}inertiastart`, phases.oninertiastart)\n }\n\n return this\n }\n\n updatePerActionListeners (actionName: ActionName, prev: Listeners, cur: Listeners) {\n if (is.array(prev) || is.object(prev)) {\n this.off(actionName, prev)\n }\n\n if (is.array(cur) || is.object(cur)) {\n this.on(actionName, cur)\n }\n }\n\n setPerAction (actionName: ActionName, options: OrBoolean) {\n const defaults = this._defaults\n\n // for all the default per-action options\n for (const optionName_ in options) {\n const optionName = optionName_ as keyof PerActionDefaults\n const actionOptions = this.options[actionName]\n const optionValue: any = options[optionName]\n\n // remove old event listeners and add new ones\n if (optionName === 'listeners') {\n this.updatePerActionListeners(actionName, actionOptions.listeners, optionValue as Listeners)\n }\n\n // if the option value is an array\n if (is.array(optionValue)) {\n ;(actionOptions[optionName] as any) = arr.from(optionValue)\n }\n // if the option value is an object\n else if (is.plainObject(optionValue)) {\n // copy the object\n ;(actionOptions[optionName] as any) = extend(\n actionOptions[optionName] || ({} as any),\n clone(optionValue),\n )\n\n // set anabled field to true if it exists in the defaults\n if (\n is.object(defaults.perAction[optionName]) &&\n 'enabled' in (defaults.perAction[optionName] as any)\n ) {\n ;(actionOptions[optionName] as any).enabled = optionValue.enabled !== false\n }\n }\n // if the option value is a boolean and the default is an object\n else if (is.bool(optionValue) && is.object(defaults.perAction[optionName])) {\n ;(actionOptions[optionName] as any).enabled = optionValue\n }\n // if it's anything else, do a plain assignment\n else {\n ;(actionOptions[optionName] as any) = optionValue\n }\n }\n }\n\n /**\n * The default function to get an Interactables bounding rect. Can be\n * overridden using {@link Interactable.rectChecker}.\n *\n * @param {Element} [element] The element to measure.\n * @return {Rect} The object's bounding rectangle.\n */\n getRect (element: Element) {\n element = element || (is.element(this.target) ? this.target : null)\n\n if (is.string(this.target)) {\n element = element || this._context.querySelector(this.target)\n }\n\n return getElementRect(element)\n }\n\n /**\n * Returns or sets the function used to calculate the interactable's\n * element's rectangle\n *\n * @param {function} [checker] A function which returns this Interactable's\n * bounding rectangle. See {@link Interactable.getRect}\n * @return {function | object} The checker function or this Interactable\n */\n rectChecker(): (element: Element) => any | null\n rectChecker(checker: (element: Element) => any): this\n rectChecker (checker?: (element: Element) => any) {\n if (is.func(checker)) {\n this._rectChecker = checker\n\n this.getRect = (element) => {\n const rect = extend({}, this._rectChecker(element))\n\n if (!(('width' in rect) as unknown)) {\n rect.width = rect.right - rect.left\n rect.height = rect.bottom - rect.top\n }\n\n return rect\n }\n\n return this\n }\n\n if (checker === null) {\n delete this.getRect\n delete this._rectChecker\n\n return this\n }\n\n return this.getRect\n }\n\n _backCompatOption (optionName: keyof Options, newValue: any) {\n if (trySelector(newValue) || is.object(newValue)) {\n ;(this.options[optionName] as any) = newValue\n\n for (const action in this._actions.map) {\n ;(this.options[action as keyof ActionMap] as any)[optionName] = newValue\n }\n\n return this\n }\n\n return this.options[optionName]\n }\n\n /**\n * Gets or sets the origin of the Interactable's element. The x and y\n * of the origin will be subtracted from action event coordinates.\n *\n * @param {Element | object | string} [origin] An HTML or SVG Element whose\n * rect will be used, an object eg. { x: 0, y: 0 } or string 'parent', 'self'\n * or any CSS selector\n *\n * @return {object} The current origin or this Interactable\n */\n origin (newValue: any) {\n return this._backCompatOption('origin', newValue)\n }\n\n /**\n * Returns or sets the mouse coordinate types used to calculate the\n * movement of the pointer.\n *\n * @param {string} [newValue] Use 'client' if you will be scrolling while\n * interacting; Use 'page' if you want autoScroll to work\n * @return {string | object} The current deltaSource or this Interactable\n */\n deltaSource(): DeltaSource\n deltaSource(newValue: DeltaSource): this\n deltaSource (newValue?: DeltaSource) {\n if (newValue === 'page' || newValue === 'client') {\n this.options.deltaSource = newValue\n\n return this\n }\n\n return this.options.deltaSource\n }\n\n /**\n * Gets the selector context Node of the Interactable. The default is\n * `window.document`.\n *\n * @return {Node} The context Node of this Interactable\n */\n context () {\n return this._context\n }\n\n inContext (element: Document | Node) {\n return this._context === element.ownerDocument || nodeContains(this._context, element)\n }\n\n testIgnoreAllow (\n this: Interactable,\n options: { ignoreFrom?: IgnoreValue, allowFrom?: IgnoreValue },\n targetNode: Node,\n eventTarget: Node,\n ) {\n return (\n !this.testIgnore(options.ignoreFrom, targetNode, eventTarget) &&\n this.testAllow(options.allowFrom, targetNode, eventTarget)\n )\n }\n\n testAllow (this: Interactable, allowFrom: IgnoreValue, targetNode: Node, element: Node) {\n if (!allowFrom) {\n return true\n }\n\n if (!is.element(element)) {\n return false\n }\n\n if (is.string(allowFrom)) {\n return matchesUpTo(element, allowFrom, targetNode)\n } else if (is.element(allowFrom)) {\n return nodeContains(allowFrom, element)\n }\n\n return false\n }\n\n testIgnore (this: Interactable, ignoreFrom: IgnoreValue, targetNode: Node, element: Node) {\n if (!ignoreFrom || !is.element(element)) {\n return false\n }\n\n if (is.string(ignoreFrom)) {\n return matchesUpTo(element, ignoreFrom, targetNode)\n } else if (is.element(ignoreFrom)) {\n return nodeContains(ignoreFrom, element)\n }\n\n return false\n }\n\n /**\n * Calls listeners for the given InteractEvent type bound globally\n * and directly to this Interactable\n *\n * @param {InteractEvent} iEvent The InteractEvent object to be fired on this\n * Interactable\n * @return {Interactable} this Interactable\n */\n fire (iEvent: E) {\n this.events.fire(iEvent)\n\n return this\n }\n\n _onOff (method: 'on' | 'off', typeArg: EventTypes, listenerArg?: ListenersArg | null, options?: any) {\n if (is.object(typeArg) && !is.array(typeArg)) {\n options = listenerArg\n listenerArg = null\n }\n\n const addRemove = method === 'on' ? 'add' : 'remove'\n const listeners = normalizeListeners(typeArg, listenerArg)\n\n for (let type in listeners) {\n if (type === 'wheel') {\n type = browser.wheelEvent\n }\n\n for (const listener of listeners[type]) {\n // if it is an action event type\n if (isNonNativeEvent(type, this._actions)) {\n this.events[method](type, listener)\n }\n // delegated event\n else if (is.string(this.target)) {\n this._scopeEvents[`${addRemove}Delegate` as 'addDelegate' | 'removeDelegate'](\n this.target,\n this._context,\n type,\n listener,\n options,\n )\n }\n // remove listener from this Interactable's element\n else {\n this._scopeEvents[addRemove](this.target, type, listener, options)\n }\n }\n }\n\n return this\n }\n\n /**\n * Binds a listener for an InteractEvent, pointerEvent or DOM event.\n *\n * @param {string | array | object} types The types of events to listen\n * for\n * @param {function | array | object} [listener] The event listener function(s)\n * @param {object | boolean} [options] options object or useCapture flag for\n * addEventListener\n * @return {Interactable} This Interactable\n */\n on (types: EventTypes, listener?: ListenersArg, options?: any) {\n return this._onOff('on', types, listener, options)\n }\n\n /**\n * Removes an InteractEvent, pointerEvent or DOM event listener.\n *\n * @param {string | array | object} types The types of events that were\n * listened for\n * @param {function | array | object} [listener] The event listener function(s)\n * @param {object | boolean} [options] options object or useCapture flag for\n * removeEventListener\n * @return {Interactable} This Interactable\n */\n off (types: string | string[] | EventTypes, listener?: ListenersArg, options?: any) {\n return this._onOff('off', types, listener, options)\n }\n\n /**\n * Reset the options of this Interactable\n *\n * @param {object} options The new settings to apply\n * @return {object} This Interactable\n */\n set (options: OptionsArg) {\n const defaults = this._defaults\n\n if (!is.object(options)) {\n options = {}\n }\n\n ;(this.options as Required) = clone(defaults.base) as Required\n\n for (const actionName_ in this._actions.methodDict) {\n const actionName = actionName_ as ActionName\n const methodName = this._actions.methodDict[actionName]\n\n this.options[actionName] = {}\n this.setPerAction(actionName, extend(extend({}, defaults.perAction), defaults.actions[actionName]))\n ;(this[methodName] as ActionMethod)(options[actionName])\n }\n\n for (const setting in options) {\n if (is.func((this as any)[setting])) {\n ;(this as any)[setting](options[setting as keyof typeof options])\n }\n }\n\n return this\n }\n\n /**\n * Remove this interactable from the list of interactables and remove it's\n * action capabilities and event listeners\n */\n unset () {\n if (is.string(this.target)) {\n // remove delegated events\n for (const type in this._scopeEvents.delegatedEvents) {\n const delegated = this._scopeEvents.delegatedEvents[type]\n\n for (let i = delegated.length - 1; i >= 0; i--) {\n const { selector, context, listeners } = delegated[i]\n\n if (selector === this.target && context === this._context) {\n delegated.splice(i, 1)\n }\n\n for (let l = listeners.length - 1; l >= 0; l--) {\n this._scopeEvents.removeDelegate(\n this.target,\n this._context,\n type,\n listeners[l][0],\n listeners[l][1],\n )\n }\n }\n }\n } else {\n this._scopeEvents.remove(this.target as Node, 'all')\n }\n }\n}\n","import type { Interactable } from '@interactjs/core/Interactable'\nimport type { OptionsArg, Options } from '@interactjs/core/options'\nimport type { Scope } from '@interactjs/core/scope'\nimport type { Target, Context } from '@interactjs/types/index'\nimport * as arr from '@interactjs/utils/arr'\nimport * as domUtils from '@interactjs/utils/domUtils'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\n\ndeclare module '@interactjs/core/scope' {\n interface SignalArgs {\n 'interactable:new': {\n interactable: Interactable\n target: Target\n options: OptionsArg\n win: Window\n }\n }\n}\n\ninterface InteractableScopeProp {\n context: Context\n interactable: Interactable\n}\n\nexport class InteractableSet {\n // all set interactables\n list: Interactable[] = []\n\n selectorMap: {\n [selector: string]: InteractableScopeProp[]\n } = {}\n\n scope: Scope\n\n constructor (scope: Scope) {\n this.scope = scope\n scope.addListeners({\n 'interactable:unset': ({ interactable }) => {\n const { target, _context: context } = interactable\n const targetMappings: InteractableScopeProp[] = is.string(target)\n ? this.selectorMap[target]\n : (target as any)[this.scope.id]\n\n const targetIndex = arr.findIndex(targetMappings, (m) => m.context === context)\n if (targetMappings[targetIndex]) {\n // Destroying mappingInfo's context and interactable\n targetMappings[targetIndex].context = null\n targetMappings[targetIndex].interactable = null\n }\n targetMappings.splice(targetIndex, 1)\n },\n })\n }\n\n new (target: Target, options?: any): Interactable {\n options = extend(options || {}, {\n actions: this.scope.actions,\n })\n const interactable = new this.scope.Interactable(target, options, this.scope.document, this.scope.events)\n const mappingInfo = { context: interactable._context, interactable }\n\n this.scope.addDocument(interactable._doc)\n this.list.push(interactable)\n\n if (is.string(target)) {\n if (!this.selectorMap[target]) {\n this.selectorMap[target] = []\n }\n this.selectorMap[target].push(mappingInfo)\n } else {\n if (!(interactable.target as any)[this.scope.id]) {\n Object.defineProperty(target, this.scope.id, {\n value: [],\n configurable: true,\n })\n }\n\n ;(target as any)[this.scope.id].push(mappingInfo)\n }\n\n this.scope.fire('interactable:new', {\n target,\n options,\n interactable,\n win: this.scope._win,\n })\n\n return interactable\n }\n\n get (target: Target, options?: Options) {\n const context = (options && options.context) || this.scope.document\n const isSelector = is.string(target)\n const targetMappings: InteractableScopeProp[] = isSelector\n ? this.selectorMap[target as string]\n : (target as any)[this.scope.id]\n\n if (!targetMappings) {\n return null\n }\n\n const found = arr.find(\n targetMappings,\n (m) => m.context === context && (isSelector || m.interactable.inContext(target as any)),\n )\n\n return found && found.interactable\n }\n\n forEachMatch (node: Node, callback: (interactable: Interactable) => T) {\n for (const interactable of this.list) {\n let ret: void | T\n\n if (\n (is.string(interactable.target)\n ? // target is a selector and the element matches\n is.element(node) && domUtils.matchesSelector(node, interactable.target)\n : // target is the element\n node === interactable.target) &&\n // the element is in context\n interactable.inContext(node)\n ) {\n ret = callback(interactable)\n }\n\n if (ret !== undefined) {\n return ret\n }\n }\n }\n}\n","import type { Scope } from '@interactjs/core/scope'\nimport type { Element } from '@interactjs/types/index'\nimport * as arr from '@interactjs/utils/arr'\nimport * as domUtils from '@interactjs/utils/domUtils'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\nimport pExtend from '@interactjs/utils/pointerExtend'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\ndeclare module '@interactjs/core/scope' {\n interface Scope {\n events: ReturnType\n }\n}\n\ntype Listener = (event: Event | FakeEvent) => any\n\nfunction install (scope: Scope) {\n const targets: Array<{\n eventTarget: EventTarget\n events: { [type: string]: Listener[] }\n }> = []\n\n const delegatedEvents: {\n [type: string]: Array<{\n selector: string\n context: Node\n listeners: Array<[Listener, { capture: boolean, passive: boolean }]>\n }>\n } = {}\n const documents: Document[] = []\n\n const eventsMethods = {\n add,\n remove,\n\n addDelegate,\n removeDelegate,\n\n delegateListener,\n delegateUseCapture,\n delegatedEvents,\n documents,\n\n targets,\n\n supportsOptions: false,\n supportsPassive: false,\n }\n\n // check if browser supports passive events and options arg\n scope.document?.createElement('div').addEventListener('test', null, {\n get capture () {\n return (eventsMethods.supportsOptions = true)\n },\n get passive () {\n return (eventsMethods.supportsPassive = true)\n },\n })\n\n scope.events = eventsMethods\n\n function add (eventTarget: EventTarget, type: string, listener: Listener, optionalArg?: boolean | any) {\n const options = getOptions(optionalArg)\n let target = arr.find(targets, (t) => t.eventTarget === eventTarget)\n\n if (!target) {\n target = {\n eventTarget,\n events: {},\n }\n\n targets.push(target)\n }\n\n if (!target.events[type]) {\n target.events[type] = []\n }\n\n if (eventTarget.addEventListener && !arr.contains(target.events[type], listener)) {\n eventTarget.addEventListener(\n type,\n listener as any,\n eventsMethods.supportsOptions ? options : options.capture,\n )\n target.events[type].push(listener)\n }\n }\n\n function remove (\n eventTarget: EventTarget,\n type: string,\n listener?: 'all' | Listener,\n optionalArg?: boolean | any,\n ) {\n const options = getOptions(optionalArg)\n const targetIndex = arr.findIndex(targets, (t) => t.eventTarget === eventTarget)\n const target = targets[targetIndex]\n\n if (!target || !target.events) {\n return\n }\n\n if (type === 'all') {\n for (type in target.events) {\n if (target.events.hasOwnProperty(type)) {\n remove(eventTarget, type, 'all')\n }\n }\n return\n }\n\n let typeIsEmpty = false\n const typeListeners = target.events[type]\n\n if (typeListeners) {\n if (listener === 'all') {\n for (let i = typeListeners.length - 1; i >= 0; i--) {\n remove(eventTarget, type, typeListeners[i], options)\n }\n return\n } else {\n for (let i = 0; i < typeListeners.length; i++) {\n if (typeListeners[i] === listener) {\n eventTarget.removeEventListener(\n type,\n listener as any,\n eventsMethods.supportsOptions ? options : options.capture,\n )\n typeListeners.splice(i, 1)\n\n if (typeListeners.length === 0) {\n delete target.events[type]\n typeIsEmpty = true\n }\n\n break\n }\n }\n }\n }\n\n if (typeIsEmpty && !Object.keys(target.events).length) {\n targets.splice(targetIndex, 1)\n }\n }\n\n function addDelegate (selector: string, context: Node, type: string, listener: Listener, optionalArg?: any) {\n const options = getOptions(optionalArg)\n if (!delegatedEvents[type]) {\n delegatedEvents[type] = []\n\n // add delegate listener functions\n for (const doc of documents) {\n add(doc, type, delegateListener)\n add(doc, type, delegateUseCapture, true)\n }\n }\n\n const delegates = delegatedEvents[type]\n let delegate = arr.find(delegates, (d) => d.selector === selector && d.context === context)\n\n if (!delegate) {\n delegate = { selector, context, listeners: [] }\n delegates.push(delegate)\n }\n\n delegate.listeners.push([listener, options])\n }\n\n function removeDelegate (\n selector: string,\n context: Document | Element,\n type: string,\n listener?: Listener,\n optionalArg?: any,\n ) {\n const options = getOptions(optionalArg)\n const delegates = delegatedEvents[type]\n let matchFound = false\n let index: number\n\n if (!delegates) return\n\n // count from last index of delegated to 0\n for (index = delegates.length - 1; index >= 0; index--) {\n const cur = delegates[index]\n // look for matching selector and context Node\n if (cur.selector === selector && cur.context === context) {\n const { listeners } = cur\n\n // each item of the listeners array is an array: [function, capture, passive]\n for (let i = listeners.length - 1; i >= 0; i--) {\n const [fn, { capture, passive }] = listeners[i]\n\n // check if the listener functions and capture and passive flags match\n if (fn === listener && capture === options.capture && passive === options.passive) {\n // remove the listener from the array of listeners\n listeners.splice(i, 1)\n\n // if all listeners for this target have been removed\n // remove the target from the delegates array\n if (!listeners.length) {\n delegates.splice(index, 1)\n\n // remove delegate function from context\n remove(context, type, delegateListener)\n remove(context, type, delegateUseCapture, true)\n }\n\n // only remove one listener\n matchFound = true\n break\n }\n }\n\n if (matchFound) {\n break\n }\n }\n }\n }\n\n // bound to the interactable context when a DOM event\n // listener is added to a selector interactable\n function delegateListener (event: Event | FakeEvent, optionalArg?: any) {\n const options = getOptions(optionalArg)\n const fakeEvent = new FakeEvent(event as Event)\n const delegates = delegatedEvents[event.type]\n const [eventTarget] = pointerUtils.getEventTargets(event as Event)\n let element: Node = eventTarget\n\n // climb up document tree looking for selector matches\n while (is.element(element)) {\n for (let i = 0; i < delegates.length; i++) {\n const cur = delegates[i]\n const { selector, context } = cur\n\n if (\n domUtils.matchesSelector(element, selector) &&\n domUtils.nodeContains(context, eventTarget) &&\n domUtils.nodeContains(context, element)\n ) {\n const { listeners } = cur\n\n fakeEvent.currentTarget = element\n\n for (const [fn, { capture, passive }] of listeners) {\n if (capture === options.capture && passive === options.passive) {\n fn(fakeEvent)\n }\n }\n }\n }\n\n element = domUtils.parentNode(element)\n }\n }\n\n function delegateUseCapture (this: Element, event: Event | FakeEvent) {\n return delegateListener.call(this, event, true)\n }\n\n // for type inferrence\n return eventsMethods\n}\n\nclass FakeEvent implements Partial {\n currentTarget: Node\n originalEvent: Event\n type: string\n\n constructor (originalEvent: Event) {\n this.originalEvent = originalEvent\n // duplicate the event so that currentTarget can be changed\n pExtend(this, originalEvent)\n }\n\n preventOriginalDefault () {\n this.originalEvent.preventDefault()\n }\n\n stopPropagation () {\n this.originalEvent.stopPropagation()\n }\n\n stopImmediatePropagation () {\n this.originalEvent.stopImmediatePropagation()\n }\n}\n\nfunction getOptions (param: { [index: string]: any } | boolean): { capture: boolean, passive: boolean } {\n if (!is.object(param)) {\n return { capture: !!param, passive: false }\n }\n\n const options = extend({}, param) as any\n\n options.capture = !!param.capture\n options.passive = !!param.passive\n\n return options\n}\n\nexport default {\n id: 'events',\n install,\n}\n","import type Interaction from '@interactjs/core/Interaction'\nimport type { Scope } from '@interactjs/core/scope'\nimport type { PointerType } from '@interactjs/types/index'\nimport * as dom from '@interactjs/utils/domUtils'\n\nexport interface SearchDetails {\n pointer: PointerType\n pointerId: number\n pointerType: string\n eventType: string\n eventTarget: EventTarget\n curEventTarget: EventTarget\n scope: Scope\n}\n\nconst finder = {\n methodOrder: ['simulationResume', 'mouseOrPen', 'hasPointer', 'idle'] as const,\n\n search (details: SearchDetails) {\n for (const method of finder.methodOrder) {\n const interaction = finder[method](details)\n\n if (interaction) {\n return interaction\n }\n }\n\n return null\n },\n\n // try to resume simulation with a new pointer\n simulationResume ({ pointerType, eventType, eventTarget, scope }: SearchDetails) {\n if (!/down|start/i.test(eventType)) {\n return null\n }\n\n for (const interaction of scope.interactions.list) {\n let element = eventTarget as Node\n\n if (\n interaction.simulation &&\n interaction.simulation.allowResume &&\n interaction.pointerType === pointerType\n ) {\n while (element) {\n // if the element is the interaction element\n if (element === interaction.element) {\n return interaction\n }\n element = dom.parentNode(element)\n }\n }\n }\n\n return null\n },\n\n // if it's a mouse or pen interaction\n mouseOrPen ({ pointerId, pointerType, eventType, scope }: SearchDetails) {\n if (pointerType !== 'mouse' && pointerType !== 'pen') {\n return null\n }\n\n let firstNonActive\n\n for (const interaction of scope.interactions.list) {\n if (interaction.pointerType === pointerType) {\n // if it's a down event, skip interactions with running simulations\n if (interaction.simulation && !hasPointerId(interaction, pointerId)) {\n continue\n }\n\n // if the interaction is active, return it immediately\n if (interaction.interacting()) {\n return interaction\n }\n // otherwise save it and look for another active interaction\n else if (!firstNonActive) {\n firstNonActive = interaction\n }\n }\n }\n\n // if no active mouse interaction was found use the first inactive mouse\n // interaction\n if (firstNonActive) {\n return firstNonActive\n }\n\n // find any mouse or pen interaction.\n // ignore the interaction if the eventType is a *down, and a simulation\n // is active\n for (const interaction of scope.interactions.list) {\n if (interaction.pointerType === pointerType && !(/down/i.test(eventType) && interaction.simulation)) {\n return interaction\n }\n }\n\n return null\n },\n\n // get interaction that has this pointer\n hasPointer ({ pointerId, scope }: SearchDetails) {\n for (const interaction of scope.interactions.list) {\n if (hasPointerId(interaction, pointerId)) {\n return interaction\n }\n }\n\n return null\n },\n\n // get first idle interaction with a matching pointerType\n idle ({ pointerType, scope }: SearchDetails) {\n for (const interaction of scope.interactions.list) {\n // if there's already a pointer held down\n if (interaction.pointers.length === 1) {\n const target = interaction.interactable\n // don't add this pointer if there is a target interactable and it\n // isn't gesturable\n if (target && !(target.options.gesture && target.options.gesture.enabled)) {\n continue\n }\n }\n // maximum of 2 pointers per interaction\n else if (interaction.pointers.length >= 2) {\n continue\n }\n\n if (!interaction.interacting() && pointerType === interaction.pointerType) {\n return interaction\n }\n }\n\n return null\n },\n}\n\nfunction hasPointerId (interaction: Interaction, pointerId: number) {\n return interaction.pointers.some(({ id }) => id === pointerId)\n}\n\nexport default finder\n","import type { Scope, ActionName, SignalArgs, Plugin } from '@interactjs/core/scope'\nimport type { Listener } from '@interactjs/types/index'\nimport browser from '@interactjs/utils/browser'\nimport domObjects from '@interactjs/utils/domObjects'\nimport { nodeContains } from '@interactjs/utils/domUtils'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\nimport InteractionBase from './Interaction'\nimport interactablePreventDefault from './interactablePreventDefault'\nimport type { SearchDetails } from './interactionFinder'\nimport finder from './interactionFinder'\n\ndeclare module '@interactjs/core/scope' {\n interface Scope {\n Interaction: typeof InteractionBase\n interactions: {\n new: (options: any) => InteractionBase\n list: Array>\n listeners: { [type: string]: Listener }\n docEvents: Array<{ type: string, listener: Listener }>\n pointerMoveTolerance: number\n }\n prevTouchTime: number\n }\n}\n\ndeclare module '@interactjs/core/scope' {\n interface SignalArgs {\n 'interactions:find': {\n interaction: InteractionBase\n searchDetails: SearchDetails\n }\n }\n}\n\nconst methodNames = [\n 'pointerDown',\n 'pointerMove',\n 'pointerUp',\n 'updatePointer',\n 'removePointer',\n 'windowBlur',\n]\n\nfunction install (scope: Scope) {\n const listeners = {} as any\n\n for (const method of methodNames) {\n listeners[method] = doOnInteractions(method, scope)\n }\n\n const pEventTypes = browser.pEventTypes\n let docEvents: typeof scope.interactions.docEvents\n\n if (domObjects.PointerEvent) {\n docEvents = [\n { type: pEventTypes.down, listener: releasePointersOnRemovedEls },\n { type: pEventTypes.down, listener: listeners.pointerDown },\n { type: pEventTypes.move, listener: listeners.pointerMove },\n { type: pEventTypes.up, listener: listeners.pointerUp },\n { type: pEventTypes.cancel, listener: listeners.pointerUp },\n ]\n } else {\n docEvents = [\n { type: 'mousedown', listener: listeners.pointerDown },\n { type: 'mousemove', listener: listeners.pointerMove },\n { type: 'mouseup', listener: listeners.pointerUp },\n\n { type: 'touchstart', listener: releasePointersOnRemovedEls },\n { type: 'touchstart', listener: listeners.pointerDown },\n { type: 'touchmove', listener: listeners.pointerMove },\n { type: 'touchend', listener: listeners.pointerUp },\n { type: 'touchcancel', listener: listeners.pointerUp },\n ]\n }\n\n docEvents.push({\n type: 'blur',\n listener (event) {\n for (const interaction of scope.interactions.list) {\n interaction.documentBlur(event)\n }\n },\n })\n\n // for ignoring browser's simulated mouse events\n scope.prevTouchTime = 0\n\n scope.Interaction = class extends InteractionBase {\n get pointerMoveTolerance () {\n return scope.interactions.pointerMoveTolerance\n }\n\n set pointerMoveTolerance (value) {\n scope.interactions.pointerMoveTolerance = value\n }\n\n _now () {\n return scope.now()\n }\n }\n\n scope.interactions = {\n // all active and idle interactions\n list: [],\n new (options: { pointerType?: string, scopeFire?: Scope['fire'] }) {\n options.scopeFire = (name, arg) => scope.fire(name, arg)\n\n const interaction = new scope.Interaction(options as Required)\n\n scope.interactions.list.push(interaction)\n return interaction\n },\n listeners,\n docEvents,\n pointerMoveTolerance: 1,\n }\n\n function releasePointersOnRemovedEls () {\n // for all inactive touch interactions with pointers down\n for (const interaction of scope.interactions.list) {\n if (!interaction.pointerIsDown || interaction.pointerType !== 'touch' || interaction._interacting) {\n continue\n }\n\n // if a pointer is down on an element that is no longer in the DOM tree\n for (const pointer of interaction.pointers) {\n if (!scope.documents.some(({ doc }) => nodeContains(doc, pointer.downTarget))) {\n // remove the pointer from the interaction\n interaction.removePointer(pointer.pointer, pointer.event)\n }\n }\n }\n }\n\n scope.usePlugin(interactablePreventDefault)\n}\n\nfunction doOnInteractions (method: string, scope: Scope) {\n return function (event: Event) {\n const interactions = scope.interactions.list\n\n const pointerType = pointerUtils.getPointerType(event)\n const [eventTarget, curEventTarget] = pointerUtils.getEventTargets(event)\n const matches: any[] = [] // [ [pointer, interaction], ...]\n\n if (/^touch/.test(event.type)) {\n scope.prevTouchTime = scope.now()\n\n // @ts-expect-error\n for (const changedTouch of event.changedTouches) {\n const pointer = changedTouch\n const pointerId = pointerUtils.getPointerId(pointer)\n const searchDetails: SearchDetails = {\n pointer,\n pointerId,\n pointerType,\n eventType: event.type,\n eventTarget,\n curEventTarget,\n scope,\n }\n const interaction = getInteraction(searchDetails)\n\n matches.push([\n searchDetails.pointer,\n searchDetails.eventTarget,\n searchDetails.curEventTarget,\n interaction,\n ])\n }\n } else {\n let invalidPointer = false\n\n if (!browser.supportsPointerEvent && /mouse/.test(event.type)) {\n // ignore mouse events while touch interactions are active\n for (let i = 0; i < interactions.length && !invalidPointer; i++) {\n invalidPointer = interactions[i].pointerType !== 'mouse' && interactions[i].pointerIsDown\n }\n\n // try to ignore mouse events that are simulated by the browser\n // after a touch event\n invalidPointer =\n invalidPointer ||\n scope.now() - scope.prevTouchTime < 500 ||\n // on iOS and Firefox Mobile, MouseEvent.timeStamp is zero if simulated\n event.timeStamp === 0\n }\n\n if (!invalidPointer) {\n const searchDetails = {\n pointer: event as PointerEvent,\n pointerId: pointerUtils.getPointerId(event as PointerEvent),\n pointerType,\n eventType: event.type,\n curEventTarget,\n eventTarget,\n scope,\n }\n\n const interaction = getInteraction(searchDetails)\n\n matches.push([\n searchDetails.pointer,\n searchDetails.eventTarget,\n searchDetails.curEventTarget,\n interaction,\n ])\n }\n }\n\n // eslint-disable-next-line no-shadow\n for (const [pointer, eventTarget, curEventTarget, interaction] of matches) {\n interaction[method](pointer, event, eventTarget, curEventTarget)\n }\n }\n}\n\nfunction getInteraction (searchDetails: SearchDetails) {\n const { pointerType, scope } = searchDetails\n\n const foundInteraction = finder.search(searchDetails)\n const signalArg = { interaction: foundInteraction, searchDetails }\n\n scope.fire('interactions:find', signalArg)\n\n return signalArg.interaction || scope.interactions.new({ pointerType })\n}\n\nfunction onDocSignal (\n { doc, scope, options }: SignalArgs[T],\n eventMethodName: 'add' | 'remove',\n) {\n const {\n interactions: { docEvents },\n events,\n } = scope\n const eventMethod = events[eventMethodName]\n\n if (scope.browser.isIOS && !options.events) {\n options.events = { passive: false }\n }\n\n // delegate event listener\n for (const eventType in events.delegatedEvents) {\n eventMethod(doc, eventType, events.delegateListener)\n eventMethod(doc, eventType, events.delegateUseCapture, true)\n }\n\n const eventOptions = options && options.events\n\n for (const { type, listener } of docEvents) {\n eventMethod(doc, type, listener, eventOptions)\n }\n}\n\nconst interactions: Plugin = {\n id: 'core/interactions',\n install,\n listeners: {\n 'scope:add-document': (arg) => onDocSignal(arg, 'add'),\n 'scope:remove-document': (arg) => onDocSignal(arg, 'remove'),\n 'interactable:unset': ({ interactable }, scope) => {\n // Stop and destroy related interactions when an Interactable is unset\n for (let i = scope.interactions.list.length - 1; i >= 0; i--) {\n const interaction = scope.interactions.list[i]\n\n if (interaction.interactable !== interactable) {\n continue\n }\n\n interaction.stop()\n scope.fire('interactions:destroy', { interaction })\n interaction.destroy()\n\n if (scope.interactions.list.length > 2) {\n scope.interactions.list.splice(i, 1)\n }\n }\n },\n },\n onDocSignal,\n doOnInteractions,\n methodNames,\n}\n\nexport default interactions\n","import type Interaction from '@interactjs/core/Interaction'\nimport browser from '@interactjs/utils/browser'\nimport clone from '@interactjs/utils/clone'\nimport domObjects from '@interactjs/utils/domObjects'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\nimport raf from '@interactjs/utils/raf'\nimport * as win from '@interactjs/utils/window'\n\nimport { Eventable } from './Eventable'\nimport type { PhaseMap } from './InteractEvent'\nimport { InteractEvent } from './InteractEvent'\nimport { createInteractStatic } from './InteractStatic'\nimport type { Interactable } from './Interactable'\nimport { Interactable as InteractableBase } from './Interactable'\nimport { InteractableSet } from './InteractableSet'\nimport events from './events'\nimport interactions from './interactions'\nimport type { OptionsArg } from './options'\nimport { defaults } from './options'\n\nexport interface SignalArgs {\n 'scope:add-document': DocSignalArg\n 'scope:remove-document': DocSignalArg\n 'interactable:unset': { interactable: InteractableBase }\n 'interactable:set': { interactable: InteractableBase, options: OptionsArg }\n 'interactions:destroy': { interaction: Interaction }\n}\n\nexport type ListenerName = keyof SignalArgs\n\nexport type ListenerMap = {\n [P in ListenerName]?: (arg: SignalArgs[P], scope: Scope, signalName: P) => void | boolean\n}\n\ninterface DocSignalArg {\n doc: Document\n window: Window\n scope: Scope\n options: Record\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-interface\nexport interface ActionMap {}\nexport type ActionName = keyof ActionMap\n\nexport interface Actions {\n map: ActionMap\n phases: PhaseMap\n methodDict: { [P in ActionName]?: keyof Interactable }\n phaselessTypes: { [type: string]: true }\n}\n\nexport interface Plugin {\n [key: string]: any\n id?: string\n listeners?: ListenerMap\n before?: string[]\n install?(scope: Scope, options?: any): void\n}\n\nexport class Scope {\n id = `__interact_scope_${Math.floor(Math.random() * 100)}`\n isInitialized = false\n listenerMaps: Array<{\n map: ListenerMap\n id: string\n }> = []\n\n browser = browser\n defaults = clone(defaults) as typeof defaults\n Eventable = Eventable\n actions: Actions = {\n map: {},\n phases: {\n start: true,\n move: true,\n end: true,\n },\n methodDict: {},\n phaselessTypes: {},\n }\n\n interactStatic = createInteractStatic(this)\n InteractEvent = InteractEvent\n Interactable: typeof InteractableBase\n interactables = new InteractableSet(this)\n\n // main window\n _win!: Window\n\n // main document\n document!: Document\n\n // main window\n window!: Window\n\n // all documents being listened to\n documents: Array<{ doc: Document, options: any }> = []\n\n _plugins: {\n list: Plugin[]\n map: { [id: string]: Plugin }\n } = {\n list: [],\n map: {},\n }\n\n constructor () {\n const scope = this\n\n this.Interactable = class extends InteractableBase {\n get _defaults () {\n return scope.defaults\n }\n\n set (this: T, options: OptionsArg) {\n super.set(options)\n\n scope.fire('interactable:set', {\n options,\n interactable: this,\n })\n\n return this\n }\n\n unset (this: InteractableBase) {\n super.unset()\n scope.interactables.list.splice(scope.interactables.list.indexOf(this), 1)\n\n scope.fire('interactable:unset', { interactable: this })\n }\n }\n }\n\n addListeners (map: ListenerMap, id?: string) {\n this.listenerMaps.push({ id, map })\n }\n\n fire (name: T, arg: SignalArgs[T]): void | false {\n for (const {\n map: { [name]: listener },\n } of this.listenerMaps) {\n if (!!listener && listener(arg as any, this, name as never) === false) {\n return false\n }\n }\n }\n\n onWindowUnload = (event: BeforeUnloadEvent) => this.removeDocument(event.target as Document)\n\n init (window: Window | typeof globalThis) {\n return this.isInitialized ? this : initScope(this, window)\n }\n\n pluginIsInstalled (plugin: Plugin) {\n return this._plugins.map[plugin.id] || this._plugins.list.indexOf(plugin) !== -1\n }\n\n usePlugin (plugin: Plugin, options?: { [key: string]: any }) {\n if (!this.isInitialized) {\n return this\n }\n\n if (this.pluginIsInstalled(plugin)) {\n return this\n }\n\n if (plugin.id) {\n this._plugins.map[plugin.id] = plugin\n }\n this._plugins.list.push(plugin)\n\n if (plugin.install) {\n plugin.install(this, options)\n }\n\n if (plugin.listeners && plugin.before) {\n let index = 0\n const len = this.listenerMaps.length\n const before = plugin.before.reduce((acc, id) => {\n acc[id] = true\n acc[pluginIdRoot(id)] = true\n return acc\n }, {})\n\n for (; index < len; index++) {\n const otherId = this.listenerMaps[index].id\n\n if (before[otherId] || before[pluginIdRoot(otherId)]) {\n break\n }\n }\n\n this.listenerMaps.splice(index, 0, { id: plugin.id, map: plugin.listeners })\n } else if (plugin.listeners) {\n this.listenerMaps.push({ id: plugin.id, map: plugin.listeners })\n }\n\n return this\n }\n\n addDocument (doc: Document, options?: any): void | false {\n // do nothing if document is already known\n if (this.getDocIndex(doc) !== -1) {\n return false\n }\n\n const window = win.getWindow(doc)\n\n options = options ? extend({}, options) : {}\n\n this.documents.push({ doc, options })\n this.events.documents.push(doc)\n\n // don't add an unload event for the main document\n // so that the page may be cached in browser history\n if (doc !== this.document) {\n this.events.add(window, 'unload', this.onWindowUnload)\n }\n\n this.fire('scope:add-document', { doc, window, scope: this, options })\n }\n\n removeDocument (doc: Document) {\n const index = this.getDocIndex(doc)\n\n const window = win.getWindow(doc)\n const options = this.documents[index].options\n\n this.events.remove(window, 'unload', this.onWindowUnload)\n\n this.documents.splice(index, 1)\n this.events.documents.splice(index, 1)\n\n this.fire('scope:remove-document', { doc, window, scope: this, options })\n }\n\n getDocIndex (doc: Document) {\n for (let i = 0; i < this.documents.length; i++) {\n if (this.documents[i].doc === doc) {\n return i\n }\n }\n\n return -1\n }\n\n getDocOptions (doc: Document) {\n const docIndex = this.getDocIndex(doc)\n\n return docIndex === -1 ? null : this.documents[docIndex].options\n }\n\n now () {\n return (((this.window as any).Date as typeof Date) || Date).now()\n }\n}\n\nexport function initScope (scope: Scope, window: Window | typeof globalThis) {\n scope.isInitialized = true\n\n if (is.window(window)) {\n win.init(window)\n }\n\n domObjects.init(window)\n browser.init(window)\n raf.init(window)\n\n // @ts-expect-error\n scope.window = window\n scope.document = window.document\n\n scope.usePlugin(interactions)\n scope.usePlugin(events)\n\n return scope\n}\n\nfunction pluginIdRoot (id: string) {\n return id && id.replace(/\\/.*$/, '')\n}\n","import { Scope } from '@interactjs/core/scope'\n\nconst scope = new Scope()\n\nconst interact = scope.interactStatic\n\nexport default interact\n\nconst _global = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : this\nscope.init(_global)\n","export default () => {}\n","export default () => {}\n","import type { SnapFunction, SnapTarget } from '@interactjs/modifiers/snap/pointer'\nimport type { Rect, Point } from '@interactjs/types/index'\n\nexport type GridOptions = (Partial | Point) & {\n range?: number\n limits?: Rect\n offset?: Point\n}\n\nexport default (grid: GridOptions) => {\n const coordFields = ([\n ['x', 'y'],\n ['left', 'top'],\n ['right', 'bottom'],\n ['width', 'height'],\n ] as const).filter(([xField, yField]) => xField in grid || yField in grid)\n\n const gridFunc: SnapFunction & {\n grid: typeof grid\n coordFields: typeof coordFields\n } = (x, y) => {\n const {\n range,\n limits = {\n left: -Infinity,\n right: Infinity,\n top: -Infinity,\n bottom: Infinity,\n },\n offset = { x: 0, y: 0 },\n } = grid\n\n const result: SnapTarget & {\n grid: typeof grid\n } = { range, grid, x: null as number, y: null as number }\n\n for (const [xField, yField] of coordFields) {\n const gridx = Math.round((x - offset.x) / (grid as any)[xField])\n const gridy = Math.round((y - offset.y) / (grid as any)[yField])\n\n result[xField] = Math.max(limits.left, Math.min(limits.right, gridx * (grid as any)[xField] + offset.x))\n result[yField] = Math.max(limits.top, Math.min(limits.bottom, gridy * (grid as any)[yField] + offset.y))\n }\n\n return result\n }\n\n gridFunc.grid = grid\n gridFunc.coordFields = coordFields\n\n return gridFunc\n}\n","import type { Plugin } from '@interactjs/core/scope'\nimport extend from '@interactjs/utils/extend'\n\nimport * as allSnappers from './all'\n\ndeclare module '@interactjs/core/InteractStatic' {\n export interface InteractStatic {\n snappers: typeof allSnappers\n createSnapGrid: typeof allSnappers.grid\n }\n}\n\nconst snappersPlugin: Plugin = {\n id: 'snappers',\n install (scope) {\n const { interactStatic: interact } = scope\n\n interact.snappers = extend(interact.snappers || {}, allSnappers)\n interact.createSnapGrid = interact.snappers.grid\n },\n}\n\nexport default snappersPlugin\n","/**\n * @module modifiers/aspectRatio\n *\n * @description\n * This module forces elements to be resized with a specified dx/dy ratio.\n *\n * ```js\n * interact(target).resizable({\n * modifiers: [\n * interact.modifiers.snapSize({\n * targets: [ interact.snappers.grid({ x: 20, y: 20 }) ],\n * }),\n * interact.aspectRatio({ ratio: 'preserve' }),\n * ],\n * });\n * ```\n */\n\nimport type { Point, Rect, EdgeOptions } from '@interactjs/types/index'\nimport extend from '@interactjs/utils/extend'\nimport { addEdges } from '@interactjs/utils/rect'\n\nimport Modification from './Modification'\nimport type { Modifier, ModifierModule, ModifierState } from './base'\nimport { makeModifier } from './base'\n\nexport interface AspectRatioOptions {\n ratio?: number | 'preserve'\n equalDelta?: boolean\n modifiers?: Modifier[]\n enabled?: boolean\n}\n\nexport type AspectRatioState = ModifierState<\nAspectRatioOptions,\n{\n startCoords: Point\n startRect: Rect\n linkedEdges: EdgeOptions\n ratio: number\n equalDelta: boolean\n xIsPrimaryAxis: boolean\n edgeSign: 1 | -1\n subModification: Modification\n}\n>\n\nconst aspectRatio: ModifierModule = {\n start (arg) {\n const { state, rect, edges: originalEdges, pageCoords: coords } = arg\n let { ratio } = state.options\n const { equalDelta, modifiers } = state.options\n\n if (ratio === 'preserve') {\n ratio = rect.width / rect.height\n }\n\n state.startCoords = extend({}, coords)\n state.startRect = extend({}, rect)\n state.ratio = ratio\n state.equalDelta = equalDelta\n\n const linkedEdges = (state.linkedEdges = {\n top: originalEdges.top || (originalEdges.left && !originalEdges.bottom),\n left: originalEdges.left || (originalEdges.top && !originalEdges.right),\n bottom: originalEdges.bottom || (originalEdges.right && !originalEdges.top),\n right: originalEdges.right || (originalEdges.bottom && !originalEdges.left),\n })\n\n state.xIsPrimaryAxis = !!(originalEdges.left || originalEdges.right)\n\n if (state.equalDelta) {\n state.edgeSign = ((linkedEdges.left ? 1 : -1) * (linkedEdges.top ? 1 : -1)) as 1 | -1\n } else {\n const negativeSecondaryEdge = state.xIsPrimaryAxis ? linkedEdges.top : linkedEdges.left\n state.edgeSign = negativeSecondaryEdge ? -1 : 1\n }\n\n extend(arg.edges, linkedEdges)\n\n if (!modifiers || !modifiers.length) return\n\n const subModification = new Modification(arg.interaction)\n\n subModification.copyFrom(arg.interaction.modification)\n subModification.prepareStates(modifiers)\n\n state.subModification = subModification\n subModification.startAll({ ...arg })\n },\n\n set (arg) {\n const { state, rect, coords } = arg\n const initialCoords = extend({}, coords)\n const aspectMethod = state.equalDelta ? setEqualDelta : setRatio\n\n aspectMethod(state, state.xIsPrimaryAxis, coords, rect)\n\n if (!state.subModification) {\n return null\n }\n\n const correctedRect = extend({}, rect)\n\n addEdges(state.linkedEdges, correctedRect, {\n x: coords.x - initialCoords.x,\n y: coords.y - initialCoords.y,\n })\n\n const result = state.subModification.setAll({\n ...arg,\n rect: correctedRect,\n edges: state.linkedEdges,\n pageCoords: coords,\n prevCoords: coords,\n prevRect: correctedRect,\n })\n\n const { delta } = result\n\n if (result.changed) {\n const xIsCriticalAxis = Math.abs(delta.x) > Math.abs(delta.y)\n\n // do aspect modification again with critical edge axis as primary\n aspectMethod(state, xIsCriticalAxis, result.coords, result.rect)\n extend(coords, result.coords)\n }\n\n return result.eventProps\n },\n\n defaults: {\n ratio: 'preserve',\n equalDelta: false,\n modifiers: [],\n enabled: false,\n },\n}\n\nfunction setEqualDelta ({ startCoords, edgeSign }: AspectRatioState, xIsPrimaryAxis: boolean, coords: Point) {\n if (xIsPrimaryAxis) {\n coords.y = startCoords.y + (coords.x - startCoords.x) * edgeSign\n } else {\n coords.x = startCoords.x + (coords.y - startCoords.y) * edgeSign\n }\n}\n\nfunction setRatio (\n { startRect, startCoords, ratio, edgeSign }: AspectRatioState,\n xIsPrimaryAxis: boolean,\n coords: Point,\n rect: Rect,\n) {\n if (xIsPrimaryAxis) {\n const newHeight = rect.width / ratio\n\n coords.y = startCoords.y + (newHeight - startRect.height) * edgeSign\n } else {\n const newWidth = rect.height * ratio\n\n coords.x = startCoords.x + (newWidth - startRect.width) * edgeSign\n }\n}\n\nexport default makeModifier(aspectRatio, 'aspectRatio')\nexport { aspectRatio }\n","import type { ModifierFunction } from '@interactjs/modifiers/base'\n\nconst noop = ((() => {}) as unknown) as ModifierFunction\n\nnoop._defaults = {}\n\nexport default noop\n","import type Interaction from '@interactjs/core/Interaction'\nimport type { RectResolvable, Rect, Point } from '@interactjs/types/index'\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\nimport * as rectUtils from '@interactjs/utils/rect'\n\nimport type { ModifierArg, ModifierModule, ModifierState } from '../base'\nimport { makeModifier } from '../base'\n\nexport interface RestrictOptions {\n // where to drag over\n restriction: RectResolvable<[number, number, Interaction]>\n // what part of self is allowed to drag over\n elementRect: Rect\n offset: Rect\n // restrict just before the end drag\n endOnly: boolean\n enabled?: boolean\n}\n\nexport type RestrictState = ModifierState<\nRestrictOptions,\n{\n offset: Rect\n}\n>\n\nfunction start ({ rect, startOffset, state, interaction, pageCoords }: ModifierArg) {\n const { options } = state\n const { elementRect } = options\n const offset: Rect = extend(\n {\n left: 0,\n top: 0,\n right: 0,\n bottom: 0,\n },\n options.offset || {},\n )\n\n if (rect && elementRect) {\n const restriction = getRestrictionRect(options.restriction, interaction, pageCoords)\n\n if (restriction) {\n const widthDiff = restriction.right - restriction.left - rect.width\n const heightDiff = restriction.bottom - restriction.top - rect.height\n\n if (widthDiff < 0) {\n offset.left += widthDiff\n offset.right += widthDiff\n }\n if (heightDiff < 0) {\n offset.top += heightDiff\n offset.bottom += heightDiff\n }\n }\n\n offset.left += startOffset.left - rect.width * elementRect.left\n offset.top += startOffset.top - rect.height * elementRect.top\n\n offset.right += startOffset.right - rect.width * (1 - elementRect.right)\n offset.bottom += startOffset.bottom - rect.height * (1 - elementRect.bottom)\n }\n\n state.offset = offset\n}\n\nfunction set ({ coords, interaction, state }: ModifierArg) {\n const { options, offset } = state\n\n const restriction = getRestrictionRect(options.restriction, interaction, coords)\n\n if (!restriction) return\n\n const rect = rectUtils.xywhToTlbr(restriction)\n\n coords.x = Math.max(Math.min(rect.right - offset.right, coords.x), rect.left + offset.left)\n coords.y = Math.max(Math.min(rect.bottom - offset.bottom, coords.y), rect.top + offset.top)\n}\n\nexport function getRestrictionRect (\n value: RectResolvable<[number, number, Interaction]>,\n interaction: Interaction,\n coords?: Point,\n) {\n if (is.func(value)) {\n return rectUtils.resolveRectLike(value, interaction.interactable, interaction.element, [\n coords.x,\n coords.y,\n interaction,\n ])\n } else {\n return rectUtils.resolveRectLike(value, interaction.interactable, interaction.element)\n }\n}\n\nconst defaults: RestrictOptions = {\n restriction: null,\n elementRect: null,\n offset: null,\n endOnly: false,\n enabled: false,\n}\n\nconst restrict: ModifierModule = {\n start,\n set,\n defaults,\n}\n\nexport default makeModifier(restrict, 'restrict')\nexport { restrict }\n","// This module adds the options.resize.restrictEdges setting which sets min and\n// max for the top, left, bottom and right edges of the target being resized.\n//\n// interact(target).resize({\n// edges: { top: true, left: true },\n// restrictEdges: {\n// inner: { top: 200, left: 200, right: 400, bottom: 400 },\n// outer: { top: 0, left: 0, right: 600, bottom: 600 },\n// },\n// })\n\nimport type { Point, Rect } from '@interactjs/types/index'\nimport extend from '@interactjs/utils/extend'\nimport * as rectUtils from '@interactjs/utils/rect'\n\nimport type { ModifierArg, ModifierState } from '../base'\nimport { makeModifier } from '../base'\n\nimport type { RestrictOptions } from './pointer'\nimport { getRestrictionRect } from './pointer'\n\nexport interface RestrictEdgesOptions {\n inner: RestrictOptions['restriction']\n outer: RestrictOptions['restriction']\n offset?: RestrictOptions['offset']\n endOnly: boolean\n enabled?: boolean\n}\n\nexport type RestrictEdgesState = ModifierState<\nRestrictEdgesOptions,\n{\n inner: Rect\n outer: Rect\n offset: RestrictEdgesOptions['offset']\n}\n>\n\nconst noInner = { top: +Infinity, left: +Infinity, bottom: -Infinity, right: -Infinity }\nconst noOuter = { top: -Infinity, left: -Infinity, bottom: +Infinity, right: +Infinity }\n\nfunction start ({ interaction, startOffset, state }: ModifierArg) {\n const { options } = state\n let offset: Point\n\n if (options) {\n const offsetRect = getRestrictionRect(options.offset, interaction, interaction.coords.start.page)\n\n offset = rectUtils.rectToXY(offsetRect)\n }\n\n offset = offset || { x: 0, y: 0 }\n\n state.offset = {\n top: offset.y + startOffset.top,\n left: offset.x + startOffset.left,\n bottom: offset.y - startOffset.bottom,\n right: offset.x - startOffset.right,\n }\n}\n\nfunction set ({ coords, edges, interaction, state }: ModifierArg) {\n const { offset, options } = state\n\n if (!edges) {\n return\n }\n\n const page = extend({}, coords)\n const inner = getRestrictionRect(options.inner, interaction, page) || ({} as Rect)\n const outer = getRestrictionRect(options.outer, interaction, page) || ({} as Rect)\n\n fixRect(inner, noInner)\n fixRect(outer, noOuter)\n\n if (edges.top) {\n coords.y = Math.min(Math.max(outer.top + offset.top, page.y), inner.top + offset.top)\n } else if (edges.bottom) {\n coords.y = Math.max(Math.min(outer.bottom + offset.bottom, page.y), inner.bottom + offset.bottom)\n }\n if (edges.left) {\n coords.x = Math.min(Math.max(outer.left + offset.left, page.x), inner.left + offset.left)\n } else if (edges.right) {\n coords.x = Math.max(Math.min(outer.right + offset.right, page.x), inner.right + offset.right)\n }\n}\n\nfunction fixRect (rect: Rect, defaults: Rect) {\n for (const edge of ['top', 'left', 'bottom', 'right']) {\n if (!(edge in rect)) {\n rect[edge] = defaults[edge]\n }\n }\n\n return rect\n}\n\nconst defaults: RestrictEdgesOptions = {\n inner: null,\n outer: null,\n offset: null,\n endOnly: false,\n enabled: false,\n}\n\nconst restrictEdges = {\n noInner,\n noOuter,\n start,\n set,\n defaults,\n}\n\nexport default makeModifier(restrictEdges, 'restrictEdges')\nexport { restrictEdges }\n","import extend from '@interactjs/utils/extend'\n\nimport { makeModifier } from '../base'\n\nimport { restrict } from './pointer'\n\nconst defaults = extend(\n {\n get elementRect () {\n return { top: 0, left: 0, bottom: 1, right: 1 }\n },\n set elementRect (_) {},\n },\n restrict.defaults,\n)\n\nconst restrictRect = {\n start: restrict.start,\n set: restrict.set,\n defaults,\n}\n\nexport default makeModifier(restrictRect, 'restrictRect')\nexport { restrictRect }\n","import type { Point, Rect, Size } from '@interactjs/types/index'\nimport extend from '@interactjs/utils/extend'\nimport * as rectUtils from '@interactjs/utils/rect'\n\nimport type { ModifierArg, ModifierState } from '../base'\nimport { makeModifier } from '../base'\n\nimport type { RestrictEdgesState } from './edges'\nimport { restrictEdges } from './edges'\nimport type { RestrictOptions } from './pointer'\nimport { getRestrictionRect } from './pointer'\n\nconst noMin = { width: -Infinity, height: -Infinity }\nconst noMax = { width: +Infinity, height: +Infinity }\n\nexport interface RestrictSizeOptions {\n min?: Size | Point | RestrictOptions['restriction']\n max?: Size | Point | RestrictOptions['restriction']\n endOnly: boolean\n enabled?: boolean\n}\n\nfunction start (arg: ModifierArg) {\n return restrictEdges.start(arg)\n}\n\nexport type RestrictSizeState = RestrictEdgesState &\nModifierState<\nRestrictSizeOptions & { inner: Rect, outer: Rect },\n{\n min: Rect\n max: Rect\n}\n>\n\nfunction set (arg: ModifierArg) {\n const { interaction, state, rect, edges } = arg\n const { options } = state\n\n if (!edges) {\n return\n }\n\n const minSize =\n rectUtils.tlbrToXywh(getRestrictionRect(options.min as any, interaction, arg.coords)) || noMin\n const maxSize =\n rectUtils.tlbrToXywh(getRestrictionRect(options.max as any, interaction, arg.coords)) || noMax\n\n state.options = {\n endOnly: options.endOnly,\n inner: extend({}, restrictEdges.noInner),\n outer: extend({}, restrictEdges.noOuter),\n }\n\n if (edges.top) {\n state.options.inner.top = rect.bottom - minSize.height\n state.options.outer.top = rect.bottom - maxSize.height\n } else if (edges.bottom) {\n state.options.inner.bottom = rect.top + minSize.height\n state.options.outer.bottom = rect.top + maxSize.height\n }\n if (edges.left) {\n state.options.inner.left = rect.right - minSize.width\n state.options.outer.left = rect.right - maxSize.width\n } else if (edges.right) {\n state.options.inner.right = rect.left + minSize.width\n state.options.outer.right = rect.left + maxSize.width\n }\n\n restrictEdges.set(arg)\n\n state.options = options\n}\n\nconst defaults: RestrictSizeOptions = {\n min: null,\n max: null,\n endOnly: false,\n enabled: false,\n}\n\nconst restrictSize = {\n start,\n set,\n defaults,\n}\n\nexport default makeModifier(restrictSize, 'restrictSize')\nexport { restrictSize }\n","import type { Interaction, InteractionProxy } from '@interactjs/core/Interaction'\nimport type { ActionName } from '@interactjs/core/scope'\nimport type { Point, RectResolvable, Element } from '@interactjs/types/index'\nimport extend from '@interactjs/utils/extend'\nimport getOriginXY from '@interactjs/utils/getOriginXY'\nimport hypot from '@interactjs/utils/hypot'\nimport is from '@interactjs/utils/is'\nimport { resolveRectLike, rectToXY } from '@interactjs/utils/rect'\n\nimport type { ModifierArg, ModifierState } from '../base'\nimport { makeModifier } from '../base'\n\nexport interface Offset {\n x: number\n y: number\n index: number\n relativePoint?: Point | null\n}\n\nexport interface SnapPosition {\n x?: number\n y?: number\n range?: number\n offset?: Offset\n [index: string]: any\n}\n\nexport type SnapFunction = (\n x: number,\n y: number,\n interaction: InteractionProxy,\n offset: Offset,\n index: number,\n) => SnapPosition\nexport type SnapTarget = SnapPosition | SnapFunction\nexport interface SnapOptions {\n targets: SnapTarget[] | null\n // target range\n range: number\n // self points for snapping. [0,0] = top left, [1,1] = bottom right\n relativePoints: Point[] | null\n // startCoords = offset snapping from drag start page position\n offset: Point | RectResolvable<[Interaction]> | 'startCoords' | null\n offsetWithOrigin?: boolean\n origin: RectResolvable<[Element]> | Point | null\n endOnly?: boolean\n enabled?: boolean\n}\n\nexport type SnapState = ModifierState<\nSnapOptions,\n{\n offsets?: Offset[]\n closest?: any\n targetFields?: string[][]\n}\n>\n\nfunction start (arg: ModifierArg) {\n const { interaction, interactable, element, rect, state, startOffset } = arg\n const { options } = state\n const origin = options.offsetWithOrigin ? getOrigin(arg) : { x: 0, y: 0 }\n\n let snapOffset: Point\n\n if (options.offset === 'startCoords') {\n snapOffset = {\n x: interaction.coords.start.page.x,\n y: interaction.coords.start.page.y,\n }\n } else {\n const offsetRect = resolveRectLike(options.offset as any, interactable, element, [interaction])\n\n snapOffset = rectToXY(offsetRect) || { x: 0, y: 0 }\n snapOffset.x += origin.x\n snapOffset.y += origin.y\n }\n\n const { relativePoints } = options\n\n state.offsets =\n rect && relativePoints && relativePoints.length\n ? relativePoints.map((relativePoint, index) => ({\n index,\n relativePoint,\n x: startOffset.left - rect.width * relativePoint.x + snapOffset.x,\n y: startOffset.top - rect.height * relativePoint.y + snapOffset.y,\n }))\n : [\n {\n index: 0,\n relativePoint: null,\n x: snapOffset.x,\n y: snapOffset.y,\n },\n ]\n}\n\nfunction set (arg: ModifierArg) {\n const { interaction, coords, state } = arg\n const { options, offsets } = state\n\n const origin = getOriginXY(interaction.interactable, interaction.element, interaction.prepared.name)\n const page = extend({}, coords)\n const targets = []\n\n if (!options.offsetWithOrigin) {\n page.x -= origin.x\n page.y -= origin.y\n }\n\n for (const offset of offsets) {\n const relativeX = page.x - offset.x\n const relativeY = page.y - offset.y\n\n for (let index = 0, len = options.targets.length; index < len; index++) {\n const snapTarget = options.targets[index]\n let target: SnapPosition\n\n if (is.func(snapTarget)) {\n target = snapTarget(relativeX, relativeY, interaction._proxy, offset, index)\n } else {\n target = snapTarget\n }\n\n if (!target) {\n continue\n }\n\n targets.push({\n x: (is.number(target.x) ? target.x : relativeX) + offset.x,\n y: (is.number(target.y) ? target.y : relativeY) + offset.y,\n\n range: is.number(target.range) ? target.range : options.range,\n source: snapTarget,\n index,\n offset,\n })\n }\n }\n\n const closest = {\n target: null,\n inRange: false,\n distance: 0,\n range: 0,\n delta: { x: 0, y: 0 },\n }\n\n for (const target of targets) {\n const range = target.range\n const dx = target.x - page.x\n const dy = target.y - page.y\n const distance = hypot(dx, dy)\n let inRange = distance <= range\n\n // Infinite targets count as being out of range\n // compared to non infinite ones that are in range\n if (range === Infinity && closest.inRange && closest.range !== Infinity) {\n inRange = false\n }\n\n if (\n !closest.target ||\n (inRange\n ? // is the closest target in range?\n closest.inRange && range !== Infinity\n ? // the pointer is relatively deeper in this target\n distance / range < closest.distance / closest.range\n : // this target has Infinite range and the closest doesn't\n (range === Infinity && closest.range !== Infinity) ||\n // OR this target is closer that the previous closest\n distance < closest.distance\n : // The other is not in range and the pointer is closer to this target\n !closest.inRange && distance < closest.distance)\n ) {\n closest.target = target\n closest.distance = distance\n closest.range = range\n closest.inRange = inRange\n closest.delta.x = dx\n closest.delta.y = dy\n }\n }\n\n if (closest.inRange) {\n coords.x = closest.target.x\n coords.y = closest.target.y\n }\n\n state.closest = closest\n return closest\n}\n\nfunction getOrigin (arg: Partial>) {\n const { element } = arg.interaction\n const optionsOrigin = rectToXY(resolveRectLike(arg.state.options.origin as any, null, null, [element]))\n const origin = optionsOrigin || getOriginXY(arg.interactable, element, arg.interaction.prepared.name)\n\n return origin\n}\n\nconst defaults: SnapOptions = {\n range: Infinity,\n targets: null,\n offset: null,\n offsetWithOrigin: true,\n origin: null,\n relativePoints: null,\n endOnly: false,\n enabled: false,\n}\nconst snap = {\n start,\n set,\n defaults,\n}\n\nexport default makeModifier(snap, 'snap')\nexport { snap }\n","// This module allows snapping of the size of targets during resize\n// interactions.\n\nimport extend from '@interactjs/utils/extend'\nimport is from '@interactjs/utils/is'\n\nimport type { ModifierArg } from '../base'\nimport { makeModifier } from '../base'\n\nimport type { SnapOptions, SnapState } from './pointer'\nimport { snap } from './pointer'\n\nexport type SnapSizeOptions = Pick\n\nfunction start (arg: ModifierArg) {\n const { state, edges } = arg\n const { options } = state\n\n if (!edges) {\n return null\n }\n\n arg.state = {\n options: {\n targets: null,\n relativePoints: [\n {\n x: edges.left ? 0 : 1,\n y: edges.top ? 0 : 1,\n },\n ],\n offset: options.offset || 'self',\n origin: { x: 0, y: 0 },\n range: options.range,\n },\n }\n\n state.targetFields = state.targetFields || [\n ['width', 'height'],\n ['x', 'y'],\n ]\n\n snap.start(arg)\n state.offsets = arg.state.offsets\n\n arg.state = state\n}\n\nfunction set (arg) {\n const { interaction, state, coords } = arg\n const { options, offsets } = state\n const relative = {\n x: coords.x - offsets[0].x,\n y: coords.y - offsets[0].y,\n }\n\n state.options = extend({}, options)\n state.options.targets = []\n\n for (const snapTarget of options.targets || []) {\n let target\n\n if (is.func(snapTarget)) {\n target = snapTarget(relative.x, relative.y, interaction)\n } else {\n target = snapTarget\n }\n\n if (!target) {\n continue\n }\n\n for (const [xField, yField] of state.targetFields) {\n if (xField in target || yField in target) {\n target.x = target[xField]\n target.y = target[yField]\n\n break\n }\n }\n\n state.options.targets.push(target)\n }\n\n const returnValue = snap.set(arg)\n\n state.options = options\n\n return returnValue\n}\n\nconst defaults: SnapSizeOptions = {\n range: Infinity,\n targets: null,\n offset: null,\n endOnly: false,\n enabled: false,\n}\n\nconst snapSize = {\n start,\n set,\n defaults,\n}\n\nexport default makeModifier(snapSize, 'snapSize')\nexport { snapSize }\n","/**\n * @module modifiers/snapEdges\n *\n * @description\n * WOW> This module allows snapping of the edges of targets during resize\n * interactions.\n *\n * ```js\n * interact(target).resizable({\n * snapEdges: {\n * targets: [interact.snappers.grid({ x: 100, y: 50 })],\n * },\n * })\n *\n * interact(target).resizable({\n * snapEdges: {\n * targets: [\n * interact.snappers.grid({\n * top: 50,\n * left: 50,\n * bottom: 100,\n * right: 100,\n * }),\n * ],\n * },\n * })\n * ```\n */\n\nimport clone from '@interactjs/utils/clone'\nimport extend from '@interactjs/utils/extend'\n\nimport type { ModifierArg, ModifierModule } from '../base'\nimport { makeModifier } from '../base'\n\nimport type { SnapOptions, SnapState } from './pointer'\nimport { snapSize } from './size'\n\nexport type SnapEdgesOptions = Pick\n\nfunction start (arg: ModifierArg) {\n const { edges } = arg\n\n if (!edges) {\n return null\n }\n\n arg.state.targetFields = arg.state.targetFields || [\n [edges.left ? 'left' : 'right', edges.top ? 'top' : 'bottom'],\n ]\n\n return snapSize.start(arg)\n}\n\nconst snapEdges: ModifierModule> = {\n start,\n set: snapSize.set,\n defaults: extend(clone(snapSize.defaults), {\n targets: null,\n range: null,\n offset: { x: 0, y: 0 },\n } as const),\n}\n\nexport default makeModifier(snapEdges, 'snapEdges')\nexport { snapEdges }\n","/* eslint-disable node/no-extraneous-import, import/no-unresolved */\nimport aspectRatio from './aspectRatio'\nimport avoid from './avoid/avoid'\nimport restrictEdges from './restrict/edges'\nimport restrict from './restrict/pointer'\nimport restrictRect from './restrict/rect'\nimport restrictSize from './restrict/size'\nimport rubberband from './rubberband/rubberband'\nimport snapEdges from './snap/edges'\nimport snap from './snap/pointer'\nimport snapSize from './snap/size'\nimport spring from './spring/spring'\nimport transform from './transform/transform'\n\nexport default {\n aspectRatio,\n restrictEdges,\n restrict,\n restrictRect,\n restrictSize,\n snapEdges,\n snap,\n snapSize,\n\n spring,\n avoid,\n transform,\n rubberband,\n}\n","import type { Plugin } from '@interactjs/core/scope'\nimport snappers from '@interactjs/snappers/plugin'\n\nimport all from './all'\nimport base from './base'\n\ndeclare module '@interactjs/core/InteractStatic' {\n export interface InteractStatic {\n modifiers: typeof all\n }\n}\n\nconst modifiers: Plugin = {\n id: 'modifiers',\n install (scope) {\n const { interactStatic: interact } = scope\n\n scope.usePlugin(base)\n scope.usePlugin(snappers)\n\n interact.modifiers = all\n\n // for backwrads compatibility\n for (const type in all) {\n const { _defaults, _methods } = all[type as keyof typeof all]\n\n ;(_defaults as any)._methods = _methods\n ;(scope.defaults.perAction as any)[type] = _defaults\n }\n },\n}\n\nexport default modifiers\n","import { BaseEvent } from '@interactjs/core/BaseEvent'\nimport type Interaction from '@interactjs/core/Interaction'\nimport type { PointerEventType, PointerType, Point } from '@interactjs/types/index'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\n\nexport default class PointerEvent extends BaseEvent {\n type: T\n originalEvent: PointerEventType\n pointerId: number\n pointerType: string\n double: boolean\n pageX: number\n pageY: number\n clientX: number\n clientY: number\n dt: number\n eventable: any;\n [key: string]: any\n\n /** */\n constructor (\n type: T,\n pointer: PointerType | PointerEvent,\n event: PointerEventType,\n eventTarget: Node,\n interaction: Interaction,\n timeStamp: number,\n ) {\n super(interaction)\n pointerUtils.pointerExtend(this, event)\n\n if (event !== pointer) {\n pointerUtils.pointerExtend(this, pointer)\n }\n\n this.timeStamp = timeStamp\n this.originalEvent = event\n this.type = type\n this.pointerId = pointerUtils.getPointerId(pointer)\n this.pointerType = pointerUtils.getPointerType(pointer)\n this.target = eventTarget\n this.currentTarget = null\n\n if (type === 'tap') {\n const pointerIndex = interaction.getPointerIndex(pointer)\n this.dt = this.timeStamp - interaction.pointers[pointerIndex].downTime\n\n const interval = this.timeStamp - interaction.tapTime\n\n this.double = !!(\n interaction.prevTap &&\n interaction.prevTap.type !== 'doubletap' &&\n interaction.prevTap.target === this.target &&\n interval < 500\n )\n } else if (type === 'doubletap') {\n this.dt = (pointer as PointerEvent<'tap'>).timeStamp - interaction.tapTime\n }\n }\n\n _subtractOrigin ({ x: originX, y: originY }: Point) {\n this.pageX -= originX\n this.pageY -= originY\n this.clientX -= originX\n this.clientY -= originY\n\n return this\n }\n\n _addOrigin ({ x: originX, y: originY }: Point) {\n this.pageX += originX\n this.pageY += originY\n this.clientX += originX\n this.clientY += originY\n\n return this\n }\n\n /**\n * Prevent the default behaviour of the original Event\n */\n preventDefault () {\n this.originalEvent.preventDefault()\n }\n}\n\nexport { PointerEvent }\n","import type { Eventable } from '@interactjs/core/Eventable'\nimport type { Interaction } from '@interactjs/core/Interaction'\nimport type { PerActionDefaults } from '@interactjs/core/options'\nimport type { Scope, SignalArgs, Plugin } from '@interactjs/core/scope'\nimport type { Point, PointerType, PointerEventType, Element } from '@interactjs/types'\nimport * as domUtils from '@interactjs/utils/domUtils'\nimport extend from '@interactjs/utils/extend'\nimport getOriginXY from '@interactjs/utils/getOriginXY'\n\nimport { PointerEvent } from './PointerEvent'\n\nexport type EventTargetList = Array<{\n node: Node\n eventable: Eventable\n props: { [key: string]: any }\n}>\n\nexport interface PointerEventOptions extends PerActionDefaults {\n enabled?: undefined // not used\n holdDuration?: number\n ignoreFrom?: any\n allowFrom?: any\n origin?: Point | string | Element\n}\n\ndeclare module '@interactjs/core/scope' {\n interface Scope {\n pointerEvents: typeof pointerEvents\n }\n}\n\ndeclare module '@interactjs/core/Interaction' {\n interface Interaction {\n prevTap?: PointerEvent\n tapTime?: number\n }\n}\n\ndeclare module '@interactjs/core/PointerInfo' {\n interface PointerInfo {\n hold?: {\n duration: number\n timeout: any\n }\n }\n}\n\ndeclare module '@interactjs/core/options' {\n interface ActionDefaults {\n pointerEvents: Options\n }\n}\n\ndeclare module '@interactjs/core/scope' {\n interface SignalArgs {\n 'pointerEvents:new': { pointerEvent: PointerEvent }\n 'pointerEvents:fired': {\n interaction: Interaction\n pointer: PointerType | PointerEvent\n event: PointerEventType | PointerEvent\n eventTarget: Node\n pointerEvent: PointerEvent\n targets?: EventTargetList\n type: string\n }\n 'pointerEvents:collect-targets': {\n interaction: Interaction\n pointer: PointerType | PointerEvent\n event: PointerEventType | PointerEvent\n eventTarget: Node\n targets?: EventTargetList\n type: string\n path: Node[]\n node: null\n }\n }\n}\n\nconst defaults: PointerEventOptions = {\n holdDuration: 600,\n ignoreFrom: null,\n allowFrom: null,\n origin: { x: 0, y: 0 },\n}\n\nconst pointerEvents: Plugin = {\n id: 'pointer-events/base',\n before: ['inertia', 'modifiers', 'auto-start', 'actions'],\n install,\n listeners: {\n 'interactions:new': addInteractionProps,\n 'interactions:update-pointer': addHoldInfo,\n 'interactions:move': moveAndClearHold,\n 'interactions:down': (arg, scope) => {\n downAndStartHold(arg, scope)\n fire(arg, scope)\n },\n 'interactions:up': (arg, scope) => {\n clearHold(arg)\n fire(arg, scope)\n tapAfterUp(arg, scope)\n },\n 'interactions:cancel': (arg, scope) => {\n clearHold(arg)\n fire(arg, scope)\n },\n },\n PointerEvent,\n fire,\n collectEventTargets,\n defaults,\n types: {\n down: true,\n move: true,\n up: true,\n cancel: true,\n tap: true,\n doubletap: true,\n hold: true,\n } as { [type: string]: true },\n}\n\nfunction fire (\n arg: {\n pointer: PointerType | PointerEvent\n event: PointerEventType | PointerEvent\n eventTarget: Node\n interaction: Interaction\n type: T\n targets?: EventTargetList\n },\n scope: Scope,\n) {\n const { interaction, pointer, event, eventTarget, type, targets = collectEventTargets(arg, scope) } = arg\n\n const pointerEvent = new PointerEvent(type, pointer, event, eventTarget, interaction, scope.now())\n\n scope.fire('pointerEvents:new', { pointerEvent })\n\n const signalArg = {\n interaction,\n pointer,\n event,\n eventTarget,\n targets,\n type,\n pointerEvent,\n }\n\n for (let i = 0; i < targets.length; i++) {\n const target = targets[i]\n\n for (const prop in target.props || {}) {\n ;(pointerEvent as any)[prop] = target.props[prop]\n }\n\n const origin = getOriginXY(target.eventable, target.node)\n\n pointerEvent._subtractOrigin(origin)\n pointerEvent.eventable = target.eventable\n pointerEvent.currentTarget = target.node\n\n target.eventable.fire(pointerEvent)\n\n pointerEvent._addOrigin(origin)\n\n if (\n pointerEvent.immediatePropagationStopped ||\n (pointerEvent.propagationStopped &&\n i + 1 < targets.length &&\n targets[i + 1].node !== pointerEvent.currentTarget)\n ) {\n break\n }\n }\n\n scope.fire('pointerEvents:fired', signalArg)\n\n if (type === 'tap') {\n // if pointerEvent should make a double tap, create and fire a doubletap\n // PointerEvent and use that as the prevTap\n const prevTap = pointerEvent.double\n ? fire(\n {\n interaction,\n pointer,\n event,\n eventTarget,\n type: 'doubletap',\n },\n scope,\n )\n : pointerEvent\n\n interaction.prevTap = prevTap\n interaction.tapTime = prevTap.timeStamp\n }\n\n return pointerEvent\n}\n\nfunction collectEventTargets (\n {\n interaction,\n pointer,\n event,\n eventTarget,\n type,\n }: {\n interaction: Interaction\n pointer: PointerType | PointerEvent\n event: PointerEventType | PointerEvent\n eventTarget: Node\n type: T\n },\n scope: Scope,\n) {\n const pointerIndex = interaction.getPointerIndex(pointer)\n const pointerInfo = interaction.pointers[pointerIndex]\n\n // do not fire a tap event if the pointer was moved before being lifted\n if (\n type === 'tap' &&\n (interaction.pointerWasMoved ||\n // or if the pointerup target is different to the pointerdown target\n !(pointerInfo && pointerInfo.downTarget === eventTarget))\n ) {\n return []\n }\n\n const path = domUtils.getPath(eventTarget as Element | Document)\n const signalArg = {\n interaction,\n pointer,\n event,\n eventTarget,\n type,\n path,\n targets: [] as EventTargetList,\n node: null,\n }\n\n for (const node of path) {\n signalArg.node = node\n\n scope.fire('pointerEvents:collect-targets', signalArg)\n }\n\n if (type === 'hold') {\n signalArg.targets = signalArg.targets.filter(\n (target) => target.eventable.options.holdDuration === interaction.pointers[pointerIndex]?.hold.duration,\n )\n }\n\n return signalArg.targets\n}\n\nfunction addInteractionProps ({ interaction }) {\n interaction.prevTap = null // the most recent tap event on this interaction\n interaction.tapTime = 0 // time of the most recent tap event\n}\n\nfunction addHoldInfo ({ down, pointerInfo }: SignalArgs['interactions:update-pointer']) {\n if (!down && pointerInfo.hold) {\n return\n }\n\n pointerInfo.hold = { duration: Infinity, timeout: null }\n}\n\nfunction clearHold ({ interaction, pointerIndex }) {\n const hold = interaction.pointers[pointerIndex].hold\n\n if (hold && hold.timeout) {\n clearTimeout(hold.timeout)\n hold.timeout = null\n }\n}\n\nfunction moveAndClearHold (arg: SignalArgs['interactions:move'], scope: Scope) {\n const { interaction, pointer, event, eventTarget, duplicate } = arg\n\n if (!duplicate && (!interaction.pointerIsDown || interaction.pointerWasMoved)) {\n if (interaction.pointerIsDown) {\n clearHold(arg)\n }\n\n fire(\n {\n interaction,\n pointer,\n event,\n eventTarget: eventTarget as Element,\n type: 'move',\n },\n scope,\n )\n }\n}\n\nfunction downAndStartHold (\n { interaction, pointer, event, eventTarget, pointerIndex }: SignalArgs['interactions:down'],\n scope: Scope,\n) {\n const timer = interaction.pointers[pointerIndex].hold\n const path = domUtils.getPath(eventTarget as Element | Document)\n const signalArg = {\n interaction,\n pointer,\n event,\n eventTarget,\n type: 'hold',\n targets: [] as EventTargetList,\n path,\n node: null,\n }\n\n for (const node of path) {\n signalArg.node = node\n\n scope.fire('pointerEvents:collect-targets', signalArg)\n }\n\n if (!signalArg.targets.length) return\n\n let minDuration = Infinity\n\n for (const target of signalArg.targets) {\n const holdDuration = target.eventable.options.holdDuration\n\n if (holdDuration < minDuration) {\n minDuration = holdDuration\n }\n }\n\n timer.duration = minDuration\n timer.timeout = setTimeout(() => {\n fire(\n {\n interaction,\n eventTarget,\n pointer,\n event,\n type: 'hold',\n },\n scope,\n )\n }, minDuration)\n}\n\nfunction tapAfterUp (\n { interaction, pointer, event, eventTarget }: SignalArgs['interactions:up'],\n scope: Scope,\n) {\n if (!interaction.pointerWasMoved) {\n fire({ interaction, eventTarget, pointer, event, type: 'tap' }, scope)\n }\n}\n\nfunction install (scope: Scope) {\n scope.pointerEvents = pointerEvents\n scope.defaults.actions.pointerEvents = pointerEvents.defaults\n extend(scope.actions.phaselessTypes, pointerEvents.types)\n}\n\nexport default pointerEvents\n","import type Interaction from '@interactjs/core/Interaction'\nimport type { ListenerMap, Scope, SignalArgs, Plugin } from '@interactjs/core/scope'\n\nimport type PointerEvent from './PointerEvent'\nimport basePlugin from './base'\n\ndeclare module '@interactjs/core/Interaction' {\n interface Interaction {\n holdIntervalHandle?: any\n }\n}\n\ndeclare module '@interactjs/pointer-events/PointerEvent' {\n interface PointerEvent {\n count?: number\n }\n}\n\ndeclare module '@interactjs/pointer-events/base' {\n interface PointerEventOptions {\n holdRepeatInterval?: number\n }\n}\n\nfunction install (scope: Scope) {\n scope.usePlugin(basePlugin)\n\n const { pointerEvents } = scope\n\n // don't repeat by default\n pointerEvents.defaults.holdRepeatInterval = 0\n pointerEvents.types.holdrepeat = scope.actions.phaselessTypes.holdrepeat = true\n}\n\nfunction onNew ({ pointerEvent }: { pointerEvent: PointerEvent }) {\n if (pointerEvent.type !== 'hold') return\n\n pointerEvent.count = (pointerEvent.count || 0) + 1\n}\n\nfunction onFired (\n { interaction, pointerEvent, eventTarget, targets }: SignalArgs['pointerEvents:fired'],\n scope: Scope,\n) {\n if (pointerEvent.type !== 'hold' || !targets.length) return\n\n // get the repeat interval from the first eventable\n const interval = targets[0].eventable.options.holdRepeatInterval\n\n // don't repeat if the interval is 0 or less\n if (interval <= 0) return\n\n // set a timeout to fire the holdrepeat event\n interaction.holdIntervalHandle = setTimeout(() => {\n scope.pointerEvents.fire(\n {\n interaction,\n eventTarget,\n type: 'hold',\n pointer: pointerEvent,\n event: pointerEvent,\n },\n scope,\n )\n }, interval)\n}\n\nfunction endHoldRepeat ({ interaction }: { interaction: Interaction }) {\n // set the interaction's holdStopTime property\n // to stop further holdRepeat events\n if (interaction.holdIntervalHandle) {\n clearInterval(interaction.holdIntervalHandle)\n interaction.holdIntervalHandle = null\n }\n}\n\nconst holdRepeat: Plugin = {\n id: 'pointer-events/holdRepeat',\n install,\n listeners: ['move', 'up', 'cancel', 'endall'].reduce(\n (acc, enderTypes) => {\n ;(acc as any)[`pointerEvents:${enderTypes}`] = endHoldRepeat\n return acc\n },\n {\n 'pointerEvents:new': onNew,\n 'pointerEvents:fired': onFired,\n } as ListenerMap,\n ),\n}\n\nexport default holdRepeat\n","import type { Interactable } from '@interactjs/core/Interactable'\nimport type { Scope, Plugin } from '@interactjs/core/scope'\nimport type { Element } from '@interactjs/types/index'\nimport extend from '@interactjs/utils/extend'\n\ndeclare module '@interactjs/core/Interactable' {\n interface Interactable {\n pointerEvents: typeof pointerEventsMethod\n __backCompatOption: (optionName: string, newValue: any) => any\n }\n}\n\nfunction install (scope: Scope) {\n const { Interactable } = scope\n\n Interactable.prototype.pointerEvents = pointerEventsMethod\n\n const __backCompatOption = Interactable.prototype._backCompatOption\n\n Interactable.prototype._backCompatOption = function (optionName, newValue) {\n const ret = __backCompatOption.call(this, optionName, newValue)\n\n if (ret === this) {\n this.events.options[optionName] = newValue\n }\n\n return ret\n }\n}\n\nfunction pointerEventsMethod (this: Interactable, options: any) {\n extend(this.events.options, options)\n\n return this\n}\n\nconst plugin: Plugin = {\n id: 'pointer-events/interactableTargets',\n install,\n listeners: {\n 'pointerEvents:collect-targets': ({ targets, node, type, eventTarget }, scope) => {\n scope.interactables.forEachMatch(node, (interactable: Interactable) => {\n const eventable = interactable.events\n const options = eventable.options\n\n if (\n eventable.types[type] &&\n eventable.types[type].length &&\n interactable.testIgnoreAllow(options, node, eventTarget)\n ) {\n targets.push({\n node,\n eventable,\n props: { interactable },\n })\n }\n })\n },\n\n 'interactable:new': ({ interactable }) => {\n interactable.events.getRect = function (element: Element) {\n return interactable.getRect(element)\n }\n },\n\n 'interactable:set': ({ interactable, options }, scope) => {\n extend(interactable.events.options, scope.pointerEvents.defaults)\n extend(interactable.events.options, options.pointerEvents || {})\n },\n },\n}\n\nexport default plugin\n","import type { Plugin } from '@interactjs/core/scope'\n\nimport * as pointerEvents from './base'\nimport holdRepeat from './holdRepeat'\nimport interactableTargets from './interactableTargets'\n\nconst plugin: Plugin = {\n id: 'pointer-events',\n install (scope) {\n scope.usePlugin(pointerEvents)\n scope.usePlugin(holdRepeat)\n scope.usePlugin(interactableTargets)\n },\n}\n\nexport default plugin\n","import type { Interactable } from '@interactjs/core/Interactable'\nimport type { ActionProps, DoAnyPhaseArg, Interaction } from '@interactjs/core/Interaction'\nimport type { ActionName, Scope, Plugin } from '@interactjs/core/scope'\nimport type { Element } from '@interactjs/types/index'\nimport * as arr from '@interactjs/utils/arr'\nimport is from '@interactjs/utils/is'\nimport { copyAction } from '@interactjs/utils/misc'\nimport * as pointerUtils from '@interactjs/utils/pointerUtils'\nimport { tlbrToXywh } from '@interactjs/utils/rect'\n\ndeclare module '@interactjs/core/scope' {\n interface SignalArgs {\n 'interactions:before-action-reflow': Omit\n 'interactions:action-reflow': DoAnyPhaseArg\n 'interactions:after-action-reflow': DoAnyPhaseArg\n }\n}\n\ndeclare module '@interactjs/core/Interactable' {\n interface Interactable {\n reflow: (action: ActionProps) => ReturnType\n }\n}\n\ndeclare module '@interactjs/core/Interaction' {\n interface Interaction {\n _reflowPromise: Promise\n _reflowResolve: (...args: unknown[]) => void\n }\n}\n\ndeclare module '@interactjs/core/InteractEvent' {\n interface PhaseMap {\n reflow?: true\n }\n}\n\nexport function install (scope: Scope) {\n const {\n /** @lends Interactable */\n Interactable,\n } = scope\n\n scope.actions.phases.reflow = true\n\n /**\n * ```js\n * const interactable = interact(target)\n * const drag = { name: drag, axis: 'x' }\n * const resize = { name: resize, edges: { left: true, bottom: true }\n *\n * interactable.reflow(drag)\n * interactable.reflow(resize)\n * ```\n *\n * Start an action sequence to re-apply modifiers, check drops, etc.\n *\n * @param { Object } action The action to begin\n * @param { string } action.name The name of the action\n * @returns { Promise } A promise that resolves to the `Interactable` when actions on all targets have ended\n */\n Interactable.prototype.reflow = function (action: ActionProps) {\n return doReflow(this, action, scope)\n }\n}\n\nfunction doReflow (\n interactable: Interactable,\n action: ActionProps