mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-20 00:17:44 +00:00
feat(grid): support F2 shortcut to edit focused result cell
This commit is contained in:
@@ -207,6 +207,7 @@ import {
|
||||
isCancelSearchShortcut,
|
||||
isCopyCurrentRowShortcut,
|
||||
isDeleteCurrentRowShortcut,
|
||||
isEditCellShortcut,
|
||||
isEditTableStructureShortcut,
|
||||
isFocusSearchShortcut,
|
||||
isFocusWhereShortcut,
|
||||
@@ -10088,7 +10089,7 @@ async function onGridKeydown(event: KeyboardEvent) {
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
if (event.key === "Enter" && editSelectedCell()) {
|
||||
if ((isEditCellShortcut(event, settingsStore.editorSettings.shortcuts) || (!event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey && event.key === "Enter")) && editSelectedCell()) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
@@ -12468,6 +12469,8 @@ defineExpose({
|
||||
toggleMultiRowTranspose,
|
||||
focusSearch,
|
||||
focusWhere,
|
||||
editSelectedCell,
|
||||
selectSingleCell,
|
||||
openGoToColumn,
|
||||
visibleColumnCount,
|
||||
displayableColumnCount,
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { createApp, defineComponent, h, markRaw, nextTick, ref, type App, type PropType } from "vue";
|
||||
import { createPinia, setActivePinia } from "pinia";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import i18n from "@/i18n";
|
||||
import type { ColumnInfo, DatabaseType, QueryResult } from "@/types/database";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
|
||||
vi.mock("@/composables/useDataGridColumnResize", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("@/composables/useDataGridColumnResize")>();
|
||||
const { ref } = await import("vue");
|
||||
return {
|
||||
...actual,
|
||||
useDataGridColumnResize: () => ({
|
||||
initColumnWidths: vi.fn(),
|
||||
onResizeStart: vi.fn(),
|
||||
autoFitColumn: vi.fn(),
|
||||
renderedColumnWidths: ref([120, 120]),
|
||||
totalWidth: ref(240),
|
||||
columnVars: ref({ "--total-w": "240px" }),
|
||||
getIsResizing: () => false,
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
import DataGrid from "../DataGrid.vue";
|
||||
import { useSettingsStore } from "@/stores/settingsStore";
|
||||
|
||||
const mountedApps: Array<{ app: App; host: HTMLElement }> = [];
|
||||
|
||||
const RecycleScroller = defineComponent({
|
||||
props: {
|
||||
items: {
|
||||
type: Array as PropType<unknown[]>,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
setup(props, { attrs, slots }) {
|
||||
return () =>
|
||||
h(
|
||||
"div",
|
||||
attrs,
|
||||
props.items.map((item) => slots.default?.({ item })),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
interface TableMeta {
|
||||
catalog?: string;
|
||||
schema?: string;
|
||||
tableName: string;
|
||||
columns: ColumnInfo[];
|
||||
primaryKeys: string[];
|
||||
}
|
||||
|
||||
function mountGrid(
|
||||
options: {
|
||||
context?: "results" | "table-data";
|
||||
databaseType?: DatabaseType;
|
||||
connectionId?: string;
|
||||
database?: string;
|
||||
tableMeta?: TableMeta | null;
|
||||
shortcut?: string;
|
||||
editable?: boolean;
|
||||
} = {},
|
||||
) {
|
||||
const pinia = createPinia();
|
||||
setActivePinia(pinia);
|
||||
const settingsStore = useSettingsStore();
|
||||
settingsStore.updateEditorSettings({
|
||||
dataGridRenderMode: "canvas",
|
||||
shortcuts: {
|
||||
...settingsStore.editorSettings.shortcuts,
|
||||
editCell: options.shortcut ?? "F2",
|
||||
},
|
||||
});
|
||||
const result = markRaw<QueryResult>({
|
||||
columns: ["id", "name"],
|
||||
rows: [
|
||||
[1, "Alice"],
|
||||
[2, "Bob"],
|
||||
],
|
||||
affected_rows: 0,
|
||||
execution_time_ms: 0,
|
||||
});
|
||||
const defaultTableMeta: TableMeta = {
|
||||
catalog: "warehouse",
|
||||
schema: "public",
|
||||
tableName: "users",
|
||||
columns: [],
|
||||
primaryKeys: ["id"],
|
||||
};
|
||||
|
||||
const host = document.createElement("div");
|
||||
const grid = ref<{
|
||||
editSelectedCell: () => boolean;
|
||||
selectSingleCell: (row: number, col: number) => void;
|
||||
}>();
|
||||
document.body.append(host);
|
||||
const Root = defineComponent({
|
||||
setup() {
|
||||
return () =>
|
||||
h(
|
||||
TooltipProvider,
|
||||
{ delayDuration: 0 },
|
||||
{
|
||||
default: () =>
|
||||
h(DataGrid, {
|
||||
ref: grid,
|
||||
result,
|
||||
databaseType: options.databaseType ?? "mysql",
|
||||
context: options.context ?? "table-data",
|
||||
editable: options.editable ?? true,
|
||||
connectionId: options.connectionId ?? "connection-1",
|
||||
database: options.database ?? "app",
|
||||
tableMeta: options.tableMeta === null ? undefined : (options.tableMeta ?? defaultTableMeta),
|
||||
}),
|
||||
},
|
||||
);
|
||||
},
|
||||
});
|
||||
const app = createApp(Root);
|
||||
app.use(pinia);
|
||||
app.use(i18n);
|
||||
app.component("RecycleScroller", RecycleScroller);
|
||||
app.mount(host);
|
||||
mountedApps.push({ app, host });
|
||||
return { host, grid };
|
||||
}
|
||||
|
||||
async function settle() {
|
||||
await nextTick();
|
||||
await Promise.resolve();
|
||||
await nextTick();
|
||||
}
|
||||
|
||||
function gridRoot(host: HTMLElement): HTMLElement {
|
||||
const root = host.querySelector<HTMLElement>("[data-grid-root]");
|
||||
if (!root) throw new Error("Data grid root not found");
|
||||
return root;
|
||||
}
|
||||
|
||||
function dispatchKey(target: HTMLElement, key: string, modifiers: { ctrlKey?: boolean; metaKey?: boolean; altKey?: boolean; shiftKey?: boolean } = {}): KeyboardEvent {
|
||||
const event = new KeyboardEvent("keydown", { bubbles: true, cancelable: true, key, ...modifiers });
|
||||
target.dispatchEvent(event);
|
||||
return event;
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
window.getSelection()?.removeAllRanges();
|
||||
for (const { app, host } of mountedApps.splice(0)) {
|
||||
app.unmount();
|
||||
host.remove();
|
||||
}
|
||||
});
|
||||
|
||||
describe("DataGrid editCell shortcut", () => {
|
||||
it("enters cell editing when F2 is pressed on a selected cell", async () => {
|
||||
const { host, grid } = mountGrid();
|
||||
await settle();
|
||||
const root = gridRoot(host);
|
||||
grid.value?.selectSingleCell(0, 1);
|
||||
await settle();
|
||||
|
||||
const event = dispatchKey(root, "F2");
|
||||
await settle();
|
||||
|
||||
expect(event.defaultPrevented).toBe(true);
|
||||
expect(host.querySelector(".cell-edit-input")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("still enters cell editing when plain Enter is pressed", async () => {
|
||||
const { host, grid } = mountGrid();
|
||||
await settle();
|
||||
const root = gridRoot(host);
|
||||
grid.value?.selectSingleCell(0, 1);
|
||||
await settle();
|
||||
|
||||
const event = dispatchKey(root, "Enter");
|
||||
await settle();
|
||||
|
||||
expect(event.defaultPrevented).toBe(true);
|
||||
expect(host.querySelector(".cell-edit-input")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("uses a configured shortcut and leaves F2 unhandled when rebound", async () => {
|
||||
const { host, grid } = mountGrid({ shortcut: "Mod+E" });
|
||||
await settle();
|
||||
const root = gridRoot(host);
|
||||
grid.value?.selectSingleCell(0, 1);
|
||||
await settle();
|
||||
|
||||
const defaultEvent = dispatchKey(root, "F2");
|
||||
await settle();
|
||||
expect(defaultEvent.defaultPrevented).toBe(false);
|
||||
expect(host.querySelector(".cell-edit-input")).toBeNull();
|
||||
|
||||
const customEvent = dispatchKey(root, "e", { ctrlKey: true });
|
||||
await settle();
|
||||
expect(customEvent.defaultPrevented).toBe(true);
|
||||
expect(host.querySelector(".cell-edit-input")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("does not consume F2 when the grid is read-only", async () => {
|
||||
const { host, grid } = mountGrid({ editable: false });
|
||||
await settle();
|
||||
const root = gridRoot(host);
|
||||
grid.value?.selectSingleCell(0, 0);
|
||||
await settle();
|
||||
|
||||
const event = dispatchKey(root, "F2");
|
||||
await settle();
|
||||
|
||||
expect(event.defaultPrevented).toBe(false);
|
||||
expect(host.querySelector(".cell-edit-input")).toBeNull();
|
||||
});
|
||||
|
||||
it("leaves editable text targets untouched on F2", async () => {
|
||||
const { host } = mountGrid();
|
||||
await settle();
|
||||
const root = gridRoot(host);
|
||||
const input = document.createElement("input");
|
||||
root.append(input);
|
||||
|
||||
const event = dispatchKey(input, "F2");
|
||||
await settle();
|
||||
|
||||
expect(event.defaultPrevented).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -7811,6 +7811,7 @@ export default withEnglishFallback({
|
||||
shortcutAddNextSelectionOccurrence: "Növbəti uyğunluğu əlavə et",
|
||||
shortcutSelectAllSelectionOccurrences: "Bütün uyğunluqları seç",
|
||||
shortcutExtendSelection: "Seçimi genişləndir",
|
||||
shortcutEditCell: "Xananı redaktə et",
|
||||
shortcutEditTableStructure: "Cədvəlin quruluşunu redaktə et",
|
||||
shortcutCopyCurrentRow: "Cari məlumat sətrini kopyala",
|
||||
shortcutDeleteCurrentRow: "Cari məlumat sətrini sil",
|
||||
|
||||
@@ -8837,6 +8837,7 @@ export default {
|
||||
shortcutSelectAllSelectionOccurrences: "Select all occurrences",
|
||||
shortcutSelectLineEnds: "Select line ends",
|
||||
shortcutExtendSelection: "Extend selection",
|
||||
shortcutEditCell: "Edit cell",
|
||||
shortcutEditTableStructure: "Edit table structure",
|
||||
shortcutCopyCurrentRow: "Copy current data row",
|
||||
shortcutDeleteCurrentRow: "Delete current data row",
|
||||
|
||||
@@ -8086,6 +8086,7 @@ export default withEnglishFallback({
|
||||
shortcutAddNextSelectionOccurrence: "Añadir siguiente coincidencia",
|
||||
shortcutSelectAllSelectionOccurrences: "Seleccionar todas las coincidencias",
|
||||
shortcutExtendSelection: "Ampliar selección",
|
||||
shortcutEditCell: "Editar celda",
|
||||
shortcutEditTableStructure: "Editar estructura de tabla",
|
||||
shortcutCopyCurrentRow: "Copiar fila de datos actual",
|
||||
shortcutDeleteCurrentRow: "Eliminar fila de datos actual",
|
||||
|
||||
@@ -8610,6 +8610,7 @@ export default withEnglishFallback({
|
||||
shortcutAddNextSelectionOccurrence: "Tambah kemunculan berikutnya",
|
||||
shortcutSelectAllSelectionOccurrences: "Pilih semua kemunculan",
|
||||
shortcutExtendSelection: "Perluas seleksi",
|
||||
shortcutEditCell: "Edit sel",
|
||||
shortcutEditTableStructure: "Edit struktur tabel",
|
||||
shortcutCopyCurrentRow: "Salin baris data saat ini",
|
||||
shortcutDeleteCurrentRow: "Hapus baris data saat ini",
|
||||
|
||||
@@ -7848,6 +7848,7 @@ export default withEnglishFallback({
|
||||
shortcutAddNextSelectionOccurrence: "Aggiungi occorrenza successiva",
|
||||
shortcutSelectAllSelectionOccurrences: "Seleziona tutte le occorrenze",
|
||||
shortcutExtendSelection: "Estendi selezione",
|
||||
shortcutEditCell: "Modifica cella",
|
||||
shortcutEditTableStructure: "Modifica struttura tabella",
|
||||
shortcutCopyCurrentRow: "Copia riga dati corrente",
|
||||
shortcutDeleteCurrentRow: "Elimina riga dati corrente",
|
||||
|
||||
@@ -7842,6 +7842,7 @@ export default withEnglishFallback({
|
||||
shortcutAddNextSelectionOccurrence: "次の出現箇所を選択に追加",
|
||||
shortcutSelectAllSelectionOccurrences: "すべての出現箇所を選択",
|
||||
shortcutExtendSelection: "選択範囲を拡張",
|
||||
shortcutEditCell: "セルを編集",
|
||||
shortcutEditTableStructure: "テーブル構造を編集",
|
||||
shortcutCopyCurrentRow: "現在のデータ行をコピー",
|
||||
shortcutDeleteCurrentRow: "現在のデータ行を削除",
|
||||
|
||||
@@ -7696,6 +7696,7 @@ export default withEnglishFallback({
|
||||
shortcutSelectAll: "모두 선택",
|
||||
shortcutAddNextSelectionOccurrence: "다음 일치 항목 선택 추가",
|
||||
shortcutSelectAllSelectionOccurrences: "모든 일치 항목 선택",
|
||||
shortcutEditCell: "셀 편집",
|
||||
shortcutEditTableStructure: "테이블 구조 편집",
|
||||
shortcutCopyCurrentRow: "현재 데이터 행 복사",
|
||||
shortcutDeleteCurrentRow: "현재 데이터 행 삭제",
|
||||
|
||||
@@ -7848,6 +7848,7 @@ export default withEnglishFallback({
|
||||
shortcutAddNextSelectionOccurrence: "Adicionar próxima ocorrência",
|
||||
shortcutSelectAllSelectionOccurrences: "Selecionar todas as ocorrências",
|
||||
shortcutExtendSelection: "Expandir seleção",
|
||||
shortcutEditCell: "Editar célula",
|
||||
shortcutEditTableStructure: "Editar estrutura da tabela",
|
||||
shortcutCopyCurrentRow: "Copiar linha de dados atual",
|
||||
shortcutDeleteCurrentRow: "Excluir linha de dados atual",
|
||||
|
||||
@@ -9137,6 +9137,7 @@ export default withEnglishFallback({
|
||||
shortcutAddNextSelectionOccurrence: "Добавить следующее вхождение",
|
||||
shortcutSelectAllSelectionOccurrences: "Выделить все вхождения",
|
||||
shortcutExtendSelection: "Расширить выделение",
|
||||
shortcutEditCell: "Редактировать ячейку",
|
||||
shortcutEditTableStructure: "Изменить структуру таблицы",
|
||||
shortcutCopyCurrentRow: "Копировать текущую строку данных",
|
||||
shortcutDeleteCurrentRow: "Удалить текущую строку данных",
|
||||
|
||||
@@ -7712,6 +7712,7 @@ export default withEnglishFallback({
|
||||
shortcutAddNextSelectionOccurrence: "Sonraki eşleşmeyi ekle",
|
||||
shortcutSelectAllSelectionOccurrences: "Tüm eşleşmeleri seç",
|
||||
shortcutExtendSelection: "Seçimi genişlet",
|
||||
shortcutEditCell: "Hücreyi düzenle",
|
||||
shortcutEditTableStructure: "Tablo yapısını düzenle",
|
||||
shortcutCopyCurrentRow: "Geçerli veri satırını kopyala",
|
||||
shortcutDeleteCurrentRow: "Geçerli veri satırını sil",
|
||||
|
||||
@@ -8824,6 +8824,7 @@ export default withEnglishFallback({
|
||||
shortcutToggleCaseSelection: "切换选中内容大小写",
|
||||
shortcutConvertNamingStyle: "切换命名风格",
|
||||
shortcutExPasteSqlInCondition: "ExPaste:粘贴为 IN 条件",
|
||||
shortcutEditCell: "编辑单元格",
|
||||
shortcutEditTableStructure: "编辑表结构",
|
||||
shortcutCopyCurrentRow: "复制当前数据行",
|
||||
shortcutDeleteCurrentRow: "删除当前数据行",
|
||||
|
||||
@@ -7167,6 +7167,7 @@ export default withEnglishFallback({
|
||||
shortcutAddNextSelectionOccurrence: "增加下一個選取詞",
|
||||
shortcutSelectAllSelectionOccurrences: "選取所有選取詞",
|
||||
shortcutExtendSelection: "擴展選取範圍",
|
||||
shortcutEditCell: "編輯儲存格",
|
||||
shortcutEditTableStructure: "編輯資料表結構",
|
||||
shortcutCopyCurrentRow: "複製目前資料列",
|
||||
shortcutDeleteCurrentRow: "刪除目前資料列",
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
eventToShortcut,
|
||||
isBrowserTaskManagerShortcut,
|
||||
isConvertNamingStyleShortcut,
|
||||
isEditCellShortcut,
|
||||
isEditTableStructureShortcut,
|
||||
isExecuteSqlInNewResultTabShortcut,
|
||||
isGoToColumnShortcut,
|
||||
@@ -215,6 +216,22 @@ describe("keyboard shortcut matching", () => {
|
||||
expect(isGoToColumnShortcut({ key: "g", ctrlKey: true, isComposing: true }, { goToColumn: "Mod+G" })).toBe(false);
|
||||
});
|
||||
|
||||
it("matches the edit-cell shortcut F2 by default on Windows and macOS", () => {
|
||||
expect(isEditCellShortcut({ key: "F2" }, undefined, "Win32")).toBe(true);
|
||||
expect(isEditCellShortcut({ key: "F2" }, undefined, "MacIntel")).toBe(true);
|
||||
expect(isEditCellShortcut({ key: "F2", ctrlKey: true }, undefined, "Win32")).toBe(false);
|
||||
expect(isEditCellShortcut({ key: "F2", shiftKey: true }, undefined, "Win32")).toBe(false);
|
||||
expect(isEditCellShortcut({ key: "F2", altKey: true }, undefined, "Win32")).toBe(false);
|
||||
expect(isEditCellShortcut({ key: "F3" }, undefined, "Win32")).toBe(false);
|
||||
});
|
||||
|
||||
it("honors custom and disabled edit-cell shortcuts", () => {
|
||||
expect(isEditCellShortcut({ key: "e", ctrlKey: true }, { editCell: "Mod+E" }, "Win32")).toBe(true);
|
||||
expect(isEditCellShortcut({ key: "F2" }, { editCell: "Mod+E" }, "Win32")).toBe(false);
|
||||
expect(isEditCellShortcut({ key: "F2" }, { editCell: "" }, "Win32")).toBe(false);
|
||||
expect(isEditCellShortcut({ key: "F2", isComposing: true }, undefined, "Win32")).toBe(false);
|
||||
});
|
||||
|
||||
it("matches the edit-table-structure shortcut on Windows and macOS", () => {
|
||||
expect(isEditTableStructureShortcut({ key: "d", ctrlKey: true, shiftKey: true }, undefined, "Win32")).toBe(true);
|
||||
expect(isEditTableStructureShortcut({ key: "d", metaKey: true, shiftKey: true }, undefined, "MacIntel")).toBe(true);
|
||||
|
||||
@@ -122,6 +122,18 @@ describe("shortcutRegistry editor actions", () => {
|
||||
expect(findShortcutConflict("goToColumn", "Mod+F", shortcuts)).toBeNull();
|
||||
});
|
||||
|
||||
it("registers edit-cell F2 as a conflict-free grid default", () => {
|
||||
const definition = SHORTCUT_DEFINITIONS.find((item) => item.id === "editCell");
|
||||
|
||||
expect(definition).toMatchObject({
|
||||
labelKey: "settings.shortcutEditCell",
|
||||
scope: "grid",
|
||||
defaultShortcut: "F2",
|
||||
});
|
||||
expect(DEFAULT_SHORTCUT_SETTINGS.editCell).toBe("F2");
|
||||
expect(findShortcutConflict("editCell", DEFAULT_SHORTCUT_SETTINGS.editCell, DEFAULT_SHORTCUT_SETTINGS)).toBeNull();
|
||||
});
|
||||
|
||||
it("registers copy-current-row Mod+D and edit-table-structure Mod+Shift+D as conflict-free grid defaults", () => {
|
||||
const definition = SHORTCUT_DEFINITIONS.find((item) => item.id === "editTableStructure");
|
||||
|
||||
|
||||
@@ -265,6 +265,10 @@ export function isCopyCurrentRowShortcut(event: ShortcutLikeEvent, shortcuts?: P
|
||||
return matchesShortcut(event, actionShortcut("copyCurrentRow", shortcuts));
|
||||
}
|
||||
|
||||
export function isEditCellShortcut(event: ShortcutLikeEvent, shortcuts?: Partial<ShortcutSettings>, platform = globalThis.navigator?.platform || ""): boolean {
|
||||
return matchesShortcut(event, actionShortcut("editCell", shortcuts, platform), platform);
|
||||
}
|
||||
|
||||
export function isEditTableStructureShortcut(event: ShortcutLikeEvent, shortcuts?: Partial<ShortcutSettings>, platform = globalThis.navigator?.platform || ""): boolean {
|
||||
return matchesShortcut(event, actionShortcut("editTableStructure", shortcuts, platform), platform);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ export type ShortcutActionId =
|
||||
| "toggleFold"
|
||||
| "foldAll"
|
||||
| "unfoldAll"
|
||||
| "editCell"
|
||||
| "editTableStructure"
|
||||
| "copyCurrentRow"
|
||||
| "deleteCurrentRow"
|
||||
@@ -381,6 +382,12 @@ export const SHORTCUT_DEFINITIONS: ShortcutDefinition[] = [
|
||||
scope: "editor",
|
||||
defaultShortcut: foldAllDefaultShortcut("unfoldAll"),
|
||||
},
|
||||
{
|
||||
id: "editCell",
|
||||
labelKey: "settings.shortcutEditCell",
|
||||
scope: "grid",
|
||||
defaultShortcut: "F2",
|
||||
},
|
||||
{
|
||||
id: "editTableStructure",
|
||||
labelKey: "settings.shortcutEditTableStructure",
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
isSwitchToPreviousTabShortcut,
|
||||
isCopyCurrentRowShortcut,
|
||||
isDeleteCurrentRowShortcut,
|
||||
isEditCellShortcut,
|
||||
isToggleResultsPaneShortcut,
|
||||
isToggleTransposeShortcut,
|
||||
isZoomInShortcut,
|
||||
@@ -427,6 +428,13 @@ test("matches copy current row Mod+D by default while honoring custom shortcuts"
|
||||
assert.equal(isCopyCurrentRowShortcut({ key: "d", altKey: true }, { copyCurrentRow: "Alt+D" }), true);
|
||||
});
|
||||
|
||||
test("matches edit cell F2 by default while honoring custom shortcuts", () => {
|
||||
assert.equal(isEditCellShortcut({ key: "F2" }), true);
|
||||
assert.equal(isEditCellShortcut({ key: "e", ctrlKey: true }, { editCell: "Mod+E" } as any), true);
|
||||
assert.equal(isEditCellShortcut({ key: "F2" }, { editCell: "Mod+E" } as any), false);
|
||||
assert.equal(isEditCellShortcut({ key: "F2", ctrlKey: true }), false);
|
||||
});
|
||||
|
||||
test("matches Delete for deleting current row", () => {
|
||||
assert.equal(isDeleteCurrentRowShortcut({ key: "Delete" }), true);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user