22
33import type { ContentKitWebFrame } from '@gitbook/api' ;
44import React from 'react' ;
5+ import { useResizeObserver } from 'usehooks-ts' ;
56
7+ import { Icon } from '@gitbook/icons' ;
68import { useContentKitClientContext } from './context' ;
79import { resolveDynamicBinding } from './dynamic' ;
810import type { ContentKitClientElementProps } from './types' ;
@@ -47,9 +49,7 @@ export function ElementWebframe(props: ContentKitClientElementProps<ContentKitWe
4749 [ renderer . security ]
4850 ) ;
4951
50- //
51- // Listen to message coming from the webframe
52- //
52+ // Listen to messages coming from the webframe
5353 React . useEffect ( ( ) => {
5454 const callback = ( event : MessageEvent ) => {
5555 if ( ! iframeRef . current ) {
@@ -83,7 +83,7 @@ export function ElementWebframe(props: ContentKitClientElementProps<ContentKitWe
8383 // https://docs.embed.ly/reference/provider-height-resizing
8484 const parsed = JSON . parse ( message ) ;
8585 if ( parsed . context === 'iframe.resize' && typeof parsed . height === 'number' ) {
86- const width = contentWindow . outerWidth ;
86+ const width = iframeRef . current . clientWidth ;
8787 const height = parsed . height ;
8888
8989 setSize ( {
@@ -145,9 +145,7 @@ export function ElementWebframe(props: ContentKitClientElementProps<ContentKitWe
145145 } ;
146146 } , [ renderer , sendMessage ] ) ;
147147
148- //
149148 // Send data to the webframe
150- //
151149 React . useEffect ( ( ) => {
152150 if ( ! element . data ) {
153151 return ;
@@ -161,12 +159,20 @@ export function ElementWebframe(props: ContentKitClientElementProps<ContentKitWe
161159 return sendMessage ( { state } ) ;
162160 } , [ element . data , renderer . state , sendMessage ] ) ;
163161
164- if ( ! mounted ) {
165- return null ;
166- }
162+ const { width : observedWidth = 0 } = useResizeObserver ( { ref : iframeRef } ) ;
163+ const liveWidth = observedWidth || iframeRef . current ?. clientWidth || 0 ;
167164
168165 const aspectRatio = size . aspectRatio || element . aspectRatio ;
169166
167+ const height =
168+ liveWidth && aspectRatio && liveWidth > ( size . height ?? 0 )
169+ ? Math . min ( Math . round ( liveWidth / aspectRatio ) , size . height ?? 32 )
170+ : 'auto' ;
171+
172+ if ( ! mounted ) {
173+ return < Icon icon = "spinner" className = "contentkit-button-loading" style = { { height } } /> ;
174+ }
175+
170176 return (
171177 < iframe
172178 ref = { iframeRef }
@@ -179,7 +185,8 @@ export function ElementWebframe(props: ContentKitClientElementProps<ContentKitWe
179185 width : '100%' ,
180186 maxWidth : '100%' ,
181187 aspectRatio,
182- height : size . height ? Math . max ( size . height , 32 ) : '100%' ,
188+ maxHeight : height ,
189+ height : 'fit-content' ,
183190 border : 'none' ,
184191 } }
185192 />
0 commit comments