mirror of
https://github.com/livebook-dev/livebook.git
synced 2024-11-17 05:18:52 +08:00
105 lines
2.7 KiB
JavaScript
105 lines
2.7 KiB
JavaScript
import { getAttributeOrThrow, parseBoolean } from "../lib/attribute";
|
|
import { cancelEvent, isEditableElement } from "../lib/utils";
|
|
|
|
/**
|
|
* A hook for ControlComponent to handle user keyboard interactions.
|
|
*
|
|
* Configuration:
|
|
*
|
|
* * `data-keydown-enabled` - whether keydown events should be intercepted
|
|
*
|
|
* * `data-keyup-enabled` - whether keyup events should be intercepted
|
|
*
|
|
* * `data-target` - the target to send live events to
|
|
*/
|
|
const KeyboardControl = {
|
|
mounted() {
|
|
this.props = getProps(this);
|
|
|
|
this.handleDocumentKeyDown = (event) => {
|
|
handleDocumentKeyDown(this, event);
|
|
};
|
|
|
|
// We intentionally register on window rather than document,
|
|
// to intercept clicks as early on as possible, even before
|
|
// the session shortcuts
|
|
window.addEventListener("keydown", this.handleDocumentKeyDown, true);
|
|
|
|
this.handleDocumentKeyUp = (event) => {
|
|
handleDocumentKeyUp(this, event);
|
|
};
|
|
|
|
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() {
|
|
this.props = getProps(this);
|
|
},
|
|
|
|
destroyed() {
|
|
window.removeEventListener("keydown", this.handleDocumentKeyDown, true);
|
|
window.removeEventListener("keyup", this.handleDocumentKeyUp, true);
|
|
window.removeEventListener("focus", this.handleDocumentFocus, true);
|
|
},
|
|
};
|
|
|
|
function getProps(hook) {
|
|
return {
|
|
isKeydownEnabled: getAttributeOrThrow(
|
|
hook.el,
|
|
"data-keydown-enabled",
|
|
parseBoolean
|
|
),
|
|
isKeyupEnabled: getAttributeOrThrow(
|
|
hook.el,
|
|
"data-keyup-enabled",
|
|
parseBoolean
|
|
),
|
|
target: getAttributeOrThrow(hook.el, "data-target"),
|
|
};
|
|
}
|
|
|
|
function handleDocumentKeyDown(hook, event) {
|
|
if (keyboardEnabled(hook)) {
|
|
cancelEvent(event);
|
|
}
|
|
|
|
if (hook.props.isKeydownEnabled) {
|
|
if (event.repeat) {
|
|
return;
|
|
}
|
|
|
|
const key = event.key;
|
|
hook.pushEventTo(hook.props.target, "keydown", { key });
|
|
}
|
|
}
|
|
|
|
function handleDocumentKeyUp(hook, event) {
|
|
if (keyboardEnabled(hook)) {
|
|
cancelEvent(event);
|
|
}
|
|
|
|
if (hook.props.isKeyupEnabled) {
|
|
const key = event.key;
|
|
hook.pushEventTo(hook.props.target, "keyup", { key });
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
export default KeyboardControl;
|