{"version":3,"file":"Canvas.mjs","names":[],"sources":["../../../src/canvas/Canvas.ts"],"sourcesContent":["import { classRegistry } from '../ClassRegistry';\nimport { NONE } from '../constants';\nimport type {\n  CanvasEvents,\n  DragEventData,\n  ObjectEvents,\n  TEventsExtraData,\n  TPointerEvent,\n  TPointerEventNames,\n  Transform,\n} from '../EventTypeDefs';\nimport { Point } from '../Point';\nimport type { ActiveSelection } from '../shapes/ActiveSelection';\nimport type { Group } from '../shapes/Group';\nimport type { IText } from '../shapes/IText/IText';\nimport type { FabricObject } from '../shapes/Object/FabricObject';\nimport { type TToCanvasElementOptions } from '../typedefs';\nimport { isTouchEvent, stopEvent } from '../util/dom_event';\nimport { getDocumentFromElement, getWindowFromElement } from '../util/dom_misc';\nimport { sendPointToPlane } from '../util/misc/planeChange';\nimport { isActiveSelection } from '../util/typeAssertions';\nimport type { CanvasOptions, TCanvasOptions } from './CanvasOptions';\nimport { SelectableCanvas } from './SelectableCanvas';\nimport { TextEditingManager } from './TextEditingManager';\n\nconst addEventOptions = { passive: false } as EventListenerOptions;\n\nconst getEventPoints = (canvas: Canvas, e: TPointerEvent) => {\n  const viewportPoint = canvas.getViewportPoint(e);\n  const scenePoint = canvas.getScenePoint(e);\n  return {\n    viewportPoint,\n    scenePoint,\n  };\n};\n\n// just to be clear, the utils are now deprecated and those are here exactly as minifier helpers\n// because el.addEventListener can't me be minified while a const yes and we use it 47 times in this file.\n// few bytes but why give it away.\nconst addListener = (\n  el: HTMLElement | Document,\n  ...args: Parameters<HTMLElement['addEventListener']>\n) => el.addEventListener(...args);\nconst removeListener = (\n  el: HTMLElement | Document,\n  ...args: Parameters<HTMLElement['removeEventListener']>\n) => el.removeEventListener(...args);\n\nconst syntheticEventConfig = {\n  mouse: {\n    in: 'over',\n    out: 'out',\n    targetIn: 'mouseover',\n    targetOut: 'mouseout',\n    canvasIn: 'mouse:over',\n    canvasOut: 'mouse:out',\n  },\n  drag: {\n    in: 'enter',\n    out: 'leave',\n    targetIn: 'dragenter',\n    targetOut: 'dragleave',\n    canvasIn: 'drag:enter',\n    canvasOut: 'drag:leave',\n  },\n} as const;\n\ntype TSyntheticEventContext = {\n  mouse: { e: TPointerEvent };\n  drag: DragEventData;\n};\n\nexport class Canvas extends SelectableCanvas implements CanvasOptions {\n  /**\n   * Contains the id of the touch event that owns the fabric transform\n   * @type Number\n   * @private\n   */\n  declare mainTouchId?: number;\n\n  declare enablePointerEvents: boolean;\n\n  /**\n   * Holds a reference to a setTimeout timer for event synchronization\n   * @type number\n   * @private\n   */\n  declare private _willAddMouseDown: number;\n\n  /**\n   * Holds a reference to an object on the canvas that is receiving the drag over event.\n   * @type FabricObject\n   * @private\n   */\n  declare private _draggedoverTarget?: FabricObject;\n\n  /**\n   * Holds a reference to an object on the canvas from where the drag operation started\n   * @type FabricObject\n   * @private\n   */\n  declare private _dragSource?: FabricObject;\n\n  /**\n   * Holds a reference to an object on the canvas that is the current drop target\n   * May differ from {@link _draggedoverTarget}\n   * @todo inspect whether {@link _draggedoverTarget} and {@link _dropTarget} should be merged somehow\n   * @type FabricObject\n   * @private\n   */\n  declare private _dropTarget: FabricObject<ObjectEvents> | undefined;\n\n  /**\n   * a boolean that keeps track of the click state during a cycle of mouse down/up.\n   * If a mouse move occurs it becomes false.\n   * Is true by default, turns false on mouse move.\n   * Used to determine if a mouseUp is a click\n   */\n  private _isClick: boolean;\n\n  textEditingManager = new TextEditingManager(this);\n\n  constructor(el?: string | HTMLCanvasElement, options: TCanvasOptions = {}) {\n    super(el, options);\n    // bind event handlers\n    (\n      [\n        '_onMouseDown',\n        '_onTouchStart',\n        '_onMouseMove',\n        '_onMouseUp',\n        '_onTouchEnd',\n        '_onResize',\n        // '_onGesture',\n        // '_onDrag',\n        // '_onShake',\n        // '_onLongPress',\n        // '_onOrientationChange',\n        '_onMouseWheel',\n        '_onMouseOut',\n        '_onMouseEnter',\n        '_onContextMenu',\n        '_onClick',\n        '_onDragStart',\n        '_onDragEnd',\n        '_onDragProgress',\n        '_onDragOver',\n        '_onDragEnter',\n        '_onDragLeave',\n        '_onDrop',\n      ] as (keyof this)[]\n    ).forEach((eventHandler) => {\n      // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n      this[eventHandler] = (this[eventHandler] as Function).bind(this);\n    });\n    // register event handlers\n    this.addOrRemove(addListener);\n  }\n\n  /**\n   * return an event prefix pointer or mouse.\n   * @private\n   */\n  private _getEventPrefix() {\n    return this.enablePointerEvents ? 'pointer' : 'mouse';\n  }\n\n  addOrRemove(functor: any, forTouch = false) {\n    const canvasElement = this.upperCanvasEl,\n      eventTypePrefix = this._getEventPrefix();\n    functor(getWindowFromElement(canvasElement), 'resize', this._onResize);\n    functor(canvasElement, eventTypePrefix + 'down', this._onMouseDown);\n    functor(\n      canvasElement,\n      `${eventTypePrefix}move`,\n      this._onMouseMove,\n      addEventOptions,\n    );\n    functor(canvasElement, `${eventTypePrefix}out`, this._onMouseOut);\n    functor(canvasElement, `${eventTypePrefix}enter`, this._onMouseEnter);\n    functor(canvasElement, 'wheel', this._onMouseWheel, { passive: false });\n    functor(canvasElement, 'contextmenu', this._onContextMenu);\n    if (!forTouch) {\n      functor(canvasElement, 'click', this._onClick);\n      functor(canvasElement, 'dblclick', this._onClick);\n    }\n    functor(canvasElement, 'dragstart', this._onDragStart);\n    functor(canvasElement, 'dragend', this._onDragEnd);\n    functor(canvasElement, 'dragover', this._onDragOver);\n    functor(canvasElement, 'dragenter', this._onDragEnter);\n    functor(canvasElement, 'dragleave', this._onDragLeave);\n    functor(canvasElement, 'drop', this._onDrop);\n    if (!this.enablePointerEvents) {\n      functor(canvasElement, 'touchstart', this._onTouchStart, addEventOptions);\n    }\n  }\n\n  /**\n   * Removes all event listeners, used when disposing the instance\n   */\n  removeListeners() {\n    this.addOrRemove(removeListener);\n    // if you dispose on a mouseDown, before mouse up, you need to clean document to...\n    const eventTypePrefix = this._getEventPrefix();\n    const doc = getDocumentFromElement(this.upperCanvasEl);\n    removeListener(\n      doc,\n      `${eventTypePrefix}up`,\n      this._onMouseUp as EventListener,\n    );\n    removeListener(\n      doc,\n      'touchend',\n      this._onTouchEnd as EventListener,\n      addEventOptions,\n    );\n    removeListener(\n      doc,\n      `${eventTypePrefix}move`,\n      this._onMouseMove as EventListener,\n      addEventOptions,\n    );\n    removeListener(\n      doc,\n      'touchmove',\n      this._onMouseMove as EventListener,\n      addEventOptions,\n    );\n    clearTimeout(this._willAddMouseDown);\n  }\n\n  /**\n   * @private\n   * @param {Event} [e] Event object fired on wheel event\n   */\n  private _onMouseWheel(e: MouseEvent) {\n    this._cacheTransformEventData(e);\n    this._handleEvent(e, 'wheel');\n    this._resetTransformEventData();\n  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mousedown\n   */\n  private _onMouseOut(e: TPointerEvent) {\n    const target = this._hoveredTarget;\n    const shared = {\n      e,\n      ...getEventPoints(this, e),\n    };\n    this.fire('mouse:out', { ...shared, target });\n    this._hoveredTarget = undefined;\n    target && target.fire('mouseout', { ...shared });\n    this._hoveredTargets.forEach((nestedTarget) => {\n      this.fire('mouse:out', { ...shared, target: nestedTarget });\n      nestedTarget && nestedTarget.fire('mouseout', { ...shared });\n    });\n    this._hoveredTargets = [];\n  }\n\n  /**\n   * @private\n   * Used when the mouse cursor enter the canvas from outside\n   * @param {Event} e Event object fired on mouseenter\n   */\n  private _onMouseEnter(e: TPointerEvent) {\n    // This find target and consequent 'mouse:over' is used to\n    // clear old instances on hovered target.\n    // calling findTarget has the side effect of killing target.__corner.\n    // as a short term fix we are not firing this if we are currently transforming.\n    // as a long term fix we need to separate the action of finding a target with the\n    // side effects we added to it.\n    const { target } = this.findTarget(e);\n    // we fire the event only when there is no target, if there is a target, the specific\n    // target event will fire.\n    if (!this._currentTransform && !target) {\n      this.fire('mouse:over', {\n        e,\n        ...getEventPoints(this, e),\n      });\n      this._hoveredTarget = undefined;\n      this._hoveredTargets = [];\n    }\n  }\n\n  /**\n   * supports native like text dragging\n   * @private\n   * @param {DragEvent} e\n   */\n  private _onDragStart(e: DragEvent) {\n    this._isClick = false;\n    const activeObject = this.getActiveObject();\n    if (activeObject && activeObject.onDragStart(e)) {\n      this._dragSource = activeObject;\n      const options = { e, target: activeObject };\n      this.fire('dragstart', options);\n      activeObject.fire('dragstart', options);\n      addListener(\n        this.upperCanvasEl,\n        'drag',\n        this._onDragProgress as EventListener,\n      );\n      return;\n    }\n    stopEvent(e);\n  }\n\n  /**\n   * First we clear top context where the effects are being rendered.\n   * Then we render the effects.\n   * Doing so will render the correct effect for all cases including an overlap between `source` and `target`.\n   * @private\n   */\n  private _renderDragEffects(\n    e: DragEvent,\n    source?: FabricObject,\n    target?: FabricObject,\n  ) {\n    let dirty = false;\n    // clear top context\n    const dropTarget = this._dropTarget;\n    if (dropTarget && dropTarget !== source && dropTarget !== target) {\n      dropTarget.clearContextTop();\n      dirty = true;\n    }\n    source?.clearContextTop();\n    target !== source && target?.clearContextTop();\n    // render effects\n    const ctx = this.contextTop;\n    ctx.save();\n    ctx.transform(...this.viewportTransform);\n    if (source) {\n      ctx.save();\n      source.transform(ctx);\n      source.renderDragSourceEffect(e);\n      ctx.restore();\n      dirty = true;\n    }\n    if (target) {\n      ctx.save();\n      target.transform(ctx);\n      target.renderDropTargetEffect(e);\n      ctx.restore();\n      dirty = true;\n    }\n    ctx.restore();\n    dirty && (this.contextTopDirty = true);\n  }\n\n  /**\n   * supports native like text dragging\n   * https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#finishing_a_drag\n   * @private\n   * @param {DragEvent} e\n   */\n  private _onDragEnd(e: DragEvent) {\n    const { currentSubTargets } = this.findTarget(e);\n    const didDrop = !!e.dataTransfer && e.dataTransfer.dropEffect !== NONE,\n      dropTarget = didDrop ? this._activeObject : undefined,\n      options = {\n        e,\n        target: this._dragSource as FabricObject,\n        subTargets: currentSubTargets,\n        dragSource: this._dragSource as FabricObject,\n        didDrop,\n        dropTarget: dropTarget as FabricObject,\n      };\n    removeListener(\n      this.upperCanvasEl,\n      'drag',\n      this._onDragProgress as EventListener,\n    );\n    this.fire('dragend', options);\n    this._dragSource && this._dragSource.fire('dragend', options);\n    delete this._dragSource;\n    // we need to call mouse up synthetically because the browser won't\n    this._onMouseUp(e);\n  }\n\n  /**\n   * fire `drag` event on canvas and drag source\n   * @private\n   * @param {DragEvent} e\n   */\n  private _onDragProgress(e: DragEvent) {\n    const options = {\n      e,\n      target: this._dragSource,\n      dragSource: this._dragSource,\n      dropTarget: this._draggedoverTarget as FabricObject,\n    };\n    this.fire('drag', options);\n    this._dragSource && this._dragSource.fire('drag', options);\n  }\n\n  /**\n   * prevent default to allow drop event to be fired\n   * https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#specifying_drop_targets\n   * @private\n   * @param {DragEvent} [e] Event object fired on Event.js shake\n   */\n  private _onDragOver(e: DragEvent) {\n    const eventType = 'dragover';\n    const { currentContainer: target, currentSubTargets } = this.findTarget(e);\n    const dragSource = this._dragSource as FabricObject;\n    const options = {\n      e,\n      target,\n      subTargets: currentSubTargets,\n      dragSource,\n      canDrop: false,\n      dropTarget: undefined,\n    };\n    let dropTarget;\n    //  fire on canvas\n    this.fire(eventType, options);\n    //  make sure we fire dragenter events before dragover\n    //  if dragleave is needed, object will not fire dragover so we don't need to trouble ourselves with it\n    this._fireEnterLeaveEvents(e, target, options);\n    if (target) {\n      if (target.canDrop(e)) {\n        dropTarget = target;\n      }\n      target.fire(eventType, options);\n    }\n    //  propagate the event to subtargets\n    for (let i = 0; i < currentSubTargets.length; i++) {\n      const subTarget = currentSubTargets[i];\n      // accept event only if previous targets didn't (the accepting target calls `preventDefault` to inform that the event is taken)\n      // TODO: verify if those should loop in inverse order then?\n      // what is the order of subtargets?\n      if (subTarget.canDrop(e)) {\n        dropTarget = subTarget;\n      }\n      subTarget.fire(eventType, options);\n    }\n    //  render drag effects now that relations between source and target is clear\n    this._renderDragEffects(e, dragSource, dropTarget);\n    this._dropTarget = dropTarget;\n  }\n\n  /**\n   * fire `dragleave` on `dragover` targets\n   * @private\n   * @param {Event} [e] Event object fired on Event.js shake\n   */\n  private _onDragEnter(e: DragEvent) {\n    const { currentContainer, currentSubTargets } = this.findTarget(e);\n    const options = {\n      e,\n      target: currentContainer,\n      subTargets: currentSubTargets,\n      dragSource: this._dragSource,\n    };\n    this.fire('dragenter', options);\n    //  fire dragenter on targets\n    this._fireEnterLeaveEvents(e, currentContainer, options);\n  }\n\n  /**\n   * fire `dragleave` on `dragover` targets\n   * @private\n   * @param {Event} [e] Event object fired on Event.js shake\n   */\n  private _onDragLeave(e: DragEvent) {\n    const { currentSubTargets } = this.findTarget(e);\n    const options = {\n      e,\n      target: this._draggedoverTarget,\n      subTargets: currentSubTargets,\n      dragSource: this._dragSource,\n    };\n    this.fire('dragleave', options);\n\n    //  fire dragleave on targets\n    this._fireEnterLeaveEvents(e, undefined, options);\n    this._renderDragEffects(e, this._dragSource);\n    this._dropTarget = undefined;\n    this._hoveredTargets = [];\n  }\n\n  /**\n   * `drop:before` is a an event that allows you to schedule logic\n   * before the `drop` event. Prefer `drop` event always, but if you need\n   * to run some drop-disabling logic on an event, since there is no way\n   * to handle event handlers ordering, use `drop:before`\n   * @private\n   * @param {Event} e\n   */\n  private _onDrop(e: DragEvent) {\n    const { currentContainer, currentSubTargets } = this.findTarget(e);\n    const options = this._basicEventHandler('drop:before', {\n      e,\n      target: currentContainer,\n      subTargets: currentSubTargets,\n      dragSource: this._dragSource,\n      ...getEventPoints(this, e),\n    });\n    //  will be set by the drop target\n    options.didDrop = false;\n    //  will be set by the drop target, used in case options.target refuses the drop\n    options.dropTarget = undefined;\n    //  fire `drop`\n    this._basicEventHandler('drop', options);\n    //  inform canvas of the drop\n    //  we do this because canvas was unaware of what happened at the time the `drop` event was fired on it\n    //  use for side effects\n    this.fire('drop:after', options);\n  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mousedown\n   */\n  private _onContextMenu(e: TPointerEvent): false {\n    const { target, subTargets } = this.findTarget(e);\n    const options = this._basicEventHandler('contextmenu:before', {\n      e,\n      target,\n      subTargets,\n    });\n    // TODO: this line is silly because the dev can subscribe to the event and prevent it themselves\n    this.stopContextMenu && stopEvent(e);\n    this._basicEventHandler('contextmenu', options);\n    return false;\n  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mousedown\n   */\n  private _onClick(e: TPointerEvent) {\n    const clicks = e.detail;\n    if (clicks > 3 || clicks < 2) return;\n    this._cacheTransformEventData(e);\n    clicks == 2 && e.type === 'dblclick' && this._handleEvent(e, 'dblclick');\n    clicks == 3 && this._handleEvent(e, 'tripleclick');\n    this._resetTransformEventData();\n  }\n\n  /**\n   * This supports gesture event firing\n   * It is a method to keep some code organized, it exposes private methods\n   * in a way that works and still keep them private\n   * This is supposed to mirror _handleEvent\n   */\n  fireEventFromPointerEvent(\n    e: TPointerEvent,\n    eventName: keyof CanvasEvents,\n    secondaryName: keyof ObjectEvents,\n    extraData:\n      | Record<string, unknown>\n      | { rotation: number }\n      | { ping: number } = {},\n  ) {\n    this._cacheTransformEventData(e);\n    const { target, subTargets } = this.findTarget(e),\n      options = {\n        e,\n        target,\n        subTargets,\n        ...getEventPoints(this, e),\n        transform: this._currentTransform,\n        ...extraData,\n      };\n    this.fire(eventName, options);\n    // this may be a little be more complicated of what we want to handle\n    target && target.fire(secondaryName, options);\n    for (let i = 0; i < subTargets.length; i++) {\n      subTargets[i] !== target && subTargets[i].fire(secondaryName, options);\n    }\n    this._resetTransformEventData();\n  }\n\n  /**\n   * Return a the id of an event.\n   * returns either the pointerId or the identifier or 0 for the mouse event\n   * @private\n   * @param {Event} evt Event object\n   */\n  getPointerId(evt: TouchEvent | PointerEvent): number {\n    const changedTouches = (evt as TouchEvent).changedTouches;\n\n    if (changedTouches) {\n      return changedTouches[0] && changedTouches[0].identifier;\n    }\n\n    if (this.enablePointerEvents) {\n      return (evt as PointerEvent).pointerId;\n    }\n\n    return -1;\n  }\n\n  /**\n   * Determines if an event has the id of the event that is considered main\n   * @private\n   * @param {evt} event Event object\n   */\n  _isMainEvent(evt: TPointerEvent): boolean {\n    if ((evt as PointerEvent).isPrimary === true) {\n      return true;\n    }\n    if ((evt as PointerEvent).isPrimary === false) {\n      return false;\n    }\n    if (evt.type === 'touchend' && (evt as TouchEvent).touches.length === 0) {\n      return true;\n    }\n    if ((evt as TouchEvent).changedTouches) {\n      return (\n        (evt as TouchEvent).changedTouches[0].identifier === this.mainTouchId\n      );\n    }\n    return true;\n  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mousedown\n   */\n  _onTouchStart(e: TouchEvent) {\n    this._cacheTransformEventData(e);\n    // we will prevent scrolling if allowTouchScrolling is not enabled and\n    let shouldPreventScrolling = !this.allowTouchScrolling;\n    const currentActiveObject = this._activeObject;\n    if (this.mainTouchId === undefined) {\n      this.mainTouchId = this.getPointerId(e);\n    }\n    this.__onMouseDown(e);\n    const { target } = this.findTarget(e);\n    // after executing fabric logic for mouse down let's see\n    // if we didn't change target or if we are drawing\n    // we want to prevent scrolling anyway\n    if (\n      this.isDrawingMode ||\n      (currentActiveObject && target === currentActiveObject)\n    ) {\n      shouldPreventScrolling = true;\n    }\n    // prevent default, will block scrolling from start\n    shouldPreventScrolling && e.preventDefault();\n    const canvasElement = this.upperCanvasEl,\n      eventTypePrefix = this._getEventPrefix();\n    const doc = getDocumentFromElement(canvasElement);\n    addListener(\n      doc,\n      'touchend',\n      this._onTouchEnd as EventListener,\n      addEventOptions,\n    );\n    // if we scroll don't register the touch move event\n    shouldPreventScrolling &&\n      addListener(\n        doc,\n        'touchmove',\n        this._onMouseMove as EventListener,\n        addEventOptions,\n      );\n    // Unbind mousedown to prevent double triggers from touch devices\n    removeListener(\n      canvasElement,\n      `${eventTypePrefix}down`,\n      this._onMouseDown as EventListener,\n    );\n    this._resetTransformEventData();\n  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mousedown\n   */\n  _onMouseDown(e: TPointerEvent) {\n    this._cacheTransformEventData(e);\n    this.__onMouseDown(e);\n    const canvasElement = this.upperCanvasEl,\n      eventTypePrefix = this._getEventPrefix();\n    // switch from moving on the canvas element to moving on the document\n    removeListener(\n      canvasElement,\n      `${eventTypePrefix}move`,\n      this._onMouseMove as EventListener,\n      addEventOptions,\n    );\n    const doc = getDocumentFromElement(canvasElement);\n    addListener(doc, `${eventTypePrefix}up`, this._onMouseUp as EventListener);\n    addListener(\n      doc,\n      `${eventTypePrefix}move`,\n      this._onMouseMove as EventListener,\n      addEventOptions,\n    );\n    this._resetTransformEventData();\n  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mousedown\n   */\n  _onTouchEnd(e: TouchEvent) {\n    if (e.touches.length > 0) {\n      // if there are still touches stop here\n      return;\n    }\n    this._cacheTransformEventData(e);\n    this.__onMouseUp(e);\n    this._resetTransformEventData();\n    delete this.mainTouchId;\n    const eventTypePrefix = this._getEventPrefix();\n    const doc = getDocumentFromElement(this.upperCanvasEl);\n    removeListener(\n      doc,\n      'touchend',\n      this._onTouchEnd as EventListener,\n      addEventOptions,\n    );\n    removeListener(\n      doc,\n      'touchmove',\n      this._onMouseMove as EventListener,\n      addEventOptions,\n    );\n    if (this._willAddMouseDown) {\n      clearTimeout(this._willAddMouseDown);\n    }\n    this._willAddMouseDown = setTimeout(() => {\n      // Wait 400ms before rebinding mousedown to prevent double triggers\n      // from touch devices\n      addListener(\n        this.upperCanvasEl,\n        `${eventTypePrefix}down`,\n        this._onMouseDown as EventListener,\n      );\n      this._willAddMouseDown = 0;\n    }, 400) as unknown as number;\n  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mouseup\n   */\n  _onMouseUp(e: TPointerEvent) {\n    this._cacheTransformEventData(e);\n    this.__onMouseUp(e);\n    const canvasElement = this.upperCanvasEl,\n      eventTypePrefix = this._getEventPrefix();\n    if (this._isMainEvent(e)) {\n      const doc = getDocumentFromElement(this.upperCanvasEl);\n      removeListener(\n        doc,\n        `${eventTypePrefix}up`,\n        this._onMouseUp as EventListener,\n      );\n      removeListener(\n        doc,\n        `${eventTypePrefix}move`,\n        this._onMouseMove as EventListener,\n        addEventOptions,\n      );\n      addListener(\n        canvasElement,\n        `${eventTypePrefix}move`,\n        this._onMouseMove as EventListener,\n        addEventOptions,\n      );\n    }\n    this._resetTransformEventData();\n  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mousemove\n   */\n  _onMouseMove(e: TPointerEvent) {\n    this._cacheTransformEventData(e);\n\n    const activeObject = this.getActiveObject();\n    !this.allowTouchScrolling &&\n      (!activeObject ||\n        // a drag event sequence is started by the active object flagging itself on mousedown / mousedown:before\n        // we must not prevent the event's default behavior in order for the window to start dragging\n        !activeObject.shouldStartDragging(e)) &&\n      e.preventDefault &&\n      e.preventDefault();\n    this.__onMouseMove(e);\n    this._resetTransformEventData();\n  }\n\n  /**\n   * @private\n   */\n  _onResize() {\n    this.calcOffset();\n    this._resetTransformEventData();\n  }\n\n  /**\n   * Decides whether the canvas should be redrawn in mouseup and mousedown events.\n   * @private\n   * @param {Object} target\n   */\n  _shouldRender(target: FabricObject | undefined) {\n    const activeObject = this.getActiveObject();\n    // if just one of them is available or if they are both but are different objects\n    // this covers: switch of target, from target to no target, selection of target\n    // multiSelection with key and mouse\n    return (\n      !!activeObject !== !!target ||\n      (activeObject && target && activeObject !== target)\n    );\n  }\n\n  /**\n   * Method that defines the actions when mouse is released on canvas.\n   * The method resets the currentTransform parameters, store the image corner\n   * position in the image object and render the canvas on top.\n   * @private\n   * @param {Event} e Event object fired on mouseup\n   */\n  __onMouseUp(e: TPointerEvent) {\n    this._handleEvent(e, 'up:before');\n\n    const transform = this._currentTransform;\n    const isClick = this._isClick;\n    const { target } = this.findTarget(e);\n\n    // if right/middle click just fire events and return\n    // target undefined will make the _handleEvent search the target\n    const { button } = e as MouseEvent;\n    if (button) {\n      ((this.fireMiddleClick && button === 1) ||\n        (this.fireRightClick && button === 2)) &&\n        this._handleEvent(e, 'up');\n      return;\n    }\n\n    if (this.isDrawingMode && this._isCurrentlyDrawing) {\n      this._onMouseUpInDrawingMode(e);\n      return;\n    }\n\n    if (!this._isMainEvent(e)) {\n      return;\n    }\n    let shouldRender = false;\n    if (transform) {\n      this._finalizeCurrentTransform(e);\n      shouldRender = transform.actionPerformed;\n    }\n    if (!isClick) {\n      const targetWasActive = target === this._activeObject;\n      this.handleSelection(e);\n      if (!shouldRender) {\n        shouldRender =\n          this._shouldRender(target) ||\n          (!targetWasActive && target === this._activeObject);\n      }\n    }\n    let pointer, corner;\n    if (target) {\n      const found = target.findControl(\n        this.getViewportPoint(e),\n        isTouchEvent(e),\n      );\n      const { key, control } = found || {};\n      corner = key;\n      if (\n        target.selectable &&\n        target !== this._activeObject &&\n        target.activeOn === 'up'\n      ) {\n        this.setActiveObject(target, e);\n        shouldRender = true;\n      } else if (control) {\n        const mouseUpHandler = control.getMouseUpHandler(e, target, control);\n        if (mouseUpHandler) {\n          pointer = this.getScenePoint(e);\n          mouseUpHandler.call(control, e, transform!, pointer.x, pointer.y);\n        }\n      }\n      target.isMoving = false;\n    }\n    // if we are ending up a transform on a different control or a new object\n    // fire the original mouse up from the corner that started the transform\n    if (\n      transform &&\n      (transform.target !== target || transform.corner !== corner)\n    ) {\n      const originalControl =\n          transform.target && transform.target.controls[transform.corner],\n        originalMouseUpHandler =\n          originalControl &&\n          originalControl.getMouseUpHandler(\n            e,\n            transform.target,\n            originalControl,\n          );\n      pointer = pointer || this.getScenePoint(e);\n      originalMouseUpHandler &&\n        originalMouseUpHandler.call(\n          originalControl,\n          e,\n          transform,\n          pointer.x,\n          pointer.y,\n        );\n    }\n    this._setCursorFromEvent(e, target);\n    this._handleEvent(e, 'up');\n    this._groupSelector = null;\n    this._currentTransform = null;\n    // reset the target information about which corner is selected\n    target && (target.__corner = undefined);\n    if (shouldRender) {\n      this.requestRenderAll();\n    } else if (!isClick && !(this._activeObject as IText)?.isEditing) {\n      this.renderTop();\n    }\n  }\n\n  _basicEventHandler<T extends keyof (CanvasEvents | ObjectEvents)>(\n    eventType: T,\n    options: (CanvasEvents & ObjectEvents)[T],\n  ) {\n    const { target, subTargets = [] } = options as {\n      target?: FabricObject;\n      subTargets: FabricObject[];\n    };\n    this.fire(eventType, options);\n    target && target.fire(eventType, options);\n    for (let i = 0; i < subTargets.length; i++) {\n      subTargets[i] !== target && subTargets[i].fire(eventType, options);\n    }\n    return options;\n  }\n\n  /**\n   * @private\n   * Handle event firing for target and subtargets\n   * @param {TPointerEvent} e event from mouse\n   * @param {TPointerEventNames} eventType\n   */\n  _handleEvent<T extends TPointerEventNames>(\n    e: TPointerEvent,\n    eventType: T,\n    extraData?: TEventsExtraData[T],\n  ) {\n    const { target, subTargets } = this.findTarget(e),\n      options: CanvasEvents[`mouse:${T}`] = {\n        e,\n        target,\n        subTargets,\n        ...getEventPoints(this, e),\n        transform: this._currentTransform,\n        ...(eventType === 'down:before' || eventType === 'down'\n          ? extraData\n          : {}),\n      } as CanvasEvents[`mouse:${T}`];\n    if (eventType === 'up:before' || eventType === 'up') {\n      (options as CanvasEvents[`mouse:up`]).isClick = this._isClick;\n    }\n\n    this.fire(`mouse:${eventType}`, options);\n    // this may be a little be more complicated of what we want to handle\n    target && target.fire(`mouse${eventType}`, options);\n    for (let i = 0; i < subTargets.length; i++) {\n      subTargets[i] !== target &&\n        subTargets[i].fire(`mouse${eventType}`, options);\n    }\n  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mousedown\n   */\n  _onMouseDownInDrawingMode(e: TPointerEvent) {\n    this._isCurrentlyDrawing = true;\n    if (this.getActiveObject()) {\n      this.discardActiveObject(e);\n      this.requestRenderAll();\n    }\n    // TODO: this is a scene point so it should be renamed\n    const pointer = this.getScenePoint(e);\n    this.freeDrawingBrush &&\n      this.freeDrawingBrush.onMouseDown(pointer, { e, pointer });\n    this._handleEvent(e, 'down', { alreadySelected: false });\n  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mousemove\n   */\n  _onMouseMoveInDrawingMode(e: TPointerEvent) {\n    if (this._isCurrentlyDrawing) {\n      const pointer = this.getScenePoint(e);\n      this.freeDrawingBrush &&\n        this.freeDrawingBrush.onMouseMove(pointer, {\n          e,\n          // this is an absolute pointer, the naming is wrong\n          pointer,\n        });\n    }\n    this.setCursor(this.freeDrawingCursor);\n    this._handleEvent(e, 'move');\n  }\n\n  /**\n   * @private\n   * @param {Event} e Event object fired on mouseup\n   */\n  _onMouseUpInDrawingMode(e: TPointerEvent) {\n    const pointer = this.getScenePoint(e);\n    if (this.freeDrawingBrush) {\n      this._isCurrentlyDrawing = !!this.freeDrawingBrush.onMouseUp({\n        e: e,\n        // this is an absolute pointer, the naming is wrong\n        pointer,\n      });\n    } else {\n      this._isCurrentlyDrawing = false;\n    }\n    this._handleEvent(e, 'up');\n  }\n\n  /**\n   * Method that defines the actions when mouse is clicked on canvas.\n   * The method inits the currentTransform parameters and renders all the\n   * canvas so the current image can be placed on the top canvas and the rest\n   * in on the container one.\n   * @private\n   * @param {Event} e Event object fired on mousedown\n   */\n  __onMouseDown(e: TPointerEvent) {\n    this._isClick = true;\n    this._handleEvent(e, 'down:before');\n\n    let { target } = this.findTarget(e);\n    let alreadySelected = !!target && target === this._activeObject;\n    // if right/middle click just fire events\n    const { button } = e as MouseEvent;\n    if (button) {\n      ((this.fireMiddleClick && button === 1) ||\n        (this.fireRightClick && button === 2)) &&\n        this._handleEvent(e, 'down', {\n          alreadySelected,\n        });\n      return;\n    }\n\n    if (this.isDrawingMode) {\n      this._onMouseDownInDrawingMode(e);\n      return;\n    }\n\n    if (!this._isMainEvent(e)) {\n      return;\n    }\n\n    // ignore if some object is being transformed at this moment\n    if (this._currentTransform) {\n      return;\n    }\n\n    let shouldRender = this._shouldRender(target);\n    let grouped = false;\n    if (this.handleMultiSelection(e, target)) {\n      // active object might have changed while grouping\n      target = this._activeObject;\n      grouped = true;\n      shouldRender = true;\n    } else if (this._shouldClearSelection(e, target)) {\n      this.discardActiveObject(e);\n    }\n    // we start a group selector rectangle if\n    // selection is enabled\n    // and there is no target, or the following 3 conditions are satisfied:\n    // target is not selectable ( otherwise we selected it )\n    // target is not editing\n    // target is not already selected ( otherwise we drag )\n    if (\n      this.selection &&\n      (!target ||\n        (!target.selectable &&\n          !(target as IText).isEditing &&\n          target !== this._activeObject))\n    ) {\n      const p = this.getScenePoint(e);\n      this._groupSelector = {\n        x: p.x,\n        y: p.y,\n        deltaY: 0,\n        deltaX: 0,\n      };\n    }\n\n    // check again because things could have changed\n    alreadySelected = !!target && target === this._activeObject;\n    if (target) {\n      if (target.selectable && target.activeOn === 'down') {\n        this.setActiveObject(target, e);\n      }\n      const handle = target.findControl(\n        this.getViewportPoint(e),\n        isTouchEvent(e),\n      );\n      if (target === this._activeObject && (handle || !grouped)) {\n        this._setupCurrentTransform(e, target, alreadySelected);\n        const control = handle ? handle.control : undefined,\n          pointer = this.getScenePoint(e),\n          mouseDownHandler =\n            control && control.getMouseDownHandler(e, target, control);\n        mouseDownHandler &&\n          mouseDownHandler.call(\n            control,\n            e,\n            this._currentTransform!,\n            pointer.x,\n            pointer.y,\n          );\n      }\n    }\n    //  we clear `_objectsToRender` in case of a change in order to repopulate it at rendering\n    //  run before firing the `down` event to give the dev a chance to populate it themselves\n    shouldRender && (this._objectsToRender = undefined);\n    this._handleEvent(e, 'down', { alreadySelected: alreadySelected });\n    // we must renderAll so that we update the visuals\n    shouldRender && this.requestRenderAll();\n  }\n\n  /**\n   * reset cache form common information needed during event processing\n   * @private\n   */\n  _resetTransformEventData() {\n    this._targetInfo = this._viewportPoint = this._scenePoint = undefined;\n  }\n\n  /**\n   * Cache common information needed during event processing\n   * @private\n   * @param {Event} e Event object fired on event\n   */\n  _cacheTransformEventData(e: TPointerEvent) {\n    // reset in order to avoid stale caching\n    this._resetTransformEventData();\n    this._viewportPoint = this.getViewportPoint(e);\n    this._scenePoint = sendPointToPlane(\n      this._viewportPoint,\n      undefined,\n      this.viewportTransform,\n    );\n    this._targetInfo = this.findTarget(e);\n    // TODO: investigate better if this can be made less implicit in the code\n    if (this._currentTransform) {\n      this._targetInfo.target = this._currentTransform.target;\n    }\n  }\n\n  /**\n   * Method that defines the actions when mouse is hovering the canvas.\n   * The currentTransform parameter will define whether the user is rotating/scaling/translating\n   * an image or neither of them (only hovering). A group selection is also possible and would cancel\n   * all any other type of action.\n   * In case of an image transformation only the top canvas will be rendered.\n   * @private\n   * @param {Event} e Event object fired on mousemove\n   */\n  __onMouseMove(e: TPointerEvent) {\n    this._isClick = false;\n    this._handleEvent(e, 'move:before');\n\n    if (this.isDrawingMode) {\n      this._onMouseMoveInDrawingMode(e);\n      return;\n    }\n\n    if (!this._isMainEvent(e)) {\n      return;\n    }\n\n    const groupSelector = this._groupSelector;\n\n    // We initially clicked in an empty area, so we draw a box for multiple selection\n    if (groupSelector) {\n      const pointer = this.getScenePoint(e);\n\n      groupSelector.deltaX = pointer.x - groupSelector.x;\n      groupSelector.deltaY = pointer.y - groupSelector.y;\n\n      this.renderTop();\n    } else if (!this._currentTransform) {\n      const { target } = this.findTarget(e);\n      this._setCursorFromEvent(e, target);\n      this._fireOverOutEvents(e, target);\n    } else {\n      this._transformObject(e);\n    }\n    this.textEditingManager.onMouseMove(e);\n    this._handleEvent(e, 'move');\n  }\n\n  /**\n   * Manage the mouseout, mouseover events for the fabric object on the canvas\n   * @param {Fabric.Object} target the target where the target from the mousemove event\n   * @param {Event} e Event object fired on mousemove\n   * @private\n   */\n  _fireOverOutEvents(e: TPointerEvent, target?: FabricObject) {\n    const { _hoveredTarget, _hoveredTargets } = this,\n      { subTargets, currentTarget: actualTarget } = this.findTarget(e),\n      length = Math.max(_hoveredTargets.length, subTargets.length);\n\n    this.fireSyntheticInOutEvents('mouse', {\n      e,\n      target,\n      oldTarget: _hoveredTarget,\n      actualTarget,\n      oldActualTarget: this._hoveredActualTarget,\n      fireCanvas: true,\n    });\n    for (let i = 0; i < length; i++) {\n      if (\n        subTargets[i] === target ||\n        (_hoveredTargets[i] && _hoveredTargets[i] === _hoveredTarget)\n      ) {\n        continue;\n      }\n      this.fireSyntheticInOutEvents('mouse', {\n        e,\n        target: subTargets[i],\n        oldTarget: _hoveredTargets[i],\n      });\n    }\n    this._hoveredActualTarget = actualTarget;\n    this._hoveredTarget = target;\n    this._hoveredTargets = subTargets;\n  }\n\n  /**\n   * Manage the dragEnter, dragLeave events for the fabric objects on the canvas\n   * @param {Fabric.Object} target the target where the target from the onDrag event\n   * @param {Object} data Event object fired on dragover\n   * @private\n   */\n  _fireEnterLeaveEvents(\n    e: TPointerEvent,\n    target: FabricObject | undefined,\n    data: DragEventData,\n  ) {\n    const draggedoverTarget = this._draggedoverTarget,\n      _hoveredTargets = this._hoveredTargets,\n      { subTargets } = this.findTarget(e),\n      length = Math.max(_hoveredTargets.length, subTargets.length);\n\n    this.fireSyntheticInOutEvents('drag', {\n      ...data,\n      target,\n      oldTarget: draggedoverTarget,\n      fireCanvas: true,\n    });\n    for (let i = 0; i < length; i++) {\n      this.fireSyntheticInOutEvents('drag', {\n        ...data,\n        target: subTargets[i],\n        oldTarget: _hoveredTargets[i],\n      });\n    }\n    this._draggedoverTarget = target;\n  }\n\n  /**\n   * Manage the synthetic in/out events for the fabric objects on the canvas\n   * @param {Fabric.Object} target the target where the target from the supported events\n   * @param {Object} data Event object fired\n   * @param {Object} config configuration for the function to work\n   * @param {String} config.targetName property on the canvas where the old target is stored\n   * @param {String} [config.canvasEvtOut] name of the event to fire at canvas level for out\n   * @param {String} config.evtOut name of the event to fire for out\n   * @param {String} [config.canvasEvtIn] name of the event to fire at canvas level for in\n   * @param {String} config.evtIn name of the event to fire for in\n   * @private\n   */\n  fireSyntheticInOutEvents<T extends keyof TSyntheticEventContext>(\n    type: T,\n    {\n      target,\n      oldTarget,\n      actualTarget,\n      oldActualTarget,\n      fireCanvas,\n      e,\n      ...data\n    }: TSyntheticEventContext[T] & {\n      target?: FabricObject;\n      oldTarget?: FabricObject;\n      actualTarget?: FabricObject;\n      oldActualTarget?: FabricObject;\n      fireCanvas?: boolean;\n    },\n  ) {\n    const { targetIn, targetOut, canvasIn, canvasOut } =\n      syntheticEventConfig[type];\n    const targetChanged = oldTarget !== target;\n    const actualTargetChanged = oldActualTarget !== actualTarget;\n    const targetFires = target && targetChanged;\n    const actualTargetFires = actualTarget && actualTargetChanged;\n    const oldTargetFires = oldTarget && targetChanged;\n    const oldActualTargetFires = oldActualTarget && actualTargetChanged;\n    const commonData = {\n      ...data,\n      e,\n      ...getEventPoints(this, e),\n    };\n\n    const outOpt: CanvasEvents[typeof canvasOut] = {\n      ...commonData,\n      target: oldTarget,\n      nextTarget: target,\n      actualTarget: oldActualTarget,\n      nextActualTarget: actualTarget,\n    };\n    if (oldTargetFires || oldActualTargetFires) {\n      fireCanvas && this.fire(canvasOut, outOpt);\n    }\n    oldTargetFires && oldTarget.fire(targetOut, outOpt);\n    oldActualTargetFires &&\n      oldTarget !== oldActualTarget &&\n      oldActualTarget.fire(targetOut, outOpt);\n\n    const inOpt: CanvasEvents[typeof canvasIn] = {\n      ...commonData,\n      target,\n      previousTarget: oldTarget,\n      actualTarget,\n      previousActualTarget: oldActualTarget,\n    };\n    if (targetFires || actualTargetFires) {\n      fireCanvas && this.fire(canvasIn, inOpt);\n    }\n    targetFires && target.fire(targetIn, inOpt);\n    actualTargetFires &&\n      actualTarget !== target &&\n      actualTarget.fire(targetIn, inOpt);\n  }\n\n  /**\n   * @private\n   * @param {Event} e Event fired on mousemove\n   */\n  _transformObject(e: TPointerEvent) {\n    const scenePoint = this.getScenePoint(e),\n      transform = this._currentTransform!,\n      target = transform.target,\n      //  transform pointer to target's containing coordinate plane\n      //  both pointer and object should agree on every point\n      localPointer = target.group\n        ? sendPointToPlane(\n            scenePoint,\n            undefined,\n            target.group.calcTransformMatrix(),\n          )\n        : scenePoint;\n    transform.shiftKey = e.shiftKey;\n    transform.altKey = !!this.centeredKey && e[this.centeredKey];\n\n    this._performTransformAction(e, transform, localPointer);\n    transform.actionPerformed && this.requestRenderAll();\n  }\n\n  /**\n   * @private\n   */\n  _performTransformAction(\n    e: TPointerEvent,\n    transform: Transform,\n    pointer: Point,\n  ) {\n    const { action, actionHandler, target } = transform;\n\n    const actionPerformed =\n      !!actionHandler && actionHandler(e, transform, pointer.x, pointer.y);\n    actionPerformed && target.setCoords();\n\n    // this object could be created from the function in the control handlers\n    if (action === 'drag' && actionPerformed) {\n      transform.target.isMoving = true;\n      this.setCursor(transform.target.moveCursor || this.moveCursor);\n    }\n    transform.actionPerformed = transform.actionPerformed || actionPerformed;\n  }\n\n  /**\n   * Sets the cursor depending on where the canvas is being hovered.\n   * Note: very buggy in Opera\n   * @param {Event} e Event object\n   * @param {Object} target Object that the mouse is hovering, if so.\n   */\n  _setCursorFromEvent(e: TPointerEvent, target?: FabricObject) {\n    if (!target) {\n      this.setCursor(this.defaultCursor);\n      return;\n    }\n    let hoverCursor = target.hoverCursor || this.hoverCursor;\n    const activeSelection = isActiveSelection(this._activeObject)\n        ? this._activeObject\n        : null,\n      // only show proper corner when group selection is not active\n      corner =\n        (!activeSelection || target.group !== activeSelection) &&\n        // here we call findTargetCorner always with undefined for the touch parameter.\n        // we assume that if you are using a cursor you do not need to interact with\n        // the bigger touch area.\n        target.findControl(this.getViewportPoint(e));\n\n    if (!corner) {\n      if ((target as Group).subTargetCheck) {\n        // hoverCursor should come from top-most subTarget,\n        // so we walk the array backwards\n        const { subTargets } = this.findTarget(e);\n        subTargets\n          .concat()\n          .reverse()\n          .forEach((_target) => {\n            hoverCursor = _target.hoverCursor || hoverCursor;\n          });\n      }\n      this.setCursor(hoverCursor);\n    } else {\n      const { control, coord } = corner;\n      this.setCursor(control.cursorStyleHandler(e, control, target, coord));\n    }\n  }\n\n  /**\n   * ## Handles multiple selection\n   * - toggles `target` selection (selects/deselects `target` if it isn't/is selected respectively)\n   * - sets the active object in case it is not set or in case there is a single active object left under active selection.\n   * ---\n   * - If the active object is the active selection we add/remove `target` from it\n   * - If not, add the active object and `target` to the active selection and make it the active object.\n   * @TODO rewrite this after find target is refactored\n   * @private\n   * @param {TPointerEvent} e Event object\n   * @param {FabricObject} target target of event to select/deselect\n   * @returns true if grouping occurred\n   */\n  protected handleMultiSelection(e: TPointerEvent, target?: FabricObject) {\n    const activeObject = this._activeObject;\n    const isAS = isActiveSelection(activeObject);\n    if (\n      // check if an active object exists on canvas and if the user is pressing the `selectionKey` while canvas supports multi selection.\n      !!activeObject &&\n      this._isSelectionKeyPressed(e) &&\n      this.selection &&\n      // on top of that the user also has to hit a target that is selectable.\n      !!target &&\n      target.selectable &&\n      // group target and active object only if they are different objects\n      // else we try to find a subtarget of `ActiveSelection`\n      (activeObject !== target || isAS) &&\n      //  make sure `activeObject` and `target` aren't ancestors of each other in case `activeObject` is not `ActiveSelection`\n      // if it is then we want to remove `target` from it\n      (isAS ||\n        (!target.isDescendantOf(activeObject) &&\n          !activeObject.isDescendantOf(target))) &&\n      //  target accepts selection\n      !target.onSelect({ e }) &&\n      // make sure we are not on top of a control\n      !activeObject.getActiveControl()\n    ) {\n      if (isAS) {\n        const prevActiveObjects = activeObject.getObjects();\n        let subTargets: FabricObject[] = [];\n        // const { subTargets: testSubTargets } = this.findTarget(e);\n        if (target === activeObject) {\n          const pointer = this.getScenePoint(e);\n          let targetInfo = this.searchPossibleTargets(\n            prevActiveObjects,\n            pointer,\n          );\n          // console.log(testSubTargets.includes(targetInfo.target));\n          if (targetInfo.target) {\n            target = targetInfo.target;\n            subTargets = targetInfo.subTargets;\n          } else {\n            targetInfo = this.searchPossibleTargets(this._objects, pointer);\n            target = targetInfo.target;\n            subTargets = targetInfo.subTargets;\n          }\n          // if nothing is found bail out\n          if (!target || !target.selectable) {\n            return false;\n          }\n        }\n        if (target.group === activeObject) {\n          // `target` is part of active selection => remove it\n          activeObject.remove(target);\n          this._hoveredTarget = target;\n          this._hoveredTargets = subTargets;\n          // if after removing an object we are left with one only...\n          if (activeObject.size() === 1) {\n            // activate last remaining object\n            // deselecting the active selection will remove the remaining object from it\n            this._setActiveObject(activeObject.item(0), e);\n          }\n        } else {\n          // `target` isn't part of active selection => add it\n          activeObject.multiSelectAdd(target);\n          this._hoveredTarget = activeObject;\n          this._hoveredTargets = subTargets;\n        }\n        this._fireSelectionEvents(prevActiveObjects, e);\n      } else {\n        (activeObject as IText).isEditing &&\n          (activeObject as IText).exitEditing();\n        // add the active object and the target to the active selection and set it as the active object\n        const klass =\n          classRegistry.getClass<typeof ActiveSelection>('ActiveSelection');\n        const newActiveSelection = new klass([], {\n          /**\n           * it is crucial to pass the canvas ref before calling {@link ActiveSelection#multiSelectAdd}\n           * since it uses {@link FabricObject#isInFrontOf} which relies on the canvas ref\n           */\n          canvas: this,\n        });\n        newActiveSelection.multiSelectAdd(activeObject, target);\n        this._hoveredTarget = newActiveSelection;\n        // ISSUE 4115: should we consider subTargets here?\n        // this._hoveredTargets = [];\n        // this._hoveredTargets = this.targets.concat();\n        this._setActiveObject(newActiveSelection, e);\n        this._fireSelectionEvents([activeObject], e);\n      }\n      return true;\n    }\n    return false;\n  }\n\n  /**\n   * ## Handles selection\n   * - selects objects that are contained in (and possibly intersecting) the selection bounding box\n   * - sets the active object\n   * ---\n   * runs on mouse up after a mouse move\n   */\n  protected handleSelection(e: TPointerEvent) {\n    if (!this.selection || !this._groupSelector) {\n      return false;\n    }\n    const { x, y, deltaX, deltaY } = this._groupSelector,\n      point1 = new Point(x, y),\n      point2 = point1.add(new Point(deltaX, deltaY)),\n      tl = point1.min(point2),\n      br = point1.max(point2),\n      size = br.subtract(tl);\n\n    const collectedObjects = this.collectObjects(\n      {\n        left: tl.x,\n        top: tl.y,\n        width: size.x,\n        height: size.y,\n      },\n      { includeIntersecting: !this.selectionFullyContained },\n    ) as FabricObject[];\n\n    const objects =\n      // though this method runs only after mouse move the pointer could do a mouse up on the same position as mouse down\n      // should it be handled as is?\n      point1.eq(point2)\n        ? collectedObjects[0]\n          ? [collectedObjects[0]]\n          : []\n        : collectedObjects.length > 1\n          ? collectedObjects\n              .filter((object) => !object.onSelect({ e }))\n              .reverse()\n          : // `setActiveObject` will call `onSelect(collectedObjects[0])` in this case\n            collectedObjects;\n\n    // set active object\n    if (objects.length === 1) {\n      // set as active object\n      this.setActiveObject(objects[0], e);\n    } else if (objects.length > 1) {\n      // add to active selection and make it the active object\n      const klass =\n        classRegistry.getClass<typeof ActiveSelection>('ActiveSelection');\n      this.setActiveObject(new klass(objects, { canvas: this }), e);\n    }\n\n    // cleanup\n    this._groupSelector = null;\n    return true;\n  }\n\n  /**\n   * Wraps the original toCanvasElement with a function that removes\n   * the context top for the time the function is run.\n   * So we avoid painting side effects on the upper canvas when exporting\n   */\n  toCanvasElement(\n    multiplier = 1,\n    options?: TToCanvasElementOptions,\n  ): HTMLCanvasElement {\n    const { upper } = this.elements;\n    upper.ctx = undefined as unknown as CanvasRenderingContext2D;\n    const htmlElement = super.toCanvasElement(multiplier, options);\n    upper.ctx = upper.el.getContext('2d')!;\n    return htmlElement;\n  }\n\n  /**\n   * @override clear {@link textEditingManager}\n   */\n  clear() {\n    this.textEditingManager.clear();\n    super.clear();\n  }\n\n  /**\n   * @override clear {@link textEditingManager}\n   */\n  destroy() {\n    this.removeListeners();\n    this.textEditingManager.dispose();\n    super.destroy();\n  }\n}\n"],"mappings":"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"}