@elacity-js/uikit
Version:
React / Material UI Design kit for Elacity project
105 lines (102 loc) • 3.93 kB
JavaScript
import { __rest } from '../node_modules/tslib/tslib.es6.js';
import { jsx } from 'react/jsx-runtime';
import React__default from 'react';
import { Fade } from '@mui/material';
import { toIpfsGateway, retry } from '@elacity-js/lib';
import useMounted from '../hooks/useMounted.js';
// eslint-disable-next-line max-len
const loadImageAsync = (src, img) => () => new Promise((resolve, reject) => {
const imgEl = new Image();
const $el = img || imgEl;
const handleLoad = () => {
resolve($el);
};
const handleError = () => {
$el.removeEventListener('load', handleLoad);
$el.removeEventListener('error', handleError);
reject(new Error('failed to load image, attempts exhausted'));
};
$el.addEventListener('load', handleLoad);
$el.addEventListener('error', handleError);
if (!img) {
imgEl.src = src;
}
});
const useImageGracefullyLoad = (src, o) => {
const mounted = useMounted();
const [source, setSrc] = React__default.useState(o.disabled ? toIpfsGateway(src) : o.fallbackImage || toIpfsGateway(src));
const [hasError, setHasError] = React__default.useState(false);
const [isLoading, setLoading] = React__default.useState(!o.disabled);
const handleError = (hasErr) => {
if (mounted.current) {
setHasError(hasErr);
}
};
const handleLoading = (value) => {
if (mounted.current) {
setLoading(value);
}
};
const handleSrc = (value) => {
if (mounted.current) {
setSrc(value);
}
};
const ref = React__default.useRef(null);
React__default.useEffect(() => {
const trustedSrc = toIpfsGateway(src);
if (o.disabled) {
handleLoading(false);
handleSrc(trustedSrc);
}
else if (trustedSrc.match(/^http/)) {
handleLoading(true);
retry(loadImageAsync(trustedSrc, ref.current), {
interval: o.retryInterval || 500,
retries: o.retries || 10,
backoffFactor: o.backoffFactor,
})
.then(() => {
handleSrc(trustedSrc);
handleError(false);
})
.catch(() => {
console.warn(`failed to load ${trustedSrc}, exhausted all attempts`);
handleSrc(o.errorImage || o.fallbackImage);
handleError(true);
})
.finally(() => handleLoading(false));
}
else if (src === '' || src === null || typeof src === 'undefined') {
handleSrc(o.errorImage || o.fallbackImage);
handleError(true);
handleLoading(false);
}
else {
handleSrc(trustedSrc);
}
}, [src]);
return {
source,
hasError,
isLoading,
ref,
disabled: o.disabled || false,
};
};
const ImageComponent = (_a) => {
var { src, style, retries, retryInterval, backoffFactor, processing } = _a, props = __rest(_a, ["src", "style", "retries", "retryInterval", "backoffFactor", "processing"]);
const { source, hasError, isLoading, ref } = useImageGracefullyLoad(src, {
retries: retries || 10,
retryInterval: retryInterval || 500,
backoffFactor,
});
return (jsx(Fade, Object.assign({ in: !hasError && !isLoading }, { children: jsx("img", Object.assign({ ref: ref }, props, { style: Object.assign(Object.assign(Object.assign(Object.assign({}, style), { transition: 'all 1s ease-out' }), (hasError && {
filter: 'blur(4px) grayscale(0.7) opacity(0.5)',
})), ((isLoading || processing) && {
animation: 'pulse 2s infinite',
filter: 'opacity(0.8) grayscale(0.7)',
})), src: source })) })));
};
export { ImageComponent as default, useImageGracefullyLoad };
//# sourceMappingURL=Image.js.map