@restnfeel/agentc-starter-kit
Version:
한국어 기업용 CMS 모듈 - Task Master AI와 함께 빠르게 웹사이트를 구현할 수 있는 재사용 가능한 컴포넌트 시스템
525 lines (468 loc) • 11.3 kB
text/typescript
/**
* Section Editor Types
* Type definitions for modular section editors with real-time preview
*/
// Base Section Types
export interface BaseSection {
id: string;
type: SectionType;
name: string;
order: number;
isActive: boolean;
content: Record<string, unknown>;
styles: SectionStyles;
settings: SectionSettings;
metadata: SectionMetadata;
}
export type SectionType =
| "hero"
| "features"
| "cta"
| "pricing"
| "testimonials"
| "contact"
| "gallery"
| "text"
| "custom";
export interface SectionStyles {
background: BackgroundStyle;
spacing: SpacingStyle;
typography: TypographyStyle;
colors: ColorStyle;
borders: BorderStyle;
effects: EffectStyle;
responsive: ResponsiveStyles;
}
export interface BackgroundStyle {
type: "color" | "gradient" | "image" | "video";
color?: string;
gradient?: GradientStyle;
image?: ImageStyle;
video?: VideoStyle;
}
export interface GradientStyle {
direction: number;
colors: Array<{ color: string; position: number }>;
}
export interface ImageStyle {
url: string;
position: "center" | "top" | "bottom" | "left" | "right";
size: "cover" | "contain" | "auto";
repeat: "no-repeat" | "repeat" | "repeat-x" | "repeat-y";
overlay?: string;
}
export interface VideoStyle {
url: string;
autoplay: boolean;
loop: boolean;
muted: boolean;
overlay?: string;
}
export interface SpacingStyle {
padding: {
top: number;
right: number;
bottom: number;
left: number;
};
margin: {
top: number;
right: number;
bottom: number;
left: number;
};
}
export interface TypographyStyle {
fontFamily: string;
fontSize: number;
fontWeight: number;
lineHeight: number;
letterSpacing: number;
textAlign: "left" | "center" | "right" | "justify";
textDecoration: "none" | "underline" | "line-through";
textTransform: "none" | "uppercase" | "lowercase" | "capitalize";
}
export interface ColorStyle {
primary: string;
secondary: string;
accent: string;
text: string;
textSecondary: string;
background: string;
border: string;
}
export interface BorderStyle {
width: number;
style: "none" | "solid" | "dashed" | "dotted";
color: string;
radius: number;
}
export interface EffectStyle {
shadow: string;
blur: number;
opacity: number;
transform: string;
transition: string;
animation: string;
}
export interface ResponsiveStyles {
mobile: Partial<SectionStyles>;
tablet: Partial<SectionStyles>;
desktop: Partial<SectionStyles>;
}
export interface SectionSettings {
isVisible: boolean;
isLocked: boolean;
animation: AnimationSettings;
seo: SeoSettings;
accessibility: AccessibilitySettings;
}
export interface AnimationSettings {
enabled: boolean;
type: "fade" | "slide" | "scale" | "rotate" | "bounce";
duration: number;
delay: number;
easing: string;
trigger: "scroll" | "hover" | "click" | "load";
}
export interface SeoSettings {
title?: string;
description?: string;
keywords?: string[];
schema?: Record<string, unknown>;
}
export interface AccessibilitySettings {
altText?: string;
ariaLabel?: string;
ariaDescription?: string;
focusable: boolean;
tabIndex?: number;
}
export interface SectionMetadata {
createdAt: Date;
updatedAt: Date;
createdBy: string;
updatedBy: string;
version: number;
templateId?: string;
customData?: Record<string, unknown>;
}
// Specific Section Content Types
export interface HeroSectionContent {
title: string;
subtitle?: string;
description?: string;
image?: ImageContent;
video?: VideoContent;
buttons: ButtonContent[];
overlay?: OverlayContent;
}
export interface FeaturesSectionContent {
title: string;
description?: string;
features: FeatureItem[];
layout: "grid" | "list" | "carousel";
columns: number;
}
export interface FeatureItem {
id: string;
title: string;
description: string;
icon?: IconContent;
image?: ImageContent;
link?: LinkContent;
}
export interface CtaSectionContent {
title: string;
description?: string;
button: ButtonContent;
background?: BackgroundContent;
layout: "centered" | "split" | "banner";
}
export interface PricingSectionContent {
title: string;
description?: string;
plans: PricingPlan[];
layout: "cards" | "table" | "comparison";
billing: "monthly" | "yearly" | "both";
}
export interface PricingPlan {
id: string;
name: string;
description?: string;
price: number;
currency: string;
billing: "monthly" | "yearly";
features: string[];
featured: boolean;
button: ButtonContent;
}
export interface ImageContent {
url: string;
alt: string;
width?: number;
height?: number;
caption?: string;
}
export interface VideoContent {
url: string;
thumbnail?: string;
autoplay: boolean;
loop: boolean;
muted: boolean;
controls: boolean;
}
export interface ButtonContent {
text: string;
url?: string;
type: "primary" | "secondary" | "outline" | "ghost";
size: "small" | "medium" | "large";
icon?: IconContent;
onClick?: string;
}
export interface IconContent {
name: string;
library: "heroicons" | "lucide" | "feather" | "custom";
size: number;
color?: string;
}
export interface LinkContent {
url: string;
text: string;
target: "_self" | "_blank" | "_parent" | "_top";
rel?: string;
}
export interface OverlayContent {
color: string;
opacity: number;
gradient?: GradientStyle;
}
export interface BackgroundContent {
type: "color" | "gradient" | "image" | "video";
value: string;
overlay?: OverlayContent;
}
// Editor Configuration Types
export interface EditorConfig {
autoSave: boolean;
autoSaveInterval: number;
enableHistory: boolean;
maxHistoryEntries: number;
enableGrid: boolean;
gridSize: number;
showOutlines: boolean;
showGuidelines: boolean;
enableKeyboardShortcuts: boolean;
previewMode: "desktop" | "tablet" | "mobile";
enableDragAndDrop: boolean;
enableCopyPaste: boolean;
enableLiveEditing: boolean;
enableCollaboration: boolean;
}
export interface EditorState {
sections: BaseSection[];
selectedSection: string | null;
selectedElement: string | null;
clipboard: ClipboardData | null;
history: HistoryEntry[];
historyIndex: number;
isDirty: boolean;
isLoading: boolean;
error: string | null;
}
export interface ClipboardData {
type: "section" | "element";
data: BaseSection | unknown;
timestamp: Date;
}
export interface HistoryEntry {
id: string;
action: "add" | "update" | "delete" | "move";
target: "section" | "element";
before: BaseSection | null;
after: BaseSection | null;
timestamp: Date;
}
// Form Field Types for Editors
export interface FormField {
id: string;
type: FormFieldType;
label: string;
description?: string;
value: unknown;
placeholder?: string;
required: boolean;
validation?: ValidationRule[];
options?: FormFieldOption[];
conditional?: ConditionalRule;
group?: string;
}
export type FormFieldType =
| "text"
| "textarea"
| "number"
| "email"
| "url"
| "tel"
| "password"
| "select"
| "multiselect"
| "radio"
| "checkbox"
| "toggle"
| "range"
| "color"
| "date"
| "datetime"
| "file"
| "image"
| "rich-text"
| "code"
| "json"
| "custom";
export interface FormFieldOption {
value: string | number;
label: string;
description?: string;
disabled?: boolean;
group?: string;
}
export interface ValidationRule {
type: "required" | "min" | "max" | "pattern" | "email" | "url" | "custom";
value?: unknown;
message: string;
validator?: (value: unknown) => boolean;
}
export interface ConditionalRule {
field: string;
operator: "=" | "!=" | ">" | "<" | ">=" | "<=" | "in" | "not-in";
value: unknown;
}
// Preview Types
export interface PreviewConfig {
device: DevicePreview;
orientation: "portrait" | "landscape";
zoom: number;
showControls: boolean;
showGrid: boolean;
showRuler: boolean;
interactive: boolean;
}
export interface DevicePreview {
name: string;
width: number;
height: number;
pixelRatio: number;
userAgent?: string;
}
// Event Types
export interface EditorEvent {
type: string;
target: string;
data?: unknown;
timestamp: Date;
}
export interface EditorEventHandler {
(event: EditorEvent): void;
}
// Component Props Types
export interface SectionEditorProps {
section?: BaseSection;
config?: EditorConfig;
onUpdate?: (section: BaseSection) => void;
onDelete?: (sectionId: string) => void;
onDuplicate?: (section: BaseSection) => void;
onMove?: (sectionId: string, direction: "up" | "down") => void;
isSelected?: boolean;
isReadOnly?: boolean;
className?: string;
showTemplateSelector?: boolean;
}
export interface SectionListProps {
className?: string;
}
export interface PreviewPanelProps {
sections: BaseSection[];
config: PreviewConfig;
selectedSection?: string;
onSectionClick: (sectionId: string) => void;
className?: string;
}
export interface PropertyPanelProps {
className?: string;
}
export interface SectionTemplateProps {
className?: string;
onSelectTemplate?: (section: BaseSection) => void;
}
export interface EditorToolbarProps {
config: EditorConfig;
onConfigChange: (config: Partial<EditorConfig>) => void;
onSave: () => void;
onUndo: () => void;
onRedo: () => void;
onPreview: () => void;
canUndo: boolean;
canRedo: boolean;
isDirty: boolean;
className?: string;
}
export interface SectionLibraryProps {
sections: SectionTemplate[];
onAdd: (template: SectionTemplate) => void;
categories: string[];
selectedCategory?: string;
onCategoryChange: (category: string) => void;
className?: string;
}
export interface SectionTemplate {
id: string;
name: string;
description: string;
category: string;
thumbnail: string;
template: Omit<BaseSection, "id" | "order">;
tags: string[];
isCustom: boolean;
isPremium: boolean;
}
// Validation error 타입
export interface ValidationError {
field: string;
message: string;
code: string;
}
// Constants
export const SECTION_TYPES: Array<{ value: SectionType; label: string }> = [
{ value: "hero", label: "Hero Section" },
{ value: "features", label: "Features" },
{ value: "cta", label: "Call to Action" },
{ value: "pricing", label: "Pricing" },
{ value: "testimonials", label: "Testimonials" },
{ value: "contact", label: "Contact" },
{ value: "gallery", label: "Gallery" },
{ value: "text", label: "Text Content" },
{ value: "custom", label: "Custom" },
];
export const DEVICE_PRESETS: DevicePreview[] = [
{ name: "Mobile", width: 375, height: 667, pixelRatio: 2 },
{ name: "Tablet", width: 768, height: 1024, pixelRatio: 2 },
{ name: "Desktop", width: 1440, height: 900, pixelRatio: 1 },
{ name: "Large Desktop", width: 1920, height: 1080, pixelRatio: 1 },
];
export const DEFAULT_EDITOR_CONFIG: EditorConfig = {
autoSave: true,
autoSaveInterval: 5000, // 5 seconds
enableHistory: true,
maxHistoryEntries: 50,
enableGrid: true,
gridSize: 12,
showOutlines: true,
showGuidelines: true,
enableKeyboardShortcuts: true,
previewMode: "desktop",
enableDragAndDrop: true,
enableCopyPaste: true,
enableLiveEditing: true,
enableCollaboration: false,
};