2019-01-15 22:23:15 +03:00
|
|
|
import React from 'react'
|
|
|
|
import ReactDOM from 'react-dom'
|
|
|
|
import {BorderBox} from '@primer/components'
|
2019-01-16 01:16:25 +03:00
|
|
|
import {assetPrefix} from './utils'
|
2019-01-15 22:23:15 +03:00
|
|
|
|
2019-01-17 01:58:41 +03:00
|
|
|
const DEFAULT_IFRAME_HEIGHT = 150
|
|
|
|
|
2019-01-15 22:23:15 +03:00
|
|
|
export default class Frame extends React.Component {
|
2019-01-16 01:16:25 +03:00
|
|
|
static defaultProps = {
|
|
|
|
border: 0,
|
2019-01-17 01:58:41 +03:00
|
|
|
borderRadius: 0,
|
|
|
|
minHeight: 0,
|
2019-01-16 01:16:25 +03:00
|
|
|
width: '100%'
|
|
|
|
}
|
|
|
|
|
2019-01-17 01:58:41 +03:00
|
|
|
constructor(props) {
|
|
|
|
super(props)
|
|
|
|
this.state = {files: [], height: props.height}
|
|
|
|
}
|
|
|
|
|
2019-01-15 22:23:15 +03:00
|
|
|
componentDidMount() {
|
|
|
|
this.doc = this.node.contentDocument
|
2019-01-17 01:58:41 +03:00
|
|
|
const files = JSON.parse(document.body.dataset.files || '[]')
|
2019-01-17 09:50:10 +03:00
|
|
|
// eslint-disable-next-line react/no-did-mount-set-state
|
2019-01-17 01:58:41 +03:00
|
|
|
this.setState({files})
|
|
|
|
this.node.addEventListener('load', () => this.setState({loaded: true}))
|
2019-01-15 22:23:15 +03:00
|
|
|
}
|
|
|
|
|
2019-01-16 01:16:25 +03:00
|
|
|
getCssLinks() {
|
2019-01-17 01:58:41 +03:00
|
|
|
const {files} = this.state
|
|
|
|
return files
|
|
|
|
? files
|
|
|
|
.filter(file => file.endsWith('.css'))
|
|
|
|
.map(file => <link rel="stylesheet" href={`${assetPrefix}/_next/${file}`} key={file} />)
|
|
|
|
: null
|
|
|
|
}
|
|
|
|
|
|
|
|
getHeight() {
|
|
|
|
if (!this.node) return null
|
|
|
|
this.node.style.height = 'max-content'
|
|
|
|
const {body} = this.node.contentDocument
|
|
|
|
return body.offsetHeight > DEFAULT_IFRAME_HEIGHT ? body.offsetHeight : body.scrollHeight
|
2019-01-16 01:16:25 +03:00
|
|
|
}
|
|
|
|
|
2019-01-15 22:23:15 +03:00
|
|
|
render() {
|
2019-01-16 01:16:25 +03:00
|
|
|
const {children, ...rest} = this.props
|
2019-01-17 01:58:41 +03:00
|
|
|
const height = this.getHeight()
|
|
|
|
const style = height ? {height} : null
|
2019-01-15 22:23:15 +03:00
|
|
|
return (
|
2019-01-17 01:58:41 +03:00
|
|
|
<BorderBox as="iframe" style={style} {...rest} ref={node => (this.node = node)}>
|
|
|
|
{this.doc
|
|
|
|
? [ReactDOM.createPortal(this.getCssLinks(), this.doc.head), ReactDOM.createPortal(children, this.doc.body)]
|
|
|
|
: null}
|
2019-01-15 22:23:15 +03:00
|
|
|
</BorderBox>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|