{"size": 4898, "ext": "js", "max_stars_repo_path": "node_modules/@thumbtack/thumbprint-react/dist/es/components/Image/use-lazy-load.js", "max_stars_repo_name": "gkweston/photolio", "max_stars_repo_stars_event_min_datetime": null, "max_stars_repo_stars_event_max_datetime": null, "max_issues_repo_path": "node_modules/@thumbtack/thumbprint-react/dist/es/components/Image/use-lazy-load.js", "max_issues_repo_name": "gkweston/photolio", "max_issues_repo_issues_event_min_datetime": null, "max_issues_repo_issues_event_max_datetime": null, "max_forks_repo_path": "node_modules/@thumbtack/thumbprint-react/dist/es/components/Image/use-lazy-load.js", "max_forks_repo_name": "gkweston/photolio", "max_forks_repo_forks_event_min_datetime": null, "max_forks_repo_forks_event_max_datetime": null}
{"max_stars_count": null, "max_issues_count": null, "max_forks_count": null, "avg_line_length": 45.3518518519, "max_line_length": 141, "alphanum_fraction": 0.6678236015}
import { slicedToArray as _slicedToArray } from '../../_virtual/_rollupPluginBabelHelpers.js';
import { useState, useRef, useEffect } from 'react';
import forEach from 'lodash/forEach';
import getScrollParent from './get-scroll-parent.js';

function getIntersectionObserverRoot(target) {
  var parent = getScrollParent(target);
  return parent && (parent.tagName === 'HTML' || parent.tagName === 'BODY') ? null : parent;
}

function useLazyLoad(el, browserSupportIntersectionObserver) {
  // The total number of Intersection Observers that we end up creating. We create one for each
  // scrollable parent element of `el`. An image within a carousel, for example, could have two
  // scrollable parents: the carousel and the `<body>` element. We'd load the image if it is
  // visible within the carousel and the carousel is visible within the body.
  var _useState = useState(0),
      _useState2 = _slicedToArray(_useState, 2),
      numObservers = _useState2[0],
      setNumObservers = _useState2[1]; // The number of Intersection Observers we've created that have intersected.


  var _useState3 = useState(0),
      _useState4 = _slicedToArray(_useState3, 2),
      numHaveIntersected = _useState4[0],
      setNumHaveIntersected = _useState4[1]; // We store the Intersection Observer instances so that we can clean them up in the `useEffect`
  // return function.


  var observers = useRef([]);
  useEffect(function () {
    if (el && browserSupportIntersectionObserver) {
      // Get array of targets and roots to use with Intersection Observer. `target` is the
      // child element and `root` is the scrollable parent. This terminology comes from the
      // Insersection Observer itself:
      // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
      var observersToCreate = []; // The first target is always the element passed in.

      var target = el;
      var root = getIntersectionObserverRoot(target);
      observersToCreate.push({
        target: target,
        root: root
      }); // If `root !== null`, that means that there is another scrollable parent. Continue
      // traversing up the DOM tree until we get to the top.

      while (root !== null) {
        target = root;
        root = getIntersectionObserverRoot(target);
        observersToCreate.push({
          target: target,
          root: root
        });
      } // We later use the total number of observers to determine if they are all visible.


      setNumObservers(observersToCreate.length); // Take the array of targets and roots and create a bunch of Intersection Observers.

      observers.current = observersToCreate.map(function (p) {
        // We disable this line since we polyfill `IntersectionObserver`.
        // eslint-disable-next-line compat/compat
        var observer = new IntersectionObserver(function (entries) {
          // We can assume it's the first one since we only observe one target per
          // IntersectionObserver.
          var entry = entries[0]; // We use both `isIntersecting` and `intersectionRatio` because Edge 15
          // doesn't support `isIntersecting`.

          if (entry.isIntersecting || entry.intersectionRatio > 0) {
            // We need to pass in a function to `setNumHaveIntersected` so that it
            // can get the current value of `numHaveIntersected` within this
            // callback.
            setNumHaveIntersected(function (n) {
              return n + 1;
            }); // We turn off the observer once it has intersected. This is a purposely
            // naïve approach even though it introduces a small bug: images within
            // an auto-advancing carousel that once were `isIntersecting`
            // within the carousel but been auto-advanced out of view will get
            // loaded once the user scrolls and the carousel intersects the
            // `<body>`. To fix this, we'd have to increment and decrement
            // `observer.current`'s and then turn them all off once the image should
            // be loaded. This would add lot of complexity for an uncommon case so
            // we leave it as is.

            observer.unobserve(entry.target);
          }
        }, {
          root: p.root,
          rootMargin: '100px'
        });
        observer.observe(p.target);
        return observer;
      });
    }

    return function cleanObservers() {
      forEach(observers.current, function (o) {
        return o.disconnect();
      });
    };
  }, [el, browserSupportIntersectionObserver]); // The image should load if there's at least one Intersection Observer set up and all of them
  // have intersected. The `> 0` check prevents the hook from returning true while before it has
  // even initialized.

  return numObservers > 0 && numObservers === numHaveIntersected;
}

export default useLazyLoad;
//# sourceMappingURL=use-lazy-load.js.map
