diff --git a/.ua/index.json b/.ua/index.json index e4c6428..342f784 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-26T11:15:10.295Z", + "generatedAt": "2026-10-26T11:16:26.554Z", "repoRoot": ".", "packages": [ { @@ -1547,6 +1547,11 @@ "t": "(value: number) => void", "k": 1, "d": "评分变化回调" + }, + { + "n": "allowClear", + "t": "boolean", + "d": "允许清除:再次点击当前分值(半星须精确相等)清零;缺省不可清" } ], "example": "const score = signal(0); rate({ value: score, max: 5, onChange: (v) => console.log(v) })", diff --git a/llms-full.txt b/llms-full.txt index 4eda94e..32668db 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-26T11:15:10.295Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-26T11:16:26.554Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手 @@ -763,6 +763,7 @@ const step = signal(1); stepper({ steps: [{ label: '下单' }, { label: '支付' - allowHalf(默认 false):boolean —— 允许半星:点击星标左半区记 0.5 分,键盘步进同为 0.5;缺省整数 - disabled:boolean | Signal —— 禁用态:布尔直接置位,传信号则动态同步 - onChange(回调):(value: number) => void —— 评分变化回调 +- allowClear:boolean —— 允许清除:再次点击当前分值(半星须精确相等)清零;缺省不可清 示例: diff --git a/packages/skin/ui/src/rate.ts b/packages/skin/ui/src/rate.ts index ec9fae5..2f4f8f9 100644 --- a/packages/skin/ui/src/rate.ts +++ b/packages/skin/ui/src/rate.ts @@ -1,13 +1,13 @@ import { effect, h, signal } from '@ui-arch/frame'; import type { RateProps } from './types.js'; -/*** 评分:星标点选(allowHalf 可记半星),hover 预览移出还原,键盘 ←→/↑↓ 调节,value 信号双向绑定 ***/ +/*** 评分:星标点选(allowHalf 可记半星,allowClear 再点当前分清零),hover 预览移出还原,键盘 ←→/↑↓ 调节,value 信号双向绑定 ***/ export function rate(props: RateProps): HTMLDivElement { const value = props.value; const max = props.max ?? 5; // 星标总数缺省 5 const step = props.allowHalf ? 0.5 : 1; // 半星模式步进 0.5 const hover = signal(0); // 预览值(1 基,0 表示无预览) - const emit = (v: number): void => { const n = Math.round(Math.min(max, Math.max(1, v)) * 2) / 2; const q = props.allowHalf ? n : Math.round(n); value(q); if (props.onChange) props.onChange(q); }; // 写回信号并回调(半星按 0.5 量化) + const emit = (v: number, allowZero = false): void => { const n = Math.round(Math.min(max, Math.max(allowZero ? 0 : 1, v)) * 2) / 2; const q = props.allowHalf ? n : Math.round(n); value(q); if (props.onChange) props.onChange(q); }; // 写回信号并回调(半星按 0.5 量化;清零仅在 allowZero 时放行) /*** 计算星标命中值:allowHalf 时左半区记 0.5 分 ***/ const hitOf = (e: MouseEvent, i: number): number => props.allowHalf && e.offsetX < (e.currentTarget as HTMLElement).offsetWidth / 2 ? i - 0.5 : i; @@ -29,11 +29,11 @@ export function rate(props: RateProps): HTMLDivElement { type: 'button', disabled: props.disabled, 'aria-label': `${i} 星`, - onClick: (e: MouseEvent) => emit(hitOf(e, i)), + onClick: (e: MouseEvent) => { const hit = hitOf(e, i); if (props.allowClear && hit === value()) emit(0, true); else emit(hit); }, // 再点当前分清零(allowClear) onMouseMove: (e: MouseEvent) => hover(hitOf(e, i)), // 半星模式下按悬停位置细分预览 }, '★')); } - const node = h('div', { class: 'ua-rate', role: 'slider', tabindex: '0', 'aria-label': '评分', 'aria-valuemin': 1, 'aria-valuemax': max, 'aria-valuenow': value(), onMouseLeave: () => hover(0) }, ...stars) as HTMLDivElement; + const node = h('div', { class: 'ua-rate', role: 'slider', tabindex: '0', 'aria-label': '评分', 'aria-valuemin': props.allowClear ? 0 : 1, 'aria-valuemax': max, 'aria-valuenow': value(), onMouseLeave: () => hover(0) }, ...stars) as HTMLDivElement; node.addEventListener('keydown', keyNav); // 每次渲染都挂:节点被替换后键盘仍可用 return node; }; diff --git a/packages/skin/ui/src/types.ts b/packages/skin/ui/src/types.ts index 8687c1e..395d90f 100644 --- a/packages/skin/ui/src/types.ts +++ b/packages/skin/ui/src/types.ts @@ -240,6 +240,7 @@ export interface RateProps { value: Signal; // 当前评分(1 基,allowHalf 时 0.5 步进),双向绑定(点击/键盘写回、外部赋值同步) max?: number; // 星标总数;缺省 5 allowHalf?: boolean; // 允许半星:点击左半区记 0.5 分,键盘步进同为 0.5;缺省整数 + allowClear?: boolean; // 允许清除:再次点击当前分值清零;缺省不可清 disabled?: boolean | Signal; // 禁用态:布尔直接置位,传信号则动态同步 onChange?: (value: number) => void; // 评分变化回调 } diff --git a/packages/skin/ui/ua.manifest.json b/packages/skin/ui/ua.manifest.json index 774fd11..8a5103d 100644 --- a/packages/skin/ui/ua.manifest.json +++ b/packages/skin/ui/ua.manifest.json @@ -1418,6 +1418,11 @@ "t": "(value: number) => void", "k": 1, "d": "评分变化回调" + }, + { + "n": "allowClear", + "t": "boolean", + "d": "允许清除:再次点击当前分值(半星须精确相等)清零;缺省不可清" } ], "example": "const score = signal(0); rate({ value: score, max: 5, onChange: (v) => console.log(v) })",