use-intersection.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.useIntersection = useIntersection;
  6. var _react = require("react");
  7. var _requestIdleCallback = require("./request-idle-callback");
  8. const hasIntersectionObserver = typeof IntersectionObserver === 'function';
  9. const observers = new Map();
  10. const idList = [];
  11. function createObserver(options) {
  12. const id = {
  13. root: options.root || null,
  14. margin: options.rootMargin || ''
  15. };
  16. const existing = idList.find((obj)=>obj.root === id.root && obj.margin === id.margin);
  17. let instance;
  18. if (existing) {
  19. instance = observers.get(existing);
  20. if (instance) {
  21. return instance;
  22. }
  23. }
  24. const elements = new Map();
  25. const observer = new IntersectionObserver((entries)=>{
  26. entries.forEach((entry)=>{
  27. const callback = elements.get(entry.target);
  28. const isVisible = entry.isIntersecting || entry.intersectionRatio > 0;
  29. if (callback && isVisible) {
  30. callback(isVisible);
  31. }
  32. });
  33. }, options);
  34. instance = {
  35. id,
  36. observer,
  37. elements
  38. };
  39. idList.push(id);
  40. observers.set(id, instance);
  41. return instance;
  42. }
  43. function observe(element, callback, options) {
  44. const { id , observer , elements } = createObserver(options);
  45. elements.set(element, callback);
  46. observer.observe(element);
  47. return function unobserve() {
  48. elements.delete(element);
  49. observer.unobserve(element);
  50. // Destroy observer when there's nothing left to watch:
  51. if (elements.size === 0) {
  52. observer.disconnect();
  53. observers.delete(id);
  54. const index = idList.findIndex((obj)=>obj.root === id.root && obj.margin === id.margin);
  55. if (index > -1) {
  56. idList.splice(index, 1);
  57. }
  58. }
  59. };
  60. }
  61. function useIntersection({ rootRef , rootMargin , disabled }) {
  62. const isDisabled = disabled || !hasIntersectionObserver;
  63. const [visible, setVisible] = (0, _react).useState(false);
  64. const [element, setElement] = (0, _react).useState(null);
  65. (0, _react).useEffect(()=>{
  66. if (hasIntersectionObserver) {
  67. if (isDisabled || visible) return;
  68. if (element && element.tagName) {
  69. const unobserve = observe(element, (isVisible)=>isVisible && setVisible(isVisible), {
  70. root: rootRef == null ? void 0 : rootRef.current,
  71. rootMargin
  72. });
  73. return unobserve;
  74. }
  75. } else {
  76. if (!visible) {
  77. const idleCallback = (0, _requestIdleCallback).requestIdleCallback(()=>setVisible(true));
  78. return ()=>(0, _requestIdleCallback).cancelIdleCallback(idleCallback);
  79. }
  80. }
  81. }, [
  82. element,
  83. isDisabled,
  84. rootMargin,
  85. rootRef,
  86. visible
  87. ]);
  88. const resetVisible = (0, _react).useCallback(()=>{
  89. setVisible(false);
  90. }, []);
  91. return [
  92. setElement,
  93. visible,
  94. resetVisible
  95. ];
  96. }
  97. if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
  98. Object.defineProperty(exports.default, '__esModule', { value: true });
  99. Object.assign(exports.default, exports);
  100. module.exports = exports.default;
  101. }
  102. //# sourceMappingURL=use-intersection.js.map