{"version":3,"file":"index.mjs","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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"}