mirror of
https://github.com/rio-labs/rio.git
synced 2026-01-06 05:09:43 -06:00
fix MultiLineTextInput swallowing ALL key events
This commit is contained in:
@@ -35,16 +35,20 @@ export class MultiLineTextInputComponent extends ComponentBase {
|
||||
// In addition to notifying the backend, also include the input's
|
||||
// current value. This ensures any event handlers actually use the up-to
|
||||
// date value.
|
||||
this.inputBox.inputElement.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter" && event.shiftKey) {
|
||||
this.state.text = this.inputBox.value;
|
||||
this.sendMessageToBackend({
|
||||
text: this.state.text,
|
||||
});
|
||||
this.inputBox.inputElement.addEventListener(
|
||||
"keydown",
|
||||
(event) => {
|
||||
if (event.key === "Enter" && event.shiftKey) {
|
||||
this.state.text = this.inputBox.value;
|
||||
this.sendMessageToBackend({
|
||||
text: this.state.text,
|
||||
});
|
||||
|
||||
markEventAsHandled(event);
|
||||
}
|
||||
});
|
||||
markEventAsHandled(event);
|
||||
}
|
||||
},
|
||||
{ capture: true }
|
||||
);
|
||||
|
||||
// Eat click events so the element can't be clicked-through
|
||||
element.addEventListener("click", (event) => {
|
||||
|
||||
@@ -71,29 +71,29 @@ export class TextInputComponent extends ComponentBase {
|
||||
// In addition to notifying the backend, also include the input's
|
||||
// current value. This ensures any event handlers actually use the up-to
|
||||
// date value.
|
||||
this.inputBox.inputElement.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter") {
|
||||
// Update the state
|
||||
this.state.text = this.inputBox.value;
|
||||
this.inputBox.inputElement.addEventListener(
|
||||
"keydown",
|
||||
(event) => {
|
||||
if (event.key === "Enter") {
|
||||
// Update the state
|
||||
this.state.text = this.inputBox.value;
|
||||
|
||||
// There is no need for the debouncer to report this call, since
|
||||
// Python will already trigger both change & confirm events when
|
||||
// it receives the message that is about to be sent.
|
||||
this.onChangeLimiter.clear();
|
||||
// There is no need for the debouncer to report this call, since
|
||||
// Python will already trigger both change & confirm events when
|
||||
// it receives the message that is about to be sent.
|
||||
this.onChangeLimiter.clear();
|
||||
|
||||
// Inform the backend
|
||||
this.sendMessageToBackend({
|
||||
type: "confirm",
|
||||
text: this.state.text,
|
||||
});
|
||||
// Inform the backend
|
||||
this.sendMessageToBackend({
|
||||
type: "confirm",
|
||||
text: this.state.text,
|
||||
});
|
||||
|
||||
markEventAsHandled(event);
|
||||
} else if (hasDefaultHandler(event)) {
|
||||
// Don't `.preventDefault()` because then the user can't type
|
||||
event.stopPropagation();
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
});
|
||||
markEventAsHandled(event);
|
||||
}
|
||||
},
|
||||
{ capture: true }
|
||||
);
|
||||
|
||||
// Eat click events so the element can't be clicked-through
|
||||
element.addEventListener("click", (event) => {
|
||||
@@ -163,35 +163,3 @@ export class TextInputComponent extends ComponentBase {
|
||||
this.inputBox.focus();
|
||||
}
|
||||
}
|
||||
|
||||
function hasDefaultHandler(event: KeyboardEvent): boolean {
|
||||
if (event.key.length === 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
"Backspace",
|
||||
"Delete",
|
||||
"Enter",
|
||||
"Home",
|
||||
"End",
|
||||
"Tab",
|
||||
"ArrowLeft",
|
||||
"ArrowRight",
|
||||
"ArrowUp",
|
||||
"ArrowDown",
|
||||
].includes(event.key)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
(event.ctrlKey || event.metaKey) &&
|
||||
["a", "c", "x", "v", "z", "y"].includes(event.key)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -93,6 +93,18 @@ export class InputBox {
|
||||
this.connectClickHandlers();
|
||||
}
|
||||
|
||||
// Eat keyboard events that have an effect on the input field
|
||||
this._inputElement.addEventListener(
|
||||
"keypress",
|
||||
(event: KeyboardEvent) => {
|
||||
if (this._hasDefaultHandler(event)) {
|
||||
// Don't `.preventDefault()` because then the user can't type
|
||||
event.stopPropagation();
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// When keyboard focus is lost, check if the input is empty so that the
|
||||
// floating label can position itself accordingly
|
||||
this._inputElement.addEventListener("blur", () => {
|
||||
@@ -153,6 +165,44 @@ export class InputBox {
|
||||
this._inputElement.addEventListener("pointerdown", stopPropagation);
|
||||
}
|
||||
|
||||
private _hasDefaultHandler(event: KeyboardEvent): boolean {
|
||||
// Letters are simply inputted into the text field
|
||||
if (event.key.length === 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
"Backspace",
|
||||
"Delete",
|
||||
"Home",
|
||||
"End",
|
||||
"Tab",
|
||||
"ArrowLeft",
|
||||
"ArrowRight",
|
||||
].includes(event.key)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
(event.ctrlKey || event.metaKey) &&
|
||||
["a", "c", "x", "v", "z", "y"].includes(event.key)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Multi-line inputs have some extra hotkeys
|
||||
if (
|
||||
this._inputElement.tagName === "TEXTAREA" &&
|
||||
["ArrowUp", "ArrowDown", "Enter"].includes(event.key)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
get inputElement(): HTMLInputElement {
|
||||
return this._inputElement;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
|
||||
"Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
|
||||
Reference in New Issue
Block a user