feat: WYSIWYG 빌더 1차 기능 완성 및 테스트 추가
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import type { WObject } from '@/lib/wysiwyg/schema'
|
||||
|
||||
export type PropsPanelProps = {
|
||||
@@ -15,9 +15,21 @@ function isImage(o: WObject): o is Extract<WObject, { type: 'image' }> {
|
||||
return o.type === 'image'
|
||||
}
|
||||
|
||||
function isText(o: WObject): o is Extract<WObject, { type: 'text' }> {
|
||||
return o.type === 'text'
|
||||
}
|
||||
|
||||
function isButton(o: WObject): o is Extract<WObject, { type: 'button' }> {
|
||||
return o.type === 'button'
|
||||
}
|
||||
|
||||
export function PropsPanel({ object, onChange }: PropsPanelProps) {
|
||||
const [model, setModel] = useState<WObject>(object)
|
||||
|
||||
useEffect(() => {
|
||||
setModel(object)
|
||||
}, [object])
|
||||
|
||||
const emit = (next: WObject) => {
|
||||
setModel(next)
|
||||
onChange?.(next)
|
||||
@@ -32,6 +44,16 @@ export function PropsPanel({ object, onChange }: PropsPanelProps) {
|
||||
const next: WObject = { ...model, props: { ...model.props, ...patch } }
|
||||
emit(next)
|
||||
}
|
||||
const updateTextProps = (patch: Partial<{ text: string }>): void => {
|
||||
if (!isText(model)) return
|
||||
const next: WObject = { ...model, props: { ...model.props, ...patch } }
|
||||
emit(next)
|
||||
}
|
||||
const updateButtonProps = (patch: Partial<{ label: string }>): void => {
|
||||
if (!isButton(model)) return
|
||||
const next: WObject = { ...model, props: { ...model.props, ...patch } }
|
||||
emit(next)
|
||||
}
|
||||
|
||||
return (
|
||||
<div aria-label="Properties Panel">
|
||||
@@ -58,6 +80,24 @@ export function PropsPanel({ object, onChange }: PropsPanelProps) {
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{isText(model) && (
|
||||
<div>
|
||||
<label>
|
||||
Text
|
||||
<input aria-label="Text" type="text" value={model.props.text} onChange={(e) => updateTextProps({ text: e.target.value })} />
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isButton(model) && (
|
||||
<div>
|
||||
<label>
|
||||
Label
|
||||
<input aria-label="Label" type="text" value={model.props.label} onChange={(e) => updateButtonProps({ label: e.target.value })} />
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isImage(model) && (
|
||||
<div>
|
||||
<label>
|
||||
|
||||
Reference in New Issue
Block a user