video 블록 및 리펙터링
This commit is contained in:
@@ -0,0 +1,278 @@
|
||||
import type { CSSProperties } from "react";
|
||||
import type { SectionBlockProps } from "@/features/editor/state/editorStore";
|
||||
|
||||
export interface SectionExportTokens {
|
||||
sectionClasses: string;
|
||||
sectionStyleParts: string[];
|
||||
backgroundVideoHtml: string;
|
||||
}
|
||||
|
||||
export function computeSectionExportTokens(props: SectionBlockProps): SectionExportTokens {
|
||||
const bgToken = props.background ?? "default";
|
||||
const bgClassMap: Record<SectionBlockProps["background"], string> = {
|
||||
default: "pb-section-bg-default",
|
||||
muted: "pb-section-bg-muted",
|
||||
primary: "pb-section-bg-primary",
|
||||
};
|
||||
const bgClass = bgClassMap[bgToken] ?? "pb-section-bg-default";
|
||||
|
||||
const pyToken = props.paddingY ?? "md";
|
||||
const pyClassMap: Record<SectionBlockProps["paddingY"], string> = {
|
||||
sm: "pb-section-py-sm",
|
||||
md: "pb-section-py-md",
|
||||
lg: "pb-section-py-lg",
|
||||
};
|
||||
const pyClass = pyClassMap[pyToken] ?? "pb-section-py-md";
|
||||
|
||||
const sectionClasses = ["pb-section", bgClass, pyClass].filter(Boolean).join(" ");
|
||||
const sectionStyleParts: string[] = [];
|
||||
|
||||
if (typeof props.backgroundColorCustom === "string" && props.backgroundColorCustom.trim() !== "") {
|
||||
sectionStyleParts.push(`background-color:${props.backgroundColorCustom.trim()}`);
|
||||
}
|
||||
|
||||
const bgImgSrc = props.backgroundImageSrc;
|
||||
if (typeof bgImgSrc === "string" && bgImgSrc.trim() !== "") {
|
||||
const url = bgImgSrc.trim();
|
||||
sectionStyleParts.push(`background-image:url(${url})`);
|
||||
|
||||
const size = props.backgroundImageSize ?? "cover";
|
||||
sectionStyleParts.push(`background-size:${size}`);
|
||||
|
||||
const posMode = props.backgroundImagePositionMode ?? "preset";
|
||||
if (posMode === "custom") {
|
||||
const x = props.backgroundImagePositionXPercent;
|
||||
const y = props.backgroundImagePositionYPercent;
|
||||
const xSafe = typeof x === "number" ? x : 50;
|
||||
const ySafe = typeof y === "number" ? y : 50;
|
||||
sectionStyleParts.push(`background-position:${xSafe}% ${ySafe}%`);
|
||||
} else {
|
||||
const posToken = props.backgroundImagePosition ?? "center";
|
||||
const position =
|
||||
posToken === "top"
|
||||
? "center top"
|
||||
: posToken === "bottom"
|
||||
? "center bottom"
|
||||
: posToken === "left"
|
||||
? "left center"
|
||||
: posToken === "right"
|
||||
? "right center"
|
||||
: "center center";
|
||||
sectionStyleParts.push(`background-position:${position}`);
|
||||
}
|
||||
|
||||
const repeat = props.backgroundImageRepeat ?? "no-repeat";
|
||||
sectionStyleParts.push(`background-repeat:${repeat}`);
|
||||
}
|
||||
|
||||
const bgVideoSrc = props.backgroundVideoSrc;
|
||||
let backgroundVideoHtml = "";
|
||||
if (typeof bgVideoSrc === "string" && bgVideoSrc.trim() !== "") {
|
||||
const url = bgVideoSrc.trim();
|
||||
backgroundVideoHtml = `<video class="pb-section-bg-video" src="${url}" autoplay loop muted playsinline></video>`;
|
||||
sectionStyleParts.push("position:relative");
|
||||
sectionStyleParts.push("overflow:hidden");
|
||||
}
|
||||
|
||||
return {
|
||||
sectionClasses,
|
||||
sectionStyleParts,
|
||||
backgroundVideoHtml,
|
||||
};
|
||||
}
|
||||
|
||||
export interface SectionPublicTokens {
|
||||
sectionStyle: CSSProperties;
|
||||
innerWrapperStyle: CSSProperties;
|
||||
columnsContainerStyle: CSSProperties;
|
||||
hasBackgroundVideo: boolean;
|
||||
backgroundVideoSrc: string | null;
|
||||
}
|
||||
|
||||
const pxToEm = (px: number, base = 16) => `${px / base}em`;
|
||||
|
||||
export function computeSectionPublicTokens(props: SectionBlockProps): SectionPublicTokens {
|
||||
const sectionStyle: CSSProperties = {};
|
||||
|
||||
if (props.backgroundColorCustom && props.backgroundColorCustom.trim() !== "") {
|
||||
sectionStyle.backgroundColor = props.backgroundColorCustom.trim();
|
||||
}
|
||||
|
||||
if (typeof props.paddingYPx === "number" && props.paddingYPx > 0) {
|
||||
const paddingEm = pxToEm(props.paddingYPx);
|
||||
sectionStyle.paddingTop = paddingEm;
|
||||
sectionStyle.paddingBottom = paddingEm;
|
||||
}
|
||||
|
||||
const rawBgVideoSrc = (props as any).backgroundVideoSrc;
|
||||
let hasBackgroundVideo = false;
|
||||
let backgroundVideoSrc: string | null = null;
|
||||
if (typeof rawBgVideoSrc === "string" && rawBgVideoSrc.trim() !== "") {
|
||||
hasBackgroundVideo = true;
|
||||
backgroundVideoSrc = rawBgVideoSrc.trim();
|
||||
sectionStyle.position = "relative";
|
||||
sectionStyle.overflow = "hidden";
|
||||
}
|
||||
|
||||
if (props.backgroundImageSrc && props.backgroundImageSrc.trim() !== "") {
|
||||
const url = props.backgroundImageSrc.trim();
|
||||
sectionStyle.backgroundImage = `url(${url})`;
|
||||
|
||||
const size = props.backgroundImageSize ?? "cover";
|
||||
sectionStyle.backgroundSize = size;
|
||||
|
||||
const posMode = props.backgroundImagePositionMode ?? "preset";
|
||||
if (
|
||||
posMode === "custom" &&
|
||||
typeof props.backgroundImagePositionXPercent === "number" &&
|
||||
typeof props.backgroundImagePositionYPercent === "number"
|
||||
) {
|
||||
const x = props.backgroundImagePositionXPercent;
|
||||
const y = props.backgroundImagePositionYPercent;
|
||||
sectionStyle.backgroundPosition = `${x}% ${y}%`;
|
||||
} else {
|
||||
const posToken = props.backgroundImagePosition ?? "center";
|
||||
const position =
|
||||
posToken === "top"
|
||||
? "center top"
|
||||
: posToken === "bottom"
|
||||
? "center bottom"
|
||||
: posToken === "left"
|
||||
? "left center"
|
||||
: posToken === "right"
|
||||
? "right center"
|
||||
: "center center";
|
||||
sectionStyle.backgroundPosition = position;
|
||||
}
|
||||
|
||||
const repeat = props.backgroundImageRepeat ?? "no-repeat";
|
||||
sectionStyle.backgroundRepeat = repeat;
|
||||
}
|
||||
|
||||
const innerWrapperStyle: CSSProperties = {};
|
||||
if (typeof props.maxWidthPx === "number" && props.maxWidthPx > 0) {
|
||||
innerWrapperStyle.maxWidth = pxToEm(props.maxWidthPx);
|
||||
}
|
||||
|
||||
const columnsContainerStyle: CSSProperties = {};
|
||||
if (typeof props.gapXPx === "number" && props.gapXPx > 0) {
|
||||
columnsContainerStyle.columnGap = pxToEm(props.gapXPx);
|
||||
}
|
||||
|
||||
return {
|
||||
sectionStyle,
|
||||
innerWrapperStyle,
|
||||
columnsContainerStyle,
|
||||
hasBackgroundVideo,
|
||||
backgroundVideoSrc,
|
||||
};
|
||||
}
|
||||
|
||||
export interface SectionEditorTokens {
|
||||
bgClass: string;
|
||||
pyClass: string;
|
||||
alignItemsClass: string;
|
||||
wrapperStyle: CSSProperties;
|
||||
innerWrapperStyle: CSSProperties;
|
||||
columnsContainerStyle: CSSProperties;
|
||||
hasBackgroundVideo: boolean;
|
||||
backgroundVideoSrc: string | null;
|
||||
}
|
||||
|
||||
export function computeSectionEditorTokens(props: SectionBlockProps): SectionEditorTokens {
|
||||
const bgClass =
|
||||
props.background === "muted"
|
||||
? "bg-slate-950/40"
|
||||
: props.background === "primary"
|
||||
? "bg-sky-950/40 border-sky-900/60"
|
||||
: "bg-slate-900/60";
|
||||
|
||||
const pyClass =
|
||||
props.paddingY === "sm"
|
||||
? "py-4"
|
||||
: props.paddingY === "lg"
|
||||
? "py-10"
|
||||
: "py-6";
|
||||
|
||||
const alignItemsClass =
|
||||
props.alignItems === "center"
|
||||
? "items-center"
|
||||
: props.alignItems === "bottom"
|
||||
? "items-end"
|
||||
: "items-start";
|
||||
|
||||
const wrapperStyle: CSSProperties = {};
|
||||
if (props.backgroundColorCustom && props.backgroundColorCustom.trim() !== "") {
|
||||
wrapperStyle.backgroundColor = props.backgroundColorCustom;
|
||||
}
|
||||
|
||||
if (typeof props.paddingYPx === "number" && props.paddingYPx > 0) {
|
||||
wrapperStyle.paddingTop = `${props.paddingYPx}px`;
|
||||
wrapperStyle.paddingBottom = `${props.paddingYPx}px`;
|
||||
}
|
||||
|
||||
let hasBackgroundVideo = false;
|
||||
let backgroundVideoSrc: string | null = null;
|
||||
if (typeof props.backgroundVideoSrc === "string" && props.backgroundVideoSrc.trim() !== "") {
|
||||
hasBackgroundVideo = true;
|
||||
backgroundVideoSrc = props.backgroundVideoSrc.trim();
|
||||
wrapperStyle.position = "relative";
|
||||
wrapperStyle.overflow = "hidden";
|
||||
}
|
||||
|
||||
if (props.backgroundImageSrc && props.backgroundImageSrc.trim() !== "") {
|
||||
const url = props.backgroundImageSrc.trim();
|
||||
wrapperStyle.backgroundImage = `url(${url})`;
|
||||
|
||||
const size = props.backgroundImageSize ?? "cover";
|
||||
wrapperStyle.backgroundSize = size;
|
||||
|
||||
const posMode = props.backgroundImagePositionMode ?? "preset";
|
||||
if (
|
||||
posMode === "custom" &&
|
||||
typeof props.backgroundImagePositionXPercent === "number" &&
|
||||
typeof props.backgroundImagePositionYPercent === "number"
|
||||
) {
|
||||
const x = props.backgroundImagePositionXPercent;
|
||||
const y = props.backgroundImagePositionYPercent;
|
||||
wrapperStyle.backgroundPosition = `${x}% ${y}%`;
|
||||
} else {
|
||||
const posToken = props.backgroundImagePosition ?? "center";
|
||||
const position =
|
||||
posToken === "top"
|
||||
? "center top"
|
||||
: posToken === "bottom"
|
||||
? "center bottom"
|
||||
: posToken === "left"
|
||||
? "left center"
|
||||
: posToken === "right"
|
||||
? "right center"
|
||||
: "center center";
|
||||
wrapperStyle.backgroundPosition = position;
|
||||
}
|
||||
|
||||
const repeat = props.backgroundImageRepeat ?? "no-repeat";
|
||||
wrapperStyle.backgroundRepeat = repeat;
|
||||
}
|
||||
|
||||
const innerWrapperStyle: CSSProperties = {};
|
||||
if (typeof props.maxWidthPx === "number" && props.maxWidthPx > 0) {
|
||||
innerWrapperStyle.maxWidth = `${props.maxWidthPx}px`;
|
||||
}
|
||||
|
||||
const columnsContainerStyle: CSSProperties = {};
|
||||
if (typeof props.gapXPx === "number" && props.gapXPx > 0) {
|
||||
columnsContainerStyle.columnGap = `${props.gapXPx}px`;
|
||||
}
|
||||
|
||||
return {
|
||||
bgClass,
|
||||
pyClass,
|
||||
alignItemsClass,
|
||||
wrapperStyle,
|
||||
innerWrapperStyle,
|
||||
columnsContainerStyle,
|
||||
hasBackgroundVideo,
|
||||
backgroundVideoSrc,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user