/**
 * @flow weak
 * Area
 * Area is an alias for native ClientRect with a few utility methods on top of it.
 */

type TContainOptions = {
  weak?: boolean
}

const defaultContainOptions = {
  weak: false
};

export default class Area {
  top: number;
  right: number;
  bottom: number;
  left: number;
  height: number;
  width: number;

  constructor(pointer: window | HTMLElement | Object): Area {
    let rect;

    if (pointer === window) {
      rect = {
        top: window.scrollY,
        left: window.scrollX,
        height: window.innerHeight || window.documentElement.clientHeight,
        width: window.innerWidth || window.documentElement.clientWidth
      };
    } else if (pointer instanceof HTMLElement) {
      rect = pointer.getBoundingClientRect();
    } else {
      rect = pointer;
    }

    /* Assign client rectangle properties */
    this.top = rect.top;
    this.right = rect.right || rect.left + rect.width;
    this.bottom = rect.bottom || rect.top + rect.height;
    this.left = rect.left;
    this.height = rect.height || rect.bottom - rect.top;
    this.width = rect.width || rect.right - rect.left;

    return this;
  }

  /**
   * Convert relative client rectangle to the absolute one.
   * Achieved by adding current scroll position.
   */
  toAbsolute = (): Area => {
    this.top += window.scrollY;
    this.right += window.scrollX;
    this.bottom += window.scrollY;
    this.left += window.scrollX;

    return this;
  }

  /**
   * Check if current Area contains the given Area or coordinates object.
   */
  contains = (area: Area | Object, options: TContainOptions): boolean => {
    const { weak } = { ...defaultContainOptions, ...options };
    const parentRect = this;

    return weak ? (
      (area.left <= parentRect.right) && (area.top <= parentRect.bottom)
    ) : (
      (parentRect.top <= area.top) &&
      (parentRect.right >= area.right) &&
      (parentRect.bottom >= area.bottom) &&
      (parentRect.left <= area.left)
    );
  }

  intersect = (area: Area): Area => {
    /* When current area completely contains the provided area, return the area */
    if (this.contains(area)) return area;

    const areaPos = {
      top: (area.bottom < this.bottom) && (area.top < this.top),
      left: (area.right < this.right) && (area.left < this.left)
    };

    return new Area({
      top: areaPos.top ? this.top : area.top,
      right: areaPos.left ? area.right : this.left,
      bottom: areaPos.top ? this.bottom : area.bottom,
      left: areaPos.left ? this.left : area.left
    });
  }
}

@@ -35,19 +35,37 @@
 is a
-n alias for
+ helper class built on top of
  nat
@@ -95,22 +95,21 @@
 ew u
-tility
+seful
  methods
  on 
@@ -108,21 +108,8 @@
 hods
- on top of it
 .%0A *
@@ -1172,16 +1172,20 @@
 Convert 
+the 
 relative
@@ -1185,16 +1185,33 @@
 elative 
+coordinates of a 
 client r
@@ -1219,16 +1219,18 @@
 ctangle 
+in
 to the a
@@ -1244,16 +1244,25 @@
  one
+s
 .%0A   * 
-A
+This is a
 chie
@@ -1275,16 +1275,18 @@
  adding 
+a 
 current 
@@ -1504,16 +1504,25 @@
 /**%0A   *
+ @summary
  Check i
@@ -1531,17 +1531,17 @@
 current 
-A
+a
 rea cont
@@ -1555,17 +1555,17 @@
 e given 
-A
+a
 rea or c
@@ -1787,84 +1787,439 @@
     
-(area.left %3C= parentRect.right) && (area.top %3C= parentRect.bottom)%0A    ) : (
+/**%0A       * Weak mode means that the provided area should not necessarily be in the parent%0A       * rectangle completely. Even partial presence will resolve.%0A       */%0A      (area.left %3C= parentRect.right) && (area.top %3C= parentRect.bottom)%0A    ) : (%0A      /**%0A       * Strong (default) mode, on the other hand, means that the area should completely lie%0A       * within the parent rectangle. Only then it should resolve.%0A       */
 %0A   
@@ -2388,16 +2388,115 @@
 );%0A  %7D%0A%0A
+  /**%0A   * @summary Get the intersection area between the current area and the provided one.%0A   */%0A
   inters
@@ -2651,16 +2651,622 @@
  area;%0A%0A
+    /**%0A     * Area position.%0A     * To properly calculate intersection, it is needed to handle 4 different scenarios of%0A     * the area position:%0A     *%0A     * - area lies completely within the parent rectangle%0A     * - area's bottom - within, while top part - beyond%0A     * - area's top - within, while bottom part - beyond%0A     * - area's right - within, while left part - beyond%0A     * - area's left - within, while the right part - beyond%0A     *%0A     * In each of these scenarios coordinates of the intersected area will be inherited from%0A     * a different source (area or parent rectangle).%0A     */%0A
     cons

Improve documentation