// shared.jsx — common components used across all 3 variations /* ---------- Photo placeholder / real image ---------- */ const Photo = ({ label, tone = 'default', style, children, src, alt = '', objectPosition = 'center' }) => { // When a real image src is provided, render it full-bleed inside the frame. if (src) { return (
{alt} {children}
); } const cls = 'photo-ph' + (tone !== 'default' ? ' ' + tone : ''); return (
{label && {label}} {children}
); }; /* ---------- Logo (image) ---------- */ const LogoMark = ({ size = 56, bg = 'transparent' }) => (
SARABASE.estate
); /* ---------- Text logo (clean type-only) ---------- */ const TextLogo = ({ color = 'var(--ink)', size = 22 }) => (
SARABASE.estate
); /* ---------- Responsive breakpoint hook ---------- desktop > 1024px, tablet 641–1024px, mobile ≤ 640px */ const useBreakpoint = () => { const get = () => { if (typeof window === 'undefined') return 'desktop'; const w = window.innerWidth; return w <= 640 ? 'mobile' : w <= 1024 ? 'tablet' : 'desktop'; }; const [bp, setBp] = React.useState(get); React.useEffect(() => { const on = () => setBp(get()); window.addEventListener('resize', on); return () => window.removeEventListener('resize', on); }, []); return bp; }; // pick a value by breakpoint; falls back desktop→tablet→mobile when undefined const pick = (bp, d, t, m) => bp === 'mobile' ? (m !== undefined ? m : (t !== undefined ? t : d)) : bp === 'tablet' ? (t !== undefined ? t : d) : d; /* ---------- Navigation bar (responsive: hamburger ≤1024px) ---------- */ const NavBar = ({ variant = 'light', items = ['MISSION', 'ABOUT', 'PROFILE', 'VOICE', 'CONTACT'] }) => { const isDark = variant === 'dark'; const bp = useBreakpoint(); const isDesktop = bp === 'desktop'; const [open, setOpen] = React.useState(false); const fg = isDark ? 'var(--warm-white)' : 'var(--ink)'; // Lock body scroll while the overlay is open React.useEffect(() => { document.body.style.overflow = open ? 'hidden' : ''; return () => { document.body.style.overflow = ''; }; }, [open]); return (
SARABASE.estate {isDesktop ? (
) : ( )} {/* Mobile / tablet overlay menu */} {!isDesktop && (
CONTACT
0776-43-3334 info@sarabase-estate.jp
)}
); }; /* ---------- SNS icons row (Instagram / Mail / Tel) ---------- */ const SnsRow = ({ color = 'var(--ink)', size = 16 }) => { const ic = { width: size, height: size, fill: 'none', stroke: color, strokeWidth: 1.4 }; return (
{/* Instagram */} {/* Mail */} {/* Tel */}
); }; /* ---------- Sketch property illustration (hand-drawn, Instagram-ish) ---------- */ const SKETCH_VARIANTS = [ // 0 — 2LDK(縦割り:左にLDK、右に洋室+水回り) (s) => ( ), // 1 — 3LDK(中央廊下+3部屋) (s) => ( ), // 2 — 1LDK(広いLDK+小部屋) (s) => ( ), // 3 — 4LDK(田の字) (s) => ( ), // 4 — LDK広々(リビング中心) (s) => ( ), // 5 — 2DK(コンパクト) (s) => ( ), ]; const SketchCard = ({ index = 0, label, height = 200, width = 280 }) => { const draw = SKETCH_VARIANTS[index % SKETCH_VARIANTS.length]; return (
{draw('var(--pink-500)')}
{label} SARABASE
); }; const MiniMap = ({ height = 280 }) => (
); /* ---------- Contact form (compact) ---------- */ const ContactForm = ({ accent = 'var(--ink)' }) => { const inputStyle = { width: '100%', padding: '14px 0', border: 'none', borderBottom: '1px solid var(--line-strong)', background: 'transparent', fontFamily: 'var(--sans-jp)', fontSize: 14, outline: 'none', }; const labelStyle = { fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: '0.18em', color: 'var(--ink-mid)', textTransform: 'uppercase', display: 'block', marginBottom: 6, }; return (