Input
ui.widgets.InputEinzeilige Eingabe für Text, E-Mail, Passwort und Suche.
BEHAVIOR CONTRACT
label, helper, error, required, schreibgeschützt, disabled, führendes Icon und IME teilen sich den vollständigen Editierkern.
RECORDED INTERACTION
Der Harness fokussiert das Feld Name und tippt echten Text.
// ── Input ──
pub fn buildInput(scope: *ui.Scope, cx: *ui.Cx) anyerror!*ui.Node {
const a = cx.allocator;
const icons = ui.assets.common;
const c = try col(cx, 12);
// ── 类型 ──
try c.appendChild(a, try label(cx, "Types"));
const n1 = try W.Input(.{ .label_text = "Name", .placeholder = "Your name", .width = 320 }).mount(scope, cx);
n1.meta.ownership.meta.test_id = "story.input.name";
try c.appendChild(a, n1);
try c.appendChild(a, try W.Input(.{ .label_text = "Email", .input_type = .email, .placeholder = "you@example.com", .width = 320 }).mount(scope, cx));
try c.appendChild(a, try W.Input(.{ .label_text = "Password", .input_type = .password, .placeholder = "••••••••", .width = 320 }).mount(scope, cx));
// ── 尺寸 ──
try c.appendChild(a, try label(cx, "Sizes (sm / md / lg)"));
inline for (.{ W.input.InputSize.sm, .md, .lg }, .{ "Small", "Medium", "Large" }) |sz, ph| {
try c.appendChild(a, try W.Input(.{ .size = sz, .placeholder = ph, .width = 320 }).mount(scope, cx));
}
// ── 带图标 / append ──
try c.appendChild(a, try label(cx, "With icon / append"));
try c.appendChild(a, try W.Input(.{ .label_text = "Search", .placeholder = "Type to search…", .leading_icon_asset = icons.search, .width = 320 }).mount(scope, cx));
try c.appendChild(a, try W.Input(.{ .label_text = "Website", .placeholder = "mysite", .append_text = ".com", .width = 320 }).mount(scope, cx));
// ── 状态:required / helper / error / readonly / disabled ──
try c.appendChild(a, try label(cx, "States"));
try c.appendChild(a, try W.Input(.{ .label_text = "Required", .placeholder = "Mandatory", .required = true, .width = 320 }).mount(scope, cx));
try c.appendChild(a, try W.Input(.{ .label_text = "With helper", .placeholder = "Username", .helper = "3–20 characters", .width = 320 }).mount(scope, cx));
try c.appendChild(a, try W.Input(.{ .label_text = "With error", .initial_value = "bad value", .error_msg = "This field is invalid", .width = 320 }).mount(scope, cx));
try c.appendChild(a, try W.Input(.{ .label_text = "Readonly", .initial_value = "Read only value", .readonly = true, .width = 320 }).mount(scope, cx));
try c.appendChild(a, try W.Input(.{ .label_text = "Disabled", .placeholder = "Cannot type", .disabled = true, .width = 320 }).mount(scope, cx));
return c;
}Der unveränderte Quellcode der Story aus dem Storybook (zenit 5f9add5+wip 2026-09-30). W steht für ui.widgets; col / row / label sind kleine Layout-Helfer des Storybooks.
InputProps
ui.widgets.Inputfn Input(props: InputProps) InputBuilderFeld
Typ
Standard
Beschreibung
initial_value?[]const u8null初始值。**只在 mount 时读取一次** —— 之后改无效。 首帧之后要写入内容,用 `mountResult()` 拿 `result.state` 再调 `setText()`(2026-07-31 新增)。
growableboolfalse—
placeholder?[]const u8null占位符
placeholder_color?Colornull占位符文本颜色覆盖
input_typeInputType.text.number.email.password.tel.text输入类型
sizeInputSize.md尺寸 (统一 ControlSize,默认 md;外框高度 = padding_y × 2 + font_size × line_height, 默认主题 xs=20 / sm=24 / md=32 / lg=40)
label_text?[]const u8null标签
helper?[]const u8null辅助文本
error_msg?[]const u8null错误信息
requiredboolfalse必填
readonlyboolfalse只读
disabledboolfalse禁用
width?f32null宽度
leading_icon_asset?svg_assets.Assetnull左侧图标
append_text?[]const u8null右侧附加文本(如计数)
append_icon_asset?svg_assets.Assetnull右侧附加图标(如 clear / eye)
embeddedboolfalse嵌入复合控件时仅保留文本编辑能力,由父控件绘制统一 shell。 Select/ComboBox 等组件使用它避免出现双层 border / focus ring。
state_id?u64null状态 ID (用于 StateStore, 如果为 null 则使用自动生成的 ID)
on_change?core.HandlerRefnull值变化回调 2026-07-31 并轨:统一 ?core.HandlerRef(用 cx.strHandlerFrom 构造以拿到文本)。
*Node
ui.widgets.Inputmount gibt *Node direkt zurück – hängen Sie es an einen Elternknoten an.