diff --git a/app/src/protyle/render/av/cell.ts b/app/src/protyle/render/av/cell.ts index 477de9e3a..5e2f8dc96 100644 --- a/app/src/protyle/render/av/cell.ts +++ b/app/src/protyle/render/av/cell.ts @@ -344,6 +344,23 @@ export const openCalcMenu = (protyle: IProtyle, calcElement: HTMLElement) => { menu.open({x: calcRect.left, y: calcRect.bottom, h: calcRect.height}); }; +export const cellScrollIntoView = (blockElement: HTMLElement, cellRect: DOMRect) => { + const avScrollElement = blockElement.querySelector(".av__scroll"); + const avScrollRect = avScrollElement.getBoundingClientRect(); + if (avScrollRect.left > cellRect.left) { + avScrollElement.scrollLeft = avScrollElement.scrollLeft + cellRect.left - avScrollRect.left; + } else if (avScrollRect.right < cellRect.right) { + avScrollElement.scrollLeft = avScrollElement.scrollLeft + cellRect.right - avScrollRect.right; + } + const avHeaderRect = blockElement.querySelector(".av__header").getBoundingClientRect() + if (avHeaderRect.bottom > cellRect.top) { + const contentElement = hasClosestByClassName(blockElement, "protyle-content"); + if (contentElement) { + contentElement.scrollTop = contentElement.scrollTop + cellRect.top - avHeaderRect.bottom; + } + } +} + export const popTextCell = (protyle: IProtyle, cellElements: HTMLElement[], type?: TAVCol) => { if (!type) { type = cellElements[0].parentElement.parentElement.firstElementChild.querySelector(`[data-col-id="${cellElements[0].getAttribute("data-col-id")}"]`).getAttribute("data-dtype") as TAVCol; @@ -357,17 +374,7 @@ export const popTextCell = (protyle: IProtyle, cellElements: HTMLElement[], type const blockElement = hasClosestBlock(cellElements[0]); let cellRect = cellElements[0].getBoundingClientRect(); if (blockElement) { - const avScrollElement = blockElement.querySelector(".av__scroll"); - const avScrollRect = avScrollElement.getBoundingClientRect(); - if (avScrollRect.left > cellRect.left) { - avScrollElement.scrollLeft = avScrollElement.scrollLeft + cellRect.left - avScrollRect.left; - } else if (avScrollRect.right < cellRect.right) { - avScrollElement.scrollLeft = avScrollElement.scrollLeft + cellRect.right - avScrollRect.right; - } - const avHeaderRect = blockElement.querySelector(".av__header").getBoundingClientRect() - if (avHeaderRect.bottom > cellRect.top) { - protyle.contentElement.scrollTop = protyle.contentElement.scrollTop + cellRect.top - avHeaderRect.bottom; - } + cellScrollIntoView(blockElement, cellRect) } cellRect = cellElements[0].getBoundingClientRect(); let html = ""; diff --git a/app/src/protyle/render/av/keydown.ts b/app/src/protyle/render/av/keydown.ts new file mode 100644 index 000000000..80ea92915 --- /dev/null +++ b/app/src/protyle/render/av/keydown.ts @@ -0,0 +1,65 @@ +import {matchHotKey} from "../../util/hotKey"; +import {selectRow, updateHeader} from "./row"; +import {cellScrollIntoView} from "./cell"; + +export const avKeydown = (event: KeyboardEvent, nodeElement: HTMLElement) => { + if (!nodeElement.classList.contains("av")) { + return false; + } + if (event.isComposing) { + event.stopPropagation(); + return true; + } + // 避免浏览器默认快捷键 + if (matchHotKey("⌘B", event) || matchHotKey("⌘I", event) || matchHotKey("⌘U", event)) { + event.preventDefault(); + return true; + } + const selectCellElement = nodeElement.querySelector(".av__cell--select") + if (selectCellElement) { + if (event.key === "Escape") { + selectCellElement.classList.remove("av__cell--select"); + selectRow(selectCellElement.parentElement.querySelector(".av__firstcol"), "select"); + event.preventDefault(); + return true; + } + if (event.key === "Enter") { + // TODO + event.preventDefault(); + return true; + } + let cellRect + if (event.key === "ArrowLeft") { + const previousRowElement = selectCellElement.parentElement.previousElementSibling + if (selectCellElement.previousElementSibling && selectCellElement.previousElementSibling.classList.contains("av__cell")) { + selectCellElement.classList.remove("av__cell--select"); + selectCellElement.previousElementSibling.classList.add("av__cell--select"); + cellRect = nodeElement.querySelector(".av__cell--select").getBoundingClientRect(); + } else if (previousRowElement && !previousRowElement.classList.contains("av__row--header")) { + selectCellElement.classList.remove("av__cell--select"); + previousRowElement.lastElementChild.previousElementSibling.classList.add("av__cell--select"); + cellRect = nodeElement.querySelector(".av__cell--select").getBoundingClientRect(); + } + if (cellRect) { + cellScrollIntoView(nodeElement, cellRect); + } + event.preventDefault(); + return true; + } + } + const selectRowElement = nodeElement.querySelector(".av__row--select:not(.av__row--header)") as HTMLElement; + if (selectRowElement) { + if (event.key === "Escape") { + selectRowElement.querySelector(".av__firstcol use").setAttribute("xlink:href", "#iconUncheck"); + selectRowElement.classList.remove("av__row--select"); + updateHeader(selectRowElement); + return true; + } + // event.shiftKey + if (event.key === "ArrowUp") { + return true; + } + } + return false; +} + diff --git a/app/src/protyle/wysiwyg/keydown.ts b/app/src/protyle/wysiwyg/keydown.ts index bf4970db9..50359c2fd 100644 --- a/app/src/protyle/wysiwyg/keydown.ts +++ b/app/src/protyle/wysiwyg/keydown.ts @@ -69,7 +69,7 @@ import {escapeHtml} from "../../util/escape"; import {insertHTML} from "../util/insertHTML"; import {removeSearchMark} from "../toolbar/util"; import {copyPNG} from "../../menus/util"; -import {selectRow, updateHeader} from "../render/av/row"; +import {avKeydown} from "../render/av/keydown"; const getContentByInlineHTML = (range: Range, cb: (content: string) => void) => { @@ -119,14 +119,10 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { return; } - if (nodeElement.classList.contains("av")) { - if (matchHotKey("⌘B", event) || matchHotKey("⌘I", event) || matchHotKey("⌘U", event)) { - event.preventDefault(); - } - if (event.key !== "Escape") { - return; - } + if (avKeydown(event, nodeElement)) { + return; } + if (nodeElement.classList.contains("protyle-wysiwyg--select") && !isCtrl(event) && !event.shiftKey && !event.altKey) { if (event.key.toLowerCase() === "a") { event.stopPropagation(); @@ -1217,11 +1213,7 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { // esc if (event.key === "Escape") { - const cellSelectElement = nodeElement.querySelector(".av__cell--select") - if (cellSelectElement) { - cellSelectElement.classList.remove("av__cell--select"); - selectRow(cellSelectElement.parentElement.querySelector(".av__firstcol"), "select"); - } else if (!protyle.toolbar.element.classList.contains("fn__none") || + if (!protyle.toolbar.element.classList.contains("fn__none") || !protyle.hint.element.classList.contains("fn__none") || !protyle.toolbar.subElement.classList.contains("fn__none")) { hideElements(["toolbar", "hint", "util"], protyle); @@ -1237,12 +1229,6 @@ export const keydown = (protyle: IProtyle, editorElement: HTMLElement) => { range.collapse(false); nodeElement.classList.add("protyle-wysiwyg--select"); countBlockWord([nodeElement.getAttribute("data-node-id")], protyle.block.rootID); - const selectRowElement = nodeElement.querySelector(".av__row--select:not(.av__row--header)") as HTMLElement; - if (selectRowElement) { - selectRowElement.querySelector(".av__firstcol use").setAttribute("xlink:href", "#iconUncheck"); - selectRowElement.classList.remove("av__row--select"); - updateHeader(selectRowElement); - } } event.preventDefault(); return;