import React, { useRef } from 'react'; import { useEditor } from '@craftjs/core'; import { labelStyle, inputStyle, sectionGap } from './shared'; /* Upload helper (same contract as ImageBlock/Navbar): uploads to WHP if a WHP_CONFIG is present, otherwise falls back to a local blob URL. */ async function uploadToWhp(file: File): Promise { const cfg = (window as any).WHP_CONFIG; if (!cfg) return URL.createObjectURL(file); const fd = new FormData(); fd.append('file', file); try { const resp = await fetch(`${cfg.apiUrl}?action=upload_asset&site_id=${cfg.siteId}`, { method: 'POST', headers: { 'X-CSRF-Token': cfg.csrfToken }, body: fd, }); const data = await resp.json(); return data.success && data.url ? data.url : null; } catch { return null; } } interface Feature { title?: string; description?: string; icon?: string; image?: string; imageAlt?: string; buttonText?: string; buttonUrl?: string; } /** * Dedicated per-feature editor for the FeaturesGrid guided panel. Unlike the * generic array editor (which only shows fields already present on the item), * this always exposes icon / image (upload or URL) / button controls, so it * works on template-created features that lack those keys. An image renders in * place of the icon whenever `image` is set. */ export const FeaturesEditor: React.FC<{ selectedId: string; features: unknown }> = ({ selectedId, features }) => { const { actions } = useEditor(); const list: Feature[] = Array.isArray(features) ? (features as Feature[]) : []; const fileRefs = useRef>({}); const mutate = (fn: (arr: Feature[]) => Feature[]) => actions.setProp(selectedId, (p: any) => { p.features = fn([...(p.features || [])]); }); const update = (i: number, field: keyof Feature, value: string) => mutate((arr) => { arr[i] = { ...arr[i], [field]: value }; return arr; }); const add = () => mutate((arr) => [...arr, { title: 'New Feature', description: 'Describe this feature.', icon: '🔧', image: '', imageAlt: '', buttonText: '', buttonUrl: '' }]); const remove = (i: number) => mutate((arr) => { arr.splice(i, 1); return arr; }); const onUpload = async (i: number, file: File) => { const url = await uploadToWhp(file); if (url) update(i, 'image', url); }; const smallBtn: React.CSSProperties = { padding: '4px 8px', fontSize: 11, borderRadius: 4, cursor: 'pointer', border: '1px solid #3f3f46', background: '#27272a', color: '#e4e4e7' }; return (
{list.map((feat, i) => (
update(i, 'title', e.target.value)} placeholder="Title" style={{ ...inputStyle, flex: 1 }} />