UNPKG

@hhgtech/hhg-components

Version:
226 lines (220 loc) • 10.5 kB
import { a as __awaiter } from './tslib.es6-ea4dfe68.js'; import React__default, { useState, useEffect, useRef, useContext, useMemo } from 'react'; import { Box, useMantineTheme } from '@mantine/core'; import { I as ImageWrap } from './useScreenSize-981e5b51.js'; import { T as TogetherComponentGlobalContext, c as callApi, d as getApiPath } from './utils-40e61585.js'; import styled from '@emotion/styled'; import { PATHS } from './togetherApiPaths.js'; import { D as DEFAULT_IMG } from './constants-f4091ce6.js'; import { y as youtubeVidIdGetter } from './post-44f3801c.js'; import { L as Loading } from './index-b94d1262.js'; const StyledSocialLinkPreview = styled.div ` .link-info-container { padding: 0.5rem 1rem; background: ${(props) => props.color || '#f4faff'}; } .link-image-wrapper { position: relative; overflow: hidden; width: 100%; padding-top: 56.25%; &.fetching { background: lightgray; } .loading-spinner { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .link-image { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; } } a { text-decoration: none; } &[data-is-marrybaby='true'] { overflow: hidden; border-radius: 1rem; } `; const useExternalScript = ({ url, onLoad, onError }) => { const [state, setState] = useState(url ? 'loading' : 'idle'); useEffect(() => { if (!url) { setState('idle'); return; } let script = document.querySelector(`script[src="${url}"]`); const handleLoadScript = () => { setState('ready'); onLoad === null || onLoad === void 0 ? void 0 : onLoad(); }; const handleErrorScript = () => { setState('error'); onError === null || onError === void 0 ? void 0 : onError(); }; if (!script) { script = document.createElement('script'); script.type = 'application/javascript'; script.src = url; script.async = true; document.body.appendChild(script); script.addEventListener('load', handleLoadScript); script.addEventListener('error', handleErrorScript); } script.addEventListener('load', handleLoadScript); script.addEventListener('error', handleErrorScript); return () => { script.removeEventListener('load', handleLoadScript); script.removeEventListener('error', handleErrorScript); }; }, [url]); return state; }; const YoutubePlyr = ({ id, autoplay }) => { const ref = useRef(null); const state = useExternalScript({ url: 'https://cdn.plyr.io/3.7.8/plyr.js' }); useEffect(() => { if (!document.getElementById('hhg-plyr-player')) { const link = document.createElement('link'); link.rel = 'stylesheet'; link.type = 'text/css'; link.href = 'https://cdn.plyr.io/3.7.8/plyr.css'; link.id = 'hhg-plyr-player'; document.head.appendChild(link); } if (state === 'ready' || typeof Plyr !== 'undefined') { new Plyr(ref.current.querySelector('[data-id="player"]'), { autoplay, muted: true, }); } }, [state]); return (React__default.createElement(React__default.Fragment, null, React__default.createElement(Box, { ref: ref, sx: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: '#000', '&, > div': { width: '100%', height: '100%', }, } }, React__default.createElement("div", { "data-id": "player" }, React__default.createElement("iframe", { width: "100%", height: "100%", src: `https://www.youtube.com/embed/${id}?&mute=1&enablejsapi=1&rel=0`, allowFullScreen: true, frameBorder: "0" }))))); }; const SocialLinkPreview = ({ url, image, className, style, baseUrl = '', autoPlay = true, onPushStatus, }) => { const { data: { locale }, } = useContext(TogetherComponentGlobalContext); const [previewData, setPreviewData] = useState(null); useEffect(() => { (() => __awaiter(void 0, void 0, void 0, function* () { if (image) return; if (!url) return setPreviewData(null); setPreviewData((_data) => (Object.assign(Object.assign({}, _data), { isFetching: true }))); // fetch('./api/fetch-meta?url=' + encodeURIComponent(url)) // .then((res) => res.json()) // .then((res) => // setPreviewData({ // url, // image: res?.image || res?.logo, // }), // ) callApi(getApiPath(PATHS.FETCH_PREVIEW, { _locale: locale, }, undefined, baseUrl), 'POST', { data: { link: url, }, headers: { 'Content-Type': 'application/json', }, }, !!baseUrl) .then((res) => { var _a, _b; setPreviewData({ url, image: ((_a = res === null || res === void 0 ? void 0 : res.data) === null || _a === void 0 ? void 0 : _a.image) || ((_b = res === null || res === void 0 ? void 0 : res.data) === null || _b === void 0 ? void 0 : _b.logo), }); }) .catch(() => { setPreviewData(null); }); }))(); }, [url, image]); const displayImage = image || (previewData === null || previewData === void 0 ? void 0 : previewData.image); const displayUrl = (previewData === null || previewData === void 0 ? void 0 : previewData.url) || url; const youtubeVidId = useMemo(() => { return youtubeVidIdGetter(displayUrl); }, [displayUrl]); const facebookVidId = useMemo(() => { return (displayUrl.includes('facebook.com') || displayUrl.includes('fb.watch')); }, [displayUrl]); const responsiveWidth = useRef(0); const responsiveHeight = useRef(0); const [forceRerenderFB, setForceRerenderFB] = useState(false); // FACEBOOK Video is not responsive for desktop browser // => hack: set size to same as container, if size change too large, re-render facebook iframe with new config useEffect(() => { const handleResize = () => { var _a; const containerRect = (_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect(); let toChangeSize = false; if (containerRect && (!responsiveWidth.current || Math.abs((responsiveWidth.current - containerRect.width) / (containerRect === null || containerRect === void 0 ? void 0 : containerRect.width)) > 0.2)) { responsiveWidth.current = Math.floor(containerRect.width); toChangeSize = true; } if (containerRect && (!responsiveHeight.current || Math.abs((responsiveHeight.current - containerRect.height) / (containerRect === null || containerRect === void 0 ? void 0 : containerRect.height)) > 0.2)) { responsiveHeight.current = Math.floor(containerRect.height); toChangeSize = true; } if (toChangeSize) { setForceRerenderFB((v) => !v); } }; handleResize(); window.addEventListener('resize', handleResize, { passive: true, }); return () => { window.removeEventListener('resize', handleResize); }; }, []); useEffect(() => { if ((previewData === null || previewData === void 0 ? void 0 : previewData.image) && (previewData === null || previewData === void 0 ? void 0 : previewData.url)) { onPushStatus === null || onPushStatus === void 0 ? void 0 : onPushStatus(true); } }, [previewData]); const containerRef = useRef(null); const _theme = useMantineTheme(); return (React__default.createElement(StyledSocialLinkPreview, { className: `${className} no-replace-click`, style: style, ref: containerRef, color: _theme.colors[_theme.primaryColor][0] }, !image && (youtubeVidId || facebookVidId) ? (React__default.createElement("div", { className: "link-image-wrapper" }, youtubeVidId ? (React__default.createElement(YoutubePlyr, { id: youtubeVidId, autoplay: autoPlay })) : facebookVidId ? (React__default.createElement("iframe", { key: String(forceRerenderFB), src: `https://www.facebook.com/plugins/video.php?href=${encodeURIComponent(displayUrl)}&autoplay=${autoPlay ? 1 : 0}&show_text=false&t=0&width=${responsiveWidth.current}&height=${responsiveHeight.current}`, style: { position: 'absolute', top: '50%', left: '50%', border: 'none', overflow: 'hidden', height: responsiveHeight.current, width: responsiveWidth.current, transform: 'translate(-50%, -50%)', }, scrolling: "no", frameBorder: "0", allowFullScreen: true, allow: "autoplay; clipboard-write; encrypted-media; picture-in-picture; web-share", loading: "lazy" })) : null)) : (React__default.createElement("a", { href: displayUrl, target: "_blank", rel: "noreferrer" }, React__default.createElement("div", { className: `link-image-wrapper ${(previewData === null || previewData === void 0 ? void 0 : previewData.isFetching) ? 'fetching' : ''}` }, (previewData === null || previewData === void 0 ? void 0 : previewData.isFetching) ? (React__default.createElement(Loading, { className: "loading-spinner" })) : (React__default.createElement(ImageWrap, { className: "link-image", src: displayImage || DEFAULT_IMG, backupSrc: DEFAULT_IMG, alt: displayUrl }))))))); }; export { SocialLinkPreview as S };