@metropolle/design-system 1.2026.0-1.7.15 → 1.2026.0-1.7.2346

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.
@@ -1470,6 +1470,125 @@ const GlassCard = require$$0.forwardRef(({ glassStyle = 'liquid', intensity = 'm
1470
1470
  });
1471
1471
  GlassCard.displayName = 'GlassCard';
1472
1472
 
1473
+ // Default placeholder avatar - adapts to theme with high transparency
1474
+ const getPlaceholderAvatar = (isDark) => {
1475
+ const bgColor = isDark ? 'rgba(26, 26, 46, 0.15)' : 'rgba(255, 255, 255, 0.1)';
1476
+ const fgColor = isDark ? 'rgba(255, 255, 255, 0.08)' : 'rgba(0, 0, 0, 0.06)';
1477
+ return 'data:image/svg+xml,' + encodeURIComponent(`
1478
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" fill="none">
1479
+ <rect width="200" height="200" fill="${bgColor}"/>
1480
+ <circle cx="100" cy="80" r="40" fill="${fgColor}"/>
1481
+ <ellipse cx="100" cy="180" rx="60" ry="50" fill="${fgColor}"/>
1482
+ </svg>
1483
+ `);
1484
+ };
1485
+ // =============================================================================
1486
+ // Icons
1487
+ // =============================================================================
1488
+ const Icons = {
1489
+ shield: (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", children: jsxRuntimeExports.jsx("path", { d: "M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm-2 16l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z", fill: "currentColor" }) })),
1490
+ plus: (jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", children: jsxRuntimeExports.jsx("path", { d: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z", fill: "currentColor" }) })),
1491
+ instagram: jsxRuntimeExports.jsx("path", { d: "M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z" }),
1492
+ x: jsxRuntimeExports.jsx("path", { d: "M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" }),
1493
+ linkedin: jsxRuntimeExports.jsx("path", { d: "M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" }),
1494
+ website: jsxRuntimeExports.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z" }),
1495
+ };
1496
+ function SocialLink({ href, title, icon }) {
1497
+ const iconPath = Icons[icon];
1498
+ if (!iconPath || typeof iconPath === 'object')
1499
+ return null;
1500
+ return (jsxRuntimeExports.jsx("a", { href: href, className: "mds-profile-card__social-link", title: title, target: "_blank", rel: "noopener noreferrer", children: jsxRuntimeExports.jsx("svg", { viewBox: "0 0 24 24", children: iconPath }) }));
1501
+ }
1502
+ function StatItem({ label, verified }) {
1503
+ return (jsxRuntimeExports.jsxs("div", { className: "mds-profile-card__stat-item", children: [jsxRuntimeExports.jsx("span", { className: "mds-profile-card__stat-label", children: label }), jsxRuntimeExports.jsx("span", { className: `mds-profile-card__stat-value ${verified ? 'mds-profile-card__stat-value--verified' : ''}`, children: verified ? 'Verified' : 'Not Verified' })] }));
1504
+ }
1505
+ // =============================================================================
1506
+ // Main Component
1507
+ // =============================================================================
1508
+ function ProfileCard({ user, variant = 'full', photoWidth, showSocial = false, socialLinks, showRotatingInfo = false, photoSlot, className = '', onSocialClick, }) {
1509
+ const [showVerifiedPopup, setShowVerifiedPopup] = require$$0.useState(false);
1510
+ const [showSocialPopup, setShowSocialPopup] = require$$0.useState(false);
1511
+ const [currentInfoIndex, setCurrentInfoIndex] = require$$0.useState(0);
1512
+ const [isDarkTheme, setIsDarkTheme] = require$$0.useState(true);
1513
+ const verifiedRef = require$$0.useRef(null);
1514
+ const socialRef = require$$0.useRef(null);
1515
+ // Calculate photo width based on variant
1516
+ const computedPhotoWidth = photoWidth ?? (variant === 'full' ? 280 : 200);
1517
+ // Detect theme
1518
+ require$$0.useEffect(() => {
1519
+ const checkTheme = () => {
1520
+ const theme = document.documentElement.getAttribute('data-theme');
1521
+ setIsDarkTheme(theme !== 'light');
1522
+ };
1523
+ checkTheme();
1524
+ const observer = new MutationObserver((mutations) => {
1525
+ mutations.forEach((mutation) => {
1526
+ if (mutation.attributeName === 'data-theme') {
1527
+ checkTheme();
1528
+ }
1529
+ });
1530
+ });
1531
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
1532
+ return () => observer.disconnect();
1533
+ }, []);
1534
+ // Dynamic info texts for rotating display
1535
+ const infoTexts = [
1536
+ `Member since ${new Date(user.created_at).getFullYear()}`,
1537
+ ...(user.verified >= 1 ? ['Email Verified'] : []),
1538
+ ...(user.verified >= 2 ? ['Identity Verified'] : []),
1539
+ ...(user.verified >= 3 ? ['Professional Verified'] : []),
1540
+ ];
1541
+ // Rotate info text
1542
+ require$$0.useEffect(() => {
1543
+ if (!showRotatingInfo)
1544
+ return;
1545
+ const interval = setInterval(() => {
1546
+ setCurrentInfoIndex((prev) => (prev + 1) % infoTexts.length);
1547
+ }, 10000);
1548
+ return () => clearInterval(interval);
1549
+ }, [infoTexts.length, showRotatingInfo]);
1550
+ // Close popups on click outside
1551
+ require$$0.useEffect(() => {
1552
+ const handleClickOutside = (e) => {
1553
+ if (verifiedRef.current && !verifiedRef.current.contains(e.target)) {
1554
+ setShowVerifiedPopup(false);
1555
+ }
1556
+ if (socialRef.current && !socialRef.current.contains(e.target)) {
1557
+ setShowSocialPopup(false);
1558
+ }
1559
+ };
1560
+ document.addEventListener('click', handleClickOutside);
1561
+ return () => document.removeEventListener('click', handleClickOutside);
1562
+ }, []);
1563
+ // Get display values
1564
+ const displayName = user.full_name || user.username || 'User';
1565
+ const profession = user.profession_name || user.profession_code || '';
1566
+ const getLocation = () => {
1567
+ if (!user.city_code && !user.state_code && !user.country_code)
1568
+ return null;
1569
+ const city = user.city_name || user.city_code?.toUpperCase() || '';
1570
+ const state = user.state_code?.toUpperCase() || '';
1571
+ const country = user.country_name || user.country_code?.toUpperCase() || '';
1572
+ const parts = [city, state, country].filter(Boolean);
1573
+ return parts.join(', ');
1574
+ };
1575
+ const memberSince = new Date(user.created_at).getFullYear().toString();
1576
+ const photoUrl = user.photo_url_medium || user.photo_url_full || getPlaceholderAvatar(isDarkTheme);
1577
+ return (jsxRuntimeExports.jsxs("article", { className: `mds-profile-card ${className}`, style: { '--mds-profile-card-photo-width': `${computedPhotoWidth}px` }, children: [jsxRuntimeExports.jsx("div", { className: "mds-profile-card__grain" }), jsxRuntimeExports.jsx("div", { className: "mds-profile-card__photo", children: photoSlot ? (jsxRuntimeExports.jsx("div", { className: "mds-profile-card__photo-slot", children: photoSlot })) : (jsxRuntimeExports.jsx("img", { src: photoUrl, alt: displayName, className: "mds-profile-card__avatar" })) }), jsxRuntimeExports.jsxs("div", { className: "mds-profile-card__content", children: [jsxRuntimeExports.jsxs("div", { className: "mds-profile-card__identity", children: [jsxRuntimeExports.jsx("h1", { className: "mds-profile-card__name", children: displayName.toUpperCase() }), variant === 'full' && profession && (jsxRuntimeExports.jsx("p", { className: "mds-profile-card__profession", children: profession.toUpperCase() })), variant === 'compact' && (jsxRuntimeExports.jsx("p", { className: "mds-profile-card__username", children: user.username }))] }), jsxRuntimeExports.jsxs("div", { className: "mds-profile-card__details", children: [variant === 'full' && getLocation() && (jsxRuntimeExports.jsx("p", { className: "mds-profile-card__location", children: getLocation() })), variant === 'full' && (jsxRuntimeExports.jsx("span", { className: "mds-profile-card__username-detail", children: user.username })), variant === 'compact' && user.email && (jsxRuntimeExports.jsx("p", { className: "mds-profile-card__email", children: user.email })), variant === 'compact' && (jsxRuntimeExports.jsxs("span", { className: "mds-profile-card__member", children: ["Member since ", memberSince] }))] }), variant === 'compact' && (jsxRuntimeExports.jsxs("div", { className: "mds-profile-card__verification", children: [jsxRuntimeExports.jsxs("button", { className: "mds-profile-card__verified-badge", title: `Verification Level ${user.verified}`, onClick: (e) => {
1578
+ e.stopPropagation();
1579
+ setShowVerifiedPopup(!showVerifiedPopup);
1580
+ }, children: [Icons.shield, jsxRuntimeExports.jsxs("span", { children: ["Level ", user.verified] })] }), jsxRuntimeExports.jsxs("div", { className: "mds-profile-card__dots", children: [jsxRuntimeExports.jsx("span", { className: `mds-profile-card__dot ${user.verified >= 1 ? 'active' : ''}`, title: "Email Verified" }), jsxRuntimeExports.jsx("span", { className: `mds-profile-card__dot ${user.verified >= 2 ? 'active' : ''}`, title: "Identity Verified" }), jsxRuntimeExports.jsx("span", { className: `mds-profile-card__dot ${user.verified >= 3 ? 'active' : ''}`, title: "Professional Verified" })] })] })), showSocial && (jsxRuntimeExports.jsxs("div", { ref: socialRef, className: "mds-profile-card__social", children: [jsxRuntimeExports.jsx("button", { className: "mds-profile-card__social-trigger", onClick: (e) => {
1581
+ e.stopPropagation();
1582
+ setShowSocialPopup(!showSocialPopup);
1583
+ setShowVerifiedPopup(false);
1584
+ onSocialClick?.();
1585
+ }, "aria-label": "Show social links", children: Icons.plus }), showSocialPopup && socialLinks && (jsxRuntimeExports.jsxs("div", { className: "mds-profile-card__social-popup", children: [socialLinks.instagram && jsxRuntimeExports.jsx(SocialLink, { href: socialLinks.instagram, title: "Instagram", icon: "instagram" }), socialLinks.x && jsxRuntimeExports.jsx(SocialLink, { href: socialLinks.x, title: "X", icon: "x" }), socialLinks.linkedin && jsxRuntimeExports.jsx(SocialLink, { href: socialLinks.linkedin, title: "LinkedIn", icon: "linkedin" }), socialLinks.website && jsxRuntimeExports.jsx(SocialLink, { href: socialLinks.website, title: "Website", icon: "website" })] }))] })), variant === 'full' && (jsxRuntimeExports.jsxs("div", { className: "mds-profile-card__dynamic-group", children: [showRotatingInfo && (jsxRuntimeExports.jsx("span", { className: "mds-profile-card__dynamic-info", children: infoTexts[currentInfoIndex] })), jsxRuntimeExports.jsxs("div", { ref: verifiedRef, className: "mds-profile-card__verified-section", children: [jsxRuntimeExports.jsx("button", { className: "mds-profile-card__verified-trigger", onClick: (e) => {
1586
+ e.stopPropagation();
1587
+ setShowVerifiedPopup(!showVerifiedPopup);
1588
+ setShowSocialPopup(false);
1589
+ }, title: "Verification Status", children: Icons.shield }), showVerifiedPopup && (jsxRuntimeExports.jsxs("div", { className: "mds-profile-card__verified-popup", children: [jsxRuntimeExports.jsxs("div", { className: "mds-profile-card__verified-header", children: ["Verification Level ", user.verified] }), jsxRuntimeExports.jsxs("div", { className: "mds-profile-card__verified-stats", children: [jsxRuntimeExports.jsx(StatItem, { label: "Email", verified: user.verified >= 1 }), jsxRuntimeExports.jsx(StatItem, { label: "Identity", verified: user.verified >= 2 }), jsxRuntimeExports.jsx(StatItem, { label: "Professional", verified: user.verified >= 3 })] }), jsxRuntimeExports.jsxs("div", { className: "mds-profile-card__verified-date", children: ["Since ", memberSince] })] }))] }), showRotatingInfo && (jsxRuntimeExports.jsx("div", { className: "mds-profile-card__info-dots", children: infoTexts.map((_, index) => (jsxRuntimeExports.jsx("span", { className: `mds-profile-card__info-dot ${index === currentInfoIndex ? 'active' : ''}` }, index))) }))] }))] })] }));
1590
+ }
1591
+
1473
1592
  const variantElementMap = {
1474
1593
  h1: 'h1',
1475
1594
  h2: 'h2',
@@ -2961,6 +3080,7 @@ exports.Modal = Modal;
2961
3080
  exports.ModalBody = ModalBody;
2962
3081
  exports.ModalFooter = ModalFooter;
2963
3082
  exports.ModalHeader = ModalHeader;
3083
+ exports.ProfileCard = ProfileCard;
2964
3084
  exports.Select = Select;
2965
3085
  exports.TableHeader = TableHeader;
2966
3086
  exports.TableRow = TableRow;