@docusaurus/plugin-ideal-image 3.7.0 → 3.8.0-canary-6327
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/lib/index.js +6 -0
- package/lib/theme/IdealImage/index.js +1 -2
- package/lib/theme/IdealImageLegacy/LICENSE +20 -0
- package/lib/theme/IdealImageLegacy/README.md +13 -0
- package/lib/theme/IdealImageLegacy/components/Icon/Download.d.ts +3 -0
- package/lib/theme/IdealImageLegacy/components/Icon/Download.js +15 -0
- package/lib/theme/IdealImageLegacy/components/Icon/Loading.d.ts +3 -0
- package/lib/theme/IdealImageLegacy/components/Icon/Loading.js +15 -0
- package/lib/theme/IdealImageLegacy/components/Icon/Offline.d.ts +3 -0
- package/lib/theme/IdealImageLegacy/components/Icon/Offline.js +15 -0
- package/lib/theme/IdealImageLegacy/components/Icon/Warning.d.ts +3 -0
- package/lib/theme/IdealImageLegacy/components/Icon/Warning.js +15 -0
- package/lib/theme/IdealImageLegacy/components/Icon/index.d.ts +8 -0
- package/lib/theme/IdealImageLegacy/components/Icon/index.js +25 -0
- package/lib/theme/IdealImageLegacy/components/IdealImage/index.d.ts +42 -0
- package/lib/theme/IdealImageLegacy/components/IdealImage/index.js +352 -0
- package/lib/theme/IdealImageLegacy/components/IdealImage/waypoint.d.ts +10 -0
- package/lib/theme/IdealImageLegacy/components/IdealImage/waypoint.js +188 -0
- package/lib/theme/IdealImageLegacy/components/IdealImageWithDefaults/index.d.ts +33 -0
- package/lib/theme/IdealImageLegacy/components/IdealImageWithDefaults/index.js +12 -0
- package/lib/theme/IdealImageLegacy/components/Media/index.d.ts +20 -0
- package/lib/theme/IdealImageLegacy/components/Media/index.js +169 -0
- package/lib/theme/IdealImageLegacy/components/MediaWithDefaults/README.md +89 -0
- package/lib/theme/IdealImageLegacy/components/MediaWithDefaults/index.d.ts +33 -0
- package/lib/theme/IdealImageLegacy/components/MediaWithDefaults/index.js +12 -0
- package/lib/theme/IdealImageLegacy/components/composeStyle.d.ts +5 -0
- package/lib/theme/IdealImageLegacy/components/composeStyle.js +37 -0
- package/lib/theme/IdealImageLegacy/components/constants.d.ts +22 -0
- package/lib/theme/IdealImageLegacy/components/constants.js +24 -0
- package/lib/theme/IdealImageLegacy/components/helpers.d.ts +22 -0
- package/lib/theme/IdealImageLegacy/components/helpers.js +141 -0
- package/lib/theme/IdealImageLegacy/components/icons.d.ts +15 -0
- package/lib/theme/IdealImageLegacy/components/icons.js +16 -0
- package/lib/theme/IdealImageLegacy/components/loaders.d.ts +4 -0
- package/lib/theme/IdealImageLegacy/components/loaders.js +112 -0
- package/lib/theme/IdealImageLegacy/components/theme.d.ts +30 -0
- package/lib/theme/IdealImageLegacy/components/theme.js +26 -0
- package/lib/theme/IdealImageLegacy/components/theme.module.css +35 -0
- package/lib/theme/IdealImageLegacy/components/unfetch.d.ts +7 -0
- package/lib/theme/IdealImageLegacy/components/unfetch.js +74 -0
- package/lib/theme/IdealImageLegacy/index.d.ts +2 -0
- package/lib/theme/IdealImageLegacy/index.js +2 -0
- package/package.json +8 -10
- package/src/index.ts +6 -0
- package/src/plugin-ideal-image.d.ts +121 -0
- package/src/theme/IdealImage/index.tsx +2 -3
- package/src/theme/IdealImageLegacy/LICENSE +20 -0
- package/src/theme/IdealImageLegacy/README.md +13 -0
- package/src/theme/IdealImageLegacy/components/Icon/Download.js +15 -0
- package/src/theme/IdealImageLegacy/components/Icon/Loading.js +15 -0
- package/src/theme/IdealImageLegacy/components/Icon/Offline.js +15 -0
- package/src/theme/IdealImageLegacy/components/Icon/Warning.js +15 -0
- package/src/theme/IdealImageLegacy/components/Icon/index.js +25 -0
- package/src/theme/IdealImageLegacy/components/IdealImage/index.js +352 -0
- package/src/theme/IdealImageLegacy/components/IdealImage/waypoint.tsx +254 -0
- package/src/theme/IdealImageLegacy/components/IdealImageWithDefaults/index.js +12 -0
- package/src/theme/IdealImageLegacy/components/Media/index.js +169 -0
- package/src/theme/IdealImageLegacy/components/MediaWithDefaults/README.md +89 -0
- package/src/theme/IdealImageLegacy/components/MediaWithDefaults/index.js +12 -0
- package/src/theme/IdealImageLegacy/components/composeStyle.js +37 -0
- package/src/theme/IdealImageLegacy/components/constants.js +24 -0
- package/src/theme/IdealImageLegacy/components/helpers.js +141 -0
- package/src/theme/IdealImageLegacy/components/icons.js +16 -0
- package/src/theme/IdealImageLegacy/components/loaders.js +112 -0
- package/src/theme/IdealImageLegacy/components/theme.js +26 -0
- package/src/theme/IdealImageLegacy/components/theme.module.css +35 -0
- package/src/theme/IdealImageLegacy/components/unfetch.js +74 -0
- package/src/theme/IdealImageLegacy/index.tsx +3 -0
- package/src/deps.d.ts +0 -124
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
Copyright (c) 2017 stereobooster
|
|
3
|
+
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Legacy React IdealImage lib
|
|
2
|
+
|
|
3
|
+
This is legacy code from an npm package we forked, then internalized
|
|
4
|
+
|
|
5
|
+
See also:
|
|
6
|
+
|
|
7
|
+
- https://github.com/slorber/docusaurus-react-ideal-image
|
|
8
|
+
- https://github.com/endiliey/react-ideal-image
|
|
9
|
+
- https://github.com/stereobooster/react-ideal-image
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
TODO: we need to clean it up, remove what we don't need, and maintain it up to date
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// This icon is from "material design icons"
|
|
2
|
+
// It is licensed under Apache License 2.0
|
|
3
|
+
// Full text is available here
|
|
4
|
+
// https://github.com/google/material-design-icons/blob/master/LICENSE
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import Icon from './index';
|
|
7
|
+
|
|
8
|
+
const Download = (props) => (
|
|
9
|
+
<Icon
|
|
10
|
+
{...props}
|
|
11
|
+
path="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export default Download;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// This icon is from "material design icons"
|
|
2
|
+
// It is licensed under Apache License 2.0
|
|
3
|
+
// Full text is available here
|
|
4
|
+
// https://github.com/google/material-design-icons/blob/master/LICENSE
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import Icon from './index';
|
|
7
|
+
|
|
8
|
+
const Loading = (props) => (
|
|
9
|
+
<Icon
|
|
10
|
+
{...props}
|
|
11
|
+
path="M6,2V8H6V8L10,12L6,16V16H6V22H18V16H18V16L14,12L18,8V8H18V2H6M16,16.5V20H8V16.5L12,12.5L16,16.5M12,11.5L8,7.5V4H16V7.5L12,11.5Z"
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export default Loading;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// This icon is from "material design icons"
|
|
2
|
+
// It is licensed under Apache License 2.0
|
|
3
|
+
// Full text is available here
|
|
4
|
+
// https://github.com/google/material-design-icons/blob/master/LICENSE
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import Icon from './index';
|
|
7
|
+
|
|
8
|
+
const Offline = (props) => (
|
|
9
|
+
<Icon
|
|
10
|
+
{...props}
|
|
11
|
+
path="M19.35 10.04C18.67 6.59 15.64 4 12 4c-1.48 0-2.85.43-4.01 1.17l1.46 1.46C10.21 6.23 11.08 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3 0 1.13-.64 2.11-1.56 2.62l1.45 1.45C23.16 18.16 24 16.68 24 15c0-2.64-2.05-4.78-4.65-4.96zM3 5.27l2.75 2.74C2.56 8.15 0 10.77 0 14c0 3.31 2.69 6 6 6h11.73l2 2L21 20.73 4.27 4 3 5.27zM7.73 10l8 8H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h1.73z"
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export default Offline;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// This icon is from "material design icons"
|
|
2
|
+
// It is licensed under Apache License 2.0
|
|
3
|
+
// Full text is available here
|
|
4
|
+
// https://github.com/google/material-design-icons/blob/master/LICENSE
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import Icon from './index';
|
|
7
|
+
|
|
8
|
+
const Warning = (props) => (
|
|
9
|
+
<Icon
|
|
10
|
+
{...props}
|
|
11
|
+
path="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export default Warning;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
// import PropTypes from 'prop-types'
|
|
3
|
+
|
|
4
|
+
const Icon = ({size = 24, fill = '#000', className, path}) => (
|
|
5
|
+
<svg
|
|
6
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
7
|
+
width={size}
|
|
8
|
+
height={size}
|
|
9
|
+
viewBox="0 0 24 24"
|
|
10
|
+
className={className}>
|
|
11
|
+
<path d="M0 0h24v24H0z" fill="none" />
|
|
12
|
+
<path fill={fill} d={path} />
|
|
13
|
+
</svg>
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
Icon.propTypes = {
|
|
18
|
+
size: PropTypes.number,
|
|
19
|
+
fill: PropTypes.string,
|
|
20
|
+
className: PropTypes.string,
|
|
21
|
+
path: PropTypes.string.isRequired,
|
|
22
|
+
}
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export default Icon;
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import React, {Component} from 'react';
|
|
2
|
+
import {Waypoint} from './waypoint';
|
|
3
|
+
import Media from '../Media';
|
|
4
|
+
import {icons, loadStates} from '../constants';
|
|
5
|
+
import {xhrLoader, imageLoader, timeout, combineCancel} from '../loaders';
|
|
6
|
+
import {
|
|
7
|
+
guessMaxImageWidth,
|
|
8
|
+
bytesToSize,
|
|
9
|
+
supportsWebp,
|
|
10
|
+
ssr,
|
|
11
|
+
nativeConnection,
|
|
12
|
+
selectSrc,
|
|
13
|
+
fallbackParams,
|
|
14
|
+
} from '../helpers';
|
|
15
|
+
|
|
16
|
+
const {initial, loading, loaded, error} = loadStates;
|
|
17
|
+
|
|
18
|
+
const defaultShouldAutoDownload = ({
|
|
19
|
+
connection,
|
|
20
|
+
size,
|
|
21
|
+
threshold,
|
|
22
|
+
possiblySlowNetwork,
|
|
23
|
+
}) => {
|
|
24
|
+
if (possiblySlowNetwork) return false;
|
|
25
|
+
if (!connection) return true;
|
|
26
|
+
const {downlink, rtt, effectiveType} = connection;
|
|
27
|
+
switch (effectiveType) {
|
|
28
|
+
case 'slow-2g':
|
|
29
|
+
case '2g':
|
|
30
|
+
return false;
|
|
31
|
+
case '3g':
|
|
32
|
+
if (downlink && size && threshold) {
|
|
33
|
+
return (size * 8) / (downlink * 1000) + rtt < threshold;
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
case '4g':
|
|
37
|
+
default:
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const defaultGetMessage = (icon, state) => {
|
|
43
|
+
switch (icon) {
|
|
44
|
+
case icons.noicon:
|
|
45
|
+
case icons.loaded:
|
|
46
|
+
return null;
|
|
47
|
+
case icons.loading:
|
|
48
|
+
return 'Loading...';
|
|
49
|
+
case icons.load:
|
|
50
|
+
// we can show `alt` here
|
|
51
|
+
const {pickedSrc} = state;
|
|
52
|
+
const {size} = pickedSrc;
|
|
53
|
+
if (size) {
|
|
54
|
+
return [
|
|
55
|
+
'Click to load (',
|
|
56
|
+
<nobr key="nb">{bytesToSize(size)}</nobr>,
|
|
57
|
+
')',
|
|
58
|
+
];
|
|
59
|
+
} else {
|
|
60
|
+
return 'Click to load';
|
|
61
|
+
}
|
|
62
|
+
case icons.offline:
|
|
63
|
+
return 'Your browser is offline. Image not loaded';
|
|
64
|
+
case icons.error:
|
|
65
|
+
const {loadInfo} = state;
|
|
66
|
+
if (loadInfo === 404) {
|
|
67
|
+
return '404. Image not found';
|
|
68
|
+
} else {
|
|
69
|
+
return 'Error. Click to reload';
|
|
70
|
+
}
|
|
71
|
+
default:
|
|
72
|
+
throw new Error(`Wrong icon: ${icon}`);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const defaultGetIcon = (state) => {
|
|
77
|
+
const {loadState, onLine, overThreshold, userTriggered} = state;
|
|
78
|
+
if (ssr) return icons.noicon;
|
|
79
|
+
switch (loadState) {
|
|
80
|
+
case loaded:
|
|
81
|
+
return icons.loaded;
|
|
82
|
+
case loading:
|
|
83
|
+
return overThreshold ? icons.loading : icons.noicon;
|
|
84
|
+
case initial:
|
|
85
|
+
if (onLine) {
|
|
86
|
+
const {shouldAutoDownload} = state;
|
|
87
|
+
if (shouldAutoDownload === undefined) return icons.noicon;
|
|
88
|
+
return userTriggered || !shouldAutoDownload ? icons.load : icons.noicon;
|
|
89
|
+
} else {
|
|
90
|
+
return icons.offline;
|
|
91
|
+
}
|
|
92
|
+
case error:
|
|
93
|
+
return onLine ? icons.error : icons.offline;
|
|
94
|
+
default:
|
|
95
|
+
throw new Error(`Wrong state: ${loadState}`);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export default class IdealImage extends Component {
|
|
100
|
+
constructor(props) {
|
|
101
|
+
super(props);
|
|
102
|
+
// TODO: validate props.srcSet
|
|
103
|
+
this.state = {
|
|
104
|
+
loadState: initial,
|
|
105
|
+
connection: nativeConnection
|
|
106
|
+
? {
|
|
107
|
+
downlink: navigator.connection.downlink, // megabits per second
|
|
108
|
+
rtt: navigator.connection.rtt, // ms
|
|
109
|
+
effectiveType: navigator.connection.effectiveType, // 'slow-2g', '2g', '3g', or '4g'
|
|
110
|
+
}
|
|
111
|
+
: null,
|
|
112
|
+
onLine: true,
|
|
113
|
+
overThreshold: false,
|
|
114
|
+
inViewport: false,
|
|
115
|
+
userTriggered: false,
|
|
116
|
+
possiblySlowNetwork: false,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/*
|
|
121
|
+
static propTypes = {
|
|
122
|
+
/!** how much to wait in ms until consider download to slow *!/
|
|
123
|
+
threshold: PropTypes.number,
|
|
124
|
+
/!** function to generate src based on width and format *!/
|
|
125
|
+
getUrl: PropTypes.func,
|
|
126
|
+
/!** array of sources *!/
|
|
127
|
+
srcSet: PropTypes.arrayOf(
|
|
128
|
+
PropTypes.shape({
|
|
129
|
+
width: PropTypes.number.isRequired,
|
|
130
|
+
src: PropTypes.string,
|
|
131
|
+
size: PropTypes.number,
|
|
132
|
+
format: PropTypes.oneOf(['jpeg', 'jpg', 'webp', 'png', 'gif']),
|
|
133
|
+
}),
|
|
134
|
+
).isRequired,
|
|
135
|
+
/!** function which decides if image should be downloaded *!/
|
|
136
|
+
shouldAutoDownload: PropTypes.func,
|
|
137
|
+
/!** function which decides what message to show *!/
|
|
138
|
+
getMessage: PropTypes.func,
|
|
139
|
+
/!** function which decides what icon to show *!/
|
|
140
|
+
getIcon: PropTypes.func,
|
|
141
|
+
/!** type of loader *!/
|
|
142
|
+
loader: PropTypes.oneOf(['image', 'xhr']),
|
|
143
|
+
/!** Width of the image in px *!/
|
|
144
|
+
width: PropTypes.number.isRequired,
|
|
145
|
+
/!** Height of the image in px *!/
|
|
146
|
+
height: PropTypes.number.isRequired,
|
|
147
|
+
placeholder: PropTypes.oneOfType([
|
|
148
|
+
PropTypes.shape({
|
|
149
|
+
/!** Solid color placeholder *!/
|
|
150
|
+
color: PropTypes.string.isRequired,
|
|
151
|
+
}),
|
|
152
|
+
PropTypes.shape({
|
|
153
|
+
/!**
|
|
154
|
+
* [Low Quality Image Placeholder](https://github.com/zouhir/lqip)
|
|
155
|
+
* [SVG-Based Image Placeholder](https://github.com/technopagan/sqip)
|
|
156
|
+
* base64 encoded image of low quality
|
|
157
|
+
*!/
|
|
158
|
+
lqip: PropTypes.string.isRequired,
|
|
159
|
+
}),
|
|
160
|
+
]).isRequired,
|
|
161
|
+
/!** Map of icons *!/
|
|
162
|
+
icons: PropTypes.object.isRequired,
|
|
163
|
+
/!** theme object - CSS Modules or React styles *!/
|
|
164
|
+
theme: PropTypes.object.isRequired,
|
|
165
|
+
}*/
|
|
166
|
+
|
|
167
|
+
static defaultProps = {
|
|
168
|
+
shouldAutoDownload: defaultShouldAutoDownload,
|
|
169
|
+
getMessage: defaultGetMessage,
|
|
170
|
+
getIcon: defaultGetIcon,
|
|
171
|
+
loader: 'xhr',
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
componentDidMount() {
|
|
175
|
+
if (nativeConnection) {
|
|
176
|
+
this.updateConnection = () => {
|
|
177
|
+
if (!navigator.onLine) return;
|
|
178
|
+
if (this.state.loadState === initial) {
|
|
179
|
+
this.setState({
|
|
180
|
+
connection: {
|
|
181
|
+
effectiveType: navigator.connection.effectiveType,
|
|
182
|
+
downlink: navigator.connection.downlink,
|
|
183
|
+
rtt: navigator.connection.rtt,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
navigator.connection.addEventListener('onchange', this.updateConnection);
|
|
189
|
+
} else if (this.props.threshold) {
|
|
190
|
+
this.possiblySlowNetworkListener = (e) => {
|
|
191
|
+
if (this.state.loadState !== initial) return;
|
|
192
|
+
const {possiblySlowNetwork} = e.detail;
|
|
193
|
+
if (!this.state.possiblySlowNetwork && possiblySlowNetwork) {
|
|
194
|
+
this.setState({possiblySlowNetwork});
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
window.document.addEventListener(
|
|
198
|
+
'possiblySlowNetwork',
|
|
199
|
+
this.possiblySlowNetworkListener,
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
this.updateOnlineStatus = () => this.setState({onLine: navigator.onLine});
|
|
203
|
+
this.updateOnlineStatus();
|
|
204
|
+
window.addEventListener('online', this.updateOnlineStatus);
|
|
205
|
+
window.addEventListener('offline', this.updateOnlineStatus);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
componentWillUnmount() {
|
|
209
|
+
this.clear();
|
|
210
|
+
if (nativeConnection) {
|
|
211
|
+
navigator.connection.removeEventListener(
|
|
212
|
+
'onchange',
|
|
213
|
+
this.updateConnection,
|
|
214
|
+
);
|
|
215
|
+
} else if (this.props.threshold) {
|
|
216
|
+
window.document.removeEventListener(
|
|
217
|
+
'possiblySlowNetwork',
|
|
218
|
+
this.possiblySlowNetworkListener,
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
window.removeEventListener('online', this.updateOnlineStatus);
|
|
222
|
+
window.removeEventListener('offline', this.updateOnlineStatus);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
onClick = () => {
|
|
226
|
+
const {loadState, onLine, overThreshold} = this.state;
|
|
227
|
+
if (!onLine) return;
|
|
228
|
+
switch (loadState) {
|
|
229
|
+
case loading:
|
|
230
|
+
if (overThreshold) this.cancel(true);
|
|
231
|
+
return;
|
|
232
|
+
case loaded:
|
|
233
|
+
// nothing
|
|
234
|
+
return;
|
|
235
|
+
case initial:
|
|
236
|
+
case error:
|
|
237
|
+
this.load(true);
|
|
238
|
+
return;
|
|
239
|
+
default:
|
|
240
|
+
throw new Error(`Wrong state: ${loadState}`);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
clear() {
|
|
245
|
+
if (this.loader) {
|
|
246
|
+
this.loader.cancel();
|
|
247
|
+
this.loader = undefined;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
cancel(userTriggered) {
|
|
252
|
+
if (loading !== this.state.loadState) return;
|
|
253
|
+
this.clear();
|
|
254
|
+
this.loadStateChange(initial, userTriggered);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
loadStateChange(loadState, userTriggered, loadInfo = null) {
|
|
258
|
+
this.setState({
|
|
259
|
+
loadState,
|
|
260
|
+
overThreshold: false,
|
|
261
|
+
userTriggered: !!userTriggered,
|
|
262
|
+
loadInfo,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
load = (userTriggered) => {
|
|
267
|
+
const {loadState, url} = this.state;
|
|
268
|
+
if (ssr || loaded === loadState || loading === loadState) return;
|
|
269
|
+
this.loadStateChange(loading, userTriggered);
|
|
270
|
+
|
|
271
|
+
const {threshold} = this.props;
|
|
272
|
+
const loader =
|
|
273
|
+
this.props.loader === 'xhr' ? xhrLoader(url) : imageLoader(url);
|
|
274
|
+
loader
|
|
275
|
+
.then(() => {
|
|
276
|
+
this.clear();
|
|
277
|
+
this.loadStateChange(loaded, false);
|
|
278
|
+
})
|
|
279
|
+
.catch((e) => {
|
|
280
|
+
this.clear();
|
|
281
|
+
if (e.status === 404) {
|
|
282
|
+
this.loadStateChange(error, false, 404);
|
|
283
|
+
} else {
|
|
284
|
+
this.loadStateChange(error, false);
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
if (threshold) {
|
|
289
|
+
const timeoutLoader = timeout(threshold);
|
|
290
|
+
timeoutLoader.then(() => {
|
|
291
|
+
if (!this.loader) return;
|
|
292
|
+
window.document.dispatchEvent(
|
|
293
|
+
new CustomEvent('possiblySlowNetwork', {
|
|
294
|
+
detail: {possiblySlowNetwork: true},
|
|
295
|
+
}),
|
|
296
|
+
);
|
|
297
|
+
this.setState({overThreshold: true});
|
|
298
|
+
if (!this.state.userTriggered) this.cancel(true);
|
|
299
|
+
});
|
|
300
|
+
this.loader = combineCancel(loader, timeoutLoader);
|
|
301
|
+
} else {
|
|
302
|
+
this.loader = loader;
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
onEnter = () => {
|
|
307
|
+
if (this.state.inViewport) return;
|
|
308
|
+
this.setState({inViewport: true});
|
|
309
|
+
const pickedSrc = selectSrc({
|
|
310
|
+
srcSet: this.props.srcSet,
|
|
311
|
+
maxImageWidth:
|
|
312
|
+
this.props.srcSet.length > 1
|
|
313
|
+
? guessMaxImageWidth(this.state.dimensions) // eslint-disable-line react/no-access-state-in-setstate
|
|
314
|
+
: 0,
|
|
315
|
+
supportsWebp,
|
|
316
|
+
});
|
|
317
|
+
const {getUrl} = this.props;
|
|
318
|
+
const url = getUrl ? getUrl(pickedSrc) : pickedSrc.src;
|
|
319
|
+
const shouldAutoDownload = this.props.shouldAutoDownload({
|
|
320
|
+
...this.state, // eslint-disable-line react/no-access-state-in-setstate
|
|
321
|
+
size: pickedSrc.size,
|
|
322
|
+
});
|
|
323
|
+
this.setState({pickedSrc, shouldAutoDownload, url}, () => {
|
|
324
|
+
if (shouldAutoDownload) this.load(false);
|
|
325
|
+
});
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
onLeave = () => {
|
|
329
|
+
if (this.state.loadState === loading && !this.state.userTriggered) {
|
|
330
|
+
this.setState({inViewport: false});
|
|
331
|
+
this.cancel(false);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
render() {
|
|
336
|
+
const icon = this.props.getIcon(this.state);
|
|
337
|
+
const message = this.props.getMessage(icon, this.state);
|
|
338
|
+
return (
|
|
339
|
+
<Waypoint onEnter={this.onEnter} onLeave={this.onLeave}>
|
|
340
|
+
<Media
|
|
341
|
+
{...this.props}
|
|
342
|
+
{...fallbackParams(this.props)}
|
|
343
|
+
onClick={this.onClick}
|
|
344
|
+
icon={icon}
|
|
345
|
+
src={this.state.url || ''}
|
|
346
|
+
onDimensions={(dimensions) => this.setState({dimensions})}
|
|
347
|
+
message={message}
|
|
348
|
+
/>
|
|
349
|
+
</Waypoint>
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
}
|