@ginia/ui 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/components/domain/resume/resume-preview/resume-preview.cjs +7 -3
  2. package/dist/components/domain/resume/resume-preview/resume-preview.cjs.map +1 -1
  3. package/dist/components/domain/resume/resume-preview/resume-preview.d.cts +2 -0
  4. package/dist/components/domain/resume/resume-preview/resume-preview.d.ts +2 -0
  5. package/dist/components/domain/resume/resume-preview/resume-preview.js +7 -3
  6. package/dist/components/domain/resume/resume-preview/resume-preview.js.map +1 -1
  7. package/dist/components/domain/resume/resume-preview/sections/contact-skills.cjs +6 -6
  8. package/dist/components/domain/resume/resume-preview/sections/contact-skills.cjs.map +1 -1
  9. package/dist/components/domain/resume/resume-preview/sections/contact-skills.js +6 -6
  10. package/dist/components/domain/resume/resume-preview/sections/contact-skills.js.map +1 -1
  11. package/dist/components/domain/resume/resume-preview/sections/experience-education.cjs +9 -18
  12. package/dist/components/domain/resume/resume-preview/sections/experience-education.cjs.map +1 -1
  13. package/dist/components/domain/resume/resume-preview/sections/experience-education.js +10 -19
  14. package/dist/components/domain/resume/resume-preview/sections/experience-education.js.map +1 -1
  15. package/dist/components/domain/resume/resume-preview/sections/footer-preview.cjs +15 -3
  16. package/dist/components/domain/resume/resume-preview/sections/footer-preview.cjs.map +1 -1
  17. package/dist/components/domain/resume/resume-preview/sections/footer-preview.js +15 -3
  18. package/dist/components/domain/resume/resume-preview/sections/footer-preview.js.map +1 -1
  19. package/dist/components/domain/resume/resume-preview/sections/header-preview.cjs +3 -3
  20. package/dist/components/domain/resume/resume-preview/sections/header-preview.cjs.map +1 -1
  21. package/dist/components/domain/resume/resume-preview/sections/header-preview.js +3 -3
  22. package/dist/components/domain/resume/resume-preview/sections/header-preview.js.map +1 -1
  23. package/dist/components/domain/resume/resume.cjs +9 -5
  24. package/dist/components/domain/resume/resume.cjs.map +1 -1
  25. package/dist/components/domain/resume/resume.d.cts +1 -1
  26. package/dist/components/domain/resume/resume.d.ts +1 -1
  27. package/dist/components/domain/resume/resume.js +9 -5
  28. package/dist/components/domain/resume/resume.js.map +1 -1
  29. package/dist/components/domain/resume/types.cjs.map +1 -1
  30. package/dist/components/domain/resume/types.d.cts +9 -0
  31. package/dist/components/domain/resume/types.d.ts +9 -0
  32. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/components/domain/resume/resume-preview/sections/experience-education.tsx"],"sourcesContent":["import { CandidateProfile } from \"../../types\";\nimport type { CVExperienceBaseItem, CVCertificationItem } from \"../../types\";\nimport { GraduationCap, Briefcase, Trophy, Award } from \"lucide-react\";\n\n/** Parsea una fecha (MM/YYYY, YYYY-MM o YYYY) a un valor numérico para ordenar (mayor = más reciente) */\nfunction parseDateToSortValue(dateStr: string | undefined): number {\n if (!dateStr || dateStr.toLowerCase() === \"presente\") return 0;\n // MM/YYYY\n const mmYyyy = dateStr.match(/^(\\d{1,2})\\/(\\d{4})$/);\n if (mmYyyy) return parseInt(mmYyyy[2], 10) * 12 + parseInt(mmYyyy[1], 10);\n // YYYY-MM o YYYY-MM-DD\n const yyyyMm = dateStr.match(/^(\\d{4})-(\\d{1,2})/);\n if (yyyyMm) return parseInt(yyyyMm[1], 10) * 12 + parseInt(yyyyMm[2], 10);\n // Solo año\n const year = dateStr.match(/\\d{4}/);\n if (year) return parseInt(year[0], 10) * 12;\n return 0;\n}\n\n/** Ordena descendente por fecha de fin; si no hay end_date (Presente), usa start_date y prioriza como más reciente */\nfunction sortByDateDesc<T extends CVExperienceBaseItem>(items: T[]): T[] {\n return [...items].sort((a, b) => {\n const aEnd = a.end_date?.toLowerCase();\n const bEnd = b.end_date?.toLowerCase();\n const aOngoing = !a.end_date || aEnd === \"presente\";\n const bOngoing = !b.end_date || bEnd === \"presente\";\n const aVal = aOngoing ? parseDateToSortValue(a.start_date) + 9999 * 12 : parseDateToSortValue(a.end_date);\n const bVal = bOngoing ? parseDateToSortValue(b.start_date) + 9999 * 12 : parseDateToSortValue(b.end_date);\n return bVal - aVal;\n });\n}\n\n/** Ordena certificaciones descendente por date_awarded */\nfunction sortCertificationsByDateDesc(items: CVCertificationItem[]): CVCertificationItem[] {\n return [...items].sort((a, b) => {\n const aVal = parseDateToSortValue(a.date_awarded);\n const bVal = parseDateToSortValue(b.date_awarded);\n return bVal - aVal;\n });\n}\n\ninterface ExperienceEducationProps {\n data: CandidateProfile;\n theme?: string;\n hideFields?: string[];\n hideSections?: string[];\n}\n\nexport function ExperienceEducation({\n data,\n theme,\n hideFields = [],\n hideSections = [],\n}: ExperienceEducationProps) {\n const experiences = sortByDateDesc(data.work_experience || []);\n const education = sortByDateDesc(data.education || []);\n const activities = sortByDateDesc(data.activities || []);\n const certifications = sortCertificationsByDateDesc(data.certifications || []);\n\n const themeStyle = theme ? { backgroundColor: theme } : undefined;\n\n return (\n <div className=\"space-y-12\">\n {/* Experience */}\n {experiences.length > 0 && !hideSections.includes(\"Experiencia laboral\") && (\n <div className=\"space-y-6\">\n <h3 className=\"flex items-center gap-2 border-b-2 border-primary/20 pb-2 text-2xl font-bold text-primary\">\n <Briefcase className=\"h-6 w-6 text-primary\" />\n Experiencia Laboral\n </h3>\n <div className=\"space-y-8\">\n {experiences.map((exp) => (\n <div\n key={exp.id}\n className=\"relative pl-6 after:absolute after:bottom-[-24px] after:left-[3px] after:top-4 after:w-[2px] after:bg-border last:after:hidden\"\n >\n <div\n className=\"pdf-line-v absolute left-0 top-2 h-2 w-2 rounded-full bg-primary\"\n style={themeStyle}\n />\n {!hideFields.includes(\"experience.title\") && (\n <h4 className=\"text-lg font-bold text-foreground\">{exp.title}</h4>\n )}\n <div className=\"mb-2 flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n {!hideFields.includes(\"experience.institution_name\") && (\n <span className=\"text-base font-semibold text-primary\">\n {exp.institution_name}\n </span>\n )}\n {(!hideFields.includes(\"experience.start_date\") ||\n !hideFields.includes(\"experience.end_date\")) && (\n <span className=\"mt-1 w-fit rounded-md bg-muted/30 px-2 py-0.5 text-sm font-medium text-muted-foreground sm:mt-0\">\n {!hideFields.includes(\"experience.start_date\") && exp.start_date}\n {!hideFields.includes(\"experience.end_date\") && (\n <> {exp.end_date ? `- ${exp.end_date}` : \"- Presente\"}</>\n )}\n </span>\n )}\n </div>\n {exp.description && !hideFields.includes(\"experience.description\") && (\n <p className=\"mt-3 whitespace-pre-wrap text-base leading-relaxed text-foreground/80\">\n {exp.description}\n </p>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Education */}\n {education.length > 0 && !hideSections.includes(\"Educación\") && (\n <div className=\"space-y-6\">\n <h3 className=\"flex items-center gap-2 border-b-2 border-primary/20 pb-2 text-2xl font-bold text-primary\">\n <GraduationCap className=\"h-6 w-6 text-primary\" />\n Educación\n </h3>\n <div className=\"space-y-8\">\n {education.map((edu) => (\n <div\n key={edu.id}\n className=\"relative pl-6 after:absolute after:bottom-[-24px] after:left-[3px] after:top-4 after:w-[2px] after:bg-border last:after:hidden\"\n >\n <div\n className=\"pdf-line-v absolute left-0 top-2 h-2 w-2 rounded-full bg-primary\"\n style={themeStyle}\n />\n {!hideFields.includes(\"education.title\") && (\n <h4 className=\"text-lg font-bold text-foreground\">{edu.title}</h4>\n )}\n <div className=\"mb-2 flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n {!hideFields.includes(\"education.institution_name\") && (\n <span className=\"text-base font-semibold text-primary\">\n {edu.institution_name}\n </span>\n )}\n {(!hideFields.includes(\"education.start_date\") ||\n !hideFields.includes(\"education.end_date\")) && (\n <span className=\"mt-1 w-fit rounded-md bg-muted/30 px-2 py-0.5 text-sm font-medium text-muted-foreground sm:mt-0\">\n {!hideFields.includes(\"education.start_date\") && edu.start_date}\n {!hideFields.includes(\"education.end_date\") && (\n <> {edu.end_date ? `- ${edu.end_date}` : \"- Presente\"}</>\n )}\n </span>\n )}\n </div>\n {edu.description && !hideFields.includes(\"education.description\") && (\n <p className=\"mt-3 whitespace-pre-wrap text-base leading-relaxed text-foreground/80\">\n {edu.description}\n </p>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Activities */}\n {activities.length > 0 && !hideSections.includes(\"Actividades y Logros\") && (\n <div className=\"space-y-6\">\n <h3 className=\"flex items-center gap-2 border-b-2 border-primary/20 pb-2 text-2xl font-bold text-primary\">\n <Trophy className=\"h-6 w-6 text-primary\" />\n Actividades y Logros\n </h3>\n <div className=\"space-y-8\">\n {activities.map((act) => (\n <div\n key={act.id}\n className=\"relative pl-6 after:absolute after:bottom-[-24px] after:left-[3px] after:top-4 after:w-[2px] after:bg-border last:after:hidden\"\n >\n <div\n className=\"pdf-line-v absolute left-0 top-2 h-2 w-2 rounded-full bg-primary\"\n style={themeStyle}\n />\n {!hideFields.includes(\"activities.title\") && (\n <h4 className=\"text-lg font-bold text-foreground\">{act.title}</h4>\n )}\n <div className=\"mb-2 flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n {!hideFields.includes(\"activities.institution_name\") && (\n <span className=\"text-base font-semibold text-primary\">\n {act.institution_name}\n </span>\n )}\n {(!hideFields.includes(\"activities.start_date\") ||\n !hideFields.includes(\"activities.end_date\")) && (\n <span className=\"mt-1 w-fit rounded-md bg-muted/30 px-2 py-0.5 text-sm font-medium text-muted-foreground sm:mt-0\">\n {!hideFields.includes(\"activities.start_date\") && act.start_date}\n {!hideFields.includes(\"activities.end_date\") && (\n <> {act.end_date ? `- ${act.end_date}` : \"- Presente\"}</>\n )}\n </span>\n )}\n </div>\n {act.description && !hideFields.includes(\"activities.description\") && (\n <p className=\"mt-3 whitespace-pre-wrap text-base leading-relaxed text-foreground/80\">\n {act.description}\n </p>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Certifications */}\n {certifications.length > 0 && !hideSections.includes(\"Certificaciones\") && (\n <div className=\"space-y-6\">\n <h3 className=\"flex items-center gap-2 border-b-2 border-primary/20 pb-2 text-2xl font-bold text-primary\">\n <Award className=\"h-6 w-6 text-primary\" />\n Certificaciones\n </h3>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n {certifications.map((cert) => (\n <div\n key={cert.id}\n className=\"rounded-lg border border-border/60 bg-card p-4 shadow-sm transition-colors hover:border-primary/30 hover:shadow-md\"\n >\n {!hideFields.includes(\"certifications.title\") && (\n <h4\n className=\"line-clamp-1 text-base font-bold text-foreground\"\n title={cert.title}\n >\n {cert.title}\n </h4>\n )}\n {!hideFields.includes(\"certifications.institution_name\") && (\n <p className=\"mt-1 line-clamp-1 text-sm text-muted-foreground\">\n {cert.institution_name}\n </p>\n )}\n <div className=\"mt-4 flex items-center justify-between\">\n {!hideFields.includes(\"certifications.date_awarded\") && (\n <span className=\"rounded-md bg-muted/50 px-2 py-1 text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n {cert.date_awarded}\n </span>\n )}\n {cert.verified && !hideFields.includes(\"certifications.verified\") && (\n <span\n className=\"pdf-badge rounded-full border px-2.5 py-1 text-xs font-bold transition-colors\"\n style={{\n backgroundColor: theme?.startsWith(\"#\") ? `${theme}15` : undefined,\n color: theme,\n borderColor: theme?.startsWith(\"#\") ? `${theme}30` : theme,\n }}\n >\n Verificado\n </span>\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"AAkEU,SA4Bc,UA3BZ,KADF;AAhEV,SAAS,eAAe,WAAW,QAAQ,aAAa;AAGxD,SAAS,qBAAqB,SAAqC;AACjE,MAAI,CAAC,WAAW,QAAQ,YAAY,MAAM,WAAY,QAAO;AAE7D,QAAM,SAAS,QAAQ,MAAM,sBAAsB;AACnD,MAAI,OAAQ,QAAO,SAAS,OAAO,CAAC,GAAG,EAAE,IAAI,KAAK,SAAS,OAAO,CAAC,GAAG,EAAE;AAExE,QAAM,SAAS,QAAQ,MAAM,oBAAoB;AACjD,MAAI,OAAQ,QAAO,SAAS,OAAO,CAAC,GAAG,EAAE,IAAI,KAAK,SAAS,OAAO,CAAC,GAAG,EAAE;AAExE,QAAM,OAAO,QAAQ,MAAM,OAAO;AAClC,MAAI,KAAM,QAAO,SAAS,KAAK,CAAC,GAAG,EAAE,IAAI;AACzC,SAAO;AACT;AAGA,SAAS,eAA+C,OAAiB;AACvE,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM;AAC/B,UAAM,OAAO,EAAE,UAAU,YAAY;AACrC,UAAM,OAAO,EAAE,UAAU,YAAY;AACrC,UAAM,WAAW,CAAC,EAAE,YAAY,SAAS;AACzC,UAAM,WAAW,CAAC,EAAE,YAAY,SAAS;AACzC,UAAM,OAAO,WAAW,qBAAqB,EAAE,UAAU,IAAI,OAAO,KAAK,qBAAqB,EAAE,QAAQ;AACxG,UAAM,OAAO,WAAW,qBAAqB,EAAE,UAAU,IAAI,OAAO,KAAK,qBAAqB,EAAE,QAAQ;AACxG,WAAO,OAAO;AAAA,EAChB,CAAC;AACH;AAGA,SAAS,6BAA6B,OAAqD;AACzF,SAAO,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM;AAC/B,UAAM,OAAO,qBAAqB,EAAE,YAAY;AAChD,UAAM,OAAO,qBAAqB,EAAE,YAAY;AAChD,WAAO,OAAO;AAAA,EAChB,CAAC;AACH;AASO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA,aAAa,CAAC;AAAA,EACd,eAAe,CAAC;AAClB,GAA6B;AAC3B,QAAM,cAAc,eAAe,KAAK,mBAAmB,CAAC,CAAC;AAC7D,QAAM,YAAY,eAAe,KAAK,aAAa,CAAC,CAAC;AACrD,QAAM,aAAa,eAAe,KAAK,cAAc,CAAC,CAAC;AACvD,QAAM,iBAAiB,6BAA6B,KAAK,kBAAkB,CAAC,CAAC;AAE7E,QAAM,aAAa,QAAQ,EAAE,iBAAiB,MAAM,IAAI;AAExD,SACE,qBAAC,SAAI,WAAU,cAEZ;AAAA,gBAAY,SAAS,KAAK,CAAC,aAAa,SAAS,qBAAqB,KACrE,qBAAC,SAAI,WAAU,aACb;AAAA,2BAAC,QAAG,WAAU,6FACZ;AAAA,4BAAC,aAAU,WAAU,wBAAuB;AAAA,QAAE;AAAA,SAEhD;AAAA,MACA,oBAAC,SAAI,WAAU,aACZ,sBAAY,IAAI,CAAC,QAChB;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UAEV;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO;AAAA;AAAA,YACT;AAAA,YACC,CAAC,WAAW,SAAS,kBAAkB,KACtC,oBAAC,QAAG,WAAU,qCAAqC,cAAI,OAAM;AAAA,YAE/D,qBAAC,SAAI,WAAU,qEACZ;AAAA,eAAC,WAAW,SAAS,6BAA6B,KACjD,oBAAC,UAAK,WAAU,wCACb,cAAI,kBACP;AAAA,eAEA,CAAC,WAAW,SAAS,uBAAuB,KAC5C,CAAC,WAAW,SAAS,qBAAqB,MAC1C,qBAAC,UAAK,WAAU,mGACb;AAAA,iBAAC,WAAW,SAAS,uBAAuB,KAAK,IAAI;AAAA,gBACrD,CAAC,WAAW,SAAS,qBAAqB,KACzC,iCAAE;AAAA;AAAA,kBAAE,IAAI,WAAW,KAAK,IAAI,QAAQ,KAAK;AAAA,mBAAa;AAAA,iBAE1D;AAAA,eAEJ;AAAA,YACC,IAAI,eAAe,CAAC,WAAW,SAAS,wBAAwB,KAC/D,oBAAC,OAAE,WAAU,yEACV,cAAI,aACP;AAAA;AAAA;AAAA,QA7BG,IAAI;AAAA,MA+BX,CACD,GACH;AAAA,OACF;AAAA,IAID,UAAU,SAAS,KAAK,CAAC,aAAa,SAAS,cAAW,KACzD,qBAAC,SAAI,WAAU,aACb;AAAA,2BAAC,QAAG,WAAU,6FACZ;AAAA,4BAAC,iBAAc,WAAU,wBAAuB;AAAA,QAAE;AAAA,SAEpD;AAAA,MACA,oBAAC,SAAI,WAAU,aACZ,oBAAU,IAAI,CAAC,QACd;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UAEV;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO;AAAA;AAAA,YACT;AAAA,YACC,CAAC,WAAW,SAAS,iBAAiB,KACrC,oBAAC,QAAG,WAAU,qCAAqC,cAAI,OAAM;AAAA,YAE/D,qBAAC,SAAI,WAAU,qEACZ;AAAA,eAAC,WAAW,SAAS,4BAA4B,KAChD,oBAAC,UAAK,WAAU,wCACb,cAAI,kBACP;AAAA,eAEA,CAAC,WAAW,SAAS,sBAAsB,KAC3C,CAAC,WAAW,SAAS,oBAAoB,MACzC,qBAAC,UAAK,WAAU,mGACb;AAAA,iBAAC,WAAW,SAAS,sBAAsB,KAAK,IAAI;AAAA,gBACpD,CAAC,WAAW,SAAS,oBAAoB,KACxC,iCAAE;AAAA;AAAA,kBAAE,IAAI,WAAW,KAAK,IAAI,QAAQ,KAAK;AAAA,mBAAa;AAAA,iBAE1D;AAAA,eAEJ;AAAA,YACC,IAAI,eAAe,CAAC,WAAW,SAAS,uBAAuB,KAC9D,oBAAC,OAAE,WAAU,yEACV,cAAI,aACP;AAAA;AAAA;AAAA,QA7BG,IAAI;AAAA,MA+BX,CACD,GACH;AAAA,OACF;AAAA,IAID,WAAW,SAAS,KAAK,CAAC,aAAa,SAAS,sBAAsB,KACrE,qBAAC,SAAI,WAAU,aACb;AAAA,2BAAC,QAAG,WAAU,6FACZ;AAAA,4BAAC,UAAO,WAAU,wBAAuB;AAAA,QAAE;AAAA,SAE7C;AAAA,MACA,oBAAC,SAAI,WAAU,aACZ,qBAAW,IAAI,CAAC,QACf;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UAEV;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO;AAAA;AAAA,YACT;AAAA,YACC,CAAC,WAAW,SAAS,kBAAkB,KACtC,oBAAC,QAAG,WAAU,qCAAqC,cAAI,OAAM;AAAA,YAE/D,qBAAC,SAAI,WAAU,qEACZ;AAAA,eAAC,WAAW,SAAS,6BAA6B,KACjD,oBAAC,UAAK,WAAU,wCACb,cAAI,kBACP;AAAA,eAEA,CAAC,WAAW,SAAS,uBAAuB,KAC5C,CAAC,WAAW,SAAS,qBAAqB,MAC1C,qBAAC,UAAK,WAAU,mGACb;AAAA,iBAAC,WAAW,SAAS,uBAAuB,KAAK,IAAI;AAAA,gBACrD,CAAC,WAAW,SAAS,qBAAqB,KACzC,iCAAE;AAAA;AAAA,kBAAE,IAAI,WAAW,KAAK,IAAI,QAAQ,KAAK;AAAA,mBAAa;AAAA,iBAE1D;AAAA,eAEJ;AAAA,YACC,IAAI,eAAe,CAAC,WAAW,SAAS,wBAAwB,KAC/D,oBAAC,OAAE,WAAU,yEACV,cAAI,aACP;AAAA;AAAA;AAAA,QA7BG,IAAI;AAAA,MA+BX,CACD,GACH;AAAA,OACF;AAAA,IAID,eAAe,SAAS,KAAK,CAAC,aAAa,SAAS,iBAAiB,KACpE,qBAAC,SAAI,WAAU,aACb;AAAA,2BAAC,QAAG,WAAU,6FACZ;AAAA,4BAAC,SAAM,WAAU,wBAAuB;AAAA,QAAE;AAAA,SAE5C;AAAA,MACA,oBAAC,SAAI,WAAU,yCACZ,yBAAe,IAAI,CAAC,SACnB;AAAA,QAAC;AAAA;AAAA,UAEC,WAAU;AAAA,UAET;AAAA,aAAC,WAAW,SAAS,sBAAsB,KAC1C;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,KAAK;AAAA,gBAEX,eAAK;AAAA;AAAA,YACR;AAAA,YAED,CAAC,WAAW,SAAS,iCAAiC,KACrD,oBAAC,OAAE,WAAU,mDACV,eAAK,kBACR;AAAA,YAEF,qBAAC,SAAI,WAAU,0CACZ;AAAA,eAAC,WAAW,SAAS,6BAA6B,KACjD,oBAAC,UAAK,WAAU,yGACb,eAAK,cACR;AAAA,cAED,KAAK,YAAY,CAAC,WAAW,SAAS,yBAAyB,KAC9D;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO;AAAA,oBACL,iBAAiB,OAAO,WAAW,GAAG,IAAI,GAAG,KAAK,OAAO;AAAA,oBACzD,OAAO;AAAA,oBACP,aAAa,OAAO,WAAW,GAAG,IAAI,GAAG,KAAK,OAAO;AAAA,kBACvD;AAAA,kBACD;AAAA;AAAA,cAED;AAAA,eAEJ;AAAA;AAAA;AAAA,QAlCK,KAAK;AAAA,MAmCZ,CACD,GACH;AAAA,OACF;AAAA,KAEJ;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../src/components/domain/resume/resume-preview/sections/experience-education.tsx"],"sourcesContent":["import { CandidateProfile } from \"../../types\";\nimport type { CVExperienceBaseItem, CVCertificationItem } from \"../../types\";\nimport { GraduationCap, Briefcase, Trophy, Award } from \"lucide-react\";\n\n/** Parsea una fecha (MM/YYYY, YYYY-MM o YYYY) a un valor numérico para ordenar (mayor = más reciente) */\nfunction parseDateToSortValue(dateStr: string | undefined): number {\n if (!dateStr || dateStr.toLowerCase() === \"presente\") return 0;\n // MM/YYYY\n const mmYyyy = dateStr.match(/^(\\d{1,2})\\/(\\d{4})$/);\n if (mmYyyy) return parseInt(mmYyyy[2], 10) * 12 + parseInt(mmYyyy[1], 10);\n // YYYY-MM o YYYY-MM-DD\n const yyyyMm = dateStr.match(/^(\\d{4})-(\\d{1,2})/);\n if (yyyyMm) return parseInt(yyyyMm[1], 10) * 12 + parseInt(yyyyMm[2], 10);\n // Solo año\n const year = dateStr.match(/\\d{4}/);\n if (year) return parseInt(year[0], 10) * 12;\n return 0;\n}\n\n/** Ordena descendente por fecha de fin; si no hay end_date (Presente), usa start_date y prioriza como más reciente */\nfunction sortByDateDesc<T extends CVExperienceBaseItem>(items: T[]): T[] {\n return [...items].sort((a, b) => {\n const aEnd = a.end_date?.toLowerCase();\n const bEnd = b.end_date?.toLowerCase();\n const aOngoing = !a.end_date || aEnd === \"presente\";\n const bOngoing = !b.end_date || bEnd === \"presente\";\n const aVal = aOngoing ? parseDateToSortValue(a.start_date) + 9999 * 12 : parseDateToSortValue(a.end_date);\n const bVal = bOngoing ? parseDateToSortValue(b.start_date) + 9999 * 12 : parseDateToSortValue(b.end_date);\n return bVal - aVal;\n });\n}\n\n/** Ordena certificaciones descendente por date_awarded */\nfunction sortCertificationsByDateDesc(items: CVCertificationItem[]): CVCertificationItem[] {\n return [...items].sort((a, b) => {\n const aVal = parseDateToSortValue(a.date_awarded);\n const bVal = parseDateToSortValue(b.date_awarded);\n return bVal - aVal;\n });\n}\n\ninterface ExperienceEducationProps {\n data: CandidateProfile;\n theme?: string;\n hideFields?: string[];\n hideSections?: string[];\n}\n\nexport function ExperienceEducation({\n data,\n theme,\n hideFields = [],\n hideSections = [],\n}: ExperienceEducationProps) {\n const experiences = sortByDateDesc(data.work_experience || []);\n const education = sortByDateDesc(data.education || []);\n const activities = sortByDateDesc(data.activities || []);\n const certifications = sortCertificationsByDateDesc(data.certifications || []);\n\n const themeStyle = theme ? { backgroundColor: theme } : undefined;\n\n return (\n <div className=\"space-y-12\">\n {/* Experience */}\n {experiences.length > 0 && !hideSections.includes(\"Experiencia laboral\") && (\n <div className=\"space-y-6\">\n <h3 className=\"flex items-center gap-2 border-b-2 border-primary/20 pb-2 text-2xl font-bold text-primary\">\n <Briefcase className=\"h-6 w-6 text-primary\" />\n Experiencia Laboral\n </h3>\n <div className=\"space-y-8\">\n {experiences.map((exp) => (\n <div\n key={exp.id}\n className=\"relative pl-6 after:absolute after:bottom-[-24px] after:left-[3px] after:top-4 after:w-[2px] after:bg-border last:after:hidden\"\n >\n <div\n className=\"pdf-line-v absolute left-0 top-2 h-2 w-2 rounded-full bg-primary\"\n style={themeStyle}\n />\n {!hideFields.includes(\"experience.title\") && (\n <h4 className=\"text-lg font-bold text-foreground\">{exp.title}</h4>\n )}\n <div className=\"mb-2 flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n {!hideFields.includes(\"experience.institution_name\") && (\n <span className=\"text-base font-semibold text-primary\">\n {exp.institution_name}\n </span>\n )}\n {(!hideFields.includes(\"experience.start_date\") ||\n !hideFields.includes(\"experience.end_date\")) && (\n <span className=\"mt-1 w-fit rounded-md bg-muted/30 px-2 py-0.5 text-sm font-medium text-muted-foreground sm:mt-0\">\n {[\n !hideFields.includes(\"experience.start_date\") && exp.start_date,\n !hideFields.includes(\"experience.end_date\") &&\n exp.end_date &&\n exp.end_date.toLowerCase() !== \"presente\"\n ? `- ${exp.end_date}`\n : null,\n ]\n .filter(Boolean)\n .join(\" \")}\n </span>\n )}\n </div>\n {exp.description && !hideFields.includes(\"experience.description\") && (\n <p className=\"mt-3 whitespace-pre-wrap text-base leading-relaxed text-foreground/80\">\n {exp.description}\n </p>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Education */}\n {education.length > 0 && !hideSections.includes(\"Educación\") && (\n <div className=\"space-y-6\">\n <h3 className=\"flex items-center gap-2 border-b-2 border-primary/20 pb-2 text-2xl font-bold text-primary\">\n <GraduationCap className=\"h-6 w-6 text-primary\" />\n Educación\n </h3>\n <div className=\"space-y-8\">\n {education.map((edu) => (\n <div\n key={edu.id}\n className=\"relative pl-6 after:absolute after:bottom-[-24px] after:left-[3px] after:top-4 after:w-[2px] after:bg-border last:after:hidden\"\n >\n <div\n className=\"pdf-line-v absolute left-0 top-2 h-2 w-2 rounded-full bg-primary\"\n style={themeStyle}\n />\n {!hideFields.includes(\"education.title\") && (\n <h4 className=\"text-lg font-bold text-foreground\">{edu.title}</h4>\n )}\n <div className=\"mb-2 flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n {!hideFields.includes(\"education.institution_name\") && (\n <span className=\"text-base font-semibold text-primary\">\n {edu.institution_name}\n </span>\n )}\n {(!hideFields.includes(\"education.start_date\") ||\n !hideFields.includes(\"education.end_date\")) && (\n <span className=\"mt-1 w-fit rounded-md bg-muted/30 px-2 py-0.5 text-sm font-medium text-muted-foreground sm:mt-0\">\n {[\n !hideFields.includes(\"education.start_date\") && edu.start_date,\n !hideFields.includes(\"education.end_date\") &&\n edu.end_date &&\n edu.end_date.toLowerCase() !== \"presente\"\n ? `- ${edu.end_date}`\n : null,\n ]\n .filter(Boolean)\n .join(\" \")}\n </span>\n )}\n </div>\n {edu.description && !hideFields.includes(\"education.description\") && (\n <p className=\"mt-3 whitespace-pre-wrap text-base leading-relaxed text-foreground/80\">\n {edu.description}\n </p>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Activities */}\n {activities.length > 0 && !hideSections.includes(\"Actividades y Logros\") && (\n <div className=\"space-y-6\">\n <h3 className=\"flex items-center gap-2 border-b-2 border-primary/20 pb-2 text-2xl font-bold text-primary\">\n <Trophy className=\"h-6 w-6 text-primary\" />\n Actividades y Logros\n </h3>\n <div className=\"space-y-8\">\n {activities.map((act) => (\n <div\n key={act.id}\n className=\"relative pl-6 after:absolute after:bottom-[-24px] after:left-[3px] after:top-4 after:w-[2px] after:bg-border last:after:hidden\"\n >\n <div\n className=\"pdf-line-v absolute left-0 top-2 h-2 w-2 rounded-full bg-primary\"\n style={themeStyle}\n />\n {!hideFields.includes(\"activities.title\") && (\n <h4 className=\"text-lg font-bold text-foreground\">{act.title}</h4>\n )}\n <div className=\"mb-2 flex flex-col sm:flex-row sm:items-center sm:justify-between\">\n {!hideFields.includes(\"activities.institution_name\") && (\n <span className=\"text-base font-semibold text-primary\">\n {act.institution_name}\n </span>\n )}\n {(!hideFields.includes(\"activities.start_date\") ||\n !hideFields.includes(\"activities.end_date\")) && (\n <span className=\"mt-1 w-fit rounded-md bg-muted/30 px-2 py-0.5 text-sm font-medium text-muted-foreground sm:mt-0\">\n {[\n !hideFields.includes(\"activities.start_date\") && act.start_date,\n !hideFields.includes(\"activities.end_date\") &&\n act.end_date &&\n act.end_date.toLowerCase() !== \"presente\"\n ? `- ${act.end_date}`\n : null,\n ]\n .filter(Boolean)\n .join(\" \")}\n </span>\n )}\n </div>\n {act.description && !hideFields.includes(\"activities.description\") && (\n <p className=\"mt-3 whitespace-pre-wrap text-base leading-relaxed text-foreground/80\">\n {act.description}\n </p>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n\n {/* Certifications */}\n {certifications.length > 0 && !hideSections.includes(\"Certificaciones\") && (\n <div className=\"space-y-6\">\n <h3 className=\"flex items-center gap-2 border-b-2 border-primary/20 pb-2 text-2xl font-bold text-primary\">\n <Award className=\"h-6 w-6 text-primary\" />\n Certificaciones\n </h3>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n {certifications.map((cert) => (\n <div\n key={cert.id}\n className=\"rounded-lg border border-border/60 bg-card p-4 shadow-sm transition-colors hover:border-primary/30 hover:shadow-md\"\n >\n {!hideFields.includes(\"certifications.title\") && (\n <h4\n className=\"line-clamp-1 text-base font-bold text-foreground\"\n title={cert.title}\n >\n {cert.title}\n </h4>\n )}\n {!hideFields.includes(\"certifications.institution_name\") && (\n <p className=\"mt-1 line-clamp-1 text-sm text-muted-foreground\">\n {cert.institution_name}\n </p>\n )}\n <div className=\"mt-4 flex items-center justify-between\">\n {!hideFields.includes(\"certifications.date_awarded\") && (\n <span className=\"rounded-md bg-muted/50 px-2 py-1 text-xs font-semibold uppercase tracking-wider text-muted-foreground\">\n {cert.date_awarded}\n </span>\n )}\n {cert.verified && !hideFields.includes(\"certifications.verified\") && (\n <span\n className=\"pdf-badge rounded-full border px-2.5 py-1 text-xs font-bold transition-colors\"\n style={{\n backgroundColor: theme?.startsWith(\"#\") ? `${theme}15` : undefined,\n color: theme,\n borderColor: theme?.startsWith(\"#\") ? `${theme}30` : theme,\n }}\n >\n Verificado\n </span>\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
@@ -24,9 +24,21 @@ module.exports = __toCommonJS(footer_preview_exports);
24
24
  var import_jsx_runtime = require("react/jsx-runtime");
25
25
  var import_logo = require("../../../../ui/logo");
26
26
  function FooterPreview() {
27
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "pdf-footer mt-auto flex hidden items-center justify-center gap-2 border-t border-border/40 pt-10", children: [
28
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_logo.Logo, { className: "size-6" }),
29
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-sm font-medium tracking-tight", children: "Creado con Ginia" })
27
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "pdf-footer mt-auto hidden flex-col items-center justify-center gap-2 border-t border-border/40 pt-10", children: [
28
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
29
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_logo.Logo, { className: "size-6" }),
30
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-sm font-medium tracking-tight", children: "Creado con Ginia" })
31
+ ] }),
32
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
33
+ "a",
34
+ {
35
+ href: "https://www.ginia.io",
36
+ target: "_blank",
37
+ rel: "noopener noreferrer",
38
+ className: "text-xs text-muted-foreground hover:text-primary hover:underline",
39
+ children: "www.ginia.io"
40
+ }
41
+ )
30
42
  ] });
31
43
  }
32
44
  // Annotate the CommonJS export names for ESM import in node:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/components/domain/resume/resume-preview/sections/footer-preview.tsx"],"sourcesContent":["import { Logo } from \"../../../../ui/logo\";\n\nexport function FooterPreview() {\n return (\n <div className=\"pdf-footer mt-auto flex hidden items-center justify-center gap-2 border-t border-border/40 pt-10\">\n <Logo className=\"size-6\" />\n <span className=\"text-sm font-medium tracking-tight\">Creado con Ginia</span>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAII;AAJJ,kBAAqB;AAEd,SAAS,gBAAgB;AAC9B,SACE,6CAAC,SAAI,WAAU,oGACb;AAAA,gDAAC,oBAAK,WAAU,UAAS;AAAA,IACzB,4CAAC,UAAK,WAAU,sCAAqC,8BAAgB;AAAA,KACvE;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../src/components/domain/resume/resume-preview/sections/footer-preview.tsx"],"sourcesContent":["import { Logo } from \"../../../../ui/logo\";\n\nexport function FooterPreview() {\n return (\n <div className=\"pdf-footer mt-auto hidden flex-col items-center justify-center gap-2 border-t border-border/40 pt-10\">\n <div className=\"flex items-center gap-2\">\n <Logo className=\"size-6\" />\n <span className=\"text-sm font-medium tracking-tight\">Creado con Ginia</span>\n </div>\n <a\n href=\"https://www.ginia.io\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-xs text-muted-foreground hover:text-primary hover:underline\"\n >\n www.ginia.io\n </a>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAKM;AALN,kBAAqB;AAEd,SAAS,gBAAgB;AAC9B,SACE,6CAAC,SAAI,WAAU,wGACb;AAAA,iDAAC,SAAI,WAAU,2BACb;AAAA,kDAAC,oBAAK,WAAU,UAAS;AAAA,MACzB,4CAAC,UAAK,WAAU,sCAAqC,8BAAgB;AAAA,OACvE;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,QAAO;AAAA,QACP,KAAI;AAAA,QACJ,WAAU;AAAA,QACX;AAAA;AAAA,IAED;AAAA,KACF;AAEJ;","names":[]}
@@ -1,9 +1,21 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { Logo } from "../../../../ui/logo";
3
3
  function FooterPreview() {
4
- return /* @__PURE__ */ jsxs("div", { className: "pdf-footer mt-auto flex hidden items-center justify-center gap-2 border-t border-border/40 pt-10", children: [
5
- /* @__PURE__ */ jsx(Logo, { className: "size-6" }),
6
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium tracking-tight", children: "Creado con Ginia" })
4
+ return /* @__PURE__ */ jsxs("div", { className: "pdf-footer mt-auto hidden flex-col items-center justify-center gap-2 border-t border-border/40 pt-10", children: [
5
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
6
+ /* @__PURE__ */ jsx(Logo, { className: "size-6" }),
7
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium tracking-tight", children: "Creado con Ginia" })
8
+ ] }),
9
+ /* @__PURE__ */ jsx(
10
+ "a",
11
+ {
12
+ href: "https://www.ginia.io",
13
+ target: "_blank",
14
+ rel: "noopener noreferrer",
15
+ className: "text-xs text-muted-foreground hover:text-primary hover:underline",
16
+ children: "www.ginia.io"
17
+ }
18
+ )
7
19
  ] });
8
20
  }
9
21
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/components/domain/resume/resume-preview/sections/footer-preview.tsx"],"sourcesContent":["import { Logo } from \"../../../../ui/logo\";\n\nexport function FooterPreview() {\n return (\n <div className=\"pdf-footer mt-auto flex hidden items-center justify-center gap-2 border-t border-border/40 pt-10\">\n <Logo className=\"size-6\" />\n <span className=\"text-sm font-medium tracking-tight\">Creado con Ginia</span>\n </div>\n );\n}\n"],"mappings":"AAII,SACE,KADF;AAJJ,SAAS,YAAY;AAEd,SAAS,gBAAgB;AAC9B,SACE,qBAAC,SAAI,WAAU,oGACb;AAAA,wBAAC,QAAK,WAAU,UAAS;AAAA,IACzB,oBAAC,UAAK,WAAU,sCAAqC,8BAAgB;AAAA,KACvE;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../src/components/domain/resume/resume-preview/sections/footer-preview.tsx"],"sourcesContent":["import { Logo } from \"../../../../ui/logo\";\n\nexport function FooterPreview() {\n return (\n <div className=\"pdf-footer mt-auto hidden flex-col items-center justify-center gap-2 border-t border-border/40 pt-10\">\n <div className=\"flex items-center gap-2\">\n <Logo className=\"size-6\" />\n <span className=\"text-sm font-medium tracking-tight\">Creado con Ginia</span>\n </div>\n <a\n href=\"https://www.ginia.io\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-xs text-muted-foreground hover:text-primary hover:underline\"\n >\n www.ginia.io\n </a>\n </div>\n );\n}\n"],"mappings":"AAKM,SACE,KADF;AALN,SAAS,YAAY;AAEd,SAAS,gBAAgB;AAC9B,SACE,qBAAC,SAAI,WAAU,wGACb;AAAA,yBAAC,SAAI,WAAU,2BACb;AAAA,0BAAC,QAAK,WAAU,UAAS;AAAA,MACzB,oBAAC,UAAK,WAAU,sCAAqC,8BAAgB;AAAA,OACvE;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,QAAO;AAAA,QACP,KAAI;AAAA,QACJ,WAAU;AAAA,QACX;AAAA;AAAA,IAED;AAAA,KACF;AAEJ;","names":[]}
@@ -36,8 +36,8 @@ function HeaderPreview({ data, headerSlot, theme, hideFields = [] }) {
36
36
  hideFields.includes("second_last_name") ? null : data.second_last_name
37
37
  ].filter(Boolean).join(" ") || "Sin nombre";
38
38
  const themeStyle = theme ? { backgroundColor: theme } : void 0;
39
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mt-4 flex flex-col items-center gap-8 md:flex-row md:items-start", children: [
40
- !hideFields.includes("photo_url") && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ui.Avatar, { className: "h-32 w-32 flex-shrink-0 rounded-none rounded-tl-none rounded-tr-2xl rounded-bl-2xl rounded-br-none border-4 border-background shadow-lg", children: [
39
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mt-8 flex flex-col items-center gap-6 md:flex-row md:items-start md:gap-6", children: [
40
+ !hideFields.includes("photo_url") && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ui.Avatar, { className: "h-32 w-32 flex-shrink-0 overflow-hidden rounded-none rounded-tl-none rounded-tr-2xl rounded-bl-2xl rounded-br-none shadow-lg", children: [
41
41
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ui.AvatarImage, { src: data.photo_url || void 0, alt: fullName, className: "object-cover" }),
42
42
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
43
43
  import_ui.AvatarFallback,
@@ -48,7 +48,7 @@ function HeaderPreview({ data, headerSlot, theme, hideFields = [] }) {
48
48
  }
49
49
  )
50
50
  ] }),
51
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mt-2 flex w-full flex-1 flex-col justify-between text-center md:mt-4 md:text-left", children: [
51
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "mt-2 flex w-full flex-1 flex-col justify-between text-center md:mt-0 md:text-left", children: [
52
52
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
53
53
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "mb-3 text-3xl font-extrabold tracking-tight text-foreground md:text-4xl", children: fullName }),
54
54
  data.summary && !hideFields.includes("summary") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-md pdf-summary mx-auto max-w-3xl font-medium leading-relaxed text-muted-foreground md:mx-0", children: data.summary })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/components/domain/resume/resume-preview/sections/header-preview.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { CandidateProfile } from \"../../types\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"../../../../ui\";\n\ninterface HeaderPreviewProps {\n data: CandidateProfile;\n headerSlot?: React.ReactNode;\n theme?: string;\n hideFields?: string[];\n}\n\nexport function HeaderPreview({ data, headerSlot, theme, hideFields = [] }: HeaderPreviewProps) {\n const getInitials = () => {\n const f = hideFields.includes(\"first_name\") ? \"\" : data.first_name?.[0] || \"\";\n const l = data.last_name?.[0] || \"\";\n return `${f}${l}`.toUpperCase() || \"CN\";\n };\n\n const fullName =\n [\n hideFields.includes(\"first_name\") ? null : data.first_name,\n hideFields.includes(\"middle_name\") ? null : data.middle_name,\n hideFields.includes(\"last_name\") ? null : data.last_name,\n hideFields.includes(\"second_last_name\") ? null : data.second_last_name,\n ]\n .filter(Boolean)\n .join(\" \") || \"Sin nombre\";\n\n const themeStyle = theme ? { backgroundColor: theme } : undefined;\n\n return (\n <div className=\"mt-4 flex flex-col items-center gap-8 md:flex-row md:items-start\">\n {!hideFields.includes(\"photo_url\") && (\n <Avatar className=\"h-32 w-32 flex-shrink-0 rounded-none rounded-tl-none rounded-tr-2xl rounded-bl-2xl rounded-br-none border-4 border-background shadow-lg\">\n <AvatarImage src={data.photo_url || undefined} alt={fullName} className=\"object-cover\" />\n <AvatarFallback\n className=\"pdf-header-initials rounded-none rounded-tl-none rounded-tr-2xl rounded-bl-2xl rounded-br-none text-3xl font-semibold text-primary-foreground\"\n style={themeStyle || { backgroundColor: \"hsl(var(--primary))\" }}\n >\n {getInitials()}\n </AvatarFallback>\n </Avatar>\n )}\n\n <div className=\"mt-2 flex w-full flex-1 flex-col justify-between text-center md:mt-4 md:text-left\">\n <div>\n <h1 className=\"mb-3 text-3xl font-extrabold tracking-tight text-foreground md:text-4xl\">\n {fullName}\n </h1>\n {data.summary && !hideFields.includes(\"summary\") && (\n <p className=\"text-md pdf-summary mx-auto max-w-3xl font-medium leading-relaxed text-muted-foreground md:mx-0\">\n {data.summary}\n </p>\n )}\n </div>\n\n {headerSlot && (\n <div className=\"pdf-hidden mt-6 flex w-full items-center justify-center md:justify-end\">\n {headerSlot}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiCQ;AA/BR,gBAAoD;AAS7C,SAAS,cAAc,EAAE,MAAM,YAAY,OAAO,aAAa,CAAC,EAAE,GAAuB;AAC9F,QAAM,cAAc,MAAM;AACxB,UAAM,IAAI,WAAW,SAAS,YAAY,IAAI,KAAK,KAAK,aAAa,CAAC,KAAK;AAC3E,UAAM,IAAI,KAAK,YAAY,CAAC,KAAK;AACjC,WAAO,GAAG,CAAC,GAAG,CAAC,GAAG,YAAY,KAAK;AAAA,EACrC;AAEA,QAAM,WACJ;AAAA,IACE,WAAW,SAAS,YAAY,IAAI,OAAO,KAAK;AAAA,IAChD,WAAW,SAAS,aAAa,IAAI,OAAO,KAAK;AAAA,IACjD,WAAW,SAAS,WAAW,IAAI,OAAO,KAAK;AAAA,IAC/C,WAAW,SAAS,kBAAkB,IAAI,OAAO,KAAK;AAAA,EACxD,EACG,OAAO,OAAO,EACd,KAAK,GAAG,KAAK;AAElB,QAAM,aAAa,QAAQ,EAAE,iBAAiB,MAAM,IAAI;AAExD,SACE,6CAAC,SAAI,WAAU,oEACZ;AAAA,KAAC,WAAW,SAAS,WAAW,KAC/B,6CAAC,oBAAO,WAAU,2IAChB;AAAA,kDAAC,yBAAY,KAAK,KAAK,aAAa,QAAW,KAAK,UAAU,WAAU,gBAAe;AAAA,MACvF;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,cAAc,EAAE,iBAAiB,sBAAsB;AAAA,UAE7D,sBAAY;AAAA;AAAA,MACf;AAAA,OACF;AAAA,IAGF,6CAAC,SAAI,WAAU,qFACb;AAAA,mDAAC,SACC;AAAA,oDAAC,QAAG,WAAU,2EACX,oBACH;AAAA,QACC,KAAK,WAAW,CAAC,WAAW,SAAS,SAAS,KAC7C,4CAAC,OAAE,WAAU,mGACV,eAAK,SACR;AAAA,SAEJ;AAAA,MAEC,cACC,4CAAC,SAAI,WAAU,0EACZ,sBACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../src/components/domain/resume/resume-preview/sections/header-preview.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { CandidateProfile } from \"../../types\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"../../../../ui\";\n\ninterface HeaderPreviewProps {\n data: CandidateProfile;\n headerSlot?: React.ReactNode;\n theme?: string;\n hideFields?: string[];\n}\n\nexport function HeaderPreview({ data, headerSlot, theme, hideFields = [] }: HeaderPreviewProps) {\n const getInitials = () => {\n const f = hideFields.includes(\"first_name\") ? \"\" : data.first_name?.[0] || \"\";\n const l = data.last_name?.[0] || \"\";\n return `${f}${l}`.toUpperCase() || \"CN\";\n };\n\n const fullName =\n [\n hideFields.includes(\"first_name\") ? null : data.first_name,\n hideFields.includes(\"middle_name\") ? null : data.middle_name,\n hideFields.includes(\"last_name\") ? null : data.last_name,\n hideFields.includes(\"second_last_name\") ? null : data.second_last_name,\n ]\n .filter(Boolean)\n .join(\" \") || \"Sin nombre\";\n\n const themeStyle = theme ? { backgroundColor: theme } : undefined;\n\n return (\n <div className=\"mt-8 flex flex-col items-center gap-6 md:flex-row md:items-start md:gap-6\">\n {!hideFields.includes(\"photo_url\") && (\n <Avatar className=\"h-32 w-32 flex-shrink-0 overflow-hidden rounded-none rounded-tl-none rounded-tr-2xl rounded-bl-2xl rounded-br-none shadow-lg\">\n <AvatarImage src={data.photo_url || undefined} alt={fullName} className=\"object-cover\" />\n <AvatarFallback\n className=\"pdf-header-initials rounded-none rounded-tl-none rounded-tr-2xl rounded-bl-2xl rounded-br-none text-3xl font-semibold text-primary-foreground\"\n style={themeStyle || { backgroundColor: \"hsl(var(--primary))\" }}\n >\n {getInitials()}\n </AvatarFallback>\n </Avatar>\n )}\n\n <div className=\"mt-2 flex w-full flex-1 flex-col justify-between text-center md:mt-0 md:text-left\">\n <div>\n <h1 className=\"mb-3 text-3xl font-extrabold tracking-tight text-foreground md:text-4xl\">\n {fullName}\n </h1>\n {data.summary && !hideFields.includes(\"summary\") && (\n <p className=\"text-md pdf-summary mx-auto max-w-3xl font-medium leading-relaxed text-muted-foreground md:mx-0\">\n {data.summary}\n </p>\n )}\n </div>\n\n {headerSlot && (\n <div className=\"pdf-hidden mt-6 flex w-full items-center justify-center md:justify-end\">\n {headerSlot}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAiCQ;AA/BR,gBAAoD;AAS7C,SAAS,cAAc,EAAE,MAAM,YAAY,OAAO,aAAa,CAAC,EAAE,GAAuB;AAC9F,QAAM,cAAc,MAAM;AACxB,UAAM,IAAI,WAAW,SAAS,YAAY,IAAI,KAAK,KAAK,aAAa,CAAC,KAAK;AAC3E,UAAM,IAAI,KAAK,YAAY,CAAC,KAAK;AACjC,WAAO,GAAG,CAAC,GAAG,CAAC,GAAG,YAAY,KAAK;AAAA,EACrC;AAEA,QAAM,WACJ;AAAA,IACE,WAAW,SAAS,YAAY,IAAI,OAAO,KAAK;AAAA,IAChD,WAAW,SAAS,aAAa,IAAI,OAAO,KAAK;AAAA,IACjD,WAAW,SAAS,WAAW,IAAI,OAAO,KAAK;AAAA,IAC/C,WAAW,SAAS,kBAAkB,IAAI,OAAO,KAAK;AAAA,EACxD,EACG,OAAO,OAAO,EACd,KAAK,GAAG,KAAK;AAElB,QAAM,aAAa,QAAQ,EAAE,iBAAiB,MAAM,IAAI;AAExD,SACE,6CAAC,SAAI,WAAU,6EACZ;AAAA,KAAC,WAAW,SAAS,WAAW,KAC/B,6CAAC,oBAAO,WAAU,gIAChB;AAAA,kDAAC,yBAAY,KAAK,KAAK,aAAa,QAAW,KAAK,UAAU,WAAU,gBAAe;AAAA,MACvF;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,cAAc,EAAE,iBAAiB,sBAAsB;AAAA,UAE7D,sBAAY;AAAA;AAAA,MACf;AAAA,OACF;AAAA,IAGF,6CAAC,SAAI,WAAU,qFACb;AAAA,mDAAC,SACC;AAAA,oDAAC,QAAG,WAAU,2EACX,oBACH;AAAA,QACC,KAAK,WAAW,CAAC,WAAW,SAAS,SAAS,KAC7C,4CAAC,OAAE,WAAU,mGACV,eAAK,SACR;AAAA,SAEJ;AAAA,MAEC,cACC,4CAAC,SAAI,WAAU,0EACZ,sBACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
@@ -13,8 +13,8 @@ function HeaderPreview({ data, headerSlot, theme, hideFields = [] }) {
13
13
  hideFields.includes("second_last_name") ? null : data.second_last_name
14
14
  ].filter(Boolean).join(" ") || "Sin nombre";
15
15
  const themeStyle = theme ? { backgroundColor: theme } : void 0;
16
- return /* @__PURE__ */ jsxs("div", { className: "mt-4 flex flex-col items-center gap-8 md:flex-row md:items-start", children: [
17
- !hideFields.includes("photo_url") && /* @__PURE__ */ jsxs(Avatar, { className: "h-32 w-32 flex-shrink-0 rounded-none rounded-tl-none rounded-tr-2xl rounded-bl-2xl rounded-br-none border-4 border-background shadow-lg", children: [
16
+ return /* @__PURE__ */ jsxs("div", { className: "mt-8 flex flex-col items-center gap-6 md:flex-row md:items-start md:gap-6", children: [
17
+ !hideFields.includes("photo_url") && /* @__PURE__ */ jsxs(Avatar, { className: "h-32 w-32 flex-shrink-0 overflow-hidden rounded-none rounded-tl-none rounded-tr-2xl rounded-bl-2xl rounded-br-none shadow-lg", children: [
18
18
  /* @__PURE__ */ jsx(AvatarImage, { src: data.photo_url || void 0, alt: fullName, className: "object-cover" }),
19
19
  /* @__PURE__ */ jsx(
20
20
  AvatarFallback,
@@ -25,7 +25,7 @@ function HeaderPreview({ data, headerSlot, theme, hideFields = [] }) {
25
25
  }
26
26
  )
27
27
  ] }),
28
- /* @__PURE__ */ jsxs("div", { className: "mt-2 flex w-full flex-1 flex-col justify-between text-center md:mt-4 md:text-left", children: [
28
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 flex w-full flex-1 flex-col justify-between text-center md:mt-0 md:text-left", children: [
29
29
  /* @__PURE__ */ jsxs("div", { children: [
30
30
  /* @__PURE__ */ jsx("h1", { className: "mb-3 text-3xl font-extrabold tracking-tight text-foreground md:text-4xl", children: fullName }),
31
31
  data.summary && !hideFields.includes("summary") && /* @__PURE__ */ jsx("p", { className: "text-md pdf-summary mx-auto max-w-3xl font-medium leading-relaxed text-muted-foreground md:mx-0", children: data.summary })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/components/domain/resume/resume-preview/sections/header-preview.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { CandidateProfile } from \"../../types\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"../../../../ui\";\n\ninterface HeaderPreviewProps {\n data: CandidateProfile;\n headerSlot?: React.ReactNode;\n theme?: string;\n hideFields?: string[];\n}\n\nexport function HeaderPreview({ data, headerSlot, theme, hideFields = [] }: HeaderPreviewProps) {\n const getInitials = () => {\n const f = hideFields.includes(\"first_name\") ? \"\" : data.first_name?.[0] || \"\";\n const l = data.last_name?.[0] || \"\";\n return `${f}${l}`.toUpperCase() || \"CN\";\n };\n\n const fullName =\n [\n hideFields.includes(\"first_name\") ? null : data.first_name,\n hideFields.includes(\"middle_name\") ? null : data.middle_name,\n hideFields.includes(\"last_name\") ? null : data.last_name,\n hideFields.includes(\"second_last_name\") ? null : data.second_last_name,\n ]\n .filter(Boolean)\n .join(\" \") || \"Sin nombre\";\n\n const themeStyle = theme ? { backgroundColor: theme } : undefined;\n\n return (\n <div className=\"mt-4 flex flex-col items-center gap-8 md:flex-row md:items-start\">\n {!hideFields.includes(\"photo_url\") && (\n <Avatar className=\"h-32 w-32 flex-shrink-0 rounded-none rounded-tl-none rounded-tr-2xl rounded-bl-2xl rounded-br-none border-4 border-background shadow-lg\">\n <AvatarImage src={data.photo_url || undefined} alt={fullName} className=\"object-cover\" />\n <AvatarFallback\n className=\"pdf-header-initials rounded-none rounded-tl-none rounded-tr-2xl rounded-bl-2xl rounded-br-none text-3xl font-semibold text-primary-foreground\"\n style={themeStyle || { backgroundColor: \"hsl(var(--primary))\" }}\n >\n {getInitials()}\n </AvatarFallback>\n </Avatar>\n )}\n\n <div className=\"mt-2 flex w-full flex-1 flex-col justify-between text-center md:mt-4 md:text-left\">\n <div>\n <h1 className=\"mb-3 text-3xl font-extrabold tracking-tight text-foreground md:text-4xl\">\n {fullName}\n </h1>\n {data.summary && !hideFields.includes(\"summary\") && (\n <p className=\"text-md pdf-summary mx-auto max-w-3xl font-medium leading-relaxed text-muted-foreground md:mx-0\">\n {data.summary}\n </p>\n )}\n </div>\n\n {headerSlot && (\n <div className=\"pdf-hidden mt-6 flex w-full items-center justify-center md:justify-end\">\n {headerSlot}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"AAiCQ,SACE,KADF;AA/BR,SAAS,QAAQ,gBAAgB,mBAAmB;AAS7C,SAAS,cAAc,EAAE,MAAM,YAAY,OAAO,aAAa,CAAC,EAAE,GAAuB;AAC9F,QAAM,cAAc,MAAM;AACxB,UAAM,IAAI,WAAW,SAAS,YAAY,IAAI,KAAK,KAAK,aAAa,CAAC,KAAK;AAC3E,UAAM,IAAI,KAAK,YAAY,CAAC,KAAK;AACjC,WAAO,GAAG,CAAC,GAAG,CAAC,GAAG,YAAY,KAAK;AAAA,EACrC;AAEA,QAAM,WACJ;AAAA,IACE,WAAW,SAAS,YAAY,IAAI,OAAO,KAAK;AAAA,IAChD,WAAW,SAAS,aAAa,IAAI,OAAO,KAAK;AAAA,IACjD,WAAW,SAAS,WAAW,IAAI,OAAO,KAAK;AAAA,IAC/C,WAAW,SAAS,kBAAkB,IAAI,OAAO,KAAK;AAAA,EACxD,EACG,OAAO,OAAO,EACd,KAAK,GAAG,KAAK;AAElB,QAAM,aAAa,QAAQ,EAAE,iBAAiB,MAAM,IAAI;AAExD,SACE,qBAAC,SAAI,WAAU,oEACZ;AAAA,KAAC,WAAW,SAAS,WAAW,KAC/B,qBAAC,UAAO,WAAU,2IAChB;AAAA,0BAAC,eAAY,KAAK,KAAK,aAAa,QAAW,KAAK,UAAU,WAAU,gBAAe;AAAA,MACvF;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,cAAc,EAAE,iBAAiB,sBAAsB;AAAA,UAE7D,sBAAY;AAAA;AAAA,MACf;AAAA,OACF;AAAA,IAGF,qBAAC,SAAI,WAAU,qFACb;AAAA,2BAAC,SACC;AAAA,4BAAC,QAAG,WAAU,2EACX,oBACH;AAAA,QACC,KAAK,WAAW,CAAC,WAAW,SAAS,SAAS,KAC7C,oBAAC,OAAE,WAAU,mGACV,eAAK,SACR;AAAA,SAEJ;AAAA,MAEC,cACC,oBAAC,SAAI,WAAU,0EACZ,sBACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../src/components/domain/resume/resume-preview/sections/header-preview.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { CandidateProfile } from \"../../types\";\nimport { Avatar, AvatarFallback, AvatarImage } from \"../../../../ui\";\n\ninterface HeaderPreviewProps {\n data: CandidateProfile;\n headerSlot?: React.ReactNode;\n theme?: string;\n hideFields?: string[];\n}\n\nexport function HeaderPreview({ data, headerSlot, theme, hideFields = [] }: HeaderPreviewProps) {\n const getInitials = () => {\n const f = hideFields.includes(\"first_name\") ? \"\" : data.first_name?.[0] || \"\";\n const l = data.last_name?.[0] || \"\";\n return `${f}${l}`.toUpperCase() || \"CN\";\n };\n\n const fullName =\n [\n hideFields.includes(\"first_name\") ? null : data.first_name,\n hideFields.includes(\"middle_name\") ? null : data.middle_name,\n hideFields.includes(\"last_name\") ? null : data.last_name,\n hideFields.includes(\"second_last_name\") ? null : data.second_last_name,\n ]\n .filter(Boolean)\n .join(\" \") || \"Sin nombre\";\n\n const themeStyle = theme ? { backgroundColor: theme } : undefined;\n\n return (\n <div className=\"mt-8 flex flex-col items-center gap-6 md:flex-row md:items-start md:gap-6\">\n {!hideFields.includes(\"photo_url\") && (\n <Avatar className=\"h-32 w-32 flex-shrink-0 overflow-hidden rounded-none rounded-tl-none rounded-tr-2xl rounded-bl-2xl rounded-br-none shadow-lg\">\n <AvatarImage src={data.photo_url || undefined} alt={fullName} className=\"object-cover\" />\n <AvatarFallback\n className=\"pdf-header-initials rounded-none rounded-tl-none rounded-tr-2xl rounded-bl-2xl rounded-br-none text-3xl font-semibold text-primary-foreground\"\n style={themeStyle || { backgroundColor: \"hsl(var(--primary))\" }}\n >\n {getInitials()}\n </AvatarFallback>\n </Avatar>\n )}\n\n <div className=\"mt-2 flex w-full flex-1 flex-col justify-between text-center md:mt-0 md:text-left\">\n <div>\n <h1 className=\"mb-3 text-3xl font-extrabold tracking-tight text-foreground md:text-4xl\">\n {fullName}\n </h1>\n {data.summary && !hideFields.includes(\"summary\") && (\n <p className=\"text-md pdf-summary mx-auto max-w-3xl font-medium leading-relaxed text-muted-foreground md:mx-0\">\n {data.summary}\n </p>\n )}\n </div>\n\n {headerSlot && (\n <div className=\"pdf-hidden mt-6 flex w-full items-center justify-center md:justify-end\">\n {headerSlot}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"AAiCQ,SACE,KADF;AA/BR,SAAS,QAAQ,gBAAgB,mBAAmB;AAS7C,SAAS,cAAc,EAAE,MAAM,YAAY,OAAO,aAAa,CAAC,EAAE,GAAuB;AAC9F,QAAM,cAAc,MAAM;AACxB,UAAM,IAAI,WAAW,SAAS,YAAY,IAAI,KAAK,KAAK,aAAa,CAAC,KAAK;AAC3E,UAAM,IAAI,KAAK,YAAY,CAAC,KAAK;AACjC,WAAO,GAAG,CAAC,GAAG,CAAC,GAAG,YAAY,KAAK;AAAA,EACrC;AAEA,QAAM,WACJ;AAAA,IACE,WAAW,SAAS,YAAY,IAAI,OAAO,KAAK;AAAA,IAChD,WAAW,SAAS,aAAa,IAAI,OAAO,KAAK;AAAA,IACjD,WAAW,SAAS,WAAW,IAAI,OAAO,KAAK;AAAA,IAC/C,WAAW,SAAS,kBAAkB,IAAI,OAAO,KAAK;AAAA,EACxD,EACG,OAAO,OAAO,EACd,KAAK,GAAG,KAAK;AAElB,QAAM,aAAa,QAAQ,EAAE,iBAAiB,MAAM,IAAI;AAExD,SACE,qBAAC,SAAI,WAAU,6EACZ;AAAA,KAAC,WAAW,SAAS,WAAW,KAC/B,qBAAC,UAAO,WAAU,gIAChB;AAAA,0BAAC,eAAY,KAAK,KAAK,aAAa,QAAW,KAAK,UAAU,WAAU,gBAAe;AAAA,MACvF;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,cAAc,EAAE,iBAAiB,sBAAsB;AAAA,UAE7D,sBAAY;AAAA;AAAA,MACf;AAAA,OACF;AAAA,IAGF,qBAAC,SAAI,WAAU,qFACb;AAAA,2BAAC,SACC;AAAA,4BAAC,QAAG,WAAU,2EACX,oBACH;AAAA,QACC,KAAK,WAAW,CAAC,WAAW,SAAS,SAAS,KAC7C,oBAAC,OAAE,WAAU,mGACV,eAAK,SACR;AAAA,SAEJ;AAAA,MAEC,cACC,oBAAC,SAAI,WAAU,0EACZ,sBACH;AAAA,OAEJ;AAAA,KACF;AAEJ;","names":[]}
@@ -128,7 +128,9 @@ function Resume({
128
128
  hideFields = [],
129
129
  hideSections = [],
130
130
  menuSlot = [],
131
- onSave
131
+ onSave,
132
+ showTopBar = true,
133
+ className
132
134
  }) {
133
135
  const themeStyle = theme ? { "--cv-theme": theme } : void 0;
134
136
  const [draftData, setDraftData] = (0, import_react.useState)(data);
@@ -211,7 +213,7 @@ function Resume({
211
213
  div.style.backgroundPosition = "center";
212
214
  div.style.borderRadius = window.getComputedStyle(img).borderRadius;
213
215
  div.className = img.className;
214
- parent2.style.marginTop = "1rem";
216
+ parent2.style.marginTop = "1.33rem";
215
217
  parent2.replaceChild(div, img);
216
218
  }
217
219
  }
@@ -320,7 +322,7 @@ function Resume({
320
322
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
321
323
  "div",
322
324
  {
323
- className: "relative h-full w-full overflow-y-auto bg-muted/20 px-4 py-8 sm:px-8",
325
+ className: "relative h-full w-full overflow-y-auto bg-muted/20 px-4 py-4 sm:px-8",
324
326
  style: themeStyle,
325
327
  children: [
326
328
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mx-auto h-full w-full max-w-5xl", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -331,7 +333,9 @@ function Resume({
331
333
  headerSlot,
332
334
  theme,
333
335
  hideFields,
334
- hideSections
336
+ hideSections,
337
+ showTopBar,
338
+ className
335
339
  }
336
340
  ) }),
337
341
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "fixed bottom-6 right-6 z-50 flex flex-col gap-3 sm:flex-row", children: [
@@ -390,7 +394,7 @@ function Resume({
390
394
  variant: "ghost",
391
395
  disabled: isDownloading,
392
396
  onClick: handleDownload,
393
- className: "flex items-center gap-2 rounded-full bg-purple-100 px-4 text-purple-100 text-primary shadow-xl",
397
+ className: "flex items-center gap-2 rounded-full bg-purple-200 px-4 text-purple-100 text-primary shadow-xl",
394
398
  children: [
395
399
  isDownloading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Loader2, { className: "h-5 w-5 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Download, { className: "h-5 w-5" }),
396
400
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "hidden font-semibold sm:inline", children: isDownloading ? "Generando..." : "Descargar" })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/domain/resume/resume.tsx"],"sourcesContent":["import { useRef, useState } from \"react\";\nimport html2canvas from \"html2canvas\";\nimport { jsPDF } from \"jspdf\";\nimport { CandidateProfile, ResumeProps, ResumeSavePayload, Action } from \"./types\";\nimport { ResumeEditor } from \"./resume-editor/resume-editor\";\nimport { ResumePreview } from \"./resume-preview/resume-preview\";\nimport { Button } from \"../../ui/button\";\nimport { Download, Edit, Loader2, Save, X } from \"lucide-react\";\nimport { Sheet, SheetTrigger, SheetContent, SheetTitle, SheetClose } from \"../../ui/sheet\";\n\nfunction calculateDiffs(original: CandidateProfile, current: CandidateProfile): ResumeSavePayload {\n // Determine diff for candidate table (academic info etc)\n const candidateData: Partial<CandidateProfile> = {};\n if (original.student_education_institution_id !== current.student_education_institution_id)\n candidateData.student_education_institution_id = current.student_education_institution_id;\n if (original.education_institution_id !== current.education_institution_id)\n candidateData.education_institution_id = current.education_institution_id;\n if (original.program_name !== current.program_name)\n candidateData.program_name = current.program_name;\n if (JSON.stringify(original.preferences) !== JSON.stringify(current.preferences))\n candidateData.preferences = current.preferences;\n if (JSON.stringify(original.advanced) !== JSON.stringify(current.advanced))\n candidateData.advanced = current.advanced;\n\n // Determine diff for user table (personal info)\n const userData: Partial<CandidateProfile> = {};\n const userFields: (keyof CandidateProfile)[] = [\n \"first_name\",\n \"middle_name\",\n \"last_name\",\n \"second_last_name\",\n \"phone_number\",\n \"phone_number_2\",\n \"email\",\n \"city\",\n \"address\",\n \"postal_code\",\n \"birth_date\",\n \"photo_url\",\n ];\n userFields.forEach((field) => {\n if (original[field] !== current[field]) {\n // @ts-expect-error - jspdf types are a bit funky\n userData[field] = current[field];\n }\n });\n\n // Helper for array diffs\n const calculateArrayDiff = (origArray: any[] = [], currArray: any[] = []) => {\n const changes: any[] = [];\n const origMap = new Map(origArray.map((item) => [item.id, item]));\n\n currArray.forEach((currItem) => {\n const origItem = origMap.get(currItem.id);\n if (!origItem) {\n // New item\n changes.push({ action: \"create\" as Action, data: currItem });\n } else if (JSON.stringify(origItem) !== JSON.stringify(currItem)) {\n // Updated item\n changes.push({ action: \"update\" as Action, data: currItem, id: currItem.id });\n }\n });\n\n const currMap = new Map(currArray.map((item) => [item.id, item]));\n origArray.forEach((origItem) => {\n if (!currMap.has(origItem.id)) {\n // Deleted item\n changes.push({ action: \"delete\" as Action, id: origItem.id });\n }\n });\n\n return changes;\n };\n\n const experiencesDiff = [\n ...calculateArrayDiff(original.work_experience, current.work_experience),\n ...calculateArrayDiff(original.education, current.education),\n ...calculateArrayDiff(original.activities, current.activities),\n ];\n\n const hwOrig = original.skills?.hard || [];\n const hwCurr = current.skills?.hard || [];\n const swOrig = original.skills?.soft || [];\n const swCurr = current.skills?.soft || [];\n\n const skillsDiff = [...calculateArrayDiff(hwOrig, hwCurr), ...calculateArrayDiff(swOrig, swCurr)];\n\n return {\n candidate: {\n action: Object.keys(candidateData).length > 0 ? \"update\" : \"none\",\n data: candidateData,\n },\n user: {\n action: Object.keys(userData).length > 0 ? \"update\" : \"none\",\n data: userData,\n },\n curriculum: {\n action: original.summary !== current.summary ? \"update\" : \"none\",\n data: { summary: current.summary },\n },\n experiences: experiencesDiff,\n skills: skillsDiff,\n certifications: calculateArrayDiff(original.certifications, current.certifications),\n };\n}\n\nexport function Resume({\n data,\n editable = false,\n headerSlot,\n withDownload = false,\n theme = \"hsl(var(--secondary))\",\n hideFields = [],\n hideSections = [],\n menuSlot = [],\n onSave,\n}: ResumeProps) {\n const themeStyle = theme ? ({ \"--cv-theme\": theme } as React.CSSProperties) : undefined;\n const [draftData, setDraftData] = useState<CandidateProfile>(data);\n const [isOpen, setIsOpen] = useState(false);\n const [isDownloading, setIsDownloading] = useState(false);\n const previewRef = useRef<HTMLDivElement>(null);\n\n const handleOpenChange = (open: boolean) => {\n if (open) {\n setDraftData(data);\n }\n setIsOpen(open);\n };\n\n const handleSave = () => {\n if (onSave) {\n const payload = calculateDiffs(data, draftData);\n onSave(payload, draftData);\n }\n setIsOpen(false);\n };\n\n const handleDownload = async () => {\n if (!previewRef.current || isDownloading) return;\n setIsDownloading(true);\n\n try {\n const element = previewRef.current;\n const canvas = await html2canvas(element, {\n scale: 2,\n useCORS: true,\n backgroundColor: \"#ffffff\",\n logging: false,\n windowWidth: 1200, // Force desktop layout breakpoint\n onclone: (clonedDoc) => {\n const clonedElement = clonedDoc.getElementById(\"resume-capture-area\");\n if (clonedElement instanceof HTMLElement) {\n clonedElement.style.height = \"auto\";\n clonedElement.style.overflow = \"visible\";\n clonedElement.style.width = \"1200px\";\n\n // Fix Background: html2canvas doesn't support mask-image. Render gradient to canvas\n // and use as background-image for pixel-perfect PDF output.\n const backgroundGradients = clonedElement.querySelectorAll(\"[data-pdf-background-gradient]\");\n const w = 1200;\n const h = 160;\n const canvas = clonedDoc.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n const hGrad = ctx.createLinearGradient(0, 0, w, 0);\n hGrad.addColorStop(0, \"#ffffff\");\n hGrad.addColorStop(0.5, \"#f3e8ff\");\n hGrad.addColorStop(1, \"#bfdbfe\");\n ctx.fillStyle = hGrad;\n ctx.fillRect(0, 0, w, h);\n ctx.globalCompositeOperation = \"destination-in\";\n const vGrad = ctx.createLinearGradient(0, 0, 0, h);\n vGrad.addColorStop(0, \"rgba(0,0,0,1)\");\n vGrad.addColorStop(1, \"rgba(0,0,0,0)\");\n ctx.fillStyle = vGrad;\n ctx.fillRect(0, 0, w, h);\n ctx.globalCompositeOperation = \"source-over\";\n }\n const dataUrl = canvas.toDataURL(\"image/png\");\n backgroundGradients.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.maskImage = \"none\";\n el.style.background = \"none\";\n el.style.backgroundImage = `url(${dataUrl})`;\n el.style.backgroundSize = \"100% 100%\";\n el.style.backgroundPosition = \"0 0\";\n }\n });\n\n // Fix for images with object-fit: cover not being respected by html2canvas\n const objectCoverImages = clonedElement.querySelectorAll(\"img.object-cover\");\n objectCoverImages.forEach((img) => {\n if (img instanceof HTMLImageElement) {\n const parent = img.parentElement;\n if (parent) {\n // Replace img with a div that has background-image: cover\n const div = clonedDoc.createElement(\"div\");\n div.style.width = \"100%\";\n div.style.height = \"100%\";\n div.style.backgroundImage = `url(${img.src})`;\n div.style.backgroundSize = \"cover\";\n div.style.backgroundPosition = \"center\";\n div.style.borderRadius = window.getComputedStyle(img).borderRadius;\n div.className = img.className;\n parent.style.marginTop = \"1rem\";\n parent.replaceChild(div, img);\n }\n }\n });\n\n // Hide elements marked as hidden for PDF\n const hiddenElements = clonedElement.querySelectorAll(\".pdf-hidden\");\n hiddenElements.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.display = \"none\";\n }\n });\n\n // Fix SVG vertical alignment for html2canvas\n // html2canvas doesn't properly handle flex align-items with SVGs\n const svgs = clonedElement.querySelectorAll(\"svg\");\n svgs.forEach((svg) => {\n svg.style.display = \"inline-block\";\n svg.style.verticalAlign = \"middle\";\n svg.style.flexShrink = \"0\";\n svg.style.marginRight = \"0.4rem\";\n svg.style.marginBottom = \"-1.2rem\";\n });\n\n // Fix line-clamp which causes text vertical cut-offs in html2canvas\n const clampElements = clonedElement.querySelectorAll(\n \".line-clamp-1, .line-clamp-2, .line-clamp-3\",\n );\n clampElements.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.display = \"block\";\n el.style.webkitLineClamp = \"unset\";\n el.style.webkitBoxOrient = \"unset\";\n el.style.overflow = \"visible\";\n el.style.whiteSpace = \"normal\";\n el.style.lineHeight = \"1.5\";\n }\n });\n\n // Replace generic HTML elements like custom badges with simple spans\n // because html2canvas struggles with flexbox and strict borders inside round pills\n const badges = clonedElement.querySelectorAll(\".pdf-badge\");\n badges.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.paddingTop = \"-10px\";\n el.style.display = \"block\";\n el.style.paddingTop = \"0px\";\n el.style.paddingBottom = \"0.8rem\";\n }\n });\n\n // Fix headers with bottom borders losing padding/margin\n const headersWithBorders = clonedElement.querySelectorAll(\"h1, h2, h3, h4\");\n headersWithBorders.forEach((el) => {\n if (el instanceof HTMLElement) {\n const hasBorder =\n el.className.includes(\"border-b\") || el.style.borderBottomWidth !== \"\";\n if (hasBorder) {\n el.style.paddingBottom = \"1.2rem\";\n }\n }\n });\n\n // Add margin top to pdf-line-v elements\n const verticalLines = clonedElement.querySelectorAll(\".pdf-line-v\");\n verticalLines.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.marginTop = \"0.5rem\";\n el.style.zIndex = \"5\";\n }\n });\n\n // Add margin bottom to initials in header for better alignment in PDF\n const headerInitials = clonedElement.querySelectorAll(\".pdf-header-initials\");\n headerInitials.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.paddingBottom = \"2rem\";\n }\n });\n\n // Add styles to summary for PDF\n const summaries = clonedElement.querySelectorAll(\".pdf-summary\");\n summaries.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.width = \"100%\";\n el.style.maxWidth = \"100%\";\n el.style.marginTop = \"1.5rem\";\n }\n });\n\n // Show footer in PDF and force grayscale for the logo\n const pdfFooters = clonedElement.querySelectorAll(\".pdf-footer\");\n pdfFooters.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.display = \"flex\";\n }\n });\n\n // Also make sure parent containers don't restrict height\n let parent = clonedElement.parentElement;\n while (parent) {\n parent.style.height = \"auto\";\n parent.style.overflow = \"visible\";\n parent = parent.parentElement;\n }\n }\n },\n });\n\n const imgData = canvas.toDataURL(\"image/jpeg\", 1);\n const imgWidthPx = canvas.width;\n const imgHeightPx = canvas.height;\n\n // Convert px to mm (at 96 DPI base * scale factor)\n const pxToMm = 25.4 / (96 * 2);\n const pdfWidth = imgWidthPx * pxToMm;\n const pdfHeight = imgHeightPx * pxToMm;\n\n const pdf = new jsPDF({\n orientation: pdfWidth > pdfHeight ? \"landscape\" : \"portrait\",\n unit: \"mm\",\n format: [pdfWidth, pdfHeight],\n });\n\n pdf.addImage(imgData, \"JPEG\", 0, 0, pdfWidth, pdfHeight, undefined, \"FAST\");\n\n const fileName = `CV_${data.first_name}_${data.last_name}`.replace(/\\s+/g, \"_\");\n pdf.save(`${fileName}.pdf`);\n } catch (error) {\n console.error(\"Error generating PDF:\", error);\n } finally {\n setIsDownloading(false);\n }\n };\n\n return (\n <div\n className=\"relative h-full w-full overflow-y-auto bg-muted/20 px-4 py-8 sm:px-8\"\n style={themeStyle}\n >\n {/* Preview Panel - Takes full width, centered like a document */}\n <div className=\"mx-auto h-full w-full max-w-5xl\">\n <ResumePreview\n ref={previewRef}\n data={draftData}\n headerSlot={headerSlot}\n theme={theme}\n hideFields={hideFields}\n hideSections={hideSections}\n />\n </div>\n\n {/* Floating Action Buttons */}\n <div className=\"fixed bottom-6 right-6 z-50 flex flex-col gap-3 sm:flex-row\">\n {editable && (\n <Sheet open={isOpen} onOpenChange={handleOpenChange}>\n <SheetTrigger asChild>\n <Button\n size=\"lg\"\n className=\"flex items-center gap-2 rounded-full bg-primary px-4 text-primary-foreground shadow-xl hover:bg-primary/90\"\n >\n <Edit className=\"h-5 w-5\" />\n <span className=\"hidden font-semibold sm:inline\">Editar</span>\n </Button>\n </SheetTrigger>\n {/* Drawer opens from the right side, taking good width */}\n <SheetContent\n side=\"right\"\n showCloseButton={false}\n className=\"flex w-full flex-col overflow-hidden bg-card p-0 sm:max-w-md md:max-w-2xl\"\n >\n {/* Header */}\n <div className=\"flex items-center justify-between p-6 pb-2\">\n <SheetTitle className=\"text-2xl font-bold text-foreground\">Editar</SheetTitle>\n <SheetClose className=\"rounded-full p-2 opacity-70 transition-colors hover:bg-muted hover:opacity-100\">\n <X className=\"h-6 w-6 text-foreground\" />\n <span className=\"sr-only\">Cerrar</span>\n </SheetClose>\n </div>\n\n {/* Scrollable editor content */}\n <div className=\"flex-1 overflow-y-auto px-6 pb-6 pt-2\">\n <ResumeEditor\n data={draftData}\n onChange={setDraftData}\n theme={theme}\n hideFields={hideFields}\n hideSections={hideSections}\n menuSlot={menuSlot}\n />\n </div>\n\n {/* Sticky save footer */}\n {onSave && (\n <div className=\"flex justify-end gap-3 p-4\">\n <SheetClose asChild>\n <Button variant=\"outline\">Cancelar</Button>\n </SheetClose>\n <Button onClick={handleSave} className=\"gap-2\">\n <Save className=\"h-4 w-4\" />\n Guardar\n </Button>\n </div>\n )}\n </SheetContent>\n </Sheet>\n )}\n\n {withDownload && (\n <Button\n size=\"lg\"\n variant=\"ghost\"\n disabled={isDownloading}\n onClick={handleDownload}\n className=\"flex items-center gap-2 rounded-full bg-purple-100 px-4 text-purple-100 text-primary shadow-xl\"\n >\n {isDownloading ? (\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n ) : (\n <Download className=\"h-5 w-5\" />\n )}\n <span className=\"hidden font-semibold sm:inline\">\n {isDownloading ? \"Generando...\" : \"Descargar\"}\n </span>\n </Button>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["html2canvas","canvas","parent"]}
1
+ {"version":3,"sources":["../../../../src/components/domain/resume/resume.tsx"],"sourcesContent":["import { useRef, useState } from \"react\";\nimport html2canvas from \"html2canvas\";\nimport { jsPDF } from \"jspdf\";\nimport { CandidateProfile, ResumeProps, ResumeSavePayload, Action } from \"./types\";\nimport { ResumeEditor } from \"./resume-editor/resume-editor\";\nimport { ResumePreview } from \"./resume-preview/resume-preview\";\nimport { Button } from \"../../ui/button\";\nimport { Download, Edit, Loader2, Save, X } from \"lucide-react\";\nimport { Sheet, SheetTrigger, SheetContent, SheetTitle, SheetClose } from \"../../ui/sheet\";\n\nfunction calculateDiffs(original: CandidateProfile, current: CandidateProfile): ResumeSavePayload {\n // Determine diff for candidate table (academic info etc)\n const candidateData: Partial<CandidateProfile> = {};\n if (original.student_education_institution_id !== current.student_education_institution_id)\n candidateData.student_education_institution_id = current.student_education_institution_id;\n if (original.education_institution_id !== current.education_institution_id)\n candidateData.education_institution_id = current.education_institution_id;\n if (original.program_name !== current.program_name)\n candidateData.program_name = current.program_name;\n if (JSON.stringify(original.preferences) !== JSON.stringify(current.preferences))\n candidateData.preferences = current.preferences;\n if (JSON.stringify(original.advanced) !== JSON.stringify(current.advanced))\n candidateData.advanced = current.advanced;\n\n // Determine diff for user table (personal info)\n const userData: Partial<CandidateProfile> = {};\n const userFields: (keyof CandidateProfile)[] = [\n \"first_name\",\n \"middle_name\",\n \"last_name\",\n \"second_last_name\",\n \"phone_number\",\n \"phone_number_2\",\n \"email\",\n \"city\",\n \"address\",\n \"postal_code\",\n \"birth_date\",\n \"photo_url\",\n ];\n userFields.forEach((field) => {\n if (original[field] !== current[field]) {\n // @ts-expect-error - jspdf types are a bit funky\n userData[field] = current[field];\n }\n });\n\n // Helper for array diffs\n const calculateArrayDiff = (origArray: any[] = [], currArray: any[] = []) => {\n const changes: any[] = [];\n const origMap = new Map(origArray.map((item) => [item.id, item]));\n\n currArray.forEach((currItem) => {\n const origItem = origMap.get(currItem.id);\n if (!origItem) {\n // New item\n changes.push({ action: \"create\" as Action, data: currItem });\n } else if (JSON.stringify(origItem) !== JSON.stringify(currItem)) {\n // Updated item\n changes.push({ action: \"update\" as Action, data: currItem, id: currItem.id });\n }\n });\n\n const currMap = new Map(currArray.map((item) => [item.id, item]));\n origArray.forEach((origItem) => {\n if (!currMap.has(origItem.id)) {\n // Deleted item\n changes.push({ action: \"delete\" as Action, id: origItem.id });\n }\n });\n\n return changes;\n };\n\n const experiencesDiff = [\n ...calculateArrayDiff(original.work_experience, current.work_experience),\n ...calculateArrayDiff(original.education, current.education),\n ...calculateArrayDiff(original.activities, current.activities),\n ];\n\n const hwOrig = original.skills?.hard || [];\n const hwCurr = current.skills?.hard || [];\n const swOrig = original.skills?.soft || [];\n const swCurr = current.skills?.soft || [];\n\n const skillsDiff = [...calculateArrayDiff(hwOrig, hwCurr), ...calculateArrayDiff(swOrig, swCurr)];\n\n return {\n candidate: {\n action: Object.keys(candidateData).length > 0 ? \"update\" : \"none\",\n data: candidateData,\n },\n user: {\n action: Object.keys(userData).length > 0 ? \"update\" : \"none\",\n data: userData,\n },\n curriculum: {\n action: original.summary !== current.summary ? \"update\" : \"none\",\n data: { summary: current.summary },\n },\n experiences: experiencesDiff,\n skills: skillsDiff,\n certifications: calculateArrayDiff(original.certifications, current.certifications),\n };\n}\n\nexport function Resume({\n data,\n editable = false,\n headerSlot,\n withDownload = false,\n theme = \"hsl(var(--secondary))\",\n hideFields = [],\n hideSections = [],\n menuSlot = [],\n onSave,\n showTopBar = true,\n className,\n}: ResumeProps) {\n const themeStyle = theme ? ({ \"--cv-theme\": theme } as React.CSSProperties) : undefined;\n const [draftData, setDraftData] = useState<CandidateProfile>(data);\n const [isOpen, setIsOpen] = useState(false);\n const [isDownloading, setIsDownloading] = useState(false);\n const previewRef = useRef<HTMLDivElement>(null);\n\n const handleOpenChange = (open: boolean) => {\n if (open) {\n setDraftData(data);\n }\n setIsOpen(open);\n };\n\n const handleSave = () => {\n if (onSave) {\n const payload = calculateDiffs(data, draftData);\n onSave(payload, draftData);\n }\n setIsOpen(false);\n };\n\n const handleDownload = async () => {\n if (!previewRef.current || isDownloading) return;\n setIsDownloading(true);\n\n try {\n const element = previewRef.current;\n const canvas = await html2canvas(element, {\n scale: 2,\n useCORS: true,\n backgroundColor: \"#ffffff\",\n logging: false,\n windowWidth: 1200, // Force desktop layout breakpoint\n onclone: (clonedDoc) => {\n const clonedElement = clonedDoc.getElementById(\"resume-capture-area\");\n if (clonedElement instanceof HTMLElement) {\n clonedElement.style.height = \"auto\";\n clonedElement.style.overflow = \"visible\";\n clonedElement.style.width = \"1200px\";\n\n // Fix Background: html2canvas doesn't support mask-image. Render gradient to canvas\n // and use as background-image for pixel-perfect PDF output.\n const backgroundGradients = clonedElement.querySelectorAll(\"[data-pdf-background-gradient]\");\n const w = 1200;\n const h = 160;\n const canvas = clonedDoc.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n const hGrad = ctx.createLinearGradient(0, 0, w, 0);\n hGrad.addColorStop(0, \"#ffffff\");\n hGrad.addColorStop(0.5, \"#f3e8ff\");\n hGrad.addColorStop(1, \"#bfdbfe\");\n ctx.fillStyle = hGrad;\n ctx.fillRect(0, 0, w, h);\n ctx.globalCompositeOperation = \"destination-in\";\n const vGrad = ctx.createLinearGradient(0, 0, 0, h);\n vGrad.addColorStop(0, \"rgba(0,0,0,1)\");\n vGrad.addColorStop(1, \"rgba(0,0,0,0)\");\n ctx.fillStyle = vGrad;\n ctx.fillRect(0, 0, w, h);\n ctx.globalCompositeOperation = \"source-over\";\n }\n const dataUrl = canvas.toDataURL(\"image/png\");\n backgroundGradients.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.maskImage = \"none\";\n el.style.background = \"none\";\n el.style.backgroundImage = `url(${dataUrl})`;\n el.style.backgroundSize = \"100% 100%\";\n el.style.backgroundPosition = \"0 0\";\n }\n });\n\n // Fix for images with object-fit: cover not being respected by html2canvas\n const objectCoverImages = clonedElement.querySelectorAll(\"img.object-cover\");\n objectCoverImages.forEach((img) => {\n if (img instanceof HTMLImageElement) {\n const parent = img.parentElement;\n if (parent) {\n // Replace img with a div that has background-image: cover\n const div = clonedDoc.createElement(\"div\");\n div.style.width = \"100%\";\n div.style.height = \"100%\";\n div.style.backgroundImage = `url(${img.src})`;\n div.style.backgroundSize = \"cover\";\n div.style.backgroundPosition = \"center\";\n div.style.borderRadius = window.getComputedStyle(img).borderRadius;\n div.className = img.className;\n parent.style.marginTop = \"1.33rem\";\n parent.replaceChild(div, img);\n }\n }\n });\n\n // Hide elements marked as hidden for PDF\n const hiddenElements = clonedElement.querySelectorAll(\".pdf-hidden\");\n hiddenElements.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.display = \"none\";\n }\n });\n\n // Fix SVG vertical alignment for html2canvas\n // html2canvas doesn't properly handle flex align-items with SVGs\n const svgs = clonedElement.querySelectorAll(\"svg\");\n svgs.forEach((svg) => {\n svg.style.display = \"inline-block\";\n svg.style.verticalAlign = \"middle\";\n svg.style.flexShrink = \"0\";\n svg.style.marginRight = \"0.4rem\";\n svg.style.marginBottom = \"-1.2rem\";\n });\n\n // Fix line-clamp which causes text vertical cut-offs in html2canvas\n const clampElements = clonedElement.querySelectorAll(\n \".line-clamp-1, .line-clamp-2, .line-clamp-3\",\n );\n clampElements.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.display = \"block\";\n el.style.webkitLineClamp = \"unset\";\n el.style.webkitBoxOrient = \"unset\";\n el.style.overflow = \"visible\";\n el.style.whiteSpace = \"normal\";\n el.style.lineHeight = \"1.5\";\n }\n });\n\n // Replace generic HTML elements like custom badges with simple spans\n // because html2canvas struggles with flexbox and strict borders inside round pills\n const badges = clonedElement.querySelectorAll(\".pdf-badge\");\n badges.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.paddingTop = \"-10px\";\n el.style.display = \"block\";\n el.style.paddingTop = \"0px\";\n el.style.paddingBottom = \"0.8rem\";\n }\n });\n\n // Fix headers with bottom borders losing padding/margin\n const headersWithBorders = clonedElement.querySelectorAll(\"h1, h2, h3, h4\");\n headersWithBorders.forEach((el) => {\n if (el instanceof HTMLElement) {\n const hasBorder =\n el.className.includes(\"border-b\") || el.style.borderBottomWidth !== \"\";\n if (hasBorder) {\n el.style.paddingBottom = \"1.2rem\";\n }\n }\n });\n\n // Add margin top to pdf-line-v elements\n const verticalLines = clonedElement.querySelectorAll(\".pdf-line-v\");\n verticalLines.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.marginTop = \"0.5rem\";\n el.style.zIndex = \"5\";\n }\n });\n\n // Add margin bottom to initials in header for better alignment in PDF\n const headerInitials = clonedElement.querySelectorAll(\".pdf-header-initials\");\n headerInitials.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.paddingBottom = \"2rem\";\n }\n });\n\n // Add styles to summary for PDF\n const summaries = clonedElement.querySelectorAll(\".pdf-summary\");\n summaries.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.width = \"100%\";\n el.style.maxWidth = \"100%\";\n el.style.marginTop = \"1.5rem\";\n }\n });\n\n // Show footer in PDF and force grayscale for the logo\n const pdfFooters = clonedElement.querySelectorAll(\".pdf-footer\");\n pdfFooters.forEach((el) => {\n if (el instanceof HTMLElement) {\n el.style.display = \"flex\";\n }\n });\n\n // Also make sure parent containers don't restrict height\n let parent = clonedElement.parentElement;\n while (parent) {\n parent.style.height = \"auto\";\n parent.style.overflow = \"visible\";\n parent = parent.parentElement;\n }\n }\n },\n });\n\n const imgData = canvas.toDataURL(\"image/jpeg\", 1);\n const imgWidthPx = canvas.width;\n const imgHeightPx = canvas.height;\n\n // Convert px to mm (at 96 DPI base * scale factor)\n const pxToMm = 25.4 / (96 * 2);\n const pdfWidth = imgWidthPx * pxToMm;\n const pdfHeight = imgHeightPx * pxToMm;\n\n const pdf = new jsPDF({\n orientation: pdfWidth > pdfHeight ? \"landscape\" : \"portrait\",\n unit: \"mm\",\n format: [pdfWidth, pdfHeight],\n });\n\n pdf.addImage(imgData, \"JPEG\", 0, 0, pdfWidth, pdfHeight, undefined, \"FAST\");\n\n const fileName = `CV_${data.first_name}_${data.last_name}`.replace(/\\s+/g, \"_\");\n pdf.save(`${fileName}.pdf`);\n } catch (error) {\n console.error(\"Error generating PDF:\", error);\n } finally {\n setIsDownloading(false);\n }\n };\n\n return (\n <div\n className=\"relative h-full w-full overflow-y-auto bg-muted/20 px-4 py-4 sm:px-8\"\n style={themeStyle}\n >\n {/* Preview Panel - Takes full width, centered like a document */}\n <div className=\"mx-auto h-full w-full max-w-5xl\">\n <ResumePreview\n ref={previewRef}\n data={draftData}\n headerSlot={headerSlot}\n theme={theme}\n hideFields={hideFields}\n hideSections={hideSections}\n showTopBar={showTopBar}\n className={className}\n />\n </div>\n\n {/* Floating Action Buttons */}\n <div className=\"fixed bottom-6 right-6 z-50 flex flex-col gap-3 sm:flex-row\">\n {editable && (\n <Sheet open={isOpen} onOpenChange={handleOpenChange}>\n <SheetTrigger asChild>\n <Button\n size=\"lg\"\n className=\"flex items-center gap-2 rounded-full bg-primary px-4 text-primary-foreground shadow-xl hover:bg-primary/90\"\n >\n <Edit className=\"h-5 w-5\" />\n <span className=\"hidden font-semibold sm:inline\">Editar</span>\n </Button>\n </SheetTrigger>\n {/* Drawer opens from the right side, taking good width */}\n <SheetContent\n side=\"right\"\n showCloseButton={false}\n className=\"flex w-full flex-col overflow-hidden bg-card p-0 sm:max-w-md md:max-w-2xl\"\n >\n {/* Header */}\n <div className=\"flex items-center justify-between p-6 pb-2\">\n <SheetTitle className=\"text-2xl font-bold text-foreground\">Editar</SheetTitle>\n <SheetClose className=\"rounded-full p-2 opacity-70 transition-colors hover:bg-muted hover:opacity-100\">\n <X className=\"h-6 w-6 text-foreground\" />\n <span className=\"sr-only\">Cerrar</span>\n </SheetClose>\n </div>\n\n {/* Scrollable editor content */}\n <div className=\"flex-1 overflow-y-auto px-6 pb-6 pt-2\">\n <ResumeEditor\n data={draftData}\n onChange={setDraftData}\n theme={theme}\n hideFields={hideFields}\n hideSections={hideSections}\n menuSlot={menuSlot}\n />\n </div>\n\n {/* Sticky save footer */}\n {onSave && (\n <div className=\"flex justify-end gap-3 p-4\">\n <SheetClose asChild>\n <Button variant=\"outline\">Cancelar</Button>\n </SheetClose>\n <Button onClick={handleSave} className=\"gap-2\">\n <Save className=\"h-4 w-4\" />\n Guardar\n </Button>\n </div>\n )}\n </SheetContent>\n </Sheet>\n )}\n\n {withDownload && (\n <Button\n size=\"lg\"\n variant=\"ghost\"\n disabled={isDownloading}\n onClick={handleDownload}\n className=\"flex items-center gap-2 rounded-full bg-purple-200 px-4 text-purple-100 text-primary shadow-xl\"\n >\n {isDownloading ? (\n <Loader2 className=\"h-5 w-5 animate-spin\" />\n ) : (\n <Download className=\"h-5 w-5\" />\n )}\n <span className=\"hidden font-semibold sm:inline\">\n {isDownloading ? \"Generando...\" : \"Descargar\"}\n </span>\n </Button>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["html2canvas","canvas","parent"]}
@@ -2,6 +2,6 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ResumeProps } from './types.cjs';
3
3
  import 'react';
4
4
 
5
- declare function Resume({ data, editable, headerSlot, withDownload, theme, hideFields, hideSections, menuSlot, onSave, }: ResumeProps): react_jsx_runtime.JSX.Element;
5
+ declare function Resume({ data, editable, headerSlot, withDownload, theme, hideFields, hideSections, menuSlot, onSave, showTopBar, className, }: ResumeProps): react_jsx_runtime.JSX.Element;
6
6
 
7
7
  export { Resume };
@@ -2,6 +2,6 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ResumeProps } from './types.js';
3
3
  import 'react';
4
4
 
5
- declare function Resume({ data, editable, headerSlot, withDownload, theme, hideFields, hideSections, menuSlot, onSave, }: ResumeProps): react_jsx_runtime.JSX.Element;
5
+ declare function Resume({ data, editable, headerSlot, withDownload, theme, hideFields, hideSections, menuSlot, onSave, showTopBar, className, }: ResumeProps): react_jsx_runtime.JSX.Element;
6
6
 
7
7
  export { Resume };
@@ -95,7 +95,9 @@ function Resume({
95
95
  hideFields = [],
96
96
  hideSections = [],
97
97
  menuSlot = [],
98
- onSave
98
+ onSave,
99
+ showTopBar = true,
100
+ className
99
101
  }) {
100
102
  const themeStyle = theme ? { "--cv-theme": theme } : void 0;
101
103
  const [draftData, setDraftData] = useState(data);
@@ -178,7 +180,7 @@ function Resume({
178
180
  div.style.backgroundPosition = "center";
179
181
  div.style.borderRadius = window.getComputedStyle(img).borderRadius;
180
182
  div.className = img.className;
181
- parent2.style.marginTop = "1rem";
183
+ parent2.style.marginTop = "1.33rem";
182
184
  parent2.replaceChild(div, img);
183
185
  }
184
186
  }
@@ -287,7 +289,7 @@ function Resume({
287
289
  return /* @__PURE__ */ jsxs(
288
290
  "div",
289
291
  {
290
- className: "relative h-full w-full overflow-y-auto bg-muted/20 px-4 py-8 sm:px-8",
292
+ className: "relative h-full w-full overflow-y-auto bg-muted/20 px-4 py-4 sm:px-8",
291
293
  style: themeStyle,
292
294
  children: [
293
295
  /* @__PURE__ */ jsx("div", { className: "mx-auto h-full w-full max-w-5xl", children: /* @__PURE__ */ jsx(
@@ -298,7 +300,9 @@ function Resume({
298
300
  headerSlot,
299
301
  theme,
300
302
  hideFields,
301
- hideSections
303
+ hideSections,
304
+ showTopBar,
305
+ className
302
306
  }
303
307
  ) }),
304
308
  /* @__PURE__ */ jsxs("div", { className: "fixed bottom-6 right-6 z-50 flex flex-col gap-3 sm:flex-row", children: [
@@ -357,7 +361,7 @@ function Resume({
357
361
  variant: "ghost",
358
362
  disabled: isDownloading,
359
363
  onClick: handleDownload,
360
- className: "flex items-center gap-2 rounded-full bg-purple-100 px-4 text-purple-100 text-primary shadow-xl",
364
+ className: "flex items-center gap-2 rounded-full bg-purple-200 px-4 text-purple-100 text-primary shadow-xl",
361
365
  children: [
362
366
  isDownloading ? /* @__PURE__ */ jsx(Loader2, { className: "h-5 w-5 animate-spin" }) : /* @__PURE__ */ jsx(Download, { className: "h-5 w-5" }),
363
367
  /* @__PURE__ */ jsx("span", { className: "hidden font-semibold sm:inline", children: isDownloading ? "Generando..." : "Descargar" })