react-native-nitro-image-pipeline 1.2.1 → 1.3.1

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 CHANGED
@@ -71,6 +71,80 @@ so a style that already rounds the view rounds the bitmap too, with no separate
71
71
  other prop (`resizeMode`, `recyclingKey`, `testID`, …) is passed straight through to
72
72
  `NativeNitroImage`.
73
73
 
74
+ ### Animating with `react-native-reanimated`
75
+
76
+ `<PipelineImage>` forwards its `ref` to the underlying `NativeNitroImage` host view, so it can be
77
+ passed straight to `Animated.createAnimatedComponent` — from
78
+ [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/) or React Native's
79
+ built-in `Animated`:
80
+
81
+ ```tsx
82
+ import Animated, { FadeIn, useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';
83
+ import { PipelineImage } from 'react-native-nitro-image-pipeline';
84
+
85
+ const AnimatedPipelineImage = Animated.createAnimatedComponent(PipelineImage);
86
+
87
+ function Photo({ url }: { url: string }) {
88
+ const pressed = useSharedValue(false);
89
+ const animatedStyle = useAnimatedStyle(() => ({
90
+ transform: [{ scale: withSpring(pressed.value ? 1.1 : 1) }],
91
+ }));
92
+
93
+ return (
94
+ <AnimatedPipelineImage
95
+ url={url}
96
+ entering={FadeIn}
97
+ style={[styles.photo, animatedStyle]}
98
+ onTouchStart={() => (pressed.value = true)}
99
+ onTouchEnd={() => (pressed.value = false)}
100
+ />
101
+ );
102
+ }
103
+
104
+ const styles = StyleSheet.create({ photo: { width: 300, height: 200, borderRadius: 12 } });
105
+ ```
106
+
107
+ Layout animations (`entering`/`exiting`) work as on any animated component, and wrapping a plain
108
+ `<PipelineImage>` in an `Animated.View` is always an option if you'd rather not create one.
109
+
110
+ Because the pipeline bakes its processing into the bitmap at load time, the props fall into two
111
+ groups — view-layer properties that animate freely, and bitmap properties that don't:
112
+
113
+ - **`transform` and `opacity`** — the ideal case: they run entirely on the UI thread and never
114
+ touch the bitmap. Prefer a `scale` transform over animating `width`/`height`.
115
+ - **`width`/`height`** — the animation itself works (Reanimated drives the native view directly),
116
+ but the bitmap doesn't follow it. With numeric dimensions in `style` (including an animated
117
+ style's initial values) the bitmap is decoded once at that size and stretched by the view while
118
+ it animates; with flex/percent sizing the size comes from `onLayout`, which fires repeatedly
119
+ during the animation and requests a new variant each time. Animate a `scale` transform instead
120
+ and let the layout settle where it will.
121
+ - **`borderRadius`** — by default the component bakes `style`'s `borderRadius` into the bitmap;
122
+ an animated radius updates only the view layer, so the baked rounding wins and stays stale. To
123
+ animate rounding, opt out of baking with `cornerRadius={0}` and round at the view layer instead:
124
+ `overflow: 'hidden'` plus the animated `borderRadius`.
125
+ - **`blur`** — not animatable. It's a load-time bitmap operation behind an async native call, not
126
+ a view property, so a changing `blur` re-runs the pipeline per value — far too slow to drive
127
+ per-frame. To animate blurriness, render the sharp and blurred variants as two stacked
128
+ `<PipelineImage>`s and cross-fade the blurred one's `opacity` (both share the URL cache, so the
129
+ second variant loads from the same fetched source):
130
+
131
+ ```tsx
132
+ function BlurFade({ url, blurred }: { url: string; blurred: boolean }) {
133
+ const blurOpacity = useAnimatedStyle(() => ({
134
+ opacity: withTiming(blurred ? 1 : 0),
135
+ }));
136
+
137
+ return (
138
+ <View style={styles.photo}>
139
+ <PipelineImage url={url} style={StyleSheet.absoluteFill} />
140
+ <Animated.View style={[StyleSheet.absoluteFill, blurOpacity]}>
141
+ <PipelineImage url={url} blur={12} style={StyleSheet.absoluteFill} />
142
+ </Animated.View>
143
+ </View>
144
+ );
145
+ }
146
+ ```
147
+
74
148
  ### `useImage` hook
75
149
 
76
150
  The simplest way to load an image in a component:
@@ -164,6 +238,7 @@ Loads an image from a URL and returns a `Promise<Image>`.
164
238
  | `onLoad` | `(image: Image) => void` | — | Called when the image finishes loading |
165
239
  | `onError` | `(error: Error) => void` | — | Called if loading fails |
166
240
  | `onLayout` | `(event: LayoutChangeEvent) => void` | — | Standard `View` layout callback; also drives the deferred resize for non-numeric sizes |
241
+ | `ref` | `Ref<PipelineImageRef>` | — | Forwarded to the underlying `NativeNitroImage` host view — gives access to native-view methods (`measure`, …) and makes the component work with `Animated.createAnimatedComponent` (see [Animating](#animating-with-react-native-reanimated)) |
167
242
  | `…NativeNitroImage props` | — | — | Everything else (`resizeMode`, `recyclingKey`, `testID`, …) is passed through to `NativeNitroImage` |
168
243
 
169
244
  ### `resizeForStyle(style)` / `resizeForLayout(width, height)`
@@ -3,13 +3,19 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.PipelineImage = PipelineImage;
6
+ exports.PipelineImage = void 0;
7
7
  var _react = require("react");
8
8
  var _reactNative = require("react-native");
9
9
  var _reactNativeNitroImage = require("react-native-nitro-image");
10
10
  var _resizeForStyle = require("./resizeForStyle");
11
11
  var _useImage = require("./useImage");
12
12
  var _jsxRuntime = require("react/jsx-runtime");
13
+ /**
14
+ * The instance `<PipelineImage>` exposes through its `ref` — the underlying
15
+ * `NativeNitroImage` host view, with the usual native-view methods
16
+ * (`measure`, …).
17
+ */
18
+
13
19
  function sameSize(a, b) {
14
20
  return a?.width === b?.width && a?.height === b?.height;
15
21
  }
@@ -37,6 +43,10 @@ function scaleRadius(cornerRadius, scale) {
37
43
  * without flashing. Without an explicit `cornerRadius` prop, `style`'s
38
44
  * `borderRadius`-family properties are baked into the bitmap instead — no
39
45
  * separate view-layer rounding needed.
46
+ *
47
+ * The `ref` is forwarded to the underlying `NativeNitroImage` host view, so
48
+ * the component works with `Animated.createAnimatedComponent` (Reanimated or
49
+ * React Native's built-in `Animated`).
40
50
  * @example
41
51
  * ```tsx
42
52
  * <PipelineImage
@@ -46,7 +56,7 @@ function scaleRadius(cornerRadius, scale) {
46
56
  * />
47
57
  * ```
48
58
  */
49
- function PipelineImage({
59
+ const PipelineImage = exports.PipelineImage = /*#__PURE__*/(0, _react.forwardRef)(function PipelineImage({
50
60
  url,
51
61
  blur = 0,
52
62
  cornerRadius,
@@ -56,7 +66,7 @@ function PipelineImage({
56
66
  style,
57
67
  onLayout,
58
68
  ...viewProps
59
- }) {
69
+ }, ref) {
60
70
  const scale = _reactNative.PixelRatio.get();
61
71
  const styleSize = (0, _resizeForStyle.resizeForStyle)(style);
62
72
  const [layoutSize, setLayoutSize] = (0, _react.useState)(undefined);
@@ -103,9 +113,14 @@ function PipelineImage({
103
113
  };
104
114
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeNitroImage.NativeNitroImage, {
105
115
  ...viewProps,
116
+ ref: ref,
106
117
  style: style,
107
118
  onLayout: handleLayout,
108
119
  image: image
109
120
  });
110
- }
121
+ });
122
+
123
+ // Reanimated and DevTools read the display name; the forwardRef wrapper
124
+ // would otherwise report as anonymous.
125
+ PipelineImage.displayName = 'PipelineImage';
111
126
  //# sourceMappingURL=PipelineImage.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","_reactNative","_reactNativeNitroImage","_resizeForStyle","_useImage","_jsxRuntime","sameSize","a","b","width","height","scaleRadius","cornerRadius","scale","topLeft","topRight","bottomLeft","bottomRight","PipelineImage","url","blur","cache","onLoad","onError","style","onLayout","viewProps","PixelRatio","get","styleSize","resizeForStyle","layoutSize","setLayoutSize","useState","undefined","resize","effectiveCornerRadius","cornerRadiusForStyle","image","error","useImage","enabled","onLoadRef","useRef","onErrorRef","useEffect","current","handleLayout","event","nativeEvent","layout","next","resizeForLayout","prev","jsx","NativeNitroImage"],"sourceRoot":"../../src","sources":["PipelineImage.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","_reactNative","_reactNativeNitroImage","_resizeForStyle","_useImage","_jsxRuntime","sameSize","a","b","width","height","scaleRadius","cornerRadius","scale","topLeft","topRight","bottomLeft","bottomRight","PipelineImage","exports","forwardRef","url","blur","cache","onLoad","onError","style","onLayout","viewProps","ref","PixelRatio","get","styleSize","resizeForStyle","layoutSize","setLayoutSize","useState","undefined","resize","effectiveCornerRadius","cornerRadiusForStyle","image","error","useImage","enabled","onLoadRef","useRef","onErrorRef","useEffect","current","handleLayout","event","nativeEvent","layout","next","resizeForLayout","prev","jsx","NativeNitroImage","displayName"],"sourceRoot":"../../src","sources":["PipelineImage.tsx"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["_NitroImagePipeline","require","_PipelineImage","_resizeForStyle","_useImage"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,mBAAA,GAAAC,OAAA;AACA,IAAAC,cAAA,GAAAD,OAAA;AACA,IAAAE,eAAA,GAAAF,OAAA;AAWA,IAAAG,SAAA,GAAAH,OAAA","ignoreList":[]}
1
+ {"version":3,"names":["_NitroImagePipeline","require","_PipelineImage","_resizeForStyle","_useImage"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,mBAAA,GAAAC,OAAA;AACA,IAAAC,cAAA,GAAAD,OAAA;AAKA,IAAAE,eAAA,GAAAF,OAAA;AAWA,IAAAG,SAAA,GAAAH,OAAA","ignoreList":[]}
@@ -1,10 +1,16 @@
1
1
  "use strict";
2
2
 
3
- import { useEffect, useRef, useState } from 'react';
3
+ import { forwardRef, useEffect, useRef, useState } from 'react';
4
4
  import { PixelRatio } from 'react-native';
5
5
  import { NativeNitroImage } from 'react-native-nitro-image';
6
6
  import { cornerRadiusForStyle, resizeForLayout, resizeForStyle } from './resizeForStyle';
7
7
  import { useImage } from './useImage';
8
+
9
+ /**
10
+ * The instance `<PipelineImage>` exposes through its `ref` — the underlying
11
+ * `NativeNitroImage` host view, with the usual native-view methods
12
+ * (`measure`, …).
13
+ */
8
14
  import { jsx as _jsx } from "react/jsx-runtime";
9
15
  function sameSize(a, b) {
10
16
  return a?.width === b?.width && a?.height === b?.height;
@@ -33,6 +39,10 @@ function scaleRadius(cornerRadius, scale) {
33
39
  * without flashing. Without an explicit `cornerRadius` prop, `style`'s
34
40
  * `borderRadius`-family properties are baked into the bitmap instead — no
35
41
  * separate view-layer rounding needed.
42
+ *
43
+ * The `ref` is forwarded to the underlying `NativeNitroImage` host view, so
44
+ * the component works with `Animated.createAnimatedComponent` (Reanimated or
45
+ * React Native's built-in `Animated`).
36
46
  * @example
37
47
  * ```tsx
38
48
  * <PipelineImage
@@ -42,7 +52,7 @@ function scaleRadius(cornerRadius, scale) {
42
52
  * />
43
53
  * ```
44
54
  */
45
- export function PipelineImage({
55
+ export const PipelineImage = /*#__PURE__*/forwardRef(function PipelineImage({
46
56
  url,
47
57
  blur = 0,
48
58
  cornerRadius,
@@ -52,7 +62,7 @@ export function PipelineImage({
52
62
  style,
53
63
  onLayout,
54
64
  ...viewProps
55
- }) {
65
+ }, ref) {
56
66
  const scale = PixelRatio.get();
57
67
  const styleSize = resizeForStyle(style);
58
68
  const [layoutSize, setLayoutSize] = useState(undefined);
@@ -99,9 +109,14 @@ export function PipelineImage({
99
109
  };
100
110
  return /*#__PURE__*/_jsx(NativeNitroImage, {
101
111
  ...viewProps,
112
+ ref: ref,
102
113
  style: style,
103
114
  onLayout: handleLayout,
104
115
  image: image
105
116
  });
106
- }
117
+ });
118
+
119
+ // Reanimated and DevTools read the display name; the forwardRef wrapper
120
+ // would otherwise report as anonymous.
121
+ PipelineImage.displayName = 'PipelineImage';
107
122
  //# sourceMappingURL=PipelineImage.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["useEffect","useRef","useState","PixelRatio","NativeNitroImage","cornerRadiusForStyle","resizeForLayout","resizeForStyle","useImage","jsx","_jsx","sameSize","a","b","width","height","scaleRadius","cornerRadius","scale","topLeft","topRight","bottomLeft","bottomRight","PipelineImage","url","blur","cache","onLoad","onError","style","onLayout","viewProps","get","styleSize","layoutSize","setLayoutSize","undefined","resize","effectiveCornerRadius","image","error","enabled","onLoadRef","onErrorRef","current","handleLayout","event","nativeEvent","layout","next","prev"],"sourceRoot":"../../src","sources":["PipelineImage.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["forwardRef","useEffect","useRef","useState","PixelRatio","NativeNitroImage","cornerRadiusForStyle","resizeForLayout","resizeForStyle","useImage","jsx","_jsx","sameSize","a","b","width","height","scaleRadius","cornerRadius","scale","topLeft","topRight","bottomLeft","bottomRight","PipelineImage","url","blur","cache","onLoad","onError","style","onLayout","viewProps","ref","get","styleSize","layoutSize","setLayoutSize","undefined","resize","effectiveCornerRadius","image","error","enabled","onLoadRef","onErrorRef","current","handleLayout","event","nativeEvent","layout","next","prev","displayName"],"sourceRoot":"../../src","sources":["PipelineImage.tsx"],"mappings":"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","ignoreList":[]}
@@ -1 +1 @@
1
- {"version":3,"names":["NitroImagePipeline","PipelineImage","cornerRadiusForStyle","resizeForLayout","resizeForStyle","useImage"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SAASA,kBAAkB,QAAQ,sBAAsB;AACzD,SAASC,aAAa,QAAiC,iBAAiB;AACxE,SACEC,oBAAoB,EACpBC,eAAe,EACfC,cAAc,QACT,kBAAkB;AAOzB,SAASC,QAAQ,QAAQ,YAAY","ignoreList":[]}
1
+ {"version":3,"names":["NitroImagePipeline","PipelineImage","cornerRadiusForStyle","resizeForLayout","resizeForStyle","useImage"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;AAAA,SAASA,kBAAkB,QAAQ,sBAAsB;AACzD,SACEC,aAAa,QAGR,iBAAiB;AACxB,SACEC,oBAAoB,EACpBC,eAAe,EACfC,cAAc,QACT,kBAAkB;AAOzB,SAASC,QAAQ,QAAQ,YAAY","ignoreList":[]}
@@ -1,8 +1,15 @@
1
+ import { type ComponentRef } from 'react';
1
2
  import { type HostComponent } from 'react-native';
2
3
  import { type Image, NativeNitroImage } from 'react-native-nitro-image';
3
4
  import type { CacheOption, CornerRadii } from './specs/nitro-image-toolkit.nitro';
4
5
  type ReactProps<T> = T extends HostComponent<infer P> ? P : never;
5
6
  type NativeImageProps = ReactProps<typeof NativeNitroImage>;
7
+ /**
8
+ * The instance `<PipelineImage>` exposes through its `ref` — the underlying
9
+ * `NativeNitroImage` host view, with the usual native-view methods
10
+ * (`measure`, …).
11
+ */
12
+ export type PipelineImageRef = ComponentRef<typeof NativeNitroImage>;
6
13
  export interface PipelineImageProps extends Omit<NativeImageProps, 'image'> {
7
14
  /** URL of the image to load through the pipeline. */
8
15
  url: string;
@@ -43,6 +50,10 @@ export interface PipelineImageProps extends Omit<NativeImageProps, 'image'> {
43
50
  * without flashing. Without an explicit `cornerRadius` prop, `style`'s
44
51
  * `borderRadius`-family properties are baked into the bitmap instead — no
45
52
  * separate view-layer rounding needed.
53
+ *
54
+ * The `ref` is forwarded to the underlying `NativeNitroImage` host view, so
55
+ * the component works with `Animated.createAnimatedComponent` (Reanimated or
56
+ * React Native's built-in `Animated`).
46
57
  * @example
47
58
  * ```tsx
48
59
  * <PipelineImage
@@ -52,6 +63,11 @@ export interface PipelineImageProps extends Omit<NativeImageProps, 'image'> {
52
63
  * />
53
64
  * ```
54
65
  */
55
- export declare function PipelineImage({ url, blur, cornerRadius, cache, onLoad, onError, style, onLayout, ...viewProps }: PipelineImageProps): import("react").JSX.Element;
66
+ export declare const PipelineImage: import("react").ForwardRefExoticComponent<PipelineImageProps & import("react").RefAttributes<import("react").Component<{
67
+ 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;
68
+ image?: Image | import("react-native-nitro-image").ImageLoader;
69
+ resizeMode?: import("react-native-nitro-image/lib/typescript/specs/ImageView.nitro").ResizeMode;
70
+ recyclingKey?: string;
71
+ } & import("react-native").ViewProps, {}, any> & import("react-native").ReactNativeElement>>;
56
72
  export {};
57
73
  //# sourceMappingURL=PipelineImage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PipelineImage.d.ts","sourceRoot":"","sources":["../../../src/PipelineImage.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,aAAa,EAGnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAOxE,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EAEZ,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,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACzE,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACpC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAChC,iCAAiC;IACjC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAqBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,EAC5B,GAAG,EACH,IAAQ,EACR,YAAY,EACZ,KAAK,EACL,MAAM,EACN,OAAO,EACP,KAAK,EACL,QAAQ,EACR,GAAG,SAAS,EACb,EAAE,kBAAkB,+BAqDpB"}
1
+ {"version":3,"file":"PipelineImage.d.ts","sourceRoot":"","sources":["../../../src/PipelineImage.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EAKlB,MAAM,OAAO,CAAC;AACf,OAAO,EACL,KAAK,aAAa,EAGnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAOxE,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EAEZ,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,gBAAgB,GAAG,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAErE,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACzE,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACpC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAChC,iCAAiC;IACjC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAqBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,aAAa;;;;;4FAqEzB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  export { NitroImagePipeline } from './NitroImagePipeline';
2
- export { PipelineImage, type PipelineImageProps } from './PipelineImage';
2
+ export { PipelineImage, type PipelineImageProps, type PipelineImageRef, } from './PipelineImage';
3
3
  export { cornerRadiusForStyle, resizeForLayout, resizeForStyle, } from './resizeForStyle';
4
4
  export type { CacheOption, CornerRadii, Options, ResizeOptions, } from './specs/nitro-image-toolkit.nitro';
5
5
  export { useImage } from './useImage';
@@ -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,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,WAAW,EACX,WAAW,EACX,OAAO,EACP,aAAa,GACd,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
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,GACd,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-image-pipeline",
3
- "version": "1.2.1",
3
+ "version": "1.3.1",
4
4
  "description": "High-performance image loading, caching, and processing for React Native, built with Nitro Modules",
5
5
  "main": "./lib/commonjs/index.js",
6
6
  "module": "./lib/module/index.js",
@@ -86,7 +86,8 @@
86
86
  "react-native-nitro-image": "0.15.1"
87
87
  },
88
88
  "overrides": {
89
- "lodash-es": "4.17.21"
89
+ "lodash-es": "4.17.21",
90
+ "typescript": "$typescript"
90
91
  },
91
92
  "react-native-builder-bob": {
92
93
  "source": "src",
@@ -1,4 +1,10 @@
1
- import { useEffect, useRef, useState } from 'react';
1
+ import {
2
+ type ComponentRef,
3
+ forwardRef,
4
+ useEffect,
5
+ useRef,
6
+ useState,
7
+ } from 'react';
2
8
  import {
3
9
  type HostComponent,
4
10
  type LayoutChangeEvent,
@@ -21,6 +27,13 @@ import { useImage } from './useImage';
21
27
  type ReactProps<T> = T extends HostComponent<infer P> ? P : never;
22
28
  type NativeImageProps = ReactProps<typeof NativeNitroImage>;
23
29
 
30
+ /**
31
+ * The instance `<PipelineImage>` exposes through its `ref` — the underlying
32
+ * `NativeNitroImage` host view, with the usual native-view methods
33
+ * (`measure`, …).
34
+ */
35
+ export type PipelineImageRef = ComponentRef<typeof NativeNitroImage>;
36
+
24
37
  export interface PipelineImageProps extends Omit<NativeImageProps, 'image'> {
25
38
  /** URL of the image to load through the pipeline. */
26
39
  url: string;
@@ -81,6 +94,10 @@ function scaleRadius(
81
94
  * without flashing. Without an explicit `cornerRadius` prop, `style`'s
82
95
  * `borderRadius`-family properties are baked into the bitmap instead — no
83
96
  * separate view-layer rounding needed.
97
+ *
98
+ * The `ref` is forwarded to the underlying `NativeNitroImage` host view, so
99
+ * the component works with `Animated.createAnimatedComponent` (Reanimated or
100
+ * React Native's built-in `Animated`).
84
101
  * @example
85
102
  * ```tsx
86
103
  * <PipelineImage
@@ -90,67 +107,77 @@ function scaleRadius(
90
107
  * />
91
108
  * ```
92
109
  */
93
- export function PipelineImage({
94
- url,
95
- blur = 0,
96
- cornerRadius,
97
- cache,
98
- onLoad,
99
- onError,
100
- style,
101
- onLayout,
102
- ...viewProps
103
- }: PipelineImageProps) {
104
- const scale = PixelRatio.get();
105
- const styleSize = resizeForStyle(style);
106
- const [layoutSize, setLayoutSize] = useState<ResizeOptions | undefined>(
107
- undefined,
108
- );
109
- // A numeric style is what the caller declared, so it wins and starts the
110
- // request a frame earlier; the measured layout is the fallback.
111
- const resize = styleSize ?? layoutSize;
112
- // Same precedence: an explicit prop wins over what style implies.
113
- const effectiveCornerRadius =
114
- cornerRadius ?? cornerRadiusForStyle(style) ?? 0;
110
+ export const PipelineImage = forwardRef<PipelineImageRef, PipelineImageProps>(
111
+ function PipelineImage(
112
+ {
113
+ url,
114
+ blur = 0,
115
+ cornerRadius,
116
+ cache,
117
+ onLoad,
118
+ onError,
119
+ style,
120
+ onLayout,
121
+ ...viewProps
122
+ },
123
+ ref,
124
+ ) {
125
+ const scale = PixelRatio.get();
126
+ const styleSize = resizeForStyle(style);
127
+ const [layoutSize, setLayoutSize] = useState<ResizeOptions | undefined>(
128
+ undefined,
129
+ );
130
+ // A numeric style is what the caller declared, so it wins and starts the
131
+ // request a frame earlier; the measured layout is the fallback.
132
+ const resize = styleSize ?? layoutSize;
133
+ // Same precedence: an explicit prop wins over what style implies.
134
+ const effectiveCornerRadius =
135
+ cornerRadius ?? cornerRadiusForStyle(style) ?? 0;
115
136
 
116
- const { image, error } = useImage({
117
- url,
118
- blur: blur * scale,
119
- cornerRadius: scaleRadius(effectiveCornerRadius, scale),
120
- cache,
121
- resize,
122
- enabled: resize !== undefined,
123
- });
137
+ const { image, error } = useImage({
138
+ url,
139
+ blur: blur * scale,
140
+ cornerRadius: scaleRadius(effectiveCornerRadius, scale),
141
+ cache,
142
+ resize,
143
+ enabled: resize !== undefined,
144
+ });
124
145
 
125
- // Latest callbacks in refs so inline arrow props don't re-fire the effects.
126
- const onLoadRef = useRef(onLoad);
127
- const onErrorRef = useRef(onError);
128
- useEffect(() => {
129
- onLoadRef.current = onLoad;
130
- onErrorRef.current = onError;
131
- });
132
- useEffect(() => {
133
- if (image) onLoadRef.current?.(image);
134
- }, [image]);
135
- useEffect(() => {
136
- if (error) onErrorRef.current?.(error);
137
- }, [error]);
146
+ // Latest callbacks in refs so inline arrow props don't re-fire the effects.
147
+ const onLoadRef = useRef(onLoad);
148
+ const onErrorRef = useRef(onError);
149
+ useEffect(() => {
150
+ onLoadRef.current = onLoad;
151
+ onErrorRef.current = onError;
152
+ });
153
+ useEffect(() => {
154
+ if (image) onLoadRef.current?.(image);
155
+ }, [image]);
156
+ useEffect(() => {
157
+ if (error) onErrorRef.current?.(error);
158
+ }, [error]);
138
159
 
139
- const handleLayout = (event: LayoutChangeEvent) => {
140
- onLayout?.(event);
141
- const { width, height } = event.nativeEvent.layout;
142
- const next = resizeForLayout(width, height);
143
- // Always record it (even when a numeric style is in charge) so a later
144
- // switch to a non-numeric style has a size to fall back on.
145
- setLayoutSize((prev) => (sameSize(prev, next) ? prev : next));
146
- };
160
+ const handleLayout = (event: LayoutChangeEvent) => {
161
+ onLayout?.(event);
162
+ const { width, height } = event.nativeEvent.layout;
163
+ const next = resizeForLayout(width, height);
164
+ // Always record it (even when a numeric style is in charge) so a later
165
+ // switch to a non-numeric style has a size to fall back on.
166
+ setLayoutSize((prev) => (sameSize(prev, next) ? prev : next));
167
+ };
147
168
 
148
- return (
149
- <NativeNitroImage
150
- {...viewProps}
151
- style={style}
152
- onLayout={handleLayout}
153
- image={image}
154
- />
155
- );
156
- }
169
+ return (
170
+ <NativeNitroImage
171
+ {...viewProps}
172
+ ref={ref}
173
+ style={style}
174
+ onLayout={handleLayout}
175
+ image={image}
176
+ />
177
+ );
178
+ },
179
+ );
180
+
181
+ // Reanimated and DevTools read the display name; the forwardRef wrapper
182
+ // would otherwise report as anonymous.
183
+ PipelineImage.displayName = 'PipelineImage';
package/src/index.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  export { NitroImagePipeline } from './NitroImagePipeline';
2
- export { PipelineImage, type PipelineImageProps } from './PipelineImage';
2
+ export {
3
+ PipelineImage,
4
+ type PipelineImageProps,
5
+ type PipelineImageRef,
6
+ } from './PipelineImage';
3
7
  export {
4
8
  cornerRadiusForStyle,
5
9
  resizeForLayout,