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 { cancelEvent } from "../lib/utils";
import { cancelEvent, isEditableElement } from "../lib/utils";
/**
* A hook for ControlComponent to handle user keyboard interactions.
@ -30,6 +30,13 @@ const KeyboardControl = {
};
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() {
@ -39,6 +46,7 @@ const KeyboardControl = {
destroyed() {
window.removeEventListener("keydown", this.handleDocumentKeyDown, 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) {
return hook.props.isKeydownEnabled || hook.props.isKeyupEnabled;
}

View file

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