timvir 0.2.31 → 0.2.32

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.
@@ -218,38 +218,6 @@ function Viewport(props, ref) {
218
218
  setMaxHeight(Math.max(height, maxHeight ?? 0));
219
219
  });
220
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
221
  /*
254
222
  * 20ms after the height has been set, we consider this block settled. This
255
223
  * time includes the 16ms CSS transition time, and a tiny bit more to allow
@@ -295,14 +263,53 @@ function Viewport(props, ref) {
295
263
  src: src,
296
264
  onLoad: ev => {
297
265
  const document = ev.currentTarget.contentDocument;
298
- if (document) {
299
- injectStyle(document);
300
- const {
301
- height
302
- } = document.body.getBoundingClientRect();
303
- setHeight(height);
304
- setMaxHeight(height);
266
+ if (!document) {
267
+ console.warn(`Viewport: iframe has no contentDocument`);
268
+ return;
305
269
  }
270
+
271
+ /*
272
+ * Some browsers (notably Firefox) don't always fully initialize the <iframe>
273
+ * element (see https://bugzilla.mozilla.org/show_bug.cgi?id=1191683). The
274
+ * 'head' and 'body' properties in Document (which we access below) may be null
275
+ * when this onLoad callback runs.
276
+ *
277
+ * We use the Document readyState to decide if we can interact and observe the
278
+ * DOM.
279
+ */
280
+
281
+ const initializeDocument = () => {
282
+ if (document.readyState === "interactive" || document.readyState === "complete") {
283
+ /*
284
+ * Inject a simple style reset into the document.
285
+ */
286
+ {
287
+ const style = document.createElement("style");
288
+ style.id = "timvir-viewport-style";
289
+ style.innerHTML = "body { margin: 0 }";
290
+ document.head.appendChild(style);
291
+ }
292
+ {
293
+ const {
294
+ height
295
+ } = document.body.getBoundingClientRect();
296
+ setHeight(height);
297
+ setMaxHeight(height);
298
+ }
299
+
300
+ /*
301
+ * The <body> element of the iframe document is the one which we observe and
302
+ * measure. It should not have any margins (we remove them by injecting a simple
303
+ * style reset into the iframe document).
304
+ */
305
+ iframeRO.observe(document.body);
306
+ } else {
307
+ document?.addEventListener("readystatechange", initializeDocument, {
308
+ once: true
309
+ });
310
+ }
311
+ };
312
+ initializeDocument();
306
313
  },
307
314
  className: "i11uos8q",
308
315
  style: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "timvir",
4
- "version": "0.2.31",
4
+ "version": "0.2.32",
5
5
  "license": "MIT",
6
6
  "sideEffects": false,
7
7
  "exports": {