timvir 0.2.31 → 0.2.33
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.
- package/blocks/Viewport/index.js +61 -55
- package/package.json +1 -1
package/blocks/Viewport/index.js
CHANGED
|
@@ -217,54 +217,6 @@ function Viewport(props, ref) {
|
|
|
217
217
|
setHeight(height);
|
|
218
218
|
setMaxHeight(Math.max(height, maxHeight ?? 0));
|
|
219
219
|
});
|
|
220
|
-
|
|
221
|
-
/*
|
|
222
|
-
* Note this useEffect runs on each render. This is fine beause it doesn't do any
|
|
223
|
-
* expensive computation, and the Viewport component only re-renders when the iframe
|
|
224
|
-
* itself changes height or the user resizes the width of the Viewport.
|
|
225
|
-
*/
|
|
226
|
-
React.useEffect(() => {
|
|
227
|
-
const document = iframeRef.current?.contentDocument;
|
|
228
|
-
if (document) {
|
|
229
|
-
injectStyle(document);
|
|
230
|
-
|
|
231
|
-
/*
|
|
232
|
-
* The <body> element of the iframe document is the one which we observe and
|
|
233
|
-
* measure. It should not have any margins (we remove them by injecting a simple
|
|
234
|
-
* style reset into the iframe document).
|
|
235
|
-
*/
|
|
236
|
-
iframeRO.observe(document.body);
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
/*
|
|
241
|
-
* Inject a simple style reset into the document.
|
|
242
|
-
*/
|
|
243
|
-
function injectStyle(document) {
|
|
244
|
-
if (document.querySelector("style#timvir-viewport-style")) {
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
const style = document.createElement("style");
|
|
248
|
-
style.id = "timvir-viewport-style";
|
|
249
|
-
style.innerHTML = "body { margin: 0 }";
|
|
250
|
-
document.head.appendChild(style);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/*
|
|
254
|
-
* 20ms after the height has been set, we consider this block settled. This
|
|
255
|
-
* time includes the 16ms CSS transition time, and a tiny bit more to allow
|
|
256
|
-
* for the content in the iframe itself to finish rendering.
|
|
257
|
-
*/
|
|
258
|
-
React.useEffect(() => {
|
|
259
|
-
const timeoutId = setTimeout(() => {
|
|
260
|
-
mutate(draft => {
|
|
261
|
-
draft.settled = true;
|
|
262
|
-
});
|
|
263
|
-
}, 20);
|
|
264
|
-
return () => {
|
|
265
|
-
clearTimeout(timeoutId);
|
|
266
|
-
};
|
|
267
|
-
}, [mutate, height]);
|
|
268
220
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
269
221
|
ref: containerRef
|
|
270
222
|
}), /*#__PURE__*/React.createElement(Root, {
|
|
@@ -295,14 +247,68 @@ function Viewport(props, ref) {
|
|
|
295
247
|
src: src,
|
|
296
248
|
onLoad: ev => {
|
|
297
249
|
const document = ev.currentTarget.contentDocument;
|
|
298
|
-
if (document) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
height
|
|
302
|
-
} = document.body.getBoundingClientRect();
|
|
303
|
-
setHeight(height);
|
|
304
|
-
setMaxHeight(height);
|
|
250
|
+
if (!document) {
|
|
251
|
+
console.warn(`Viewport: iframe has no contentDocument`);
|
|
252
|
+
return;
|
|
305
253
|
}
|
|
254
|
+
|
|
255
|
+
/*
|
|
256
|
+
* Some browsers (notably Firefox) don't always fully initialize the <iframe>
|
|
257
|
+
* element (see https://bugzilla.mozilla.org/show_bug.cgi?id=1191683). The
|
|
258
|
+
* 'head' and 'body' properties in Document (which we access below) may be null
|
|
259
|
+
* when this onLoad callback runs.
|
|
260
|
+
*
|
|
261
|
+
* We use the Document readyState to decide if we can interact and observe the
|
|
262
|
+
* DOM.
|
|
263
|
+
*/
|
|
264
|
+
|
|
265
|
+
const initializeDocument = () => {
|
|
266
|
+
if (document.readyState === "complete") {
|
|
267
|
+
/*
|
|
268
|
+
* Inject a simple style reset into the document.
|
|
269
|
+
*/
|
|
270
|
+
{
|
|
271
|
+
const style = document.createElement("style");
|
|
272
|
+
style.id = "timvir-viewport-style";
|
|
273
|
+
style.innerHTML = "body { margin: 0 }";
|
|
274
|
+
document.head.appendChild(style);
|
|
275
|
+
}
|
|
276
|
+
{
|
|
277
|
+
const {
|
|
278
|
+
height
|
|
279
|
+
} = document.body.getBoundingClientRect();
|
|
280
|
+
setHeight(height);
|
|
281
|
+
setMaxHeight(height);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/*
|
|
285
|
+
* The <body> element of the iframe document is the one which we observe and
|
|
286
|
+
* measure. It should not have any margins (we remove them by injecting a simple
|
|
287
|
+
* style reset into the iframe document).
|
|
288
|
+
*/
|
|
289
|
+
iframeRO.observe(document.body);
|
|
290
|
+
|
|
291
|
+
/*
|
|
292
|
+
* 50ms after the iframe document is complete, we consider the Viewport block
|
|
293
|
+
* settled. This time includes the 16ms CSS transition time, and a tiny bit more
|
|
294
|
+
* to allow for the content in the iframe itself to finish rendering.
|
|
295
|
+
*
|
|
296
|
+
* This time is not quite enough if the iframe loads additional code or needs to
|
|
297
|
+
* load data from a remote source. But should be enough for statically rendered
|
|
298
|
+
* content.
|
|
299
|
+
*/
|
|
300
|
+
setTimeout(() => {
|
|
301
|
+
mutate(draft => {
|
|
302
|
+
draft.settled = true;
|
|
303
|
+
});
|
|
304
|
+
}, 50);
|
|
305
|
+
} else {
|
|
306
|
+
document?.addEventListener("readystatechange", initializeDocument, {
|
|
307
|
+
once: true
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
initializeDocument();
|
|
306
312
|
},
|
|
307
313
|
className: "i11uos8q",
|
|
308
314
|
style: {
|