コンテンツにスキップ

input —— 入力フィールド

入力フィールドはフォームの土台です。core/input は 4 つのことを管理します:文字数カウントの表示と計算、超過入力の切り詰め、サイズバリエーションごとのインラインスタイル、そして入力フィールドのアクセシビリティ属性パック。意図的に関与しないのは検証(それは core/form の責務)とデバウンス(それは UI 層のリアクティブな仕事)です。

  • 各端の LhInput の実装(textarea バリアントを含む:--textarea 修飾クラス)。
  • カスタム入力コントロールで同一の文字数カウントと aria 属性を再利用したい場合。
  • 使うべきでない:数値入力には core/input-number(ステップとクランプ付き)、時刻には core/time-picker、日付には core/date-picker。
import {
getWordCount,
shouldShowWordLimit,
clampString,
getInputStyle,
getInputAria,
} from '@lh-ui/share/core/input'
import type { LhInputState } from '@lh-ui/share/core/input'

getWordCount の 2 つの境界はどちらも実際のクロスプラットフォームの差異に由来します:

  • value が undefined のときカウントは 0 にフォールバックします——React / uniapp ではマウント前に制御付きの値が一時的に undefined になることがあり、undefined.length はそのままクラッシュします。
  • maxlength が undefined のとき上限表示は 'undefined' ではなく ∞ になります。この記号により「上限が設定されていない」ことが視覚的に明確になり、バグのように見えるのを防ぎます。

getInputStyle のサイズスタイルはクラス名ではなくインラインです:lh-ui の入力フィールドは ConfigProvider のグローバルサイズをサポートしますが、グローバルサイズの切り替えでクラス名を再計算する必要はありません——インラインスタイルが props に合わせて再計算されるだけです。ここでのサイズマッピングはボタンとは異なり(ボタンはクラス名を使う)、各コンポーネントの歴史的な進化の結果です。

関数 シグネチャ 戻り値 役割
getWordCount (state: Pick<LhInputState, 'value' | 'maxlength'>) => string "使用量/上限" 文字数カウント文字列
shouldShowWordLimit (state: Pick<LhInputState, 'maxlength' | 'minlength'>) => boolean 真偽値 maxlength または minlength を設定すればカウントを表示
clampString (value: string, maxlength?: number) => string 文字列 超過分を切り詰め
getInputStyle (size: string) => Record<string, string> インラインスタイル サイズバリエーションで padding / 字サイズをマッピング
getInputAria (options: { label?: string; describedby?: string; invalid?: boolean; required?: boolean }) => LhAriaAttrs aria 属性パック 必要に応じて 4 属性を出力

getInputStyle のバリエーションマッピング:mini は padding 4px 8px / 字サイズ 12、small は 6px 10px / 12、medium は 8px 12px / 14、large は 12px 16px / 16;未知の size は medium にフォールバックします。

export interface LhInputState {
value: string
size: LhComponentSize
maxlength: number | undefined
minlength: number | undefined
}

getInputAria の 4 つの属性はすべて必要に応じて掛けられます(真値のときのみ出力し、偽値のときはキーを出現させません):

getInputAria({ label: 'ユーザー名', required: true })
// { 'aria-label': 'ユーザー名', 'aria-required': true }
getInputAria({ invalid: true, describedby: 'lh-form-error-username' })
// { 'aria-invalid': true, 'aria-describedby': 'lh-form-error-username' }

core/form との連動が重要な使い方です:LhFormItem がエラーメッセージ要素をレンダリングし(id は getFormFieldErrorId(prop) が生成)、その id を describedby 経由で渡すと、スクリーンリーダーが「無効な入力、エラーは……」と読み上げます。form を参照してください。

import { getWordCount, clampString, getInputAria } from '@lh-ui/share/core/input'
getWordCount({ value: 'hello', maxlength: 10 }) // '5/10'
getWordCount({ value: 'hello', maxlength: undefined }) // '5/∞'
getWordCount({ value: undefined, maxlength: 10 }) // '0/10'
clampString('abcdef', 3) // 'abc'
clampString('abcdef') // 'abcdef'(上限なしはそのまま返す)
getInputAria({ label: '検索' }) // { 'aria-label': '検索' }
<!-- Vue3 -->
<div :class="['lh-input', `lh-input--${size}`, { 'lh-input--textarea': type === 'textarea' }]">
<div class="lh-input__wrapper">
<input
class="lh-input__inner"
:style="getInputStyle(size)"
v-bind="getInputAria({ label, describedby, invalid: !!error, required })"
/>
</div>
<span v-if="shouldShowWordLimit({ maxlength, minlength })" class="lh-input__count">
{{ getWordCount({ value, maxlength }) }}
</span>
</div>
// React
const aria = getInputAria({ label, describedby, invalid: !!error, required })
return (
<div className={`lh-input lh-input--${size}`}>
<div className="lh-input__wrapper">
<input className="lh-input__inner" style={getInputStyle(size)} {...aria} />
</div>
</div>
)
// uniapp:<input> は内蔵コンポーネントで、class と style のバインドを両方サポート;
// textarea には <textarea> コンポーネントを使い、文字数カウントは非 h5 端ではコンポーネント組み込みの count 属性が引き受ける
クラス名 意味
.lh-input 基底クラス
.lh-input--{mini|small|medium|large} サイズのバリエーション
.lh-input--textarea textarea バリアント
.lh-input--disabled / .lh-input--prefix / .lh-input--suffix 状態とスロット
.lh-input__wrapper ラッパー(ボーダー、フォーカス状態)
.lh-input__wrapper--focused / --disabled / --has-label ラッパーの状態
.lh-input__inner ネイティブな入力要素
.lh-input__label / --float フローティングラベル(material 風)
.lh-input__prefix / __suffix 前 / 後のスロット(アイコン、ボタン)
.lh-input__clear / __count クリアボタン / 文字数カウント

フォーカス時のボーダー色は var(--lh-primary-color)、エラー状態は var(--lh-danger-color) です。

  • --has-label の非対称な padding:フローティングラベルを伴うとき padding-top は 16px になります(ラベルのために場所を空ける)が、それ以外のバリエーションは対称です。これは「高度トークン専用」に記録された統一待ち項目です。
  • コントロールの高さが不統一:input 37px / select 32px / cascader 27→32px など。根本原因は var.scss に --lh-control-height-* トークンがないことです(同上、今後の changeset で対応予定)。
  • maxlength の「文字」のセマンティクス:clampString は slice を使い、UTF-16 コード単位でカウントします;emoji の補助平面文字は 2 とカウントされます。コードポイント単位でカウントしたい場合は UI 層で別途処理してください。
  • getInputStyle の戻り値で sx を上書きしないでください——sx のほうが優先度が高く、両者は上書きではなくマージすべきです。
@lh-ui/share/core/input → getWordCount( )
返回值
(填好参数后点运行)

Copyright © 2024-2026 FengMo WenXue