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

5.2 KiB
Raw Blame History

@g3soft/ui
@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 条,断言的是焦点真的落到相邻格而不只是「没跳格」。