import { getLayoutStyles, CodeEmbedItem as TCodeEmbedItem, AreaAnchor, FontFaceGenerator } from '@cntrl-site/sdk'; import { FC, useEffect, useId, useState } from 'react'; import { useCntrlContext } from '../../../provider/useCntrlContext'; import { ItemProps } from '../Item'; import JSXStyle from 'styled-jsx/style'; import { useRegisterResize } from '../../../common/useRegisterResize'; import { useItemAngle } from '../useItemAngle'; import { LinkWrapper } from '../LinkWrapper'; import { useCodeEmbedItem } from './useCodeEmbedItem'; import { useItemGeometry } from '../../../ItemGeometry/useItemGeometry'; const stylesMap = { [AreaAnchor.TopLeft]: {}, [AreaAnchor.TopCenter]: { justifyContent: 'center' }, [AreaAnchor.TopRight]: { justifyContent: 'flex-end' }, [AreaAnchor.MiddleLeft]: { alignItems: 'center' }, [AreaAnchor.MiddleCenter]: { justifyContent: 'center', alignItems: 'center' }, [AreaAnchor.MiddleRight]: { justifyContent: 'flex-end', alignItems: 'center' }, [AreaAnchor.BottomLeft]: { alignItems: 'flex-end' }, [AreaAnchor.BottomCenter]: { justifyContent: 'center', alignItems: 'flex-end' }, [AreaAnchor.BottomRight]: { justifyContent: 'flex-end', alignItems: 'flex-end' } }; export const CodeEmbedItem: FC> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => { const reactId = useId(); const id = `${reactId}-codeembed-${item.id}`; const { layouts, fonts } = useCntrlContext(); const fontGoogleTags = fonts?.google; const fontAdobeTags = fonts?.adobe; const fontCustomTags = new FontFaceGenerator(fonts?.custom ?? []).generate(); const { anchor, blur: itemBlur, opacity: itemOpacity } = useCodeEmbedItem(item, sectionId); const itemAngle = useItemAngle(item, sectionId); const html = decodeBase64(item.commonParams.html); const [ref, setRef] = useState(null); useRegisterResize(ref, onResize); useItemGeometry(item.id, ref); const pos = stylesMap[anchor]; const layoutValues: Record[] = [item.area, item.layoutParams]; const stateParams = interactionCtrl?.getState(['angle', 'blur', 'opacity']); const blur = (stateParams?.styles?.blur ?? itemBlur) as number; const opacity = stateParams?.styles?.opacity ?? itemOpacity; const angle = stateParams?.styles?.angle ?? itemAngle; useEffect(() => { if (!ref) return; const scripts = ref.querySelectorAll('script'); for (const script of scripts) { const newScript = document.createElement('script'); for (const attr of script.getAttributeNames()) { newScript.setAttribute(attr, script.getAttribute(attr)!); } newScript.textContent = script.textContent; script.parentNode!.removeChild(script); ref.appendChild(newScript); } }, [html]); useEffect(() => { if (!ref) return; const iframe: HTMLIFrameElement | null = ref.querySelector(`[data-embed="${item.id}"]`); if (!iframe) return; const htmlWithStyles = ` ${fontGoogleTags} ${fontAdobeTags} ${html} `; iframe.srcdoc = htmlWithStyles; }, [html, item.commonParams.iframe, ref]); const isInteractive = opacity !== 0; useEffect(() => { onVisibilityChange?.(isInteractive); }, [isInteractive, onVisibilityChange]); return (
{item.commonParams.iframe ? (