expo-image 1.10.4 → 1.11.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.
- package/CHANGELOG.md +18 -5
- package/android/build.gradle +1 -1
- package/android/src/main/java/expo/modules/image/CustomDownsampleStrategy.kt +102 -3
- package/android/src/main/java/expo/modules/image/ExpoImageModule.kt +6 -1
- package/android/src/main/java/expo/modules/image/ExpoImageViewWrapper.kt +16 -2
- package/android/src/main/java/expo/modules/image/records/DecodeFormat.kt +22 -0
- package/build/ExpoImage.web.d.ts +1 -1
- package/build/ExpoImage.web.d.ts.map +1 -1
- package/build/ExpoImage.web.js +13 -7
- package/build/ExpoImage.web.js.map +1 -1
- package/build/Image.d.ts +12 -0
- package/build/Image.d.ts.map +1 -1
- package/build/Image.js +11 -0
- package/build/Image.js.map +1 -1
- package/build/Image.types.d.ts +32 -7
- package/build/Image.types.d.ts.map +1 -1
- package/build/Image.types.js.map +1 -1
- package/build/web/useSourceSelection.d.ts +1 -1
- package/build/web/useSourceSelection.d.ts.map +1 -1
- package/build/web/useSourceSelection.js +2 -3
- package/build/web/useSourceSelection.js.map +1 -1
- package/ios/ImageModule.swift +15 -0
- package/ios/ImageUtils.swift +9 -0
- package/package.json +2 -2
- package/src/ExpoImage.web.tsx +16 -4
- package/src/Image.tsx +15 -0
- package/src/Image.types.ts +34 -7
- package/src/web/useSourceSelection.ts +2 -3
package/CHANGELOG.md
CHANGED
|
@@ -10,20 +10,33 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
-
## 1.
|
|
13
|
+
## 1.11.0 — 2024-02-05
|
|
14
|
+
|
|
15
|
+
### 🎉 New features
|
|
16
|
+
|
|
17
|
+
- [Android] Adds new prop `decodeFormat` to specify the format that should be used during the decoding process. ([#26442](https://github.com/expo/expo/pull/26442) by [@lukmccall](https://github.com/lukmccall))
|
|
18
|
+
- [iOS] Added `generateBlurhashAsync` function. ([#26430](https://github.com/expo/expo/pull/26430) by [@aleqsio](https://github.com/aleqsio))
|
|
19
|
+
- [Android] Adds automatic downsampling when the asset exceeds the hardware bitmap size limit. ([#26792](https://github.com/expo/expo/pull/26792) by [@lukmccall](https://github.com/lukmccall))
|
|
20
|
+
|
|
21
|
+
### 🐛 Bug fixes
|
|
22
|
+
|
|
23
|
+
- Fixed ResizeObserver attaching on every image transition. ([#25819](https://github.com/expo/expo/pull/25819) by [@aleqsio](https://github.com/aleqsio))
|
|
24
|
+
- [Android] Fixed the tine color was applied to the mask element. ([#26323](https://github.com/expo/expo/pull/26323) by [@lukmccall](https://github.com/lukmccall))
|
|
25
|
+
- [Web] Fixed `nativeViewRef` invalid prop warning. ([#25922](https://github.com/expo/expo/pull/25922) by [@intergalacticspacehighway](https://github.com/intergalacticspacehighway))
|
|
26
|
+
|
|
27
|
+
## 1.10.4 - 2024-01-18
|
|
14
28
|
|
|
15
29
|
_This version does not introduce any user-facing changes._
|
|
16
30
|
|
|
17
|
-
## 1.10.3
|
|
31
|
+
## 1.10.3 - 2024-01-12
|
|
18
32
|
|
|
19
33
|
_This version does not introduce any user-facing changes._
|
|
20
34
|
|
|
21
|
-
## 1.10.2
|
|
35
|
+
## 1.10.2 - 2024-01-10
|
|
22
36
|
|
|
23
37
|
### 🐛 Bug fixes
|
|
24
38
|
|
|
25
39
|
- [Android] Fixed the issue with the application of tint color when an element does not have a style assigned to it. ([#26251](https://github.com/expo/expo/pull/26251) by [@lukmccall](https://github.com/lukmccall))
|
|
26
|
-
- [Android] Fixed the tint color was applied to the mask element. ([#26323](https://github.com/expo/expo/pull/26323) by [@lukmccall](https://github.com/lukmccall))
|
|
27
40
|
- [Android] Fixed the tint color wasn't applied to the root element. ([#26339](https://github.com/expo/expo/pull/26339) by [@lukmccall](https://github.com/lukmccall))
|
|
28
41
|
- [Android] Fixed that the tint color on SVGs can't be changed dynamically. ([#26350](https://github.com/expo/expo/pull/26350) by [@lukmccall](https://github.com/lukmccall))
|
|
29
42
|
|
|
@@ -31,7 +44,7 @@ _This version does not introduce any user-facing changes._
|
|
|
31
44
|
|
|
32
45
|
- Replace deprecated `com.facebook.react:react-native:+` Android dependency with `com.facebook.react:react-android`. ([#26237](https://github.com/expo/expo/pull/26237) by [@kudo](https://github.com/kudo))
|
|
33
46
|
|
|
34
|
-
## 1.10.1
|
|
47
|
+
## 1.10.1 - 2023-12-19
|
|
35
48
|
|
|
36
49
|
_This version does not introduce any user-facing changes._
|
|
37
50
|
|
package/android/build.gradle
CHANGED
|
@@ -67,7 +67,7 @@ android {
|
|
|
67
67
|
namespace "expo.modules.image"
|
|
68
68
|
defaultConfig {
|
|
69
69
|
versionCode 1
|
|
70
|
-
versionName "1.
|
|
70
|
+
versionName "1.11.0"
|
|
71
71
|
consumerProguardFiles("proguard-rules.pro")
|
|
72
72
|
|
|
73
73
|
buildConfigField("boolean", "ALLOW_GLIDE_LOGS", project.properties.get("EXPO_ALLOW_GLIDE_LOGS", "false"))
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
package expo.modules.image
|
|
2
2
|
|
|
3
|
+
import android.os.Build
|
|
3
4
|
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy
|
|
4
5
|
import com.bumptech.glide.request.target.Target
|
|
5
6
|
import expo.modules.image.enums.ContentFit
|
|
7
|
+
import expo.modules.image.records.DecodeFormat
|
|
8
|
+
import kotlin.math.floor
|
|
9
|
+
import kotlin.math.max
|
|
6
10
|
import kotlin.math.min
|
|
11
|
+
import kotlin.math.sqrt
|
|
7
12
|
|
|
8
13
|
/**
|
|
9
14
|
* Glide uses `hashCode` and `equals` of the `DownsampleStrategy` to calculate the cache key.
|
|
@@ -23,7 +28,7 @@ abstract class CustomDownsampleStrategy : DownsampleStrategy() {
|
|
|
23
28
|
}
|
|
24
29
|
}
|
|
25
30
|
|
|
26
|
-
|
|
31
|
+
object NoopDownsampleStrategy : DownsampleStrategy() {
|
|
27
32
|
override fun getScaleFactor(
|
|
28
33
|
sourceWidth: Int,
|
|
29
34
|
sourceHeight: Int,
|
|
@@ -39,7 +44,10 @@ class NoopDownsampleStrategy : DownsampleStrategy() {
|
|
|
39
44
|
): SampleSizeRounding = SampleSizeRounding.QUALITY
|
|
40
45
|
}
|
|
41
46
|
|
|
42
|
-
class ContentFitDownsampleStrategy(
|
|
47
|
+
class ContentFitDownsampleStrategy(
|
|
48
|
+
private val target: ImageViewWrapperTarget,
|
|
49
|
+
private val contentFit: ContentFit
|
|
50
|
+
) : CustomDownsampleStrategy() {
|
|
43
51
|
private var wasTriggered = false
|
|
44
52
|
override fun getScaleFactor(
|
|
45
53
|
sourceWidth: Int,
|
|
@@ -86,7 +94,6 @@ class ContentFitDownsampleStrategy(private val target: ImageViewWrapperTarget, p
|
|
|
86
94
|
requestedWidth / sourceWidth,
|
|
87
95
|
requestedHeight / sourceHeight
|
|
88
96
|
)
|
|
89
|
-
ContentFit.Fill, ContentFit.None -> 1f
|
|
90
97
|
ContentFit.ScaleDown -> if (requestedWidth < sourceWidth || requestedHeight < sourceHeight) {
|
|
91
98
|
// The container is smaller than the image — scale it down and behave like `contain`
|
|
92
99
|
min(
|
|
@@ -97,6 +104,7 @@ class ContentFitDownsampleStrategy(private val target: ImageViewWrapperTarget, p
|
|
|
97
104
|
// The container is bigger than the image — don't scale it and behave like `none`
|
|
98
105
|
1f
|
|
99
106
|
}
|
|
107
|
+
else -> 1f
|
|
100
108
|
}
|
|
101
109
|
|
|
102
110
|
override fun getSampleSizeRounding(
|
|
@@ -106,3 +114,94 @@ class ContentFitDownsampleStrategy(private val target: ImageViewWrapperTarget, p
|
|
|
106
114
|
requestedHeight: Int
|
|
107
115
|
) = SampleSizeRounding.QUALITY
|
|
108
116
|
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Android has hardware bitmap size limit that can be drown on the canvas.
|
|
120
|
+
* To prevents crashes, we need to downsample the image to fit into the maximum bitmap size.
|
|
121
|
+
*/
|
|
122
|
+
class SafeDownsampleStrategy(
|
|
123
|
+
private val decodeFormat: DecodeFormat
|
|
124
|
+
) : CustomDownsampleStrategy() {
|
|
125
|
+
override fun getScaleFactor(
|
|
126
|
+
sourceWidth: Int,
|
|
127
|
+
sourceHeight: Int,
|
|
128
|
+
requestedWidth: Int,
|
|
129
|
+
requestedHeight: Int
|
|
130
|
+
): Float {
|
|
131
|
+
if (maxBitmapSize <= 0) {
|
|
132
|
+
return 1f
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
val sourceSize = sourceWidth * sourceHeight * decodeFormat.toBytes()
|
|
136
|
+
if (sourceSize <= maxBitmapSize) {
|
|
137
|
+
return 1f
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// We need to downsample the image to fit into the maximum bitmap size.
|
|
141
|
+
// Calculate the aspect ratio of the source image. It's always <= 1.
|
|
142
|
+
val srcAspectRatio = min(sourceWidth, sourceHeight).toDouble() / max(sourceWidth, sourceHeight).toDouble()
|
|
143
|
+
// Calculate the area of the destination image.
|
|
144
|
+
val dstArea = maxBitmapSize / decodeFormat.toBytes()
|
|
145
|
+
// Calculate the longer side of the destination image using following formulas:
|
|
146
|
+
// dstLongerSide * dstSmallerSide = dstArea
|
|
147
|
+
// srcAspectRation * dstLongerSide = dstSmallerSide
|
|
148
|
+
// after substitution:
|
|
149
|
+
// srcAspectRation * dstLongerSide * dstLongerSide = dstArea
|
|
150
|
+
// dstLongerSide = sqrt(dstArea / srcAspectRatio)
|
|
151
|
+
val x = floor(sqrt(dstArea.toDouble() / srcAspectRatio)).toInt()
|
|
152
|
+
|
|
153
|
+
// Calculate the scale factor using longer side of both images.
|
|
154
|
+
val scaleFactor = x.toDouble() / max(sourceWidth, sourceHeight).toDouble()
|
|
155
|
+
|
|
156
|
+
return scaleFactor.toFloat()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
override fun getSampleSizeRounding(
|
|
160
|
+
sourceWidth: Int,
|
|
161
|
+
sourceHeight: Int,
|
|
162
|
+
requestedWidth: Int,
|
|
163
|
+
requestedHeight: Int
|
|
164
|
+
): SampleSizeRounding {
|
|
165
|
+
return SampleSizeRounding.MEMORY
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private val maxBitmapSize by lazy {
|
|
169
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
|
170
|
+
return@lazy -1
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return@lazy try {
|
|
174
|
+
val defaultSize = 100 * 1024 * 1024 // 100 MB - from `RecordingCanvas` src
|
|
175
|
+
|
|
176
|
+
// We're trying to get the value of `ro.hwui.max_texture_allocation_size` property
|
|
177
|
+
// which is used by `RecordingCanvas` to determine the maximum bitmap size.
|
|
178
|
+
@Suppress("PrivateApi")
|
|
179
|
+
val getIntMethod = Class
|
|
180
|
+
.forName("android.os.SystemProperties")
|
|
181
|
+
.getMethod("getInt", String::class.java, Int::class.java)
|
|
182
|
+
getIntMethod.isAccessible = true
|
|
183
|
+
(getIntMethod.invoke(null, "ro.hwui.max_texture_allocation_size", defaultSize) as Int)
|
|
184
|
+
.coerceAtLeast(defaultSize)
|
|
185
|
+
} catch (e: Throwable) {
|
|
186
|
+
// If something goes wrong we just return -1 and don't downsample the image.
|
|
187
|
+
-1
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
override fun equals(other: Any?): Boolean {
|
|
192
|
+
if (this === other) {
|
|
193
|
+
return true
|
|
194
|
+
}
|
|
195
|
+
if (other !is SafeDownsampleStrategy) {
|
|
196
|
+
return false
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return decodeFormat == other.decodeFormat
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
override fun hashCode(): Int {
|
|
203
|
+
var result = super.hashCode()
|
|
204
|
+
result = 31 * result + decodeFormat.hashCode()
|
|
205
|
+
return result
|
|
206
|
+
}
|
|
207
|
+
}
|
|
@@ -18,6 +18,7 @@ import expo.modules.image.enums.ContentFit
|
|
|
18
18
|
import expo.modules.image.enums.Priority
|
|
19
19
|
import expo.modules.image.records.CachePolicy
|
|
20
20
|
import expo.modules.image.records.ContentPosition
|
|
21
|
+
import expo.modules.image.records.DecodeFormat
|
|
21
22
|
import expo.modules.image.records.ImageTransition
|
|
22
23
|
import expo.modules.image.records.SourceMap
|
|
23
24
|
import expo.modules.kotlin.Promise
|
|
@@ -42,7 +43,7 @@ class ExpoImageModule : Module() {
|
|
|
42
43
|
.load(GlideUrl(it)) // Use `load` instead of `download` to store the asset in the memory cache
|
|
43
44
|
// We added `quality` and `downsample` to create the same cache key as in final image load.
|
|
44
45
|
.encodeQuality(100)
|
|
45
|
-
.downsample(NoopDownsampleStrategy
|
|
46
|
+
.downsample(NoopDownsampleStrategy)
|
|
46
47
|
.apply {
|
|
47
48
|
if (cachePolicy == CachePolicy.MEMORY) {
|
|
48
49
|
diskCacheStrategy(DiskCacheStrategy.NONE)
|
|
@@ -239,6 +240,10 @@ class ExpoImageModule : Module() {
|
|
|
239
240
|
view.autoplay = autoplay ?: true
|
|
240
241
|
}
|
|
241
242
|
|
|
243
|
+
Prop("decodeFormat") { view: ExpoImageViewWrapper, format: DecodeFormat? ->
|
|
244
|
+
view.decodeFormat = format ?: DecodeFormat.ARGB_8888
|
|
245
|
+
}
|
|
246
|
+
|
|
242
247
|
AsyncFunction("startAnimating") { view: ExpoImageViewWrapper ->
|
|
243
248
|
view.setIsAnimating(true)
|
|
244
249
|
}
|
|
@@ -26,6 +26,7 @@ import expo.modules.image.events.OkHttpProgressListener
|
|
|
26
26
|
import expo.modules.image.okhttp.GlideUrlWrapper
|
|
27
27
|
import expo.modules.image.records.CachePolicy
|
|
28
28
|
import expo.modules.image.records.ContentPosition
|
|
29
|
+
import expo.modules.image.records.DecodeFormat
|
|
29
30
|
import expo.modules.image.records.ImageErrorEvent
|
|
30
31
|
import expo.modules.image.records.ImageLoadEvent
|
|
31
32
|
import expo.modules.image.records.ImageProgressEvent
|
|
@@ -166,6 +167,12 @@ class ExpoImageViewWrapper(context: Context, appContext: AppContext) : ExpoView(
|
|
|
166
167
|
shouldRerender = true
|
|
167
168
|
}
|
|
168
169
|
|
|
170
|
+
internal var decodeFormat: DecodeFormat = DecodeFormat.ARGB_8888
|
|
171
|
+
set(value) {
|
|
172
|
+
field = value
|
|
173
|
+
shouldRerender = true
|
|
174
|
+
}
|
|
175
|
+
|
|
169
176
|
internal var autoplay: Boolean = true
|
|
170
177
|
|
|
171
178
|
internal var priority: Priority = Priority.NORMAL
|
|
@@ -512,10 +519,16 @@ class ExpoImageViewWrapper(context: Context, appContext: AppContext) : ExpoView(
|
|
|
512
519
|
}
|
|
513
520
|
newTarget.hasSource = sourceToLoad != null
|
|
514
521
|
|
|
515
|
-
val downsampleStrategy = if (allowDownscaling) {
|
|
522
|
+
val downsampleStrategy = if (!allowDownscaling) {
|
|
523
|
+
DownsampleStrategy.NONE
|
|
524
|
+
} else if (
|
|
525
|
+
contentFit != ContentFit.Fill &&
|
|
526
|
+
contentFit != ContentFit.None
|
|
527
|
+
) {
|
|
516
528
|
ContentFitDownsampleStrategy(newTarget, contentFit)
|
|
517
529
|
} else {
|
|
518
|
-
|
|
530
|
+
// it won't downscale the image if the image is smaller than hardware bitmap size limit
|
|
531
|
+
SafeDownsampleStrategy(decodeFormat)
|
|
519
532
|
}
|
|
520
533
|
|
|
521
534
|
val request = requestManager
|
|
@@ -540,6 +553,7 @@ class ExpoImageViewWrapper(context: Context, appContext: AppContext) : ExpoView(
|
|
|
540
553
|
.downsample(downsampleStrategy)
|
|
541
554
|
.addListener(GlideRequestListener(WeakReference(this)))
|
|
542
555
|
.encodeQuality(100)
|
|
556
|
+
.format(decodeFormat.toGlideFormat())
|
|
543
557
|
.apply(propOptions)
|
|
544
558
|
|
|
545
559
|
tintColor?.let {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package expo.modules.image.records
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.types.Enumerable
|
|
4
|
+
|
|
5
|
+
enum class DecodeFormat(val value: String) : Enumerable {
|
|
6
|
+
ARGB_8888("argb"),
|
|
7
|
+
RGB_565("rgb");
|
|
8
|
+
|
|
9
|
+
fun toGlideFormat(): com.bumptech.glide.load.DecodeFormat {
|
|
10
|
+
return when (this) {
|
|
11
|
+
ARGB_8888 -> com.bumptech.glide.load.DecodeFormat.PREFER_ARGB_8888
|
|
12
|
+
RGB_565 -> com.bumptech.glide.load.DecodeFormat.PREFER_RGB_565
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
fun toBytes(): Int {
|
|
17
|
+
return when (this) {
|
|
18
|
+
ARGB_8888 -> 4
|
|
19
|
+
RGB_565 -> 2
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
package/build/ExpoImage.web.d.ts
CHANGED
|
@@ -4,5 +4,5 @@ export declare const ExpoImageModule: {
|
|
|
4
4
|
clearMemoryCache(): Promise<boolean>;
|
|
5
5
|
clearDiskCache(): Promise<boolean>;
|
|
6
6
|
};
|
|
7
|
-
export default function ExpoImage({ source, placeholder, contentFit, contentPosition, placeholderContentFit, cachePolicy, onLoad, transition, onError, responsivePolicy, onLoadEnd, priority, blurRadius, recyclingKey, style, ...props }: ImageNativeProps): JSX.Element;
|
|
7
|
+
export default function ExpoImage({ source, placeholder, contentFit, contentPosition, placeholderContentFit, cachePolicy, onLoad, transition, onError, responsivePolicy, onLoadEnd, priority, blurRadius, recyclingKey, style, nativeViewRef, ...props }: ImageNativeProps): JSX.Element;
|
|
8
8
|
//# sourceMappingURL=ExpoImage.web.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoImage.web.d.ts","sourceRoot":"","sources":["../src/ExpoImage.web.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAmC,MAAM,eAAe,CAAC;AAQlF,eAAO,MAAM,eAAe;mBACL,MAAM,GAAG,MAAM,EAAE,WAAM,QAAQ,OAAO,CAAC;wBAqBlC,QAAQ,OAAO,CAAC;sBAIlB,QAAQ,OAAO,CAAC;CAGzC,CAAC;
|
|
1
|
+
{"version":3,"file":"ExpoImage.web.d.ts","sourceRoot":"","sources":["../src/ExpoImage.web.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAmC,MAAM,eAAe,CAAC;AAQlF,eAAO,MAAM,eAAe;mBACL,MAAM,GAAG,MAAM,EAAE,WAAM,QAAQ,OAAO,CAAC;wBAqBlC,QAAQ,OAAO,CAAC;sBAIlB,QAAQ,OAAO,CAAC;CAGzC,CAAC;AAwCF,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,MAAM,EACN,WAAW,EACX,UAAU,EACV,eAAe,EACf,qBAAqB,EACrB,WAAW,EACX,MAAM,EACN,UAAU,EACV,OAAO,EACP,gBAAgB,EAChB,SAAS,EACT,QAAQ,EACR,UAAU,EACV,YAAY,EACZ,KAAK,EACL,aAAa,EACb,GAAG,KAAK,EACT,EAAE,gBAAgB,eAiFlB"}
|
package/build/ExpoImage.web.js
CHANGED
|
@@ -51,22 +51,28 @@ function onErrorAdapter(onError) {
|
|
|
51
51
|
});
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
-
// Used for
|
|
55
|
-
|
|
54
|
+
// Used for flip transitions to mimic native animations
|
|
55
|
+
function setCssVariablesForFlipTransitions(element, size) {
|
|
56
56
|
element?.style.setProperty('--expo-image-width', `${size.width}px`);
|
|
57
57
|
element?.style.setProperty('--expo-image-height', `${size.height}px`);
|
|
58
|
-
}
|
|
59
|
-
|
|
58
|
+
}
|
|
59
|
+
function isFlipTransition(transition) {
|
|
60
|
+
return (transition?.effect === 'flip-from-bottom' ||
|
|
61
|
+
transition?.effect === 'flip-from-top' ||
|
|
62
|
+
transition?.effect === 'flip-from-left' ||
|
|
63
|
+
transition?.effect === 'flip-from-right');
|
|
64
|
+
}
|
|
65
|
+
export default function ExpoImage({ source, placeholder, contentFit, contentPosition, placeholderContentFit, cachePolicy, onLoad, transition, onError, responsivePolicy, onLoadEnd, priority, blurRadius, recyclingKey, style, nativeViewRef, ...props }) {
|
|
60
66
|
const imagePlaceholderContentFit = placeholderContentFit || 'scale-down';
|
|
61
67
|
const imageHashStyle = {
|
|
62
68
|
objectFit: placeholderContentFit || contentFit,
|
|
63
69
|
};
|
|
64
|
-
const { containerRef, source: selectedSource } = useSourceSelection(source, responsivePolicy,
|
|
70
|
+
const { containerRef, source: selectedSource } = useSourceSelection(source, responsivePolicy, isFlipTransition(transition) ? setCssVariablesForFlipTransitions : null);
|
|
65
71
|
const initialNodeAnimationKey = (recyclingKey ? `${recyclingKey}-${placeholder?.[0]?.uri}` : placeholder?.[0]?.uri) ?? '';
|
|
66
72
|
const initialNode = placeholder?.[0]?.uri
|
|
67
73
|
? [
|
|
68
74
|
initialNodeAnimationKey,
|
|
69
|
-
({ onAnimationFinished }) => (className, style) => (<ImageWrapper {...props} source={placeholder?.[0]} style={{
|
|
75
|
+
({ onAnimationFinished }) => (className, style) => (<ImageWrapper {...props} ref={nativeViewRef} source={placeholder?.[0]} style={{
|
|
70
76
|
objectFit: imagePlaceholderContentFit,
|
|
71
77
|
...(blurRadius ? { filter: `blur(${blurRadius}px)` } : {}),
|
|
72
78
|
...style,
|
|
@@ -80,7 +86,7 @@ export default function ExpoImage({ source, placeholder, contentFit, contentPosi
|
|
|
80
86
|
: selectedSource?.uri ?? placeholder?.[0]?.uri) ?? '';
|
|
81
87
|
const currentNode = [
|
|
82
88
|
currentNodeAnimationKey,
|
|
83
|
-
({ onAnimationFinished, onReady, onMount, onError: onErrorInner }) => (className, style) => (<ImageWrapper {...props} source={selectedSource || placeholder?.[0]} events={{
|
|
89
|
+
({ onAnimationFinished, onReady, onMount, onError: onErrorInner }) => (className, style) => (<ImageWrapper {...props} ref={nativeViewRef} source={selectedSource || placeholder?.[0]} events={{
|
|
84
90
|
onError: [onErrorAdapter(onError), onLoadEnd, onErrorInner],
|
|
85
91
|
onLoad: [onLoadAdapter(onLoad), onLoadEnd, onReady],
|
|
86
92
|
onMount: [onMount],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoImage.web.js","sourceRoot":"","sources":["../src/ExpoImage.web.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { View } from 'react-native-web';\n\nimport { ImageNativeProps, ImageSource, ImageLoadEventData } from './Image.types';\nimport AnimationManager, { AnimationManagerNode } from './web/AnimationManager';\nimport ImageWrapper from './web/ImageWrapper';\nimport loadStyle from './web/imageStyles';\nimport useSourceSelection from './web/useSourceSelection';\n\nloadStyle();\n\nexport const ExpoImageModule = {\n async prefetch(urls: string | string[], _): Promise<boolean> {\n const urlsArray = Array.isArray(urls) ? urls : [urls];\n\n return new Promise<boolean>((resolve) => {\n let imagesLoaded = 0;\n\n urlsArray.forEach((url) => {\n const img = new Image();\n img.src = url;\n img.onload = () => {\n imagesLoaded++;\n\n if (imagesLoaded === urlsArray.length) {\n resolve(true);\n }\n };\n img.onerror = () => resolve(false);\n });\n });\n },\n\n async clearMemoryCache(): Promise<boolean> {\n return false;\n },\n\n async clearDiskCache(): Promise<boolean> {\n return false;\n },\n};\n\nfunction onLoadAdapter(onLoad?: (event: ImageLoadEventData) => void) {\n return (event: React.SyntheticEvent<HTMLImageElement, Event>) => {\n const target = event.target as HTMLImageElement;\n onLoad?.({\n source: {\n url: target.currentSrc,\n width: target.naturalWidth,\n height: target.naturalHeight,\n mediaType: null,\n },\n cacheType: 'none',\n });\n };\n}\n\nfunction onErrorAdapter(onError?: { (event: { error: string }): void }) {\n return ({ source }: { source?: ImageSource | null }) => {\n onError?.({\n error: `Failed to load image from url: ${source?.uri}`,\n });\n };\n}\n\n// Used for some transitions to mimic native animations\nconst setCssVariables = (element: HTMLElement, size: DOMRect) => {\n element?.style.setProperty('--expo-image-width', `${size.width}px`);\n element?.style.setProperty('--expo-image-height', `${size.height}px`);\n};\n\nexport default function ExpoImage({\n source,\n placeholder,\n contentFit,\n contentPosition,\n placeholderContentFit,\n cachePolicy,\n onLoad,\n transition,\n onError,\n responsivePolicy,\n onLoadEnd,\n priority,\n blurRadius,\n recyclingKey,\n style,\n ...props\n}: ImageNativeProps) {\n const imagePlaceholderContentFit = placeholderContentFit || 'scale-down';\n const imageHashStyle = {\n objectFit: placeholderContentFit || contentFit,\n };\n const { containerRef, source: selectedSource } = useSourceSelection(\n source,\n responsivePolicy,\n setCssVariables\n );\n\n const initialNodeAnimationKey =\n (recyclingKey ? `${recyclingKey}-${placeholder?.[0]?.uri}` : placeholder?.[0]?.uri) ?? '';\n\n const initialNode: AnimationManagerNode | null = placeholder?.[0]?.uri\n ? [\n initialNodeAnimationKey,\n ({ onAnimationFinished }) =>\n (className, style) => (\n <ImageWrapper\n {...props}\n source={placeholder?.[0]}\n style={{\n objectFit: imagePlaceholderContentFit,\n ...(blurRadius ? { filter: `blur(${blurRadius}px)` } : {}),\n ...style,\n }}\n className={className}\n events={{\n onTransitionEnd: [onAnimationFinished],\n }}\n contentPosition={{ left: '50%', top: '50%' }}\n hashPlaceholderContentPosition={contentPosition}\n hashPlaceholderStyle={imageHashStyle}\n />\n ),\n ]\n : null;\n\n const currentNodeAnimationKey =\n (recyclingKey\n ? `${recyclingKey}-${selectedSource?.uri ?? placeholder?.[0]?.uri}`\n : selectedSource?.uri ?? placeholder?.[0]?.uri) ?? '';\n\n const currentNode: AnimationManagerNode = [\n currentNodeAnimationKey,\n ({ onAnimationFinished, onReady, onMount, onError: onErrorInner }) =>\n (className, style) => (\n <ImageWrapper\n {...props}\n source={selectedSource || placeholder?.[0]}\n events={{\n onError: [onErrorAdapter(onError), onLoadEnd, onErrorInner],\n onLoad: [onLoadAdapter(onLoad), onLoadEnd, onReady],\n onMount: [onMount],\n onTransitionEnd: [onAnimationFinished],\n }}\n style={{\n objectFit: selectedSource ? contentFit : imagePlaceholderContentFit,\n ...(blurRadius ? { filter: `blur(${blurRadius}px)` } : {}),\n ...style,\n }}\n className={className}\n cachePolicy={cachePolicy}\n priority={priority}\n contentPosition={selectedSource ? contentPosition : { top: '50%', left: '50%' }}\n hashPlaceholderContentPosition={contentPosition}\n hashPlaceholderStyle={imageHashStyle}\n accessibilityLabel={props.accessibilityLabel}\n />\n ),\n ];\n return (\n <View ref={containerRef} dataSet={{ expoimage: true }} style={[{ overflow: 'hidden' }, style]}>\n <AnimationManager transition={transition} recyclingKey={recyclingKey} initial={initialNode}>\n {currentNode}\n </AnimationManager>\n </View>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ExpoImage.web.js","sourceRoot":"","sources":["../src/ExpoImage.web.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { View } from 'react-native-web';\n\nimport { ImageNativeProps, ImageSource, ImageLoadEventData } from './Image.types';\nimport AnimationManager, { AnimationManagerNode } from './web/AnimationManager';\nimport ImageWrapper from './web/ImageWrapper';\nimport loadStyle from './web/imageStyles';\nimport useSourceSelection from './web/useSourceSelection';\n\nloadStyle();\n\nexport const ExpoImageModule = {\n async prefetch(urls: string | string[], _): Promise<boolean> {\n const urlsArray = Array.isArray(urls) ? urls : [urls];\n\n return new Promise<boolean>((resolve) => {\n let imagesLoaded = 0;\n\n urlsArray.forEach((url) => {\n const img = new Image();\n img.src = url;\n img.onload = () => {\n imagesLoaded++;\n\n if (imagesLoaded === urlsArray.length) {\n resolve(true);\n }\n };\n img.onerror = () => resolve(false);\n });\n });\n },\n\n async clearMemoryCache(): Promise<boolean> {\n return false;\n },\n\n async clearDiskCache(): Promise<boolean> {\n return false;\n },\n};\n\nfunction onLoadAdapter(onLoad?: (event: ImageLoadEventData) => void) {\n return (event: React.SyntheticEvent<HTMLImageElement, Event>) => {\n const target = event.target as HTMLImageElement;\n onLoad?.({\n source: {\n url: target.currentSrc,\n width: target.naturalWidth,\n height: target.naturalHeight,\n mediaType: null,\n },\n cacheType: 'none',\n });\n };\n}\n\nfunction onErrorAdapter(onError?: { (event: { error: string }): void }) {\n return ({ source }: { source?: ImageSource | null }) => {\n onError?.({\n error: `Failed to load image from url: ${source?.uri}`,\n });\n };\n}\n\n// Used for flip transitions to mimic native animations\nfunction setCssVariablesForFlipTransitions(element: HTMLElement, size: DOMRect) {\n element?.style.setProperty('--expo-image-width', `${size.width}px`);\n element?.style.setProperty('--expo-image-height', `${size.height}px`);\n}\n\nfunction isFlipTransition(transition: ImageNativeProps['transition']) {\n return (\n transition?.effect === 'flip-from-bottom' ||\n transition?.effect === 'flip-from-top' ||\n transition?.effect === 'flip-from-left' ||\n transition?.effect === 'flip-from-right'\n );\n}\n\nexport default function ExpoImage({\n source,\n placeholder,\n contentFit,\n contentPosition,\n placeholderContentFit,\n cachePolicy,\n onLoad,\n transition,\n onError,\n responsivePolicy,\n onLoadEnd,\n priority,\n blurRadius,\n recyclingKey,\n style,\n nativeViewRef,\n ...props\n}: ImageNativeProps) {\n const imagePlaceholderContentFit = placeholderContentFit || 'scale-down';\n const imageHashStyle = {\n objectFit: placeholderContentFit || contentFit,\n };\n const { containerRef, source: selectedSource } = useSourceSelection(\n source,\n responsivePolicy,\n isFlipTransition(transition) ? setCssVariablesForFlipTransitions : null\n );\n\n const initialNodeAnimationKey =\n (recyclingKey ? `${recyclingKey}-${placeholder?.[0]?.uri}` : placeholder?.[0]?.uri) ?? '';\n\n const initialNode: AnimationManagerNode | null = placeholder?.[0]?.uri\n ? [\n initialNodeAnimationKey,\n ({ onAnimationFinished }) =>\n (className, style) => (\n <ImageWrapper\n {...props}\n ref={nativeViewRef as React.Ref<HTMLImageElement> | undefined}\n source={placeholder?.[0]}\n style={{\n objectFit: imagePlaceholderContentFit,\n ...(blurRadius ? { filter: `blur(${blurRadius}px)` } : {}),\n ...style,\n }}\n className={className}\n events={{\n onTransitionEnd: [onAnimationFinished],\n }}\n contentPosition={{ left: '50%', top: '50%' }}\n hashPlaceholderContentPosition={contentPosition}\n hashPlaceholderStyle={imageHashStyle}\n />\n ),\n ]\n : null;\n\n const currentNodeAnimationKey =\n (recyclingKey\n ? `${recyclingKey}-${selectedSource?.uri ?? placeholder?.[0]?.uri}`\n : selectedSource?.uri ?? placeholder?.[0]?.uri) ?? '';\n\n const currentNode: AnimationManagerNode = [\n currentNodeAnimationKey,\n ({ onAnimationFinished, onReady, onMount, onError: onErrorInner }) =>\n (className, style) => (\n <ImageWrapper\n {...props}\n ref={nativeViewRef as React.Ref<HTMLImageElement> | undefined}\n source={selectedSource || placeholder?.[0]}\n events={{\n onError: [onErrorAdapter(onError), onLoadEnd, onErrorInner],\n onLoad: [onLoadAdapter(onLoad), onLoadEnd, onReady],\n onMount: [onMount],\n onTransitionEnd: [onAnimationFinished],\n }}\n style={{\n objectFit: selectedSource ? contentFit : imagePlaceholderContentFit,\n ...(blurRadius ? { filter: `blur(${blurRadius}px)` } : {}),\n ...style,\n }}\n className={className}\n cachePolicy={cachePolicy}\n priority={priority}\n contentPosition={selectedSource ? contentPosition : { top: '50%', left: '50%' }}\n hashPlaceholderContentPosition={contentPosition}\n hashPlaceholderStyle={imageHashStyle}\n accessibilityLabel={props.accessibilityLabel}\n />\n ),\n ];\n return (\n <View ref={containerRef} dataSet={{ expoimage: true }} style={[{ overflow: 'hidden' }, style]}>\n <AnimationManager transition={transition} recyclingKey={recyclingKey} initial={initialNode}>\n {currentNode}\n </AnimationManager>\n </View>\n );\n}\n"]}
|
package/build/Image.d.ts
CHANGED
|
@@ -44,6 +44,18 @@ export declare class Image extends React.PureComponent<ImageProps> {
|
|
|
44
44
|
* to `null` if the image does not exist in the cache.
|
|
45
45
|
*/
|
|
46
46
|
static getCachePathAsync(cacheKey: string): Promise<string | null>;
|
|
47
|
+
/**
|
|
48
|
+
* Asynchronously generates a [Blurhash](https://blurha.sh) from an image.
|
|
49
|
+
* @param url - The URL of the image to generate a blurhash from.
|
|
50
|
+
* @param numberOfComponents - The number of components to encode the blurhash with.
|
|
51
|
+
* Must be between 1 and 9. Defaults to `[4, 3]`.
|
|
52
|
+
* @platform ios
|
|
53
|
+
* @return A promise resolving to the blurhash string.
|
|
54
|
+
*/
|
|
55
|
+
static generateBlurhashAsync(url: string, numberOfComponents: [number, number] | {
|
|
56
|
+
width: number;
|
|
57
|
+
height: number;
|
|
58
|
+
}): Promise<string | null>;
|
|
47
59
|
/**
|
|
48
60
|
* Asynchronously starts playback of the view's image if it is animated.
|
|
49
61
|
* @platform android
|
package/build/Image.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../src/Image.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAM3C,qBAAa,KAAM,SAAQ,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC;IACxD,aAAa,MAAC;gBAEF,KAAK,KAAA;IAKjB;;;;;;;;;;OAUG;WACU,QAAQ,CACnB,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,WAAW,GAAE,aAAa,GAAG,QAAwB,GACpD,OAAO,CAAC,OAAO,CAAC;IAInB;;;;;;;OAOG;WACU,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAIjD;;;;;;;OAOG;WACU,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/C;;;;;;;;;OASG;WACU,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIxE;;;;OAIG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrC;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC,MAAM;CAsCP"}
|
|
1
|
+
{"version":3,"file":"Image.d.ts","sourceRoot":"","sources":["../src/Image.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAM3C,qBAAa,KAAM,SAAQ,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC;IACxD,aAAa,MAAC;gBAEF,KAAK,KAAA;IAKjB;;;;;;;;;;OAUG;WACU,QAAQ,CACnB,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,EACvB,WAAW,GAAE,aAAa,GAAG,QAAwB,GACpD,OAAO,CAAC,OAAO,CAAC;IAInB;;;;;;;OAOG;WACU,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC;IAIjD;;;;;;;OAOG;WACU,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAI/C;;;;;;;;;OASG;WACU,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIxE;;;;;;;OAOG;WACU,qBAAqB,CAChC,GAAG,EAAE,MAAM,EACX,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GACvE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIzB;;;;OAIG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrC;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAIpC,MAAM;CAsCP"}
|
package/build/Image.js
CHANGED
|
@@ -59,6 +59,17 @@ export class Image extends React.PureComponent {
|
|
|
59
59
|
static async getCachePathAsync(cacheKey) {
|
|
60
60
|
return await ExpoImageModule.getCachePathAsync(cacheKey);
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Asynchronously generates a [Blurhash](https://blurha.sh) from an image.
|
|
64
|
+
* @param url - The URL of the image to generate a blurhash from.
|
|
65
|
+
* @param numberOfComponents - The number of components to encode the blurhash with.
|
|
66
|
+
* Must be between 1 and 9. Defaults to `[4, 3]`.
|
|
67
|
+
* @platform ios
|
|
68
|
+
* @return A promise resolving to the blurhash string.
|
|
69
|
+
*/
|
|
70
|
+
static async generateBlurhashAsync(url, numberOfComponents) {
|
|
71
|
+
return await ExpoImageModule.generateBlurhashAsync(url, numberOfComponents);
|
|
72
|
+
}
|
|
62
73
|
/**
|
|
63
74
|
* Asynchronously starts playback of the view's image if it is animated.
|
|
64
75
|
* @platform android
|
package/build/Image.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Image.js","sourceRoot":"","sources":["../src/Image.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { StyleSheet } from 'react-native';\n\nimport ExpoImage, { ExpoImageModule } from './ExpoImage';\nimport { ImageProps } from './Image.types';\nimport { resolveContentFit, resolveContentPosition, resolveTransition } from './utils';\nimport { resolveSources } from './utils/resolveSources';\n\nlet loggedDefaultSourceDeprecationWarning = false;\n\nexport class Image extends React.PureComponent<ImageProps> {\n nativeViewRef;\n\n constructor(props) {\n super(props);\n this.nativeViewRef = React.createRef();\n }\n\n /**\n * Preloads images at the given URLs that can be later used in the image view.\n * Preloaded images are cached to the memory and disk by default, so make sure\n * to use `disk` (default) or `memory-disk` [cache policy](#cachepolicy).\n * @param urls - A URL string or an array of URLs of images to prefetch.\n * @param cachePolicy - The cache policy for prefetched images.\n * @return A promise resolving to `true` as soon as all images have been\n * successfully prefetched. If an image fails to be prefetched, the promise\n * will immediately resolve to `false` regardless of whether other images have\n * finished prefetching.\n */\n static async prefetch(\n urls: string | string[],\n cachePolicy: 'memory-disk' | 'memory' = 'memory-disk'\n ): Promise<boolean> {\n return ExpoImageModule.prefetch(Array.isArray(urls) ? urls : [urls], cachePolicy);\n }\n\n /**\n * Asynchronously clears all images stored in memory.\n * @platform android\n * @platform ios\n * @return A promise resolving to `true` when the operation succeeds.\n * It may resolve to `false` on Android when the activity is no longer available.\n * Resolves to `false` on Web.\n */\n static async clearMemoryCache(): Promise<boolean> {\n return await ExpoImageModule.clearMemoryCache();\n }\n\n /**\n * Asynchronously clears all images from the disk cache.\n * @platform android\n * @platform ios\n * @return A promise resolving to `true` when the operation succeeds.\n * It may resolve to `false` on Android when the activity is no longer available.\n * Resolves to `false` on Web.\n */\n static async clearDiskCache(): Promise<boolean> {\n return await ExpoImageModule.clearDiskCache();\n }\n\n /**\n * Asynchronously checks if an image exists in the disk cache and resolves to\n * the path of the cached image if it does.\n * @param cacheKey - The cache key for the requested image. Unless you have set\n * a custom cache key, this will be the source URL of the image.\n * @platform android\n * @platform ios\n * @return A promise resolving to the path of the cached image. It will resolve\n * to `null` if the image does not exist in the cache.\n */\n static async getCachePathAsync(cacheKey: string): Promise<string | null> {\n return await ExpoImageModule.getCachePathAsync(cacheKey);\n }\n\n /**\n * Asynchronously starts playback of the view's image if it is animated.\n * @platform android\n * @platform ios\n */\n async startAnimating(): Promise<void> {\n await this.nativeViewRef.current.startAnimating();\n }\n\n /**\n * Asynchronously stops the playback of the view's image if it is animated.\n * @platform android\n * @platform ios\n */\n async stopAnimating(): Promise<void> {\n await this.nativeViewRef.current.stopAnimating();\n }\n\n render() {\n const {\n style,\n source,\n placeholder,\n contentFit,\n contentPosition,\n transition,\n fadeDuration,\n resizeMode: resizeModeProp,\n defaultSource,\n loadingIndicatorSource,\n ...restProps\n } = this.props;\n\n const { resizeMode: resizeModeStyle, ...restStyle } = StyleSheet.flatten(style) || {};\n const resizeMode = resizeModeProp ?? resizeModeStyle;\n\n if ((defaultSource || loadingIndicatorSource) && !loggedDefaultSourceDeprecationWarning) {\n console.warn(\n '[expo-image]: `defaultSource` and `loadingIndicatorSource` props are deprecated, use `placeholder` instead'\n );\n loggedDefaultSourceDeprecationWarning = true;\n }\n\n return (\n <ExpoImage\n {...restProps}\n style={restStyle}\n source={resolveSources(source)}\n placeholder={resolveSources(placeholder ?? defaultSource ?? loadingIndicatorSource)}\n contentFit={resolveContentFit(contentFit, resizeMode)}\n contentPosition={resolveContentPosition(contentPosition)}\n transition={resolveTransition(transition, fadeDuration)}\n nativeViewRef={this.nativeViewRef}\n />\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Image.js","sourceRoot":"","sources":["../src/Image.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { StyleSheet } from 'react-native';\n\nimport ExpoImage, { ExpoImageModule } from './ExpoImage';\nimport { ImageProps } from './Image.types';\nimport { resolveContentFit, resolveContentPosition, resolveTransition } from './utils';\nimport { resolveSources } from './utils/resolveSources';\n\nlet loggedDefaultSourceDeprecationWarning = false;\n\nexport class Image extends React.PureComponent<ImageProps> {\n nativeViewRef;\n\n constructor(props) {\n super(props);\n this.nativeViewRef = React.createRef();\n }\n\n /**\n * Preloads images at the given URLs that can be later used in the image view.\n * Preloaded images are cached to the memory and disk by default, so make sure\n * to use `disk` (default) or `memory-disk` [cache policy](#cachepolicy).\n * @param urls - A URL string or an array of URLs of images to prefetch.\n * @param cachePolicy - The cache policy for prefetched images.\n * @return A promise resolving to `true` as soon as all images have been\n * successfully prefetched. If an image fails to be prefetched, the promise\n * will immediately resolve to `false` regardless of whether other images have\n * finished prefetching.\n */\n static async prefetch(\n urls: string | string[],\n cachePolicy: 'memory-disk' | 'memory' = 'memory-disk'\n ): Promise<boolean> {\n return ExpoImageModule.prefetch(Array.isArray(urls) ? urls : [urls], cachePolicy);\n }\n\n /**\n * Asynchronously clears all images stored in memory.\n * @platform android\n * @platform ios\n * @return A promise resolving to `true` when the operation succeeds.\n * It may resolve to `false` on Android when the activity is no longer available.\n * Resolves to `false` on Web.\n */\n static async clearMemoryCache(): Promise<boolean> {\n return await ExpoImageModule.clearMemoryCache();\n }\n\n /**\n * Asynchronously clears all images from the disk cache.\n * @platform android\n * @platform ios\n * @return A promise resolving to `true` when the operation succeeds.\n * It may resolve to `false` on Android when the activity is no longer available.\n * Resolves to `false` on Web.\n */\n static async clearDiskCache(): Promise<boolean> {\n return await ExpoImageModule.clearDiskCache();\n }\n\n /**\n * Asynchronously checks if an image exists in the disk cache and resolves to\n * the path of the cached image if it does.\n * @param cacheKey - The cache key for the requested image. Unless you have set\n * a custom cache key, this will be the source URL of the image.\n * @platform android\n * @platform ios\n * @return A promise resolving to the path of the cached image. It will resolve\n * to `null` if the image does not exist in the cache.\n */\n static async getCachePathAsync(cacheKey: string): Promise<string | null> {\n return await ExpoImageModule.getCachePathAsync(cacheKey);\n }\n\n /**\n * Asynchronously generates a [Blurhash](https://blurha.sh) from an image.\n * @param url - The URL of the image to generate a blurhash from.\n * @param numberOfComponents - The number of components to encode the blurhash with.\n * Must be between 1 and 9. Defaults to `[4, 3]`.\n * @platform ios\n * @return A promise resolving to the blurhash string.\n */\n static async generateBlurhashAsync(\n url: string,\n numberOfComponents: [number, number] | { width: number; height: number }\n ): Promise<string | null> {\n return await ExpoImageModule.generateBlurhashAsync(url, numberOfComponents);\n }\n\n /**\n * Asynchronously starts playback of the view's image if it is animated.\n * @platform android\n * @platform ios\n */\n async startAnimating(): Promise<void> {\n await this.nativeViewRef.current.startAnimating();\n }\n\n /**\n * Asynchronously stops the playback of the view's image if it is animated.\n * @platform android\n * @platform ios\n */\n async stopAnimating(): Promise<void> {\n await this.nativeViewRef.current.stopAnimating();\n }\n\n render() {\n const {\n style,\n source,\n placeholder,\n contentFit,\n contentPosition,\n transition,\n fadeDuration,\n resizeMode: resizeModeProp,\n defaultSource,\n loadingIndicatorSource,\n ...restProps\n } = this.props;\n\n const { resizeMode: resizeModeStyle, ...restStyle } = StyleSheet.flatten(style) || {};\n const resizeMode = resizeModeProp ?? resizeModeStyle;\n\n if ((defaultSource || loadingIndicatorSource) && !loggedDefaultSourceDeprecationWarning) {\n console.warn(\n '[expo-image]: `defaultSource` and `loadingIndicatorSource` props are deprecated, use `placeholder` instead'\n );\n loggedDefaultSourceDeprecationWarning = true;\n }\n\n return (\n <ExpoImage\n {...restProps}\n style={restStyle}\n source={resolveSources(source)}\n placeholder={resolveSources(placeholder ?? defaultSource ?? loadingIndicatorSource)}\n contentFit={resolveContentFit(contentFit, resizeMode)}\n contentPosition={resolveContentPosition(contentPosition)}\n transition={resolveTransition(transition, fadeDuration)}\n nativeViewRef={this.nativeViewRef}\n />\n );\n }\n}\n"]}
|
package/build/Image.types.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import ExpoImage from './ExpoImage';
|
|
|
3
3
|
export type ImageSource = {
|
|
4
4
|
/**
|
|
5
5
|
* A string representing the resource identifier for the image,
|
|
6
|
-
* which could be an
|
|
6
|
+
* which could be an HTTPS address, a local file path, or the name of a static image resource.
|
|
7
7
|
*/
|
|
8
8
|
uri?: string;
|
|
9
9
|
/**
|
|
@@ -13,24 +13,30 @@ export type ImageSource = {
|
|
|
13
13
|
headers?: Record<string, string>;
|
|
14
14
|
/**
|
|
15
15
|
* Can be specified if known at build time, in which case the value
|
|
16
|
-
* will be used to set the default `<Image/>` component dimension
|
|
16
|
+
* will be used to set the default `<Image/>` component dimension.
|
|
17
17
|
*/
|
|
18
18
|
width?: number;
|
|
19
19
|
/**
|
|
20
20
|
* Can be specified if known at build time, in which case the value
|
|
21
|
-
* will be used to set the default `<Image/>` component dimension
|
|
21
|
+
* will be used to set the default `<Image/>` component dimension.
|
|
22
22
|
*/
|
|
23
23
|
height?: number;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* A string used to generate the image [`placeholder`](#placeholder). For example,
|
|
26
|
+
* `placeholder={blurhash}`. If `uri` is provided as the value of the `source` prop,
|
|
27
|
+
* this is ignored since the `source` can only have `blurhash` or `uri`.
|
|
28
|
+
*
|
|
27
29
|
* When using the blurhash, you should also provide `width` and `height` (higher values reduce performance),
|
|
28
30
|
* otherwise their default value is `16`.
|
|
31
|
+
* For more information, see [`woltapp/blurhash`](https://github.com/woltapp/blurhash) repository.
|
|
29
32
|
*/
|
|
30
33
|
blurhash?: string;
|
|
31
34
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
35
|
+
* A string used to generate the image [`placeholder`](#placeholder). For example,
|
|
36
|
+
* `placeholder={thumbhash}`. If `uri` is provided as the value of the `source` prop,
|
|
37
|
+
* this is ignored since the `source` can only have `thumbhash` or `uri`.
|
|
38
|
+
*
|
|
39
|
+
* For more information, see [`thumbhash website`](https://evanw.github.io/thumbhash/).
|
|
34
40
|
*/
|
|
35
41
|
thumbhash?: string;
|
|
36
42
|
/**
|
|
@@ -62,6 +68,12 @@ export type ImageStyle = RNImageStyle;
|
|
|
62
68
|
* @hidden Described in the {@link ImageProps['contentFit']}
|
|
63
69
|
*/
|
|
64
70
|
export type ImageContentFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
|
|
71
|
+
/**
|
|
72
|
+
* Determines which format should be used to decode the image.
|
|
73
|
+
* It's suggestion for the platform to use the specified format, but it's not guaranteed.
|
|
74
|
+
* @hidden Described in the {@link ImageProps['decodeFormat']}
|
|
75
|
+
*/
|
|
76
|
+
export type ImageDecodeFormat = 'argb' | 'rgb';
|
|
65
77
|
/**
|
|
66
78
|
* Some props are from React Native Image that Expo Image supports (more or less) for easier migration,
|
|
67
79
|
* but all of them are deprecated and might be removed in the future.
|
|
@@ -179,6 +191,7 @@ export interface ImageProps extends ViewProps {
|
|
|
179
191
|
* Determines if an image should automatically begin playing if it is an
|
|
180
192
|
* animated image.
|
|
181
193
|
* @default true
|
|
194
|
+
* @platform android
|
|
182
195
|
* @platform ios
|
|
183
196
|
*/
|
|
184
197
|
autoplay?: boolean;
|
|
@@ -268,6 +281,18 @@ export interface ImageProps extends ViewProps {
|
|
|
268
281
|
* @default true
|
|
269
282
|
*/
|
|
270
283
|
allowDownscaling?: boolean;
|
|
284
|
+
/**
|
|
285
|
+
* The format in which the image data should be decoded.
|
|
286
|
+
* It's not guaranteed that the platform will use the specified format.
|
|
287
|
+
*
|
|
288
|
+
* - `'argb'` - The image is decoded into a 32-bit color space with alpha channel (https://developer.android.com/reference/android/graphics/Bitmap.Config#ARGB_8888).
|
|
289
|
+
*
|
|
290
|
+
* - `'rgb'` - The image is decoded into a 16-bit color space without alpha channel (https://developer.android.com/reference/android/graphics/Bitmap.Config#RGB_565).
|
|
291
|
+
*
|
|
292
|
+
* @default 'argb'
|
|
293
|
+
* @platform android
|
|
294
|
+
*/
|
|
295
|
+
decodeFormat?: ImageDecodeFormat;
|
|
271
296
|
}
|
|
272
297
|
/**
|
|
273
298
|
* It narrows down some props to types expected by the native/web side.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Image.types.d.ts","sourceRoot":"","sources":["../src/Image.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE3F,OAAO,SAAS,MAAM,aAAa,CAAC;AAEpC,MAAM,MAAM,WAAW,GAAG;IACxB;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB
|
|
1
|
+
{"version":3,"file":"Image.types.d.ts","sourceRoot":"","sources":["../src/Image.types.ts"],"names":[],"mappings":"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"}
|
package/build/Image.types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Image.types.js","sourceRoot":"","sources":["../src/Image.types.ts"],"names":[],"mappings":"","sourcesContent":["import { ImageStyle as RNImageStyle, ViewProps, StyleProp, ViewStyle } from 'react-native';\n\nimport ExpoImage from './ExpoImage';\n\nexport type ImageSource = {\n /**\n * A string representing the resource identifier for the image,\n * which could be an http address, a local file path, or the name of a static image resource.\n */\n uri?: string;\n /**\n * An object representing the HTTP headers to send along with the request for a remote image.\n * On web requires the `Access-Control-Allow-Origin` header returned by the server to include the current domain.\n */\n headers?: Record<string, string>;\n /**\n * Can be specified if known at build time, in which case the value\n * will be used to set the default `<Image/>` component dimension\n */\n width?: number;\n /**\n * Can be specified if known at build time, in which case the value\n * will be used to set the default `<Image/>` component dimension\n */\n height?: number;\n\n /**\n * The blurhash string to use to generate the image. You can read more about the blurhash\n * on [`woltapp/blurhash`](https://github.com/woltapp/blurhash) repo. Ignored when `uri` is provided.\n * When using the blurhash, you should also provide `width` and `height` (higher values reduce performance),\n * otherwise their default value is `16`.\n */\n blurhash?: string;\n\n /**\n * The thumbhash string to use to generate the image placeholder. You can read more about thumbhash\n * on the [`thumbhash website`](https://evanw.github.io/thumbhash/). Ignored when `uri` is provided.\n */\n thumbhash?: string;\n\n /**\n * The cache key used to query and store this specific image.\n * If not provided, the `uri` is used also as the cache key.\n */\n cacheKey?: string;\n /**\n * The max width of the viewport for which this source should be selected.\n * Has no effect if `source` prop is not an array or has only 1 element.\n * Has no effect if `responsivePolicy` is not set to `static`.\n * Ignored if `blurhash` or `thumbhash` is provided (image hashes are never selected if passed in an array).\n * @platform web\n */\n webMaxViewportWidth?: number;\n /**\n * Whether the image is animated (an animated GIF or WebP for example).\n * @platform android\n * @platform ios\n */\n isAnimated?: boolean;\n};\n\n/**\n * @hidden\n */\nexport type ImageStyle = RNImageStyle;\n\n/**\n * Determines how the image should be resized to fit its container.\n * @hidden Described in the {@link ImageProps['contentFit']}\n */\nexport type ImageContentFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';\n\n/**\n * Some props are from React Native Image that Expo Image supports (more or less) for easier migration,\n * but all of them are deprecated and might be removed in the future.\n */\nexport interface ImageProps extends ViewProps {\n /** @hidden */\n style?: StyleProp<RNImageStyle>;\n\n /**\n * The image source, either a remote URL, a local file resource or a number that is the result of the `require()` function.\n * When provided as an array of sources, the source that fits best into the container size and is closest to the screen scale\n * will be chosen. In this case it is important to provide `width`, `height` and `scale` properties.\n */\n source?: ImageSource | string | number | ImageSource[] | string[] | null;\n\n /**\n * An image to display while loading the proper image and no image has been displayed yet or the source is unset.\n */\n placeholder?: ImageSource | string | number | ImageSource[] | string[] | null;\n\n /**\n * Determines how the image should be resized to fit its container. This property tells the image to fill the container\n * in a variety of ways; such as \"preserve that aspect ratio\" or \"stretch up and take up as much space as possible\".\n * It mirrors the CSS [`object-fit`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) property.\n *\n * - `'cover'` - The image is sized to maintain its aspect ratio while filling the container box.\n * If the image's aspect ratio does not match the aspect ratio of its box, then the object will be clipped to fit.\n *\n * - `'contain'` - The image is scaled down or up to maintain its aspect ratio while fitting within the container box.\n *\n * - `'fill'` - The image is sized to entirely fill the container box. If necessary, the image will be stretched or squished to fit.\n *\n * - `'none'` - The image is not resized and is centered by default.\n * When specified, the exact position can be controlled with [`contentPosition`](#contentposition) prop.\n *\n * - `'scale-down'` - The image is sized as if `none` or `contain` were specified, whichever would result in a smaller concrete image size.\n *\n * @default 'cover'\n */\n contentFit?: ImageContentFit;\n\n /**\n * Determines how the placeholder should be resized to fit its container. Available resize modes are the same as for the [`contentFit`](#contentfit) prop.\n * @default 'scale-down'\n */\n placeholderContentFit?: ImageContentFit;\n\n /**\n * It is used together with [`contentFit`](#contentfit) to specify how the image should be positioned with x/y coordinates inside its own container.\n * An equivalent of the CSS [`object-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) property.\n * @default 'center'\n */\n contentPosition?: ImageContentPosition;\n\n /**\n * Describes how the image view should transition the contents when switching the image source.\\\n * If provided as a number, it is the duration in milliseconds of the `'cross-dissolve'` effect.\n */\n transition?: ImageTransition | number | null;\n\n /**\n * The radius of the blur in points, `0` means no blur effect.\n * This effect is not applied to placeholders.\n * @default 0\n */\n blurRadius?: number;\n\n /**\n * A color used to tint template images (a bitmap image where only the opacity matters).\n * The color is applied to every non-transparent pixel, causing the image’s shape to adopt that color.\n * This effect is not applied to placeholders.\n * @default null\n */\n tintColor?: string | null;\n\n /**\n * Priorities for completing loads. If more than one load is queued at a time,\n * the load with the higher priority will be started first.\n * Priorities are considered best effort, there are no guarantees about the order in which loads will start or finish.\n * @default 'normal'\n */\n priority?: 'low' | 'normal' | 'high' | null;\n\n /**\n * Determines whether to cache the image and where: on the disk, in the memory or both.\n *\n * - `'none'` - Image is not cached at all.\n *\n * - `'disk'` - Image is queried from the disk cache if exists, otherwise it's downloaded and then stored on the disk.\n *\n * - `'memory'` - Image is cached in memory. Might be useful when you render a high-resolution picture many times.\n * Memory cache may be purged very quickly to prevent high memory usage and the risk of out of memory exceptions.\n *\n * - `'memory-disk'` - Image is cached in memory, but with a fallback to the disk cache.\n *\n * @default 'disk'\n */\n cachePolicy?: 'none' | 'disk' | 'memory' | 'memory-disk' | /** @hidden */ null;\n\n /**\n * Controls the selection of the image source based on the container or viewport size on the web.\n *\n * If set to `'static'`, the browser selects the correct source based on user's viewport width. Works with static rendering.\n * Make sure to set the `'webMaxViewportWidth'` property on each source for best results.\n * For example, if an image occupies 1/3 of the screen width, set the `'webMaxViewportWidth'` to 3x the image width.\n * The source with the largest `'webMaxViewportWidth'` is used even for larger viewports.\n *\n * If set to `'initial'`, the component will select the correct source during mount based on container size. Does not work with static rendering.\n *\n * If set to `'live'`, the component will select the correct source on every resize based on container size. Does not work with static rendering.\n *\n * @default 'static'\n * @platform web\n */\n responsivePolicy?: 'live' | 'initial' | 'static';\n\n /**\n * Changing this prop resets the image view content to blank or a placeholder before loading and rendering the final image.\n * This is especially useful for any kinds of recycling views like [FlashList](https://github.com/shopify/flash-list)\n * to prevent showing the previous source before the new one fully loads.\n * @default null\n * @platform android\n * @platform ios\n */\n recyclingKey?: string | null;\n\n /**\n * Determines if an image should automatically begin playing if it is an\n * animated image.\n * @default true\n * @platform ios\n */\n autoplay?: boolean;\n\n /**\n * Called when the image starts to load.\n */\n onLoadStart?: () => void;\n\n /**\n * Called when the image load completes successfully.\n */\n onLoad?: (event: ImageLoadEventData) => void;\n\n /**\n * Called when the image is loading. Can be called multiple times before the image has finished loading.\n * The event object provides details on how many bytes were loaded so far and what's the expected total size.\n */\n onProgress?: (event: ImageProgressEventData) => void;\n\n /**\n * Called on an image fetching error.\n */\n onError?: (event: ImageErrorEventData) => void;\n\n /**\n * Called when the image load either succeeds or fails.\n */\n onLoadEnd?: () => void;\n\n // DEPRECATED\n\n /**\n * @deprecated Provides compatibility for [`defaultSource` from React Native Image](https://reactnative.dev/docs/image#defaultsource).\n * Use [`placeholder`](#placeholder) prop instead.\n */\n defaultSource?: ImageSource | null;\n\n /**\n * @deprecated Provides compatibility for [`loadingIndicatorSource` from React Native Image](https://reactnative.dev/docs/image#loadingindicatorsource).\n * Use [`placeholder`](#placeholder) prop instead.\n */\n loadingIndicatorSource?: ImageSource | null;\n\n /**\n * @deprecated Provides compatibility for [`resizeMode` from React Native Image](https://reactnative.dev/docs/image#resizemode).\n * Note that `\"repeat\"` option is not supported at all.\n * Use the more powerful [`contentFit`](#contentfit) and [`contentPosition`](#contentposition) props instead.\n */\n resizeMode?: 'cover' | 'contain' | 'stretch' | 'repeat' | 'center';\n\n /**\n * @deprecated Provides compatibility for [`fadeDuration` from React Native Image](https://reactnative.dev/docs/image#fadeduration-android).\n * Instead use [`transition`](#transition) with the provided duration.\n */\n fadeDuration?: number;\n\n /**\n * Whether this View should be focusable with a non-touch input device and receive focus with a hardware keyboard.\n * @default false\n * @platform android\n */\n focusable?: boolean;\n\n /**\n * When true, indicates that the view is an accessibility element.\n * When a view is an accessibility element, it groups its children into a single selectable component.\n *\n * On Android, the `accessible` property will be translated into the native `isScreenReaderFocusable`,\n * so it's only affecting the screen readers behaviour.\n * @default false\n * @platform android\n * @platform ios\n */\n accessible?: boolean;\n\n /**\n * The text that's read by the screen reader when the user interacts with the image. Sets the the `alt` tag on web which is used for web crawlers and link traversal.\n * @default undefined\n */\n accessibilityLabel?: string;\n\n /**\n * The text that's read by the screen reader when the user interacts with the image. Sets the the `alt` tag on web which is used for web crawlers and link traversal. Is an alias for `accessibilityLabel`.\n *\n * @alias accessibilityLabel\n * @default undefined\n */\n alt?: string;\n\n /**\n * Enables Live Text interaction with the image. Check official [Apple documentation](https://developer.apple.com/documentation/visionkit/enabling_live_text_interactions_with_images) for more details.\n * @default false\n * @platform ios 16.0+\n */\n enableLiveTextInteraction?: boolean;\n\n /**\n * Whether the image should be downscaled to match the size of the view container.\n * Turning off this functionality could negatively impact the application's performance, particularly when working with large assets.\n * However, it would result in smoother image resizing, and end-users would always have access to the highest possible asset quality.\n *\n * Downscaling is never used when the `contentFit` prop is set to `none` or `fill`.\n * @default true\n */\n allowDownscaling?: boolean;\n}\n\n/**\n * It narrows down some props to types expected by the native/web side.\n * @hidden\n */\nexport interface ImageNativeProps extends ImageProps {\n style?: RNImageStyle;\n source?: ImageSource[];\n placeholder?: ImageSource[];\n contentPosition?: ImageContentPositionObject;\n transition?: ImageTransition | null;\n autoplay?: boolean;\n nativeViewRef?: React.RefObject<ExpoImage>;\n}\n\n/**\n * A value that represents the relative position of a single axis.\n *\n * If `number`, it is a distance in points (logical pixels) from the respective edge.\\\n * If `string`, it must be a percentage value where `'100%'` is the difference in size between the container and the image along the respective axis,\n * or `'center'` which is an alias for `'50%'` that is the default value. You can read more regarding percentages on the MDN docs for\n * [`background-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-position#regarding_percentages) that describes this concept well.\n */\nexport type ImageContentPositionValue = number | string | `${number}%` | `${number}` | 'center';\n\n// eslint-disable\n// prettier-ignore\n/**\n * Specifies the position of the image inside its container. One value controls the x-axis and the second value controls the y-axis.\n *\n * Additionally, it supports stringified shorthand form that specifies the edges to which to align the image content:\\\n * `'center'`, `'top'`, `'right'`, `'bottom'`, `'left'`, `'top center'`, `'top right'`, `'top left'`, `'right center'`, `'right top'`,\n * `'right bottom'`, `'bottom center'`, `'bottom right'`, `'bottom left'`, `'left center'`, `'left top'`, `'left bottom'`.\\\n * If only one keyword is provided, then the other dimension is set to `'center'` (`'50%'`), so the image is placed in the middle of the specified edge.\\\n * As an example, `'top right'` is the same as `{ top: 0, right: 0 }` and `'bottom'` is the same as `{ bottom: 0, left: '50%' }`.\n */\nexport type ImageContentPosition =\n /**\n * An object that positions the image relatively to the top-right corner.\n */\n {\n top?: ImageContentPositionValue;\n right?: ImageContentPositionValue;\n } |\n /**\n * An object that positions the image relatively to the top-left corner.\n */\n {\n top?: ImageContentPositionValue;\n left?: ImageContentPositionValue;\n } |\n /**\n * An object that positions the image relatively to the bottom-right corner.\n */\n {\n bottom?: ImageContentPositionValue;\n right?: ImageContentPositionValue;\n } |\n /**\n * An object that positions the image relatively to the bottom-left corner.\n */\n {\n bottom?: ImageContentPositionValue;\n left?: ImageContentPositionValue;\n }\n | ImageContentPositionString;\n// eslint-enable\n\nexport interface ImageBackgroundProps extends Omit<ImageProps, 'style'> {\n /** The style of the image container */\n style?: StyleProp<ViewStyle> | undefined;\n /** Style object for the image */\n imageStyle?: StyleProp<RNImageStyle> | undefined;\n /** @hidden */\n children?: React.ReactNode | undefined;\n}\n\n/**\n * @hidden It's described as part of {@link ImageContentPosition}.\n */\nexport type ImageContentPositionString =\n | 'center'\n | 'top'\n | 'right'\n | 'bottom'\n | 'left'\n | 'top center'\n | 'top right'\n | 'top left'\n | 'right center'\n | 'right top'\n | 'right bottom'\n | 'bottom center'\n | 'bottom right'\n | 'bottom left'\n | 'left center'\n | 'left top'\n | 'left bottom';\n\ntype OnlyObject<T> = T extends object ? T : never;\n\n/**\n * @hidden It's a conditional type that matches only objects of {@link ImageContentPosition}.\n */\nexport type ImageContentPositionObject = OnlyObject<ImageContentPosition>;\n\n/**\n * An object that describes the smooth transition when switching the image source.\n */\nexport type ImageTransition = {\n /**\n * The duration of the transition in milliseconds.\n * @default 0\n */\n duration?: number;\n\n /**\n * Specifies the speed curve of the transition effect and how intermediate values are calculated.\n * @default 'ease-in-out'\n */\n timing?: 'ease-in-out' | 'ease-in' | 'ease-out' | 'linear';\n\n /**\n * An animation effect used for transition.\n * @default 'cross-dissolve'\n *\n * On Android, only `'cross-dissolve'` is supported.\n * On Web, `'curl-up'` and `'curl-down'` effects are not supported.\n */\n effect?:\n | 'cross-dissolve'\n | 'flip-from-top'\n | 'flip-from-right'\n | 'flip-from-bottom'\n | 'flip-from-left'\n | 'curl-up'\n | 'curl-down'\n | null;\n};\n\nexport type ImageLoadEventData = {\n cacheType: 'none' | 'disk' | 'memory';\n source: {\n url: string;\n width: number;\n height: number;\n mediaType: string | null;\n isAnimated?: boolean;\n };\n};\n\nexport type ImageProgressEventData = {\n loaded: number;\n total: number;\n};\n\nexport type ImageErrorEventData = {\n error: string;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"Image.types.js","sourceRoot":"","sources":["../src/Image.types.ts"],"names":[],"mappings":"","sourcesContent":["import { ImageStyle as RNImageStyle, ViewProps, StyleProp, ViewStyle } from 'react-native';\n\nimport ExpoImage from './ExpoImage';\n\nexport type ImageSource = {\n /**\n * A string representing the resource identifier for the image,\n * which could be an HTTPS address, a local file path, or the name of a static image resource.\n */\n uri?: string;\n /**\n * An object representing the HTTP headers to send along with the request for a remote image.\n * On web requires the `Access-Control-Allow-Origin` header returned by the server to include the current domain.\n */\n headers?: Record<string, string>;\n /**\n * Can be specified if known at build time, in which case the value\n * will be used to set the default `<Image/>` component dimension.\n */\n width?: number;\n /**\n * Can be specified if known at build time, in which case the value\n * will be used to set the default `<Image/>` component dimension.\n */\n height?: number;\n\n /**\n * A string used to generate the image [`placeholder`](#placeholder). For example,\n * `placeholder={blurhash}`. If `uri` is provided as the value of the `source` prop,\n * this is ignored since the `source` can only have `blurhash` or `uri`.\n *\n * When using the blurhash, you should also provide `width` and `height` (higher values reduce performance),\n * otherwise their default value is `16`.\n * For more information, see [`woltapp/blurhash`](https://github.com/woltapp/blurhash) repository.\n */\n blurhash?: string;\n\n /**\n * A string used to generate the image [`placeholder`](#placeholder). For example,\n * `placeholder={thumbhash}`. If `uri` is provided as the value of the `source` prop,\n * this is ignored since the `source` can only have `thumbhash` or `uri`.\n *\n * For more information, see [`thumbhash website`](https://evanw.github.io/thumbhash/).\n */\n thumbhash?: string;\n\n /**\n * The cache key used to query and store this specific image.\n * If not provided, the `uri` is used also as the cache key.\n */\n cacheKey?: string;\n /**\n * The max width of the viewport for which this source should be selected.\n * Has no effect if `source` prop is not an array or has only 1 element.\n * Has no effect if `responsivePolicy` is not set to `static`.\n * Ignored if `blurhash` or `thumbhash` is provided (image hashes are never selected if passed in an array).\n * @platform web\n */\n webMaxViewportWidth?: number;\n /**\n * Whether the image is animated (an animated GIF or WebP for example).\n * @platform android\n * @platform ios\n */\n isAnimated?: boolean;\n};\n\n/**\n * @hidden\n */\nexport type ImageStyle = RNImageStyle;\n\n/**\n * Determines how the image should be resized to fit its container.\n * @hidden Described in the {@link ImageProps['contentFit']}\n */\nexport type ImageContentFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';\n\n/**\n * Determines which format should be used to decode the image.\n * It's suggestion for the platform to use the specified format, but it's not guaranteed.\n * @hidden Described in the {@link ImageProps['decodeFormat']}\n */\nexport type ImageDecodeFormat = 'argb' | 'rgb';\n\n/**\n * Some props are from React Native Image that Expo Image supports (more or less) for easier migration,\n * but all of them are deprecated and might be removed in the future.\n */\nexport interface ImageProps extends ViewProps {\n /** @hidden */\n style?: StyleProp<RNImageStyle>;\n\n /**\n * The image source, either a remote URL, a local file resource or a number that is the result of the `require()` function.\n * When provided as an array of sources, the source that fits best into the container size and is closest to the screen scale\n * will be chosen. In this case it is important to provide `width`, `height` and `scale` properties.\n */\n source?: ImageSource | string | number | ImageSource[] | string[] | null;\n\n /**\n * An image to display while loading the proper image and no image has been displayed yet or the source is unset.\n */\n placeholder?: ImageSource | string | number | ImageSource[] | string[] | null;\n\n /**\n * Determines how the image should be resized to fit its container. This property tells the image to fill the container\n * in a variety of ways; such as \"preserve that aspect ratio\" or \"stretch up and take up as much space as possible\".\n * It mirrors the CSS [`object-fit`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) property.\n *\n * - `'cover'` - The image is sized to maintain its aspect ratio while filling the container box.\n * If the image's aspect ratio does not match the aspect ratio of its box, then the object will be clipped to fit.\n *\n * - `'contain'` - The image is scaled down or up to maintain its aspect ratio while fitting within the container box.\n *\n * - `'fill'` - The image is sized to entirely fill the container box. If necessary, the image will be stretched or squished to fit.\n *\n * - `'none'` - The image is not resized and is centered by default.\n * When specified, the exact position can be controlled with [`contentPosition`](#contentposition) prop.\n *\n * - `'scale-down'` - The image is sized as if `none` or `contain` were specified, whichever would result in a smaller concrete image size.\n *\n * @default 'cover'\n */\n contentFit?: ImageContentFit;\n\n /**\n * Determines how the placeholder should be resized to fit its container. Available resize modes are the same as for the [`contentFit`](#contentfit) prop.\n * @default 'scale-down'\n */\n placeholderContentFit?: ImageContentFit;\n\n /**\n * It is used together with [`contentFit`](#contentfit) to specify how the image should be positioned with x/y coordinates inside its own container.\n * An equivalent of the CSS [`object-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) property.\n * @default 'center'\n */\n contentPosition?: ImageContentPosition;\n\n /**\n * Describes how the image view should transition the contents when switching the image source.\\\n * If provided as a number, it is the duration in milliseconds of the `'cross-dissolve'` effect.\n */\n transition?: ImageTransition | number | null;\n\n /**\n * The radius of the blur in points, `0` means no blur effect.\n * This effect is not applied to placeholders.\n * @default 0\n */\n blurRadius?: number;\n\n /**\n * A color used to tint template images (a bitmap image where only the opacity matters).\n * The color is applied to every non-transparent pixel, causing the image’s shape to adopt that color.\n * This effect is not applied to placeholders.\n * @default null\n */\n tintColor?: string | null;\n\n /**\n * Priorities for completing loads. If more than one load is queued at a time,\n * the load with the higher priority will be started first.\n * Priorities are considered best effort, there are no guarantees about the order in which loads will start or finish.\n * @default 'normal'\n */\n priority?: 'low' | 'normal' | 'high' | null;\n\n /**\n * Determines whether to cache the image and where: on the disk, in the memory or both.\n *\n * - `'none'` - Image is not cached at all.\n *\n * - `'disk'` - Image is queried from the disk cache if exists, otherwise it's downloaded and then stored on the disk.\n *\n * - `'memory'` - Image is cached in memory. Might be useful when you render a high-resolution picture many times.\n * Memory cache may be purged very quickly to prevent high memory usage and the risk of out of memory exceptions.\n *\n * - `'memory-disk'` - Image is cached in memory, but with a fallback to the disk cache.\n *\n * @default 'disk'\n */\n cachePolicy?: 'none' | 'disk' | 'memory' | 'memory-disk' | /** @hidden */ null;\n\n /**\n * Controls the selection of the image source based on the container or viewport size on the web.\n *\n * If set to `'static'`, the browser selects the correct source based on user's viewport width. Works with static rendering.\n * Make sure to set the `'webMaxViewportWidth'` property on each source for best results.\n * For example, if an image occupies 1/3 of the screen width, set the `'webMaxViewportWidth'` to 3x the image width.\n * The source with the largest `'webMaxViewportWidth'` is used even for larger viewports.\n *\n * If set to `'initial'`, the component will select the correct source during mount based on container size. Does not work with static rendering.\n *\n * If set to `'live'`, the component will select the correct source on every resize based on container size. Does not work with static rendering.\n *\n * @default 'static'\n * @platform web\n */\n responsivePolicy?: 'live' | 'initial' | 'static';\n\n /**\n * Changing this prop resets the image view content to blank or a placeholder before loading and rendering the final image.\n * This is especially useful for any kinds of recycling views like [FlashList](https://github.com/shopify/flash-list)\n * to prevent showing the previous source before the new one fully loads.\n * @default null\n * @platform android\n * @platform ios\n */\n recyclingKey?: string | null;\n\n /**\n * Determines if an image should automatically begin playing if it is an\n * animated image.\n * @default true\n * @platform android\n * @platform ios\n */\n autoplay?: boolean;\n\n /**\n * Called when the image starts to load.\n */\n onLoadStart?: () => void;\n\n /**\n * Called when the image load completes successfully.\n */\n onLoad?: (event: ImageLoadEventData) => void;\n\n /**\n * Called when the image is loading. Can be called multiple times before the image has finished loading.\n * The event object provides details on how many bytes were loaded so far and what's the expected total size.\n */\n onProgress?: (event: ImageProgressEventData) => void;\n\n /**\n * Called on an image fetching error.\n */\n onError?: (event: ImageErrorEventData) => void;\n\n /**\n * Called when the image load either succeeds or fails.\n */\n onLoadEnd?: () => void;\n\n // DEPRECATED\n\n /**\n * @deprecated Provides compatibility for [`defaultSource` from React Native Image](https://reactnative.dev/docs/image#defaultsource).\n * Use [`placeholder`](#placeholder) prop instead.\n */\n defaultSource?: ImageSource | null;\n\n /**\n * @deprecated Provides compatibility for [`loadingIndicatorSource` from React Native Image](https://reactnative.dev/docs/image#loadingindicatorsource).\n * Use [`placeholder`](#placeholder) prop instead.\n */\n loadingIndicatorSource?: ImageSource | null;\n\n /**\n * @deprecated Provides compatibility for [`resizeMode` from React Native Image](https://reactnative.dev/docs/image#resizemode).\n * Note that `\"repeat\"` option is not supported at all.\n * Use the more powerful [`contentFit`](#contentfit) and [`contentPosition`](#contentposition) props instead.\n */\n resizeMode?: 'cover' | 'contain' | 'stretch' | 'repeat' | 'center';\n\n /**\n * @deprecated Provides compatibility for [`fadeDuration` from React Native Image](https://reactnative.dev/docs/image#fadeduration-android).\n * Instead use [`transition`](#transition) with the provided duration.\n */\n fadeDuration?: number;\n\n /**\n * Whether this View should be focusable with a non-touch input device and receive focus with a hardware keyboard.\n * @default false\n * @platform android\n */\n focusable?: boolean;\n\n /**\n * When true, indicates that the view is an accessibility element.\n * When a view is an accessibility element, it groups its children into a single selectable component.\n *\n * On Android, the `accessible` property will be translated into the native `isScreenReaderFocusable`,\n * so it's only affecting the screen readers behaviour.\n * @default false\n * @platform android\n * @platform ios\n */\n accessible?: boolean;\n\n /**\n * The text that's read by the screen reader when the user interacts with the image. Sets the the `alt` tag on web which is used for web crawlers and link traversal.\n * @default undefined\n */\n accessibilityLabel?: string;\n\n /**\n * The text that's read by the screen reader when the user interacts with the image. Sets the the `alt` tag on web which is used for web crawlers and link traversal. Is an alias for `accessibilityLabel`.\n *\n * @alias accessibilityLabel\n * @default undefined\n */\n alt?: string;\n\n /**\n * Enables Live Text interaction with the image. Check official [Apple documentation](https://developer.apple.com/documentation/visionkit/enabling_live_text_interactions_with_images) for more details.\n * @default false\n * @platform ios 16.0+\n */\n enableLiveTextInteraction?: boolean;\n\n /**\n * Whether the image should be downscaled to match the size of the view container.\n * Turning off this functionality could negatively impact the application's performance, particularly when working with large assets.\n * However, it would result in smoother image resizing, and end-users would always have access to the highest possible asset quality.\n *\n * Downscaling is never used when the `contentFit` prop is set to `none` or `fill`.\n * @default true\n */\n allowDownscaling?: boolean;\n\n /**\n * The format in which the image data should be decoded.\n * It's not guaranteed that the platform will use the specified format.\n *\n * - `'argb'` - The image is decoded into a 32-bit color space with alpha channel (https://developer.android.com/reference/android/graphics/Bitmap.Config#ARGB_8888).\n *\n * - `'rgb'` - The image is decoded into a 16-bit color space without alpha channel (https://developer.android.com/reference/android/graphics/Bitmap.Config#RGB_565).\n *\n * @default 'argb'\n * @platform android\n */\n decodeFormat?: ImageDecodeFormat;\n}\n\n/**\n * It narrows down some props to types expected by the native/web side.\n * @hidden\n */\nexport interface ImageNativeProps extends ImageProps {\n style?: RNImageStyle;\n source?: ImageSource[];\n placeholder?: ImageSource[];\n contentPosition?: ImageContentPositionObject;\n transition?: ImageTransition | null;\n autoplay?: boolean;\n nativeViewRef?: React.RefObject<ExpoImage>;\n}\n\n/**\n * A value that represents the relative position of a single axis.\n *\n * If `number`, it is a distance in points (logical pixels) from the respective edge.\\\n * If `string`, it must be a percentage value where `'100%'` is the difference in size between the container and the image along the respective axis,\n * or `'center'` which is an alias for `'50%'` that is the default value. You can read more regarding percentages on the MDN docs for\n * [`background-position`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-position#regarding_percentages) that describes this concept well.\n */\nexport type ImageContentPositionValue = number | string | `${number}%` | `${number}` | 'center';\n\n// eslint-disable\n// prettier-ignore\n/**\n * Specifies the position of the image inside its container. One value controls the x-axis and the second value controls the y-axis.\n *\n * Additionally, it supports stringified shorthand form that specifies the edges to which to align the image content:\\\n * `'center'`, `'top'`, `'right'`, `'bottom'`, `'left'`, `'top center'`, `'top right'`, `'top left'`, `'right center'`, `'right top'`,\n * `'right bottom'`, `'bottom center'`, `'bottom right'`, `'bottom left'`, `'left center'`, `'left top'`, `'left bottom'`.\\\n * If only one keyword is provided, then the other dimension is set to `'center'` (`'50%'`), so the image is placed in the middle of the specified edge.\\\n * As an example, `'top right'` is the same as `{ top: 0, right: 0 }` and `'bottom'` is the same as `{ bottom: 0, left: '50%' }`.\n */\nexport type ImageContentPosition =\n /**\n * An object that positions the image relatively to the top-right corner.\n */\n {\n top?: ImageContentPositionValue;\n right?: ImageContentPositionValue;\n } |\n /**\n * An object that positions the image relatively to the top-left corner.\n */\n {\n top?: ImageContentPositionValue;\n left?: ImageContentPositionValue;\n } |\n /**\n * An object that positions the image relatively to the bottom-right corner.\n */\n {\n bottom?: ImageContentPositionValue;\n right?: ImageContentPositionValue;\n } |\n /**\n * An object that positions the image relatively to the bottom-left corner.\n */\n {\n bottom?: ImageContentPositionValue;\n left?: ImageContentPositionValue;\n }\n | ImageContentPositionString;\n// eslint-enable\n\nexport interface ImageBackgroundProps extends Omit<ImageProps, 'style'> {\n /** The style of the image container */\n style?: StyleProp<ViewStyle> | undefined;\n /** Style object for the image */\n imageStyle?: StyleProp<RNImageStyle> | undefined;\n /** @hidden */\n children?: React.ReactNode | undefined;\n}\n\n/**\n * @hidden It's described as part of {@link ImageContentPosition}.\n */\nexport type ImageContentPositionString =\n | 'center'\n | 'top'\n | 'right'\n | 'bottom'\n | 'left'\n | 'top center'\n | 'top right'\n | 'top left'\n | 'right center'\n | 'right top'\n | 'right bottom'\n | 'bottom center'\n | 'bottom right'\n | 'bottom left'\n | 'left center'\n | 'left top'\n | 'left bottom';\n\ntype OnlyObject<T> = T extends object ? T : never;\n\n/**\n * @hidden It's a conditional type that matches only objects of {@link ImageContentPosition}.\n */\nexport type ImageContentPositionObject = OnlyObject<ImageContentPosition>;\n\n/**\n * An object that describes the smooth transition when switching the image source.\n */\nexport type ImageTransition = {\n /**\n * The duration of the transition in milliseconds.\n * @default 0\n */\n duration?: number;\n\n /**\n * Specifies the speed curve of the transition effect and how intermediate values are calculated.\n * @default 'ease-in-out'\n */\n timing?: 'ease-in-out' | 'ease-in' | 'ease-out' | 'linear';\n\n /**\n * An animation effect used for transition.\n * @default 'cross-dissolve'\n *\n * On Android, only `'cross-dissolve'` is supported.\n * On Web, `'curl-up'` and `'curl-down'` effects are not supported.\n */\n effect?:\n | 'cross-dissolve'\n | 'flip-from-top'\n | 'flip-from-right'\n | 'flip-from-bottom'\n | 'flip-from-left'\n | 'curl-up'\n | 'curl-down'\n | null;\n};\n\nexport type ImageLoadEventData = {\n cacheType: 'none' | 'disk' | 'memory';\n source: {\n url: string;\n width: number;\n height: number;\n mediaType: string | null;\n isAnimated?: boolean;\n };\n};\n\nexport type ImageProgressEventData = {\n loaded: number;\n total: number;\n};\n\nexport type ImageErrorEventData = {\n error: string;\n};\n"]}
|
|
@@ -9,6 +9,6 @@ type UseSourceSelectionReturn = {
|
|
|
9
9
|
containerRef: (element: HTMLDivElement) => void;
|
|
10
10
|
source: ImageSource | SrcSetSource | null;
|
|
11
11
|
};
|
|
12
|
-
export default function useSourceSelection(sources?: ImageSource[], responsivePolicy?: ImageProps['responsivePolicy'], measurementCallback?: (target: HTMLElement, size: DOMRect) => void): UseSourceSelectionReturn;
|
|
12
|
+
export default function useSourceSelection(sources?: ImageSource[], responsivePolicy?: ImageProps['responsivePolicy'], measurementCallback?: ((target: HTMLElement, size: DOMRect) => void) | null): UseSourceSelectionReturn;
|
|
13
13
|
export {};
|
|
14
14
|
//# sourceMappingURL=useSourceSelection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSourceSelection.d.ts","sourceRoot":"","sources":["../../src/web/useSourceSelection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAoCzD,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IAEd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;CAChB;AAmDD,KAAK,wBAAwB,GAAG;IAC9B,YAAY,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAChD,MAAM,EAAE,WAAW,GAAG,YAAY,GAAG,IAAI,CAAC;CAC3C,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACxC,OAAO,CAAC,EAAE,WAAW,EAAE,EACvB,gBAAgB,GAAE,UAAU,CAAC,kBAAkB,CAAY,EAC3D,mBAAmB,CAAC,
|
|
1
|
+
{"version":3,"file":"useSourceSelection.d.ts","sourceRoot":"","sources":["../../src/web/useSourceSelection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAoCzD,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IAEd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,CAAC;CAChB;AAmDD,KAAK,wBAAwB,GAAG;IAC9B,YAAY,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAChD,MAAM,EAAE,WAAW,GAAG,YAAY,GAAG,IAAI,CAAC;CAC3C,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,kBAAkB,CACxC,OAAO,CAAC,EAAE,WAAW,EAAE,EACvB,gBAAgB,GAAE,UAAU,CAAC,kBAAkB,CAAY,EAC3D,mBAAmB,GAAE,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAW,GAChF,wBAAwB,CA6C1B"}
|
|
@@ -59,7 +59,7 @@ function selectSource(sources, size, responsivePolicy) {
|
|
|
59
59
|
type: 'srcset',
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
|
-
export default function useSourceSelection(sources, responsivePolicy = 'static', measurementCallback) {
|
|
62
|
+
export default function useSourceSelection(sources, responsivePolicy = 'static', measurementCallback = null) {
|
|
63
63
|
const hasMoreThanOneSource = (sources?.length ?? 0) > 1;
|
|
64
64
|
// null - not calculated yet, DOMRect - size available
|
|
65
65
|
const [size, setSize] = useState(null);
|
|
@@ -70,7 +70,6 @@ export default function useSourceSelection(sources, responsivePolicy = 'static',
|
|
|
70
70
|
};
|
|
71
71
|
}, []);
|
|
72
72
|
const containerRef = React.useCallback((element) => {
|
|
73
|
-
// we can't short circuit here since we need to read the size for better animated transitions
|
|
74
73
|
if (!hasMoreThanOneSource && !measurementCallback) {
|
|
75
74
|
return;
|
|
76
75
|
}
|
|
@@ -88,7 +87,7 @@ export default function useSourceSelection(sources, responsivePolicy = 'static',
|
|
|
88
87
|
});
|
|
89
88
|
resizeObserver.current.observe(element);
|
|
90
89
|
}
|
|
91
|
-
}, [hasMoreThanOneSource, responsivePolicy]);
|
|
90
|
+
}, [hasMoreThanOneSource, responsivePolicy, measurementCallback]);
|
|
92
91
|
const source = selectSource(sources, size, responsivePolicy);
|
|
93
92
|
return React.useMemo(() => ({
|
|
94
93
|
containerRef,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSourceSelection.js","sourceRoot":"","sources":["../../src/web/useSourceSelection.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"useSourceSelection.js","sourceRoot":"","sources":["../../src/web/useSourceSelection.ts"],"names":[],"mappings":"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","sourcesContent":["import React, { useState, useRef } from 'react';\n\nimport { ImageProps, ImageSource } from '../Image.types';\nimport { isBlurhashString, isThumbhashString } from '../utils/resolveSources';\n\nfunction findBestSourceForSize(\n sources: ImageSource[] | undefined,\n size: DOMRect | null\n): ImageSource | null {\n if (sources?.length === 1) {\n return sources[0];\n }\n return (\n [...(sources || [])]\n // look for the smallest image that's still larger then a container\n ?.map((source) => {\n if (!size) {\n return { source, penalty: 0, covers: false };\n }\n const { width, height } =\n typeof source === 'object' ? source : { width: null, height: null };\n if (width == null || height == null) {\n return { source, penalty: 0, covers: false };\n }\n if (width < size.width || height < size.height) {\n return {\n source,\n penalty: Math.max(size.width - width, size.height - height),\n covers: false,\n };\n }\n return { source, penalty: (width - size.width) * (height - size.height), covers: true };\n })\n .sort((a, b) => a.penalty - b.penalty)\n .sort((a, b) => Number(b.covers) - Number(a.covers))[0]?.source ?? null\n );\n}\n\nexport interface SrcSetSource extends ImageSource {\n srcset: string;\n sizes: string;\n // used as key and a fallback in case srcset is not supported\n uri: string;\n type: 'srcset';\n}\n\nfunction getCSSMediaQueryForSource(source: ImageSource) {\n return `(max-width: ${source.webMaxViewportWidth ?? source.width}px) ${source.width}px`;\n}\n\nfunction selectSource(\n sources: ImageSource[] | undefined,\n size: DOMRect | null,\n responsivePolicy: ImageProps['responsivePolicy']\n): ImageSource | SrcSetSource | null {\n if (sources == null || sources.length === 0) {\n return null;\n }\n\n if (sources.length === 1) {\n return sources[0];\n }\n\n if (responsivePolicy !== 'static') {\n return findBestSourceForSize(sources, size);\n }\n const staticSupportedSources = sources\n .filter(\n (s) => s.uri && s.width != null && !isBlurhashString(s.uri) && !isThumbhashString(s.uri)\n )\n .sort(\n (a, b) => (a.webMaxViewportWidth ?? a.width ?? 0) - (b.webMaxViewportWidth ?? b.width ?? 0)\n );\n\n if (staticSupportedSources.length === 0) {\n console.warn(\n \"You've set the `static` responsivePolicy but none of the sources have the `width` properties set. Make sure you set both `width` and `webMaxViewportWidth` for best results when using static responsiveness. Falling back to the `initial` policy.\"\n );\n return findBestSourceForSize(sources, size);\n }\n\n const srcset = staticSupportedSources\n ?.map((source) => `${source.uri} ${source.width}w`)\n .join(', ');\n const sizes = `${staticSupportedSources\n ?.map(getCSSMediaQueryForSource)\n .join(', ')}, ${staticSupportedSources[staticSupportedSources.length - 1]?.width}px`;\n return {\n srcset,\n sizes,\n uri: staticSupportedSources[staticSupportedSources.length - 1]?.uri ?? '',\n type: 'srcset',\n };\n}\n\ntype UseSourceSelectionReturn = {\n containerRef: (element: HTMLDivElement) => void;\n source: ImageSource | SrcSetSource | null;\n};\n\nexport default function useSourceSelection(\n sources?: ImageSource[],\n responsivePolicy: ImageProps['responsivePolicy'] = 'static',\n measurementCallback: ((target: HTMLElement, size: DOMRect) => void) | null = null\n): UseSourceSelectionReturn {\n const hasMoreThanOneSource = (sources?.length ?? 0) > 1;\n // null - not calculated yet, DOMRect - size available\n const [size, setSize] = useState<null | DOMRect>(null);\n const resizeObserver = useRef<ResizeObserver | null>(null);\n\n React.useEffect(() => {\n return () => {\n resizeObserver.current?.disconnect();\n };\n }, []);\n\n const containerRef = React.useCallback(\n (element: HTMLDivElement) => {\n if (!hasMoreThanOneSource && !measurementCallback) {\n return;\n }\n const rect = element?.getBoundingClientRect();\n measurementCallback?.(element, rect);\n setSize(rect);\n\n if (responsivePolicy === 'live') {\n resizeObserver.current?.disconnect();\n if (!element) {\n return;\n }\n resizeObserver.current = new ResizeObserver((entries) => {\n setSize(entries[0].contentRect);\n measurementCallback?.(entries[0].target as any, entries[0].contentRect);\n });\n resizeObserver.current.observe(element);\n }\n },\n [hasMoreThanOneSource, responsivePolicy, measurementCallback]\n );\n\n const source = selectSource(sources, size, responsivePolicy);\n\n return React.useMemo(\n () => ({\n containerRef,\n source,\n }),\n [source]\n );\n}\n"]}
|
package/ios/ImageModule.swift
CHANGED
|
@@ -130,6 +130,21 @@ public final class ImageModule: Module {
|
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
AsyncFunction("generateBlurhashAsync") { (url: URL, numberOfComponents: CGSize, promise: Promise) in
|
|
134
|
+
let downloader = SDWebImageDownloader()
|
|
135
|
+
let parsedNumberOfComponents = (Int(numberOfComponents.width), Int(numberOfComponents.height))
|
|
136
|
+
downloader.downloadImage(with: url, progress: nil, completed: { image, _, _, _ in
|
|
137
|
+
DispatchQueue.global().async {
|
|
138
|
+
if let downloadedImage = image {
|
|
139
|
+
let blurhashString = blurhash(fromImage: downloadedImage, numberOfComponents: parsedNumberOfComponents)
|
|
140
|
+
promise.resolve(blurhashString)
|
|
141
|
+
} else {
|
|
142
|
+
promise.reject(BlurhashGenerationException())
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
}
|
|
147
|
+
|
|
133
148
|
AsyncFunction("clearMemoryCache") { () -> Bool in
|
|
134
149
|
SDImageCache.shared.clearMemory()
|
|
135
150
|
return true
|
package/ios/ImageUtils.swift
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
import SDWebImage
|
|
4
4
|
import ExpoModulesCore
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
An exception to throw when it its not possible to generate a blurhash for a given URL.
|
|
8
|
+
*/
|
|
9
|
+
public final class BlurhashGenerationException: Exception {
|
|
10
|
+
override public var reason: String {
|
|
11
|
+
"Unable to generate blurhash, make sure the image exists at the given URL"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
6
15
|
/**
|
|
7
16
|
Checks if the image is animated and returns an SDAnimatedImage if it does. Otherwise returns the UIImage.
|
|
8
17
|
*/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-image",
|
|
3
3
|
"title": "Expo Image",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.11.0",
|
|
5
5
|
"description": "A cross-platform, performant image component for React Native and Expo with Web support",
|
|
6
6
|
"main": "build/index.js",
|
|
7
7
|
"types": "build/index.d.ts",
|
|
@@ -35,5 +35,5 @@
|
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"expo": "*"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "ae8dd44927fbd4102993a5ae17131cf59d51d773"
|
|
39
39
|
}
|
package/src/ExpoImage.web.tsx
CHANGED
|
@@ -63,11 +63,20 @@ function onErrorAdapter(onError?: { (event: { error: string }): void }) {
|
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
// Used for
|
|
67
|
-
|
|
66
|
+
// Used for flip transitions to mimic native animations
|
|
67
|
+
function setCssVariablesForFlipTransitions(element: HTMLElement, size: DOMRect) {
|
|
68
68
|
element?.style.setProperty('--expo-image-width', `${size.width}px`);
|
|
69
69
|
element?.style.setProperty('--expo-image-height', `${size.height}px`);
|
|
70
|
-
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function isFlipTransition(transition: ImageNativeProps['transition']) {
|
|
73
|
+
return (
|
|
74
|
+
transition?.effect === 'flip-from-bottom' ||
|
|
75
|
+
transition?.effect === 'flip-from-top' ||
|
|
76
|
+
transition?.effect === 'flip-from-left' ||
|
|
77
|
+
transition?.effect === 'flip-from-right'
|
|
78
|
+
);
|
|
79
|
+
}
|
|
71
80
|
|
|
72
81
|
export default function ExpoImage({
|
|
73
82
|
source,
|
|
@@ -85,6 +94,7 @@ export default function ExpoImage({
|
|
|
85
94
|
blurRadius,
|
|
86
95
|
recyclingKey,
|
|
87
96
|
style,
|
|
97
|
+
nativeViewRef,
|
|
88
98
|
...props
|
|
89
99
|
}: ImageNativeProps) {
|
|
90
100
|
const imagePlaceholderContentFit = placeholderContentFit || 'scale-down';
|
|
@@ -94,7 +104,7 @@ export default function ExpoImage({
|
|
|
94
104
|
const { containerRef, source: selectedSource } = useSourceSelection(
|
|
95
105
|
source,
|
|
96
106
|
responsivePolicy,
|
|
97
|
-
|
|
107
|
+
isFlipTransition(transition) ? setCssVariablesForFlipTransitions : null
|
|
98
108
|
);
|
|
99
109
|
|
|
100
110
|
const initialNodeAnimationKey =
|
|
@@ -107,6 +117,7 @@ export default function ExpoImage({
|
|
|
107
117
|
(className, style) => (
|
|
108
118
|
<ImageWrapper
|
|
109
119
|
{...props}
|
|
120
|
+
ref={nativeViewRef as React.Ref<HTMLImageElement> | undefined}
|
|
110
121
|
source={placeholder?.[0]}
|
|
111
122
|
style={{
|
|
112
123
|
objectFit: imagePlaceholderContentFit,
|
|
@@ -136,6 +147,7 @@ export default function ExpoImage({
|
|
|
136
147
|
(className, style) => (
|
|
137
148
|
<ImageWrapper
|
|
138
149
|
{...props}
|
|
150
|
+
ref={nativeViewRef as React.Ref<HTMLImageElement> | undefined}
|
|
139
151
|
source={selectedSource || placeholder?.[0]}
|
|
140
152
|
events={{
|
|
141
153
|
onError: [onErrorAdapter(onError), onLoadEnd, onErrorInner],
|
package/src/Image.tsx
CHANGED
|
@@ -72,6 +72,21 @@ export class Image extends React.PureComponent<ImageProps> {
|
|
|
72
72
|
return await ExpoImageModule.getCachePathAsync(cacheKey);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Asynchronously generates a [Blurhash](https://blurha.sh) from an image.
|
|
77
|
+
* @param url - The URL of the image to generate a blurhash from.
|
|
78
|
+
* @param numberOfComponents - The number of components to encode the blurhash with.
|
|
79
|
+
* Must be between 1 and 9. Defaults to `[4, 3]`.
|
|
80
|
+
* @platform ios
|
|
81
|
+
* @return A promise resolving to the blurhash string.
|
|
82
|
+
*/
|
|
83
|
+
static async generateBlurhashAsync(
|
|
84
|
+
url: string,
|
|
85
|
+
numberOfComponents: [number, number] | { width: number; height: number }
|
|
86
|
+
): Promise<string | null> {
|
|
87
|
+
return await ExpoImageModule.generateBlurhashAsync(url, numberOfComponents);
|
|
88
|
+
}
|
|
89
|
+
|
|
75
90
|
/**
|
|
76
91
|
* Asynchronously starts playback of the view's image if it is animated.
|
|
77
92
|
* @platform android
|
package/src/Image.types.ts
CHANGED
|
@@ -5,7 +5,7 @@ import ExpoImage from './ExpoImage';
|
|
|
5
5
|
export type ImageSource = {
|
|
6
6
|
/**
|
|
7
7
|
* A string representing the resource identifier for the image,
|
|
8
|
-
* which could be an
|
|
8
|
+
* which could be an HTTPS address, a local file path, or the name of a static image resource.
|
|
9
9
|
*/
|
|
10
10
|
uri?: string;
|
|
11
11
|
/**
|
|
@@ -15,26 +15,32 @@ export type ImageSource = {
|
|
|
15
15
|
headers?: Record<string, string>;
|
|
16
16
|
/**
|
|
17
17
|
* Can be specified if known at build time, in which case the value
|
|
18
|
-
* will be used to set the default `<Image/>` component dimension
|
|
18
|
+
* will be used to set the default `<Image/>` component dimension.
|
|
19
19
|
*/
|
|
20
20
|
width?: number;
|
|
21
21
|
/**
|
|
22
22
|
* Can be specified if known at build time, in which case the value
|
|
23
|
-
* will be used to set the default `<Image/>` component dimension
|
|
23
|
+
* will be used to set the default `<Image/>` component dimension.
|
|
24
24
|
*/
|
|
25
25
|
height?: number;
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
28
|
+
* A string used to generate the image [`placeholder`](#placeholder). For example,
|
|
29
|
+
* `placeholder={blurhash}`. If `uri` is provided as the value of the `source` prop,
|
|
30
|
+
* this is ignored since the `source` can only have `blurhash` or `uri`.
|
|
31
|
+
*
|
|
30
32
|
* When using the blurhash, you should also provide `width` and `height` (higher values reduce performance),
|
|
31
33
|
* otherwise their default value is `16`.
|
|
34
|
+
* For more information, see [`woltapp/blurhash`](https://github.com/woltapp/blurhash) repository.
|
|
32
35
|
*/
|
|
33
36
|
blurhash?: string;
|
|
34
37
|
|
|
35
38
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
39
|
+
* A string used to generate the image [`placeholder`](#placeholder). For example,
|
|
40
|
+
* `placeholder={thumbhash}`. If `uri` is provided as the value of the `source` prop,
|
|
41
|
+
* this is ignored since the `source` can only have `thumbhash` or `uri`.
|
|
42
|
+
*
|
|
43
|
+
* For more information, see [`thumbhash website`](https://evanw.github.io/thumbhash/).
|
|
38
44
|
*/
|
|
39
45
|
thumbhash?: string;
|
|
40
46
|
|
|
@@ -70,6 +76,13 @@ export type ImageStyle = RNImageStyle;
|
|
|
70
76
|
*/
|
|
71
77
|
export type ImageContentFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
|
|
72
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Determines which format should be used to decode the image.
|
|
81
|
+
* It's suggestion for the platform to use the specified format, but it's not guaranteed.
|
|
82
|
+
* @hidden Described in the {@link ImageProps['decodeFormat']}
|
|
83
|
+
*/
|
|
84
|
+
export type ImageDecodeFormat = 'argb' | 'rgb';
|
|
85
|
+
|
|
73
86
|
/**
|
|
74
87
|
* Some props are from React Native Image that Expo Image supports (more or less) for easier migration,
|
|
75
88
|
* but all of them are deprecated and might be removed in the future.
|
|
@@ -200,6 +213,7 @@ export interface ImageProps extends ViewProps {
|
|
|
200
213
|
* Determines if an image should automatically begin playing if it is an
|
|
201
214
|
* animated image.
|
|
202
215
|
* @default true
|
|
216
|
+
* @platform android
|
|
203
217
|
* @platform ios
|
|
204
218
|
*/
|
|
205
219
|
autoplay?: boolean;
|
|
@@ -306,6 +320,19 @@ export interface ImageProps extends ViewProps {
|
|
|
306
320
|
* @default true
|
|
307
321
|
*/
|
|
308
322
|
allowDownscaling?: boolean;
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* The format in which the image data should be decoded.
|
|
326
|
+
* It's not guaranteed that the platform will use the specified format.
|
|
327
|
+
*
|
|
328
|
+
* - `'argb'` - The image is decoded into a 32-bit color space with alpha channel (https://developer.android.com/reference/android/graphics/Bitmap.Config#ARGB_8888).
|
|
329
|
+
*
|
|
330
|
+
* - `'rgb'` - The image is decoded into a 16-bit color space without alpha channel (https://developer.android.com/reference/android/graphics/Bitmap.Config#RGB_565).
|
|
331
|
+
*
|
|
332
|
+
* @default 'argb'
|
|
333
|
+
* @platform android
|
|
334
|
+
*/
|
|
335
|
+
decodeFormat?: ImageDecodeFormat;
|
|
309
336
|
}
|
|
310
337
|
|
|
311
338
|
/**
|
|
@@ -101,7 +101,7 @@ type UseSourceSelectionReturn = {
|
|
|
101
101
|
export default function useSourceSelection(
|
|
102
102
|
sources?: ImageSource[],
|
|
103
103
|
responsivePolicy: ImageProps['responsivePolicy'] = 'static',
|
|
104
|
-
measurementCallback
|
|
104
|
+
measurementCallback: ((target: HTMLElement, size: DOMRect) => void) | null = null
|
|
105
105
|
): UseSourceSelectionReturn {
|
|
106
106
|
const hasMoreThanOneSource = (sources?.length ?? 0) > 1;
|
|
107
107
|
// null - not calculated yet, DOMRect - size available
|
|
@@ -116,7 +116,6 @@ export default function useSourceSelection(
|
|
|
116
116
|
|
|
117
117
|
const containerRef = React.useCallback(
|
|
118
118
|
(element: HTMLDivElement) => {
|
|
119
|
-
// we can't short circuit here since we need to read the size for better animated transitions
|
|
120
119
|
if (!hasMoreThanOneSource && !measurementCallback) {
|
|
121
120
|
return;
|
|
122
121
|
}
|
|
@@ -136,7 +135,7 @@ export default function useSourceSelection(
|
|
|
136
135
|
resizeObserver.current.observe(element);
|
|
137
136
|
}
|
|
138
137
|
},
|
|
139
|
-
[hasMoreThanOneSource, responsivePolicy]
|
|
138
|
+
[hasMoreThanOneSource, responsivePolicy, measurementCallback]
|
|
140
139
|
);
|
|
141
140
|
|
|
142
141
|
const source = selectSource(sources, size, responsivePolicy);
|