@symbiote-native/components 0.2.5 → 0.2.6
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/build/index.js
CHANGED
|
@@ -24,7 +24,7 @@ export { switchReducer, createInitialSwitchState, shouldSnapBack, valueFromChang
|
|
|
24
24
|
export { resolveDecelerationRate, selectScrollIntrinsics, readLayoutDimension, didContentSizeChange, SCROLL_VIEW_BASE_HORIZONTAL, SCROLL_VIEW_BASE_VERTICAL, } from './view/render-scroll-view.js';
|
|
25
25
|
export { buildScrollViewHandle, splitLayoutProps, attachStickyScroll, isSymbioteEvent, forwardScrollEvent, } from './scroll-view-commands.js';
|
|
26
26
|
export { computeStickyInterpolation, nextStickyHeaderY, stickyDebounceMs, readLayoutNumber, STICKY_HEADER_Z_INDEX, } from './view/render-scroll-sticky.js';
|
|
27
|
-
export { renderImage } from './view/render-image.js';
|
|
27
|
+
export { renderImage } from './view/render-image/index.js';
|
|
28
28
|
export { imageStatics, setImageSourceResolver } from '@symbiote-native/engine';
|
|
29
29
|
// ImageBackground: render-only composition (absolute-fill image behind, children on top).
|
|
30
30
|
export { renderImageBackground } from './view/render-image-background.js';
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// the box. `imageStyle` wins last.
|
|
11
11
|
import { dlog, flattenStyle, } from '@symbiote-native/engine';
|
|
12
12
|
import { el } from '../descriptor.js';
|
|
13
|
-
import { renderImage } from './render-image.js';
|
|
13
|
+
import { renderImage } from './render-image/index.js';
|
|
14
14
|
// The inner Image's positioning: absolute-fill behind the wrapper's children.
|
|
15
15
|
const IMAGE_BACKGROUND_ABSOLUTE_FILL = {
|
|
16
16
|
position: 'absolute',
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/components",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"description": "Framework-agnostic component logic (state machines + render functions) for SymbioteNative — written once, inherited by every adapter (React, Vue, Angular, ...).",
|
|
5
|
+
"license": "MIT",
|
|
5
6
|
"repository": {
|
|
6
7
|
"type": "git",
|
|
7
8
|
"url": "git+https://github.com/OneEyed1366/symbiote-native.git",
|
|
@@ -33,12 +34,12 @@
|
|
|
33
34
|
"access": "public"
|
|
34
35
|
},
|
|
35
36
|
"peerDependencies": {
|
|
36
|
-
"@symbiote-native/engine": ">=0.1.
|
|
37
|
+
"@symbiote-native/engine": ">=0.1.7",
|
|
37
38
|
"react-native": ">=0.86"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
41
|
"@types/node": "^26.0.0",
|
|
41
|
-
"@symbiote-native/engine": "0.1.
|
|
42
|
+
"@symbiote-native/engine": "0.1.7"
|
|
42
43
|
},
|
|
43
44
|
"scripts": {
|
|
44
45
|
"typecheck": "tsc --build",
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { type IImageSource, type IImageSourceProp, type IStyleProp, type ISymbioteEvent, type IViewStyle } from '@symbiote-native/engine';
|
|
2
|
-
import type { IAccessibilityProps, IAriaProps } from '../accessibility-props';
|
|
3
|
-
import { type IDescriptor } from '../descriptor';
|
|
4
|
-
export type { IImageSource, IImageSourceProp };
|
|
5
|
-
type IImageEventHandler = (event: ISymbioteEvent) => void;
|
|
6
|
-
export type IResizeMode = 'cover' | 'contain' | 'stretch' | 'repeat' | 'center';
|
|
7
|
-
export type IImageCapInsets = {
|
|
8
|
-
top: number;
|
|
9
|
-
left: number;
|
|
10
|
-
bottom: number;
|
|
11
|
-
right: number;
|
|
12
|
-
};
|
|
13
|
-
export type IResizeMethod = 'auto' | 'resize' | 'scale' | 'none';
|
|
14
|
-
export type IImageProps = IAccessibilityProps & IAriaProps & {
|
|
15
|
-
source?: IImageSourceProp;
|
|
16
|
-
defaultSource?: IImageSourceProp;
|
|
17
|
-
loadingIndicatorSource?: IImageSourceProp;
|
|
18
|
-
style?: IStyleProp<IViewStyle>;
|
|
19
|
-
resizeMode?: IResizeMode;
|
|
20
|
-
resizeMethod?: IResizeMethod;
|
|
21
|
-
tintColor?: string;
|
|
22
|
-
blurRadius?: number;
|
|
23
|
-
capInsets?: IImageCapInsets;
|
|
24
|
-
fadeDuration?: number;
|
|
25
|
-
progressiveRenderingEnabled?: boolean;
|
|
26
|
-
src?: string;
|
|
27
|
-
srcSet?: string;
|
|
28
|
-
alt?: string;
|
|
29
|
-
width?: number;
|
|
30
|
-
height?: number;
|
|
31
|
-
crossOrigin?: 'anonymous' | 'use-credentials';
|
|
32
|
-
referrerPolicy?: string;
|
|
33
|
-
onLoadStart?: IImageEventHandler;
|
|
34
|
-
onLoad?: IImageEventHandler;
|
|
35
|
-
onLoadEnd?: IImageEventHandler;
|
|
36
|
-
onError?: IImageEventHandler;
|
|
37
|
-
onProgress?: IImageEventHandler;
|
|
38
|
-
onPartialLoad?: IImageEventHandler;
|
|
39
|
-
};
|
|
40
|
-
export type IImageViewProps = {
|
|
41
|
-
source?: IImageSourceProp;
|
|
42
|
-
defaultSource?: IImageSourceProp;
|
|
43
|
-
loadingIndicatorSource?: IImageSourceProp;
|
|
44
|
-
style?: IStyleProp<IViewStyle>;
|
|
45
|
-
resizeMode?: IResizeMode;
|
|
46
|
-
tintColor?: string;
|
|
47
|
-
src?: string;
|
|
48
|
-
srcSet?: string;
|
|
49
|
-
alt?: string;
|
|
50
|
-
width?: number;
|
|
51
|
-
height?: number;
|
|
52
|
-
crossOrigin?: 'anonymous' | 'use-credentials';
|
|
53
|
-
referrerPolicy?: string;
|
|
54
|
-
passthrough: Record<string, unknown>;
|
|
55
|
-
};
|
|
56
|
-
export declare function renderImage(view: IImageViewProps): IDescriptor;
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { dlog, flattenStyle, resolveImageSource, } from '@symbiote-native/engine';
|
|
2
|
-
import { el } from '../descriptor.js';
|
|
3
|
-
// Resolve the source, then normalize to the array shape native expects. A single
|
|
4
|
-
// object/number becomes a one-element array; an already-array source passes through.
|
|
5
|
-
function normalizeSource(source) {
|
|
6
|
-
const resolved = resolveImageSource(source);
|
|
7
|
-
const sources = Array.isArray(resolved) ? resolved : [resolved];
|
|
8
|
-
dlog(`Image source resolved to ${JSON.stringify(sources)}`);
|
|
9
|
-
return sources;
|
|
10
|
-
}
|
|
11
|
-
// The HTTP headers the W3C aliases (crossOrigin / referrerPolicy) contribute to
|
|
12
|
-
// every folded source, mirroring ImageSourceUtils.js getImageSourcesFromImageProps:
|
|
13
|
-
// 'use-credentials' adds the credentials header; referrerPolicy adds Referrer-Policy.
|
|
14
|
-
function headersFromAliases(view) {
|
|
15
|
-
const headers = {};
|
|
16
|
-
if (view.crossOrigin === 'use-credentials') {
|
|
17
|
-
headers['Access-Control-Allow-Credentials'] = 'true';
|
|
18
|
-
}
|
|
19
|
-
if (view.referrerPolicy !== undefined) {
|
|
20
|
-
headers['Referrer-Policy'] = view.referrerPolicy;
|
|
21
|
-
}
|
|
22
|
-
return headers;
|
|
23
|
-
}
|
|
24
|
-
// Expand a `srcSet` descriptor list into scaled sources, falling back to `src` for
|
|
25
|
-
// the 1x slot when srcSet omits it. Direct port of getImageSourcesFromImageProps'
|
|
26
|
-
// srcSet branch (ImageSourceUtils.js:48). Invalid scale tokens are skipped, matching
|
|
27
|
-
// RN's parse-and-warn behavior.
|
|
28
|
-
function expandSrcSet(srcSet, view, headers) {
|
|
29
|
-
const sources = [];
|
|
30
|
-
let useSrcForDefaultScale = true;
|
|
31
|
-
for (const entry of srcSet.split(', ')) {
|
|
32
|
-
const [uri, xScale = '1x'] = entry.split(' ');
|
|
33
|
-
if (!xScale.endsWith('x')) {
|
|
34
|
-
dlog(`Image srcSet: unsupported scale token "${xScale}", skipping`);
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
const scale = parseInt(xScale.slice(0, -1), 10);
|
|
38
|
-
if (Number.isNaN(scale))
|
|
39
|
-
continue;
|
|
40
|
-
if (scale === 1)
|
|
41
|
-
useSrcForDefaultScale = false;
|
|
42
|
-
sources.push({ uri, scale, width: view.width, height: view.height, ...{ headers } });
|
|
43
|
-
}
|
|
44
|
-
if (useSrcForDefaultScale && view.src !== undefined) {
|
|
45
|
-
sources.push({
|
|
46
|
-
uri: view.src,
|
|
47
|
-
scale: 1,
|
|
48
|
-
width: view.width,
|
|
49
|
-
height: view.height,
|
|
50
|
-
...{ headers },
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
if (sources.length === 0)
|
|
54
|
-
dlog('Image srcSet: produced no valid sources');
|
|
55
|
-
return sources;
|
|
56
|
-
}
|
|
57
|
-
// Resolve the native `source` array from whichever of source / src / srcSet the
|
|
58
|
-
// caller provided. Mirrors ImageSourceUtils.js getImageSourcesFromImageProps:
|
|
59
|
-
// srcSet wins, then src, then a header-decorated source, then the plain source.
|
|
60
|
-
// Always returns the array shape native expects (the same contract normalizeSource
|
|
61
|
-
// guarantees), so the component never sends a bare object.
|
|
62
|
-
function resolveSourceArray(view) {
|
|
63
|
-
const headers = headersFromAliases(view);
|
|
64
|
-
if (view.srcSet !== undefined) {
|
|
65
|
-
return expandSrcSet(view.srcSet, view, headers);
|
|
66
|
-
}
|
|
67
|
-
if (view.src !== undefined) {
|
|
68
|
-
return [{ uri: view.src, width: view.width, height: view.height, ...{ headers } }];
|
|
69
|
-
}
|
|
70
|
-
if (view.source === undefined) {
|
|
71
|
-
dlog('Image: no source / src / srcSet provided');
|
|
72
|
-
return [];
|
|
73
|
-
}
|
|
74
|
-
const sources = normalizeSource(view.source);
|
|
75
|
-
// A header-decorated single object source gets the headers merged in, per RN's
|
|
76
|
-
// `source.uri && headers` branch; the array/number shapes pass through untouched.
|
|
77
|
-
if (Object.keys(headers).length > 0 && sources.length === 1) {
|
|
78
|
-
const [only] = sources;
|
|
79
|
-
if (typeof only === 'object' && only !== null && typeof Reflect.get(only, 'uri') === 'string') {
|
|
80
|
-
return [{ ...only, headers }];
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return sources;
|
|
84
|
-
}
|
|
85
|
-
function readStyleString(style, key) {
|
|
86
|
-
if (style === undefined)
|
|
87
|
-
return undefined;
|
|
88
|
-
// style is a StyleProp (possibly a nested array), so flatten before reading a key.
|
|
89
|
-
const flat = flattenStyle(style);
|
|
90
|
-
const value = Object.hasOwn(flat, key) ? flat[key] : undefined;
|
|
91
|
-
return typeof value === 'string' ? value : undefined;
|
|
92
|
-
}
|
|
93
|
-
// Resolve an asset source and read its single uri. RN forwards the Android
|
|
94
|
-
// loading indicator as a bare uri string (`loadingIndicatorSrc`), not the
|
|
95
|
-
// array shape the main source uses, so we resolve and pluck the uri.
|
|
96
|
-
function readSourceUri(source) {
|
|
97
|
-
const [resolved] = normalizeSource(source);
|
|
98
|
-
if (typeof resolved === 'object' && resolved !== null) {
|
|
99
|
-
const uri = Reflect.get(resolved, 'uri');
|
|
100
|
-
if (typeof uri === 'string')
|
|
101
|
-
return uri;
|
|
102
|
-
}
|
|
103
|
-
return undefined;
|
|
104
|
-
}
|
|
105
|
-
export function renderImage(view) {
|
|
106
|
-
// `width` / `height` aliases fold into style (ImageProps.js:195,202); explicit
|
|
107
|
-
// style keys win, matching RN's `{width, height}, ...style` ordering.
|
|
108
|
-
const foldedStyle = view.width === undefined && view.height === undefined
|
|
109
|
-
? view.style
|
|
110
|
-
: [{ width: view.width, height: view.height }, view.style];
|
|
111
|
-
const mapped = {
|
|
112
|
-
...view.passthrough,
|
|
113
|
-
style: foldedStyle,
|
|
114
|
-
source: resolveSourceArray(view),
|
|
115
|
-
resizeMode: view.resizeMode ?? readStyleString(view.style, 'resizeMode'),
|
|
116
|
-
tintColor: view.tintColor ?? readStyleString(view.style, 'tintColor'),
|
|
117
|
-
};
|
|
118
|
-
// `alt` is the accessibility text: it sets accessibilityLabel and marks the image
|
|
119
|
-
// accessible (Image.ios.js / Image.android.js: alt -> accessibilityLabel + accessible).
|
|
120
|
-
// An explicit accessibilityLabel (already folded into passthrough) still wins.
|
|
121
|
-
if (view.alt !== undefined) {
|
|
122
|
-
if (mapped.accessibilityLabel === undefined)
|
|
123
|
-
mapped.accessibilityLabel = view.alt;
|
|
124
|
-
mapped.accessible = true;
|
|
125
|
-
}
|
|
126
|
-
if (view.defaultSource !== undefined)
|
|
127
|
-
mapped.defaultSource = normalizeSource(view.defaultSource);
|
|
128
|
-
if (view.loadingIndicatorSource !== undefined) {
|
|
129
|
-
mapped.loadingIndicatorSrc = readSourceUri(view.loadingIndicatorSource);
|
|
130
|
-
}
|
|
131
|
-
dlog('Image -> RCTImageView');
|
|
132
|
-
return el('symbiote-image', mapped);
|
|
133
|
-
}
|