UNPKG

react-native-fast-image

Version:
270 lines (269 loc) • 10.1 kB
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } }); //#region \0rolldown/runtime.js var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { key = keys[i]; if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: ((k) => from[k]).bind(null, key), enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); //#endregion let react = require("react"); react = __toESM(react); let react_native = require("react-native"); //#region src/constants.ts const resizeMode = { contain: "contain", cover: "cover", stretch: "stretch", center: "center", repeat: "repeat" }; const priority = { low: "low", normal: "normal", high: "high" }; const cacheControl = { immutable: "immutable", web: "web", cacheOnly: "cacheOnly" }; //#endregion //#region src/index.web.tsx const notSupported = { ok: false, error: "Not supported on the web" }; function FastImageBase({ source, defaultSource, tintColor, blurRadius, onLoadStart, onLoad, onError, onLoadEnd, style, children, resizeMode: mode = "cover", forwardedRef, onLayout, pointerEvents, fallback: _fallback, recyclingKey: _recyclingKey, loop: _loop, imageRendering: _imageRendering, paused: _paused, transition: _transition, downsample: _downsample, onProgress: _onProgress, ...props }) { const result = (0, react.useRef)(void 0); const sent = (0, react.useRef)(Promise.resolve()); const image = (0, react.useRef)(null); const sizes = Array.isArray(source) && source.length > 1 ? source : void 0; const single = Array.isArray(source) ? source[0] : source; const uri = typeof single === "object" && single ? single.uri : void 0; const webSource = typeof single === "number" ? single : uri ? { uri } : void 0; return /* @__PURE__ */ react.default.createElement(react_native.View, { style: [styles.container, style], onLayout, pointerEvents, ref: forwardedRef }, sizes ? /* @__PURE__ */ react.default.createElement(react_native.View, { ...props, style: styles.image }, /* @__PURE__ */ react.default.createElement(ImageSizes, { sources: sizes, resizeMode: mode, blurRadius, onLoadStart, onLoad, onError, onLoadEnd })) : /* @__PURE__ */ react.default.createElement(react_native.Image, { ...props, style: styles.image, source: webSource, defaultSource, resizeMode: mode, tintColor, blurRadius, ref: image, onLoadStart, onLoad: (event) => { var _event$nativeEvent; sent.current = loadedSize(event === null || event === void 0 || (_event$nativeEvent = event.nativeEvent) === null || _event$nativeEvent === void 0 ? void 0 : _event$nativeEvent.target, image.current, uri).then(({ width, height }) => { result.current = { ok: true, width, height }; onLoad === null || onLoad === void 0 || onLoad({ nativeEvent: { width, height } }); }); }, onError: (event) => { var _event$nativeEvent$er, _event$nativeEvent2; const error = String((_event$nativeEvent$er = event === null || event === void 0 || (_event$nativeEvent2 = event.nativeEvent) === null || _event$nativeEvent2 === void 0 ? void 0 : _event$nativeEvent2.error) !== null && _event$nativeEvent$er !== void 0 ? _event$nativeEvent$er : "Failed to load the image"); result.current = { ok: false, error }; sent.current = Promise.resolve(); onError === null || onError === void 0 || onError({ nativeEvent: { error } }); }, onLoadEnd: () => { sent.current.then(() => { var _result$current; onLoadEnd === null || onLoadEnd === void 0 || onLoadEnd((_result$current = result.current) !== null && _result$current !== void 0 ? _result$current : { ok: false, error: "Failed to load the image" }); result.current = void 0; }); } }), children); } function ImageSizes({ sources, resizeMode: mode, blurRadius, onLoadStart, onLoad, onError, onLoadEnd }) { var _largest$uri, _sources$find; const sized = sources.filter((source) => (source === null || source === void 0 ? void 0 : source.uri) && source.width).map((source) => { var _source$width, _source$scale; return { uri: source.uri, width: Math.round(((_source$width = source.width) !== null && _source$width !== void 0 ? _source$width : 0) * ((_source$scale = source.scale) !== null && _source$scale !== void 0 ? _source$scale : 1)) }; }); const largest = sized.reduce((best, source) => !best || source.width > best.width ? source : best, void 0); const src = (_largest$uri = largest === null || largest === void 0 ? void 0 : largest.uri) !== null && _largest$uri !== void 0 ? _largest$uri : (_sources$find = sources.find((source) => source === null || source === void 0 ? void 0 : source.uri)) === null || _sources$find === void 0 ? void 0 : _sources$find.uri; const srcSet = sized.length > 0 ? sized.map((source) => `${source.uri} ${source.width}w`).join(", ") : void 0; (0, react.useEffect)(() => { onLoadStart === null || onLoadStart === void 0 || onLoadStart(); }, [src, srcSet]); return /* @__PURE__ */ react.default.createElement("img", { src, srcSet, sizes: srcSet ? "auto, 100vw" : void 0, loading: "lazy", alt: "", draggable: false, style: { position: "absolute", width: "100%", height: "100%", objectFit: OBJECT_FIT[mode !== null && mode !== void 0 ? mode : "cover"], filter: blurRadius ? `blur(${blurRadius}px)` : void 0 }, onLoad: (event) => { var _picked$width; const image = event.currentTarget; const picked = srcSet ? sized.find((source) => new URL(source.uri, image.currentSrc).href === image.currentSrc) : void 0; const loadedWidth = (_picked$width = picked === null || picked === void 0 ? void 0 : picked.width) !== null && _picked$width !== void 0 ? _picked$width : image.naturalWidth; const loadedHeight = picked ? Math.round(image.naturalHeight * picked.width / image.naturalWidth) : image.naturalHeight; onLoad === null || onLoad === void 0 || onLoad({ nativeEvent: { width: loadedWidth, height: loadedHeight } }); onLoadEnd === null || onLoadEnd === void 0 || onLoadEnd({ ok: true, width: loadedWidth, height: loadedHeight }); }, onError: () => { const error = "Failed to load the image"; onError === null || onError === void 0 || onError({ nativeEvent: { error } }); onLoadEnd === null || onLoadEnd === void 0 || onLoadEnd({ ok: false, error }); } }); } const OBJECT_FIT = { cover: "cover", contain: "contain", stretch: "fill", center: "scale-down", repeat: "cover" }; const FastImageMemo = (0, react.memo)(FastImageBase); const FastImageComponent = (0, react.forwardRef)((props, ref) => /* @__PURE__ */ react.default.createElement(FastImageMemo, { forwardedRef: ref, ...props })); FastImageComponent.displayName = "FastImage"; async function loadedSize(loaded, view, uri) { var _view$querySelector; if (loaded === null || loaded === void 0 ? void 0 : loaded.naturalWidth) return { width: loaded.naturalWidth, height: loaded.naturalHeight }; await new Promise((resolve) => setTimeout(resolve, 0)); const shown = view === null || view === void 0 || (_view$querySelector = view.querySelector) === null || _view$querySelector === void 0 ? void 0 : _view$querySelector.call(view, "img"); if (shown === null || shown === void 0 ? void 0 : shown.naturalWidth) return { width: shown.naturalWidth, height: shown.naturalHeight }; const src = uri !== null && uri !== void 0 ? uri : shown === null || shown === void 0 ? void 0 : shown.src; return src ? getSize(src) : { width: 0, height: 0 }; } function getSize(uri) { return new Promise((resolve) => { react_native.Image.getSize(uri, (width, height) => resolve({ width, height }), () => resolve({ width: 0, height: 0 })); }); } const FastImage = FastImageComponent; FastImage.resizeMode = resizeMode; FastImage.cacheControl = cacheControl; FastImage.priority = priority; FastImage.preload = (sources) => Promise.all(sources.map((source) => { const uri = source ? source.uri : void 0; if (typeof uri !== "string" || !uri) return Promise.resolve({ ok: false, error: "Invalid source: no uri", uri }); return react_native.Image.prefetch(uri).then(() => getSize(uri).then((size) => ({ ok: true, uri, ...size })), () => ({ ok: false, error: "Failed to load the image", uri })); })); FastImage.clearMemoryCache = () => Promise.resolve(notSupported); FastImage.clearDiskCache = () => Promise.resolve(notSupported); FastImage.configureCache = () => Promise.resolve({}); FastImage.writeToCache = () => Promise.resolve(notSupported); FastImage.getCachePath = () => Promise.resolve(notSupported); const styles = react_native.StyleSheet.create({ container: { overflow: "hidden" }, image: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%" } }); const FastImageWithRef = FastImageComponent; const FastImageBackground = (0, react.forwardRef)(({ style, imageStyle, imageRef, children, ...props }, ref) => /* @__PURE__ */ react.default.createElement(react_native.View, { style, ref }, /* @__PURE__ */ react.default.createElement(FastImageWithRef, { ...props, style: [react_native.StyleSheet.absoluteFill, imageStyle], ref: imageRef }), children)); FastImageBackground.displayName = "FastImageBackground"; //#endregion exports.FastImageBackground = FastImageBackground; exports.default = FastImage;