import React, { useCallback, useState, useRef } from 'react'; import { useEditor } from '@craftjs/core'; import { StylePanelProps, CollapsibleSection, ColorPickerField, uploadToWhp, labelStyle, inputStyle, smallInputStyle, btnActiveStyle, sectionGap, } from './shared'; /* ---------- Asset Browser Inline ---------- */ const AssetBrowser: React.FC<{ filter: 'image' | 'video' | 'all'; onSelect: (url: string) => void; }> = ({ filter, onSelect }) => { const [assets, setAssets] = useState([]); const [loading, setLoading] = useState(false); const [open, setOpen] = useState(false); const loadAssets = useCallback(async () => { const cfg = (window as any).WHP_CONFIG; if (!cfg) return; setLoading(true); try { const resp = await fetch(`${cfg.apiUrl}?action=list_assets&site_id=${cfg.siteId}`); const data = await resp.json(); if (data.success && Array.isArray(data.assets)) { const filtered = filter === 'all' ? data.assets : data.assets.filter((a: any) => { const t = (a.type || '').toLowerCase(); return filter === 'image' ? t.startsWith('image') : t.startsWith('video'); }); setAssets(filtered); } } catch (e) { console.error('Load assets failed:', e); } setLoading(false); }, [filter]); const handleToggle = useCallback(() => { if (!open) loadAssets(); setOpen(!open); }, [open, loadAssets]); return (
{open && (
{assets.map((asset, i) => (
{ onSelect(asset.url); setOpen(false); }} style={{ cursor: 'pointer', borderRadius: 4, overflow: 'hidden', border: '2px solid transparent', aspectRatio: '1', transition: 'border-color 0.15s', background: '#27272a', display: 'flex', alignItems: 'center', justifyContent: 'center' }} onMouseEnter={(e) => { e.currentTarget.style.borderColor = '#3b82f6'; }} onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'transparent'; }}> {(asset.type || '').startsWith('image') ? ( {asset.name} ) : (
{asset.name?.replace(/^\d+_[a-f0-9]+_/, '')}
)}
))} {assets.length === 0 && (

No {filter} assets uploaded yet

)}
)}
); }; /* ---------- HERO STYLE PANEL ---------- */ export const HeroStylePanel: React.FC = ({ selectedId, nodeProps }) => { const { actions } = useEditor(); const fileInputRef = useRef(null); const setProp = useCallback((key: string, value: any) => { actions.setProp(selectedId, (props: any) => { props[key] = value; }); }, [actions, selectedId]); const handleUpload = useCallback(async (file: File, propKey: string) => { const url = await uploadToWhp(file); if (url) setProp(propKey, url); }, [setProp]); const bgType = nodeProps.bgType || 'color'; return ( <>
setProp('heading', e.target.value)} style={inputStyle} />