@ubertheme/slider
Version:
UB Slider Module for Magento PWA Studio
200 lines (188 loc) • 6.05 kB
JavaScript
import React from 'react';
import {string, number, shape} from 'prop-types';
import {Link, resourceUrl} from '@magento/venia-ui/lib/drivers';
import ReactPlayer from 'react-player'
import RickText from '@magento/venia-ui/lib/components/RichText';
import { useItem } from '../../talons/Slider/useItem';
import { mergeClasses } from '@magento/venia-ui/lib/classify';
import defaultClasses from './styles/item.css';
import { useExtraCss } from '@ubertheme/base/src/talons/useExtraCss';
import { generateSrcset, generateUrl } from '@magento/venia-ui/lib/util/images';
import { UNCONSTRAINED_SIZE_KEY } from '@magento/peregrine/lib/talons/Image/useImage';
/**
* Item component.
*
* This component is a renderer of slide item
*
* @typedef Item
* @kind functional component
*
* @param {Object} props React component props
*
* @returns {React.Element} A React component.
*/
const Item = props => {
const {
parentStyle = 'default',
item,
height,
width,
mobileWidth
} = props;
// Mapping width by breakpoint to optimize images
const widths = new Map()
.set(640, mobileWidth)
.set(UNCONSTRAINED_SIZE_KEY, width); //default width
// call useItem Hooks
const {
isMobile,
handleClick,
openedId,
imageSizes
} = useItem({ item, width, widths });
const classes = mergeClasses(defaultClasses, props.classes);
const additionalClasses = item.additional_class;
const { classNames } = useExtraCss({classes, additionalClasses});
let itemStyle = {};
let itemClassNames = classNames;
let image = item.image;
if (isMobile && item.mobile_image) {
image = item.mobile_image;
}
let itemContent = null;
if (item.content_type === 'image' && image) {
//generates image sources
const src = generateUrl(
`/media/ubcontentslider/images${image}`,
'image-slide'
)(width, height);
const srcSet = generateSrcset(
`/media/ubcontentslider/images${image}`,
'image-slide'
);
//make content
itemContent = (
<img
loading="lazy"
alt={item.title}
height={height}
width={width}
sizes={imageSizes}
src={src}
srcSet={srcSet}
/>
);
} else if (item.content_type.indexOf('video') !== -1 && item.video_id) {
//append extra css global class 'clickToPlay'
itemClassNames += ' clickToPlay';
//make video url
let videoUrl;
if (item.content_type == 'youtube_video') {
videoUrl = `https://www.youtube.com/watch?v=${item.video_id}`;
} else if (item.content_type == 'vimeo_video') {
videoUrl = `https://vimeo.com/${item.video_id}`;
}
//make cover image urls
let src = null;
let srcSet = null;
if (item.video_cover) {
src = item.video_cover;
const absoluteUrl = /^(data|http|https)?:/i;
const isAbsolute = absoluteUrl.test(src) || (src.indexOf('//') !== -1);
if (!isAbsolute) { // has uploaded video cover image
src = generateUrl(
`/media/ubcontentslider/images${item.video_cover}`,
'image-slide'
)(width, height);
srcSet = generateSrcset(
`/media/ubcontentslider/images${item.video_cover}`,
'image-slide'
);
}
}
//make content
itemContent = (
(openedId && openedId === item.id) ?
<ReactPlayer
className='react-player'
url={videoUrl}
width='100%'
height='100%'
controls
playing
/> : (
<span><img
loading="lazy"
alt={item.title}
height={height}
width={width}
sizes={imageSizes}
src={src}
srcSet={srcSet}
/></span>
)
);
}
//build item desc elements
let itemDesc = (
(
item.id !== openedId
|| (item.id == openedId && ( parentStyle === 'outside'
|| (parentStyle !== 'outside' && isMobile)
|| classNames.indexOf('captionedOut') !== -1))
) ?
<div className={'desc'}>
<h3>
<Link
className={''}
to={resourceUrl(`/${item.link}`)}
>
{item.title}
</Link>
</h3>
<RickText
content={item.desc}
classes={{
root: 'descContent'
}}
/>
<Link
className={'readmore'}
to={resourceUrl(`/${item.link}`)}
>
View More
</Link>
</div>
: null
);
return (
<div style={itemStyle} className={itemClassNames}>
<div className={'info'}>
<Link
className={'media'}
to={resourceUrl(`/${item.link}`)}
onClick={(e) => handleClick(e)}
>
{itemContent}
</Link>
{itemDesc}
</div>
</div>
);
};
Item.propTypes = {
id: number,
classes: shape({
root: string
}),
parentStyle: string.isRequired,
item: shape({
title: string.isRequired,
link: string.isRequired,
link_target: string.isRequired
}).isRequired,
height: number,
width: number,
mobileWidth: number
};
export default Item;