import { useMemo } from "react"; import { Image, type ImageRequireSource, type ImageSourcePropType, type NativeSyntheticEvent, } from "react-native"; import ImagesNativeComponent, { type NativeImageEntry, } from "./ImagesNativeComponent"; import "./NativeImagesModule"; import { type BaseProps } from "../../types/BaseProps"; /** * An image source with optional SDF (Signed Distance Field) rendering mode. */ export type ImageSourceWithSdf = { source: ImageSourcePropType; sdf?: boolean; }; /** * A map image entry: a URL string, a native asset require, or an * {@link ImageSourceWithSdf} object. */ export type ImageEntry = string | ImageRequireSource | ImageSourceWithSdf; export interface ImagesProps extends BaseProps { /** * Specifies the images in key-value pairs required for the style. Keys are * names used in style expressions (e.g., "customIcon"). * * Values provide a `source`, which can be one of the following types: * - A string URL: `"https://example.com/icon.png"` * - A native asset name: `"pin"` (from xcassets on iOS or drawable on Android) * - A require/import: `require('./icon.png')` * * If your image supports SDF, you can set the `sdf` property to true: * `{ source: require('./sdf-icon.png'), sdf: true }` * * @example * ```tsx * ; * ``` */ images: { [key: string]: ImageEntry }; /** * Called when a layer references an image that is not present in the style. You * can use this to dynamically add images on demand. * * @example * ```tsx * { * setImages((prev) => ({ ...prev, [event.nativeEvent.image]: fallbackIcon })); * }} * />; * ``` */ onImageMissing?: (event: NativeSyntheticEvent<{ image: string }>) => void; } /** * Images defines the images used in Symbol layers. * * Use this component to add images to the map style that can be referenced by * symbol layers using the `iconImage` property. */ export const Images = ({ testID, images, onImageMissing }: ImagesProps) => { const nativeImages = useMemo(() => { const result: Record = {}; Object.entries(images).forEach(([imageName, value]) => { if (typeof value === "string") { result[imageName] = { uri: value, }; } else { const resolved = Image.resolveAssetSource( typeof value === "number" ? value : value.source, ); result[imageName] = { uri: resolved.uri, scale: resolved.scale, sdf: typeof value === "object" ? value.sdf : false, }; } }); return result; }, [images]); return ( ); };