@@ -111,7 +111,152 @@ export interface UserActionRowWidgetParams {
111111 canShowFeedbackForm : boolean ;
112112}
113113
114- export type View = ( input : UserActionRowViewInput , output : ViewOutput , target : HTMLElement ) => void ;
114+ export const DEFAULT_VIEW = ( input : UserActionRowViewInput , output : ViewOutput , target : HTMLElement ) : void => {
115+ // clang-format off
116+ Lit . render ( html `
117+ < style > ${ Input . textInputStylesRaw . cssContent } </ style >
118+ < style > ${ userActionRowStyles . cssContent } </ style >
119+ < div class ="ai-assistance-feedback-row ">
120+ < div class ="rate-buttons ">
121+ ${ input . showRateButtons ? html `
122+ < devtools-button
123+ .data =${ {
124+ variant : Buttons . Button . Variant . ICON ,
125+ size : Buttons . Button . Size . SMALL ,
126+ iconName : 'thumb-up' ,
127+ toggledIconName : 'thumb-up-filled' ,
128+ toggled : input . currentRating === Host . AidaClient . Rating . POSITIVE ,
129+ toggleType : Buttons . Button . ToggleType . PRIMARY ,
130+ title : lockedString ( UIStringsNotTranslate . thumbsUp ) ,
131+ jslogContext : 'thumbs-up' ,
132+ } as Buttons . Button . ButtonData }
133+ @click =${ ( ) => input . onRatingClick ( Host . AidaClient . Rating . POSITIVE ) }
134+ > </ devtools-button >
135+ < devtools-button
136+ .data =${ {
137+ variant : Buttons . Button . Variant . ICON ,
138+ size : Buttons . Button . Size . SMALL ,
139+ iconName : 'thumb-down' ,
140+ toggledIconName : 'thumb-down-filled' ,
141+ toggled : input . currentRating === Host . AidaClient . Rating . NEGATIVE ,
142+ toggleType : Buttons . Button . ToggleType . PRIMARY ,
143+ title : lockedString ( UIStringsNotTranslate . thumbsDown ) ,
144+ jslogContext : 'thumbs-down' ,
145+ } as Buttons . Button . ButtonData }
146+ @click =${ ( ) => input . onRatingClick ( Host . AidaClient . Rating . NEGATIVE ) }
147+ > </ devtools-button >
148+ < div class ="vertical-separator "> </ div >
149+ ` : Lit . nothing }
150+ < devtools-button
151+ .data =${
152+ {
153+ variant : Buttons . Button . Variant . ICON ,
154+ size : Buttons . Button . Size . SMALL ,
155+ title : lockedString ( UIStringsNotTranslate . report ) ,
156+ iconName : 'report' ,
157+ jslogContext : 'report' ,
158+ } as Buttons . Button . ButtonData
159+ }
160+ @click =${ input . onReportClick }
161+ > </ devtools-button >
162+ </ div >
163+ ${ input . suggestions ? html `< div class ="suggestions-container ">
164+ < div class ="scroll-button-container left hidden " ${ ref ( element => { output . suggestionsLeftScrollButtonContainer = element ; } ) } >
165+ < devtools-button
166+ class ='scroll-button '
167+ .data =${ {
168+ variant : Buttons . Button . Variant . ICON ,
169+ size : Buttons . Button . Size . SMALL ,
170+ iconName : 'chevron-left' ,
171+ title : lockedString ( UIStringsNotTranslate . scrollToPrevious ) ,
172+ jslogContext : 'chevron-left' ,
173+ } as Buttons . Button . ButtonData }
174+ @click =${ ( ) => input . scrollSuggestionsScrollContainer ( 'left' ) }
175+ > </ devtools-button >
176+ </ div >
177+ < div class ="suggestions-scroll-container " @scroll =${ input . onSuggestionsScrollOrResize } ${ ref ( element => { output . suggestionsScrollContainer = element ; } ) } >
178+ ${ input . suggestions . map ( suggestion => html `< devtools-button
179+ class ='suggestion '
180+ .data =${ {
181+ variant : Buttons . Button . Variant . OUTLINED ,
182+ title : suggestion ,
183+ jslogContext : 'suggestion' ,
184+ } as Buttons . Button . ButtonData }
185+ @click =${ ( ) => input . onSuggestionClick ( suggestion ) }
186+ > ${ suggestion } </ devtools-button > ` ) }
187+ </ div >
188+ < div class ="scroll-button-container right hidden " ${ ref ( element => { output . suggestionsRightScrollButtonContainer = element ; } ) } >
189+ < devtools-button
190+ class ='scroll-button '
191+ .data =${ {
192+ variant : Buttons . Button . Variant . ICON ,
193+ size : Buttons . Button . Size . SMALL ,
194+ iconName : 'chevron-right' ,
195+ title : lockedString ( UIStringsNotTranslate . scrollToNext ) ,
196+ jslogContext : 'chevron-right' ,
197+ } as Buttons . Button . ButtonData }
198+ @click =${ ( ) => input . scrollSuggestionsScrollContainer ( 'right' ) }
199+ > </ devtools-button >
200+ </ div >
201+ </ div > ` : Lit . nothing }
202+ </ div >
203+ ${ input . isShowingFeedbackForm ? html `
204+ < form class ="feedback-form " @submit =${ input . onSubmit } >
205+ < div class ="feedback-header ">
206+ < h4 class ="feedback-title "> ${ lockedString (
207+ UIStringsNotTranslate . whyThisRating ,
208+ ) } </ h4 >
209+ < devtools-button
210+ aria-label =${ lockedString ( UIStringsNotTranslate . close ) }
211+ @click =${ input . onClose }
212+ .data=${
213+ {
214+ variant : Buttons . Button . Variant . ICON ,
215+ iconName : 'cross' ,
216+ size : Buttons . Button . Size . SMALL ,
217+ title : lockedString ( UIStringsNotTranslate . close ) ,
218+ jslogContext : 'close' ,
219+ } as Buttons . Button . ButtonData
220+ }
221+ > </ devtools-button >
222+ </ div >
223+ < input
224+ type ="text "
225+ class ="devtools-text-input feedback-input "
226+ @input =${ ( event : KeyboardEvent ) => input . onInputChange ( ( event . target as HTMLInputElement ) . value ) }
227+ placeholder =${ lockedString (
228+ UIStringsNotTranslate . provideFeedbackPlaceholder ,
229+ ) }
230+ jslog=${ VisualLogging . textField ( 'feedback' ) . track ( { keydown : 'Enter' } ) }
231+ >
232+ < span class ="feedback-disclaimer "> ${
233+ lockedString ( UIStringsNotTranslate . disclaimer )
234+ } </ span >
235+ < div >
236+ < devtools-button
237+ aria-label =${ lockedString ( UIStringsNotTranslate . submit ) }
238+ .data =${
239+ {
240+ type : 'submit' ,
241+ disabled : input . isSubmitButtonDisabled ,
242+ variant : Buttons . Button . Variant . OUTLINED ,
243+ size : Buttons . Button . Size . SMALL ,
244+ title : lockedString ( UIStringsNotTranslate . submit ) ,
245+ jslogContext : 'send' ,
246+ } as Buttons . Button . ButtonData
247+ }
248+ > ${
249+ lockedString ( UIStringsNotTranslate . submit )
250+ } </ devtools-button >
251+ </ div >
252+ </ div >
253+ </ form >
254+ ` : Lit . nothing }
255+ ` , target , { host : target } ) ;
256+ // clang-format on
257+ } ;
258+
259+ export type View = typeof DEFAULT_VIEW ;
115260
116261/**
117262 * This presenter has too many responsibilities (rating buttons, feedback
@@ -132,159 +277,12 @@ export class UserActionRow extends UI.Widget.Widget implements UserActionRowWidg
132277 #isShowingFeedbackForm = false ;
133278 #isSubmitButtonDisabled = true ;
134279
135- # view: View ;
280+ view : View ;
136281 #viewOutput: ViewOutput = { } ;
137282
138283 constructor ( element ?: HTMLElement , view ?: View ) {
139284 super ( false , false , element ) ;
140- this . registerRequiredCSS ( Input . textInputStylesRaw ) ;
141- this . registerRequiredCSS ( userActionRowStyles ) ;
142- // clang-format off
143- this . #view = view ?? ( ( input , output , target ) => {
144- Lit . render (
145- html `
146- < div class ="ai-assistance-feedback-row ">
147- < div class ="rate-buttons ">
148- ${ input . showRateButtons ? html `
149- < devtools-button
150- .data =${ {
151- variant : Buttons . Button . Variant . ICON ,
152- size : Buttons . Button . Size . SMALL ,
153- iconName : 'thumb-up' ,
154- toggledIconName : 'thumb-up-filled' ,
155- toggled : input . currentRating === Host . AidaClient . Rating . POSITIVE ,
156- toggleType : Buttons . Button . ToggleType . PRIMARY ,
157- title : lockedString ( UIStringsNotTranslate . thumbsUp ) ,
158- jslogContext : 'thumbs-up' ,
159- } as Buttons . Button . ButtonData }
160- @click =${ ( ) => input . onRatingClick ( Host . AidaClient . Rating . POSITIVE ) }
161- > </ devtools-button >
162- < devtools-button
163- .data =${ {
164- variant : Buttons . Button . Variant . ICON ,
165- size : Buttons . Button . Size . SMALL ,
166- iconName : 'thumb-down' ,
167- toggledIconName : 'thumb-down-filled' ,
168- toggled : input . currentRating === Host . AidaClient . Rating . NEGATIVE ,
169- toggleType : Buttons . Button . ToggleType . PRIMARY ,
170- title : lockedString ( UIStringsNotTranslate . thumbsDown ) ,
171- jslogContext : 'thumbs-down' ,
172- } as Buttons . Button . ButtonData }
173- @click =${ ( ) => input . onRatingClick ( Host . AidaClient . Rating . NEGATIVE ) }
174- > </ devtools-button >
175- < div class ="vertical-separator "> </ div >
176- ` : Lit . nothing }
177- < devtools-button
178- .data =${
179- {
180- variant : Buttons . Button . Variant . ICON ,
181- size : Buttons . Button . Size . SMALL ,
182- title : lockedString ( UIStringsNotTranslate . report ) ,
183- iconName : 'report' ,
184- jslogContext : 'report' ,
185- } as Buttons . Button . ButtonData
186- }
187- @click =${ input . onReportClick }
188- > </ devtools-button >
189- </ div >
190- ${ input . suggestions ? html `< div class ="suggestions-container ">
191- < div class ="scroll-button-container left hidden " ${ ref ( element => { output . suggestionsLeftScrollButtonContainer = element ; } ) } >
192- < devtools-button
193- class ='scroll-button '
194- .data =${ {
195- variant : Buttons . Button . Variant . ICON ,
196- size : Buttons . Button . Size . SMALL ,
197- iconName : 'chevron-left' ,
198- title : lockedString ( UIStringsNotTranslate . scrollToPrevious ) ,
199- jslogContext : 'chevron-left' ,
200- } as Buttons . Button . ButtonData }
201- @click =${ ( ) => input . scrollSuggestionsScrollContainer ( 'left' ) }
202- > </ devtools-button >
203- </ div >
204- < div class ="suggestions-scroll-container " @scroll =${ input . onSuggestionsScrollOrResize } ${ ref ( element => { output . suggestionsScrollContainer = element ; } ) } >
205- ${ input . suggestions . map ( suggestion => html `< devtools-button
206- class ='suggestion '
207- .data =${ {
208- variant : Buttons . Button . Variant . OUTLINED ,
209- title : suggestion ,
210- jslogContext : 'suggestion' ,
211- } as Buttons . Button . ButtonData }
212- @click =${ ( ) => input . onSuggestionClick ( suggestion ) }
213- > ${ suggestion } </ devtools-button > ` ) }
214- </ div >
215- < div class ="scroll-button-container right hidden " ${ ref ( element => { output . suggestionsRightScrollButtonContainer = element ; } ) } >
216- < devtools-button
217- class ='scroll-button '
218- .data =${ {
219- variant : Buttons . Button . Variant . ICON ,
220- size : Buttons . Button . Size . SMALL ,
221- iconName : 'chevron-right' ,
222- title : lockedString ( UIStringsNotTranslate . scrollToNext ) ,
223- jslogContext : 'chevron-right' ,
224- } as Buttons . Button . ButtonData }
225- @click =${ ( ) => input . scrollSuggestionsScrollContainer ( 'right' ) }
226- > </ devtools-button >
227- </ div >
228- </ div > ` : Lit . nothing }
229- </ div >
230- ${ input . isShowingFeedbackForm ? html `
231- < form class ="feedback-form " @submit =${ input . onSubmit } >
232- < div class ="feedback-header ">
233- < h4 class ="feedback-title "> ${ lockedString (
234- UIStringsNotTranslate . whyThisRating ,
235- ) } </ h4 >
236- < devtools-button
237- aria-label =${ lockedString ( UIStringsNotTranslate . close ) }
238- @click =${ input . onClose }
239- .data=${
240- {
241- variant : Buttons . Button . Variant . ICON ,
242- iconName : 'cross' ,
243- size : Buttons . Button . Size . SMALL ,
244- title : lockedString ( UIStringsNotTranslate . close ) ,
245- jslogContext : 'close' ,
246- } as Buttons . Button . ButtonData
247- }
248- > </ devtools-button >
249- </ div >
250- < input
251- type ="text "
252- class ="devtools-text-input feedback-input "
253- @input =${ ( event : KeyboardEvent ) => input . onInputChange ( ( event . target as HTMLInputElement ) . value ) }
254- placeholder =${ lockedString (
255- UIStringsNotTranslate . provideFeedbackPlaceholder ,
256- ) }
257- jslog=${ VisualLogging . textField ( 'feedback' ) . track ( { keydown : 'Enter' } ) }
258- >
259- < span class ="feedback-disclaimer "> ${
260- lockedString ( UIStringsNotTranslate . disclaimer )
261- } </ span >
262- < div >
263- < devtools-button
264- aria-label =${ lockedString ( UIStringsNotTranslate . submit ) }
265- .data =${
266- {
267- type : 'submit' ,
268- disabled : input . isSubmitButtonDisabled ,
269- variant : Buttons . Button . Variant . OUTLINED ,
270- size : Buttons . Button . Size . SMALL ,
271- title : lockedString ( UIStringsNotTranslate . submit ) ,
272- jslogContext : 'send' ,
273- } as Buttons . Button . ButtonData
274- }
275- > ${
276- lockedString ( UIStringsNotTranslate . submit )
277- } </ devtools-button >
278- </ div >
279- </ div >
280- </ form >
281- ` : Lit . nothing }
282- ` ,
283- target ,
284- { host : target }
285- ) ;
286- } ) as View ;
287- // clang-format on
285+ this . view = view ?? DEFAULT_VIEW ;
288286 }
289287
290288 override wasShown ( ) : void {
@@ -298,7 +296,7 @@ export class UserActionRow extends UI.Widget.Widget implements UserActionRowWidg
298296 }
299297
300298 override performUpdate ( ) : Promise < void > | void {
301- this . # view(
299+ this . view (
302300 {
303301 onSuggestionClick : this . onSuggestionClick ,
304302 onRatingClick : this . #handleRateClick. bind ( this ) ,
0 commit comments