Files
workspace/code/g3soft-libs/.changeset/table-keyboard-arrows-enter.md
T
2026-10-16 17:30:17 +08:00

31 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
'@g3soft/ui': minor
---
G3Table 键盘:左右键改为「**输入框先消费、到边界才切格**」,Enter 确认并下移,并**移除 `textarea` 编辑器**。
**单击格仍直接进入编辑** —— 本组件的既有交互不变,这次调整的是键盘分工、横向移动能力与编辑器类型集合。
- **左右键:`input` 先消费,消费不了才切格**(本次最核心的变化)。判据是「输入框还能不能消费这一记按键」:
- 光标在文本中间、或**存在选区** → 归输入框(移光标 / `Shift+左右` 选文本 / 按词跳);
- **值为空**、或**光标已贴在该方向的边界**(`←` 在 0、`→` 在末尾)→ 归表格,切到相邻的**可编辑格**并继续编辑;
- 取不到 `selection`(旧内核的 `number`、焦点还没落到 input 上)→ 也算消费不了,让切格生效,避免出现「按了完全没反应」的死键。
- ⚠️ 此前左右键**无条件**归输入框,结果是编辑态里**永远无法横向换格**:改完金额想去右边那格只能按 `Tab`,而 `Tab` 会跨行回绕、还会跳过只读列,横向连改几列的手感是「跳」而不是「逐格走」。反过来一律给表格则没法改金额中间那一位 —— 按「能不能消费」分档才把两种意图都保住。
- `Shift` / `Ctrl` / `Alt` / `Meta` + 左右**永远**留给输入框(选中到边界是有效操作,按词跳是平台约定)。
- 横向移动**到行边界即停、不跨行**(跨行用 `Tab` / `Enter`):一记水平按键若把人带到下一行开头是纯粹的意外。
- `date` 编辑器按同一套判据,并在切格前显式提交手输草稿。
- **移除 `textarea` 编辑器**:行内编辑的单元格高度就是行高(默认 30px),多行编辑器在里面放不下正文 —— 要么撑着行高不齐、要么内部滚动,两种都不算「在格子里改值」。需要多行文本请用 Input 的 textarea 形态放在表单 / 弹层里。
- `TableEditor.type` 收窄为 `'text' | 'number' | 'password' | 'select' | 'checkbox' | 'date'`(**类型层面即报错**,不会静默降级);`INPUT_TYPE_MAP` 与表格样式里多行相关的分支(footer 定位、外壳 padding 归零)一并删除。
- 顺带简化了键盘语义:**上下键只有一种去向**(一律让给表格切行),不再有「多行要跨行移光标」那一档;Enter 也不再分单行 / 多行两种含义。
- **Enter = 确认 + 下移到下一行同列**(Excel / Sheets / AG Grid / Handsontable 的通行约定)。
- 旧行为是 `preventDefault` + `select()` —— **全选文本,且不提交**。它既不是浏览器行为(单行 `input` 的 Enter 原生是「提交表单 / 无动作」,**不换行**),也不是表格软件的行为,而且「确认」这个动作整个缺失:改完按回车值还没落库。
- 表尾 / 下面全是不可编辑行 → **停在原地**(不循环回表头:回车一路按到底突然跳回第一行会很意外)。
- **移格前一律显式提交**(Enter / 上下键 / 左右键到边界)。三个出口共用同一个 `commitValue`:
- 必须显式,不能依赖随之而来的失焦:移动会让编辑器 vnode 卸载,而 **DOM 元素被移除时浏览器不派发 blur**(做日期编辑器时踩过这个坑),只靠 `onBlur` 的话敲完按一下方向键值就丢了;
- 抽成一个函数是因为四个出口各写一遍已经出过事故(某个出口漏调 `notifyChange`,值落了库却没抛 `change`,「有时候会保存、有时候不会」这种最难查的分叉)。
- **IME 组合态一律不拦**:`event.isComposing || event.keyCode === 229` 时直接返回。修前在候选框上按 `Enter` 确认候选词会被当成「确认并下移」——候选词上不了屏、光标还跳到下一行;候选框里 `↑↓` 选字也会被当成切行。两个判据都要:部分浏览器在「确认候选」那一下 `isComposing` 已置回 false,只剩 `keyCode 229` 可用。
- **`Shift+上下` 必须 `stopPropagation`**:只「不主动放行」是不够的,事件照样冒泡到底座的选区导航上把格子切走 —— 表现是「想选中到开头,结果跳到了上一行」。
- 内部:`findCellBelow` 泛化为 `findAdjacentCell(..., direction)`(四向),新增 `EditableContext.moveToAdjacent`;`moveToCellBelow` 与它共用 G3Table 里同一个 `moveToAdjacentCell`,让鼠标点击 / `Tab` / `Enter` / 方向键四条路径都走「改选区 → 激活编辑」这一条链路,避免各写一套而行为分叉。
- 配套:playground 的 `table-keys-wrap` 三列改为单行(text / number / text),并去掉为其多行编辑器准备的 `row-height`;文档、`editable` 示例与 ERP 的 `table-test` 页同步。
- 单测:`editable.test.ts` 从 63 增至 86 条(新增左右键边界判据一组、四向 `findAdjacentCell` 一组、IME 组合态、`Shift+上下`、Enter 显式提交;删掉两条多行用例),table 包合计 185 条全绿;e2e 方向键一组 9 条(中间移光标 / 两个方向的边界切格 / 值为空切格 / 到行边界不跨行 / `Shift+左右` / 切格前显式提交)与 Enter 一组 2 条,断言的是**焦点真的落到相邻格**而不只是「没跳格」。