0.4.4 • Published 7 months ago

@gcsc/common-compo v0.4.4

Weekly downloads
-
License
MIT
Repository
-
Last release
7 months ago

Vue 3 + TypeScript + Vite 공통 컴포넌트 패키지

1. BaseList 컴포넌트

1-1) 요약

BaseList는 세 가지 모드(기본, 드래그 가능, 트리 구조)를 지원하는 다목적 리스트 컴포넌트입니다. 체크박스 기능, 드래그 앤 드롭, 트리 구조의 계층형 데이터를 표시할 수 있으며, 각 요소를 슬롯을 통해 커스터마이징할 수 있습니다.

1-2) Props

Prop 이름타입필수기본값설명
itemsListItem[]-리스트에 표시할 아이템 배열
draggableboolean-false드래그 앤 드롭 기능 활성화
treeboolean-false트리 구조 활성화
checkableboolean-false체크박스 기능 활성화

1-3) Slots

Slot 이름Props설명
header-checkbox-content-전체 선택 헤더 커스터마이징
item-checkbox{ item, checked }아이템 체크박스 커스터마이징
item-image{ item }아이템 이미지 커스터마이징
item-header{ item }아이템 헤더 영역 커스터마이징
item-title{ item }아이템 제목 커스터마이징
item-time{ item }아이템 시간 커스터마이징
item-preview{ item }아이템 미리보기 커스터마이징
tree-toggle{ item }트리 토글 버튼 커스터마이징
child-item-checkbox{ item, checked }자식 아이템 체크박스 커스터마이징
child-item-image{ item }자식 아이템 이미지 커스터마이징
child-item-header{ item }자식 아이템 헤더 커스터마이징
child-item-title{ item }자식 아이템 제목 커스터마이징
child-item-time{ item }자식 아이템 시간 커스터마이징
child-item-preview{ item }자식 아이템 미리보기 커스터마이징

1-4) Events

이벤트 이름파라미터설명
itemClick(item: ListItem)아이템 클릭 시 발생
check(checkedItems: number[])체크박스 상태 변경 시 발생
checkAll(checked: boolean)전체 선택/해제 시 발생
update:items(items: ListItem[])드래그로 순서 변경 시 발생
update:modelValue(value: number[])선택된 아이템 ID 배열 업데이트

1-5) 타입 정의

interface ListItem {
  id: number;
  imageUrl: string;
  title: string;
  preview: string;
  time: string | Date;
  checked?: boolean;
  children?: ListItem[];
  isOpen?: boolean;
}

interface BaseListProps {
  modelValue?: number[];
  items: ListItem[];
  draggable?: boolean;
  tree?: boolean;
  checkable?: boolean;
}

type BaseListEmits = {
  (e: 'itemClick', item: ListItem): void;
  (e: 'update:items', items: ListItem[]): void;
  (e: 'update:modelValue', value: number[]): void;
  (e: 'check', checkedItems: number[]): void;
  (e: 'checkAll', checked: boolean): void;
}

1-6) 사용 예시

1-6-1) 기본 리스트
<template>
  <BaseList 
    :items="items"
    :checkable="true"
    @item-click="handleItemClick"
  >
    <template #item-title="{ item }">
      <div class="custom-title">{{ item.title }}</div>
    </template>
  </BaseList>
</template>
1-6-2) 드래거블 리스트
<template>
  <BaseList 
    :items="items"
    :draggable="true"
    @update:items="handleReorder"
  >
    <template #item-preview="{ item }">
      <div class="preview-with-badge">
        <span class="badge">{{ item.category }}</span>
        <p>{{ item.preview }}</p>
      </div>
    </template>
  </BaseList>
</template>
1-6-3) 트리 리스트
<template>
  <BaseList 
    :items="treeItems"
    :tree="true"
    :checkable="true"
    @check="handleCheck"
  >
    <template #tree-toggle="{ item }">
      <i :class="['tree-icon', item.isOpen ? 'open' : 'closed']" />
    </template>
    
    <template #child-item-title="{ item }">
      <span class="child-title">{{ item.title }}</span>
    </template>
  </BaseList>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { ListItem } from '@/components/BaseList.vue'

// 리스트 아이템 데이터
const items = ref<ListItem[]>([
  {
    id: 1,
    imageUrl: 'https://example.com/image1.jpg',
    title: '첫 번째 아이템',
    preview: '이것은 첫 번째 아이템의 미리보기입니다.',
    time: new Date(),
    checked: false
  },
  {
    id: 2,
    imageUrl: 'https://example.com/image2.jpg',
    title: '두 번째 아이템',
    preview: '이것은 두 번째 아이템의 미리보기입니다.',
    time: new Date(),
    checked: false
  },
    
...(생략)
</script>

2. BaseTable 컴포넌트

2-1) 요약

BaseTable은 정렬 기능을 지원하는 기본 테이블 컴포넌트입니다. 컬럼별 정렬, 행 클릭 이벤트, 슬롯을 통한 커스텀 셀 렌더링을 지원하며, 데이터가 없을 경우 안내 메시지를 표시합니다.

2-2) Props

Prop 이름타입필수기본값설명
columnsTableColumn[]-테이블 컬럼 설정 배열
dataTableItem[]-테이블에 표시할 데이터 배열

2-3) Slots

Slot 이름Props설명
column.key{ row: TableItem }각 컬럼별 커스텀 셀 렌더링

2-4) Events

이벤트 이름파라미터설명
row-click(row: TableItem)행 클릭 시 발생
sort(sortStates: SortState[])정렬 상태 변경 시 발생

2-5) 타입 정의

interface TableColumn {
  key: string;
  label: string;
  sortable?: boolean;
}

interface TableItem {
  [key: string]: any;
}

interface SortState {
  column: string;
  direction: 'asc' | 'desc';
}

interface TableProps {
  columns: TableColumn[];
  data: TableItem[];
}

type TableEmits = {
  (e: 'row-click', row: TableItem): void;
  (e: 'sort', sortStates: SortState[]): void;
}

2-6) 사용 예시

<template>
  <BaseTable
      :columns="columns"
      :data="tableData"
      @row-click="handleRowClick"
      @sort="handleSort"
  >
    <!-- 이름 컬럼 커스터마이징 -->
    <template #name="{ row }">
      <div class="user-name">
        <img :src="row.avatar" :alt="row.name" class="avatar">
        <span>{{ row.name }}</span>
      </div>
    </template>

    <!-- 상태 컬럼 커스터마이징 -->
    <template #status="{ row }">
      <span :class="['status-badge', row.status]">
        {{ row.status }}
      </span>
    </template>
  </BaseTable>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { TableColumn, TableItem, SortState } from '@gcsc/common-compo'

// 컬럼 정의
const columns: TableColumn[] = [
  { key: 'name', label: '이름', sortable: true },
  { key: 'email', label: '이메일', sortable: true },
  { key: 'status', label: '상태', sortable: true },
  { key: 'createdAt', label: '생성일', sortable: true }
]

// 테이블 데이터
const tableData = ref<TableItem[]>([
  {
    name: '홍길동',
    email: 'hong@example.com',
    status: 'active',
    createdAt: '2024-03-20',
    avatar: 'https://example.com/avatar1.jpg'
  },
  // ... 더 많은 데이터
])

...(생략)
</script>

3. BaseCalendar 컴포넌트

3-1) 요약

BaseCalendar는 날짜와 시간을 선택할 수 있는 캘린더 컴포넌트입니다. 연도, 월, 일 선택 기능을 제공하며, 시간 선택 옵션도 포함되어 있습니다. 다양한 뷰(연도, 월, 일)를 지원하고 날짜 범위 선택이 가능합니다.

3-2) Props

Prop 이름타입필수기본값설명
modelValueDateRange-{ start: null, end: null }선택된 날짜 범위
currentDateDayjs-dayjs()현재 날짜
startDatestring | null-null시작 날짜
endDatestring | null-null종료 날짜
selectedInput'start' | 'end' | null-null선택된 입력 필드
enableTimeSelectionboolean-false시간 선택 활성화
minDatestring | undefined-undefined최소 선택 가능 날짜
maxDatestring | undefined-undefined최대 선택 가능 날짜
disabledDatesstring[]-[]비활성화된 날짜 배열
firstDayOfWeeknumber-0주의 첫 번째 요일

3-3) Slots

Slot 이름Props설명
close-button-닫기 버튼 커스터마이징
time-selection{ startDate, endDate, startTime, endTime, updateStartTime, updateEndTime }시간 선택 영역 커스터마이징
footer{ onRefresh, onCancel, onApply }푸터 영역 커스터마이징

3-4) Events

이벤트 이름파라미터설명
select(range: DateRange)날짜/시간 선택 시 발생
apply(range: DateRange)선택 적용 시 발생
cancel-취소 시 발생

3-5) 타입 정의

interface DateRange {
  start: string | null;
  end: string | null;
}

interface TimeValue {
  hours: number;
  minutes: number;
}

type CalendarView = 'calendar' | 'month' | 'year';

interface CalendarProps {
  modelValue?: DateRange;
  currentDate?: Dayjs;
  startDate?: string | null;
  endDate?: string | null;
  selectedInput?: 'start' | 'end' | null;
  enableTimeSelection?: boolean;
  minDate?: string;
  maxDate?: string;
  disabledDates?: string[];
  firstDayOfWeek?: number;
}

3-6) 사용 예시

<template>
  <BaseCalendar
    v-model="dateRange"
    :enable-time-selection="true"
    @select="handleDateSelect"
    @apply="handleApply"
    @cancel="handleCancel"
  >
    <!-- 닫기 버튼 커스터마이징 -->
    <template #close-button>
      <button class="close-btn">×</button>
    </template>

    <!-- 시간 선택 영역 커스터마이징 -->
    <template #time-selection="{ startTime, endTime, updateStartTime, updateEndTime }">
      <div class="custom-time-selector">
        <TimeSelector
          :start-time="startTime"
          :end-time="endTime"
          @update:start-time="updateStartTime"
          @update:end-time="updateEndTime"
        />
      </div>
    </template>

    <!-- 푸터 영역 커스터마이징 -->
    <template #footer="{ onApply, onCancel }">
      <div class="custom-footer">
        <button @click="onCancel">취소</button>
        <button @click="onApply">확인</button>
      </div>
    </template>
  </BaseCalendar>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import type { DateRange } from '@gcsc/common-compo'

const dateRange = ref<DateRange>({
  start: null,
  end: null
})

...(생략)
</script>

4. InputCalendar 컴포넌트

4-1) 요약

InputCalendar는 날짜 범위를 선택할 수 있는 입력 필드와 캘린더 팝업을 제공하는 컴포넌트입니다. 시작일과 종료일을 선택할 수 있으며, 시간 선택 옵션도 지원합니다. 두 개의 연속된 캘린더를 통해 직관적인 날짜 범위 선택이 가능합니다.

4-2) Props

Prop 이름타입필수기본값설명
modelValueDateRange-선택된 날짜 범위
enableTimeSelectionboolean-false시간 선택 기능 활성화
placeholderstring--입력 필드 플레이스홀더

4-3) Slots

Slot 이름Props설명
close-button{ onCancel }닫기 버튼 커스터마이징
footer{ onRefresh, onCancel, onApply }푸터 영역 커스터마이징

4-4) Events

이벤트 이름파라미터설명
update:modelValue(value: DateRange)날짜 범위 변경 시 발생
cancel-캘린더 닫기 시 발생

4-5) 타입 정의

interface DateRange {
  start: string | null;
  end: string | null;
}

interface DateTime {
  date: string;
  fullInput: string;
  time: {
    hours: number;
    minutes: number;
  };
}

interface InputCalendarProps {
  modelValue: DateRange;
  enableTimeSelection?: boolean;
  placeholder?: string;
}

interface DateInfo {
  date: string;
  day: number;
  currentMonth: boolean;
}

4-6) 사용 예시

<template>
  <InputCalendar
    v-model="dateRange"
    :enable-time-selection="true"
    placeholder="YYYY-MM-DD HH:mm"
    @cancel="handleCancel"
  >
    <!-- 닫기 버튼 커스터마이징 -->
    <template #close-button="{ onCancel }">
      <button class="close-btn" @click="onCancel">×</button>
    </template>

    <!-- 푸터 커스터마이징 -->
    <template #footer="{ onRefresh, onCancel, onApply }">
      <div class="calendar-footer">
        <button @click="onRefresh">초기화</button>
        <button @click="onCancel">취소</button>
        <button @click="onApply">확인</button>
      </div>
    </template>
  </InputCalendar>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import type { DateRange } from '@gcsc/common-compo'

const dateRange = ref<DateRange>({
  start: null,
  end: null
})

...(생략)
</script>

5. BaseCheckbox 컴포넌트

5-1) 요약

BaseCheckbox는 단일 체크박스와 다중 선택(체크박스/라디오) 기능을 제공하는 컴포넌트입니다. 전체 선택 기능과 개별 항목 선택이 가능하며, 비활성화 상태도 지원합니다. 체크박스와 라디오 버튼 두 가지 타입을 제공합니다.

5-2) Props

Prop 이름타입필수기본값설명
modelValueboolean | (string | number)[] | string | numberfalse선택된 값
itemsCheckboxItem[]-[]선택 항목 배열
labelstring-''단일 체크박스 라벨
type'checkbox' | 'radio'-'checkbox'체크박스 타입
namestring-''입력 필드 이름
disabledboolean-false비활성화 여부

5-3) Slots

Slot 이름Props설명
default-단일 체크박스 라벨 커스터마이징
select-all{ allChecked, indeterminate, toggleAll }전체 선택 영역 커스터마이징

5-4) Events

이벤트 이름파라미터설명
update:modelValue(value: boolean | (string | number)[] | string | number)값 변경 시 발생
check(value: boolean | (string | number)[] | string | number)항목 선택 시 발생
checkAll(checked: boolean)전체 선택/해제 시 발생

5-5) 타입 정의

interface CheckboxItem {
  id: number;
  label: string;
}

interface CheckboxProps {
  modelValue?: boolean | (string | number)[] | string | number;
  items?: CheckboxItem[];
  label?: string;
  type?: 'checkbox' | 'radio';
  name?: string;
  disabled?: boolean;
}

type CheckboxEmits = {
  (e: 'update:modelValue', value: boolean | (string | number)[] | string | number): void;
  (e: 'check', value: boolean | (string | number)[] | string | number): void;
  (e: 'checkAll', checked: boolean): void;
}

5-6) 사용 예시

<template>
  <!-- 단일 체크박스 -->
  <BaseCheckbox
    v-model="isChecked"
    label="동의합니다"
    @check="handleCheck"
  />

  <!-- 다중 체크박스 -->
  <BaseCheckbox
    v-model="selectedItems"
    :items="checkboxItems"
    type="checkbox"
    @check="handleItemsCheck"
    @checkAll="handleCheckAll"
  >
    <!-- 전체 선택 커스터마이징 -->
    <template #select-all="{ allChecked, indeterminate, toggleAll }">
      <div class="select-all-wrapper">
        <label class="checkbox-item">
          <input
            type="checkbox"
            :checked="allChecked"
            :indeterminate="indeterminate"
            @change="toggleAll"
          />
          <span class="item-label">전체 선택</span>
        </label>
      </div>
    </template>
  </BaseCheckbox>

  <!-- 라디오 버튼 -->
  <BaseCheckbox
    v-model="selectedOption"
    :items="radioItems"
    type="radio"
    name="options"
    @check="handleOptionSelect"
  />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import type { CheckboxItem } from '@gcsc/common-compo'

// 단일 체크박스
const isChecked = ref(false)
const handleCheck = (checked: boolean) => {
console.log('체크 상태:', checked)
}

// 다중 체크박스
const checkboxItems: CheckboxItem[] = [
{ id: 1, label: '옵션 1' },
{ id: 2, label: '옵션 2' },
{ id: 3, label: '옵션 3' }
]
const selectedItems = ref<(string | number)[]>([])

const handleItemsCheck = (items: (string | number)[]) => {
console.log('선택된 항목:', items)
}

const handleCheckAll = (checked: boolean) => {
console.log('전체 선택:', checked)
}

// 라디오 버튼
const radioItems: CheckboxItem[] = [
{ id: 1, label: '라디오 1' },
{ id: 2, label: '라디오 2' },
{ id: 3, label: '라디오 3' }
]
const selectedOption = ref<number | null>(null)

const handleOptionSelect = (option: number) => {
console.log('선택된 옵션:', option)
}
</script>

6. ListCheckbox 컴포넌트

6-1) 요약

ListCheckbox는 리스트 형태의 항목들에 대한 체크박스 기능을 제공하는 컴포넌트입니다. 전체 선택/해제 기능과 개별 항목 선택이 가능하며, 선택된 항목 수를 표시합니다. 리스트의 헤더에 위치하여 일괄적인 항목 선택을 관리합니다.

6-2) Props

Prop 이름타입필수기본값설명
itemsListItem[][]체크박스 항목 배열
modelValuenumber[][]선택된 항목 ID 배열

6-3) Slots

Slot 이름Props설명
header-checkbox{ allChecked, indeterminate, toggleAll }헤더 체크박스 영역 커스터마이징
header-checkbox-content-헤더 체크박스 내용 커스터마이징

6-4) Events

이벤트 이름파라미터설명
update:modelValue(value: number[])선택된 항목 배열 변경 시 발생
check(checkedIds: number[])항목 선택/해제 시 발생
checkAll(checked: boolean)전체 선택/해제 시 발생

6-5) 타입 정의

interface ListItem {
  id: number;
  label: string;
}

interface ListCheckboxProps {
  items: ListItem[];
  modelValue: number[];
}

type BaseListEmits = {
  (e: 'update:modelValue', value: number[]): void;
  (e: 'check', checkedIds: number[]): void;
  (e: 'checkAll', checked: boolean): void;
}

6-6) 사용예시

<template>
  <ListCheckbox
    v-model="selectedItems"
    :items="listItems"
    @check="handleCheck"
    @checkAll="handleCheckAll"
  >
    <!-- 헤더 체크박스 커스터마이징 -->
    <template #header-checkbox="{ allChecked, indeterminate, toggleAll }">
      <div class="custom-header-checkbox">
        <label>
          <input
            type="checkbox"
            :checked="allChecked"
            :indeterminate="indeterminate"
            @change="toggleAll"
          />
          <slot name="header-checkbox-content">
            <span class="selection-count">
              선택된 항목: {{ selectedItems.length }}/{{ listItems.length }}
            </span>
          </slot>
        </label>
      </div>
    </template>
  </ListCheckbox>

  <!-- 리스트 항목들 -->
  <div class="list-items">
    <div
      v-for="item in listItems"
      :key="item.id"
      class="list-item"
      @click="toggleItem(item.id, $event)"
    >
      <input
        type="checkbox"
        :checked="isChecked(item.id)"
        @change="e => e.stopPropagation()"
      />
      <span>{{ item.label }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import type { ListItem } from '@gcsc/common-compo'

// 리스트 항목 데이터
const listItems: ListItem[] = [
  { id: 1, label: '항목 1' },
  { id: 2, label: '항목 2' },
  { id: 3, label: '항목 3' },
  { id: 4, label: '항목 4' }
]

const selectedItems = ref<number[]>([])

// 이벤트 핸들러
const handleCheck = (checkedIds: number[]) => {
  console.log('선택된 항목:', checkedIds)
}

const handleCheckAll = (checked: boolean) => {
  console.log('전체 선택 상태:', checked)
}

// 항목 토글 함수
const toggleItem = (itemId: number, event: Event) => {
  event.stopPropagation()
  const index = selectedItems.value.indexOf(itemId)
  if (index === -1) {
    selectedItems.value.push(itemId)
  } else {
    selectedItems.value.splice(index, 1)
  }
}
</script>

7. BaseButton 컴포넌트

7-1) 요약

BaseButton은 다양한 스타일과 기능을 제공하는 기본 버튼 컴포넌트입니다. 다양한 변형(variant)을 지원하며, 비활성화 상태와 타입(button, submit, reset)을 설정할 수 있습니다. 클릭과 제출 이벤트를 처리할 수 있습니다.

7-2) Props

Prop 이름타입필수기본값설명
variant'primary' | 'secondary' | 'outline' | 'text'-버튼 스타일 변형
disabledboolean-false비활성화 여부
type'button' | 'submit' | 'reset'-'button'버튼 타입

7-3) Slots

Slot 이름Props설명
default-버튼 내용 커스터마이징

7-4) Events

이벤트 이름파라미터설명
click(event: MouseEvent)클릭 시 발생
submit(event: Event)제출 시 발생

7-5) 타입 정의

type ButtonVariant = 'primary' | 'secondary' | 'outline' | 'text';
type ButtonType = 'button' | 'submit' | 'reset';

interface ButtonProps {
  variant: ButtonVariant;
  disabled?: boolean;
  type?: ButtonType;
}

type ButtonEmits = {
  (e: 'click', event: MouseEvent): void;
  (e: 'submit', event: Event): void;
}

7-6) 사용 예시

<template>
  <div class="button-examples">
    <!-- 기본 버튼 -->
    <BaseButton
      variant="primary"
      @click="handleClick"
    >
      기본 버튼
    </BaseButton>

    <!-- 제출 버튼 -->
    <BaseButton
      variant="primary"
      type="submit"
      @submit="handleSubmit"
    >
      제출
    </BaseButton>

    <!-- 비활성화된 버튼 -->
    <BaseButton
      variant="secondary"
      :disabled="true"
    >
      비활성화
    </BaseButton>

    <!-- 아이콘이 있는 버튼 -->
    <BaseButton
      variant="outline"
      @click="handleIconClick"
    >
      <i class="icon">+</i>
      아이콘 버튼
    </BaseButton>

    <!-- 텍스트 버튼 -->
    <BaseButton
      variant="text"
      @click="handleTextClick"
    >
      텍스트 버튼
    </BaseButton>
  </div>
</template>

<script setup lang="ts">
const handleClick = (event: MouseEvent) => {
  console.log('버튼 클릭:', event)
}

const handleSubmit = (event: Event) => {
  console.log('폼 제출:', event)
}

const handleIconClick = () => {
  console.log('아이콘 버튼 클릭')
}

const handleTextClick = () => {
  console.log('텍스트 버튼 클릭')
}
</script>

8. BaseInput 컴포넌트

8-1) 요약

BaseInput은 다양한 스타일과 기능을 제공하는 기본 입력 필드 컴포넌트입니다. 다양한 변형(variant)을 지원하며, 비활성화 상태와 필수 입력 여부를 설정할 수 있습니다. v-model을 통한 양방향 바인딩을 지원합니다.

8-2) Props

Prop 이름타입필수기본값설명
modelValuestring-입력 필드 값
variant'default' | 'primary' | 'error'-'default'입력 필드 스타일 변형
type'text' | 'password' | 'email' | 'number'-'text'입력 필드 타입
disabledboolean-false비활성화 여부
placeholderstring--플레이스홀더 텍스트
requiredboolean-false필수 입력 여부

8-3) Events

이벤트 이름파라미터설명
update:modelValue(value: string)입력값 변경 시 발생

8-4) 타입 정의

type InputVariant = 'default' | 'primary' | 'error';
type InputType = 'text' | 'password' | 'email' | 'number';

interface InputProps {
  modelValue: string;
  variant?: InputVariant;
  type?: InputType;
  disabled?: boolean;
  placeholder?: string;
  required?: boolean;
}

type InputEmits = {
  (e: 'update:modelValue', value: string): void;
}

8-5) 사용 예시

<template>
  <div class="input-examples">
    <!-- 기본 입력 필드 -->
    <BaseInput
      v-model="textValue"
      placeholder="기본 입력"
    />

    <!-- 비밀번호 입력 필드 -->
    <BaseInput
      v-model="passwordValue"
      type="password"
      placeholder="비밀번호 입력"
    />

    <!-- 이메일 입력 필드 -->
    <BaseInput
      v-model="emailValue"
      type="email"
      placeholder="이메일 입력"
      required
    />

    <!-- 숫자 입력 필드 -->
    <BaseInput
      v-model="numberValue"
      type="number"
      placeholder="숫자 입력"
    />

    <!-- 에러 상태 입력 필드 -->
    <BaseInput
      v-model="errorValue"
      variant="error"
      placeholder="에러 상태"
    />

    <!-- 비활성화된 입력 필드 -->
    <BaseInput
      v-model="disabledValue"
      disabled
      placeholder="비활성화"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const textValue = ref('')
const passwordValue = ref('')
const emailValue = ref('')
const numberValue = ref('')
const errorValue = ref('')
const disabledValue = ref('비활성화된 값')
</script>

9. BaseSelect 컴포넌트

9-1) 요약

BaseSelect는 드롭다운 선택 필드를 제공하는 컴포넌트입니다. 옵션 배열을 통한 동적 렌더링과 사용자 정의 옵션을 위한 슬롯을 지원합니다. 플레이스홀더, 비활성화 상태, 필수 입력 여부를 설정할 수 있으며, 다양한 스타일 변형을 제공합니다.

9-2) Props

Prop 이름타입필수기본값설명
modelValuestring-선택된 값
optionsSelectOption[]-선택 옵션 배열
variant'default' | 'primary' | 'error'-'default'선택 필드 스타일 변형
withAccompanyboolean-false동반 요소 표시 여부
disabledboolean-false비활성화 여부
requiredboolean-false필수 선택 여부
placeholderstring--플레이스홀더 텍스트

9-3) Slots

Slot 이름Props설명
default-사용자 정의 옵션을 위한 슬롯

9-4) Events

이벤트 이름파라미터설명
update:modelValue(value: string)선택값 변경 시 발생

9-5) 타입 정의

type SelectVariant = 'default' | 'primary' | 'error';

interface SelectOption {
  value: string;
  label: string;
  disabled?: boolean;
}

interface SelectProps {
  modelValue: string;
  options: SelectOption[];
  variant?: SelectVariant;
  withAccompany?: boolean;
  disabled?: boolean;
  required?: boolean;
  placeholder?: string;
}

type SelectEmits = {
  (e: 'update:modelValue', value: string): void;
}

9-6) 사용 예시

<template>
  <div class="select-examples">
    <!-- 기본 선택 필드 -->
    <BaseSelect
      v-model="selectedValue"
      :options="options"
      placeholder="선택하세요"
    />

    <!-- 동반 요소가 있는 선택 필드 -->
    <BaseSelect
      v-model="accompanyValue"
      :options="options"
      with-accompany
      placeholder="동반 요소 선택"
    >
      <template #accompany>
        <span class="accompany-text">동반</span>
      </template>
    </BaseSelect>

    <!-- 에러 상태 선택 필드 -->
    <BaseSelect
      v-model="errorValue"
      :options="options"
      variant="error"
      placeholder="에러 상태"
    />

    <!-- 비활성화된 선택 필드 -->
    <BaseSelect
      v-model="disabledValue"
      :options="options"
      disabled
      placeholder="비활성화"
    />

    <!-- 사용자 정의 옵션이 있는 선택 필드 -->
    <BaseSelect
      v-model="customValue"
      :options="options"
      placeholder="사용자 정의 옵션"
    >
      <option value="custom1">사용자 정의 옵션 1</option>
      <option value="custom2">사용자 정의 옵션 2</option>
    </BaseSelect>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import type { Option } from '@gcsc/common-compo'

const options: Option[] = [
  { value: 'option1', label: '옵션 1' },
  { value: 'option2', label: '옵션 2' },
  { value: 'option3', label: '옵션 3', disabled: true },
  { value: 'option4', label: '옵션 4' }
]

const selectedValue = ref('')
const accompanyValue = ref('')
const errorValue = ref('')
const disabledValue = ref('option1')
const customValue = ref('')
</script>

10. BaseDialog 컴포넌트

10-1) 요약

BaseDialog은 드래그 가능한 모달 다이얼로그를 제공하는 컴포넌트입니다. 오버레이, 헤더, 컨텐츠, 푸터 영역을 포함하며, 커스터마이징 가능한 슬롯을 제공합니다. 확인/취소 버튼을 기본으로 제공하며, 오버레이 클릭 시 닫기 옵션을 지원합니다.

10-2) Props

Prop 이름타입필수기본값설명
modelValueboolean-모달 표시 여부
titlestring-'알림'모달 제목
contentstring-''모달 내용
showConfirmboolean-true확인 버튼 표시 여부
showCancelboolean-true취소 버튼 표시 여부
confirmTextstring-'확인'확인 버튼 텍스트
cancelTextstring-'취소'취소 버튼 텍스트
closeOnOverlayClickboolean-true오버레이 클릭 시 닫기 여부

10-3) Slots

Slot 이름Props설명
title-제목 영역 커스터마이징
content-내용 영역 커스터마이징
footer{ close }푸터 영역 커스터마이징
buttons{ close }버튼 영역 커스터마이징

10-4) Events

이벤트 이름파라미터설명
update:modelValue(value: boolean)모달 표시 상태 변경 시 발생
confirm-확인 버튼 클릭 시 발생
cancel-취소 버튼 클릭 시 발생

10-5) 타입 정의

interface DialogProps {
  modelValue: boolean;
  title?: string;
  content?: string;
  showConfirm?: boolean;
  showCancel?: boolean;
  confirmText?: string;
  cancelText?: string;
  closeOnOverlayClick?: boolean;
}

type DilogEmits = {
  (e: 'update:modelValue', value: boolean): void;
  (e: 'confirm'): void;
  (e: 'cancel'): void;
}

10-6) 사용 예시

<template>
  <BaseDialog
    v-model="showDialog"
    title="사용자 정보"
    @confirm="handleConfirm"
    @cancel="handleCancel"
  >
    <!-- 제목 커스터마이징 -->
    <template #title>
      <h2 class="custom-title">사용자 정보 수정</h2>
    </template>

    <!-- 내용 커스터마이징 -->
    <template #content>
      <div class="user-form">
        <div class="form-group">
          <label>이름</label>
          <input v-model="userName" type="text" />
        </div>
        <div class="form-group">
          <label>이메일</label>
          <input v-model="userEmail" type="email" />
        </div>
      </div>
    </template>

    <!-- 버튼 커스터마이징 -->
    <template #buttons="{ close }">
      <button class="custom-button save" @click="handleSave">저장</button>
      <button class="custom-button cancel" @click="close">닫기</button>
    </template>
  </BaseDialog>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const showDialog = ref(false)
const userName = ref('')
const userEmail = ref('')

const handleConfirm = () => {
  console.log('확인 버튼 클릭')
}

const handleCancel = () => {
  console.log('취소 버튼 클릭')
}

const handleSave = () => {
  console.log('저장 버튼 클릭', {
    name: userName.value,
    email: userEmail.value
  })
}
</script>

11. BasePagination 컴포넌트

11-1) 요약

BasePagination은 페이지 네비게이션을 제공하는 컴포넌트입니다. 첫 페이지, 이전 페이지, 페이지 번호, 다음 페이지, 마지막 페이지 버튼을 포함하며, 최대 표시 페이지 수를 설정할 수 있습니다. 현재 페이지 그룹에 따라 페이지 번호를 동적으로 표시합니다.

11-2) Props

Prop 이름타입필수기본값설명
currentPagenumber-현재 페이지 번호
totalPagesnumber-전체 페이지 수
maxDisplayPagesnumber-5한 번에 표시할 최대 페이지 수

11-3) Events

이벤트 이름파라미터설명
update:currentPage(page: number)페이지 변경 시 발생

11-4) 타입 정의

interface PaginationProps {
  currentPage: number;
  totalPages: number;
  maxDisplayPages?: number;
}

11-5) 사용 예시

<template>
  <div class="pagination-example">
    <!-- 기본 페이지네이션 -->
    <BasePagination
      v-model:current-page="currentPage"
      :total-pages="totalPages"
      @update:current-page="handlePageChange"
    />

    <!-- 커스텀 스타일 페이지네이션 -->
    <BasePagination
      v-model:current-page="customPage"
      :total-pages="totalPages"
      :max-display-pages="7"
      class="custom-pagination"
      @update:current-page="handleCustomPageChange"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const currentPage = ref(1)
const customPage = ref(1)
const totalPages = 20

const handlePageChange = (page: number) => {
  console.log('페이지 변경:', page)
}

const handleCustomPageChange = (page: number) => {
  console.log('커스텀 페이지 변경:', page)
}
</script>

12. BaseLoading 컴포넌트

12-1) 요약

BaseLoading은 세 가지 다른 스타일의 로딩 인디케이터를 제공하는 컴포넌트입니다. 스피너, 바, 점 애니메이션 중 하나를 선택하여 사용할 수 있으며, 오버레이 옵션과 크기 조절이 가능합니다. 각 로딩 타입은 상황에 맞게 커스터마이징할 수 있습니다.

12-2) Props

Prop 이름타입필수기본값설명
size'small' | 'medium' | 'large'-'medium'로딩 인디케이터 크기
overlayboolean-false오버레이 표시 여부
spinnerboolean-false스피너 로딩 표시 여부
barboolean-false바 로딩 표시 여부
dotsboolean-false점 로딩 표시 여부

12-3) 타입 정의

type LoadingSize = 'small' | 'medium' | 'large';

interface LoadingProps {
  size?: LoadingSize;
  overlay?: boolean;
  spinner?: boolean;
  bar?: boolean;
  dots?: boolean;
}

12-4) 사용 예시

<template>
  <div class="loading-examples">
    <!-- 스피너 로딩 -->
    <BaseLoading
      spinner
      size="medium"
    />

    <!-- 바 로딩 -->
    <BaseLoading
      bar
      size="large"
    />

    <!-- 점 로딩 -->
    <BaseLoading
      dots
      size="small"
    />

    <!-- 오버레이가 있는 로딩 -->
    <BaseLoading
      spinner
      overlay
      size="large"
    />
  </div>
</template>

<script setup lang="ts">
// 컴포넌트 import
</script>

13. BaseToast 컴포넌트

13-1) 요약

BaseToast는 알림 메시지를 표시하는 컴포넌트입니다. 성공, 에러, 경고, 정보 등 다양한 타입의 토스트 메시지를 지원하며, 위치와 지속 시간을 설정할 수 있습니다. 아이콘, 메시지, 닫기 버튼을 커스터마이징할 수 있는 슬롯을 제공합니다.

13-2) Props

Prop 이름타입필수기본값설명
idstring | number-토스트 고유 식별자
messagestring-토스트 메시지
type'success' | 'error' | 'warning' | 'info'-'info'토스트 타입
durationnumber | null-null표시 지속 시간 (ms)
position'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'-'top-right'표시 위치

13-3) Slots

Slot 이름Props설명
icon-아이콘 영역 커스터마이징
message-메시지 영역 커스터마이징
close-button-닫기 버튼 영역 커스터마이징
default-전체 토스트 영역 커스터마이징

13-4) Events

이벤트 이름파라미터설명
close(id: string | number)토스트 닫힐 때 발생

13-5) 타입 정의

type ToastType = 'success' | 'error' | 'warning' | 'info';
type ToastPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left';

interface ToastProps {
  id: string | number;
  message: string;
  type?: ToastType;
  duration?: number | null;
  position?: ToastPosition;
}

type ToastEmits = {
  (e: 'close', id: string | number): void;
}

13-6) 사용 예시

<template>
  <div class="toast-examples">
    <!-- 기본 토스트 -->
    <BaseToast
      id="1"
      message="기본 알림 메시지입니다."
      type="info"
    />

    <!-- 성공 토스트 -->
    <BaseToast
      id="2"
      message="성공적으로 저장되었습니다."
      type="success"
      duration="3000"
    />

    <!-- 에러 토스트 -->
    <BaseToast
      id="3"
      message="오류가 발생했습니다."
      type="error"
      position="top-left"
    >
      <!-- 커스텀 아이콘 -->
      <template #icon>
        <span class="custom-icon">⚠️</span>
      </template>
    </BaseToast>

    <!-- 경고 토스트 -->
    <BaseToast
      id="4"
      message="주의하세요!"
      type="warning"
      position="bottom-right"
    >
      <!-- 커스텀 닫기 버튼 -->
      <template #close-button>
        <button class="custom-close" @click="handleClose">닫기</button>
      </template>
    </BaseToast>

    <!-- 완전 커스텀 토스트 -->
    <BaseToast
      id="5"
      message="커스텀 토스트"
      type="info"
      position="bottom-left"
    >
      <div class="custom-toast">
        <div class="custom-content">
          <span class="custom-icon">🎉</span>
          <span class="custom-message">커스텀 메시지</span>
        </div>
        <button class="custom-close" @click="handleCustomClose">×</button>
      </div>
    </BaseToast>
  </div>
</template>

<script setup lang="ts">
const handleClose = () => {
  console.log('토스트 닫기')
}

const handleCustomClose = () => {
  console.log('커스텀 토스트 닫기')
}
</script>

14. BaseModal 컴포넌트

14-1) 요약

BaseModal은 드래그 가능한 모달 창으로, 커스터마이징 가능한 헤더/컨텐츠/푸터, 스크롤바 표시 옵션, 닫기 버튼 표시 옵션을 제공하며 TypeScript를 지원합니다.

14-2) Props

PropTypeDefaultDescription
draggablebooleantrue모달의 드래그 가능 여부
headerModalHeader{ showCloseButton: true }헤더 관련 설정
contentModalContent{ showScrollbar: true }컨텐츠 관련 설정
footerModalFooter{ showFooter: false }푸터 관련 설정

14-3) Slots

이름설명
default기본 컨텐츠 영역
header커스텀 헤더 영역 (header.customHeader가 true일 때)
content커스텀 컨텐츠 영역 (content.customContent가 true일 때)
footer기본 푸터 영역
custom-footer커스텀 푸터 영역 (footer.customFooter가 true일 때)

14-4) Events

이벤트설명
close모달이 닫힐 때 발생하는 이벤트

14-5) 타입 정의

// ModalHeader 타입
interface ModalHeader {
  title?: string;           // 헤더 제목
  showCloseButton?: boolean; // 닫기 버튼 표시 여부
  customHeader?: boolean;    // 커스텀 헤더 사용 여부
}

// ModalContent 타입
interface ModalContent {
    customContent?: boolean;   // 커스텀 컨텐츠 사용 여부
    showScrollbar?: boolean;   // 스크롤바 표시 여부
}

// ModalFooter 타입
interface ModalFooter {
    showFooter?: boolean;      // 푸터 표시 여부
    customFooter?: boolean;    // 커스텀 푸터 사용 여부
}

14-6) 사용 예시

(1) 기본 사용
<template>
  <BaseModal
      :header="{ title: '기본 모달' }"
      :content="{ showScrollbar: true }"
      @close="handleClose"
  >
    <p>모달 내용</p>
  </BaseModal>
</template>

<script setup lang="ts">
import {ref} from "vue";

const isModalOpen = ref(false);
const handleClose = () => {
  isModalOpen.value = false;
};
</script>
(2) 커스텀 헤더 사용
<template>
  <BaseModal
    :header="{ customHeader: true }"
    @close="handleClose"
  >
    <template #header>
      <div class="custom-header">
        <h2>커스텀 헤더</h2>
      </div>
    </template>
    
    <p>모달 내용</p>
  </BaseModal>
</template>

<script setup lang="ts">
import {ref} from "vue";

const isModalOpen = ref(false);
const handleClose = () => {
  isModalOpen.value = false;
};
</script>
(3) 커스텀 푸터 사용
<template>
  <BaseModal
      :header="{ title: '푸터 예시' }"
      :footer="{ showFooter: true, customFooter: true }"
      @close="handleClose"
  >
    <p>모달 내용</p>

    <template #custom-footer>
      <div class="custom-footer">
        <button @click="handleSave">저장</button>
        <button @click="handleClose">취소</button>
      </div>
    </template>
  </BaseModal>
</template>

<script setup lang="ts">
import {ref} from "vue";

const isModalOpen = ref(false);
const handleClose = () => {
  isModalOpen.value = false;
};

const handleSave = () => {
  // 저장 처리
};
</script>
0.4.4

7 months ago

0.4.3

7 months ago

0.4.2

7 months ago

0.4.1

7 months ago

0.4.0

7 months ago

0.3.6

7 months ago

0.3.5

7 months ago

0.3.4

7 months ago

0.3.3

7 months ago

0.3.2

7 months ago

0.3.1

7 months ago

0.3.0

7 months ago

0.2.9

7 months ago

0.2.8

7 months ago

0.2.7

7 months ago

0.2.6

7 months ago

0.2.5

7 months ago

0.2.4

7 months ago

0.2.3

7 months ago

0.2.2

7 months ago

0.2.1

7 months ago

0.2.0

7 months ago

0.1.9

7 months ago

0.1.8

7 months ago

0.1.7

7 months ago

0.1.6

7 months ago

0.1.5

7 months ago

0.1.4

7 months ago

0.1.3

7 months ago

0.1.2

7 months ago

0.1.1

7 months ago

0.1.0

7 months ago

0.0.9

7 months ago

0.0.8

7 months ago

0.0.7

7 months ago

0.0.6

7 months ago

0.0.5

7 months ago

0.0.4

7 months ago

0.0.3

7 months ago

0.0.2

7 months ago

0.0.1

7 months ago