iter: d14 新增抽屉 drawer 组件
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
import { effect, h } from '@ui-arch/frame';
|
||||
import type { DrawerProps } from './types.js';
|
||||
|
||||
/*** 抽屉:open 信号驱动侧滑面板,点遮罩 / × / Esc 关闭;与 modal 的分工是不打断主视图、可从侧边保留上下文 ***/
|
||||
export function drawer(props: DrawerProps, ...children: unknown[]): HTMLElement {
|
||||
const close = (): void => {
|
||||
if (!props.open()) return; // 卫语句:已关闭不重复触发回调
|
||||
props.open(false);
|
||||
props.onClose?.();
|
||||
};
|
||||
const overlay = h('div', {
|
||||
class: () => `ua-drawer-overlay${props.open() ? ' ua-open' : ''}`,
|
||||
onClick: (e: Event) => {
|
||||
if (e.target === overlay) close(); // 卫语句:仅点遮罩本身关闭
|
||||
},
|
||||
});
|
||||
const panel = h(
|
||||
'aside',
|
||||
{
|
||||
class: `ua-drawer ua-drawer-${props.placement ?? 'right'}`,
|
||||
style: `width:${props.width ?? 320}px`,
|
||||
role: 'dialog',
|
||||
'aria-hidden': () => String(!props.open()),
|
||||
},
|
||||
h('div', { class: 'ua-drawer-head' }, h('h3', { class: 'ua-drawer-title' }, props.title), h('button', { class: 'ua-drawer-close', 'aria-label': '关闭抽屉', onClick: close }, '×')),
|
||||
h('div', { class: 'ua-drawer-body' }, ...children),
|
||||
props.footer ? h('div', { class: 'ua-drawer-foot' }, props.footer) : null,
|
||||
);
|
||||
overlay.append(panel);
|
||||
|
||||
effect(() => {
|
||||
if (!props.open()) return;
|
||||
(panel.querySelector('button, input, textarea') as HTMLElement | null)?.focus(); // 打开时聚焦首个可交互元素
|
||||
});
|
||||
document.addEventListener('keydown', (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape' && props.open()) close();
|
||||
});
|
||||
return overlay;
|
||||
}
|
||||
@@ -23,5 +23,6 @@ export { spinner } from './spinner.js';
|
||||
export { progress } from './progress.js';
|
||||
export { tabs } from './tabs.js';
|
||||
export { modal } from './modal.js';
|
||||
export { drawer } from './drawer.js';
|
||||
export { form, formItem } from './form.js';
|
||||
export { dataTable } from './dataTable.js';
|
||||
|
||||
@@ -232,6 +232,16 @@ export interface ModalProps {
|
||||
onClose?: () => void; // 关闭回调(点遮罩、× 或 Esc 触发)
|
||||
}
|
||||
|
||||
/*** 抽屉入参 ***/
|
||||
export interface DrawerProps {
|
||||
title: string; // 标题
|
||||
open: Signal<boolean>; // 开关信号:true 滑出 / false 收起
|
||||
placement?: 'left' | 'right'; // 滑出方向;缺省 right
|
||||
width?: number; // 面板宽度像素;缺省 320
|
||||
footer?: unknown; // 底部操作区内容;缺省不渲染
|
||||
onClose?: () => void; // 关闭回调(遮罩 / × / Esc 触发)
|
||||
}
|
||||
|
||||
/*** 表单校验规则:按序执行,首个失败即停止 ***/
|
||||
export interface FormRule {
|
||||
required?: boolean; // 非空校验(trim 后判定)
|
||||
|
||||
Reference in New Issue
Block a user