// wf/primitives.jsx — shared sketchy wireframe parts // Phone shell — lighter wireframe bezel for breadth-mode mockups. const Phone = ({ children, statusInk = false, height = 720 }) => (
9:41
{children}
); // Burger / language / search row that sits beneath the status bar const PhoneHeader = ({ right = 'FR / EN' }) => (
{right}
); // Bottom icon strip — the persistent navigation seen in the reference const BottomNav = ({ active = 0 }) => { const ions = ['home','key','pin','wifi','utensils','wave']; return (
{ions.map((k,i) => (
))}
); }; // Minimal hairline icon set — stand-ins that match the lucide/logo line weight const Icon = ({ name, size = 22, color }) => { const s = size; const stroke = color || 'var(--wf-ink)'; const props = { width:s, height:s, viewBox:'0 0 24 24', fill:'none', stroke, strokeWidth:1.4, strokeLinecap:'round', strokeLinejoin:'round' }; switch(name){ case 'home': return ; case 'key': return ; case 'pin': return ; case 'rules': return ; case 'wifi': return ; case 'faq': return ; case 'cart': return ; case 'basket': return ; case 'map': return ; case 'ship': return ; case 'bike': return ; case 'utensils': return ; case 'cocktail': return ; case 'leaf': return ; case 'wave': return ; case 'phone': return ; case 'alert': return ; case 'arrow-r': return ; case 'arrow-l': return ; case 'star': return ; case 'plus': return ; case 'x': return ; case 'chev-d': return ; case 'chev-r': return ; case 'search': return ; case 'globe': return ; case 'clock': return ; case 'door': return ; default: return ; } }; // Placeholder photo box. variant: arch | circle | rect | bleed const Photo = ({ w=140, h=100, variant='rect', label='Photo', style={} }) => { const cls = variant === 'circle' ? 'ph circle' : variant === 'arch' ? 'ph arch' : 'ph'; return
{label}
; }; // Small annotation marker — handwritten note + curving arrow const Annot = ({ children, x, y, w=120, align='left', arrow }) => (
{arrow === 'tl' && } {children} {arrow === 'br' && }
); // Squiggly text underline (sketch vibe) const Squig = ({ w = 80, color }) => ( ); // Faux line of body text — gray bar const TextLine = ({ w = '100%', h = 7, mt = 4, opacity = 0.5 }) => (
); // A row of N faux lines of body text, shrinking const Para = ({ lines = 3, opacity = 0.4 }) => (
{Array.from({length:lines}).map((_,i)=>( ))}
); // Small "pill" button outline (wireframe) const PillBtn = ({ children, w, dark = false, style = {} }) => (
{children}
); // Rectangular accent button (the "Rechercher" style) const AccentBtn = ({ children, w = 'auto', style = {} }) => (
{children}
); // Section eyebrow with squiggle underline const Eyebrow = ({ children, color }) => (
{children}
); // Category metadata used across the wireframes const CATEGORIES = [ { id:'welcome', icon:'home', fr:'Bienvenue', en:'Welcome' }, { id:'rules', icon:'rules', fr:'Règles de la maison',en:'House rules' }, { id:'wifi', icon:'wifi', fr:'Wi-Fi', en:'Wi-Fi' }, { id:'check', icon:'key', fr:'Check-in / out', en:'Check-in / out' }, { id:'resto', icon:'utensils', fr:'Restaurants', en:'Restaurants' }, { id:'bars', icon:'cocktail', fr:'Bars & cocktails', en:'Bars & cocktails' }, { id:'spa', icon:'leaf', fr:'Spa & bien-être', en:'Spa & wellness' }, { id:'beach', icon:'wave', fr:'Plages', en:'Beaches' }, { id:'transp', icon:'ship', fr:'Transports', en:'Transport' }, { id:'shops', icon:'basket', fr:'Commerces', en:'Local shops' }, { id:'help', icon:'alert', fr:'Urgences', en:'Emergencies' }, ]; Object.assign(window, { Phone, PhoneHeader, BottomNav, Icon, Photo, Annot, Squig, TextLine, Para, PillBtn, AccentBtn, Eyebrow, CATEGORIES });