npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@jiin.seok/formkit-react

v0.1.4

Published

A powerful React form library with Compound Component Pattern, built-in validation, and TypeScript support

Readme

@jiin.seok/formkit-react

🚀 Compound Component Pattern과 내장 검증, TypeScript 지원을 갖춘 강력한 React 폼 라이브러리

npm version License: MIT

English Documentation

✨ 주요 기능

  • 🎯 Compound Component Pattern - 깔끔하고 조합 가능한 API
  • 🔄 React Hook Form 통합 - 성능 최적화
  • 🛡️ Zod 스키마 지원 - 타입 안전 검증
  • 접근성 우선 - ARIA 준수
  • 🎨 Tailwind CSS 스타일링 - 기본적으로 아름다운 디자인
  • 📝 TypeScript - 완전한 타입 안정성
  • 🔒 비밀번호 토글 - 내장 가시성 토글
  • 🎛️ Select 컴포넌트 - Radix UI 기반

📦 설치

npm install @jiin.seok/formkit-react
# 또는
yarn add @jiin.seok/formkit-react
# 또는
pnpm add @jiin.seok/formkit-react

Peer Dependencies

npm install react react-dom react-hook-form
# Zod 검증을 위한 선택적 설치
npm install zod @hookform/resolvers

🚀 빠른 시작

기본 예제

import FormKit from '@jiin.seok/formkit-react'

function LoginForm() {
  const handleSubmit = (data) => {
    console.log('폼 데이터:', data)
  }

  return (
    <FormKit.Root formId="login" onSubmit={handleSubmit}>
      <FormKit.Title>로그인</FormKit.Title>
      
      <FormKit.Field>
        <FormKit.Label>이메일</FormKit.Label>
        <FormKit.Input name="email" type="email" required />
      </FormKit.Field>
      
      <FormKit.Field>
        <FormKit.Label>비밀번호</FormKit.Label>
        <FormKit.Input name="password" type="password" required />
      </FormKit.Field>
      
      <FormKit.SubmitButton>로그인</FormKit.SubmitButton>
    </FormKit.Root>
  )
}

Zod 검증과 함께 사용

import FormKit from '@jiin.seok/formkit-react'
import { z } from 'zod'

const loginSchema = z.object({
  email: z.string().email('유효하지 않은 이메일 주소입니다'),
  password: z.string().min(8, '비밀번호는 최소 8자 이상이어야 합니다')
})

function LoginForm() {
  const handleSubmit = (data) => {
    console.log('검증된 데이터:', data)
  }

  return (
    <FormKit.Root 
      formId="login" 
      schema={loginSchema} 
      onSubmit={handleSubmit}
    >
      <FormKit.Field>
        <FormKit.Label>이메일</FormKit.Label>
        <FormKit.Input name="email" type="email" />
      </FormKit.Field>
      
      <FormKit.Field>
        <FormKit.Label>비밀번호</FormKit.Label>
        <FormKit.Input name="password" type="password" />
      </FormKit.Field>
      
      <FormKit.SubmitButton>로그인</FormKit.SubmitButton>
    </FormKit.Root>
  )
}

Select를 포함한 고급 폼

import FormKit from '@jiin.seok/formkit-react'

function RegistrationForm() {
  const countries = [
    { value: 'kr', label: '대한민국' },
    { value: 'us', label: '미국' },
    { value: 'jp', label: '일본' },
  ]

  return (
    <FormKit.Root formId="registration" onSubmit={handleSubmit}>
      <FormKit.Fieldset>
        <FormKit.Legend required>개인 정보</FormKit.Legend>
        
        <FormKit.Field>
          <FormKit.Label>이름</FormKit.Label>
          <FormKit.Input name="fullName" required />
        </FormKit.Field>
        
        <FormKit.Field>
          <FormKit.Label>국가</FormKit.Label>
          <FormKit.Select 
            name="country" 
            options={countries}
            placeholder="국가를 선택하세요"
            required
          />
        </FormKit.Field>
        
        <FormKit.Field>
          <FormKit.Label>자기소개</FormKit.Label>
          <FormKit.Textarea 
            name="bio" 
            placeholder="간단한 자기소개를 작성해주세요"
            maxLength={500}
          />
        </FormKit.Field>
      </FormKit.Fieldset>
      
      <FormKit.SubmitButton>가입하기</FormKit.SubmitButton>
    </FormKit.Root>
  )
}

📦 사용 가능한 컴포넌트

FormKit은 포괄적인 폼 컴포넌트 세트를 제공합니다:

📝 핵심 컴포넌트

  • FormKit.Root - 검증 컨텍스트를 포함한 메인 폼 컨테이너
  • FormKit.Field - 레이블-입력 연결이 있는 필드 래퍼
  • FormKit.Fieldset - 관련된 필드 그룹화
  • FormKit.Legend - 필수 표시가 선택적으로 포함된 필드셋 제목

🎨 입력 컴포넌트

  • FormKit.Input - 비밀번호 토글, 이메일, 숫자 등을 지원하는 텍스트 입력
  • FormKit.Textarea - 여러 줄 텍스트 입력
  • FormKit.Select - 검색 기능이 있는 드롭다운 선택 (Radix UI 기반)

🏷️ 표시 컴포넌트

  • FormKit.Label - 필드 레이블
  • FormKit.Title - 폼 제목
  • FormKit.Wrapper - 커스텀 레이아웃용 컨테이너
  • FormKit.Unit - 단위 표시 (예: "원", "kg")
  • FormKit.Error - 오류 메시지 표시

🎯 액션 컴포넌트

  • FormKit.SubmitButton - 로딩 상태가 있는 제출 버튼
  • FormKit.ResetButton - 폼을 초기값으로 재설정

📚 API 레퍼런스

FormKit.Root

모든 자식 컴포넌트에 컨텍스트를 제공하는 메인 폼 컨테이너입니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | formId | string | ✅ | 폼의 고유 식별자 | | onSubmit | (data) => void | ✅ | 폼 제출 핸들러 | | schema | ZodSchema | ❌ | 검증을 위한 Zod 스키마 | | defaultValues | object | ❌ | 기본 폼 값 |

FormKit.Field

자동 레이블-입력 연결이 있는 폼 입력용 컨테이너입니다.

| Prop | Type | 기본값 | 설명 | |------|------|--------|------| | isInline | boolean | false | 레이블과 입력을 가로로 표시 | | hidden | boolean | false | 필드 숨기기 | | htmlFor | string | auto | 레이블-입력 연결을 위한 커스텀 ID |

FormKit.Input

내장 기능이 있는 향상된 입력 컴포넌트입니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | name | string | ✅ | 필드 이름 | | type | string | ❌ | 입력 타입 (text, email, password 등) | | required | boolean | ❌ | 필드를 필수로 표시 | | minLength | number | ❌ | 최소 문자 길이 | | maxLength | number | ❌ | 최대 문자 길이 |

기능:

  • 🔒 type="password"에 대한 자동 비밀번호 가시성 토글
  • ✅ 확인 필드에 대한 자동 검증 (예: confirmPassword)
  • 🎯 완전한 TypeScript 지원

FormKit.Select

Radix UI를 사용한 드롭다운 선택 컴포넌트입니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | name | string | ✅ | 필드 이름 | | options | Array<{value, label}> | ✅ | 선택 옵션 | | placeholder | string | ❌ | 플레이스홀더 텍스트 | | required | boolean | ❌ | 필드를 필수로 표시 |

FormKit.Textarea

여러 줄 텍스트 입력 컴포넌트입니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | name | string | ✅ | 필드 이름 | | required | boolean | ❌ | 필드를 필수로 표시 | | minLength | number | ❌ | 최소 문자 길이 | | maxLength | number | ❌ | 최대 문자 길이 | | rows | number | ❌ | 표시되는 텍스트 줄 수 (기본값: 4) |

FormKit.Fieldset

관련된 폼 필드를 함께 그룹화합니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | className | string | ❌ | 커스텀 CSS 클래스 | | children | ReactNode | ✅ | 자식 컴포넌트 |

FormKit.Legend

필수 표시가 선택적으로 있는 필드셋 제목입니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | required | boolean | ❌ | 빨간색 별표(*) 표시 | | className | string | ❌ | 커스텀 CSS 클래스 | | children | ReactNode | ✅ | 범례 텍스트 |

FormKit.Label

폼 입력을 위한 접근 가능한 레이블입니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | className | string | ❌ | 커스텀 CSS 클래스 | | children | ReactNode | ✅ | 레이블 텍스트 |

FormKit.Title

폼 제목/헤더 컴포넌트입니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | className | string | ❌ | 커스텀 CSS 클래스 | | children | ReactNode | ✅ | 제목 텍스트 |

FormKit.SubmitButton

내장 로딩 상태가 있는 제출 버튼입니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | variant | string | ❌ | 버튼 스타일 변형 | | disabled | boolean | ❌ | 버튼 비활성화 | | className | string | ❌ | 커스텀 CSS 클래스 | | children | ReactNode | ✅ | 버튼 텍스트 |

FormKit.ResetButton

폼을 초기값으로 재설정합니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | onClick | function | ❌ | 추가 클릭 핸들러 | | className | string | ❌ | 커스텀 CSS 클래스 | | children | ReactNode | ✅ | 버튼 텍스트 |

FormKit.Wrapper

커스텀 레이아웃용 컨테이너 컴포넌트입니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | className | string | ❌ | 커스텀 CSS 클래스 | | children | ReactNode | ✅ | 자식 컴포넌트 |

FormKit.Unit

입력 필드 옆에 단위를 표시합니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | unit | string | ✅ | 단위 텍스트 (예: "원", "kg", "%") |

FormKit.Error

검증 오류 메시지를 표시합니다.

| Prop | Type | 필수 | 설명 | |------|------|------|------| | error | FieldError | ❌ | react-hook-form의 오류 객체 |

🎨 스타일링

FormKit은 테마를 위해 CSS 변수와 함께 Tailwind CSS를 사용합니다. CSS에 다음 변수를 추가하세요:

:root {
  --border: 214.3 31.8% 91.4%;
  --input: 214.3 31.8% 91.4%;
  --ring: 222.2 84% 4.9%;
  --background: 0 0% 100%;
  --foreground: 222.2 84% 4.9%;
  --primary: 222.2 47.4% 11.2%;
  --primary-foreground: 210 40% 98%;
  --secondary: 210 40% 96.1%;
  --secondary-foreground: 222.2 47.4% 11.2%;
  --destructive: 0 84.2% 60.2%;
  --destructive-foreground: 210 40% 98%;
  --muted: 210 40% 96.1%;
  --muted-foreground: 215.4 16.3% 46.9%;
  --accent: 210 40% 96.1%;
  --accent-foreground: 222.2 47.4% 11.2%;
  --popover: 0 0% 100%;
  --popover-foreground: 222.2 84% 4.9%;
}

.dark {
  --border: 217.2 32.6% 17.5%;
  --input: 217.2 32.6% 17.5%;
  --ring: 212.7 26.8% 83.9%;
  --background: 222.2 84% 4.9%;
  --foreground: 210 40% 98%;
  /* ... 다른 다크 모드 변수들 */
}

🧪 테스팅

import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import FormKit from '@jiin.seok/formkit-react'

test('폼 데이터 제출', async () => {
  const handleSubmit = jest.fn()
  
  render(
    <FormKit.Root formId="test" onSubmit={handleSubmit}>
      <FormKit.Field>
        <FormKit.Input name="username" />
      </FormKit.Field>
      <FormKit.SubmitButton>제출</FormKit.SubmitButton>
    </FormKit.Root>
  )
  
  await userEvent.type(screen.getByRole('textbox'), 'john')
  await userEvent.click(screen.getByRole('button'))
  
  expect(handleSubmit).toHaveBeenCalledWith({ username: 'john' })
})

📄 라이선스

MIT © [Jiin Seok]

🔗 링크