import React, { CSSProperties, useState } from 'react'; import { useNode, UserComponent } from '@craftjs/core'; import { cssPropsToString } from '../../utils/style-helpers'; import { escapeHtml, escapeAttr, safeUrl, scopeId, cssValue } from '../../utils/escape'; /* ---------- Types ---------- */ interface MenuLink { text: string; href: string; isExternal?: boolean; isCta?: boolean; /** Adds the `download` attribute to the exported anchor (F3: links to files). */ download?: boolean; } interface MenuProps { links?: MenuLink[]; alignment?: 'left' | 'center' | 'right'; linkColor?: string; linkHoverColor?: string; ctaBgColor?: string; ctaTextColor?: string; gap?: string; orientation?: 'horizontal' | 'vertical'; fontSize?: string; style?: CSSProperties; hideOnDesktop?: boolean; hideOnTablet?: boolean; hideOnMobile?: boolean; animation?: string; animationDelay?: string; } /* ---------- Defaults ---------- */ const defaultLinks: MenuLink[] = [ { text: 'Home', href: '/' }, { text: 'About', href: '#about' }, { text: 'Services', href: '#services' }, { text: 'Contact', href: '#contact', isCta: true }, ]; /* ---------- Component ---------- */ export const Menu: UserComponent = ({ links = defaultLinks, alignment = 'right', linkColor = '#3f3f46', linkHoverColor = '#3b82f6', ctaBgColor = '#3b82f6', ctaTextColor = '#ffffff', gap = '24px', orientation = 'horizontal', fontSize = '14px', style = {}, }) => { const { connectors: { connect, drag }, } = useNode(); const [hoveredLink, setHoveredLink] = useState(null); const justifyMap = { left: 'flex-start', center: 'center', right: 'flex-end' }; return ( ); }; /* ---------- Craft config ---------- */ Menu.craft = { displayName: 'Menu', props: { links: defaultLinks, alignment: 'right', linkColor: '#3f3f46', linkHoverColor: '#3b82f6', ctaBgColor: '#3b82f6', ctaTextColor: '#ffffff', gap: '24px', orientation: 'horizontal', fontSize: '14px', style: {}, hideOnDesktop: false, hideOnTablet: false, hideOnMobile: false, animation: 'none', animationDelay: '0', } as MenuProps, rules: { canDrag: () => true, canMoveIn: () => false, canMoveOut: () => true, }, }; /* ---------- HTML export ---------- */ (Menu as any).toHtml = (props: MenuProps, _childrenHtml: string, nodeId?: string) => { // Sanitized once here -- linkCol/hoverCol/ctaBg/ctaText/gap/fSize are raw // string-interpolation sinks below (hoverCol goes into a breakout -> arbitrary