import * as React from 'react'; import styled from 'styled-components'; import { colors } from '../variables'; import BaseButton from './Button'; interface CodeProps { children: React.ReactNode; language?: string; } interface CodeState { hlCode?: string; copied?: boolean; } const Button = styled(BaseButton)` opacity: 0; position: absolute; top: 1rem; right: 1rem; transition: opacity 0.2s; `; const Base = styled.div < CodeProps > ` color: ${props => (props.language === undefined ? colors.white : 'inherit')}; background-color: ${props => (props.language === undefined ? colors.black : colors.lightGray)}; white-space: ${props => (props.language === undefined ? 'nowrap' : '')}; position: relative; &:hover ${Button} { opacity: 1; } `; const StyledCode = styled.code` padding: 1.5rem; display: block; overflow-y: scroll; -webkit-overflow-scrolling: touch; `; const StyledPre = styled.pre` margin: 0; `; const StyledCopyInput = styled.textarea` height: 0; position: absolute; top: 0; right: 0; z-index: -1; `; const CopyInput = StyledCopyInput as any; class Code extends React.Component { code = React.createRef(); state: CodeState = {}; constructor(props: CodeProps) { super(props); } async componentDidMount() { const { language, children } = this.props; if (language !== undefined) { const { highlight } = await import(/* webpackChunkName: 'highlight.js' */ 'highlight.js'); const { value: hlCode } = highlight(language, children as string); this.setState({ hlCode }); } } handleCopy = async () => { try { if ('clipboard' in navigator) { await (navigator as any).clipboard.writeText(this.props.children); this.setState({ copied: true }); } else { this.code.current.focus(); this.code.current.select(); document.execCommand('copy'); this.setState({ copied: true }); } } catch (error) { this.setState({ copied: false }); } }; render() { const { language, children } = this.props; return ( {this.state.hlCode !== undefined ? ( ) : ( {this.props.children} )} {!('clipboard' in navigator) ? (