11<template >
2- <div class =" mismatchfinder__language-selector" >
3- <div class =" languageSelector__mobile-header" >
4- <span >{{ $i18n( 'language-selector-mobile-header' ) }}</span >
5- <button @click =" onCloseMenu" >
6- <img :src =" closeUrl" :alt =" $i18n( 'language-selector-close-button-label' )" >
7- </button >
2+ <div class =" mismatchfinder__language-selector" >
3+ <div class =" languageSelector__mobile-header" >
4+ <span >{{ $i18n( 'language-selector-mobile-header' ) }}</span >
5+ <button @click =" onCloseMenu" >
6+ <img :src =" closeUrl" :alt =" $i18n( 'language-selector-close-button-label' )" >
7+ </button >
8+ </div >
9+ <LanguageSelectorInput
10+ ref =" input"
11+ :value =" searchInput"
12+ :placeholder =" $i18n( 'language-selector-input-placeholder' )"
13+ @input =" onInput"
14+ @clear =" onClearInputValue"
15+ @tab =" onCloseMenu"
16+ @arrowDown =" onArrowDown"
17+ @arrowUp =" onArrowUp"
18+ @enter =" onEnter"
19+ @escape =" onCloseMenu"
20+ />
21+ <LanguageSelectorOptionsMenu
22+ tabindex =" -1"
23+ :languages =" shownLanguages"
24+ :highlighted-index =" highlightedIndex"
25+ @select =" onSelect"
26+ >
27+ <template #no-results >
28+ <slot name =" no-results" />
29+ </template >
30+ </LanguageSelectorOptionsMenu >
831 </div >
9- <LanguageSelectorInput
10- ref =" input"
11- :value =" searchInput"
12- :placeholder =" $i18n( 'language-selector-input-placeholder' )"
13- @input =" onInput"
14- @clear =" onClearInputValue"
15- @tab =" onCloseMenu"
16- @arrowDown =" onArrowDown"
17- @arrowUp =" onArrowUp"
18- @enter =" onEnter"
19- @escape =" onCloseMenu"
20- />
21- <LanguageSelectorOptionsMenu
22- tabindex =" -1"
23- :languages =" shownLanguages"
24- :highlighted-index =" highlightedIndex"
25- @select =" onSelect"
26- >
27- <template #no-results >
28- <slot name =" no-results" />
29- </template >
30- </LanguageSelectorOptionsMenu >
31- </div >
3232</template >
3333<script setup lang="ts">
3434import LanguageSelectorOptionsMenu from " ./LanguageSelectorOptionsMenu.vue" ;
3535import LanguageSelectorInput from " ./LanguageSelectorInput.vue" ;
3636import Language from ' ../types/Language' ;
3737import closeUrlSvg from ' ../../img/close.svg' ;
3838
39- import { ref , computed } from " vue" ;
40- import type { Ref } from ' vue' ;
39+ import {ref , computed } from " vue" ;
40+ import type {Ref } from ' vue' ;
4141import languageData from " @wikimedia/language-data" ;
4242
4343const searchInput: Ref <string > = ref (' ' );
@@ -49,55 +49,55 @@ const input = ref<InstanceType<typeof LanguageSelectorInput> | null>(null);
4949const emit = defineEmits ([' select' , ' close' ]);
5050
5151const languages = computed <Language []>(() => {
52- const autonyms = languageData .getAutonyms ();
53- const languageCodes = Object .keys ( autonyms );
54- languageCodes .sort ( languageData .sortByAutonym );
55- return languageCodes .map ( ( code ) => ( {
56- code ,
57- autonym: autonyms [ code ],
58- } ) );
52+ const autonyms = languageData .getAutonyms ();
53+ const languageCodes = Object .keys (autonyms );
54+ languageCodes .sort (languageData .sortByAutonym );
55+ return languageCodes .map (( code ) => ({
56+ code ,
57+ autonym: autonyms [code ],
58+ }) );
5959});
6060
6161const shownLanguages = computed <Language []>(() => {
62- return languages .value .filter ( ( language ) =>
63- language .code .startsWith ( searchInput .value .toLowerCase () ) ||
64- language .autonym .toLowerCase ().includes ( searchInput .value .toLowerCase () ),
65- );
62+ return languages .value .filter (( language ) =>
63+ language .code .startsWith (searchInput .value .toLowerCase ()) ||
64+ language .autonym .toLowerCase ().includes (searchInput .value .toLowerCase ()),
65+ );
6666});
6767
6868function onInput(searchedLanguage : string ): void {
69- searchInput .value = searchedLanguage ;
70- highlightedIndex .value = 0 ;
69+ searchInput .value = searchedLanguage ;
70+ highlightedIndex .value = 0 ;
7171}
7272
7373function onSelect(languageCode : string ): void {
74- emit (' select' , languageCode );
74+ emit (' select' , languageCode );
7575}
7676
7777function onClearInputValue(): void {
78- searchInput .value = ' ' ;
78+ searchInput .value = ' ' ;
7979}
8080
8181function onCloseMenu(): void {
82- emit (' close' );
82+ emit (' close' );
8383}
8484
8585// eslint-disable-next-line @typescript-eslint/no-unused-vars
8686function focus(): void {
87- input .value ?.focus ();
87+ input .value ?.focus ();
8888}
8989
9090function onArrowDown(): void {
91- highlightedIndex .value = ( highlightedIndex .value + 1 ) % shownLanguages .value .length ;
91+ highlightedIndex .value = (highlightedIndex .value + 1 ) % shownLanguages .value .length ;
9292}
9393
9494function onArrowUp(): void {
95- const length = shownLanguages .value .length ;
96- highlightedIndex .value = ( highlightedIndex .value + length - 1 ) % length ;
95+ const length = shownLanguages .value .length ;
96+ highlightedIndex .value = (highlightedIndex .value + length - 1 ) % length ;
9797}
9898
9999function onEnter(): void {
100- onSelect ( shownLanguages .value [ highlightedIndex .value ].code )
100+ onSelect (shownLanguages .value [highlightedIndex .value ].code )
101101}
102102
103103defineExpose ({focus })
@@ -107,37 +107,37 @@ defineExpose({focus})
107107$tinyViewportWidth : 38em ;
108108
109109.mismatchfinder__language-selector {
110- position : absolute ;
111- inset-inline-end : 0 ;
112- width : 384px ;
113- z-index : 1 ;
114-
115- @media (max-width : $tinyViewportWidth ) {
116- width : 100% ;
117- position : fixed ;
118- top : 0 ;
119- display : flex ;
120- flex-direction : column ;
121- height : 100% ;
122- }
123-
124- .languageSelector__mobile-header {
125- display : none ;
126- padding-block : 12px ;
127- padding-inline : 16px ;
128- justify-content : space-between ;
129- background-color : #fff ;
130-
131- span {
132- color : #202122 ;
133- font-family : -apple-system , BlinkMacSystemFont, ' Segoe UI' , Roboto, Lato, Helvetica , Arial , sans-serif ;
134- font-size : 1em ;
135- font-weight : bold ;
136- }
110+ position : absolute ;
111+ inset-inline-end : 0 ;
112+ width : 384px ;
113+ z-index : 1 ;
137114
138115 @media (max-width : $tinyViewportWidth ) {
139- display : flex ;
116+ width : 100% ;
117+ position : fixed ;
118+ top : 0 ;
119+ display : flex ;
120+ flex-direction : column ;
121+ height : 100% ;
122+ }
123+
124+ .languageSelector__mobile-header {
125+ display : none ;
126+ padding-block : 12px ;
127+ padding-inline : 16px ;
128+ justify-content : space-between ;
129+ background-color : #fff ;
130+
131+ span {
132+ color : #202122 ;
133+ font-family : -apple-system , BlinkMacSystemFont, ' Segoe UI' , Roboto, Lato, Helvetica , Arial , sans-serif ;
134+ font-size : 1em ;
135+ font-weight : bold ;
136+ }
137+
138+ @media (max-width : $tinyViewportWidth ) {
139+ display : flex ;
140+ }
140141 }
141- }
142142}
143143 </style >
0 commit comments