@open-iframe-resizer/core 1.0.0-rc1

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.
@@ -0,0 +1,2 @@
1
+ declare function initializeChildListener(): void;
2
+ export { initializeChildListener };
@@ -0,0 +1,12 @@
1
+ import { Settings } from './type';
2
+ declare const isInIframe: () => boolean;
3
+ declare const isSameOriginIframe: (iframe: HTMLIFrameElement) => iframe is HTMLIFrameElement & {
4
+ contentDocument: Document;
5
+ };
6
+ declare const isHtmlIframeElement: (element: Element) => element is HTMLIFrameElement;
7
+ declare const deferWhenDomContentIsLoaded: (document: Document, executable: () => void) => void;
8
+ declare const deferWhenPageIsLoaded: (document: Document, executable: () => void) => void;
9
+ declare const getDefaultSettings: () => Settings;
10
+ declare const isIframeSameOrigin: (iframe: HTMLIFrameElement) => boolean;
11
+ declare function debounce<T extends (...args: any[]) => any>(f: T, delay: number): (...args: unknown[]) => void;
12
+ export { isInIframe, isSameOriginIframe, deferWhenDomContentIsLoaded, isHtmlIframeElement, deferWhenPageIsLoaded, isIframeSameOrigin, debounce, getDefaultSettings, };
@@ -0,0 +1,3 @@
1
+ export * from './parent';
2
+ export * from './child';
3
+ export type * from './type';
package/dist/index.js ADDED
@@ -0,0 +1,112 @@
1
+ const w = () => window && window.self !== window.top, l = (e) => e instanceof HTMLIFrameElement, b = () => ({ offsetSize: 0, checkOrigin: !0 }), y = (e) => {
2
+ try {
3
+ return new URL(e.src, window.location.origin).origin === window.location.origin;
4
+ } catch {
5
+ return !1;
6
+ }
7
+ };
8
+ function m(e, t) {
9
+ let n;
10
+ return (...i) => {
11
+ clearTimeout(n), n = setTimeout(() => e.apply(void 0, i), t);
12
+ };
13
+ }
14
+ const f = I(), d = [], S = (e, t) => {
15
+ const n = { ...b(), ...e }, i = O(t), r = v(n, i);
16
+ return i.map((c) => {
17
+ const o = d.push({ iframe: c, settings: n }), s = p(c, n, r);
18
+ return {
19
+ unsubscribe: () => {
20
+ s(), d.splice(o - 1, 1);
21
+ }
22
+ };
23
+ });
24
+ };
25
+ function O(e) {
26
+ return typeof e == "string" ? Array.from(document.querySelectorAll(e)).filter(l) : e ? l(e) ? [e] : [] : Array.from(document.getElementsByTagName("iframe"));
27
+ }
28
+ function v(e, t) {
29
+ if (Array.isArray(e.checkOrigin))
30
+ return e.checkOrigin;
31
+ if (!e.checkOrigin)
32
+ return [];
33
+ const n = [];
34
+ for (const i of t) {
35
+ const r = z(i);
36
+ r && n.push(r);
37
+ }
38
+ return n;
39
+ }
40
+ function z(e) {
41
+ try {
42
+ const t = new URL(e.src).origin;
43
+ if (t !== "about:blank")
44
+ return t;
45
+ } catch {
46
+ }
47
+ return null;
48
+ }
49
+ function p(e, t, n) {
50
+ return y(e) ? E(e) : L(e, t, n);
51
+ }
52
+ function L(e, t, n) {
53
+ const i = (r) => {
54
+ var o;
55
+ if ((!t.checkOrigin || n.includes(r.origin)) && ((o = r.data) == null ? void 0 : o.type) === "iframe-resized" && e.contentWindow === r.source) {
56
+ const { width: s, height: a } = r.data;
57
+ g({ width: s, height: a, iframe: e, settings: t });
58
+ }
59
+ };
60
+ return window.addEventListener("message", i, !1), () => window.removeEventListener("message", i, !1);
61
+ }
62
+ function E(e) {
63
+ const t = () => {
64
+ var i;
65
+ const n = (i = e.contentDocument) == null ? void 0 : i.body;
66
+ if (!n) {
67
+ console.error("Unable to observe the iframe content document body");
68
+ return;
69
+ }
70
+ f.observe(n);
71
+ };
72
+ return e.addEventListener("load", t), () => {
73
+ var n;
74
+ (n = e.contentDocument) != null && n.body && f.unobserve(e.contentDocument.body), e.removeEventListener("load", t);
75
+ };
76
+ }
77
+ function I() {
78
+ const e = ({ target: n }) => {
79
+ var a;
80
+ const i = d.find((h) => {
81
+ var u;
82
+ return ((u = h.iframe.contentDocument) == null ? void 0 : u.body) === n;
83
+ });
84
+ if (!i)
85
+ return;
86
+ const { iframe: r, settings: c } = i, { scrollHeight: o, scrollWidth: s } = ((a = r.contentDocument) == null ? void 0 : a.documentElement) ?? {};
87
+ o !== void 0 && s !== void 0 && g({ width: s, height: o, iframe: r, settings: c });
88
+ }, t = m((n) => n.forEach(e), 10);
89
+ return new ResizeObserver(t);
90
+ }
91
+ function g({ width: e, height: t, iframe: n, settings: i }) {
92
+ n.style.width = `${e}px`, n.style.height = `${t + i.offsetSize}px`;
93
+ }
94
+ w() && R();
95
+ function R() {
96
+ window.addEventListener("load", () => {
97
+ const e = m(() => {
98
+ const n = {
99
+ type: "iframe-resized",
100
+ width: document.documentElement.scrollWidth,
101
+ height: document.documentElement.scrollHeight
102
+ };
103
+ window.parent.postMessage(n, "*");
104
+ }, 10);
105
+ new ResizeObserver(e).observe(document.body);
106
+ });
107
+ }
108
+ export {
109
+ S as initialize,
110
+ R as initializeChildListener
111
+ };
112
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/common.ts","../src/parent.ts","../src/child.ts"],"sourcesContent":["import type { Settings } from \"~/type\";\n\nconst isInIframe = () => window && window.self !== window.top;\n\nconst isSameOriginIframe = (iframe: HTMLIFrameElement): iframe is HTMLIFrameElement & { contentDocument: Document } => !!iframe.contentDocument;\n\nconst isHtmlIframeElement = (element: Element): element is HTMLIFrameElement => element instanceof HTMLIFrameElement;\n\nconst deferWhenDomContentIsLoaded = (document: Document, executable: () => void) => {\n\tdocument.readyState === \"loading\" ? document.addEventListener(\"DOMContentLoaded\", executable) : executable();\n};\n\nconst deferWhenPageIsLoaded = (document: Document, executable: () => void) => {\n\tdocument.readyState !== \"complete\" ? document.addEventListener(\"load\", executable) : executable();\n};\n\nconst getDefaultSettings: () => Settings = () => ({ offsetSize: 0, checkOrigin: true });\n\nconst isIframeSameOrigin = (iframe: HTMLIFrameElement) => {\n\ttry {\n\t\tconst iframeSrc = new URL(iframe.src, window.location.origin);\n\t\treturn iframeSrc.origin === window.location.origin;\n\t} catch (e) {\n\t\treturn false;\n\t}\n};\n\n// biome-ignore lint/suspicious/noExplicitAny:\nfunction debounce<T extends (...args: any[]) => any>(f: T, delay: number) {\n\tlet timer: NodeJS.Timeout;\n\treturn (...args: unknown[]) => {\n\t\tclearTimeout(timer);\n\t\ttimer = setTimeout(() => f.apply(undefined, args), delay);\n\t};\n}\n\nexport {\n\tisInIframe,\n\tisSameOriginIframe,\n\tdeferWhenDomContentIsLoaded,\n\tisHtmlIframeElement,\n\tdeferWhenPageIsLoaded,\n\tisIframeSameOrigin,\n\tdebounce,\n\tgetDefaultSettings,\n};\n","import { debounce, getDefaultSettings, isHtmlIframeElement, isIframeSameOrigin } from \"~/common\";\nimport type { IframeResizeEvent, InitializeFunction, Settings } from \"./type\";\n\nconst resizeObserver = createResizeObserver();\nconst registeredIframes: Array<{ iframe: HTMLIFrameElement; settings: Settings }> = [];\n\nconst initialize: InitializeFunction = (clientSettings, selector) => {\n\tconst finalSettings = { ...getDefaultSettings(), ...clientSettings };\n\tconst iframes = resolveIframesToRegister(selector);\n\tconst allowedOrigins = registerIframesAllowOrigins(finalSettings, iframes);\n\n\treturn iframes.map((iframe) => {\n\t\tconst length = registeredIframes.push({ iframe, settings: finalSettings });\n\t\tconst unsubscribeResizeListener = addChildResizeListener(iframe, finalSettings, allowedOrigins);\n\t\treturn {\n\t\t\tunsubscribe: () => {\n\t\t\t\tunsubscribeResizeListener();\n\t\t\t\tregisteredIframes.splice(length - 1, 1);\n\t\t\t},\n\t\t};\n\t});\n};\n\nfunction resolveIframesToRegister(selector?: string | HTMLIFrameElement): HTMLIFrameElement[] {\n\tif (typeof selector === \"string\") {\n\t\treturn Array.from(document.querySelectorAll<HTMLElement>(selector)).filter(isHtmlIframeElement);\n\t}\n\tif (selector) {\n\t\treturn isHtmlIframeElement(selector) ? [selector] : [];\n\t}\n\treturn Array.from(document.getElementsByTagName(\"iframe\"));\n}\n\nfunction registerIframesAllowOrigins(settings: Settings, iframes: HTMLIFrameElement[]) {\n\tif (Array.isArray(settings.checkOrigin)) {\n\t\treturn settings.checkOrigin;\n\t}\n\n\tif (!settings.checkOrigin) {\n\t\treturn [];\n\t}\n\n\tconst allowedOrigins: string[] = [];\n\tfor (const iframe of iframes) {\n\t\tconst origin = extractIframeOrigin(iframe);\n\t\tif (origin) {\n\t\t\tallowedOrigins.push(origin);\n\t\t}\n\t}\n\treturn allowedOrigins;\n}\n\nfunction extractIframeOrigin(iframe: HTMLIFrameElement): string | null {\n\ttry {\n\t\tconst origin = new URL(iframe.src).origin;\n\t\tif (origin !== \"about:blank\") {\n\t\t\treturn origin;\n\t\t}\n\t} catch (error) {}\n\treturn null;\n}\n\nfunction addChildResizeListener(iframe: HTMLIFrameElement, settings: Settings, allowedOrigins: string[]) {\n\tif (isIframeSameOrigin(iframe)) {\n\t\treturn addSameOriginChildResizeListener(iframe);\n\t}\n\treturn addCrossOriginChildResizeListener(iframe, settings, allowedOrigins);\n}\n\nfunction addCrossOriginChildResizeListener(iframe: HTMLIFrameElement, settings: Settings, allowedOrigins: string[]) {\n\tconst handleIframeResizedMessage = (event: MessageEvent) => {\n\t\tconst isOriginValid = !settings.checkOrigin || allowedOrigins.includes(event.origin);\n\n\t\tif (isOriginValid && event.data?.type === \"iframe-resized\" && iframe.contentWindow === event.source) {\n\t\t\tconst { width, height } = (event as IframeResizeEvent).data;\n\t\t\tupdateIframeDimensions({ width, height, iframe, settings });\n\t\t}\n\t};\n\n\twindow.addEventListener(\"message\", handleIframeResizedMessage, false);\n\n\treturn () => window.removeEventListener(\"message\", handleIframeResizedMessage, false);\n}\n\nfunction addSameOriginChildResizeListener(iframe: HTMLIFrameElement) {\n\tconst startListener = () => {\n\t\tconst contentBody = iframe.contentDocument?.body;\n\n\t\tif (!contentBody) {\n\t\t\tconsole.error(\"Unable to observe the iframe content document body\");\n\t\t\treturn;\n\t\t}\n\n\t\tresizeObserver.observe(contentBody);\n\t};\n\n\tiframe.addEventListener(\"load\", startListener);\n\n\treturn () => {\n\t\tif (iframe.contentDocument?.body) {\n\t\t\tresizeObserver.unobserve(iframe.contentDocument.body);\n\t\t}\n\t\tiframe.removeEventListener(\"load\", startListener);\n\t};\n}\n\nfunction createResizeObserver() {\n\tconst handleEntry = ({ target }: ResizeObserverEntry) => {\n\t\tconst matchingRegisteredIframe = registeredIframes.find((value) => value.iframe.contentDocument?.body === target);\n\t\tif (!matchingRegisteredIframe) {\n\t\t\treturn;\n\t\t}\n\t\tconst { iframe, settings } = matchingRegisteredIframe;\n\t\tconst { scrollHeight, scrollWidth } = iframe.contentDocument?.documentElement ?? {};\n\t\tif (scrollHeight !== undefined && scrollWidth !== undefined) {\n\t\t\tupdateIframeDimensions({ width: scrollWidth, height: scrollHeight, iframe, settings });\n\t\t}\n\t};\n\n\tconst resizeObserverCallback = debounce<ResizeObserverCallback>((entries) => entries.forEach(handleEntry), 10);\n\treturn new ResizeObserver(resizeObserverCallback);\n}\n\nfunction updateIframeDimensions({ width, height, iframe, settings }: { iframe: HTMLIFrameElement; width: number; height: number; settings: Settings }) {\n\tiframe.style.width = `${width}px`;\n\tiframe.style.height = `${height + settings.offsetSize}px`;\n}\n\nexport { initialize };\n","import { debounce, isInIframe } from \"~/common\";\nimport type { IframeResizeEventData } from \"./type\";\n\nif (isInIframe()) {\n\tinitializeChildListener();\n}\n\nfunction initializeChildListener() {\n\twindow.addEventListener(\"load\", () => {\n\t\tconst resizeObserverCallback = debounce<ResizeObserverCallback>(() => {\n\t\t\tconst data: IframeResizeEventData = {\n\t\t\t\ttype: \"iframe-resized\",\n\t\t\t\twidth: document.documentElement.scrollWidth,\n\t\t\t\theight: document.documentElement.scrollHeight,\n\t\t\t};\n\t\t\twindow.parent.postMessage(data, \"*\");\n\t\t}, 10);\n\n\t\tconst resizeObserver = new ResizeObserver(resizeObserverCallback);\n\t\tresizeObserver.observe(document.body);\n\t});\n}\n\nexport { initializeChildListener };\n"],"names":["isInIframe","isHtmlIframeElement","element","getDefaultSettings","isIframeSameOrigin","iframe","debounce","f","delay","timer","args","resizeObserver","createResizeObserver","registeredIframes","initialize","clientSettings","selector","finalSettings","iframes","resolveIframesToRegister","allowedOrigins","registerIframesAllowOrigins","length","unsubscribeResizeListener","addChildResizeListener","settings","origin","extractIframeOrigin","addSameOriginChildResizeListener","addCrossOriginChildResizeListener","handleIframeResizedMessage","event","_a","width","height","updateIframeDimensions","startListener","contentBody","handleEntry","target","matchingRegisteredIframe","value","scrollHeight","scrollWidth","resizeObserverCallback","entries","initializeChildListener","data"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ (function(o,d){typeof exports=="object"&&typeof module<"u"?d(exports):typeof define=="function"&&define.amd?define(["exports"],d):(o=typeof globalThis<"u"?globalThis:o||self,d(o.iframeResizer={}))})(this,function(o){"use strict";const d=()=>window&&window.self!==window.top,f=e=>e instanceof HTMLIFrameElement,y=()=>({offsetSize:0,checkOrigin:!0}),O=e=>{try{return new URL(e.src,window.location.origin).origin===window.location.origin}catch{return!1}};function m(e,i){let n;return(...t)=>{clearTimeout(n),n=setTimeout(()=>e.apply(void 0,t),i)}}const g=S(),l=[],z=(e,i)=>{const n={...y(),...e},t=p(i),r=v(n,t);return t.map(a=>{const s=l.push({iframe:a,settings:n}),c=E(a,n,r);return{unsubscribe:()=>{c(),l.splice(s-1,1)}}})};function p(e){return typeof e=="string"?Array.from(document.querySelectorAll(e)).filter(f):e?f(e)?[e]:[]:Array.from(document.getElementsByTagName("iframe"))}function v(e,i){if(Array.isArray(e.checkOrigin))return e.checkOrigin;if(!e.checkOrigin)return[];const n=[];for(const t of i){const r=L(t);r&&n.push(r)}return n}function L(e){try{const i=new URL(e.src).origin;if(i!=="about:blank")return i}catch{}return null}function E(e,i,n){return O(e)?I(e):R(e,i,n)}function R(e,i,n){const t=r=>{var s;if((!i.checkOrigin||n.includes(r.origin))&&((s=r.data)==null?void 0:s.type)==="iframe-resized"&&e.contentWindow===r.source){const{width:c,height:u}=r.data;h({width:c,height:u,iframe:e,settings:i})}};return window.addEventListener("message",t,!1),()=>window.removeEventListener("message",t,!1)}function I(e){const i=()=>{var t;const n=(t=e.contentDocument)==null?void 0:t.body;if(!n){console.error("Unable to observe the iframe content document body");return}g.observe(n)};return e.addEventListener("load",i),()=>{var n;(n=e.contentDocument)!=null&&n.body&&g.unobserve(e.contentDocument.body),e.removeEventListener("load",i)}}function S(){const e=({target:n})=>{var u;const t=l.find(k=>{var w;return((w=k.iframe.contentDocument)==null?void 0:w.body)===n});if(!t)return;const{iframe:r,settings:a}=t,{scrollHeight:s,scrollWidth:c}=((u=r.contentDocument)==null?void 0:u.documentElement)??{};s!==void 0&&c!==void 0&&h({width:c,height:s,iframe:r,settings:a})},i=m(n=>n.forEach(e),10);return new ResizeObserver(i)}function h({width:e,height:i,iframe:n,settings:t}){n.style.width=`${e}px`,n.style.height=`${i+t.offsetSize}px`}d()&&b();function b(){window.addEventListener("load",()=>{const e=m(()=>{const n={type:"iframe-resized",width:document.documentElement.scrollWidth,height:document.documentElement.scrollHeight};window.parent.postMessage(n,"*")},10);new ResizeObserver(e).observe(document.body)})}o.initialize=z,o.initializeChildListener=b,Object.defineProperty(o,Symbol.toStringTag,{value:"Module"})});
2
+ //# sourceMappingURL=index.umd.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.umd.cjs","sources":["../src/common.ts","../src/parent.ts","../src/child.ts"],"sourcesContent":["import type { Settings } from \"~/type\";\n\nconst isInIframe = () => window && window.self !== window.top;\n\nconst isSameOriginIframe = (iframe: HTMLIFrameElement): iframe is HTMLIFrameElement & { contentDocument: Document } => !!iframe.contentDocument;\n\nconst isHtmlIframeElement = (element: Element): element is HTMLIFrameElement => element instanceof HTMLIFrameElement;\n\nconst deferWhenDomContentIsLoaded = (document: Document, executable: () => void) => {\n\tdocument.readyState === \"loading\" ? document.addEventListener(\"DOMContentLoaded\", executable) : executable();\n};\n\nconst deferWhenPageIsLoaded = (document: Document, executable: () => void) => {\n\tdocument.readyState !== \"complete\" ? document.addEventListener(\"load\", executable) : executable();\n};\n\nconst getDefaultSettings: () => Settings = () => ({ offsetSize: 0, checkOrigin: true });\n\nconst isIframeSameOrigin = (iframe: HTMLIFrameElement) => {\n\ttry {\n\t\tconst iframeSrc = new URL(iframe.src, window.location.origin);\n\t\treturn iframeSrc.origin === window.location.origin;\n\t} catch (e) {\n\t\treturn false;\n\t}\n};\n\n// biome-ignore lint/suspicious/noExplicitAny:\nfunction debounce<T extends (...args: any[]) => any>(f: T, delay: number) {\n\tlet timer: NodeJS.Timeout;\n\treturn (...args: unknown[]) => {\n\t\tclearTimeout(timer);\n\t\ttimer = setTimeout(() => f.apply(undefined, args), delay);\n\t};\n}\n\nexport {\n\tisInIframe,\n\tisSameOriginIframe,\n\tdeferWhenDomContentIsLoaded,\n\tisHtmlIframeElement,\n\tdeferWhenPageIsLoaded,\n\tisIframeSameOrigin,\n\tdebounce,\n\tgetDefaultSettings,\n};\n","import { debounce, getDefaultSettings, isHtmlIframeElement, isIframeSameOrigin } from \"~/common\";\nimport type { IframeResizeEvent, InitializeFunction, Settings } from \"./type\";\n\nconst resizeObserver = createResizeObserver();\nconst registeredIframes: Array<{ iframe: HTMLIFrameElement; settings: Settings }> = [];\n\nconst initialize: InitializeFunction = (clientSettings, selector) => {\n\tconst finalSettings = { ...getDefaultSettings(), ...clientSettings };\n\tconst iframes = resolveIframesToRegister(selector);\n\tconst allowedOrigins = registerIframesAllowOrigins(finalSettings, iframes);\n\n\treturn iframes.map((iframe) => {\n\t\tconst length = registeredIframes.push({ iframe, settings: finalSettings });\n\t\tconst unsubscribeResizeListener = addChildResizeListener(iframe, finalSettings, allowedOrigins);\n\t\treturn {\n\t\t\tunsubscribe: () => {\n\t\t\t\tunsubscribeResizeListener();\n\t\t\t\tregisteredIframes.splice(length - 1, 1);\n\t\t\t},\n\t\t};\n\t});\n};\n\nfunction resolveIframesToRegister(selector?: string | HTMLIFrameElement): HTMLIFrameElement[] {\n\tif (typeof selector === \"string\") {\n\t\treturn Array.from(document.querySelectorAll<HTMLElement>(selector)).filter(isHtmlIframeElement);\n\t}\n\tif (selector) {\n\t\treturn isHtmlIframeElement(selector) ? [selector] : [];\n\t}\n\treturn Array.from(document.getElementsByTagName(\"iframe\"));\n}\n\nfunction registerIframesAllowOrigins(settings: Settings, iframes: HTMLIFrameElement[]) {\n\tif (Array.isArray(settings.checkOrigin)) {\n\t\treturn settings.checkOrigin;\n\t}\n\n\tif (!settings.checkOrigin) {\n\t\treturn [];\n\t}\n\n\tconst allowedOrigins: string[] = [];\n\tfor (const iframe of iframes) {\n\t\tconst origin = extractIframeOrigin(iframe);\n\t\tif (origin) {\n\t\t\tallowedOrigins.push(origin);\n\t\t}\n\t}\n\treturn allowedOrigins;\n}\n\nfunction extractIframeOrigin(iframe: HTMLIFrameElement): string | null {\n\ttry {\n\t\tconst origin = new URL(iframe.src).origin;\n\t\tif (origin !== \"about:blank\") {\n\t\t\treturn origin;\n\t\t}\n\t} catch (error) {}\n\treturn null;\n}\n\nfunction addChildResizeListener(iframe: HTMLIFrameElement, settings: Settings, allowedOrigins: string[]) {\n\tif (isIframeSameOrigin(iframe)) {\n\t\treturn addSameOriginChildResizeListener(iframe);\n\t}\n\treturn addCrossOriginChildResizeListener(iframe, settings, allowedOrigins);\n}\n\nfunction addCrossOriginChildResizeListener(iframe: HTMLIFrameElement, settings: Settings, allowedOrigins: string[]) {\n\tconst handleIframeResizedMessage = (event: MessageEvent) => {\n\t\tconst isOriginValid = !settings.checkOrigin || allowedOrigins.includes(event.origin);\n\n\t\tif (isOriginValid && event.data?.type === \"iframe-resized\" && iframe.contentWindow === event.source) {\n\t\t\tconst { width, height } = (event as IframeResizeEvent).data;\n\t\t\tupdateIframeDimensions({ width, height, iframe, settings });\n\t\t}\n\t};\n\n\twindow.addEventListener(\"message\", handleIframeResizedMessage, false);\n\n\treturn () => window.removeEventListener(\"message\", handleIframeResizedMessage, false);\n}\n\nfunction addSameOriginChildResizeListener(iframe: HTMLIFrameElement) {\n\tconst startListener = () => {\n\t\tconst contentBody = iframe.contentDocument?.body;\n\n\t\tif (!contentBody) {\n\t\t\tconsole.error(\"Unable to observe the iframe content document body\");\n\t\t\treturn;\n\t\t}\n\n\t\tresizeObserver.observe(contentBody);\n\t};\n\n\tiframe.addEventListener(\"load\", startListener);\n\n\treturn () => {\n\t\tif (iframe.contentDocument?.body) {\n\t\t\tresizeObserver.unobserve(iframe.contentDocument.body);\n\t\t}\n\t\tiframe.removeEventListener(\"load\", startListener);\n\t};\n}\n\nfunction createResizeObserver() {\n\tconst handleEntry = ({ target }: ResizeObserverEntry) => {\n\t\tconst matchingRegisteredIframe = registeredIframes.find((value) => value.iframe.contentDocument?.body === target);\n\t\tif (!matchingRegisteredIframe) {\n\t\t\treturn;\n\t\t}\n\t\tconst { iframe, settings } = matchingRegisteredIframe;\n\t\tconst { scrollHeight, scrollWidth } = iframe.contentDocument?.documentElement ?? {};\n\t\tif (scrollHeight !== undefined && scrollWidth !== undefined) {\n\t\t\tupdateIframeDimensions({ width: scrollWidth, height: scrollHeight, iframe, settings });\n\t\t}\n\t};\n\n\tconst resizeObserverCallback = debounce<ResizeObserverCallback>((entries) => entries.forEach(handleEntry), 10);\n\treturn new ResizeObserver(resizeObserverCallback);\n}\n\nfunction updateIframeDimensions({ width, height, iframe, settings }: { iframe: HTMLIFrameElement; width: number; height: number; settings: Settings }) {\n\tiframe.style.width = `${width}px`;\n\tiframe.style.height = `${height + settings.offsetSize}px`;\n}\n\nexport { initialize };\n","import { debounce, isInIframe } from \"~/common\";\nimport type { IframeResizeEventData } from \"./type\";\n\nif (isInIframe()) {\n\tinitializeChildListener();\n}\n\nfunction initializeChildListener() {\n\twindow.addEventListener(\"load\", () => {\n\t\tconst resizeObserverCallback = debounce<ResizeObserverCallback>(() => {\n\t\t\tconst data: IframeResizeEventData = {\n\t\t\t\ttype: \"iframe-resized\",\n\t\t\t\twidth: document.documentElement.scrollWidth,\n\t\t\t\theight: document.documentElement.scrollHeight,\n\t\t\t};\n\t\t\twindow.parent.postMessage(data, \"*\");\n\t\t}, 10);\n\n\t\tconst resizeObserver = new ResizeObserver(resizeObserverCallback);\n\t\tresizeObserver.observe(document.body);\n\t});\n}\n\nexport { initializeChildListener };\n"],"names":["isInIframe","isHtmlIframeElement","element","getDefaultSettings","isIframeSameOrigin","iframe","debounce","f","delay","timer","args","resizeObserver","createResizeObserver","registeredIframes","initialize","clientSettings","selector","finalSettings","iframes","resolveIframesToRegister","allowedOrigins","registerIframesAllowOrigins","length","unsubscribeResizeListener","addChildResizeListener","settings","origin","extractIframeOrigin","addSameOriginChildResizeListener","addCrossOriginChildResizeListener","handleIframeResizedMessage","event","_a","width","height","updateIframeDimensions","startListener","contentBody","handleEntry","target","matchingRegisteredIframe","value","scrollHeight","scrollWidth","resizeObserverCallback","entries","initializeChildListener","data"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { InitializeFunction } from './type';
2
+ declare const initialize: InitializeFunction;
3
+ export { initialize };
package/dist/type.d.ts ADDED
@@ -0,0 +1,21 @@
1
+ interface Window {
2
+ iframeResizer: {
3
+ initialize: InitializeFunction;
4
+ };
5
+ }
6
+
7
+ export type InitializeFunction = (settings?: Partial<Settings>, selector?: string | HTMLIFrameElement) => InitializeResult[];
8
+ export type InitializeResult = { unsubscribe: () => void };
9
+
10
+ export type Settings = {
11
+ offsetSize: number;
12
+ checkOrigin: string[] | boolean;
13
+ };
14
+
15
+ export type IframeResizeEventData = {
16
+ type: "iframe-resized";
17
+ width: number;
18
+ height: number;
19
+ };
20
+
21
+ export type IframeResizeEvent = MessageEvent<IframeResizeEventData>;
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@open-iframe-resizer/core",
3
+ "private": false,
4
+ "version": "1.0.0-rc1",
5
+ "description": "An open iframe resizer library",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "iframe-resizer",
9
+ "iframe",
10
+ "resize"
11
+ ],
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/Lemick/open-iframe-resizer.git"
15
+ },
16
+ "type": "module",
17
+ "main": "./dist/index.cjs",
18
+ "module": "./dist/index.js",
19
+ "typings": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js",
24
+ "require": "./dist/index.cjs"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "scripts": {
31
+ "docs": "npm run typedoc",
32
+ "lint": "biome lint ./src",
33
+ "build": "tsc && npm run lint && vite build && typedoc",
34
+ "build:watch": "vite build --watch && typedoc",
35
+ "build:usecases-html": "node scripts/generate-use-cases-html.js",
36
+ "dev": "concurrently \"vite build --watch\" \"npm run serve\"",
37
+ "serve": "concurrently \"vite --port 5550\" \"vite --port 5551\"",
38
+ "test": "npm run test:unit && npm run test:e2e",
39
+ "test:e2e": "npx playwright install --with-deps && npx playwright test",
40
+ "test:unit": "vitest run"
41
+ },
42
+ "devDependencies": {
43
+ "@microsoft/tsdoc": "^0.14.1",
44
+ "picocolors": "^1.0.1"
45
+ }
46
+ }