dbeaver/cloudbeaver#3815 upgrades lib to version where it works (#4165)

* dbeaver/cloudbeaver#3815 upgrades lib to version where it works

* dbeaver/pro#3815 updates react-hotkeys-hook lib

* dbeaver/pro#3815 fixes build

* dbeaver/pro#3815 fixes case dependant hotkeys activation

* dbeaver/pro#3815 allows textbox form tag to support sql editor

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
This commit is contained in:
sergeyteleshev
2026-07-07 14:09:27 +02:00
committed by GitHub
co-authored by Daria Marutkina
parent 5c58343a10
commit af11aaa8fe
6 changed files with 63 additions and 45 deletions
+1 -1
View File
@@ -42,7 +42,7 @@
"mobx-react-lite": "^4",
"react": "^19",
"react-dom": "^19",
"react-hotkeys-hook": "5.1.0",
"react-hotkeys-hook": "^5",
"react-minisearch": "^7",
"subscript": "^9",
"tslib": "^2"
+37 -25
View File
@@ -1,54 +1,66 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2025 DBeaver Corp and others
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import type { DependencyList } from 'react';
export { useHotkeys, type Hotkey } from 'react-hotkeys-hook';
// TODO: types broken in ESM
declare module 'react-hotkeys-hook' {
export type FormTags = 'input' | 'textarea' | 'select' | 'INPUT' | 'TEXTAREA' | 'SELECT';
export type Keys = string | readonly string[];
export type FormTags =
| 'input'
| 'textarea'
| 'select'
| 'INPUT'
| 'TEXTAREA'
| 'SELECT'
| 'searchbox'
| 'slider'
| 'spinbutton'
| 'menuitem'
| 'menuitemcheckbox'
| 'menuitemradio'
| 'option'
| 'radio'
| 'textbox';
export type Scopes = string | readonly string[];
export type EventListenerOptions =
| {
capture?: boolean;
once?: boolean;
passive?: boolean;
signal?: AbortSignal;
}
| boolean; // useCapture
export type KeyboardModifiers = {
alt?: boolean;
ctrl?: boolean;
meta?: boolean;
shift?: boolean;
mod?: boolean;
useKey?: boolean;
useKey?: boolean; // Custom modifier to listen to the produced key instead of the code
};
export type Hotkey = KeyboardModifiers & {
keys?: readonly string[];
scopes?: Scopes;
description?: string;
isSequence?: boolean;
hotkey: string;
metadata?: Record<string, unknown>;
};
export type HotkeysEvent = Hotkey;
export type HotkeyCallback = (keyboardEvent: KeyboardEvent, hotkeysEvent: HotkeysEvent) => void;
export type Trigger = boolean | ((keyboardEvent: KeyboardEvent, hotkeysEvent: HotkeysEvent) => boolean);
export type Options = {
enabled?: Trigger;
enableOnFormTags?: readonly FormTags[] | boolean;
enableOnContentEditable?: boolean;
ignoreEventWhen?: (e: KeyboardEvent) => boolean;
splitKey?: string;
delimiter?: string;
scopes?: Scopes;
keyup?: boolean;
keydown?: boolean;
preventDefault?: Trigger;
description?: string;
document?: Document;
ignoreModifiers?: boolean;
eventListenerOptions?: EventListenerOptions;
useKey?: boolean;
sequenceTimeoutMs?: number;
sequenceSplitKey?: string;
};
export type OptionsOrDependencyArray = Options | import('react').DependencyList;
export type OptionsOrDependencyArray = Options | DependencyList;
export function useHotkeys<T extends HTMLElement>(
keys: Keys,
callback: HotkeyCallback,
@@ -66,7 +66,8 @@ export const CaptureView = observer<React.PropsWithChildren<ICaptureViewProps>>(
},
{
enabled: allKeys.length > 0,
enableOnFormTags: ['INPUT', 'SELECT', 'TEXTAREA'],
useKey: true,
enableOnFormTags: ['INPUT', 'SELECT', 'TEXTAREA', 'textbox'],
preventDefault(event, handler) {
// Don't prevent default if event was already handled by a child view
if (EventContext.has(event, EventStopPropagationFlag)) {
@@ -139,10 +139,14 @@ describe('parseHotkey', () => {
expect(result.keys).toContain('a');
});
it('sets isSequence and useKey to false', () => {
it('sets isSequence to false', () => {
const result = parseHotkey('ctrl+a');
expect(result.isSequence).toBe(false);
expect(result.useKey).toBe(false);
});
it('sets useKey to true', () => {
const result = parseHotkey('ctrl+a');
expect(result.useKey).toBe(true);
});
it('does not include modifiers in keys array', () => {
@@ -82,10 +82,9 @@ export function isBindingPressed<T extends HTMLElement>(event: KeyboardEvent<T>,
}
export function parseHotkey(hotkey: string, combinationKey = '+'): Hotkey {
const keys = hotkey
.toLocaleLowerCase()
.split(combinationKey)
.map(k => mapKey(k));
hotkey = hotkey.toLocaleLowerCase();
const keys = hotkey.split(combinationKey).map(k => mapKey(k));
const modifiers: Record<string, boolean> = {
alt: keys.includes('alt'),
@@ -99,9 +98,11 @@ export function parseHotkey(hotkey: string, combinationKey = '+'): Hotkey {
return {
...modifiers,
hotkey,
keys: singleCharKeys,
isSequence: false,
useKey: false,
metadata: undefined,
useKey: true,
description: undefined,
};
}
+11 -11
View File
@@ -1531,7 +1531,7 @@ __metadata:
mobx-react-lite: "npm:^4"
react: "npm:^19"
react-dom: "npm:^19"
react-hotkeys-hook: "npm:5.1.0"
react-hotkeys-hook: "npm:^5"
react-minisearch: "npm:^7"
rimraf: "npm:^6"
subscript: "npm:^9"
@@ -17220,16 +17220,6 @@ __metadata:
languageName: node
linkType: hard
"react-hotkeys-hook@npm:5.1.0":
version: 5.1.0
resolution: "react-hotkeys-hook@npm:5.1.0"
peerDependencies:
react: ">=16.8.0"
react-dom: ">=16.8.0"
checksum: 10c0/99df6d3c305b139ac7afd073b58575961bf30a819fb23e8f1251b1b3a9f1c7662737f8b6266e3fc42bd5bdfdaca81aa1e019613f95f9a6313267de265e45836d
languageName: node
linkType: hard
"react-hotkeys-hook@npm:^4.6.1":
version: 4.6.2
resolution: "react-hotkeys-hook@npm:4.6.2"
@@ -17240,6 +17230,16 @@ __metadata:
languageName: node
linkType: hard
"react-hotkeys-hook@npm:^5":
version: 5.3.3
resolution: "react-hotkeys-hook@npm:5.3.3"
peerDependencies:
react: ">=16.8.0"
react-dom: ">=16.8.0"
checksum: 10c0/311f3b749cdd5ba20832fb2ea97cd94248f25ebe8417f0da2a76be7a2ca0fa94dfd2fe9eb1d399f41305f65937690825d167708f5d5c27652cb90a97ce0dbf06
languageName: node
linkType: hard
"react-inspector@npm:^6.0.2":
version: 6.0.2
resolution: "react-inspector@npm:6.0.2"