react-native-nitro-image-pipeline 1.5.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +142 -18
  2. package/android/src/main/java/com/margelo/nitro/nitroimagepipeline/HybridNitroImagePipeline.kt +72 -16
  3. package/android/src/main/java/com/margelo/nitro/nitroimagepipeline/PipelineImageLoader.kt +47 -8
  4. package/android/src/main/java/com/margelo/nitro/nitroimagepipeline/transform/FitGeometry.kt +104 -0
  5. package/android/src/main/java/com/margelo/nitro/nitroimagepipeline/transform/PipelineRoundedCornersTransformation.kt +103 -0
  6. package/android/src/main/java/com/margelo/nitro/nitroimagepipeline/transform/ResizeTransformation.kt +69 -16
  7. package/ios/FitResizeProcessor.swift +127 -0
  8. package/ios/HybridNitroImagePipeline.swift +88 -24
  9. package/ios/PipelineImageLoader.swift +108 -18
  10. package/lib/commonjs/NativePipelineImage.js +20 -4
  11. package/lib/commonjs/NativePipelineImage.js.map +1 -1
  12. package/lib/commonjs/PipelineImage.js +13 -1
  13. package/lib/commonjs/PipelineImage.js.map +1 -1
  14. package/lib/commonjs/index.js +13 -0
  15. package/lib/commonjs/index.js.map +1 -1
  16. package/lib/commonjs/resizeForStyle.js +3 -1
  17. package/lib/commonjs/resizeForStyle.js.map +1 -1
  18. package/lib/commonjs/resolveImageSource.js +89 -0
  19. package/lib/commonjs/resolveImageSource.js.map +1 -0
  20. package/lib/commonjs/useImage.js +14 -6
  21. package/lib/commonjs/useImage.js.map +1 -1
  22. package/lib/commonjs/usePipelineImageLoader.js +114 -11
  23. package/lib/commonjs/usePipelineImageLoader.js.map +1 -1
  24. package/lib/module/NativePipelineImage.js +20 -4
  25. package/lib/module/NativePipelineImage.js.map +1 -1
  26. package/lib/module/PipelineImage.js +13 -1
  27. package/lib/module/PipelineImage.js.map +1 -1
  28. package/lib/module/index.js +1 -0
  29. package/lib/module/index.js.map +1 -1
  30. package/lib/module/resizeForStyle.js +3 -1
  31. package/lib/module/resizeForStyle.js.map +1 -1
  32. package/lib/module/resolveImageSource.js +83 -0
  33. package/lib/module/resolveImageSource.js.map +1 -0
  34. package/lib/module/useImage.js +14 -6
  35. package/lib/module/useImage.js.map +1 -1
  36. package/lib/module/usePipelineImageLoader.js +115 -12
  37. package/lib/module/usePipelineImageLoader.js.map +1 -1
  38. package/lib/typescript/src/NativePipelineImage.d.ts +51 -5
  39. package/lib/typescript/src/NativePipelineImage.d.ts.map +1 -1
  40. package/lib/typescript/src/PipelineImage.d.ts +35 -3
  41. package/lib/typescript/src/PipelineImage.d.ts.map +1 -1
  42. package/lib/typescript/src/index.d.ts +2 -1
  43. package/lib/typescript/src/index.d.ts.map +1 -1
  44. package/lib/typescript/src/resizeForStyle.d.ts +3 -1
  45. package/lib/typescript/src/resizeForStyle.d.ts.map +1 -1
  46. package/lib/typescript/src/resolveImageSource.d.ts +56 -0
  47. package/lib/typescript/src/resolveImageSource.d.ts.map +1 -0
  48. package/lib/typescript/src/specs/nitro-image-toolkit.nitro.d.ts +95 -8
  49. package/lib/typescript/src/specs/nitro-image-toolkit.nitro.d.ts.map +1 -1
  50. package/lib/typescript/src/useImage.d.ts +13 -6
  51. package/lib/typescript/src/useImage.d.ts.map +1 -1
  52. package/lib/typescript/src/usePipelineImageLoader.d.ts +7 -3
  53. package/lib/typescript/src/usePipelineImageLoader.d.ts.map +1 -1
  54. package/nitrogen/generated/android/NitroImagePipelineOnLoad.cpp +4 -0
  55. package/nitrogen/generated/android/c++/JFunc_void_double_double.hpp +75 -0
  56. package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +76 -0
  57. package/nitrogen/generated/android/c++/JHybridNitroImagePipelineSpec.cpp +8 -0
  58. package/nitrogen/generated/android/c++/JOptions.hpp +2 -0
  59. package/nitrogen/generated/android/c++/JResizeFit.hpp +64 -0
  60. package/nitrogen/generated/android/c++/JResizeOptions.hpp +14 -4
  61. package/nitrogen/generated/android/c++/JViewOptions.hpp +42 -3
  62. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroimagepipeline/Func_void_double_double.kt +78 -0
  63. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroimagepipeline/Func_void_std__string.kt +78 -0
  64. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroimagepipeline/ResizeFit.kt +25 -0
  65. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroimagepipeline/ResizeOptions.kt +14 -4
  66. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitroimagepipeline/ViewOptions.kt +29 -5
  67. package/nitrogen/generated/ios/NitroImagePipeline-Swift-Cxx-Bridge.cpp +16 -0
  68. package/nitrogen/generated/ios/NitroImagePipeline-Swift-Cxx-Bridge.hpp +107 -0
  69. package/nitrogen/generated/ios/NitroImagePipeline-Swift-Cxx-Umbrella.hpp +4 -0
  70. package/nitrogen/generated/ios/c++/HybridNitroImagePipelineSpecSwift.hpp +4 -0
  71. package/nitrogen/generated/ios/swift/Func_void_double_double.swift +46 -0
  72. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +46 -0
  73. package/nitrogen/generated/ios/swift/ResizeFit.swift +48 -0
  74. package/nitrogen/generated/ios/swift/ResizeOptions.swift +31 -2
  75. package/nitrogen/generated/ios/swift/ViewOptions.swift +82 -1
  76. package/nitrogen/generated/shared/c++/ResizeFit.hpp +84 -0
  77. package/nitrogen/generated/shared/c++/ResizeOptions.hpp +14 -4
  78. package/nitrogen/generated/shared/c++/ViewOptions.hpp +24 -3
  79. package/package.json +1 -1
  80. package/src/NativePipelineImage.tsx +75 -6
  81. package/src/PipelineImage.tsx +46 -3
  82. package/src/index.ts +6 -0
  83. package/src/resizeForStyle.ts +3 -1
  84. package/src/resolveImageSource.ts +83 -0
  85. package/src/specs/nitro-image-toolkit.nitro.ts +96 -8
  86. package/src/useImage.ts +38 -17
  87. package/src/usePipelineImageLoader.ts +126 -11
@@ -1,9 +1,36 @@
1
1
  "use strict";
2
2
 
3
- import { useMemo } from 'react';
3
+ import { useLayoutEffect, useMemo, useRef } from 'react';
4
4
  import { NitroImagePipeline } from './NitroImagePipeline';
5
+ import { resolveImageUrlOrFallback } from './resolveImageSource';
6
+ // Identifies a loader in the callbacks below without them capturing it. A
7
+ // callback the native loader owns that captured the loader back would be a
8
+ // cycle across the language boundary — neither side collectable, and the JS
9
+ // runtime left to take it apart at teardown.
10
+ let nextLoaderToken = 0;
5
11
  /**
6
- * Creates (and memoizes) an {@linkcode ImageLoader} for `url` to pass to
12
+ * The callbacks handed to a native loader. Built out here, where the scope
13
+ * holds nothing but the token and the two refs, so the loader can't end up
14
+ * captured by a callback it owns.
15
+ */
16
+ function makeReporters(token, activeToken, callbacks) {
17
+ return {
18
+ onLoad: (width, height) => {
19
+ if (activeToken.current === token) {
20
+ callbacks.current.onLoad?.(width, height);
21
+ }
22
+ },
23
+ onError: message => {
24
+ if (activeToken.current === token) {
25
+ callbacks.current.onError?.(message);
26
+ }
27
+ }
28
+ };
29
+ }
30
+
31
+ /**
32
+ * Creates (and memoizes) an {@linkcode ImageLoader} for `source` — a URL
33
+ * string or a `require()`d asset, see {@linkcode ImageSource} — to pass to
7
34
  * `<NativeNitroImage image={...} />`. The view drives it entirely natively:
8
35
  * the request starts when the view attaches — at the view's laid-out size,
9
36
  * with no JS round trips — and is cancelled when it detaches. See
@@ -11,9 +38,11 @@ import { NitroImagePipeline } from './NitroImagePipeline';
11
38
  *
12
39
  * `blur`/`cornerRadius` are in **points** (unlike `useImage`, where they are
13
40
  * bitmap pixels); the screen scale is applied natively. Inline object
14
- * literals are fine — options are compared by value, not identity.
41
+ * literals are fine — options are compared by value, not identity, and the
42
+ * `onLoad`/`onError` callbacks are read through a ref, so inline arrows don't
43
+ * recreate the loader either.
15
44
  */
16
- export function usePipelineImageLoader(url, options) {
45
+ export function usePipelineImageLoader(source, options) {
17
46
  // Split the options into primitives (like useImage does) so an inline
18
47
  // literal — a new identity every render — doesn't recreate the loader;
19
48
  // recreating it would re-trigger the native load.
@@ -31,35 +60,109 @@ export function usePipelineImageLoader(url, options) {
31
60
  } = isUniformRadius || cornerRadius === undefined ? {} : cornerRadius;
32
61
  const resizeWidth = options?.resize?.width;
33
62
  const resizeHeight = options?.resize?.height;
34
- return useMemo(() => {
63
+ const resizeFit = options?.resize?.fit;
64
+ const resizeAllowUpscale = options?.resize?.allowUpscale;
65
+ const fit = options?.fit;
66
+ const allowUpscale = options?.allowUpscale;
67
+ const onLoad = options?.onLoad;
68
+ const onError = options?.onError;
69
+ // Only *whether* a callback is set can change the loader: what the native
70
+ // side gets is a wrapper that reads the latest callbacks from a ref (like
71
+ // PipelineImage does). So an inline arrow — a new identity every render —
72
+ // doesn't recreate the loader and re-trigger the native load.
73
+ const hasOnLoad = onLoad !== undefined;
74
+ const hasOnError = onError !== undefined;
75
+ const callbacks = useRef({
76
+ onLoad,
77
+ onError
78
+ });
79
+ // A layout effect, not a passive one: passive effects are flushed in a later
80
+ // task, so a load reported between the commit and that flush would read the
81
+ // previous render's callbacks — a callback added alongside a new loader
82
+ // could miss its only event. This runs in the same task as the commit, and
83
+ // the view can't reach the loader before the commit installs it, so the ref
84
+ // is always current by the time native calls back. (Assigning it during
85
+ // render instead would mutate on renders React throws away.)
86
+ useLayoutEffect(() => {
87
+ callbacks.current = {
88
+ onLoad,
89
+ onError
90
+ };
91
+ });
92
+ // The token of the loader the view is currently on. Swapping loaders (a
93
+ // changed url or options) never drops the old one — the view just stops
94
+ // referring to it — so a load it already had in flight can still report.
95
+ // Without this check the wrappers, which read the latest callbacks, would
96
+ // hand the previous image's size to the current `onLoad`.
97
+ const activeToken = useRef(-1);
98
+ const memoized = useMemo(() => {
99
+ // Runs during render, so an unregistered `require()` id must not throw:
100
+ // it becomes a URL the native loader fails on at load time instead.
101
+ const url = resolveImageUrlOrFallback(source);
35
102
  const cornerRadiusOption = isUniformRadius ? uniformRadius : hasCornerObject ? {
36
103
  topLeft,
37
104
  topRight,
38
105
  bottomLeft,
39
106
  bottomRight
40
107
  } : undefined;
108
+ // What is loaded — the callbacks are deliberately not part of it, so two
109
+ // loaders that differ only in them are the same image.
41
110
  const stableOptions = {
42
111
  blur,
43
112
  cache,
44
113
  cornerRadius: cornerRadiusOption,
45
114
  resize: resizeWidth !== undefined && resizeHeight !== undefined ? {
46
115
  width: resizeWidth,
47
- height: resizeHeight
48
- } : undefined
116
+ height: resizeHeight,
117
+ fit: resizeFit,
118
+ allowUpscale: resizeAllowUpscale
119
+ } : undefined,
120
+ fit,
121
+ allowUpscale
49
122
  };
50
- const loader = NitroImagePipeline.createImageLoader(url, stableOptions);
123
+ const token = nextLoaderToken++;
124
+ // The reporters read the refs, but only when the native side calls them —
125
+ // the rule can't see that they aren't called here.
126
+ // oxlint-disable-next-line react/refs
127
+ const reporters = makeReporters(token, activeToken, callbacks);
128
+ const loader = NitroImagePipeline.createImageLoader(url, {
129
+ ...stableOptions,
130
+ // Passed only when the caller wants them: without a callback nothing
131
+ // ever crosses into JS, which is the point of the native path.
132
+ onLoad: hasOnLoad ? reporters.onLoad : undefined,
133
+ onError: hasOnError ? reporters.onError : undefined
134
+ });
51
135
  // `NativeNitroImage` needs a way to tell two loader instances apart when
52
136
  // diffing its `image` prop; tag the loader with what it will load (the
53
- // same convention react-native-nitro-image's own loaders use).
137
+ // same convention react-native-nitro-image's own loaders use). Toggling a
138
+ // callback on or off makes a different loader, so the tag has to say so —
139
+ // otherwise the view keeps the old one installed. Their identities stay
140
+ // out of it: those don't change what is loaded, or which loader this is.
54
141
  Object.defineProperty(loader, '__source', {
55
142
  enumerable: true,
56
143
  configurable: true,
57
144
  value: {
58
145
  url,
59
- options: stableOptions
146
+ options: stableOptions,
147
+ callbacks: {
148
+ onLoad: hasOnLoad,
149
+ onError: hasOnError
150
+ }
60
151
  }
61
152
  });
62
- return loader;
63
- }, [url, blur, cache, isUniformRadius, uniformRadius, hasCornerObject, topLeft, topRight, bottomLeft, bottomRight, resizeWidth, resizeHeight]);
153
+ return {
154
+ loader,
155
+ token
156
+ };
157
+ }, [source, blur, cache, isUniformRadius, uniformRadius, hasCornerObject, topLeft, topRight, bottomLeft, bottomRight, resizeWidth, resizeHeight, resizeFit, resizeAllowUpscale, fit, allowUpscale, hasOnLoad, hasOnError,
158
+ // Stable ref objects; listed to satisfy the exhaustive-deps rules.
159
+ activeToken, callbacks]);
160
+
161
+ // Same reasoning as the callbacks ref: a layout effect is current before the
162
+ // view — which the commit has only just handed this loader — can report.
163
+ useLayoutEffect(() => {
164
+ activeToken.current = memoized.token;
165
+ }, [memoized, activeToken]);
166
+ return memoized.loader;
64
167
  }
65
168
  //# sourceMappingURL=usePipelineImageLoader.js.map
@@ -1 +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":[]}
1
+ {"version":3,"names":["useLayoutEffect","useMemo","useRef","NitroImagePipeline","resolveImageUrlOrFallback","nextLoaderToken","makeReporters","token","activeToken","callbacks","onLoad","width","height","current","onError","message","usePipelineImageLoader","source","options","blur","cache","cornerRadius","isUniformRadius","uniformRadius","hasCornerObject","undefined","topLeft","topRight","bottomLeft","bottomRight","resizeWidth","resize","resizeHeight","resizeFit","fit","resizeAllowUpscale","allowUpscale","hasOnLoad","hasOnError","memoized","url","cornerRadiusOption","stableOptions","reporters","loader","createImageLoader","Object","defineProperty","enumerable","configurable","value"],"sourceRoot":"../../src","sources":["usePipelineImageLoader.ts"],"mappings":"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","ignoreList":[]}
@@ -1,7 +1,8 @@
1
1
  import { type ComponentRef } from 'react';
2
2
  import type { HostComponent } from 'react-native';
3
3
  import { NativeNitroImage } from 'react-native-nitro-image';
4
- import type { CacheOption, CornerRadii, ResizeOptions } from './specs/nitro-image-toolkit.nitro';
4
+ import { type ImageSource } from './resolveImageSource';
5
+ import type { CacheOption, CornerRadii, ResizeFit, ResizeOptions } from './specs/nitro-image-toolkit.nitro';
5
6
  type ReactProps<T> = T extends HostComponent<infer P> ? P : never;
6
7
  type NativeImageProps = ReactProps<typeof NativeNitroImage>;
7
8
  /**
@@ -11,8 +12,12 @@ type NativeImageProps = ReactProps<typeof NativeNitroImage>;
11
12
  */
12
13
  export type NativePipelineImageRef = ComponentRef<typeof NativeNitroImage>;
13
14
  export interface NativePipelineImageProps extends Omit<NativeImageProps, 'image'> {
14
- /** URL of the image to load through the pipeline. */
15
- url: string;
15
+ /**
16
+ * The image to load through the pipeline: a URL string (`https://`,
17
+ * `file://`, an absolute path) or a `require()`d asset — see
18
+ * {@linkcode ImageSource}.
19
+ */
20
+ url: ImageSource;
16
21
  /**
17
22
  * Gaussian blur sigma in **points** (density-independent), like
18
23
  * `PipelineImage`. Applied natively with the screen scale.
@@ -33,6 +38,46 @@ export interface NativePipelineImageProps extends Omit<NativeImageProps, 'image'
33
38
  * @default undefined (measure the view natively)
34
39
  */
35
40
  resize?: ResizeOptions;
41
+ /**
42
+ * How the source is fitted into the measured view size when the bitmap is
43
+ * produced — see {@linkcode ResizeFit}. When omitted it follows
44
+ * `resizeMode`, like `PipelineImage`. Set this to decouple the two.
45
+ * @default undefined (derived from `resizeMode`, or `'cover'` if unset)
46
+ */
47
+ fit?: ResizeFit;
48
+ /**
49
+ * `false` never enlarges a source smaller than the view when the
50
+ * **bitmap** is produced — see {@linkcode ResizeOptions.allowUpscale}: it
51
+ * stays at its own pixel size, so nothing is decoded or blurred larger
52
+ * than the source. The **view** still displays that bitmap per
53
+ * `resizeMode`, so `cover`/`contain`/`stretch` scale it up on screen (and
54
+ * a baked `blur`/`cornerRadius` with it); `resizeMode="center"` shows it
55
+ * pixel for pixel instead, on both platforms.
56
+ * @default true
57
+ */
58
+ allowUpscale?: boolean;
59
+ /**
60
+ * Called when the view has displayed the image, with the size of the bitmap
61
+ * it displays in **pixels**.
62
+ *
63
+ * Unlike `PipelineImage`'s `onLoad` this doesn't hand you the `Image` — the
64
+ * bitmap stays native, which is the point of this component — and it means
65
+ * "the view is now showing this image" rather than firing exactly once: a
66
+ * recycled cell re-attaching calls it again, and a single view may call it
67
+ * more than once for the same image. Make it idempotent.
68
+ *
69
+ * Setting it means there is per-image JS work again; leave it unset and the
70
+ * component stays free of JS round trips.
71
+ */
72
+ onLoad?: (width: number, height: number) => void;
73
+ /**
74
+ * Called when loading fails, with the underlying error's message. A load
75
+ * cancelled by the view detaching is not a failure and doesn't call this.
76
+ *
77
+ * Without it, failures on this component are silent — there is no `Image`
78
+ * and no promise to surface them.
79
+ */
80
+ onError?: (message: string) => void;
36
81
  }
37
82
  /**
38
83
  * The fully native-driven variant of `PipelineImage`: after the first render
@@ -43,8 +88,9 @@ export interface NativePipelineImageProps extends Omit<NativeImageProps, 'image'
43
88
  * the same pipeline and caches as `useImage`/`preLoadImage`.
44
89
  *
45
90
  * Compared to `PipelineImage`:
46
- * - No `onLoad`/`onError` callbacks the loaded `Image` never crosses into
47
- * JS. Use `PipelineImage` (or `useImage`) when you need them.
91
+ * - `onLoad` reports the bitmap's pixel size rather than the `Image` itself,
92
+ * which never crosses into JS, and can fire more than once for a view. Use
93
+ * `PipelineImage` (or `useImage`) when you need the `Image`.
48
94
  * - The bitmap is loaded once at the size the view first has; if the view is
49
95
  * resized later, the bitmap scales with it instead of reloading.
50
96
  * @example
@@ -1 +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
+ {"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,EAAE,KAAK,WAAW,EAAmB,MAAM,sBAAsB,CAAC;AACzE,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,SAAS,EACT,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;;;;OAIG;IACH,GAAG,EAAE,WAAW,CAAC;IACjB;;;;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;IACvB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,mBAAmB;;;;;4FAgD9B,CAAC"}
@@ -1,7 +1,8 @@
1
1
  import { type ComponentRef } from 'react';
2
2
  import { type HostComponent } from 'react-native';
3
3
  import { type Image, NativeNitroImage } from 'react-native-nitro-image';
4
- import type { CacheOption, CornerRadii } from './specs/nitro-image-toolkit.nitro';
4
+ import type { ImageSource } from './resolveImageSource';
5
+ import type { CacheOption, CornerRadii, ResizeFit } from './specs/nitro-image-toolkit.nitro';
5
6
  type ReactProps<T> = T extends HostComponent<infer P> ? P : never;
6
7
  type NativeImageProps = ReactProps<typeof NativeNitroImage>;
7
8
  /**
@@ -11,8 +12,12 @@ type NativeImageProps = ReactProps<typeof NativeNitroImage>;
11
12
  */
12
13
  export type PipelineImageRef = ComponentRef<typeof NativeNitroImage>;
13
14
  export interface PipelineImageProps extends Omit<NativeImageProps, 'image'> {
14
- /** URL of the image to load through the pipeline. */
15
- url: string;
15
+ /**
16
+ * The image to load through the pipeline: a URL string (`https://`,
17
+ * `file://`, an absolute path) or a `require()`d asset — see
18
+ * {@linkcode ImageSource}.
19
+ */
20
+ url: ImageSource;
16
21
  /**
17
22
  * Gaussian blur sigma in **points** (density-independent). Unlike
18
23
  * `useImage`/`loadImage`, where it is bitmap pixels, the component
@@ -33,6 +38,33 @@ export interface PipelineImageProps extends Omit<NativeImageProps, 'image'> {
33
38
  */
34
39
  cornerRadius?: number | CornerRadii;
35
40
  cache?: CacheOption;
41
+ /**
42
+ * How the source is fitted into the display size when the bitmap is
43
+ * produced — see {@linkcode ResizeFit}. When omitted it follows
44
+ * `resizeMode`, so `resizeMode="contain"` decodes an aspect-fitted bitmap
45
+ * (no crop, no padding) instead of a center-cropped one the view then
46
+ * letterboxes. Set this to decouple the two.
47
+ *
48
+ * One iOS caveat, inherited from nitro-image's `Image`: an `Image` handed
49
+ * to the view is a scale-1 image, which `resizeMode="center"` — the one
50
+ * mode that draws an image at its own size — shows at 1 pt per pixel,
51
+ * i.e. `PixelRatio.get()`× larger than Android draws it. The bitmap is
52
+ * right; the display is not. `NativePipelineImage` draws `center` pixel
53
+ * for pixel on both platforms; use it when you need that mode.
54
+ * @default undefined (derived from `resizeMode`, or `'cover'` if unset)
55
+ */
56
+ fit?: ResizeFit;
57
+ /**
58
+ * `false` never enlarges a source smaller than the display size when the
59
+ * **bitmap** is produced — see {@linkcode ResizeOptions.allowUpscale}: it
60
+ * stays at its own pixel size, so nothing is decoded or blurred larger
61
+ * than the source. The **view** still displays that bitmap per
62
+ * `resizeMode`, so `cover`/`contain`/`stretch` scale it up on screen (and
63
+ * a baked `blur`/`cornerRadius` with it); `resizeMode="center"` shows it
64
+ * at its natural size instead.
65
+ * @default true
66
+ */
67
+ allowUpscale?: boolean;
36
68
  /** Called with the processed `Image` each time a new variant resolves. */
37
69
  onLoad?: (image: Image) => void;
38
70
  /** Called when loading fails. */
@@ -1 +1 @@
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
+ {"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,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,SAAS,EAEV,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;;;;OAIG;IACH,GAAG,EAAE,WAAW,CAAC;IACjB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACpC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;;;;;;;;;;;;OAcG;IACH,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,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;;;;;4FA+EzB,CAAC"}
@@ -1,8 +1,9 @@
1
1
  export { NativePipelineImage, type NativePipelineImageProps, type NativePipelineImageRef, } from './NativePipelineImage';
2
2
  export { NitroImagePipeline } from './NitroImagePipeline';
3
3
  export { PipelineImage, type PipelineImageProps, type PipelineImageRef, } from './PipelineImage';
4
+ export { type ImageSource, resolveImageUrl, UNREGISTERED_ASSET_URL, } from './resolveImageSource';
4
5
  export { cornerRadiusForStyle, resizeForLayout, resizeForStyle, } from './resizeForStyle';
5
- export type { CacheOption, CornerRadii, Options, ResizeOptions, ViewOptions, } from './specs/nitro-image-toolkit.nitro';
6
+ export type { CacheOption, CornerRadii, Options, ResizeFit, ResizeOptions, ViewOptions, } from './specs/nitro-image-toolkit.nitro';
6
7
  export { useImage } from './useImage';
7
8
  export { usePipelineImageLoader } from './usePipelineImageLoader';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
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"}
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,KAAK,WAAW,EAChB,eAAe,EACf,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,cAAc,GACf,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,WAAW,EACX,WAAW,EACX,OAAO,EACP,SAAS,EACT,aAAa,EACb,WAAW,GACZ,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC"}
@@ -3,7 +3,9 @@ import type { CornerRadii, ResizeOptions } from './specs/nitro-image-toolkit.nit
3
3
  /**
4
4
  * Converts a layout size in points (dp) to the pipeline's `resize` option in
5
5
  * whole bitmap pixels using `PixelRatio.getPixelSizeForLayoutSize`. Returns
6
- * `undefined` unless both values are positive numbers.
6
+ * `undefined` unless both values are positive numbers. Spread a `fit` into
7
+ * the result for the other resize modes — under `contain` and `center` the
8
+ * size is the box the bitmap fits in, not necessarily its final size.
7
9
  */
8
10
  export declare function resizeForLayout(width: unknown, height: unknown): ResizeOptions | undefined;
9
11
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"resizeForStyle.d.ts","sourceRoot":"","sources":["../../../src/resizeForStyle.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EAEd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACd,MAAM,mCAAmC,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,OAAO,GACd,aAAa,GAAG,SAAS,CAS3B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,GAC1B,aAAa,GAAG,SAAS,CAG3B;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,GAC1B,MAAM,GAAG,WAAW,GAAG,SAAS,CAoClC"}
1
+ {"version":3,"file":"resizeForStyle.d.ts","sourceRoot":"","sources":["../../../src/resizeForStyle.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EAEd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACd,MAAM,mCAAmC,CAAC;AAE3C;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,OAAO,GACd,aAAa,GAAG,SAAS,CAS3B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,GAC1B,aAAa,GAAG,SAAS,CAG3B;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,GAC1B,MAAM,GAAG,WAAW,GAAG,SAAS,CAoClC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * What the pipeline can load: a URL string, or the id a `require()`d image
3
+ * asset evaluates to.
4
+ *
5
+ * As a string, `url` is passed to the native loader as-is. Accepted forms:
6
+ *
7
+ * - `https://` / `http://` — fetched over the network and cached on disk.
8
+ * - `file://` URLs and plain absolute paths (`/var/…/photo.jpg`) — read from
9
+ * the file system. The result is cached in memory only; there is nothing
10
+ * to gain from copying a local file into the disk cache.
11
+ * - Android also accepts `content://` URIs and, from a release build's
12
+ * resources, a bare drawable name — which is what `require()` resolves to
13
+ * there. iOS resolves `require()` to a `file://` URL into the app bundle.
14
+ *
15
+ * A `require('./photo.png')` is resolved with `Image.resolveAssetSource`, so
16
+ * it works the same in debug (streamed from Metro) and release (bundled).
17
+ */
18
+ export type ImageSource = string | number;
19
+ /**
20
+ * Turns an {@linkcode ImageSource} into the URL string the native pipeline
21
+ * loads: strings pass through unchanged, a `require()`d asset is resolved via
22
+ * `Image.resolveAssetSource` (the scale-matched variant, like `<Image>`).
23
+ *
24
+ * The components and hooks call this for you; use it when calling
25
+ * `NitroImagePipeline.loadImage`/`preLoadImage` directly with a `require()`.
26
+ * @throws If `source` is a number that is not a registered asset.
27
+ * @example
28
+ * ```ts
29
+ * const image = await NitroImagePipeline.loadImage(
30
+ * resolveImageUrl(require('./photo.png')),
31
+ * { blur: 4 },
32
+ * );
33
+ * ```
34
+ */
35
+ export declare function resolveImageUrl(source: ImageSource): string;
36
+ /**
37
+ * A URL no loader can resolve, standing in for a `require()` id that is not
38
+ * a registered asset. Its scheme has no fetcher on either platform, so the
39
+ * request fails at load time — the same way a missing file does — instead of
40
+ * throwing from a component's render.
41
+ */
42
+ export declare const UNREGISTERED_ASSET_URL = "unregistered-asset://";
43
+ /**
44
+ * {@linkcode resolveImageUrl} for code that runs during render: an
45
+ * unregistered `require()` id yields {@linkcode UNREGISTERED_ASSET_URL} (and
46
+ * a warning in development) rather than throwing.
47
+ */
48
+ export declare function resolveImageUrlOrFallback(source: ImageSource): string;
49
+ /**
50
+ * A stable, per-source `recyclingKey` for `<NativeNitroImage>`: the URL
51
+ * itself for strings, and a tag derived from the asset id for a `require()`
52
+ * (resolving it would cost an asset-registry lookup per render for nothing
53
+ * more than a distinct key).
54
+ */
55
+ export declare function recyclingKeyFor(source: ImageSource): string;
56
+ //# sourceMappingURL=resolveImageSource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolveImageSource.d.ts","sourceRoot":"","sources":["../../../src/resolveImageSource.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAS3D;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,0BAA0B,CAAC;AAE9D;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAWrE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAE3D"}
@@ -12,13 +12,45 @@ export interface CornerRadii {
12
12
  bottomRight?: number;
13
13
  }
14
14
  /**
15
- * Target bitmap size in pixels. The image is scaled to fill this size and
16
- * center-cropped (like CSS `object-fit: cover`), upscaling if needed, so the
17
- * result is exactly `width` × `height` pixels.
15
+ * How the source is fitted into the {@linkcode ResizeOptions} box. Mirrors
16
+ * `NativeNitroImage`'s `resizeMode`, so a view's `resizeMode` and the bitmap
17
+ * it displays can be derived from one value. With a `w` × `h` source and a
18
+ * `W` × `H` box, the produced bitmap is:
19
+ *
20
+ * - `cover`: scale by `max(W/w, H/h)`, center-crop → exactly `W` × `H`
21
+ * (CSS `object-fit: cover`).
22
+ * - `contain`: scale by `min(W/w, H/h)` → `round(w·s)` × `round(h·s)`, the
23
+ * largest size with the source's aspect ratio that fits the box. The
24
+ * bitmap is *not* padded to the box.
25
+ * - `stretch`: scale each axis independently → exactly `W` × `H`, aspect
26
+ * ratio ignored.
27
+ * - `center`: no scaling; center-crop to `min(w, W)` × `min(h, H)`. A source
28
+ * smaller than the box is left untouched.
29
+ */
30
+ export type ResizeFit = 'cover' | 'contain' | 'stretch' | 'center';
31
+ /**
32
+ * Target bitmap size in pixels. By default the image is scaled to fill this
33
+ * size and center-cropped (like CSS `object-fit: cover`), upscaling if
34
+ * needed, so the result is exactly `width` × `height` pixels; {@linkcode fit}
35
+ * selects the other resize modes.
18
36
  */
19
37
  export interface ResizeOptions {
20
38
  width: number;
21
39
  height: number;
40
+ /**
41
+ * How the source is fitted into `width` × `height` — see
42
+ * {@linkcode ResizeFit} for the size each mode produces.
43
+ * @default 'cover'
44
+ */
45
+ fit?: ResizeFit;
46
+ /**
47
+ * `false` never enlarges the source: the scale is clamped to at most 1 for
48
+ * `cover`, `contain` and `stretch`, so a source smaller than the box keeps
49
+ * its own size (and, under `cover`, is only cropped to the box). No effect
50
+ * on `center`, which never scales.
51
+ * @default true
52
+ */
53
+ allowUpscale?: boolean;
22
54
  }
23
55
  export type Options = {
24
56
  /**
@@ -51,10 +83,11 @@ export type Options = {
51
83
  */
52
84
  cornerRadius?: number | CornerRadii;
53
85
  /**
54
- * Resize the image to exactly this size in pixels (aspect-fill,
55
- * center-crop) before `blur` and `cornerRadius` are applied. Besides making
56
- * `cornerRadius` predictable, this avoids decoding and processing
57
- * full-resolution bitmaps you only display small.
86
+ * Resize the image into this box in pixels aspect-fill + center-crop by
87
+ * default, or another {@linkcode ResizeFit} — before `blur` and
88
+ * `cornerRadius` are applied. Besides making `cornerRadius` predictable,
89
+ * this avoids decoding and processing full-resolution bitmaps you only
90
+ * display small.
58
91
  *
59
92
  * @default undefined (keep the source size)
60
93
  */
@@ -85,15 +118,64 @@ export type ViewOptions = {
85
118
  /**
86
119
  * Target bitmap size in **pixels**, overriding the size measured from the
87
120
  * view. Rarely needed — without it the loader resizes to the view's
88
- * laid-out size × screen scale, which is what you want in a UI.
121
+ * laid-out size × screen scale, which is what you want in a UI. Its own
122
+ * `fit`/`allowUpscale`, when set, win over the top-level ones below.
89
123
  * @default undefined (measure the view)
90
124
  */
91
125
  resize?: ResizeOptions;
126
+ /**
127
+ * How the source is fitted into the box the loader resizes to (the view's
128
+ * size, or {@linkcode resize}) — see {@linkcode ResizeFit}. Pass the view's
129
+ * `resizeMode` so the bitmap matches how the view displays it.
130
+ * @default 'cover'
131
+ */
132
+ fit?: ResizeFit;
133
+ /**
134
+ * `false` never enlarges the source — see
135
+ * {@linkcode ResizeOptions.allowUpscale}.
136
+ * @default true
137
+ */
138
+ allowUpscale?: boolean;
139
+ /**
140
+ * Called when a view finishes displaying the image, with the size of the
141
+ * bitmap it displays in **pixels**.
142
+ *
143
+ * The bitmap itself deliberately stays native — passing the `Image` into JS
144
+ * would keep it alive there and defeat the point of the native path. Use
145
+ * `useImage`/`loadImage` when you need the `Image` object.
146
+ *
147
+ * This reports "the view is now showing this image", not a one-shot event:
148
+ * a loader is per URL + options, not per view, so every view using it
149
+ * reports, a recycled cell reports again when it re-attaches, and a single
150
+ * view can report more than once (it requests the image both when its
151
+ * `image` prop is set and when it becomes visible). Memory-cache hits, which
152
+ * resolve synchronously, report too. It does not fire for imperative loads
153
+ * through `ImageLoader.loadImage()` — those resolve through their promise.
154
+ *
155
+ * Setting it means there *is* per-image JS work; leave it unset and the
156
+ * native path stays free of JS round trips entirely.
157
+ * @default undefined (nothing crosses into JS)
158
+ */
159
+ onLoad?: (width: number, height: number) => void;
160
+ /**
161
+ * Called when a view fails to load the image, with the underlying error's
162
+ * message. Cancelling a load (the view detaching before it finishes) is not
163
+ * a failure and does not call this.
164
+ * @default undefined (failures are silent)
165
+ */
166
+ onError?: (message: string) => void;
92
167
  };
93
168
  export interface NitroImagePipeline extends HybridObject<{
94
169
  ios: 'swift';
95
170
  android: 'kotlin';
96
171
  }> {
172
+ /**
173
+ * Loads `url` through the pipeline. Besides `http(s)://`, `url` may be a
174
+ * `file://` URL or a plain absolute path (read from the file system, cached
175
+ * in memory only), a `data:` URL, or — on Android — a `content://` URI or
176
+ * the bare resource name a `require()` resolves to in a release build. Use
177
+ * `resolveImageUrl(require('./photo.png'))` to pass a bundled asset.
178
+ */
97
179
  loadImage(url: string, options?: Options): Promise<Image>;
98
180
  /**
99
181
  * Creates an {@linkcode ImageLoader} for `url` that a `<NativeNitroImage>`
@@ -108,6 +190,11 @@ export interface NitroImagePipeline extends HybridObject<{
108
190
  * attaches, the load waits for its first layout.
109
191
  */
110
192
  createImageLoader(url: string, options?: ViewOptions): ImageLoader;
193
+ /**
194
+ * Warms the disk cache with the download for `url`, without decoding it.
195
+ * Local sources (`file://`, paths, resources) have no download to warm it
196
+ * with and are a no-op.
197
+ */
111
198
  preLoadImage(url: string): Promise<void>;
112
199
  preLoadImages(urls: string[]): Promise<void>;
113
200
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"nitro-image-toolkit.nitro.d.ts","sourceRoot":"","sources":["../../../../src/specs/nitro-image-toolkit.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAErD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,OAAO,GAAG;IACpB;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACpC;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACpC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,CAAC;AAEF,MAAM,WAAW,kBAAmB,SAAQ,YAAY,CAAC;IACvD,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;CACnB,CAAC;IACA,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1D;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,CAAC;IACnE,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C;;;;OAIG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAG3D;;;;;;;;OAQG;IACH,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B"}
1
+ {"version":3,"file":"nitro-image-toolkit.nitro.d.ts","sourceRoot":"","sources":["../../../../src/specs/nitro-image-toolkit.nitro.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAErD;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEnE;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,MAAM,OAAO,GAAG;IACpB;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;;;;;;;;;;;OAaG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACpC;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACpC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,WAAW,kBAAmB,SAAQ,YAAY,CAAC;IACvD,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,QAAQ,CAAC;CACnB,CAAC;IACA;;;;;;OAMG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1D;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,WAAW,CAAC;IACnE;;;;OAIG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C;;;;OAIG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAG3D;;;;;;;;OAQG;IACH,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7B"}