@heroelc/fsociety 0.0.11 → 0.0.13

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.
@@ -1 +1 @@
1
- {"version":3,"file":"heroelc-fsociety.mjs","sources":["../../../projects/fsociety/src/lib/fsociety.service.ts","../../../projects/fsociety/src/lib/fsociety.component.ts","../../../projects/fsociety/src/lib/button/button.component.ts","../../../projects/fsociety/src/lib/button/button.component.html","../../../projects/fsociety/src/lib/badge/badge.component.ts","../../../projects/fsociety/src/lib/badge/badge.component.html","../../../projects/fsociety/src/lib/tabs/tabs.component.ts","../../../projects/fsociety/src/lib/tabs/tabs.component.html","../../../projects/fsociety/src/lib/alert/alert.component.ts","../../../projects/fsociety/src/lib/alert/alert.component.html","../../../projects/fsociety/src/lib/experience-card/experience-card.component.ts","../../../projects/fsociety/src/lib/experience-card/experience-card.component.html","../../../projects/fsociety/src/lib/profile-card/profile-card.component.ts","../../../projects/fsociety/src/lib/profile-card/profile-card.component.html","../../../projects/fsociety/src/public-api.ts","../../../projects/fsociety/src/heroelc-fsociety.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class FsocietyService {\r\n\r\n constructor() { }\r\n}\r\n","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'fs-fsociety',\r\n imports: [],\r\n template: `\r\n <p>\r\n fsociety works!\r\n </p>\r\n `,\r\n styles: ``\r\n})\r\nexport class FsocietyComponent {\r\n\r\n}\r\n","import {\n Component,\n Input,\n Output,\n EventEmitter,\n ChangeDetectionStrategy,\n HostBinding,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\nexport type FsButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger' | 'link';\nexport type FsButtonSize = 'sm' | 'md' | 'lg';\nexport type FsButtonType = 'button' | 'submit' | 'reset';\n\n@Component({\n selector: 'fs-button',\n standalone: true,\n imports: [CommonModule],\n templateUrl: './button.component.html',\n styleUrl: './button.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FsButtonComponent {\n\n /** Variante visual del botón */\n @Input() variant: FsButtonVariant = 'primary';\n\n /** Tamaño del botón */\n @Input() size: FsButtonSize = 'md';\n\n /** Tipo HTML nativo */\n @Input() type: FsButtonType = 'button';\n\n /** Deshabilita el botón */\n @Input() disabled = false;\n\n /** Muestra spinner y deshabilita el botón */\n @Input() loading = false;\n\n /** Texto del botón (alternativa al content projection) */\n @Input() label?: string;\n\n /** Ícono izquierdo — string SVG path o nombre de ícono */\n @Input() iconLeft?: string;\n\n /** Ícono derecho */\n @Input() iconRight?: string;\n\n /** Ancho completo del contenedor */\n @Input() fullWidth = false;\n\n /** Emite el click — no dispara si disabled o loading */\n @Output() fsClick = new EventEmitter<MouseEvent>();\n\n @HostBinding('style.width')\n get hostWidth(): string {\n return this.fullWidth ? '100%' : 'auto';\n }\n\n get isDisabled(): boolean {\n return this.disabled || this.loading;\n }\n\n get classes(): Record<string, boolean> {\n return {\n [`fs-btn--${this.variant}`]: true,\n [`fs-btn--${this.size}`]: true,\n 'fs-btn--loading': this.loading,\n 'fs-btn--disabled': this.isDisabled,\n 'fs-btn--full-width': this.fullWidth,\n };\n }\n\n onClick(event: MouseEvent): void {\n if (this.isDisabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n this.fsClick.emit(event);\n }\n}\n","<button\n class=\"fs-btn\"\n [ngClass]=\"classes\"\n [type]=\"type\"\n [disabled]=\"isDisabled\"\n [attr.aria-disabled]=\"isDisabled\"\n [attr.aria-busy]=\"loading\"\n (click)=\"onClick($event)\"\n>\n <!-- spinner (solo cuando loading) -->\n <span *ngIf=\"loading\" class=\"fs-btn__spinner\" aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle cx=\"8\" cy=\"8\" r=\"6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\n stroke-dasharray=\"28\" stroke-dashoffset=\"10\" />\n </svg>\n </span>\n\n <!-- ícono izquierdo -->\n <span *ngIf=\"iconLeft && !loading\" class=\"fs-btn__icon fs-btn__icon--left\" aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path [attr.d]=\"iconLeft\" stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n\n <!-- label vía input o content projection -->\n <span class=\"fs-btn__label\">\n <ng-content>{{ label }}</ng-content>\n </span>\n\n <!-- ícono derecho -->\n <span *ngIf=\"iconRight && !loading\" class=\"fs-btn__icon fs-btn__icon--right\" aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path [attr.d]=\"iconRight\" stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n</button>\n","import {\n Component,\n Input,\n Output,\n EventEmitter,\n ChangeDetectionStrategy,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\nexport type FsBadgeColor = 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'neutral';\nexport type FsBadgeVariant = 'filled' | 'outline';\nexport type FsBadgeSize = 'sm' | 'md';\n\n@Component({\n selector: 'fs-badge',\n standalone: true,\n imports: [CommonModule],\n templateUrl: './badge.component.html',\n styleUrl: './badge.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FsBadgeComponent {\n\n /** Color semántico del badge */\n @Input() color: FsBadgeColor = 'neutral';\n\n /** Filled = fondo sutil · outline = solo borde */\n @Input() variant: FsBadgeVariant = 'filled';\n\n /** Tamaño */\n @Input() size: FsBadgeSize = 'md';\n\n /** Texto del badge (alternativa al content projection) */\n @Input() label?: string;\n\n /** Muestra punto de estado a la izquierda */\n @Input() dot = false;\n\n /**\n * SVG path del ícono izquierdo (viewBox 0 0 24 24).\n */\n @Input() iconLeft?: string;\n\n /**\n * SVG path del ícono derecho (viewBox 0 0 24 24).\n */\n @Input() iconRight?: string;\n\n /**\n * URL o ruta de imagen izquierda.\n * Ejemplo: 'assets/icons/angular.svg' o 'https://...'\n * Tiene prioridad sobre iconLeft si ambos están definidos.\n */\n @Input() imgLeft?: string;\n\n /**\n * URL o ruta de imagen derecha.\n * Tiene prioridad sobre iconRight si ambos están definidos.\n */\n @Input() imgRight?: string;\n\n /** Alt text para imgLeft — por defecto vacío (decorativo) */\n @Input() imgLeftAlt = '';\n\n /** Alt text para imgRight — por defecto vacío (decorativo) */\n @Input() imgRightAlt = '';\n\n /**\n * Modo solo ícono — oculta el label y hace el badge cuadrado/circular.\n * Requiere iconLeft, iconRight, imgLeft o imgRight.\n */\n @Input() iconOnly = false;\n\n /** Badge removible — muestra botón X */\n @Input() removable = false;\n\n /** Emite cuando se clickea el botón remove */\n @Output() removed = new EventEmitter<void>();\n\n get classes(): Record<string, boolean> {\n return {\n [`fs-badge--${this.color}`]: true,\n [`fs-badge--${this.variant}`]: true,\n [`fs-badge--${this.size}`]: true,\n 'fs-badge--dot': this.dot,\n 'fs-badge--icon-only': this.iconOnly,\n 'fs-badge--removable': this.removable,\n };\n }\n\n onRemove(event: MouseEvent): void {\n event.stopPropagation();\n this.removed.emit();\n }\n}\n","<span class=\"fs-badge\" [ngClass]=\"classes\">\n\n <!-- dot de estado -->\n <span *ngIf=\"dot\" class=\"fs-badge__dot\" aria-hidden=\"true\"></span>\n\n <!-- imagen izquierda (prioridad sobre iconLeft) -->\n <span *ngIf=\"imgLeft\" class=\"fs-badge__icon fs-badge__icon--left\" aria-hidden=\"true\">\n <img [src]=\"imgLeft\" [alt]=\"imgLeftAlt\" class=\"fs-badge__img\" />\n </span>\n\n <!-- ícono izquierdo SVG (solo si no hay imgLeft) -->\n <span *ngIf=\"iconLeft && !imgLeft\" class=\"fs-badge__icon fs-badge__icon--left\" aria-hidden=\"true\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path [attr.d]=\"iconLeft\"/>\n </svg>\n </span>\n\n <!-- label — oculto en iconOnly -->\n <span *ngIf=\"!iconOnly\" class=\"fs-badge__label\">\n <ng-content>{{ label }}</ng-content>\n </span>\n\n <!-- imagen derecha (prioridad sobre iconRight) -->\n <span *ngIf=\"imgRight\" class=\"fs-badge__icon fs-badge__icon--right\" aria-hidden=\"true\">\n <img [src]=\"imgRight\" [alt]=\"imgRightAlt\" class=\"fs-badge__img\" />\n </span>\n\n <!-- ícono derecho SVG (solo si no hay imgRight) -->\n <span *ngIf=\"iconRight && !imgRight\" class=\"fs-badge__icon fs-badge__icon--right\" aria-hidden=\"true\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path [attr.d]=\"iconRight\"/>\n </svg>\n </span>\n\n <!-- botón remove -->\n <button\n *ngIf=\"removable\"\n class=\"fs-badge__remove\"\n type=\"button\"\n aria-label=\"Remover\"\n (click)=\"onRemove($event)\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M2 2l6 6M8 2L2 8\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n </button>\n\n</span>\n","import {\n Component,\n Input,\n Output,\n EventEmitter,\n AfterViewInit,\n OnChanges,\n SimpleChanges,\n ViewChild,\n ElementRef,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n NgZone,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\nexport interface FsTab {\n /** Identificador único de la tab */\n id: string;\n /** Texto visible en el encabezado */\n label: string;\n /** Deshabilita la tab */\n disabled?: boolean;\n}\n\n@Component({\n selector: 'fs-tabs',\n standalone: true,\n imports: [CommonModule],\n templateUrl: './tabs.component.html',\n styleUrl: './tabs.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FsTabsComponent implements AfterViewInit, OnChanges {\n\n /** Lista de tabs a renderizar */\n @Input() tabs: FsTab[] = [];\n\n /** Id de la tab activa */\n @Input() activeTab = '';\n\n /** Two-way binding: [(activeTab)] */\n @Output() activeTabChange = new EventEmitter<string>();\n\n /** Emite la tab completa al cambiar */\n @Output() tabChange = new EventEmitter<FsTab>();\n\n @ViewChild('tabsRow') tabsRow!: ElementRef<HTMLElement>;\n\n indicatorLeft = 0;\n indicatorWidth = 0;\n\n constructor(\n private cdr: ChangeDetectorRef,\n private zone: NgZone,\n ) {}\n\n ngAfterViewInit(): void {\n this.updateIndicator();\n\n // Recalcular al cambiar el tamaño del contenedor\n this.zone.runOutsideAngular(() => {\n const ro = new ResizeObserver(() => {\n this.zone.run(() => {\n this.updateIndicator();\n this.cdr.markForCheck();\n });\n });\n ro.observe(this.tabsRow.nativeElement);\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['activeTab'] || changes['tabs']) {\n // Defer para que el DOM se actualice primero\n setTimeout(() => this.updateIndicator());\n }\n }\n\n selectTab(tab: FsTab): void {\n if (tab.disabled) return;\n this.activeTab = tab.id;\n this.activeTabChange.emit(tab.id);\n this.tabChange.emit(tab);\n this.updateIndicator();\n }\n\n isActive(tab: FsTab): boolean {\n return this.activeTab === tab.id;\n }\n\n private updateIndicator(): void {\n if (!this.tabsRow) return;\n\n const row = this.tabsRow.nativeElement;\n const items = row.querySelectorAll<HTMLElement>('.fs-tabs__item');\n const idx = this.tabs.findIndex(t => t.id === this.activeTab);\n\n if (idx === -1 || !items[idx]) return;\n\n const item = items[idx];\n this.indicatorLeft = item.offsetLeft;\n this.indicatorWidth = item.offsetWidth;\n this.cdr.markForCheck();\n }\n}\n","<div class=\"fs-tabs\">\n\n <!-- encabezado -->\n <div class=\"fs-tabs__header\" #tabsRow role=\"tablist\">\n\n <button\n *ngFor=\"let tab of tabs\"\n class=\"fs-tabs__item\"\n [class.fs-tabs__item--active]=\"isActive(tab)\"\n [class.fs-tabs__item--disabled]=\"tab.disabled\"\n role=\"tab\"\n [attr.aria-selected]=\"isActive(tab)\"\n [attr.aria-disabled]=\"tab.disabled\"\n [disabled]=\"tab.disabled\"\n (click)=\"selectTab(tab)\"\n >\n {{ tab.label }}\n </button>\n\n <!-- indicator deslizante -->\n <span\n class=\"fs-tabs__indicator\"\n [style.left.px]=\"indicatorLeft\"\n [style.width.px]=\"indicatorWidth\"\n aria-hidden=\"true\"\n ></span>\n\n </div>\n\n <!-- contenido vía content projection -->\n <div class=\"fs-tabs__content\" role=\"tabpanel\">\n <ng-content></ng-content>\n </div>\n\n</div>\n","import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnDestroy,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\nexport type FsAlertType = 'info' | 'success' | 'warning' | 'danger' | 'neutral';\nexport type FsAlertVariant = 'filled' | 'accent';\n\n@Component({\n selector: 'fs-alert',\n standalone: true,\n imports: [CommonModule],\n templateUrl: './alert.component.html',\n styleUrl: './alert.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FsAlertComponent implements OnInit, OnDestroy {\n\n /** Tipo semántico del alert */\n @Input() type: FsAlertType = 'info';\n\n /** filled = fondo sutil · accent = borde izquierdo */\n @Input() variant: FsAlertVariant = 'filled';\n\n /** Título opcional en negrita */\n @Input() title?: string;\n\n /** Muestra botón X para cerrar */\n @Input() dismissible = false;\n\n /**\n * Auto-cierre en milisegundos.\n * 0 = deshabilitado.\n * Muestra progress bar cuando está activo.\n */\n @Input() autoDismiss = 0;\n\n /** Emite cuando el alert se cierra (botón X o auto-dismiss) */\n @Output() dismissed = new EventEmitter<void>();\n\n // Estado interno de animación\n animState: 'entering' | 'visible' | 'exiting' = 'entering';\n\n private autoTimer?: ReturnType<typeof setTimeout>;\n\n constructor(private cdr: ChangeDetectorRef) {}\n\n ngOnInit(): void {\n // tras la animación de entrada → visible\n setTimeout(() => {\n this.animState = 'visible';\n this.cdr.markForCheck();\n }, 300);\n\n if (this.autoDismiss > 0) {\n this.autoTimer = setTimeout(() => this.dismiss(), this.autoDismiss);\n }\n }\n\n ngOnDestroy(): void {\n if (this.autoTimer) clearTimeout(this.autoTimer);\n }\n\n dismiss(): void {\n if (this.animState === 'exiting') return;\n this.animState = 'exiting';\n this.cdr.markForCheck();\n\n // esperar la animación de salida antes de emitir\n setTimeout(() => {\n this.dismissed.emit();\n }, 240);\n }\n\n get progressDuration(): string {\n return `${this.autoDismiss}ms`;\n }\n\n get iconPath(): string {\n const icons: Record<FsAlertType, string> = {\n info: 'M8 7v4M8 5.5v.01M2 8a6 6 0 1 0 12 0A6 6 0 0 0 2 8z',\n success: 'M5 8l2 2 4-4M2 8a6 6 0 1 0 12 0A6 6 0 0 0 2 8z',\n warning: 'M8 2L2 13h12L8 2zM8 7v3M8 11.5v.01',\n danger: 'M8 5v4M8 10.5v.01M2 8a6 6 0 1 0 12 0A6 6 0 0 0 2 8z',\n neutral: 'M8 7v4M8 5.5v.01M2 8a6 6 0 1 0 12 0A6 6 0 0 0 2 8z',\n };\n return icons[this.type];\n }\n}\n","<div\n *ngIf=\"animState !== 'exiting' || true\"\n class=\"fs-alert\"\n [class.fs-alert--entering]=\"animState === 'entering'\"\n [class.fs-alert--visible]=\"animState === 'visible'\"\n [class.fs-alert--exiting]=\"animState === 'exiting'\"\n [class]=\"'fs-alert fs-alert--' + type + ' fs-alert--' + variant\"\n [attr.role]=\"type === 'danger' ? 'alert' : 'status'\"\n [attr.aria-live]=\"type === 'danger' ? 'assertive' : 'polite'\"\n>\n\n <!-- ícono semántico -->\n <svg\n class=\"fs-alert__icon\"\n width=\"16\" height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n [attr.d]=\"iconPath\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n\n <!-- cuerpo -->\n <div class=\"fs-alert__body\">\n <div *ngIf=\"title\" class=\"fs-alert__title\">{{ title }}</div>\n <div class=\"fs-alert__desc\">\n <ng-content></ng-content>\n </div>\n </div>\n\n <!-- botón cerrar -->\n <button\n *ngIf=\"dismissible\"\n class=\"fs-alert__close\"\n type=\"button\"\n aria-label=\"Cerrar\"\n (click)=\"dismiss()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path\n d=\"M3 3l8 8M11 3L3 11\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n\n <!-- progress bar de auto-dismiss -->\n <div\n *ngIf=\"autoDismiss > 0\"\n class=\"fs-alert__progress\"\n [style.animation-duration]=\"progressDuration\"\n ></div>\n\n</div>\n","import {\n Component,\n Input,\n OnInit,\n ChangeDetectionStrategy,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FsBadgeComponent, FsBadgeColor } from '../badge/badge.component';\n\nexport interface FsExperienceBadge {\n label: string;\n color?: FsBadgeColor;\n iconLeft?: string;\n}\n\nexport interface FsExperienceCard {\n /** Nombre de la empresa */\n company: string;\n\n /** Rol / puesto */\n role: string;\n\n /** Fecha de inicio — formato libre: 'abr 2022' */\n startDate: string;\n\n /** Fecha de fin — omitir si es trabajo actual */\n endDate?: string;\n\n /** Marca el trabajo como actual — muestra dot verde y \"actualidad\" */\n current?: boolean;\n\n /** Logo de la empresa — URL de imagen */\n logoUrl?: string;\n\n /** Texto corto para el logo cuando no hay imagen: 'X CALE' */\n logoText?: string;\n\n /** Lista de responsabilidades / bullets */\n bullets?: string[];\n\n /** Cuántos bullets mostrar antes del \"ver más\" */\n bulletsPreview?: number;\n\n /** Badges de tecnologías */\n badges?: FsExperienceBadge[];\n}\n\n@Component({\n selector: 'fs-experience-card',\n standalone: true,\n imports: [CommonModule, FsBadgeComponent],\n templateUrl: './experience-card.component.html',\n styleUrl: './experience-card.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FsExperienceCardComponent implements OnInit {\n\n /** Datos de la experiencia */\n @Input() experience!: FsExperienceCard;\n\n /** Variante de presentación */\n @Input() variant: 'full' | 'compact' = 'full';\n\n /** Muestra la línea vertical de timeline a la izquierda */\n @Input() timeline = false;\n\n /** Si es el último item del timeline (no dibuja la línea hacia abajo) */\n @Input() timelineLast = false;\n\n expanded = false;\n\n get hasBullets(): boolean {\n return !!(this.experience?.bullets?.length);\n }\n\n get visibleBullets(): string[] {\n if (!this.experience?.bullets) return [];\n const preview = this.experience.bulletsPreview ?? 3;\n return this.expanded\n ? this.experience.bullets\n : this.experience.bullets.slice(0, preview);\n }\n\n get hasMoreBullets(): boolean {\n if (!this.experience?.bullets) return false;\n const preview = this.experience.bulletsPreview ?? 3;\n return this.experience.bullets.length > preview;\n }\n\n get duration(): string {\n return this.calculateDuration();\n }\n\n get isCurrent(): boolean {\n return this.experience?.current ?? false;\n }\n\n ngOnInit(): void {\n this.expanded = false;\n }\n\n toggleExpand(): void {\n this.expanded = !this.expanded;\n }\n\n private calculateDuration(): string {\n if (!this.experience?.startDate) return '';\n\n const start = this.parseDate(this.experience.startDate);\n const end = this.experience.current || !this.experience.endDate\n ? new Date()\n : this.parseDate(this.experience.endDate);\n\n if (!start || !end) return '';\n\n let months = (end.getFullYear() - start.getFullYear()) * 12\n + (end.getMonth() - start.getMonth());\n\n const years = Math.floor(months / 12);\n const remain = months % 12;\n\n const parts: string[] = [];\n if (years > 0) parts.push(`${years} ${years === 1 ? 'año' : 'años'}`);\n if (remain > 0) parts.push(`${remain} ${remain === 1 ? 'mes' : 'meses'}`);\n\n return parts.join(' ');\n }\n\n private parseDate(dateStr: string): Date | null {\n const months: Record<string, number> = {\n ene: 0, feb: 1, mar: 2, abr: 3, may: 4, jun: 5,\n jul: 6, ago: 7, sep: 8, oct: 9, nov: 10, dic: 11,\n };\n\n const parts = dateStr.trim().toLowerCase().split(' ');\n if (parts.length === 2) {\n const month = months[parts[0]];\n const year = parseInt(parts[1], 10);\n if (month !== undefined && !isNaN(year)) {\n return new Date(year, month, 1);\n }\n }\n\n // fallback: intentar parsear como fecha estándar\n const d = new Date(dateStr);\n return isNaN(d.getTime()) ? null : d;\n }\n}\n","<div\n class=\"fs-exp\"\n [class.fs-exp--compact]=\"variant === 'compact'\"\n [class.fs-exp--timeline]=\"timeline\"\n [class.fs-exp--timeline-last]=\"timeline && timelineLast\"\n>\n\n <!-- línea vertical de timeline -->\n <div *ngIf=\"timeline\" class=\"fs-exp__timeline-line\"></div>\n\n <!-- dot del timeline -->\n <div *ngIf=\"timeline\" class=\"fs-exp__timeline-dot\"\n [class.fs-exp__timeline-dot--current]=\"isCurrent\">\n </div>\n\n <!-- card -->\n <div class=\"fs-exp__card\">\n\n <!-- header -->\n <div class=\"fs-exp__header\">\n\n <!-- logo -->\n <div class=\"fs-exp__logo\">\n <img\n *ngIf=\"experience.logoUrl\"\n [src]=\"experience.logoUrl\"\n [alt]=\"experience.company\"\n class=\"fs-exp__logo-img\"\n />\n <span *ngIf=\"!experience.logoUrl\" class=\"fs-exp__logo-text\">\n {{ experience.logoText || experience.company.slice(0, 4).toUpperCase() }}\n </span>\n </div>\n\n <!-- info -->\n <div class=\"fs-exp__info\">\n <div class=\"fs-exp__company\">{{ experience.company }}</div>\n <div class=\"fs-exp__role\">{{ experience.role }}</div>\n <div class=\"fs-exp__date\">\n <span\n class=\"fs-exp__dot\"\n [class.fs-exp__dot--current]=\"isCurrent\"\n ></span>\n <span>\n {{ experience.startDate }} –\n {{ experience.current ? 'actualidad' : experience.endDate }}\n </span>\n <span *ngIf=\"duration\" class=\"fs-exp__duration\">\n · {{ duration }}\n </span>\n </div>\n </div>\n\n </div>\n\n <!-- cuerpo — solo en variante full -->\n <ng-container *ngIf=\"variant === 'full'\">\n\n <div *ngIf=\"hasBullets || experience.badges?.length\" class=\"fs-exp__divider\"></div>\n\n <!-- bullets -->\n <ul *ngIf=\"hasBullets\" class=\"fs-exp__bullets\">\n <li *ngFor=\"let bullet of visibleBullets\" class=\"fs-exp__bullet\">\n <span class=\"fs-exp__bullet-arrow\" aria-hidden=\"true\">▸</span>\n <span>{{ bullet }}</span>\n </li>\n </ul>\n\n <!-- toggle ver más / menos -->\n <button\n *ngIf=\"hasMoreBullets\"\n class=\"fs-exp__toggle\"\n type=\"button\"\n (click)=\"toggleExpand()\"\n >\n <svg\n class=\"fs-exp__toggle-icon\"\n [class.fs-exp__toggle-icon--open]=\"expanded\"\n width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\"\n >\n <path d=\"M3 4.5l3 3 3-3\"\n stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n {{ expanded ? 'ver menos' : 'ver más' }}\n </button>\n\n <!-- badges -->\n <div *ngIf=\"experience.badges?.length\" class=\"fs-exp__badges\">\n <fs-badge\n *ngFor=\"let badge of experience.badges\"\n [color]=\"badge.color || 'neutral'\"\n [iconLeft]=\"badge.iconLeft\"\n variant=\"filled\"\n size=\"sm\"\n >{{ badge.label }}</fs-badge>\n </div>\n\n </ng-container>\n\n </div>\n</div>\n","import {\n Component,\n Input,\n Output,\n EventEmitter,\n ChangeDetectionStrategy,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FsBadgeComponent, FsBadgeColor } from '../badge/badge.component';\n\nexport interface FsProfileStat {\n /** Valor principal: '4+', '985', '12' */\n value: string | number;\n /** Etiqueta debajo del valor */\n label: string;\n}\n\nexport interface FsProfileLink {\n /** Texto visible */\n label: string;\n /** URL destino */\n url?: string;\n /** SVG path del ícono (viewBox 0 0 16 16) */\n icon?: string;\n}\n\nexport interface FsProfileBadge {\n label: string;\n color?: FsBadgeColor;\n iconLeft?: string;\n}\n\n@Component({\n selector: 'fs-profile-card',\n standalone: true,\n imports: [CommonModule, FsBadgeComponent],\n templateUrl: './profile-card.component.html',\n styleUrl: './profile-card.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FsProfileCardComponent {\n\n // -------------------------------------------------------------------------\n // Identidad\n // -------------------------------------------------------------------------\n\n /** Nombre completo */\n @Input() name = '';\n\n /** Handle sin @ */\n @Input() handle = '';\n\n /** Rol / título */\n @Input() role = '';\n\n /** Muestra el badge de verificado */\n @Input() verified = false;\n\n // -------------------------------------------------------------------------\n // Imágenes\n // -------------------------------------------------------------------------\n\n /**\n * URL de la foto de perfil.\n * Si no se provee, se muestran las iniciales.\n */\n @Input() avatarUrl?: string;\n\n /**\n * URL de imagen para el banner.\n * Si no se provee, se usa el degradé navy por defecto.\n */\n @Input() bannerUrl?: string;\n\n // -------------------------------------------------------------------------\n // Contenido\n // -------------------------------------------------------------------------\n\n /** Links de redes sociales / ubicación */\n @Input() links: FsProfileLink[] = [];\n\n /** Badges de tecnologías */\n @Input() badges: FsProfileBadge[] = [];\n\n /**\n * Stats configurables: años de exp., proyectos, seguidores, etc.\n * Array de { value, label } — se muestran todos en el footer.\n */\n @Input() stats: FsProfileStat[] = [];\n\n // -------------------------------------------------------------------------\n // Variante\n // -------------------------------------------------------------------------\n\n /**\n * Muestra los botones de acción (Seguir / Mensaje).\n * false = variante readonly / portfolio propio.\n */\n @Input() showActions = false;\n\n /** Label del botón primario */\n @Input() primaryActionLabel = 'Seguir';\n\n /** Label del botón secundario */\n @Input() secondaryActionLabel = 'Mensaje';\n\n // -------------------------------------------------------------------------\n // Outputs\n // -------------------------------------------------------------------------\n\n @Output() primaryAction = new EventEmitter<void>();\n @Output() secondaryAction = new EventEmitter<void>();\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n get initials(): string {\n return this.name\n .split(' ')\n .slice(0, 2)\n .map(w => w[0])\n .join('')\n .toUpperCase();\n }\n}\n","<div class=\"fs-profile\">\n\n <!-- banner -->\n <div class=\"fs-profile__banner\">\n <img\n *ngIf=\"bannerUrl\"\n [src]=\"bannerUrl\"\n [alt]=\"name + ' banner'\"\n class=\"fs-profile__banner-img\"\n />\n <div *ngIf=\"!bannerUrl\" class=\"fs-profile__banner-gradient\"></div>\n <div class=\"fs-profile__banner-line\"></div>\n </div>\n\n <!-- body -->\n <div class=\"fs-profile__body\">\n\n <!-- avatar -->\n <div class=\"fs-profile__avatar-wrap\">\n <div class=\"fs-profile__avatar\">\n <img\n *ngIf=\"avatarUrl\"\n [src]=\"avatarUrl\"\n [alt]=\"name\"\n class=\"fs-profile__avatar-img\"\n />\n <span *ngIf=\"!avatarUrl\" class=\"fs-profile__avatar-initials\">\n {{ initials }}\n </span>\n </div>\n <div *ngIf=\"verified\" class=\"fs-profile__verified\" aria-label=\"Verificado\">\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M2 5l2 2 4-4\"\n stroke=\"white\" stroke-width=\"1.6\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n </div>\n\n <!-- identidad -->\n <div class=\"fs-profile__name\">{{ name }}</div>\n <div *ngIf=\"handle\" class=\"fs-profile__handle\">&#64;{{ handle }}</div>\n <div *ngIf=\"role\" class=\"fs-profile__role\">{{ role }}</div>\n\n <!-- acciones -->\n <div *ngIf=\"showActions\" class=\"fs-profile__actions\">\n <button\n class=\"fs-profile__btn fs-profile__btn--primary\"\n type=\"button\"\n (click)=\"primaryAction.emit()\"\n >\n {{ primaryActionLabel }}\n </button>\n <button\n class=\"fs-profile__btn fs-profile__btn--outline\"\n type=\"button\"\n (click)=\"secondaryAction.emit()\"\n >\n {{ secondaryActionLabel }}\n </button>\n </div>\n\n <!-- links -->\n <div *ngIf=\"links.length\" class=\"fs-profile__links\">\n <a\n *ngFor=\"let link of links\"\n class=\"fs-profile__link\"\n [href]=\"link.url || '#'\"\n [attr.target]=\"link.url ? '_blank' : null\"\n [attr.rel]=\"link.url ? 'noopener noreferrer' : null\"\n >\n <svg *ngIf=\"link.icon\" width=\"12\" height=\"12\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path [attr.d]=\"link.icon\" stroke=\"currentColor\" stroke-width=\"1.3\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span>{{ link.label }}</span>\n </a>\n </div>\n\n <!-- badges -->\n <div *ngIf=\"badges.length\" class=\"fs-profile__badges\">\n <fs-badge\n *ngFor=\"let badge of badges\"\n [color]=\"badge.color || 'neutral'\"\n [iconLeft]=\"badge.iconLeft\"\n variant=\"filled\"\n size=\"sm\"\n >{{ badge.label }}</fs-badge>\n </div>\n\n </div>\n\n <!-- stats footer -->\n <div *ngIf=\"stats.length\" class=\"fs-profile__stats\">\n <div *ngFor=\"let stat of stats\" class=\"fs-profile__stat\">\n <span class=\"fs-profile__stat-value\">{{ stat.value }}</span>\n <span class=\"fs-profile__stat-label\">{{ stat.label }}</span>\n </div>\n </div>\n\n</div>\n","/*\r\n * Public API Surface of fsociety\r\n */\r\n\r\nexport * from './lib/fsociety.service';\r\nexport * from './lib/fsociety.component';\r\n\r\nexport * from './lib/button/button.component';\r\nexport type { FsButtonVariant, FsButtonSize, FsButtonType } from './lib/button/button.component';\r\n\r\nexport * from './lib/badge/badge.component';\r\nexport type { FsBadgeColor, FsBadgeVariant, FsBadgeSize } from './lib/badge/badge.component';\r\n\r\nexport * from './lib/tabs/tabs.component';\r\nexport type { FsTab } from './lib/tabs/tabs.component';\r\n\r\nexport * from './lib/alert/alert.component';\r\nexport type { FsAlertType, FsAlertVariant } from './lib/alert/alert.component';\r\n\r\nexport * from './lib/experience-card/experience-card.component';\r\nexport type { FsExperienceCard, FsExperienceBadge } from './lib/experience-card/experience-card.component';\r\n\r\nexport * from './lib/profile-card/profile-card.component';\r\nexport type { FsProfileStat, FsProfileLink, FsProfileBadge } from './lib/profile-card/profile-card.component';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"heroelc-fsociety.mjs","sources":["../../../projects/fsociety/src/lib/fsociety.service.ts","../../../projects/fsociety/src/lib/fsociety.component.ts","../../../projects/fsociety/src/lib/button/button.component.ts","../../../projects/fsociety/src/lib/button/button.component.html","../../../projects/fsociety/src/lib/badge/badge.component.ts","../../../projects/fsociety/src/lib/badge/badge.component.html","../../../projects/fsociety/src/lib/tabs/tabs.component.ts","../../../projects/fsociety/src/lib/tabs/tabs.component.html","../../../projects/fsociety/src/lib/alert/alert.component.ts","../../../projects/fsociety/src/lib/alert/alert.component.html","../../../projects/fsociety/src/lib/experience-card/experience-card.component.ts","../../../projects/fsociety/src/lib/experience-card/experience-card.component.html","../../../projects/fsociety/src/lib/profile-card/profile-card.component.ts","../../../projects/fsociety/src/lib/profile-card/profile-card.component.html","../../../projects/fsociety/src/public-api.ts","../../../projects/fsociety/src/heroelc-fsociety.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class FsocietyService {\r\n\r\n constructor() { }\r\n}\r\n","import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'fs-fsociety',\r\n imports: [],\r\n template: `\r\n <p>\r\n fsociety works!\r\n </p>\r\n `,\r\n styles: ``\r\n})\r\nexport class FsocietyComponent {\r\n\r\n}\r\n","import {\n Component,\n Input,\n Output,\n EventEmitter,\n ChangeDetectionStrategy,\n HostBinding,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\nexport type FsButtonVariant = 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger' | 'link';\nexport type FsButtonSize = 'sm' | 'md' | 'lg';\nexport type FsButtonType = 'button' | 'submit' | 'reset';\n\n@Component({\n selector: 'fs-button',\n standalone: true,\n imports: [CommonModule],\n templateUrl: './button.component.html',\n styleUrl: './button.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FsButtonComponent {\n\n /** Variante visual del botón */\n @Input() variant: FsButtonVariant = 'primary';\n\n /** Tamaño del botón */\n @Input() size: FsButtonSize = 'md';\n\n /** Tipo HTML nativo */\n @Input() type: FsButtonType = 'button';\n\n /** Deshabilita el botón */\n @Input() disabled = false;\n\n /** Muestra spinner y deshabilita el botón */\n @Input() loading = false;\n\n /** Texto del botón (alternativa al content projection) */\n @Input() label?: string;\n\n /** Ícono izquierdo — string SVG path o nombre de ícono */\n @Input() iconLeft?: string;\n\n /** Ícono derecho */\n @Input() iconRight?: string;\n\n /** Ancho completo del contenedor */\n @Input() fullWidth = false;\n\n /** Emite el click — no dispara si disabled o loading */\n @Output() fsClick = new EventEmitter<MouseEvent>();\n\n @HostBinding('style.width')\n get hostWidth(): string {\n return this.fullWidth ? '100%' : 'auto';\n }\n\n get isDisabled(): boolean {\n return this.disabled || this.loading;\n }\n\n get classes(): Record<string, boolean> {\n return {\n [`fs-btn--${this.variant}`]: true,\n [`fs-btn--${this.size}`]: true,\n 'fs-btn--loading': this.loading,\n 'fs-btn--disabled': this.isDisabled,\n 'fs-btn--full-width': this.fullWidth,\n };\n }\n\n onClick(event: MouseEvent): void {\n if (this.isDisabled) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n this.fsClick.emit(event);\n }\n}\n","<button\n class=\"fs-btn\"\n [ngClass]=\"classes\"\n [type]=\"type\"\n [disabled]=\"isDisabled\"\n [attr.aria-disabled]=\"isDisabled\"\n [attr.aria-busy]=\"loading\"\n (click)=\"onClick($event)\"\n>\n <!-- spinner (solo cuando loading) -->\n <span *ngIf=\"loading\" class=\"fs-btn__spinner\" aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <circle cx=\"8\" cy=\"8\" r=\"6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\n stroke-dasharray=\"28\" stroke-dashoffset=\"10\" />\n </svg>\n </span>\n\n <!-- ícono izquierdo -->\n <span *ngIf=\"iconLeft && !loading\" class=\"fs-btn__icon fs-btn__icon--left\" aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path [attr.d]=\"iconLeft\" stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n\n <!-- label vía input o content projection -->\n <span class=\"fs-btn__label\">\n <ng-content>{{ label }}</ng-content>\n </span>\n\n <!-- ícono derecho -->\n <span *ngIf=\"iconRight && !loading\" class=\"fs-btn__icon fs-btn__icon--right\" aria-hidden=\"true\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path [attr.d]=\"iconRight\" stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </span>\n</button>\n","import {\n Component,\n Input,\n Output,\n EventEmitter,\n ChangeDetectionStrategy,\n OnChanges,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\nexport type FsBadgeColor = 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'neutral';\nexport type FsBadgeVariant = 'filled' | 'outline';\nexport type FsBadgeSize = 'sm' | 'md';\n\n@Component({\n selector: 'fs-badge',\n standalone: true,\n imports: [CommonModule],\n templateUrl: './badge.component.html',\n styleUrl: './badge.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FsBadgeComponent implements OnChanges {\n\n /** Color semántico del badge */\n @Input() color: FsBadgeColor = 'neutral';\n\n /**\n * Color personalizado en formato hex.\n * Ejemplo: '#7c3aed'\n * Cuando se provee, tiene prioridad sobre `color` y genera\n * automáticamente el fondo, borde y texto con la opacidad correcta.\n */\n @Input() customColor?: string;\n\n /** Filled = fondo sutil · outline = solo borde */\n @Input() variant: FsBadgeVariant = 'filled';\n\n /** Tamaño */\n @Input() size: FsBadgeSize = 'md';\n\n /** Texto del badge (alternativa al content projection) */\n @Input() label?: string;\n\n /** Muestra punto de estado a la izquierda */\n @Input() dot = false;\n\n /** SVG path del ícono izquierdo (viewBox 0 0 24 24) */\n @Input() iconLeft?: string;\n\n /** SVG path del ícono derecho (viewBox 0 0 24 24) */\n @Input() iconRight?: string;\n\n /**\n * URL o ruta de imagen izquierda.\n * Ejemplo: 'assets/icons/angular.svg' o 'https://cdn.simpleicons.org/angular/white'\n * Tiene prioridad sobre iconLeft si ambos están definidos.\n */\n @Input() imgLeft?: string;\n\n /**\n * URL o ruta de imagen derecha.\n * Tiene prioridad sobre iconRight si ambos están definidos.\n */\n @Input() imgRight?: string;\n\n /** Alt text para imgLeft — por defecto vacío (decorativo) */\n @Input() imgLeftAlt = '';\n\n /** Alt text para imgRight — por defecto vacío (decorativo) */\n @Input() imgRightAlt = '';\n\n /**\n * Modo solo ícono — oculta el label y hace el badge cuadrado/circular.\n * Requiere iconLeft, iconRight, imgLeft o imgRight.\n */\n @Input() iconOnly = false;\n\n /** Badge removible — muestra botón X */\n @Input() removable = false;\n\n /** Emite cuando se clickea el botón remove */\n @Output() removed = new EventEmitter<void>();\n\n // Estilos calculados para customColor\n customStyles: Record<string, string> = {};\n\n ngOnChanges(): void {\n if (this.customColor) {\n this.customStyles = this.buildCustomStyles(this.customColor);\n } else {\n this.customStyles = {};\n }\n }\n\n get classes(): Record<string, boolean> {\n return {\n [`fs-badge--${this.color}`]: !this.customColor,\n [`fs-badge--${this.variant}`]: true,\n [`fs-badge--${this.size}`]: true,\n 'fs-badge--custom': !!this.customColor,\n 'fs-badge--dot': this.dot,\n 'fs-badge--icon-only': this.iconOnly,\n 'fs-badge--removable': this.removable,\n };\n }\n\n onRemove(event: MouseEvent): void {\n event.stopPropagation();\n this.removed.emit();\n }\n\n private buildCustomStyles(hex: string): Record<string, string> {\n // Convertir hex a rgb para poder usar con opacidad\n const r = parseInt(hex.slice(1, 3), 16);\n const g = parseInt(hex.slice(3, 5), 16);\n const b = parseInt(hex.slice(5, 7), 16);\n\n if (this.variant === 'outline') {\n return {\n 'background': 'transparent',\n 'color': hex,\n 'border-color': hex,\n };\n }\n\n return {\n 'background': `rgba(${r}, ${g}, ${b}, 0.15)`,\n 'color': this.lightenHex(r, g, b),\n 'border-color': `rgba(${r}, ${g}, ${b}, 0.30)`,\n };\n }\n\n private lightenHex(r: number, g: number, b: number): string {\n // Mezcla con blanco al 60% para el texto\n const mix = (c: number) => Math.round(c + (255 - c) * 0.6);\n return `rgb(${mix(r)}, ${mix(g)}, ${mix(b)})`;\n }\n}\n","<span class=\"fs-badge\" [ngClass]=\"classes\" [ngStyle]=\"customStyles\">\n\n <!-- dot de estado -->\n <span *ngIf=\"dot\" class=\"fs-badge__dot\" aria-hidden=\"true\"></span>\n\n <!-- imagen izquierda (prioridad sobre iconLeft) -->\n <span *ngIf=\"imgLeft\" class=\"fs-badge__icon fs-badge__icon--left\" aria-hidden=\"true\">\n <img [src]=\"imgLeft\" [alt]=\"imgLeftAlt\" class=\"fs-badge__img\" />\n </span>\n\n <!-- ícono izquierdo SVG (solo si no hay imgLeft) -->\n <span *ngIf=\"iconLeft && !imgLeft\" class=\"fs-badge__icon fs-badge__icon--left\" aria-hidden=\"true\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path [attr.d]=\"iconLeft\"/>\n </svg>\n </span>\n\n <!-- label — oculto en iconOnly -->\n <span *ngIf=\"!iconOnly\" class=\"fs-badge__label\">\n <ng-content>{{ label }}</ng-content>\n </span>\n\n <!-- imagen derecha (prioridad sobre iconRight) -->\n <span *ngIf=\"imgRight\" class=\"fs-badge__icon fs-badge__icon--right\" aria-hidden=\"true\">\n <img [src]=\"imgRight\" [alt]=\"imgRightAlt\" class=\"fs-badge__img\" />\n </span>\n\n <!-- ícono derecho SVG (solo si no hay imgRight) -->\n <span *ngIf=\"iconRight && !imgRight\" class=\"fs-badge__icon fs-badge__icon--right\" aria-hidden=\"true\">\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path [attr.d]=\"iconRight\"/>\n </svg>\n </span>\n\n <!-- botón remove -->\n <button\n *ngIf=\"removable\"\n class=\"fs-badge__remove\"\n type=\"button\"\n aria-label=\"Remover\"\n (click)=\"onRemove($event)\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M2 2l6 6M8 2L2 8\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n </button>\n\n</span>\n","import {\n Component,\n Input,\n Output,\n EventEmitter,\n AfterViewInit,\n OnChanges,\n SimpleChanges,\n ViewChild,\n ElementRef,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n NgZone,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\nexport interface FsTab {\n /** Identificador único de la tab */\n id: string;\n /** Texto visible en el encabezado */\n label: string;\n /** Deshabilita la tab */\n disabled?: boolean;\n}\n\n@Component({\n selector: 'fs-tabs',\n standalone: true,\n imports: [CommonModule],\n templateUrl: './tabs.component.html',\n styleUrl: './tabs.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FsTabsComponent implements AfterViewInit, OnChanges {\n\n /** Lista de tabs a renderizar */\n @Input() tabs: FsTab[] = [];\n\n /** Id de la tab activa */\n @Input() activeTab = '';\n\n /** Two-way binding: [(activeTab)] */\n @Output() activeTabChange = new EventEmitter<string>();\n\n /** Emite la tab completa al cambiar */\n @Output() tabChange = new EventEmitter<FsTab>();\n\n @ViewChild('tabsRow') tabsRow!: ElementRef<HTMLElement>;\n\n indicatorLeft = 0;\n indicatorWidth = 0;\n\n constructor(\n private cdr: ChangeDetectorRef,\n private zone: NgZone,\n ) {}\n\n ngAfterViewInit(): void {\n this.updateIndicator();\n\n // Recalcular al cambiar el tamaño del contenedor\n this.zone.runOutsideAngular(() => {\n const ro = new ResizeObserver(() => {\n this.zone.run(() => {\n this.updateIndicator();\n this.cdr.markForCheck();\n });\n });\n ro.observe(this.tabsRow.nativeElement);\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['activeTab'] || changes['tabs']) {\n // Defer para que el DOM se actualice primero\n setTimeout(() => this.updateIndicator());\n }\n }\n\n selectTab(tab: FsTab): void {\n if (tab.disabled) return;\n this.activeTab = tab.id;\n this.activeTabChange.emit(tab.id);\n this.tabChange.emit(tab);\n this.updateIndicator();\n }\n\n isActive(tab: FsTab): boolean {\n return this.activeTab === tab.id;\n }\n\n private updateIndicator(): void {\n if (!this.tabsRow) return;\n\n const row = this.tabsRow.nativeElement;\n const items = row.querySelectorAll<HTMLElement>('.fs-tabs__item');\n const idx = this.tabs.findIndex(t => t.id === this.activeTab);\n\n if (idx === -1 || !items[idx]) return;\n\n const item = items[idx];\n this.indicatorLeft = item.offsetLeft;\n this.indicatorWidth = item.offsetWidth;\n this.cdr.markForCheck();\n }\n}\n","<div class=\"fs-tabs\">\n\n <!-- encabezado -->\n <div class=\"fs-tabs__header\" #tabsRow role=\"tablist\">\n\n <button\n *ngFor=\"let tab of tabs\"\n class=\"fs-tabs__item\"\n [class.fs-tabs__item--active]=\"isActive(tab)\"\n [class.fs-tabs__item--disabled]=\"tab.disabled\"\n role=\"tab\"\n [attr.aria-selected]=\"isActive(tab)\"\n [attr.aria-disabled]=\"tab.disabled\"\n [disabled]=\"tab.disabled\"\n (click)=\"selectTab(tab)\"\n >\n {{ tab.label }}\n </button>\n\n <!-- indicator deslizante -->\n <span\n class=\"fs-tabs__indicator\"\n [style.left.px]=\"indicatorLeft\"\n [style.width.px]=\"indicatorWidth\"\n aria-hidden=\"true\"\n ></span>\n\n </div>\n\n <!-- contenido vía content projection -->\n <div class=\"fs-tabs__content\" role=\"tabpanel\">\n <ng-content></ng-content>\n </div>\n\n</div>\n","import {\n Component,\n Input,\n Output,\n EventEmitter,\n OnInit,\n OnDestroy,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\n\nexport type FsAlertType = 'info' | 'success' | 'warning' | 'danger' | 'neutral';\nexport type FsAlertVariant = 'filled' | 'accent';\n\n@Component({\n selector: 'fs-alert',\n standalone: true,\n imports: [CommonModule],\n templateUrl: './alert.component.html',\n styleUrl: './alert.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FsAlertComponent implements OnInit, OnDestroy {\n\n /** Tipo semántico del alert */\n @Input() type: FsAlertType = 'info';\n\n /** filled = fondo sutil · accent = borde izquierdo */\n @Input() variant: FsAlertVariant = 'filled';\n\n /** Título opcional en negrita */\n @Input() title?: string;\n\n /** Muestra botón X para cerrar */\n @Input() dismissible = false;\n\n /**\n * Auto-cierre en milisegundos.\n * 0 = deshabilitado.\n * Muestra progress bar cuando está activo.\n */\n @Input() autoDismiss = 0;\n\n /** Emite cuando el alert se cierra (botón X o auto-dismiss) */\n @Output() dismissed = new EventEmitter<void>();\n\n // Estado interno de animación\n animState: 'entering' | 'visible' | 'exiting' = 'entering';\n\n private autoTimer?: ReturnType<typeof setTimeout>;\n\n constructor(private cdr: ChangeDetectorRef) {}\n\n ngOnInit(): void {\n // tras la animación de entrada → visible\n setTimeout(() => {\n this.animState = 'visible';\n this.cdr.markForCheck();\n }, 300);\n\n if (this.autoDismiss > 0) {\n this.autoTimer = setTimeout(() => this.dismiss(), this.autoDismiss);\n }\n }\n\n ngOnDestroy(): void {\n if (this.autoTimer) clearTimeout(this.autoTimer);\n }\n\n dismiss(): void {\n if (this.animState === 'exiting') return;\n this.animState = 'exiting';\n this.cdr.markForCheck();\n\n // esperar la animación de salida antes de emitir\n setTimeout(() => {\n this.dismissed.emit();\n }, 240);\n }\n\n get progressDuration(): string {\n return `${this.autoDismiss}ms`;\n }\n\n get iconPath(): string {\n const icons: Record<FsAlertType, string> = {\n info: 'M8 7v4M8 5.5v.01M2 8a6 6 0 1 0 12 0A6 6 0 0 0 2 8z',\n success: 'M5 8l2 2 4-4M2 8a6 6 0 1 0 12 0A6 6 0 0 0 2 8z',\n warning: 'M8 2L2 13h12L8 2zM8 7v3M8 11.5v.01',\n danger: 'M8 5v4M8 10.5v.01M2 8a6 6 0 1 0 12 0A6 6 0 0 0 2 8z',\n neutral: 'M8 7v4M8 5.5v.01M2 8a6 6 0 1 0 12 0A6 6 0 0 0 2 8z',\n };\n return icons[this.type];\n }\n}\n","<div\n *ngIf=\"animState !== 'exiting' || true\"\n class=\"fs-alert\"\n [class.fs-alert--entering]=\"animState === 'entering'\"\n [class.fs-alert--visible]=\"animState === 'visible'\"\n [class.fs-alert--exiting]=\"animState === 'exiting'\"\n [class]=\"'fs-alert fs-alert--' + type + ' fs-alert--' + variant\"\n [attr.role]=\"type === 'danger' ? 'alert' : 'status'\"\n [attr.aria-live]=\"type === 'danger' ? 'assertive' : 'polite'\"\n>\n\n <!-- ícono semántico -->\n <svg\n class=\"fs-alert__icon\"\n width=\"16\" height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n [attr.d]=\"iconPath\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n\n <!-- cuerpo -->\n <div class=\"fs-alert__body\">\n <div *ngIf=\"title\" class=\"fs-alert__title\">{{ title }}</div>\n <div class=\"fs-alert__desc\">\n <ng-content></ng-content>\n </div>\n </div>\n\n <!-- botón cerrar -->\n <button\n *ngIf=\"dismissible\"\n class=\"fs-alert__close\"\n type=\"button\"\n aria-label=\"Cerrar\"\n (click)=\"dismiss()\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path\n d=\"M3 3l8 8M11 3L3 11\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n\n <!-- progress bar de auto-dismiss -->\n <div\n *ngIf=\"autoDismiss > 0\"\n class=\"fs-alert__progress\"\n [style.animation-duration]=\"progressDuration\"\n ></div>\n\n</div>\n","import {\n Component,\n Input,\n OnInit,\n ChangeDetectionStrategy,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FsBadgeComponent, FsBadgeColor } from '../badge/badge.component';\n\nexport interface FsExperienceBadge {\n label: string;\n color?: FsBadgeColor;\n customColor?: string;\n iconLeft?: string;\n imgLeft?: string;\n imgLeftAlt?: string;\n}\n\nexport interface FsExperienceCard {\n /** Nombre de la empresa */\n company: string;\n\n /** Rol / puesto */\n role: string;\n\n /** Fecha de inicio — formato libre: 'abr 2022' */\n startDate: string;\n\n /** Fecha de fin — omitir si es trabajo actual */\n endDate?: string;\n\n /** Marca el trabajo como actual — muestra dot verde y \"actualidad\" */\n current?: boolean;\n\n /** Logo de la empresa — URL de imagen */\n logoUrl?: string;\n\n /** Texto corto para el logo cuando no hay imagen: 'X CALE' */\n logoText?: string;\n\n /** Lista de responsabilidades / bullets */\n bullets?: string[];\n\n /** Cuántos bullets mostrar antes del \"ver más\" */\n bulletsPreview?: number;\n\n /** Badges de tecnologías */\n badges?: FsExperienceBadge[];\n}\n\n@Component({\n selector: 'fs-experience-card',\n standalone: true,\n imports: [CommonModule, FsBadgeComponent],\n templateUrl: './experience-card.component.html',\n styleUrl: './experience-card.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FsExperienceCardComponent implements OnInit {\n\n /** Datos de la experiencia */\n @Input() experience!: FsExperienceCard;\n\n /** Variante de presentación */\n @Input() variant: 'full' | 'compact' = 'full';\n\n /** Muestra la línea vertical de timeline a la izquierda */\n @Input() timeline = false;\n\n /** Si es el último item del timeline (no dibuja la línea hacia abajo) */\n @Input() timelineLast = false;\n\n expanded = false;\n\n get hasBullets(): boolean {\n return !!(this.experience?.bullets?.length);\n }\n\n get visibleBullets(): string[] {\n if (!this.experience?.bullets) return [];\n const preview = this.experience.bulletsPreview ?? 3;\n return this.expanded\n ? this.experience.bullets\n : this.experience.bullets.slice(0, preview);\n }\n\n get hasMoreBullets(): boolean {\n if (!this.experience?.bullets) return false;\n const preview = this.experience.bulletsPreview ?? 3;\n return this.experience.bullets.length > preview;\n }\n\n get duration(): string {\n return this.calculateDuration();\n }\n\n get isCurrent(): boolean {\n return this.experience?.current ?? false;\n }\n\n ngOnInit(): void {\n this.expanded = false;\n }\n\n toggleExpand(): void {\n this.expanded = !this.expanded;\n }\n\n private calculateDuration(): string {\n if (!this.experience?.startDate) return '';\n\n const start = this.parseDate(this.experience.startDate);\n const end = this.experience.current || !this.experience.endDate\n ? new Date()\n : this.parseDate(this.experience.endDate);\n\n if (!start || !end) return '';\n\n let months = (end.getFullYear() - start.getFullYear()) * 12\n + (end.getMonth() - start.getMonth());\n\n const years = Math.floor(months / 12);\n const remain = months % 12;\n\n const parts: string[] = [];\n if (years > 0) parts.push(`${years} ${years === 1 ? 'año' : 'años'}`);\n if (remain > 0) parts.push(`${remain} ${remain === 1 ? 'mes' : 'meses'}`);\n\n return parts.join(' ');\n }\n\n private parseDate(dateStr: string): Date | null {\n const months: Record<string, number> = {\n ene: 0, feb: 1, mar: 2, abr: 3, may: 4, jun: 5,\n jul: 6, ago: 7, sep: 8, oct: 9, nov: 10, dic: 11,\n };\n\n const parts = dateStr.trim().toLowerCase().split(' ');\n if (parts.length === 2) {\n const month = months[parts[0]];\n const year = parseInt(parts[1], 10);\n if (month !== undefined && !isNaN(year)) {\n return new Date(year, month, 1);\n }\n }\n\n // fallback: intentar parsear como fecha estándar\n const d = new Date(dateStr);\n return isNaN(d.getTime()) ? null : d;\n }\n}\n","<div\n class=\"fs-exp\"\n [class.fs-exp--compact]=\"variant === 'compact'\"\n [class.fs-exp--timeline]=\"timeline\"\n [class.fs-exp--timeline-last]=\"timeline && timelineLast\"\n>\n\n <!-- línea vertical de timeline -->\n <div *ngIf=\"timeline\" class=\"fs-exp__timeline-line\"></div>\n\n <!-- dot del timeline -->\n <div *ngIf=\"timeline\" class=\"fs-exp__timeline-dot\"\n [class.fs-exp__timeline-dot--current]=\"isCurrent\">\n </div>\n\n <!-- card -->\n <div class=\"fs-exp__card\">\n\n <!-- header -->\n <div class=\"fs-exp__header\">\n\n <!-- logo -->\n <div class=\"fs-exp__logo\">\n <img\n *ngIf=\"experience.logoUrl\"\n [src]=\"experience.logoUrl\"\n [alt]=\"experience.company\"\n class=\"fs-exp__logo-img\"\n />\n <span *ngIf=\"!experience.logoUrl\" class=\"fs-exp__logo-text\">\n {{ experience.logoText || experience.company.slice(0, 4).toUpperCase() }}\n </span>\n </div>\n\n <!-- info -->\n <div class=\"fs-exp__info\">\n <div class=\"fs-exp__company\">{{ experience.company }}</div>\n <div class=\"fs-exp__role\">{{ experience.role }}</div>\n <div class=\"fs-exp__date\">\n <span\n class=\"fs-exp__dot\"\n [class.fs-exp__dot--current]=\"isCurrent\"\n ></span>\n <span>\n {{ experience.startDate }} –\n {{ experience.current ? 'actualidad' : experience.endDate }}\n </span>\n <span *ngIf=\"duration\" class=\"fs-exp__duration\">\n · {{ duration }}\n </span>\n </div>\n </div>\n\n </div>\n\n <!-- cuerpo — solo en variante full -->\n <ng-container *ngIf=\"variant === 'full'\">\n\n <div *ngIf=\"hasBullets || experience.badges?.length\" class=\"fs-exp__divider\"></div>\n\n <!-- bullets -->\n <ul *ngIf=\"hasBullets\" class=\"fs-exp__bullets\">\n <li *ngFor=\"let bullet of visibleBullets\" class=\"fs-exp__bullet\">\n <span class=\"fs-exp__bullet-arrow\" aria-hidden=\"true\">▸</span>\n <span>{{ bullet }}</span>\n </li>\n </ul>\n\n <!-- toggle ver más / menos -->\n <button\n *ngIf=\"hasMoreBullets\"\n class=\"fs-exp__toggle\"\n type=\"button\"\n (click)=\"toggleExpand()\"\n >\n <svg\n class=\"fs-exp__toggle-icon\"\n [class.fs-exp__toggle-icon--open]=\"expanded\"\n width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\"\n >\n <path d=\"M3 4.5l3 3 3-3\"\n stroke=\"currentColor\" stroke-width=\"1.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n {{ expanded ? 'ver menos' : 'ver más' }}\n </button>\n\n <!-- badges -->\n <div *ngIf=\"experience.badges?.length\" class=\"fs-exp__badges\">\n <fs-badge\n *ngFor=\"let badge of experience.badges\"\n [color]=\"badge.color || 'neutral'\"\n [customColor]=\"badge.customColor\"\n [iconLeft]=\"badge.iconLeft\"\n [imgLeft]=\"badge.imgLeft\"\n [imgLeftAlt]=\"badge.imgLeftAlt || ''\"\n variant=\"filled\"\n size=\"sm\"\n >{{ badge.label }}</fs-badge>\n </div>\n\n </ng-container>\n\n </div>\n</div>\n","import {\n Component,\n Input,\n Output,\n EventEmitter,\n ChangeDetectionStrategy,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FsBadgeComponent, FsBadgeColor } from '../badge/badge.component';\n\nexport interface FsProfileStat {\n value: string | number;\n label: string;\n}\n\nexport interface FsProfileLink {\n /** Texto visible */\n label: string;\n /** URL destino — se ignora si hay encodedEmail */\n url?: string;\n /**\n * Email codificado en base64 — tiene prioridad sobre url.\n * Generá el valor con btoa('tu@email.com') en la consola del browser.\n * El componente lo decodifica en runtime con atob() — nunca aparece\n * el mailto: en el HTML estático, protegiéndolo de email scrapers.\n * Ejemplo: btoa('johndoe@example.com') → 'am9obmRvZUBleGFtcGxlLmNvbQ=='\n */\n encodedEmail?: string;\n /** SVG path del ícono (viewBox 0 0 16 16) — se ignora si hay imgUrl */\n icon?: string;\n /**\n * URL o ruta de imagen para el ícono del link.\n * Ejemplo: 'https://cdn.simpleicons.org/linkedin/white'\n * Tiene prioridad sobre icon si ambos están definidos.\n */\n imgUrl?: string;\n /** Alt text para imgUrl — por defecto vacío (decorativo) */\n imgAlt?: string;\n}\n\nexport interface FsProfileBadge {\n label: string;\n color?: FsBadgeColor;\n customColor?: string;\n iconLeft?: string;\n imgLeft?: string;\n imgLeftAlt?: string;\n}\n\n@Component({\n selector: 'fs-profile-card',\n standalone: true,\n imports: [CommonModule, FsBadgeComponent],\n templateUrl: './profile-card.component.html',\n styleUrl: './profile-card.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FsProfileCardComponent {\n\n @Input() name = '';\n @Input() handle = '';\n @Input() role = '';\n @Input() verified = false;\n @Input() avatarUrl?: string;\n @Input() bannerUrl?: string;\n @Input() links: FsProfileLink[] = [];\n @Input() badges: FsProfileBadge[] = [];\n @Input() stats: FsProfileStat[] = [];\n @Input() showActions = false;\n @Input() primaryActionLabel = 'Seguir';\n @Input() secondaryActionLabel = 'Mensaje';\n\n @Output() primaryAction = new EventEmitter<void>();\n @Output() secondaryAction = new EventEmitter<void>();\n\n get initials(): string {\n return this.name\n .split(' ')\n .slice(0, 2)\n .map(w => w[0])\n .join('')\n .toUpperCase();\n }\n\n /**\n * Resuelve el href de un link.\n * Si tiene encodedEmail, lo decodifica con atob() y retorna 'mailto:email'.\n * Si tiene url, la retorna directamente.\n * Si no tiene ninguno, retorna null.\n */\n getLinkHref(link: FsProfileLink): string | null {\n if (link.encodedEmail) {\n try {\n return 'mailto:' + atob(link.encodedEmail);\n } catch {\n return null;\n }\n }\n return link.url ?? null;\n }\n}\n","<div class=\"fs-profile\">\n\n <!-- banner -->\n <div class=\"fs-profile__banner\">\n <img\n *ngIf=\"bannerUrl\"\n [src]=\"bannerUrl\"\n [alt]=\"name + ' banner'\"\n class=\"fs-profile__banner-img\"\n />\n <div *ngIf=\"!bannerUrl\" class=\"fs-profile__banner-gradient\"></div>\n <div class=\"fs-profile__banner-line\"></div>\n </div>\n\n <!-- body -->\n <div class=\"fs-profile__body\">\n\n <!-- avatar -->\n <div class=\"fs-profile__avatar-wrap\">\n <div class=\"fs-profile__avatar\">\n <img\n *ngIf=\"avatarUrl\"\n [src]=\"avatarUrl\"\n [alt]=\"name\"\n class=\"fs-profile__avatar-img\"\n />\n <span *ngIf=\"!avatarUrl\" class=\"fs-profile__avatar-initials\">\n {{ initials }}\n </span>\n </div>\n <div *ngIf=\"verified\" class=\"fs-profile__verified\" aria-label=\"Verificado\">\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M2 5l2 2 4-4\"\n stroke=\"white\" stroke-width=\"1.6\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n </div>\n\n <!-- identidad -->\n <div class=\"fs-profile__name\">{{ name }}</div>\n <div *ngIf=\"handle\" class=\"fs-profile__handle\">&#64;{{ handle }}</div>\n <div *ngIf=\"role\" class=\"fs-profile__role\">{{ role }}</div>\n\n <!-- acciones -->\n <div *ngIf=\"showActions\" class=\"fs-profile__actions\">\n <button\n class=\"fs-profile__btn fs-profile__btn--primary\"\n type=\"button\"\n (click)=\"primaryAction.emit()\"\n >\n {{ primaryActionLabel }}\n </button>\n <button\n class=\"fs-profile__btn fs-profile__btn--outline\"\n type=\"button\"\n (click)=\"secondaryAction.emit()\"\n >\n {{ secondaryActionLabel }}\n </button>\n </div>\n\n <!-- links -->\n <div *ngIf=\"links.length\" class=\"fs-profile__links\">\n <a\n *ngFor=\"let link of links\"\n class=\"fs-profile__link\"\n [href]=\"getLinkHref(link) || '#'\"\n [attr.target]=\"link.url && !link.encodedEmail ? '_blank' : null\"\n [attr.rel]=\"link.url && !link.encodedEmail ? 'noopener noreferrer' : null\"\n >\n <!-- imagen del link (prioridad sobre icon SVG) -->\n <img\n *ngIf=\"link.imgUrl\"\n [src]=\"link.imgUrl\"\n [alt]=\"link.imgAlt || ''\"\n class=\"fs-profile__link-img\"\n aria-hidden=\"true\"\n />\n <!-- ícono SVG (solo si no hay imgUrl) -->\n <svg\n *ngIf=\"link.icon && !link.imgUrl\"\n width=\"12\" height=\"12\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path [attr.d]=\"link.icon\" stroke=\"currentColor\" stroke-width=\"1.3\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span>{{ link.label }}</span>\n </a>\n </div>\n\n <!-- badges -->\n <div *ngIf=\"badges.length\" class=\"fs-profile__badges\">\n <fs-badge\n *ngFor=\"let badge of badges\"\n [color]=\"badge.color || 'neutral'\"\n [customColor]=\"badge.customColor\"\n [iconLeft]=\"badge.iconLeft\"\n [imgLeft]=\"badge.imgLeft\"\n [imgLeftAlt]=\"badge.imgLeftAlt || ''\"\n variant=\"filled\"\n size=\"sm\"\n >{{ badge.label }}</fs-badge>\n </div>\n\n </div>\n\n <!-- stats footer -->\n <div *ngIf=\"stats.length\" class=\"fs-profile__stats\">\n <div *ngFor=\"let stat of stats\" class=\"fs-profile__stat\">\n <span class=\"fs-profile__stat-value\">{{ stat.value }}</span>\n <span class=\"fs-profile__stat-label\">{{ stat.label }}</span>\n </div>\n </div>\n\n</div>\n","/*\r\n * Public API Surface of fsociety\r\n */\r\n\r\nexport * from './lib/fsociety.service';\r\nexport * from './lib/fsociety.component';\r\n\r\nexport * from './lib/button/button.component';\r\nexport type { FsButtonVariant, FsButtonSize, FsButtonType } from './lib/button/button.component';\r\n\r\nexport * from './lib/badge/badge.component';\r\nexport type { FsBadgeColor, FsBadgeVariant, FsBadgeSize } from './lib/badge/badge.component';\r\n\r\nexport * from './lib/tabs/tabs.component';\r\nexport type { FsTab } from './lib/tabs/tabs.component';\r\n\r\nexport * from './lib/alert/alert.component';\r\nexport type { FsAlertType, FsAlertVariant } from './lib/alert/alert.component';\r\n\r\nexport * from './lib/experience-card/experience-card.component';\r\nexport type { FsExperienceCard, FsExperienceBadge } from './lib/experience-card/experience-card.component';\r\n\r\nexport * from './lib/profile-card/profile-card.component';\r\nexport type { FsProfileStat, FsProfileLink, FsProfileBadge } from './lib/profile-card/profile-card.component';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1,11 +1,18 @@
1
- import { EventEmitter } from '@angular/core';
1
+ import { EventEmitter, OnChanges } from '@angular/core';
2
2
  import * as i0 from "@angular/core";
3
3
  export type FsBadgeColor = 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'danger' | 'neutral';
4
4
  export type FsBadgeVariant = 'filled' | 'outline';
5
5
  export type FsBadgeSize = 'sm' | 'md';
6
- export declare class FsBadgeComponent {
6
+ export declare class FsBadgeComponent implements OnChanges {
7
7
  /** Color semántico del badge */
8
8
  color: FsBadgeColor;
9
+ /**
10
+ * Color personalizado en formato hex.
11
+ * Ejemplo: '#7c3aed'
12
+ * Cuando se provee, tiene prioridad sobre `color` y genera
13
+ * automáticamente el fondo, borde y texto con la opacidad correcta.
14
+ */
15
+ customColor?: string;
9
16
  /** Filled = fondo sutil · outline = solo borde */
10
17
  variant: FsBadgeVariant;
11
18
  /** Tamaño */
@@ -14,17 +21,13 @@ export declare class FsBadgeComponent {
14
21
  label?: string;
15
22
  /** Muestra punto de estado a la izquierda */
16
23
  dot: boolean;
17
- /**
18
- * SVG path del ícono izquierdo (viewBox 0 0 24 24).
19
- */
24
+ /** SVG path del ícono izquierdo (viewBox 0 0 24 24) */
20
25
  iconLeft?: string;
21
- /**
22
- * SVG path del ícono derecho (viewBox 0 0 24 24).
23
- */
26
+ /** SVG path del ícono derecho (viewBox 0 0 24 24) */
24
27
  iconRight?: string;
25
28
  /**
26
29
  * URL o ruta de imagen izquierda.
27
- * Ejemplo: 'assets/icons/angular.svg' o 'https://...'
30
+ * Ejemplo: 'assets/icons/angular.svg' o 'https://cdn.simpleicons.org/angular/white'
28
31
  * Tiene prioridad sobre iconLeft si ambos están definidos.
29
32
  */
30
33
  imgLeft?: string;
@@ -46,8 +49,12 @@ export declare class FsBadgeComponent {
46
49
  removable: boolean;
47
50
  /** Emite cuando se clickea el botón remove */
48
51
  removed: EventEmitter<void>;
52
+ customStyles: Record<string, string>;
53
+ ngOnChanges(): void;
49
54
  get classes(): Record<string, boolean>;
50
55
  onRemove(event: MouseEvent): void;
56
+ private buildCustomStyles;
57
+ private lightenHex;
51
58
  static ɵfac: i0.ɵɵFactoryDeclaration<FsBadgeComponent, never>;
52
- static ɵcmp: i0.ɵɵComponentDeclaration<FsBadgeComponent, "fs-badge", never, { "color": { "alias": "color"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "size": { "alias": "size"; "required": false; }; "label": { "alias": "label"; "required": false; }; "dot": { "alias": "dot"; "required": false; }; "iconLeft": { "alias": "iconLeft"; "required": false; }; "iconRight": { "alias": "iconRight"; "required": false; }; "imgLeft": { "alias": "imgLeft"; "required": false; }; "imgRight": { "alias": "imgRight"; "required": false; }; "imgLeftAlt": { "alias": "imgLeftAlt"; "required": false; }; "imgRightAlt": { "alias": "imgRightAlt"; "required": false; }; "iconOnly": { "alias": "iconOnly"; "required": false; }; "removable": { "alias": "removable"; "required": false; }; }, { "removed": "removed"; }, never, ["*"], true, never>;
59
+ static ɵcmp: i0.ɵɵComponentDeclaration<FsBadgeComponent, "fs-badge", never, { "color": { "alias": "color"; "required": false; }; "customColor": { "alias": "customColor"; "required": false; }; "variant": { "alias": "variant"; "required": false; }; "size": { "alias": "size"; "required": false; }; "label": { "alias": "label"; "required": false; }; "dot": { "alias": "dot"; "required": false; }; "iconLeft": { "alias": "iconLeft"; "required": false; }; "iconRight": { "alias": "iconRight"; "required": false; }; "imgLeft": { "alias": "imgLeft"; "required": false; }; "imgRight": { "alias": "imgRight"; "required": false; }; "imgLeftAlt": { "alias": "imgLeftAlt"; "required": false; }; "imgRightAlt": { "alias": "imgRightAlt"; "required": false; }; "iconOnly": { "alias": "iconOnly"; "required": false; }; "removable": { "alias": "removable"; "required": false; }; }, { "removed": "removed"; }, never, ["*"], true, never>;
53
60
  }
@@ -4,7 +4,10 @@ import * as i0 from "@angular/core";
4
4
  export interface FsExperienceBadge {
5
5
  label: string;
6
6
  color?: FsBadgeColor;
7
+ customColor?: string;
7
8
  iconLeft?: string;
9
+ imgLeft?: string;
10
+ imgLeftAlt?: string;
8
11
  }
9
12
  export interface FsExperienceCard {
10
13
  /** Nombre de la empresa */
@@ -2,64 +2,64 @@ import { EventEmitter } from '@angular/core';
2
2
  import { FsBadgeColor } from '../badge/badge.component';
3
3
  import * as i0 from "@angular/core";
4
4
  export interface FsProfileStat {
5
- /** Valor principal: '4+', '985', '12' */
6
5
  value: string | number;
7
- /** Etiqueta debajo del valor */
8
6
  label: string;
9
7
  }
10
8
  export interface FsProfileLink {
11
9
  /** Texto visible */
12
10
  label: string;
13
- /** URL destino */
11
+ /** URL destino — se ignora si hay encodedEmail */
14
12
  url?: string;
15
- /** SVG path del ícono (viewBox 0 0 16 16) */
13
+ /**
14
+ * Email codificado en base64 — tiene prioridad sobre url.
15
+ * Generá el valor con btoa('tu@email.com') en la consola del browser.
16
+ * El componente lo decodifica en runtime con atob() — nunca aparece
17
+ * el mailto: en el HTML estático, protegiéndolo de email scrapers.
18
+ * Ejemplo: btoa('johndoe@example.com') → 'am9obmRvZUBleGFtcGxlLmNvbQ=='
19
+ */
20
+ encodedEmail?: string;
21
+ /** SVG path del ícono (viewBox 0 0 16 16) — se ignora si hay imgUrl */
16
22
  icon?: string;
23
+ /**
24
+ * URL o ruta de imagen para el ícono del link.
25
+ * Ejemplo: 'https://cdn.simpleicons.org/linkedin/white'
26
+ * Tiene prioridad sobre icon si ambos están definidos.
27
+ */
28
+ imgUrl?: string;
29
+ /** Alt text para imgUrl — por defecto vacío (decorativo) */
30
+ imgAlt?: string;
17
31
  }
18
32
  export interface FsProfileBadge {
19
33
  label: string;
20
34
  color?: FsBadgeColor;
35
+ customColor?: string;
21
36
  iconLeft?: string;
37
+ imgLeft?: string;
38
+ imgLeftAlt?: string;
22
39
  }
23
40
  export declare class FsProfileCardComponent {
24
- /** Nombre completo */
25
41
  name: string;
26
- /** Handle sin @ */
27
42
  handle: string;
28
- /** Rol / título */
29
43
  role: string;
30
- /** Muestra el badge de verificado */
31
44
  verified: boolean;
32
- /**
33
- * URL de la foto de perfil.
34
- * Si no se provee, se muestran las iniciales.
35
- */
36
45
  avatarUrl?: string;
37
- /**
38
- * URL de imagen para el banner.
39
- * Si no se provee, se usa el degradé navy por defecto.
40
- */
41
46
  bannerUrl?: string;
42
- /** Links de redes sociales / ubicación */
43
47
  links: FsProfileLink[];
44
- /** Badges de tecnologías */
45
48
  badges: FsProfileBadge[];
46
- /**
47
- * Stats configurables: años de exp., proyectos, seguidores, etc.
48
- * Array de { value, label } — se muestran todos en el footer.
49
- */
50
49
  stats: FsProfileStat[];
51
- /**
52
- * Muestra los botones de acción (Seguir / Mensaje).
53
- * false = variante readonly / portfolio propio.
54
- */
55
50
  showActions: boolean;
56
- /** Label del botón primario */
57
51
  primaryActionLabel: string;
58
- /** Label del botón secundario */
59
52
  secondaryActionLabel: string;
60
53
  primaryAction: EventEmitter<void>;
61
54
  secondaryAction: EventEmitter<void>;
62
55
  get initials(): string;
56
+ /**
57
+ * Resuelve el href de un link.
58
+ * Si tiene encodedEmail, lo decodifica con atob() y retorna 'mailto:email'.
59
+ * Si tiene url, la retorna directamente.
60
+ * Si no tiene ninguno, retorna null.
61
+ */
62
+ getLinkHref(link: FsProfileLink): string | null;
63
63
  static ɵfac: i0.ɵɵFactoryDeclaration<FsProfileCardComponent, never>;
64
64
  static ɵcmp: i0.ɵɵComponentDeclaration<FsProfileCardComponent, "fs-profile-card", never, { "name": { "alias": "name"; "required": false; }; "handle": { "alias": "handle"; "required": false; }; "role": { "alias": "role"; "required": false; }; "verified": { "alias": "verified"; "required": false; }; "avatarUrl": { "alias": "avatarUrl"; "required": false; }; "bannerUrl": { "alias": "bannerUrl"; "required": false; }; "links": { "alias": "links"; "required": false; }; "badges": { "alias": "badges"; "required": false; }; "stats": { "alias": "stats"; "required": false; }; "showActions": { "alias": "showActions"; "required": false; }; "primaryActionLabel": { "alias": "primaryActionLabel"; "required": false; }; "secondaryActionLabel": { "alias": "secondaryActionLabel"; "required": false; }; }, { "primaryAction": "primaryAction"; "secondaryAction": "secondaryAction"; }, never, never, true, never>;
65
65
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heroelc/fsociety",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "Angular component library with design system tokens, mixins and UI components",
5
5
  "author": "Heroel Carpinetti <heroeljcarpinetti@gmail.com>",
6
6
  "license": "MIT",