// Калькулятор ЗП — 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,
});