# J-Component

> Vue.js 3 기반 Atomic Design 패턴 컴포넌트 라이브러리

## 📋 프로젝트 개요

J-Component는 Vue.js 3와 TypeScript를 기반으로 한 재사용 가능한 UI 컴포넌트 라이브러리입니다. shadcn/ui 디자인 시스템과 Atomic Design 패턴을 적용하여 일관성 있고 확장 가능한 컴포넌트를 제공합니다.

## 🚀 현재 버전: v2.1.3

**최신 업데이트 (2026년 5월 7일)**
- **JFormField description 슬롯 추가**: 라벨 우측 info 아이콘 hover 팝오버 본문에 `description` named slot을 신규 노출 — 단순 문자열을 넘어 `<strong>`/`<code>`/줄바꿈/컴포넌트 등 자유로운 마크업으로 도움말을 구성할 수 있으며, 슬롯 미지정 시 기존 `description` prop 텍스트를 그대로 출력해 v2.1.2 사용처와 호환됩니다.
- **JSplitter Methods 타입 정정**: `JSplitterMethods.isFirstCollapsed` / `isSecondCollapsed` 타입을 `boolean`에서 `ComputedRef<boolean>`으로 정정해 `defineExpose`로 노출되는 실제 형태와 시그니처를 일치시켰습니다 — 외부에서 `splitterRef.value.isFirstCollapsed.value` 접근 시 누락되던 `.value`를 컴파일러가 검출합니다 (런타임 동작 변경 없음).
- **tsconfig 정리**: `tsconfig.app.json`에서 사용하지 않는 `baseUrl` 옵션을 제거해 `paths`만 사용하도록 정리했습니다 (빌드 산출물 및 외부 사용 영향 없음).

[전체 릴리즈 노트 보기](./RELEASE_NOTES.md)

## 🛠️ 기술 스택

### 핵심 프레임워크
- **Vue.js 3.5** - 프론트엔드 프레임워크
- **TypeScript 5.9** - 타입 시스템
- **Vite 7** - 빌드 도구

### UI & 스타일링
- **TailwindCSS 3.4** - 유틸리티 CSS 프레임워크
- **shadcn/ui** - 디자인 시스템 (radix-vue 기반)
- **Lucide Icons** - 아이콘 라이브러리

### 개발 도구
- **Storybook 9** - 컴포넌트 문서화 및 테스트
  - Docs 탭: 다양한 폼 스키마/도메인 예시 자동 미리보기 지원
  - 테마 셀렉터: 8가지 tweakcn 테마 지원 (Default, Slate, Rose, Blue, Green, Purple, Orange, Vescrow)
  - 다크모드 토글: 라이트/다크 모드 실시간 전환
- **ESLint 9** - 코드 품질 검사
- **Prettier** - 코드 포맷팅

## 📁 프로젝트 구조

```
jwms-portal-frontend/
├── src/
│   ├── components/          # Atomic Design Components
│   │   ├── atoms/           # 기본 UI 요소 (JButton, JInput, JIcon 등)
│   │   ├── molecules/       # atoms의 조합 (JFormField, JCard, JAlert 등)
│   │   ├── organisms/       # molecules의 조합 (JModal, JDynamicTabs, JDynamicForm 등)
│   │   ├── shadcn/          # shadcn 컴포넌트 래핑
│   │   └── templates/       # 페이지 레이아웃
│   ├── stories/             # Storybook 스토리
│   ├── types/               # TypeScript 타입 정의
│   ├── composables/         # Vue Composition Functions
│   └── services/            # API 서비스
├── docs/                    # 컴포넌트 사용 가이드
└── dist/                    # 빌드 결과물
```

## 🚀 시작하기

### 설치

```bash
# 저장소 클론
git clone <repository-url>
cd J-Component

# 의존성 설치
cd jwms-portal-frontend
npm install
# 또는
pnpm install
```

### 개발 서버 실행

```bash
# 개발 서버 시작 (http://localhost:5173)
npm run dev
```

### Storybook 실행

```bash
# Storybook 시작 (http://localhost:6006)
npm run storybook
```

**Storybook 기능:**
- 다양한 폼 레이아웃/스키마(검색, 개인정보, 섹션, Wizard 등)와 Args/Docs 자동 문서 예시 확인 가능
- 툴바에서 테마 선택 (Default, Slate, Rose, Blue, Green)
- 다크모드 토글로 라이트/다크 모드 전환

### 빌드

```bash
# 프로덕션 빌드
npm run build

# 빌드 결과 미리보기
npm run preview
```

## 📚 주요 컴포넌트

### Atoms (기본 요소)
- **JButton** - 버튼 컴포넌트
- **JInput** - 입력 필드
- **JIcon** - 아이콘 컴포넌트
- **JLabel** - 라벨 컴포넌트
- **JBadge** - 배지 컴포넌트
- **JProgress** - 진행률 표시
- **JSpinner** - 로딩 스피너
- **JGrid** - AG Grid 기반 데이터 그리드 컴포넌트 (Enterprise 기능 지원: 그룹핑, 피벗, Excel 내보내기)

### Molecules (조합 요소)
- **JFormField** - 폼 필드 래퍼
- **JCard** - 카드 컴포넌트
- **JAlert** - 알림 컴포넌트
- **JAccordion** - 아코디언 컴포넌트
- **JContextMenu** - 컨텍스트 메뉴
- **JSearchAddr** - 주소 검색 컴포넌트
- **JTabs** - 탭 컴포넌트 (탭 전환 이벤트 처리 개선, component 속성 활용 지원)
- **JButtonGroup** - 버튼 그룹 컴포넌트 (구분선 자동 표시 지원)
- **JTitlebar** - 타이틀바 컴포넌트 (제목, 설명, 팝오버 기능)

### Organisms (복합 요소)
- **JModal** - 모달 컴포넌트 (size prop 지원: sm, md, lg, xl, 2xl, full)
- **JDynamicTabs** - 동적 탭 관리
- **JDynamicForm** - 스키마 기반 동적 폼(기본/섹션/다단계, Docs 탭/다양한 예시 참조)
- **JFormModal** - JDynamicForm 기반 동적 폼 모달 컴포넌트 (size prop 지원)
- **JSearchPanel** - JDynamicForm 기반 재사용 가능한 검색 패널 (Collapsible, 조건 요약, 초기화 기능 지원)
- **JSidebarAdvanced** - 고급 사이드바 (검색, 즐겨찾기, 다단계 메뉴 지원)
- **JSidebarSimple** - 간단한 사이드바 (다단계 메뉴, 검색 지원)

### Templates (레이아웃)
- **JLayoutAdvanced** - 고급 레이아웃 (JHeader + JSidebarAdvanced + JDynamicTabs 조합)
- **JLayoutSimple** - 간단한 레이아웃 (JHeader + JSidebarSimple + JPageContainer 조합)

## 📖 사용 예시

> 💡 **컴포넌트 사용 가이드**: [사용 가이드](./docs/USAGE_GUIDE.md)에서 JDynamicTabs 경로 기반 컴포넌트 로딩 방법 등 상세 가이드를 확인하세요.

### NPM 패키지 사용 (권장)

```vue
<template>
  <div class="p-4">
    <JButton variant="primary" @click="handleClick">
      클릭하세요
    </JButton>
    
    <JFormField label="이름" required>
      <JInput v-model="name" placeholder="이름을 입력하세요" />
    </JFormField>
    
    <JAlert type="info" title="알림">
      이것은 정보 알림입니다.
    </JAlert>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { JButton, JFormField, JInput, JAlert } from '@j-solution/components'
// CSS는 자동으로 포함됩니다 - 별도 import 불필요

const name = ref('')

const handleClick = () => {
  console.log('버튼 클릭됨')
}
</script>
```

> 💡 **참고**: NPM 패키지는 패키지 진입점에서 CSS가 자동으로 import되므로, 컴포넌트만 import하면 스타일이 자동으로 적용됩니다.

### Standard 방식 사용 (파일 복사)

```vue
<template>
  <div class="p-4">
    <JButton variant="primary" @click="handleClick">
      클릭하세요
    </JButton>
    
    <JFormField label="이름" required>
      <JInput v-model="name" placeholder="이름을 입력하세요" />
    </JFormField>
    
    <JAlert type="info" title="알림">
      이것은 정보 알림입니다.
    </JAlert>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { JButton, JFormField, JInput, JAlert } from '@/components'

const name = ref('')

const handleClick = () => {
  console.log('버튼 클릭됨')
}
</script>
```

### 주소 검색 컴포넌트

```vue
<template>
  <JSearchAddr 
    v-model="address" 
    @select="handleAddressSelect"
    placeholder="주소를 검색하세요"
  />
</template>

<script setup>
import { ref } from 'vue'
import { JSearchAddr } from '@/components/molecules'

const address = ref('')

const handleAddressSelect = (selectedAddress) => {
  console.log('선택된 주소:', selectedAddress)
}
</script>
```

## 📚 문서 가이드

> **모든 문서는 이 README.md를 기준으로 연결되어 있습니다.**

### 📖 주요 문서

| 문서 | 설명 | 대상 |
|------|------|------|
| **[설치 가이드](./docs/INSTALLATION_GUIDE.md)** | 처음 설치하는 방법 | Standard 방식, NPM 방식 설치 가이드 |
| **[업데이트 가이드](./docs/UPDATE_GUIDE.md)** | 버전 업데이트 방법 | Standard 방식, NPM 방식 업데이트 가이드 |
| **[사용 가이드](./docs/USAGE_GUIDE.md)** | 컴포넌트 사용 방법 | 컴포넌트 목록, 사용 예시, 권장사항 |
| **[릴리즈 노트](./RELEASE_NOTES.md)** | 버전별 변경사항 | 모든 버전의 변경 이력 |

### 📦 패키지 문서

패키지에 포함된 문서들 (원본: `docs/` 디렉토리):

- **`packages/v{version}/README.md`**: 패키지 소개 및 설치 방법
- **`packages/v{version}/USAGE_GUIDE.md`**: 컴포넌트 사용 가이드
- **`packages/v{version}/UPDATE_GUIDE.md`**: 버전 업데이트 가이드

> 💡 **참고**: 패키지 문서는 `docs/` 디렉토리의 원본을 기반으로 패키징 시 자동으로 포함됩니다.

### 🗺️ 문서 구조

```
J-Component/
├── README.md                    # 메인 문서 (이 파일)
├── RELEASE_NOTES.md             # 릴리즈 노트
├── docs/                        # 문서 원본
│   ├── INSTALLATION_GUIDE.md    # 설치 가이드
│   ├── UPDATE_GUIDE.md          # 업데이트 가이드
│   └── USAGE_GUIDE.md           # 사용 가이드
└── packages/                    # 배포 패키지
    └── v{version}/
        ├── README.md            # (docs에서 복사)
        ├── USAGE_GUIDE.md      # (docs에서 복사)
        └── UPDATE_GUIDE.md     # (docs에서 복사)
```

---

## 📦 컴포넌트 패키징 및 배포

> **⚠️ 중요**: 패키지를 생성하거나 버전을 업데이트하기 전에 **반드시** 다음 문서를 참조하세요:
> - **상세 가이드**: [`jwms-portal-frontend/PACKAGING.md`](./jwms-portal-frontend/PACKAGING.md)
> - **빠른 참조**: [`PACKAGING_GUIDE.md`](./PACKAGING_GUIDE.md)

J-Component는 **두 가지 배포 방식**을 지원합니다:

### 🚀 통합 패키징 (권장)

**하나의 명령어로 두 가지 방식 모두 생성:**

```bash
cd jwms-portal-frontend
npm run package
```

이 명령어는 다음을 자동으로 실행합니다:
1. **Standard 방식**: `packages/v{version}/` 디렉토리에 파일 복사 방식 패키지 생성
2. **NPM 방식**: `dist/npm/` 디렉토리에 npm 패키지 생성

### 1) Standard 방식 (파일 복사)

- **출력 위치**: `packages/v{version}/`
- **사용 방법**: 타겟 프로젝트에 파일을 직접 복사하여 사용
- **특징**: 
  - 기존 프로젝트 구조와 동일
  - Git에 커밋 가능 (버전별 스냅샷)
  - `packages/latest/standard/`에 최신 버전 포인터 제공

### 2) NPM 방식 (npm 패키지)

- **출력 위치**: `dist/npm/`
- **사용 방법**: 
  - 로컬 테스트: `npm install file:../path/to/dist/npm`
  - npm 레지스트리: `npm install @j-solution/components` (배포 후)
- **특징**:
  - ES Module + CommonJS + TypeScript 타입 정의 포함
  - 가상 모듈 자동 인라인 처리
  - `dist` 디렉토리는 `.gitignore`에 포함 (빌드 시 자동 생성)

#### NPM 패키지 배포

```bash
# 로컬에서 빌드 및 배포
cd jwms-portal-frontend/dist/npm
npm publish --access public
# 또는
pnpm publish --access public
```

#### 자동 배포 (GitHub Actions)
- GitHub에서 Release를 생성하면 자동으로 npm 레지스트리에 배포
- `.github/workflows/publish-npm.yml` 워크플로우 자동 실행
- `NPM_TOKEN` 시크릿 필요

### ⚠️ 중요 사항

- **v1.0.0부터 namespaced 방식 지원 중단**
  - 기존: standard, namespaced, npm (3가지)
  - 현재: standard, npm (2가지)
  - namespaced 방식은 npm 방식으로 대체됨

### 개별 패키징

필요한 경우 개별로 실행할 수 있습니다:

```bash
# Standard 방식만
npm run package:standard

# NPM 방식만
npm run package:npm
```

자세한 내용: [PACKAGING.md](./jwms-portal-frontend/PACKAGING.md)

> 💡 **설치 및 업데이트 방법**: [설치 가이드](./docs/INSTALLATION_GUIDE.md) 및 [업데이트 가이드](./docs/UPDATE_GUIDE.md)를 참고하세요.

### 패키지 다운로드

패키지 폴더만 다운로드하는 방법 (전체 리포지토리 클론 불필요):

**⭐ 추천: Git Sparse Checkout** (패키지 폴더만 다운로드):
```bash
# Public 리포지토리
git clone --depth 1 --filter=blob:none --sparse <repository-url>
cd J-Component
git sparse-checkout set packages/v1.0.0
# 또는 packages/latest/standard

# Private 리포지토리 (인증 필요)
git clone --depth 1 --filter=blob:none --sparse git@github.com:<username>/<repository>.git
cd J-Component
git sparse-checkout set packages/v1.0.0
```

**다른 방법들**:
- GitHub 웹 인터페이스에서 특정 디렉토리 ZIP 다운로드
- GitHub API 사용
- Git Submodule 사용

> **📝 참고**: 각 패키지의 `README.md`에 상세한 다운로드 방법이 안내되어 있습니다.

## 🔧 개발 가이드

### 컴포넌트 작성 규칙

1. **Atomic Design 패턴** 준수
2. **TypeScript** 타입 정의 필수
3. **Props** 인터페이스 정의
4. **Storybook** 스토리 작성
5. **Tailwind CSS** 스타일링

### 컴포넌트 템플릿

```vue
<template>
  <div class="j-component">
    <!-- 컴포넌트 내용 -->
  </div>
</template>

<script setup lang="ts">
interface Props {
  variant?: 'primary' | 'secondary'
  size?: 'sm' | 'md' | 'lg'
  disabled?: boolean
}

interface Emits {
  (e: 'click', value: string): void
}

const props = withDefaults(defineProps<Props>(), {
  variant: 'primary',
  size: 'md',
  disabled: false
})

const emit = defineEmits<Emits>()
</script>
```
