refactor(builder): remove dead component settings UI

Each component defined a .craft.related.settings panel that was never
rendered -- the right panel renders only GuidedStyles (per-type
*StylePanel components), never .related.settings. Removed all dead
settings components across every component, their settings-only helpers
(including the dead uploadToWhp/showBrowser/handleBrowse asset-browse
blocks in Logo/Navbar/VideoBlock/FeaturesGrid, and CtasEditor in
_cta-helpers), and dropped the now-empty related keys. Render output,
.craft props/rules, and toHtml statics are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-12 13:16:53 -07:00
co-authored by Claude Opus 4.8
parent 4674a99ec9
commit 65a10a1ef9
40 changed files with 10 additions and 6718 deletions
+1 -113
View File
@@ -1,4 +1,4 @@
import React, { CSSProperties } from 'react';
import { CSSProperties } from 'react';
import { escapeHtml, escapeAttr, safeUrl } from '../../utils/escape';
export type CtaVariant = 'primary' | 'outline' | 'ghost';
@@ -86,115 +86,3 @@ export function ctasToHtml(ctas: CtaButton[], defaults: CtaStyleDefaults): strin
}).join('');
}
/* ---------- CTAs editor (settings UI) ---------- */
interface CtasEditorProps {
ctas: CtaButton[];
/** Called whenever the user mutates the array. Sections wire this via setProp. */
onChange: (next: CtaButton[]) => void;
/** Max items the user can add. Default 4. */
max?: number;
}
const inputStyle: CSSProperties = {
width: '100%', padding: '6px 8px', background: '#27272a',
color: '#e4e4e7', border: '1px solid #3f3f46', borderRadius: 4, fontSize: 12,
};
const labelStyle: CSSProperties = {
fontSize: 11, color: '#a1a1aa', display: 'block', marginBottom: 4,
};
export const CtasEditor: React.FC<CtasEditorProps> = ({ ctas, onChange, max = 4 }) => {
const update = (i: number, patch: Partial<CtaButton>) => {
const next = ctas.slice();
next[i] = { ...next[i], ...patch };
onChange(next);
};
const remove = (i: number) => onChange(ctas.filter((_, j) => j !== i));
const add = () => {
if (ctas.length >= max) return;
onChange([...ctas, { text: 'New button', href: '#', variant: ctas.length === 0 ? 'primary' : 'outline' }]);
};
const move = (i: number, dir: -1 | 1) => {
const j = i + dir;
if (j < 0 || j >= ctas.length) return;
const next = ctas.slice();
[next[i], next[j]] = [next[j], next[i]];
onChange(next);
};
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
<div style={{ fontSize: 11, color: '#a1a1aa', fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.5px' }}>
Buttons ({ctas.length})
</div>
{ctas.length === 0 && (
<div style={{ fontSize: 11, color: '#71717a', fontStyle: 'italic', padding: '8px 0' }}>
No buttons. Click "Add button" to insert one.
</div>
)}
{ctas.map((cta, i) => (
<div key={i} style={{
background: '#18181b', border: '1px solid #3f3f46', borderRadius: 6,
padding: 10, display: 'flex', flexDirection: 'column', gap: 6,
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
<span style={{ fontSize: 10, color: '#a1a1aa', fontWeight: 600, flex: 1 }}>Button {i + 1}</span>
<button onClick={() => move(i, -1)} disabled={i === 0} title="Move up"
style={iconBtn(i === 0)}>↑</button>
<button onClick={() => move(i, 1)} disabled={i === ctas.length - 1} title="Move down"
style={iconBtn(i === ctas.length - 1)}>↓</button>
<button onClick={() => remove(i)} title="Remove"
style={{ ...iconBtn(false), color: '#fca5a5' }}>✕</button>
</div>
<div>
<label style={labelStyle}>Text</label>
<input type="text" value={cta.text} onChange={(e) => update(i, { text: e.target.value })} style={inputStyle} />
</div>
<div>
<label style={labelStyle}>URL</label>
<input type="text" value={cta.href} onChange={(e) => update(i, { href: e.target.value })}
placeholder="https://… or #anchor" style={inputStyle} />
</div>
<div style={{ display: 'flex', gap: 6 }}>
<div style={{ flex: 1 }}>
<label style={labelStyle}>Style</label>
<select value={cta.variant || 'primary'}
onChange={(e) => update(i, { variant: e.target.value as CtaVariant })}
style={{ ...inputStyle, padding: '5px 6px' }}>
<option value="primary">Primary (filled)</option>
<option value="outline">Outline</option>
<option value="ghost">Ghost (text)</option>
</select>
</div>
<div style={{ flex: '0 0 auto', display: 'flex', alignItems: 'flex-end' }}>
<label style={{ fontSize: 11, color: '#a1a1aa', display: 'inline-flex', alignItems: 'center', gap: 4, cursor: 'pointer', whiteSpace: 'nowrap' }}>
<input type="checkbox" checked={cta.target === '_blank'}
onChange={(e) => update(i, { target: e.target.checked ? '_blank' : undefined })} />
New tab
</label>
</div>
</div>
</div>
))}
{ctas.length < max && (
<button onClick={add} style={{
padding: '8px 12px', fontSize: 12, fontWeight: 600,
color: '#3b82f6', background: 'rgba(59,130,246,0.1)',
border: '1px dashed #3b82f6', borderRadius: 4, cursor: 'pointer',
}}>
+ Add button{ctas.length === 0 ? '' : ` (${max - ctas.length} more)`}
</button>
)}
</div>
);
};
function iconBtn(disabled: boolean): CSSProperties {
return {
width: 22, height: 22, fontSize: 11,
background: '#27272a', color: disabled ? '#52525b' : '#a1a1aa',
border: '1px solid #3f3f46', borderRadius: 4,
cursor: disabled ? 'not-allowed' : 'pointer',
};
}