tilda-component
Version:
React компонент для встраивания Tilda блоков через iframe
1 lines • 7.46 kB
Source Map (JSON)
{"version":3,"sources":["../src/TildaComponent.tsx","../src/TildaComponent.module.scss"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport styles from \"./TildaComponent.module.scss\";\n\nexport type Tilda = {\n css: string[];\n js: string[];\n promoBlockId: number;\n content: string;\n};\n\ntype BlobProps = {\n cssArr: string[];\n jsArr: string[];\n id: number;\n};\n\ntype IframeElement = HTMLIFrameElement & {\n initHTML?: () => string;\n};\n\ntype Props = {\n tilda: Tilda;\n className?: string;\n onError?: (_error: ErrorEvent) => void;\n onLoad?: () => void;\n};\n\nexport const TildaComponent = ({\n tilda,\n className,\n onError,\n onLoad,\n}: Props) => {\n const ref = useRef<IframeElement>(null);\n\n const getGeneratedPageURL = ({ cssArr, jsArr, id }: BlobProps) => {\n const getBlobURL = (code: string, type: string) => {\n const blob = new Blob([code], { type });\n return URL.createObjectURL(blob);\n };\n\n const getCSS = (cssArray: string[]) =>\n cssArray\n .map(css => `<link rel=\"stylesheet\" type=\"text/css\" href=\"${css}\" />`)\n .join(' ');\n\n const getJS = (jsArray: string[]) =>\n jsArray\n .map(js => `<script src=\"${js}\" blocking=\"render\"></script>`)\n .join(' ');\n\n const source = `\n <html>\n <head>\n ${getCSS(cssArr)}\n ${getJS(jsArr)}\n </head>\n <body style=\"overflow: hidden\">\n <div id=\"tilda\">tilda body content</div>\n <script>\n const EL = document.getElementById('tilda');\n const IFRAME = window.parent.document.getElementById('iframe${id}');\n const setHTML = (html) => {\n const range = document.createRange();\n range.selectNode(EL);\n const documentFragment = range.createContextualFragment(html);\n EL.innerHTML = '';\n EL.append(documentFragment);\n };\n document.onreadystatechange = () => {\n if (document.readyState === \"complete\") {\n const html = IFRAME.initHTML();\n setHTML(html);\n // Уведомляем родительское окно о полной загрузке контента\n window.parent.postMessage({ \n type: 'TILDA_CONTENT_LOADED', \n blockId: ${id} \n }, '*');\n }\n };\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n IFRAME.style.height = entry.target.clientHeight + 30 +'px';\n }\n });\n resizeObserver.observe(EL);\n window.addEventListener('unload', () => resizeObserver.disconnect());\n </script>\n </body>\n </html>\n `;\n\n return getBlobURL(source, 'text/html');\n };\n\n useEffect(() => {\n let url = '';\n if (ref.current && tilda.content) {\n // Отзываем предыдущий URL\n if (ref.current.src.startsWith('blob:')) {\n URL.revokeObjectURL(ref.current.src);\n }\n\n url = getGeneratedPageURL({\n cssArr: tilda.css,\n jsArr: tilda.js,\n id: tilda.promoBlockId,\n });\n ref.current.src = url;\n ref.current.initHTML = () => tilda.content;\n }\n return () => {\n if (url) URL.revokeObjectURL(url);\n };\n }, [tilda]);\n\n useEffect(() => {\n const handleError =\n onError ||\n ((error: ErrorEvent) => {\n console.error('Iframe loading failed:', error);\n });\n const iframe = ref.current;\n\n if (iframe) {\n iframe.addEventListener('error', handleError);\n return () => iframe.removeEventListener('error', handleError);\n }\n }, [onError]);\n\n /** Обработка сообщений от iframe для отслеживания загрузки контента */\n useEffect(() => {\n const handleMessage = (event: MessageEvent) => {\n if (\n event.data.type === 'TILDA_CONTENT_LOADED' &&\n event.data.blockId === tilda.promoBlockId\n ) {\n // Вызываем onLoad когда контент полностью загружен\n if (onLoad) onLoad();\n }\n };\n\n window.addEventListener('message', handleMessage);\n return () => window.removeEventListener('message', handleMessage);\n }, [onLoad, tilda.promoBlockId]);\n\n /** Дополнительный обработчик для события load самого iframe (до загрузки контента) */\n useEffect(() => {\n const iframe = ref.current;\n\n const handleIframeLoad = () => {\n // Этот обработчик срабатывает когда iframe загрузился, но контент еще может грузиться\n console.log('Iframe DOM loaded');\n };\n\n if (iframe) {\n iframe.addEventListener('load', handleIframeLoad);\n return () => iframe.removeEventListener('load', handleIframeLoad);\n }\n }, []);\n\n return (\n <div className={className ? className : styles.container}>\n <iframe\n ref={ref}\n style={{ width: '100%' }}\n id={`iframe${tilda.promoBlockId}`}\n />\n </div>\n );\n};",".container {\n width: 100%;\n overflow: hidden;\n}\n"],"mappings":"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","names":[]}