Editor
블록 타입 레퍼런스
opt-editor 기본 카탈로그에 포함된 15개 블록 타입의 Props, 중첩 구조, AI 프롬프트 활용 방식을 정리합니다.
reopt design업데이트
1. 블록 목록
| type | Props | 설명 | 편집 | 컨테이너 |
|---|---|---|---|---|
| paragraph | { text: string } | 일반 텍스트 문단. split/merge 지원. | text | - |
| heading | { text: string, level: number } | 제목 (h1-h6). level로 크기 지정. | text | - |
| quote | { text: string } | 인용 블록. 좌측 테두리 스타일. | text | - |
| callout | { variant: "info"|"warning"|"error"|"success", text: string } | 정보/경고/에러/성공 박스. 아이콘 자동 매핑. | text | - |
| code | { code: string, language: string } | 코드 블록. highlightCode 주입 시 syntax highlighting. | code | - |
| divider | {} | 수평 구분선. | - | - |
| list | { ordered: boolean } | 리스트 컨테이너. children은 list-item. | - | Yes |
| list-item | { text: string } | 리스트 아이템. list의 자식으로만 사용. | text | - |
| table | {} | 테이블 컨테이너. children은 table-row. | - | Yes |
| table-row | {} | 테이블 행. children은 table-cell. | - | Yes |
| table-cell | { text: string, header: boolean } | 테이블 셀. header=true이면 <th scope='col'>. | text | - |
| image | { src: string, alt: string, width?: number, height?: number, caption?: string, align?: "left"|"center"|"right" } | 이미지. 정렬, 리사이즈, 캡션 인라인 편집, 더블클릭 프리뷰, 파일 업로드/붙여넣기/드롭 지원. | caption | - |
| video | { src: string, poster?: string, caption?: string } | 비디오. <video controls> 렌더링. | - | - |
| file | { url: string, name: string, size?: string } | 파일 첨부. 다운로드 링크 렌더링. | - | - |
| embed | { url: string, title?: string, aspectRatio?: string } | 임베드. sandboxed iframe 렌더링. | - | - |
2. 중첩 구조
컨테이너 블록은 canHaveChildren: true로 선언됩니다. 자식 블록의 ID 배열을 children 필드에 저장합니다.
text
list (container)
└── list-item (leaf)
table (container)
└── table-row (container)
└── table-cell (leaf)Validator가 부모-자식 관계를 검증합니다: table-cell은 반드시 table-row의 자식, table-row는 반드시 table의 자식이어야 합니다.
3. 커스텀 블록 추가
tsx
import type {
BlockDefinition,
BlockRenderProps,
} from "@reopt-ai/opt-editor";
interface BannerAttrs {
title?: string;
color?: string;
}
function BannerBlock({
id,
attrs,
selected,
editableStringAttr,
}: BlockRenderProps<BannerAttrs>) {
return (
<div
data-block-id={id}
data-block-type="banner"
data-selected={selected || undefined}
style={{ background: attrs.color ?? "#eef2ff", padding: "1em" }}
>
{editableStringAttr?.("title", {
as: "strong",
placeholder: "Banner title",
}) ?? attrs.title}
</div>
);
}
export const bannerDefinition: BlockDefinition<BannerAttrs> = {
type: "banner",
attrsSchema: {
title: { type: "string", default: "" },
color: { type: "string", default: "#eef2ff" },
},
component: BannerBlock,
prompt: "A colored banner. Set title and color (CSS color value).",
};