```
import EventEmitter from "./event-emitter.mjs";
export default class DrawArea extends EventEmitter {
  constructor(container, { minSize = 10 } = {}) {
    super(); // Initialize EventTarget

    this.containerRef = container ? new WeakRef(container) : null;
    this.minSize = minSize;

    // Bind event handlers to maintain context
    this.handleMouseDown = this.handleMouseDown.bind(this);
    this.handleMouseMove = this.handleMouseMove.bind(this);
    this.handleMouseUp = this.handleMouseUp.bind(this);

    // State variables
    this.isDrawing = false;
    this.currentRect = null;

    // Internal flags
    this.isStarted = false;
  }

  getContainer() {
    const container = this.containerRef?.deref();
    if (!container) {
      throw new Error("DrawArea: Container element is no longer available.");
    }
    return container;
  }

  start(container) {
    if (this.isStarted) return;

    if (container) {
      this.containerRef = new WeakRef(container);
    } else {
      container = this.getContainer();
    }

    if (!(container instanceof HTMLElement)) {
      throw new TypeError(
        'DrawArea: "container" must be an instance of HTMLElement.'
      );
    }

    const position = getComputedStyle(container).position;
    if (!["relative", "absolute", "fixed", "sticky"].includes(position)) {
      container.style.position = "relative";
    }

    // Attach mouse event listeners
    container.addEventListener("mousedown", this.handleMouseDown);
    window.addEventListener("mousemove", this.handleMouseMove);
    window.addEventListener("mouseup", this.handleMouseUp);

    this.isStarted = true;
  }

  stop() {
    if (!this.isStarted) return;
    try {
      const container = this.getContainer();
      container.removeEventListener("mousedown", this.handleMouseDown);
    } finally {
      window.removeEventListener("mousemove", this.handleMouseMove);
      window.removeEventListener("mouseup", this.handleMouseUp);

      this.isStarted = false;
      this.isDrawing = false;
      this.currentRect = null;
    }
  }

  handleMouseDown(e) {
    if (e.button !== 0) return;

    const container = this.getContainer();

    // Prevent drawing if clicking on child
    if (e.target !== container) return;
    if (e.composedPath()[0] !== container) return;

    e.preventDefault(); // Prevent text selection and other default behaviors

    this.isDrawing = true;
    const { left, top } = container.getBoundingClientRect();
    const rect = container.getBoundingClientRect();
    const startX = e.clientX - left;
    const startY = e.clientY - top;
    this.currentRect = {
      startX,
      startY,
      x: startX,
      y: startY,
      width: 0,
      height: 0,
      isMinSizeReached: false,
      shouldCreate: false,
    };
    this.emit("draw:start", this.currentRect);
  }

  handleMouseMove(e) {
    if (!this.isDrawing) return;
    const container = this.getContainer();

    const { left, top } = container.getBoundingClientRect();
    const currentX = e.clientX - left;
    const currentY = e.clientY - top;
    const { currentRect, minSize } = this;
    const { startX, startY } = currentRect;

    // Calculate absolute width and height
    const width = Math.abs(currentX - startX);
    const height = Math.abs(currentY - startY);

    // top-left corner
    const x = Math.min(currentX, startX);
    const y = Math.min(currentY, startY);

    if (!currentRect.isMinSizeReached) {
      if (width >= minSize || height >= minSize) {
        currentRect.isMinSizeReached = true;
      } else {
        return;
      }
    }

    Object.assign(currentRect, { x, y, width, height });

    this.emit("draw:upsert", currentRect);
  }

  handleMouseUp(e) {
    if (!this.isDrawing) return;

    const { currentRect, minSize } = this;

    this.isDrawing = false;

    if (currentRect?.isMinSizeReached) {
      const { width, height } = currentRect;
      currentRect.shouldCreate = width >= minSize || height >= minSize;
    }

    this.emit("draw:end", currentRect);
    this.currentRect = null;
  }
}

```
before emit, convert rect coordinate (x,y) relative to that of container