Skip to content

Commit 83d8855

Browse files
Lemickbezbac
andauthored
[FEATURE] Add before iframe resize (#23)
#22 --------- Co-authored-by: Ben Bachem <10088265+bezbac@users.noreply.github.com>
1 parent f14cfb1 commit 83d8855

File tree

18 files changed

+142
-18
lines changed

18 files changed

+142
-18
lines changed

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/core/e2e/usecase-18.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { test } from "@playwright/test";
2+
import { allIframesOffsetHeightMatch, type AssertArg } from "./utils";
3+
4+
test("Should resize according to onBeforeResize handler (while height is lesser than 2000px)", async ({ page }) => {
5+
await page.goto("/usecases/18-on-before-resize-handler/index.html");
6+
7+
await page.waitForTimeout(1000); // Wait for the content to be added
8+
9+
await page.waitForFunction<boolean, AssertArg>(allIframesOffsetHeightMatch, { comparator: "greaterThan", threshold: 1000 });
10+
11+
await page.waitForFunction<boolean, AssertArg>(allIframesOffsetHeightMatch, { comparator: "lesserThan", threshold: 2000 });
12+
});

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@open-iframe-resizer/core",
33
"private": false,
4-
"version": "1.4.3",
4+
"version": "1.5.0",
55
"description": "Open-source modern iframe resizer",
66
"license": "MIT",
77
"repository": {

packages/core/src/parent.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ function resizeIframe({ registeredElement, newHeight }: { registeredElement: Reg
217217
clearTimeout(initContext.retryTimeoutId);
218218
}
219219

220+
if (settings.onBeforeIframeResize?.({ iframe, settings: { ...settings }, observedHeight: newHeight }) === false) {
221+
return;
222+
}
223+
220224
const previousBoundingRect = iframe.getBoundingClientRect();
221225
const newCalculatedHeight = newHeight + settings.offsetSize;
222226
iframe.style.height = `${newCalculatedHeight}px`;

packages/core/src/type.d.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ export type Settings = {
5252
* Default: `undefined`
5353
*/
5454
bodyMargin?: string;
55+
56+
/**
57+
* Called whenever the observed content size changes and the iframe is about to be resized.
58+
* Return `false` to cancel the resize; returning `true` or nothing will allow it.
59+
*
60+
* Default: `undefined`
61+
*/
62+
onBeforeIframeResize?: (context: BeforeResizeContext) => boolean | undefined;
63+
5564
/**
5665
* Listener that is called after the iframe has been resized.
5766
* You can use a predefined handler like `updateParentScrollOnResize` or create your own custom handler.
@@ -90,6 +99,12 @@ export type ResizeContext = {
9099
nextRenderState: ResizeRenderState;
91100
};
92101

102+
export type BeforeResizeContext = {
103+
iframe: HTMLIFrameElement;
104+
settings: Settings;
105+
observedHeight: number;
106+
};
107+
93108
export type RegisteredElement = {
94109
iframe: HTMLIFrameElement;
95110
settings: Settings;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Text Loader Example</title>
7+
<style>
8+
body {
9+
font-family: Arial, sans-serif;
10+
padding: 20px;
11+
}
12+
</style>
13+
</head>
14+
<body>
15+
<h1 id="title">The text will grow periodically</h1>
16+
<p id="content">This is the initial text that loads with the page.</p>
17+
18+
<script>
19+
const lorem = "At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat\n";
20+
const content = document.getElementById("content");
21+
const additionalText = lorem.repeat(10);
22+
23+
let times = 0;
24+
const intervalId = setInterval(() => {
25+
if (times < 3) {
26+
content.innerHTML += additionalText;
27+
times++;
28+
} else {
29+
clearInterval(intervalId);
30+
}
31+
}, 300);
32+
</script>
33+
</body>
34+
</html>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Iframe Resize Example</title>
7+
<style>
8+
iframe {
9+
border: 2px dotted red;
10+
width: 800px;
11+
height: 100px;
12+
}
13+
</style>
14+
</head>
15+
<body>
16+
<iframe id="myIframe" src="iframe-content.html"></iframe>
17+
18+
<script type="module">
19+
import { initialize } from "/dist/index.js";
20+
21+
initialize({
22+
onBeforeIframeResize: ({ observedHeight }) => {
23+
if (observedHeight >= 2000) {
24+
return false;
25+
}
26+
},
27+
}, "#myIframe");
28+
</script>
29+
30+
</body>
31+
</html>

packages/core/usecases/root.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ <h1>Directory Index</h1>
3131
<li><a href="./15-cross-origin-target-element-selector/index.html">15 Cross Origin Target Element Selector</a></li>
3232
<li><a href="./16-custom-padding-margin/index.html">16 Custom Padding Margin</a></li>
3333
<li><a href="./17-cross-origin-custom-padding-margin/index.html">17 Cross Origin Custom Padding Margin</a></li>
34+
<li><a href="./18-on-before-resize-handler/index.html">18 On Before Resize Handler</a></li>
35+
3436
</ul>
3537
</body>
3638
</html>

packages/react/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@open-iframe-resizer/react",
33
"private": false,
4-
"version": "1.4.3",
4+
"version": "1.5.0",
55
"description": "Open-source modern iframe resizer component",
66
"license": "MIT",
77
"repository": {
@@ -45,7 +45,7 @@
4545
"test": "npx playwright install --with-deps && npx playwright test"
4646
},
4747
"dependencies": {
48-
"@open-iframe-resizer/core": "1.4.3"
48+
"@open-iframe-resizer/core": "1.5.0"
4949
},
5050
"devDependencies": {
5151
"@testing-library/react": "^16.1.0",

packages/react/src/components/index.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,25 @@ export function IframeResizer(props: Props) {
2121
}
2222

2323
function filterProps(props: Props): { iframeAttributes: IframeHTMLAttributes<HTMLIFrameElement>; settings: Partial<Settings> } {
24-
const { offsetSize, enableLegacyLibSupport, checkOrigin, onIframeResize, targetElementSelector, bodyMargin, bodyPadding, ...iframeAttributes } = props;
24+
const {
25+
offsetSize,
26+
enableLegacyLibSupport,
27+
checkOrigin,
28+
onIframeResize,
29+
onBeforeIframeResize,
30+
targetElementSelector,
31+
bodyMargin,
32+
bodyPadding,
33+
...iframeAttributes
34+
} = props;
2535

2636
// biome-ignore lint/suspicious/noExplicitAny: Compile fail if no key exhaustiveness
2737
const settings: Required<{ [K in keyof Settings]: any }> = {
2838
offsetSize,
2939
enableLegacyLibSupport,
3040
checkOrigin,
3141
onIframeResize,
42+
onBeforeIframeResize,
3243
targetElementSelector,
3344
bodyMargin,
3445
bodyPadding,

packages/react/usecases/01-module-load/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
React.createElement(IframeResizer, {
3535
src: './iframe-content.html',
3636
style: { width: '100%' },
37+
onBeforeIframeResize: (height) => {
38+
console.log('Iframe content height:', height);
39+
},
3740
})
3841
);
3942
}

packages/react/usecases/02-cross-origin-iframe-resizer-compat/index.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@
3434
React.createElement(IframeResizer, {
3535
src: 'http://localhost:5553/usecases/02-cross-origin-iframe-resizer-compat/iframe-content.html',
3636
style: { width: '100%' },
37-
enableLegacyLibSupport: true
37+
enableLegacyLibSupport: true,
38+
onBeforeIframeResize: (height) => {
39+
console.log('Iframe content height:', height);
40+
},
3841
})
3942
);
4043
}

packages/react/usecases/03-cross-origin-iframe/index.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@
3232
mounted &&
3333
React.createElement(IframeResizer, {
3434
src: 'http://localhost:5553/usecases/03-cross-origin-iframe/iframe-content.html',
35-
style: { width: '100%' }
35+
style: { width: '100%' },
36+
onBeforeIframeResize: (height) => {
37+
console.log('Iframe content height:', height);
38+
},
3639
})
3740
);
3841
}

packages/vue/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@open-iframe-resizer/vue",
33
"private": false,
4-
"version": "1.4.3",
4+
"version": "1.5.0",
55
"description": "Open-source modern iframe resizer component",
66
"license": "MIT",
77
"repository": {
@@ -43,7 +43,7 @@
4343
"test": "npx playwright install --with-deps && npx playwright test"
4444
},
4545
"dependencies": {
46-
"@open-iframe-resizer/core": "1.4.3"
46+
"@open-iframe-resizer/core": "1.5.0"
4747
},
4848
"devDependencies": {
4949
"@vitejs/plugin-vue": "^5.2.3",

packages/vue/src/components/IframeResizer.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export default defineComponent(<Props>{
1414
offsetSize: [String, Number, Object] as PropType<Settings["offsetSize"]>,
1515
checkOrigin: [Boolean, Array] as PropType<Settings["checkOrigin"]>,
1616
onIframeResize: Function as PropType<Settings["onIframeResize"]>,
17+
onBeforeIframeResize: Function as PropType<Settings["onBeforeIframeResize"]>,
1718
targetElementSelector: [String] as PropType<Settings["targetElementSelector"]>,
1819
bodyMargin: [String, Number] as PropType<Settings["bodyMargin"]>,
1920
bodyPadding: [String, Number] as PropType<Settings["bodyPadding"]>,
@@ -30,6 +31,7 @@ export default defineComponent(<Props>{
3031
enableLegacyLibSupport: props.enableLegacyLibSupport,
3132
checkOrigin: props.checkOrigin,
3233
onIframeResize: props.onIframeResize,
34+
onBeforeIframeResize: props.onBeforeIframeResize,
3335
targetElementSelector: props.targetElementSelector,
3436
bodyMargin: props.bodyMargin,
3537
bodyPadding: props.bodyPadding,

packages/vue/tsconfig.app.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"extends": "@vue/tsconfig/tsconfig.dom.json",
33
"compilerOptions": {
44
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
5-
65
"strict": true,
76
"noUnusedLocals": true,
87
"noUnusedParameters": true,

packages/vue/tsconfig.node.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,12 @@
66
"module": "ESNext",
77
"skipLibCheck": true,
88

9-
/* Bundler mode */
109
"moduleResolution": "bundler",
1110
"allowImportingTsExtensions": true,
1211
"isolatedModules": true,
1312
"moduleDetection": "force",
1413
"noEmit": true,
1514

16-
/* Linting */
1715
"strict": true,
1816
"noUnusedLocals": true,
1917
"noUnusedParameters": true,

website/src/content/docs/reference/api.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,13 @@ Below is a detailed description of each property:
8080
- **Description**: Listener that is called after the iframe has been resized. You can use a predefined handler like `updateParentScrollOnResize` create your own custom handler.
8181
- **Default**: `undefined`
8282

83+
84+
### `onBeforeIframeResize`
85+
86+
- **Type**: `(context: BeforeResizeContext) => boolean | undefined`
87+
- **Description**: Called whenever the observed content size changes and the iframe is about to be resized. Return `false` to cancel the resize; returning `true` or nothing will allow it.
88+
- **Default**: `undefined`
89+
8390
---
8491
## Resize handlers
8592

0 commit comments

Comments
 (0)