Files
site-builder/craft/src/panels/right/styles/FormStylePanel.tsx
T

140 lines
5.6 KiB
TypeScript
Raw Normal View History

import React, { useCallback } from 'react';
import { useEditor } from '@craftjs/core';
import {
BG_COLORS,
SPACING_PRESETS,
RADIUS_PRESETS,
} from '../../../constants/presets';
import {
StylePanelProps,
SectionLabel,
ColorSwatchGrid,
PresetButtonGrid,
CollapsibleSection,
labelStyle,
inputStyle,
btnActiveStyle,
sectionGap,
} from './shared';
/* ---------- FORM ---------- */
export const FormStylePanel: React.FC<StylePanelProps> = ({ selectedId, nodeProps }) => {
const { actions } = useEditor();
const setProp = useCallback((key: string, value: any) => {
actions.setProp(selectedId, (props: any) => { props[key] = value; });
}, [actions, selectedId]);
const setPropStyle = useCallback((key: string, value: string) => {
actions.setProp(selectedId, (props: any) => {
props.style = { ...props.style, [key]: value };
});
}, [actions, selectedId]);
const style = nodeProps.style || {};
return (
<>
{/* Form action/method */}
{nodeProps.action !== undefined && (
<div style={sectionGap}>
<label style={labelStyle}>Form Action URL</label>
<input type="text" value={nodeProps.action || ''} onChange={(e) => setProp('action', e.target.value)} placeholder="https://..." style={inputStyle} />
</div>
)}
{nodeProps.method !== undefined && (
<div style={sectionGap}>
<label style={labelStyle}>Method</label>
<div style={{ display: 'flex', gap: 4 }}>
{['GET', 'POST'].map((m) => (
<button key={m} onClick={() => setProp('method', m)} style={btnActiveStyle(nodeProps.method === m)}>{m}</button>
))}
</div>
</div>
)}
{/* Input field props */}
{nodeProps.label !== undefined && (
<div style={sectionGap}>
<label style={labelStyle}>Label</label>
<input type="text" value={nodeProps.label || ''} onChange={(e) => setProp('label', e.target.value)} style={inputStyle} />
</div>
)}
{nodeProps.placeholder !== undefined && (
<div style={sectionGap}>
<label style={labelStyle}>Placeholder</label>
<input type="text" value={nodeProps.placeholder || ''} onChange={(e) => setProp('placeholder', e.target.value)} style={inputStyle} />
</div>
)}
{nodeProps.name !== undefined && (
<div style={sectionGap}>
<label style={labelStyle}>Field Name</label>
<input type="text" value={nodeProps.name || ''} onChange={(e) => setProp('name', e.target.value)} style={inputStyle} />
</div>
)}
{nodeProps.type !== undefined && typeof nodeProps.type === 'string' && (
<div style={sectionGap}>
<label style={labelStyle}>Input Type</label>
<select value={nodeProps.type} onChange={(e) => setProp('type', e.target.value)} style={{ ...inputStyle, cursor: 'pointer' }}>
{['text', 'email', 'password', 'number', 'tel', 'url'].map((t) => (
<option key={t} value={t}>{t}</option>
))}
</select>
</div>
)}
{nodeProps.required !== undefined && (
<div style={sectionGap}>
<label style={{ ...labelStyle, display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer' }}>
<input type="checkbox" checked={nodeProps.required || false} onChange={(e) => setProp('required', e.target.checked)} />
Required
</label>
</div>
)}
{/* Button text */}
{nodeProps.text !== undefined && nodeProps.label === undefined && (
<div style={sectionGap}>
<label style={labelStyle}>Button Text</label>
<input type="text" value={nodeProps.text || ''} onChange={(e) => setProp('text', e.target.value)} style={inputStyle} />
</div>
)}
{/* Subscribe form props */}
{nodeProps.buttonText !== undefined && (
<div style={sectionGap}>
<label style={labelStyle}>Button Text</label>
<input type="text" value={nodeProps.buttonText || ''} onChange={(e) => setProp('buttonText', e.target.value)} style={inputStyle} />
</div>
)}
{nodeProps.placeholderText !== undefined && (
<div style={sectionGap}>
<label style={labelStyle}>Placeholder Text</label>
<input type="text" value={nodeProps.placeholderText || ''} onChange={(e) => setProp('placeholderText', e.target.value)} style={inputStyle} />
</div>
)}
{nodeProps.successMessage !== undefined && (
<div style={sectionGap}>
<label style={labelStyle}>Success Message</label>
<input type="text" value={nodeProps.successMessage || ''} onChange={(e) => setProp('successMessage', e.target.value)} style={inputStyle} />
</div>
)}
{/* Style */}
<CollapsibleSection title="Style" defaultOpen={false}>
<div className="guided-section">
<SectionLabel>Background</SectionLabel>
<ColorSwatchGrid colors={BG_COLORS} activeValue={style.backgroundColor} onSelect={(v: string) => setPropStyle('backgroundColor', v)} />
</div>
<div className="guided-section">
<SectionLabel>Padding</SectionLabel>
<PresetButtonGrid presets={SPACING_PRESETS} activeValue={style.padding as string} onSelect={(v) => setPropStyle('padding', v)} />
</div>
<div className="guided-section">
<SectionLabel>Border Radius</SectionLabel>
<PresetButtonGrid presets={RADIUS_PRESETS} activeValue={style.borderRadius as string} onSelect={(v) => setPropStyle('borderRadius', v)} />
</div>
</CollapsibleSection>
</>
);
};