/* ui.jsx — shared icons + small primitives */ /* Minimal line-icon set (simple geometric strokes only) */ const Icon = { bag: (p) => (), plus: (p) => (), minus: (p) => (), x: (p) => (), check: (p) => (), arrowR: (p) => (), arrowL: (p) => (), leaf: (p) => (), bowl: (p) => (), spoon: (p) => (), heart: ({ filled, ...p } = {}) => (), truck: (p) => (), store: (p) => (), lock: (p) => (), clock: (p) => (), pin: (p) => (), info: (p) => (), mail: (p) => (), flame: (p) => (), }; /* tag chip */ function Tag({ k }) { const label = (window.TAG_LABEL || {})[k] || k; const cls = { vegan: "tag-vegan", veg: "tag-veg", gf: "tag-gf", spicy: "tag-spicy" }[k] || ""; const ic = k === "vegan" || k === "veg" ? : k === "spicy" ? : null; return ({ic}{label}); } /* image-slot wrapper — renders the drop-in slot with a tasteful tinted fallback */ function Photo({ id, label, tint, shape, radius, style, src }) { const ref = React.useRef(null); // Real photo: explicit src wins, else look up by slot id in window.IMAGES. // Falls back to the tinted empty state when neither is set. const photo = src || (window.IMAGES && window.IMAGES[id]) || undefined; return ( ); } function mixTint(hex) { // subtle diagonal wash using the soup's tint over cream return `repeating-linear-gradient(135deg, ${hexA(hex,0.13)} 0 16px, ${hexA(hex,0.22)} 16px 32px), var(--cream-deep)`; } function hexA(hex, a) { const h = hex.replace("#", ""); const r = parseInt(h.slice(0,2),16), g = parseInt(h.slice(2,4),16), b = parseInt(h.slice(4,6),16); return `rgba(${r},${g},${b},${a})`; } /* quantity stepper */ function Stepper({ qty, onDec, onInc, min }) { return (
{qty}
); } const CHF = (n) => "CHF " + n.toFixed(2).replace(".", "."); Object.assign(window, { Icon, Tag, Photo, Stepper, CHF, hexA });