{"version":3,"file":"index.cjs","names":[],"sources":["../../core/src/utils/drawRoundedRect.ts","../../core/src/utils/drawGrid.ts","../../core/src/utils/loadImageURL.ts","../../core/src/utils/loadImageFile.ts","../../core/src/utils/isFileAPISupported.ts","../../core/src/AvatarEditor.ts","../../core/src/utils/isPassiveSupported.ts","../src/index.ts"],"sourcesContent":["/**\n * Draws a rounded rectangle on a 2D context.\n */\nexport const drawRoundedRect = (\n  context: CanvasRenderingContext2D,\n  x: number,\n  y: number,\n  width: number,\n  height: number,\n  borderRadius: number,\n) => {\n  if (borderRadius === 0) {\n    context.rect(x, y, width, height)\n  } else {\n    const widthMinusRad = width - borderRadius\n    const heightMinusRad = height - borderRadius\n    context.translate(x, y)\n    context.arc(\n      borderRadius,\n      borderRadius,\n      borderRadius,\n      Math.PI,\n      Math.PI * 1.5,\n    )\n    context.lineTo(widthMinusRad, 0)\n    context.arc(\n      widthMinusRad,\n      borderRadius,\n      borderRadius,\n      Math.PI * 1.5,\n      Math.PI * 2,\n    )\n    context.lineTo(width, heightMinusRad)\n    context.arc(\n      widthMinusRad,\n      heightMinusRad,\n      borderRadius,\n      Math.PI * 2,\n      Math.PI * 0.5,\n    )\n    context.lineTo(borderRadius, height)\n    context.arc(\n      borderRadius,\n      heightMinusRad,\n      borderRadius,\n      Math.PI * 0.5,\n      Math.PI,\n    )\n    context.closePath()\n    context.translate(-x, -y)\n  }\n}\n","/**\n * Draws a \"Rule of Three\" grid on the canvas.\n */\nexport const drawGrid = (\n  context: CanvasRenderingContext2D,\n  x: number,\n  y: number,\n  width: number,\n  height: number,\n  gridColor: string,\n) => {\n  context.fillStyle = gridColor\n  const thirdsX = width / 3\n  const thirdsY = height / 3\n\n  // vertical bars\n  context.fillRect(x, y, 1, height)\n  context.fillRect(thirdsX + x, y, 1, height)\n  context.fillRect(thirdsX * 2 + x, y, 1, height)\n  context.fillRect(thirdsX * 3 + x, y, 1, height)\n  context.fillRect(thirdsX * 4 + x, y, 1, height)\n\n  // horizontal bars\n  context.fillRect(x, y, width, 1)\n  context.fillRect(x, thirdsY + y, width, 1)\n  context.fillRect(x, thirdsY * 2 + y, width, 1)\n  context.fillRect(x, thirdsY * 3 + y, width, 1)\n  context.fillRect(x, thirdsY * 4 + y, width, 1)\n}\n","const isDataURL = (str: string) => {\n  const regex =\n    /^\\s*data:([a-z]+\\/[a-z]+(;[a-z-]+=[a-z-]+)?)?(;base64)?,[a-z0-9!$&',()*+;=\\-._~:@/?%\\s]*\\s*$/i\n  return !!str.match(regex)\n}\n\nexport const loadImageURL = (imageURL: string, crossOrigin?: string) =>\n  new Promise<HTMLImageElement>((resolve, reject) => {\n    const image = new Image()\n    image.addEventListener('load', () => resolve(image))\n    image.addEventListener('error', reject)\n    if (!isDataURL(imageURL) && crossOrigin) {\n      image.crossOrigin = crossOrigin\n    }\n    image.src = imageURL\n  })\n","import { loadImageURL } from './loadImageURL'\n\nexport const loadImageFile = (file: File) =>\n  new Promise<HTMLImageElement>((resolve, reject) => {\n    const reader = new FileReader()\n    reader.addEventListener('load', (e) => {\n      try {\n        if (!e?.target?.result) {\n          throw new Error('No image data')\n        }\n        const image = loadImageURL(e.target.result as string)\n        resolve(image)\n      } catch (err) {\n        reject(err)\n      }\n    })\n    reader.readAsDataURL(file)\n  })\n","export const isFileAPISupported = typeof File !== 'undefined'\n","import type {\n  ImageState,\n  Position,\n  AvatarEditorConfig,\n  Dimensions,\n  CroppingRect,\n} from './types'\nimport { drawRoundedRect } from './utils/drawRoundedRect'\nimport { drawGrid } from './utils/drawGrid'\nimport { loadImageURL } from './utils/loadImageURL'\nimport { loadImageFile } from './utils/loadImageFile'\nimport { isFileAPISupported } from './utils/isFileAPISupported'\n\nconst toRadians = (degree: number) => degree * (Math.PI / 180)\n\nconst defaultEmptyImage: ImageState = {\n  x: 0.5,\n  y: 0.5,\n}\n\nexport class AvatarEditorCore {\n  private config: Required<AvatarEditorConfig>\n  private imageState: ImageState = defaultEmptyImage\n  private pixelRatio: number\n\n  constructor(config: AvatarEditorConfig) {\n    this.config = {\n      border: 25,\n      borderRadius: 0,\n      scale: 1,\n      rotate: 0,\n      color: [0, 0, 0, 0.5],\n      backgroundColor: '',\n      borderColor: undefined,\n      showGrid: false,\n      gridColor: '#666',\n      disableBoundaryChecks: false,\n      disableHiDPIScaling: false,\n      disableCanvasRotation: true,\n      crossOrigin: undefined,\n      ...config,\n    } as Required<AvatarEditorConfig>\n\n    this.pixelRatio =\n      typeof window !== 'undefined' &&\n      window.devicePixelRatio &&\n      !this.config.disableHiDPIScaling\n        ? window.devicePixelRatio\n        : 1\n  }\n\n  getPixelRatio(): number {\n    return this.pixelRatio\n  }\n\n  getImageState(): ImageState {\n    return this.imageState\n  }\n\n  setImageState(state: ImageState): void {\n    this.imageState = state\n  }\n\n  updateConfig(config: Partial<AvatarEditorConfig>): void {\n    this.config = { ...this.config, ...config } as Required<AvatarEditorConfig>\n  }\n\n  isVertical(): boolean {\n    return !this.config.disableCanvasRotation && this.config.rotate % 180 !== 0\n  }\n\n  getBorders(border?: number | [number, number]): [number, number] {\n    const b = border ?? this.config.border\n    return Array.isArray(b) ? b : [b, b]\n  }\n\n  getDimensions(): Dimensions {\n    const { width, height, rotate, border } = this.config\n    const canvas = { width: 0, height: 0 }\n    const [borderX, borderY] = this.getBorders(border)\n\n    if (this.isVertical()) {\n      canvas.width = height\n      canvas.height = width\n    } else {\n      canvas.width = width\n      canvas.height = height\n    }\n\n    canvas.width += borderX * 2\n    canvas.height += borderY * 2\n\n    return {\n      canvas,\n      rotate,\n      width,\n      height,\n      border,\n    }\n  }\n\n  getXScale(): number {\n    if (!this.imageState.width || !this.imageState.height) {\n      throw new Error('Image dimension is unknown.')\n    }\n\n    const canvasAspect = this.config.width / this.config.height\n    const imageAspect = this.imageState.width / this.imageState.height\n\n    return Math.min(1, canvasAspect / imageAspect)\n  }\n\n  getYScale(): number {\n    if (!this.imageState.width || !this.imageState.height) {\n      throw new Error('Image dimension is unknown.')\n    }\n\n    const canvasAspect = this.config.height / this.config.width\n    const imageAspect = this.imageState.height / this.imageState.width\n\n    return Math.min(1, canvasAspect / imageAspect)\n  }\n\n  getCroppingRect(position?: Position): CroppingRect {\n    if (!this.imageState.width || !this.imageState.height) {\n      return { x: 0, y: 0, width: 1, height: 1 }\n    }\n\n    const pos = position || {\n      x: this.imageState.x,\n      y: this.imageState.y,\n    }\n    const rectWidth = (1 / this.config.scale) * this.getXScale()\n    const rectHeight = (1 / this.config.scale) * this.getYScale()\n\n    const croppingRect = {\n      x: pos.x - rectWidth / 2,\n      y: pos.y - rectHeight / 2,\n      width: rectWidth,\n      height: rectHeight,\n    }\n\n    let xMin = 0\n    let xMax = 1 - croppingRect.width\n    let yMin = 0\n    let yMax = 1 - croppingRect.height\n\n    const isLargerThanImage =\n      this.config.disableBoundaryChecks || rectWidth > 1 || rectHeight > 1\n\n    if (isLargerThanImage) {\n      xMin = -croppingRect.width\n      xMax = 1\n      yMin = -croppingRect.height\n      yMax = 1\n    }\n\n    return {\n      ...croppingRect,\n      x: Math.max(xMin, Math.min(croppingRect.x, xMax)),\n      y: Math.max(yMin, Math.min(croppingRect.y, yMax)),\n    }\n  }\n\n  getInitialSize(\n    imgWidth: number,\n    imgHeight: number,\n  ): { width: number; height: number } {\n    let newHeight: number\n    let newWidth: number\n\n    const dimensions = this.getDimensions()\n    const canvasRatio = dimensions.height / dimensions.width\n    const imageRatio = imgHeight / imgWidth\n\n    if (canvasRatio > imageRatio) {\n      newHeight = dimensions.height\n      newWidth = imgWidth * (newHeight / imgHeight)\n    } else {\n      newWidth = dimensions.width\n      newHeight = imgHeight * (newWidth / imgWidth)\n    }\n\n    return {\n      height: newHeight,\n      width: newWidth,\n    }\n  }\n\n  async loadImage(file: File | string): Promise<ImageState> {\n    let image: HTMLImageElement\n\n    if (isFileAPISupported && file instanceof File) {\n      image = await loadImageFile(file)\n    } else if (typeof file === 'string') {\n      image = await loadImageURL(file, this.config.crossOrigin)\n    } else {\n      throw new Error('Invalid image source')\n    }\n\n    const imageState: ImageState = {\n      ...this.getInitialSize(image.width, image.height),\n      resource: image,\n      x: 0.5,\n      y: 0.5,\n    }\n\n    this.imageState = imageState\n    return imageState\n  }\n\n  clearImage(): void {\n    this.imageState = defaultEmptyImage\n  }\n\n  calculatePosition(\n    image = this.imageState,\n    border?: number | [number, number],\n  ): {\n    x: number\n    y: number\n    width: number\n    height: number\n  } {\n    const [borderX, borderY] = this.getBorders(border)\n\n    if (!image.width || !image.height) {\n      throw new Error('Image dimension is unknown.')\n    }\n\n    const croppingRect = this.getCroppingRect()\n\n    const width = image.width * this.config.scale\n    const height = image.height * this.config.scale\n\n    let x = -croppingRect.x * width\n    let y = -croppingRect.y * height\n\n    if (this.isVertical()) {\n      x += borderY\n      y += borderX\n    } else {\n      x += borderX\n      y += borderY\n    }\n\n    return { x, y, height, width }\n  }\n\n  paint(context: CanvasRenderingContext2D): void {\n    context.save()\n    context.scale(this.pixelRatio, this.pixelRatio)\n    context.translate(0, 0)\n    context.fillStyle = 'rgba(' + this.config.color.slice(0, 4).join(',') + ')'\n\n    let borderRad = this.config.borderRadius\n    const dimensions = this.getDimensions()\n    const [borderSizeX, borderSizeY] = this.getBorders(dimensions.border)\n    const h = dimensions.canvas.height\n    const w = dimensions.canvas.width\n\n    // clamp border radius between zero (perfect rectangle) and half the size without borders (perfect circle or \"pill\")\n    borderRad = Math.max(borderRad, 0)\n    borderRad = Math.min(borderRad, w / 2 - borderSizeX, h / 2 - borderSizeY)\n\n    context.beginPath()\n    // inner rect, possibly rounded\n    drawRoundedRect(\n      context,\n      borderSizeX,\n      borderSizeY,\n      w - borderSizeX * 2,\n      h - borderSizeY * 2,\n      borderRad,\n    )\n    context.rect(w, 0, -w, h) // outer rect, drawn \"counterclockwise\"\n    context.fill('evenodd')\n\n    // Draw 1px border around the mask only if borderColor is provided\n    if (this.config.borderColor) {\n      context.strokeStyle =\n        'rgba(' + this.config.borderColor.slice(0, 4).join(',') + ')'\n      context.lineWidth = 1\n      context.beginPath()\n      drawRoundedRect(\n        context,\n        borderSizeX + 0.5,\n        borderSizeY + 0.5,\n        w - borderSizeX * 2 - 1,\n        h - borderSizeY * 2 - 1,\n        borderRad,\n      )\n      context.stroke()\n    }\n\n    if (this.config.showGrid) {\n      drawGrid(\n        context,\n        borderSizeX,\n        borderSizeY,\n        w - borderSizeX * 2,\n        h - borderSizeY * 2,\n        this.config.gridColor,\n      )\n    }\n    context.restore()\n  }\n\n  paintImage(\n    context: CanvasRenderingContext2D,\n    image: ImageState,\n    borderValue: number | [number, number],\n    scaleFactor = this.pixelRatio,\n  ): void {\n    if (!image.resource) return\n\n    const pos = this.calculatePosition(image, borderValue)\n\n    context.save()\n\n    context.translate(context.canvas.width / 2, context.canvas.height / 2)\n    context.rotate((this.config.rotate * Math.PI) / 180)\n    context.translate(-(context.canvas.width / 2), -(context.canvas.height / 2))\n\n    if (this.isVertical()) {\n      context.translate(\n        (context.canvas.width - context.canvas.height) / 2,\n        (context.canvas.height - context.canvas.width) / 2,\n      )\n    }\n\n    context.scale(scaleFactor, scaleFactor)\n\n    context.globalCompositeOperation = 'destination-over'\n    context.drawImage(image.resource, pos.x, pos.y, pos.width, pos.height)\n\n    if (this.config.backgroundColor) {\n      context.fillStyle = this.config.backgroundColor\n      context.fillRect(0, 0, context.canvas.width, context.canvas.height)\n    }\n\n    context.restore()\n  }\n\n  getImage(): HTMLCanvasElement {\n    const cropRect = this.getCroppingRect()\n    const image = this.imageState\n\n    if (!image.resource) {\n      throw new Error(\n        'No image resource available, please report this to: https://github.com/mosch/react-avatar-editor/issues',\n      )\n    }\n\n    // get actual pixel coordinates\n    cropRect.x *= image.resource.width\n    cropRect.y *= image.resource.height\n    cropRect.width *= image.resource.width\n    cropRect.height *= image.resource.height\n\n    // create a canvas with the correct dimensions\n    const canvasEl = document.createElement('canvas')\n\n    if (this.isVertical()) {\n      canvasEl.width = Math.round(cropRect.height)\n      canvasEl.height = Math.round(cropRect.width)\n    } else {\n      canvasEl.width = Math.round(cropRect.width)\n      canvasEl.height = Math.round(cropRect.height)\n    }\n\n    const context = canvasEl.getContext('2d')\n\n    if (!context) {\n      throw new Error(\n        'No context found, please report this to: https://github.com/mosch/react-avatar-editor/issues',\n      )\n    }\n\n    context.translate(canvasEl.width / 2, canvasEl.height / 2)\n    context.rotate((this.config.rotate * Math.PI) / 180)\n    context.translate(-(canvasEl.width / 2), -(canvasEl.height / 2))\n\n    if (this.isVertical()) {\n      context.translate(\n        (canvasEl.width - canvasEl.height) / 2,\n        (canvasEl.height - canvasEl.width) / 2,\n      )\n    }\n\n    if (this.config.backgroundColor) {\n      context.fillStyle = this.config.backgroundColor\n      context.fillRect(0, 0, canvasEl.width, canvasEl.height)\n    }\n\n    context.drawImage(image.resource, -cropRect.x, -cropRect.y)\n\n    return canvasEl\n  }\n\n  getImageScaledToCanvas(): HTMLCanvasElement {\n    const dimensions = this.getDimensions()\n    const image = this.imageState\n    const canvasEl = document.createElement('canvas')\n\n    if (this.isVertical()) {\n      canvasEl.width = dimensions.height\n      canvasEl.height = dimensions.width\n    } else {\n      canvasEl.width = dimensions.width\n      canvasEl.height = dimensions.height\n    }\n\n    if (!image.resource) return canvasEl\n\n    const context = canvasEl.getContext('2d')\n    if (!context) return canvasEl\n\n    const pos = this.calculatePosition(image, 0)\n\n    context.save()\n    context.translate(canvasEl.width / 2, canvasEl.height / 2)\n    context.rotate((this.config.rotate * Math.PI) / 180)\n    context.translate(-(canvasEl.width / 2), -(canvasEl.height / 2))\n\n    if (this.isVertical()) {\n      context.translate(\n        (canvasEl.width - canvasEl.height) / 2,\n        (canvasEl.height - canvasEl.width) / 2,\n      )\n    }\n\n    if (this.config.backgroundColor) {\n      context.fillStyle = this.config.backgroundColor\n      context.fillRect(0, 0, canvasEl.width, canvasEl.height)\n    }\n\n    context.drawImage(image.resource, pos.x, pos.y, pos.width, pos.height)\n    context.restore()\n\n    return canvasEl\n  }\n\n  calculateDragPosition(\n    mousePositionX: number,\n    mousePositionY: number,\n    lastMx: number,\n    lastMy: number,\n  ): Position {\n    const deltaX = lastMx - mousePositionX\n    const deltaY = lastMy - mousePositionY\n\n    if (!this.imageState.width || !this.imageState.height) {\n      throw new Error('Image dimension is unknown.')\n    }\n\n    const w = this.imageState.width * this.config.scale\n    const h = this.imageState.height * this.config.scale\n\n    let { x: lastX, y: lastY } = this.getCroppingRect()\n\n    lastX *= w\n    lastY *= h\n\n    // helpers to calculate vectors\n    let rot = this.config.rotate\n    rot %= 360\n    rot = rot < 0 ? rot + 360 : rot\n\n    const cos = Math.cos(toRadians(rot))\n    const sin = Math.sin(toRadians(rot))\n\n    const x = lastX + deltaX * cos + deltaY * sin\n    const y = lastY + -deltaX * sin + deltaY * cos\n\n    const relativeWidth = (1 / this.config.scale) * this.getXScale()\n    const relativeHeight = (1 / this.config.scale) * this.getYScale()\n\n    return {\n      x: x / w + relativeWidth / 2,\n      y: y / h + relativeHeight / 2,\n    }\n  }\n}\n","// https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener\nconst noop = () => {}\n\nexport const isPassiveSupported = () => {\n  let passiveSupported = false\n  try {\n    const options = Object.defineProperty({}, 'passive', {\n      get: function () {\n        passiveSupported = true\n      },\n    })\n\n    window.addEventListener('test', noop, options)\n    window.removeEventListener('test', noop, options)\n  } catch {\n    passiveSupported = false\n  }\n  return passiveSupported\n}\n","import React, {\n  type TouchEventHandler,\n  type CSSProperties,\n  type MouseEventHandler,\n  useState,\n  useRef,\n  useEffect,\n  useCallback,\n  useImperativeHandle,\n  forwardRef,\n} from 'react'\n\nimport {\n  AvatarEditorCore,\n  type ImageState,\n  type Position,\n  type AvatarEditorConfig,\n  isPassiveSupported,\n} from '@react-avatar-editor/core'\n\nexport interface Props extends AvatarEditorConfig {\n  style?: CSSProperties\n  image?: string | File\n  position?: Position\n  onLoadStart?: () => void\n  onLoadFailure?: () => void\n  onLoadSuccess?: (image: ImageState) => void\n  onImageReady?: () => void\n  onImageChange?: () => void\n  onMouseUp?: () => void\n  onMouseMove?: (e: TouchEvent | MouseEvent) => void\n  onPositionChange?: (position: Position) => void\n}\n\nexport type { Position, ImageState }\n\nexport interface AvatarEditorRef {\n  getImage: () => HTMLCanvasElement\n  getImageScaledToCanvas: () => HTMLCanvasElement\n  getCroppingRect: () => { x: number; y: number; width: number; height: number }\n}\n\nconst AvatarEditor = forwardRef<AvatarEditorRef, Props>((props, ref) => {\n  const {\n    scale = 1,\n    rotate = 0,\n    border = 25,\n    borderRadius = 0,\n    width = 200,\n    height = 200,\n    color = [0, 0, 0, 0.5],\n    showGrid = false,\n    gridColor = '#666',\n    disableBoundaryChecks = false,\n    disableHiDPIScaling = false,\n    disableCanvasRotation = true,\n    image,\n    position,\n    backgroundColor,\n    crossOrigin,\n    onLoadStart,\n    onLoadFailure,\n    onLoadSuccess,\n    onImageReady,\n    onImageChange,\n    onMouseUp,\n    onMouseMove,\n    onPositionChange,\n    borderColor,\n    style,\n  } = props\n\n  const canvas = useRef<HTMLCanvasElement>(null)\n  const coreRef = useRef<AvatarEditorCore>(\n    new AvatarEditorCore({\n      width,\n      height,\n      border,\n      borderRadius,\n      scale,\n      rotate,\n      color,\n      backgroundColor,\n      borderColor,\n      showGrid,\n      gridColor,\n      disableBoundaryChecks,\n      disableHiDPIScaling,\n      disableCanvasRotation,\n      crossOrigin,\n    }),\n  )\n\n  // Use refs for drag state to avoid stale closures in document-level listeners.\n  // These values are read/written in handlers registered once on mount.\n  const dragRef = useRef(false)\n  const mxRef = useRef<number | undefined>(undefined)\n  const myRef = useRef<number | undefined>(undefined)\n\n  // Keep state for `drag` and `loading` to trigger re-renders\n  const [drag, setDrag] = useState(false)\n  const [loading, setLoading] = useState(false)\n  const [imageState, setImageState] = useState<ImageState>(\n    coreRef.current.getImageState(),\n  )\n\n  // Store latest callback props in refs so document handlers always call current versions\n  const onMouseUpRef = useRef(onMouseUp)\n  onMouseUpRef.current = onMouseUp\n  const onMouseMoveRef = useRef(onMouseMove)\n  onMouseMoveRef.current = onMouseMove\n  const onPositionChangeRef = useRef(onPositionChange)\n  onPositionChangeRef.current = onPositionChange\n\n  // Update core config when props change\n  useEffect(() => {\n    coreRef.current.updateConfig({\n      width,\n      height,\n      border,\n      borderRadius,\n      scale,\n      rotate,\n      color,\n      backgroundColor,\n      borderColor,\n      showGrid,\n      gridColor,\n      disableBoundaryChecks,\n      disableHiDPIScaling,\n      disableCanvasRotation,\n      crossOrigin,\n    })\n  }, [\n    width,\n    height,\n    border,\n    borderRadius,\n    scale,\n    rotate,\n    color,\n    backgroundColor,\n    borderColor,\n    showGrid,\n    gridColor,\n    disableBoundaryChecks,\n    disableHiDPIScaling,\n    disableCanvasRotation,\n    crossOrigin,\n  ])\n\n  const getCanvas = useCallback((): HTMLCanvasElement => {\n    if (!canvas.current) {\n      throw new Error(\n        'No canvas found, please report this to: https://github.com/mosch/react-avatar-editor/issues',\n      )\n    }\n    return canvas.current\n  }, [])\n\n  const getContext = useCallback(() => {\n    const context = getCanvas().getContext('2d')\n    if (!context) {\n      throw new Error(\n        'No context found, please report this to: https://github.com/mosch/react-avatar-editor/issues',\n      )\n    }\n    return context\n  }, [getCanvas])\n\n  const loadImage = useCallback(\n    async (file: File | string) => {\n      setLoading(true)\n      onLoadStart?.()\n      try {\n        const newImageState = await coreRef.current.loadImage(file)\n        dragRef.current = false\n        setDrag(false)\n        setImageState(newImageState)\n        onImageReady?.()\n        onLoadSuccess?.(newImageState)\n      } catch {\n        onLoadFailure?.()\n      } finally {\n        setLoading(false)\n      }\n    },\n    [onLoadStart, onImageReady, onLoadSuccess, onLoadFailure],\n  )\n\n  const clearImage = useCallback(() => {\n    const canvasEl = getCanvas()\n    const context = getContext()\n    context.clearRect(0, 0, canvasEl.width, canvasEl.height)\n    coreRef.current.clearImage()\n    setImageState(coreRef.current.getImageState())\n  }, [getCanvas, getContext])\n\n  const repaint = useCallback(() => {\n    const context = getContext()\n    const canvasEl = getCanvas()\n    context.clearRect(0, 0, canvasEl.width, canvasEl.height)\n    coreRef.current.paint(context)\n    coreRef.current.paintImage(context, imageState, border)\n    // eslint-disable-next-line -- all visual props must trigger repaint\n  }, [\n    getContext,\n    getCanvas,\n    imageState,\n    border,\n    width,\n    height,\n    borderRadius,\n    scale,\n    rotate,\n    color,\n    backgroundColor,\n    borderColor,\n    showGrid,\n    gridColor,\n    disableBoundaryChecks,\n    disableHiDPIScaling,\n    disableCanvasRotation,\n    crossOrigin,\n  ])\n\n  const handleMouseDown: MouseEventHandler<HTMLCanvasElement> = useCallback(\n    (e) => {\n      e.preventDefault()\n      dragRef.current = true\n      mxRef.current = undefined\n      myRef.current = undefined\n      setDrag(true)\n    },\n    [],\n  )\n\n  const handleTouchStart: TouchEventHandler<HTMLCanvasElement> =\n    useCallback(() => {\n      dragRef.current = true\n      mxRef.current = undefined\n      myRef.current = undefined\n      setDrag(true)\n    }, [])\n\n  // Expose imperative methods via ref\n  useImperativeHandle(\n    ref,\n    () => ({\n      getImage: () => coreRef.current.getImage(),\n      getImageScaledToCanvas: () => coreRef.current.getImageScaledToCanvas(),\n      getCroppingRect: () => coreRef.current.getCroppingRect(),\n    }),\n    [],\n  )\n\n  // Mount effect - setup document-level event listeners.\n  // Handlers read from refs (not closures) to always have current values.\n  useEffect(() => {\n    const context = getContext()\n\n    if (image) {\n      loadImage(image)\n    }\n    coreRef.current.paint(context)\n\n    const handleDocumentMouseMove = (e: MouseEvent | TouchEvent) => {\n      if (!dragRef.current) {\n        return\n      }\n\n      if (e.cancelable) e.preventDefault()\n\n      const mousePositionX =\n        'targetTouches' in e ? e.targetTouches[0].pageX : e.clientX\n      const mousePositionY =\n        'targetTouches' in e ? e.targetTouches[0].pageY : e.clientY\n\n      const prevMx = mxRef.current\n      const prevMy = myRef.current\n\n      mxRef.current = mousePositionX\n      myRef.current = mousePositionY\n\n      if (prevMx !== undefined && prevMy !== undefined) {\n        const currentImageState = coreRef.current.getImageState()\n        if (currentImageState.width && currentImageState.height) {\n          const newPosition = coreRef.current.calculateDragPosition(\n            mousePositionX,\n            mousePositionY,\n            prevMx,\n            prevMy,\n          )\n\n          onPositionChangeRef.current?.(newPosition)\n\n          const updatedImageState = { ...currentImageState, ...newPosition }\n          coreRef.current.setImageState(updatedImageState)\n          setImageState(updatedImageState)\n        }\n      }\n\n      onMouseMoveRef.current?.(e)\n    }\n\n    const handleDocumentMouseUp = () => {\n      if (dragRef.current) {\n        dragRef.current = false\n        setDrag(false)\n        onMouseUpRef.current?.()\n      }\n    }\n\n    const options = isPassiveSupported() ? { passive: false } : false\n    document.addEventListener('mousemove', handleDocumentMouseMove, options)\n    document.addEventListener('mouseup', handleDocumentMouseUp, options)\n    document.addEventListener('touchmove', handleDocumentMouseMove, options)\n    document.addEventListener('touchend', handleDocumentMouseUp, options)\n\n    return () => {\n      document.removeEventListener('mousemove', handleDocumentMouseMove, false)\n      document.removeEventListener('mouseup', handleDocumentMouseUp, false)\n      document.removeEventListener('touchmove', handleDocumentMouseMove, false)\n      document.removeEventListener('touchend', handleDocumentMouseUp, false)\n    }\n  }, [])\n\n  // Effect to handle image changes\n  useEffect(() => {\n    if (image) {\n      loadImage(image)\n    } else if (!image && imageState.x !== 0.5 && imageState.y !== 0.5) {\n      clearImage()\n    }\n  }, [image, width, height, backgroundColor])\n\n  // Effect to repaint canvas whenever relevant props/state change\n  useEffect(() => {\n    repaint()\n  }, [repaint])\n\n  // Pulsate the full canvas while loading\n  useEffect(() => {\n    if (!loading) return\n    const canvasEl = canvas.current\n    if (!canvasEl) return\n    const ctx = canvasEl.getContext('2d')\n    if (!ctx) return\n\n    let frameId: number\n    const start = performance.now()\n\n    const draw = (now: number) => {\n      const t = (now - start) / 1000\n      const alpha = 0.03 + Math.sin(t * 2.5) * 0.02 + 0.02\n\n      ctx.save()\n      ctx.clearRect(0, 0, canvasEl.width, canvasEl.height)\n      ctx.fillStyle = `rgba(255,255,255,${alpha})`\n      ctx.fillRect(0, 0, canvasEl.width, canvasEl.height)\n      ctx.restore()\n\n      frameId = requestAnimationFrame(draw)\n    }\n\n    frameId = requestAnimationFrame(draw)\n    return () => cancelAnimationFrame(frameId)\n  }, [loading])\n\n  // Effect to trigger onImageChange callback\n  const prevPropsRef = useRef({\n    image,\n    width,\n    height,\n    position,\n    scale,\n    rotate,\n    imageX: imageState.x,\n    imageY: imageState.y,\n  })\n  useEffect(() => {\n    const prev = prevPropsRef.current\n    if (\n      prev.image !== image ||\n      prev.width !== width ||\n      prev.height !== height ||\n      prev.position !== position ||\n      prev.scale !== scale ||\n      prev.rotate !== rotate ||\n      prev.imageX !== imageState.x ||\n      prev.imageY !== imageState.y\n    ) {\n      onImageChange?.()\n      prevPropsRef.current = {\n        image,\n        width,\n        height,\n        position,\n        scale,\n        rotate,\n        imageX: imageState.x,\n        imageY: imageState.y,\n      }\n    }\n  }, [\n    image,\n    width,\n    height,\n    position,\n    scale,\n    rotate,\n    imageState.x,\n    imageState.y,\n    onImageChange,\n  ])\n\n  const dimensions = coreRef.current.getDimensions()\n  const pixelRatio = coreRef.current.getPixelRatio()\n\n  const defaultStyle: CSSProperties = {\n    width: dimensions.canvas.width,\n    height: dimensions.canvas.height,\n    cursor: drag ? 'grabbing' : 'grab',\n    touchAction: 'none',\n    maxWidth: 'none',\n    maxHeight: 'none',\n  }\n\n  return React.createElement('canvas', {\n    width: dimensions.canvas.width * pixelRatio,\n    height: dimensions.canvas.height * pixelRatio,\n    onMouseDown: handleMouseDown,\n    onTouchStart: handleTouchStart,\n    style: { ...defaultStyle, ...style },\n    ref: canvas,\n  })\n})\n\nAvatarEditor.displayName = 'AvatarEditor'\n\nexport function useAvatarEditor() {\n  const ref = useRef<AvatarEditorRef>(null)\n\n  return {\n    ref,\n    getImage: (): HTMLCanvasElement | null => {\n      try {\n        return ref.current?.getImage() ?? null\n      } catch {\n        return null\n      }\n    },\n    getImageScaledToCanvas: (): HTMLCanvasElement | null => {\n      try {\n        return ref.current?.getImageScaledToCanvas() ?? null\n      } catch {\n        return null\n      }\n    },\n    getCroppingRect: (): {\n      x: number\n      y: number\n      width: number\n      height: number\n    } | null => {\n      return ref.current?.getCroppingRect() ?? null\n    },\n  }\n}\n\nexport default AvatarEditor\n"],"mappings":"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"}