Wizard: Add Keyboard drop down

This adds a drop down for keyboard selection. The options are populated with an output of `localectl list-keymaps`.
This commit is contained in:
regexowl 2024-12-06 11:21:11 +01:00 committed by Lucas Garfield
parent 60175aa911
commit 97877114f6
4 changed files with 784 additions and 11 deletions

View file

@ -0,0 +1,184 @@
import React, { useEffect, useState } from 'react';
import {
Button,
FormGroup,
MenuToggle,
MenuToggleElement,
Select,
SelectList,
SelectOption,
TextInputGroup,
TextInputGroupMain,
TextInputGroupUtilities,
} from '@patternfly/react-core';
import { TimesIcon } from '@patternfly/react-icons';
import { useAppDispatch, useAppSelector } from '../../../../../store/hooks';
import {
changeKeyboard,
selectKeyboard,
} from '../../../../../store/wizardSlice';
import { keyboardsList } from '../keyboardsList';
const KeyboardDropDown = () => {
const keyboard = useAppSelector(selectKeyboard);
const dispatch = useAppDispatch();
const [isOpen, setIsOpen] = useState(false);
const [inputValue, setInputValue] = useState<string>('');
const [filterValue, setFilterValue] = useState<string>('');
const [selectOptions, setSelectOptions] = useState<string[]>(keyboardsList);
useEffect(() => {
let filteredKeyboards = keyboardsList;
if (filterValue) {
filteredKeyboards = keyboardsList.filter((keyboard: string) =>
String(keyboard).toLowerCase().includes(filterValue.toLowerCase())
);
if (!filteredKeyboards.length) {
filteredKeyboards = [`No results found for "${filterValue}"`];
}
if (!isOpen) {
setIsOpen(true);
}
}
setSelectOptions(filteredKeyboards.sort((a, b) => sortfn(a, b)));
// This useEffect hook should run *only* on when the filter value changes.
// eslint's exhaustive-deps rule does not support this use.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [filterValue]);
const sortfn = (a: string, b: string) => {
const aKeyboard = a.toLowerCase();
const bKeyboard = b.toLowerCase();
// check exact match first
if (aKeyboard === filterValue) {
return -1;
}
if (bKeyboard === filterValue) {
return 1;
}
// check for keyboards that start with the search term
if (
aKeyboard.startsWith(filterValue) &&
!bKeyboard.startsWith(filterValue)
) {
return -1;
}
if (
bKeyboard.startsWith(filterValue) &&
!aKeyboard.startsWith(filterValue)
) {
return 1;
}
// if both (or neither) start with the search term
// sort alphabetically
if (aKeyboard < bKeyboard) {
return -1;
}
if (bKeyboard < aKeyboard) {
return 1;
}
return 0;
};
const onToggle = (isOpen: boolean) => {
setIsOpen(!isOpen);
};
const onInputClick = () => {
if (!isOpen) {
setIsOpen(true);
} else if (!inputValue) {
setIsOpen(false);
}
};
const onSelect = (_event: React.MouseEvent, value: string) => {
if (value && !value.includes('No results')) {
setInputValue(value);
setFilterValue('');
dispatch(changeKeyboard(value));
setIsOpen(false);
}
};
const onTextInputChange = (_event: React.FormEvent, value: string) => {
setInputValue(value);
setFilterValue(value);
if (value !== keyboard) {
dispatch(changeKeyboard(''));
}
};
const onToggleClick = () => {
setIsOpen(!isOpen);
};
const onClearButtonClick = () => {
setInputValue('');
setFilterValue('');
dispatch(changeKeyboard(''));
};
const toggle = (toggleRef: React.Ref<MenuToggleElement>) => (
<MenuToggle
ref={toggleRef}
variant="typeahead"
onClick={onToggleClick}
isExpanded={isOpen}
isFullWidth
>
<TextInputGroup isPlain>
<TextInputGroupMain
value={keyboard ? keyboard : inputValue}
onClick={onInputClick}
onChange={onTextInputChange}
autoComplete="off"
placeholder="Select a keyboard"
isExpanded={isOpen}
/>
{keyboard && (
<TextInputGroupUtilities>
<Button
variant="plain"
onClick={onClearButtonClick}
aria-label="Clear input"
>
<TimesIcon />
</Button>
</TextInputGroupUtilities>
)}
</TextInputGroup>
</MenuToggle>
);
return (
<FormGroup isRequired={false} label="Keyboard">
<Select
isScrollable
isOpen={isOpen}
selected={keyboard}
onSelect={onSelect}
onOpenChange={onToggle}
toggle={toggle}
shouldFocusFirstItemOnOpen={false}
>
<SelectList>
{selectOptions.map((option) => (
<SelectOption key={option} value={option}>
{option}
</SelectOption>
))}
</SelectList>
</Select>
</FormGroup>
);
};
export default KeyboardDropDown;

View file

@ -1,9 +0,0 @@
import React from 'react';
import { FormGroup } from '@patternfly/react-core';
const KeyboardInput = () => {
return <FormGroup isRequired={false} label="Keyboard"></FormGroup>;
};
export default KeyboardInput;

View file

@ -2,7 +2,7 @@ import React from 'react';
import { Text, Form, Title } from '@patternfly/react-core';
import KeyboardInput from './components/KeyboardInput';
import KeyboardDropDown from './components/KeyboardDropDown';
import LanguagesDropDown from './components/LanguagesDropDown';
const LocaleStep = () => {
@ -13,7 +13,7 @@ const LocaleStep = () => {
</Title>
<Text>Select locale for your image.</Text>
<LanguagesDropDown />
<KeyboardInput />
<KeyboardDropDown />
</Form>
);
};

View file

@ -0,0 +1,598 @@
export const keyboardsList = [
'3l',
'adnw',
'al',
'al-plisi',
'amiga-de',
'amiga-us',
'ANSI-dvorak',
'apple-a1048-sv',
'apple-a1243-sv',
'apple-a1243-sv-fn-reverse',
'apple-internal-0x0253-sv',
'apple-internal-0x0253-sv-fn-reverse',
'applkey',
'ara',
'at',
'atari-de',
'atari-se',
'atari-uk-falcon',
'atari-us',
'at-mac',
'at-nodeadkeys',
'az',
'azerty',
'ba',
'ba-alternatequotes',
'backspace',
'bashkir',
'ba-unicode',
'ba-unicodeus',
'ba-us',
'be',
'be-iso-alternate',
'be-latin1',
'be-nodeadkeys',
'be-oss',
'be-oss_latin9',
'be-wang',
'bg_bds-cp1251',
'bg_bds-utf8',
'bg-cp1251',
'bg-cp855',
'bg_pho-cp1251',
'bg_pho-utf8',
'bone',
'br',
'br-abnt',
'br-abnt2',
'br-dvorak',
'br-latin1-abnt2',
'br-latin1-us',
'br-nativo',
'br-nativo-epo',
'br-nativo-us',
'br-nodeadkeys',
'br-thinkpad',
'by',
'by-cp1251',
'by-latin',
'bywin-cp1251',
'ca',
'ca-eng',
'ca-fr-dvorak',
'ca-fr-legacy',
'ca-multix',
'carpalx',
'carpalx-full',
'cf',
'ch',
'ch-de_mac',
'ch-de_nodeadkeys',
'ch-fr',
'ch-fr_mac',
'ch-fr_nodeadkeys',
'ch-legacy',
'cm',
'cm-azerty',
'cm-dvorak',
'cm-french',
'cm-mmuock',
'cm-qwerty',
'cn',
'cn-altgr-pinyin',
'croat',
'ctrl',
'cz',
'cz-bksl',
'cz-cp1250',
'cz-dvorak-ucw',
'cz-lat2',
'cz-lat2-prog',
'cz-qwerty',
'cz-qwerty_bksl',
'cz-qwerty-mac',
'cz-rus',
'cz-us-qwertz',
'cz-winkeys',
'cz-winkeys-qwerty',
'de',
'de_alt_UTF-8',
'de_CH-latin1',
'de-deadacute',
'de-deadgraveacute',
'de-deadtilde',
'de-dsb',
'de-dsb_qwertz',
'de-dvorak',
'de-e1',
'de-e2',
'defkeymap',
'defkeymap_V1.0',
'de-latin1',
'de-latin1-nodeadkeys',
'de-mac',
'de-mac_nodeadkeys',
'de-mobii',
'de-neo',
'de-nodeadkeys',
'de-qwerty',
'de-ro',
'de-ro_nodeadkeys',
'de-T3',
'de-tr',
'de-us',
'dk',
'dk-dvorak',
'dk-latin1',
'dk-mac',
'dk-mac_nodeadkeys',
'dk-nodeadkeys',
'dk-winkeys',
'dvorak',
'dvorak-ca-fr',
'dvorak-de',
'dvorak-es',
'dvorak-fr',
'dvorak-l',
'dvorak-la',
'dvorak-no',
'dvorak-programmer',
'dvorak-r',
'dvorak-ru',
'dvorak-sv-a1',
'dvorak-sv-a5',
'dvorak-uk',
'dvorak-ukp',
'dz',
'dz-azerty-deadkeys',
'dz-qwerty-gb-deadkeys',
'dz-qwerty-us-deadkeys',
'ee',
'ee-dvorak',
'ee-nodeadkeys',
'ee-us',
'emacs',
'emacs2',
'en',
'en-latin9',
'epo',
'epo-legacy',
'es',
'es-ast',
'es-cat',
'es-cp850',
'es-deadtilde',
'es-dvorak',
'es-nodeadkeys',
'es-olpc',
'es-winkeys',
'et',
'et-nodeadkeys',
'euro',
'euro1',
'euro2',
'fa',
'fi',
'fi-classic',
'fi-mac',
'fi-nodeadkeys',
'fi-smi',
'fi-winkeys',
'fo',
'fo-nodeadkeys',
'fr',
'fr-afnor',
'fr-azerty',
'fr-bepo',
'fr-bepo_afnor',
'fr-bepo-latin9',
'fr-bepo_latin9',
'fr-bre',
'fr_CH',
'fr_CH-latin1',
'fr-dvorak',
'fr-ergol',
'fr-ergol_iso',
'fr-latin0',
'fr-latin1',
'fr-latin9',
'fr-latin9_nodeadkeys',
'fr-mac',
'fr-nodeadkeys',
'fr-oci',
'fr-old',
'fr-oss',
'fr-oss_latin9',
'fr-oss_nodeadkeys',
'fr-pc',
'fr-us',
'gb',
'gb-colemak',
'gb-colemak_dh',
'gb-dvorak',
'gb-dvorakukp',
'gb-extd',
'gb-gla',
'gb-intl',
'gb-mac',
'gb-mac_intl',
'gb-pl',
'ge',
'ge-ergonomic',
'ge-mess',
'ge-ru',
'gh',
'gh-akan',
'gh-avn',
'gh-ewe',
'gh-fula',
'gh-ga',
'gh-generic',
'gh-gillbt',
'gh-hausa',
'gr',
'gr-pc',
'hr',
'hr-alternatequotes',
'hr-unicode',
'hr-unicodeus',
'hr-us',
'hu',
'hu101',
'hu-101_qwerty_comma_dead',
'hu-101_qwerty_comma_nodead',
'hu-101_qwerty_dot_dead',
'hu-101_qwerty_dot_nodead',
'hu-101_qwertz_comma_dead',
'hu-101_qwertz_comma_nodead',
'hu-101_qwertz_dot_dead',
'hu-101_qwertz_dot_nodead',
'hu-102_qwerty_comma_dead',
'hu-102_qwerty_comma_nodead',
'hu-102_qwerty_dot_dead',
'hu-102_qwerty_dot_nodead',
'hu-102_qwertz_comma_dead',
'hu-102_qwertz_comma_nodead',
'hu-102_qwertz_dot_dead',
'hu-102_qwertz_dot_nodead',
'hu-nodeadkeys',
'hu-qwerty',
'hu-standard',
'id',
'ie',
'ie-CloGaelach',
'ie-ogam_is434',
'ie-UnicodeExpert',
'il',
'il-heb',
'il-phonetic',
'il-si2',
'in-eng',
'in-iipa',
'iq-ku',
'iq-ku_alt',
'iq-ku_ara',
'iq-ku_f',
'ir-ku',
'ir-ku_alt',
'ir-ku_ara',
'ir-ku_f',
'is',
'is-dvorak',
'is-latin1',
'is-latin1-us',
'is-mac',
'is-mac_legacy',
'it',
'it2',
'it-fur',
'it-geo',
'it-ibm',
'it-mac',
'it-nodeadkeys',
'it-scn',
'it-us',
'it-winkeys',
'jp',
'jp106',
'jp-dvorak',
'jp-kana86',
'jp-OADG109A',
'kazakh',
'ke',
'ke-kik',
'keypad',
'ko',
'koy',
'kr',
'kr-kr104',
'ky_alt_sh-UTF-8',
'kyrgyz',
'kz-latin',
'la-latin1',
'latam',
'latam-colemak',
'latam-deadtilde',
'latam-dvorak',
'latam-nodeadkeys',
'lk-us',
'lt',
'lt.baltic',
'lt-ibm',
'lt.l4',
'lt-lekp',
'lt-lekpa',
'lt-ratise',
'lt-sgs',
'lt-std',
'lt-us',
'lv',
'lv-adapted',
'lv-apostrophe',
'lv-ergonomic',
'lv-fkey',
'lv-modern',
'lv-tilde',
'mac-be',
'mac-de_CH',
'mac-de-latin1',
'mac-de-latin1-nodeadkeys',
'mac-dk-latin1',
'mac-dvorak',
'mac-es',
'mac-euro',
'mac-euro2',
'mac-fi-latin1',
'mac-fr',
'mac-fr_CH-latin1',
'mac-fr-legacy',
'mac-it',
'mac-no-latin1',
'mac-pl',
'mac-pt-latin1',
'mac-se',
'mac-template',
'mac-uk',
'mac-us',
'ma-french',
'ma-rif',
'md',
'md-gag',
'me',
'me-latinalternatequotes',
'me-latinunicode',
'me-latinunicodeyz',
'me-latinyz',
'mk',
'mk0',
'mk-cp1251',
'mk-utf',
'ml',
'ml-fr-oss',
'ml-us-intl',
'ml-us-mac',
'mm',
'mm-mnw',
'mm-shn',
'mod-dh-ansi-us',
'mod-dh-ansi-us-awing',
'mod-dh-ansi-us-fatz',
'mod-dh-ansi-us-fatz-wide',
'mod-dh-ansi-us-wide',
'mod-dh-iso-uk',
'mod-dh-iso-uk-wide',
'mod-dh-iso-us',
'mod-dh-iso-us-wide',
'mod-dh-matrix-us',
'mt',
'mt-alt-gb',
'mt-alt-us',
'mt-us',
'neo',
'neoqwertz',
'ng',
'ng-hausa',
'ng-igbo',
'ng-yoruba',
'nl',
'nl2',
'nl-mac',
'nl-std',
'nl-us',
'no',
'no-colemak',
'no-colemak_dh',
'no-colemak_dh_wide',
'no-dvorak',
'no-latin1',
'no-mac',
'no-mac_nodeadkeys',
'no-nodeadkeys',
'no-smi',
'no-smi_nodeadkeys',
'no-winkeys',
'nz',
'nz-mao',
'pc110',
'ph',
'ph-capewell-dvorak',
'ph-capewell-qwerf2k6',
'ph-colemak',
'ph-dvorak',
'pl',
'pl1',
'pl2',
'pl3',
'pl4',
'pl-csb',
'pl-dvorak',
'pl-dvorak_altquotes',
'pl-dvorak_quotes',
'pl-dvp',
'pl-legacy',
'pl-qwertz',
'pl-szl',
'pt',
'pt-latin1',
'pt-latin9',
'pt-mac',
'pt-mac_nodeadkeys',
'pt-nativo',
'pt-nativo-epo',
'pt-nativo-us',
'pt-nodeadkeys',
'pt-olpc',
'ro',
'ro-std',
'ro_std',
'ro-winkeys',
'rs-latin',
'rs-latinalternatequotes',
'rs-latinunicode',
'rs-latinunicodeyz',
'rs-latinyz',
'ru',
'ru1',
'ru2',
'ru3',
'ru4',
'ru-cp1251',
'ru-cv_latin',
'ru-ms',
'ru-ruchey_en',
'ru_win',
'ruwin_alt-CP1251',
'ruwin_alt-KOI8-R',
'ruwin_alt_sh-UTF-8',
'ruwin_alt-UTF-8',
'ruwin_cplk-CP1251',
'ruwin_cplk-KOI8-R',
'ruwin_cplk-UTF-8',
'ruwin_ctrl-CP1251',
'ruwin_ctrl-KOI8-R',
'ruwin_ctrl-UTF-8',
'ruwin_ct_sh-CP1251',
'ruwin_ct_sh-KOI8-R',
'ruwin_ct_sh-UTF-8',
'ru-yawerty',
'se',
'se-dvorak',
'se-fi-ir209',
'se-fi-lat6',
'se-ir209',
'se-lat6',
'se-latin1',
'se-mac',
'se-nodeadkeys',
'se-smi',
'se-svdvorak',
'se-us',
'se-us_dvorak',
'sg',
'sg-latin1',
'sg-latin1-lk450',
'si',
'si-alternatequotes',
'si-us',
'sk',
'sk-bksl',
'sk-prog-qwerty',
'sk-prog-qwertz',
'sk-qwerty',
'sk-qwerty_bksl',
'sk-qwertz',
'slovene',
'sr-cy',
'sr-latin',
'sundvorak',
'sunkeymap',
'sun-pl',
'sun-pl-altgraph',
'sunt4-es',
'sunt4-fi-latin1',
'sunt4-no-latin1',
'sunt5-cz-us',
'sunt5-de-latin1',
'sunt5-es',
'sunt5-fi-latin1',
'sunt5-fr-latin1',
'sunt5-ru',
'sunt5-uk',
'sunt5-us-cz',
'sunt6-uk',
'sv-latin1',
'sy-ku',
'sy-ku_alt',
'sy-ku_f',
'tj_alt-UTF8',
'tm',
'tm-alt',
'tr',
'tr-alt',
'tralt',
'tr-e',
'tr-f',
'trf',
'trf-fgGIod',
'tr_f-latin5',
'tr-intl',
'tr-ku',
'tr-ku_alt',
'tr-ku_f',
'trq',
'tr_q-latin5',
'ttwin_alt-UTF-8',
'ttwin_cplk-UTF-8',
'ttwin_ctrl-UTF-8',
'ttwin_ct_sh-UTF-8',
'tw',
'tw-indigenous',
'tw-saisiyat',
'ua',
'ua-cp1251',
'ua-crh',
'ua-crh_alt',
'ua-crh_f',
'ua-utf',
'ua-utf-ws',
'ua-ws',
'uk',
'unicode',
'us',
'us1',
'us-acentos',
'us-altgr-intl',
'us-alt-intl',
'us-colemak',
'us-colemak_dh',
'us-colemak_dh_iso',
'us-colemak_dh_ortho',
'us-colemak_dh_wide',
'us-colemak_dh_wide_iso',
'us-dvorak',
'us-dvorak-alt-intl',
'us-dvorak-classic',
'us-dvorak-intl',
'us-dvorak-l',
'us-dvorak-mac',
'us-dvorak-r',
'us-dvp',
'us-euro',
'us-haw',
'us-hbs',
'us-intl',
'us-mac',
'us-norman',
'us-olpc2',
'us-symbolic',
'us-workman',
'us-workman-intl',
'uz-latin',
'vn',
'vn-fr',
'vn-us',
'wangbe',
'wangbe2',
'windowkeys',
];