react-lazy-load-image-component 1.4.2 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,71 @@
1
+ # For most projects, this workflow file will not need changing; you simply need
2
+ # to commit it to your repository.
3
+ #
4
+ # You may wish to alter this file to override the set of languages analyzed,
5
+ # or to provide custom queries or build logic.
6
+ name: "CodeQL"
7
+
8
+ on:
9
+ push:
10
+ branches: [master]
11
+ pull_request:
12
+ # The branches below must be a subset of the branches above
13
+ branches: [master]
14
+ schedule:
15
+ - cron: '0 14 * * 1'
16
+
17
+ jobs:
18
+ analyze:
19
+ name: Analyze
20
+ runs-on: ubuntu-latest
21
+
22
+ strategy:
23
+ fail-fast: false
24
+ matrix:
25
+ # Override automatic language detection by changing the below list
26
+ # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python']
27
+ language: ['javascript']
28
+ # Learn more...
29
+ # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
30
+
31
+ steps:
32
+ - name: Checkout repository
33
+ uses: actions/checkout@v2
34
+ with:
35
+ # We must fetch at least the immediate parents so that if this is
36
+ # a pull request then we can checkout the head.
37
+ fetch-depth: 2
38
+
39
+ # If this run was triggered by a pull request event, then checkout
40
+ # the head of the pull request instead of the merge commit.
41
+ - run: git checkout HEAD^2
42
+ if: ${{ github.event_name == 'pull_request' }}
43
+
44
+ # Initializes the CodeQL tools for scanning.
45
+ - name: Initialize CodeQL
46
+ uses: github/codeql-action/init@v1
47
+ with:
48
+ languages: ${{ matrix.language }}
49
+ # If you wish to specify custom queries, you can do so here or in a config file.
50
+ # By default, queries listed here will override any specified in a config file.
51
+ # Prefix the list here with "+" to use these queries and those in the config file.
52
+ # queries: ./path/to/local/query, your-org/your-repo/queries@main
53
+
54
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
55
+ # If this step fails, then you should remove it and run the build manually (see below)
56
+ - name: Autobuild
57
+ uses: github/codeql-action/autobuild@v1
58
+
59
+ # ℹ️ Command-line programs to run using the OS shell.
60
+ # 📚 https://git.io/JvXDl
61
+
62
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
63
+ # and modify them (or add more) to build your code if your project
64
+ # uses a compiled language
65
+
66
+ #- run: |
67
+ # make bootstrap
68
+ # make release
69
+
70
+ - name: Perform CodeQL Analysis
71
+ uses: github/codeql-action/analyze@v1
package/README.md CHANGED
@@ -77,6 +77,7 @@ export default MyImage;
77
77
  | useIntersectionObserver | `Boolean` | true | Whether to use browser's IntersectionObserver when available. |
78
78
  | visibleByDefault | `Boolean` | false | Whether the image must be visible from the beginning. |
79
79
  | wrapperClassName | `String` | | In some occasions (for example, when using a placeholderSrc) a wrapper span tag is rendered. This prop allows setting a class to that element. |
80
+ | wrapperProps | `Object` | null | Props that should be passed to the wrapper span when it is rendered (for example, when using placeholderSrc or effect) |
80
81
  | ... | | | Any other image attribute |
81
82
 
82
83
 
@@ -146,7 +147,6 @@ export default Article;
146
147
  | useIntersectionObserver | `Boolean` | true | Whether to use browser's IntersectionObserver when available. |
147
148
  | visibleByDefault | `Boolean` | false | Whether the component must be visible from the beginning. |
148
149
 
149
-
150
150
  ## Using `trackWindowScroll` HOC to improve performance
151
151
 
152
152
  When you have many elements to lazy load in the same page, you might get poor performance because each one is listening to the scroll/resize events. In that case, it's better to wrap the deepest common parent of those components with a HOC to track those events (`trackWindowScroll`).
@@ -193,6 +193,7 @@ You must set the prop `scrollPosition` to the lazy load components. This way, th
193
193
  | placeholder | `ReactClass` | `<span>` | React element to use as a placeholder. |
194
194
  | threshold | `Number` | 100 | Threshold in pixels. So the image starts loading before it appears in the viewport. |
195
195
  | visibleByDefault | `Boolean` | false | Whether the image must be visible from the beginning. |
196
+ | wrapperProps | `Object` | null | Props that should be passed to the wrapper span when it is rendered (for example, when using placeholderSrc or effect) |
196
197
  | ... | | | Any other image attribute |
197
198
 
198
199
  Component wrapped with `trackWindowScroll` (in the example, `Gallery`)
@@ -251,6 +252,18 @@ export default trackWindowScroll(Gallery);
251
252
 
252
253
  ## Common errors
253
254
 
255
+ ### All images are being loaded at once
256
+
257
+ This package loads images when they are visible in the viewport. Before an image is loaded, it occupies 0x0 pixels, so if you have a gallery of images, that means all images will be in the visible part of the page until the first ones load and start pushing down the other ones.
258
+
259
+ To fix this issue, make sure you either set a `height` and `width` props or a `placeholder` to your images.
260
+
261
+ ### Effects are not working
262
+
263
+ You need to import the effect CSS as shown in the [Using effects](#using-effects) code example.
264
+
265
+ Also, notice browsers might behave differently while images are loading. Some times, while an image is not completely loaded yet, the browser will show a white background behind it, making the effect not to be visible. This is an issue with browsers and not something that can be fixed in this package.
266
+
254
267
  ### Warning: setState(...): Can only update a mounted or mounting component.
255
268
 
256
269
  That warning might appear if there are two components using `trackWindowScroll` at the same time. Notice it's not possible to have a LazyLoadImage/LazyLoadComponent inside another LazyLoadComponent for now. Also, make sure you are passing down `scrollPosition` to all components wrapped inside `trackWindowScroll`.
package/build/index.js CHANGED
@@ -275,15 +275,29 @@ module.exports = (function(e) {
275
275
  function u(e) {
276
276
  return e && e.__esModule ? e : { default: e };
277
277
  }
278
- var c = (function(e) {
279
- function t(e) {
280
- !(function(e, t) {
281
- if (!(e instanceof t))
282
- throw new TypeError(
283
- 'Cannot call a class as a function'
284
- );
285
- })(this, t);
286
- var r = (function(e, t) {
278
+ var c = function(e) {
279
+ e.forEach(function(e) {
280
+ e.isIntersecting && e.target.onVisible();
281
+ });
282
+ },
283
+ f = {},
284
+ p = function(e) {
285
+ return (
286
+ (f[e] =
287
+ f[e] ||
288
+ new IntersectionObserver(c, { rootMargin: e + 'px' })),
289
+ f[e]
290
+ );
291
+ },
292
+ d = (function(e) {
293
+ function t(e) {
294
+ !(function(e, t) {
295
+ if (!(e instanceof t))
296
+ throw new TypeError(
297
+ 'Cannot call a class as a function'
298
+ );
299
+ })(this, t);
300
+ var r = (function(e, t) {
287
301
  if (!e)
288
302
  throw new ReferenceError(
289
303
  "this hasn't been initialised - super() hasn't been called"
@@ -295,182 +309,170 @@ module.exports = (function(e) {
295
309
  })(
296
310
  this,
297
311
  (t.__proto__ || Object.getPrototypeOf(t)).call(this, e)
298
- ),
299
- n =
300
- !e.scrollPosition &&
301
- e.useIntersectionObserver &&
302
- (0, l.default)();
303
- if (((r.LAZY_LOAD_OBSERVER = { supportsObserver: n }), n)) {
304
- var o = e.threshold;
305
- r.LAZY_LOAD_OBSERVER.observer = new IntersectionObserver(
306
- r.checkIntersections,
307
- { rootMargin: o + 'px' }
308
312
  );
313
+ if (
314
+ ((r.supportsObserver =
315
+ !e.scrollPosition &&
316
+ e.useIntersectionObserver &&
317
+ (0, l.default)()),
318
+ r.supportsObserver)
319
+ ) {
320
+ var n = e.threshold;
321
+ r.observer = p(n);
322
+ }
323
+ return r;
309
324
  }
310
- return r;
311
- }
312
- return (
313
- (function(e, t) {
314
- if ('function' != typeof t && null !== t)
315
- throw new TypeError(
316
- 'Super expression must either be null or a function, not ' +
317
- typeof t
318
- );
319
- (e.prototype = Object.create(t && t.prototype, {
320
- constructor: {
321
- value: e,
322
- enumerable: !1,
323
- writable: !0,
324
- configurable: !0,
325
+ return (
326
+ (function(e, t) {
327
+ if ('function' != typeof t && null !== t)
328
+ throw new TypeError(
329
+ 'Super expression must either be null or a function, not ' +
330
+ typeof t
331
+ );
332
+ (e.prototype = Object.create(t && t.prototype, {
333
+ constructor: {
334
+ value: e,
335
+ enumerable: !1,
336
+ writable: !0,
337
+ configurable: !0,
338
+ },
339
+ })),
340
+ t &&
341
+ (Object.setPrototypeOf
342
+ ? Object.setPrototypeOf(e, t)
343
+ : (e.__proto__ = t));
344
+ })(t, e),
345
+ o(t, [
346
+ {
347
+ key: 'componentDidMount',
348
+ value: function() {
349
+ this.placeholder &&
350
+ this.observer &&
351
+ ((this.placeholder.onVisible = this.props.onVisible),
352
+ this.observer.observe(this.placeholder)),
353
+ this.supportsObserver ||
354
+ this.updateVisibility();
355
+ },
325
356
  },
326
- })),
327
- t &&
328
- (Object.setPrototypeOf
329
- ? Object.setPrototypeOf(e, t)
330
- : (e.__proto__ = t));
331
- })(t, e),
332
- o(t, [
333
- {
334
- key: 'checkIntersections',
335
- value: function(e) {
336
- e.forEach(function(e) {
337
- e.isIntersecting && e.target.onVisible();
338
- });
357
+ {
358
+ key: 'componentWillUnmount',
359
+ value: function() {
360
+ this.observer &&
361
+ this.observer.unobserve(this.placeholder);
362
+ },
339
363
  },
340
- },
341
- {
342
- key: 'componentDidMount',
343
- value: function() {
344
- this.placeholder &&
345
- this.LAZY_LOAD_OBSERVER &&
346
- this.LAZY_LOAD_OBSERVER.observer &&
347
- ((this.placeholder.onVisible = this.props.onVisible),
348
- this.LAZY_LOAD_OBSERVER.observer.observe(
349
- this.placeholder
350
- )),
351
- this.LAZY_LOAD_OBSERVER &&
352
- !this.LAZY_LOAD_OBSERVER.supportsObserver &&
364
+ {
365
+ key: 'componentDidUpdate',
366
+ value: function() {
367
+ this.supportsObserver ||
353
368
  this.updateVisibility();
369
+ },
354
370
  },
355
- },
356
- {
357
- key: 'componentWillUnmount',
358
- value: function() {
359
- this.LAZY_LOAD_OBSERVER &&
360
- this.LAZY_LOAD_OBSERVER.observer.unobserve(
361
- this.placeholder
362
- );
363
- },
364
- },
365
- {
366
- key: 'componentDidUpdate',
367
- value: function() {
368
- this.LAZY_LOAD_OBSERVER &&
369
- !this.LAZY_LOAD_OBSERVER.supportsObserver &&
370
- this.updateVisibility();
371
- },
372
- },
373
- {
374
- key: 'getPlaceholderBoundingBox',
375
- value: function() {
376
- var e =
377
- arguments.length > 0 &&
378
- void 0 !== arguments[0]
379
- ? arguments[0]
380
- : this.props.scrollPosition,
381
- t = this.placeholder.getBoundingClientRect(),
382
- r = a.default.findDOMNode(this.placeholder)
383
- .style,
384
- n = {
385
- left:
386
- parseInt(
387
- r.getPropertyValue('margin-left'),
388
- 10
389
- ) || 0,
390
- top:
391
- parseInt(
392
- r.getPropertyValue('margin-top'),
393
- 10
394
- ) || 0,
371
+ {
372
+ key: 'getPlaceholderBoundingBox',
373
+ value: function() {
374
+ var e =
375
+ arguments.length > 0 &&
376
+ void 0 !== arguments[0]
377
+ ? arguments[0]
378
+ : this.props.scrollPosition,
379
+ t = this.placeholder.getBoundingClientRect(),
380
+ r = a.default.findDOMNode(this.placeholder)
381
+ .style,
382
+ n = {
383
+ left:
384
+ parseInt(
385
+ r.getPropertyValue(
386
+ 'margin-left'
387
+ ),
388
+ 10
389
+ ) || 0,
390
+ top:
391
+ parseInt(
392
+ r.getPropertyValue(
393
+ 'margin-top'
394
+ ),
395
+ 10
396
+ ) || 0,
397
+ };
398
+ return {
399
+ bottom: e.y + t.bottom + n.top,
400
+ left: e.x + t.left + n.left,
401
+ right: e.x + t.right + n.left,
402
+ top: e.y + t.top + n.top,
395
403
  };
396
- return {
397
- bottom: e.y + t.bottom + n.top,
398
- left: e.x + t.left + n.left,
399
- right: e.x + t.right + n.left,
400
- top: e.y + t.top + n.top,
401
- };
404
+ },
402
405
  },
403
- },
404
- {
405
- key: 'isPlaceholderInViewport',
406
- value: function() {
407
- if (
408
- 'undefined' == typeof window ||
409
- !this.placeholder
410
- )
411
- return !1;
412
- var e = this.props,
413
- t = e.scrollPosition,
414
- r = e.threshold,
415
- n = this.getPlaceholderBoundingBox(t),
416
- o = t.y + window.innerHeight,
417
- i = t.x,
418
- a = t.x + window.innerWidth,
419
- s = t.y;
420
- return Boolean(
421
- s - r <= n.bottom &&
422
- o + r >= n.top &&
423
- i - r <= n.right &&
424
- a + r >= n.left
425
- );
406
+ {
407
+ key: 'isPlaceholderInViewport',
408
+ value: function() {
409
+ if (
410
+ 'undefined' == typeof window ||
411
+ !this.placeholder
412
+ )
413
+ return !1;
414
+ var e = this.props,
415
+ t = e.scrollPosition,
416
+ r = e.threshold,
417
+ n = this.getPlaceholderBoundingBox(t),
418
+ o = t.y + window.innerHeight,
419
+ i = t.x,
420
+ a = t.x + window.innerWidth,
421
+ s = t.y;
422
+ return Boolean(
423
+ s - r <= n.bottom &&
424
+ o + r >= n.top &&
425
+ i - r <= n.right &&
426
+ a + r >= n.left
427
+ );
428
+ },
426
429
  },
427
- },
428
- {
429
- key: 'updateVisibility',
430
- value: function() {
431
- this.isPlaceholderInViewport() &&
432
- this.props.onVisible();
430
+ {
431
+ key: 'updateVisibility',
432
+ value: function() {
433
+ this.isPlaceholderInViewport() &&
434
+ this.props.onVisible();
435
+ },
433
436
  },
434
- },
435
- {
436
- key: 'render',
437
- value: function() {
438
- var e = this,
439
- t = this.props,
440
- r = t.className,
441
- o = t.height,
442
- a = t.placeholder,
443
- s = t.style,
444
- l = t.width;
445
- if (a && 'function' != typeof a.type)
446
- return i.default.cloneElement(a, {
447
- ref: function(t) {
448
- return (e.placeholder = t);
449
- },
450
- });
451
- var u = n({ display: 'inline-block' }, s);
452
- return (
453
- void 0 !== l && (u.width = l),
454
- void 0 !== o && (u.height = o),
455
- i.default.createElement(
456
- 'span',
457
- {
458
- className: r,
437
+ {
438
+ key: 'render',
439
+ value: function() {
440
+ var e = this,
441
+ t = this.props,
442
+ r = t.className,
443
+ o = t.height,
444
+ a = t.placeholder,
445
+ s = t.style,
446
+ l = t.width;
447
+ if (a && 'function' != typeof a.type)
448
+ return i.default.cloneElement(a, {
459
449
  ref: function(t) {
460
450
  return (e.placeholder = t);
461
451
  },
462
- style: u,
463
- },
464
- a
465
- )
466
- );
452
+ });
453
+ var u = n({ display: 'inline-block' }, s);
454
+ return (
455
+ void 0 !== l && (u.width = l),
456
+ void 0 !== o && (u.height = o),
457
+ i.default.createElement(
458
+ 'span',
459
+ {
460
+ className: r,
461
+ ref: function(t) {
462
+ return (e.placeholder = t);
463
+ },
464
+ style: u,
465
+ },
466
+ a
467
+ )
468
+ );
469
+ },
467
470
  },
468
- },
469
- ]),
470
- t
471
- );
472
- })(i.default.Component);
473
- (c.propTypes = {
471
+ ]),
472
+ t
473
+ );
474
+ })(i.default.Component);
475
+ (d.propTypes = {
474
476
  onVisible: s.PropTypes.func.isRequired,
475
477
  className: s.PropTypes.string,
476
478
  height: s.PropTypes.oneOfType([
@@ -489,13 +491,13 @@ module.exports = (function(e) {
489
491
  s.PropTypes.string,
490
492
  ]),
491
493
  }),
492
- (c.defaultProps = {
494
+ (d.defaultProps = {
493
495
  className: '',
494
496
  placeholder: null,
495
497
  threshold: 100,
496
498
  useIntersectionObserver: !0,
497
499
  }),
498
- (t.default = c);
500
+ (t.default = d);
499
501
  },
500
502
  function(e, t) {
501
503
  e.exports = require('react-dom');
@@ -879,6 +881,7 @@ module.exports = (function(e) {
879
881
  e.useIntersectionObserver,
880
882
  e.visibleByDefault,
881
883
  e.wrapperClassName,
884
+ e.wrapperProps,
882
885
  (function(e, t) {
883
886
  var r = {};
884
887
  for (var n in e)
@@ -902,6 +905,7 @@ module.exports = (function(e) {
902
905
  'useIntersectionObserver',
903
906
  'visibleByDefault',
904
907
  'wrapperClassName',
908
+ 'wrapperProps',
905
909
  ]));
906
910
  return i.default.createElement(
907
911
  'img',
@@ -950,31 +954,34 @@ module.exports = (function(e) {
950
954
  value: function(e) {
951
955
  var t = this.props,
952
956
  r = t.effect,
953
- n = t.height,
954
- o = t.placeholderSrc,
955
- a = t.width,
956
- s = t.wrapperClassName,
957
- l = this.state.loaded,
958
- u = l ? ' lazy-load-image-loaded' : '';
957
+ o = t.height,
958
+ a = t.placeholderSrc,
959
+ s = t.width,
960
+ l = t.wrapperClassName,
961
+ u = t.wrapperProps,
962
+ c = this.state.loaded,
963
+ f = c ? ' lazy-load-image-loaded' : '';
959
964
  return i.default.createElement(
960
965
  'span',
961
- {
962
- className:
963
- s +
964
- ' lazy-load-image-background ' +
965
- r +
966
- u,
967
- style: {
968
- backgroundImage:
969
- l || !o ? '' : 'url(' + o + ')',
970
- backgroundSize:
971
- l || !o ? '' : '100% 100%',
972
- color: 'transparent',
973
- display: 'inline-block',
974
- height: n,
975
- width: a,
966
+ n(
967
+ {
968
+ className:
969
+ l +
970
+ ' lazy-load-image-background ' +
971
+ r +
972
+ f,
973
+ style: {
974
+ backgroundImage:
975
+ c || !a ? '' : 'url(' + a + ')',
976
+ backgroundSize:
977
+ c || !a ? '' : '100% 100%',
978
+ display: 'inline-block',
979
+ height: o,
980
+ width: s,
981
+ },
976
982
  },
977
- },
983
+ u
984
+ ),
978
985
  e
979
986
  );
980
987
  },
@@ -986,10 +993,12 @@ module.exports = (function(e) {
986
993
  t = e.effect,
987
994
  r = e.placeholderSrc,
988
995
  n = e.visibleByDefault,
989
- o = this.getLazyLoadImage();
990
- return (!t && !r) || n
991
- ? o
992
- : this.getWrappedLazyLoadImage(o);
996
+ o = e.wrapperClassName,
997
+ i = e.wrapperProps,
998
+ a = this.getLazyLoadImage();
999
+ return ((t || r) && !n) || o || i
1000
+ ? this.getWrappedLazyLoadImage(a)
1001
+ : a;
993
1002
  },
994
1003
  },
995
1004
  ]),
@@ -1007,6 +1016,7 @@ module.exports = (function(e) {
1007
1016
  useIntersectionObserver: a.PropTypes.bool,
1008
1017
  visibleByDefault: a.PropTypes.bool,
1009
1018
  wrapperClassName: a.PropTypes.string,
1019
+ wrapperProps: a.PropTypes.object,
1010
1020
  }),
1011
1021
  (u.defaultProps = {
1012
1022
  afterLoad: function() {
@@ -1223,18 +1233,18 @@ module.exports = (function(e) {
1223
1233
  p = !1,
1224
1234
  d = !0;
1225
1235
  if ('function' != typeof e) throw new TypeError(r);
1226
- function O(t) {
1236
+ function w(t) {
1227
1237
  var r = o,
1228
1238
  n = i;
1229
1239
  return (o = i = void 0), (c = t), (s = e.apply(n, r));
1230
1240
  }
1231
- function w(e) {
1241
+ function O(e) {
1232
1242
  var r = e - u;
1233
1243
  return void 0 === u || r >= t || r < 0 || (p && e - c >= a);
1234
1244
  }
1235
1245
  function g() {
1236
1246
  var e = b();
1237
- if (w(e)) return _(e);
1247
+ if (O(e)) return P(e);
1238
1248
  l = setTimeout(
1239
1249
  g,
1240
1250
  (function(e) {
@@ -1243,22 +1253,22 @@ module.exports = (function(e) {
1243
1253
  })(e)
1244
1254
  );
1245
1255
  }
1246
- function _(e) {
1247
- return (l = void 0), d && o ? O(e) : ((o = i = void 0), s);
1256
+ function P(e) {
1257
+ return (l = void 0), d && o ? w(e) : ((o = i = void 0), s);
1248
1258
  }
1249
- function P() {
1259
+ function T() {
1250
1260
  var e = b(),
1251
- r = w(e);
1261
+ r = O(e);
1252
1262
  if (((o = arguments), (i = this), (u = e), r)) {
1253
1263
  if (void 0 === l)
1254
1264
  return (function(e) {
1255
1265
  return (
1256
1266
  (c = e),
1257
1267
  (l = setTimeout(g, t)),
1258
- f ? O(e) : s
1268
+ f ? w(e) : s
1259
1269
  );
1260
1270
  })(u);
1261
- if (p) return (l = setTimeout(g, t)), O(u);
1271
+ if (p) return (l = setTimeout(g, t)), w(u);
1262
1272
  }
1263
1273
  return void 0 === l && (l = setTimeout(g, t)), s;
1264
1274
  }
@@ -1270,15 +1280,15 @@ module.exports = (function(e) {
1270
1280
  ? y(m(n.maxWait) || 0, t)
1271
1281
  : a),
1272
1282
  (d = 'trailing' in n ? !!n.trailing : d)),
1273
- (P.cancel = function() {
1283
+ (T.cancel = function() {
1274
1284
  void 0 !== l && clearTimeout(l),
1275
1285
  (c = 0),
1276
1286
  (o = u = i = l = void 0);
1277
1287
  }),
1278
- (P.flush = function() {
1279
- return void 0 === l ? s : _(b());
1288
+ (T.flush = function() {
1289
+ return void 0 === l ? s : P(b());
1280
1290
  }),
1281
- P
1291
+ T
1282
1292
  );
1283
1293
  };
1284
1294
  }.call(this, r(7)));
@@ -1323,13 +1333,13 @@ module.exports = (function(e) {
1323
1333
  n = i;
1324
1334
  return (o = i = void 0), (c = t), (s = e.apply(n, r));
1325
1335
  }
1326
- function w(e) {
1336
+ function O(e) {
1327
1337
  var r = e - u;
1328
1338
  return void 0 === u || r >= t || r < 0 || (p && e - c >= a);
1329
1339
  }
1330
1340
  function g() {
1331
1341
  var e = b();
1332
- if (w(e)) return _(e);
1342
+ if (O(e)) return P(e);
1333
1343
  l = setTimeout(
1334
1344
  g,
1335
1345
  (function(e) {
@@ -1338,12 +1348,12 @@ module.exports = (function(e) {
1338
1348
  })(e)
1339
1349
  );
1340
1350
  }
1341
- function _(e) {
1351
+ function P(e) {
1342
1352
  return (l = void 0), d && o ? v(e) : ((o = i = void 0), s);
1343
1353
  }
1344
- function P() {
1354
+ function T() {
1345
1355
  var e = b(),
1346
- r = w(e);
1356
+ r = O(e);
1347
1357
  if (((o = arguments), (i = this), (u = e), r)) {
1348
1358
  if (void 0 === l)
1349
1359
  return (function(e) {
@@ -1358,29 +1368,29 @@ module.exports = (function(e) {
1358
1368
  return void 0 === l && (l = setTimeout(g, t)), s;
1359
1369
  }
1360
1370
  return (
1361
- (t = O(t) || 0),
1371
+ (t = w(t) || 0),
1362
1372
  m(n) &&
1363
1373
  ((f = !!n.leading),
1364
1374
  (a = (p = 'maxWait' in n)
1365
- ? y(O(n.maxWait) || 0, t)
1375
+ ? y(w(n.maxWait) || 0, t)
1366
1376
  : a),
1367
1377
  (d = 'trailing' in n ? !!n.trailing : d)),
1368
- (P.cancel = function() {
1378
+ (T.cancel = function() {
1369
1379
  void 0 !== l && clearTimeout(l),
1370
1380
  (c = 0),
1371
1381
  (o = u = i = l = void 0);
1372
1382
  }),
1373
- (P.flush = function() {
1374
- return void 0 === l ? s : _(b());
1383
+ (T.flush = function() {
1384
+ return void 0 === l ? s : P(b());
1375
1385
  }),
1376
- P
1386
+ T
1377
1387
  );
1378
1388
  }
1379
1389
  function m(e) {
1380
1390
  var t = typeof e;
1381
1391
  return !!e && ('object' == t || 'function' == t);
1382
1392
  }
1383
- function O(e) {
1393
+ function w(e) {
1384
1394
  if ('number' == typeof e) return e;
1385
1395
  if (
1386
1396
  (function(e) {
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "react-lazy-load-image-component",
3
- "version": "1.4.2",
3
+ "version": "1.5.1",
4
4
  "description": " React Component to lazy load images using a HOC to track window scroll position. ",
5
5
  "main": "build/index.js",
6
6
  "peerDependencies": {
7
- "react": "^15.x.x || ^16.x.x",
8
- "react-dom": "^15.x.x || ^16.x.x"
7
+ "react": "^15.x.x || ^16.x.x || ^17.x.x",
8
+ "react-dom": "^15.x.x || ^16.x.x || ^17.x.x"
9
9
  },
10
10
  "dependencies": {
11
11
  "lodash.debounce": "^4.0.8",
@@ -66,6 +66,7 @@ describe('LazyLoadComponent', function() {
66
66
  isIntersectionObserverAvailable.mockImplementation(() => true);
67
67
  window.IntersectionObserver = jest.fn(function() {
68
68
  this.observe = jest.fn(); // eslint-disable-line babel/no-invalid-this
69
+ this.unobserve = jest.fn(); // eslint-disable-line babel/no-invalid-this
69
70
  });
70
71
 
71
72
  const lazyLoadComponent = mount(
@@ -93,6 +94,7 @@ describe('LazyLoadComponent', function() {
93
94
  isIntersectionObserverAvailable.mockImplementation(() => true);
94
95
  window.IntersectionObserver = jest.fn(function() {
95
96
  this.observe = jest.fn(); // eslint-disable-line babel/no-invalid-this
97
+ this.unobserve = jest.fn(); // eslint-disable-line babel/no-invalid-this
96
98
  });
97
99
 
98
100
  const lazyLoadComponent = mount(
@@ -40,6 +40,7 @@ class LazyLoadImage extends React.Component {
40
40
  useIntersectionObserver,
41
41
  visibleByDefault,
42
42
  wrapperClassName,
43
+ wrapperProps,
43
44
  ...imgProps
44
45
  } = this.props;
45
46
 
@@ -89,6 +90,7 @@ class LazyLoadImage extends React.Component {
89
90
  placeholderSrc,
90
91
  width,
91
92
  wrapperClassName,
93
+ wrapperProps,
92
94
  } = this.props;
93
95
  const { loaded } = this.state;
94
96
 
@@ -114,6 +116,7 @@ class LazyLoadImage extends React.Component {
114
116
  height: height,
115
117
  width: width,
116
118
  }}
119
+ {...wrapperProps}
117
120
  >
118
121
  {lazyLoadImage}
119
122
  </span>
@@ -121,11 +124,18 @@ class LazyLoadImage extends React.Component {
121
124
  }
122
125
 
123
126
  render() {
124
- const { effect, placeholderSrc, visibleByDefault } = this.props;
127
+ const {
128
+ effect,
129
+ placeholderSrc,
130
+ visibleByDefault,
131
+ wrapperClassName,
132
+ wrapperProps,
133
+ } = this.props;
125
134
 
126
135
  const lazyLoadImage = this.getLazyLoadImage();
136
+ const needsWrapper = (effect || placeholderSrc) && !visibleByDefault;
127
137
 
128
- if ((!effect && !placeholderSrc) || visibleByDefault) {
138
+ if (!needsWrapper && !wrapperClassName && !wrapperProps) {
129
139
  return lazyLoadImage;
130
140
  }
131
141
 
@@ -144,6 +154,7 @@ LazyLoadImage.propTypes = {
144
154
  useIntersectionObserver: PropTypes.bool,
145
155
  visibleByDefault: PropTypes.bool,
146
156
  wrapperClassName: PropTypes.string,
157
+ wrapperProps: PropTypes.object,
147
158
  };
148
159
 
149
160
  LazyLoadImage.defaultProps = {
@@ -3,64 +3,61 @@ import ReactDOM from 'react-dom';
3
3
  import { PropTypes } from 'prop-types';
4
4
  import isIntersectionObserverAvailable from '../utils/intersection-observer';
5
5
 
6
+ const checkIntersections = entries => {
7
+ entries.forEach(entry => {
8
+ if (entry.isIntersecting) {
9
+ entry.target.onVisible();
10
+ }
11
+ });
12
+ };
13
+
14
+ const LAZY_LOAD_OBSERVERS = {};
15
+
16
+ const getObserver = threshold => {
17
+ LAZY_LOAD_OBSERVERS[threshold] =
18
+ LAZY_LOAD_OBSERVERS[threshold] ||
19
+ new IntersectionObserver(checkIntersections, {
20
+ rootMargin: threshold + 'px',
21
+ });
22
+
23
+ return LAZY_LOAD_OBSERVERS[threshold];
24
+ };
25
+
6
26
  class PlaceholderWithoutTracking extends React.Component {
7
27
  constructor(props) {
8
28
  super(props);
9
29
 
10
- const supportsObserver =
30
+ this.supportsObserver =
11
31
  !props.scrollPosition &&
12
32
  props.useIntersectionObserver &&
13
33
  isIntersectionObserverAvailable();
14
34
 
15
- this.LAZY_LOAD_OBSERVER = { supportsObserver };
16
-
17
- if (supportsObserver) {
35
+ if (this.supportsObserver) {
18
36
  const { threshold } = props;
19
37
 
20
- this.LAZY_LOAD_OBSERVER.observer = new IntersectionObserver(
21
- this.checkIntersections,
22
- { rootMargin: threshold + 'px' }
23
- );
38
+ this.observer = getObserver(threshold);
24
39
  }
25
40
  }
26
41
 
27
- checkIntersections(entries) {
28
- entries.forEach(entry => {
29
- if (entry.isIntersecting) {
30
- entry.target.onVisible();
31
- }
32
- });
33
- }
34
-
35
42
  componentDidMount() {
36
- if (
37
- this.placeholder &&
38
- this.LAZY_LOAD_OBSERVER &&
39
- this.LAZY_LOAD_OBSERVER.observer
40
- ) {
43
+ if (this.placeholder && this.observer) {
41
44
  this.placeholder.onVisible = this.props.onVisible;
42
- this.LAZY_LOAD_OBSERVER.observer.observe(this.placeholder);
45
+ this.observer.observe(this.placeholder);
43
46
  }
44
47
 
45
- if (
46
- this.LAZY_LOAD_OBSERVER &&
47
- !this.LAZY_LOAD_OBSERVER.supportsObserver
48
- ) {
48
+ if (!this.supportsObserver) {
49
49
  this.updateVisibility();
50
50
  }
51
51
  }
52
52
 
53
53
  componentWillUnmount() {
54
- if (this.LAZY_LOAD_OBSERVER) {
55
- this.LAZY_LOAD_OBSERVER.observer.unobserve(this.placeholder);
54
+ if (this.observer) {
55
+ this.observer.unobserve(this.placeholder);
56
56
  }
57
57
  }
58
58
 
59
59
  componentDidUpdate() {
60
- if (
61
- this.LAZY_LOAD_OBSERVER &&
62
- !this.LAZY_LOAD_OBSERVER.supportsObserver
63
- ) {
60
+ if (!this.supportsObserver) {
64
61
  this.updateVisibility();
65
62
  }
66
63
  }
@@ -197,6 +197,7 @@ describe('PlaceholderWithoutTracking', function() {
197
197
  isIntersectionObserverAvailable.mockImplementation(() => true);
198
198
  window.IntersectionObserver = jest.fn(function() {
199
199
  this.observe = jest.fn(); // eslint-disable-line babel/no-invalid-this
200
+ this.unobserve = jest.fn(); // eslint-disable-line babel/no-invalid-this
200
201
  });
201
202
  const onVisible = jest.fn();
202
203
  const component = renderPlaceholderWithoutTracking({
@@ -211,6 +212,7 @@ describe('PlaceholderWithoutTracking', function() {
211
212
  isIntersectionObserverAvailable.mockImplementation(() => true);
212
213
  window.IntersectionObserver = jest.fn(function() {
213
214
  this.observe = jest.fn(); // eslint-disable-line babel/no-invalid-this
215
+ this.unobserve = jest.fn(); // eslint-disable-line babel/no-invalid-this
214
216
  });
215
217
  const offset = 100000;
216
218
  const onVisible = jest.fn();
@@ -1,5 +1,4 @@
1
1
  .lazy-load-image-background.opacity {
2
- background-image: none !important;
3
2
  opacity: 0;
4
3
  }
5
4