@uiw/react-iframe
Version:
This component allows you to wrap your entire React application or each component in an iFrame.
100 lines • 3.54 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
var _excluded = ["children", "head", "initialContent", "src", "mountTarget"];
import { useCallback, useEffect, useState, forwardRef, useImperativeHandle, useMemo, useRef } from 'react';
import { createPortal } from 'react-dom';
import { FrameContext } from "./Context.js";
import { jsx as _jsx } from "react/jsx-runtime";
export { FrameContext, useFrame } from "./Context.js";
var IFrame = /*#__PURE__*/forwardRef((_ref, ref) => {
var {
children,
head,
initialContent,
src,
mountTarget
} = _ref,
other = _objectWithoutPropertiesLoose(_ref, _excluded);
var [iframeLoaded, setIframeLoaded] = useState(false);
var [mountNode, setMountNode] = useState();
var refContent = node => {
if (node) {
setMountNode(node);
}
};
useImperativeHandle(ref, () => mountNode, [mountNode]);
var html = initialContent || "<!DOCTYPE html><html><head></head><body></body></html>";
var getDoc = () => mountNode ? mountNode.contentDocument : null;
var getMountTarget = () => {
var doc = getDoc();
if (mountTarget) {
return doc == null ? void 0 : doc.querySelector(mountTarget);
}
return doc == null ? void 0 : doc.body;
};
var evnRef = useRef();
var handleLoad = useCallback(evn => {
evnRef.current = evn;
/**
* In certain situations on a cold cache DOMContentLoaded never gets called
* fallback to an interval to check if that's the case
*/
var loadCheck = () => setInterval(() => handleLoad(evn), 500);
clearInterval(loadCheck());
// Bail update as some browsers will trigger on both DOMContentLoaded & onLoad ala firefox
if (!iframeLoaded) {
setIframeLoaded(true);
}
}, [iframeLoaded]);
useMemo(() => {
if (!src && other.onLoad && iframeLoaded) {
other.onLoad(evnRef.current);
}
}, [iframeLoaded]);
useEffect(() => {
if (mountNode && !src) {
var _mountNode$contentWin;
(_mountNode$contentWin = mountNode.contentWindow) == null || _mountNode$contentWin.addEventListener('DOMContentLoaded', handleLoad);
}
return () => {
if (mountNode && !src) {
var _mountNode$contentWin2;
(_mountNode$contentWin2 = mountNode.contentWindow) == null || _mountNode$contentWin2.removeEventListener('DOMContentLoaded', handleLoad);
}
};
}, [mountNode, handleLoad]);
var renderFrameContents = () => {
var _getDoc;
var doc = getDoc();
var header = (_getDoc = getDoc()) == null ? void 0 : _getDoc.head;
var mountTarget = getMountTarget();
// @ts-ignore
var win = (doc == null ? void 0 : doc.defaultView) || (doc == null ? void 0 : doc.parentView);
var contents = /*#__PURE__*/_jsx(FrameContext.Provider, {
value: {
document: doc,
window: win
},
children: children
});
return [header && head && /*#__PURE__*/createPortal(head, header), mountNode && mountTarget && /*#__PURE__*/createPortal(contents, mountTarget)];
};
var reProps = {};
if (src) {
delete reProps.srcDoc;
reProps.src = src;
reProps.onLoad = other.onLoad;
} else {
reProps.srcDoc = html;
}
return /*#__PURE__*/_jsx("iframe", _extends({
title: other.title,
ref: refContent
}, other, {
onLoad: handleLoad
}, reProps, {
children: iframeLoaded && renderFrameContents()
}));
});
IFrame.displayName = 'IFrame';
export default IFrame;