Merge commit '80be7c5a7600c080f897823837890fbdef58f565' into jskim-node
Made-with: Cursor # Conflicts: # .cursor/agents/pipeline-common-rules.md # .cursor/agents/pipeline-frontend.md # .cursor/agents/pipeline-ui.md
This commit is contained in:
@@ -304,9 +304,16 @@ export const DynamicComponentRenderer: React.FC<DynamicComponentRendererProps> =
|
||||
return type;
|
||||
};
|
||||
|
||||
const componentType = mapToV2ComponentType(rawComponentType);
|
||||
const mappedComponentType = mapToV2ComponentType(rawComponentType);
|
||||
|
||||
// 컴포넌트 타입 변환 완료
|
||||
// fieldType 기반 동적 컴포넌트 전환 (통합 필드 설정 패널에서 설정된 값)
|
||||
const componentType = (() => {
|
||||
const ft = (component as any).componentConfig?.fieldType;
|
||||
if (!ft) return mappedComponentType;
|
||||
if (["text", "number", "password", "textarea", "slider", "color", "numbering"].includes(ft)) return "v2-input";
|
||||
if (["select", "category", "entity"].includes(ft)) return "v2-select";
|
||||
return mappedComponentType;
|
||||
})();
|
||||
|
||||
// 🆕 조건부 렌더링 체크 (conditionalConfig)
|
||||
// componentConfig 또는 overrides에서 conditionalConfig를 가져와서 formData와 비교
|
||||
@@ -740,7 +747,21 @@ export const DynamicComponentRenderer: React.FC<DynamicComponentRendererProps> =
|
||||
// 컬럼 메타데이터 기반 componentConfig 병합 (DB 최신 설정 우선)
|
||||
const isEntityJoinColumn = fieldName?.includes(".");
|
||||
const baseColumnName = isEntityJoinColumn ? undefined : fieldName;
|
||||
const mergedComponentConfig = mergeColumnMeta(screenTableName, baseColumnName, component.componentConfig || {});
|
||||
const rawMergedConfig = mergeColumnMeta(screenTableName, baseColumnName, component.componentConfig || {});
|
||||
|
||||
// fieldType이 설정된 경우, source/inputType 보조 속성 자동 보완
|
||||
const mergedComponentConfig = (() => {
|
||||
const ft = rawMergedConfig?.fieldType;
|
||||
if (!ft) return rawMergedConfig;
|
||||
const patch: Record<string, any> = {};
|
||||
if (["select", "category", "entity"].includes(ft) && !rawMergedConfig.source) {
|
||||
patch.source = ft === "category" ? "category" : ft === "entity" ? "entity" : "static";
|
||||
}
|
||||
if (["text", "number", "password", "textarea", "slider", "color", "numbering"].includes(ft) && !rawMergedConfig.inputType) {
|
||||
patch.inputType = ft;
|
||||
}
|
||||
return Object.keys(patch).length > 0 ? { ...rawMergedConfig, ...patch } : rawMergedConfig;
|
||||
})();
|
||||
|
||||
// NOT NULL 기반 필수 여부를 component.required에 반영
|
||||
const notNullRequired = isColumnRequiredByMeta(screenTableName, baseColumnName);
|
||||
@@ -757,17 +778,16 @@ export const DynamicComponentRenderer: React.FC<DynamicComponentRendererProps> =
|
||||
onClick,
|
||||
onDragStart,
|
||||
onDragEnd,
|
||||
size: needsExternalHorizLabel
|
||||
? { ...(component.size || newComponent.defaultSize), width: undefined, height: undefined }
|
||||
: component.size || newComponent.defaultSize,
|
||||
position: component.position,
|
||||
config: mergedComponentConfig,
|
||||
componentConfig: mergedComponentConfig,
|
||||
// componentConfig의 모든 속성을 props로 spread (tableName, displayField 등)
|
||||
// componentConfig spread를 먼저 → 이후 명시적 속성이 override
|
||||
...(mergedComponentConfig || {}),
|
||||
// 🔧 style은 맨 마지막에! (componentConfig.style이 있어도 mergedStyle이 우선)
|
||||
// size/position/style/label은 componentConfig spread 이후에 설정 (덮어쓰기 방지)
|
||||
size: needsExternalHorizLabel
|
||||
? { ...(component.size || newComponent.defaultSize), width: undefined }
|
||||
: component.size || newComponent.defaultSize,
|
||||
position: component.position,
|
||||
style: mergedStyle,
|
||||
// 수평 라벨 → 외부에서 처리하므로 label 전달 안 함
|
||||
label: needsExternalHorizLabel ? undefined : effectiveLabel,
|
||||
// NOT NULL 메타데이터 포함된 필수 여부 (V2Hierarchy 등 직접 props.required 참조하는 컴포넌트용)
|
||||
required: effectiveRequired,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import {
|
||||
@@ -13,7 +13,18 @@ import {
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Plus, X } from "lucide-react";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "@/components/ui/command";
|
||||
import { Plus, X, Check, ChevronsUpDown } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { ConfigFieldDefinition, ConfigOption } from "./ConfigPanelTypes";
|
||||
|
||||
interface ConfigFieldProps<T = any> {
|
||||
@@ -29,6 +40,8 @@ export function ConfigField<T>({
|
||||
onChange,
|
||||
tableColumns,
|
||||
}: ConfigFieldProps<T>) {
|
||||
const [comboboxOpen, setComboboxOpen] = useState(false);
|
||||
|
||||
const handleChange = (newValue: any) => {
|
||||
onChange(field.key, newValue);
|
||||
};
|
||||
@@ -41,7 +54,7 @@ export function ConfigField<T>({
|
||||
value={value ?? ""}
|
||||
onChange={(e) => handleChange(e.target.value)}
|
||||
placeholder={field.placeholder}
|
||||
className="h-8 text-xs"
|
||||
className="h-7 text-xs"
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -59,7 +72,7 @@ export function ConfigField<T>({
|
||||
min={field.min}
|
||||
max={field.max}
|
||||
step={field.step}
|
||||
className="h-8 text-xs"
|
||||
className="h-7 text-xs"
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -77,7 +90,7 @@ export function ConfigField<T>({
|
||||
value={value ?? ""}
|
||||
onValueChange={handleChange}
|
||||
>
|
||||
<SelectTrigger className="h-8 text-xs">
|
||||
<SelectTrigger className="h-7 text-xs">
|
||||
<SelectValue placeholder={field.placeholder || "선택"} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -103,25 +116,25 @@ export function ConfigField<T>({
|
||||
|
||||
case "color":
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<input
|
||||
type="color"
|
||||
value={value ?? "#000000"}
|
||||
onChange={(e) => handleChange(e.target.value)}
|
||||
className="h-8 w-8 cursor-pointer rounded border"
|
||||
className="h-7 w-7 cursor-pointer rounded border"
|
||||
/>
|
||||
<Input
|
||||
value={value ?? ""}
|
||||
onChange={(e) => handleChange(e.target.value)}
|
||||
placeholder="#000000"
|
||||
className="h-8 flex-1 text-xs"
|
||||
className="h-7 flex-1 text-xs"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
case "slider":
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Input
|
||||
type="number"
|
||||
value={value ?? field.min ?? 0}
|
||||
@@ -129,17 +142,17 @@ export function ConfigField<T>({
|
||||
min={field.min}
|
||||
max={field.max}
|
||||
step={field.step}
|
||||
className="h-8 w-20 text-xs"
|
||||
className="h-7 w-16 text-xs"
|
||||
/>
|
||||
<span className="text-muted-foreground text-[10px]">
|
||||
{field.min ?? 0} ~ {field.max ?? 100}
|
||||
<span className="text-muted-foreground text-[9px]">
|
||||
{field.min ?? 0}~{field.max ?? 100}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
|
||||
case "multi-select":
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
<div className="space-y-0.5">
|
||||
{(field.options || []).map((opt) => {
|
||||
const selected = Array.isArray(value) && value.includes(opt.value);
|
||||
return (
|
||||
@@ -230,7 +243,7 @@ export function ConfigField<T>({
|
||||
value={value ?? ""}
|
||||
onValueChange={handleChange}
|
||||
>
|
||||
<SelectTrigger className="h-8 text-xs">
|
||||
<SelectTrigger className="h-7 text-xs">
|
||||
<SelectValue placeholder={field.placeholder || "컬럼 선택"} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -244,21 +257,123 @@ export function ConfigField<T>({
|
||||
);
|
||||
}
|
||||
|
||||
case "checkbox":
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox
|
||||
id={`field-${field.key}`}
|
||||
checked={!!value}
|
||||
onCheckedChange={handleChange}
|
||||
/>
|
||||
{field.description && (
|
||||
<label
|
||||
htmlFor={`field-${field.key}`}
|
||||
className="cursor-pointer text-xs text-muted-foreground"
|
||||
>
|
||||
{field.description}
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
case "combobox": {
|
||||
const options = field.options || [];
|
||||
const selectedLabel = options.find((opt) => opt.value === value)?.label;
|
||||
return (
|
||||
<Popover open={comboboxOpen} onOpenChange={setComboboxOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
aria-expanded={comboboxOpen}
|
||||
className="h-7 w-full justify-between text-xs font-normal"
|
||||
>
|
||||
<span className="truncate">
|
||||
{selectedLabel || field.placeholder || "선택"}
|
||||
</span>
|
||||
<ChevronsUpDown className="ml-1 h-3 w-3 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
className="p-0"
|
||||
style={{ width: "var(--radix-popover-trigger-width)" }}
|
||||
align="start"
|
||||
>
|
||||
<Command>
|
||||
<CommandInput placeholder="검색..." className="text-xs" />
|
||||
<CommandList>
|
||||
<CommandEmpty className="py-2 text-center text-xs">
|
||||
결과 없음
|
||||
</CommandEmpty>
|
||||
<CommandGroup>
|
||||
{options.map((opt) => (
|
||||
<CommandItem
|
||||
key={opt.value}
|
||||
value={opt.value}
|
||||
onSelect={(currentValue) => {
|
||||
handleChange(currentValue === value ? "" : currentValue);
|
||||
setComboboxOpen(false);
|
||||
}}
|
||||
className="text-xs"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-1.5 h-3 w-3",
|
||||
value === opt.value ? "opacity-100" : "opacity-0",
|
||||
)}
|
||||
/>
|
||||
{opt.label}
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="text-xs font-medium">{field.label}</Label>
|
||||
{field.type === "switch" && renderField()}
|
||||
// textarea, multi-select, key-value는 전체 폭 수직 레이아웃
|
||||
const isFullWidth = ["textarea", "multi-select", "key-value"].includes(field.type);
|
||||
// checkbox는 description을 인라인으로 표시하므로 별도 처리
|
||||
const isCheckbox = field.type === "checkbox";
|
||||
|
||||
if (isFullWidth) {
|
||||
return (
|
||||
<div className="py-1.5">
|
||||
<Label className="mb-1 block text-xs text-muted-foreground">{field.label}</Label>
|
||||
{field.description && !isCheckbox && (
|
||||
<p className="text-muted-foreground/60 mb-1 text-[9px]">{field.description}</p>
|
||||
)}
|
||||
{renderField()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// switch, checkbox: 라벨 왼쪽, 컨트롤 오른쪽 (고정폭 없이)
|
||||
if (field.type === "switch" || isCheckbox) {
|
||||
return (
|
||||
<div className="flex items-center justify-between py-1.5">
|
||||
<Label className="mr-3 truncate text-xs text-muted-foreground">{field.label}</Label>
|
||||
{renderField()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// 기본: 수평 property row (라벨 왼쪽, 컨트롤 오른쪽 고정폭)
|
||||
return (
|
||||
<div className="flex items-center justify-between py-1.5">
|
||||
<Label className="mr-3 min-w-0 shrink truncate text-xs text-muted-foreground">
|
||||
{field.label}
|
||||
</Label>
|
||||
<div className="w-[140px] flex-shrink-0">
|
||||
{renderField()}
|
||||
</div>
|
||||
{field.description && (
|
||||
<p className="text-muted-foreground text-[10px]">{field.description}</p>
|
||||
)}
|
||||
{field.type !== "switch" && renderField()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,75 +1,144 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { ConfigPanelBuilderProps } from "./ConfigPanelTypes";
|
||||
import { ConfigPanelBuilderProps, ConfigSectionDefinition } from "./ConfigPanelTypes";
|
||||
import { ConfigSection } from "./ConfigSection";
|
||||
import { ConfigField } from "./ConfigField";
|
||||
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
|
||||
|
||||
function renderSections<T extends Record<string, any>>(
|
||||
sections: ConfigSectionDefinition<T>[],
|
||||
config: T,
|
||||
onChange: (key: string, value: any) => void,
|
||||
tableColumns?: any[],
|
||||
) {
|
||||
return sections.map((section) => {
|
||||
if (section.condition && !section.condition(config)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const visibleFields = section.fields.filter(
|
||||
(field) => !field.condition || field.condition(config),
|
||||
);
|
||||
|
||||
if (visibleFields.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ConfigSection key={section.id} section={section}>
|
||||
{visibleFields.map((field) => (
|
||||
<ConfigField
|
||||
key={field.key}
|
||||
field={field}
|
||||
value={(config as any)[field.key]}
|
||||
onChange={onChange}
|
||||
tableColumns={tableColumns}
|
||||
/>
|
||||
))}
|
||||
</ConfigSection>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function ConfigPanelBuilder<T extends Record<string, any>>({
|
||||
config,
|
||||
onChange,
|
||||
onConfigChange,
|
||||
sections,
|
||||
presets,
|
||||
tableColumns,
|
||||
children,
|
||||
mode = "flat",
|
||||
context,
|
||||
}: ConfigPanelBuilderProps<T>) {
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
{/* 프리셋 버튼 */}
|
||||
{presets && presets.length > 0 && (
|
||||
<div className="border-b pb-3">
|
||||
<h4 className="mb-2 text-xs font-medium text-muted-foreground">
|
||||
빠른 설정
|
||||
</h4>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{presets.map((preset, idx) => (
|
||||
<button
|
||||
key={idx}
|
||||
onClick={() => {
|
||||
Object.entries(preset.values).forEach(([key, value]) => {
|
||||
onChange(key, value);
|
||||
});
|
||||
}}
|
||||
className="rounded-full bg-muted px-2.5 py-1 text-[10px] font-medium text-muted-foreground transition-colors hover:bg-primary hover:text-primary-foreground"
|
||||
title={preset.description}
|
||||
>
|
||||
{preset.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
const effectiveTableColumns = tableColumns || context?.tableColumns;
|
||||
|
||||
const presetSection = presets && presets.length > 0 && (
|
||||
<div className="border-b border-border/40 pb-2.5">
|
||||
<h4 className="mb-1.5 text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
|
||||
빠른 설정
|
||||
</h4>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{presets.map((preset, idx) => (
|
||||
<button
|
||||
key={idx}
|
||||
onClick={() => {
|
||||
Object.entries(preset.values).forEach(([key, value]) => {
|
||||
onChange(key, value);
|
||||
});
|
||||
if (onConfigChange) {
|
||||
onConfigChange({ ...config, ...preset.values } as Record<string, any>);
|
||||
}
|
||||
}}
|
||||
className="rounded border border-border bg-background px-2 py-0.5 text-[10px] font-medium text-muted-foreground transition-colors hover:border-primary hover:text-primary"
|
||||
title={preset.description}
|
||||
>
|
||||
{preset.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (mode === "tabs") {
|
||||
const groupMap = new Map<string, ConfigSectionDefinition<T>[]>();
|
||||
const ungrouped: ConfigSectionDefinition<T>[] = [];
|
||||
|
||||
for (const section of sections) {
|
||||
if (section.group) {
|
||||
const existing = groupMap.get(section.group) || [];
|
||||
existing.push(section);
|
||||
groupMap.set(section.group, existing);
|
||||
} else {
|
||||
ungrouped.push(section);
|
||||
}
|
||||
}
|
||||
|
||||
const tabGroups = Array.from(groupMap.entries());
|
||||
|
||||
if (tabGroups.length === 0) {
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
{presetSection}
|
||||
{renderSections(sections, config, onChange, effectiveTableColumns)}
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
);
|
||||
}
|
||||
|
||||
{/* 섹션 렌더링 */}
|
||||
{sections.map((section) => {
|
||||
if (section.condition && !section.condition(config)) {
|
||||
return null;
|
||||
}
|
||||
const defaultTab = tabGroups[0]?.[0] || "general";
|
||||
|
||||
const visibleFields = section.fields.filter(
|
||||
(field) => !field.condition || field.condition(config),
|
||||
);
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
{presetSection}
|
||||
|
||||
if (visibleFields.length === 0) {
|
||||
return null;
|
||||
}
|
||||
{ungrouped.length > 0 && renderSections(ungrouped, config, onChange, effectiveTableColumns)}
|
||||
|
||||
return (
|
||||
<ConfigSection key={section.id} section={section}>
|
||||
{visibleFields.map((field) => (
|
||||
<ConfigField
|
||||
key={field.key}
|
||||
field={field}
|
||||
value={(config as any)[field.key]}
|
||||
onChange={onChange}
|
||||
tableColumns={tableColumns}
|
||||
/>
|
||||
<Tabs defaultValue={defaultTab} className="w-full">
|
||||
<TabsList className="h-7 w-full">
|
||||
{tabGroups.map(([groupName]) => (
|
||||
<TabsTrigger key={groupName} value={groupName} className="h-6 text-xs">
|
||||
{groupName}
|
||||
</TabsTrigger>
|
||||
))}
|
||||
</ConfigSection>
|
||||
);
|
||||
})}
|
||||
</TabsList>
|
||||
{tabGroups.map(([groupName, groupSections]) => (
|
||||
<TabsContent key={groupName} value={groupName} className="mt-1">
|
||||
{renderSections(groupSections, config, onChange, effectiveTableColumns)}
|
||||
</TabsContent>
|
||||
))}
|
||||
</Tabs>
|
||||
|
||||
{/* 커스텀 children */}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-1">
|
||||
{presetSection}
|
||||
{renderSections(sections, config, onChange, effectiveTableColumns)}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -10,7 +10,9 @@ export type ConfigFieldType =
|
||||
| "slider"
|
||||
| "multi-select"
|
||||
| "key-value"
|
||||
| "column-picker";
|
||||
| "column-picker"
|
||||
| "checkbox"
|
||||
| "combobox";
|
||||
|
||||
export interface ConfigOption {
|
||||
label: string;
|
||||
@@ -40,11 +42,13 @@ export interface ConfigSectionDefinition<T = any> {
|
||||
defaultOpen?: boolean;
|
||||
fields: ConfigFieldDefinition<T>[];
|
||||
condition?: (config: T) => boolean;
|
||||
group?: string;
|
||||
}
|
||||
|
||||
export interface ConfigPanelBuilderProps<T = any> {
|
||||
config: T;
|
||||
onChange: (key: string, value: any) => void;
|
||||
onConfigChange?: (config: Record<string, any>) => void;
|
||||
sections: ConfigSectionDefinition<T>[];
|
||||
presets?: Array<{
|
||||
label: string;
|
||||
@@ -53,4 +57,30 @@ export interface ConfigPanelBuilderProps<T = any> {
|
||||
}>;
|
||||
tableColumns?: ConfigOption[];
|
||||
children?: React.ReactNode;
|
||||
mode?: "flat" | "tabs";
|
||||
context?: ConfigPanelContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 설정 패널에 전달되는 화면/컴포넌트 컨텍스트 정보
|
||||
*/
|
||||
export interface ConfigPanelContext {
|
||||
tables?: any[];
|
||||
tableColumns?: any[];
|
||||
screenTableName?: string;
|
||||
menuObjid?: number;
|
||||
allComponents?: any[];
|
||||
currentComponent?: any;
|
||||
allTables?: any[];
|
||||
screenComponents?: any[];
|
||||
currentScreenCompanyCode?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 모든 ConfigPanel이 공통으로 받는 표준 Props
|
||||
*/
|
||||
export interface StandardConfigPanelProps {
|
||||
config: Record<string, any>;
|
||||
onChange: (config: Record<string, any>) => void;
|
||||
context?: ConfigPanelContext;
|
||||
}
|
||||
|
||||
@@ -14,39 +14,45 @@ export function ConfigSection({ section, children }: ConfigSectionProps) {
|
||||
|
||||
if (section.collapsible) {
|
||||
return (
|
||||
<div className="border-b pb-3">
|
||||
<div className="border-b border-border/40 py-2.5">
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className="flex w-full items-center gap-1.5 py-1 text-left"
|
||||
className="flex w-full items-center justify-between py-0.5 text-left"
|
||||
>
|
||||
{isOpen ? (
|
||||
<ChevronDown className="h-3.5 w-3.5 shrink-0" />
|
||||
) : (
|
||||
<ChevronRight className="h-3.5 w-3.5 shrink-0" />
|
||||
)}
|
||||
<span className="text-sm font-medium">{section.title}</span>
|
||||
{section.description && (
|
||||
<span className="text-muted-foreground ml-auto text-[10px]">
|
||||
{section.description}
|
||||
</span>
|
||||
)}
|
||||
<span className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
|
||||
{section.title}
|
||||
</span>
|
||||
<div className="flex items-center gap-1.5">
|
||||
{section.description && (
|
||||
<span className="text-muted-foreground/60 text-[9px]">
|
||||
{section.description}
|
||||
</span>
|
||||
)}
|
||||
{isOpen ? (
|
||||
<ChevronDown className="h-3 w-3 shrink-0 text-muted-foreground/50" />
|
||||
) : (
|
||||
<ChevronRight className="h-3 w-3 shrink-0 text-muted-foreground/50" />
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
{isOpen && <div className="mt-2 space-y-3">{children}</div>}
|
||||
{isOpen && <div className="mt-1.5 space-y-1">{children}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="border-b pb-3">
|
||||
<div className="mb-2">
|
||||
<h4 className="text-sm font-medium">{section.title}</h4>
|
||||
<div className="border-b border-border/40 py-2.5">
|
||||
<div className="mb-1.5 flex items-center justify-between">
|
||||
<h4 className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
|
||||
{section.title}
|
||||
</h4>
|
||||
{section.description && (
|
||||
<p className="text-muted-foreground text-[10px]">
|
||||
<span className="text-muted-foreground/60 text-[9px]">
|
||||
{section.description}
|
||||
</p>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="space-y-3">{children}</div>
|
||||
<div className="space-y-1">{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import type { WebType } from "@/types/screen";
|
||||
import { SelectedItemsDetailInputWrapper } from "./SelectedItemsDetailInputComponent";
|
||||
import { SelectedItemsDetailInputConfigPanel } from "./SelectedItemsDetailInputConfigPanel";
|
||||
import { V2SelectedItemsDetailInputConfigPanel } from "@/components/v2/config-panels/V2SelectedItemsDetailInputConfigPanel";
|
||||
import { SelectedItemsDetailInputConfig } from "./types";
|
||||
|
||||
/**
|
||||
@@ -33,7 +31,7 @@ export const SelectedItemsDetailInputDefinition = createComponentDefinition({
|
||||
readonly: false,
|
||||
} as SelectedItemsDetailInputConfig,
|
||||
defaultSize: { width: 800, height: 400 },
|
||||
configPanel: SelectedItemsDetailInputConfigPanel,
|
||||
configPanel: V2SelectedItemsDetailInputConfigPanel,
|
||||
icon: "Table",
|
||||
tags: ["선택", "상세입력", "반복", "테이블", "데이터전달"],
|
||||
version: "1.0.0",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { AggregationWidgetWrapper } from "./AggregationWidgetComponent";
|
||||
import { AggregationWidgetConfigPanel } from "./AggregationWidgetConfigPanel";
|
||||
import { V2AggregationWidgetConfigPanel } from "@/components/v2/config-panels/V2AggregationWidgetConfigPanel";
|
||||
import type { AggregationWidgetConfig } from "./types";
|
||||
|
||||
/**
|
||||
@@ -34,7 +34,7 @@ export const V2AggregationWidgetDefinition = createComponentDefinition({
|
||||
refreshOnFormChange: true, // 폼 변경 시 자동 새로고침
|
||||
} as Partial<AggregationWidgetConfig>,
|
||||
defaultSize: { width: 400, height: 60 },
|
||||
configPanel: AggregationWidgetConfigPanel,
|
||||
configPanel: V2AggregationWidgetConfigPanel,
|
||||
icon: "Calculator",
|
||||
tags: ["집계", "합계", "평균", "개수", "통계", "데이터", "필터"],
|
||||
version: "1.1.0",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { createComponentDefinition } from "../../utils/createComponentDefinition
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import type { WebType } from "@/types/screen";
|
||||
import { ApprovalStepWrapper } from "./ApprovalStepComponent";
|
||||
import { ApprovalStepConfigPanel } from "./ApprovalStepConfigPanel";
|
||||
import { V2ApprovalStepConfigPanel as ApprovalStepConfigPanel } from "@/components/v2/config-panels/V2ApprovalStepConfigPanel";
|
||||
import { ApprovalStepConfig } from "./types";
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import type { WebType } from "@/types/screen";
|
||||
import { ButtonPrimaryWrapper } from "./ButtonPrimaryComponent";
|
||||
import { ButtonPrimaryConfig } from "./types";
|
||||
import { V2ButtonConfigPanel } from "@/components/v2/config-panels/V2ButtonConfigPanel";
|
||||
|
||||
/**
|
||||
* ButtonPrimary 컴포넌트 정의
|
||||
@@ -30,7 +28,7 @@ export const V2ButtonPrimaryDefinition = createComponentDefinition({
|
||||
},
|
||||
},
|
||||
defaultSize: { width: 120, height: 40 },
|
||||
configPanel: undefined, // 상세 설정 패널(ButtonConfigPanel)이 대신 사용됨
|
||||
configPanel: V2ButtonConfigPanel,
|
||||
icon: "MousePointer",
|
||||
tags: ["버튼", "액션", "클릭"],
|
||||
version: "1.0.0",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { createComponentDefinition } from "../../utils/createComponentDefinition
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import type { WebType } from "@/types/screen";
|
||||
import { CardDisplayComponent } from "./CardDisplayComponent";
|
||||
import { CardDisplayConfigPanel } from "./CardDisplayConfigPanel";
|
||||
import { V2CardDisplayConfigPanel } from "@/components/v2/config-panels/V2CardDisplayConfigPanel";
|
||||
import { CardDisplayConfig } from "./types";
|
||||
|
||||
/**
|
||||
@@ -38,7 +38,7 @@ export const V2CardDisplayDefinition = createComponentDefinition({
|
||||
staticData: [],
|
||||
},
|
||||
defaultSize: { width: 800, height: 400 },
|
||||
configPanel: CardDisplayConfigPanel,
|
||||
configPanel: V2CardDisplayConfigPanel,
|
||||
icon: "Grid3x3",
|
||||
tags: ["card", "display", "table", "grid"],
|
||||
version: "1.0.0",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { V2CategoryManagerComponent } from "./V2CategoryManagerComponent";
|
||||
import { V2CategoryManagerConfigPanel } from "./V2CategoryManagerConfigPanel";
|
||||
import { V2CategoryManagerConfigPanel } from "@/components/v2/config-panels/V2CategoryManagerConfigPanel";
|
||||
import { defaultV2CategoryManagerConfig } from "./types";
|
||||
|
||||
/**
|
||||
@@ -32,5 +32,5 @@ export const V2CategoryManagerDefinition = createComponentDefinition({
|
||||
// 타입 내보내기
|
||||
export type { V2CategoryManagerConfig, CategoryValue, ViewMode } from "./types";
|
||||
export { V2CategoryManagerComponent } from "./V2CategoryManagerComponent";
|
||||
export { V2CategoryManagerConfigPanel } from "./V2CategoryManagerConfigPanel";
|
||||
export { V2CategoryManagerConfigPanel } from "@/components/v2/config-panels/V2CategoryManagerConfigPanel";
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { createComponentDefinition } from "../../utils/createComponentDefinition
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import type { WebType } from "@/types/screen";
|
||||
import { DividerLineWrapper } from "./DividerLineComponent";
|
||||
import { DividerLineConfigPanel } from "./DividerLineConfigPanel";
|
||||
import { V2DividerLineConfigPanel } from "@/components/v2/config-panels/V2DividerLineConfigPanel";
|
||||
import { DividerLineConfig } from "./types";
|
||||
|
||||
/**
|
||||
@@ -25,7 +25,7 @@ export const V2DividerLineDefinition = createComponentDefinition({
|
||||
maxLength: 255,
|
||||
},
|
||||
defaultSize: { width: 400, height: 2 },
|
||||
configPanel: DividerLineConfigPanel,
|
||||
configPanel: V2DividerLineConfigPanel,
|
||||
icon: "Layout",
|
||||
tags: [],
|
||||
version: "1.0.0",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { createComponentDefinition } from "../../utils/createComponentDefinition
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import type { WebType } from "@/types/screen";
|
||||
import { FileUploadComponent } from "./FileUploadComponent";
|
||||
import { FileUploadConfigPanel } from "./FileUploadConfigPanel";
|
||||
import { V2FileUploadConfigPanel } from "@/components/v2/config-panels/V2FileUploadConfigPanel";
|
||||
import { FileUploadConfig } from "./types";
|
||||
|
||||
/**
|
||||
@@ -27,7 +27,7 @@ export const V2FileUploadDefinition = createComponentDefinition({
|
||||
maxSize: 10 * 1024 * 1024, // 10MB
|
||||
},
|
||||
defaultSize: { width: 350, height: 240 },
|
||||
configPanel: FileUploadConfigPanel,
|
||||
configPanel: V2FileUploadConfigPanel,
|
||||
icon: "Upload",
|
||||
tags: ["file", "upload", "attachment", "v2"],
|
||||
version: "2.0.0",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { V2InputConfigPanel } from "@/components/v2/config-panels/V2InputConfigPanel";
|
||||
import { V2FieldConfigPanel } from "@/components/v2/config-panels/V2FieldConfigPanel";
|
||||
import { V2Input } from "@/components/v2/V2Input";
|
||||
|
||||
export const V2InputDefinition = createComponentDefinition({
|
||||
@@ -72,7 +72,7 @@ export const V2InputDefinition = createComponentDefinition({
|
||||
tags: ["input", "text", "number", "v2"],
|
||||
|
||||
// 설정 패널
|
||||
configPanel: V2InputConfigPanel,
|
||||
configPanel: V2FieldConfigPanel,
|
||||
});
|
||||
|
||||
export default V2InputDefinition;
|
||||
|
||||
@@ -4,7 +4,7 @@ import React from "react";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { ItemRoutingComponent } from "./ItemRoutingComponent";
|
||||
import { ItemRoutingConfigPanel } from "./ItemRoutingConfigPanel";
|
||||
import { V2ItemRoutingConfigPanel as ItemRoutingConfigPanel } from "@/components/v2/config-panels/V2ItemRoutingConfigPanel";
|
||||
import { defaultConfig } from "./config";
|
||||
|
||||
export const V2ItemRoutingDefinition = createComponentDefinition({
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { LocationSwapSelectorComponent } from "./LocationSwapSelectorComponent";
|
||||
import { LocationSwapSelectorConfigPanel } from "./LocationSwapSelectorConfigPanel";
|
||||
import { V2LocationSwapSelectorConfigPanel as LocationSwapSelectorConfigPanel } from "@/components/v2/config-panels/V2LocationSwapSelectorConfigPanel";
|
||||
|
||||
/**
|
||||
* LocationSwapSelector 컴포넌트 정의
|
||||
|
||||
@@ -4,7 +4,7 @@ import React from "react";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { NumberingRuleWrapper } from "./NumberingRuleComponent";
|
||||
import { NumberingRuleConfigPanel } from "./NumberingRuleConfigPanel";
|
||||
import { V2NumberingRuleConfigPanel } from "@/components/v2/config-panels/V2NumberingRuleConfigPanel";
|
||||
import { defaultConfig } from "./config";
|
||||
|
||||
/**
|
||||
@@ -25,7 +25,7 @@ export const V2NumberingRuleDefinition = createComponentDefinition({
|
||||
height: 800,
|
||||
gridColumnSpan: "12",
|
||||
},
|
||||
configPanel: NumberingRuleConfigPanel,
|
||||
configPanel: V2NumberingRuleConfigPanel,
|
||||
icon: "Hash",
|
||||
tags: ["코드", "채번", "규칙", "표시", "자동생성"],
|
||||
version: "1.0.0",
|
||||
|
||||
@@ -43,7 +43,7 @@ export type {
|
||||
|
||||
// 컴포넌트 내보내기
|
||||
export { PivotGridComponent } from "./PivotGridComponent";
|
||||
export { PivotGridConfigPanel } from "./PivotGridConfigPanel";
|
||||
export { V2PivotGridConfigPanel as PivotGridConfigPanel } from "@/components/v2/config-panels/V2PivotGridConfigPanel";
|
||||
|
||||
// 유틸리티
|
||||
export {
|
||||
|
||||
@@ -4,7 +4,7 @@ import React from "react";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { ProcessWorkStandardComponent } from "./ProcessWorkStandardComponent";
|
||||
import { ProcessWorkStandardConfigPanel } from "./ProcessWorkStandardConfigPanel";
|
||||
import { V2ProcessWorkStandardConfigPanel as ProcessWorkStandardConfigPanel } from "@/components/v2/config-panels/V2ProcessWorkStandardConfigPanel";
|
||||
import { defaultConfig } from "./config";
|
||||
|
||||
export const V2ProcessWorkStandardDefinition = createComponentDefinition({
|
||||
|
||||
@@ -4,7 +4,7 @@ import React from "react";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { RackStructureWrapper } from "./RackStructureComponent";
|
||||
import { RackStructureConfigPanel } from "./RackStructureConfigPanel";
|
||||
import { V2RackStructureConfigPanel as RackStructureConfigPanel } from "@/components/v2/config-panels/V2RackStructureConfigPanel";
|
||||
import { defaultConfig } from "./config";
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { RepeatContainerWrapper } from "./RepeatContainerComponent";
|
||||
import { RepeatContainerConfigPanel } from "./RepeatContainerConfigPanel";
|
||||
import { V2RepeatContainerConfigPanel as RepeatContainerConfigPanel } from "@/components/v2/config-panels/V2RepeatContainerConfigPanel";
|
||||
import type { RepeatContainerConfig } from "./types";
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { SectionCardComponent } from "./SectionCardComponent";
|
||||
import { SectionCardConfigPanel } from "./SectionCardConfigPanel";
|
||||
import { V2SectionCardConfigPanel } from "@/components/v2/config-panels/V2SectionCardConfigPanel";
|
||||
|
||||
/**
|
||||
* Section Card 컴포넌트 정의
|
||||
@@ -28,7 +28,7 @@ export const V2SectionCardDefinition = createComponentDefinition({
|
||||
defaultOpen: true,
|
||||
},
|
||||
defaultSize: { width: 800, height: 250 },
|
||||
configPanel: SectionCardConfigPanel,
|
||||
configPanel: V2SectionCardConfigPanel,
|
||||
icon: "LayoutPanelTop",
|
||||
tags: ["섹션", "그룹", "카드", "컨테이너", "제목", "card"],
|
||||
version: "1.0.0",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { SectionPaperComponent } from "./SectionPaperComponent";
|
||||
import { SectionPaperConfigPanel } from "./SectionPaperConfigPanel";
|
||||
import { V2SectionPaperConfigPanel } from "@/components/v2/config-panels/V2SectionPaperConfigPanel";
|
||||
|
||||
/**
|
||||
* Section Paper 컴포넌트 정의
|
||||
@@ -25,7 +25,7 @@ export const V2SectionPaperDefinition = createComponentDefinition({
|
||||
showBorder: false,
|
||||
},
|
||||
defaultSize: { width: 800, height: 200 },
|
||||
configPanel: SectionPaperConfigPanel,
|
||||
configPanel: V2SectionPaperConfigPanel,
|
||||
icon: "Square",
|
||||
tags: ["섹션", "그룹", "배경", "컨테이너", "색종이", "paper"],
|
||||
version: "1.0.0",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { V2SelectConfigPanel } from "@/components/v2/config-panels/V2SelectConfigPanel";
|
||||
import { V2FieldConfigPanel } from "@/components/v2/config-panels/V2FieldConfigPanel";
|
||||
import { V2Select } from "@/components/v2/V2Select";
|
||||
|
||||
export const V2SelectDefinition = createComponentDefinition({
|
||||
@@ -82,7 +82,7 @@ export const V2SelectDefinition = createComponentDefinition({
|
||||
tags: ["select", "dropdown", "combobox", "v2"],
|
||||
|
||||
// 설정 패널
|
||||
configPanel: V2SelectConfigPanel,
|
||||
configPanel: V2FieldConfigPanel,
|
||||
});
|
||||
|
||||
export default V2SelectDefinition;
|
||||
|
||||
@@ -4,7 +4,7 @@ import React from "react";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { SplitLineWrapper } from "./SplitLineComponent";
|
||||
import { SplitLineConfigPanel } from "./SplitLineConfigPanel";
|
||||
import { V2SplitLineConfigPanel } from "@/components/v2/config-panels/V2SplitLineConfigPanel";
|
||||
import { SplitLineConfig } from "./types";
|
||||
|
||||
/**
|
||||
@@ -25,7 +25,7 @@ export const V2SplitLineDefinition = createComponentDefinition({
|
||||
lineWidth: 4,
|
||||
} as SplitLineConfig,
|
||||
defaultSize: { width: 8, height: 600 },
|
||||
configPanel: SplitLineConfigPanel,
|
||||
configPanel: V2SplitLineConfigPanel,
|
||||
icon: "SeparatorVertical",
|
||||
tags: ["스플릿", "분할", "분할선", "레이아웃"],
|
||||
version: "1.0.0",
|
||||
|
||||
@@ -4,7 +4,7 @@ import React from "react";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { SplitPanelLayoutWrapper } from "./SplitPanelLayoutComponent";
|
||||
import { SplitPanelLayoutConfigPanel } from "./SplitPanelLayoutConfigPanel";
|
||||
import { V2SplitPanelLayoutConfigPanel } from "@/components/v2/config-panels/V2SplitPanelLayoutConfigPanel";
|
||||
import { SplitPanelLayoutConfig } from "./types";
|
||||
|
||||
/**
|
||||
@@ -42,7 +42,7 @@ export const V2SplitPanelLayoutDefinition = createComponentDefinition({
|
||||
syncSelection: true,
|
||||
} as SplitPanelLayoutConfig,
|
||||
defaultSize: { width: 800, height: 600 },
|
||||
configPanel: SplitPanelLayoutConfigPanel,
|
||||
configPanel: V2SplitPanelLayoutConfigPanel,
|
||||
icon: "PanelLeftRight",
|
||||
tags: ["분할", "마스터", "디테일", "레이아웃"],
|
||||
version: "1.0.0",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { StatusCountWrapper } from "./StatusCountComponent";
|
||||
import { StatusCountConfigPanel } from "./StatusCountConfigPanel";
|
||||
import { V2StatusCountConfigPanel } from "@/components/v2/config-panels/V2StatusCountConfigPanel";
|
||||
|
||||
export const V2StatusCountDefinition = createComponentDefinition({
|
||||
id: "v2-status-count",
|
||||
@@ -13,7 +13,7 @@ export const V2StatusCountDefinition = createComponentDefinition({
|
||||
category: ComponentCategory.DISPLAY,
|
||||
webType: "text",
|
||||
component: StatusCountWrapper,
|
||||
configPanel: StatusCountConfigPanel,
|
||||
configPanel: V2StatusCountConfigPanel,
|
||||
defaultConfig: {
|
||||
title: "상태 현황",
|
||||
tableName: "",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { createComponentDefinition } from "../../utils/createComponentDefinition
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import type { WebType } from "@/types/screen";
|
||||
import { TableGroupedComponent } from "./TableGroupedComponent";
|
||||
import { TableGroupedConfigPanel } from "./TableGroupedConfigPanel";
|
||||
import { V2TableGroupedConfigPanel } from "@/components/v2/config-panels/V2TableGroupedConfigPanel";
|
||||
import { TableGroupedConfig } from "./types";
|
||||
|
||||
/**
|
||||
@@ -63,7 +63,7 @@ export const V2TableGroupedDefinition = createComponentDefinition({
|
||||
maxHeight: 600,
|
||||
},
|
||||
defaultSize: { width: 800, height: 500 },
|
||||
configPanel: TableGroupedConfigPanel,
|
||||
configPanel: V2TableGroupedConfigPanel,
|
||||
icon: "Layers",
|
||||
tags: ["테이블", "그룹화", "접기", "펼치기", "목록"],
|
||||
version: "1.0.0",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { createComponentDefinition } from "../../utils/createComponentDefinition
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import type { WebType } from "@/types/screen";
|
||||
import { TableListWrapper } from "./TableListComponent";
|
||||
import { TableListConfigPanel } from "./TableListConfigPanel";
|
||||
import { V2TableListConfigPanel } from "@/components/v2/config-panels/V2TableListConfigPanel";
|
||||
import { TableListConfig } from "./types";
|
||||
|
||||
/**
|
||||
@@ -109,7 +109,7 @@ export const V2TableListDefinition = createComponentDefinition({
|
||||
autoLoad: true,
|
||||
},
|
||||
defaultSize: { width: 1000, height: 600 }, // 테이블 리스트 기본 크기 (너비 1000px, 높이 600px)
|
||||
configPanel: TableListConfigPanel,
|
||||
configPanel: V2TableListConfigPanel,
|
||||
icon: "Table",
|
||||
tags: ["테이블", "데이터", "목록", "그리드"],
|
||||
version: "1.0.0",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { ComponentRegistry } from "../../ComponentRegistry";
|
||||
import { TableSearchWidget } from "./TableSearchWidget";
|
||||
import { TableSearchWidgetRenderer } from "./TableSearchWidgetRenderer";
|
||||
import { TableSearchWidgetConfigPanel } from "./TableSearchWidgetConfigPanel";
|
||||
import { V2TableSearchWidgetConfigPanel } from "@/components/v2/config-panels/V2TableSearchWidgetConfigPanel";
|
||||
|
||||
// 검색 필터 위젯 등록 (v2)
|
||||
ComponentRegistry.registerComponent({
|
||||
@@ -30,7 +30,7 @@ ComponentRegistry.registerComponent({
|
||||
},
|
||||
},
|
||||
renderer: TableSearchWidgetRenderer.render,
|
||||
configPanel: TableSearchWidgetConfigPanel,
|
||||
configPanel: V2TableSearchWidgetConfigPanel,
|
||||
version: "1.0.0",
|
||||
author: "WACE",
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@ import { createComponentDefinition } from "../../utils/createComponentDefinition
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import type { WebType } from "@/types/screen";
|
||||
import { TextDisplayWrapper } from "./TextDisplayComponent";
|
||||
import { TextDisplayConfigPanel } from "./TextDisplayConfigPanel";
|
||||
import { V2TextDisplayConfigPanel } from "@/components/v2/config-panels/V2TextDisplayConfigPanel";
|
||||
import { TextDisplayConfig } from "./types";
|
||||
|
||||
/**
|
||||
@@ -28,7 +28,7 @@ export const V2TextDisplayDefinition = createComponentDefinition({
|
||||
textAlign: "left",
|
||||
},
|
||||
defaultSize: { width: 150, height: 24 },
|
||||
configPanel: TextDisplayConfigPanel,
|
||||
configPanel: V2TextDisplayConfigPanel,
|
||||
icon: "Type",
|
||||
tags: ["텍스트", "표시", "라벨"],
|
||||
version: "1.0.0",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { ComponentCategory } from "@/types/component";
|
||||
import { createComponentDefinition } from "../../utils/createComponentDefinition";
|
||||
import { TimelineSchedulerComponent } from "./TimelineSchedulerComponent";
|
||||
import { TimelineSchedulerConfigPanel } from "./TimelineSchedulerConfigPanel";
|
||||
import { V2TimelineSchedulerConfigPanel as TimelineSchedulerConfigPanel } from "@/components/v2/config-panels/V2TimelineSchedulerConfigPanel";
|
||||
import { defaultTimelineSchedulerConfig } from "./config";
|
||||
import { TimelineSchedulerConfig } from "./types";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user