/* CargoNote — shared components (icons, chips, badges, buttons) */ // ===== Icons (small set, stroke-based) ===== const Icon = ({ name, size = 16, ...p }) => { const common = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round", ...p }; const paths = { inbox: <>, plus: <>, file: <>, pdf: <>PDF, image: <>, mail: <>, upload: <>, search: <>, settings:<>, chev: , chevD: , arrow: <>, check: , x: <>, spark: , eye: <>, edit: <>, download:<>, print: <>, refresh: <>, save: <>, flag: <>, alert: <>, info: <>, filter: <>, sort: <>, folder: <>, paperclip:<>, mapPin: <>, calendar:<>, truck: <>, layers: <>, history: <>, bell: <>, dot: , }; return {paths[name]}; }; // ===== Confidence chip ===== const ConfidenceChip = ({ score, compact = false }) => { if (score == null) return null; const pct = Math.round(score * 100); const cls = score >= 0.9 ? "hi" : score >= 0.7 ? "med" : "lo"; const label = score >= 0.9 ? "Élevée" : score >= 0.7 ? "Moyenne" : "Faible"; return ( {compact ? `${pct}%` : `${label} · ${pct}%`} ); }; // ===== Status badge ===== const StatusBadge = ({ status }) => { const m = { processing: "Traitement", review: "À vérifier", approved: "Validé", error: "Erreur", }; return ( {m[status] || status} ); }; // ===== Source icon ===== const SourceIcon = ({ source }) => { if (source === "email") return ; if (source === "upload") return ; return ; }; // ===== Field card ===== const FieldCard = ({ id, label, box, value, conf, status, active, onActivate, onEdit, multiline, placeholder, conflictWith }) => { // status overrides confidence visuals: "edited" | "conflict" const dataConf = status || (conf == null ? null : (conf >= 0.9 ? "hi" : conf >= 0.7 ? "med" : "lo")); const empty = value == null || value === "" || value === "—"; return (
onActivate && onActivate(id)} >
{box} {label} {status === "edited" && ( Modifié )} {status === "conflict" && ( Conflit )} {!status && conf != null && !empty && ( )} {empty && !status && ( Vide )}
onEdit && onEdit(id, e.currentTarget.innerText)} >{empty ? "" : value}
{conflictWith && (
Conflit avec {conflictWith.source} : « {conflictWith.value} »
)}
); }; // ===== Group section header ===== const Group = ({ title, count, action, children }) => (

{title}

{count != null && {count}} {action}
{children}
); // ===== Tooltip-ish hover region (used for doc highlights legend) ===== const Legend = () => (
Élevée Moyenne Faible Modifié Conflit
); // Export to window for cross-script use Object.assign(window, { Icon, ConfidenceChip, StatusBadge, SourceIcon, FieldCard, Group, Legend });