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.
- 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();
|