From 5bc854b939f90b2b925b0301dbf2c5aeabe337ed Mon Sep 17 00:00:00 2001 From: HIsheR Date: Mon, 26 Oct 2026 19:13:52 +0800 Subject: [PATCH] =?UTF-8?q?iter(g204):=20textarea=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E8=87=AA=E9=80=82=E5=BA=94=E9=AB=98=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .ua/index.json | 7 ++++++- llms-full.txt | 3 ++- packages/skin/ui/src/textarea.ts | 19 +++++++++++++++++++ packages/skin/ui/src/types.ts | 1 + packages/skin/ui/ua.manifest.json | 7 ++++++- 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/.ua/index.json b/.ua/index.json index 2cfe94f..155cf3c 100644 --- a/.ua/index.json +++ b/.ua/index.json @@ -1,6 +1,6 @@ { "$schema": "ui-arch-registry-index/0.1", - "generatedAt": "2026-10-26T09:56:49.160Z", + "generatedAt": "2026-10-26T11:13:22.375Z", "repoRoot": ".", "packages": [ { @@ -535,6 +535,11 @@ "n": "maxCount", "t": "number", "d": "字数上限:同时设原生 maxlength,并在下方附加块显示实时计数;缺省不限" + }, + { + "n": "autosize", + "t": "boolean | { minRows?, maxRows? }", + "d": "自适应内容高度:true 跟随内容涨落,对象态钳最小/最大行数,超出 maxRows 内部滚动;缺省固定行数" } ], "example": "const bio = signal(''); textarea({ value: bio, rows: 4, placeholder: '一句话介绍…' })", diff --git a/llms-full.txt b/llms-full.txt index f71525a..e65cba6 100644 --- a/llms-full.txt +++ b/llms-full.txt @@ -1,6 +1,6 @@ # @ui-arch 组件库 Agent 文档(无图形版) -> 自动生成于 2026-10-26T09:56:49.160Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 +> 自动生成于 2026-10-26T11:13:22.375Z,数据源:各包 ua.manifest.json,勿手改。人类版文档站:apps/docs/index.html。 > 组件 = 普通函数,传 props 返回 DOM;状态用 signal 双向绑定:读 signal() 写 signal(v)。 ## 快速上手 @@ -177,6 +177,7 @@ const qty = signal(1); const el = inputNumber({ value: qty, min: 1, max: 99, onC - prefix:string | HTMLElement —— 前置附加块(textField/inputNumber 在输入框内侧前、textarea 在上方);缺省不渲染 - suffix:string | HTMLElement —— 后置附加块(textField/inputNumber 在输入框内侧后、textarea 在下方);缺省不渲染 - maxCount:number —— 字数上限:同时设原生 maxlength,并在下方附加块显示实时计数;缺省不限 +- autosize:boolean | { minRows?, maxRows? } —— 自适应内容高度:true 跟随内容涨落,对象态钳最小/最大行数,超出 maxRows 内部滚动;缺省固定行数 示例: diff --git a/packages/skin/ui/src/textarea.ts b/packages/skin/ui/src/textarea.ts index ff06132..8244c33 100644 --- a/packages/skin/ui/src/textarea.ts +++ b/packages/skin/ui/src/textarea.ts @@ -22,5 +22,24 @@ export function textarea(props: TextareaProps): HTMLElement { effect(() => { if (props.value) props.value(); syncCount(); }); // 初始与外部写回时同步(读信号建依赖) } const suffix = counter ? h('span', { class: 'ua-textarea-count-group' }, counter, props.suffix ?? null) : props.suffix; // 计数并入下方附加组 + if (props.autosize) { + const cfg = props.autosize === true ? {} : props.autosize; // 对象态带行数钳制 + const frame = (): void => { // 量高与钳制共用一帧:行高/内距从 computed style 推导,零硬编码 + const cs = getComputedStyle(el); + const lh = parseFloat(cs.lineHeight) || parseFloat(cs.fontSize) * 1.5; // line-height 为 normal 时按 1.5 倍字号退化 + const extra = parseFloat(cs.paddingTop) + parseFloat(cs.paddingBottom) + parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth); // 盒模型补偿:scrollHeight 不含边框 + if (cfg.minRows) el.style.minHeight = `${lh * cfg.minRows + extra}px`; + if (cfg.maxRows) { + el.style.maxHeight = `${lh * cfg.maxRows + extra}px`; + el.style.overflowY = 'auto'; // 超 maxRows 转内部滚动 + } + el.style.height = 'auto'; // 先复位再量,scrollHeight 才是内容真实高度 + el.style.height = `${el.scrollHeight}px`; + }; + el.style.resize = 'none'; // 高度交给自适应,手动拖拽失去意义 + el.addEventListener('input', frame); // 输入即重算 + effect(() => { if (props.value) props.value(); frame(); }); // 外部写回信号也重算 + frame(); // 初始按当前内容定高 + } return addonWrap(el, props.prefix, suffix, true); } diff --git a/packages/skin/ui/src/types.ts b/packages/skin/ui/src/types.ts index d27eca0..ac11465 100644 --- a/packages/skin/ui/src/types.ts +++ b/packages/skin/ui/src/types.ts @@ -202,6 +202,7 @@ export interface TextareaProps { prefix?: string | HTMLElement; // 上方附加块(如标题、计数说明);缺省不渲染 suffix?: string | HTMLElement; // 下方附加块(如字数提示);缺省不渲染 maxCount?: number; // 字数上限;传了即设原生 maxlength 并在下方显示实时计数 + autosize?: boolean | { minRows?: number; maxRows?: number }; // 自适应内容高度:true 跟随内容涨落,对象态钳最小/最大行数,超限内部滚动 } /*** 数字输入入参 ***/ diff --git a/packages/skin/ui/ua.manifest.json b/packages/skin/ui/ua.manifest.json index 5e0c965..6dd5afb 100644 --- a/packages/skin/ui/ua.manifest.json +++ b/packages/skin/ui/ua.manifest.json @@ -406,6 +406,11 @@ "n": "maxCount", "t": "number", "d": "字数上限:同时设原生 maxlength,并在下方附加块显示实时计数;缺省不限" + }, + { + "n": "autosize", + "t": "boolean | { minRows?, maxRows? }", + "d": "自适应内容高度:true 跟随内容涨落,对象态钳最小/最大行数,超出 maxRows 内部滚动;缺省固定行数" } ], "example": "const bio = signal(''); textarea({ value: bio, rows: 4, placeholder: '一句话介绍…' })", @@ -3628,4 +3633,4 @@ } ] } -} +} \ No newline at end of file