한 줄 텍스트를 입력받고 Field의 레이블·설명·오류 상태와 조합하는 컴포넌트입니다.
import "./styles" ;
import { root } from "@lynx-js/react" ;
import { Field, TextField, VStack, useSeedClassName } from "@seed-design/lynx-react" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" gap = "x4" >
< Field.Root className = "text-field-input-preview__content" >
< Field.Header >
< Field.Label >제목</ Field.Label >
</ Field.Header >
< TextField.Root >
< TextField.Input
accessibility-label = "제목"
maxlength = { 100 }
placeholder = "제목을 입력해 주세요"
/>
</ TextField.Root >
< Field.Footer >
< Field.Description >한 줄로 제목을 입력해 주세요.</ Field.Description >
</ Field.Footer >
</ Field.Root >
</ VStack >
</ page >
);
}
root. render (< Root />);
npx @seed-design/cli add ui:text-field pnpm dlx @seed-design/cli add ui:text-field yarn dlx @seed-design/cli add ui:text-field bun x @seed-design/cli add ui:text-field
의존성 설치
npm install @seed-design/lynx-react yarn add @seed-design/lynx-react pnpm add @seed-design/lynx-react bun add @seed-design/lynx-react 아래 코드를 복사 후 붙여넣고 사용하세요 /**
* @file ui:text-field
* @requires @seed-design/lynx-react@>=0.1.0 <1.0.0
* @requires @seed-design/lynx-css@>=0.1.0 <1.0.0
**/
import * as React from "@lynx-js/react" ;
import {
Field as SeedField,
TextField as SeedTextField,
type UseTextFieldWithGraphemesParams,
useTextFieldWithGraphemes,
} from "@seed-design/lynx-react" ;
type TextFieldRootRef = React . ComponentRef < typeof SeedTextField.Root>;
type FieldRootRef = React . ComponentRef < typeof SeedField.Root>;
export interface TextFieldProps
extends Omit < SeedTextField . RootProps , "children" | "onValueChange" > {
children ?: React . ReactNode ;
label ?: React . ReactNode ;
labelWeight ?: SeedField . LabelProps [ "weight" ];
indicator ?: React . ReactNode ;
prefixIcon ?: SeedTextField . PrefixIconProps [ "icon" ];
prefix ?: React . ReactNode ;
suffixIcon ?: SeedTextField . SuffixIconProps [ "icon" ];
suffix ?: React . ReactNode ;
description ?: React . ReactNode ;
errorMessage ?: React . ReactNode ;
hideCharacterCount ?: boolean ;
maxGraphemeCount ?: number ;
showRequiredIndicator ?: boolean ;
fieldRef ?: React . Ref < FieldRootRef >;
onValueChange ?: UseTextFieldWithGraphemesParams [ "onValueChange" ];
}
/**
* @see https://seed-design.io/lynx/components/text-field-input
*/
export const TextField = React. forwardRef < TextFieldRootRef , TextFieldProps >(
(
{
children,
label,
labelWeight,
indicator,
prefixIcon,
prefix,
suffixIcon,
suffix,
description,
errorMessage,
hideCharacterCount,
maxGraphemeCount,
showRequiredIndicator,
fieldRef,
value,
defaultValue,
onValueChange,
required,
disabled,
invalid,
readOnly,
name,
... rootProps
},
ref,
) => {
const { textFieldRootProps , counterProps } = useTextFieldWithGraphemes ({
value,
defaultValue,
onValueChange,
maxGraphemeCount,
});
const renderHeader = label != null || indicator != null ;
const renderDescription = description != null && ! (invalid && errorMessage != null );
const renderErrorMessage = invalid && errorMessage != null ;
const renderCharacterCount = ! hideCharacterCount && maxGraphemeCount !== undefined ;
const renderFooter = renderDescription || renderErrorMessage || renderCharacterCount;
return (
< SeedField.Root
ref = {fieldRef}
required = {required}
disabled = {disabled}
invalid = {invalid}
readOnly = {readOnly}
>
{renderHeader ? (
< SeedField.Header >
< SeedField.Label weight = {labelWeight}>
{label}
{showRequiredIndicator ? < SeedField.RequiredIndicator /> : null }
{indicator != null ? (
< SeedField.IndicatorText >{indicator}</ SeedField.IndicatorText >
) : null }
</ SeedField.Label >
</ SeedField.Header >
) : null }
< SeedTextField.Root ref = {ref} name = {name} { ... rootProps} { ... textFieldRootProps}>
{prefixIcon ? < SeedTextField.PrefixIcon icon = {prefixIcon} /> : null }
{prefix != null ? < SeedTextField.PrefixText >{prefix}</ SeedTextField.PrefixText > : null }
{children}
{suffix != null ? < SeedTextField.SuffixText >{suffix}</ SeedTextField.SuffixText > : null }
{suffixIcon ? < SeedTextField.SuffixIcon icon = {suffixIcon} /> : null }
</ SeedTextField.Root >
{renderFooter ? (
< SeedField.Footer >
{renderDescription ? (
< SeedField.Description >{description}</ SeedField.Description >
) : null }
{renderErrorMessage ? (
< SeedField.ErrorMessage >{errorMessage}</ SeedField.ErrorMessage >
) : null }
{renderCharacterCount ? < SeedField.CharacterCount { ... counterProps} /> : null }
</ SeedField.Footer >
) : null }
</ SeedField.Root >
);
},
);
TextField.displayName = "TextField" ;
export interface TextFieldInputProps extends SeedTextField . InputProps {}
/**
* @see https://seed-design.io/lynx/components/text-field-input
*/
export const TextFieldInput = SeedTextField.Input;
export interface TextFieldTextareaProps extends SeedTextField . TextareaProps {}
/**
* @see https://seed-design.io/lynx/components/text-field-textarea
*/
export const TextFieldTextarea = SeedTextField.Textarea;
/**
* This file is a snippet from SEED Design, helping you get started quickly with @seed-design/* packages.
* You can extend this snippet however you want.
*/
children?React.ReactNode
label?React.ReactNode
labelWeight?"medium" | "bold" | undefined
indicator?React.ReactNode
prefixIcon?React.ReactElement < LynxIconElementProps, string | React.JSXElementConstructor < any >> | undefined
prefix?React.ReactNode
suffixIcon?React.ReactElement < LynxIconElementProps, string | React.JSXElementConstructor < any >> | undefined
suffix?React.ReactNode
description?React.ReactNode
errorMessage?React.ReactNode
hideCharacterCount?boolean | undefined
maxGraphemeCount?number | undefined
showRequiredIndicator?boolean | undefined
fieldRef?React.Ref < NodesRef > | undefined
onValueChange?(( values : { value : string ; graphemes : string []; slicedValue : string ; slicedGraphemes : string []; }) => void ) | undefined
variant?"outline" | "underline" | undefined
size?"medium" | "large" | undefined
invalid?boolean | undefined
readOnly?boolean | undefined
disabled?boolean | undefined
value?string | undefined
defaultValue?string | undefined
required?boolean | undefined
name?string | undefined
style?CSSProperties | undefined
className?string | undefined
placeholder?string | undefined
confirm-type?"send" | "search" | "go" | "done" | "next" | undefined
maxlength?number | undefined
readonly?boolean | undefined
disabled?boolean | undefined
input-filter?string | undefined
type?"number" | "text" | "digit" | "password" | "tel" | "email" | undefined
ios-auto-correct?boolean | undefined
ios-spell-check?boolean | undefined
android-fullscreen-mode?boolean | undefined
bindfocus?(( e : BaseEvent < "bindfocus" , InputFocusEvent >) => void ) | undefined
bindblur?(( e : BaseEvent < "bindblur" , InputBlurEvent >) => void ) | undefined
bindconfirm?(( e : BaseEvent < "bindconfirm" , InputConfirmEvent >) => void ) | undefined
bindinput?(( e : BaseEvent < "bindinput" , InputInputEvent >) => void ) | undefined
bindselection?(( e : BaseEvent < "bindselection" , InputSelectionEvent >) => void ) | undefined
id?string | undefined
name?string | undefined
hidden?boolean | undefined
flatten?boolean | undefined
focusable?boolean | undefined
bindlayoutchange?EventHandler < LayoutChangeDetailEvent < Target >> | undefined
main-thread:bindlayoutchange?EventHandler < LayoutChangeDetailEvent < Element >> | undefined
style?CSSProperties | undefined
className?string | undefined
import "./styles" ;
import { root } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" >
< TextField label = "라벨" description = "설명을 써주세요" >
< TextFieldInput accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
import "./styles" ;
import { root } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" >
< TextField label = "라벨" description = "설명을 써주세요" disabled >
< TextFieldInput accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
import "./styles" ;
import { root } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" >
< TextField
label = "라벨"
description = "설명을 써주세요"
defaultValue = "수정할 수 없는 값"
readOnly
>
< TextFieldInput accessibility-label = "라벨" />
</ TextField >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
size로 TextField의 크기를 정합니다. (default: large)
Lynx에서는 large와 medium을 지원합니다. CSS viewport breakpoint가 없어 responsive는 지원하지 않습니다.
import "./styles" ;
import { root } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" gap = "spacingY.componentDefault" >
< TextField label = "라벨" description = "size=large (default)" size = "large" >
< TextFieldInput accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
< TextField label = "라벨" description = "size=medium" size = "medium" >
< TextFieldInput accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
< TextField variant = "underline" description = "size=large (default)" size = "large" >
< TextFieldInput accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
< TextField variant = "underline" description = "size=medium" size = "medium" >
< TextFieldInput accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
아이콘만으로 맥락을 전달할 때는 description 또는 label에 아이콘의 의미를 설명하는 텍스트를 포함하세요. 아이콘 자체를 읽어야 한다면 accessibility-label을 지정하세요.
import "./styles" ;
import IconMagnifyingglassLine from "@karrotmarket/lynx-monochrome-icon/IconMagnifyingglassLine" ;
import { root } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" gap = "spacingY.componentDefault" >
< TextField
label = "소셜 미디어 URL"
description = "프로필이나 페이지 URL을 입력해주세요."
prefix = "https://"
>
< TextFieldInput accessibility-label = "소셜 미디어 URL" placeholder = "example.com" />
</ TextField >
< TextField
label = "검색"
description = "글 제목 또는 내용으로 검색할 수 있습니다."
prefixIcon = {< IconMagnifyingglassLine />}
>
< TextFieldInput accessibility-label = "검색" placeholder = "레모네이드 레시피" />
</ TextField >
< TextField
variant = "underline"
description = "프로필이나 페이지 URL을 입력해주세요."
prefix = "https://"
>
< TextFieldInput accessibility-label = "소셜 미디어 URL" placeholder = "example.com" />
</ TextField >
< TextField
variant = "underline"
description = "글 제목 또는 내용으로 검색할 수 있습니다."
prefixIcon = {< IconMagnifyingglassLine />}
>
< TextFieldInput accessibility-label = "검색" placeholder = "레모네이드 레시피" />
</ TextField >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
import "./styles" ;
import IconWonLine from "@karrotmarket/lynx-monochrome-icon/IconWonLine" ;
import { root } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" gap = "spacingY.componentDefault" >
< TextField label = "너비" description = "직접 측정 후 입력해주세요." suffix = "cm" >
< TextFieldInput accessibility-label = "너비" placeholder = "200" />
</ TextField >
< TextField label = "금액" description = "단위: 원" suffixIcon = {< IconWonLine />}>
< TextFieldInput accessibility-label = "금액" placeholder = "50,000" />
</ TextField >
< TextField variant = "underline" description = "직접 측정 후 입력해주세요." suffix = "cm" >
< TextFieldInput accessibility-label = "너비" placeholder = "200" />
</ TextField >
< TextField variant = "underline" description = "단위: 원" suffixIcon = {< IconWonLine />}>
< TextFieldInput accessibility-label = "금액" placeholder = "50,000" />
</ TextField >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
import "./styles" ;
import IconPlusCircleLine from "@karrotmarket/lynx-monochrome-icon/IconPlusCircleLine" ;
import IconWonLine from "@karrotmarket/lynx-monochrome-icon/IconWonLine" ;
import { root } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" gap = "spacingY.componentDefault" >
< TextField
label = "나이"
description = "오늘 기준, 만 나이를 입력해주세요."
prefix = "만"
suffix = "세"
>
< TextFieldInput accessibility-label = "나이" placeholder = "플레이스홀더" />
</ TextField >
< TextField
label = "금액"
description = "정산할 금액을 입력해주세요."
prefixIcon = {< IconPlusCircleLine />}
suffixIcon = {< IconWonLine accessibility-label = "원" />}
>
< TextFieldInput accessibility-label = "금액" placeholder = "플레이스홀더" />
</ TextField >
< TextField
variant = "underline"
description = "오늘 기준, 만 나이를 입력해주세요."
prefix = "만"
suffix = "세"
>
< TextFieldInput accessibility-label = "나이" placeholder = "플레이스홀더" />
</ TextField >
< TextField
variant = "underline"
description = "정산할 금액을 입력해주세요."
prefixIcon = {< IconPlusCircleLine />}
suffixIcon = {< IconWonLine accessibility-label = "원" />}
>
< TextFieldInput accessibility-label = "금액" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
indicator 또는 showRequiredIndicator prop을 사용할 수 있습니다.
import "./styles" ;
import { root } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" gap = "spacingY.componentDefault" >
< TextField
label = "선택 필드"
labelWeight = "bold"
description = "설명을 써주세요"
indicator = "선택"
>
< TextFieldInput accessibility-label = "선택 필드" placeholder = "플레이스홀더" />
</ TextField >
< TextField label = "필수 필드" description = "설명을 써주세요" required >
< TextFieldInput accessibility-label = "필수 필드" placeholder = "플레이스홀더" />
</ TextField >
< TextField label = "필수 필드" description = "설명을 써주세요" required showRequiredIndicator >
< TextFieldInput accessibility-label = "필수 필드" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
import "./styles" ;
import { root } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" gap = "spacingY.componentDefault" >
< TextField label = "라벨" description = "설명을 써주세요" maxGraphemeCount = { 8 }>
< TextFieldInput accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
< TextField
label = "라벨"
description = "설명을 써주세요"
maxGraphemeCount = { 8 }
invalid
errorMessage = "에러 메시지"
>
< TextFieldInput accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
value를 사용자 인식 문자(grapheme cluster) 단위로 나눈 결과를 onValueChange 콜백의 graphemes와 slicedGraphemes로 제공합니다.
문자 분리는 unicode-segmenter 를 통해 이루어집니다.
import "./styles" ;
import { root, useState } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
const [ value , setValue ] = useState ( "" );
const [ graphemes , setGraphemes ] = useState < string []>([]);
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" gap = "x4" >
< TextField
label = "라벨"
description = "국기 이모지 🇰🇷 를 추가해보세요."
maxGraphemeCount = { 100 }
value = {value}
onValueChange = {({ slicedValue , slicedGraphemes }) => {
setValue (slicedValue);
setGraphemes (slicedGraphemes);
}}
>
< TextFieldInput accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
< VStack gap = "x2" >
< text className = "text-field-input-preview__status" >
graphemes.length: { JSON . stringify (graphemes. length )}
</ text >
< text className = "text-field-input-preview__status" >
value.length: { JSON . stringify (value. length )}
</ text >
< text className = "text-field-input-preview__status" >
graphemes: { JSON . stringify (graphemes)}
</ text >
< text className = "text-field-input-preview__status" >value: {value}</ text >
</ VStack >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
Lynx는 HTML Form을 지원하지 않습니다. value와 onValueChange를 사용해 입력값을 React state로 관리할 수 있습니다.
import "./styles" ;
import { root, useState } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
const [ value , setValue ] = useState ( "안녕하세요" );
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" gap = "x3" >
< TextField
label = "이름"
description = "입력값을 React state로 관리합니다."
value = {value}
onValueChange = {({ value : nextValue }) => setValue (nextValue)}
>
< TextFieldInput accessibility-label = "이름" placeholder = "홍길동" />
</ TextField >
< text className = "text-field-input-preview__status" >입력값: {value}</ text >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
import "./styles" ;
import { root, useState } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function formatNumber ( value : string ) {
const digits = value. replace ( / \D / g , "" );
return digits. replace ( / \B (?=( \d {3} ) + (?! \d )) / g , "," );
}
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
const [ value , setValue ] = useState ( "1,000" );
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" >
< TextField
label = "금액"
description = "금액을 써주세요"
value = {value}
onValueChange = {({ value : nextValue }) => setValue ( formatNumber (nextValue))}
>
< TextFieldInput accessibility-label = "금액" placeholder = "9,999,999" />
</ TextField >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
import "./styles" ;
import { root, useState } from "@lynx-js/react" ;
import { useSeedClassName, VStack } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
function Root () {
const seedClassName = useSeedClassName ({ colorMode: "system" });
const [ value , setValue ] = useState ( "" );
return (
< page className = {seedClassName}>
< VStack className = "text-field-input-preview" >
< VStack className = "text-field-input-preview__content" >
< TextField
label = "라벨"
description = "6글자까지 입력 가능합니다"
maxGraphemeCount = { 6 }
value = {value}
onValueChange = {({ slicedValue }) => setValue (slicedValue)}
>
< TextFieldInput accessibility-label = "라벨" placeholder = "플레이스홀더" />
</ TextField >
</ VStack >
</ VStack >
</ page >
);
}
root. render (< Root />);
KeyboardAvoidingScrollView 안에 배치하면 TextFieldInput이 focus될 때 자동으로 등록되어 키보드에 가려지지 않는 위치로 스크롤됩니다.
import { KeyboardAvoidingScrollView } from "@seed-design/lynx-react" ;
import { TextField, TextFieldInput } from "@/components/ui/text-field" ;
export function KeyboardAwareFields () {
return (
< KeyboardAvoidingScrollView >
< TextField label = "제목" >
< TextFieldInput accessibility-label = "제목" />
</ TextField >
</ KeyboardAvoidingScrollView >
);
}
편집 가능한 상태에서는 HTML <input> 대신 Lynx native <input> element를 렌더링합니다.
readOnly 상태에서는 native focus·selection·잘라내기 메뉴를 제거하기 위해 <text> element로 렌더링합니다. 이 상태의 ref는 <text>를 가리키며 input 전용 UI method와 이벤트는 사용할 수 없습니다.
onChange 대신 snippet TextField의 onValueChange를 사용합니다. 원문과 grapheme 단위로 자른 값을 함께 제공합니다.
native bindinput은 TextFieldInput에 추가로 전달할 수 있습니다.
Field.Label과 입력의 DOM id 연결이 없으므로 accessibility-label을 입력에 직접 제공합니다.
포커스 시 키보드가 나타나도록 show-soft-input-on-focus의 기본값은 true입니다. undefined가 native attribute로 전달되지 않도록 컴포넌트가 이 기본값을 명시적으로 적용합니다. 커스텀 키보드를 사용하는 경우에는 false로 재정의할 수 있습니다.
android-set-soft-input-mode의 기본값은 "unspecified"입니다. Android에서 undefined가 native attribute로 전달되면 오류가 발생할 수 있어 컴포넌트가 이 기본값을 명시적으로 적용합니다.
android-set-soft-input-mode는 입력 요소가 포함된 host window 전역에 영향을 줍니다. 기본값인 "unspecified"도 기존 Activity 설정을 그대로 보존하는 값이 아니라 시스템 판단 모드로 다시 설정합니다. KeyboardAvoidingScrollView가 키보드 회피를 전담하는 화면에서는 별도 pan/resize를 막기 위해 "nothing"으로 재정의합니다. 같은 window에 있는 입력 요소에는 가능한 한 같은 값을 사용합니다.
size="responsive"는 CSS viewport breakpoint가 없는 Lynx에서 지원하지 않습니다. large 또는 medium을 명시합니다.
HTML form submit, browser validation, React Hook Form, aria-describedby id 연결은 지원하지 않습니다.