@willbooster/react-frame-component 0.0.0-semantically-released → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -67,7 +67,7 @@ var Frame = class extends Component {
|
|
|
67
67
|
}
|
|
68
68
|
componentWillUnmount() {
|
|
69
69
|
this._isMounted = false;
|
|
70
|
-
this.nodeRef.current
|
|
70
|
+
this.nodeRef.current?.contentWindow?.removeEventListener("DOMContentLoaded", this.handleLoad);
|
|
71
71
|
}
|
|
72
72
|
getDoc() {
|
|
73
73
|
return this.nodeRef.current ? this.nodeRef.current.contentDocument : void 0;
|
|
@@ -85,26 +85,23 @@ var Frame = class extends Component {
|
|
|
85
85
|
else if (forwardedRef) forwardedRef.current = node;
|
|
86
86
|
};
|
|
87
87
|
handleLoad = () => {
|
|
88
|
-
clearInterval(this.loadCheck);
|
|
89
88
|
if (!this.state.iframeLoaded) this.setState({ iframeLoaded: true });
|
|
90
89
|
};
|
|
91
|
-
loadCheck = () => setInterval(() => {
|
|
92
|
-
this.handleLoad();
|
|
93
|
-
}, 500);
|
|
94
90
|
renderFrameContents() {
|
|
95
91
|
if (!this._isMounted) return;
|
|
96
92
|
const doc = this.getDoc();
|
|
97
93
|
if (!doc) return;
|
|
98
|
-
const contentDidMount = this.props
|
|
99
|
-
const
|
|
94
|
+
const { contentDidMount, contentDidUpdate } = this.props;
|
|
95
|
+
const win = doc.defaultView || doc.parentView;
|
|
96
|
+
if (!this._contextValue || this._contextValue.document !== doc || this._contextValue.window !== win) this._contextValue = {
|
|
97
|
+
document: doc,
|
|
98
|
+
window: win
|
|
99
|
+
};
|
|
100
100
|
const contents = /* @__PURE__ */ jsx(Content, {
|
|
101
101
|
contentDidMount,
|
|
102
102
|
contentDidUpdate,
|
|
103
103
|
children: /* @__PURE__ */ jsx(FrameContextProvider, {
|
|
104
|
-
value:
|
|
105
|
-
document: doc,
|
|
106
|
-
window: doc.defaultView || doc.parentView
|
|
107
|
-
},
|
|
104
|
+
value: this._contextValue,
|
|
108
105
|
children: /* @__PURE__ */ jsx("div", {
|
|
109
106
|
className: "frame-content",
|
|
110
107
|
children: this.props.children
|
|
@@ -118,23 +115,13 @@ var Frame = class extends Component {
|
|
|
118
115
|
}
|
|
119
116
|
const mountTarget = this.getMountTarget();
|
|
120
117
|
if (!mountTarget) return;
|
|
121
|
-
return [ReactDOM.createPortal(this.props.head,
|
|
118
|
+
return [ReactDOM.createPortal(this.props.head, doc.head, "head"), ReactDOM.createPortal(contents, mountTarget, "contents")];
|
|
122
119
|
}
|
|
123
120
|
render() {
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
children: void 0
|
|
127
|
-
};
|
|
128
|
-
if (!this.props.dangerouslyUseDocWrite) props.srcDoc = this.props.initialContent;
|
|
129
|
-
delete props.head;
|
|
130
|
-
delete props.initialContent;
|
|
131
|
-
delete props.mountTarget;
|
|
132
|
-
delete props.dangerouslyUseDocWrite;
|
|
133
|
-
delete props.contentDidMount;
|
|
134
|
-
delete props.contentDidUpdate;
|
|
135
|
-
delete props.forwardedRef;
|
|
121
|
+
const { children: _children, contentDidMount: _contentDidMount, contentDidUpdate: _contentDidUpdate, dangerouslyUseDocWrite, forwardedRef: _forwardedRef, head: _head, initialContent, mountTarget: _mountTarget, ...iframeProps } = this.props;
|
|
122
|
+
if (!dangerouslyUseDocWrite) iframeProps.srcDoc = initialContent;
|
|
136
123
|
return /* @__PURE__ */ jsx("iframe", {
|
|
137
|
-
...
|
|
124
|
+
...iframeProps,
|
|
138
125
|
ref: this.setRef,
|
|
139
126
|
onLoad: this.handleLoad,
|
|
140
127
|
children: this.state.iframeLoaded && this.renderFrameContents()
|
|
@@ -146,6 +133,6 @@ var Frame_default = React.forwardRef((props, ref) => /* @__PURE__ */ jsx(Frame,
|
|
|
146
133
|
forwardedRef: ref
|
|
147
134
|
}));
|
|
148
135
|
//#endregion
|
|
149
|
-
export { FrameContext, FrameContextConsumer, Frame_default as default, useFrame };
|
|
136
|
+
export { FrameContext, FrameContextConsumer, FrameContextProvider, Frame_default as default, useFrame };
|
|
150
137
|
|
|
151
138
|
//# sourceMappingURL=react-frame-component.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-frame-component.esm.js","names":[],"sources":["../src/Context.jsx","../src/Content.jsx","../src/Frame.jsx"],"sourcesContent":["import React from 'react';\n\nlet doc;\nlet win;\nif (typeof document !== 'undefined') {\n doc = document;\n}\nif (globalThis.window !== undefined) {\n win = globalThis.window;\n}\n\nexport const FrameContext = React.createContext({ document: doc, window: win });\n\nexport const useFrame = () => React.useContext(FrameContext);\n\nexport const { Provider: FrameContextProvider, Consumer: FrameContextConsumer } = FrameContext;\n","import
|
|
1
|
+
{"version":3,"file":"react-frame-component.esm.js","names":[],"sources":["../src/Context.jsx","../src/Content.jsx","../src/Frame.jsx"],"sourcesContent":["import React from 'react';\n\nlet doc;\nlet win;\nif (typeof document !== 'undefined') {\n doc = document;\n}\nif (globalThis.window !== undefined) {\n win = globalThis.window;\n}\n\nexport const FrameContext = React.createContext({ document: doc, window: win });\n\nexport const useFrame = () => React.useContext(FrameContext);\n\nexport const { Provider: FrameContextProvider, Consumer: FrameContextConsumer } = FrameContext;\n","import { Children, Component } from 'react';\nimport PropTypes from 'prop-types';\n\nexport default class Content extends Component {\n static propTypes = {\n children: PropTypes.element.isRequired,\n contentDidMount: PropTypes.func.isRequired,\n contentDidUpdate: PropTypes.func.isRequired,\n };\n\n componentDidMount() {\n this.props.contentDidMount();\n }\n\n componentDidUpdate() {\n this.props.contentDidUpdate();\n }\n\n render() {\n return Children.only(this.props.children);\n }\n}\n","import React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport PropTypes from 'prop-types';\nimport { FrameContextProvider } from './Context';\nimport Content from './Content';\n\nexport class Frame extends Component {\n // React warns when you render directly into the body since browser extensions\n // also inject into the body and can mess up React. For this reason\n // initialContent is expected to have a div inside of the body\n // element that we render react into.\n static propTypes = {\n style: PropTypes.object,\n head: PropTypes.node,\n initialContent: PropTypes.string,\n mountTarget: PropTypes.string,\n dangerouslyUseDocWrite: PropTypes.bool,\n contentDidMount: PropTypes.func,\n contentDidUpdate: PropTypes.func,\n children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)]),\n };\n\n static defaultProps = {\n style: {},\n head: undefined,\n children: undefined,\n mountTarget: undefined,\n dangerouslyUseDocWrite: false,\n contentDidMount: () => {},\n contentDidUpdate: () => {},\n initialContent: '<!DOCTYPE html><html><head></head><body><div class=\"frame-root\"></div></body></html>',\n };\n\n constructor(props, context) {\n super(props, context);\n this._isMounted = false;\n this.nodeRef = React.createRef();\n this.state = { iframeLoaded: false };\n }\n\n componentDidMount() {\n this._isMounted = true;\n\n const doc = this.getDoc();\n\n if (doc) {\n this.nodeRef.current.contentWindow.addEventListener('DOMContentLoaded', this.handleLoad);\n }\n\n if (this.props.dangerouslyUseDocWrite) {\n this.handleLoad();\n }\n }\n\n componentWillUnmount() {\n this._isMounted = false;\n\n // The listener was added to the iframe's content window in componentDidMount.\n this.nodeRef.current?.contentWindow?.removeEventListener('DOMContentLoaded', this.handleLoad);\n }\n\n getDoc() {\n return this.nodeRef.current ? this.nodeRef.current.contentDocument : undefined;\n }\n\n getMountTarget() {\n const doc = this.getDoc();\n\n if (!doc || !doc.body) {\n return;\n }\n\n if (this.props.mountTarget) {\n return doc.querySelector(this.props.mountTarget);\n }\n\n return doc.body.children[0];\n }\n\n setRef = (node) => {\n this.nodeRef.current = node;\n\n const { forwardedRef } = this.props;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n };\n\n handleLoad = () => {\n // Bail update as some browsers will trigger on both DOMContentLoaded & onLoad ala firefox\n if (!this.state.iframeLoaded) {\n this.setState({ iframeLoaded: true });\n }\n };\n\n renderFrameContents() {\n if (!this._isMounted) {\n return;\n }\n\n const doc = this.getDoc();\n\n if (!doc) {\n return;\n }\n\n const { contentDidMount, contentDidUpdate } = this.props;\n\n const win = doc.defaultView || doc.parentView;\n // Reuse the context value across renders so consumers only re-render when the\n // document or window actually changes, not on every render of Frame.\n if (!this._contextValue || this._contextValue.document !== doc || this._contextValue.window !== win) {\n this._contextValue = { document: doc, window: win };\n }\n const contents = (\n <Content contentDidMount={contentDidMount} contentDidUpdate={contentDidUpdate}>\n <FrameContextProvider value={this._contextValue}>\n <div className=\"frame-content\">{this.props.children}</div>\n </FrameContextProvider>\n </Content>\n );\n\n if (this.props.dangerouslyUseDocWrite && doc.body.children.length === 0) {\n doc.open('text/html', 'replace');\n doc.write(this.props.initialContent);\n doc.close();\n }\n\n const mountTarget = this.getMountTarget();\n\n if (!mountTarget) {\n return;\n }\n\n return [\n ReactDOM.createPortal(this.props.head, doc.head, 'head'),\n ReactDOM.createPortal(contents, mountTarget, 'contents'),\n ];\n }\n\n render() {\n // The iframe isn't ready so we drop children from the iframe props here. #12, #17\n const {\n children: _children,\n contentDidMount: _contentDidMount,\n contentDidUpdate: _contentDidUpdate,\n dangerouslyUseDocWrite,\n forwardedRef: _forwardedRef,\n head: _head,\n initialContent,\n mountTarget: _mountTarget,\n ...iframeProps\n } = this.props;\n\n if (!dangerouslyUseDocWrite) {\n iframeProps.srcDoc = initialContent;\n }\n\n return (\n // oxlint-disable-next-line jsx-a11y/iframe-has-title -- consumers can pass `title` via the props spread\n <iframe {...iframeProps} ref={this.setRef} onLoad={this.handleLoad}>\n {this.state.iframeLoaded && this.renderFrameContents()}\n </iframe>\n );\n }\n}\n\nexport default React.forwardRef((props, ref) => <Frame {...props} forwardedRef={ref} />);\n"],"mappings":"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"}
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
}
|
|
102
102
|
componentWillUnmount() {
|
|
103
103
|
this._isMounted = false;
|
|
104
|
-
this.nodeRef.current
|
|
104
|
+
this.nodeRef.current?.contentWindow?.removeEventListener("DOMContentLoaded", this.handleLoad);
|
|
105
105
|
}
|
|
106
106
|
getDoc() {
|
|
107
107
|
return this.nodeRef.current ? this.nodeRef.current.contentDocument : void 0;
|
|
@@ -119,26 +119,23 @@
|
|
|
119
119
|
else if (forwardedRef) forwardedRef.current = node;
|
|
120
120
|
};
|
|
121
121
|
handleLoad = () => {
|
|
122
|
-
clearInterval(this.loadCheck);
|
|
123
122
|
if (!this.state.iframeLoaded) this.setState({ iframeLoaded: true });
|
|
124
123
|
};
|
|
125
|
-
loadCheck = () => setInterval(() => {
|
|
126
|
-
this.handleLoad();
|
|
127
|
-
}, 500);
|
|
128
124
|
renderFrameContents() {
|
|
129
125
|
if (!this._isMounted) return;
|
|
130
126
|
const doc = this.getDoc();
|
|
131
127
|
if (!doc) return;
|
|
132
|
-
const contentDidMount = this.props
|
|
133
|
-
const
|
|
128
|
+
const { contentDidMount, contentDidUpdate } = this.props;
|
|
129
|
+
const win = doc.defaultView || doc.parentView;
|
|
130
|
+
if (!this._contextValue || this._contextValue.document !== doc || this._contextValue.window !== win) this._contextValue = {
|
|
131
|
+
document: doc,
|
|
132
|
+
window: win
|
|
133
|
+
};
|
|
134
134
|
const contents = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Content, {
|
|
135
135
|
contentDidMount,
|
|
136
136
|
contentDidUpdate,
|
|
137
137
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FrameContextProvider, {
|
|
138
|
-
value:
|
|
139
|
-
document: doc,
|
|
140
|
-
window: doc.defaultView || doc.parentView
|
|
141
|
-
},
|
|
138
|
+
value: this._contextValue,
|
|
142
139
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
143
140
|
className: "frame-content",
|
|
144
141
|
children: this.props.children
|
|
@@ -152,23 +149,13 @@
|
|
|
152
149
|
}
|
|
153
150
|
const mountTarget = this.getMountTarget();
|
|
154
151
|
if (!mountTarget) return;
|
|
155
|
-
return [react_dom.default.createPortal(this.props.head,
|
|
152
|
+
return [react_dom.default.createPortal(this.props.head, doc.head, "head"), react_dom.default.createPortal(contents, mountTarget, "contents")];
|
|
156
153
|
}
|
|
157
154
|
render() {
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
children: void 0
|
|
161
|
-
};
|
|
162
|
-
if (!this.props.dangerouslyUseDocWrite) props.srcDoc = this.props.initialContent;
|
|
163
|
-
delete props.head;
|
|
164
|
-
delete props.initialContent;
|
|
165
|
-
delete props.mountTarget;
|
|
166
|
-
delete props.dangerouslyUseDocWrite;
|
|
167
|
-
delete props.contentDidMount;
|
|
168
|
-
delete props.contentDidUpdate;
|
|
169
|
-
delete props.forwardedRef;
|
|
155
|
+
const { children: _children, contentDidMount: _contentDidMount, contentDidUpdate: _contentDidUpdate, dangerouslyUseDocWrite, forwardedRef: _forwardedRef, head: _head, initialContent, mountTarget: _mountTarget, ...iframeProps } = this.props;
|
|
156
|
+
if (!dangerouslyUseDocWrite) iframeProps.srcDoc = initialContent;
|
|
170
157
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
|
|
171
|
-
...
|
|
158
|
+
...iframeProps,
|
|
172
159
|
ref: this.setRef,
|
|
173
160
|
onLoad: this.handleLoad,
|
|
174
161
|
children: this.state.iframeLoaded && this.renderFrameContents()
|
|
@@ -182,6 +169,7 @@
|
|
|
182
169
|
//#endregion
|
|
183
170
|
exports.FrameContext = FrameContext;
|
|
184
171
|
exports.FrameContextConsumer = FrameContextConsumer;
|
|
172
|
+
exports.FrameContextProvider = FrameContextProvider;
|
|
185
173
|
exports.default = Frame_default;
|
|
186
174
|
exports.useFrame = useFrame;
|
|
187
175
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-frame-component.umd.js","names":[],"sources":["../src/Context.jsx","../src/Content.jsx","../src/Frame.jsx"],"sourcesContent":["import React from 'react';\n\nlet doc;\nlet win;\nif (typeof document !== 'undefined') {\n doc = document;\n}\nif (globalThis.window !== undefined) {\n win = globalThis.window;\n}\n\nexport const FrameContext = React.createContext({ document: doc, window: win });\n\nexport const useFrame = () => React.useContext(FrameContext);\n\nexport const { Provider: FrameContextProvider, Consumer: FrameContextConsumer } = FrameContext;\n","import
|
|
1
|
+
{"version":3,"file":"react-frame-component.umd.js","names":[],"sources":["../src/Context.jsx","../src/Content.jsx","../src/Frame.jsx"],"sourcesContent":["import React from 'react';\n\nlet doc;\nlet win;\nif (typeof document !== 'undefined') {\n doc = document;\n}\nif (globalThis.window !== undefined) {\n win = globalThis.window;\n}\n\nexport const FrameContext = React.createContext({ document: doc, window: win });\n\nexport const useFrame = () => React.useContext(FrameContext);\n\nexport const { Provider: FrameContextProvider, Consumer: FrameContextConsumer } = FrameContext;\n","import { Children, Component } from 'react';\nimport PropTypes from 'prop-types';\n\nexport default class Content extends Component {\n static propTypes = {\n children: PropTypes.element.isRequired,\n contentDidMount: PropTypes.func.isRequired,\n contentDidUpdate: PropTypes.func.isRequired,\n };\n\n componentDidMount() {\n this.props.contentDidMount();\n }\n\n componentDidUpdate() {\n this.props.contentDidUpdate();\n }\n\n render() {\n return Children.only(this.props.children);\n }\n}\n","import React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport PropTypes from 'prop-types';\nimport { FrameContextProvider } from './Context';\nimport Content from './Content';\n\nexport class Frame extends Component {\n // React warns when you render directly into the body since browser extensions\n // also inject into the body and can mess up React. For this reason\n // initialContent is expected to have a div inside of the body\n // element that we render react into.\n static propTypes = {\n style: PropTypes.object,\n head: PropTypes.node,\n initialContent: PropTypes.string,\n mountTarget: PropTypes.string,\n dangerouslyUseDocWrite: PropTypes.bool,\n contentDidMount: PropTypes.func,\n contentDidUpdate: PropTypes.func,\n children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)]),\n };\n\n static defaultProps = {\n style: {},\n head: undefined,\n children: undefined,\n mountTarget: undefined,\n dangerouslyUseDocWrite: false,\n contentDidMount: () => {},\n contentDidUpdate: () => {},\n initialContent: '<!DOCTYPE html><html><head></head><body><div class=\"frame-root\"></div></body></html>',\n };\n\n constructor(props, context) {\n super(props, context);\n this._isMounted = false;\n this.nodeRef = React.createRef();\n this.state = { iframeLoaded: false };\n }\n\n componentDidMount() {\n this._isMounted = true;\n\n const doc = this.getDoc();\n\n if (doc) {\n this.nodeRef.current.contentWindow.addEventListener('DOMContentLoaded', this.handleLoad);\n }\n\n if (this.props.dangerouslyUseDocWrite) {\n this.handleLoad();\n }\n }\n\n componentWillUnmount() {\n this._isMounted = false;\n\n // The listener was added to the iframe's content window in componentDidMount.\n this.nodeRef.current?.contentWindow?.removeEventListener('DOMContentLoaded', this.handleLoad);\n }\n\n getDoc() {\n return this.nodeRef.current ? this.nodeRef.current.contentDocument : undefined;\n }\n\n getMountTarget() {\n const doc = this.getDoc();\n\n if (!doc || !doc.body) {\n return;\n }\n\n if (this.props.mountTarget) {\n return doc.querySelector(this.props.mountTarget);\n }\n\n return doc.body.children[0];\n }\n\n setRef = (node) => {\n this.nodeRef.current = node;\n\n const { forwardedRef } = this.props;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n };\n\n handleLoad = () => {\n // Bail update as some browsers will trigger on both DOMContentLoaded & onLoad ala firefox\n if (!this.state.iframeLoaded) {\n this.setState({ iframeLoaded: true });\n }\n };\n\n renderFrameContents() {\n if (!this._isMounted) {\n return;\n }\n\n const doc = this.getDoc();\n\n if (!doc) {\n return;\n }\n\n const { contentDidMount, contentDidUpdate } = this.props;\n\n const win = doc.defaultView || doc.parentView;\n // Reuse the context value across renders so consumers only re-render when the\n // document or window actually changes, not on every render of Frame.\n if (!this._contextValue || this._contextValue.document !== doc || this._contextValue.window !== win) {\n this._contextValue = { document: doc, window: win };\n }\n const contents = (\n <Content contentDidMount={contentDidMount} contentDidUpdate={contentDidUpdate}>\n <FrameContextProvider value={this._contextValue}>\n <div className=\"frame-content\">{this.props.children}</div>\n </FrameContextProvider>\n </Content>\n );\n\n if (this.props.dangerouslyUseDocWrite && doc.body.children.length === 0) {\n doc.open('text/html', 'replace');\n doc.write(this.props.initialContent);\n doc.close();\n }\n\n const mountTarget = this.getMountTarget();\n\n if (!mountTarget) {\n return;\n }\n\n return [\n ReactDOM.createPortal(this.props.head, doc.head, 'head'),\n ReactDOM.createPortal(contents, mountTarget, 'contents'),\n ];\n }\n\n render() {\n // The iframe isn't ready so we drop children from the iframe props here. #12, #17\n const {\n children: _children,\n contentDidMount: _contentDidMount,\n contentDidUpdate: _contentDidUpdate,\n dangerouslyUseDocWrite,\n forwardedRef: _forwardedRef,\n head: _head,\n initialContent,\n mountTarget: _mountTarget,\n ...iframeProps\n } = this.props;\n\n if (!dangerouslyUseDocWrite) {\n iframeProps.srcDoc = initialContent;\n }\n\n return (\n // oxlint-disable-next-line jsx-a11y/iframe-has-title -- consumers can pass `title` via the props spread\n <iframe {...iframeProps} ref={this.setRef} onLoad={this.handleLoad}>\n {this.state.iframeLoaded && this.renderFrameContents()}\n </iframe>\n );\n }\n}\n\nexport default React.forwardRef((props, ref) => <Frame {...props} forwardedRef={ref} />);\n"],"mappings":"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"}
|
package/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface FrameComponentProps
|
|
|
9
9
|
contentDidMount?: (() => void) | undefined;
|
|
10
10
|
contentDidUpdate?: (() => void) | undefined;
|
|
11
11
|
dangerouslyUseDocWrite?: boolean | undefined;
|
|
12
|
-
children
|
|
12
|
+
children?: React.ReactNode | undefined;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
declare const FrameComponent: React.ForwardRefExoticComponent<FrameComponentProps>;
|
package/package.json
CHANGED