@@ -2615,129 +2615,140 @@ function react(gd, data, layout, config) {
26152615 configChanged = diffConfig ( oldConfig , gd . _context ) ;
26162616 }
26172617
2618- gd . data = data || [ ] ;
2619- helpers . cleanData ( gd . data ) ;
2620- gd . layout = layout || { } ;
2621- helpers . cleanLayout ( gd . layout ) ;
2622-
2623- applyUIRevisions ( gd . data , gd . layout , oldFullData , oldFullLayout ) ;
2624-
2625- // "true" skips updating calcdata and remapping arrays from calcTransforms,
2626- // which supplyDefaults usually does at the end, but we may need to NOT do
2627- // if the diff (which we haven't determined yet) says we'll recalc
2628- Plots . supplyDefaults ( gd , { skipUpdateCalc : true } ) ;
2629-
2630- var newFullData = gd . _fullData ;
2631- var newFullLayout = gd . _fullLayout ;
2632- var immutable = newFullLayout . datarevision === undefined ;
2633- var transition = newFullLayout . transition ;
2634-
2635- var relayoutFlags = diffLayout ( gd , oldFullLayout , newFullLayout , immutable , transition ) ;
2636- var newDataRevision = relayoutFlags . newDataRevision ;
2637- var restyleFlags = diffData ( gd , oldFullData , newFullData , immutable , transition , newDataRevision ) ;
2638-
2639- // TODO: how to translate this part of relayout to Plotly.react?
2640- // // Setting width or height to null must reset the graph's width / height
2641- // // back to its initial value as computed during the first pass in Plots.plotAutoSize.
2642- // //
2643- // // To do so, we must manually set them back here using the _initialAutoSize cache.
2644- // if(['width', 'height'].indexOf(ai) !== -1 && vi === null) {
2645- // fullLayout[ai] = gd._initialAutoSize[ai];
2646- // }
2647-
2648- if ( updateAutosize ( gd ) ) relayoutFlags . layoutReplot = true ;
2649-
2650- // clear calcdata and empty categories if required
2651- if ( restyleFlags . calc || relayoutFlags . calc ) {
2652- gd . calcdata = undefined ;
2653- var allNames = Object . getOwnPropertyNames ( newFullLayout ) ;
2654- for ( var q = 0 ; q < allNames . length ; q ++ ) {
2655- var name = allNames [ q ] ;
2656- var start = name . substring ( 0 , 5 ) ;
2657- if ( start === 'xaxis' || start === 'yaxis' ) {
2658- var emptyCategories = newFullLayout [ name ] . _emptyCategories ;
2659- if ( emptyCategories ) emptyCategories ( ) ;
2618+ if ( configChanged ) {
2619+ // Save event listeners as newPlot will remove them
2620+ const eventListeners = gd . _ev . eventNames ( ) . map ( name => [ name , gd . _ev . listeners ( name ) ] ) ;
2621+ plotDone = exports . newPlot ( gd , data , layout , config )
2622+ . then ( ( ) => {
2623+ for ( const [ name , callbacks ] of eventListeners ) {
2624+ callbacks . forEach ( ( cb ) => gd . on ( name , cb ) ) ;
2625+ }
2626+
2627+ // Call react in case transition should have occurred along with config change
2628+ return exports . react ( gd , data , layout , config )
2629+ } ) ;
2630+ } else {
2631+ gd . data = data || [ ] ;
2632+ helpers . cleanData ( gd . data ) ;
2633+ gd . layout = layout || { } ;
2634+ helpers . cleanLayout ( gd . layout ) ;
2635+
2636+ applyUIRevisions ( gd . data , gd . layout , oldFullData , oldFullLayout ) ;
2637+
2638+ // "true" skips updating calcdata and remapping arrays from calcTransforms,
2639+ // which supplyDefaults usually does at the end, but we may need to NOT do
2640+ // if the diff (which we haven't determined yet) says we'll recalc
2641+ Plots . supplyDefaults ( gd , { skipUpdateCalc : true } ) ;
2642+
2643+ var newFullData = gd . _fullData ;
2644+ var newFullLayout = gd . _fullLayout ;
2645+ var immutable = newFullLayout . datarevision === undefined ;
2646+ var transition = newFullLayout . transition ;
2647+
2648+ var relayoutFlags = diffLayout ( gd , oldFullLayout , newFullLayout , immutable , transition ) ;
2649+ var newDataRevision = relayoutFlags . newDataRevision ;
2650+ var restyleFlags = diffData ( gd , oldFullData , newFullData , immutable , transition , newDataRevision ) ;
2651+
2652+ // TODO: how to translate this part of relayout to Plotly.react?
2653+ // // Setting width or height to null must reset the graph's width / height
2654+ // // back to its initial value as computed during the first pass in Plots.plotAutoSize.
2655+ // //
2656+ // // To do so, we must manually set them back here using the _initialAutoSize cache.
2657+ // if(['width', 'height'].indexOf(ai) !== -1 && vi === null) {
2658+ // fullLayout[ai] = gd._initialAutoSize[ai];
2659+ // }
2660+
2661+ if ( updateAutosize ( gd ) ) relayoutFlags . layoutReplot = true ;
2662+
2663+ // clear calcdata and empty categories if required
2664+ if ( restyleFlags . calc || relayoutFlags . calc ) {
2665+ gd . calcdata = undefined ;
2666+ var allNames = Object . getOwnPropertyNames ( newFullLayout ) ;
2667+ for ( var q = 0 ; q < allNames . length ; q ++ ) {
2668+ var name = allNames [ q ] ;
2669+ var start = name . substring ( 0 , 5 ) ;
2670+ if ( start === 'xaxis' || start === 'yaxis' ) {
2671+ var emptyCategories = newFullLayout [ name ] . _emptyCategories ;
2672+ if ( emptyCategories ) emptyCategories ( ) ;
2673+ }
26602674 }
2675+ // otherwise do the calcdata updates and calcTransform array remaps that we skipped earlier
2676+ } else {
2677+ Plots . supplyDefaultsUpdateCalc ( gd . calcdata , newFullData ) ;
26612678 }
2662- // otherwise do the calcdata updates and calcTransform array remaps that we skipped earlier
2663- } else {
2664- Plots . supplyDefaultsUpdateCalc ( gd . calcdata , newFullData ) ;
2665- }
26662679
2667- // Note: what restyle/relayout use impliedEdits and clearAxisTypes for
2668- // must be handled by the user when using Plotly.react.
2680+ // Note: what restyle/relayout use impliedEdits and clearAxisTypes for
2681+ // must be handled by the user when using Plotly.react.
26692682
2670- // fill in redraw sequence
2671- var seq = [ ] ;
2683+ // fill in redraw sequence
2684+ var seq = [ ] ;
26722685
2673- if ( frames ) {
2674- gd . _transitionData = { } ;
2675- Plots . createTransitionData ( gd ) ;
2676- seq . push ( addFrames ) ;
2677- }
2686+ if ( frames ) {
2687+ gd . _transitionData = { } ;
2688+ Plots . createTransitionData ( gd ) ;
2689+ seq . push ( addFrames ) ;
2690+ }
26782691
2679- // Transition pathway,
2680- // only used when 'transition' is set by user and
2681- // when at least one animatable attribute has changed,
2682- // N.B. config changed aren't animatable
2683- if ( newFullLayout . transition && ! configChanged && ( restyleFlags . anim || relayoutFlags . anim ) ) {
2684- if ( relayoutFlags . ticks ) seq . push ( subroutines . doTicksRelayout ) ;
2692+ // Transition pathway,
2693+ // only used when 'transition' is set by user and
2694+ // when at least one animatable attribute has changed,
2695+ // N.B. config changed aren't animatable
2696+ if ( newFullLayout . transition && ( restyleFlags . anim || relayoutFlags . anim ) ) {
2697+ if ( relayoutFlags . ticks ) seq . push ( subroutines . doTicksRelayout ) ;
26852698
2686- Plots . doCalcdata ( gd ) ;
2687- subroutines . doAutoRangeAndConstraints ( gd ) ;
2699+ Plots . doCalcdata ( gd ) ;
2700+ subroutines . doAutoRangeAndConstraints ( gd ) ;
26882701
2689- seq . push ( function ( ) {
2690- return Plots . transitionFromReact ( gd , restyleFlags , relayoutFlags , oldFullLayout ) ;
2691- } ) ;
2692- } else if ( restyleFlags . fullReplot || relayoutFlags . layoutReplot || configChanged ) {
2693- gd . _fullLayout . _skipDefaults = true ;
2694- seq . push ( exports . _doPlot ) ;
2695- } else {
2696- for ( var componentType in relayoutFlags . arrays ) {
2697- var indices = relayoutFlags . arrays [ componentType ] ;
2698- if ( indices . length ) {
2699- var drawOne = Registry . getComponentMethod ( componentType , 'drawOne' ) ;
2700- if ( drawOne !== Lib . noop ) {
2701- for ( var i = 0 ; i < indices . length ; i ++ ) {
2702- drawOne ( gd , indices [ i ] ) ;
2703- }
2704- } else {
2705- var draw = Registry . getComponentMethod ( componentType , 'draw' ) ;
2706- if ( draw === Lib . noop ) {
2707- throw new Error ( 'cannot draw components: ' + componentType ) ;
2702+ seq . push ( function ( ) {
2703+ return Plots . transitionFromReact ( gd , restyleFlags , relayoutFlags , oldFullLayout ) ;
2704+ } ) ;
2705+ } else if ( restyleFlags . fullReplot || relayoutFlags . layoutReplot ) {
2706+ gd . _fullLayout . _skipDefaults = true ;
2707+ seq . push ( exports . _doPlot ) ;
2708+ } else {
2709+ for ( var componentType in relayoutFlags . arrays ) {
2710+ var indices = relayoutFlags . arrays [ componentType ] ;
2711+ if ( indices . length ) {
2712+ var drawOne = Registry . getComponentMethod ( componentType , 'drawOne' ) ;
2713+ if ( drawOne !== Lib . noop ) {
2714+ for ( var i = 0 ; i < indices . length ; i ++ ) {
2715+ drawOne ( gd , indices [ i ] ) ;
2716+ }
2717+ } else {
2718+ var draw = Registry . getComponentMethod ( componentType , 'draw' ) ;
2719+ if ( draw === Lib . noop ) {
2720+ throw new Error ( 'cannot draw components: ' + componentType ) ;
2721+ }
2722+ draw ( gd ) ;
27082723 }
2709- draw ( gd ) ;
27102724 }
27112725 }
2712- }
27132726
2714- seq . push ( Plots . previousPromises ) ;
2715- if ( restyleFlags . style ) seq . push ( subroutines . doTraceStyle ) ;
2716- if ( restyleFlags . colorbars || relayoutFlags . colorbars ) seq . push ( subroutines . doColorBars ) ;
2717- if ( relayoutFlags . legend ) seq . push ( subroutines . doLegend ) ;
2718- if ( relayoutFlags . layoutstyle ) seq . push ( subroutines . layoutStyles ) ;
2719- if ( relayoutFlags . axrange ) addAxRangeSequence ( seq ) ;
2720- if ( relayoutFlags . ticks ) seq . push ( subroutines . doTicksRelayout ) ;
2721- if ( relayoutFlags . modebar ) seq . push ( subroutines . doModeBar ) ;
2722- if ( relayoutFlags . camera ) seq . push ( subroutines . doCamera ) ;
2723- seq . push ( emitAfterPlot ) ;
2724- }
2727+ seq . push ( Plots . previousPromises ) ;
2728+ if ( restyleFlags . style ) seq . push ( subroutines . doTraceStyle ) ;
2729+ if ( restyleFlags . colorbars || relayoutFlags . colorbars ) seq . push ( subroutines . doColorBars ) ;
2730+ if ( relayoutFlags . legend ) seq . push ( subroutines . doLegend ) ;
2731+ if ( relayoutFlags . layoutstyle ) seq . push ( subroutines . layoutStyles ) ;
2732+ if ( relayoutFlags . axrange ) addAxRangeSequence ( seq ) ;
2733+ if ( relayoutFlags . ticks ) seq . push ( subroutines . doTicksRelayout ) ;
2734+ if ( relayoutFlags . modebar ) seq . push ( subroutines . doModeBar ) ;
2735+ if ( relayoutFlags . camera ) seq . push ( subroutines . doCamera ) ;
2736+ seq . push ( emitAfterPlot ) ;
2737+ }
27252738
2726- seq . push (
2727- Plots . rehover ,
2728- Plots . redrag ,
2729- Plots . reselect
2730- ) ;
2739+ seq . push (
2740+ Plots . rehover ,
2741+ Plots . redrag ,
2742+ Plots . reselect
2743+ ) ;
27312744
2732- plotDone = Lib . syncOrAsync ( seq , gd ) ;
2733- if ( ! plotDone || ! plotDone . then ) plotDone = Promise . resolve ( gd ) ;
2745+ plotDone = Lib . syncOrAsync ( seq , gd ) ;
2746+ if ( ! plotDone || ! plotDone . then ) plotDone = Promise . resolve ( gd ) ;
2747+ }
27342748 }
27352749
2736- return plotDone . then ( function ( ) {
2737- gd . emit ( 'plotly_react' , {
2738- data : data ,
2739- layout : layout
2740- } ) ;
2750+ return plotDone . then ( ( ) => {
2751+ if ( ! configChanged ) gd . emit ( 'plotly_react' , { config, data, layout } ) ;
27412752
27422753 return gd ;
27432754 } ) ;
@@ -3675,11 +3686,11 @@ function makePlotFramework(gd) {
36753686 // The plot container should always take the full with the height of its
36763687 // parent (the graph div). This ensures that for responsive plots
36773688 // without a height or width set, the paper div will take up the full
3678- // height & width of the graph div.
3689+ // height & width of the graph div.
36793690 // So, for responsive plots without a height or width set, if the plot
36803691 // container's height is left to 'auto', its height will be dictated by
36813692 // its childrens' height. (The plot container's only child is the paper
3682- // div.)
3693+ // div.)
36833694 // In this scenario, the paper div's height will be set to 100%,
36843695 // which will be 100% of the plot container's auto height. That is
36853696 // meaninglesss, so the browser will use the paper div's children to set
0 commit comments