// East Quabbin Health — shared UI primitives
// Icons drawn as simple line SVGs; illustration uses abstract soft shapes
const EqIcon = ({ name, size = 20, stroke = 1.8, color = 'currentColor' }) => {
const paths = {
arrowLeft: ,
arrowRight: ,
check: ,
x: <>>,
plus: <>>,
minus: ,
shield: ,
clock: <>>,
heart: ,
home: <>>,
phone: ,
mail: <>>,
user: <>>,
users: <>>,
pill: <>>,
car: <>>,
calendar: <>>,
pen: <>>,
sparkle: <>>,
info: <>>,
globe: <>>,
printer: <>>,
hand: <>>,
moon: ,
sun: <>>,
bell: <>>,
};
return (
);
};
// Soft organic shape — procedurally generated blob for backgrounds
const EqBlob = ({ color = '#B8C9B4', size = 120, seed = 1, opacity = 1, style = {} }) => {
const rand = (s) => {
const x = Math.sin(s * 9999) * 10000;
return x - Math.floor(x);
};
const points = [];
const n = 8;
for (let i = 0; i < n; i++) {
const a = (i / n) * Math.PI * 2;
const r = 40 + rand(seed + i) * 14;
points.push([50 + Math.cos(a) * r, 50 + Math.sin(a) * r]);
}
const d = points.map((p, i) => {
if (i === 0) return `M ${p[0]},${p[1]}`;
const prev = points[i - 1];
const mid = [(p[0] + prev[0]) / 2, (p[1] + prev[1]) / 2];
return `Q ${prev[0]},${prev[1]} ${mid[0]},${mid[1]}`;
}).join(' ') + ' Z';
return (
);
};
// Little organic "health" logo mark — abstract leaf/heart hybrid
const EqMark = ({ size = 40 }) => (
);
// Header bar inside phone frame (back arrow + step)
const EqHeader = ({ current, total, onBack, onSave, showBack = true, savedFlash, t }) => (
{t.common.step} {current} {t.common.of} {total}
{savedFlash ? '✓ ' + t.common.saved : t.steps[current - 1]?.label}
);
// Footer with primary action
const EqFooter = ({ children, sticky = true }) => (
{children}
);
// Big title block used atop each screen
const EqTitle = ({ title, sub, icon, accent }) => (
{icon && (
)}
{title}
{sub &&
{sub}
}
);
// Form row helper
const EqRow = ({ label, children, hint, optional }) => (
{label && (
{optional && Optional}
)}
{children}
{hint &&
{hint}
}
);
// Stepper for numeric count
const EqStepper = ({ value, onChange, min = 0, max = 20 }) => (
{value}
);
// Option (select / multi-select) — a tappable row
const EqOption = ({ on, onClick, children, multi = false, icon }) => (
);
// Tweak-panel segmented control
const EqSeg = ({ options, value, onChange }) => (
{options.map((o) => (
))}
);
Object.assign(window, {
EqIcon, EqBlob, EqMark, EqHeader, EqFooter, EqTitle, EqRow,
EqStepper, EqOption, EqSeg,
});