import * as AllIcons from 'iconoir-react'; import React from 'react'; import styled from 'styled-components'; import { showNotification } from '../lib/showNotification'; import { ResetButton } from './Button'; import { DEFAULT_CUSTOMIZATIONS, Icon as IconType } from './IconList'; const HEADER = ''; function bakeSvg( svgString: string, color: string, strokeWidth: string | number, ) { return ( HEADER + svgString .replace( /stroke="currentColor"/g, `stroke="currentColor" stroke-width="${strokeWidth}"`, ) .replace(/currentColor/g, color) ); } export interface IconProps { iconWidth: number; icon: IconType; } export function Icon({ iconWidth, icon }: IconProps) { const IconComponent = (AllIcons as any)[icon.iconComponentName]; const iconContainerRef = React.useRef(null); const downloadRef = React.useRef(null); const htmlContentsRef = React.useRef(''); const iconContext = React.useContext(AllIcons.IconoirContext); const [supportsClipboard, setSupportsClipboard] = React.useState(false); React.useEffect(() => { setSupportsClipboard( typeof window !== 'undefined' && typeof window?.navigator?.clipboard?.writeText !== 'undefined', ); }, []); React.useEffect(() => { if (iconContainerRef.current) { htmlContentsRef.current = bakeSvg( (iconContainerRef.current.firstChild as SVGElement).outerHTML, iconContext.color || DEFAULT_CUSTOMIZATIONS.hexColor, iconContext.strokeWidth || DEFAULT_CUSTOMIZATIONS.strokeWidth, ); } }, [iconContext, supportsClipboard]); React.useEffect(() => { const element = downloadRef.current || (iconContainerRef.current as unknown as HTMLAnchorElement); if (element) { element.href = `data:image/svg+xml;base64,${btoa( htmlContentsRef.current, )}`; } }, [iconContext, supportsClipboard]); return (
{icon.filename.includes('-solid') ? SOLID : ''} {supportsClipboard ? ( { if (htmlContentsRef.current) { navigator.clipboard .writeText(htmlContentsRef.current) .then(() => { showNotification('SVG code copied!'); }) .catch((err) => { console.error(err); }); } }} > Copy SVG Download ) : null} {icon.filename}
); } const Overlay = styled.div` position: absolute; border-radius: 50%; border: solid 2px var(--g0); background: var(--white); width: 8px; height: 8px; `; const CornerBR = styled(Overlay)` bottom: -6px; right: -6px; z-index: 999; `; const CornerTR = styled(Overlay)` top: -6px; right: -6px; `; const CornerBL = styled(Overlay)` bottom: -6px; left: -6px; `; const CornerTL = styled(Overlay)` top: -6px; left: -6px; `; const HoverContainer = styled.div` position: absolute; inset: 0; display: flex; align-items: stretch; justify-content: stretch; flex-direction: column; transform: translateZ(0px); // Safari Fix transition: opacity 0.1s linear; opacity: 0; pointer-events: none; `; const HoverButton = styled(ResetButton)` &&& { display: flex; align-items: center; justify-content: center; background: var(--white); border-radius: 0px; transition: background 0.1s linear; color: var(--g0); font-size: 14px; line-height: 23px; font-weight: 700; text-align: center; flex: 1; cursor: pointer; text-decoration: none; &:hover, &:active { background: var(--g0); color: var(--white); } } `; const BorderContainer = styled.div<{ $iconWidth: number }>` width: ${(props) => props.$iconWidth}px; box-sizing: border-box; padding-bottom: 100%; position: relative; border: solid 1px var(--g6); border-radius: 12px; margin-bottom: 10px; @media (hover: hover) { &:hover ${HoverContainer} { opacity: 1; pointer-events: all; border: solid 2px var(--g0); } } `; const IconContainer = styled.div` position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; `; const IconTag = styled.div` background-color: var(--g6); position: absolute; top: 0px; right: 0px; border-radius: 5px 10px; padding: 3px 6px; letter-spacing: 0.3px; font-weight: 600; font-size: 11px; color: var(--g0); `; const Subtitle = styled.div<{ $iconWidth: number }>` font-size: 11px; font-weight: 500; line-height: 14.74px; color: var(--black-60); text-align: center; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; width: ${(props) => props.$iconWidth}px; `;