@opsnow-mcp/opsnow-mcp-common-ui-server 1.0.21 → 1.0.23
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/build/components/data/icon-names.js +129 -0
- package/build/components/examples/opsnow-common-calendar-examples-data.js +48 -0
- package/build/components/examples/opsnow-common-chart-examples-data.js +6843 -0
- package/build/components/examples/opsnow-common-data-status-examples-data.js +65 -0
- package/build/components/examples/opsnow-common-file-upload-examples-data.js +95 -0
- package/build/components/examples/opsnow-common-forms-examples-data.js +1715 -0
- package/build/components/examples/opsnow-common-grid-examples-data.js +2389 -0
- package/build/components/examples/opsnow-common-icons-examples-data.js +72 -0
- package/build/components/examples/opsnow-common-layout-examples-data.js +97 -0
- package/build/components/examples/opsnow-common-notification-examples-data.js +78 -0
- package/build/components/examples/opsnow-common-pagination-examples-data.js +82 -0
- package/build/components/examples/opsnow-common-popup-examples-data.js +205 -0
- package/build/components/examples/opsnow-common-progress-examples-data.js +86 -0
- package/build/components/examples/opsnow-common-select-examples-data.js +131 -0
- package/build/components/examples/opsnow-common-stepper-examples-data.js +180 -0
- package/build/components/examples/opsnow-common-storage-examples-data.js +8 -0
- package/build/components/examples/opsnow-common-tab-examples-data.js +87 -0
- package/build/components/examples/opsnow-common-toast-popup-examples-data.js +129 -0
- package/build/components/examples/opsnow-common-tooltip-examples-data.js +80 -0
- package/build/components/examples/opsnow-common-typography-examples-data.js +366 -0
- package/build/components/opsnow-common-calendar.js +228 -0
- package/build/components/opsnow-common-chart.js +1643 -0
- package/build/components/opsnow-common-data-status.js +116 -0
- package/build/components/opsnow-common-examples.js +109 -0
- package/build/components/opsnow-common-file-upload.js +57 -0
- package/build/components/opsnow-common-forms.js +1009 -0
- package/build/components/opsnow-common-grid.js +352 -0
- package/build/components/opsnow-common-icons.js +139 -0
- package/build/components/opsnow-common-layout.js +141 -0
- package/build/components/opsnow-common-notification.js +110 -0
- package/build/components/opsnow-common-pagination.js +164 -0
- package/build/components/opsnow-common-popup.js +71 -0
- package/build/components/opsnow-common-progress.js +177 -0
- package/build/components/opsnow-common-select.js +135 -0
- package/build/components/opsnow-common-stepper.js +72 -0
- package/build/components/opsnow-common-tab.js +111 -0
- package/build/components/opsnow-common-toast-popup.js +135 -0
- package/build/components/opsnow-common-tooltip.js +204 -0
- package/build/components/opsnow-common-typography.js +93 -0
- package/build/index.js +135 -0
- package/package.json +1 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// Stepper 컴포넌트 관련 스키마 정의 (예제 코드에 맞게 확장)
|
|
3
|
+
export const StepperSchema = z.object({
|
|
4
|
+
steps: z.array(z.object({
|
|
5
|
+
label: z.string().describe("스텝 라벨"),
|
|
6
|
+
status: z.string().optional().describe("스텝 상태 (NotStarted, Completed, Error 등)"),
|
|
7
|
+
optionalText: z.string().optional().describe("옵셔널 텍스트"),
|
|
8
|
+
description: z.string().optional(),
|
|
9
|
+
icon: z.string().optional(),
|
|
10
|
+
// slot은 StepContent에서만 사용
|
|
11
|
+
})).describe("스텝 목록"),
|
|
12
|
+
activeStep: z.number().optional().default(0).describe("현재 스텝 인덱스"),
|
|
13
|
+
orientation: z.enum(["horizontal", "vertical"]).optional().default("horizontal").describe("스텝 방향"),
|
|
14
|
+
align: z.enum(["left", "center", "right"]).optional().describe("스텝 정렬"),
|
|
15
|
+
isSimpleView: z.boolean().optional().describe("심플 뷰 여부"),
|
|
16
|
+
connector: z.string().optional().describe("커스텀 커넥터 컴포넌트(JSX 문자열)"),
|
|
17
|
+
onStepClick: z.string().optional().describe("스텝 클릭 핸들러 함수명"),
|
|
18
|
+
contentPadding: z.string().optional().describe("컨텐츠 패딩 스타일"),
|
|
19
|
+
contentHeight: z.string().optional().describe("컨텐츠 높이 스타일"),
|
|
20
|
+
nonLinear: z.boolean().optional().describe("논리니어 여부"),
|
|
21
|
+
contentDependency: z.boolean().optional().describe("컨텐츠 의존성 여부"),
|
|
22
|
+
size: z.enum(["default", "small"]).optional().default("default").describe("스텝 크기"),
|
|
23
|
+
onChange: z.string().optional().describe("스텝 변경 이벤트 핸들러 함수명"),
|
|
24
|
+
clickable: z.boolean().optional().default(false).describe("스텝 클릭 가능 여부")
|
|
25
|
+
});
|
|
26
|
+
// Stepper 컴포넌트 함수 - 배열 반환
|
|
27
|
+
export function createStepperComponent() {
|
|
28
|
+
return [
|
|
29
|
+
{
|
|
30
|
+
name: "createStepper",
|
|
31
|
+
description: `스텝퍼 컴포넌트 - 단계별 진행 상황 표시
|
|
32
|
+
|
|
33
|
+
**import 예시(React의 모든 훅(useState, useEffect, useCommonComponents 등)은 반드시 함수 컴포넌트 내부에서 호출):**
|
|
34
|
+
\`\`\`javascript
|
|
35
|
+
import { useCommonComponents } from '@opsnow-common/opsnow-finops-common-ui-loader';
|
|
36
|
+
const { OpsnowCommonStepper, OpsnowCommonStepContent } = useCommonComponents();
|
|
37
|
+
\`\`\``,
|
|
38
|
+
parameters: StepperSchema,
|
|
39
|
+
handler: async (args) => {
|
|
40
|
+
const { steps, activeStep = 0, orientation = "horizontal", align, isSimpleView, connector, onStepClick, contentPadding, contentHeight, nonLinear, contentDependency, size = "default", onChange, clickable } = args;
|
|
41
|
+
// 태그 props만 생성
|
|
42
|
+
const propList = [
|
|
43
|
+
`steps={steps}`,
|
|
44
|
+
`activeStep={activeStep}`,
|
|
45
|
+
`orientation=\"${orientation}\"`,
|
|
46
|
+
align ? `align=\"${align}\"` : '',
|
|
47
|
+
isSimpleView ? 'isSimpleView' : '',
|
|
48
|
+
connector ? `connector={${connector}}` : '',
|
|
49
|
+
onStepClick ? `onStepClick={${onStepClick}}` : '',
|
|
50
|
+
contentPadding ? `contentPadding=\"${contentPadding}\"` : '',
|
|
51
|
+
contentHeight ? `contentHeight=\"${contentHeight}\"` : '',
|
|
52
|
+
nonLinear ? 'nonLinear' : '',
|
|
53
|
+
typeof contentDependency === 'boolean' ? `contentDependency={${contentDependency}}` : '',
|
|
54
|
+
`size=\"${size}\"`,
|
|
55
|
+
onChange ? `onChange={${onChange}}` : '',
|
|
56
|
+
clickable ? 'clickable' : ''
|
|
57
|
+
].filter(Boolean);
|
|
58
|
+
// StepContent 샘플
|
|
59
|
+
const stepContent = steps.map((_, idx) => ` <OpsnowCommonStepContent stepIndex={${idx}} />`).join('\n');
|
|
60
|
+
const code = `<OpsnowCommonStepper\n ${propList.join('\n ')}\n>\n${stepContent}\n</OpsnowCommonStepper>`;
|
|
61
|
+
return {
|
|
62
|
+
content: [
|
|
63
|
+
{
|
|
64
|
+
type: "text",
|
|
65
|
+
text: `\`\`\`jsx\n${code}\n\`\`\``
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
];
|
|
72
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// Tab 컴포넌트 관련 스키마 정의
|
|
3
|
+
export const TabSchema = z.object({
|
|
4
|
+
items: z
|
|
5
|
+
.array(z.object({
|
|
6
|
+
label: z.string().describe("탭 라벨 - icon이 들어가지 않음 icon 사용 시 반드시 iconName으로 사용"),
|
|
7
|
+
content: z.string().describe("각 탭에 들어가는 내용"),
|
|
8
|
+
disabled: z
|
|
9
|
+
.boolean()
|
|
10
|
+
.optional()
|
|
11
|
+
.default(false)
|
|
12
|
+
.describe("탭 비활성화 여부"),
|
|
13
|
+
iconName: z.string().optional().describe("아이콘 이름"),
|
|
14
|
+
}))
|
|
15
|
+
.describe("탭 목록"),
|
|
16
|
+
orientation: z
|
|
17
|
+
.enum(["horizontal", "vertical"])
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("탭 방향"),
|
|
20
|
+
contentGap: z
|
|
21
|
+
.enum(["small", "medium", "large"])
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("탭 간격"),
|
|
24
|
+
fullWidth: z.boolean().optional().describe("탭 전체 너비 사용 여부"),
|
|
25
|
+
value: z
|
|
26
|
+
.string()
|
|
27
|
+
.describe("선택되어 있는 탭 값 - state 변수명(변경했을때 반영가능하도록 useSate), 숫자 "),
|
|
28
|
+
depth: z.number().min(1).max(3).optional().describe("탭 깊이 1~3"),
|
|
29
|
+
onChange: z.string().optional().describe("탭 변경 이벤트 핸들러 함수명"),
|
|
30
|
+
color: z.enum(["primary", "secondary"]).optional().describe("탭 색상"),
|
|
31
|
+
}).describe("탭 컴포넌트 - createIconsComponent에서 iconName을 반드시 참조하여 string으로 입력");
|
|
32
|
+
// Tab 컴포넌트 함수 - 배열 반환
|
|
33
|
+
export function createTabComponent() {
|
|
34
|
+
return [
|
|
35
|
+
{
|
|
36
|
+
name: "createTab",
|
|
37
|
+
description: `탭 컴포넌트 - 탭 인터페이스 및 콘텐츠 관리
|
|
38
|
+
**import 예시:**
|
|
39
|
+
\`\`\`javascript
|
|
40
|
+
import { useCommonComponents } from '@opsnow-common/opsnow-finops-common-ui-loader';
|
|
41
|
+
const { OpsnowCommonTab } = useCommonComponents();
|
|
42
|
+
\`\`\`
|
|
43
|
+
`,
|
|
44
|
+
parameters: TabSchema,
|
|
45
|
+
handler: async (args) => {
|
|
46
|
+
// 탭 컴포넌트 로직 구현
|
|
47
|
+
let code = "";
|
|
48
|
+
if (args.onChange) {
|
|
49
|
+
code += `
|
|
50
|
+
const ${args.onChange} = (_event, newValue) => {
|
|
51
|
+
// 탭 변경 이벤트 핸들러 함수 구현
|
|
52
|
+
`;
|
|
53
|
+
}
|
|
54
|
+
const props = [];
|
|
55
|
+
if (args.value) {
|
|
56
|
+
props.push(`value={${args.value}}`);
|
|
57
|
+
}
|
|
58
|
+
if (args.items) {
|
|
59
|
+
const itemsArray = args.items
|
|
60
|
+
.map((item) => {
|
|
61
|
+
const itemProps = [];
|
|
62
|
+
itemProps.push(`label: '${item.label}'`);
|
|
63
|
+
if (item.content) {
|
|
64
|
+
itemProps.push(`content: <div>${item.content}</div>`);
|
|
65
|
+
}
|
|
66
|
+
if (item.disabled) {
|
|
67
|
+
itemProps.push(`disabled: ${item.disabled}`);
|
|
68
|
+
}
|
|
69
|
+
if (item.iconName) {
|
|
70
|
+
itemProps.push(`iconName: '${item.iconName}'`);
|
|
71
|
+
}
|
|
72
|
+
return `{ ${itemProps.join(", ")} }`;
|
|
73
|
+
})
|
|
74
|
+
.join(",\n ");
|
|
75
|
+
props.push(`items={[
|
|
76
|
+
${itemsArray}
|
|
77
|
+
]}`);
|
|
78
|
+
}
|
|
79
|
+
if (args.orientation) {
|
|
80
|
+
props.push(`orientation="${args.orientation}"`);
|
|
81
|
+
}
|
|
82
|
+
if (args.contentGap) {
|
|
83
|
+
props.push(`contentGap="${args.contentGap}"`);
|
|
84
|
+
}
|
|
85
|
+
if (args.fullWidth) {
|
|
86
|
+
props.push(`fullWidth={${args.fullWidth}}`);
|
|
87
|
+
}
|
|
88
|
+
if (args.depth) {
|
|
89
|
+
props.push(`depth={${args.depth}}`);
|
|
90
|
+
}
|
|
91
|
+
if (args.onChange) {
|
|
92
|
+
props.push(`onChange={${args.onChange}}`);
|
|
93
|
+
}
|
|
94
|
+
if (args.color) {
|
|
95
|
+
props.push(`color="${args.color}"`);
|
|
96
|
+
}
|
|
97
|
+
code += `
|
|
98
|
+
<OpsnowCommonTab ${props.join(" ")} />
|
|
99
|
+
`;
|
|
100
|
+
return {
|
|
101
|
+
content: [
|
|
102
|
+
{
|
|
103
|
+
type: "text",
|
|
104
|
+
text: `\`\`\`jsx\n${code}\n\`\`\``,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// Toast Popup 컴포넌트 관련 스키마 정의
|
|
3
|
+
export const ToastPopupSchema = z.object({
|
|
4
|
+
message: z.string().describe("토스트에 표시될 메시지"),
|
|
5
|
+
options: z.object({
|
|
6
|
+
color: z
|
|
7
|
+
.enum(["success", "error", "info", "warning", "default"])
|
|
8
|
+
.optional()
|
|
9
|
+
.default("default")
|
|
10
|
+
.describe("토스트 타입"),
|
|
11
|
+
autoHideDuration: z
|
|
12
|
+
.number()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("토스트 메시지 노출 시간(ms)"),
|
|
15
|
+
useCancelButton: z
|
|
16
|
+
.boolean()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("취소 버튼 사용 여부"),
|
|
19
|
+
useTitle: z
|
|
20
|
+
.boolean()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("타이틀 사용 여부 - title 속성 사용 시 자동으로 true로 설정"),
|
|
23
|
+
title: z.string().optional().describe("토스트 팝업 타이틀"),
|
|
24
|
+
customAction: z.string().optional().describe("토스트 팝업 내부 버튼 커스텀 코드(반드시 OpsnowCommonButton 컴포넌트 사용) - 예시: <OpsnowCommonButton onClick={handleCustomAction} /> "),
|
|
25
|
+
anchorOrigin: z
|
|
26
|
+
.object({
|
|
27
|
+
vertical: z
|
|
28
|
+
.enum(["top", "bottom"])
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("토스트 vertical 위치"),
|
|
31
|
+
horizontal: z
|
|
32
|
+
.enum(["left", "center", "right"])
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("토스트 horizontal 위치"),
|
|
35
|
+
})
|
|
36
|
+
.optional()
|
|
37
|
+
.describe("토스트 위치 - vertical, horizontal"),
|
|
38
|
+
preventDuplicate: z
|
|
39
|
+
.boolean()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("중복 토스트 방지 여부"),
|
|
42
|
+
persist: z.boolean().optional().default(false).describe("토스트 지속 여부"),
|
|
43
|
+
transitionDuration: z
|
|
44
|
+
.object({
|
|
45
|
+
enter: z
|
|
46
|
+
.number()
|
|
47
|
+
.optional()
|
|
48
|
+
.default(300)
|
|
49
|
+
.describe("토스트 애니메이션 지속 시간(ms)"),
|
|
50
|
+
exit: z
|
|
51
|
+
.number()
|
|
52
|
+
.optional()
|
|
53
|
+
.default(300)
|
|
54
|
+
.describe("토스트 애니메이션 지속 시간(ms)"),
|
|
55
|
+
})
|
|
56
|
+
.optional()
|
|
57
|
+
.describe("토스트 애니메이션 지속 시간(ms)"),
|
|
58
|
+
action: z.string().optional().describe("JSX 노드 또는 key를 받아 노드를 반환하는 함수도 지원"),
|
|
59
|
+
TransitionComponent: z.string().optional().describe("MUI 트랜지션 컴포넌트(Grow, Zoom, Fade, Slide 등)를 import해서 함수명 그대로 입력 (예: Grow, Zoom})"),
|
|
60
|
+
style: z.record(z.string(), z.string()).optional().describe("토스트 팝업에 적용할 인라인 스타일 객체. 모든 CSS 속성(key)과 값(value)을 string으로 입력 (예: { 'boxShadow': '...', 'borderLeft': '...', 'backgroundColor': '...' })")
|
|
61
|
+
}),
|
|
62
|
+
}).describe("토스트 팝업 - 버튼 컴포넌트 반드시 동시 호출 필요");
|
|
63
|
+
// Toast Popup 컴포넌트 함수 - 배열 반환
|
|
64
|
+
export function createToastPopupComponent() {
|
|
65
|
+
return [
|
|
66
|
+
{
|
|
67
|
+
name: "createToastPopup",
|
|
68
|
+
description: `토스트 팝업 컴포넌트 - 버튼 클릭 시 간단한 알림 메시지 표시
|
|
69
|
+
토스트 팝업 사용 시 버튼 컴포넌트의 onClick은 반드시 필요함.
|
|
70
|
+
버튼 컴포넌트 onClick 함수 내부에 showToast를 사용하여 토스트 팝업 표시
|
|
71
|
+
|
|
72
|
+
**import**:
|
|
73
|
+
import { useCommonComponents } from '@opsnow-common/opsnow-finops-common-ui-loader';
|
|
74
|
+
const { OpsnowCommonToastPopup, showToast, OpsnowCommonButton } = useCommonComponents();
|
|
75
|
+
`,
|
|
76
|
+
parameters: ToastPopupSchema,
|
|
77
|
+
handler: async (args) => {
|
|
78
|
+
// 토스트 팝업 컴포넌트 로직 구현
|
|
79
|
+
let code = "";
|
|
80
|
+
// 토스트 팝업 코드 생성
|
|
81
|
+
let toastCode = "";
|
|
82
|
+
if (args.options) {
|
|
83
|
+
const optionProps = [];
|
|
84
|
+
if (args.options.color)
|
|
85
|
+
optionProps.push(`color: '${args.options.color}'`);
|
|
86
|
+
if (args.options.autoHideDuration)
|
|
87
|
+
optionProps.push(`autoHideDuration: ${args.options.autoHideDuration}`);
|
|
88
|
+
if (args.options.useCancelButton)
|
|
89
|
+
optionProps.push(`useCancelButton: ${args.options.useCancelButton}`);
|
|
90
|
+
if (args.options.useTitle)
|
|
91
|
+
optionProps.push(`useTitle: ${args.options.useTitle}`);
|
|
92
|
+
if (args.options.title)
|
|
93
|
+
optionProps.push(`title: ${args.options.title}`);
|
|
94
|
+
if (args.options.customAction) {
|
|
95
|
+
optionProps.push(`customAction: (${args.options.customAction})`);
|
|
96
|
+
}
|
|
97
|
+
if (args.options.anchorOrigin?.vertical || args.options.anchorOrigin?.horizontal)
|
|
98
|
+
optionProps.push(`anchorOrigin: ${args.options.anchorOrigin?.vertical ? `vertical: ${args.options.anchorOrigin?.vertical}` : ""}, ${args.options.anchorOrigin?.horizontal ? `horizontal: ${args.options.anchorOrigin?.horizontal}` : ""}`);
|
|
99
|
+
if (args.options.preventDuplicate)
|
|
100
|
+
optionProps.push(`preventDuplicate: ${args.options.preventDuplicate}`);
|
|
101
|
+
if (args.options.persist)
|
|
102
|
+
optionProps.push(`persist: ${args.options.persist}`);
|
|
103
|
+
if (args.options.transitionDuration?.enter || args.options.transitionDuration?.exit)
|
|
104
|
+
optionProps.push(`transitionDuration: ${args.options.transitionDuration?.enter ? `enter: ${args.options.transitionDuration?.enter}` : ""}, ${args.options.transitionDuration?.exit ? `exit: ${args.options.transitionDuration?.exit}` : ""}`);
|
|
105
|
+
if (args.options.action)
|
|
106
|
+
optionProps.push(`action: ${args.options.action}`);
|
|
107
|
+
if (args.options.TransitionComponent)
|
|
108
|
+
optionProps.push(`TransitionComponent: ${args.options.TransitionComponent}`);
|
|
109
|
+
if (args.options.style) {
|
|
110
|
+
optionProps.push(`style: {${Object.entries(args.options.style)
|
|
111
|
+
.map(([key, value]) => `${key}: '${value}'`)
|
|
112
|
+
.join(', ')}}`);
|
|
113
|
+
}
|
|
114
|
+
;
|
|
115
|
+
toastCode += `{
|
|
116
|
+
${optionProps.join(', ')}
|
|
117
|
+
}`;
|
|
118
|
+
}
|
|
119
|
+
code += `
|
|
120
|
+
const (버튼 컴포넌트 onClick 함수명) = () => {
|
|
121
|
+
showToast(${args.message ? args.message + ", " : ""}${toastCode});
|
|
122
|
+
}
|
|
123
|
+
`;
|
|
124
|
+
return {
|
|
125
|
+
content: [
|
|
126
|
+
{
|
|
127
|
+
type: "text",
|
|
128
|
+
text: `\`\`\`jsx\n${code}\n\`\`\``,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// Tooltip 컴포넌트 관련 스키마 정의
|
|
3
|
+
export const TooltipSchema = z.object({
|
|
4
|
+
isIconTooltip: z
|
|
5
|
+
.boolean()
|
|
6
|
+
.optional()
|
|
7
|
+
.describe("아이콘으로 툴팁 사용 여부(아이콘 호버 시 툴팁 표시) - 미사용 시 Tooltip 컴포넌트 내부 버튼 필요"),
|
|
8
|
+
titleProps: z
|
|
9
|
+
.object({
|
|
10
|
+
imgSrc: z.string().optional().describe("이미지 소스"),
|
|
11
|
+
imgAlt: z.string().optional().describe("이미지 대체 텍스트"),
|
|
12
|
+
title: z.string().optional().describe("툴팁 내용"),
|
|
13
|
+
})
|
|
14
|
+
.optional()
|
|
15
|
+
.describe("titleProps를 사용할 경우 title or imgSrc 중 하나 필수"),
|
|
16
|
+
placement: z
|
|
17
|
+
.enum([
|
|
18
|
+
"bottom-end",
|
|
19
|
+
"bottom-start",
|
|
20
|
+
"bottom",
|
|
21
|
+
"left-end",
|
|
22
|
+
"left-start",
|
|
23
|
+
"left",
|
|
24
|
+
"right-end",
|
|
25
|
+
"right-start",
|
|
26
|
+
"right",
|
|
27
|
+
"top-end",
|
|
28
|
+
"top-start",
|
|
29
|
+
"top",
|
|
30
|
+
])
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("툴팁 표시 위치 (top, bottom, left, right 및 각각의 start/end 변형)"),
|
|
33
|
+
iconTooltipProps: z
|
|
34
|
+
.object({
|
|
35
|
+
iconName: z
|
|
36
|
+
.string()
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("아이콘 이름 - iconProps.useIcon이 true일 경우 필수"),
|
|
39
|
+
useIcon: z.boolean().optional().describe("아이콘 사용 여부 - iconName이 있을 경우 iconProps.useIcon은 true여야 함, useMuiIcon 과 동시에 true안됨"),
|
|
40
|
+
useMuiIcon: z.boolean().optional().describe("MUI 아이콘 사용 여부 - useIcon 과 동시에 true 안됨"),
|
|
41
|
+
alignItems: z.string().optional().describe("아이콘 정렬 방식"),
|
|
42
|
+
justifyContent: z.string().optional().describe("아이콘 정렬 방식"),
|
|
43
|
+
label: z.string().describe("툴팁 라벨"),
|
|
44
|
+
colorProps: z
|
|
45
|
+
.object({
|
|
46
|
+
commonColor: z.string().optional().describe("툴팁 색상"),
|
|
47
|
+
muiColor: z
|
|
48
|
+
.enum([
|
|
49
|
+
"primary",
|
|
50
|
+
"secondary",
|
|
51
|
+
"error",
|
|
52
|
+
"info",
|
|
53
|
+
"success",
|
|
54
|
+
"warning",
|
|
55
|
+
])
|
|
56
|
+
.optional()
|
|
57
|
+
.describe("툴팁 MUI 색상"),
|
|
58
|
+
})
|
|
59
|
+
.optional()
|
|
60
|
+
.describe("툴팁 색상 설정- color, muiColor 둘 중 하나만 사용 가능"),
|
|
61
|
+
size: z.number().optional().describe("아이콘 툴팁 크기"),
|
|
62
|
+
})
|
|
63
|
+
.optional()
|
|
64
|
+
.describe("isIconTooltip이 true일 경우 추가 필드"),
|
|
65
|
+
onOpen: z.string().optional().describe("툴팁 열림 시 실행할 함수명"),
|
|
66
|
+
onClose: z.string().optional().describe("툴팁 닫힘 시 실행할 함수명"),
|
|
67
|
+
disableFocusListener: z.boolean().describe("포커스 리스너 비활성화 여부"),
|
|
68
|
+
disableHoverListener: z.boolean().describe("호버 리스너 비활성화 여부"),
|
|
69
|
+
disableTouchListener: z.boolean().describe("터치 리스너 비활성화 여부"),
|
|
70
|
+
disableInteractive: z.boolean().describe("대화형 컴포넌트 비활성화 여부"),
|
|
71
|
+
enterDelay: z.number().optional().describe("툴팁 진입 지연 시간 (ms)"),
|
|
72
|
+
enterTouchDelay: z
|
|
73
|
+
.number()
|
|
74
|
+
.optional()
|
|
75
|
+
.describe("툴팁 진입 터치 지연 시간 (ms)"),
|
|
76
|
+
enterNextDelay: z
|
|
77
|
+
.number()
|
|
78
|
+
.optional()
|
|
79
|
+
.describe("툴팁 진입 다음 지연 시간 (ms)"),
|
|
80
|
+
leaveDelay: z.number().optional().describe("툴팁 이탈 지연 시간 (ms)"),
|
|
81
|
+
leaveNextDelay: z
|
|
82
|
+
.number()
|
|
83
|
+
.optional()
|
|
84
|
+
.describe("툴팁 이탈 다음 지연 시간 (ms)"),
|
|
85
|
+
open: z.boolean().describe("툴팁 열림 여부"),
|
|
86
|
+
tooltipFullWidth: z
|
|
87
|
+
.boolean()
|
|
88
|
+
.optional()
|
|
89
|
+
.describe("툴팁 open시 전체 너비 사용 여부"),
|
|
90
|
+
tooltipPreview: z.boolean().optional().describe("툴팁 미리보기 사용 여부"),
|
|
91
|
+
ref: z
|
|
92
|
+
.string()
|
|
93
|
+
.optional()
|
|
94
|
+
.describe("ref를 사용할 경우, ref 변수 명만 문자열로 입력"),
|
|
95
|
+
}).describe("iconName을 사용하는 경우 - createIconsComponent에서 iconName을 반드시 참조하여 string으로 입력, useIcon/useMuiIcon 둘 중 true");
|
|
96
|
+
// Tooltip 컴포넌트 함수 - 배열 반환
|
|
97
|
+
export function createTooltipComponent() {
|
|
98
|
+
return [
|
|
99
|
+
{
|
|
100
|
+
name: "createTooltip",
|
|
101
|
+
description: `툴팁 컴포넌트 - 요소에 대한 추가 정보 표시
|
|
102
|
+
**import 예시:**
|
|
103
|
+
\`\`\`javascript
|
|
104
|
+
import { useCommonComponents } from '@opsnow-common/opsnow-finops-common-ui-loader';
|
|
105
|
+
const { OpsnowCommonTooltip, OpsnowCommonIconTooltip } = useCommonComponents();
|
|
106
|
+
\`\`\`
|
|
107
|
+
`,
|
|
108
|
+
parameters: TooltipSchema,
|
|
109
|
+
handler: async (args) => {
|
|
110
|
+
let code = "";
|
|
111
|
+
const props = [];
|
|
112
|
+
if (args.ref) {
|
|
113
|
+
code += `const ${args.ref} = useRef(null);
|
|
114
|
+
// ref 객체에는 openTooltip(), closeTooltip(), getOpenState() 메서드가 제공됨`;
|
|
115
|
+
props.push(`ref={${args.ref}}`);
|
|
116
|
+
}
|
|
117
|
+
if (args.titleProps) {
|
|
118
|
+
if (args.titleProps.title)
|
|
119
|
+
props.push(`title="${args.titleProps.title}"`);
|
|
120
|
+
else if (args.titleProps.imgSrc) {
|
|
121
|
+
props.push(`title = {<img src="${args.titleProps.imgSrc}" ${args.titleProps.imgAlt ? "alt= " + args.titleProps.imgAlt : ""} />}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (args.iconTooltipProps) {
|
|
125
|
+
if (args.iconTooltipProps.iconName)
|
|
126
|
+
props.push(`iconName={"${args.iconTooltipProps.iconName}"}`);
|
|
127
|
+
if (args.placement)
|
|
128
|
+
props.push(`placement="${args.placement}"`);
|
|
129
|
+
if (args.iconTooltipProps.useIcon)
|
|
130
|
+
props.push(`useIcon={${args.iconTooltipProps.useIcon}}`);
|
|
131
|
+
if (args.iconTooltipProps.useMuiIcon)
|
|
132
|
+
props.push(`useMuiIcon={${args.iconTooltipProps.useMuiIcon}}`);
|
|
133
|
+
if (args.iconTooltipProps.alignItems)
|
|
134
|
+
props.push(`alignItems="${args.iconTooltipProps.alignItems}"`);
|
|
135
|
+
if (args.iconTooltipProps.justifyContent)
|
|
136
|
+
props.push(`justifyContent="${args.iconTooltipProps.justifyContent}"`);
|
|
137
|
+
if (args.iconTooltipProps.colorProps) {
|
|
138
|
+
if (args.iconTooltipProps.colorProps.commonColor)
|
|
139
|
+
props.push(`commonColor={'${args.iconTooltipProps.colorProps.commonColor}'}`);
|
|
140
|
+
if (args.iconTooltipProps.colorProps.muiColor)
|
|
141
|
+
props.push(`muiColor={'${args.iconTooltipProps.colorProps.muiColor}'}`);
|
|
142
|
+
}
|
|
143
|
+
if (args.iconTooltipProps.size)
|
|
144
|
+
props.push(`size={${args.iconTooltipProps.size}}`);
|
|
145
|
+
}
|
|
146
|
+
if (args.disableFocusListener)
|
|
147
|
+
props.push(`disableFocusListener`);
|
|
148
|
+
if (args.disableHoverListener)
|
|
149
|
+
props.push(`disableHoverListener`);
|
|
150
|
+
if (args.disableTouchListener)
|
|
151
|
+
props.push(`disableTouchListener`);
|
|
152
|
+
if (args.disableInteractive)
|
|
153
|
+
props.push(`disableInteractive`);
|
|
154
|
+
if (args.enterDelay)
|
|
155
|
+
props.push(`enterDelay={${args.enterDelay}}`);
|
|
156
|
+
if (args.enterTouchDelay)
|
|
157
|
+
props.push(`enterTouchDelay={${args.enterTouchDelay}}`);
|
|
158
|
+
if (args.enterNextDelay)
|
|
159
|
+
props.push(`enterNextDelay={${args.enterNextDelay}}`);
|
|
160
|
+
if (args.leaveDelay)
|
|
161
|
+
props.push(`leaveDelay={${args.leaveDelay}}`);
|
|
162
|
+
if (args.leaveNextDelay)
|
|
163
|
+
props.push(`leaveNextDelay={${args.leaveNextDelay}}`);
|
|
164
|
+
if (args.open)
|
|
165
|
+
props.push(`open={${args.open}}`);
|
|
166
|
+
if (args.tooltipFullWidth)
|
|
167
|
+
props.push(`tooltipFullWidth={${args.tooltipFullWidth}}`);
|
|
168
|
+
if (args.tooltipPreview) {
|
|
169
|
+
if (args.isIconTooltip)
|
|
170
|
+
props.push(`tooltipPreview={${args.tooltipPreview}}`);
|
|
171
|
+
else
|
|
172
|
+
props.push(`useTooltipPreview={${args.tooltipPreview}}`);
|
|
173
|
+
}
|
|
174
|
+
if (args.onOpen)
|
|
175
|
+
props.push(`onOpen={${args.onOpen}}`);
|
|
176
|
+
if (args.onClose)
|
|
177
|
+
props.push(`onClose={${args.onClose}}`);
|
|
178
|
+
if (args.isIconTooltip) {
|
|
179
|
+
code += `
|
|
180
|
+
<OpsnowCommonIconTooltip ${props.join(" ")}>
|
|
181
|
+
</OpsnowCommonIconTooltip>
|
|
182
|
+
`;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
code += `
|
|
186
|
+
<OpsnowCommonTooltip ${props.join(" ")}
|
|
187
|
+
>
|
|
188
|
+
// Button 컴포넌트 필요(Mui Button or OpsnowCommonButton)
|
|
189
|
+
</OpsnowCommonTooltip>
|
|
190
|
+
`;
|
|
191
|
+
}
|
|
192
|
+
// 툴팁 컴포넌트 로직 구현
|
|
193
|
+
return {
|
|
194
|
+
content: [
|
|
195
|
+
{
|
|
196
|
+
type: "text",
|
|
197
|
+
text: `\`\`\`jsx\n${code}\n\`\`\``,
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
};
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
];
|
|
204
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// MUI typography variants to support in addition to e-r/e-m/e-b
|
|
3
|
+
const muiVariants = [
|
|
4
|
+
'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
|
|
5
|
+
'subtitle1', 'subtitle2',
|
|
6
|
+
'body1', 'body2',
|
|
7
|
+
'caption', 'overline',
|
|
8
|
+
];
|
|
9
|
+
// 지원하는 variant만 명확히 제한
|
|
10
|
+
const variantList = [
|
|
11
|
+
...Array.from({ length: 13 }, (_, i) => `e-r${i + 1}`),
|
|
12
|
+
...Array.from({ length: 13 }, (_, i) => `e-m${i + 1}`),
|
|
13
|
+
...Array.from({ length: 13 }, (_, i) => `e-b${i + 1}`),
|
|
14
|
+
...muiVariants,
|
|
15
|
+
];
|
|
16
|
+
// z.enum에 [string, ...string[]] 타입으로 변환
|
|
17
|
+
const variantListForEnum = variantList;
|
|
18
|
+
// 1. CommonPalette 색상 그룹과 단계 정의
|
|
19
|
+
const commonPaletteColors = [
|
|
20
|
+
'gray', 'darkblue', 'blue', 'skyblue', 'green', 'cyan', 'yellow', 'pink', 'purple', 'orange', 'red',
|
|
21
|
+
// 필요시 etc. 추가
|
|
22
|
+
];
|
|
23
|
+
const commonPaletteDepths = [
|
|
24
|
+
'100', '200', '300', '400', '500', '600', '700', '800', '900',
|
|
25
|
+
];
|
|
26
|
+
// 2. 모든 조합을 string literal union 타입으로 생성
|
|
27
|
+
const commonPaletteList = commonPaletteColors.flatMap(color => commonPaletteDepths.map(depth => `commonPalette.${color}.${depth}`));
|
|
28
|
+
const commonPaletteListForEnum = commonPaletteList;
|
|
29
|
+
export const TypographySchema = z.object({
|
|
30
|
+
text: z.string().describe("표시할 텍스트"),
|
|
31
|
+
variant: z.enum(variantListForEnum).describe("타이포그래피 스타일(variant, e-r1~e-b13만 허용)"),
|
|
32
|
+
color: z.enum(commonPaletteListForEnum).optional().describe("텍스트 색상 또는 CommonPalette 팔레트 값만 허용 (예: commonPalette.green.300)"),
|
|
33
|
+
theme: z.enum([
|
|
34
|
+
"primary", "secondary", "warning", "success", "error", "info", "description", "disabled"
|
|
35
|
+
]).optional().describe("테마 색상"),
|
|
36
|
+
align: z.enum([
|
|
37
|
+
"inherit", "left", "center", "right", "justify"
|
|
38
|
+
]).optional().describe("정렬 방식"),
|
|
39
|
+
gutterBottom: z.boolean().optional().describe("하단 마진 추가 여부"),
|
|
40
|
+
noWrap: z.boolean().optional().describe("텍스트 줄바꿈 방지 여부"),
|
|
41
|
+
paragraph: z.boolean().optional().describe("paragraph 스타일 적용 여부"),
|
|
42
|
+
component: z.string().optional().describe("커스텀 태그(component) 지정"),
|
|
43
|
+
textDecoration: z.string().optional().describe("텍스트 데코레이션(underline 등)"),
|
|
44
|
+
textTransform: z.string().optional().describe("텍스트 변환(uppercase 등)"),
|
|
45
|
+
});
|
|
46
|
+
export function createTypographyComponent() {
|
|
47
|
+
return [
|
|
48
|
+
{
|
|
49
|
+
name: "createTypography",
|
|
50
|
+
description: `타이포그래피 컴포넌트 - e-r1~e-b13 variant만 지원
|
|
51
|
+
|
|
52
|
+
- variant: e-r1~e-b13만 허용
|
|
53
|
+
- 예제 테이블 스타일에 맞는 Typography만 생성 가능
|
|
54
|
+
|
|
55
|
+
\`\`\`javascript
|
|
56
|
+
import { OpsnowCommonTypography } from '@opsnow-common/opsnow-common-style'
|
|
57
|
+
\`\`\`
|
|
58
|
+
`,
|
|
59
|
+
parameters: TypographySchema,
|
|
60
|
+
handler: async (args) => {
|
|
61
|
+
const props = [`variant="${args.variant}"`];
|
|
62
|
+
if (args.color)
|
|
63
|
+
props.push(`color="${args.color}"`);
|
|
64
|
+
if (args.theme)
|
|
65
|
+
props.push(`theme="${args.theme}"`);
|
|
66
|
+
if (args.align)
|
|
67
|
+
props.push(`align="${args.align}"`);
|
|
68
|
+
if (args.gutterBottom)
|
|
69
|
+
props.push(`gutterBottom`);
|
|
70
|
+
if (args.noWrap)
|
|
71
|
+
props.push(`noWrap`);
|
|
72
|
+
if (args.paragraph)
|
|
73
|
+
props.push(`paragraph`);
|
|
74
|
+
if (args.component)
|
|
75
|
+
props.push(`component="${args.component}"`);
|
|
76
|
+
if (args.textDecoration)
|
|
77
|
+
props.push(`textDecoration="${args.textDecoration}"`);
|
|
78
|
+
if (args.textTransform)
|
|
79
|
+
props.push(`textTransform="${args.textTransform}"`);
|
|
80
|
+
const propsString = props.join(' ');
|
|
81
|
+
const code = `<OpsnowCommonTypography ${propsString}>${args.text}</OpsnowCommonTypography>`;
|
|
82
|
+
return {
|
|
83
|
+
content: [
|
|
84
|
+
{
|
|
85
|
+
type: "text",
|
|
86
|
+
text: `\`\`\`jsx\n${code}\n\`\`\``
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
];
|
|
93
|
+
}
|