Files
UI/packages/skin/ui/src/textField.ts
T

46 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { effect, h } from '@ui-arch/frame';
import { addonWrap } from './addons.js';
import type { TextFieldProps } from './types.js';
/*** 文本输入:value 信号双向绑定,disabled 支持布尔或信号禁用,onInput 为输入回调;prefix/suffix 包附加组,clearable 一键清空,maxCount 显示字数统计 ***/
export function textField(props: TextFieldProps): HTMLElement {
const el = h('input', { class: 'ua-input', placeholder: props.placeholder ?? '', disabled: props.disabled }) as HTMLInputElement; // false/undefined 移除属性,Signal 走响应式
if (props.value) {
const signal = props.value;
el.addEventListener('input', () => signal(el.value)); // 用户输入写回信号
effect(() => {
if (el.value !== signal()) el.value = signal(); // 外部变化写回输入框
});
}
if (props.onInput) el.addEventListener('input', () => props.onInput!(el.value));
let clearBtn: HTMLElement | null = null; // 一键清空按钮;clearable 关闭时不创建
if (props.clearable) {
clearBtn = h(
'button',
{
type: 'button',
class: 'ua-input-clear is-hidden', // 初始无值隐藏
'aria-label': '清空输入',
tabIndex: -1, // 不进 Tab 序,清空走鼠标/触屏
onClick: () => { el.value = ''; props.value?.(''); props.onInput?.(''); el.focus(); }, // 清空并同步信号与回调
},
'×',
);
const syncClear = (): void => { clearBtn!.classList.toggle('is-hidden', el.value === ''); }; // 有值才显示
el.addEventListener('input', syncClear); // 用户输入时同步
effect(() => { if (props.value) props.value(); syncClear(); }); // 外部写回时同步(读信号建依赖)
}
let counter: HTMLElement | null = null; // 字数统计块;maxCount 未传不创建
if (props.maxCount) {
el.setAttribute('maxlength', String(props.maxCount)); // 原生拦截超限输入
counter = h('span', { class: 'ua-input-count' });
const syncCount = (): void => { counter!.textContent = `${el.value.length}/${props.maxCount}`; }; // 实时 n/limit
el.addEventListener('input', syncCount); // 用户输入时同步
effect(() => { if (props.value) props.value(); syncCount(); }); // 初始与外部写回时同步(读信号建依赖)
}
const suffix = clearBtn || counter
? h('span', { class: 'ua-input-clear-group' }, clearBtn, counter, props.suffix ?? null) // 清空按钮 / 计数并入后置附加组
: props.suffix;
return addonWrap(el, props.prefix, suffix);
}