@symbiote-native/image 0.0.0-stage → 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +45 -2
- package/build/angular/image/index.d.ts +20 -0
- package/build/angular/image/index.js +113 -0
- package/build/angular/image-background/index.d.ts +14 -0
- package/build/angular/image-background/index.js +107 -0
- package/build/angular/index.d.ts +4 -0
- package/build/angular/index.js +6 -0
- package/build/angular/inject-image.d.ts +8 -0
- package/build/angular/inject-image.js +20 -0
- package/build/core/constants.d.ts +3 -0
- package/build/core/constants.js +4 -0
- package/build/core/hash-strings.d.ts +5 -0
- package/build/core/hash-strings.js +20 -0
- package/build/core/image-api.d.ts +18 -0
- package/build/core/image-api.js +30 -0
- package/build/core/image-background.d.ts +11 -0
- package/build/core/image-background.js +26 -0
- package/build/core/image-loader.d.ts +20 -0
- package/build/core/image-loader.js +42 -0
- package/build/core/image-ref-loader.d.ts +4 -0
- package/build/core/image-ref-loader.js +10 -0
- package/build/core/image-view-events.d.ts +9 -0
- package/build/core/image-view-events.js +32 -0
- package/build/core/image-view.d.ts +14 -0
- package/build/core/image-view.js +111 -0
- package/build/core/index.d.ts +10 -0
- package/build/core/index.js +7 -0
- package/build/core/native-module.d.ts +27 -0
- package/build/core/native-module.js +3 -0
- package/build/core/native-style.d.ts +19 -0
- package/build/core/native-style.js +62 -0
- package/build/core/props.d.ts +11 -0
- package/build/core/props.js +87 -0
- package/build/core/sources.d.ts +8 -0
- package/build/core/sources.js +59 -0
- package/build/core/types.d.ts +186 -0
- package/build/core/types.js +1 -0
- package/build/react/image-background.d.ts +7 -0
- package/build/react/image-background.js +7 -0
- package/build/react/image.d.ts +8 -0
- package/build/react/image.js +6 -0
- package/build/react/index.d.ts +6 -0
- package/build/react/index.js +5 -0
- package/build/react/use-image.d.ts +8 -0
- package/build/react/use-image.js +20 -0
- package/build/solid/image-background.d.ts +7 -0
- package/build/solid/image-background.js +4 -0
- package/build/solid/image.d.ts +45 -0
- package/build/solid/image.js +4 -0
- package/build/solid/index.d.ts +5 -0
- package/build/solid/index.js +5 -0
- package/build/solid/use-image.d.ts +8 -0
- package/build/solid/use-image.js +16 -0
- package/build/svelte/image-background-props.d.ts +5 -0
- package/build/svelte/image-background-props.js +1 -0
- package/build/svelte/image-background.svelte +10 -0
- package/build/svelte/image-background.svelte.d.ts +4 -0
- package/build/svelte/image.svelte +26 -0
- package/build/svelte/image.svelte.d.ts +10 -0
- package/build/svelte/index.d.ts +6 -0
- package/build/svelte/index.js +5 -0
- package/build/svelte/use-image.svelte.d.ts +10 -0
- package/build/svelte/use-image.svelte.js +26 -0
- package/build/vue/image-background.d.ts +3 -0
- package/build/vue/image-background.js +12 -0
- package/build/vue/image.d.ts +2 -0
- package/build/vue/image.js +4 -0
- package/build/vue/index.d.ts +4 -0
- package/build/vue/index.js +5 -0
- package/build/vue/use-image.d.ts +8 -0
- package/build/vue/use-image.js +18 -0
- package/build-ngc/angular/image/index.d.ts +23 -0
- package/build-ngc/angular/image/index.js +72 -0
- package/build-ngc/angular/image/index.js.map +1 -0
- package/build-ngc/angular/image-background/index.d.ts +17 -0
- package/build-ngc/angular/image-background/index.js +66 -0
- package/build-ngc/angular/image-background/index.js.map +1 -0
- package/build-ngc/angular/index.d.ts +4 -0
- package/build-ngc/angular/index.js +7 -0
- package/build-ngc/angular/index.js.map +1 -0
- package/build-ngc/angular/inject-image.d.ts +8 -0
- package/build-ngc/angular/inject-image.js +23 -0
- package/build-ngc/angular/inject-image.js.map +1 -0
- package/build-ngc/core/constants.d.ts +3 -0
- package/build-ngc/core/constants.js +5 -0
- package/build-ngc/core/constants.js.map +1 -0
- package/build-ngc/core/hash-strings.d.ts +5 -0
- package/build-ngc/core/hash-strings.js +21 -0
- package/build-ngc/core/hash-strings.js.map +1 -0
- package/build-ngc/core/image-api.d.ts +18 -0
- package/build-ngc/core/image-api.js +31 -0
- package/build-ngc/core/image-api.js.map +1 -0
- package/build-ngc/core/image-background.d.ts +11 -0
- package/build-ngc/core/image-background.js +27 -0
- package/build-ngc/core/image-background.js.map +1 -0
- package/build-ngc/core/image-loader.d.ts +20 -0
- package/build-ngc/core/image-loader.js +43 -0
- package/build-ngc/core/image-loader.js.map +1 -0
- package/build-ngc/core/image-ref-loader.d.ts +4 -0
- package/build-ngc/core/image-ref-loader.js +11 -0
- package/build-ngc/core/image-ref-loader.js.map +1 -0
- package/build-ngc/core/image-view-events.d.ts +9 -0
- package/build-ngc/core/image-view-events.js +33 -0
- package/build-ngc/core/image-view-events.js.map +1 -0
- package/build-ngc/core/image-view.d.ts +14 -0
- package/build-ngc/core/image-view.js +112 -0
- package/build-ngc/core/image-view.js.map +1 -0
- package/build-ngc/core/index.d.ts +10 -0
- package/build-ngc/core/index.js +8 -0
- package/build-ngc/core/index.js.map +1 -0
- package/build-ngc/core/native-module.d.ts +27 -0
- package/build-ngc/core/native-module.js +4 -0
- package/build-ngc/core/native-module.js.map +1 -0
- package/build-ngc/core/native-style.d.ts +19 -0
- package/build-ngc/core/native-style.js +63 -0
- package/build-ngc/core/native-style.js.map +1 -0
- package/build-ngc/core/props.d.ts +11 -0
- package/build-ngc/core/props.js +88 -0
- package/build-ngc/core/props.js.map +1 -0
- package/build-ngc/core/sources.d.ts +8 -0
- package/build-ngc/core/sources.js +60 -0
- package/build-ngc/core/sources.js.map +1 -0
- package/build-ngc/core/types.d.ts +186 -0
- package/build-ngc/core/types.js +2 -0
- package/build-ngc/core/types.js.map +1 -0
- package/native-link.json +13 -0
- package/package.json +145 -3
- package/src/angular/image/index.ts +78 -0
- package/src/angular/image-background/index.ts +69 -0
- package/src/angular/index.ts +7 -0
- package/src/angular/inject-image.ts +29 -0
- package/src/core/constants.ts +6 -0
- package/src/core/hash-strings.ts +27 -0
- package/src/core/image-api.ts +67 -0
- package/src/core/image-background.ts +42 -0
- package/src/core/image-loader.ts +65 -0
- package/src/core/image-ref-loader.ts +16 -0
- package/src/core/image-view-events.ts +41 -0
- package/src/core/image-view.ts +156 -0
- package/src/core/index.ts +50 -0
- package/src/core/native-module.ts +45 -0
- package/src/core/native-style.ts +89 -0
- package/src/core/props.ts +118 -0
- package/src/core/sources.ts +70 -0
- package/src/core/types.ts +278 -0
- package/src/react/image-background.ts +14 -0
- package/src/react/image.ts +14 -0
- package/src/react/index.ts +8 -0
- package/src/react/use-image.ts +29 -0
- package/src/solid/image-background.ts +13 -0
- package/src/solid/image.ts +8 -0
- package/src/solid/index.ts +7 -0
- package/src/solid/use-image.ts +30 -0
- package/src/svelte/image-background-props.ts +6 -0
- package/src/svelte/image-background.svelte +10 -0
- package/src/svelte/image.svelte +26 -0
- package/src/svelte/index.ts +8 -0
- package/src/svelte/svelte-ambient.d.ts +3 -0
- package/src/svelte/svelte-compile.test-helper.ts +6 -0
- package/src/svelte/use-image.svelte.ts +38 -0
- package/src/vue/image-background.ts +17 -0
- package/src/vue/image.ts +5 -0
- package/src/vue/index.ts +6 -0
- package/src/vue/use-image.ts +34 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const CENTER = { top: '50%', left: '50%' };
|
|
2
|
+
const POSITION_BY_KEYWORD = {
|
|
3
|
+
center: CENTER,
|
|
4
|
+
top: { top: 0, left: '50%' },
|
|
5
|
+
right: { top: '50%', right: 0 },
|
|
6
|
+
bottom: { bottom: 0, left: '50%' },
|
|
7
|
+
left: { top: '50%', left: 0 },
|
|
8
|
+
'top center': { top: 0, left: '50%' },
|
|
9
|
+
'top right': { top: 0, right: 0 },
|
|
10
|
+
'top left': { top: 0, left: 0 },
|
|
11
|
+
'right center': { top: '50%', right: 0 },
|
|
12
|
+
'right top': { top: 0, right: 0 },
|
|
13
|
+
'right bottom': { bottom: 0, right: 0 },
|
|
14
|
+
'bottom center': { bottom: 0, left: '50%' },
|
|
15
|
+
'bottom right': { bottom: 0, right: 0 },
|
|
16
|
+
'bottom left': { bottom: 0, left: 0 },
|
|
17
|
+
'left center': { top: '50%', left: 0 },
|
|
18
|
+
'left top': { top: 0, left: 0 },
|
|
19
|
+
'left bottom': { bottom: 0, left: 0 },
|
|
20
|
+
};
|
|
21
|
+
const warned = new Set();
|
|
22
|
+
export function warnOnce(message) {
|
|
23
|
+
if (warned.has(message)) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
warned.add(message);
|
|
27
|
+
console.warn(`[expo-image]: ${message}`);
|
|
28
|
+
}
|
|
29
|
+
export function resetDeprecationWarnings() {
|
|
30
|
+
warned.clear();
|
|
31
|
+
}
|
|
32
|
+
function fitFromResizeMode(resizeMode) {
|
|
33
|
+
warnOnce('Prop "resizeMode" is deprecated, use "contentFit" instead');
|
|
34
|
+
switch (resizeMode) {
|
|
35
|
+
case 'contain':
|
|
36
|
+
case 'cover':
|
|
37
|
+
return resizeMode;
|
|
38
|
+
case 'stretch':
|
|
39
|
+
return 'fill';
|
|
40
|
+
case 'center':
|
|
41
|
+
return 'scale-down';
|
|
42
|
+
case 'repeat':
|
|
43
|
+
warnOnce('Resize mode "repeat" is no longer supported');
|
|
44
|
+
return 'cover';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** An SF Symbol defaults to `contain` to keep its aspect ratio */
|
|
48
|
+
export function resolveContentFit(contentFit, resizeMode, isSfSymbol) {
|
|
49
|
+
if (contentFit) {
|
|
50
|
+
return contentFit;
|
|
51
|
+
}
|
|
52
|
+
if (resizeMode) {
|
|
53
|
+
return fitFromResizeMode(resizeMode);
|
|
54
|
+
}
|
|
55
|
+
return isSfSymbol ? 'contain' : 'cover';
|
|
56
|
+
}
|
|
57
|
+
/** Native reads only the two-edge object form */
|
|
58
|
+
export function resolveContentPosition(contentPosition) {
|
|
59
|
+
if (typeof contentPosition !== 'string') {
|
|
60
|
+
return contentPosition ?? CENTER;
|
|
61
|
+
}
|
|
62
|
+
const resolved = POSITION_BY_KEYWORD[contentPosition];
|
|
63
|
+
if (!resolved) {
|
|
64
|
+
warnOnce(`Content position "${contentPosition}" is invalid`);
|
|
65
|
+
return CENTER;
|
|
66
|
+
}
|
|
67
|
+
return resolved;
|
|
68
|
+
}
|
|
69
|
+
/** Every form of `sfEffect` becomes a list of effect objects */
|
|
70
|
+
export function resolveSfEffect(sfEffect) {
|
|
71
|
+
if (sfEffect == null) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const effects = Array.isArray(sfEffect) ? sfEffect : [sfEffect];
|
|
75
|
+
return effects.map(item => (typeof item === 'string' ? { effect: item } : item));
|
|
76
|
+
}
|
|
77
|
+
/** A number is the duration of a cross dissolve */
|
|
78
|
+
export function resolveTransition(transition, fadeDuration) {
|
|
79
|
+
if (typeof transition === 'number') {
|
|
80
|
+
return { duration: transition };
|
|
81
|
+
}
|
|
82
|
+
if (!transition && typeof fadeDuration === 'number') {
|
|
83
|
+
warnOnce('Prop "fadeDuration" is deprecated, use "transition" instead');
|
|
84
|
+
return { duration: fadeDuration };
|
|
85
|
+
}
|
|
86
|
+
return transition ?? null;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=props.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"props.js","sourceRoot":"","sources":["../../src/core/props.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SharedRef } from 'expo-modules-core';
|
|
2
|
+
import type { IImageSource, IImageSources } from './types';
|
|
3
|
+
type IImageSourceInput = IImageSource | string | number | null | undefined;
|
|
4
|
+
export declare function isImageRef(value: unknown): value is SharedRef<'image'>;
|
|
5
|
+
export declare function resolveSource(source: IImageSourceInput): IImageSource | null;
|
|
6
|
+
/** The shape the native view takes: a list of sources or a shared object id */
|
|
7
|
+
export declare function resolveSources(sources: IImageSources | undefined): IImageSource[] | number;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { resolveAssetSource } from '@symbiote-native/engine';
|
|
2
|
+
import { SharedRef } from 'expo-modules-core';
|
|
3
|
+
import { SF_SYMBOL_PREFIX } from './constants';
|
|
4
|
+
import { resolveBlurhashString, resolveThumbhashString } from './hash-strings';
|
|
5
|
+
const BLURHASH_PATTERN = /^(blurhash:\/)+[\w#$%*+,\-.:;=?@[\]^_{}|~]+(\/[\d.]+)*$/;
|
|
6
|
+
const THUMBHASH_PREFIX = 'thumbhash:/';
|
|
7
|
+
// Any native image reference, an `ImageRef` or a `VideoThumbnail`, the view takes both
|
|
8
|
+
export function isImageRef(value) {
|
|
9
|
+
return value instanceof SharedRef && value.nativeRefType === 'image';
|
|
10
|
+
}
|
|
11
|
+
function sharedIdOf(ref) {
|
|
12
|
+
const id = Reflect.get(ref, '__expo_shared_object_id__');
|
|
13
|
+
return typeof id === 'number' ? id : 0;
|
|
14
|
+
}
|
|
15
|
+
function isImageSource(value) {
|
|
16
|
+
return typeof value === 'object' && value !== null;
|
|
17
|
+
}
|
|
18
|
+
function nativeAssetSource(id) {
|
|
19
|
+
const asset = resolveAssetSource(id);
|
|
20
|
+
return isImageSource(asset) ? asset : null;
|
|
21
|
+
}
|
|
22
|
+
export function resolveSource(source) {
|
|
23
|
+
if (typeof source === 'string') {
|
|
24
|
+
if (BLURHASH_PATTERN.test(source)) {
|
|
25
|
+
return resolveBlurhashString(source);
|
|
26
|
+
}
|
|
27
|
+
if (source.startsWith(THUMBHASH_PREFIX)) {
|
|
28
|
+
return resolveThumbhashString(source);
|
|
29
|
+
}
|
|
30
|
+
if (source.startsWith(SF_SYMBOL_PREFIX)) {
|
|
31
|
+
return { uri: `${SF_SYMBOL_PREFIX}/${source.slice(SF_SYMBOL_PREFIX.length)}` };
|
|
32
|
+
}
|
|
33
|
+
return { uri: source };
|
|
34
|
+
}
|
|
35
|
+
if (typeof source === 'number') {
|
|
36
|
+
return nativeAssetSource(source);
|
|
37
|
+
}
|
|
38
|
+
if (source?.blurhash || source?.thumbhash) {
|
|
39
|
+
const { blurhash, thumbhash, ...rest } = source;
|
|
40
|
+
const resolved = thumbhash
|
|
41
|
+
? resolveThumbhashString(thumbhash)
|
|
42
|
+
: resolveBlurhashString(blurhash ?? '');
|
|
43
|
+
return { ...resolved, ...rest };
|
|
44
|
+
}
|
|
45
|
+
return source ?? null;
|
|
46
|
+
}
|
|
47
|
+
function isPresent(source) {
|
|
48
|
+
return source !== null;
|
|
49
|
+
}
|
|
50
|
+
/** The shape the native view takes: a list of sources or a shared object id */
|
|
51
|
+
export function resolveSources(sources) {
|
|
52
|
+
if (Array.isArray(sources)) {
|
|
53
|
+
return sources.map(resolveSource).filter(isPresent);
|
|
54
|
+
}
|
|
55
|
+
if (isImageRef(sources)) {
|
|
56
|
+
return sharedIdOf(sources);
|
|
57
|
+
}
|
|
58
|
+
return [resolveSource(sources)].filter(isPresent);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=sources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources.js","sourceRoot":"","sources":["../../src/core/sources.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import type { IAccessibilityProps, IAriaProps, IResponderProps } from '@symbiote-native/components';
|
|
2
|
+
import type { IColorValue, IStyleProp, ITextStyle, IViewStyle } from '@symbiote-native/engine';
|
|
3
|
+
import type { SharedRef } from 'expo-modules-core';
|
|
4
|
+
import type { SFSymbol } from 'sf-symbols-typescript';
|
|
5
|
+
export type IImageSource = {
|
|
6
|
+
/** `http(s)`, `file`, `data`, an asset URI and the `sf:/` and `blurhash:/` schemes */
|
|
7
|
+
uri?: string;
|
|
8
|
+
/** Sent with the request */
|
|
9
|
+
headers?: Record<string, string>;
|
|
10
|
+
/** Used for layout while the image loads, and the size of a hash placeholder */
|
|
11
|
+
width?: number | null;
|
|
12
|
+
height?: number | null;
|
|
13
|
+
/** A Blurhash string, the source becomes a `blurhash:/` uri */
|
|
14
|
+
blurhash?: string;
|
|
15
|
+
/** A Thumbhash string, the source becomes a `thumbhash:/` uri */
|
|
16
|
+
thumbhash?: string;
|
|
17
|
+
/** The key of the cache entry, the uri by default */
|
|
18
|
+
cacheKey?: string;
|
|
19
|
+
/** Web only */
|
|
20
|
+
webMaxViewportWidth?: number;
|
|
21
|
+
/** Plays the image as an animation, detected from the content by default */
|
|
22
|
+
isAnimated?: boolean;
|
|
23
|
+
};
|
|
24
|
+
export type IImageContentFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
|
|
25
|
+
export type IImageDecodeFormat = 'argb' | 'rgb';
|
|
26
|
+
export type IImageResizeMode = 'cover' | 'contain' | 'stretch' | 'repeat' | 'center';
|
|
27
|
+
export type IImageContentPositionValue = number | string | `${number}%` | `${number}` | 'center';
|
|
28
|
+
export type IImageContentPositionString = 'center' | 'top' | 'right' | 'bottom' | 'left' | 'top center' | 'top right' | 'top left' | 'right center' | 'right top' | 'right bottom' | 'bottom center' | 'bottom right' | 'bottom left' | 'left center' | 'left top' | 'left bottom';
|
|
29
|
+
/** Two edges, the native side takes only this form */
|
|
30
|
+
export type IImageContentPositionObject = {
|
|
31
|
+
top?: IImageContentPositionValue;
|
|
32
|
+
right?: IImageContentPositionValue;
|
|
33
|
+
} | {
|
|
34
|
+
top?: IImageContentPositionValue;
|
|
35
|
+
left?: IImageContentPositionValue;
|
|
36
|
+
} | {
|
|
37
|
+
bottom?: IImageContentPositionValue;
|
|
38
|
+
right?: IImageContentPositionValue;
|
|
39
|
+
} | {
|
|
40
|
+
bottom?: IImageContentPositionValue;
|
|
41
|
+
left?: IImageContentPositionValue;
|
|
42
|
+
};
|
|
43
|
+
export type IImageContentPosition = IImageContentPositionObject | IImageContentPositionString;
|
|
44
|
+
export type IImageTransition = {
|
|
45
|
+
/** In milliseconds */
|
|
46
|
+
duration?: number;
|
|
47
|
+
timing?: 'ease-in-out' | 'ease-in' | 'ease-out' | 'linear';
|
|
48
|
+
effect?: 'cross-dissolve' | 'flip-from-top' | 'flip-from-right' | 'flip-from-bottom' | 'flip-from-left' | 'curl-up' | 'curl-down' | 'sf:replace' | 'sf:down-up' | 'sf:up-up' | 'sf:off-up' | null;
|
|
49
|
+
};
|
|
50
|
+
export type ISfSymbolEffectType = 'bounce' | 'bounce/up' | 'bounce/down' | 'pulse' | 'variable-color' | 'variable-color/iterative' | 'variable-color/cumulative' | 'scale' | 'scale/up' | 'scale/down' | 'appear' | 'disappear' | 'wiggle' | 'rotate' | 'breathe' | 'draw/on' | 'draw/off';
|
|
51
|
+
export type ISfSymbolEffectObject = {
|
|
52
|
+
effect: ISfSymbolEffectType;
|
|
53
|
+
/** `-1` repeats forever */
|
|
54
|
+
repeat?: number;
|
|
55
|
+
scope?: 'by-layer' | 'whole-symbol' | null;
|
|
56
|
+
};
|
|
57
|
+
/** iOS 17+ for an SF Symbol source */
|
|
58
|
+
export type ISfSymbolEffect = ISfSymbolEffectType | ISfSymbolEffectObject | (ISfSymbolEffectType | ISfSymbolEffectObject)[];
|
|
59
|
+
export type IImageLoadEventData = {
|
|
60
|
+
cacheType: 'none' | 'disk' | 'memory';
|
|
61
|
+
source: {
|
|
62
|
+
url: string;
|
|
63
|
+
width: number;
|
|
64
|
+
height: number;
|
|
65
|
+
mediaType: string | null;
|
|
66
|
+
isAnimated?: boolean;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
export type IImageProgressEventData = {
|
|
70
|
+
loaded: number;
|
|
71
|
+
total: number;
|
|
72
|
+
};
|
|
73
|
+
export type IImageErrorEventData = {
|
|
74
|
+
error: string;
|
|
75
|
+
};
|
|
76
|
+
export type IImagePrefetchOptions = {
|
|
77
|
+
/** `memory-disk` by default */
|
|
78
|
+
cachePolicy?: 'disk' | 'memory-disk' | 'memory';
|
|
79
|
+
headers?: Record<string, string>;
|
|
80
|
+
};
|
|
81
|
+
export type IImageCacheConfig = {
|
|
82
|
+
/** In bytes */
|
|
83
|
+
maxDiskSize?: number;
|
|
84
|
+
/** In bytes */
|
|
85
|
+
maxMemoryCost?: number;
|
|
86
|
+
maxMemoryCount?: number;
|
|
87
|
+
};
|
|
88
|
+
export type IImageLoadOptions = {
|
|
89
|
+
maxWidth?: number;
|
|
90
|
+
maxHeight?: number;
|
|
91
|
+
tintColor?: IColorValue | number;
|
|
92
|
+
/** `retry` loads again */
|
|
93
|
+
onError?(error: Error, retry: () => void): void;
|
|
94
|
+
};
|
|
95
|
+
/** A reference to a native image, an image view takes it as its source */
|
|
96
|
+
export declare class ImageRef extends SharedRef<'image'> {
|
|
97
|
+
readonly width: number;
|
|
98
|
+
readonly height: number;
|
|
99
|
+
readonly scale: number;
|
|
100
|
+
readonly mediaType: string | null;
|
|
101
|
+
readonly isAnimated?: boolean;
|
|
102
|
+
/** The id the native view looks the shared object up by */
|
|
103
|
+
readonly __expo_shared_object_id__: number;
|
|
104
|
+
}
|
|
105
|
+
export type IImageStyle = IViewStyle & {
|
|
106
|
+
tintColor?: IColorValue;
|
|
107
|
+
resizeMode?: IImageResizeMode;
|
|
108
|
+
/** With `color` and `fontSize` for an SF Symbol */
|
|
109
|
+
fontWeight?: ITextStyle['fontWeight'];
|
|
110
|
+
color?: IColorValue;
|
|
111
|
+
fontSize?: number;
|
|
112
|
+
};
|
|
113
|
+
export type IImageSources = IImageSource | `sf:${SFSymbol}` | (string & {}) | number | IImageSource[] | string[] | SharedRef<'image'> | null;
|
|
114
|
+
export type IImageViewProps = IAccessibilityProps & IAriaProps & IResponderProps & {
|
|
115
|
+
style?: IStyleProp<IImageStyle>;
|
|
116
|
+
/** A uri, an asset, a source object, a list of them or an `ImageRef` */
|
|
117
|
+
source?: IImageSources;
|
|
118
|
+
/** Shown while `source` loads */
|
|
119
|
+
placeholder?: IImageSource | string | number | IImageSource[] | string[] | SharedRef<'image'> | null;
|
|
120
|
+
/** `cover` by default, `contain` for an SF Symbol */
|
|
121
|
+
contentFit?: IImageContentFit;
|
|
122
|
+
placeholderContentFit?: IImageContentFit;
|
|
123
|
+
/** `center` by default */
|
|
124
|
+
contentPosition?: IImageContentPosition;
|
|
125
|
+
/** A number is the duration of a cross dissolve */
|
|
126
|
+
transition?: IImageTransition | number | null;
|
|
127
|
+
blurRadius?: number;
|
|
128
|
+
tintColor?: IColorValue | null;
|
|
129
|
+
priority?: 'low' | 'normal' | 'high' | null;
|
|
130
|
+
loading?: 'lazy' | 'eager';
|
|
131
|
+
cachePolicy?: 'none' | 'disk' | 'memory' | 'memory-disk' | null;
|
|
132
|
+
/** How the image follows a changing view size */
|
|
133
|
+
responsivePolicy?: 'live' | 'initial' | 'static';
|
|
134
|
+
/** Lets a recycled list cell tell its images apart */
|
|
135
|
+
recyclingKey?: string | null;
|
|
136
|
+
/** Plays an animated image on its own, `true` by default */
|
|
137
|
+
autoplay?: boolean;
|
|
138
|
+
/** An effect of an SF Symbol source, iOS 17+ */
|
|
139
|
+
sfEffect?: ISfSymbolEffect | null;
|
|
140
|
+
onLoadStart?: () => void;
|
|
141
|
+
onLoad?: (event: IImageLoadEventData) => void;
|
|
142
|
+
onProgress?: (event: IImageProgressEventData) => void;
|
|
143
|
+
onError?: (event: IImageErrorEventData) => void;
|
|
144
|
+
onLoadEnd?: () => void;
|
|
145
|
+
onDisplay?: () => void;
|
|
146
|
+
/** @deprecated Use `placeholder` */
|
|
147
|
+
defaultSource?: IImageSource | null;
|
|
148
|
+
/** @deprecated Use `placeholder` */
|
|
149
|
+
loadingIndicatorSource?: IImageSource | null;
|
|
150
|
+
/** @deprecated Use `contentFit` */
|
|
151
|
+
resizeMode?: IImageResizeMode;
|
|
152
|
+
/** @deprecated Use `transition` */
|
|
153
|
+
fadeDuration?: number;
|
|
154
|
+
focusable?: boolean;
|
|
155
|
+
accessible?: boolean;
|
|
156
|
+
accessibilityLabel?: string;
|
|
157
|
+
/** The accessibility label when none is given */
|
|
158
|
+
alt?: string;
|
|
159
|
+
/** iOS only, lets the user select text in the image */
|
|
160
|
+
enableLiveTextInteraction?: boolean;
|
|
161
|
+
/** Downscales a larger image to the view, `true` by default */
|
|
162
|
+
allowDownscaling?: boolean;
|
|
163
|
+
/** Android only, `argb` by default */
|
|
164
|
+
decodeFormat?: IImageDecodeFormat;
|
|
165
|
+
/** iOS only */
|
|
166
|
+
useAppleWebpCodec?: boolean;
|
|
167
|
+
/** Android only */
|
|
168
|
+
enforceEarlyResizing?: boolean;
|
|
169
|
+
/** iOS only */
|
|
170
|
+
preferHighDynamicRange?: boolean;
|
|
171
|
+
/** Web only */
|
|
172
|
+
draggable?: boolean;
|
|
173
|
+
testID?: string;
|
|
174
|
+
nativeID?: string;
|
|
175
|
+
};
|
|
176
|
+
/** What a ref to the view hands out */
|
|
177
|
+
export type IImageViewHandle = {
|
|
178
|
+
/** Starts an animated image */
|
|
179
|
+
startAnimating(): Promise<void>;
|
|
180
|
+
stopAnimating(): Promise<void>;
|
|
181
|
+
/** Keeps the resource from being reloaded */
|
|
182
|
+
lockResourceAsync(): Promise<void>;
|
|
183
|
+
unlockResourceAsync(): Promise<void>;
|
|
184
|
+
/** Reloads the resource, the lock is ignored */
|
|
185
|
+
reloadAsync(): Promise<void>;
|
|
186
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":""}
|
package/native-link.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,148 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/image",
|
|
3
|
-
"version": "0.0.0
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "expo-image wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. The image view with caching, placeholders and SF Symbols, plus the image cache and hash functions.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/OneEyed1366/symbiote-native.git",
|
|
9
|
+
"directory": "packages/image"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/OneEyed1366/symbiote-native/tree/master/packages/image#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/OneEyed1366/symbiote-native/issues"
|
|
14
|
+
},
|
|
15
|
+
"author": "Andrey Prokopenko <psevdoproger@gmail.com>",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"react-native",
|
|
18
|
+
"symbiote-native",
|
|
19
|
+
"expo-image",
|
|
20
|
+
"react",
|
|
21
|
+
"vue",
|
|
22
|
+
"svelte",
|
|
23
|
+
"solid",
|
|
24
|
+
"angular",
|
|
25
|
+
"image"
|
|
26
|
+
],
|
|
27
|
+
"type": "module",
|
|
28
|
+
"main": "./build/core/index.js",
|
|
29
|
+
"module": "./build/core/index.js",
|
|
30
|
+
"types": "./build/core/index.d.ts",
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./build/core/index.d.ts",
|
|
34
|
+
"default": "./build/core/index.js"
|
|
35
|
+
},
|
|
36
|
+
"./vue": {
|
|
37
|
+
"types": "./build/vue/index.d.ts",
|
|
38
|
+
"default": "./build/vue/index.js"
|
|
39
|
+
},
|
|
40
|
+
"./react": {
|
|
41
|
+
"types": "./build/react/index.d.ts",
|
|
42
|
+
"default": "./build/react/index.js"
|
|
43
|
+
},
|
|
44
|
+
"./svelte": "./src/svelte/index.ts",
|
|
45
|
+
"./solid": {
|
|
46
|
+
"types": "./build/solid/index.d.ts",
|
|
47
|
+
"default": "./build/solid/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./angular": {
|
|
50
|
+
"types": "./build-ngc/angular/index.d.ts",
|
|
51
|
+
"react-native": "./build-ngc/angular/index.js",
|
|
52
|
+
"default": "./src/angular/index.ts"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"files": [
|
|
56
|
+
"src",
|
|
57
|
+
"build",
|
|
58
|
+
"build-ngc",
|
|
59
|
+
"native-link.json",
|
|
60
|
+
"!src/**/*.test.*",
|
|
61
|
+
"!src/**/*.spec.*",
|
|
62
|
+
"!src/**/*.detox.*"
|
|
63
|
+
],
|
|
64
|
+
"publishConfig": {
|
|
65
|
+
"access": "public"
|
|
66
|
+
},
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"expo-image": "57.0.5",
|
|
69
|
+
"expo-modules-core": "57.0.20",
|
|
70
|
+
"sf-symbols-typescript": "^2.0.0",
|
|
71
|
+
"@symbiote-native/components": "3.1.4"
|
|
72
|
+
},
|
|
73
|
+
"peerDependencies": {
|
|
74
|
+
"@angular/core": ">=20",
|
|
75
|
+
"@vue/runtime-core": "^3.5.13",
|
|
76
|
+
"react": ">=19.0.0",
|
|
77
|
+
"react-native": ">=0.86",
|
|
78
|
+
"solid-js": ">=1.9.0",
|
|
79
|
+
"svelte": ">=5.56.0",
|
|
80
|
+
"vue": ">=3.5.0",
|
|
81
|
+
"@symbiote-native/angular": "^3.2.0",
|
|
82
|
+
"@symbiote-native/engine": "^1.5.0",
|
|
83
|
+
"@symbiote-native/solid": "^3.1.0",
|
|
84
|
+
"@symbiote-native/react": "^3.2.0",
|
|
85
|
+
"@symbiote-native/svelte": "^3.1.0",
|
|
86
|
+
"@symbiote-native/vue": "^3.2.0"
|
|
87
|
+
},
|
|
88
|
+
"peerDependenciesMeta": {
|
|
89
|
+
"@symbiote-native/angular": {
|
|
90
|
+
"optional": true
|
|
91
|
+
},
|
|
92
|
+
"@symbiote-native/react": {
|
|
93
|
+
"optional": true
|
|
94
|
+
},
|
|
95
|
+
"@symbiote-native/solid": {
|
|
96
|
+
"optional": true
|
|
97
|
+
},
|
|
98
|
+
"@symbiote-native/svelte": {
|
|
99
|
+
"optional": true
|
|
100
|
+
},
|
|
101
|
+
"@symbiote-native/vue": {
|
|
102
|
+
"optional": true
|
|
103
|
+
},
|
|
104
|
+
"@angular/core": {
|
|
105
|
+
"optional": true
|
|
106
|
+
},
|
|
107
|
+
"@vue/runtime-core": {
|
|
108
|
+
"optional": true
|
|
109
|
+
},
|
|
110
|
+
"react": {
|
|
111
|
+
"optional": true
|
|
112
|
+
},
|
|
113
|
+
"solid-js": {
|
|
114
|
+
"optional": true
|
|
115
|
+
},
|
|
116
|
+
"svelte": {
|
|
117
|
+
"optional": true
|
|
118
|
+
},
|
|
119
|
+
"vue": {
|
|
120
|
+
"optional": true
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
"devDependencies": {
|
|
124
|
+
"@angular/compiler": "~22.0.8",
|
|
125
|
+
"@angular/compiler-cli": "~22.0.8",
|
|
126
|
+
"@angular/core": "~22.0.8",
|
|
127
|
+
"@types/node": "^26.0.0",
|
|
128
|
+
"@types/react": "^19.2.0",
|
|
129
|
+
"@vue/runtime-core": "^3.5.13",
|
|
130
|
+
"react": "19.2.3",
|
|
131
|
+
"solid-js": "^1.9.14",
|
|
132
|
+
"svelte": "^5.56.0",
|
|
133
|
+
"typescript": "~6.0.0",
|
|
134
|
+
"@symbiote-native/angular": "3.2.0",
|
|
135
|
+
"@symbiote-native/solid": "3.1.0",
|
|
136
|
+
"@symbiote-native/engine": "1.5.0",
|
|
137
|
+
"@symbiote-native/vue": "3.2.0",
|
|
138
|
+
"@symbiote-native/test-utils": "0.4.6",
|
|
139
|
+
"@symbiote-native/svelte": "3.1.0",
|
|
140
|
+
"@symbiote-native/react": "3.2.0"
|
|
141
|
+
},
|
|
142
|
+
"scripts": {
|
|
143
|
+
"typecheck": "tsc --build",
|
|
144
|
+
"clean": "rm -rf build-ngc",
|
|
145
|
+
"ng:build": "pnpm run clean && ngc -p tsconfig.angular.json",
|
|
146
|
+
"format": "prettier --write \"src/**/*.{ts,tsx}\""
|
|
147
|
+
}
|
|
6
148
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
|
2
|
+
import { DescriptorOutlet, NativeViewBase } from '@symbiote-native/angular';
|
|
3
|
+
import type { IDescriptor } from '@symbiote-native/components';
|
|
4
|
+
import type { IStyleProp } from '@symbiote-native/engine';
|
|
5
|
+
import { createImageView } from '../../core';
|
|
6
|
+
import type { IImageStyle, IImageViewProps } from '../../core';
|
|
7
|
+
|
|
8
|
+
// One list is the inputs of the component and the props it hands to the native view
|
|
9
|
+
const IMAGE_INPUTS = [
|
|
10
|
+
'source',
|
|
11
|
+
'placeholder',
|
|
12
|
+
'contentFit',
|
|
13
|
+
'placeholderContentFit',
|
|
14
|
+
'contentPosition',
|
|
15
|
+
'transition',
|
|
16
|
+
'blurRadius',
|
|
17
|
+
'tintColor',
|
|
18
|
+
'priority',
|
|
19
|
+
'loading',
|
|
20
|
+
'cachePolicy',
|
|
21
|
+
'responsivePolicy',
|
|
22
|
+
'recyclingKey',
|
|
23
|
+
'autoplay',
|
|
24
|
+
'sfEffect',
|
|
25
|
+
'onLoadStart',
|
|
26
|
+
'onLoad',
|
|
27
|
+
'onProgress',
|
|
28
|
+
'onError',
|
|
29
|
+
'onLoadEnd',
|
|
30
|
+
'onDisplay',
|
|
31
|
+
'defaultSource',
|
|
32
|
+
'loadingIndicatorSource',
|
|
33
|
+
'resizeMode',
|
|
34
|
+
'fadeDuration',
|
|
35
|
+
'alt',
|
|
36
|
+
'enableLiveTextInteraction',
|
|
37
|
+
'allowDownscaling',
|
|
38
|
+
'decodeFormat',
|
|
39
|
+
'useAppleWebpCodec',
|
|
40
|
+
'enforceEarlyResizing',
|
|
41
|
+
'preferHighDynamicRange',
|
|
42
|
+
'draggable',
|
|
43
|
+
] as const;
|
|
44
|
+
|
|
45
|
+
// Types the inputs for the template, the decorators that would do it are replaced by `inputs`
|
|
46
|
+
export interface ExpoImage
|
|
47
|
+
extends Partial<Pick<IImageViewProps, (typeof IMAGE_INPUTS)[number]>> {}
|
|
48
|
+
|
|
49
|
+
/** Angular twin of `expo-image`'s `Image`, `Image` itself is a primitive tag of the adapter */
|
|
50
|
+
@Component({
|
|
51
|
+
selector: 'ExpoImage',
|
|
52
|
+
standalone: true,
|
|
53
|
+
imports: [DescriptorOutlet],
|
|
54
|
+
inputs: [...IMAGE_INPUTS],
|
|
55
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
56
|
+
template: `@if (descriptor; as node) {
|
|
57
|
+
<symbiote-descriptor-outlet [node]="node" />
|
|
58
|
+
}`,
|
|
59
|
+
})
|
|
60
|
+
export class ExpoImage extends NativeViewBase {
|
|
61
|
+
// The `style` input of the base, typed with the image keys such as `tintColor`
|
|
62
|
+
declare style?: IStyleProp<IImageStyle>;
|
|
63
|
+
|
|
64
|
+
private readonly view = createImageView(() => this.hostNode());
|
|
65
|
+
|
|
66
|
+
// The functions of the view are members of the component, a `@ViewChild` reaches them
|
|
67
|
+
readonly startAnimating = this.view.handle.startAnimating;
|
|
68
|
+
readonly stopAnimating = this.view.handle.stopAnimating;
|
|
69
|
+
readonly lockResourceAsync = this.view.handle.lockResourceAsync;
|
|
70
|
+
readonly unlockResourceAsync = this.view.handle.unlockResourceAsync;
|
|
71
|
+
readonly reloadAsync = this.view.handle.reloadAsync;
|
|
72
|
+
|
|
73
|
+
protected override readonly propNames = IMAGE_INPUTS;
|
|
74
|
+
|
|
75
|
+
protected override renderView(props: object): IDescriptor | null {
|
|
76
|
+
return this.view.render(props);
|
|
77
|
+
}
|
|
78
|
+
}
|