import { IMedia, isMediaImage, isMediaVideo } from '@websolutespa/bom-core'; import { CSSProperties, RefObject, useMemo } from 'react'; import { MediaImage, MediaSize } from './media-image'; import { MediaVideo } from './media-video'; export type IMediaItemOptions = { size?: MediaSize; width?: CSSProperties['width']; height?: CSSProperties['height']; aspectRatio?: CSSProperties['aspectRatio']; aspectRatioSm?: CSSProperties['aspectRatio']; aspectRatioMd?: CSSProperties['aspectRatio']; aspectRatioLg?: CSSProperties['aspectRatio']; aspectRatioXl?: CSSProperties['aspectRatio']; eager?: boolean; galleryId?: string; alt?: string | undefined; title?: string | undefined; open?: (media: IMedia) => void; onLoaded?: (ref: RefObject) => void; canLoad?: boolean; informative?: boolean; }; export type IMediaItemProps = { src?: string | undefined; mimeType?: string | undefined; alt?: string | undefined; title?: string | undefined; mediaWidth?: number; mediaHeight?: number; mediaFocalX?: number; mediaFocalY?: number; width?: CSSProperties['width']; height?: CSSProperties['height']; aspectRatio?: CSSProperties['aspectRatio']; aspectRatioSm?: CSSProperties['aspectRatio']; aspectRatioMd?: CSSProperties['aspectRatio']; aspectRatioLg?: CSSProperties['aspectRatio']; aspectRatioXl?: CSSProperties['aspectRatio']; size?: MediaSize; loading?: 'eager' | 'lazy'; 'data-gallery'?: string; onClick?: (event: React.MouseEvent) => void; onLoaded?: (ref: RefObject) => void; canLoad?: boolean; informative?: boolean; }; export type IMediaItem = IMedia & { mediaWidth?: number; mediaHeight?: number; mediaFocalX?: number; mediaFocalY?: number; width?: CSSProperties['width']; height?: CSSProperties['height']; aspectRatio?: CSSProperties['aspectRatio']; aspectRatioSm?: CSSProperties['aspectRatio']; aspectRatioMd?: CSSProperties['aspectRatio']; aspectRatioLg?: CSSProperties['aspectRatio']; aspectRatioXl?: CSSProperties['aspectRatio']; onLoaded?: (ref: RefObject) => void; canLoad?: boolean; }; export const MediaItem = ({ item, options = {}, }: { item: IMedia, options?: IMediaItemOptions }) => { const mediaItem: IMediaItem = useMemo(() => getMediaItem(item, options), [item, options]); const mediaItemProps: IMediaItemProps = useMemo(() => getMediaItemProps(mediaItem, options), [mediaItem, options]); return (isMediaVideo(mediaItem)) ? ( ) : ( ); }; export const MediaItems = ({ item, options = {}, }: { item: IMedia | IMedia[], options?: IMediaItemOptions }) => { const items = (Array.isArray(item) ? item : [item]); return items.map((item, m) => ( )); }; function getMediaItem(item: IMedia, options: IMediaItemOptions): IMediaItem { if (typeof item['media'] === 'object') { item = item['media']; } const mediaItem: IMediaItem = { type: item.type, src: item.src, }; if (item.abstract) { mediaItem.abstract = item.abstract; } if (item.alt) { mediaItem.alt = item.alt; } if (item.mimeType) { mediaItem.mimeType = item.mimeType; } if (item.url) { mediaItem.src = item.url; } if (item.title) { mediaItem.title = item.title; } if (typeof item.width === 'number') { mediaItem.mediaWidth = item.width; } if (typeof item.height === 'number') { mediaItem.mediaHeight = item.height; } if (typeof item.focalX === 'number') { mediaItem.mediaFocalX = item.focalX; } if (typeof item.focalY === 'number') { mediaItem.mediaFocalY = item.focalY; } mediaItem.width = options.width; mediaItem.height = options.height; mediaItem.aspectRatio = options.aspectRatio; mediaItem.aspectRatioSm = options.aspectRatioSm; mediaItem.aspectRatioMd = options.aspectRatioMd; mediaItem.aspectRatioLg = options.aspectRatioLg; mediaItem.aspectRatioXl = options.aspectRatioXl; mediaItem.onLoaded = options.onLoaded; mediaItem.canLoad = options.canLoad; return mediaItem; } function getMediaItemProps(mediaItem: IMediaItem, options: IMediaItemOptions): IMediaItemProps { const { width, height, sizes, ...media } = mediaItem; const title: string | undefined = (media.title || options.title) as string | undefined; // console.log('getMediaItemProps', media.alt, options.alt); const alt: string | undefined = (media.alt || options.alt) as string | undefined; // const alt: string = (options.alt || ''); const src: string = (media.src || media.url || '') as string; const mediaItemProps: IMediaItemProps = { src, title, alt, size: options.size, mimeType: media.mimeType, onLoaded: mediaItem.onLoaded, canLoad: mediaItem.canLoad, }; const hasGallery = options.galleryId != null && typeof options.open === 'function'; if (hasGallery) { mediaItemProps['data-gallery'] = JSON.stringify({ galleryId: options.galleryId, media }); mediaItemProps.onClick = (event: React.MouseEvent) => { if (options.open) { options.open(media); } }; } if (isMediaImage(media)) { mediaItemProps.mediaWidth = mediaItem.mediaWidth; mediaItemProps.mediaHeight = mediaItem.mediaHeight; mediaItemProps.mediaFocalX = mediaItem.mediaFocalX; mediaItemProps.mediaFocalY = mediaItem.mediaFocalY; mediaItemProps.width = options.width; mediaItemProps.height = options.height; mediaItemProps.aspectRatio = options.aspectRatio; mediaItemProps.aspectRatioSm = options.aspectRatioSm; mediaItemProps.aspectRatioMd = options.aspectRatioMd; mediaItemProps.aspectRatioLg = options.aspectRatioLg; mediaItemProps.aspectRatioXl = options.aspectRatioXl; mediaItemProps.informative = options.informative; if (options.eager) { mediaItemProps.loading = 'eager'; } } return mediaItemProps; }