import { NodeViewWrapper } from '@tiptap/react' import React, { useState, useRef, useEffect } from 'react' import { Upload, Link as LinkIcon, GripVertical, GripHorizontal, AlignCenter, Cuboid, Code } from 'lucide-react' import { useEditorProvider } from '@components/Contexts/Editor/EditorContext' import { SiGithub, SiReplit, SiSpotify, SiLoom, SiGooglemaps, SiCodepen, SiCanva, SiNotion, SiGoogledocs, SiGitlab, SiX, SiFigma, SiGiphy } from '@icons-pack/react-simple-icons' import { useRouter } from 'next/navigation' import DOMPurify from 'dompurify' function EmbedObjectsComponent(props: any) { const [embedType, setEmbedType] = useState<'url' | 'code'>(props.node.attrs.embedType || 'url') const [embedUrl, setEmbedUrl] = useState(props.node.attrs.embedUrl || '') const [embedCode, setEmbedCode] = useState(props.node.attrs.embedCode || '') const [embedHeight, setEmbedHeight] = useState(props.node.attrs.embedHeight || 300) const [embedWidth, setEmbedWidth] = useState(props.node.attrs.embedWidth || '100%') const [alignment, setAlignment] = useState(props.node.attrs.alignment || 'left') const resizeRef = useRef(null) const editorState = useEditorProvider() as any const isEditable = editorState.isEditable const router = useRouter() const supportedProducts = [ { name: 'GitHub', icon: SiGithub, color: '#181717', guide: 'https://emgithub.com/' }, { name: 'Replit', icon: SiReplit, color: '#F26207', guide: 'https://docs.replit.com/hosting/embedding-repls' }, { name: 'Spotify', icon: SiSpotify, color: '#1DB954', guide: 'https://developer.spotify.com/documentation/embeds' }, { name: 'Loom', icon: SiLoom, color: '#625DF5', guide: 'https://support.loom.com/hc/en-us/articles/360002208317-How-to-embed-your-video-into-a-webpage' }, { name: 'GMaps', icon: SiGooglemaps, color: '#4285F4', guide: 'https://developers.google.com/maps/documentation/embed/get-started' }, { name: 'CodePen', icon: SiCodepen, color: '#000000', guide: 'https://blog.codepen.io/documentation/embedded-pens/' }, { name: 'Canva', icon: SiCanva, color: '#00C4CC', guide: 'https://www.canva.com/help/article/embed-designs' }, { name: 'Notion', icon: SiNotion, color: '#878787', guide: 'https://www.notion.so/help/embed-and-connect-other-apps#7a70ac4b5c5f4ec889e69d262e0de9e7' }, { name: 'G Docs', icon: SiGoogledocs, color: '#4285F4', guide: 'https://support.google.com/docs/answer/183965?hl=en&co=GENIE.Platform%3DDesktop' }, { name: 'X', icon: SiX, color: '#000000', guide: 'https://help.twitter.com/en/using-twitter/how-to-embed-a-tweet' }, { name: 'Figma', icon: SiFigma, color: '#F24E1E', guide: 'https://help.figma.com/hc/en-us/articles/360041057214-Embed-files-and-prototypes' }, { name: 'Giphy', icon: SiGiphy, color: '#FF6666', guide: 'https://developers.giphy.com/docs/embed/' }, ] const [sanitizedEmbedCode, setSanitizedEmbedCode] = useState('') useEffect(() => { if (embedType === 'code' && embedCode) { const sanitized = DOMPurify.sanitize(embedCode, { ADD_TAGS: ['iframe'], ADD_ATTR: ['*'] }) setSanitizedEmbedCode(sanitized) } }, [embedCode, embedType]) const handleEmbedTypeChange = (type: 'url' | 'code') => { setEmbedType(type) props.updateAttributes({ embedType: type }) } const handleUrlChange = (event: React.ChangeEvent) => { const newUrl = event.target.value; // Sanitize the URL const sanitizedUrl = DOMPurify.sanitize(newUrl); setEmbedUrl(sanitizedUrl); props.updateAttributes({ embedUrl: sanitizedUrl, embedType: 'url', }); }; const handleCodeChange = (event: React.ChangeEvent) => { const newCode = event.target.value; setEmbedCode(newCode); props.updateAttributes({ embedCode: newCode, embedType: 'code', }); }; const handleResizeStart = (event: React.MouseEvent, direction: 'horizontal' | 'vertical') => { event.preventDefault() const startX = event.clientX const startY = event.clientY const startWidth = resizeRef.current?.offsetWidth || 0 const startHeight = resizeRef.current?.offsetHeight || 0 const handleMouseMove = (e: MouseEvent) => { if (resizeRef.current) { if (direction === 'horizontal') { const newWidth = startWidth + e.clientX - startX const parentWidth = resizeRef.current.parentElement?.offsetWidth || 1 const widthPercentage = Math.min(100, Math.max(10, (newWidth / parentWidth) * 100)) const newWidthValue = `${widthPercentage}%` setEmbedWidth(newWidthValue) props.updateAttributes({ embedWidth: newWidthValue }) } else { const newHeight = Math.max(100, startHeight + e.clientY - startY) setEmbedHeight(newHeight) props.updateAttributes({ embedHeight: newHeight }) } } } const handleMouseUp = () => { document.removeEventListener('mousemove', handleMouseMove) document.removeEventListener('mouseup', handleMouseUp) } document.addEventListener('mousemove', handleMouseMove) document.addEventListener('mouseup', handleMouseUp) } const handleCenterBlock = () => { const newAlignment = alignment === 'center' ? 'left' : 'center' setAlignment(newAlignment) props.updateAttributes({ alignment: newAlignment }) } const handleProductClick = (guide: string) => { window.open(guide, '_blank', 'noopener,noreferrer') } return (
{embedType === 'url' && embedUrl ? (