diff --git a/.ua/index.json b/.ua/index.json index 8ff7e1f..268c385 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-26T11:17:54.464Z", + "generatedAt": "2026-10-26T11:20:15.456Z", "repoRoot": ".", "packages": [ { @@ -3132,6 +3132,11 @@ "n": "onChange", "t": "(values: string[]) => void", "d": "变更回调(传副本)" + }, + { + "n": "clearable", + "t": "boolean", + "d": "开启后有选中值时在右缘显示一键清空按钮;缺省不渲染" } ], "example": "multiSelect({ value: tagPick, max: 3, placeholder: '选择技术栈', options: [{ value: 'ts', label: 'TypeScript' }, { value: 'css', label: 'CSS 令牌' }] })", diff --git a/llms-full.txt b/llms-full.txt index 6737ac1..1fd58dc 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-26T11:17:54.464Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-26T11:20:15.456Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手 @@ -1629,6 +1629,7 @@ affix({ offset: 8 }, card({ title: '滚动时我会贴顶' }, h('p', null, '正 - searchable:boolean —— 是否可输入过滤;缺省 true - disabled:boolean | Signal —— 禁用整个下拉 - onChange:(values: string[]) => void —— 变更回调(传副本) +- clearable:boolean —— 开启后有选中值时在右缘显示一键清空按钮;缺省不渲染 示例: diff --git a/packages/skin/ui/src/multiSelect.ts b/packages/skin/ui/src/multiSelect.ts index 6d45456..2e2aa12 100644 --- a/packages/skin/ui/src/multiSelect.ts +++ b/packages/skin/ui/src/multiSelect.ts @@ -54,7 +54,9 @@ export function multiSelect(props: MultiSelectProps): HTMLElement { box.append(tagWrap, input); // 标签区在前、输入框在后,横向排布 const list = h('ul', { class: 'ua-multiselect-list', role: 'listbox', 'aria-multiselectable': 'true' }) as HTMLElement; const pop = h('div', { class: () => `ua-multiselect-pop${open() ? ' ua-open' : ''}${place() === 'top' ? ' is-flip' : ''}` }, list) as HTMLElement; - const root = h('div', { class: () => `ua-multiselect${open() ? ' ua-open' : ''}` }, box, pop) as HTMLElement; + const clearBtn = h('button', { type: 'button', class: 'ua-select-clear', 'aria-label': '清空所选', hidden: true, onClick: (e: Event) => { e.stopPropagation(); update([]); input.focus(); } }, '×') as HTMLElement; // 复用 select 清空钮样式;阻止冒泡免得清完又展开 + const root = h('div', { class: () => `ua-multiselect${open() ? ' ua-open' : ''}` }, box, props.clearable ? clearBtn : null, pop) as HTMLElement; + effect(() => { clearBtn.hidden = !value().length; }); // 有值才显示(clearable 未开时按钮根本不挂载) /*** 重绘标签区与候选:标签带删除钮,候选带勾选态与禁用态 ***/ const render = (): void => { diff --git a/packages/skin/ui/src/types.ts b/packages/skin/ui/src/types.ts index cf267a9..113cad8 100644 --- a/packages/skin/ui/src/types.ts +++ b/packages/skin/ui/src/types.ts @@ -732,6 +732,7 @@ export interface MultiSelectProps { max?: number; // 最多选几项:到上限后未选项禁用 maxTagCount?: number; // 标签区最多显示几个,超出折成「+N」;缺省全显示 searchable?: boolean; // 是否可输入过滤;缺省 true + clearable?: boolean; // 开启后有选中值时显示一键清空按钮;缺省不渲染 disabled?: boolean | Signal; // 禁用整个下拉 onChange?: (values: string[]) => void; // 变更回调(传副本) } diff --git a/packages/skin/ui/ua.manifest.json b/packages/skin/ui/ua.manifest.json index e584b96..205d78d 100644 --- a/packages/skin/ui/ua.manifest.json +++ b/packages/skin/ui/ua.manifest.json @@ -3003,6 +3003,11 @@ "n": "onChange", "t": "(values: string[]) => void", "d": "变更回调(传副本)" + }, + { + "n": "clearable", + "t": "boolean", + "d": "开启后有选中值时在右缘显示一键清空按钮;缺省不渲染" } ], "example": "multiSelect({ value: tagPick, max: 3, placeholder: '选择技术栈', options: [{ value: 'ts', label: 'TypeScript' }, { value: 'css', label: 'CSS 令牌' }] })", diff --git a/packages/skin/ui/ui.css b/packages/skin/ui/ui.css index 3920a5a..0cbc3c2 100644 --- a/packages/skin/ui/ui.css +++ b/packages/skin/ui/ui.css @@ -3875,6 +3875,10 @@ button.ua-step-dot:hover { display: inline-block; min-width: 240px; } +/* 多选清空钮:复用 select 清空钮样式,右缘内收一档贴合标签区(select 的 24px 是给箭头让位) */ +.ua-multiselect .ua-select-clear { + right: var(--ua-space-2); +} .ua-multiselect-box { display: flex; flex-wrap: wrap;