@@ -16,7 +16,7 @@ import {
1616  SUBMIT_BUTTON_LABEL , 
1717  SUCCESS_MESSAGE_TEXT , 
1818}  from  './constants' ; 
19- import  type  {  FeedbackInternalOptions ,  OptionalFeedbackConfiguration ,   Widget  }  from  './types' ; 
19+ import  type  {  FeedbackInternalOptions ,  FeedbackWidget ,   OptionalFeedbackConfiguration  }  from  './types' ; 
2020import  {  mergeOptions  }  from  './util/mergeOptions' ; 
2121import  {  createActorStyles  }  from  './widget/Actor.css' ; 
2222import  {  createShadowHost  }  from  './widget/createShadowHost' ; 
@@ -48,12 +48,12 @@ export class Feedback implements Integration {
4848  /** 
4949   * Reference to widget element that is created when autoInject is true 
5050   */ 
51-   private  _widget : Widget  |  null ; 
51+   private  _widget : FeedbackWidget  |  null ; 
5252
5353  /** 
5454   * List of all widgets that are created from the integration 
5555   */ 
56-   private  _widgets : Set < Widget > ; 
56+   private  _widgets : Set < FeedbackWidget > ; 
5757
5858  /** 
5959   * Reference to the host element where widget is inserted 
@@ -166,15 +166,7 @@ export class Feedback implements Integration {
166166    } 
167167
168168    try  { 
169-       // TODO: This is only here for hot reloading 
170-       if  ( this . _host )  { 
171-         this . remove ( ) ; 
172-       } 
173-       const  existingFeedback  =  doc . querySelector ( `#${ this . options . id }  ` ) ; 
174-       if  ( existingFeedback )  { 
175-         existingFeedback . remove ( ) ; 
176-       } 
177-       // TODO: End hotloading 
169+       this . _cleanupWidgetIfExists ( ) ; 
178170
179171      const  {  autoInject }  =  this . options ; 
180172
@@ -183,20 +175,49 @@ export class Feedback implements Integration {
183175        return ; 
184176      } 
185177
186-       this . _widget   =   this . _createWidget ( this . options ) ; 
178+       this . _createWidget ( this . options ) ; 
187179    }  catch  ( err )  { 
188180      __DEBUG_BUILD__  &&  logger . error ( err ) ; 
189181    } 
190182  } 
191183
184+   /** 
185+    * Allows user to open the dialog box. Creates a new widget if 
186+    * `autoInject` was false, otherwise re-uses the default widget that was 
187+    * created during initialization of the integration. 
188+    */ 
189+   public  openDialog ( ) : void   { 
190+     if  ( ! this . _widget )  { 
191+       this . _createWidget ( {  ...this . options ,  shouldCreateActor : false  } ) ; 
192+     } 
193+ 
194+     if  ( ! this . _widget )  { 
195+       return ; 
196+     } 
197+ 
198+     this . _widget . openDialog ( ) ; 
199+   } 
200+ 
201+   /** 
202+    * Closes the dialog for the default widget, if it exists 
203+    */ 
204+   public  closeDialog ( ) : void   { 
205+     if  ( ! this . _widget )  { 
206+       // Nothing to do if widget does not exist 
207+       return ; 
208+     } 
209+ 
210+     this . _widget . closeDialog ( ) ; 
211+   } 
212+ 
192213  /** 
193214   * Adds click listener to attached element to open a feedback dialog 
194215   */ 
195-   public  attachTo ( el : Element  |  string ,  optionOverrides : OptionalFeedbackConfiguration ) : Widget  |  null  { 
216+   public  attachTo ( el : Element  |  string ,  optionOverrides ? : OptionalFeedbackConfiguration ) : FeedbackWidget  |  null  { 
196217    try  { 
197-       const  options  =  mergeOptions ( this . options ,  optionOverrides ) ; 
218+       const  options  =  mergeOptions ( this . options ,  optionOverrides   ||   { } ) ; 
198219
199-       return  this . _ensureShadowHost < Widget  |  null > ( options ,  ( {  shadow } )  =>  { 
220+       return  this . _ensureShadowHost < FeedbackWidget  |  null > ( options ,  ( {  shadow } )  =>  { 
200221        const  targetEl  = 
201222          typeof  el  ===  'string'  ? doc . querySelector ( el )  : typeof  el . addEventListener  ===  'function'  ? el  : null ; 
202223
@@ -207,6 +228,11 @@ export class Feedback implements Integration {
207228
208229        const  widget  =  createWidget ( {  shadow,  options,  attachTo : targetEl  } ) ; 
209230        this . _widgets . add ( widget ) ; 
231+ 
232+         if  ( ! this . _widget )  { 
233+           this . _widget  =  widget ; 
234+         } 
235+ 
210236        return  widget ; 
211237      } ) ; 
212238    }  catch  ( err )  { 
@@ -218,9 +244,11 @@ export class Feedback implements Integration {
218244  /** 
219245   * Creates a new widget. Accepts partial options to override any options passed to constructor. 
220246   */ 
221-   public  createWidget ( optionOverrides : OptionalFeedbackConfiguration ) : Widget  |  null  { 
247+   public  createWidget ( 
248+     optionOverrides ?: OptionalFeedbackConfiguration  &  {  shouldCreateActor ?: boolean  } , 
249+   ) : FeedbackWidget  |  null  { 
222250    try  { 
223-       return  this . _createWidget ( mergeOptions ( this . options ,  optionOverrides ) ) ; 
251+       return  this . _createWidget ( mergeOptions ( this . options ,  optionOverrides   ||   { } ) ) ; 
224252    }  catch  ( err )  { 
225253      __DEBUG_BUILD__  &&  logger . error ( err ) ; 
226254      return  null ; 
@@ -230,7 +258,7 @@ export class Feedback implements Integration {
230258  /** 
231259   * Removes a single widget 
232260   */ 
233-   public  removeWidget ( widget : Widget  |  null  |  undefined ) : boolean  { 
261+   public  removeWidget ( widget : FeedbackWidget  |  null  |  undefined ) : boolean  { 
234262    if  ( ! widget )  { 
235263      return  false ; 
236264    } 
@@ -240,6 +268,12 @@ export class Feedback implements Integration {
240268        widget . removeActor ( ) ; 
241269        widget . removeDialog ( ) ; 
242270        this . _widgets . delete ( widget ) ; 
271+ 
272+         if  ( this . _widget  ===  widget )  { 
273+           // TODO: is more clean-up needed? e.g. call remove() 
274+           this . _widget  =  null ; 
275+         } 
276+ 
243277        return  true ; 
244278      } 
245279    }  catch  ( err )  { 
@@ -249,6 +283,13 @@ export class Feedback implements Integration {
249283    return  false ; 
250284  } 
251285
286+   /** 
287+    * Returns the default (first-created) widget 
288+    */ 
289+   public  getWidget ( ) : FeedbackWidget  |  null  { 
290+     return  this . _widget ; 
291+   } 
292+ 
252293  /** 
253294   * Removes the Feedback integration (including host, shadow DOM, and all widgets) 
254295   */ 
@@ -270,11 +311,25 @@ export class Feedback implements Integration {
270311    this . _hasInsertedActorStyles  =  false ; 
271312  } 
272313
314+   /** 
315+    * Clean-up the widget if it already exists in the DOM. This shouldn't happen 
316+    * in prod, but can happen in development with hot module reloading. 
317+    */ 
318+   protected  _cleanupWidgetIfExists ( ) : void   { 
319+     if  ( this . _host )  { 
320+       this . remove ( ) ; 
321+     } 
322+     const  existingFeedback  =  doc . querySelector ( `#${ this . options . id }  ` ) ; 
323+     if  ( existingFeedback )  { 
324+       existingFeedback . remove ( ) ; 
325+     } 
326+   } 
327+ 
273328  /** 
274329   * Creates a new widget, after ensuring shadow DOM exists 
275330   */ 
276-   protected  _createWidget ( options : FeedbackInternalOptions ) : Widget  |  null  { 
277-     return  this . _ensureShadowHost < Widget > ( options ,  ( {  shadow } )  =>  { 
331+   protected  _createWidget ( options : FeedbackInternalOptions   &   {   shouldCreateActor ?:  boolean   } ) : FeedbackWidget  |  null  { 
332+     return  this . _ensureShadowHost < FeedbackWidget > ( options ,  ( {  shadow } )  =>  { 
278333      const  widget  =  createWidget ( {  shadow,  options } ) ; 
279334
280335      if  ( ! this . _hasInsertedActorStyles  &&  widget . actor )  { 
@@ -283,6 +338,11 @@ export class Feedback implements Integration {
283338      } 
284339
285340      this . _widgets . add ( widget ) ; 
341+ 
342+       if  ( ! this . _widget )  { 
343+         this . _widget  =  widget ; 
344+       } 
345+ 
286346      return  widget ; 
287347    } ) ; 
288348  } 
0 commit comments