Skip to content

Commit f7de966

Browse files
authored
Merge pull request #575 from sanchit3008/master
Keyboard usability + bug fixes
2 parents 57e0d63 + e21990a commit f7de966

File tree

6 files changed

+332
-83
lines changed

6 files changed

+332
-83
lines changed

packages/core/src/events/keyboard.ts

Lines changed: 165 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import {
1313
} from "../modules/selection";
1414
import { cancelPaintModel, handleBold } from "../modules/toolbar";
1515
import { hasPartMC } from "../modules/validation";
16-
import { GlobalCache } from "../types";
17-
import { getNowDateTime, isAllowEdit } from "../utils";
16+
import { CellMatrix, GlobalCache } from "../types";
17+
import { getNowDateTime, getSheetIndex, isAllowEdit } from "../utils";
1818
import { handleCopy } from "./copy";
1919
import { jfrefreshgrid } from "../modules/refresh";
2020

@@ -95,29 +95,174 @@ export function handleGlobalEnter(
9595
}
9696
}
9797

98-
function handleBatchSelectionWithArrowKey(ctx: Context, e: KeyboardEvent) {
99-
if (
100-
ctx.luckysheetCellUpdate.length > 0
101-
// || $("#luckysheet-singleRange-dialog").is(":visible") ||
102-
// $("#luckysheet-multiRange-dialog").is(":visible")
103-
) {
104-
return;
98+
function moveToEdge(
99+
sheetData: CellMatrix,
100+
key: string,
101+
curr: number,
102+
rowDelta: 0 | 1 | -1,
103+
colDelta: 0 | 1 | -1,
104+
startR: number,
105+
endR: number,
106+
startC: number,
107+
endC: number,
108+
maxRow: number,
109+
maxCol: number
110+
) {
111+
let selectedLimit = -1;
112+
if (key === "ArrowUp") selectedLimit = startR - 1;
113+
else if (key === "ArrowDown") selectedLimit = endR + 1;
114+
else if (key === "ArrowLeft") selectedLimit = startC - 1;
115+
else if (key === "ArrowRight") selectedLimit = endC + 1;
116+
117+
const maxRowCol = colDelta === 0 ? maxRow : maxCol;
118+
let r = colDelta === 0 ? selectedLimit : curr;
119+
let c = colDelta === 0 ? curr : selectedLimit;
120+
121+
while (r > 0 && c > 0 && (colDelta === 0 ? r : c) < maxRowCol - 1) {
122+
if (
123+
!_.isNil(sheetData?.[r]?.[c]?.v) &&
124+
(_.isNil(sheetData?.[r - rowDelta]?.[c - colDelta]?.v) ||
125+
_.isNil(sheetData?.[r + rowDelta]?.[c + colDelta]?.v))
126+
) {
127+
break;
128+
} else {
129+
r += 1 * rowDelta;
130+
c += 1 * colDelta;
131+
}
105132
}
133+
return colDelta === 0 ? r : c;
134+
}
135+
136+
function handleControlPlusArrowKey(
137+
ctx: Context,
138+
e: KeyboardEvent,
139+
shiftPressed: boolean
140+
) {
141+
if (ctx.luckysheetCellUpdate.length > 0) return;
142+
143+
const idx = getSheetIndex(ctx, ctx.currentSheetId);
144+
if (_.isNil(idx)) return;
145+
146+
const file = ctx.luckysheetfile[idx];
147+
if (!file || !file.row || !file.column) return;
148+
const maxRow = file.row;
149+
const maxCol = file.column;
150+
let last;
151+
if (ctx.luckysheet_select_save && ctx.luckysheet_select_save.length > 0)
152+
last = ctx.luckysheet_select_save[ctx.luckysheet_select_save.length - 1];
153+
if (!last) return;
154+
155+
const currR = last.row_focus;
156+
const currC = last.column_focus;
157+
if (_.isNil(currR) || _.isNil(currC)) return;
158+
159+
const startR = last.row[0];
160+
const endR = last.row[1];
161+
const startC = last.column[0];
162+
const endC = last.column[1];
163+
164+
const horizontalOffset = currC - endC !== 0 ? currC - endC : currC - startC;
165+
const verticalOffset = currR - endR !== 0 ? currR - endR : currR - startR;
166+
167+
const sheetData = file.data;
168+
if (!sheetData) return;
169+
let selectedLimit;
170+
106171
switch (e.key) {
107-
/*
108172
case "ArrowUp":
109-
luckysheetMoveHighlightRange2("up", "rangeOfSelect");
173+
selectedLimit = moveToEdge(
174+
sheetData,
175+
e.key,
176+
currC,
177+
-1,
178+
0,
179+
startR,
180+
endR,
181+
startC,
182+
endC,
183+
maxRow,
184+
maxCol
185+
);
186+
if (shiftPressed) {
187+
moveHighlightRange(ctx, "down", verticalOffset, "rangeOfSelect");
188+
moveHighlightRange(ctx, "down", selectedLimit - currR, "rangeOfSelect");
189+
} else {
190+
moveHighlightCell(ctx, "down", selectedLimit - currR, "rangeOfSelect");
191+
}
110192
break;
111193
case "ArrowDown":
112-
luckysheetMoveHighlightRange2("down", "rangeOfSelect");
194+
selectedLimit = moveToEdge(
195+
sheetData,
196+
e.key,
197+
currC,
198+
1,
199+
0,
200+
startR,
201+
endR,
202+
startC,
203+
endC,
204+
maxRow,
205+
maxCol
206+
);
207+
if (shiftPressed) {
208+
moveHighlightRange(ctx, "down", verticalOffset, "rangeOfSelect");
209+
moveHighlightRange(ctx, "down", selectedLimit - currR, "rangeOfSelect");
210+
} else {
211+
moveHighlightCell(ctx, "down", selectedLimit - currR, "rangeOfSelect");
212+
}
113213
break;
114214
case "ArrowLeft":
115-
luckysheetMoveHighlightRange2("left", "rangeOfSelect");
215+
selectedLimit = moveToEdge(
216+
sheetData,
217+
e.key,
218+
currR,
219+
0,
220+
-1,
221+
startR,
222+
endR,
223+
startC,
224+
endC,
225+
maxRow,
226+
maxCol
227+
);
228+
if (shiftPressed) {
229+
moveHighlightRange(ctx, "right", horizontalOffset, "rangeOfSelect");
230+
moveHighlightRange(
231+
ctx,
232+
"right",
233+
selectedLimit - currC,
234+
"rangeOfSelect"
235+
);
236+
} else {
237+
moveHighlightCell(ctx, "right", selectedLimit - currC, "rangeOfSelect");
238+
}
116239
break;
117240
case "ArrowRight":
118-
luckysheetMoveHighlightRange2("right", "rangeOfSelect");
241+
selectedLimit = moveToEdge(
242+
sheetData,
243+
e.key,
244+
currR,
245+
0,
246+
1,
247+
startR,
248+
endR,
249+
startC,
250+
endC,
251+
maxRow,
252+
maxCol
253+
);
254+
if (shiftPressed) {
255+
moveHighlightRange(ctx, "right", horizontalOffset, "rangeOfSelect");
256+
moveHighlightRange(
257+
ctx,
258+
"right",
259+
selectedLimit - currC,
260+
"rangeOfSelect"
261+
);
262+
} else {
263+
moveHighlightCell(ctx, "right", selectedLimit - currC, "rangeOfSelect");
264+
}
119265
break;
120-
*/
121266
default:
122267
break;
123268
}
@@ -143,7 +288,7 @@ export function handleWithCtrlOrMetaKey(
143288

144289
if (["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)) {
145290
// Ctrl + Shift + 方向键 调整选区
146-
handleBatchSelectionWithArrowKey(ctx, e);
291+
handleControlPlusArrowKey(ctx, e, true);
147292
} else if (_.includes([";", '"', ":", "'"], e.key)) {
148293
const last =
149294
ctx.luckysheet_select_save?.[ctx.luckysheet_select_save.length - 1];
@@ -166,6 +311,10 @@ export function handleWithCtrlOrMetaKey(
166311
e.stopPropagation();
167312
return;
168313
}
314+
} else if (
315+
["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].includes(e.key)
316+
) {
317+
handleControlPlusArrowKey(ctx, e, false);
169318
} else if (e.code === "KeyB") {
170319
// Ctrl + B 加粗
171320
handleBold(ctx, cellInput);

packages/core/src/events/paste.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,11 @@ function pasteHandlerOfCopyPaste(
11001100
const c_c1 = copyRange.copyRange[0].column[0];
11011101
const c_c2 = copyRange.copyRange[0].column[1];
11021102

1103+
const isSingleCellPaste =
1104+
copyRange.copyRange.length === 1 &&
1105+
copyRange.copyRange[0].row[0] === copyRange.copyRange[0].row[1] &&
1106+
copyRange.copyRange[0].column[0] === copyRange.copyRange[0].column[1];
1107+
11031108
let arr: CellMatrix = [];
11041109
let isSameRow = false;
11051110
for (let i = 0; i < copyRange.copyRange.length; i += 1) {
@@ -1224,6 +1229,12 @@ function pasteHandlerOfCopyPaste(
12241229
let mtc = 0;
12251230
let maxcellCahe = 0;
12261231
let maxrowCache = 0;
1232+
1233+
const file = ctx.luckysheetfile[getSheetIndex(ctx, ctx.currentSheetId)!];
1234+
let hiddenRows;
1235+
if (isSingleCellPaste)
1236+
hiddenRows = new Set(Object.keys(file.config?.rowhidden || {}));
1237+
12271238
for (let th = 1; th <= timesH; th += 1) {
12281239
for (let tc = 1; tc <= timesC; tc += 1) {
12291240
mth = minh + (th - 1) * copyh;
@@ -1237,6 +1248,8 @@ function pasteHandlerOfCopyPaste(
12371248

12381249
const offsetMC: any = {};
12391250
for (let h = mth; h < maxrowCache; h += 1) {
1251+
// skip if row is hidden
1252+
if (isSingleCellPaste && hiddenRows?.has(h.toString())) continue;
12401253
const x = d[h];
12411254

12421255
for (let c = mtc; c < maxcellCahe; c += 1) {
@@ -1446,7 +1459,6 @@ function pasteHandlerOfCopyPaste(
14461459
last.row = [minh, maxh];
14471460
last.column = [minc, maxc];
14481461

1449-
const file = ctx.luckysheetfile[getSheetIndex(ctx, ctx.currentSheetId)!];
14501462
file.config = cfg;
14511463
file.luckysheet_conditionformat_save = cdformat;
14521464
file.dataVerification = { ...file.dataVerification, ...dataVerification };

packages/core/src/modules/dropCell.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2286,6 +2286,7 @@ export function updateDropCell(ctx: Context) {
22862286
const index = getSheetIndex(ctx, ctx.currentSheetId);
22872287
if (index == null) return;
22882288
const file = ctx.luckysheetfile[index];
2289+
const hiddenRows = new Set(Object.keys(file.config?.rowhidden || {}));
22892290

22902291
const cfg = _.cloneDeep(ctx.config);
22912292
if (cfg.borderInfo == null) {
@@ -2337,6 +2338,7 @@ export function updateDropCell(ctx: Context) {
23372338

23382339
if (direction === "down") {
23392340
for (let j = apply_str_r; j <= apply_end_r; j += 1) {
2341+
if (hiddenRows.has(`${j}`)) continue;
23402342
const cell = applyData[j - apply_str_r];
23412343

23422344
if (cell?.f != null) {
@@ -2448,6 +2450,7 @@ export function updateDropCell(ctx: Context) {
24482450
}
24492451
if (direction === "up") {
24502452
for (let j = apply_end_r; j >= apply_str_r; j -= 1) {
2453+
if (hiddenRows.has(`${j}`)) continue;
24512454
const cell = applyData[apply_end_r - j];
24522455

24532456
if (cell?.f != null) {
@@ -2549,6 +2552,7 @@ export function updateDropCell(ctx: Context) {
25492552
const asLen = apply_end_c - apply_str_c + 1;
25502553

25512554
for (let i = apply_str_r; i <= apply_end_r; i += 1) {
2555+
if (hiddenRows.has(`${i}`)) continue;
25522556
const copyD = copyData[i - apply_str_r];
25532557

25542558
const applyData = getApplyData(copyD, csLen, asLen);

packages/core/src/modules/formula.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,7 +2088,7 @@ function searchFunction(ctx: Context, searchtxt: string) {
20882088
// );
20892089
}
20902090

2091-
function getrangeseleciton() {
2091+
export function getrangeseleciton() {
20922092
const currSelection = window.getSelection();
20932093
if (!currSelection) return null;
20942094
const { anchorNode, anchorOffset } = currSelection;
@@ -2585,11 +2585,12 @@ export function handleFormulaInput(
25852585
if (!currSelection) return;
25862586
if (currSelection.anchorNode?.nodeName.toLowerCase() === "div") {
25872587
const editorlen = $editor.querySelectorAll("span").length;
2588-
ctx.formulaCache.functionRangeIndex = [
2589-
editorlen - 1,
2590-
$editor.querySelectorAll("span").item(editorlen - 1).textContent
2591-
?.length!,
2592-
];
2588+
if (editorlen > 0)
2589+
ctx.formulaCache.functionRangeIndex = [
2590+
editorlen - 1,
2591+
$editor.querySelectorAll("span").item(editorlen - 1).textContent
2592+
?.length!,
2593+
];
25932594
} else {
25942595
ctx.formulaCache.functionRangeIndex = [
25952596
_.indexOf(

packages/react/src/components/SheetOverlay/FormulaSearch/index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ const FormulaSearch: React.FC<React.HTMLAttributes<HTMLDivElement>> = (
1515
id="luckysheet-formula-search-c"
1616
className="luckysheet-formula-search-c"
1717
>
18-
{context.functionCandidates.map((v) => (
18+
{context.functionCandidates.map((v, index) => (
1919
<div
2020
key={v.n}
2121
data-func={v.n}
22-
className="luckysheet-formula-search-item"
22+
className={`luckysheet-formula-search-item ${
23+
index === 0 ? "luckysheet-formula-search-item-active" : ""
24+
}`}
2325
>
2426
<div className="luckysheet-formula-search-func">{v.n}</div>
2527
<div className="luckysheet-formula-search-detail">{v.d}</div>

0 commit comments

Comments
 (0)