|
@@ -6,12 +6,15 @@ import "./hotkeyInput.css";
|
|
|
|
|
|
interface HotkeyInputProps {
|
|
|
initialValue?: HotkeyObj;
|
|
|
- resetValue?: HotkeyObj;
|
|
|
onChange: (hotkey: HotkeyObj) => void;
|
|
|
}
|
|
|
|
|
|
+let initialHotkey: HotkeyObj | undefined;
|
|
|
+
|
|
|
/** Creates a hotkey input element */
|
|
|
-export function createHotkeyInput({ initialValue, resetValue, onChange }: HotkeyInputProps): HTMLElement {
|
|
|
+export function createHotkeyInput({ initialValue, onChange }: HotkeyInputProps): HTMLElement {
|
|
|
+ initialHotkey = initialValue;
|
|
|
+
|
|
|
const wrapperElem = document.createElement("div");
|
|
|
wrapperElem.classList.add("bytm-hotkey-wrapper");
|
|
|
|
|
@@ -26,26 +29,44 @@ export function createHotkeyInput({ initialValue, resetValue, onChange }: Hotkey
|
|
|
inputElem.ariaLabel = inputElem.title = t("hotkey_input_click_to_change_tooltip");
|
|
|
|
|
|
const resetElem = document.createElement("span");
|
|
|
- resetElem.classList.add("bytm-hotkey-reset", "bytm-link");
|
|
|
+ resetElem.classList.add("bytm-hotkey-reset", "bytm-link", "bytm-hidden");
|
|
|
resetElem.role = "button";
|
|
|
resetElem.tabIndex = 0;
|
|
|
resetElem.textContent = `(${t("reset")})`;
|
|
|
+ resetElem.ariaLabel = resetElem.title = t("reset");
|
|
|
+
|
|
|
+ const deactivate = () => {
|
|
|
+ siteEvents.emit("hotkeyInputActive", false);
|
|
|
+ const curVal = getFeatures().switchSitesHotkey ?? initialValue;
|
|
|
+ inputElem.value = curVal?.code ?? t("hotkey_input_click_to_change");
|
|
|
+ inputElem.dataset.state = "inactive";
|
|
|
+ inputElem.ariaLabel = inputElem.title = t("hotkey_input_click_to_change_tooltip");
|
|
|
+ infoElem.innerHTML = curVal ? getHotkeyInfoHtml(curVal) : "";
|
|
|
+ };
|
|
|
+
|
|
|
+ const activate = () => {
|
|
|
+ siteEvents.emit("hotkeyInputActive", true);
|
|
|
+ inputElem.value = "< ... >";
|
|
|
+ inputElem.dataset.state = "active";
|
|
|
+ inputElem.ariaLabel = inputElem.title = t("hotkey_input_click_to_cancel_tooltip");
|
|
|
+ };
|
|
|
|
|
|
const resetClicked = (e: MouseEvent | KeyboardEvent) => {
|
|
|
e.preventDefault();
|
|
|
e.stopImmediatePropagation();
|
|
|
|
|
|
- onChange(resetValue!);
|
|
|
- inputElem.value = resetValue!.code;
|
|
|
- inputElem.dataset.state = "inactive";
|
|
|
- infoElem.textContent = getHotkeyInfo(resetValue!);
|
|
|
+ onChange(initialValue!);
|
|
|
+ deactivate();
|
|
|
+ inputElem.value = initialValue!.code;
|
|
|
+ infoElem.innerHTML = getHotkeyInfoHtml(initialValue!);
|
|
|
+ resetElem.classList.add("bytm-hidden");
|
|
|
};
|
|
|
|
|
|
resetElem.addEventListener("click", resetClicked);
|
|
|
- resetElem.addEventListener("keydown", (e) => e.key === "Enter" && resetClicked(e));
|
|
|
+ resetElem.addEventListener("keydown", (e) => ["Enter", " ", "Space"].includes(e.key) && resetClicked(e));
|
|
|
|
|
|
if(initialValue)
|
|
|
- infoElem.textContent = getHotkeyInfo(initialValue);
|
|
|
+ infoElem.innerHTML = getHotkeyInfoHtml(initialValue);
|
|
|
|
|
|
let lastKeyDown: HotkeyObj | undefined;
|
|
|
|
|
@@ -65,7 +86,8 @@ export function createHotkeyInput({ initialValue, resetValue, onChange }: Hotkey
|
|
|
} as HotkeyObj;
|
|
|
inputElem.value = hotkey.code;
|
|
|
inputElem.dataset.state = "inactive";
|
|
|
- infoElem.textContent = getHotkeyInfo(hotkey);
|
|
|
+ infoElem.innerHTML = getHotkeyInfoHtml(hotkey);
|
|
|
+ inputElem.ariaLabel = inputElem.title = t("hotkey_input_click_to_cancel_tooltip");
|
|
|
onChange(hotkey);
|
|
|
});
|
|
|
|
|
@@ -82,54 +104,51 @@ export function createHotkeyInput({ initialValue, resetValue, onChange }: Hotkey
|
|
|
shift: e.shiftKey,
|
|
|
ctrl: e.ctrlKey,
|
|
|
alt: e.altKey,
|
|
|
- } as HotkeyObj;
|
|
|
+ } satisfies HotkeyObj;
|
|
|
+
|
|
|
+ const keyChanged = initialHotkey?.code !== hotkey.code || initialHotkey?.shift !== hotkey.shift || initialHotkey?.ctrl !== hotkey.ctrl || initialHotkey?.alt !== hotkey.alt;
|
|
|
lastKeyDown = hotkey;
|
|
|
|
|
|
- inputElem.value = hotkey.code;
|
|
|
- inputElem.dataset.state = "inactive";
|
|
|
- infoElem.textContent = getHotkeyInfo(hotkey);
|
|
|
- inputElem.ariaLabel = inputElem.title = t("hotkey_input_click_to_cancel_tooltip");
|
|
|
onChange(hotkey);
|
|
|
- });
|
|
|
|
|
|
- const deactivate = () => {
|
|
|
- siteEvents.emit("hotkeyInputActive", false);
|
|
|
- const curVal = getFeatures().switchSitesHotkey ?? initialValue;
|
|
|
- inputElem.value = curVal?.code ?? t("hotkey_input_click_to_change");
|
|
|
- inputElem.dataset.state = "inactive";
|
|
|
- inputElem.ariaLabel = inputElem.title = t("hotkey_input_click_to_change_tooltip");
|
|
|
- infoElem.textContent = curVal ? getHotkeyInfo(curVal) : "";
|
|
|
- };
|
|
|
+ if(keyChanged) {
|
|
|
+ deactivate();
|
|
|
+ resetElem.classList.remove("bytm-hidden");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ resetElem.classList.add("bytm-hidden");
|
|
|
|
|
|
- const activate = () => {
|
|
|
- siteEvents.emit("hotkeyInputActive", true);
|
|
|
- inputElem.value = "< ... >";
|
|
|
- inputElem.dataset.state = "active";
|
|
|
- inputElem.ariaLabel = inputElem.title = t("hotkey_input_click_to_cancel_tooltip");
|
|
|
- };
|
|
|
+ inputElem.value = hotkey.code;
|
|
|
+ inputElem.dataset.state = "inactive";
|
|
|
+ infoElem.innerHTML = getHotkeyInfoHtml(hotkey);
|
|
|
+ });
|
|
|
|
|
|
siteEvents.on("cfgMenuClosed", deactivate);
|
|
|
|
|
|
inputElem.addEventListener("click", () => {
|
|
|
- if(inputElem.dataset.state === "active")
|
|
|
- deactivate();
|
|
|
+ if(inputElem.dataset.state === "inactive")
|
|
|
+ activate();
|
|
|
else
|
|
|
+ deactivate();
|
|
|
+ });
|
|
|
+ inputElem.addEventListener("keydown", (e) => {
|
|
|
+ if(inputElem.dataset.state === "inactive" && ["Enter", " ", "Space"].includes(e.key))
|
|
|
activate();
|
|
|
});
|
|
|
|
|
|
+ wrapperElem.appendChild(resetElem);
|
|
|
wrapperElem.appendChild(infoElem);
|
|
|
wrapperElem.appendChild(inputElem);
|
|
|
- resetValue && wrapperElem.appendChild(resetElem);
|
|
|
|
|
|
return wrapperElem;
|
|
|
}
|
|
|
|
|
|
-function getHotkeyInfo(hotkey: HotkeyObj) {
|
|
|
+function getHotkeyInfoHtml(hotkey: HotkeyObj) {
|
|
|
const modifiers = [] as string[];
|
|
|
- hotkey.ctrl && modifiers.push(t("hotkey_key_ctrl"));
|
|
|
- hotkey.shift && modifiers.push(t("hotkey_key_shift"));
|
|
|
- hotkey.alt && modifiers.push(getOS() === "mac" ? t("hotkey_key_mac_option") : t("hotkey_key_alt"));
|
|
|
- return modifiers.reduce((a, c) => a += `${c} + `, "");
|
|
|
+ hotkey.ctrl && modifiers.push(`<kbd class="bytm-kbd">${t("hotkey_key_ctrl")}</kbd>`);
|
|
|
+ hotkey.shift && modifiers.push(`<kbd class="bytm-kbd">${t("hotkey_key_shift")}</kbd>`);
|
|
|
+ hotkey.alt && modifiers.push(`<kbd class="bytm-kbd">${getOS() === "mac" ? t("hotkey_key_mac_option") : t("hotkey_key_alt")}</kbd>`);
|
|
|
+ return `${modifiers.join(" ")}${modifiers.length > 0 ? " + " : ""}`;
|
|
|
}
|
|
|
|
|
|
/** Crude OS detection for keyboard layout purposes */
|