@j-solution/components 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/USAGE_GUIDE.md +1068 -61
- package/assets/jwms-portal-frontend-D8DdrheA.css +1 -0
- package/assets/styles/j-components.css +1 -1
- package/components/atoms/JEditor.vue.cjs +7 -0
- package/components/atoms/JEditor.vue.cjs.map +1 -0
- package/components/atoms/JEditor.vue.js +13 -0
- package/components/atoms/JEditor.vue.js.map +1 -0
- package/components/atoms/JEditor.vue2.cjs +2 -0
- package/components/atoms/JEditor.vue2.cjs.map +1 -0
- package/components/atoms/JEditor.vue2.js +43 -0
- package/components/atoms/JEditor.vue2.js.map +1 -0
- package/components/atoms/JPreview.vue.cjs +7 -0
- package/components/atoms/JPreview.vue.cjs.map +1 -0
- package/components/atoms/JPreview.vue.js +13 -0
- package/components/atoms/JPreview.vue.js.map +1 -0
- package/components/atoms/JPreview.vue2.cjs +2 -0
- package/components/atoms/JPreview.vue2.cjs.map +1 -0
- package/components/atoms/JPreview.vue2.js +121 -0
- package/components/atoms/JPreview.vue2.js.map +1 -0
- package/components/molecules/JAlert.vue.cjs +1 -1
- package/components/molecules/JAlert.vue.cjs.map +1 -1
- package/components/molecules/JAlert.vue.js +26 -20
- package/components/molecules/JAlert.vue.js.map +1 -1
- package/components/molecules/JFormField.vue.cjs +1 -1
- package/components/molecules/JFormField.vue.cjs.map +1 -1
- package/components/molecules/JFormField.vue.js +8 -2
- package/components/molecules/JFormField.vue.js.map +1 -1
- package/components/molecules/JTitlebar.vue.cjs +1 -1
- package/components/molecules/JTitlebar.vue.cjs.map +1 -1
- package/components/molecules/JTitlebar.vue.js +26 -20
- package/components/molecules/JTitlebar.vue.js.map +1 -1
- package/components/organisms/JDynamicForm.vue2.cjs +1 -1
- package/components/organisms/JDynamicForm.vue2.cjs.map +1 -1
- package/components/organisms/JDynamicForm.vue2.js +8 -2
- package/components/organisms/JDynamicForm.vue2.js.map +1 -1
- package/components/organisms/JFormModal.vue.cjs +1 -1
- package/components/organisms/JFormModal.vue.cjs.map +1 -1
- package/components/organisms/JFormModal.vue.js +21 -15
- package/components/organisms/JFormModal.vue.js.map +1 -1
- package/components/organisms/JModal.vue.cjs +1 -1
- package/components/organisms/JModal.vue.cjs.map +1 -1
- package/components/organisms/JModal.vue.js +22 -16
- package/components/organisms/JModal.vue.js.map +1 -1
- package/components/organisms/JSearchPanel.vue2.cjs +1 -1
- package/components/organisms/JSearchPanel.vue2.cjs.map +1 -1
- package/components/organisms/JSearchPanel.vue2.js +45 -39
- package/components/organisms/JSearchPanel.vue2.js.map +1 -1
- package/index.cjs +1 -1
- package/index.js +82 -76
- package/package.json +3 -1
- package/tailwind.config.js +2 -1
- package/types/index.d.ts +141 -90
- package/assets/jwms-portal-frontend-BqyV9oqF.css +0 -1
package/USAGE_GUIDE.md
CHANGED
|
@@ -59,7 +59,7 @@ import { JButton } from '@/components'
|
|
|
59
59
|
|
|
60
60
|
## 컴포넌트 목록
|
|
61
61
|
|
|
62
|
-
### Atoms (원자) -
|
|
62
|
+
### Atoms (원자) - 25개
|
|
63
63
|
|
|
64
64
|
기본적인 UI 요소들로, 더 이상 분해할 수 없는 최소 단위의 컴포넌트입니다.
|
|
65
65
|
|
|
@@ -72,6 +72,7 @@ import { JButton } from '@/components'
|
|
|
72
72
|
| **JCombo** | 드롭다운 선택 | 단일/다중 선택 |
|
|
73
73
|
| **JDatepicker** | 날짜 선택기 | 날짜 입력 |
|
|
74
74
|
| **JDivider** | 구분선 | 콘텐츠 구분 |
|
|
75
|
+
| **JEditor** | 마크다운 에디터 | 마크다운 문서 작성 |
|
|
75
76
|
| **JGrid** | 데이터 그리드 | 테이블 데이터 표시 (AG Grid 기반) |
|
|
76
77
|
| **JIcon** | 아이콘 | 시각적 표시 |
|
|
77
78
|
| **JImage** | 이미지 | 이미지 표시 |
|
|
@@ -80,12 +81,14 @@ import { JButton } from '@/components'
|
|
|
80
81
|
| **JLabel** | 라벨 | 폼 필드 라벨 |
|
|
81
82
|
| **JLink** | 링크 | 네비게이션 |
|
|
82
83
|
| **JPopover** | 팝오버 | 추가 정보 표시 |
|
|
84
|
+
| **JPreview** | 마크다운/HTML 뷰어 | 마크다운 또는 HTML 문서 표시 |
|
|
83
85
|
| **JProgress** | 진행률 표시 | 작업 진행 상태 |
|
|
84
86
|
| **JRadio** | 라디오 버튼 | 단일 선택 |
|
|
85
87
|
| **JSearchCombo** | 검색 가능한 드롭다운 | 많은 옵션 중 검색 선택 |
|
|
86
88
|
| **JSpinner** | 로딩 스피너 | 로딩 상태 표시 |
|
|
87
89
|
| **JSwitch** | 토글 스위치 | ON/OFF 설정 |
|
|
88
90
|
| **JTextarea** | 멀티라인 텍스트 입력 | 여러 라인 텍스트 입력 |
|
|
91
|
+
| **JToaster** | Toast 알림 컨테이너 | 전역 알림 메시지 표시 |
|
|
89
92
|
| **JTooltip** | 툴팁 | 추가 설명 표시 |
|
|
90
93
|
|
|
91
94
|
### Molecules (분자) - 11개
|
|
@@ -278,6 +281,7 @@ Templates (템플릿)
|
|
|
278
281
|
| 상황 | 추천 컴포넌트 | 이유 |
|
|
279
282
|
|------|--------------|------|
|
|
280
283
|
| 성공/경고/에러 메시지 | `JAlert` | 타입별 스타일 자동 적용 |
|
|
284
|
+
| 전역 알림 메시지 (Toast) | `JToast` (함수) + `JToaster` (컴포넌트) | 화면 상단/하단에 일시적으로 표시되는 알림 |
|
|
281
285
|
| 추가 설명 | `JTooltip` | 호버 시 설명 표시 |
|
|
282
286
|
| 추가 정보 | `JPopover` | 클릭 시 정보 표시 |
|
|
283
287
|
|
|
@@ -352,6 +356,1018 @@ const enabled = ref(false)
|
|
|
352
356
|
</script>
|
|
353
357
|
```
|
|
354
358
|
|
|
359
|
+
### 이벤트 처리
|
|
360
|
+
|
|
361
|
+
컴포넌트는 표준 Vue 이벤트를 발생시킵니다. `v-model`과 함께 이벤트 핸들러를 사용할 수 있습니다:
|
|
362
|
+
|
|
363
|
+
```vue
|
|
364
|
+
<template>
|
|
365
|
+
<JButton @click="handleClick">클릭</JButton>
|
|
366
|
+
<JInput v-model="name" @change="handleChange" />
|
|
367
|
+
<JModal
|
|
368
|
+
:open="isOpen"
|
|
369
|
+
@confirm="handleConfirm"
|
|
370
|
+
@cancel="handleCancel"
|
|
371
|
+
/>
|
|
372
|
+
</template>
|
|
373
|
+
|
|
374
|
+
<script setup>
|
|
375
|
+
import { ref } from 'vue'
|
|
376
|
+
|
|
377
|
+
const name = ref('')
|
|
378
|
+
const isOpen = ref(false)
|
|
379
|
+
|
|
380
|
+
const handleClick = () => {
|
|
381
|
+
console.log('버튼 클릭')
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const handleChange = (value) => {
|
|
385
|
+
console.log('값 변경:', value)
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const handleConfirm = () => {
|
|
389
|
+
console.log('확인')
|
|
390
|
+
isOpen.value = false
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const handleCancel = () => {
|
|
394
|
+
console.log('취소')
|
|
395
|
+
isOpen.value = false
|
|
396
|
+
}
|
|
397
|
+
</script>
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### 컴포넌트별 기본 사용법
|
|
401
|
+
|
|
402
|
+
#### Atoms (원자 컴포넌트)
|
|
403
|
+
|
|
404
|
+
##### JAvatar - 사용자 아바타
|
|
405
|
+
|
|
406
|
+
```vue
|
|
407
|
+
<template>
|
|
408
|
+
<!-- 기본 사용 -->
|
|
409
|
+
<JAvatar fallback="JD" />
|
|
410
|
+
|
|
411
|
+
<!-- 이미지와 함께 사용 -->
|
|
412
|
+
<JAvatar
|
|
413
|
+
src="https://example.com/avatar.jpg"
|
|
414
|
+
alt="사용자 이름"
|
|
415
|
+
fallback="JD"
|
|
416
|
+
size="lg"
|
|
417
|
+
shape="circle"
|
|
418
|
+
status="online"
|
|
419
|
+
/>
|
|
420
|
+
</template>
|
|
421
|
+
|
|
422
|
+
<script setup>
|
|
423
|
+
import { JAvatar } from '@/components/atoms'
|
|
424
|
+
</script>
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
##### JBadge - 상태 표시 배지
|
|
428
|
+
|
|
429
|
+
```vue
|
|
430
|
+
<template>
|
|
431
|
+
<JBadge styletype="success">활성</JBadge>
|
|
432
|
+
<JBadge styletype="warning">대기</JBadge>
|
|
433
|
+
<JBadge styletype="danger">비활성</JBadge>
|
|
434
|
+
<JBadge styletype="primary" size="lg">프리미엄</JBadge>
|
|
435
|
+
</template>
|
|
436
|
+
|
|
437
|
+
<script setup>
|
|
438
|
+
import { JBadge } from '@/components/atoms'
|
|
439
|
+
</script>
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
##### JCheckbox - 체크박스
|
|
443
|
+
|
|
444
|
+
```vue
|
|
445
|
+
<template>
|
|
446
|
+
<JCheckbox v-model="checked" label="동의합니다" />
|
|
447
|
+
<JCheckbox v-model="terms" label="약관에 동의합니다" required />
|
|
448
|
+
</template>
|
|
449
|
+
|
|
450
|
+
<script setup>
|
|
451
|
+
import { ref } from 'vue'
|
|
452
|
+
import { JCheckbox } from '@/components/atoms'
|
|
453
|
+
|
|
454
|
+
const checked = ref(false)
|
|
455
|
+
const terms = ref(false)
|
|
456
|
+
</script>
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
##### JCombo - 드롭다운 선택
|
|
460
|
+
|
|
461
|
+
```vue
|
|
462
|
+
<template>
|
|
463
|
+
<JCombo
|
|
464
|
+
v-model="selected"
|
|
465
|
+
:options="options"
|
|
466
|
+
placeholder="선택하세요"
|
|
467
|
+
/>
|
|
468
|
+
</template>
|
|
469
|
+
|
|
470
|
+
<script setup>
|
|
471
|
+
import { ref } from 'vue'
|
|
472
|
+
import { JCombo } from '@/components/atoms'
|
|
473
|
+
|
|
474
|
+
const selected = ref('')
|
|
475
|
+
const options = [
|
|
476
|
+
{ value: 'option1', label: '옵션 1' },
|
|
477
|
+
{ value: 'option2', label: '옵션 2' },
|
|
478
|
+
{ value: 'option3', label: '옵션 3' },
|
|
479
|
+
]
|
|
480
|
+
</script>
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
##### JDatepicker - 날짜 선택기
|
|
484
|
+
|
|
485
|
+
```vue
|
|
486
|
+
<template>
|
|
487
|
+
<JDatepicker
|
|
488
|
+
v-model="date"
|
|
489
|
+
placeholder="날짜를 선택하세요"
|
|
490
|
+
/>
|
|
491
|
+
</template>
|
|
492
|
+
|
|
493
|
+
<script setup>
|
|
494
|
+
import { ref } from 'vue'
|
|
495
|
+
import { JDatepicker } from '@/components/atoms'
|
|
496
|
+
|
|
497
|
+
const date = ref(null)
|
|
498
|
+
</script>
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
##### JDivider - 구분선
|
|
502
|
+
|
|
503
|
+
```vue
|
|
504
|
+
<template>
|
|
505
|
+
<div>위쪽 콘텐츠</div>
|
|
506
|
+
<JDivider />
|
|
507
|
+
<div>아래쪽 콘텐츠</div>
|
|
508
|
+
|
|
509
|
+
<!-- 텍스트와 함께 사용 -->
|
|
510
|
+
<JDivider>또는</JDivider>
|
|
511
|
+
</template>
|
|
512
|
+
|
|
513
|
+
<script setup>
|
|
514
|
+
import { JDivider } from '@/components/atoms'
|
|
515
|
+
</script>
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
##### JGrid - 데이터 그리드
|
|
519
|
+
|
|
520
|
+
```vue
|
|
521
|
+
<template>
|
|
522
|
+
<JGrid
|
|
523
|
+
:column-defs="columnDefs"
|
|
524
|
+
:row-data="rowData"
|
|
525
|
+
/>
|
|
526
|
+
</template>
|
|
527
|
+
|
|
528
|
+
<script setup>
|
|
529
|
+
import { JGrid } from '@/components/atoms'
|
|
530
|
+
|
|
531
|
+
const columnDefs = [
|
|
532
|
+
{ field: 'name', headerName: '이름' },
|
|
533
|
+
{ field: 'age', headerName: '나이' },
|
|
534
|
+
{ field: 'email', headerName: '이메일' },
|
|
535
|
+
]
|
|
536
|
+
|
|
537
|
+
const rowData = [
|
|
538
|
+
{ name: '홍길동', age: 30, email: 'hong@example.com' },
|
|
539
|
+
{ name: '김철수', age: 25, email: 'kim@example.com' },
|
|
540
|
+
]
|
|
541
|
+
</script>
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
##### JIcon - 아이콘
|
|
545
|
+
|
|
546
|
+
```vue
|
|
547
|
+
<template>
|
|
548
|
+
<JIcon name="user" size="lg" />
|
|
549
|
+
<JIcon name="settings" styletype="primary" />
|
|
550
|
+
<JIcon name="check" styletype="success" />
|
|
551
|
+
</template>
|
|
552
|
+
|
|
553
|
+
<script setup>
|
|
554
|
+
import { JIcon } from '@/components/atoms'
|
|
555
|
+
</script>
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
##### JImage - 이미지
|
|
559
|
+
|
|
560
|
+
```vue
|
|
561
|
+
<template>
|
|
562
|
+
<JImage
|
|
563
|
+
src="https://example.com/image.jpg"
|
|
564
|
+
alt="이미지 설명"
|
|
565
|
+
width="300"
|
|
566
|
+
height="200"
|
|
567
|
+
/>
|
|
568
|
+
</template>
|
|
569
|
+
|
|
570
|
+
<script setup>
|
|
571
|
+
import { JImage } from '@/components/atoms'
|
|
572
|
+
</script>
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
##### JKbd - 키보드 단축키 표시
|
|
576
|
+
|
|
577
|
+
```vue
|
|
578
|
+
<template>
|
|
579
|
+
<div>
|
|
580
|
+
저장: <JKbd>Ctrl</JKbd> + <JKbd>S</JKbd>
|
|
581
|
+
복사: <JKbd>Ctrl</JKbd> + <JKbd>C</JKbd>
|
|
582
|
+
</div>
|
|
583
|
+
</template>
|
|
584
|
+
|
|
585
|
+
<script setup>
|
|
586
|
+
import { JKbd } from '@/components/atoms'
|
|
587
|
+
</script>
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
##### JLabel - 라벨
|
|
591
|
+
|
|
592
|
+
```vue
|
|
593
|
+
<template>
|
|
594
|
+
<JLabel for="input-id">이름</JLabel>
|
|
595
|
+
<JInput id="input-id" v-model="name" />
|
|
596
|
+
</template>
|
|
597
|
+
|
|
598
|
+
<script setup>
|
|
599
|
+
import { ref } from 'vue'
|
|
600
|
+
import { JLabel, JInput } from '@/components/atoms'
|
|
601
|
+
|
|
602
|
+
const name = ref('')
|
|
603
|
+
</script>
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
##### JLink - 링크
|
|
607
|
+
|
|
608
|
+
```vue
|
|
609
|
+
<template>
|
|
610
|
+
<JLink href="/about">소개</JLink>
|
|
611
|
+
<JLink href="/contact" styletype="primary">연락처</JLink>
|
|
612
|
+
</template>
|
|
613
|
+
|
|
614
|
+
<script setup>
|
|
615
|
+
import { JLink } from '@/components/atoms'
|
|
616
|
+
</script>
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
##### JPopover - 팝오버
|
|
620
|
+
|
|
621
|
+
```vue
|
|
622
|
+
<template>
|
|
623
|
+
<JPopover>
|
|
624
|
+
<template #trigger>
|
|
625
|
+
<JButton>팝오버 열기</JButton>
|
|
626
|
+
</template>
|
|
627
|
+
<template #content>
|
|
628
|
+
<div class="p-4">
|
|
629
|
+
<p>팝오버 내용입니다.</p>
|
|
630
|
+
</div>
|
|
631
|
+
</template>
|
|
632
|
+
</JPopover>
|
|
633
|
+
</template>
|
|
634
|
+
|
|
635
|
+
<script setup>
|
|
636
|
+
import { JPopover, JButton } from '@/components/atoms'
|
|
637
|
+
</script>
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
##### JProgress - 진행률 표시
|
|
641
|
+
|
|
642
|
+
```vue
|
|
643
|
+
<template>
|
|
644
|
+
<JProgress :value="progress" />
|
|
645
|
+
<JProgress :value="75" styletype="success" />
|
|
646
|
+
</template>
|
|
647
|
+
|
|
648
|
+
<script setup>
|
|
649
|
+
import { ref } from 'vue'
|
|
650
|
+
import { JProgress } from '@/components/atoms'
|
|
651
|
+
|
|
652
|
+
const progress = ref(50)
|
|
653
|
+
</script>
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
##### JRadio - 라디오 버튼
|
|
657
|
+
|
|
658
|
+
```vue
|
|
659
|
+
<template>
|
|
660
|
+
<JRadio v-model="selected" value="option1" label="옵션 1" />
|
|
661
|
+
<JRadio v-model="selected" value="option2" label="옵션 2" />
|
|
662
|
+
<JRadio v-model="selected" value="option3" label="옵션 3" />
|
|
663
|
+
</template>
|
|
664
|
+
|
|
665
|
+
<script setup>
|
|
666
|
+
import { ref } from 'vue'
|
|
667
|
+
import { JRadio } from '@/components/atoms'
|
|
668
|
+
|
|
669
|
+
const selected = ref('option1')
|
|
670
|
+
</script>
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
##### JSearchCombo - 검색 가능한 드롭다운
|
|
674
|
+
|
|
675
|
+
```vue
|
|
676
|
+
<template>
|
|
677
|
+
<JSearchCombo
|
|
678
|
+
v-model="selected"
|
|
679
|
+
:options="options"
|
|
680
|
+
placeholder="검색하여 선택하세요"
|
|
681
|
+
/>
|
|
682
|
+
</template>
|
|
683
|
+
|
|
684
|
+
<script setup>
|
|
685
|
+
import { ref } from 'vue'
|
|
686
|
+
import { JSearchCombo } from '@/components/atoms'
|
|
687
|
+
|
|
688
|
+
const selected = ref('')
|
|
689
|
+
const options = [
|
|
690
|
+
{ value: '1', label: '항목 1' },
|
|
691
|
+
{ value: '2', label: '항목 2' },
|
|
692
|
+
// ... 많은 옵션들
|
|
693
|
+
]
|
|
694
|
+
</script>
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
##### JSpinner - 로딩 스피너
|
|
698
|
+
|
|
699
|
+
```vue
|
|
700
|
+
<template>
|
|
701
|
+
<JSpinner v-if="loading" />
|
|
702
|
+
<div v-else>콘텐츠</div>
|
|
703
|
+
</template>
|
|
704
|
+
|
|
705
|
+
<script setup>
|
|
706
|
+
import { ref } from 'vue'
|
|
707
|
+
import { JSpinner } from '@/components/atoms'
|
|
708
|
+
|
|
709
|
+
const loading = ref(true)
|
|
710
|
+
</script>
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
##### JSwitch - 토글 스위치
|
|
714
|
+
|
|
715
|
+
```vue
|
|
716
|
+
<template>
|
|
717
|
+
<JSwitch v-model="enabled" label="알림 받기" />
|
|
718
|
+
</template>
|
|
719
|
+
|
|
720
|
+
<script setup>
|
|
721
|
+
import { ref } from 'vue'
|
|
722
|
+
import { JSwitch } from '@/components/atoms'
|
|
723
|
+
|
|
724
|
+
const enabled = ref(false)
|
|
725
|
+
</script>
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
##### JTextarea - 멀티라인 텍스트 입력
|
|
729
|
+
|
|
730
|
+
```vue
|
|
731
|
+
<template>
|
|
732
|
+
<JTextarea
|
|
733
|
+
v-model="description"
|
|
734
|
+
placeholder="설명을 입력하세요"
|
|
735
|
+
rows="5"
|
|
736
|
+
/>
|
|
737
|
+
</template>
|
|
738
|
+
|
|
739
|
+
<script setup>
|
|
740
|
+
import { ref } from 'vue'
|
|
741
|
+
import { JTextarea } from '@/components/atoms'
|
|
742
|
+
|
|
743
|
+
const description = ref('')
|
|
744
|
+
</script>
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
##### JTooltip - 툴팁
|
|
748
|
+
|
|
749
|
+
```vue
|
|
750
|
+
<template>
|
|
751
|
+
<JTooltip content="이것은 툴팁입니다">
|
|
752
|
+
<JButton>호버하세요</JButton>
|
|
753
|
+
</JTooltip>
|
|
754
|
+
</template>
|
|
755
|
+
|
|
756
|
+
<script setup>
|
|
757
|
+
import { JTooltip, JButton } from '@/components/atoms'
|
|
758
|
+
</script>
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
##### JButton - 버튼
|
|
762
|
+
|
|
763
|
+
**주요 props**: `styletype` (primary, secondary, danger, outline, ghost, link, sm, lg), `disabled`, `loading`
|
|
764
|
+
|
|
765
|
+
**권장 사용 시나리오**:
|
|
766
|
+
- `styletype="primary"`: 주요 액션 (저장, 확인 등)
|
|
767
|
+
- `styletype="secondary"`: 보조 액션
|
|
768
|
+
- `styletype="danger"`: 위험한 액션 (삭제 등)
|
|
769
|
+
- `styletype="outline"`: 덜 강조된 액션
|
|
770
|
+
- `styletype="ghost"`: 최소한의 시각적 강조
|
|
771
|
+
- `disabled`: 비활성화 상태
|
|
772
|
+
- `loading`: 비동기 작업 진행 중 표시
|
|
773
|
+
|
|
774
|
+
##### JInput - 텍스트 입력 필드
|
|
775
|
+
|
|
776
|
+
**주요 props**: `modelValue`, `type` (text, email, password, number 등), `placeholder`, `disabled`, `readonly`, `required`, `styletype` (default, error, success, warning, sm, lg)
|
|
777
|
+
|
|
778
|
+
**권장 사용 시나리오**:
|
|
779
|
+
- `type="text"`: 일반 텍스트 입력
|
|
780
|
+
- `type="email"`: 이메일 주소 입력
|
|
781
|
+
- `type="password"`: 비밀번호 입력
|
|
782
|
+
- `type="number"`: 숫자 입력
|
|
783
|
+
- `styletype="error"`: 유효성 검사 실패 시
|
|
784
|
+
- `styletype="success"`: 유효성 검사 통과 시
|
|
785
|
+
- `readonly`: 읽기 전용 표시
|
|
786
|
+
|
|
787
|
+
##### JEditor - 마크다운 에디터
|
|
788
|
+
|
|
789
|
+
**주요 props**: `modelValue` (마크다운 문자열), `placeholder`, `disabled`, `readonly`, `height`, `theme` (light, dark)
|
|
790
|
+
|
|
791
|
+
**권장 사용 시나리오**:
|
|
792
|
+
- `modelValue`: v-model로 마크다운 내용 바인딩
|
|
793
|
+
- `height`: 에디터 높이 설정 (기본값: 500)
|
|
794
|
+
- `theme`: 다크모드 지원
|
|
795
|
+
- `readonly`: 읽기 전용 모드 (프리뷰 전용)
|
|
796
|
+
|
|
797
|
+
##### JPreview - 마크다운/HTML 뷰어
|
|
798
|
+
|
|
799
|
+
**주요 props**: `modelValue` (마크다운 또는 HTML 문자열), `theme` (light, dark)
|
|
800
|
+
|
|
801
|
+
**권장 사용 시나리오**:
|
|
802
|
+
- `modelValue`: 마크다운 또는 HTML 문자열 자동 감지 및 렌더링
|
|
803
|
+
- HTML 문서는 `<!DOCTYPE html>` 또는 `<html>` 태그로 시작하면 자동 감지
|
|
804
|
+
- 마크다운은 그 외 모든 경우에 자동 처리
|
|
805
|
+
- `theme`: 다크모드 지원
|
|
806
|
+
- JEditor로 작성한 마크다운을 자동으로 변환하여 표시
|
|
807
|
+
|
|
808
|
+
##### JToaster - Toast 알림 컨테이너
|
|
809
|
+
|
|
810
|
+
**권장 사용 시나리오**:
|
|
811
|
+
- 앱의 루트 레벨에 `<JToaster />` 컴포넌트 추가
|
|
812
|
+
- `JToast` 함수와 함께 사용: `JToast.success()`, `JToast.error()`, `JToast.info()`, `JToast.warning()`
|
|
813
|
+
- 자동 사라짐 기능 내장
|
|
814
|
+
- 여러 Toast 동시 표시 가능
|
|
815
|
+
|
|
816
|
+
#### Molecules (분자 컴포넌트)
|
|
817
|
+
|
|
818
|
+
##### JAccordion - 접을 수 있는 콘텐츠 섹션
|
|
819
|
+
|
|
820
|
+
```vue
|
|
821
|
+
<template>
|
|
822
|
+
<JAccordion
|
|
823
|
+
:items="items"
|
|
824
|
+
type="single"
|
|
825
|
+
collapsible
|
|
826
|
+
/>
|
|
827
|
+
</template>
|
|
828
|
+
|
|
829
|
+
<script setup>
|
|
830
|
+
import { JAccordion } from '@/components/molecules'
|
|
831
|
+
|
|
832
|
+
const items = [
|
|
833
|
+
{
|
|
834
|
+
value: 'item-1',
|
|
835
|
+
title: '첫 번째 항목',
|
|
836
|
+
content: '첫 번째 항목의 내용입니다.',
|
|
837
|
+
},
|
|
838
|
+
{
|
|
839
|
+
value: 'item-2',
|
|
840
|
+
title: '두 번째 항목',
|
|
841
|
+
content: '두 번째 항목의 내용입니다.',
|
|
842
|
+
},
|
|
843
|
+
]
|
|
844
|
+
</script>
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
##### JAlert - 알림 메시지 표시
|
|
848
|
+
|
|
849
|
+
```vue
|
|
850
|
+
<template>
|
|
851
|
+
<JAlert
|
|
852
|
+
variant="default"
|
|
853
|
+
title="알림"
|
|
854
|
+
description="이것은 알림 메시지입니다."
|
|
855
|
+
button-text="확인"
|
|
856
|
+
:show-footer="true"
|
|
857
|
+
@confirm="handleConfirm"
|
|
858
|
+
/>
|
|
859
|
+
</template>
|
|
860
|
+
|
|
861
|
+
<script setup>
|
|
862
|
+
import { JAlert } from '@/components/molecules'
|
|
863
|
+
|
|
864
|
+
const handleConfirm = () => {
|
|
865
|
+
console.log('확인 클릭')
|
|
866
|
+
}
|
|
867
|
+
</script>
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
##### JBreadcrumb - 페이지 네비게이션 경로
|
|
871
|
+
|
|
872
|
+
```vue
|
|
873
|
+
<template>
|
|
874
|
+
<JBreadcrumb :items="breadcrumbItems" />
|
|
875
|
+
</template>
|
|
876
|
+
|
|
877
|
+
<script setup>
|
|
878
|
+
import { JBreadcrumb } from '@/components/molecules'
|
|
879
|
+
|
|
880
|
+
const breadcrumbItems = [
|
|
881
|
+
{ label: '홈', href: '/' },
|
|
882
|
+
{ label: '카테고리', href: '/category' },
|
|
883
|
+
{ label: '현재 페이지' },
|
|
884
|
+
]
|
|
885
|
+
</script>
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
##### JButtonGroup - 버튼 그룹
|
|
889
|
+
|
|
890
|
+
```vue
|
|
891
|
+
<template>
|
|
892
|
+
<JButtonGroup>
|
|
893
|
+
<JButton>저장</JButton>
|
|
894
|
+
<JButton>취소</JButton>
|
|
895
|
+
<JButton>삭제</JButton>
|
|
896
|
+
</JButtonGroup>
|
|
897
|
+
</template>
|
|
898
|
+
|
|
899
|
+
<script setup>
|
|
900
|
+
import { JButtonGroup, JButton } from '@/components/molecules'
|
|
901
|
+
</script>
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
##### JCard - 카드 컴포넌트
|
|
905
|
+
|
|
906
|
+
```vue
|
|
907
|
+
<template>
|
|
908
|
+
<JCard
|
|
909
|
+
title="카드 제목"
|
|
910
|
+
description="카드 설명"
|
|
911
|
+
footer="푸터 텍스트"
|
|
912
|
+
>
|
|
913
|
+
<p>카드 내용입니다.</p>
|
|
914
|
+
</JCard>
|
|
915
|
+
</template>
|
|
916
|
+
|
|
917
|
+
<script setup>
|
|
918
|
+
import { JCard } from '@/components/molecules'
|
|
919
|
+
</script>
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
##### JContextMenu - 우클릭 컨텍스트 메뉴
|
|
923
|
+
|
|
924
|
+
```vue
|
|
925
|
+
<template>
|
|
926
|
+
<JContextMenu>
|
|
927
|
+
<template #trigger>
|
|
928
|
+
<div>우클릭하세요</div>
|
|
929
|
+
</template>
|
|
930
|
+
<template #content>
|
|
931
|
+
<div class="p-2">
|
|
932
|
+
<div class="p-2 hover:bg-gray-100 cursor-pointer">복사</div>
|
|
933
|
+
<div class="p-2 hover:bg-gray-100 cursor-pointer">붙여넣기</div>
|
|
934
|
+
<div class="p-2 hover:bg-gray-100 cursor-pointer">삭제</div>
|
|
935
|
+
</div>
|
|
936
|
+
</template>
|
|
937
|
+
</JContextMenu>
|
|
938
|
+
</template>
|
|
939
|
+
|
|
940
|
+
<script setup>
|
|
941
|
+
import { JContextMenu } from '@/components/molecules'
|
|
942
|
+
</script>
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
##### JGroupCombo - 그룹화된 드롭다운
|
|
946
|
+
|
|
947
|
+
```vue
|
|
948
|
+
<template>
|
|
949
|
+
<JGroupCombo
|
|
950
|
+
v-model="selected"
|
|
951
|
+
:groups="groupedOptions"
|
|
952
|
+
placeholder="그룹에서 선택하세요"
|
|
953
|
+
/>
|
|
954
|
+
</template>
|
|
955
|
+
|
|
956
|
+
<script setup>
|
|
957
|
+
import { ref } from 'vue'
|
|
958
|
+
import { JGroupCombo } from '@/components/molecules'
|
|
959
|
+
|
|
960
|
+
const selected = ref('')
|
|
961
|
+
const groupedOptions = [
|
|
962
|
+
{
|
|
963
|
+
label: '그룹 1',
|
|
964
|
+
options: [
|
|
965
|
+
{ value: '1-1', label: '옵션 1-1' },
|
|
966
|
+
{ value: '1-2', label: '옵션 1-2' },
|
|
967
|
+
],
|
|
968
|
+
},
|
|
969
|
+
{
|
|
970
|
+
label: '그룹 2',
|
|
971
|
+
options: [
|
|
972
|
+
{ value: '2-1', label: '옵션 2-1' },
|
|
973
|
+
{ value: '2-2', label: '옵션 2-2' },
|
|
974
|
+
],
|
|
975
|
+
},
|
|
976
|
+
]
|
|
977
|
+
</script>
|
|
978
|
+
```
|
|
979
|
+
|
|
980
|
+
##### JSearchAddr - 주소 검색
|
|
981
|
+
|
|
982
|
+
```vue
|
|
983
|
+
<template>
|
|
984
|
+
<JSearchAddr
|
|
985
|
+
v-model="address"
|
|
986
|
+
@select="handleAddressSelect"
|
|
987
|
+
/>
|
|
988
|
+
</template>
|
|
989
|
+
|
|
990
|
+
<script setup>
|
|
991
|
+
import { ref } from 'vue'
|
|
992
|
+
import { JSearchAddr } from '@/components/molecules'
|
|
993
|
+
|
|
994
|
+
const address = ref('')
|
|
995
|
+
|
|
996
|
+
const handleAddressSelect = (data) => {
|
|
997
|
+
console.log('선택된 주소:', data)
|
|
998
|
+
}
|
|
999
|
+
</script>
|
|
1000
|
+
```
|
|
1001
|
+
|
|
1002
|
+
##### JTabs - 탭 UI
|
|
1003
|
+
|
|
1004
|
+
```vue
|
|
1005
|
+
<template>
|
|
1006
|
+
<JTabs
|
|
1007
|
+
:tabs="tabs"
|
|
1008
|
+
v-model:active-tab-id="activeTab"
|
|
1009
|
+
@tab-change="handleTabChange"
|
|
1010
|
+
/>
|
|
1011
|
+
</template>
|
|
1012
|
+
|
|
1013
|
+
<script setup>
|
|
1014
|
+
import { ref } from 'vue'
|
|
1015
|
+
import { JTabs } from '@/components/molecules'
|
|
1016
|
+
|
|
1017
|
+
const activeTab = ref('tab1')
|
|
1018
|
+
const tabs = [
|
|
1019
|
+
{ id: 'tab1', label: '탭 1', closable: false },
|
|
1020
|
+
{ id: 'tab2', label: '탭 2', closable: true },
|
|
1021
|
+
{ id: 'tab3', label: '탭 3', closable: true },
|
|
1022
|
+
]
|
|
1023
|
+
|
|
1024
|
+
const handleTabChange = (id) => {
|
|
1025
|
+
console.log('탭 변경:', id)
|
|
1026
|
+
}
|
|
1027
|
+
</script>
|
|
1028
|
+
```
|
|
1029
|
+
|
|
1030
|
+
##### JTitlebar - 타이틀바
|
|
1031
|
+
|
|
1032
|
+
```vue
|
|
1033
|
+
<template>
|
|
1034
|
+
<JTitlebar
|
|
1035
|
+
title="페이지 제목"
|
|
1036
|
+
description="페이지 설명"
|
|
1037
|
+
>
|
|
1038
|
+
<template #actions>
|
|
1039
|
+
<JButton>액션 1</JButton>
|
|
1040
|
+
<JButton>액션 2</JButton>
|
|
1041
|
+
</template>
|
|
1042
|
+
</JTitlebar>
|
|
1043
|
+
</template>
|
|
1044
|
+
|
|
1045
|
+
<script setup>
|
|
1046
|
+
import { JTitlebar, JButton } from '@/components/molecules'
|
|
1047
|
+
</script>
|
|
1048
|
+
```
|
|
1049
|
+
|
|
1050
|
+
##### JFormField - 폼 필드 래퍼
|
|
1051
|
+
|
|
1052
|
+
**주요 props**: `type` (input, textarea, checkbox, switch, combo, radio, searchCombo, datepicker), `label`, `description`, `errorMsg`, `modelValue`, `placeholder`, `disabled`, `required`, `orientation` (vertical, horizontal, responsive), `labelAlign`, `labelWidth`
|
|
1053
|
+
|
|
1054
|
+
**권장 사용 시나리오**:
|
|
1055
|
+
- `type` prop으로 원하는 입력 컴포넌트 선택
|
|
1056
|
+
- `label` prop으로 라벨 값을 입력하면 UI 배치시 라벨이 포함되며, 입력 필드와 자동 연결 (접근성)
|
|
1057
|
+
- `errorMsg` prop으로 에러 메시지 값을 입력하면 UI 배치시 에러 메시지가 포함됨
|
|
1058
|
+
- `orientation="horizontal"`: 레이블과 입력 필드를 가로로 배치
|
|
1059
|
+
- `orientation="vertical"`: 레이블과 입력 필드를 세로로 배치 (기본값)
|
|
1060
|
+
- `orientation="responsive"`: 화면 크기에 따라 자동 조정
|
|
1061
|
+
- 레이아웃 일관성 유지
|
|
1062
|
+
|
|
1063
|
+
#### Organisms (유기체 컴포넌트)
|
|
1064
|
+
|
|
1065
|
+
##### JDynamicForm - 스키마 기반 동적 폼
|
|
1066
|
+
|
|
1067
|
+
**주요 props**: `schema` (JSON 스키마), `modelValue`, `type` (simple, sectioned, wizard)
|
|
1068
|
+
|
|
1069
|
+
**권장 사용 시나리오**:
|
|
1070
|
+
- `type="simple"`: 단순한 폼
|
|
1071
|
+
- `type="sectioned"`: 섹션별로 구분된 폼
|
|
1072
|
+
- `type="wizard"`: 단계별 입력 폼
|
|
1073
|
+
- JSON 스키마로 폼 자동 생성
|
|
1074
|
+
- `schema.fields` 배열에 필드 정의: `controlName`, `label`, `type`, `isRequired` 등
|
|
1075
|
+
- Props 기반의 사용을 권장합니다
|
|
1076
|
+
|
|
1077
|
+
##### JModal - 모달 다이얼로그
|
|
1078
|
+
|
|
1079
|
+
**주요 props**: `open`, `size` (sm, md, lg, xl, 2xl, full), `title`, `description`, `show-footer`, `confirm-text`, `cancel-text`
|
|
1080
|
+
|
|
1081
|
+
**권장 사용 시나리오**:
|
|
1082
|
+
- `open`: 모달 열림/닫힘 상태 제어
|
|
1083
|
+
- `size="sm"`: 작은 모달
|
|
1084
|
+
- `size="md"`: 중간 모달 (기본값)
|
|
1085
|
+
- `size="lg"`: 큰 모달
|
|
1086
|
+
- `size="xl"`: 매우 큰 모달
|
|
1087
|
+
- `size="2xl"`: 초대형 모달
|
|
1088
|
+
- `size="full"`: 전체 화면 모달
|
|
1089
|
+
- `title`: 모달 제목
|
|
1090
|
+
- `show-footer`: 푸터 표시 여부
|
|
1091
|
+
- `@confirm`: 확인 버튼 클릭 이벤트
|
|
1092
|
+
- `@cancel`: 취소 버튼 클릭 이벤트
|
|
1093
|
+
- Props 기반의 사용을 권장합니다
|
|
1094
|
+
|
|
1095
|
+
##### JFormModal - 폼 모달
|
|
1096
|
+
|
|
1097
|
+
```vue
|
|
1098
|
+
<template>
|
|
1099
|
+
<JFormModal
|
|
1100
|
+
:open="isOpen"
|
|
1101
|
+
:schema="formSchema"
|
|
1102
|
+
v-model="formData"
|
|
1103
|
+
title="폼 모달"
|
|
1104
|
+
@confirm="handleConfirm"
|
|
1105
|
+
@cancel="handleCancel"
|
|
1106
|
+
/>
|
|
1107
|
+
</template>
|
|
1108
|
+
|
|
1109
|
+
<script setup>
|
|
1110
|
+
import { ref } from 'vue'
|
|
1111
|
+
import { JFormModal } from '@/components/organisms'
|
|
1112
|
+
|
|
1113
|
+
const isOpen = ref(false)
|
|
1114
|
+
const formData = ref({})
|
|
1115
|
+
const formSchema = {
|
|
1116
|
+
type: 'simple',
|
|
1117
|
+
fields: [
|
|
1118
|
+
{ controlName: 'name', label: '이름', type: 'input', isRequired: true },
|
|
1119
|
+
{ controlName: 'email', label: '이메일', type: 'input', inputType: 'email' },
|
|
1120
|
+
],
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
const handleConfirm = () => {
|
|
1124
|
+
console.log('확인:', formData.value)
|
|
1125
|
+
isOpen.value = false
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
const handleCancel = () => {
|
|
1129
|
+
isOpen.value = false
|
|
1130
|
+
}
|
|
1131
|
+
</script>
|
|
1132
|
+
```
|
|
1133
|
+
|
|
1134
|
+
##### JHeader - 애플리케이션 헤더
|
|
1135
|
+
|
|
1136
|
+
```vue
|
|
1137
|
+
<template>
|
|
1138
|
+
<JHeader
|
|
1139
|
+
:menu-items="menuItems"
|
|
1140
|
+
:user="user"
|
|
1141
|
+
@menu-click="handleMenuClick"
|
|
1142
|
+
/>
|
|
1143
|
+
</template>
|
|
1144
|
+
|
|
1145
|
+
<script setup>
|
|
1146
|
+
import { JHeader } from '@/components/organisms'
|
|
1147
|
+
|
|
1148
|
+
const menuItems = [
|
|
1149
|
+
{ id: '1', label: '홈', path: '/' },
|
|
1150
|
+
{ id: '2', label: '설정', path: '/settings' },
|
|
1151
|
+
]
|
|
1152
|
+
|
|
1153
|
+
const user = {
|
|
1154
|
+
name: '홍길동',
|
|
1155
|
+
avatar: 'https://example.com/avatar.jpg',
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
const handleMenuClick = (item) => {
|
|
1159
|
+
console.log('메뉴 클릭:', item)
|
|
1160
|
+
}
|
|
1161
|
+
</script>
|
|
1162
|
+
```
|
|
1163
|
+
|
|
1164
|
+
##### JPageContainer - 페이지 컨테이너
|
|
1165
|
+
|
|
1166
|
+
```vue
|
|
1167
|
+
<template>
|
|
1168
|
+
<JPageContainer>
|
|
1169
|
+
<template #header>
|
|
1170
|
+
<h1>페이지 제목</h1>
|
|
1171
|
+
</template>
|
|
1172
|
+
<template #content>
|
|
1173
|
+
<p>페이지 내용입니다.</p>
|
|
1174
|
+
</template>
|
|
1175
|
+
</JPageContainer>
|
|
1176
|
+
</template>
|
|
1177
|
+
|
|
1178
|
+
<script setup>
|
|
1179
|
+
import { JPageContainer } from '@/components/organisms'
|
|
1180
|
+
</script>
|
|
1181
|
+
```
|
|
1182
|
+
|
|
1183
|
+
##### JSearchPanel - 검색 조건 패널
|
|
1184
|
+
|
|
1185
|
+
```vue
|
|
1186
|
+
<template>
|
|
1187
|
+
<JSearchPanel
|
|
1188
|
+
:schema="searchSchema"
|
|
1189
|
+
v-model="searchData"
|
|
1190
|
+
@search="handleSearch"
|
|
1191
|
+
/>
|
|
1192
|
+
</template>
|
|
1193
|
+
|
|
1194
|
+
<script setup>
|
|
1195
|
+
import { ref } from 'vue'
|
|
1196
|
+
import { JSearchPanel } from '@/components/organisms'
|
|
1197
|
+
|
|
1198
|
+
const searchData = ref({})
|
|
1199
|
+
const searchSchema = {
|
|
1200
|
+
type: 'simple',
|
|
1201
|
+
fields: [
|
|
1202
|
+
{ controlName: 'keyword', label: '검색어', type: 'input' },
|
|
1203
|
+
{ controlName: 'category', label: '카테고리', type: 'combo', options: [] },
|
|
1204
|
+
],
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
const handleSearch = (data) => {
|
|
1208
|
+
console.log('검색:', data)
|
|
1209
|
+
}
|
|
1210
|
+
</script>
|
|
1211
|
+
```
|
|
1212
|
+
|
|
1213
|
+
##### JSidebarAdvanced - 고급 사이드바
|
|
1214
|
+
|
|
1215
|
+
```vue
|
|
1216
|
+
<template>
|
|
1217
|
+
<JSidebarAdvanced
|
|
1218
|
+
:menu-items="menuItems"
|
|
1219
|
+
:favorites="favorites"
|
|
1220
|
+
@menu-click="handleMenuClick"
|
|
1221
|
+
/>
|
|
1222
|
+
</template>
|
|
1223
|
+
|
|
1224
|
+
<script setup>
|
|
1225
|
+
import { JSidebarAdvanced } from '@/components/organisms'
|
|
1226
|
+
|
|
1227
|
+
const menuItems = [
|
|
1228
|
+
{ id: '1', label: '홈', path: '/', icon: 'house' },
|
|
1229
|
+
{ id: '2', label: '설정', path: '/settings', icon: 'settings' },
|
|
1230
|
+
]
|
|
1231
|
+
|
|
1232
|
+
const favorites = ['1']
|
|
1233
|
+
|
|
1234
|
+
const handleMenuClick = (item) => {
|
|
1235
|
+
console.log('메뉴 클릭:', item)
|
|
1236
|
+
}
|
|
1237
|
+
</script>
|
|
1238
|
+
```
|
|
1239
|
+
|
|
1240
|
+
##### JSidebarSimple - 간단한 사이드바
|
|
1241
|
+
|
|
1242
|
+
```vue
|
|
1243
|
+
<template>
|
|
1244
|
+
<JSidebarSimple
|
|
1245
|
+
:menu-items="menuItems"
|
|
1246
|
+
@menu-click="handleMenuClick"
|
|
1247
|
+
/>
|
|
1248
|
+
</template>
|
|
1249
|
+
|
|
1250
|
+
<script setup>
|
|
1251
|
+
import { JSidebarSimple } from '@/components/organisms'
|
|
1252
|
+
|
|
1253
|
+
const menuItems = [
|
|
1254
|
+
{ id: '1', label: '홈', path: '/' },
|
|
1255
|
+
{ id: '2', label: '설정', path: '/settings' },
|
|
1256
|
+
]
|
|
1257
|
+
|
|
1258
|
+
const handleMenuClick = (item) => {
|
|
1259
|
+
console.log('메뉴 클릭:', item)
|
|
1260
|
+
}
|
|
1261
|
+
</script>
|
|
1262
|
+
```
|
|
1263
|
+
|
|
1264
|
+
---
|
|
1265
|
+
|
|
1266
|
+
## 고급 사용법
|
|
1267
|
+
|
|
1268
|
+
### JToast/JToaster 사용법
|
|
1269
|
+
|
|
1270
|
+
Toast 알림은 전역적으로 메시지를 표시하는 데 사용됩니다. `JToast` 함수와 `JToaster` 컴포넌트를 함께 사용합니다.
|
|
1271
|
+
|
|
1272
|
+
#### 설치 및 설정
|
|
1273
|
+
|
|
1274
|
+
앱의 루트 레벨에 `<JToaster />` 컴포넌트를 추가해야 합니다:
|
|
1275
|
+
|
|
1276
|
+
```vue
|
|
1277
|
+
<template>
|
|
1278
|
+
<RouterView />
|
|
1279
|
+
<JToaster />
|
|
1280
|
+
</template>
|
|
1281
|
+
|
|
1282
|
+
<script setup>
|
|
1283
|
+
import { JToaster } from '@/components/atoms'
|
|
1284
|
+
// 또는 NPM 패키지 사용 시
|
|
1285
|
+
// import { JToaster } from '@j-solution/components'
|
|
1286
|
+
</script>
|
|
1287
|
+
```
|
|
1288
|
+
|
|
1289
|
+
#### 기본 사용법
|
|
1290
|
+
|
|
1291
|
+
```vue
|
|
1292
|
+
<script setup>
|
|
1293
|
+
import { JToast } from '@/components/atoms'
|
|
1294
|
+
// 또는 NPM 패키지 사용 시
|
|
1295
|
+
// import { JToast } from '@j-solution/components'
|
|
1296
|
+
|
|
1297
|
+
// 기본 Toast
|
|
1298
|
+
const showToast = () => {
|
|
1299
|
+
JToast('메시지가 표시됩니다')
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
// Success Toast
|
|
1303
|
+
const showSuccess = () => {
|
|
1304
|
+
JToast.success('성공적으로 저장되었습니다')
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
// Error Toast
|
|
1308
|
+
const showError = () => {
|
|
1309
|
+
JToast.error('오류가 발생했습니다')
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
// Info Toast
|
|
1313
|
+
const showInfo = () => {
|
|
1314
|
+
JToast.info('정보 메시지입니다')
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
// Warning Toast
|
|
1318
|
+
const showWarning = () => {
|
|
1319
|
+
JToast.warning('경고 메시지입니다')
|
|
1320
|
+
}
|
|
1321
|
+
</script>
|
|
1322
|
+
```
|
|
1323
|
+
|
|
1324
|
+
#### 고급 사용법
|
|
1325
|
+
|
|
1326
|
+
```vue
|
|
1327
|
+
<script setup>
|
|
1328
|
+
import { JToast } from '@/components/atoms'
|
|
1329
|
+
|
|
1330
|
+
// Description이 있는 Toast
|
|
1331
|
+
const showWithDescription = () => {
|
|
1332
|
+
JToast('제목', {
|
|
1333
|
+
description: '추가 설명 텍스트',
|
|
1334
|
+
})
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
// Action 버튼이 있는 Toast
|
|
1338
|
+
const showWithAction = () => {
|
|
1339
|
+
JToast('제목', {
|
|
1340
|
+
description: '설명 텍스트',
|
|
1341
|
+
action: {
|
|
1342
|
+
label: '실행 취소',
|
|
1343
|
+
onClick: () => {
|
|
1344
|
+
console.log('실행 취소')
|
|
1345
|
+
},
|
|
1346
|
+
},
|
|
1347
|
+
})
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
// Promise Toast (비동기 작업 표시)
|
|
1351
|
+
const showPromiseToast = async () => {
|
|
1352
|
+
await JToast.promise(
|
|
1353
|
+
fetch('/api/data').then(res => res.json()),
|
|
1354
|
+
{
|
|
1355
|
+
loading: '로딩 중...',
|
|
1356
|
+
success: (data) => `${data.name}이(가) 생성되었습니다`,
|
|
1357
|
+
error: '오류가 발생했습니다',
|
|
1358
|
+
}
|
|
1359
|
+
)
|
|
1360
|
+
}
|
|
1361
|
+
</script>
|
|
1362
|
+
```
|
|
1363
|
+
|
|
1364
|
+
**주요 특징:**
|
|
1365
|
+
- `JToast`: Toast 메시지를 표시하는 함수 (`JToast.success()`, `JToast.error()` 등)
|
|
1366
|
+
- `JToaster`: Toast를 렌더링하는 컨테이너 컴포넌트 (`<JToaster />`)
|
|
1367
|
+
- 자동 사라짐: 기본적으로 몇 초 후 자동으로 사라집니다
|
|
1368
|
+
- 여러 Toast 동시 표시 가능
|
|
1369
|
+
- 위치 설정 가능: `top-left`, `top-center`, `top-right`, `bottom-left`, `bottom-center`, `bottom-right`
|
|
1370
|
+
|
|
355
1371
|
### JFormField 사용 권장사항
|
|
356
1372
|
|
|
357
1373
|
폼 필드를 만들 때는 `JFormField`를 사용하세요. `label`, `error-msg` prop으로 값을 입력하면 UI 배치시 라벨과 에러 메시지가 포함됩니다. `type` prop으로 원하는 입력 컴포넌트를 선택할 수 있습니다:
|
|
@@ -428,51 +1444,6 @@ const formSchema = {
|
|
|
428
1444
|
- `sectioned`: 섹션별로 구분된 폼
|
|
429
1445
|
- `wizard`: 단계별 입력 폼
|
|
430
1446
|
|
|
431
|
-
### 이벤트 처리
|
|
432
|
-
|
|
433
|
-
컴포넌트는 표준 Vue 이벤트를 발생시킵니다. `v-model`과 함께 이벤트 핸들러를 사용할 수 있습니다:
|
|
434
|
-
|
|
435
|
-
```vue
|
|
436
|
-
<template>
|
|
437
|
-
<JButton @click="handleClick">클릭</JButton>
|
|
438
|
-
<JInput v-model="name" @change="handleChange" />
|
|
439
|
-
<JModal
|
|
440
|
-
:open="isOpen"
|
|
441
|
-
@confirm="handleConfirm"
|
|
442
|
-
@cancel="handleCancel"
|
|
443
|
-
/>
|
|
444
|
-
</template>
|
|
445
|
-
|
|
446
|
-
<script setup>
|
|
447
|
-
import { ref } from 'vue'
|
|
448
|
-
|
|
449
|
-
const name = ref('')
|
|
450
|
-
const isOpen = ref(false)
|
|
451
|
-
|
|
452
|
-
const handleClick = () => {
|
|
453
|
-
console.log('버튼 클릭')
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
const handleChange = (value) => {
|
|
457
|
-
console.log('값 변경:', value)
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
const handleConfirm = () => {
|
|
461
|
-
console.log('확인')
|
|
462
|
-
isOpen.value = false
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
const handleCancel = () => {
|
|
466
|
-
console.log('취소')
|
|
467
|
-
isOpen.value = false
|
|
468
|
-
}
|
|
469
|
-
</script>
|
|
470
|
-
```
|
|
471
|
-
|
|
472
|
-
---
|
|
473
|
-
|
|
474
|
-
## 고급 사용법
|
|
475
|
-
|
|
476
1447
|
### JDynamicTabs - 경로 기반 컴포넌트 로딩
|
|
477
1448
|
|
|
478
1449
|
`JDynamicTabs`는 런타임에 탭을 동적으로 추가/제거할 수 있는 컴포넌트입니다. 경로(`/user/info` 같은)만 가지고 있을 때 해당 경로의 Vue 컴포넌트를 탭 콘텐츠로 표시하는 방법에 대한 가이드입니다.
|
|
@@ -706,6 +1677,30 @@ const handleMenuClick = (item) => {
|
|
|
706
1677
|
|
|
707
1678
|
템플릿 컴포넌트는 전체 페이지 레이아웃을 구성하는 데 사용됩니다. 프로젝트의 요구사항에 따라 적절한 템플릿을 선택하세요.
|
|
708
1679
|
|
|
1680
|
+
### JLayout - 기본 레이아웃
|
|
1681
|
+
|
|
1682
|
+
커스텀 레이아웃을 구성할 때 사용합니다.
|
|
1683
|
+
|
|
1684
|
+
```vue
|
|
1685
|
+
<template>
|
|
1686
|
+
<JLayout>
|
|
1687
|
+
<template #header>
|
|
1688
|
+
<JHeader :menu-items="menuItems" />
|
|
1689
|
+
</template>
|
|
1690
|
+
<template #sidebar>
|
|
1691
|
+
<JSidebarSimple :menu-items="menuItems" />
|
|
1692
|
+
</template>
|
|
1693
|
+
<template #content>
|
|
1694
|
+
<RouterView />
|
|
1695
|
+
</template>
|
|
1696
|
+
</JLayout>
|
|
1697
|
+
</template>
|
|
1698
|
+
|
|
1699
|
+
<script setup>
|
|
1700
|
+
import { JLayout, JHeader, JSidebarSimple } from '@/components'
|
|
1701
|
+
</script>
|
|
1702
|
+
```
|
|
1703
|
+
|
|
709
1704
|
### JLayoutAdvanced 사용 시
|
|
710
1705
|
|
|
711
1706
|
- 탭 기반 멀티 페이지 애플리케이션
|
|
@@ -714,15 +1709,21 @@ const handleMenuClick = (item) => {
|
|
|
714
1709
|
- 권한 관리 필요
|
|
715
1710
|
|
|
716
1711
|
```vue
|
|
717
|
-
<
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
<
|
|
724
|
-
|
|
725
|
-
</
|
|
1712
|
+
<template>
|
|
1713
|
+
<JLayoutAdvanced
|
|
1714
|
+
:menu-items="menuItems"
|
|
1715
|
+
:favorites="favorites"
|
|
1716
|
+
:permissions="permissions"
|
|
1717
|
+
>
|
|
1718
|
+
<template #content-tab-{id}>
|
|
1719
|
+
<RouterView />
|
|
1720
|
+
</template>
|
|
1721
|
+
</JLayoutAdvanced>
|
|
1722
|
+
</template>
|
|
1723
|
+
|
|
1724
|
+
<script setup>
|
|
1725
|
+
import { JLayoutAdvanced } from '@/components'
|
|
1726
|
+
</script>
|
|
726
1727
|
```
|
|
727
1728
|
|
|
728
1729
|
### JLayoutSimple 사용 시
|
|
@@ -732,17 +1733,23 @@ const handleMenuClick = (item) => {
|
|
|
732
1733
|
- 검색 기능만 필요
|
|
733
1734
|
|
|
734
1735
|
```vue
|
|
735
|
-
<
|
|
736
|
-
<
|
|
737
|
-
<
|
|
738
|
-
|
|
739
|
-
</
|
|
1736
|
+
<template>
|
|
1737
|
+
<JLayoutSimple :menu-items="menuItems">
|
|
1738
|
+
<template #content>
|
|
1739
|
+
<YourPageContent />
|
|
1740
|
+
</template>
|
|
1741
|
+
</JLayoutSimple>
|
|
1742
|
+
</template>
|
|
1743
|
+
|
|
1744
|
+
<script setup>
|
|
1745
|
+
import { JLayoutSimple } from '@/components'
|
|
1746
|
+
</script>
|
|
740
1747
|
```
|
|
741
1748
|
|
|
742
1749
|
> 💡 **레이아웃 컴포넌트 상세 정보**: [LAYOUT_TEMPLATE_GUIDE.md](./LAYOUT_TEMPLATE_GUIDE.md)를 참고하세요.
|
|
743
1750
|
|
|
744
1751
|
---
|
|
745
1752
|
|
|
746
|
-
**문서 버전**: v1.0
|
|
1753
|
+
**문서 버전**: v1.2.0
|
|
747
1754
|
**최종 업데이트**: 2025년 12월
|
|
748
1755
|
|