import React, { useCallback } from 'react'; import { useEditor } from '@craftjs/core'; import { SPACING_PRESETS, } from '../../../constants/presets'; import { StylePanelProps, SectionLabel, PresetButtonGrid, CollapsibleSection, ColorPickerField, navColorFields, btnActiveStyle, labelStyle, inputStyle, smallInputStyle, sectionGap, useNodeProp, } from './shared'; import { AssetPicker } from '../../../ui/AssetPicker'; /* ---------- NAV / MENU / LOGO ---------- */ export const NavStylePanel: React.FC = ({ selectedId, nodeProps }) => { const { actions } = useEditor(); const { setProp, setPropStyle } = useNodeProp(selectedId); const links: any[] = nodeProps.links || []; const updateLink = useCallback((index: number, field: string, value: any) => { actions.setProp(selectedId, (props: any) => { const updated = [...(props.links || [])]; updated[index] = { ...updated[index], [field]: value }; props.links = updated; }); }, [actions, selectedId]); const addLink = useCallback(() => { actions.setProp(selectedId, (props: any) => { props.links = [...(props.links || []), { text: 'New Link', href: '#' }]; }); }, [actions, selectedId]); const removeLink = useCallback((index: number) => { actions.setProp(selectedId, (props: any) => { const updated = [...(props.links || [])]; updated.splice(index, 1); props.links = updated; }); }, [actions, selectedId]); /* Detect standalone Logo vs Navbar/Menu */ const isStandaloneLogo = nodeProps.type !== undefined && (nodeProps.type === 'text' || nodeProps.type === 'image') && nodeProps.logoText === undefined; /* Color controls, derived from the props the selected component actually has */ const colorFields = navColorFields(nodeProps); /* Menu layout controls (alignment/orientation/gap/font size). These props are unique to the Menu component — Navbar uses navAlignment and has no orientation/gap/fontSize — so guarding on their presence scopes this section to the Menu without leaking into Navbar or a standalone Logo. */ const hasMenuLayout = !isStandaloneLogo && ( nodeProps.alignment !== undefined || nodeProps.orientation !== undefined || nodeProps.gap !== undefined || nodeProps.fontSize !== undefined ); const GAP_PRESETS = ['8px', '16px', '24px', '32px', '40px'].map((g) => ({ label: g, value: g })); return ( <> {/* Standalone Logo component settings */} {isStandaloneLogo && (
{nodeProps.type === 'text' && ( <>
setProp('text', e.target.value)} style={inputStyle} />
setProp('fontSize', e.target.value)} placeholder="20px" style={inputStyle} />
setProp('color', v)} /> )} {nodeProps.type === 'image' && ( <>
setProp('imageSrc', url)} variant="full" />
setProp('imageWidth', e.target.value)} placeholder="120px" style={inputStyle} />
)}
setProp('href', e.target.value)} placeholder="/" style={inputStyle} />
)} {/* Navbar Logo settings */} {nodeProps.logoText !== undefined && (
setProp('logoText', e.target.value)} style={inputStyle} />
{nodeProps.logoImage !== undefined && (
setProp('logoImage', url)} variant="full" />
)} {nodeProps.logoUrl !== undefined && (
setProp('logoUrl', e.target.value)} placeholder="/" style={inputStyle} />
)}
)} {/* Links (not shown for standalone Logo) */} {!isStandaloneLogo && (
{links.map((link, i) => (
updateLink(i, 'text', e.target.value)} placeholder="Text" style={{ ...smallInputStyle, flex: 1 }} />
updateLink(i, 'href', e.target.value)} placeholder="URL" style={{ ...smallInputStyle, color: '#71717a' }} />
))}
)} {/* Colors (not shown for standalone Logo - it has its own color picker). Fields are derived from whichever color props the selected component actually has, so Menu (linkColor/ctaBg/…) and Navbar (backgroundColor/…) each get the right controls instead of an empty section. */} {!isStandaloneLogo && colorFields.length > 0 && ( {colorFields.map((f) => ( setProp(f.key, v)} /> ))} )} {/* Menu layout (alignment / orientation / gap / font size) */} {hasMenuLayout && ( {nodeProps.alignment !== undefined && (
{(['left', 'center', 'right'] as const).map((a) => ( ))}
)} {nodeProps.orientation !== undefined && (
{(['horizontal', 'vertical'] as const).map((o) => ( ))}
)} {nodeProps.gap !== undefined && (
setProp('gap', v)} />
)} {nodeProps.fontSize !== undefined && (
setProp('fontSize', e.target.value)} placeholder="14px" style={inputStyle} />
)}
)} {/* Style overrides */}
Padding setPropStyle('padding', v)} />
); };