diff --git a/examples/iframe-rendering/Readme.md b/examples/iframe-rendering/Readme.md
new file mode 100644
index 000000000..bc30e1aaf
--- /dev/null
+++ b/examples/iframe-rendering/Readme.md
@@ -0,0 +1,7 @@
+
+# IFrame rendering example
+
+This example shows how to render Slate into IFrame, preserving single react component tree.
+You may need this if you want to have separate styles for editor content & application.
+
+Check out the [Examples readme](..) to see how to run it!
diff --git a/examples/iframe-rendering/index.js b/examples/iframe-rendering/index.js
new file mode 100644
index 000000000..d55676233
--- /dev/null
+++ b/examples/iframe-rendering/index.js
@@ -0,0 +1,93 @@
+import React from 'react'
+import ReactDOM from 'react-dom'
+
+function resolveDocument (reactIFrameElementNode) {
+ const iFrame = ReactDOM.findDOMNode(reactIFrameElementNode);
+ return iFrame.contentDocument
+}
+
+//appending context to body > div, to suppress react warning
+function getRootDiv (doc) {
+ let rootDiv = doc.querySelector('div#root')
+ if (!rootDiv) {
+ rootDiv = doc.createElement('div')
+ rootDiv.setAttribute('id', 'root')
+ rootDiv.id = 'root'
+ rootDiv.setAttribute('style', 'width: 100%; height: 100%')
+
+ doc.body.appendChild(rootDiv)
+ }
+ return rootDiv
+}
+
+class IFrame extends React.Component {
+
+ static propTypes = {
+ head: React.PropTypes.node,
+ children: React.PropTypes.node,
+ }
+
+ //rendering plain frame.
+ render () {
+ return
+ }
+
+ componentDidMount = () => {
+ this.renderContents()
+ }
+
+ componentDidUpdate = () => {
+ this.renderContents()
+ }
+
+ componentWillUnmount = () => this.getDocument().then((doc) => {
+ ReactDOM.unmountComponentAtNode(doc.body)
+ if (this.props.head) {
+ ReactDOM.unmountComponentAtNode(doc.head)
+ }
+ })
+
+ renderContents = () => this.getDocument().then((doc) => {
+ if (this.props.head) {
+ ReactDOM.unstable_renderSubtreeIntoContainer(this, this.props.head, doc.head)
+ }
+ const rootDiv = getRootDiv(doc)
+ ReactDOM.unstable_renderSubtreeIntoContainer(this, this.props.children, rootDiv)
+ })
+
+
+ getDocument = () => new Promise((resolve) => {
+ const resolveTick = () => { //using arrow function to preserve `this` context
+ let doc = resolveDocument(this)
+ if (doc && doc.readyState === 'complete') {
+ resolve(doc)
+ } else {
+ window.requestAnimationFrame(resolveTick)
+ }
+ }
+ resolveTick()
+ })
+
+}
+
+class IFrameRendering extends React.Component {
+
+ render () {
+ const bootstrapCDN =
+
+
+
+ return (
+
+ )
+ }
+
+}
+
+export default IFrameRendering
diff --git a/examples/index.js b/examples/index.js
index d894e8666..f1565354e 100644
--- a/examples/index.js
+++ b/examples/index.js
@@ -22,6 +22,7 @@ import RTL from './rtl'
import Tables from './tables'
import DevPerformancePlain from './development/performance-plain'
import DevPerformanceRich from './development/performance-rich'
+import IFrameRendering from './iframe-rendering'
/**
* Perf.
@@ -76,6 +77,7 @@ class App extends React.Component {
{this.renderTab('Read-only', 'read-only')}
{this.renderTab('RTL', 'rtl')}
{this.renderTab('Plugins', 'plugins')}
+ {this.renderTab('IFrame', 'iframe')}
)
}
@@ -134,6 +136,7 @@ const router = (
+
)