import React, { useRef, useEffect } from "react"; import { useRecoilValue, useSetRecoilState } from "recoil"; import { motion } from "framer-motion"; import { Svg2Png } from "svg2png-converter"; import { saveAs } from "file-saver"; import { Copy, X, CheckCircle, Download } from "phosphor-react"; import ReactGA from "react-ga"; import { iconWeightAtom, iconSizeAtom, iconColorAtom, iconPreviewOpenAtom, } from "../../state/atoms"; import useTransientState from "../../hooks/useTransientState"; import TagCloud from "./TagCloud"; import { IconEntry } from "../../lib"; const panelVariants = { open: { opacity: 1, height: "100%", marginTop: 4, marginBottom: 4, // transition: { stiffness: 600, damping: 32, duration: 0.2 }, }, collapsed: { opacity: 0, height: 0, marginTop: 0, marginBottom: 0, // transition: { stiffness: 600, damping: 32, duration: 0.2 }, }, }; const contentVariants = { open: { opacity: 1, transition: { duration: 0.2 } }, collapsed: { opacity: 0, transition: { duration: 0.1 } }, }; const buttonColor = "#35313D"; const successColor = "#1FA647"; const disabledColor = "#B7B7B7"; interface InfoPanelProps { index: number; spans: number; isDark: boolean; entry: IconEntry; } const DetailsPanel: React.FC = (props) => { const { index, spans, isDark, entry } = props; const { name, Icon, categories, tags } = entry; const weight = useRecoilValue(iconWeightAtom); const size = useRecoilValue(iconSizeAtom); const color = useRecoilValue(iconColorAtom); const setOpen = useSetRecoilState(iconPreviewOpenAtom); const [copied, setCopied] = useTransientState(false, 2000); const ref = useRef(null); useEffect( () => ReactGA.event({ category: "Grid", action: "Details", label: name }), [name] ); const buttonBarStyle: React.CSSProperties = { color: isDark ? "white" : buttonColor, }; const snippetButtonStyle: React.CSSProperties = weight === "duotone" ? { color: disabledColor, userSelect: "none" } : { color: buttonColor }; const snippets = { html: weight === "duotone" ? "This weight is not yet supported" : ``, react: `<${Icon.displayName} size={${size}} ${ color !== "#000000" ? `color="${color}" ` : "" }${weight === "regular" ? "" : `weight="${weight}" `}/>`, vue: ``, }; const handleCopySnippet = ( event: React.MouseEvent, type: "html" | "react" | "vue" ) => { event.currentTarget.blur(); setCopied(type); const data = snippets[type]; data && void navigator.clipboard?.writeText(data); }; const handleCopySVG = ( event: React.MouseEvent ) => { event.currentTarget.blur(); setCopied("svg"); ref.current && void navigator.clipboard?.writeText(ref.current.outerHTML); }; const handleDownloadSVG = ( event: React.MouseEvent ) => { event.currentTarget.blur(); if (!ref.current?.outerHTML) return; const blob = new Blob([ref.current.outerHTML]); saveAs(blob, `${name}${weight === "regular" ? "" : `-${weight}`}.svg`); }; const handleDownloadPNG = async ( event: React.MouseEvent ) => { event.currentTarget.blur(); if (!ref.current?.outerHTML) return; Svg2Png.save( ref.current, `${name}${weight === "regular" ? "" : `-${weight}`}.png`, { scaleX: 1.334, scaleY: 1.334 } ); }; return (

{name}

([...categories, ...name.split("-"), ...tags]) )} isDark={isDark} />
React
            {snippets.react}
            
          
Vue
            {snippets.vue}
            
          
HTML/CSS
            {snippets.html}
            
          
setOpen(false)} onKeyDown={(e) => { e.key === "Enter" && setOpen(false); }} />
); }; export default DetailsPanel;