import { IMedia, getClassNames, withSchema } from '@websolutespa/bom-core'; import { RefObject, forwardRef } from 'react'; import styled, { css } from 'styled-components'; import { UIComponentWithRef, UIStyledComponentProps } from '../../components/types'; import { getAspectResponsive, getCssResponsive } from '../../components/utils'; import { useMediaGalleryContext } from '../media-gallery/media-gallery-context'; import { MediaSize } from './media-image'; import { MediaItems } from './media-items'; export type MediaInfoProps = UIStyledComponentProps; const StyledMediaInfo = styled.div` position: absolute; display: flex; flex-direction: column; top: 0; left: 0; width: 100%; height: 100%; z-index: 1; color: var(--color-neutral-100); ${props => getCssResponsive(props)} `; const MediaInfo = ({ children, className, ...props }: MediaInfoProps) => { const classNames = getClassNames(className, 'media-info'); return ({children}); }; type Props = { size?: MediaSize; circle?: boolean; rounded?: boolean; overlay?: boolean | number; eager?: boolean; alt?: string; title?: string; informative?: boolean; item?: IMedia | IMedia[]; onLoaded?: (ref: RefObject) => void; canLoad?: boolean; }; export type MediaProps = UIStyledComponentProps; export type MediaComponent = UIComponentWithRef; const StyledMedia = styled.div` position: relative; display: flex; flex-direction: column; justify-content: center; align-items: center; ${props => getCssResponsive(props)} &>:not(.media-info) { width: 100%; height: 100%; } &>.image:not(.image-svg), &>video, &>.video { object-fit: cover; background: transparent; } &>svg { height: 100%; } &.media--gallery { display: flex; justify-content: center; align-items: center; overflow: hidden; cursor: pointer; &>:not(.media-info) { transition: ease-in-out 200ms; transition-property: transform, opacity; } &:hover { &>:not(.media-info) { transform: scale(1.05); } } } ${props => props.circle ? css` aspect-ratio: 1; overflow: hidden; border-radius: 50%; &>* { top: 0; left: 0; height: 100%; } ` : ''} ${props => props.rounded ? css` overflow: hidden; border-radius: var(--border-radius); ` : ''} ${props => getAspectResponsive(props, props.circle ? { aspectRatio: 1 } : undefined)} ${props => props.overlay ? css` position: relative; &:after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; ${getOverlayCss(props.overlay)} } ` : ''} `; function getOverlayCss(overlay: boolean | number): string { return ( typeof overlay === 'number' ? `background: rgba(0,0,0,${overlay});` : 'background: rgba(0,0,0,0.4);' ); // 'background-image: linear-gradient(180deg, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.1) 15.9%, rgba(0, 0, 0, 0) 41.67%, rgba(0, 0, 0, 0.1) 61.79%, rgba(0, 0, 0, 0.6) 100%);' } const MediaBase: MediaComponent = forwardRef(({ children, item, className, width, height, size, eager, alt, title, informative, onClick, onLoaded, canLoad, as = 'div', ...props }, ref) => { const { id, open } = useMediaGalleryContext(); const classNames = getClassNames(className, 'media', { 'media--gallery': id }); const style: { width?: string, height?: string } = {}; if (typeof width === 'string') { style.width = width; } if (typeof height === 'string') { style.height = height; } return ( {children ? ( children ) : ( item && )} ); }); MediaBase.displayName = 'Media'; export const Media = withSchema( MediaBase, { Info: MediaInfo, });