react-frame-component
Version:
React component to wrap your application or component in an iFrame for encapsulation purposes
189 lines (188 loc) • 6.88 kB
JavaScript
(function(global, factory) {
typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react"), require("react-dom"), require("prop-types"), require("react/jsx-runtime")) : typeof define === "function" && define.amd ? define([
"exports",
"react",
"react-dom",
"prop-types",
"react/jsx-runtime"
], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.ReactFrameComponent = {}, global.React, global.ReactDOM, global.PropTypes, global["react/jsx-runtime"]));
})(this, function(exports, react, react_dom, prop_types, react_jsx_runtime) {
Object.defineProperties(exports, {
__esModule: { value: true },
[Symbol.toStringTag]: { value: "Module" }
});
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
react = __toESM(react);
react_dom = __toESM(react_dom);
prop_types = __toESM(prop_types);
//#region src/Context.jsx
var doc;
var win;
if (typeof document !== "undefined") doc = document;
if (typeof window !== "undefined") win = window;
var FrameContext = react.default.createContext({
document: doc,
window: win
});
var useFrame = () => react.default.useContext(FrameContext);
var { Provider: FrameContextProvider, Consumer: FrameContextConsumer } = FrameContext;
//#endregion
//#region src/Content.jsx
var Content = class extends react.Component {
static propTypes = {
children: prop_types.default.element.isRequired,
contentDidMount: prop_types.default.func.isRequired,
contentDidUpdate: prop_types.default.func.isRequired
};
componentDidMount() {
this.props.contentDidMount();
}
componentDidUpdate() {
this.props.contentDidUpdate();
}
render() {
return react.Children.only(this.props.children);
}
};
//#endregion
//#region src/Frame.jsx
var Frame = class extends react.Component {
static propTypes = {
style: prop_types.default.object,
head: prop_types.default.node,
initialContent: prop_types.default.string,
mountTarget: prop_types.default.string,
dangerouslyUseDocWrite: prop_types.default.bool,
contentDidMount: prop_types.default.func,
contentDidUpdate: prop_types.default.func,
children: prop_types.default.oneOfType([prop_types.default.element, prop_types.default.arrayOf(prop_types.default.element)])
};
static defaultProps = {
style: {},
head: null,
children: void 0,
mountTarget: void 0,
dangerouslyUseDocWrite: false,
contentDidMount: () => {},
contentDidUpdate: () => {},
initialContent: "<!DOCTYPE html><html><head></head><body><div class=\"frame-root\"></div></body></html>"
};
constructor(props, context) {
super(props, context);
this._isMounted = false;
this.nodeRef = react.default.createRef();
this.state = { iframeLoaded: false };
}
componentDidMount() {
this._isMounted = true;
if (this.getDoc()) this.nodeRef.current.contentWindow.addEventListener("DOMContentLoaded", this.handleLoad);
if (this.props.dangerouslyUseDocWrite) this.handleLoad();
}
componentWillUnmount() {
this._isMounted = false;
this.nodeRef.current.removeEventListener("DOMContentLoaded", this.handleLoad);
}
getDoc() {
return this.nodeRef.current ? this.nodeRef.current.contentDocument : null;
}
getMountTarget() {
const doc = this.getDoc();
if (!doc || !doc.body) return null;
if (this.props.mountTarget) return doc.querySelector(this.props.mountTarget);
return doc.body.children[0];
}
setRef = (node) => {
this.nodeRef.current = node;
const { forwardedRef } = this.props;
if (typeof forwardedRef === "function") forwardedRef(node);
else if (forwardedRef) forwardedRef.current = node;
};
handleLoad = () => {
clearInterval(this.loadCheck);
if (!this.state.iframeLoaded) this.setState({ iframeLoaded: true });
};
loadCheck = () => setInterval(() => {
this.handleLoad();
}, 500);
renderFrameContents() {
if (!this._isMounted) return null;
const doc = this.getDoc();
if (!doc) return null;
const contentDidMount = this.props.contentDidMount;
const contentDidUpdate = this.props.contentDidUpdate;
const contents = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Content, {
contentDidMount,
contentDidUpdate,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FrameContextProvider, {
value: {
document: doc,
window: doc.defaultView || doc.parentView
},
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "frame-content",
children: this.props.children
})
})
});
if (this.props.dangerouslyUseDocWrite && doc.body.children.length < 1) {
doc.open("text/html", "replace");
doc.write(this.props.initialContent);
doc.close();
}
const mountTarget = this.getMountTarget();
if (!mountTarget) return null;
return [react_dom.default.createPortal(this.props.head, this.getDoc().head), react_dom.default.createPortal(contents, mountTarget)];
}
render() {
const props = {
...this.props,
children: void 0
};
if (!this.props.dangerouslyUseDocWrite) props.srcDoc = this.props.initialContent;
delete props.head;
delete props.initialContent;
delete props.mountTarget;
delete props.dangerouslyUseDocWrite;
delete props.contentDidMount;
delete props.contentDidUpdate;
delete props.forwardedRef;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
...props,
ref: this.setRef,
onLoad: this.handleLoad,
children: this.state.iframeLoaded && this.renderFrameContents()
});
}
};
var Frame_default = react.default.forwardRef((props, ref) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Frame, {
...props,
forwardedRef: ref
}));
//#endregion
exports.FrameContext = FrameContext;
exports.FrameContextConsumer = FrameContextConsumer;
exports.default = Frame_default;
exports.useFrame = useFrame;
});
//# sourceMappingURL=react-frame-component.umd.js.map