react-native-fast-image
Version:
FastImage, performant React Native image component.
299 lines (298 loc) • 11.2 kB
JavaScript
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.tsx
const resolveDefaultSource = (defaultSource) => {
if (!defaultSource) return null;
if (react_native.Platform.OS === "android") {
const resolved = react_native.Image.resolveAssetSource(defaultSource);
if (resolved) return resolved.uri;
return null;
}
return defaultSource;
};
function tintColorFromStyle(style) {
if (Array.isArray(style)) {
for (let i = style.length - 1; i >= 0; i--) {
const found = tintColorFromStyle(style[i]);
if (found !== void 0) return found;
}
return;
}
if (typeof style === "number") {
const flattened = react_native.StyleSheet.flatten(style);
return flattened ? flattened.tintColor : void 0;
}
return style && typeof style === "object" ? style.tintColor : void 0;
}
function loopCount(loop) {
if (loop === void 0) return -1;
if (loop === true) return 0;
if (loop === false) return 1;
return Number.isFinite(loop) ? Math.max(1, Math.floor(loop)) : 0;
}
function loadResult(event) {
var _event$width, _event$height, _event$error;
return event.ok ? {
ok: true,
width: (_event$width = event.width) !== null && _event$width !== void 0 ? _event$width : 0,
height: (_event$height = event.height) !== null && _event$height !== void 0 ? _event$height : 0
} : {
ok: false,
error: (_event$error = event.error) !== null && _event$error !== void 0 ? _event$error : "Failed to load the image"
};
}
function withProgress(onProgress) {
return onProgress && ((event) => {
const { loaded, total } = event.nativeEvent;
event.nativeEvent.progress = total > 0 ? Math.min(1, Math.max(0, loaded / total)) : 0;
onProgress(event);
});
}
const DEFAULT_FADE_MS = react_native.Platform.OS === "ios" ? 250 : 300;
function transitionProps(transition) {
var _transition$duration;
const { duration, betweenImages, skipOnCacheHit } = typeof transition === "number" ? { duration: transition } : typeof transition === "object" && transition ? {
...transition,
duration: (_transition$duration = transition.duration) !== null && _transition$duration !== void 0 ? _transition$duration : DEFAULT_FADE_MS
} : { duration: transition ? DEFAULT_FADE_MS : 0 };
return {
transitionDuration: typeof duration === "number" && duration > 0 ? duration : 0,
transitionBetweenImages: !!betweenImages,
transitionSkipOnCacheHit: skipOnCacheHit || "memory"
};
}
function withoutCache(source) {
const { cache: _cache, ...rest } = source || {};
return rest;
}
function FastImageBase({ source, defaultSource, tintColor, onLoadStart, onProgress, onLoad, onError, onLoadEnd, style, fallback, children, resizeMode = "cover", loop, transition, forwardedRef, onLayout, pointerEvents, hitSlop, onStartShouldSetResponder, onStartShouldSetResponderCapture, onMoveShouldSetResponder, onMoveShouldSetResponderCapture, onResponderGrant, onResponderReject, onResponderStart, onResponderMove, onResponderEnd, onResponderRelease, onResponderTerminationRequest, onResponderTerminate, onTouchStart, onTouchMove, onTouchEnd, onTouchCancel, onTouchEndCapture, ...viewProps }) {
const { onClick, ...props } = viewProps;
const fallbackResult = (0, react.useRef)(void 0);
const wrapperProps = {
onLayout,
onClick,
pointerEvents,
hitSlop,
onStartShouldSetResponder,
onStartShouldSetResponderCapture,
onMoveShouldSetResponder,
onMoveShouldSetResponderCapture,
onResponderGrant,
onResponderReject,
onResponderStart,
onResponderMove,
onResponderEnd,
onResponderRelease,
onResponderTerminationRequest,
onResponderTerminate,
onTouchStart,
onTouchMove,
onTouchEnd,
onTouchCancel,
onTouchEndCapture
};
const imageProps = {
...props,
pointerEvents: pointerEvents === "box-none" ? "none" : void 0
};
const resolvedTintColor = tintColor != null ? tintColor : tintColorFromStyle(style);
if (fallback) {
const cleanedSource = typeof source === "number" ? source : Array.isArray(source) ? source.map(withoutCache) : withoutCache(source);
const resolvedSource = react_native.Image.resolveAssetSource(cleanedSource);
return /* @__PURE__ */ react.default.createElement(react_native.View, {
style: [styles.imageContainer, style],
...wrapperProps,
ref: forwardedRef
}, /* @__PURE__ */ react.default.createElement(react_native.Image, {
...imageProps,
style: [styles.fallbackImage, { tintColor: resolvedTintColor }],
source: resolvedSource,
defaultSource,
onLoadStart,
onProgress: withProgress(onProgress),
onLoad: onLoadEnd ? (event) => {
const { width, height } = event.nativeEvent.source;
fallbackResult.current = {
ok: true,
width,
height
};
onLoad === null || onLoad === void 0 || onLoad(event);
} : onLoad,
onError: onLoadEnd ? (event) => {
fallbackResult.current = {
ok: false,
error: String(event.nativeEvent.error)
};
onError === null || onError === void 0 || onError(event);
} : onError,
onLoadEnd: onLoadEnd && (() => {
var _fallbackResult$curre;
return onLoadEnd((_fallbackResult$curre = fallbackResult.current) !== null && _fallbackResult$curre !== void 0 ? _fallbackResult$curre : {
ok: false,
error: "Failed to load the image"
});
}),
resizeMode
}), children);
}
const sources = Array.isArray(source) ? source.length === 1 ? void 0 : source : void 0;
const single = Array.isArray(source) ? source[0] : source;
const resolvedSource = sources ? void 0 : react_native.Image.resolveAssetSource(single);
const resolvedDefaultSource = resolveDefaultSource(defaultSource);
return /* @__PURE__ */ react.default.createElement(react_native.View, {
style: [styles.imageContainer, style],
...wrapperProps,
ref: forwardedRef
}, /* @__PURE__ */ react.default.createElement(FastImageView, {
...imageProps,
tintColor: resolvedTintColor,
loopCount: loopCount(loop),
...transitionProps(transition),
style: react_native.StyleSheet.absoluteFill,
source: resolvedSource,
sources,
defaultSource: resolvedDefaultSource,
onFastImageLoadStart: onLoadStart,
onFastImageProgress: withProgress(onProgress),
trackProgress: !!onProgress,
onFastImageLoad: onLoad,
onFastImageError: onError,
onFastImageLoadEnd: onLoadEnd && ((event) => onLoadEnd(loadResult(event.nativeEvent))),
resizeMode
}), children);
}
const FastImageMemo = (0, react.memo)(FastImageBase);
const FastImageComponent = (0, react.forwardRef)((props, ref) => /* @__PURE__ */ react.default.createElement(FastImageMemo, {
forwardedRef: ref,
...props
}));
FastImageComponent.displayName = "FastImage";
const noResult = {
ok: false,
error: "No result"
};
const FastImage = FastImageComponent;
FastImage.resizeMode = resizeMode;
FastImage.cacheControl = cacheControl;
FastImage.priority = priority;
const ONE_SOURCE = "Takes one source, not an array of sizes: pass the size to use";
FastImage.preload = (sources) => Promise.resolve(react_native.NativeModules.FastImageView.preload(sources.map((s) => s && !Array.isArray(s) ? s : {}))).then((results) => sources.map((source, i) => {
var _results$i;
if (Array.isArray(source)) return {
ok: false,
error: ONE_SOURCE,
uri: void 0
};
const uri = source ? source.uri : void 0;
const result = (_results$i = results === null || results === void 0 ? void 0 : results[i]) !== null && _results$i !== void 0 ? _results$i : noResult;
if (!result.ok) return {
...result,
uri
};
return typeof uri === "string" ? {
...result,
uri
} : {
ok: false,
error: "Invalid source: no uri",
uri
};
}));
FastImage.clearMemoryCache = () => Promise.resolve(react_native.NativeModules.FastImageView.clearMemoryCache());
FastImage.clearDiskCache = () => Promise.resolve(react_native.NativeModules.FastImageView.clearDiskCache());
FastImage.configureCache = (limits = {}) => Promise.resolve(react_native.NativeModules.FastImageView.configureCache(limits));
FastImage.writeToCache = (source, file) => Array.isArray(source) ? Promise.resolve({
ok: false,
error: ONE_SOURCE
}) : Promise.resolve(react_native.NativeModules.FastImageView.writeToCache(source || {}, file));
FastImage.getCachePath = (source) => Array.isArray(source) ? Promise.resolve({
ok: false,
error: ONE_SOURCE
}) : Promise.resolve(react_native.NativeModules.FastImageView.getCachePath(source || {}));
const styles = react_native.StyleSheet.create({
fallbackImage: {
position: "absolute",
top: 0,
left: 0,
width: "100%",
height: "100%"
},
imageContainer: { overflow: "hidden" }
});
/**
* An image with content on top of it, like React Native's `ImageBackground`: a
* view that the image fills, with the children on top. Use it rather than
* giving `FastImage` children, which it won't render in the next major version
* (the image will be a single native view). The other props go to the image;
* the ref is the view's.
*/
const FastImageBackground = (0, react.forwardRef)(({ style, imageStyle, imageRef, children, importantForAccessibility, ...props }, ref) => /* @__PURE__ */ react.default.createElement(react_native.View, {
accessibilityIgnoresInvertColors: true,
importantForAccessibility,
style,
ref
}, /* @__PURE__ */ react.default.createElement(FastImageComponent, {
...props,
importantForAccessibility,
style: [react_native.StyleSheet.absoluteFill, imageStyle],
ref: imageRef
}), children));
FastImageBackground.displayName = "FastImageBackground";
const FastImageView = (0, react_native.requireNativeComponent)("FastImageView", FastImage, { nativeOnly: {
onFastImageLoadStart: true,
onFastImageProgress: true,
onFastImageLoad: true,
onFastImageError: true,
onFastImageLoadEnd: true,
trackProgress: true
} });
//#endregion
exports.FastImageBackground = FastImageBackground;
exports.default = FastImage;