컴포넌트 추가방식 변경
This commit is contained in:
91
frontend/lib/registry/components/select-basic/README.md
Normal file
91
frontend/lib/registry/components/select-basic/README.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# SelectBasic 컴포넌트
|
||||
|
||||
select-basic 컴포넌트입니다
|
||||
|
||||
## 개요
|
||||
|
||||
- **ID**: `select-basic`
|
||||
- **카테고리**: input
|
||||
- **웹타입**: select
|
||||
- **작성자**: 개발팀
|
||||
- **버전**: 1.0.0
|
||||
|
||||
## 특징
|
||||
|
||||
- ✅ 자동 등록 시스템
|
||||
- ✅ 타입 안전성
|
||||
- ✅ Hot Reload 지원
|
||||
- ✅ 설정 패널 제공
|
||||
- ✅ 반응형 디자인
|
||||
|
||||
## 사용법
|
||||
|
||||
### 기본 사용법
|
||||
|
||||
```tsx
|
||||
import { SelectBasicComponent } from "@/lib/registry/components/select-basic";
|
||||
|
||||
<SelectBasicComponent
|
||||
component={{
|
||||
id: "my-select-basic",
|
||||
type: "widget",
|
||||
webType: "select",
|
||||
position: { x: 100, y: 100, z: 1 },
|
||||
size: { width: 200, height: 36 },
|
||||
config: {
|
||||
// 설정값들
|
||||
}
|
||||
}}
|
||||
isDesignMode={false}
|
||||
/>
|
||||
```
|
||||
|
||||
### 설정 옵션
|
||||
|
||||
| 속성 | 타입 | 기본값 | 설명 |
|
||||
|------|------|--------|------|
|
||||
| placeholder | string | "" | 플레이스홀더 텍스트 |
|
||||
| disabled | boolean | false | 비활성화 여부 |
|
||||
| required | boolean | false | 필수 입력 여부 |
|
||||
| readonly | boolean | false | 읽기 전용 여부 |
|
||||
|
||||
## 이벤트
|
||||
|
||||
- `onChange`: 값 변경 시
|
||||
- `onFocus`: 포커스 시
|
||||
- `onBlur`: 포커스 해제 시
|
||||
- `onClick`: 클릭 시
|
||||
|
||||
## 스타일링
|
||||
|
||||
컴포넌트는 다음과 같은 스타일 옵션을 제공합니다:
|
||||
|
||||
- `variant`: "default" | "outlined" | "filled"
|
||||
- `size`: "sm" | "md" | "lg"
|
||||
|
||||
## 예시
|
||||
|
||||
```tsx
|
||||
// 기본 예시
|
||||
<SelectBasicComponent
|
||||
component={{
|
||||
id: "sample-select-basic",
|
||||
config: {
|
||||
placeholder: "입력하세요",
|
||||
required: true,
|
||||
variant: "outlined"
|
||||
}
|
||||
}}
|
||||
/>
|
||||
```
|
||||
|
||||
## 개발자 정보
|
||||
|
||||
- **생성일**: 2025-09-11
|
||||
- **CLI 명령어**: `node scripts/create-component.js select-basic --category=input --webType=select`
|
||||
- **경로**: `lib/registry/components/select-basic/`
|
||||
|
||||
## 관련 문서
|
||||
|
||||
- [컴포넌트 시스템 가이드](../../docs/컴포넌트_시스템_가이드.md)
|
||||
- [개발자 문서](https://docs.example.com/components/select-basic)
|
||||
@@ -0,0 +1,141 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { ComponentRendererProps } from "@/types/component";
|
||||
import { SelectBasicConfig } from "./types";
|
||||
|
||||
export interface SelectBasicComponentProps extends ComponentRendererProps {
|
||||
config?: SelectBasicConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* SelectBasic 컴포넌트
|
||||
* select-basic 컴포넌트입니다
|
||||
*/
|
||||
export const SelectBasicComponent: React.FC<SelectBasicComponentProps> = ({
|
||||
component,
|
||||
isDesignMode = false,
|
||||
isSelected = false,
|
||||
onClick,
|
||||
onDragStart,
|
||||
onDragEnd,
|
||||
config,
|
||||
className,
|
||||
style,
|
||||
...props
|
||||
}) => {
|
||||
// 컴포넌트 설정
|
||||
const componentConfig = {
|
||||
...config,
|
||||
...component.config,
|
||||
} as SelectBasicConfig;
|
||||
|
||||
// 스타일 계산 (위치는 RealtimePreviewDynamic에서 처리하므로 제외)
|
||||
const componentStyle: React.CSSProperties = {
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
...component.style,
|
||||
...style,
|
||||
};
|
||||
|
||||
// 디자인 모드 스타일
|
||||
if (isDesignMode) {
|
||||
componentStyle.border = "1px dashed #cbd5e1";
|
||||
componentStyle.borderColor = isSelected ? "#3b82f6" : "#cbd5e1";
|
||||
}
|
||||
|
||||
// 이벤트 핸들러
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
onClick?.();
|
||||
};
|
||||
|
||||
// DOM에 전달하면 안 되는 React-specific props 필터링
|
||||
const {
|
||||
selectedScreen,
|
||||
onZoneComponentDrop,
|
||||
onZoneClick,
|
||||
componentConfig: _componentConfig,
|
||||
component: _component,
|
||||
isSelected: _isSelected,
|
||||
onClick: _onClick,
|
||||
onDragStart: _onDragStart,
|
||||
onDragEnd: _onDragEnd,
|
||||
size: _size,
|
||||
position: _position,
|
||||
style: _style,
|
||||
...domProps
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div style={componentStyle} className={className} {...domProps}>
|
||||
{/* 라벨 렌더링 */}
|
||||
{component.label && (
|
||||
<label
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "-25px",
|
||||
left: "0px",
|
||||
fontSize: component.style?.labelFontSize || "14px",
|
||||
color: component.style?.labelColor || "#374151",
|
||||
fontWeight: "500",
|
||||
}}
|
||||
>
|
||||
{component.label}
|
||||
{component.required && <span style={{ color: "#ef4444" }}>*</span>}
|
||||
</label>
|
||||
)}
|
||||
|
||||
<select
|
||||
value={component.value || ""}
|
||||
disabled={componentConfig.disabled || false}
|
||||
required={componentConfig.required || false}
|
||||
multiple={componentConfig.multiple || false}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
border: "1px solid #d1d5db",
|
||||
borderRadius: "4px",
|
||||
padding: "8px 12px",
|
||||
fontSize: "14px",
|
||||
outline: "none",
|
||||
backgroundColor: "white",
|
||||
}}
|
||||
onClick={handleClick}
|
||||
onDragStart={onDragStart}
|
||||
onDragEnd={onDragEnd}
|
||||
onChange={(e) => {
|
||||
if (component.onChange) {
|
||||
component.onChange(e.target.value);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{componentConfig.placeholder && (
|
||||
<option value="" disabled>
|
||||
{componentConfig.placeholder}
|
||||
</option>
|
||||
)}
|
||||
{(componentConfig.options || []).map((option, index) => (
|
||||
<option key={index} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
{(!componentConfig.options || componentConfig.options.length === 0) && (
|
||||
<>
|
||||
<option value="option1">옵션 1</option>
|
||||
<option value="option2">옵션 2</option>
|
||||
<option value="option3">옵션 3</option>
|
||||
</>
|
||||
)}
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* SelectBasic 래퍼 컴포넌트
|
||||
* 추가적인 로직이나 상태 관리가 필요한 경우 사용
|
||||
*/
|
||||
export const SelectBasicWrapper: React.FC<SelectBasicComponentProps> = (props) => {
|
||||
return <SelectBasicComponent {...props} />;
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { SelectBasicConfig } from "./types";
|
||||
|
||||
export interface SelectBasicConfigPanelProps {
|
||||
config: SelectBasicConfig;
|
||||
onChange: (config: Partial<SelectBasicConfig>) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* SelectBasic 설정 패널
|
||||
* 컴포넌트의 설정값들을 편집할 수 있는 UI 제공
|
||||
*/
|
||||
export const SelectBasicConfigPanel: React.FC<SelectBasicConfigPanelProps> = ({
|
||||
config,
|
||||
onChange,
|
||||
}) => {
|
||||
const handleChange = (key: keyof SelectBasicConfig, value: any) => {
|
||||
onChange({ [key]: value });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="text-sm font-medium">
|
||||
select-basic 설정
|
||||
</div>
|
||||
|
||||
{/* select 관련 설정 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="placeholder">플레이스홀더</Label>
|
||||
<Input
|
||||
id="placeholder"
|
||||
value={config.placeholder || ""}
|
||||
onChange={(e) => handleChange("placeholder", e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 공통 설정 */}
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="disabled">비활성화</Label>
|
||||
<Checkbox
|
||||
id="disabled"
|
||||
checked={config.disabled || false}
|
||||
onCheckedChange={(checked) => handleChange("disabled", checked)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="required">필수 입력</Label>
|
||||
<Checkbox
|
||||
id="required"
|
||||
checked={config.required || false}
|
||||
onCheckedChange={(checked) => handleChange("required", checked)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="readonly">읽기 전용</Label>
|
||||
<Checkbox
|
||||
id="readonly"
|
||||
checked={config.readonly || false}
|
||||
onCheckedChange={(checked) => handleChange("readonly", checked)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { AutoRegisteringComponentRenderer } from "../../AutoRegisteringComponentRenderer";
|
||||
import { SelectBasicDefinition } from "./index";
|
||||
import { SelectBasicComponent } from "./SelectBasicComponent";
|
||||
|
||||
/**
|
||||
* SelectBasic 렌더러
|
||||
* 자동 등록 시스템을 사용하여 컴포넌트를 레지스트리에 등록
|
||||
*/
|
||||
export class SelectBasicRenderer extends AutoRegisteringComponentRenderer {
|
||||
static componentDefinition = SelectBasicDefinition;
|
||||
|
||||
render(): React.ReactElement {
|
||||
return <SelectBasicComponent {...this.props} renderer={this} />;
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트별 특화 메서드들
|
||||
*/
|
||||
|
||||
// select 타입 특화 속성 처리
|
||||
protected getSelectBasicProps() {
|
||||
const baseProps = this.getWebTypeProps();
|
||||
|
||||
// select 타입에 특화된 추가 속성들
|
||||
return {
|
||||
...baseProps,
|
||||
// 여기에 select 타입 특화 속성들 추가
|
||||
};
|
||||
}
|
||||
|
||||
// 값 변경 처리
|
||||
protected handleValueChange = (value: any) => {
|
||||
this.updateComponent({ value });
|
||||
};
|
||||
|
||||
// 포커스 처리
|
||||
protected handleFocus = () => {
|
||||
// 포커스 로직
|
||||
};
|
||||
|
||||
// 블러 처리
|
||||
protected handleBlur = () => {
|
||||
// 블러 로직
|
||||
};
|
||||
}
|
||||
|
||||
// 자동 등록 실행
|
||||
SelectBasicRenderer.registerSelf();
|
||||
|
||||
// Hot Reload 지원 (개발 모드)
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
SelectBasicRenderer.enableHotReload();
|
||||
}
|
||||
41
frontend/lib/registry/components/select-basic/config.ts
Normal file
41
frontend/lib/registry/components/select-basic/config.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
"use client";
|
||||
|
||||
import { SelectBasicConfig } from "./types";
|
||||
|
||||
/**
|
||||
* SelectBasic 컴포넌트 기본 설정
|
||||
*/
|
||||
export const SelectBasicDefaultConfig: SelectBasicConfig = {
|
||||
options: [],
|
||||
placeholder: "선택하세요",
|
||||
|
||||
// 공통 기본값
|
||||
disabled: false,
|
||||
required: false,
|
||||
readonly: false,
|
||||
variant: "default",
|
||||
size: "md",
|
||||
};
|
||||
|
||||
/**
|
||||
* SelectBasic 컴포넌트 설정 스키마
|
||||
* 유효성 검사 및 타입 체크에 사용
|
||||
*/
|
||||
export const SelectBasicConfigSchema = {
|
||||
placeholder: { type: "string", default: "" },
|
||||
|
||||
// 공통 스키마
|
||||
disabled: { type: "boolean", default: false },
|
||||
required: { type: "boolean", default: false },
|
||||
readonly: { type: "boolean", default: false },
|
||||
variant: {
|
||||
type: "enum",
|
||||
values: ["default", "outlined", "filled"],
|
||||
default: "default"
|
||||
},
|
||||
size: {
|
||||
type: "enum",
|
||||
values: ["sm", "md", "lg"],
|
||||
default: "md"
|
||||
},
|
||||
};
|
||||
41
frontend/lib/registry/components/select-basic/index.ts
Normal file
41
frontend/lib/registry/components/select-basic/index.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import type { WebType } from "@/types/screen";
|
||||
import { SelectBasicWrapper } from "./SelectBasicComponent";
|
||||
import { SelectBasicConfigPanel } from "./SelectBasicConfigPanel";
|
||||
import { SelectBasicConfig } from "./types";
|
||||
|
||||
/**
|
||||
* SelectBasic 컴포넌트 정의
|
||||
* select-basic 컴포넌트입니다
|
||||
*/
|
||||
export const SelectBasicDefinition = createComponentDefinition({
|
||||
id: "select-basic",
|
||||
name: "선택상자",
|
||||
nameEng: "SelectBasic Component",
|
||||
description: "옵션 선택을 위한 드롭다운 선택상자 컴포넌트",
|
||||
category: ComponentCategory.INPUT,
|
||||
webType: "select",
|
||||
component: SelectBasicWrapper,
|
||||
defaultConfig: {
|
||||
options: [],
|
||||
placeholder: "선택하세요",
|
||||
},
|
||||
defaultSize: { width: 200, height: 36 },
|
||||
configPanel: SelectBasicConfigPanel,
|
||||
icon: "Edit",
|
||||
tags: [],
|
||||
version: "1.0.0",
|
||||
author: "개발팀",
|
||||
documentation: "https://docs.example.com/components/select-basic",
|
||||
});
|
||||
|
||||
// 타입 내보내기
|
||||
export type { SelectBasicConfig } from "./types";
|
||||
|
||||
// 컴포넌트 내보내기
|
||||
export { SelectBasicComponent } from "./SelectBasicComponent";
|
||||
export { SelectBasicRenderer } from "./SelectBasicRenderer";
|
||||
46
frontend/lib/registry/components/select-basic/types.ts
Normal file
46
frontend/lib/registry/components/select-basic/types.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
"use client";
|
||||
|
||||
import { ComponentConfig } from "@/types/component";
|
||||
|
||||
/**
|
||||
* SelectBasic 컴포넌트 설정 타입
|
||||
*/
|
||||
export interface SelectBasicConfig extends ComponentConfig {
|
||||
// select 관련 설정
|
||||
placeholder?: string;
|
||||
|
||||
// 공통 설정
|
||||
disabled?: boolean;
|
||||
required?: boolean;
|
||||
readonly?: boolean;
|
||||
placeholder?: string;
|
||||
helperText?: string;
|
||||
|
||||
// 스타일 관련
|
||||
variant?: "default" | "outlined" | "filled";
|
||||
size?: "sm" | "md" | "lg";
|
||||
|
||||
// 이벤트 관련
|
||||
onChange?: (value: any) => void;
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* SelectBasic 컴포넌트 Props 타입
|
||||
*/
|
||||
export interface SelectBasicProps {
|
||||
id?: string;
|
||||
name?: string;
|
||||
value?: any;
|
||||
config?: SelectBasicConfig;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
|
||||
// 이벤트 핸들러
|
||||
onChange?: (value: any) => void;
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
onClick?: () => void;
|
||||
}
|
||||
Reference in New Issue
Block a user