react-native-fast-image 9.3.7 → 10.0.0

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.
Files changed (76) hide show
  1. package/README.md +87 -61
  2. package/RNFastImage.podspec +14 -9
  3. package/android/build.gradle +21 -47
  4. package/android/consumer-rules.pro +7 -7
  5. package/android/src/main/AndroidManifest.xml +1 -2
  6. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageAnimatable.java +1 -1
  7. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageAnimated.java +2 -2
  8. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageApng.java +2 -2
  9. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageBlur.java +4 -6
  10. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageCacheControl.java +1 -1
  11. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageCacheLimits.java +4 -1
  12. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageCacheWrite.java +1 -1
  13. package/android/src/main/java/com/fastimage/FastImageCrop.java +92 -0
  14. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageEvent.java +2 -3
  15. package/android/src/main/java/com/fastimage/FastImageEvents.java +74 -0
  16. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageGif.java +1 -1
  17. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageGlide.java +3 -3
  18. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageGlideModule.java +1 -1
  19. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageKeyedGlideUrl.java +1 -1
  20. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageOkHttpProgressGlideModule.java +36 -9
  21. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageRequestListener.java +6 -1
  22. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageSharedDownloads.java +1 -1
  23. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageSource.java +1 -1
  24. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageSourceSize.java +12 -2
  25. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageSvg.java +3 -3
  26. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageSvgRenderer.java +1 -1
  27. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageUrl.java +1 -1
  28. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageViewConverter.java +7 -8
  29. package/android/src/main/java/com/fastimage/FastImageViewManager.java +591 -0
  30. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageViewModule.java +31 -28
  31. package/android/src/main/java/com/fastimage/FastImageViewPackage.java +51 -0
  32. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageViewWithUrl.java +352 -126
  33. package/android/src/main/java/com/{dylanvann/fastimage → fastimage}/FastImageWebGlideUrl.java +1 -1
  34. package/app.plugin.js +2 -7
  35. package/dist/index.cjs.js +276 -157
  36. package/dist/index.cjs.js.flow +33 -17
  37. package/dist/index.cjs.web.js +211 -61
  38. package/dist/index.cjs.web.js.flow +33 -17
  39. package/dist/index.d.ts +83 -58
  40. package/dist/index.js +278 -159
  41. package/dist/index.js.flow +33 -17
  42. package/dist/index.web.js +212 -62
  43. package/dist/index.web.js.flow +33 -17
  44. package/dist/objectFit.d.ts +2 -2
  45. package/dist/objectPosition.d.ts +42 -0
  46. package/dist/specs/FastImageViewNativeComponent.d.ts +48 -0
  47. package/dist/specs/NativeFastImageModule.d.ts +11 -0
  48. package/dist/warnings.d.ts +3 -0
  49. package/ios/FastImage/FFFDownsampledImage.h +4 -8
  50. package/ios/FastImage/FFFDownsampledImage.m +0 -34
  51. package/ios/FastImage/FFFastImageModule.h +8 -0
  52. package/ios/FastImage/{FFFastImageViewManager.m → FFFastImageModule.mm} +70 -59
  53. package/ios/FastImage/FFFastImageView.h +36 -7
  54. package/ios/FastImage/FFFastImageView.m +201 -164
  55. package/ios/FastImage/FFFastImageViewComponentView.h +11 -0
  56. package/ios/FastImage/FFFastImageViewComponentView.mm +325 -0
  57. package/ios/FastImage/RCTConvert+FFFastImage.h +1 -1
  58. package/ios/FastImage/RCTConvert+FFFastImage.m +7 -10
  59. package/package.json +28 -9
  60. package/src/constants.ts +28 -0
  61. package/src/index.js.flow +179 -0
  62. package/src/index.tsx +1103 -0
  63. package/src/index.web.tsx +548 -0
  64. package/src/objectFit.ts +48 -0
  65. package/src/objectPosition.ts +243 -0
  66. package/src/specs/FastImageViewNativeComponent.ts +83 -0
  67. package/src/specs/NativeFastImageModule.ts +35 -0
  68. package/src/warnings.ts +37 -0
  69. package/android/src/main/AndroidManifestNew.xml +0 -3
  70. package/android/src/main/java/com/dylanvann/fastimage/FastImageCookieHandler.java +0 -63
  71. package/android/src/main/java/com/dylanvann/fastimage/FastImageEvents.java +0 -49
  72. package/android/src/main/java/com/dylanvann/fastimage/FastImageProgressListener.java +0 -18
  73. package/android/src/main/java/com/dylanvann/fastimage/FastImageShadowNode.java +0 -21
  74. package/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java +0 -379
  75. package/android/src/main/java/com/dylanvann/fastimage/FastImageViewPackage.java +0 -27
  76. package/ios/FastImage/FFFastImageViewManager.h +0 -5
@@ -1,4 +1,4 @@
1
- package com.dylanvann.fastimage;
1
+ package com.fastimage;
2
2
 
3
3
  import com.bumptech.glide.load.model.GlideUrl;
4
4
  import com.bumptech.glide.load.model.Headers;
package/app.plugin.js CHANGED
@@ -40,13 +40,8 @@ function setAndroidManifest(manifest, options = {}) {
40
40
  }
41
41
 
42
42
  function withFastImage(config, options) {
43
- // From the Expo project, which has it (older SDKs only as the package).
44
- let plugins
45
- try {
46
- plugins = require('expo/config-plugins')
47
- } catch {
48
- plugins = require('@expo/config-plugins')
49
- }
43
+ // From the Expo project's expo package.
44
+ const plugins = require('expo/config-plugins')
50
45
  config = plugins.withInfoPlist(config, (mod) => {
51
46
  mod.modResults = setInfoPlist(mod.modResults, options)
52
47
  return mod
package/dist/index.cjs.js CHANGED
@@ -61,13 +61,6 @@ function fromStyle(style, key) {
61
61
  }
62
62
  return style && typeof style === "object" ? style[key] : void 0;
63
63
  }
64
- const RESIZE_MODE_FIT = {
65
- contain: "contain",
66
- cover: "cover",
67
- stretch: "fill",
68
- center: "center",
69
- repeat: "repeat"
70
- };
71
64
  const FITS = {
72
65
  fill: true,
73
66
  contain: true,
@@ -75,31 +68,204 @@ const FITS = {
75
68
  none: true,
76
69
  "scale-down": true
77
70
  };
78
- function resolveObjectFit(objectFit, style, resizeMode) {
79
- var _RESIZE_MODE_FIT$resi;
71
+ function resolveObjectFit(objectFit, style) {
80
72
  const fit = objectFit != null ? objectFit : fromStyle(style, "objectFit");
81
- if (fit && FITS[fit] === true) return fit;
82
- return (_RESIZE_MODE_FIT$resi = RESIZE_MODE_FIT[resizeMode]) !== null && _RESIZE_MODE_FIT$resi !== void 0 ? _RESIZE_MODE_FIT$resi : "cover";
73
+ return fit && FITS[fit] === true ? fit : "cover";
74
+ }
75
+ //#endregion
76
+ //#region src/warnings.ts
77
+ const warned = /* @__PURE__ */ new Set();
78
+ function warnOnce(key, message, level) {
79
+ if (!warned.has(key)) {
80
+ warned.add(key);
81
+ console[level](message);
82
+ }
83
+ }
84
+ function warnIfChildren(children) {
85
+ if (react.Children.toArray(children).length > 0) warnOnce("children", "react-native-fast-image: FastImage doesn't render children (since 10.0): use FastImageBackground for content over an image.", "error");
83
86
  }
84
87
  //#endregion
88
+ //#region src/objectPosition.ts
89
+ const START = {
90
+ fraction: 0,
91
+ offset: 0
92
+ };
93
+ const CENTER = {
94
+ fraction: .5,
95
+ offset: 0
96
+ };
97
+ const END = {
98
+ fraction: 1,
99
+ offset: 0
100
+ };
101
+ /** The default, `50% 50%`. */
102
+ const CENTERED = {
103
+ x: CENTER,
104
+ y: CENTER
105
+ };
106
+ const NUMBER = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i;
107
+ function length(text) {
108
+ const lower = text.toLowerCase();
109
+ if (lower.endsWith("%")) {
110
+ const number = lower.slice(0, -1);
111
+ return NUMBER.test(number) ? {
112
+ fraction: Number(number) / 100,
113
+ offset: 0
114
+ } : null;
115
+ }
116
+ if (lower.endsWith("px")) {
117
+ const number = lower.slice(0, -2);
118
+ return NUMBER.test(number) ? {
119
+ fraction: 0,
120
+ offset: Number(number)
121
+ } : null;
122
+ }
123
+ return NUMBER.test(lower) && Number(lower) === 0 ? START : null;
124
+ }
125
+ function token(text) {
126
+ const lower = text.toLowerCase();
127
+ if (lower === "left" || lower === "right" || lower === "top" || lower === "bottom" || lower === "center") return { keyword: lower };
128
+ const axis = length(text);
129
+ return axis ? { length: axis } : null;
130
+ }
131
+ const X = {
132
+ left: START,
133
+ center: CENTER,
134
+ right: END
135
+ };
136
+ const Y = {
137
+ top: START,
138
+ center: CENTER,
139
+ bottom: END
140
+ };
141
+ const x = (t) => "length" in t ? t.length : X[t.keyword];
142
+ const y = (t) => "length" in t ? t.length : Y[t.keyword];
143
+ function fromEdge(edge, axis) {
144
+ return edge === "left" || edge === "top" ? axis : {
145
+ fraction: 1 - axis.fraction,
146
+ offset: -axis.offset || 0
147
+ };
148
+ }
149
+ function parse(text) {
150
+ const tokens = [];
151
+ for (const part of text.trim().split(/\s+/)) {
152
+ const t = token(part);
153
+ if (!t) return null;
154
+ tokens.push(t);
155
+ }
156
+ if (tokens.length === 1) {
157
+ const [a] = tokens;
158
+ if ("keyword" in a && (a.keyword === "top" || a.keyword === "bottom")) return {
159
+ x: CENTER,
160
+ y: Y[a.keyword]
161
+ };
162
+ return {
163
+ x: x(a),
164
+ y: CENTER
165
+ };
166
+ }
167
+ if (tokens.length === 2) {
168
+ const [a, b] = tokens;
169
+ const ax = x(a);
170
+ const by = y(b);
171
+ if (ax && by) return {
172
+ x: ax,
173
+ y: by
174
+ };
175
+ if ("keyword" in a && "keyword" in b) {
176
+ const bx = X[b.keyword];
177
+ const ay = Y[a.keyword];
178
+ if (bx && ay) return {
179
+ x: bx,
180
+ y: ay
181
+ };
182
+ }
183
+ return null;
184
+ }
185
+ if (tokens.length === 4) {
186
+ const [a, b, c, d] = tokens;
187
+ if (!("keyword" in a && "length" in b && "keyword" in c && "length" in d)) return null;
188
+ const horizontal = (k) => k === "left" || k === "right";
189
+ const vertical = (k) => k === "top" || k === "bottom";
190
+ if (horizontal(a.keyword) && vertical(c.keyword)) return {
191
+ x: fromEdge(a.keyword, b.length),
192
+ y: fromEdge(c.keyword, d.length)
193
+ };
194
+ if (vertical(a.keyword) && horizontal(c.keyword)) return {
195
+ x: fromEdge(c.keyword, d.length),
196
+ y: fromEdge(a.keyword, b.length)
197
+ };
198
+ }
199
+ return null;
200
+ }
201
+ const parsed = /* @__PURE__ */ new Map();
202
+ function objectLength(value) {
203
+ if (typeof value === "number") return Number.isFinite(value) ? {
204
+ fraction: 0,
205
+ offset: value
206
+ } : null;
207
+ return typeof value === "string" && value.endsWith("%") ? length(value) : null;
208
+ }
209
+ /**
210
+ * The position for objectPosition, or null if it isn't valid. A string is
211
+ * CSS's syntax; an object has one of `top` and `bottom` and one of `left`
212
+ * and `right`, each in points or a percentage, and a missing axis is
213
+ * centered. Unset is centered.
214
+ */
215
+ function resolveObjectPosition(position) {
216
+ if (position == null) return CENTERED;
217
+ if (typeof position === "string") {
218
+ let result = parsed.get(position);
219
+ if (result === void 0) {
220
+ result = parse(position);
221
+ if (parsed.size < 100) parsed.set(position, result);
222
+ }
223
+ return result;
224
+ }
225
+ if (typeof position !== "object") return null;
226
+ const edges = position;
227
+ const axis = (start, end) => {
228
+ const hasStart = edges[start] != null;
229
+ const hasEnd = edges[end] != null;
230
+ if (hasStart && hasEnd) return null;
231
+ if (!hasStart && !hasEnd) return CENTER;
232
+ const edge = hasStart ? start : end;
233
+ const value = objectLength(edges[edge]);
234
+ return value && fromEdge(edge, value);
235
+ };
236
+ const resolvedX = axis("left", "right");
237
+ const resolvedY = axis("top", "bottom");
238
+ return resolvedX && resolvedY ? {
239
+ x: resolvedX,
240
+ y: resolvedY
241
+ } : null;
242
+ }
243
+ /**
244
+ * The position for objectPosition, or centered if it isn't valid (as CSS
245
+ * ignores it), with a warning in development.
246
+ */
247
+ function objectPositionOrCentered(position) {
248
+ const resolved = resolveObjectPosition(position);
249
+ if (resolved) return resolved;
250
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
251
+ const value = JSON.stringify(position);
252
+ warnOnce(`objectPosition ${value}`, `react-native-fast-image: objectPosition ${value} isn't a position, so the image is centered. Use CSS's syntax with px or % (e.g. 'right 10px bottom 20%'), or { top | bottom, left | right } in points or percentages.`, "warn");
253
+ }
254
+ return CENTERED;
255
+ }
256
+ //#endregion
257
+ //#region src/specs/FastImageViewNativeComponent.ts
258
+ var FastImageViewNativeComponent_default = (0, react_native.codegenNativeComponent)("FastImageView");
259
+ //#endregion
260
+ //#region src/specs/NativeFastImageModule.ts
261
+ var NativeFastImageModule_default = react_native.TurboModuleRegistry.get("FastImageModule");
262
+ //#endregion
85
263
  //#region src/index.tsx
86
264
  const resolveDefaultSource = (defaultSource) => {
87
265
  if (!defaultSource) return null;
88
- if (react_native.Platform.OS === "android") {
89
- const resolved = react_native.Image.resolveAssetSource(defaultSource);
90
- if (resolved) return resolved.uri;
91
- return null;
92
- }
93
- return defaultSource;
94
- };
95
- const NATIVE_RESIZE_MODE = {
96
- fill: "stretch",
97
- contain: "contain",
98
- cover: "cover",
99
- none: "none",
100
- "scale-down": "scale-down",
101
- center: "center",
102
- repeat: "repeat"
266
+ const resolved = react_native.Image.resolveAssetSource(defaultSource);
267
+ if (!resolved) return null;
268
+ return react_native.Platform.OS === "android" ? resolved.uri : resolved;
103
269
  };
104
270
  function loopCount(loop) {
105
271
  if (loop === void 0) return -1;
@@ -118,127 +284,81 @@ function loadResult(event) {
118
284
  error: (_event$error = event.error) !== null && _event$error !== void 0 ? _event$error : "Failed to load the image"
119
285
  };
120
286
  }
121
- function withProgress(onProgress) {
122
- return onProgress && ((event) => {
123
- const { loaded, total } = event.nativeEvent;
124
- event.nativeEvent.progress = total > 0 ? Math.min(1, Math.max(0, loaded / total)) : 0;
125
- onProgress(event);
126
- });
287
+ function handledEvents({ onLoadStart, onProgress, onLoad, onError, onLoadEnd }) {
288
+ return (onLoadStart ? 1 : 0) | (onProgress ? 2 : 0) | (onLoad ? 4 : 0) | (onError ? 8 : 0) | (onLoadEnd ? 16 : 0);
127
289
  }
128
- const DEFAULT_FADE_MS = react_native.Platform.OS === "ios" ? 250 : 300;
129
- function transitionProps(transition) {
130
- var _transition$duration;
131
- const { duration, betweenImages, skipOnCacheHit } = typeof transition === "number" ? { duration: transition } : typeof transition === "object" && transition ? {
132
- ...transition,
133
- duration: (_transition$duration = transition.duration) !== null && _transition$duration !== void 0 ? _transition$duration : DEFAULT_FADE_MS
134
- } : { duration: transition ? DEFAULT_FADE_MS : 0 };
290
+ function usualFadeMs() {
291
+ return react_native.Platform.OS === "ios" ? 250 : 300;
292
+ }
293
+ const NO_TRANSITION = {
294
+ transitionDuration: 0,
295
+ transitionBetweenImages: false,
296
+ transitionSkipOnCacheHit: "memory"
297
+ };
298
+ function resolveTransition(transition, base) {
299
+ if (transition == null) return base;
300
+ if (transition === false) return {
301
+ ...base,
302
+ transitionDuration: 0
303
+ };
304
+ const usual = base.transitionDuration > 0 ? base.transitionDuration : usualFadeMs();
305
+ if (transition === true) return {
306
+ ...base,
307
+ transitionDuration: usual
308
+ };
309
+ const { duration, betweenImages, skipOnCacheHit } = typeof transition === "number" ? { duration: transition } : transition;
310
+ const resolvedDuration = duration !== null && duration !== void 0 ? duration : usual;
135
311
  return {
136
- transitionDuration: typeof duration === "number" && duration > 0 ? duration : 0,
137
- transitionBetweenImages: !!betweenImages,
138
- transitionSkipOnCacheHit: skipOnCacheHit || "memory"
312
+ transitionDuration: typeof resolvedDuration === "number" && resolvedDuration > 0 ? resolvedDuration : 0,
313
+ transitionBetweenImages: betweenImages !== null && betweenImages !== void 0 ? betweenImages : base.transitionBetweenImages,
314
+ transitionSkipOnCacheHit: skipOnCacheHit !== null && skipOnCacheHit !== void 0 ? skipOnCacheHit : base.transitionSkipOnCacheHit
139
315
  };
140
316
  }
141
- function withoutCache(source) {
142
- const { cache: _cache, ...rest } = source || {};
143
- return rest;
317
+ function builtInTransition() {
318
+ return resolveTransition(react_native.Platform.OS === "android", NO_TRANSITION);
144
319
  }
145
- function FastImageBase({ source, defaultSource, tintColor, onLoadStart, onProgress, onLoad, onError, onLoadEnd, style, fallback, children, objectFit, 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 }) {
146
- const { onClick, ...props } = viewProps;
147
- const fallbackResult = (0, react.useRef)(void 0);
148
- const wrapperProps = {
149
- onLayout,
150
- onClick,
151
- pointerEvents,
152
- hitSlop,
153
- onStartShouldSetResponder,
154
- onStartShouldSetResponderCapture,
155
- onMoveShouldSetResponder,
156
- onMoveShouldSetResponderCapture,
157
- onResponderGrant,
158
- onResponderReject,
159
- onResponderStart,
160
- onResponderMove,
161
- onResponderEnd,
162
- onResponderRelease,
163
- onResponderTerminationRequest,
164
- onResponderTerminate,
165
- onTouchStart,
166
- onTouchMove,
167
- onTouchEnd,
168
- onTouchCancel,
169
- onTouchEndCapture
170
- };
171
- const imageProps = {
172
- ...props,
173
- pointerEvents: pointerEvents === "box-none" ? "none" : void 0
174
- };
320
+ let defaultTransition;
321
+ function FastImageBase({ source, defaultSource, tintColor, onLoadStart, onProgress, onLoad, onError, onLoadEnd, style, children, objectFit, objectPosition, loop, transition, forwardedRef, ...viewProps }) {
322
+ var _props$recyclingKey, _defaultTransition;
323
+ const { fallback, resizeMode: _resizeMode, ...props } = viewProps;
324
+ if (__DEV__ && fallback !== void 0) warnOnce("fallback", "react-native-fast-image: `fallback` was removed in 10.0, and does nothing: images always load natively. Remove it, or use React Native's Image for those images.", "warn");
325
+ if (__DEV__) warnIfChildren(children);
175
326
  const resolvedTintColor = tintColor != null ? tintColor : fromStyle(style, "tintColor");
176
- const mode = NATIVE_RESIZE_MODE[resolveObjectFit(objectFit, style, resizeMode)];
177
- if (fallback) {
178
- const cleanedSource = typeof source === "number" ? source : Array.isArray(source) ? source.map(withoutCache) : withoutCache(source);
179
- const resolvedSource = react_native.Image.resolveAssetSource(cleanedSource);
180
- return /* @__PURE__ */ react.default.createElement(react_native.View, {
181
- style: [styles.imageContainer, style],
182
- ...wrapperProps,
183
- ref: forwardedRef
184
- }, /* @__PURE__ */ react.default.createElement(react_native.Image, {
185
- ...imageProps,
186
- style: [styles.fallbackImage, { tintColor: resolvedTintColor }],
187
- source: resolvedSource,
188
- defaultSource,
189
- onLoadStart,
190
- onProgress: withProgress(onProgress),
191
- onLoad: onLoadEnd ? (event) => {
192
- const { width, height } = event.nativeEvent.source;
193
- fallbackResult.current = {
194
- ok: true,
195
- width,
196
- height
197
- };
198
- onLoad === null || onLoad === void 0 || onLoad(event);
199
- } : onLoad,
200
- onError: onLoadEnd ? (event) => {
201
- fallbackResult.current = {
202
- ok: false,
203
- error: String(event.nativeEvent.error)
204
- };
205
- onError === null || onError === void 0 || onError(event);
206
- } : onError,
207
- onLoadEnd: onLoadEnd && (() => {
208
- var _fallbackResult$curre;
209
- return onLoadEnd((_fallbackResult$curre = fallbackResult.current) !== null && _fallbackResult$curre !== void 0 ? _fallbackResult$curre : {
210
- ok: false,
211
- error: "Failed to load the image"
212
- });
213
- }),
214
- resizeMode: mode === "none" || mode === "scale-down" ? "center" : mode
215
- }), children);
216
- }
327
+ const fit = resolveObjectFit(objectFit, style);
328
+ const position = objectPositionOrCentered(objectPosition);
217
329
  const sources = Array.isArray(source) ? source.length === 1 ? void 0 : source : void 0;
218
330
  const single = Array.isArray(source) ? source[0] : source;
219
331
  const resolvedSource = sources ? void 0 : react_native.Image.resolveAssetSource(single);
220
332
  const resolvedDefaultSource = resolveDefaultSource(defaultSource);
221
- return /* @__PURE__ */ react.default.createElement(react_native.View, {
222
- style: [styles.imageContainer, style],
223
- ...wrapperProps,
224
- ref: forwardedRef
225
- }, /* @__PURE__ */ react.default.createElement(FastImageView, {
226
- ...imageProps,
227
- tintColor: resolvedTintColor,
333
+ return /* @__PURE__ */ react.default.createElement(FastImageViewNativeComponent_default, {
334
+ ...props,
335
+ ref: forwardedRef,
336
+ style: [styles.image, style],
337
+ recyclingKey: (_props$recyclingKey = props.recyclingKey) !== null && _props$recyclingKey !== void 0 ? _props$recyclingKey : void 0,
228
338
  loopCount: loopCount(loop),
229
- ...transitionProps(transition),
230
- style: react_native.StyleSheet.absoluteFill,
339
+ ...resolveTransition(transition, (_defaultTransition = defaultTransition) !== null && _defaultTransition !== void 0 ? _defaultTransition : builtInTransition()),
231
340
  source: resolvedSource,
232
341
  sources,
233
342
  defaultSource: resolvedDefaultSource,
234
343
  onFastImageLoadStart: onLoadStart,
235
- onFastImageProgress: withProgress(onProgress),
236
- trackProgress: !!onProgress,
344
+ onFastImageProgress: onProgress,
345
+ handledEvents: handledEvents({
346
+ onLoadStart,
347
+ onProgress,
348
+ onLoad,
349
+ onError,
350
+ onLoadEnd
351
+ }),
237
352
  onFastImageLoad: onLoad,
238
353
  onFastImageError: onError,
239
354
  onFastImageLoadEnd: onLoadEnd && ((event) => onLoadEnd(loadResult(event.nativeEvent))),
240
- resizeMode: mode
241
- }), children);
355
+ tintColor: resolvedTintColor,
356
+ objectFit: fit,
357
+ objectPositionX: position.x.fraction,
358
+ objectPositionXOffset: position.x.offset,
359
+ objectPositionY: position.y.fraction,
360
+ objectPositionYOffset: position.y.offset
361
+ });
242
362
  }
243
363
  const FastImageMemo = (0, react.memo)(FastImageBase);
244
364
  const FastImageComponent = (0, react.forwardRef)((props, ref) => /* @__PURE__ */ react.default.createElement(FastImageMemo, {
@@ -250,13 +370,21 @@ const noResult = {
250
370
  ok: false,
251
371
  error: "No result"
252
372
  };
373
+ function nativeModule() {
374
+ if (!NativeFastImageModule_default) throw new Error("react-native-fast-image: the native module FastImageModule isn't in this app. Rebuild the app after installing the package (run pod install on iOS). It needs the New Architecture, and isn't in Expo Go: use a development build. In Jest, mock the function (e.g. jest.spyOn(FastImage, \"preload\")).");
375
+ return NativeFastImageModule_default;
376
+ }
253
377
  const FastImage = FastImageComponent;
254
- FastImage.resizeMode = resizeMode;
255
378
  FastImage.cacheControl = cacheControl;
256
379
  FastImage.priority = priority;
380
+ FastImage.resizeMode = resizeMode;
381
+ FastImage.setDefaults = ({ transition } = {}) => {
382
+ if (transition === null) defaultTransition = void 0;
383
+ else if (transition !== void 0) defaultTransition = resolveTransition(transition, builtInTransition());
384
+ };
257
385
  const ONE_SOURCE = "Takes one source, not an array of sizes: pass the size to use";
258
386
  const isSourceObject = (source) => typeof source === "object" && source !== null && !Array.isArray(source);
259
- FastImage.preload = (sources) => Promise.resolve(react_native.NativeModules.FastImageView.preload(sources.map((s) => isSourceObject(s) ? s : {}))).then((results) => sources.map((source, i) => {
387
+ FastImage.preload = (sources) => Promise.resolve(nativeModule().preload(sources.map((s) => isSourceObject(s) ? s : {}))).then((results) => sources.map((source, i) => {
260
388
  var _results$i;
261
389
  if (Array.isArray(source)) return {
262
390
  ok: false,
@@ -278,32 +406,31 @@ FastImage.preload = (sources) => Promise.resolve(react_native.NativeModules.Fast
278
406
  uri
279
407
  };
280
408
  }));
281
- FastImage.clearMemoryCache = () => Promise.resolve(react_native.NativeModules.FastImageView.clearMemoryCache());
282
- FastImage.clearDiskCache = () => Promise.resolve(react_native.NativeModules.FastImageView.clearDiskCache());
283
- FastImage.configureCache = (limits = {}) => Promise.resolve(react_native.NativeModules.FastImageView.configureCache(limits));
409
+ FastImage.clearMemoryCache = () => nativeModule().clearMemoryCache();
410
+ FastImage.clearDiskCache = () => nativeModule().clearDiskCache();
411
+ FastImage.configureCache = (limits) => {
412
+ const set = {};
413
+ const reset = [];
414
+ for (const [name, value] of Object.entries(limits !== null && limits !== void 0 ? limits : {})) if (value === null) reset.push(name);
415
+ else if (typeof value === "number") set[name] = value;
416
+ return nativeModule().configureCache({
417
+ ...set,
418
+ reset
419
+ });
420
+ };
284
421
  FastImage.writeToCache = (source, file) => Array.isArray(source) ? Promise.resolve({
285
422
  ok: false,
286
423
  error: ONE_SOURCE
287
- }) : Promise.resolve(react_native.NativeModules.FastImageView.writeToCache(isSourceObject(source) ? source : {}, file));
424
+ }) : Promise.resolve(nativeModule().writeToCache(isSourceObject(source) ? source : {}, file));
288
425
  FastImage.getCachePath = (source) => Array.isArray(source) ? Promise.resolve({
289
426
  ok: false,
290
427
  error: ONE_SOURCE
291
- }) : Promise.resolve(react_native.NativeModules.FastImageView.getCachePath(isSourceObject(source) ? source : {}));
292
- const styles = react_native.StyleSheet.create({
293
- fallbackImage: {
294
- position: "absolute",
295
- top: 0,
296
- left: 0,
297
- width: "100%",
298
- height: "100%"
299
- },
300
- imageContainer: { overflow: "hidden" }
301
- });
428
+ }) : Promise.resolve(nativeModule().getCachePath(isSourceObject(source) ? source : {}));
429
+ const styles = react_native.StyleSheet.create({ image: { overflow: "hidden" } });
302
430
  /**
303
431
  * An image with content on top of it, like React Native's `ImageBackground`: a
304
- * view that the image fills, with the children on top. Use it rather than
305
- * giving `FastImage` children, which it won't render in the next major version
306
- * (the image will be a single native view). The other props go to the image;
432
+ * view that the image fills, with the children on top (`FastImage` is a single
433
+ * native view, which doesn't take children). The other props go to the image;
307
434
  * the ref is the view's.
308
435
  */
309
436
  const FastImageBackground = (0, react.forwardRef)(({ style, imageStyle, imageRef, children, importantForAccessibility, ...props }, ref) => /* @__PURE__ */ react.default.createElement(react_native.View, {
@@ -318,14 +445,6 @@ const FastImageBackground = (0, react.forwardRef)(({ style, imageStyle, imageRef
318
445
  ref: imageRef
319
446
  }), children));
320
447
  FastImageBackground.displayName = "FastImageBackground";
321
- const FastImageView = (0, react_native.requireNativeComponent)("FastImageView", FastImage, { nativeOnly: {
322
- onFastImageLoadStart: true,
323
- onFastImageProgress: true,
324
- onFastImageLoad: true,
325
- onFastImageError: true,
326
- onFastImageLoadEnd: true,
327
- trackProgress: true
328
- } });
329
448
  //#endregion
330
449
  exports.FastImageBackground = FastImageBackground;
331
450
  exports.default = FastImage;
@@ -1,25 +1,23 @@
1
1
  // @flow
2
2
 
3
- import type { ViewProps } from 'react-native/Libraries/Components/View/ViewPropTypes'
4
- import type { SyntheticEvent } from 'react-native/Libraries/Types/CoreEventTypes'
3
+ import type { NativeSyntheticEvent, ViewProps } from 'react-native'
5
4
 
6
- export type OnLoadEvent = SyntheticEvent<
5
+ export type OnLoadEvent = NativeSyntheticEvent<
7
6
  $ReadOnly<{
8
7
  width: number,
9
8
  height: number,
10
- // The view's React tag. Missing on Android with the legacy architecture.
11
- // TODO: make it required once the New Architecture is the minimum.
9
+ // The view's React tag (on iOS and Android; not on the web).
12
10
  target?: number,
13
11
  }>,
14
12
  >
15
13
 
16
- export type OnErrorEvent = SyntheticEvent<
14
+ export type OnErrorEvent = NativeSyntheticEvent<
17
15
  $ReadOnly<{|
18
16
  error: string,
19
17
  |}>,
20
18
  >
21
19
 
22
- export type OnProgressEvent = SyntheticEvent<
20
+ export type OnProgressEvent = NativeSyntheticEvent<
23
21
  $ReadOnly<{|
24
22
  loaded: number,
25
23
  total: number,
@@ -28,6 +26,12 @@ export type OnProgressEvent = SyntheticEvent<
28
26
  |}>,
29
27
  >
30
28
 
29
+ export type Priority = $ReadOnly<{|
30
+ low: 'low',
31
+ normal: 'normal',
32
+ high: 'high',
33
+ |}>
34
+
31
35
  export type ResizeMode = $ReadOnly<{|
32
36
  contain: 'contain',
33
37
  cover: 'cover',
@@ -36,20 +40,22 @@ export type ResizeMode = $ReadOnly<{|
36
40
  repeat: 'repeat',
37
41
  |}>
38
42
 
39
- export type Priority = $ReadOnly<{|
40
- low: 'low',
41
- normal: 'normal',
42
- high: 'high',
43
- |}>
44
-
45
43
  export type CacheControl = $ReadOnly<{|
46
44
  immutable: 'immutable',
47
45
  web: 'web',
48
46
  cacheOnly: 'cacheOnly',
49
47
  |}>
50
48
 
51
- export type ResizeModes = $Values<ResizeMode>
52
49
  export type ObjectFit = 'fill' | 'contain' | 'cover' | 'none' | 'scale-down'
50
+ export type PositionLength = number | string
51
+ export type ObjectPosition =
52
+ | string
53
+ | $ReadOnly<{|
54
+ top?: PositionLength,
55
+ bottom?: PositionLength,
56
+ left?: PositionLength,
57
+ right?: PositionLength,
58
+ |}>
53
59
  export type Priorities = $Values<Priority>
54
60
  export type CacheControls = $Values<CacheControl>
55
61
 
@@ -82,6 +88,10 @@ export type Transition = $ReadOnly<{|
82
88
  skipOnCacheHit?: ?('none' | 'memory' | 'all'),
83
89
  |}>
84
90
 
91
+ export type FastImageDefaults = $ReadOnly<{|
92
+ transition?: ?(boolean | number | Transition),
93
+ |}>
94
+
85
95
  export type PreloadSuccess = {|
86
96
  uri: string,
87
97
  ok: true,
@@ -125,9 +135,7 @@ export type FastImageProps = $ReadOnly<{|
125
135
 
126
136
  tintColor?: number | string,
127
137
  objectFit?: ?ObjectFit,
128
- // Deprecated: use objectFit.
129
- resizeMode?: ?ResizeModes,
130
- fallback?: ?boolean,
138
+ objectPosition?: ?ObjectPosition,
131
139
  recyclingKey?: ?string,
132
140
  loop?: ?(boolean | number),
133
141
  imageRendering?: ?('auto' | 'smooth' | 'pixelated'),
@@ -136,6 +144,9 @@ export type FastImageProps = $ReadOnly<{|
136
144
  downsample?: ?boolean,
137
145
  blurRadius?: ?number,
138
146
  testID?: ?string,
147
+ // FastImage is a single native view, which doesn't take children (since
148
+ // 10.0): use FastImageBackground.
149
+ children?: "FastImage doesn't take children: use FastImageBackground for content over an image",
139
150
  |}>
140
151
 
141
152
  export type FastImageBackgroundProps = $ReadOnly<{|
@@ -148,14 +159,19 @@ export type FastImageBackgroundProps = $ReadOnly<{|
148
159
  declare export var FastImageBackground: React$ComponentType<FastImageBackgroundProps>
149
160
 
150
161
  declare export default class FastImage extends React$Component<FastImageProps> {
162
+ // Deprecated: removed in 10.0, and a resizeMode prop is ignored; use
163
+ // objectFit. Kept so code that reads it doesn't throw.
151
164
  static resizeMode: ResizeMode;
165
+ // Deprecated: use the strings instead, e.g. priority: 'high'.
152
166
  static priority: Priority;
167
+ // Deprecated: use the strings instead, e.g. cache: 'immutable'.
153
168
  static cacheControl: CacheControl;
154
169
  static preload: PreloadFn;
155
170
  static clearMemoryCache: () => Promise<ClearCacheResult>;
156
171
  static clearDiskCache: () => Promise<ClearCacheResult>;
157
172
  static getCachePath: (source: FastImageSource) => Promise<CachePathResult>;
158
173
  static configureCache: (limits?: CacheLimits) => Promise<CacheState>;
174
+ static setDefaults: (defaults: FastImageDefaults) => void;
159
175
  static writeToCache: (
160
176
  source: FastImageSource,
161
177
  file: string,