{"version":3,"file":"InteractiveObject.min.mjs","sources":["../../../../src/shapes/Object/InteractiveObject.ts"],"sourcesContent":["import { Point, ZERO } from '../../Point';\nimport type { TCornerPoint, TDegree } from '../../typedefs';\nimport { FabricObject } from './Object';\nimport { degreesToRadians } from '../../util/misc/radiansDegreesConversion';\nimport type { TQrDecomposeOut } from '../../util/misc/matrix';\nimport {\n  calcDimensionsMatrix,\n  createRotateMatrix,\n  createTranslateMatrix,\n  multiplyTransformMatrices,\n  qrDecompose,\n} from '../../util/misc/matrix';\nimport type { Control } from '../../controls/Control';\nimport { sizeAfterTransform } from '../../util/misc/objectTransforms';\nimport type { ObjectEvents, TPointerEvent } from '../../EventTypeDefs';\nimport type { Canvas } from '../../canvas/Canvas';\nimport type { ControlRenderingStyleOverride } from '../../controls/controlRendering';\nimport type { FabricObjectProps } from './types/FabricObjectProps';\nimport type { TFabricObjectProps, SerializedObjectProps } from './types';\nimport { createObjectDefaultControls } from '../../controls/commonControls';\nimport { interactiveObjectDefaultValues } from './defaultValues';\n\nexport type TOCoord = Point & {\n  corner: TCornerPoint;\n  touchCorner: TCornerPoint;\n};\n\nexport type TControlSet = Record<string, Control>;\n\nexport type TBorderRenderingStyleOverride = Partial<\n  Pick<InteractiveFabricObject, 'borderColor' | 'borderDashArray'>\n>;\n\nexport type TStyleOverride = ControlRenderingStyleOverride &\n  TBorderRenderingStyleOverride &\n  Partial<\n    Pick<InteractiveFabricObject, 'hasBorders' | 'hasControls'> & {\n      forActiveSelection: boolean;\n    }\n  >;\n\nexport class InteractiveFabricObject<\n  Props extends TFabricObjectProps = Partial<FabricObjectProps>,\n  SProps extends SerializedObjectProps = SerializedObjectProps,\n  EventSpec extends ObjectEvents = ObjectEvents\n>\n  extends FabricObject<Props, SProps, EventSpec>\n  implements FabricObjectProps {\n\n\n\n  declare noScaleCache: boolean;\n\n  declare snapAngle?: TDegree;\n  declare snapThreshold?: TDegree;\n\n  declare lockMovementX: boolean;\n  declare lockMovementY: boolean;\n  declare lockRotation: boolean;\n  declare lockScalingX: boolean;\n  declare lockScalingY: boolean;\n  declare lockSkewingX: boolean;\n  declare lockSkewingY: boolean;\n  declare lockScalingFlip: boolean;\n\n  declare cornerSize: number;\n  declare touchCornerSize: number;\n  declare transparentCorners: boolean;\n  declare cornerColor: string;\n  declare cornerStrokeColor: string;\n  declare cornerStyle: 'rect' | 'circle';\n  declare cornerDashArray: number[] | null;\n  declare hasControls: boolean;\n\n  declare borderColor: string;\n  declare borderDashArray: number[] | null;\n  declare borderOpacityWhenMoving: number;\n  declare borderScaleFactor: number;\n  declare hasBorders: boolean;\n  declare selectionBackgroundColor: string;\n\n  declare selectable: boolean;\n  declare evented: boolean;\n  declare perPixelTargetFind: boolean;\n  declare activeOn: 'down' | 'up';\n\n  declare hoverCursor: CSSStyleDeclaration['cursor'] | null;\n  declare moveCursor: CSSStyleDeclaration['cursor'] | null;\n\n  /**\n   * The object's controls' position in viewport coordinates\n   * Calculated by {@link Control#positionHandler} and {@link Control#calcCornerCoords}, depending on {@link padding}.\n   * `corner/touchCorner` describe the 4 points forming the interactive area of the corner.\n   * Used to draw and locate controls.\n   */\n  declare oCoords: Record<string, TOCoord>;\n\n  /**\n   * keeps the value of the last hovered corner during mouse move.\n   * 0 is no corner, or 'mt', 'ml', 'mtr' etc..\n   * It should be private, but there is no harm in using it as\n   * a read-only property.\n   * this isn't cleaned automatically. Non selected objects may have wrong values\n   * @type [string]\n   */\n  declare __corner?: string;\n\n  /**\n   * a map of control visibility for this object.\n   * this was left when controls were introduced to not break the api too much\n   * this takes priority over the generic control visibility\n   */\n  declare _controlsVisibility: Record<string, boolean>;\n\n  /**\n   * holds the controls for the object.\n   * controls are added by default_controls.js\n   */\n  declare controls: TControlSet;\n\n  /**\n   * internal boolean to signal the code that the object is\n   * part of the move action.\n   */\n  declare isMoving?: boolean;\n\n  /**\n   * A boolean used from the gesture module to keep tracking of a scaling\n   * action when there is no scaling transform in place.\n   * This is an edge case and is used twice in all codebase.\n   * Probably added to keep track of some performance issues\n   * @TODO use git blame to investigate why it was added\n   * DON'T USE IT. WE WILL TRY TO REMOVE IT\n   */\n  declare _scaling?: boolean;\n\n  declare canvas?: Canvas;\n\n  static ownDefaults = interactiveObjectDefaultValues;\n\n  static getDefaults(): Record<string, any> {\n    return {\n      ...super.getDefaults(),\n      controls: createObjectDefaultControls(),\n      ...InteractiveFabricObject.ownDefaults,\n    };\n  }\n\n  /**\n   * Update width and height of the canvas for cache\n   * returns true or false if canvas needed resize.\n   * @private\n   * @return {Boolean} true if the canvas has been resized\n   */\n  _updateCacheCanvas() {\n    const targetCanvas = this.canvas;\n    if (this.noScaleCache && targetCanvas && targetCanvas._currentTransform) {\n      const transform = targetCanvas._currentTransform,\n        target = transform.target,\n        action = transform.action;\n      if (\n        this === (target as unknown as this) &&\n        action &&\n        action.startsWith('scale')\n      ) {\n        return false;\n      }\n    }\n    return super._updateCacheCanvas();\n  }\n\n  getActiveControl() {\n    const key = this.__corner;\n    return key\n      ? {\n        key,\n        control: this.controls[key],\n        coord: this.oCoords[key],\n      }\n      : undefined;\n  }\n\n  /**\n   * Determines which corner is under the mouse cursor, represented by `pointer`.\n   * This function is return a corner only if the object is the active one.\n   * This is done to avoid selecting corner of non active object and activating transformations\n   * rather than drag action. The default behavior of fabricJS is that if you want to transform\n   * an object, first you select it to show the control set\n   * @private\n   * @param {Object} pointer The pointer indicating the mouse position\n   * @param {boolean} forTouch indicates if we are looking for interaction area with a touch action\n   * @return {String|Boolean} corner code (tl, tr, bl, br, etc.), or 0 if nothing is found.\n   */\n  findControl(\n    pointer: Point,\n    forTouch = false\n  ): { key: string; control: Control; coord: TOCoord } | undefined {\n    if (!this.hasControls || !this.canvas) {\n      return undefined;\n    }\n\n    this.__corner = undefined;\n    const cornerEntries = Object.entries(this.oCoords);\n    for (let i = cornerEntries.length - 1; i >= 0; i--) {\n      const [key, corner] = cornerEntries[i];\n      const control = this.controls[key];\n\n      if (\n        control.shouldActivate(\n          key,\n          this,\n          pointer,\n          forTouch ? corner.touchCorner : corner.corner\n        )\n      ) {\n        // this.canvas.contextTop.fillRect(pointer.x - 1, pointer.y - 1, 2, 2);\n        this.__corner = key;\n\n        return { key, control, coord: this.oCoords[key] };\n      }\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Calculates the coordinates of the center of each control plus the corners of the control itself\n   * This basically just delegates to each control positionHandler\n   * WARNING: changing what is passed to positionHandler is a breaking change, since position handler\n   * is a public api and should be done just if extremely necessary\n   * @return {Record<string, TOCoord>}\n   */\n  calcOCoords(): Record<string, TOCoord> {\n    const vpt = this.getViewportTransform(),\n      center = this.getCenterPoint(),\n      tMatrix = createTranslateMatrix(center.x, center.y),\n      rMatrix = createRotateMatrix({\n        angle: this.getTotalAngle() - (!!this.group && this.flipX ? 180 : 0),\n      }),\n      positionMatrix = multiplyTransformMatrices(tMatrix, rMatrix),\n      startMatrix = multiplyTransformMatrices(vpt, positionMatrix),\n      finalMatrix = multiplyTransformMatrices(startMatrix, [\n        1 / vpt[0],\n        0,\n        0,\n        1 / vpt[3],\n        0,\n        0,\n      ]),\n      transformOptions = this.group\n        ? qrDecompose(this.calcTransformMatrix())\n        : undefined;\n    // decomposing could bring negative scaling and `_calculateCurrentDimensions` can't take it\n    if (transformOptions) {\n      transformOptions.scaleX = Math.abs(transformOptions.scaleX);\n      transformOptions.scaleY = Math.abs(transformOptions.scaleY);\n    }\n    const dim = this._calculateCurrentDimensions(transformOptions),\n      coords: Record<string, TOCoord> = {};\n\n    this.forEachControl((control, key) => {\n      const position = control.positionHandler(dim, finalMatrix, this, control);\n      // coords[key] are sometimes used as points. Those are points to which we add\n      // the property corner and touchCorner from `_calcCornerCoords`.\n      // don't remove this assign for an object spread.\n      coords[key] = Object.assign(\n        position,\n        this._calcCornerCoords(control, position)\n      );\n    });\n\n    // debug code\n    /*\n      const canvas = this.canvas;\n      setTimeout(function () {\n      if (!canvas) return;\n        canvas.contextTop.clearRect(0, 0, 700, 700);\n        canvas.contextTop.fillStyle = 'green';\n        Object.keys(coords).forEach(function(key) {\n          const control = coords[key];\n          canvas.contextTop.fillRect(control.x, control.y, 3, 3);\n        });\n      } 50);\n    */\n    return coords;\n  }\n\n  /**\n   * Sets the coordinates that determine the interaction area of each control\n   * note: if we would switch to ROUND corner area, all of this would disappear.\n   * everything would resolve to a single point and a pythagorean theorem for the distance\n   * @todo evaluate simplification of code switching to circle interaction area at runtime\n   * @private\n   */\n  private _calcCornerCoords(control: Control, position: Point) {\n    const angle = this.getTotalAngle();\n    const corner = control.calcCornerCoords(\n      angle,\n      this.cornerSize,\n      position.x,\n      position.y,\n      false,\n      this\n    );\n    const touchCorner = control.calcCornerCoords(\n      angle,\n      this.touchCornerSize,\n      position.x,\n      position.y,\n      true,\n      this\n    );\n    return { corner, touchCorner };\n  }\n\n  /**\n   * @override set controls' coordinates as well\n   * See {@link https://github.com/fabricjs/fabric.js/wiki/When-to-call-setCoords} and {@link http://fabricjs.com/fabric-gotchas}\n   * @return {void}\n   */\n  setCoords(): void {\n    super.setCoords();\n    this.canvas && (this.oCoords = this.calcOCoords());\n  }\n\n  /**\n   * Calls a function for each control. The function gets called,\n   * with the control, the control's key and the object that is calling the iterator\n   * @param {Function} fn function to iterate over the controls over\n   */\n  forEachControl(\n    fn: (\n      control: Control,\n      key: string,\n      fabricObject: InteractiveFabricObject\n    ) => any\n  ) {\n    for (const i in this.controls) {\n      fn(this.controls[i], i, this);\n    }\n  }\n\n  /**\n   * Draws a colored layer behind the object, inside its selection borders.\n   * Requires public options: padding, selectionBackgroundColor\n   * this function is called when the context is transformed\n   * has checks to be skipped when the object is on a staticCanvas\n   * @todo evaluate if make this disappear in favor of a pre-render hook for objects\n   * this was added by Andrea Bogazzi to make possible some feature for work reasons\n   * it seemed a good option, now is an edge case\n   * @param {CanvasRenderingContext2D} ctx Context to draw on\n   */\n  drawSelectionBackground(ctx: CanvasRenderingContext2D): void {\n    if (\n      !this.selectionBackgroundColor ||\n      (this.canvas && (this.canvas._activeObject as unknown as this) !== this)\n    ) {\n      return;\n    }\n    ctx.save();\n    const center = this.getRelativeCenterPoint(),\n      wh = this._calculateCurrentDimensions(),\n      vpt = this.getViewportTransform();\n    ctx.translate(center.x, center.y);\n    ctx.scale(1 / vpt[0], 1 / vpt[3]);\n    ctx.rotate(degreesToRadians(this.angle));\n    ctx.fillStyle = this.selectionBackgroundColor;\n    ctx.fillRect(-wh.x / 2, -wh.y / 2, wh.x, wh.y);\n    ctx.restore();\n  }\n\n  /**\n   * @public override this function in order to customize the drawing of the control box, e.g. rounded corners, different border style.\n   * @param {CanvasRenderingContext2D} ctx ctx is rotated and translated so that (0,0) is at object's center\n   * @param {Point} size the control box size used\n   */\n  strokeBorders(ctx: CanvasRenderingContext2D, size: Point): void {\n    ctx.strokeRect(-size.x / 2, -size.y / 2, size.x, size.y);\n  }\n\n  /**\n   * @private\n   * @param {CanvasRenderingContext2D} ctx Context to draw on\n   * @param {Point} size\n   * @param {TStyleOverride} styleOverride object to override the object style\n   */\n  _drawBorders(\n    ctx: CanvasRenderingContext2D,\n    size: Point,\n    styleOverride: TStyleOverride = {}\n  ): void {\n    const options = {\n      hasControls: this.hasControls,\n      borderColor: this.borderColor,\n      borderDashArray: this.borderDashArray,\n      ...styleOverride,\n    };\n    ctx.save();\n    ctx.strokeStyle = options.borderColor;\n    this._setLineDash(ctx, options.borderDashArray);\n    this.strokeBorders(ctx, size);\n    options.hasControls && this.drawControlsConnectingLines(ctx, size);\n    ctx.restore();\n  }\n\n  /**\n   * Renders controls and borders for the object\n   * the context here is not transformed\n   * @todo move to interactivity\n   * @param {CanvasRenderingContext2D} ctx Context to render on\n   * @param {TStyleOverride} [styleOverride] properties to override the object style\n   */\n  _renderControls(\n    ctx: CanvasRenderingContext2D,\n    styleOverride: TStyleOverride = {}\n  ) {\n    const { hasBorders, hasControls } = this;\n    const styleOptions = {\n      hasBorders,\n      hasControls,\n      ...styleOverride,\n    };\n    const vpt = this.getViewportTransform(),\n      shouldDrawBorders = styleOptions.hasBorders,\n      shouldDrawControls = styleOptions.hasControls;\n    const matrix = multiplyTransformMatrices(vpt, this.calcTransformMatrix());\n    const options = qrDecompose(matrix);\n    ctx.save();\n    ctx.translate(options.translateX, options.translateY);\n    ctx.lineWidth = 1 * this.borderScaleFactor;\n    // since interactive groups have been introduced, an object could be inside a group and needing controls\n    // the following equality check `this.group === this.parent` covers:\n    // object without a group ( undefined === undefined )\n    // object inside a group\n    // excludes object inside a group but multi selected since group and parent will differ in value\n    if (this.group === this.parent) {\n      ctx.globalAlpha = this.isMoving ? this.borderOpacityWhenMoving : 1;\n    }\n    if (this.flipX) {\n      options.angle -= 180;\n    }\n    ctx.rotate(degreesToRadians(this.group ? options.angle : this.angle));\n    shouldDrawBorders && this.drawBorders(ctx, options, styleOverride);\n    shouldDrawControls && this.drawControls(ctx, styleOverride);\n    ctx.restore();\n  }\n\n  /**\n   * Draws borders of an object's bounding box.\n   * Requires public properties: width, height\n   * Requires public options: padding, borderColor\n   * @param {CanvasRenderingContext2D} ctx Context to draw on\n   * @param {object} options object representing current object parameters\n   * @param {TStyleOverride} [styleOverride] object to override the object style\n   */\n  drawBorders(\n    ctx: CanvasRenderingContext2D,\n    options: TQrDecomposeOut,\n    styleOverride: TStyleOverride\n  ): void {\n    let size;\n    if ((styleOverride && styleOverride.forActiveSelection) || this.group) {\n      const bbox = sizeAfterTransform(\n        this.width,\n        this.height,\n        calcDimensionsMatrix(options)\n      ),\n        stroke = !this.isStrokeAccountedForInDimensions()\n          ? (this.strokeUniform\n            ? new Point().scalarAdd(this.canvas ? this.canvas.getZoom() : 1)\n            : // this is extremely confusing. options comes from the upper function\n            // and is the qrDecompose of a matrix that takes in account zoom too\n            new Point(options.scaleX, options.scaleY)\n          ).scalarMultiply(this.strokeWidth)\n          : ZERO;\n      size = bbox\n        .add(stroke)\n        .scalarAdd(this.borderScaleFactor)\n        .scalarAdd(this.padding * 2);\n    } else {\n      size = this._calculateCurrentDimensions().scalarAdd(\n        this.borderScaleFactor\n      );\n    }\n    this._drawBorders(ctx, size, styleOverride);\n  }\n\n  /**\n   * Draws lines from a borders of an object's bounding box to controls that have `withConnection` property set.\n   * Requires public properties: width, height\n   * Requires public options: padding, borderColor\n   * @param {CanvasRenderingContext2D} ctx Context to draw on\n   * @param {Point} size object size x = width, y = height\n   */\n  drawControlsConnectingLines(\n    ctx: CanvasRenderingContext2D,\n    size: Point\n  ): void {\n    let shouldStroke = false;\n\n    ctx.beginPath();\n    this.forEachControl((control, key) => {\n      // in this moment, the ctx is centered on the object.\n      // width and height of the above function are the size of the bbox.\n      if (control.withConnection && control.getVisibility(this, key)) {\n        // reset movement for each control\n        shouldStroke = true;\n        ctx.moveTo(control.x * size.x, control.y * size.y);\n        ctx.lineTo(\n          control.x * size.x + control.offsetX,\n          control.y * size.y + control.offsetY\n        );\n      }\n    });\n    shouldStroke && ctx.stroke();\n  }\n\n  /**\n   * Draws corners of an object's bounding box.\n   * Requires public properties: width, height\n   * Requires public options: cornerSize, padding\n   * @param {CanvasRenderingContext2D} ctx Context to draw on\n   * @param {ControlRenderingStyleOverride} styleOverride object to override the object style\n   */\n  drawControls(\n    ctx: CanvasRenderingContext2D,\n    styleOverride: ControlRenderingStyleOverride = {}\n  ) {\n    ctx.save();\n    const retinaScaling = this.getCanvasRetinaScaling();\n    const { cornerStrokeColor, cornerDashArray, cornerColor } = this;\n    const options = {\n      cornerStrokeColor,\n      cornerDashArray,\n      cornerColor,\n      ...styleOverride,\n    };\n    ctx.setTransform(retinaScaling, 0, 0, retinaScaling, 0, 0);\n    ctx.strokeStyle = ctx.fillStyle = options.cornerColor;\n    if (!this.transparentCorners) {\n      ctx.strokeStyle = options.cornerStrokeColor;\n    }\n    this._setLineDash(ctx, options.cornerDashArray);\n    this.setCoords();\n    this.forEachControl((control, key) => {\n      if (control.getVisibility(this, key)) {\n        const p = this.oCoords[key];\n        control.render(ctx, p.x, p.y, options, this);\n      }\n    });\n    ctx.restore();\n  }\n\n  /**\n   * Returns true if the specified control is visible, false otherwise.\n   * @param {string} controlKey The key of the control. Possible values are usually 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr',\n   * but since the control api allow for any control name, can be any string.\n   * @returns {boolean} true if the specified control is visible, false otherwise\n   */\n  isControlVisible(controlKey: string): boolean {\n    return (\n      this.controls[controlKey] &&\n      this.controls[controlKey].getVisibility(this, controlKey)\n    );\n  }\n\n  /**\n   * Sets the visibility of the specified control.\n   * please do not use.\n   * @param {String} controlKey The key of the control. Possible values are 'tl', 'tr', 'br', 'bl', 'ml', 'mt', 'mr', 'mb', 'mtr'.\n   * but since the control api allow for any control name, can be any string.\n   * @param {Boolean} visible true to set the specified control visible, false otherwise\n   * @todo discuss this overlap of priority here with the team. Andrea Bogazzi for details\n   */\n  setControlVisible(controlKey: string, visible: boolean) {\n    if (!this._controlsVisibility) {\n      this._controlsVisibility = {};\n    }\n    this._controlsVisibility[controlKey] = visible;\n  }\n\n  /**\n   * Sets the visibility state of object controls, this is just a bulk option for setControlVisible;\n   * @param {Record<string, boolean>} [options] with an optional key per control\n   * example: {Boolean} [options.bl] true to enable the bottom-left control, false to disable it\n   */\n  setControlsVisibility(options: Record<string, boolean> = {}) {\n    Object.entries(options).forEach(([controlKey, visibility]) =>\n      this.setControlVisible(controlKey, visibility)\n    );\n  }\n\n  /**\n   * Clears the canvas.contextTop in a specific area that corresponds to the object's bounding box\n   * that is in the canvas.contextContainer.\n   * This function is used to clear pieces of contextTop where we render ephemeral effects on top of the object.\n   * Example: blinking cursor text selection, drag effects.\n   * @todo discuss swapping restoreManually with a renderCallback, but think of async issues\n   * @param {Boolean} [restoreManually] When true won't restore the context after clear, in order to draw something else.\n   * @return {CanvasRenderingContext2D|undefined} canvas.contextTop that is either still transformed\n   * with the object transformMatrix, or restored to neutral transform\n   */\n  clearContextTop(\n    restoreManually?: boolean\n  ): CanvasRenderingContext2D | undefined {\n    if (!this.canvas) {\n      return;\n    }\n    const ctx = this.canvas.contextTop;\n    if (!ctx) {\n      return;\n    }\n    const v = this.canvas.viewportTransform;\n    ctx.save();\n    ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);\n    this.transform(ctx);\n    // we add 4 pixel, to be sure to do not leave any pixel out\n    const width = this.width + 4,\n      height = this.height + 4;\n    ctx.clearRect(-width / 2, -height / 2, width, height);\n\n    restoreManually || ctx.restore();\n    return ctx;\n  }\n\n  /**\n   * This callback function is called every time _discardActiveObject or _setActiveObject\n   * try to to deselect this object. If the function returns true, the process is cancelled\n   * @param {Object} [options] options sent from the upper functions\n   * @param {TPointerEvent} [options.e] event if the process is generated by an event\n   * @param {FabricObject} [options.object] next object we are setting as active, and reason why\n   * this is being deselected\n   */\n  onDeselect(options?: {\n    e?: TPointerEvent;\n    object?: InteractiveFabricObject;\n  }): boolean {\n    // implemented by sub-classes, as needed.\n    return false;\n  }\n\n  /**\n   * This callback function is called every time _discardActiveObject or _setActiveObject\n   * try to to select this object. If the function returns true, the process is cancelled\n   * @param {Object} [options] options sent from the upper functions\n   * @param {Event} [options.e] event if the process is generated by an event\n   */\n  onSelect(options?: { e?: TPointerEvent }): boolean {\n    // implemented by sub-classes, as needed.\n    return false;\n  }\n\n  /**\n   * Override to customize Drag behavior\n   * Fired from {@link Canvas#_onMouseMove}\n   * @returns true in order for the window to start a drag session\n   */\n  shouldStartDragging(e: TPointerEvent) {\n    return false;\n  }\n\n  /**\n   * Override to customize Drag behavior\\\n   * Fired once a drag session has started\n   * @returns true to handle the drag event\n   */\n  onDragStart(e: DragEvent) {\n    return false;\n  }\n\n  /**\n   * Override to customize drag and drop behavior\n   * @public\n   * @param {DragEvent} e\n   * @returns {boolean} true if the object currently dragged can be dropped on the target\n   */\n  canDrop(e: DragEvent): boolean {\n    return false;\n  }\n\n  /**\n   * Override to customize drag and drop behavior\n   * render a specific effect when an object is the source of a drag event\n   * example: render the selection status for the part of text that is being dragged from a text object\n   * @public\n   * @param {DragEvent} e\n   */\n  renderDragSourceEffect(e: DragEvent) {\n    // for subclasses\n  }\n\n  /**\n   * Override to customize drag and drop behavior\n   * render a specific effect when an object is the target of a drag event\n   * used to show that the underly object can receive a drop, or to show how the\n   * object will change when dropping. example: show the cursor where the text is about to be dropped\n   * @public\n   * @param {DragEvent} e\n   */\n  renderDropTargetEffect(e: DragEvent) {\n    // for subclasses\n  }\n}\n"],"names":["InteractiveFabricObject","FabricObject","getDefaults","_objectSpread","super","controls","createObjectDefaultControls","ownDefaults","_updateCacheCanvas","targetCanvas","this","canvas","noScaleCache","_currentTransform","transform","target","action","startsWith","getActiveControl","key","__corner","control","coord","oCoords","undefined","findControl","pointer","forTouch","arguments","length","hasControls","cornerEntries","Object","entries","i","corner","shouldActivate","touchCorner","calcOCoords","vpt","getViewportTransform","center","getCenterPoint","tMatrix","createTranslateMatrix","x","y","rMatrix","createRotateMatrix","angle","getTotalAngle","group","flipX","positionMatrix","multiplyTransformMatrices","startMatrix","finalMatrix","transformOptions","qrDecompose","calcTransformMatrix","scaleX","Math","abs","scaleY","dim","_calculateCurrentDimensions","coords","forEachControl","position","positionHandler","assign","_calcCornerCoords","calcCornerCoords","cornerSize","touchCornerSize","setCoords","fn","drawSelectionBackground","ctx","selectionBackgroundColor","_activeObject","save","getRelativeCenterPoint","wh","translate","scale","rotate","degreesToRadians","fillStyle","fillRect","restore","strokeBorders","size","strokeRect","_drawBorders","styleOverride","options","borderColor","borderDashArray","strokeStyle","_setLineDash","drawControlsConnectingLines","_renderControls","hasBorders","styleOptions","shouldDrawBorders","shouldDrawControls","matrix","translateX","translateY","lineWidth","borderScaleFactor","parent","globalAlpha","isMoving","borderOpacityWhenMoving","drawBorders","drawControls","forActiveSelection","bbox","sizeAfterTransform","width","height","calcDimensionsMatrix","stroke","isStrokeAccountedForInDimensions","ZERO","strokeUniform","Point","scalarAdd","getZoom","scalarMultiply","strokeWidth","add","padding","shouldStroke","beginPath","withConnection","getVisibility","moveTo","lineTo","offsetX","offsetY","retinaScaling","getCanvasRetinaScaling","cornerStrokeColor","cornerDashArray","cornerColor","setTransform","transparentCorners","p","render","isControlVisible","controlKey","setControlVisible","visible","_controlsVisibility","setControlsVisibility","forEach","_ref","visibility","clearContextTop","restoreManually","contextTop","v","viewportTransform","clearRect","onDeselect","onSelect","shouldStartDragging","e","onDragStart","canDrop","renderDragSourceEffect","renderDropTargetEffect","_defineProperty","interactiveObjectDefaultValues"],"mappings":"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"}