iter: d26 select 键盘导航(↑↓ 环形移动、Home/End、Esc 回焦触发器)
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "ui-arch-registry-index/0.1",
|
"$schema": "ui-arch-registry-index/0.1",
|
||||||
"generatedAt": "2026-10-23T09:06:10.925Z",
|
"generatedAt": "2026-10-23T09:08:47.698Z",
|
||||||
"repoRoot": ".",
|
"repoRoot": ".",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { effect, h, signal } from '@ui-arch/frame';
|
import { effect, h, signal } from '@ui-arch/frame';
|
||||||
import type { SelectProps } from './types.js';
|
import type { SelectProps } from './types.js';
|
||||||
|
|
||||||
/*** 下拉选择:自绘弹层替代原生 select,value 信号双向绑定;点选项 / 点外部 / Esc 关闭 ***/
|
/*** 下拉选择:自绘弹层替代原生 select,value 信号双向绑定;支持 ↑↓/Home/End 键盘导航,点选项 / 点外部 / Esc 关闭 ***/
|
||||||
export function select(props: SelectProps): HTMLElement {
|
export function select(props: SelectProps): HTMLElement {
|
||||||
// —— 状态集中声明 ——
|
// —— 状态集中声明 ——
|
||||||
const open = signal(false); // 弹层开合
|
const open = signal(false); // 弹层开合
|
||||||
@@ -50,7 +50,18 @@ export function select(props: SelectProps): HTMLElement {
|
|||||||
const root = h('div', { class: () => `ua-select${open() ? ' ua-open' : ''}` }, trigger, pop); // 根带开合类,供箭头旋转
|
const root = h('div', { class: () => `ua-select${open() ? ' ua-open' : ''}` }, trigger, pop); // 根带开合类,供箭头旋转
|
||||||
|
|
||||||
root.addEventListener('keydown', (e: KeyboardEvent) => {
|
root.addEventListener('keydown', (e: KeyboardEvent) => {
|
||||||
if (e.key === 'Escape') open(false); // Esc 关闭弹层
|
if (e.key === 'Escape') { open(false); trigger.focus(); return; } // Esc 关闭并回焦触发器
|
||||||
|
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
||||||
|
e.preventDefault(); // 阻止页面滚动
|
||||||
|
if (!open()) { open(true); options[0]?.focus(); return; } // 未展开:展开并聚焦首个选项
|
||||||
|
const idx = options.indexOf(document.activeElement as HTMLElement); // 展开中:在选项间环形移动
|
||||||
|
const dir = e.key === 'ArrowDown' ? 1 : -1;
|
||||||
|
const next = (idx + dir + options.length) % options.length;
|
||||||
|
options[next]?.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.key === 'Home' && open()) { e.preventDefault(); options[0]?.focus(); return; } // Home 跳首项
|
||||||
|
if (e.key === 'End' && open()) { e.preventDefault(); options[options.length - 1]?.focus(); } // End 跳末项
|
||||||
});
|
});
|
||||||
document.addEventListener('click', (e) => {
|
document.addEventListener('click', (e) => {
|
||||||
if (root.contains(e.target as Node)) return; // 卫语句:组件内点击不处理
|
if (root.contains(e.target as Node)) return; // 卫语句:组件内点击不处理
|
||||||
|
|||||||
Reference in New Issue
Block a user