GitHub

Command Palette

Search for a command to run...

OTPInput

(A) 한줄 요약

OTPInput은 인증 코드(One-Time Password)를 “슬롯 UI”로 입력받는 컴포넌트다.
실제 입력은 보이지 않는 TextInput이 담당하고, 화면에는 OTPSlot들이 렌더링된다. 붙여넣기/패턴 검증/완료 콜백(onComplete)을 제공하며, useOTPInput 훅으로 동일 로직을 분리해 사용할 수도 있다.


(B) 설치 방법 (Track A / Track B)

공통 전제: 앱 엔트리 파일에서 unistyles side-effect import는 필수예요.

  • Track A: import '@fleet-ui/local/core/unistyles';
  • Track B: import '@fleet-ui/core/unistyles';

Track A (CLI / local install)

Track A: add OTPInput
pnpm dlx @fleet-ui/cli add OTPInput
Track A: import
import { OTPInput } from '@fleet-ui/local/components';

Track B (NPM package)

Track B: import
import { OTPInput } from '@fleet-ui/components';

(D) 핵심 기능(컴포넌트별) & 사용법

D-1. 가장 흔한 사용 시나리오(최소 예제)

OTPInput basic usage
import { OTPInput } from '@fleet-ui/components';
 
export function Example() {
  return (
    <OTPInput
      maxLength={6}
      onComplete={(code) => console.log('complete', code)}
      accessibilityLabel="인증 코드 입력"
    />
  );
}

D-2. 패턴 검증: pattern

pattern을 제공하면 입력 값이 정규식에 맞지 않을 때 업데이트를 무시한다.

Digits only
import { OTPInput } from '@fleet-ui/components';
 
export function Example() {
  return <OTPInput maxLength={6} pattern="^\\d*$" />;
}

D-3. 붙여넣기 처리: pasteTransformer

입력 이벤트에서 “한 번에 여러 글자”가 들어오면 붙여넣기로 간주하고 pasteTransformer로 변환 후 적용한다.
기본 변환기는 pasted 텍스트에서 maxLength 자리 숫자를 추출한다.

D-4. 커스텀 렌더: render

render를 제공하면 기본 OTPSlot 대신, slots 렌더 정보를 받아 커스텀 UI를 그릴 수 있다.


(E) 내부 상태 / Shared Value / Animation (필수)

E-1. 상태 모델(useOTPInput)

훅 내부에서 관리되는 핵심 상태는 아래다.

  • value: 현재 OTP 문자열
  • prevValue: 이전 프레임 값(슬롯 애니메이션 트리거용)
  • isFocused: 전체 포커스 상태

입력 처리:

  • 입력은 maxLength로 잘라 저장한다.
  • pattern이 있으면 정규식 통과 여부를 검사한다.
  • 길이가 maxLength가 되면 onComplete(value)를 호출한다.

슬롯 생성:

  • slots[index]char/prevChar/placeholderChar/isActive/hasFakeCaret 등을 포함한다.

E-2. Reanimated / Shared Value

OTPSlot은 다음 애니메이션을 써요.

  • 타이핑 바운스(새 글자 입력 시): scale + translateY 시퀀스
  • 포커스 표시:
    • bordered/faded는 borderWidth 1↔2
    • underlined는 underlineScale 0↔1
  • 색상 전환: background/border 색을 스프링으로 전환(에러일 때 error 색)

OTPCaret는 깜빡임을 withRepeat(withTiming)으로 구현한다.


(F) 접근성(누락 금지)

접근성은 “보이지 않는 실제 TextInput”에 집중시키는 구조다.

  • 슬롯 컨테이너(Pressable)는 accessible={false}로 숨기고
  • 실제 TextInputaccessible이며:
    • accessibilityRole="text"
    • accessibilityState={{ disabled }}
    • 기본 라벨: OTP input with ${maxLength} digits
    • 기본 힌트: Enter your verification code

iOS에서는 붙여넣기 기능을 위해 opacity: 0 대신 opacity: 0.02로 숨긴다(캐럿은 숨김).


(G) Props Table (필수: 인터페이스 전체)

기준: packages/components/src/OTPInput/OTPInput.types.ts의 public 타입들.

OTPInput — OTPInputProps

PropTypeRequiredDefaultDescriptionPlatform notes
maxLengthnumberYes-OTP 길이(슬롯 개수)
defaultValuestringNo''초기 값
onChangeText(value: string) => voidNo-값 변경 콜백
onComplete(value: string) => voidNo-모두 입력 완료 콜백
patternstring | RegExpNo-입력 검증 정규식불일치 시 업데이트 무시
placeholderstringNo-슬롯별 placeholder 문자열
pasteTransformer(pasted: string) => stringNo-붙여넣기 변환 함수기본 변환기 제공
colorScheme'primary' | 'neutral' | 'error' | 'success' | 'warning' | 'info'No'neutral'슬롯 포커스/색상 스킴
variant'flat' | 'bordered' | 'underlined' | 'faded'No'bordered'슬롯 스타일 variant
size'sm' | 'md' | 'lg' | 'xl'No'md'슬롯 크기/간격/타이포
rounded'none' | 'sm' | 'md' | 'lg' | 'full'No'md'라운드
shadow'none' | 'sm' | 'md' | 'lg'No'none'그림자
isDisabledbooleanNofalse비활성화
isInvalidbooleanNofalse에러 상태슬롯 색상 전환
gap'sm' | 'md' | 'lg' | 'xl' | numberNo-슬롯 간 간격size로 자동 결정 가능
containerStyleStyleProp<ViewStyle>No-루트 컨테이너 스타일
slotStyleStyleProp<ViewStyle>No-슬롯 스타일 오버라이드
slotTextStyleStyleProp<TextStyle>No-슬롯 텍스트 스타일
caretStyleStyleProp<ViewStyle>No-캐럿 스타일
render(props: OTPRenderProps) => ReactNodeNo-커스텀 렌더 함수기본 OTPSlot 대체

TextInputProps 상속(요약)

OTPInputPropsTextInputProps를 상속하지만, value, onChangeText, maxLength, style은 컴포넌트가 제어한다.
accessibilityLabel/accessibilityHint, inputMode, keyboardType, secureTextEntry 등은 그대로 전달 가능하다.

Hook: useOTPInput

useOTPInput(options)inputRef/value/isFocused/renderProps/handlers/actions를 반환해, 커스텀 UI에서도 동일한 입력 로직을 재사용할 수 있다.