// Калькулятор ЗП — UI primitives // Building blocks shared by all screens. const { useState, useEffect, useRef } = React; /* ---------- Icon (Lucide via CDN, tinted to cream) ---------- */ function Icon({ name, size = 16, color }) { return ( ); } /* ---------- Eyebrow / Micro ---------- */ function Eyebrow({ tone = 'mute', children }) { const color = tone === 'warm' ? 'var(--orange-300)' : 'var(--text-3)'; return (
{children}
); } function Micro({ children, style }) { return (
{children}
); } /* ---------- Button ---------- */ function Button({ variant = 'primary', size = 'md', icon, children, ...rest }) { return ( ); } /* ---------- Field + Input ---------- */ function Field({ label, hint, children }) { return ( ); } function MoneyInput({ value, onChange, placeholder }) { const [focused, setFocused] = useState(false); const display = focused ? (value === '' || value == null ? '' : String(value)) : (value === '' || value == null ? '' : fmtMoney(value)); return ( setFocused(true)} onBlur={() => setFocused(false)} onChange={e => { const raw = e.target.value.replace(/[^\d.,-]/g, '').replace(',', '.'); onChange(raw === '' ? '' : Number(raw)); }} /> ); } function TextInput({ value, onChange, placeholder, icon, ...rest }) { return (
{icon && ( )} onChange(e.target.value)} {...rest} />
); } /* ---------- Chip (pill) ---------- */ function Chip({ tone, dot, children }) { const cls = `chip${tone ? ' chip-' + tone : ''}`; return ( {dot && } {children} ); } /* ---------- Money (display) ---------- */ function Money({ value, size = 'md', tone = 'cream' }) { const colors = { cream: 'var(--cream)', orange: 'var(--orange-300)', success: 'var(--success)', error: 'var(--error)', mute: 'var(--text-3)', }; const sizes = { sm: { fontSize: 14, fontFamily: 'var(--font-sans)', fontWeight: 500 }, md: { fontSize: 18, fontFamily: 'var(--font-sans)', fontWeight: 500 }, lg: { fontSize: 28, fontFamily: 'var(--font-display)', fontWeight: 400, letterSpacing: '-0.012em' }, xl: { fontSize: 48, fontFamily: 'var(--font-display)', fontWeight: 300, letterSpacing: '-0.025em', lineHeight: 1 }, }; return ( {fmtMoney(value)} ); } /* ---------- GlassCard ---------- */ function GlassCard({ elevated = false, children, style, className = '' }) { return (
{children}
); } /* ---------- Orb (brand mark, CSS-rendered) ---------- */ function Orb({ size = 180 }) { return (
); } /* ---------- Plural ---------- */ function plural(n, forms) { const abs = Math.abs(n) % 100; const n1 = abs % 10; if (abs > 10 && abs < 20) return forms[2]; if (n1 > 1 && n1 < 5) return forms[1]; if (n1 === 1) return forms[0]; return forms[2]; } Object.assign(window, { Icon, Eyebrow, Micro, Button, Field, MoneyInput, TextInput, Chip, Money, GlassCard, Orb, plural, });