react-lazy-load-image-component 1.4.2 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/codeql-analysis.yml +71 -0
- package/README.md +14 -1
- package/build/index.js +234 -224
- package/package.json +3 -3
- package/src/components/LazyLoadComponent.spec.js +2 -0
- package/src/components/LazyLoadImage.jsx +13 -2
- package/src/components/PlaceholderWithoutTracking.jsx +29 -32
- package/src/components/PlaceholderWithoutTracking.spec.js +2 -0
- package/src/effects/opacity.css +0 -1
@@ -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 =
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
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
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
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
|
-
|
328
|
-
(
|
329
|
-
|
330
|
-
|
331
|
-
|
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
|
-
|
343
|
-
|
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
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
.
|
384
|
-
|
385
|
-
left
|
386
|
-
|
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
|
-
|
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
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
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
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
430
|
+
{
|
431
|
+
key: 'updateVisibility',
|
432
|
+
value: function() {
|
433
|
+
this.isPlaceholderInViewport() &&
|
434
|
+
this.props.onVisible();
|
435
|
+
},
|
433
436
|
},
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
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
|
-
|
463
|
-
|
464
|
-
|
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
|
-
|
471
|
-
);
|
472
|
-
|
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
|
-
(
|
494
|
+
(d.defaultProps = {
|
493
495
|
className: '',
|
494
496
|
placeholder: null,
|
495
497
|
threshold: 100,
|
496
498
|
useIntersectionObserver: !0,
|
497
499
|
}),
|
498
|
-
(t.default =
|
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
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
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
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
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 =
|
990
|
-
|
991
|
-
|
992
|
-
|
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
|
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
|
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 (
|
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
|
1247
|
-
return (l = void 0), d && o ?
|
1256
|
+
function P(e) {
|
1257
|
+
return (l = void 0), d && o ? w(e) : ((o = i = void 0), s);
|
1248
1258
|
}
|
1249
|
-
function
|
1259
|
+
function T() {
|
1250
1260
|
var e = b(),
|
1251
|
-
r =
|
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 ?
|
1268
|
+
f ? w(e) : s
|
1259
1269
|
);
|
1260
1270
|
})(u);
|
1261
|
-
if (p) return (l = setTimeout(g, t)),
|
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
|
-
(
|
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
|
-
(
|
1279
|
-
return void 0 === l ? s :
|
1288
|
+
(T.flush = function() {
|
1289
|
+
return void 0 === l ? s : P(b());
|
1280
1290
|
}),
|
1281
|
-
|
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
|
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 (
|
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
|
1351
|
+
function P(e) {
|
1342
1352
|
return (l = void 0), d && o ? v(e) : ((o = i = void 0), s);
|
1343
1353
|
}
|
1344
|
-
function
|
1354
|
+
function T() {
|
1345
1355
|
var e = b(),
|
1346
|
-
r =
|
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 =
|
1371
|
+
(t = w(t) || 0),
|
1362
1372
|
m(n) &&
|
1363
1373
|
((f = !!n.leading),
|
1364
1374
|
(a = (p = 'maxWait' in n)
|
1365
|
-
? y(
|
1375
|
+
? y(w(n.maxWait) || 0, t)
|
1366
1376
|
: a),
|
1367
1377
|
(d = 'trailing' in n ? !!n.trailing : d)),
|
1368
|
-
(
|
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
|
-
(
|
1374
|
-
return void 0 === l ? s :
|
1383
|
+
(T.flush = function() {
|
1384
|
+
return void 0 === l ? s : P(b());
|
1375
1385
|
}),
|
1376
|
-
|
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
|
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.
|
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 {
|
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 (
|
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
|
-
|
30
|
+
this.supportsObserver =
|
11
31
|
!props.scrollPosition &&
|
12
32
|
props.useIntersectionObserver &&
|
13
33
|
isIntersectionObserverAvailable();
|
14
34
|
|
15
|
-
this.
|
16
|
-
|
17
|
-
if (supportsObserver) {
|
35
|
+
if (this.supportsObserver) {
|
18
36
|
const { threshold } = props;
|
19
37
|
|
20
|
-
this.
|
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.
|
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.
|
55
|
-
this.
|
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();
|