11import React , {
2+ useState ,
23 forwardRef ,
34 useCallback ,
45 useImperativeHandle ,
@@ -101,23 +102,28 @@ function _sliceSeries(
101102 */
102103function getDimensions (
103104 options : any ,
104- style : any ,
105- deviceWidth : number ,
106- deviceHeight : number ,
105+ width : number ,
106+ height : number ,
107+ // style: any,
108+ // deviceWidth: number,
109+ // deviceHeight: number,
107110 margin : { title ?: number ; legend ?: number } ,
108111) : {
109112 optionsFinal : any ;
110- containerWidth : number ;
111- containerHeight : number ;
113+ // containerWidth: number;
114+ // containerHeight: number;
112115} {
113- var containerWidth = options ?. width || style ?. width || deviceWidth ;
114- containerWidth = Math . min ( containerWidth , deviceWidth ) ;
116+ // var containerWidth = options?.width || style?.width || deviceWidth;
117+ // containerWidth = Math.min(containerWidth, deviceWidth);
115118
116- var containerHeight = options ?. height || style ?. height || deviceHeight ;
117- containerHeight = Math . min ( containerHeight , deviceHeight ) ;
119+ // var containerHeight = options?.height || style?.height || deviceHeight;
120+ // containerHeight = Math.min(containerHeight, deviceHeight);
118121
119- var uplotWidth = containerWidth ;
120- var uplotHeight = containerHeight ;
122+ // var uplotWidth = containerWidth;
123+ // var uplotHeight = containerHeight;
124+
125+ var uplotWidth = width ;
126+ var uplotHeight = height ;
121127
122128 if ( options ?. title ) {
123129 // Subtract height for title
@@ -135,11 +141,12 @@ function getDimensions(
135141 optionsFinal . width = uplotWidth ;
136142 optionsFinal . height = uplotHeight ;
137143
138- return { optionsFinal, containerWidth, containerHeight } ;
144+ return optionsFinal ;
145+ // return { optionsFinal, containerWidth, containerHeight };
139146}
140147
141148function getCreateChartString (
142- data : number [ ] [ ] | null ,
149+ data : number [ ] [ ] | null = null ,
143150 options : any ,
144151 bgColor : string = 'transparent' ,
145152 injectedJavaScript : string = '' ,
@@ -152,7 +159,7 @@ function getCreateChartString(
152159 data !== null ? `if (window.__CHART_CREATED__) return;` : `` ;
153160
154161 return `
155- (function() {
162+ (function() {
156163 ${ chartCreatedCheck }
157164 window.__CHART_CREATED__ = true;
158165
@@ -217,21 +224,50 @@ const ChartUPlot = forwardRef<any, UPlotProps>(
217224 let webref : any = useRef ( null ) ;
218225 const uplotInstance = useRef < any > ( null ) ;
219226 const dataRef = useRef < number [ ] [ ] > ( data as number [ ] [ ] ) ;
220- const initialized = useRef ( false ) ;
227+ const variablesRef = useRef < { [ key : string ] : any } > ( { } ) ;
228+ const initialized = useRef < boolean > ( false ) ;
229+ const containerRef = useRef < any > ( null ) ;
230+ const dimensionsRef = useRef ( {
231+ containerWidth : options ?. width || style ?. width || height ,
232+ containerHeight : options ?. height || style ?. height || width ,
233+ } ) ;
221234
222235 const bgColor = style ?. backgroundColor || 'transparent' ;
223236
224- var { optionsFinal, containerWidth, containerHeight } = useMemo ( ( ) => {
225- return getDimensions ( options , style , width , height , margin ) ;
226- } , [ options , style , width , height ] ) ;
237+ const handleLayout = useCallback ( ( event ) => {
238+ const { width, height } = event . nativeEvent . layout ;
239+ dimensionsRef . current = {
240+ containerWidth : width ,
241+ containerHeight : height ,
242+ } ;
243+ } , [ ] ) ;
244+
245+ // var { optionsFinal, containerWidth, containerHeight } = useMemo(() => {
246+
247+ // const { containerWidth, containerHeight } = dimensionsRef.current.containerWidth
248+ // ? dimensionsRef.current
249+ // : { containerWidth: width, containerHeight: height };
250+
251+ // return getDimensions(options, style, containerWidth, containerHeight, margin);
252+ // }, [style, width, height]);
253+
254+ // var optsFinal = useMemo(() => {
255+ // return options
256+ // // return getDimensions(
257+ // // options,
258+ // // dimensionsRef.current.containerWidth,
259+ // // dimensionsRef.current.containerHeight,
260+ // // margin,
261+ // // );
262+ // }, [style, margin]);
227263
228264 useEffect ( ( ) => {
229265 // update uplot height and width if options change
230266
231267 if ( isWeb ) {
232268 uplotInstance . current ?. setSize ( {
233- width : containerWidth ,
234- height : containerHeight ,
269+ width : dimensionsRef . current . containerWidth ,
270+ height : dimensionsRef . current . containerHeight ,
235271 } ) ;
236272 } else {
237273 if ( ! webref . current ) {
@@ -241,24 +277,39 @@ const ChartUPlot = forwardRef<any, UPlotProps>(
241277
242278 webref . current . injectJavaScript ( `
243279 if (window._chart) {
244- window._chart.setSize(${ JSON . stringify ( containerWidth ) } , ${ JSON . stringify ( containerHeight ) } );
280+ window._chart.setSize(${ JSON . stringify ( dimensionsRef . current . containerWidth ) } , ${ JSON . stringify ( dimensionsRef . current . containerHeight ) } );
245281 } else {
246282 console.error('Chart not initialized');
247283 }
248284 true;
249285 ` ) ;
250286 }
251- } , [ containerWidth , containerHeight ] ) ;
287+ } , [
288+ dimensionsRef . current . containerHeight ,
289+ dimensionsRef . current . containerWidth ,
290+ ] ) ;
252291
253292 // eslint-disable-next-line @typescript-eslint/no-explicit-any
254293 const createChart = useCallback (
255- ( opts : any , data : number [ ] [ ] , bgColor ?: string ) : void => {
294+ ( opts : any , data : number [ ] [ ] | null = null , bgColor ?: string ) : void => {
256295 if ( initialized . current ) {
257296 return ;
258297 }
259298
299+ const optsFinal = getDimensions (
300+ opts ,
301+ // style,
302+ dimensionsRef . current . containerWidth ,
303+ dimensionsRef . current . containerHeight ,
304+ margin ,
305+ ) ;
306+
260307 if ( isWeb ) {
261- uplotInstance . current = new uPlot ( opts , data , webref . current ) ;
308+ uplotInstance . current = new uPlot (
309+ optsFinal ,
310+ data == null ? dataRef . current : data ,
311+ webref . current ,
312+ ) ;
262313 } else {
263314 // inject background color before chart setup if provided
264315 if ( ! webref ?. current ) {
@@ -267,7 +318,7 @@ const ChartUPlot = forwardRef<any, UPlotProps>(
267318 }
268319
269320 webref . current . injectJavaScript (
270- getCreateChartString ( data , opts , bgColor ) ,
321+ getCreateChartString ( data , optsFinal , bgColor ) ,
271322 ) ;
272323 }
273324 initialized . current = true ;
@@ -282,24 +333,10 @@ const ChartUPlot = forwardRef<any, UPlotProps>(
282333 * @param {Object } newOptions - The new options to set for the chart.
283334 */
284335 const updateOptions = useCallback ( ( newOptions : any ) : void => {
285- if ( isWeb ) {
286- if ( uplotInstance . current ) {
287- uplotInstance . current . destroy ( ) ;
288- }
336+ // call getDimensions to update optionsFinal
289337
290- uplotInstance . current = new uPlot (
291- newOptions ,
292- dataRef . current ,
293- webref . current ,
294- ) ;
295- } else {
296- if ( ! webref ?. current ) {
297- console . error ( 'WebView reference is not set' ) ;
298- return ;
299- }
300-
301- webref . current . injectJavaScript ( getCreateChartString ( null , newOptions ) ) ;
302- }
338+ destroy ( true ) ; // keep data
339+ createChart ( newOptions ) ;
303340 } , [ ] ) ;
304341
305342 /**
@@ -374,7 +411,6 @@ const ChartUPlot = forwardRef<any, UPlotProps>(
374411 window._data[i].push(item[i]);
375412 }
376413 if (window._chart) {
377- console.debug('Pushing new data to uPlot chart');
378414 window._chart.setData(window._data);
379415 } else {
380416 console.error('Chart not initialized');
@@ -455,6 +491,8 @@ const ChartUPlot = forwardRef<any, UPlotProps>(
455491 // if web, sets the variable to window.[name]
456492 // if native, sets the variable to window.[name] via webref.current.injectJavaScript
457493 const setVariable = useCallback ( ( name : string , value : any ) : void => {
494+ variablesRef . current [ name ] = value ;
495+
458496 if ( isWeb ) {
459497 if ( ! window ) {
460498 console . error ( 'Window is not defined' ) ;
@@ -469,11 +507,7 @@ const ChartUPlot = forwardRef<any, UPlotProps>(
469507 }
470508
471509 webref . current . injectJavaScript ( `
472- if (window._chart) {
473- window.${ name } = ${ JSON . stringify ( value ) } ;
474- } else {
475- console.error('Chart not initialized');
476- }
510+ window.${ name } = ${ JSON . stringify ( value ) } ;
477511 true;
478512 ` ) ;
479513 }
@@ -501,23 +535,27 @@ const ChartUPlot = forwardRef<any, UPlotProps>(
501535 } , [ ] ) ;
502536
503537 // function to call destroy, also clears the data
504- const destroy = useCallback ( ( ) : void => {
538+ const destroy = useCallback ( ( keepData : boolean = false ) : void => {
505539 if ( isWeb ) {
506540 uplotInstance . current ?. destroy ( ) ;
507- dataRef . current = [ ] ;
541+ if ( ! keepData ) {
542+ dataRef . current = [ ] ;
543+ }
508544 } else {
509545 if ( ! webref ?. current ) {
510546 console . error ( 'WebView reference is not set' ) ;
511547 return ;
512548 }
513549
550+ var keepDataStr = keepData ? '' : `window._data = [];` ;
551+
514552 webref . current . injectJavaScript ( `
515- window._data = []
553+ ${ keepDataStr }
516554
517555 if (window._chart) {
518556 window._chart.destroy();
519- window.__CHART_CREATED__ = false;
520557 }
558+ window.__CHART_CREATED__ = false;
521559 true;
522560 ` ) ;
523561 }
@@ -550,15 +588,17 @@ const ChartUPlot = forwardRef<any, UPlotProps>(
550588 return (
551589 < View
552590 ref = { ( r ) : any => {
591+ containerRef . current = r ;
553592 webref . current = r ;
554593 if ( r ) {
555- createChart ( optionsFinal , data ) ;
594+ createChart ( options , data ) ;
556595 }
557596 } }
597+ onLayout = { handleLayout }
558598 style = { {
559599 ...style ,
560- width : containerWidth ,
561- height : containerHeight ,
600+ width : options ?. width || style ?. width || '100%' ,
601+ height : options ?. height || style ?. height || '100%' ,
562602 } }
563603 />
564604 ) ;
@@ -570,22 +610,47 @@ const ChartUPlot = forwardRef<any, UPlotProps>(
570610 source = { html }
571611 style = { {
572612 ...style ,
573- width : containerWidth ,
574- height : containerHeight ,
613+ width : options ?. width || style ?. width || '100%' ,
614+ height : options ?. height || style ?. height || '100%' ,
575615 } }
576616 scrollEnabled = { false }
577617 onLoadEnd = { ( ) : void => {
578- createChart ( optionsFinal , data , bgColor ) ;
618+ createChart ( options , data , bgColor ) ;
579619
580620 if ( onLoad ) {
581621 onLoad ( ) ;
582622 }
583623 } }
584624 ref = { ( r ) => {
585625 if ( r ) {
626+ var shouldReinit = containerRef . current && r !== webref . current ;
627+
628+ if ( shouldReinit ) {
629+ initialized . current = false ;
630+ destroy ( true ) ;
631+ }
632+
633+ containerRef . current = r ;
586634 webref . current = r ;
635+
636+ if ( shouldReinit ) {
637+ // re-add any variables that were set
638+ var injectedVars = '' ;
639+ Object . keys ( variablesRef . current ) . forEach ( ( key ) => {
640+ injectedVars += `window.${ key } = ${ JSON . stringify (
641+ variablesRef . current [ key ] ,
642+ ) } ;`;
643+ } ) ;
644+ webref . current . injectJavaScript ( `
645+ ${ injectedVars }
646+ true;
647+ ` ) ;
648+
649+ createChart ( options , data , bgColor ) ;
650+ }
587651 }
588652 } }
653+ onLayout = { handleLayout }
589654 javaScriptEnabled = { true }
590655 injectedJavaScript = { `${ injectedJavaScript } ; true;` }
591656 onMessage = { ( payload ) : void => {
0 commit comments