11import fuzzysort from 'fuzzysort' ;
22import type { TemplateResult } from 'lit' ;
3- import { html , LitElement , nothing , type PropertyValues } from 'lit' ;
4- import { customElement , property , state } from 'lit/decorators.js' ;
3+ import { html , LitElement , type PropertyValues } from 'lit' ;
4+ import { customElement , property , query , state } from 'lit/decorators.js' ;
55import { repeat } from 'lit/directives/repeat.js' ;
66import type { FileUnderTestModel , Metrics , MetricsResult , MutationTestMetricsResult , TestMetrics } from 'mutation-testing-metrics' ;
77import { TestFileModel } from 'mutation-testing-metrics' ;
@@ -27,20 +27,24 @@ export class MutationTestReportFilePickerComponent extends LitElement {
2727 @property ( { attribute : false } )
2828 public declare rootModel : MutationTestMetricsResult | undefined ;
2929
30- @state ( )
31- public declare openPicker : boolean ;
32-
3330 @state ( )
3431 public declare filteredFiles : ( ModelEntry & { template ?: ( string | TemplateResult ) [ ] } ) [ ] ;
3532
3633 @state ( )
3734 public declare fileIndex : number ;
3835
36+ @query ( 'dialog' )
37+ private declare dialog : HTMLDialogElement ;
38+
39+ get isOpen ( ) {
40+ return this . dialog . open ;
41+ }
42+
3943 constructor ( ) {
4044 super ( ) ;
4145
42- this . openPicker = false ;
4346 this . fileIndex = 0 ;
47+ this . filteredFiles = [ ] ;
4448 }
4549
4650 connectedCallback ( ) : void {
@@ -64,38 +68,26 @@ export class MutationTestReportFilePickerComponent extends LitElement {
6468 }
6569 }
6670
67- updated ( changedProperties : PropertyValues < this> ) : void {
68- if ( changedProperties . has ( 'openPicker' ) ) {
69- if ( this . openPicker ) {
70- document . body . style . overflow = 'hidden' ;
71- this . #focusInput( ) ;
72- } else {
73- document . body . style . overflow = this . #originalDocumentOverflow;
74- }
75- }
76- }
71+ open = ( ) => {
72+ this . dialog . showModal ( ) ;
73+ } ;
7774
78- open ( ) {
79- this . openPicker = true ;
80- }
75+ close = ( ) => {
76+ this . dialog . close ( ) ;
77+ } ;
8178
8279 render ( ) {
83- if ( ! this . openPicker ) {
84- return nothing ;
85- }
86-
8780 return html `
88- < div
89- id ="backdrop "
90- @click ="${ this . #closePicker} "
91- class ="fixed left-0 top-0 z-50 flex h-full w-full justify-center bg-gray-950/50 backdrop-blur-lg "
81+ < dialog
82+ @click ="${ this . close } "
83+ @close ="${ this . #handleClose} "
84+ @show ="${ this . #handleShow} "
85+ aria-labelledby ="file-picker-label "
86+ class ="my-4 max-w-[40rem] bg-transparent backdrop:bg-gray-950/50 backdrop:backdrop-blur-lg md:w-1/2 "
9287 >
9388 < div
9489 @click ="${ ( e : MouseEvent ) => e . stopPropagation ( ) } "
95- role ="dialog "
96- aria-labelledby ="file-picker-label "
97- id ="picker "
98- class ="m-4 flex h-fit max-h-[33rem] w-full max-w-[40rem] flex-col rounded-lg bg-gray-200/60 p-4 backdrop-blur-lg md:w-1/2 "
90+ class ="mx-auto flex h-fit max-h-[33rem] flex-col rounded-lg bg-gray-200/60 p-4 backdrop-blur-lg "
9991 >
10092 < div class ="mb-3 flex items-center rounded bg-gray-200/60 p-2 text-gray-800 shadow-lg ">
10193 < div class ="mx-2 flex items-center "> ${ searchIcon } </ div >
@@ -113,20 +105,13 @@ export class MutationTestReportFilePickerComponent extends LitElement {
113105 </ div >
114106 ${ this . #renderFoundFiles( ) }
115107 </ div >
116- </ div >
108+ </ dialog >
117109 ` ;
118110 }
119111
120112 #renderFoundFiles( ) {
121113 return html `
122- < ul
123- id ="files "
124- tabindex ="-1 "
125- class ="flex snap-y flex-col gap-2 overflow-auto "
126- role ="listbox "
127- @focusout ="${ this . #focusInput} "
128- aria-labelledby ="file-picker-label "
129- >
114+ < ul id ="files " tabindex ="-1 " class ="flex snap-y flex-col gap-2 overflow-auto " role ="listbox " aria-labelledby ="file-picker-label ">
130115 ${ renderIf ( this . filteredFiles . length === 0 , ( ) => html `< li class ="text-gray-800 "> No files found</ li > ` ) }
131116 ${ repeat (
132117 this . filteredFiles ,
@@ -141,7 +126,7 @@ export class MutationTestReportFilePickerComponent extends LitElement {
141126 >
142127 < a
143128 tabindex ="${ index === this . fileIndex ? 0 : - 1 } "
144- @click ="${ this . #closePicker } "
129+ @click ="${ this . close } "
145130 class ="flex h-full flex-wrap items-center p-2 outline-none "
146131 @mousemove ="${ ( ) => ( this . fileIndex = index ) } "
147132 href ="${ toAbsoluteUrl ( view , name ) } "
@@ -200,13 +185,15 @@ export class MutationTestReportFilePickerComponent extends LitElement {
200185 }
201186
202187 #handleKeyDown = ( event : KeyboardEvent ) => {
203- if ( ( event . ctrlKey || event . metaKey ) && event . key === 'k' ) {
188+ if ( ( ( event . ctrlKey || event . metaKey ) && event . key === 'k' ) || ( ! this . isOpen && event . key === '/' ) ) {
204189 this . #togglePicker( event ) ;
205- } else if ( ! this . openPicker && event . key === '/' ) {
206- this . #togglePicker( event ) ;
207- } else if ( event . key === 'Escape' ) {
208- this . #closePicker( ) ;
209- } else if ( event . key === 'ArrowUp' ) {
190+ }
191+
192+ if ( ! this . isOpen ) {
193+ return ;
194+ }
195+
196+ if ( event . key === 'ArrowUp' ) {
210197 this . #handleArrowUp( ) ;
211198 } else if ( event . key === 'ArrowDown' ) {
212199 this . #handleArrowDown( ) ;
@@ -253,28 +240,32 @@ export class MutationTestReportFilePickerComponent extends LitElement {
253240
254241 const entry = this . filteredFiles [ this . fileIndex ] ;
255242 window . location . href = toAbsoluteUrl ( this . #getView( entry . file ) , entry . name ) ;
256- this . #closePicker ( ) ;
243+ this . close ( ) ;
257244 }
258245
259246 #togglePicker = ( event : KeyboardEvent | null = null ) => {
260247 event ?. preventDefault ( ) ;
261248 event ?. stopPropagation ( ) ;
262249
263- this . openPicker = ! this . openPicker ;
264- } ;
265-
266- #focusInput = ( ) => {
267- this . renderRoot . querySelector ( 'input' ) ?. focus ( ) ;
250+ if ( this . isOpen ) {
251+ this . close ( ) ;
252+ } else {
253+ this . open ( ) ;
254+ }
268255 } ;
269256
270- #closePicker = ( ) => {
271- this . openPicker = false ;
257+ #handleClose = ( ) => {
272258 this . fileIndex = 0 ;
273259 this . #filter( '' ) ;
260+ document . body . style . overflow = this . #originalDocumentOverflow;
261+ } ;
262+
263+ #handleShow = ( ) => {
264+ document . body . style . overflow = 'hidden' ;
274265 } ;
275266
276267 #handleSearch = ( event : InputEvent ) => {
277- if ( ! this . openPicker ) {
268+ if ( ! this . isOpen ) {
278269 return ;
279270 }
280271
0 commit comments