1414 * limitations under the License.
1515 */
1616
17- import React , { useLayoutEffect , useRef , useState } from ' react' ;
17+ import React , { useLayoutEffect , useRef , useState } from " react" ;
1818
19- import { PresentationDimension , SlideAreaDimension } from ' ./PresentationDimensions' ;
19+ import { PresentationDimension , SlideAreaDimension } from " ./PresentationDimensions" ;
2020
21- import ' ./PresentationSlideContainer.css' ;
21+ import " ./PresentationSlideContainer.css" ;
2222
2323interface Props {
2424 slideIdx : number ;
@@ -32,75 +32,108 @@ interface Props {
3232}
3333
3434export function PresentationSlideContainer ( {
35- slideIdx,
36- maxScaleRatio,
37- isPadded,
38- isScaled,
39- isCentered,
40- presentationArea,
41- slideArea,
42- render
43- } : Props ) {
35+ slideIdx,
36+ maxScaleRatio,
37+ isPadded,
38+ isScaled,
39+ isCentered,
40+ presentationArea,
41+ slideArea,
42+ render,
43+ } : Props ) {
4444 const [ scaleRatio , setScaleRatio ] = useState ( 1 ) ;
4545 const [ slideAppeared , setSlideAppeared ] = useState ( false ) ;
4646
4747 const contentNode = useRef < HTMLDivElement > ( null ) ;
4848
4949 useLayoutEffect ( ( ) => {
50- setScaleRatio ( isScaled ?
51- calcScale ( presentationArea , slideArea , contentNode . current ! , isPadded , maxScaleRatio ) :
52- 1.0 ) ;
53-
54- setSlideAppeared ( true ) ;
55- } , [ isPadded , maxScaleRatio , isScaled , slideIdx , presentationArea , slideArea ] )
56-
57- const className = "znai-presentation-slide-container " +
50+ if ( ! isScaled ) {
51+ setScaleRatio ( 1.0 ) ;
52+ setSlideAppeared ( true ) ;
53+ return ;
54+ }
55+
56+ const node = contentNode . current ! ;
57+
58+ const tryCalcScale = ( ) => {
59+ if ( ! hasContentLoaded ( node ) ) {
60+ return false ;
61+ }
62+ setScaleRatio ( calcScale ( presentationArea , slideArea , node , isPadded , maxScaleRatio ) ) ;
63+ setSlideAppeared ( true ) ;
64+ return true ;
65+ } ;
66+
67+ if ( tryCalcScale ( ) ) {
68+ return ;
69+ }
70+
71+ const resizeObserver = new ResizeObserver ( ( ) => {
72+ if ( tryCalcScale ( ) ) {
73+ resizeObserver . disconnect ( ) ;
74+ }
75+ } ) ;
76+ resizeObserver . observe ( node ) ;
77+
78+ return ( ) => {
79+ resizeObserver . disconnect ( ) ;
80+ } ;
81+ } , [ isPadded , maxScaleRatio , isScaled , slideIdx , presentationArea , slideArea ] ) ;
82+
83+ const className =
84+ "znai-presentation-slide-container " +
5885 ( isCentered ? " centered" : "" ) +
5986 ( isPadded ? " padded" : "" ) +
6087 ( slideAppeared ? " znai-presentation-slide-appeared" : "" ) ;
6188
6289 const rendered = render ( ) ;
6390
6491 const wrappedChildren = isScaled ? (
65- < div ref = { contentNode } style = { { transform : "scale(" + scaleRatio + ")" } } >
92+ < div ref = { contentNode } style = { { transform : "scale(" + scaleRatio + ")" } } >
6693 { rendered }
6794 </ div >
68- ) : rendered ;
95+ ) : (
96+ rendered
97+ ) ;
6998
70- const maxWidth = presentationArea . width * slideArea . widthPercentage / 100.0
71- const maxHeight = presentationArea . height * slideArea . heightPercentage / 100.0
99+ const maxWidth = ( presentationArea . width * slideArea . widthPercentage ) / 100.0 ;
100+ const maxHeight = ( presentationArea . height * slideArea . heightPercentage ) / 100.0 ;
72101
73102 return (
74- < div className = { className } style = { { width : maxWidth , height : maxHeight } } >
103+ < div className = { className } style = { { width : maxWidth , height : maxHeight } } >
75104 { wrappedChildren }
76105 </ div >
77- )
106+ ) ;
78107}
79108
80- function calcScale ( presentationArea : PresentationDimension ,
81- slideArea : SlideAreaDimension ,
82- contentNode : HTMLDivElement ,
83- isPadded : boolean ,
84- maxScaleRatio : number ) : number {
109+ function hasContentLoaded ( contentNode : HTMLDivElement ) : boolean {
110+ return contentNode . offsetWidth > 0 && contentNode . offsetHeight > 0 ;
111+ }
112+
113+ function calcScale (
114+ presentationArea : PresentationDimension ,
115+ slideArea : SlideAreaDimension ,
116+ contentNode : HTMLDivElement ,
117+ isPadded : boolean ,
118+ maxScaleRatio : number
119+ ) : number {
85120 // code based padding to avoid margin collapse
86121 const hPad = isPadded ? 60 : 0 ;
87122 const vPad = isPadded ? 30 : 0 ;
88123
89- const maxWidth = calcMaxWidth ( presentationArea , slideArea )
90- const maxHeight = calcMaxHeight ( presentationArea , slideArea )
124+ const maxWidth = calcMaxWidth ( presentationArea , slideArea ) ;
125+ const maxHeight = calcMaxHeight ( presentationArea , slideArea ) ;
91126
92127 const widthRatio = ( maxWidth - hPad ) / contentNode . offsetWidth ;
93128 const heightRatio = ( maxHeight - vPad ) / contentNode . offsetHeight ;
94129
95130 return Math . min ( widthRatio , heightRatio , maxScaleRatio ) ;
96131}
97132
98- function calcMaxWidth ( presentationArea : PresentationDimension ,
99- slideArea : SlideAreaDimension ) {
100- return presentationArea . width * slideArea . widthPercentage / 100.0
133+ function calcMaxWidth ( presentationArea : PresentationDimension , slideArea : SlideAreaDimension ) {
134+ return ( presentationArea . width * slideArea . widthPercentage ) / 100.0 ;
101135}
102136
103- function calcMaxHeight ( presentationArea : PresentationDimension ,
104- slideArea : SlideAreaDimension ) {
105- return presentationArea . height * slideArea . heightPercentage / 100.0
106- }
137+ function calcMaxHeight ( presentationArea : PresentationDimension , slideArea : SlideAreaDimension ) {
138+ return ( presentationArea . height * slideArea . heightPercentage ) / 100.0 ;
139+ }
0 commit comments