fabric
Version:
Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.
1 lines • 75.4 kB
Source Map (JSON)
{"version":3,"file":"Canvas.min.mjs","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 } = this.findTarget(e),\n length = Math.max(_hoveredTargets.length, subTargets.length);\n\n this.fireSyntheticInOutEvents('mouse', {\n e,\n target,\n oldTarget: _hoveredTarget,\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._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 fireCanvas,\n e,\n ...data\n }: TSyntheticEventContext[T] & {\n target?: FabricObject;\n oldTarget?: FabricObject;\n fireCanvas?: boolean;\n },\n ) {\n const { targetIn, targetOut, canvasIn, canvasOut } =\n syntheticEventConfig[type];\n const targetChanged = oldTarget !== target;\n\n if (oldTarget && targetChanged) {\n const outOpt: CanvasEvents[typeof canvasOut] = {\n ...data,\n e,\n target: oldTarget,\n nextTarget: target,\n ...getEventPoints(this, e),\n };\n fireCanvas && this.fire(canvasOut, outOpt);\n oldTarget.fire(targetOut, outOpt);\n }\n if (target && targetChanged) {\n const inOpt: CanvasEvents[typeof canvasIn] = {\n ...data,\n e,\n target,\n previousTarget: oldTarget,\n ...getEventPoints(this, e),\n };\n fireCanvas && this.fire(canvasIn, inOpt);\n target.fire(targetIn, inOpt);\n }\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"],"names":["addEventOptions","passive","getEventPoints","canvas","e","viewportPoint","getViewportPoint","scenePoint","getScenePoint","addListener","el","_len","arguments","length","args","Array","_key","addEventListener","removeListener","_len2","_key2","removeEventListener","syntheticEventConfig","mouse","in","out","targetIn","targetOut","canvasIn","canvasOut","drag","Canvas","SelectableCanvas","constructor","super","undefined","_defineProperty","this","TextEditingManager","forEach","eventHandler","bind","addOrRemove","_getEventPrefix","enablePointerEvents","functor","forTouch","canvasElement","upperCanvasEl","eventTypePrefix","getWindowFromElement","_onResize","_onMouseDown","_onMouseMove","_onMouseOut","_onMouseEnter","_onMouseWheel","_onContextMenu","_onClick","_onDragStart","_onDragEnd","_onDragOver","_onDragEnter","_onDragLeave","_onDrop","_onTouchStart","removeListeners","doc","getDocumentFromElement","_onMouseUp","_onTouchEnd","clearTimeout","_willAddMouseDown","_cacheTransformEventData","_handleEvent","_resetTransformEventData","target","_hoveredTarget","shared","fire","_hoveredTargets","nestedTarget","findTarget","_currentTransform","_isClick","activeObject","getActiveObject","onDragStart","_dragSource","options","_onDragProgress","stopEvent","_renderDragEffects","source","dirty","dropTarget","_dropTarget","clearContextTop","ctx","contextTop","save","transform","viewportTransform","renderDragSourceEffect","restore","renderDropTargetEffect","contextTopDirty","currentSubTargets","didDrop","dataTransfer","dropEffect","NONE","_activeObject","subTargets","dragSource","_draggedoverTarget","eventType","currentContainer","canDrop","_fireEnterLeaveEvents","i","subTarget","_basicEventHandler","stopContextMenu","clicks","detail","type","fireEventFromPointerEvent","eventName","secondaryName","extraData","getPointerId","evt","changedTouches","identifier","pointerId","_isMainEvent","isPrimary","touches","mainTouchId","shouldPreventScrolling","allowTouchScrolling","currentActiveObject","__onMouseDown","isDrawingMode","preventDefault","__onMouseUp","setTimeout","shouldStartDragging","__onMouseMove","calcOffset","_shouldRender","_this$_activeObject","isClick","button","fireMiddleClick","fireRightClick","_isCurrentlyDrawing","_onMouseUpInDrawingMode","pointer","corner","shouldRender","_finalizeCurrentTransform","actionPerformed","targetWasActive","handleSelection","found","findControl","isTouchEvent","key","control","selectable","activeOn","setActiveObject","mouseUpHandler","getMouseUpHandler","call","x","y","isMoving","originalControl","controls","originalMouseUpHandler","_setCursorFromEvent","_groupSelector","__corner","requestRenderAll","isEditing","renderTop","_onMouseDownInDrawingMode","discardActiveObject","freeDrawingBrush","onMouseDown","alreadySelected","_onMouseMoveInDrawingMode","onMouseMove","setCursor","freeDrawingCursor","onMouseUp","grouped","handleMultiSelection","_shouldClearSelection","selection","p","deltaY","deltaX","handle","_setupCurrentTransform","mouseDownHandler","getMouseDownHandler","_objectsToRender","_targetInfo","_viewportPoint","_scenePoint","sendPointToPlane","groupSelector","_transformObject","_fireOverOutEvents","textEditingManager","Math","max","fireSyntheticInOutEvents","oldTarget","fireCanvas","data","draggedoverTarget","_ref","targetChanged","outOpt","nextTarget","inOpt","previousTarget","localPointer","group","calcTransformMatrix","shiftKey","altKey","centeredKey","_performTransformAction","action","actionHandler","setCoords","moveCursor","defaultCursor","hoverCursor","activeSelection","isActiveSelection","coord","cursorStyleHandler","subTargetCheck","concat","reverse","_target","isAS","_isSelectionKeyPressed","isDescendantOf","onSelect","getActiveControl","prevActiveObjects","getObjects","targetInfo","searchPossibleTargets","_objects","remove","size","_setActiveObject","item","multiSelectAdd","_fireSelectionEvents","exitEditing","newActiveSelection","classRegistry","getClass","point1","Point","point2","add","tl","min","subtract","collectedObjects","collectObjects","left","top","width","height","includeIntersecting","selectionFullyContained","objects","eq","filter","object","klass","toCanvasElement","multiplier","upper","elements","htmlElement","getContext","clear","destroy","dispose"],"mappings":"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"}