Skip to content

Commit

Permalink
[FEATURE] Avoid errors when loaded in SSR env
Browse files Browse the repository at this point in the history
- Improve .dts
  • Loading branch information
Lemick committed Nov 14, 2024
1 parent 18e9722 commit e088d05
Show file tree
Hide file tree
Showing 10 changed files with 201 additions and 308 deletions.
449 changes: 164 additions & 285 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
"copyfiles": "^2.4.1",
"jsdom": "^25.0.1",
"rollup-plugin-visualizer": "^5.12.0",
"rollup-preserve-directives": "^1.1.2",
"tslib": "^2.8.0",
"typedoc": "^0.26.10",
"typescript": "^5.6.3",
"vite": "^5.4.10",
"vite-plugin-dts": "^4.1.1",
"vite-plugin-dts": "^4.3.0",
"vite-plugin-progress": "^0.0.7",
"vitest": "^2.1.3"
},
Expand Down
10 changes: 6 additions & 4 deletions packages/core/src/child.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { deferWhenWindowIsLoaded, getBoundingRectHeight, isInIframe } from "~/common";
import { deferWhenWindowIsLoaded, getBoundingRectHeight, isBrowser, isInIframe } from "~/common";
import type { IframeResizeEventData } from "./type";

if (isInIframe()) {
initializeChildListener();
}
initializeChildListener();

function initializeChildListener() {
if (!isBrowser() || !isInIframe()) {
return;
}

deferWhenWindowIsLoaded(window, () => {
const resizeObserverCallback = () => {
const data: IframeResizeEventData = {
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { Settings } from "~/type";

export const isInIframe = () => window && window.self !== window.top;
export const isBrowser = () => typeof window !== "undefined";

export const isInIframe = () => window.self !== window.top;

export const isHtmlIframeElement = (element: Element): element is HTMLIFrameElement => element instanceof HTMLIFrameElement;

Expand Down
19 changes: 9 additions & 10 deletions packages/core/src/parent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
extractIframeOrigin,
getBoundingRectHeight,
getDefaultSettings,
isBrowser,
isHtmlIframeElement,
isIframeSameOrigin,
removeUndefinedProperties,
Expand All @@ -12,10 +13,13 @@ import type { IframeResizeEvent, InitializeFunction, InteractionState, ResizeCon

type RegisteredElement = { iframe: HTMLIFrameElement; settings: Settings; interactionState: InteractionState };

const resizeObserver = createResizeObserver();
const resizeObserver: ResizeObserver | null = isBrowser() ? createResizeObserver() : null;
let registeredElements: Array<RegisteredElement> = [];

const initialize: InitializeFunction = (clientSettings, selector) => {
if (!isBrowser()) {
return [];
}
const finalSettings = { ...getDefaultSettings(), ...removeUndefinedProperties(clientSettings ?? {}) };
const iframes = resolveIframesToRegister(selector);
const allowedOrigins = registerIframesAllowOrigins(finalSettings, iframes);
Expand Down Expand Up @@ -108,31 +112,26 @@ function addCrossOriginChildResizeListener(registeredElement: RegisteredElement,
return () => window.removeEventListener("message", handleIframeResizedMessage);
}

function addSameOriginChildResizeListener(registeredElement: RegisteredElement) {
const { iframe } = registeredElement;
function addSameOriginChildResizeListener({ iframe }: RegisteredElement) {
const startListener = () => {
const contentBody = iframe.contentDocument?.body;
if (!contentBody) {
console.error("Unable to observe the iframe content document body");
return;
}

resizeObserver.observe(contentBody);
resizeObserver?.observe(contentBody);
};

deferWhenSameOriginIframeIsLoaded(iframe, startListener);

return () => {
if (iframe.contentDocument?.body) {
resizeObserver.unobserve(iframe.contentDocument.body);
resizeObserver?.unobserve(iframe.contentDocument.body);
}
iframe.removeEventListener("load", startListener);
};
}

function addInteractionListeners(registeredElement: RegisteredElement) {
const { iframe, interactionState } = registeredElement;

function addInteractionListeners({ iframe, interactionState }: RegisteredElement) {
const onMouseEnter = () => {
interactionState.isHovered = true;
};
Expand Down
8 changes: 1 addition & 7 deletions packages/core/src/type.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
interface Window {
iframeResizer: {
initialize: InitializeFunction;
};
}

/**
* Automatically resizes the selected iframes.
* Automatically resize the selected iframes when their inner content grows.
* @param settings The settings for the selected iframes. The default settings properties are picked if empty.
* @param selector The selector for the iframe(s) or the HTMLIFrameElement to be resized. If empty, all document iframe elements will be selected.
* @returns A result array, which can be used to clean up the listeners if you often remove iframes from the document.
Expand Down
10 changes: 10 additions & 0 deletions packages/core/test/ssr.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// @vitest-environment node

import { expect, test } from "vitest";
import { initialize, initializeChildListener } from "../src";

test("API functions shouldn't throw error when executed on unsupported environments with no window (SSR, Node..)", () => {
expect(typeof window).toBe("undefined");
expect(initialize).not.toThrow();
expect(initializeChildListener).not.toThrow();
});
1 change: 1 addition & 0 deletions packages/core/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default defineConfig((env) => ({
dts({
entryRoot: "src",
copyDtsFiles: true,
rollupTypes: true,
tsconfigPath: path.join(__dirname, "tsconfig.json"),
}),
],
Expand Down
2 changes: 2 additions & 0 deletions packages/react/src/components/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import { type Settings, initialize } from "@open-iframe-resizer/core";
import { type IframeHTMLAttributes, useEffect, useRef } from "react";

Expand Down
3 changes: 3 additions & 0 deletions packages/react/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import * as path from "node:path";
import react from "@vitejs/plugin-react";
import preserveDirectives from "rollup-preserve-directives";
import dts from "vite-plugin-dts";
import { defineConfig } from "vitest/config";

const formattedName = "open-iframe-resizer-react";

export default defineConfig((env) => ({
plugins: [
preserveDirectives(),
react(),
dts({
insertTypesEntry: true,
rollupTypes: true,
}),
],
build: {
Expand Down

0 comments on commit e088d05

Please sign in to comment.