컴포넌트 문서

1. 데이터 클래스 (Data Class)

설명

EasyObj와 EasyList는 React에서 복잡한 상태 관리를 단순화하는 데이터 클래스입니다.

객체나 배열의 중첩된 속성까지 자동으로 상태를 관리하며, 직관적인 방식으로 데이터를 조작할 수 있습니다.

useState와 달리 상태 변경 시 setter 함수를 호출할 필요가 없으며, 불변성을 자동으로 관리합니다.

  • EasyObj: 객체 형태 상태를 프록시로 래핑
  • EasyList: 배열 상태에 CRUD 메서드 제공
  • forAll: 모든 항목 순회하며 수정
  • toJS: 순수 JS 구조로 변환

EasyObj

{
  "name": "홍길동",
  "age": 20,
  "hobbies": [
    "독서",
    "운동"
  ],
  "address": {
    "city": "서울",
    "street": "강남대로"
  }
}
EasyObj는 객체의 중첩된 속성까지 자동으로 상태를 관리합니다.
jsx
const dataObj = Lib.EasyObj({
    name: '홍길동',
    age: 20,
    hobbies: ['독서', '운동'],
    address: {
        city: '서울',
        street: '강남대로'
    }
});

// 상태 변경 시 자동으로 리렌더링
dataObj.age += 1;
dataObj.hobbies.push('여행');
dataObj.address.city = '부산';

EasyList

[
  {
    "id": 1,
    "text": "할 일 1"
  },
  {
    "id": 2,
    "text": "할 일 2"
  }
]
EasyList는 배열 메서드를 지원하며 각 항목의 상태도 자동으로 관리합니다.
jsx
const taskList = Lib.EasyList([
    { id: 1, text: '할 일 1' },
    { id: 2, text: '할 일 2' }
]);

// 배열 메서드 사용
taskList.push({ id: 3, text: '할 일 3' });
taskList.pop();

// forAll 메서드로 모든 항목 수정
taskList.forAll(item => {
    item.text += ' (완료)';
});

2. 버튼 (Button)

설명

Button 컴포넌트는 className prop을 통해 Tailwind CSS로 스타일을 커스터마이징할 수 있습니다.

기본 스타일을 유지하면서 추가적인 스타일을 적용하거나, 완전히 새로운 스타일을 정의할 수 있습니다.

  • children: 버튼 내용
  • variant?: 버튼 색상 스타일 (기본: 'primary')
  • size?: 버튼 크기 'sm' | 'md' | 'lg' (기본: 'md')
  • icon?: 아이콘 이름 (react-icons)
  • iconPosition?: 아이콘 위치 'left' | 'right' (기본: 'left')
  • disabled?: 비활성화 상태
  • loading?: 로딩 스피너 표시
  • onClick?: 클릭 핸들러
  • className?: 추가 Tailwind 클래스
  • type?: HTML 버튼 타입 (기본: 'button')

버튼 종류

기본 버튼 (Primary)
jsx
<Lib.Button>기본 버튼</Lib.Button>
Secondary 버튼
jsx
<Lib.Button variant="secondary">Secondary</Lib.Button>
Outline 버튼
jsx
<Lib.Button variant="outline">Outline</Lib.Button>
Ghost 버튼
jsx
<Lib.Button variant="ghost">Ghost</Lib.Button>
Danger 버튼
jsx
<Lib.Button variant="danger">Danger</Lib.Button>
Success 버튼
jsx
<Lib.Button variant="success">Success</Lib.Button>
Warning 버튼
jsx
<Lib.Button variant="warning">Warning</Lib.Button>
Link 스타일 버튼
jsx
<Lib.Button variant="link">Link Button</Lib.Button>
Dark 버튼
jsx
<Lib.Button variant="dark">Dark</Lib.Button>
커스텀 버튼
jsx
<Lib.Button
    className="bg-gradient-to-r from-purple-500 to-pink-500
    hover:from-purple-600 hover:to-pink-600"
>
    그라데이션
</Lib.Button>
아이콘이 있는 버튼
jsx
<Lib.Button>
    <Lib.Icon icon="ri:RiSearchLine" className="w-5 h-5 mr-2" />
    검색
</Lib.Button>
비활성화 버튼
jsx
<Lib.Button disabled>Disabled</Lib.Button>

버튼 크기

Small 버튼
jsx
<Lib.Button size="sm">Small</Lib.Button>
Medium 버튼
jsx
<Lib.Button size="md">Medium</Lib.Button>
Large 버튼
jsx
<Lib.Button size="lg">Large</Lib.Button>

3. 아이콘 (Icon)

설명

Icon 컴포넌트는 다양한 아이콘 라이브러리를 통합하여 제공합니다.

각 아이콘 세트의 prefix를 사용하여 원하는 아이콘을 선택할 수 있습니다.

  • icon: 세트prefix:아이콘이름
  • size?: 아이콘 크기 (기본: 1em)
  • color?: 아이콘 색상
  • ariaLabel?: 접근성 라벨
  • decorative?: 장식용 여부(true면 숨김)
  • className?: 추가 Tailwind 클래스

사용 가능한 아이콘 세트

기본 사용법

기본 Material 아이콘과 크기 변형
jsx
// 기본 아이콘
<Lib.Icon icon="md:MdHome" size="24px" />

// 다양한 크기
<Lib.Icon icon="md:MdHome" size="16px" />  // 작은 크기
<Lib.Icon icon="md:MdHome" size="24px" />  // 기본 크기
<Lib.Icon icon="md:MdHome" size="32px" />  // 큰 크기
<Lib.Icon icon="md:MdHome" size="48px" />  // 더 큰 크기
색상이 있는 Bootstrap 아이콘과 크기 변형
jsx
// 색상이 있는 아이콘
<Lib.Icon icon="bs:BsCheckCircle" className="text-green-500" size="24px" />

// 다양한 크기
<Lib.Icon icon="bs:BsCheckCircle" className="text-green-500" size="16px" />
<Lib.Icon icon="bs:BsCheckCircle" className="text-green-500" size="24px" />
<Lib.Icon icon="bs:BsCheckCircle" className="text-green-500" size="32px" />
<Lib.Icon icon="bs:BsCheckCircle" className="text-green-500" size="48px" />
소셜 미디어 아이콘 (Feather)과 크기 변형
jsx
// 소셜 미디어 아이콘
<Lib.Icon icon="fi:FiGithub" size="24px" />

// 다양한 크기
<Lib.Icon icon="fi:FiGithub" size="16px" />
<Lib.Icon icon="fi:FiGithub" size="24px" />
<Lib.Icon icon="fi:FiGithub" size="32px" />
<Lib.Icon icon="fi:FiGithub" size="48px" />

4. 입력 (Input)

설명

Input 컴포넌트는 dataObj와 dataKey를 통해 양방향 바인딩을 지원합니다.

주요 기능:

  • 마스크 입력 지원 (전화번호, 사업자번호 등)
  • 문자 필터링 (한글만, 영문/숫자만 등)
  • 숫자 입력 시 자릿수 제한 (정수부, 소수부)
  • 에러 상태 표시
  • IME 입력 지원 (한글, 일본어 등)
  • dataObj?/dataKey?: 바운드 상태 객체와 키
  • value?/defaultValue?: 제어/초기 값
  • type?: HTML input 타입 (기본: 'text')
  • placeholder?: 안내 문구
  • filter?: 허용 문자 필터
  • mask?: 입력 마스크 패턴 문자열 또는 함수
  • maxDigits?/maxDecimals?: 숫자 자릿수 제한
  • prefix?/suffix?: 입력 앞/뒤 표시 문자열
  • togglePassword?: 비밀번호 토글 버튼
  • error?: 에러 메시지
  • onChange?/onValueChange?: 값 변경 콜백
  • className?: 추가 Tailwind 클래스

기본 입력

가장 기본적인 텍스트 입력과 이메일 입력 예시입니다.
기본 입력
jsx
<Lib.Input
    dataObj={inputDataObj}
    dataKey="basicInput"
    placeholder="텍스트 입력하세요"
/>
이메일 입력
jsx
<Lib.Input
    dataObj={inputDataObj}
    dataKey="email"
    type="email"
    placeholder="이메일을 입력하세요"
/>

마스크 입력

전화번호, 사업자번호 등 형식이 정해진 입력에 사용됩니다. 마스크 패턴: # (숫자), A (대문자), a (소문자), ? (대소문자), * (모든문자)
전화번호 마스킹
jsx
<Lib.Input
    dataObj={inputDataObj}
    dataKey="phone"
    mask="###-####-####"
    placeholder="전화번호: 010-1234-5678"
/>
사업자번호 마스킹
jsx
<Lib.Input
    dataObj={inputDataObj}
    dataKey="businessNo"
    mask="###-##-#####"
    placeholder="사업자번호 123-45-67890"
/>

필터/숫자 입력

숫자 자릿수 제한과 문자 필터 입력을 함께 보여줍니다. 한글, 영문, 숫자 등 원하는 문자셋을 지정할 수 있습니다.
숫자 입력 (자리수 제한)
jsx
<Lib.Input
    dataObj={inputDataObj}
    dataKey="amount"
    type="number"
    maxDigits={10}
    maxDecimals={2}
    placeholder="숫자 입력 (최대 10자리, 소수점2자리)"
/>
영문/숫자 필터
jsx
<Lib.Input
    dataObj={inputDataObj}
    dataKey="code"
    filter="A-Za-z0-9"
    placeholder="영문/숫자 입력"
/>
한글 필터
jsx
<Lib.Input
    dataObj={inputDataObj}
    dataKey="koreanName"
    filter="가-힣"
    placeholder="한글 입력"
/>

고급 기능

접두어/접미어, 아이콘, 비밀번호 토글 등 고급 기능을 제공합니다.
에러 상태
jsx
<Lib.Input
    dataObj={inputDataObj}
    dataKey="email"
    error="이메일 형식이 올바르지 않습니다"
    placeholder="에러 상태 표시"
/>
금액 입력 (우측 정렬, 접미사 표시)
jsx
<Lib.Input
    dataObj={inputDataObj}
    dataKey="price"
    type="number"
    maxDigits={10}
    className="text-right"
    placeholder="금액 입력"
    suffix="원"
/>
아이콘이 있는 검색 입력
jsx
<Lib.Input
    dataObj={inputDataObj}
    dataKey="searchKeyword"
    prefix={<Lib.Icon icon="ri:RiSearchLine" className="w-5 h-5 text-gray-400" />}
    placeholder="검색어를 입력하세요"
/>
비밀번호 토글 기능
jsx
<Lib.Input
    dataObj={inputDataObj}
    dataKey="password"
    type="password"
    placeholder="비밀번호 입력"
    togglePassword
/>

5. 텍스트영역 (Textarea)

설명

바운드와 컨트롤드 모드를 지원하며 줄바꿈을 보존하고 aria-invalid를 사용합니다.

  • rows?: 기본 줄 수 (기본: 4)
  • dataObj?/dataKey?: 바운드 상태 객체와 키
  • value?/defaultValue?: 제어/초기 값
  • error?: 에러 메시지
  • onChange?/onValueChange?: 값 변경 콜백
  • placeholder?: 안내 문구
  • className?: 추가 Tailwind 클래스
  • disabled?/readOnly?: 상태 제어

바운드 모드

바운드 모드
textDataObj.memo = 초기 메모
dataObj + dataKey 로 상태 바인딩
jsx
const textDataObj = Lib.EasyObj({ memo: '' });

<Lib.Textarea
  dataObj={textDataObj}
  dataKey="memo"
  rows={4}
  placeholder="메모를 입력하세요"
/>

컨트롤드 모드

컨트롤드 모드
value = 로컬 상태
컨트롤드 모드 (value + onValueChange)
jsx
const [textValue, setTextValue] = useState('');

<Lib.Textarea
  value={textValue}
  onValueChange={setTextValue}
  rows={3}
/>

검증/에러 상태

검증/에러 상태
10자 이상 입력해주세요
error prop 과 aria-invalid 활용
jsx
<Lib.Textarea
  dataObj={textDataObj}
  dataKey="memo"
  rows={4}
  error={textDataObj.memo.length < 10}
  placeholder="10자 이상 입력"
/>
<div className="mt-1 text-xs text-red-600">{textDataObj.memo.length < 10 ? '10자 이상 입력해주세요' : '정상'}</div>

읽기 전용/비활성

readOnly / disabled 상태
jsx
<Lib.Textarea placeholder="읽기 전용" value="내용 편집 불가" readOnly />
<Lib.Textarea placeholder="비활성화" disabled />

6. 선택 (Select)

설명

Select 컴포넌트는 dataList의 selected 속성을 통해 선택 상태를 관리합니다.

옵션을 선택하면 선택된 항목의 selected가 true로, 나머지는 false로 자동 변경됩니다.

또는 dataObj/dataKey를 주면 EasyObj 바인딩으로 동작하며, 선택 값이 자동으로 반영됩니다.

  • dataList: 옵션 배열(EasyList 가능)
  • valueKey/textKey?: 값/라벨 키 (기본: 'value'/'text')
  • dataObj/dataKey?: EasyObj 바인딩 (value prop보다 우선하지 않음)
  • value?/onValueChange?: 선택 값을 외부 상태와 동기화할 때 사용
  • onChange?: change 이벤트 콜백 (value 포함)
  • disabled?: 비활성화 여부
  • error?: 에러 상태 표시
  • className?: 추가 Tailwind 클래스

기본 사용법

dataList의 selected 플래그와 동기화됩니다.

현재 선택된 id
EasyList 모드 — dataList 내부의 selected 플래그만으로 선택 상태를 관리
jsx
const jobOptionList = Lib.EasyList([
  { id: '', label: '직무를 선택하세요', placeholder: true, selected: true },
  { id: 'designer', label: '디자이너' },
  { id: 'developer', label: '개발자' },
  { id: 'pm', label: '프로덕트 매니저' },
]);

<Lib.Select
  dataList={jobOptionList}
  valueKey="id"
  textKey="label"
  status="success"
  statusMessage="dataList의 selected 플래그와 동기화됩니다."
/>

value prop: developer

value = developer
컨트롤드 모드 — value/onValueChange로 외부 상태와 동기화하면서도 dataList.selected는 자동 갱신
jsx
const [roleValue, setRoleValue] = useState('developer');

<Lib.Select
  dataList={jobOptionList}
  valueKey="id"
  textKey="label"
  value={roleValue}
  onValueChange={setRoleValue}
  status="info"
  statusMessage={`value prop: ${roleValue}`}
/>

상태

사용할 수 없는 상태입니다.옵션을 불러오는 중입니다.

로딩/비활성화 상태 — status="loading" + assistiveText로 라이브 영역 안내
jsx
<Lib.Select
  dataList={loadingOptionList}
  valueKey="id"
  textKey="label"
  status="loading"
  assistiveText="옵션을 불러오는 중입니다."
  disabled
/>

필수 입력 항목입니다.

에러 상태 — status="error"와 안내 메시지
jsx
<Lib.Select
  dataList={jobOptionList}
  valueKey="id"
  textKey="label"
  status="error"
  statusMessage="필수 입력 항목입니다."
/>

표시할 항목이 없습니다.선택 가능한 항목이 비어 있습니다.

빈 상태 — status="empty" 프리셋으로 항목 부재 안내 및 aria-live=assertive 적용
jsx
<Lib.Select
  dataList={Lib.EasyList([])}
  status="empty"
  assistiveText="선택 가능한 항목이 비어 있습니다."
/>

7. 체크박스 (Checkbox)

설명

Checkbox 컴포넌트는 dataObj와 dataKey를 통해 양방향 바인딩을 지원합니다.

name prop이 없을 경우 dataKey 또는 label을 name으로 사용합니다.

  • label?: 체크박스 옆에 표시할 텍스트
  • name?: 그룹/폼 이름
  • checked?: 선택 상태 제어
  • dataObj?/dataKey?: 바운드 상태 객체와 키
  • onChange?: 선택 변경 콜백
  • color?: 체크박스 색상 또는 CSS 컬러
  • disabled?: 비활성화 여부
  • className?: 추가 Tailwind 클래스

기본 사용법

기본 체크박스 (dataObj/dataKey 바인딩).
jsx
<Lib.Checkbox
    label="기본 체크박스"
    dataObj={checkboxDataObj}
    dataKey="basicCheckbox"
/>
비활성화 상태
jsx
<Lib.Checkbox
    label="비활성화 체크박스"
    disabled
/>

응용 예시

다양한 색상
jsx
<Lib.Checkbox
    label="기본 색상 (Primary)"
    dataObj={checkboxDataObj}
    dataKey="primary"
    color="primary"
/>
<Lib.Checkbox
    label="커스텀 빨간색"
    dataObj={checkboxDataObj}
    dataKey="red"
    color="#FF0000"
/>
현재 상태: 체크 해제됨
제어 컴포넌트 방식
jsx
const [isChecked, setIsChecked] = useState(false);

<Lib.Checkbox
    label="제어 컴포넌트"
    checked={isChecked}
    onChange={(event) => setIsChecked(event.target.checked)}
/>

약관 동의

실제 사용 예시 (약관 동의)
jsx
<Lib.Checkbox
    name="terms"
    label="[필수] 서비스 이용약관 동의"
    dataObj={termsDataObj}
    dataKey="termsAgreed"
/>

8. 체크버튼 (CheckButton)

설명

CheckButton 컴포넌트는 Checkbox와 동일한 방식으로 dataObj와 dataKey를 통해 양방향 바인딩을 지원합니다.

버튼 형태로 체크박스 기능을 제공합니다.

name prop이 없을 경우 dataKey 또는 children을 name으로 사용합니다.

  • children: 버튼 내부 콘텐츠
  • name?: 그룹/폼 이름
  • checked?: 선택 상태 제어
  • dataObj?/dataKey?: 바운드 상태 객체와 키
  • onChange?: 선택 변경 콜백
  • color?: 버튼 색상 또는 CSS 컬러
  • disabled?: 비활성화 여부
  • className?: 추가 Tailwind 클래스

기본 사용법

기본 체크버튼 (dataObj/dataKey 바인딩).
jsx
<Lib.CheckButton
    dataObj={checkDataObj}
    dataKey="basicCheckButton"
>
    기본 체크버튼
</Lib.CheckButton>
비활성화 상태
jsx
<Lib.CheckButton disabled>
    비활성화 체크버튼
</Lib.CheckButton>

응용 예시

다양한 색상
jsx
<Lib.CheckButton color="#FF0000" dataObj={colorDataObj} dataKey="redButton">
    빨간색
</Lib.CheckButton>
<Lib.CheckButton color="#4CAF50" dataObj={colorDataObj} dataKey="greenButton">
    초록색
</Lib.CheckButton>
<Lib.CheckButton color="#2196F3" dataObj={colorDataObj} dataKey="blueButton">
    파란색
</Lib.CheckButton>
현재 상태: 비활성화
제어 컴포넌트 방식
jsx
const [isChecked, setIsChecked] = useState(false);

<Lib.CheckButton
    checked={isChecked}
    onChange={() => setIsChecked(!isChecked)}
>
    제어 컴포넌트
</Lib.CheckButton>

9. 라디오박스 (Radiobox)

설명

Radiobox 컴포넌트는 dataObj와 dataKey를 통해 양방향 바인딩을 지원합니다.

같은 name을 가진 라디오박스 그룹에서 선택된 value가 dataObj에 저장됩니다.

name prop이 없을 경우 dataKey 또는 label을 name으로 사용합니다.

  • label?: 라벨 텍스트
  • name?: 그룹/폼 이름
  • value: 선택 값
  • dataObj?/dataKey?: 바운드 상태 객체와 키
  • checked?/defaultChecked?: 선택 상태 제어
  • onChange?: 선택 변경 콜백
  • color?: 표시 색상
  • disabled?: 비활성화 여부
  • className?: 추가 Tailwind 클래스

기본 사용법

기본 라디오박스 (dataObj/dataKey 바인딩).
jsx
<Lib.Radiobox
    name="job"
    label="개발자"
    value="developer"
    dataObj={radioDataObj}
    dataKey="selectedJob"
/>
비활성화 상태
jsx
<Lib.Radiobox
    name="disabled"
    label="비활성화 1"
    value="disabled1"
    disabled
/>

응용 예시

결제 수단 선택

커스텀 색상
jsx
<Lib.Radiobox
    name="payment"
    label="신용카드"
    value="card"
    dataObj={radioDataObj}
    dataKey="paymentMethod"
    color="#FF6B6B"
/>
선택된 값: 없음
제어 컴포넌트 방식
jsx
const [optionValue, setOptionValue] = useState('');

<Lib.Radiobox
    name="controlled"
    label="옵션 1"
    value="option1"
    checked={optionValue === 'option1'}
    onChange={(event) => setOptionValue(event.target.value)}
/>

10. 라디오버튼 (RadioButton)

설명

RadioButton 컴포넌트는 Radiobox와 동일한 방식으로 dataObj와 dataKey를 통해 양방향 바인딩을 지원합니다.

버튼 형태로 라디오박스 기능을 제공합니다.

name prop이 없을 경우 dataKey 또는 children을 name으로 사용합니다.

  • children: 버튼 내부 콘텐츠
  • name?: 그룹/폼 이름
  • value: 선택 값
  • checked?: 선택 상태 제어
  • dataObj?/dataKey?: 바운드 상태 객체와 키
  • onChange?: 선택 변경 콜백
  • color?: 버튼 색상
  • disabled?: 비활성화 여부
  • className?: 추가 Tailwind 클래스

기본 사용법

기본 라디오버튼 (dataObj/dataKey 바인딩).
jsx
<Lib.RadioButton
    name="size"
    value="small"
    dataObj={radioDataObj}
    dataKey="selectedSize"
>
    Small
</Lib.RadioButton>
비활성화 상태
jsx
<Lib.RadioButton
    name="disabled"
    value="disabled1"
    disabled
>
    비활성화 1
</Lib.RadioButton>

응용 예시

커스텀 색상
jsx
<Lib.RadioButton
    name="theme"
    value="light"
    dataObj={radioDataObj}
    dataKey="selectedTheme"
    color="#FF6B6B"
>
    라이트
</Lib.RadioButton>
선택된 언어: 없음
제어 컴포넌트 방식
jsx
const [languageValue, setLanguageValue] = useState('');

<Lib.RadioButton
    name="controlled"
    value="kr"
    checked={languageValue === 'kr'}
    onChange={(event) => setLanguageValue(event.target.value)}
>
    한국어
</Lib.RadioButton>

11. 스위치 (Switch)

설명

접근성을 준수하기 위해 role="switch"와 aria-checked를 사용합니다. dataObj와 dataKey 또는 제어 모드를 지원합니다.

  • name?: 그룹/폼 이름
  • checked?: 선택 상태 제어
  • defaultChecked?: 초기 선택 상태
  • dataObj?/dataKey?: 바운드 상태 객체와 키
  • onChange?/onValueChange?: 값 변경 콜백
  • disabled?: 비활성화 여부
  • label?: 스위치 라벨
  • className?: 추가 Tailwind 클래스
  • id?: input id 지정

바운드 모드

switchDataObj.enabled = false
dataObj + dataKey 로 상태 바인딩
jsx
const switchDataObj = Lib.EasyObj({ enabled: false });

<Lib.Switch
  dataObj={switchDataObj}
  dataKey="enabled"
  label={`바운드: ${switchDataObj.enabled ? 'ON' : 'OFF'}`}
/>

컨트롤드 모드

isLocalOn = false
컨트롤드 모드 (checked + onValueChange)
jsx
const [isLocalOn, setIsLocalOn] = useState(false);

<Lib.Switch
  checked={isLocalOn}
  onValueChange={(nextValue) => setIsLocalOn(nextValue)}
  label={`컨트롤드: ${isLocalOn ? 'ON' : 'OFF'}`}
/>

비활성/기본값

disabled / defaultChecked 조합
jsx
<Lib.Switch disabled defaultChecked label="비활성화" />
<Lib.Switch disabled label="비활성화 (OFF)" />

접근성

접근성: id/label 로 명확한 레이블 제공
jsx
<Lib.Switch
  dataObj={switchDataObj}
  dataKey="notifications"
  id="notify-switch"
  label="알림 허용"
/>

12. 숫자 입력 (Number)

설명

스텝 버튼이 있는 숫자 입력입니다. EasyObj 바운드와 컨트롤드 모드를 지원합니다.

  • value?/defaultValue?: 제어/초기 값
  • min?/max?: 허용 범위
  • step?: 증감 단위 (기본: 1)
  • dataObj?/dataKey?: 바운드 상태 객체와 키
  • placeholder?: 안내 문구
  • onChange?/onValueChange?: 값 변경 콜백
  • className?: 추가 Tailwind 클래스
  • disabled?: 비활성화 여부
  • readOnly?: 읽기 전용
  • id?: input id 지정

기본

numberDataObj.qty = 1
기본: 바운드 + step 1
jsx
const numberDataObj = Lib.EasyObj({ qty: 1 });

<Lib.NumberInput dataObj={numberDataObj} dataKey="qty" min={0} step={1} />

범위/스텝

min/max/step 조합
jsx
<Lib.NumberInput dataObj={priceDataObj} dataKey="price" min={0} max={100} step={0.5} />

언바운드

언바운드 + defaultValue
jsx
<Lib.NumberInput defaultValue={10} step={5} />

13. 날짜/시간 (Date/Time)

설명

브라우저 기본 Date와 Time 입력을 래핑한 컴포넌트입니다. EasyObj 바운드와 컨트롤드 모드를 지원합니다.

  • value?: ISO 문자열 제어 값
  • dataObj?/dataKey?: 바운드 상태 객체와 키
  • defaultValue?: 초기 값
  • min?/max?: 선택 가능 범위
  • onChange?/onValueChange?: 값 변경 콜백
  • className?: 추가 Tailwind 클래스
  • disabled?: 입력 비활성화
  • readOnly?: 읽기 전용
  • placeholder?: 안내 문구
  • id?: input id 지정

날짜

dateDataObj.date =
기본: 바운드
jsx
const dateDataObj = Lib.EasyObj({ date: '' });

<Lib.DateInput dataObj={dateDataObj} dataKey="date" />
min/max + 기본값
jsx
<Lib.DateInput defaultValue="2025-01-01" min="2025-01-01" max="2025-12-31" />

시간

timeDataObj.time =
기본: 바운드
jsx
const timeDataObj = Lib.EasyObj({ time: '' });

<Lib.TimeInput dataObj={timeDataObj} dataKey="time" />
기본값 + 분 단위(step)
jsx
<Lib.TimeInput defaultValue="09:30" step={60} />

14. 콤보박스 (Combobox)

설명

검색 가능한 단일·다중 선택 입력입니다. dataList(selected)를 기반으로 한 선택 모델을 사용하며 초성 검색을 지원합니다.

  • dataList: 선택 항목 배열(EasyList 가능)
  • valueKey / textKey (선택): 값/라벨 키 (기본: 'value'/'text')
  • value?: 제어 값 (단일 또는 배열)
  • defaultValue?: 초기 선택 값
  • multi?: 다중 선택 모드
  • multiSummary?: 다중 선택 요약 배지 표시
  • summaryText?: 요약 배지 텍스트 템플릿
  • filterable?: 입력 검색 기능
  • placeholder?: 선택 전 표시 문구
  • noResultsText?: 검색 결과 없음 문구
  • showSelectAll?: 전체 선택/해제 버튼 표시
  • selectAllText?/clearAllText?: 전체 선택/해제 텍스트
  • onChange?/onValueChange?: 값 변경 콜백
  • className?: 추가 Tailwind 클래스
  • id?: input id 지정
  • disabled?: 비활성화 여부

기본

선택 도시: incheon

EasyObj 바운드 모드 — dataObj/dataKey로 주소 객체와 동기화
jsx
const cityList = Lib.EasyList([
  { value: 'seoul', text: '서울' },
  { value: 'busan', text: '부산' },
  { value: 'incheon', text: '인천' },
  { value: 'daegu', text: '대구' },
]);
const profileDataObj = Lib.EasyObj({ address: { city: 'incheon' } });

<Lib.Combobox
  dataList={cityList}
  dataObj={profileDataObj.address}
  dataKey="city"
  placeholder="도시 선택"
  status="success"
  statusMessage={`선택 도시: ${profileDataObj.address.city}`}
/>

바운드

value prop: seoul

초성검색 예: ㅅㅇ→서울, ㅂㅅ→부산
컨트롤드 모드 — value/onValueChange 조합
jsx
const [controlledCity, setControlledCity] = useState('seoul');

<Lib.Combobox
  dataList={cityList}
  value={controlledCity}
  onValueChange={setControlledCity}
  placeholder="도시 선택 (컨트롤드)"
  status="info"
  statusMessage={`value prop: ${controlledCity}`}
/>

다중 선택

다중 선택 (EasyList selected/바운드 값 동시 반영)

multi + EasyObj 배열 바운드 — favorites 배열과 EasyList selected 동기화
jsx
<Lib.Combobox
  dataList={cityList}
  dataObj={profileDataObj.address}
  dataKey="favorites"
  multi
  multiSummary
  showSelectAll
  summaryText="{count}개 도시 선택"
  placeholder="좋아하는 도시 선택"
  status="warning"
  statusMessage="다중 선택 (EasyList selected/바운드 값 동시 반영)"
/>

요약/전체 선택

사용할 수 없는 상태입니다.도시 목록을 불러오는 중입니다.

로딩/비활성화 — status="loading" + assistiveText
jsx
<Lib.Combobox
  dataList={Lib.EasyList([{ value: '', text: '불러오는 중', placeholder: true }])}
  status="loading"
  assistiveText="도시 목록을 불러오는 중입니다."
  disabled
/>

16. 로딩 (Loading)

설명

전역 setLoading을 통해 전체 화면 로딩 오버레이를 표시합니다.

  • 별도 props 없이 중앙에 표시됩니다.

기본 사용

전체 화면 로딩 표시
jsx
const loadingTimerRef = useRef(null);
const { setLoading } = useGlobalUi();

/**
 * @description 전역 로딩 예제 타이머를 정리
 * 처리 규칙: 예제 컴포넌트가 사라지면 pending timeout을 취소한다.
 */
useEffect(() => () => clearTimeout(loadingTimerRef.current), []);

/**
 * @description 전역 로딩 버튼 클릭을 처리
 * 처리 규칙: 로딩 표시 후 2초 뒤 자동 해제한다.
 */
const handleLoadingClick = () => {
  setLoading(true);
  clearTimeout(loadingTimerRef.current);
  loadingTimerRef.current = setTimeout(() => setLoading(false), 2000);
};

<Lib.Button onClick={handleLoadingClick}>
  전체 화면 로딩 (2초)
</Lib.Button>

17. 알림 (Alert)

설명

전역 스토어(useGlobalUi)의 showAlert로 간단히 알림을 표시합니다.

정보/성공/경고/오류 유형을 지원하며 제목과 메시지를 지정할 수 있습니다.

  • title?: 알림 제목 (기본: '알림')
  • text: 표시 메시지
  • type?: 'info' | 'success' | 'warning' | 'error'
  • onClick?: 확인 버튼 클릭 콜백

기본 사용

기본 알림
jsx
// useSharedStore 사용
const { showAlert } = useGlobalUi();

// 기본 알림
showAlert('기본 알림 메시지입니다.');

알림 유형

알림 유형
jsx
// 정보/성공/경고/오류 알림
showAlert('정보 알림 메시지입니다.', { title: '정보', type: 'info' });
showAlert('성공 알림 메시지입니다.', { title: '성공', type: 'success' });
showAlert('경고 알림 메시지입니다.', { title: '경고', type: 'warning' });
showAlert('오류 알림 메시지입니다.', { title: '오류', type: 'error' });

콜백 함수

알림 닫힘 콜백
jsx
// 알림 닫힘 시 실행될 콜백
showAlert('작업이 완료되었습니다.', {
  title: '알림',
  onClick: function() {
    alert('알림을 닫았습니다.');
  }
});

포커스 이동

알림 닫힘 후 지정된 요소로 포커스 이동
jsx
// useRef 로 입력창 참조 생성
const inputRef = useRef(null);

// 알림을 닫으면 입력창으로 포커스 이동
<div className="flex gap-4 items-center">
  <Lib.Button
    onClick={() => {
      showAlert('알림을 닫히면 입력창으로 커서가 이동합니다.', {
        title: '알림',
        onFocus: () => inputRef.current?.focus(),
      });
    }}
  >
    알림 띄우기
  </Lib.Button>
  <Lib.Input ref={inputRef} placeholder="커서가 여기로 이동합니다" />
</div>

18. 확인 (Confirm)

설명

전역 스토어(useGlobalUi)의 showConfirm로 확인 대화상자를 띄웁니다.

Promise를 반환하며, 사용자의 선택(확인: true, 취소: false)을 then으로 받을 수 있습니다.

  • title?: 대화상자 제목
  • text: 표시 메시지
  • type?: 'info' | 'warning' | 'danger'
  • onConfirm?, onCancel?: 콜백
  • confirmText?, cancelText?: 버튼 텍스트

기본 사용

기본 확인 모달
jsx
// useSharedStore 사용
const { showConfirm, showAlert } = useGlobalUi();

// 기본 확인
showConfirm('정말 진행하시겠습니까?').then((result) => {
  if (result) showAlert('확인했습니다.');
});

확인 유형

확인 모달 유형
jsx
// 경고 확인
showConfirm('해당 작업은 되돌릴 수 없습니다.\n계속하시겠습니까?', {
  title: '주의',
  type: 'warning',
  confirmText: '계속',
  cancelText: '중단',
});

// 위험 확인
showConfirm('모든 데이터를 삭제합니다.\n정말 삭제하시겠습니까?', {
  title: '위험 확인',
  type: 'danger',
  confirmText: '삭제',
  cancelText: '취소',
});

콜백

확인/취소 콜백
jsx
// 확인/취소 시 실행될 콜백
showConfirm('삭제를 진행하시겠습니까?', {
  title: '위험 확인',
  type: 'danger',
  confirmText: '삭제',
  cancelText: '취소',
  onConfirm: () => showAlert('삭제가 완료되었습니다.'),
  onCancel: () => showAlert('삭제가 취소되었습니다.'),
});

포커스 이동

확인 모달 닫힘 후 포커스 이동
jsx
// useRef 로 입력창 참조 생성
const inputRef = useRef(null);

// 모달 닫힘 후 입력창으로 포커스 이동
<div className="flex gap-4 items-center">
  <Lib.Button
    onClick={() => {
      showConfirm('확인 모달이 닫히면 입력창으로 커서가 이동합니다.', {
        title: '포커스 이동',
        onFocus: () => inputRef.current?.focus(),
      });
    }}
  >
    포커스 이동 표시
  </Lib.Button>
  <Lib.Input ref={inputRef} placeholder="커서가 여기로 이동합니다" />
</div>

19. 토스트 (Toast)

설명

전역 스토어(useGlobalUi)의 showToast로 간단한 알림 배너를 표시합니다.

정보/성공/경고/오류 유형, 6가지 위치, 지속시간 제어를 지원합니다.

  • message: 표시 내용
  • type?: 'info' | 'success' | 'warning' | 'error'
  • position?: top/bottom - left/center/right
  • duration?: 자동 닫힘 시간(ms), Infinity로 무한

기본 사용

기본 토스트
jsx
// useSharedStore 사용
const { showToast } = useGlobalUi();

// 기본 토스트
showToast('기본 토스트 메시지입니다.');

토스트 유형

토스트 유형
jsx
showToast('정보 토스트 메시지입니다.', { type: 'info' });
showToast('성공 토스트 메시지입니다.', { type: 'success' });
showToast('경고 토스트 메시지입니다.', { type: 'warning' });
showToast('오류 토스트 메시지입니다.', { type: 'error' });

토스트 위치

토스트 위치
jsx
showToast('상단 왼쪽에 표시합니다.', { position: 'top-left' });
showToast('상단 중앙에 표시합니다.', { position: 'top-center' });
showToast('상단 오른쪽에 표시합니다.', { position: 'top-right' });
showToast('하단 왼쪽에 표시합니다.', { position: 'bottom-left' });
showToast('하단 중앙에 표시합니다.', { position: 'bottom-center' });
showToast('하단 오른쪽에 표시합니다.', { position: 'bottom-right' });

토스트 지속시간

토스트 유지 시간
jsx
showToast('2초에 사라집니다.', { duration: 2000 });
showToast('5초에 사라집니다.', { duration: 5000 });
showToast('자동으로 사라지지 않습니다.', { duration: Infinity });

20. 툴팁 (Tooltip)

설명

hover, focus 또는 클릭에 반응하는 간단한 툴팁입니다.

  • content: 툴팁 내용
  • placement?: 위치 'top' | 'bottom' | 'left' | 'right'
  • trigger?: 'hover' | 'click' | 'focus'
  • delay?: 표시 지연(ms)
  • disabled?: 비활성화 여부
  • textDirection?: 텍스트 방향 'lr' | 'tb'
  • className?: 추가 Tailwind 클래스
  • children?: 트리거 요소

기본

기본 사용 (hover/focus)
jsx
<Lib.Tooltip content="기본 툴팁">
  <Lib.Button>Hover</Lib.Button>
</Lib.Tooltip>

방향

placement: top/bottom/left/right
jsx
<Lib.Tooltip content="오른쪽" placement="right"><Lib.Button>right</Lib.Button></Lib.Tooltip>

트리거

trigger="click" 으로 클릭 시 표시
jsx
<Lib.Tooltip content="클릭" trigger="click"><Lib.Button>Click</Lib.Button></Lib.Tooltip>

21. 배지/태그 (Badge/Tag)

설명

상태 표시용 레이블입니다. 색상, 크기, 모양을 지원합니다.

  • children: 표시할 내용
  • variant?: 색상 스타일 (기본: 'neutral')
  • size?: 크기 'sm' | 'md' (기본: 'sm')
  • pill?: 둥근 모양 여부 (기본: false)
  • className?: 추가 Tailwind 클래스

색상 Variants

NeutralPrimarySuccessWarningDanger
기본/색상 Variant
jsx
<Lib.Badge>Neutral</Lib.Badge>
<Lib.Badge variant="primary">Primary</Lib.Badge>
<Lib.Badge variant="success">Success</Lib.Badge>
<Lib.Badge variant="warning">Warning</Lib.Badge>
<Lib.Badge variant="danger">Danger</Lib.Badge>

Outline / Pill

OutlineRounded
outline / pill
jsx
<Lib.Badge variant="outline">Outline</Lib.Badge>
<Lib.Badge pill>Rounded</Lib.Badge>

크기

SmallMedium
size: sm / md
jsx
<Lib.Badge size="sm">Small</Lib.Badge>
<Lib.Badge size="md">Medium</Lib.Badge>

아이콘 포함

완료 진행중 실패
아이콘을 포함한 Badge
jsx
<Lib.Badge variant="success"><Lib.Icon icon="md:MdCheck" /> 완료</Lib.Badge>
<Lib.Badge variant="warning"><Lib.Icon icon="md:MdSchedule" /> 진행중</Lib.Badge>
<Lib.Badge variant="danger"><Lib.Icon icon="md:MdClose" /> 실패</Lib.Badge>

22. 지표 카드 (Stat)

설명

간단한 KPI/지표를 보여주는 카드. 아이콘은 aria-hidden, 값/증감에는 라벨 제공.

  • label: 지표 이름
  • value: 표시할 값
  • delta?: 증감 수치 또는 텍스트
  • deltaType?: 'up' | 'down' | 'neutral' (기본 neutral)
  • icon?: 우측 아이콘 노드
  • helpText?: 하단 보조 설명
  • className?: 루트 추가 클래스

기본

주간 활성 사용자
12,340
+3.2%
증가 지표(up) 예시
jsx
<Lib.Stat label="주간 활성 사용자" value="12,340" delta="+3.2%" deltaType="up" />

추가 예시

월간 이탈률
1,024
-1.1%
감소 지표(down) 예시
jsx
<Lib.Stat label="월간 이탈률" value="1,024" delta="-1.1%" deltaType="down" />
서버 상태
정상
중립 지표(neutral) 예시
jsx
<Lib.Stat label="서버 상태" value="정상" deltaType="neutral" />

23. 스켈레톤 (Skeleton)

설명

로딩 중 콘텐츠 구조를 힌트로 보여주는 플레이스홀더입니다.

  • variant?: 'rect' | 'text' | 'circle'
  • lines?: 텍스트 라인 수 (variant='text')
  • circleSize?: 원형 크기(px)
  • className?: 추가 Tailwind 클래스

텍스트

텍스트 라인 스켈레톤
jsx
<Lib.Skeleton variant="text" lines={3} />

아바타 + 텍스트

아바타 + 텍스트
jsx
<Lib.Skeleton variant="circle" circleSize={48} />
<Lib.Skeleton variant="text" lines={2} />

카드 스켈레톤

카드 스켈레톤 조합
jsx
<Lib.Card className="bg-white">
  <div className="flex items-center gap-3">
    <Lib.Skeleton variant="circle" circleSize={40} />
    <div className="flex-1">
      <Lib.Skeleton variant="text" lines={2} />
    </div>
  </div>
  <div className="mt-4">
    <Lib.Skeleton className="h-24 w-full" />
  </div>
</Lib.Card>

24. 엠티 (Empty)

설명

데이터가 없을 때 안내와 액션을 제공합니다.

  • icon?: 상단 아이콘 (react-icons)
  • title?: 제목 텍스트
  • description?: 부가 설명
  • children?: 추가 내용
  • action?: 버튼 등 액션 요소
  • className?: 추가 Tailwind 클래스

기본

데이터가 없습니다

기본 Empty
jsx
<Lib.Empty />

설명/액션

검색 결과 없음

다른 키워드로 다시 시도해 보세요

설명/액션 포함
jsx
<Lib.Empty title="검색 결과 없음" description="다른 키워드로 다시 시도해 보세요" action={<Lib.Button>새로 만들기</Lib.Button>} />

25. 카드 (Card)

설명

헤더, 본문, 푸터로 구성된 컴포넌트입니다.

  • children: 본문 콘텐츠
  • title?: 헤더 제목
  • subtitle?: 제목 아래 보조 텍스트
  • actions?: 헤더 우측 액션 요소
  • footer?: 하단 푸터 콘텐츠
  • className?: 추가 Tailwind 클래스

기본 Card

간단 카드

보조 설명

카드 본문을 간결하게 구성합니다.
기본 Card: title + subtitle + 본문
jsx
<Lib.Card title="간단 카드" subtitle="보조 설명">
  카드 본문을 간결하게 구성합니다.
</Lib.Card>

액션/푸터

액션 카드

버튼과 함께

리스트 항목 1
리스트 항목 2
푸터 텍스트
actions + footer 사용
jsx
<Lib.Card
  title="액션 카드"
  subtitle="버튼과 함께"
  actions={<Lib.Button onClick={() => showAlert('버튼 액션')}>Action</Lib.Button>}
  footer="푸터 텍스트"
>
  <div className="space-y-2">
    <div>리스트 항목 1</div>
    <div>리스트 항목 2</div>
  </div>
</Lib.Card>

본문 전용

헤더/푸터 패딩이 있는 카드입니다.
헤더/푸터 패딩(custom className*)
jsx
<Lib.Card className="bg-slate-50" bodyClassName="p-6">
  헤더/푸터 패딩이 있는 카드입니다.
</Lib.Card>

조합 예시

조합 예시

New
IMG
이미지/아이콘과 텍스트
레이아웃과 구성 예시
업데이트: 방금 전
Badge, Icon 조합
jsx
<Lib.Card
  title="조합 예시"
  actions={<Lib.Badge variant="primary">New</Lib.Badge>}
  footer={<div className="flex items-center gap-2 text-xs"><Lib.Icon icon="md:MdSchedule" /> 업데이트: 방금 전</div>}
>
  <div className="flex items-start gap-3">
    <div className="h-12 w-12 rounded bg-zinc-100 flex items-center justify-center text-zinc-700 ring-1 ring-zinc-200/60">IMG</div>
    <div>
      <div className="font-medium">이미지/아이콘과 텍스트</div>
      <div className="text-sm text-gray-600">레이아웃과 구성 예시</div>
    </div>
  </div>
</Lib.Card>

26. 테이블 (Table)

설명

데이터 테이블과 카드 리스트를 렌더링합니다. 제어형 및 비제어 페이징을 지원하며 URL과 스토리지에 상태를 보존합니다.

  • data: 행 데이터 배열/EasyList
  • columns: 열 정의 배열
  • rowKey?: 행 키 결정 함수/키
  • className?: 래퍼 추가 클래스
  • headerClassName?/rowClassName?/cellClassName?/rowsClassName?: 세부 스타일
  • empty?: 빈 상태 메시지
  • loading?: 로딩 표시
  • onRowClick?: 행 클릭 콜백
  • page?/pageSize?/defaultPage?: 현재/페이지당/초기 페이지
  • onPageChange?: 페이지 변경 콜백
  • pageParam?/persist?/persistKey?: URL/스토리지 상태 유지
  • maxPageButtons?: 페이지 버튼 수
  • variant?: 'table' | 'card'
  • renderCard?: 카드 모드 렌더 함수
  • gridClassName?: 카드 모드 grid 클래스

기본

ID
이름
이메일
권한
1
사용자 1
user1@example.com
Admin
2
사용자 2
user2@example.com
Editor
3
사용자 3
user3@example.com
Viewer
4
사용자 4
user4@example.com
Admin
5
사용자 5
user5@example.com
Editor
6
사용자 6
user6@example.com
Viewer
7
사용자 7
user7@example.com
Admin
8
사용자 8
user8@example.com
Editor
9
사용자 9
user9@example.com
Viewer
10
사용자 10
user10@example.com
Admin
기본 테이블: URL(page) 동기화 + 세션 보존, 페이지당 10개
jsx
<Lib.EasyTable
  data={tableRowList}
  columns={tableColumnList}
  pageParam="page"
  persistKey="table-basic"
  defaultPage={1}
  pageSize={10}
/>

제어형 페이지

ID
이름
이메일
권한
6
사용자 6
user6@example.com
Viewer
7
사용자 7
user7@example.com
Admin
8
사용자 8
user8@example.com
Editor
9
사용자 9
user9@example.com
Viewer
10
사용자 10
user10@example.com
Admin
제어형 페이지: page/onPageChange로 바깥에서 관리 (pageSize=5)
jsx
const [pageNo, setPageNo] = useState(2);

<Lib.EasyTable
  data={tableRowList}
  columns={tableColumnList}
  page={pageNo}
  pageSize={5}
  maxPageButtons={7}
  onPageChange={setPageNo}
/>

카드

#1
사용자 1
user1@example.com
Admin
#2
사용자 2
user2@example.com
Editor
#3
사용자 3
user3@example.com
Viewer
#4
사용자 4
user4@example.com
Admin
#5
사용자 5
user5@example.com
Editor
#6
사용자 6
user6@example.com
Viewer
#7
사용자 7
user7@example.com
Admin
#8
사용자 8
user8@example.com
Editor
카드 변형: variant="card" + renderCard로 카드 UI 구성
jsx
<Lib.EasyTable
  variant="card"
  data={tableRowList}
  pageSize={8}
  renderCard={(row) => (
    <div className="border rounded p-4 bg-white hover:shadow">...</div>
  )}
/>

커스텀 스타일

ID
이름
이메일
권한
1
사용자 1
user1@example.com
Admin
2
사용자 2
user2@example.com
Editor
3
사용자 3
user3@example.com
Viewer
4
사용자 4
user4@example.com
Admin
5
사용자 5
user5@example.com
Editor
6
사용자 6
user6@example.com
Viewer
커스텀 스타일: 셀 rounded-2xl + ring, 헤더/행 gap으로 물리적 분리된 모던 스타일
jsx
<Lib.EasyTable
  data={tableRowList}
  columns={tableStyleColList}
  headerClassName="bg-transparent gap-2"
  rowClassName="gap-2 !bg-transparent !border-0 hover:!bg-transparent"
  rowsClassName="mt-2 space-y-2"
  cellClassName="bg-white ring-1 ring-gray-200 rounded-2xl shadow-sm p-3"
  pageSize={6}
/>

빈 상태

ID
이름
이메일
권한
표시할 데이터가 없습니다.
빈 상태/메시지 커스터마이즈
jsx
<Lib.EasyTable data={[]} columns={tableColumnList} empty="표시할 데이터가 없습니다." />

27. 페이지네이션 (Pagination)

설명

독립 컴포넌트로 제어형 페이지 이동을 제공하며, Table 내장 페이징으로도 사용할 수 있습니다.

  • page: 현재 페이지 번호 (1부터)
  • pageCount: 전체 페이지 수
  • onChange: 페이지 변경 시 호출 (새 페이지 전달)
  • maxButtons?: 표시할 최대 번호 버튼 (기본 7)
  • showEdges?: 처음/끝 버튼 및 ... 표시 여부 (기본 true)
  • className?: 래퍼 추가 클래스

기본 (독립 컴포넌트)

현재 페이지: 2 / 12
기본 제어형 페이지네이션 (page/onChange)
jsx
const [pageNo, setPageNo] = useState(2);

<Lib.Pagination page={pageNo} pageCount={12} onChange={setPageNo} />

대용량/버튼 제한

현재 페이지: 5 / 50
버튼 수 제한(maxButtons=5) 대용량 페이지
jsx
const [pageNo, setPageNo] = useState(5);

<Lib.Pagination page={pageNo} pageCount={50} maxButtons={5} onChange={setPageNo} />

28. 탭 (Tab)

설명

Tab 컴포넌트는 Tab.Item을 사용하여 탭 패널을 구성합니다.

기본 상태는 EasyObj 바인딩을 우선 사용하고, 제어 props 동작 설명용 예제에서만 useState를 함께 보여줍니다.

className prop을 통해 커스텀 스타일링을 지원합니다.

  • dataObj?/dataKey?: 현재 탭 인덱스 바인딩
  • tabIndex?: 초기 탭 인덱스
  • onChange?: 탭 변경 시 호출
  • className?: 래퍼 추가 클래스
  • children: Tab.Item 목록

기본 사용법

첫번째 탭의 내용입니다.
EasyObj를 사용한 기본 탭
jsx
const tabDataObj = Lib.EasyObj({
    selectedTab: 0
});

<Lib.Tab dataObj={tabDataObj} dataKey="selectedTab">...</Lib.Tab>

제어 컴포넌트

사용자 프로필

tabIndex와 onChange를 직접 연결한 제어 탭 예시입니다.

tabIndex와 onChange 제어 예시
jsx
const [activeTab, setActiveTab] = useState(0);

<Lib.Tab tabIndex={activeTab} onChange={setActiveTab}>...</Lib.Tab>

스타일링

className prop으로 커스텀 스타일을 적용할 수 있습니다.
커스텀 스타일링
jsx
<Lib.Tab
    className="bg-gray-100 rounded-lg p-4"
    dataObj={tabDataObj}
    dataKey="customTab"
>...</Lib.Tab>

아이콘 탭

탭 제목에 아이콘과 텍스트를 함께 사용할 수 있습니다.
아이콘이 있는 탭
jsx
<Lib.Tab dataObj={tabDataObj} dataKey="iconTab">...</Lib.Tab>

29. 드로어 (Drawer)

설명

화면 측면에서 슬라이드 인 되는 패널입니다. 외부 Collapse 탭과 리사이즈를 지원하며 Tailwind px 클래스 기반 크기 설정이 가능합니다.

  • isOpen: 열림 상태
  • onClose?: 닫힘 콜백
  • side?: 위치 'right' | 'left' | 'top' | 'bottom'
  • size?: 패널 크기 Tailwind 클래스 문자열(min-[1468px]:w-[360px], min-[1468px]:h-[220px] 등)
  • closeOnBackdrop?: 배경 클릭 시 닫힘
  • closeOnEsc?: ESC 키로 닫힘
  • resizable?: 드래그로 크기 조절
  • collapseButton?: 접기 버튼 표시
  • className?: 추가 Tailwind 클래스
  • children?: 패널 내용

오른쪽 (기본)

오른쪽에서 열리는 기본 드로어 (리사이즈 가능, 핸들 포함)
jsx
<Lib.Drawer isOpen={open} onClose={close} side="right" resizable collapseButton>내용 없음</Lib.Drawer>

오른쪽 (size="min-[1468px]:w-[360px]")

오른쪽 드로어 너비를 Tailwind px 클래스 문자열로 지정(size="min-[1468px]:w-[360px]")
jsx
<Lib.Drawer isOpen={open} onClose={close} side="right" size="min-[1468px]:w-[360px]" collapseButton>width 360px</Lib.Drawer>

왼쪽 (size="min-[1468px]:w-[420px]")

왼쪽 드로어 너비를 Tailwind px 클래스 문자열로 지정(size="min-[1468px]:w-[420px]")
jsx
<Lib.Drawer isOpen={open} onClose={close} side="left" size="min-[1468px]:w-[420px]" collapseButton>width 420px</Lib.Drawer>

위쪽 (size="min-[1468px]:h-[220px]")

위쪽 드로어 높이를 Tailwind px 클래스 문자열로 지정(size="min-[1468px]:h-[220px]")
jsx
<Lib.Drawer isOpen={open} onClose={close} side="top" size="min-[1468px]:h-[220px]" collapseButton>height 220px</Lib.Drawer>

아래쪽 (size="min-[1468px]:h-[260px]")

아래쪽 드로어 높이를 Tailwind px 클래스 문자열로 지정(size="min-[1468px]:h-[260px]")
jsx
<Lib.Drawer isOpen={open} onClose={close} side="bottom" size="min-[1468px]:h-[260px]" collapseButton>height 260px</Lib.Drawer>

카드 샘플

카드 컴포넌트를 포함한 드로어
jsx
<Lib.Drawer isOpen={open} onClose={close} side="right" collapseButton><Lib.Card title="카드 샘플">드로어 안 카드</Lib.Card></Lib.Drawer>

메뉴 샘플

리스트 메뉴를 담은 드로어
jsx
<Lib.Drawer isOpen={open} onClose={close} side="left" collapseButton><ul className="p-4 space-y-2"><li>...</li></ul></Lib.Drawer>

30. 모달 (Modal)

설명

Modal 컴포넌트는 Header, Body, Footer 구조를 가진 팝업 대화상자입니다.

5가지 크기(sm, md, lg, xl, full)를 지원하며, 드래그 기능을 선택적으로 활성화할 수 있습니다.

ESC 키, 백드롭 클릭으로 닫기가 가능하며, 포커스 트랩을 지원합니다.

  • isOpen: 열림 상태
  • onClose?: 닫힘 콜백
  • size?: 'sm' | 'md' | 'lg' | 'xl' | 'full'
  • draggable?: 헤더 드래그 이동
  • closeOnBackdrop?: 배경 클릭 시 닫힘
  • closeOnEsc?: ESC 키로 닫힘
  • top?/left?: 초기 위치 지정
  • className?: 추가 Tailwind 클래스
  • children: 모달 내부 콘텐츠

31. 리치 에디터 (EasyEditor)

설명

EasyEditor는 Tiptap 기반 리치 텍스트 에디터로, EasyObj 바인딩과 프리셋 확장을 통해 쉽게 사용할 수 있습니다. 기본 직렬화는 JSON이며 serialization="html" | "text"로 모드를 바꿀 수 있습니다. 글자 크기, 색상, 정렬, 링크, 이미지/파일 첨부, Editor/HTML 모드 전환 등 핵심 기능을 제공합니다.

  • dataObj + dataKey: EasyObj 객체 바인딩 (JSON이 기본 직렬화)
  • value + onChange: 컨트롤드 모드
  • serialization?: 'json' | 'html' | 'text' (기본: 'json')
  • extensions?: Tiptap Extension 배열 (메모이즈되어 불필요한 재생성 방지)
  • imageUploadUrl?, fileUploadUrl?: 업로드 엔드포인트 (기본 제공 Alert 안내)
  • onUploadImage?, onUploadFile?: 커스텀 업로드 함수 주입 가능
  • toolbar?: 툴바 표시 여부 (기본: true)
  • status?: 'idle' | 'loading' | 'error' | 'success', 상태에 따른 스타일
  • readOnly?: 읽기 전용 모드 (HTML 모드 전환 시 비활성화)
  • Editor/HTML 모드 전환 시 HTML을 즉시 반영하며, 바인딩에도 동기화됩니다.

툴바에서 폰트, 색상, 정렬, HTML 모드를 시험해보세요.

현재 값 요약: 내용 없음

EasyObj 바인딩 기반 기본 사용

jsx
<Lib.EasyEditor
  dataObj={editorDataObj}
  dataKey="announcement"
  serialization="html"
  placeholder="팀 공지를 작성하세요"
  label="공지 작성"
  helperText="툴바에서 폰트, 색상, 정렬, HTML 모드를 시험해보세요."
/>

status='success'로 상태 프리셋을 표시합니다.

현재 값 요약: 온보딩 가이드 새로운 팀원을 환영합니다. 아래 체크리스트를 확인하세요.

스타터 콘텐츠가 있는 바인딩 케이스

jsx
<Lib.EasyEditor
  dataObj={editorDataObj}
  dataKey="onboardingGuide"
  serialization="html"
  placeholder="온보딩 가이드를 작성하세요"
  label="가이드 편집"
  status="success"
  helperText="status='success'로 상태 프리셋을 표시합니다."
/>
<h3>HTML 메모</h3><p>컨트롤드 모드에서는 <strong>serialization="html"</strong>을 사용하십시오.</p>

EasyObj 바인딩 + HTML 직렬화

jsx
const editorDataObj = Lib.EasyObj({ htmlMemo: '<p>초기 HTML</p>' });

<Lib.EasyEditor
  dataObj={editorDataObj}
  dataKey="htmlMemo"
  serialization="html"
  placeholder="HTML 문자열을 직접 관리"
  label="컨트롤드 HTML 편집기"
/>

툴바 숨김 + 수정 불가

오류 스타일 및 안내

처리 중 상태

성공 스타일

readOnly/invalid/status 매트릭스 예시

jsx
<div className="grid md:grid-cols-2 gap-4">
  <Lib.EasyEditor value={'<p>읽기 전용 내용</p>'} serialization="html" readOnly toolbar={false} />
  <Lib.EasyEditor value={'<p>유효성 오류 예시</p>'} serialization="html" invalid />
  <Lib.EasyEditor value={'<p>로딩 상태</p>'} serialization="html" status="loading" />
  <Lib.EasyEditor value={'<p>성공 상태</p>'} serialization="html" status="success" />
</div>

32. 차트 (EasyChart)

설명

Recharts 기반 카드형 차트 래퍼(EasyList 대응)

EasyList/배열 데이터를 그대로 받아 카드 스타일로 차트를 렌더링한다.

시리즈는 {seriesId, seriesNm, dataKey, type, color} 구조를 권장.

Prop설명
dataListEasyList/배열 차트 데이터
seriesListEasyList/배열 시리즈 ({seriesId, seriesNm, dataKey, type, color})
xKeyX축에 사용할 필드 키 (기본 label)
type기본 시리즈 타입 line|bar|area|pie|donut (기본 line)
loading / status로딩/에러/빈 상태 표시 플래그
empty빈 상태 메시지 혹은 노드
actions카드 우측 액션 영역
hideLegend범례 숨김 여부
기본 라인 차트 예시
jsx
const sampleData = [
  { label: "1월", signups: 120, active: 90, churn: 12 },
  { label: "2월", signups: 150, active: 110, churn: 15 },
  { label: "3월", signups: 180, active: 130, churn: 18 },
  { label: "4월", signups: 220, active: 170, churn: 16 },
  { label: "5월", signups: 240, active: 190, churn: 20 },
];

<EasyChart
  dataList={sampleDataList}
  seriesList={[
    { seriesId: "signups", seriesNm: "가입자", dataKey: "signups", color: "#18181b" },
    { seriesId: "active", seriesNm: "활성이용자", dataKey: "active", color: "#0f766e" },
  ]}
  xKey="label"
  type="line"
  hideLegend={false}
  height={260}
  actions={<Button size="sm">내보내기</Button>}
/>
단일 바 차트
jsx
const sampleData = [
  { label: "1월", signups: 120, active: 90, churn: 12 },
  { label: "2월", signups: 150, active: 110, churn: 15 },
  { label: "3월", signups: 180, active: 130, churn: 18 },
  { label: "4월", signups: 220, active: 170, churn: 16 },
  { label: "5월", signups: 240, active: 190, churn: 20 },
];

<EasyChart
  dataList={sampleDataList}
  seriesList={[
    { seriesId: "signups", seriesNm: "가입자", dataKey: "signups", type: "bar", color: "#18181b" },
    { seriesId: "active", seriesNm: "활성이용자", dataKey: "active", type: "bar", color: "#0f766e" },
  ]}
  xKey="label"
  type="bar"
  hideLegend
  height={260}
/>
바+라인 혼합 스택 차트
jsx
const sampleData = [
  { label: "1월", signups: 120, active: 90, churn: 12 },
  { label: "2월", signups: 150, active: 110, churn: 15 },
  { label: "3월", signups: 180, active: 130, churn: 18 },
  { label: "4월", signups: 220, active: 170, churn: 16 },
  { label: "5월", signups: 240, active: 190, churn: 20 },
];

<EasyChart
  dataList={sampleDataList}
  seriesList={[
    { seriesId: "signups", seriesNm: "가입자", dataKey: "signups", type: "bar", color: "#18181b", stackId: "v" },
    { seriesId: "active", seriesNm: "활성이용자", dataKey: "active", type: "bar", color: "#0f766e", stackId: "v" },
    { seriesId: "churn", seriesNm: "이탈", dataKey: "churn", type: "line", color: "#dc2626" },
  ]}
  xKey="label"
  type="bar"
  hideLegend={false}
  xLabelFormatter={(label) => `${label} /22`}
  yLabelFormatter={(val) => `${val}명`}
  height={260}
/>
파이 차트
jsx
const sampleData = [
  { label: "1월", signups: 120, active: 90, churn: 12 },
  { label: "2월", signups: 150, active: 110, churn: 15 },
  { label: "3월", signups: 180, active: 130, churn: 18 },
  { label: "4월", signups: 220, active: 170, churn: 16 },
  { label: "5월", signups: 240, active: 190, churn: 20 },
];

<EasyChart
  dataList={sampleDataList}
  seriesList={[
    { seriesId: "signups", seriesNm: "가입자", dataKey: "signups", type: "pie", color: "#18181b" },
    { seriesId: "active", seriesNm: "활성이용자", dataKey: "active", type: "pie", color: "#0f766e" },
    { seriesId: "churn", seriesNm: "이탈", dataKey: "churn", type: "pie", color: "#dc2626" },
  ]}
  xKey="label"
  type="pie"
  hideLegend={false}
  height={260}
/>
도넛 차트
jsx
const sampleData = [
  { label: "1월", signups: 120, active: 90, churn: 12 },
  { label: "2월", signups: 150, active: 110, churn: 15 },
  { label: "3월", signups: 180, active: 130, churn: 18 },
  { label: "4월", signups: 220, active: 170, churn: 16 },
  { label: "5월", signups: 240, active: 190, churn: 20 },
];

<EasyChart
  dataList={sampleDataList}
  seriesList={[
    { seriesId: "signups", seriesNm: "가입자", dataKey: "signups", type: "donut", color: "#18181b" },
    { seriesId: "active", seriesNm: "활성이용자", dataKey: "active", type: "donut", color: "#0f766e" },
    { seriesId: "churn", seriesNm: "이탈", dataKey: "churn", type: "donut", color: "#dc2626" },
  ]}
  xKey="label"
  type="donut"
  hideLegend
  height={260}
/>
로딩 상태
jsx
<EasyChart dataList={[]} seriesList={[]} xKey="label" loading hideLegend />
빈 상태
시리즈 설정이 필요합니다. dataKey와 라벨을 전달해 주세요.
jsx
<EasyChart dataList={[]} seriesList={[]} xKey="label" status="empty" empty="데이터 없음" />
에러 상태 + 에러 메시지 표시
jsx
const sampleData = [
  { label: "1월", signups: 120, active: 90, churn: 12 },
  { label: "2월", signups: 150, active: 110, churn: 15 },
  { label: "3월", signups: 180, active: 130, churn: 18 },
  { label: "4월", signups: 220, active: 170, churn: 16 },
  { label: "5월", signups: 240, active: 190, churn: 20 },
];

<EasyChart dataList={sampleDataList} seriesList={[]} xKey="label" status="error" errorText="API 에러가 발생했습니다." />

33. PDF 뷰어 (PdfViewer)

설명

로컬 파일 또는 외부 URL의 PDF를 미리봅니다. public/pdf-sample.pdf 예제가 포함되어 있습니다.

  • Props: src(string|File|Blob|ArrayBuffer), workerSrc?, withToolbar?
  • 외부 URL은 CORS 허용이 필요합니다.

public/pdf-sample.pdf 파일이 제공되면 아래 뷰어가 렌더링됩니다.

PDF 소스를 확인할 수 없습니다.

public 폴더의 pdf-sample.pdf 미리보기

jsx
<Lib.PdfViewer src="/pdf-sample.pdf" />

툴바 비활성화(페이지/검색/줌 UI 숨김)

PDF 소스를 확인할 수 없습니다.

withToolbar=false 예시

jsx
<Lib.PdfViewer src="/pdf-sample.pdf" withToolbar={false} />

로컬 파일 선택 후 뷰어로 표시

jsx
const [localFile, setLocalFile] = useState(null);

<input
  type="file"
  accept="application/pdf"
  onChange={(event) => setLocalFile(event.target.files?.[0] ?? null)}
/>
{localFile && <Lib.PdfViewer src={localFile} />}

원격 URL로 PDF 표시(서버 CORS 허용 필요)

jsx
const [remoteUrl, setRemoteUrl] = useState('');

<input
  value={remoteUrl}
  onChange={(event) => setRemoteUrl(event.target.value)}
/>
{remoteUrl && <Lib.PdfViewer src={remoteUrl} />}

오류 상태(404) 시 Empty 안내로 대체

PDF 소스를 확인할 수 없습니다.

404/네트워크 오류시 오류 안내 렌더링

jsx
<Lib.PdfViewer src="/not-exists.pdf" />