Disable keyboard control when an editable element is focused (#885)

This commit is contained in:
Jonatan Kłosko 2022-01-19 13:05:21 +01:00 committed by GitHub
parent f7fcb8f884
commit 3a0d77d879
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 4 deletions

View file

@ -1,5 +1,5 @@
import { getAttributeOrThrow, parseBoolean } from "../lib/attribute"; import { getAttributeOrThrow, parseBoolean } from "../lib/attribute";
import { cancelEvent } from "../lib/utils"; import { cancelEvent, isEditableElement } from "../lib/utils";
/** /**
* A hook for ControlComponent to handle user keyboard interactions. * A hook for ControlComponent to handle user keyboard interactions.
@ -30,6 +30,13 @@ const KeyboardControl = {
}; };
window.addEventListener("keyup", this.handleDocumentKeyUp, true); window.addEventListener("keyup", this.handleDocumentKeyUp, true);
this.handleDocumentFocus = (event) => {
handleDocumentFocus(this, event);
};
// Note: the focus event doesn't bubble, so we register for the capture phase
window.addEventListener("focus", this.handleDocumentFocus, true);
}, },
updated() { updated() {
@ -39,6 +46,7 @@ const KeyboardControl = {
destroyed() { destroyed() {
window.removeEventListener("keydown", this.handleDocumentKeyDown, true); window.removeEventListener("keydown", this.handleDocumentKeyDown, true);
window.removeEventListener("keyup", this.handleDocumentKeyUp, true); window.removeEventListener("keyup", this.handleDocumentKeyUp, true);
window.removeEventListener("focus", this.handleDocumentFocus, true);
}, },
}; };
@ -84,6 +92,12 @@ function handleDocumentKeyUp(hook, event) {
} }
} }
function handleDocumentFocus(hook, event) {
if (hook.props.isKeydownEnabled && isEditableElement(event.target)) {
hook.pushEventTo(hook.props.target, "disable_keyboard", {});
}
}
function keyboardEnabled(hook) { function keyboardEnabled(hook) {
return hook.props.isKeydownEnabled || hook.props.isKeyupEnabled; return hook.props.isKeydownEnabled || hook.props.isKeyupEnabled;
} }

View file

@ -61,10 +61,19 @@ defmodule LivebookWeb.Output.ControlComponent do
@impl true @impl true
def handle_event("toggle_keyboard", %{}, socket) do def handle_event("toggle_keyboard", %{}, socket) do
socket = update(socket, :keyboard_enabled, &not/1) socket = update(socket, :keyboard_enabled, &not/1)
maybe_report_status(socket)
{:noreply, socket}
end
if :status in socket.assigns.attrs.events do def handle_event("disable_keyboard", %{}, socket) do
report_event(socket, %{type: :status, enabled: socket.assigns.keyboard_enabled}) socket =
end if socket.assigns.keyboard_enabled do
socket = assign(socket, keyboard_enabled: false)
maybe_report_status(socket)
socket
else
socket
end
{:noreply, socket} {:noreply, socket}
end end
@ -84,6 +93,12 @@ defmodule LivebookWeb.Output.ControlComponent do
{:noreply, socket} {:noreply, socket}
end end
defp maybe_report_status(socket) do
if :status in socket.assigns.attrs.events do
report_event(socket, %{type: :status, enabled: socket.assigns.keyboard_enabled})
end
end
defp report_event(socket, attrs) do defp report_event(socket, attrs) do
topic = socket.assigns.attrs.ref topic = socket.assigns.attrs.ref
event = Map.merge(%{origin: self()}, attrs) event = Map.merge(%{origin: self()}, attrs)