video 블록 및 리펙터링
This commit is contained in:
@@ -10,11 +10,12 @@ import { createFaqTemplateBlocks } from "@/app/editor/templates/faqTemplate";
|
||||
import { createPricingTemplateBlocks } from "@/app/editor/templates/pricingTemplate";
|
||||
import { createTestimonialsTemplateBlocks } from "@/app/editor/templates/testimonialsTemplate";
|
||||
|
||||
// 블록 타입 정의: 텍스트/버튼/이미지/섹션/구분선/리스트/폼 블록/폼 요소 블록
|
||||
// 블록 타입 정의: 텍스트/버튼/이미지/비디오/섹션/구분선/리스트/폼 블록/폼 요소 블록
|
||||
export type BlockType =
|
||||
| "text"
|
||||
| "button"
|
||||
| "image"
|
||||
| "video"
|
||||
| "section"
|
||||
| "divider"
|
||||
| "list"
|
||||
@@ -138,6 +139,34 @@ export interface ImageBlockProps {
|
||||
assetId?: string | null;
|
||||
}
|
||||
|
||||
export interface VideoBlockProps {
|
||||
sourceUrl: string;
|
||||
sourceType?: "asset" | "externalUrl";
|
||||
assetId?: string | null;
|
||||
posterImageSrc?: string;
|
||||
posterSourceType?: "asset" | "externalUrl";
|
||||
posterAssetId?: string | null;
|
||||
platform?: "auto" | "youtube" | "vimeo" | "html5";
|
||||
align?: "left" | "center" | "right";
|
||||
widthMode?: "auto" | "full" | "fixed";
|
||||
widthPx?: number;
|
||||
aspectRatio?: "16:9" | "4:3" | "1:1";
|
||||
autoplay?: boolean;
|
||||
loop?: boolean;
|
||||
muted?: boolean;
|
||||
controls?: boolean;
|
||||
titleText?: string;
|
||||
ariaLabel?: string;
|
||||
captionText?: string;
|
||||
// HTML5 비디오 재생 범위(초 단위)
|
||||
startTimeSec?: number;
|
||||
endTimeSec?: number;
|
||||
// 카드 스타일: 배경색/패딩/모서리 둥글기
|
||||
backgroundColorCustom?: string;
|
||||
cardPaddingPx?: number;
|
||||
borderRadiusPx?: number;
|
||||
}
|
||||
|
||||
// 구분선 블록 속성
|
||||
export interface DividerBlockProps {
|
||||
align: "left" | "center" | "right";
|
||||
@@ -494,6 +523,20 @@ export interface SectionBlockProps {
|
||||
gapXPx?: number;
|
||||
alignItems?: "top" | "center" | "bottom";
|
||||
backgroundColorCustom?: string;
|
||||
// 섹션 배경 이미지
|
||||
backgroundImageSrc?: string;
|
||||
backgroundImageSourceType?: "asset" | "externalUrl";
|
||||
backgroundImageAssetId?: string | null;
|
||||
backgroundImageSize?: "auto" | "cover" | "contain";
|
||||
backgroundImagePosition?: "center" | "top" | "bottom" | "left" | "right";
|
||||
backgroundImageRepeat?: "no-repeat" | "repeat" | "repeat-x" | "repeat-y";
|
||||
backgroundImagePositionMode?: "preset" | "custom";
|
||||
backgroundImagePositionXPercent?: number;
|
||||
backgroundImagePositionYPercent?: number;
|
||||
// 섹션 배경 비디오
|
||||
backgroundVideoSrc?: string;
|
||||
backgroundVideoSourceType?: "asset" | "externalUrl";
|
||||
backgroundVideoAssetId?: string | null;
|
||||
}
|
||||
|
||||
// 폼 입력/셀렉트/체크박스/라디오 공통 스타일 속성
|
||||
@@ -651,6 +694,7 @@ export interface Block {
|
||||
| TextBlockProps
|
||||
| ButtonBlockProps
|
||||
| ImageBlockProps
|
||||
| VideoBlockProps
|
||||
| SectionBlockProps
|
||||
| DividerBlockProps
|
||||
| ListBlockProps
|
||||
@@ -676,6 +720,7 @@ export interface EditorState {
|
||||
addTextBlock: () => void;
|
||||
addButtonBlock: () => void;
|
||||
addImageBlock: () => void;
|
||||
addVideoBlock: () => void;
|
||||
addDividerBlock: () => void;
|
||||
addListBlock: () => void;
|
||||
addSectionBlock: () => void;
|
||||
@@ -1182,6 +1227,52 @@ const createEditorState = (set: any, get: any): EditorState => ({
|
||||
}));
|
||||
},
|
||||
|
||||
// 비디오 블록 추가: 기본 소스/정렬/비율 설정과 함께 생성 후 선택 상태로 만든다
|
||||
addVideoBlock: () => {
|
||||
const id = createId();
|
||||
|
||||
const { selectedBlockId, blocks } = get();
|
||||
let sectionId: string | null = null;
|
||||
let columnId: string | null = null;
|
||||
|
||||
if (selectedBlockId) {
|
||||
const target = blocks.find((b: Block) => b.id === selectedBlockId);
|
||||
if (target) {
|
||||
if (target.type === "section") {
|
||||
const sProps = target.props as SectionBlockProps;
|
||||
sectionId = target.id;
|
||||
columnId = sProps.columns?.[0]?.id ?? null;
|
||||
} else {
|
||||
sectionId = (target as any).sectionId ?? null;
|
||||
columnId = (target as any).columnId ?? null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const newBlock: Block = {
|
||||
id,
|
||||
type: "video",
|
||||
props: {
|
||||
sourceUrl: "",
|
||||
platform: "auto",
|
||||
align: "center",
|
||||
widthMode: "auto",
|
||||
aspectRatio: "16:9",
|
||||
controls: true,
|
||||
autoplay: false,
|
||||
loop: false,
|
||||
muted: false,
|
||||
},
|
||||
sectionId,
|
||||
columnId,
|
||||
};
|
||||
|
||||
set((state: EditorState) => ({
|
||||
blocks: [...state.blocks, newBlock],
|
||||
selectedBlockId: id,
|
||||
}));
|
||||
},
|
||||
|
||||
// 폼 입력 블록 추가: 루트에 기본 label/formFieldName 과 함께 생성 후 선택 상태로 만든다
|
||||
addFormInputBlock: () => {
|
||||
const id = createId();
|
||||
|
||||
Reference in New Issue
Block a user