텍스트 스타일 및 프리뷰 렌더링 정리
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
"use client";
|
||||
|
||||
import { useCallback } from "react";
|
||||
import { useEditorStore } from "@/features/editor/state/editorStore";
|
||||
|
||||
// 좌측 블록/폼/템플릿 추가 사이드바를 분리한 컴포넌트
|
||||
export function BlocksSidebar() {
|
||||
const addTextBlock = useEditorStore((state) => state.addTextBlock);
|
||||
const addButtonBlock = useEditorStore((state) => state.addButtonBlock);
|
||||
const addImageBlock = useEditorStore((state) => state.addImageBlock);
|
||||
const addDividerBlock = useEditorStore((state) => state.addDividerBlock);
|
||||
const addListBlock = useEditorStore((state) => state.addListBlock);
|
||||
const addSectionBlock = useEditorStore((state) => state.addSectionBlock);
|
||||
|
||||
const addFormBlock = useEditorStore((state) => state.addFormBlock);
|
||||
const addFormInputBlock = useEditorStore((state) => (state as any).addFormInputBlock);
|
||||
const addFormSelectBlock = useEditorStore((state) => (state as any).addFormSelectBlock);
|
||||
const addFormCheckboxBlock = useEditorStore((state) => (state as any).addFormCheckboxBlock);
|
||||
const addFormRadioBlock = useEditorStore((state) => (state as any).addFormRadioBlock);
|
||||
|
||||
const addHeroTemplateSection = useEditorStore((state) => state.addHeroTemplateSection);
|
||||
const addFeaturesTemplateSection = useEditorStore((state) => state.addFeaturesTemplateSection);
|
||||
const addCtaTemplateSection = useEditorStore((state) => state.addCtaTemplateSection);
|
||||
const addFaqTemplateSection = useEditorStore((state) => state.addFaqTemplateSection);
|
||||
const addPricingTemplateSection = useEditorStore((state) => state.addPricingTemplateSection);
|
||||
const addTestimonialsTemplateSection = useEditorStore((state) => state.addTestimonialsTemplateSection);
|
||||
const addBlogTemplateSection = useEditorStore((state) => state.addBlogTemplateSection);
|
||||
const addTeamTemplateSection = useEditorStore((state) => state.addTeamTemplateSection);
|
||||
const addFooterTemplateSection = useEditorStore((state) => state.addFooterTemplateSection);
|
||||
|
||||
// 버튼 핸들러를 useCallback으로 래핑해 불필요한 재생성을 줄인다.
|
||||
const handleAddText = useCallback(() => addTextBlock(), [addTextBlock]);
|
||||
const handleAddButton = useCallback(() => addButtonBlock(), [addButtonBlock]);
|
||||
const handleAddImage = useCallback(() => addImageBlock(), [addImageBlock]);
|
||||
const handleAddDivider = useCallback(() => addDividerBlock(), [addDividerBlock]);
|
||||
const handleAddList = useCallback(() => addListBlock(), [addListBlock]);
|
||||
const handleAddSection = useCallback(() => addSectionBlock(), [addSectionBlock]);
|
||||
|
||||
const handleAddFormBlock = useCallback(() => addFormBlock(), [addFormBlock]);
|
||||
const handleAddFormInput = useCallback(() => addFormInputBlock(), [addFormInputBlock]);
|
||||
const handleAddFormSelect = useCallback(() => addFormSelectBlock(), [addFormSelectBlock]);
|
||||
const handleAddFormRadio = useCallback(() => addFormRadioBlock(), [addFormRadioBlock]);
|
||||
const handleAddFormCheckbox = useCallback(() => addFormCheckboxBlock(), [addFormCheckboxBlock]);
|
||||
|
||||
const handleAddHeroTemplate = useCallback(
|
||||
() => addHeroTemplateSection(),
|
||||
[addHeroTemplateSection],
|
||||
);
|
||||
const handleAddFeaturesTemplate = useCallback(
|
||||
() => addFeaturesTemplateSection(),
|
||||
[addFeaturesTemplateSection],
|
||||
);
|
||||
const handleAddCtaTemplate = useCallback(() => addCtaTemplateSection(), [addCtaTemplateSection]);
|
||||
const handleAddFaqTemplate = useCallback(() => addFaqTemplateSection(), [addFaqTemplateSection]);
|
||||
const handleAddPricingTemplate = useCallback(
|
||||
() => addPricingTemplateSection(),
|
||||
[addPricingTemplateSection],
|
||||
);
|
||||
const handleAddTestimonialsTemplate = useCallback(
|
||||
() => addTestimonialsTemplateSection(),
|
||||
[addTestimonialsTemplateSection],
|
||||
);
|
||||
const handleAddBlogTemplate = useCallback(() => addBlogTemplateSection(), [addBlogTemplateSection]);
|
||||
const handleAddTeamTemplate = useCallback(() => addTeamTemplateSection(), [addTeamTemplateSection]);
|
||||
const handleAddFooterTemplate = useCallback(
|
||||
() => addFooterTemplateSection(),
|
||||
[addFooterTemplateSection],
|
||||
);
|
||||
|
||||
return (
|
||||
<aside className="w-60 border-r border-slate-800 p-4 text-sm space-y-3">
|
||||
<h2 className="font-medium">블록</h2>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddText}
|
||||
>
|
||||
텍스트 블록 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddButton}
|
||||
>
|
||||
버튼 블록 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddImage}
|
||||
>
|
||||
이미지 블록 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddDivider}
|
||||
>
|
||||
구분선 블록 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddList}
|
||||
>
|
||||
리스트 블록 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddSection}
|
||||
>
|
||||
섹션 블록 추가
|
||||
</button>
|
||||
|
||||
<div className="pt-3 border-t border-slate-800 mt-3 space-y-2">
|
||||
<h3 className="text-[11px] font-medium text-slate-300">폼 요소</h3>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-emerald-700 bg-emerald-950 px-3 py-2 text-left text-xs text-emerald-100 hover:bg-emerald-900"
|
||||
onClick={handleAddFormBlock}
|
||||
>
|
||||
폼 블록 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddFormInput}
|
||||
>
|
||||
폼 입력 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddFormSelect}
|
||||
>
|
||||
폼 셀렉트 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddFormRadio}
|
||||
>
|
||||
폼 라디오 그룹 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddFormCheckbox}
|
||||
>
|
||||
폼 체크박스 추가
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="pt-3 border-t border-slate-800 mt-3 space-y-2">
|
||||
<h3 className="text-[11px] font-medium text-slate-300">템플릿</h3>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-sky-700 bg-sky-950 px-3 py-2 text-left text-xs text-sky-100 hover:bg-sky-900"
|
||||
onClick={handleAddHeroTemplate}
|
||||
>
|
||||
Hero 템플릿 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddFeaturesTemplate}
|
||||
>
|
||||
Features 템플릿 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddCtaTemplate}
|
||||
>
|
||||
CTA 템플릿 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddFaqTemplate}
|
||||
>
|
||||
FAQ 템플릿 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddPricingTemplate}
|
||||
>
|
||||
Pricing 템플릿 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddTestimonialsTemplate}
|
||||
>
|
||||
Testimonials 템플릿 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddBlogTemplate}
|
||||
>
|
||||
Blog 템플릿 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddTeamTemplate}
|
||||
>
|
||||
Team 템플릿 추가
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded border border-slate-700 bg-slate-900 px-3 py-2 text-left text-xs hover:bg-slate-800"
|
||||
onClick={handleAddFooterTemplate}
|
||||
>
|
||||
Footer 템플릿 추가
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-slate-500">
|
||||
Text / Image / Button / Divider / List / Section 블록을 이 영역에서 추가할 수 있습니다.
|
||||
</p>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user