react-native-nitro-image-pipeline 1.4.0 → 1.5.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/README.md +72 -5
- package/android/CMakeLists.txt +4 -0
- package/android/src/main/cpp/GaussianBlur.cpp +165 -0
- package/android/src/main/cpp/GaussianBlur.hpp +52 -0
- package/android/src/main/cpp/GaussianBlurJni.cpp +50 -0
- package/android/src/main/java/com/margelo/nitro/nitroimagepipeline/HybridNitroImagePipeline.kt +141 -74
- package/android/src/main/java/com/margelo/nitro/nitroimagepipeline/PipelineImageLoader.kt +177 -0
- package/android/src/main/java/com/margelo/nitro/nitroimagepipeline/transform/BlurTransformation.kt +36 -81
- package/android/src/main/java/com/margelo/nitro/nitroimagepipeline/transform/HardwareBitmapTransformation.kt +45 -0
- package/ios/GaussianBlur.swift +48 -9
- package/ios/HybridNitroImagePipeline.swift +63 -33
- package/ios/PipelineImageLoader.swift +195 -0
- package/ios/RoundedCornersProcessor.swift +5 -0
- package/lib/commonjs/NativePipelineImage.js +71 -0
- package/lib/commonjs/NativePipelineImage.js.map +1 -0
- package/lib/commonjs/index.js +14 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/usePipelineImageLoader.js +69 -0
- package/lib/commonjs/usePipelineImageLoader.js.map +1 -0
- package/lib/module/NativePipelineImage.js +67 -0
- package/lib/module/NativePipelineImage.js.map +1 -0
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/usePipelineImageLoader.js +65 -0
- package/lib/module/usePipelineImageLoader.js.map +1 -0
- package/lib/typescript/src/NativePipelineImage.d.ts +66 -0
- package/lib/typescript/src/NativePipelineImage.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +3 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/nitro-image-toolkit.nitro.d.ts +44 -1
- package/lib/typescript/src/specs/nitro-image-toolkit.nitro.d.ts.map +1 -1
- package/lib/typescript/src/usePipelineImageLoader.d.ts +15 -0
- package/lib/typescript/src/usePipelineImageLoader.d.ts.map +1 -0
- package/nitrogen/generated/android/c++/JHybridNitroImagePipelineSpec.cpp +13 -0
- package/nitrogen/generated/android/c++/JHybridNitroImagePipelineSpec.hpp +1 -0
- package/nitrogen/generated/android/c++/JViewOptions.hpp +77 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroimagepipeline/HybridNitroImagePipelineSpec.kt +5 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroimagepipeline/ViewOptions.kt +66 -0
- package/nitrogen/generated/ios/NitroImagePipeline-Swift-Cxx-Bridge.cpp +10 -0
- package/nitrogen/generated/ios/NitroImagePipeline-Swift-Cxx-Bridge.hpp +44 -0
- package/nitrogen/generated/ios/NitroImagePipeline-Swift-Cxx-Umbrella.hpp +8 -0
- package/nitrogen/generated/ios/c++/HybridNitroImagePipelineSpecSwift.hpp +14 -0
- package/nitrogen/generated/ios/swift/HybridNitroImagePipelineSpec.swift +1 -0
- package/nitrogen/generated/ios/swift/HybridNitroImagePipelineSpec_cxx.swift +15 -0
- package/nitrogen/generated/ios/swift/ViewOptions.swift +101 -0
- package/nitrogen/generated/shared/c++/HybridNitroImagePipelineSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridNitroImagePipelineSpec.hpp +7 -0
- package/nitrogen/generated/shared/c++/ViewOptions.hpp +104 -0
- package/package.json +4 -3
- package/src/NativePipelineImage.tsx +103 -0
- package/src/index.ts +7 -0
- package/src/specs/nitro-image-toolkit.nitro.ts +45 -1
- package/src/usePipelineImageLoader.ts +82 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
//
|
|
2
|
+
// PipelineImageLoader.swift
|
|
3
|
+
// NitroImagePipeline
|
|
4
|
+
//
|
|
5
|
+
|
|
6
|
+
import Foundation
|
|
7
|
+
import NitroImage
|
|
8
|
+
import NitroModules
|
|
9
|
+
import Nuke
|
|
10
|
+
import UIKit
|
|
11
|
+
|
|
12
|
+
/// An `ImageLoader` (react-native-nitro-image) backed by the shared pipeline.
|
|
13
|
+
///
|
|
14
|
+
/// `<NativeNitroImage image={loader} />` drives it entirely natively: the view
|
|
15
|
+
/// calls `requestImage` when it attaches to a window and `dropImage` when it
|
|
16
|
+
/// detaches. The load runs at the view's laid-out size (× screen scale) with
|
|
17
|
+
/// no JS round trips, and detaching cancels the request and releases the
|
|
18
|
+
/// bitmap — the decoded image stays in the shared memory/disk caches, so
|
|
19
|
+
/// re-attaching (list recycling) is instant.
|
|
20
|
+
///
|
|
21
|
+
/// `ViewOptions` values are in points; this class converts them to the
|
|
22
|
+
/// pixel-based `Options` of the shared request builder using the view's
|
|
23
|
+
/// display scale, so cache keys match an equivalent `loadImage` call.
|
|
24
|
+
class PipelineImageLoader: HybridImageLoaderSpec {
|
|
25
|
+
private let url: String
|
|
26
|
+
private let options: ViewOptions?
|
|
27
|
+
|
|
28
|
+
// Per-view in-flight work, keyed by the view's identity, so a loader
|
|
29
|
+
// shared between several views cancels only the right request. Confined
|
|
30
|
+
// to the main thread — every access happens inside a main-queue block.
|
|
31
|
+
private var tasks: [ObjectIdentifier: Task<Void, Never>] = [:]
|
|
32
|
+
private var pendingLayouts: [ObjectIdentifier: NSKeyValueObservation] = [:]
|
|
33
|
+
|
|
34
|
+
init(url: String, options: ViewOptions?) {
|
|
35
|
+
self.url = url
|
|
36
|
+
self.options = options
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private var pipeline: ImagePipeline { HybridNitroImagePipeline.sharedPipeline }
|
|
40
|
+
|
|
41
|
+
/// visionOS has no `UIScreen.main`; there UIKit reports 2.0 as the
|
|
42
|
+
/// display scale of trait environments.
|
|
43
|
+
private static var fallbackScale: CGFloat {
|
|
44
|
+
#if os(visionOS)
|
|
45
|
+
return 2.0
|
|
46
|
+
#else
|
|
47
|
+
return UIScreen.main.scale
|
|
48
|
+
#endif
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private static func displayScale(of view: UIView) -> CGFloat {
|
|
52
|
+
let scale = view.traitCollection.displayScale
|
|
53
|
+
// 0 means "unspecified" (view not in a hierarchy yet).
|
|
54
|
+
return scale > 0 ? scale : fallbackScale
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// The point-based `ViewOptions` as pixel-based `Options`, resolved
|
|
58
|
+
/// against `scale` and the target size in pixels.
|
|
59
|
+
private func pixelOptions(scale: CGFloat, sizePx: CGSize?) -> Options {
|
|
60
|
+
let cornerRadius = options?.cornerRadius.map { radius -> Variant_Double_CornerRadii in
|
|
61
|
+
switch radius {
|
|
62
|
+
case .first(let uniform):
|
|
63
|
+
return .first(uniform * scale)
|
|
64
|
+
case .second(let radii):
|
|
65
|
+
return .second(CornerRadii(
|
|
66
|
+
topLeft: radii.topLeft.map { $0 * scale },
|
|
67
|
+
topRight: radii.topRight.map { $0 * scale },
|
|
68
|
+
bottomLeft: radii.bottomLeft.map { $0 * scale },
|
|
69
|
+
bottomRight: radii.bottomRight.map { $0 * scale }
|
|
70
|
+
))
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return Options(
|
|
74
|
+
blur: options?.blur.map { $0 * scale },
|
|
75
|
+
cache: options?.cache,
|
|
76
|
+
cornerRadius: cornerRadius,
|
|
77
|
+
resize: sizePx.map { ResizeOptions(width: Double($0.width), height: Double($0.height)) }
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// An explicit `resize` override (pixels), when set and valid.
|
|
82
|
+
private var explicitResize: CGSize? {
|
|
83
|
+
guard let resize = options?.resize, resize.width > 0, resize.height > 0 else {
|
|
84
|
+
return nil
|
|
85
|
+
}
|
|
86
|
+
return CGSize(width: resize.width, height: resize.height)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// MARK: - ImageLoader
|
|
90
|
+
|
|
91
|
+
func loadImage() throws -> Promise<any HybridImageSpec> {
|
|
92
|
+
return Promise.async {
|
|
93
|
+
guard let imageUrl = URL(string: self.url) else {
|
|
94
|
+
throw RuntimeError.error(withMessage: "Invalid URL: \(self.url)")
|
|
95
|
+
}
|
|
96
|
+
// No view to measure here: use the explicit resize if given, and
|
|
97
|
+
// the main screen's scale for the point-based options.
|
|
98
|
+
let scale = await MainActor.run { Self.fallbackScale }
|
|
99
|
+
let request = HybridNitroImagePipeline.makeRequest(
|
|
100
|
+
url: imageUrl,
|
|
101
|
+
options: self.pixelOptions(scale: scale, sizePx: self.explicitResize)
|
|
102
|
+
)
|
|
103
|
+
let image = try await self.pipeline.image(for: request)
|
|
104
|
+
return HybridImage(uiImage: image)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
func requestImage(forView view: any HybridNitroImageViewSpec) throws {
|
|
109
|
+
guard let nativeView = view as? NativeImageView else { return }
|
|
110
|
+
let key = ObjectIdentifier(view)
|
|
111
|
+
// Always hop (asynchronously) to main: `requestImage` fires while the
|
|
112
|
+
// view is being mounted, and only after the current mounting
|
|
113
|
+
// transaction finishes is its final frame guaranteed to be set.
|
|
114
|
+
DispatchQueue.main.async {
|
|
115
|
+
self.load(into: nativeView.imageView, key: key)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
func dropImage(forView view: any HybridNitroImageViewSpec) throws {
|
|
120
|
+
guard let nativeView = view as? NativeImageView else { return }
|
|
121
|
+
let key = ObjectIdentifier(view)
|
|
122
|
+
// Same queue as `requestImage`, so rapid attach/detach sequences
|
|
123
|
+
// (list recycling) replay in call order.
|
|
124
|
+
DispatchQueue.main.async {
|
|
125
|
+
self.cancel(key: key)
|
|
126
|
+
nativeView.imageView.image = nil
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// MARK: - Main-thread loading
|
|
131
|
+
|
|
132
|
+
private func cancel(key: ObjectIdentifier) {
|
|
133
|
+
tasks[key]?.cancel()
|
|
134
|
+
tasks[key] = nil
|
|
135
|
+
// Releasing the observation invalidates it.
|
|
136
|
+
pendingLayouts[key] = nil
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private func load(into imageView: UIImageView, key: ObjectIdentifier) {
|
|
140
|
+
cancel(key: key)
|
|
141
|
+
|
|
142
|
+
if let sizePx = explicitResize {
|
|
143
|
+
start(into: imageView, key: key, sizePx: sizePx)
|
|
144
|
+
return
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
let bounds = imageView.bounds.size
|
|
148
|
+
if bounds.width > 0, bounds.height > 0 {
|
|
149
|
+
let scale = Self.displayScale(of: imageView)
|
|
150
|
+
start(into: imageView, key: key, sizePx: CGSize(
|
|
151
|
+
width: bounds.width * scale,
|
|
152
|
+
height: bounds.height * scale
|
|
153
|
+
))
|
|
154
|
+
} else {
|
|
155
|
+
// Mounted at zero size (e.g. a flex child before its container
|
|
156
|
+
// grows): wait for real bounds. Observed on the layer — CALayer
|
|
157
|
+
// properties are KVO-compliant, UIView's are not.
|
|
158
|
+
pendingLayouts[key] = imageView.layer.observe(\.bounds) { [weak self, weak imageView] layer, _ in
|
|
159
|
+
guard layer.bounds.width > 0, layer.bounds.height > 0 else { return }
|
|
160
|
+
DispatchQueue.main.async {
|
|
161
|
+
guard let self, let imageView else { return }
|
|
162
|
+
guard self.pendingLayouts[key] != nil else { return }
|
|
163
|
+
self.load(into: imageView, key: key)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
private func start(into imageView: UIImageView, key: ObjectIdentifier, sizePx: CGSize) {
|
|
170
|
+
guard let imageUrl = URL(string: url) else { return }
|
|
171
|
+
let scale = Self.displayScale(of: imageView)
|
|
172
|
+
let request = HybridNitroImagePipeline.makeRequest(
|
|
173
|
+
url: imageUrl,
|
|
174
|
+
options: pixelOptions(scale: scale, sizePx: sizePx)
|
|
175
|
+
)
|
|
176
|
+
let pipeline = self.pipeline
|
|
177
|
+
// A memory-cache hit is served synchronously. Going through
|
|
178
|
+
// `pipeline.image(for:)` would resume on Nuke's queue and then hop
|
|
179
|
+
// back to the main actor, so a recycled cell (whose image `dropImage`
|
|
180
|
+
// just cleared) would show empty for a frame or two even though the
|
|
181
|
+
// bitmap is already in memory. The subscript honours the request's
|
|
182
|
+
// `.disableMemoryCacheReads`, so `cache: 'disk'`/`'none'` still miss.
|
|
183
|
+
if !request.options.contains(.disableMemoryCacheReads), let cached = pipeline.cache[request] {
|
|
184
|
+
imageView.image = cached.image
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
// Cancelling the Task cancels Nuke's request; a finished task stays in
|
|
188
|
+
// the map (cancelling it is a no-op) until `cancel` replaces it.
|
|
189
|
+
tasks[key] = Task { @MainActor [weak imageView] in
|
|
190
|
+
guard let image = try? await pipeline.image(for: request) else { return }
|
|
191
|
+
guard !Task.isCancelled else { return }
|
|
192
|
+
imageView?.image = image
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
@@ -48,6 +48,11 @@ struct RoundedCornersProcessor: ImageProcessing {
|
|
|
48
48
|
let format = UIGraphicsImageRendererFormat()
|
|
49
49
|
format.scale = image.scale
|
|
50
50
|
format.opaque = false
|
|
51
|
+
// `.automatic` picks the extended (16-bit-per-channel) range on
|
|
52
|
+
// wide-gamut displays, which doubles the bytes of this bitmap — the
|
|
53
|
+
// one that ends up in the memory cache and on screen — for an 8-bit
|
|
54
|
+
// sRGB source that gains nothing from it.
|
|
55
|
+
format.preferredRange = .standard
|
|
51
56
|
|
|
52
57
|
let rect = CGRect(origin: .zero, size: size)
|
|
53
58
|
return UIGraphicsImageRenderer(size: size, format: format).image { context in
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.NativePipelineImage = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _reactNativeNitroImage = require("react-native-nitro-image");
|
|
9
|
+
var _resizeForStyle = require("./resizeForStyle");
|
|
10
|
+
var _usePipelineImageLoader = require("./usePipelineImageLoader");
|
|
11
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
12
|
+
/**
|
|
13
|
+
* The instance `<NativePipelineImage>` exposes through its `ref` — the
|
|
14
|
+
* underlying `NativeNitroImage` host view, with the usual native-view
|
|
15
|
+
* methods (`measure`, …).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The fully native-driven variant of `PipelineImage`: after the first render
|
|
20
|
+
* there is **zero JS work per image**. The native view starts the request
|
|
21
|
+
* when it attaches to the window — at its own laid-out size, so nothing
|
|
22
|
+
* waits for an `onLayout` round trip — and cancels it (releasing the bitmap)
|
|
23
|
+
* when it detaches, which makes off-screen list cells free. Loads go through
|
|
24
|
+
* the same pipeline and caches as `useImage`/`preLoadImage`.
|
|
25
|
+
*
|
|
26
|
+
* Compared to `PipelineImage`:
|
|
27
|
+
* - No `onLoad`/`onError` callbacks — the loaded `Image` never crosses into
|
|
28
|
+
* JS. Use `PipelineImage` (or `useImage`) when you need them.
|
|
29
|
+
* - The bitmap is loaded once at the size the view first has; if the view is
|
|
30
|
+
* resized later, the bitmap scales with it instead of reloading.
|
|
31
|
+
* @example
|
|
32
|
+
* ```tsx
|
|
33
|
+
* <NativePipelineImage
|
|
34
|
+
* url="https://example.com/photo.jpg"
|
|
35
|
+
* style={{ width: 300, height: 200, borderRadius: 24 }}
|
|
36
|
+
* blur={4}
|
|
37
|
+
* />
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
const NativePipelineImage = exports.NativePipelineImage = /*#__PURE__*/(0, _react.forwardRef)(function NativePipelineImage({
|
|
41
|
+
url,
|
|
42
|
+
blur,
|
|
43
|
+
cornerRadius,
|
|
44
|
+
cache,
|
|
45
|
+
resize,
|
|
46
|
+
style,
|
|
47
|
+
...viewProps
|
|
48
|
+
}, ref) {
|
|
49
|
+
// Same precedence as PipelineImage: an explicit prop wins over style.
|
|
50
|
+
const effectiveCornerRadius = cornerRadius ?? (0, _resizeForStyle.cornerRadiusForStyle)(style);
|
|
51
|
+
const loader = (0, _usePipelineImageLoader.usePipelineImageLoader)(url, {
|
|
52
|
+
blur,
|
|
53
|
+
cornerRadius: effectiveCornerRadius,
|
|
54
|
+
cache,
|
|
55
|
+
resize
|
|
56
|
+
});
|
|
57
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeNitroImage.NativeNitroImage
|
|
58
|
+
// Before the spread so a caller-provided recyclingKey wins.
|
|
59
|
+
, {
|
|
60
|
+
recyclingKey: url,
|
|
61
|
+
...viewProps,
|
|
62
|
+
ref: ref,
|
|
63
|
+
style: style,
|
|
64
|
+
image: loader
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Reanimated and DevTools read the display name; the forwardRef wrapper
|
|
69
|
+
// would otherwise report as anonymous.
|
|
70
|
+
NativePipelineImage.displayName = 'NativePipelineImage';
|
|
71
|
+
//# sourceMappingURL=NativePipelineImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","require","_reactNativeNitroImage","_resizeForStyle","_usePipelineImageLoader","_jsxRuntime","NativePipelineImage","exports","forwardRef","url","blur","cornerRadius","cache","resize","style","viewProps","ref","effectiveCornerRadius","cornerRadiusForStyle","loader","usePipelineImageLoader","jsx","NativeNitroImage","recyclingKey","image","displayName"],"sourceRoot":"../../src","sources":["NativePipelineImage.tsx"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEA,IAAAC,sBAAA,GAAAD,OAAA;AAEA,IAAAE,eAAA,GAAAF,OAAA;AAMA,IAAAG,uBAAA,GAAAH,OAAA;AAAkE,IAAAI,WAAA,GAAAJ,OAAA;AAKlE;AACA;AACA;AACA;AACA;;AA+BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMK,mBAAmB,GAAAC,OAAA,CAAAD,mBAAA,gBAAG,IAAAE,iBAAU,EAG3C,SAASF,mBAAmBA,CAC5B;EAAEG,GAAG;EAAEC,IAAI;EAAEC,YAAY;EAAEC,KAAK;EAAEC,MAAM;EAAEC,KAAK;EAAE,GAAGC;AAAU,CAAC,EAC/DC,GAAG,EACH;EACA;EACA,MAAMC,qBAAqB,GAAGN,YAAY,IAAI,IAAAO,oCAAoB,EAACJ,KAAK,CAAC;EACzE,MAAMK,MAAM,GAAG,IAAAC,8CAAsB,EAACX,GAAG,EAAE;IACzCC,IAAI;IACJC,YAAY,EAAEM,qBAAqB;IACnCL,KAAK;IACLC;EACF,CAAC,CAAC;EAEF,oBACE,IAAAR,WAAA,CAAAgB,GAAA,EAACnB,sBAAA,CAAAoB;EACC;EAAA;IACAC,YAAY,EAAEd,GAAI;IAAA,GACdM,SAAS;IACbC,GAAG,EAAEA,GAAI;IACTF,KAAK,EAAEA,KAAM;IACbU,KAAK,EAAEL;EAAO,CACf,CAAC;AAEN,CAAC,CAAC;;AAEF;AACA;AACAb,mBAAmB,CAACmB,WAAW,GAAG,qBAAqB","ignoreList":[]}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "NativePipelineImage", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _NativePipelineImage.NativePipelineImage;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
6
12
|
Object.defineProperty(exports, "NitroImagePipeline", {
|
|
7
13
|
enumerable: true,
|
|
8
14
|
get: function () {
|
|
@@ -39,8 +45,16 @@ Object.defineProperty(exports, "useImage", {
|
|
|
39
45
|
return _useImage.useImage;
|
|
40
46
|
}
|
|
41
47
|
});
|
|
48
|
+
Object.defineProperty(exports, "usePipelineImageLoader", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () {
|
|
51
|
+
return _usePipelineImageLoader.usePipelineImageLoader;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
var _NativePipelineImage = require("./NativePipelineImage");
|
|
42
55
|
var _NitroImagePipeline = require("./NitroImagePipeline");
|
|
43
56
|
var _PipelineImage = require("./PipelineImage");
|
|
44
57
|
var _resizeForStyle = require("./resizeForStyle");
|
|
45
58
|
var _useImage = require("./useImage");
|
|
59
|
+
var _usePipelineImageLoader = require("./usePipelineImageLoader");
|
|
46
60
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["_NativePipelineImage","require","_NitroImagePipeline","_PipelineImage","_resizeForStyle","_useImage","_usePipelineImageLoader"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,oBAAA,GAAAC,OAAA;AAKA,IAAAC,mBAAA,GAAAD,OAAA;AACA,IAAAE,cAAA,GAAAF,OAAA;AAKA,IAAAG,eAAA,GAAAH,OAAA;AAYA,IAAAI,SAAA,GAAAJ,OAAA;AACA,IAAAK,uBAAA,GAAAL,OAAA","ignoreList":[]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.usePipelineImageLoader = usePipelineImageLoader;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
var _NitroImagePipeline = require("./NitroImagePipeline");
|
|
9
|
+
/**
|
|
10
|
+
* Creates (and memoizes) an {@linkcode ImageLoader} for `url` to pass to
|
|
11
|
+
* `<NativeNitroImage image={...} />`. The view drives it entirely natively:
|
|
12
|
+
* the request starts when the view attaches — at the view's laid-out size,
|
|
13
|
+
* with no JS round trips — and is cancelled when it detaches. See
|
|
14
|
+
* {@linkcode NitroImagePipeline.createImageLoader}.
|
|
15
|
+
*
|
|
16
|
+
* `blur`/`cornerRadius` are in **points** (unlike `useImage`, where they are
|
|
17
|
+
* bitmap pixels); the screen scale is applied natively. Inline object
|
|
18
|
+
* literals are fine — options are compared by value, not identity.
|
|
19
|
+
*/
|
|
20
|
+
function usePipelineImageLoader(url, options) {
|
|
21
|
+
// Split the options into primitives (like useImage does) so an inline
|
|
22
|
+
// literal — a new identity every render — doesn't recreate the loader;
|
|
23
|
+
// recreating it would re-trigger the native load.
|
|
24
|
+
const blur = options?.blur;
|
|
25
|
+
const cache = options?.cache;
|
|
26
|
+
const cornerRadius = options?.cornerRadius;
|
|
27
|
+
const isUniformRadius = typeof cornerRadius === 'number';
|
|
28
|
+
const uniformRadius = isUniformRadius ? cornerRadius : 0;
|
|
29
|
+
const hasCornerObject = !isUniformRadius && cornerRadius !== undefined;
|
|
30
|
+
const {
|
|
31
|
+
topLeft = 0,
|
|
32
|
+
topRight = 0,
|
|
33
|
+
bottomLeft = 0,
|
|
34
|
+
bottomRight = 0
|
|
35
|
+
} = isUniformRadius || cornerRadius === undefined ? {} : cornerRadius;
|
|
36
|
+
const resizeWidth = options?.resize?.width;
|
|
37
|
+
const resizeHeight = options?.resize?.height;
|
|
38
|
+
return (0, _react.useMemo)(() => {
|
|
39
|
+
const cornerRadiusOption = isUniformRadius ? uniformRadius : hasCornerObject ? {
|
|
40
|
+
topLeft,
|
|
41
|
+
topRight,
|
|
42
|
+
bottomLeft,
|
|
43
|
+
bottomRight
|
|
44
|
+
} : undefined;
|
|
45
|
+
const stableOptions = {
|
|
46
|
+
blur,
|
|
47
|
+
cache,
|
|
48
|
+
cornerRadius: cornerRadiusOption,
|
|
49
|
+
resize: resizeWidth !== undefined && resizeHeight !== undefined ? {
|
|
50
|
+
width: resizeWidth,
|
|
51
|
+
height: resizeHeight
|
|
52
|
+
} : undefined
|
|
53
|
+
};
|
|
54
|
+
const loader = _NitroImagePipeline.NitroImagePipeline.createImageLoader(url, stableOptions);
|
|
55
|
+
// `NativeNitroImage` needs a way to tell two loader instances apart when
|
|
56
|
+
// diffing its `image` prop; tag the loader with what it will load (the
|
|
57
|
+
// same convention react-native-nitro-image's own loaders use).
|
|
58
|
+
Object.defineProperty(loader, '__source', {
|
|
59
|
+
enumerable: true,
|
|
60
|
+
configurable: true,
|
|
61
|
+
value: {
|
|
62
|
+
url,
|
|
63
|
+
options: stableOptions
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
return loader;
|
|
67
|
+
}, [url, blur, cache, isUniformRadius, uniformRadius, hasCornerObject, topLeft, topRight, bottomLeft, bottomRight, resizeWidth, resizeHeight]);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=usePipelineImageLoader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","require","_NitroImagePipeline","usePipelineImageLoader","url","options","blur","cache","cornerRadius","isUniformRadius","uniformRadius","hasCornerObject","undefined","topLeft","topRight","bottomLeft","bottomRight","resizeWidth","resize","width","resizeHeight","height","useMemo","cornerRadiusOption","stableOptions","loader","NitroImagePipeline","createImageLoader","Object","defineProperty","enumerable","configurable","value"],"sourceRoot":"../../src","sources":["usePipelineImageLoader.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAGA,IAAAC,mBAAA,GAAAD,OAAA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASE,sBAAsBA,CACpCC,GAAW,EACXC,OAAqB,EACR;EACb;EACA;EACA;EACA,MAAMC,IAAI,GAAGD,OAAO,EAAEC,IAAI;EAC1B,MAAMC,KAAK,GAAGF,OAAO,EAAEE,KAAK;EAC5B,MAAMC,YAAY,GAAGH,OAAO,EAAEG,YAAY;EAC1C,MAAMC,eAAe,GAAG,OAAOD,YAAY,KAAK,QAAQ;EACxD,MAAME,aAAa,GAAGD,eAAe,GAAGD,YAAY,GAAG,CAAC;EACxD,MAAMG,eAAe,GAAG,CAACF,eAAe,IAAID,YAAY,KAAKI,SAAS;EACtE,MAAM;IACJC,OAAO,GAAG,CAAC;IACXC,QAAQ,GAAG,CAAC;IACZC,UAAU,GAAG,CAAC;IACdC,WAAW,GAAG;EAChB,CAAC,GAAGP,eAAe,IAAID,YAAY,KAAKI,SAAS,GAAG,CAAC,CAAC,GAAGJ,YAAY;EACrE,MAAMS,WAAW,GAAGZ,OAAO,EAAEa,MAAM,EAAEC,KAAK;EAC1C,MAAMC,YAAY,GAAGf,OAAO,EAAEa,MAAM,EAAEG,MAAM;EAE5C,OAAO,IAAAC,cAAO,EAAC,MAAM;IACnB,MAAMC,kBAAoD,GAAGd,eAAe,GACxEC,aAAa,GACbC,eAAe,GACb;MAAEE,OAAO;MAAEC,QAAQ;MAAEC,UAAU;MAAEC;IAAY,CAAC,GAC9CJ,SAAS;IACf,MAAMY,aAA0B,GAAG;MACjClB,IAAI;MACJC,KAAK;MACLC,YAAY,EAAEe,kBAAkB;MAChCL,MAAM,EACJD,WAAW,KAAKL,SAAS,IAAIQ,YAAY,KAAKR,SAAS,GACnD;QAAEO,KAAK,EAAEF,WAAW;QAAEI,MAAM,EAAED;MAAa,CAAC,GAC5CR;IACR,CAAC;IACD,MAAMa,MAAM,GAAGC,sCAAkB,CAACC,iBAAiB,CAACvB,GAAG,EAAEoB,aAAa,CAAC;IACvE;IACA;IACA;IACAI,MAAM,CAACC,cAAc,CAACJ,MAAM,EAAE,UAAU,EAAE;MACxCK,UAAU,EAAE,IAAI;MAChBC,YAAY,EAAE,IAAI;MAClBC,KAAK,EAAE;QAAE5B,GAAG;QAAEC,OAAO,EAAEmB;MAAc;IACvC,CAAC,CAAC;IACF,OAAOC,MAAM;EACf,CAAC,EAAE,CACDrB,GAAG,EACHE,IAAI,EACJC,KAAK,EACLE,eAAe,EACfC,aAAa,EACbC,eAAe,EACfE,OAAO,EACPC,QAAQ,EACRC,UAAU,EACVC,WAAW,EACXC,WAAW,EACXG,YAAY,CACb,CAAC;AACJ","ignoreList":[]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { NativeNitroImage } from 'react-native-nitro-image';
|
|
5
|
+
import { cornerRadiusForStyle } from './resizeForStyle';
|
|
6
|
+
import { usePipelineImageLoader } from './usePipelineImageLoader';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The instance `<NativePipelineImage>` exposes through its `ref` — the
|
|
10
|
+
* underlying `NativeNitroImage` host view, with the usual native-view
|
|
11
|
+
* methods (`measure`, …).
|
|
12
|
+
*/
|
|
13
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
+
/**
|
|
15
|
+
* The fully native-driven variant of `PipelineImage`: after the first render
|
|
16
|
+
* there is **zero JS work per image**. The native view starts the request
|
|
17
|
+
* when it attaches to the window — at its own laid-out size, so nothing
|
|
18
|
+
* waits for an `onLayout` round trip — and cancels it (releasing the bitmap)
|
|
19
|
+
* when it detaches, which makes off-screen list cells free. Loads go through
|
|
20
|
+
* the same pipeline and caches as `useImage`/`preLoadImage`.
|
|
21
|
+
*
|
|
22
|
+
* Compared to `PipelineImage`:
|
|
23
|
+
* - No `onLoad`/`onError` callbacks — the loaded `Image` never crosses into
|
|
24
|
+
* JS. Use `PipelineImage` (or `useImage`) when you need them.
|
|
25
|
+
* - The bitmap is loaded once at the size the view first has; if the view is
|
|
26
|
+
* resized later, the bitmap scales with it instead of reloading.
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* <NativePipelineImage
|
|
30
|
+
* url="https://example.com/photo.jpg"
|
|
31
|
+
* style={{ width: 300, height: 200, borderRadius: 24 }}
|
|
32
|
+
* blur={4}
|
|
33
|
+
* />
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export const NativePipelineImage = /*#__PURE__*/forwardRef(function NativePipelineImage({
|
|
37
|
+
url,
|
|
38
|
+
blur,
|
|
39
|
+
cornerRadius,
|
|
40
|
+
cache,
|
|
41
|
+
resize,
|
|
42
|
+
style,
|
|
43
|
+
...viewProps
|
|
44
|
+
}, ref) {
|
|
45
|
+
// Same precedence as PipelineImage: an explicit prop wins over style.
|
|
46
|
+
const effectiveCornerRadius = cornerRadius ?? cornerRadiusForStyle(style);
|
|
47
|
+
const loader = usePipelineImageLoader(url, {
|
|
48
|
+
blur,
|
|
49
|
+
cornerRadius: effectiveCornerRadius,
|
|
50
|
+
cache,
|
|
51
|
+
resize
|
|
52
|
+
});
|
|
53
|
+
return /*#__PURE__*/_jsx(NativeNitroImage
|
|
54
|
+
// Before the spread so a caller-provided recyclingKey wins.
|
|
55
|
+
, {
|
|
56
|
+
recyclingKey: url,
|
|
57
|
+
...viewProps,
|
|
58
|
+
ref: ref,
|
|
59
|
+
style: style,
|
|
60
|
+
image: loader
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Reanimated and DevTools read the display name; the forwardRef wrapper
|
|
65
|
+
// would otherwise report as anonymous.
|
|
66
|
+
NativePipelineImage.displayName = 'NativePipelineImage';
|
|
67
|
+
//# sourceMappingURL=NativePipelineImage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["forwardRef","NativeNitroImage","cornerRadiusForStyle","usePipelineImageLoader","jsx","_jsx","NativePipelineImage","url","blur","cornerRadius","cache","resize","style","viewProps","ref","effectiveCornerRadius","loader","recyclingKey","image","displayName"],"sourceRoot":"../../src","sources":["NativePipelineImage.tsx"],"mappings":";;AAAA,SAA4BA,UAAU,QAAQ,OAAO;AAErD,SAASC,gBAAgB,QAAQ,0BAA0B;AAE3D,SAASC,oBAAoB,QAAQ,kBAAkB;AAMvD,SAASC,sBAAsB,QAAQ,0BAA0B;;AAKjE;AACA;AACA;AACA;AACA;AAJA,SAAAC,GAAA,IAAAC,IAAA;AAmCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,mBAAmB,gBAAGN,UAAU,CAG3C,SAASM,mBAAmBA,CAC5B;EAAEC,GAAG;EAAEC,IAAI;EAAEC,YAAY;EAAEC,KAAK;EAAEC,MAAM;EAAEC,KAAK;EAAE,GAAGC;AAAU,CAAC,EAC/DC,GAAG,EACH;EACA;EACA,MAAMC,qBAAqB,GAAGN,YAAY,IAAIP,oBAAoB,CAACU,KAAK,CAAC;EACzE,MAAMI,MAAM,GAAGb,sBAAsB,CAACI,GAAG,EAAE;IACzCC,IAAI;IACJC,YAAY,EAAEM,qBAAqB;IACnCL,KAAK;IACLC;EACF,CAAC,CAAC;EAEF,oBACEN,IAAA,CAACJ;EACC;EAAA;IACAgB,YAAY,EAAEV,GAAI;IAAA,GACdM,SAAS;IACbC,GAAG,EAAEA,GAAI;IACTF,KAAK,EAAEA,KAAM;IACbM,KAAK,EAAEF;EAAO,CACf,CAAC;AAEN,CAAC,CAAC;;AAEF;AACA;AACAV,mBAAmB,CAACa,WAAW,GAAG,qBAAqB","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
export { NativePipelineImage } from './NativePipelineImage';
|
|
3
4
|
export { NitroImagePipeline } from './NitroImagePipeline';
|
|
4
5
|
export { PipelineImage } from './PipelineImage';
|
|
5
6
|
export { cornerRadiusForStyle, resizeForLayout, resizeForStyle } from './resizeForStyle';
|
|
6
7
|
export { useImage } from './useImage';
|
|
8
|
+
export { usePipelineImageLoader } from './usePipelineImageLoader';
|
|
7
9
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NitroImagePipeline","PipelineImage","cornerRadiusForStyle","resizeForLayout","resizeForStyle","useImage"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,
|
|
1
|
+
{"version":3,"names":["NativePipelineImage","NitroImagePipeline","PipelineImage","cornerRadiusForStyle","resizeForLayout","resizeForStyle","useImage","usePipelineImageLoader"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SACEA,mBAAmB,QAGd,uBAAuB;AAC9B,SAASC,kBAAkB,QAAQ,sBAAsB;AACzD,SACEC,aAAa,QAGR,iBAAiB;AACxB,SACEC,oBAAoB,EACpBC,eAAe,EACfC,cAAc,QACT,kBAAkB;AAQzB,SAASC,QAAQ,QAAQ,YAAY;AACrC,SAASC,sBAAsB,QAAQ,0BAA0B","ignoreList":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { NitroImagePipeline } from './NitroImagePipeline';
|
|
5
|
+
/**
|
|
6
|
+
* Creates (and memoizes) an {@linkcode ImageLoader} for `url` to pass to
|
|
7
|
+
* `<NativeNitroImage image={...} />`. The view drives it entirely natively:
|
|
8
|
+
* the request starts when the view attaches — at the view's laid-out size,
|
|
9
|
+
* with no JS round trips — and is cancelled when it detaches. See
|
|
10
|
+
* {@linkcode NitroImagePipeline.createImageLoader}.
|
|
11
|
+
*
|
|
12
|
+
* `blur`/`cornerRadius` are in **points** (unlike `useImage`, where they are
|
|
13
|
+
* bitmap pixels); the screen scale is applied natively. Inline object
|
|
14
|
+
* literals are fine — options are compared by value, not identity.
|
|
15
|
+
*/
|
|
16
|
+
export function usePipelineImageLoader(url, options) {
|
|
17
|
+
// Split the options into primitives (like useImage does) so an inline
|
|
18
|
+
// literal — a new identity every render — doesn't recreate the loader;
|
|
19
|
+
// recreating it would re-trigger the native load.
|
|
20
|
+
const blur = options?.blur;
|
|
21
|
+
const cache = options?.cache;
|
|
22
|
+
const cornerRadius = options?.cornerRadius;
|
|
23
|
+
const isUniformRadius = typeof cornerRadius === 'number';
|
|
24
|
+
const uniformRadius = isUniformRadius ? cornerRadius : 0;
|
|
25
|
+
const hasCornerObject = !isUniformRadius && cornerRadius !== undefined;
|
|
26
|
+
const {
|
|
27
|
+
topLeft = 0,
|
|
28
|
+
topRight = 0,
|
|
29
|
+
bottomLeft = 0,
|
|
30
|
+
bottomRight = 0
|
|
31
|
+
} = isUniformRadius || cornerRadius === undefined ? {} : cornerRadius;
|
|
32
|
+
const resizeWidth = options?.resize?.width;
|
|
33
|
+
const resizeHeight = options?.resize?.height;
|
|
34
|
+
return useMemo(() => {
|
|
35
|
+
const cornerRadiusOption = isUniformRadius ? uniformRadius : hasCornerObject ? {
|
|
36
|
+
topLeft,
|
|
37
|
+
topRight,
|
|
38
|
+
bottomLeft,
|
|
39
|
+
bottomRight
|
|
40
|
+
} : undefined;
|
|
41
|
+
const stableOptions = {
|
|
42
|
+
blur,
|
|
43
|
+
cache,
|
|
44
|
+
cornerRadius: cornerRadiusOption,
|
|
45
|
+
resize: resizeWidth !== undefined && resizeHeight !== undefined ? {
|
|
46
|
+
width: resizeWidth,
|
|
47
|
+
height: resizeHeight
|
|
48
|
+
} : undefined
|
|
49
|
+
};
|
|
50
|
+
const loader = NitroImagePipeline.createImageLoader(url, stableOptions);
|
|
51
|
+
// `NativeNitroImage` needs a way to tell two loader instances apart when
|
|
52
|
+
// diffing its `image` prop; tag the loader with what it will load (the
|
|
53
|
+
// same convention react-native-nitro-image's own loaders use).
|
|
54
|
+
Object.defineProperty(loader, '__source', {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
configurable: true,
|
|
57
|
+
value: {
|
|
58
|
+
url,
|
|
59
|
+
options: stableOptions
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return loader;
|
|
63
|
+
}, [url, blur, cache, isUniformRadius, uniformRadius, hasCornerObject, topLeft, topRight, bottomLeft, bottomRight, resizeWidth, resizeHeight]);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=usePipelineImageLoader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useMemo","NitroImagePipeline","usePipelineImageLoader","url","options","blur","cache","cornerRadius","isUniformRadius","uniformRadius","hasCornerObject","undefined","topLeft","topRight","bottomLeft","bottomRight","resizeWidth","resize","width","resizeHeight","height","cornerRadiusOption","stableOptions","loader","createImageLoader","Object","defineProperty","enumerable","configurable","value"],"sourceRoot":"../../src","sources":["usePipelineImageLoader.ts"],"mappings":";;AAAA,SAASA,OAAO,QAAQ,OAAO;AAG/B,SAASC,kBAAkB,QAAQ,sBAAsB;AAMzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,sBAAsBA,CACpCC,GAAW,EACXC,OAAqB,EACR;EACb;EACA;EACA;EACA,MAAMC,IAAI,GAAGD,OAAO,EAAEC,IAAI;EAC1B,MAAMC,KAAK,GAAGF,OAAO,EAAEE,KAAK;EAC5B,MAAMC,YAAY,GAAGH,OAAO,EAAEG,YAAY;EAC1C,MAAMC,eAAe,GAAG,OAAOD,YAAY,KAAK,QAAQ;EACxD,MAAME,aAAa,GAAGD,eAAe,GAAGD,YAAY,GAAG,CAAC;EACxD,MAAMG,eAAe,GAAG,CAACF,eAAe,IAAID,YAAY,KAAKI,SAAS;EACtE,MAAM;IACJC,OAAO,GAAG,CAAC;IACXC,QAAQ,GAAG,CAAC;IACZC,UAAU,GAAG,CAAC;IACdC,WAAW,GAAG;EAChB,CAAC,GAAGP,eAAe,IAAID,YAAY,KAAKI,SAAS,GAAG,CAAC,CAAC,GAAGJ,YAAY;EACrE,MAAMS,WAAW,GAAGZ,OAAO,EAAEa,MAAM,EAAEC,KAAK;EAC1C,MAAMC,YAAY,GAAGf,OAAO,EAAEa,MAAM,EAAEG,MAAM;EAE5C,OAAOpB,OAAO,CAAC,MAAM;IACnB,MAAMqB,kBAAoD,GAAGb,eAAe,GACxEC,aAAa,GACbC,eAAe,GACb;MAAEE,OAAO;MAAEC,QAAQ;MAAEC,UAAU;MAAEC;IAAY,CAAC,GAC9CJ,SAAS;IACf,MAAMW,aAA0B,GAAG;MACjCjB,IAAI;MACJC,KAAK;MACLC,YAAY,EAAEc,kBAAkB;MAChCJ,MAAM,EACJD,WAAW,KAAKL,SAAS,IAAIQ,YAAY,KAAKR,SAAS,GACnD;QAAEO,KAAK,EAAEF,WAAW;QAAEI,MAAM,EAAED;MAAa,CAAC,GAC5CR;IACR,CAAC;IACD,MAAMY,MAAM,GAAGtB,kBAAkB,CAACuB,iBAAiB,CAACrB,GAAG,EAAEmB,aAAa,CAAC;IACvE;IACA;IACA;IACAG,MAAM,CAACC,cAAc,CAACH,MAAM,EAAE,UAAU,EAAE;MACxCI,UAAU,EAAE,IAAI;MAChBC,YAAY,EAAE,IAAI;MAClBC,KAAK,EAAE;QAAE1B,GAAG;QAAEC,OAAO,EAAEkB;MAAc;IACvC,CAAC,CAAC;IACF,OAAOC,MAAM;EACf,CAAC,EAAE,CACDpB,GAAG,EACHE,IAAI,EACJC,KAAK,EACLE,eAAe,EACfC,aAAa,EACbC,eAAe,EACfE,OAAO,EACPC,QAAQ,EACRC,UAAU,EACVC,WAAW,EACXC,WAAW,EACXG,YAAY,CACb,CAAC;AACJ","ignoreList":[]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type ComponentRef } from 'react';
|
|
2
|
+
import type { HostComponent } from 'react-native';
|
|
3
|
+
import { NativeNitroImage } from 'react-native-nitro-image';
|
|
4
|
+
import type { CacheOption, CornerRadii, ResizeOptions } from './specs/nitro-image-toolkit.nitro';
|
|
5
|
+
type ReactProps<T> = T extends HostComponent<infer P> ? P : never;
|
|
6
|
+
type NativeImageProps = ReactProps<typeof NativeNitroImage>;
|
|
7
|
+
/**
|
|
8
|
+
* The instance `<NativePipelineImage>` exposes through its `ref` — the
|
|
9
|
+
* underlying `NativeNitroImage` host view, with the usual native-view
|
|
10
|
+
* methods (`measure`, …).
|
|
11
|
+
*/
|
|
12
|
+
export type NativePipelineImageRef = ComponentRef<typeof NativeNitroImage>;
|
|
13
|
+
export interface NativePipelineImageProps extends Omit<NativeImageProps, 'image'> {
|
|
14
|
+
/** URL of the image to load through the pipeline. */
|
|
15
|
+
url: string;
|
|
16
|
+
/**
|
|
17
|
+
* Gaussian blur sigma in **points** (density-independent), like
|
|
18
|
+
* `PipelineImage`. Applied natively with the screen scale.
|
|
19
|
+
* @default 0
|
|
20
|
+
*/
|
|
21
|
+
blur?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Corner radius in **points** — a single number or per-corner radii.
|
|
24
|
+
* When omitted, it's derived from `style`'s `borderRadius`-family
|
|
25
|
+
* properties instead — set this prop to override that.
|
|
26
|
+
* @default undefined (derived from `style`, or square corners if unset there)
|
|
27
|
+
*/
|
|
28
|
+
cornerRadius?: number | CornerRadii;
|
|
29
|
+
cache?: CacheOption;
|
|
30
|
+
/**
|
|
31
|
+
* Target bitmap size in **pixels**, overriding the size the native side
|
|
32
|
+
* measures from the view. Rarely needed.
|
|
33
|
+
* @default undefined (measure the view natively)
|
|
34
|
+
*/
|
|
35
|
+
resize?: ResizeOptions;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The fully native-driven variant of `PipelineImage`: after the first render
|
|
39
|
+
* there is **zero JS work per image**. The native view starts the request
|
|
40
|
+
* when it attaches to the window — at its own laid-out size, so nothing
|
|
41
|
+
* waits for an `onLayout` round trip — and cancels it (releasing the bitmap)
|
|
42
|
+
* when it detaches, which makes off-screen list cells free. Loads go through
|
|
43
|
+
* the same pipeline and caches as `useImage`/`preLoadImage`.
|
|
44
|
+
*
|
|
45
|
+
* Compared to `PipelineImage`:
|
|
46
|
+
* - No `onLoad`/`onError` callbacks — the loaded `Image` never crosses into
|
|
47
|
+
* JS. Use `PipelineImage` (or `useImage`) when you need them.
|
|
48
|
+
* - The bitmap is loaded once at the size the view first has; if the view is
|
|
49
|
+
* resized later, the bitmap scales with it instead of reloading.
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* <NativePipelineImage
|
|
53
|
+
* url="https://example.com/photo.jpg"
|
|
54
|
+
* style={{ width: 300, height: 200, borderRadius: 24 }}
|
|
55
|
+
* blur={4}
|
|
56
|
+
* />
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare const NativePipelineImage: import("react").ForwardRefExoticComponent<NativePipelineImageProps & import("react").RefAttributes<import("react").Component<{
|
|
60
|
+
hybridRef?: import("react-native-nitro-modules").NitroViewWrappedCallback<((ref: import("react-native-nitro-modules").HybridView<import("react-native-nitro-image/lib/typescript/specs/ImageView.nitro").NativeNitroImageViewProps, import("react-native-nitro-image/lib/typescript/specs/ImageView.nitro").NativeNitroImageViewMethods>) => void) | undefined> | undefined;
|
|
61
|
+
image?: import("react-native-nitro-image").Image | import("react-native-nitro-image").ImageLoader;
|
|
62
|
+
resizeMode?: import("react-native-nitro-image/lib/typescript/specs/ImageView.nitro").ResizeMode;
|
|
63
|
+
recyclingKey?: string;
|
|
64
|
+
} & import("react-native").ViewProps, {}, any> & import("react-native").ReactNativeElement>>;
|
|
65
|
+
export {};
|
|
66
|
+
//# sourceMappingURL=NativePipelineImage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativePipelineImage.d.ts","sourceRoot":"","sources":["../../../src/NativePipelineImage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAc,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG5D,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,aAAa,EACd,MAAM,mCAAmC,CAAC;AAG3C,KAAK,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;AAClE,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE5D;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAAG,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE3E,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CACpD,gBAAgB,EAChB,OAAO,CACR;IACC,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACpC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,mBAAmB;;;;;4FA0B9B,CAAC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
export { NativePipelineImage, type NativePipelineImageProps, type NativePipelineImageRef, } from './NativePipelineImage';
|
|
1
2
|
export { NitroImagePipeline } from './NitroImagePipeline';
|
|
2
3
|
export { PipelineImage, type PipelineImageProps, type PipelineImageRef, } from './PipelineImage';
|
|
3
4
|
export { cornerRadiusForStyle, resizeForLayout, resizeForStyle, } from './resizeForStyle';
|
|
4
|
-
export type { CacheOption, CornerRadii, Options, ResizeOptions, } from './specs/nitro-image-toolkit.nitro';
|
|
5
|
+
export type { CacheOption, CornerRadii, Options, ResizeOptions, ViewOptions, } from './specs/nitro-image-toolkit.nitro';
|
|
5
6
|
export { useImage } from './useImage';
|
|
7
|
+
export { usePipelineImageLoader } from './usePipelineImageLoader';
|
|
6
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,WAAW,EACX,WAAW,EACX,OAAO,EACP,aAAa,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,GAC5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,WAAW,EACX,WAAW,EACX,OAAO,EACP,aAAa,EACb,WAAW,GACZ,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC"}
|