From 82459112721a5076e8f99d03afccd09bed517cca Mon Sep 17 00:00:00 2001 From: Mritunjay Goutam Date: Mon, 9 Mar 2026 16:07:48 +0530 Subject: [PATCH 01/13] change color for data validation --- packages/react/src/components/DataVerification/ColorPicker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react/src/components/DataVerification/ColorPicker.tsx b/packages/react/src/components/DataVerification/ColorPicker.tsx index e69311d9..c7fe66bd 100644 --- a/packages/react/src/components/DataVerification/ColorPicker.tsx +++ b/packages/react/src/components/DataVerification/ColorPicker.tsx @@ -10,7 +10,7 @@ import { export const TEXT_COLORS = [ { name: "Light Gray", value: "228, 232, 237" }, - { name: "White", value: "249, 249, 249" }, + { name: "White", value: "219, 233, 236" }, { name: "Pink", value: "244, 217, 227" }, { name: "Peach", value: "247, 229, 207" }, { name: "Blue", value: "217, 234, 244" }, From f7e1218f3a9341b5a92900c77fdacaaf72feeaa5 Mon Sep 17 00:00:00 2001 From: Mritunjay Goutam Date: Tue, 10 Mar 2026 18:45:07 +0530 Subject: [PATCH 02/13] minor changes --- packages/core/package.json | 2 +- packages/react/package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 285934a2..a4eff59d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@fileverse-dev/fortune-core", - "version": "1.3.10", + "version": "1.3.10-input", "main": "lib/index.js", "module": "es/index.js", "typings": "lib/index.d.ts", diff --git a/packages/react/package.json b/packages/react/package.json index 76d9cf0a..2dfff41e 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@fileverse-dev/fortune-react", - "version": "1.3.10", + "version": "1.3.10-input", "main": "lib/index.js", "types": "lib/index.d.ts", "module": "es/index.js", @@ -16,7 +16,7 @@ "tsc": "tsc" }, "dependencies": { - "@fileverse-dev/fortune-core": "1.3.10", + "@fileverse-dev/fortune-core": "1.3.10-input", "@fileverse/ui": "5.0.0", "@tippyjs/react": "^4.2.6", "@types/regenerator-runtime": "^0.13.6", From 0c4301ed47abde55d65e8a4cafaa2029640e6eff Mon Sep 17 00:00:00 2001 From: Mritunjay Goutam Date: Thu, 12 Mar 2026 15:14:23 +0530 Subject: [PATCH 03/13] add cmd + shift + arrow --- packages/core/package.json | 2 +- packages/core/src/events/keyboard.ts | 33 ++- packages/core/src/events/mouse.ts | 1 + packages/core/src/locale/en.ts | 3 + packages/core/src/locale/es.ts | 3 + packages/core/src/locale/hi.ts | 3 + packages/core/src/locale/zh.ts | 3 + packages/core/src/locale/zh_tw.ts | 3 + packages/core/src/modules/ConditionFormat.ts | 38 ++++ packages/core/src/types.ts | 3 + packages/react/package.json | 4 +- .../ConditionFormat/ConditionRules.tsx | 20 +- .../src/components/ConditionFormat/index.tsx | 1 + .../src/components/SheetOverlay/InputBox.tsx | 197 ++++++++++++------ 14 files changed, 235 insertions(+), 79 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index a4eff59d..7245dac4 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@fileverse-dev/fortune-core", - "version": "1.3.10-input", + "version": "1.3.10-input-1", "main": "lib/index.js", "module": "es/index.js", "typings": "lib/index.d.ts", diff --git a/packages/core/src/events/keyboard.ts b/packages/core/src/events/keyboard.ts index 254355cd..2c82fe10 100644 --- a/packages/core/src/events/keyboard.ts +++ b/packages/core/src/events/keyboard.ts @@ -155,19 +155,19 @@ function handleControlPlusArrowKey( e: KeyboardEvent, shiftPressed: boolean ) { - if (ctx.luckysheetCellUpdate.length > 0) return; + //if (ctx.luckysheetCellUpdate.length > 0) return; const idx = getSheetIndex(ctx, ctx.currentSheetId); if (_.isNil(idx)) return; const file = ctx.luckysheetfile[idx]; - if (!file || !file.row || !file.column) return; + //if (!file || !file.row || !file.column) return; const maxRow = file.row; const maxCol = file.column; let last; if (ctx.luckysheet_select_save && ctx.luckysheet_select_save.length > 0) last = ctx.luckysheet_select_save[ctx.luckysheet_select_save.length - 1]; - if (!last) return; + //if (!last) return; const currR = last.row_focus; const currC = last.column_focus; @@ -872,7 +872,29 @@ export async function handleGlobalKeyDown( kstr === "ArrowLeft" || kstr === "ArrowRight" ) { - handleArrowKey(ctx, e); + const isEditing = ctx.luckysheetCellUpdate.length > 0; + const inputText = cellInput?.innerText ?? ""; + const isFormulaEdit = isEditing && inputText.trim().startsWith("="); + const enteredByTyping = cache.enteredEditByTyping === true; + + // Only when we entered edit by typing (not double-click): arrow keys + // commit and move to next cell in that direction. + if (isEditing && !isFormulaEdit && enteredByTyping) { + updateCell( + ctx, + ctx.luckysheetCellUpdate[0], + ctx.luckysheetCellUpdate[1], + cellInput, + undefined, + canvas + ); + cache.enteredEditByTyping = false; + handleArrowKey(ctx, e); + e.preventDefault(); + } else { + // Double-click edit mode or formula: preserve existing behavior + handleArrowKey(ctx, e); + } } else if ( !( (kcode >= 112 && kcode <= 123) || @@ -907,6 +929,8 @@ export async function handleGlobalKeyDown( ctx.luckysheetCellUpdate = [row_index, col_index]; cache.overwriteCell = true; + cache.overwriteCellFirstChar = e.key; + cache.enteredEditByTyping = true; // if (kstr === "Backspace") { // $("#luckysheet-rich-text-editor").html("
"); @@ -917,6 +941,7 @@ export async function handleGlobalKeyDown( // $("#luckysheet-rich-text-editor"), // kcode // ); + e.preventDefault(); } } } diff --git a/packages/core/src/events/mouse.ts b/packages/core/src/events/mouse.ts index faa5be66..6dbf7eff 100644 --- a/packages/core/src/events/mouse.ts +++ b/packages/core/src/events/mouse.ts @@ -1437,6 +1437,7 @@ export function handleCellAreaDoubleClick( col_index = column_focus; } + globalCache.enteredEditByTyping = false; luckysheetUpdateCell(ctx, row_index, col_index); // } } diff --git a/packages/core/src/locale/en.ts b/packages/core/src/locale/en.ts index 25cb4c1c..cdb86e3a 100644 --- a/packages/core/src/locale/en.ts +++ b/packages/core/src/locale/en.ts @@ -11674,6 +11674,8 @@ export default { conditionformat_textContains: "Conditional format - Text Contains", conditionformat_textContains_title: "Format cells containing the following text", + conditionformat_empty: "Conditional format - Empty", + conditionformat_empty_title: "Format cells that are empty", conditionformat_occurrenceDate: "Conditional format - Occurrence Date", conditionformat_occurrenceDate_title: "Format cells containing the following dates", @@ -11780,6 +11782,7 @@ export default { between2: "", contain: "Contain", textContains: "Text contains", + empty: "Empty", duplicateValue: "Duplicate value", uniqueValue: "Unique value", top: "Top", diff --git a/packages/core/src/locale/es.ts b/packages/core/src/locale/es.ts index 3f04055a..06ed075b 100644 --- a/packages/core/src/locale/es.ts +++ b/packages/core/src/locale/es.ts @@ -11657,6 +11657,8 @@ export default { conditionformat_textContains: "Conditionformat-TextContains", conditionformat_textContains_title: "Dar formato a las celdas que contienen el siguiente texto", + conditionformat_empty: "Conditional format - Empty", + conditionformat_empty_title: "Dar formato a las celdas vacías", conditionformat_occurrenceDate: "Conditionformat-OccurrenceDate", conditionformat_occurrenceDate_title: "Dar formato a celdas que contienen las siguientes fechas", @@ -11768,6 +11770,7 @@ export default { between2: "", contain: "Contiene", textContains: "Texto contiene", + empty: "Vacío", duplicateValue: "Valor duplicado", uniqueValue: "Valor Unico", top: "Mejor", diff --git a/packages/core/src/locale/hi.ts b/packages/core/src/locale/hi.ts index 5891d7e0..a6140922 100644 --- a/packages/core/src/locale/hi.ts +++ b/packages/core/src/locale/hi.ts @@ -11696,6 +11696,8 @@ export default { conditionformat_textContains: "Conditionformat-TextContains", conditionformat_textContains_title: "निम्नलिखित पाठ वाली कोशिकाओं को प्रारूपित करें", + conditionformat_empty: "Conditional format - Empty", + conditionformat_empty_title: "खाली कोशिकाओं को प्रारूपित करें", conditionformat_occurrenceDate: "Conditionformat-OccurrenceDate", conditionformat_occurrenceDate_title: "निम्नलिखित तिथियों वाली कोशिकाओं को प्रारूपित करें", @@ -11806,6 +11808,7 @@ export default { between2: "", contain: "शामिल", textContains: "पाठ शामिल है", + empty: "खाली", duplicateValue: "डुप्लिकेट मान", uniqueValue: "अद्वितीय मान", top: "शीर्ष", diff --git a/packages/core/src/locale/zh.ts b/packages/core/src/locale/zh.ts index 7c5b1b40..3b7fe7f7 100644 --- a/packages/core/src/locale/zh.ts +++ b/packages/core/src/locale/zh.ts @@ -11723,6 +11723,8 @@ export default { conditionformat_equal_title: "为等于以下值的单元格设置格式", conditionformat_textContains: "条件格式——文本包含", conditionformat_textContains_title: "为包含以下文本的单元格设置格式", + conditionformat_empty: "条件格式——空值", + conditionformat_empty_title: "为空单元格设置格式", conditionformat_occurrenceDate: "条件格式——发生日期", conditionformat_occurrenceDate_title: "为包含以下日期的单元格设置格式", conditionformat_duplicateValue: "条件格式——重复值", @@ -11825,6 +11827,7 @@ export default { between2: "之间", contain: "包含", textContains: "文本包含", + empty: "空值", duplicateValue: "重复值", uniqueValue: "唯一值", top: "前", diff --git a/packages/core/src/locale/zh_tw.ts b/packages/core/src/locale/zh_tw.ts index 2197eb8d..a23bd33b 100644 --- a/packages/core/src/locale/zh_tw.ts +++ b/packages/core/src/locale/zh_tw.ts @@ -11680,6 +11680,8 @@ export default { conditionformat_equal_title: "為等於以下值的儲存格設定格式", conditionformat_textContains: "條件格式——文字包含", conditionformat_textContains_title: "為包含以下文字的儲存格設定格式", + conditionformat_empty: "條件格式——空值", + conditionformat_empty_title: "為空儲存格設定格式", conditionformat_occurrenceDate: "條件格式——發生日期", conditionformat_occurrenceDate_title: "為包含以下日期的儲存格設定格式", conditionformat_duplicateValue: "條件格式——重複值", @@ -11782,6 +11784,7 @@ export default { between2: "之間", contain: "包含", textContains: "文字包含", + empty: "空值", duplicateValue: "重複值", uniqueValue: "唯一值", top: "前", diff --git a/packages/core/src/modules/ConditionFormat.ts b/packages/core/src/modules/ConditionFormat.ts index d45fba03..d9ace972 100644 --- a/packages/core/src/modules/ConditionFormat.ts +++ b/packages/core/src/modules/ConditionFormat.ts @@ -976,6 +976,44 @@ export function compute(ctx: Context, ruleArr: any, d: CellMatrix) { } } } + } else if (conditionName === "empty") { + // Format cells that are empty (no value or blank) + for ( + let r = cellrange[s].row[0]; + r <= cellrange[s].row[1]; + r += 1 + ) { + for ( + let c = cellrange[s].column[0]; + c <= cellrange[s].column[1]; + c += 1 + ) { + const cell = _.isNil(d[r]) || _.isNil(d[r][c]) ? null : d[r][c]; + const isEmpty = + _.isNil(cell) || + _.isNil(cell.v) || + isRealNull(cell.v); + if (isEmpty) { + if (`${r}_${c}` in computeMap) { + computeMap[`${r}_${c}`].textColor = textColor; + computeMap[`${r}_${c}`].cellColor = cellColor; + computeMap[`${r}_${c}`].bold = bold; + computeMap[`${r}_${c}`].italic = italic; + computeMap[`${r}_${c}`].underline = underline; + computeMap[`${r}_${c}`].strikethrough = strikethrough; + } else { + computeMap[`${r}_${c}`] = { + textColor, + cellColor, + bold, + italic, + underline, + strikethrough, + }; + } + } + } + } } else if (conditionName === "between") { // UPDATED BETWEEN COMPARISON WITH STRING SUPPORT // 循环应用范围计算 diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 06e3354b..7136829b 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -305,6 +305,9 @@ export type GlobalCache = { verticalScrollLock?: boolean; horizontalScrollLock?: boolean; overwriteCell?: boolean; + overwriteCellFirstChar?: string; + /** True when current cell was opened for edit by typing (not double-click). Used so arrow keys commit+move only in that case. */ + enteredEditByTyping?: boolean; ignoreWriteCell?: boolean; doNotFocus?: boolean; doNotUpdateCell?: boolean; diff --git a/packages/react/package.json b/packages/react/package.json index 2dfff41e..e70e15f3 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@fileverse-dev/fortune-react", - "version": "1.3.10-input", + "version": "1.3.10-input-1", "main": "lib/index.js", "types": "lib/index.d.ts", "module": "es/index.js", @@ -16,7 +16,7 @@ "tsc": "tsc" }, "dependencies": { - "@fileverse-dev/fortune-core": "1.3.10-input", + "@fileverse-dev/fortune-core": "1.3.10-input-1", "@fileverse/ui": "5.0.0", "@tippyjs/react": "^4.2.6", "@types/regenerator-runtime": "^0.13.6", diff --git a/packages/react/src/components/ConditionFormat/ConditionRules.tsx b/packages/react/src/components/ConditionFormat/ConditionRules.tsx index dde571c7..be9c689b 100644 --- a/packages/react/src/components/ConditionFormat/ConditionRules.tsx +++ b/packages/react/src/components/ConditionFormat/ConditionRules.tsx @@ -317,6 +317,7 @@ const ConditionRules: React.FC<{ context?: any }> = ({ context }) => { { text: "between", value: "[]", label: "Between" }, { text: "equal", value: "=", label: "Equal" }, { text: "textContains", value: "()", label: "Text Contains" }, + { text: "empty", value: "", label: "Empty" }, { text: "occurrenceDate", value: conditionformat.yesterday, @@ -443,8 +444,9 @@ const ConditionRules: React.FC<{ context?: any }> = ({ context }) => { (conditionformat as any)[ allConditionFormats[key].conditionName ] - }{" "} - {allConditionFormats[key].conditionValue?.[0]} + } + {allConditionFormats[key].conditionName !== "empty" && + ` ${allConditionFormats[key].conditionValue?.[0] ?? ""}`}

= ({ context }) => {