@metropolle/design-system 1.2025.1-2.5.1903 → 1.2026.0-1.10.2344
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.
- package/dist/css/compat/back.css +12 -0
- package/dist/css/components.css +2594 -144
- package/dist/css/liquid-glass.css +468 -0
- package/dist/react/components/react/Button/Button.d.ts +1 -1
- package/dist/react/components/react/Button/Button.d.ts.map +1 -1
- package/dist/react/components/react/DataTable/DataTable.d.ts.map +1 -1
- package/dist/react/components/react/DataTable/TableHeader.d.ts.map +1 -1
- package/dist/react/components/react/DataTable/TableRow.d.ts.map +1 -1
- package/dist/react/components/react/DataTable/types.d.ts +2 -1
- package/dist/react/components/react/DataTable/types.d.ts.map +1 -1
- package/dist/react/components/react/DetailModal/DetailModal.d.ts +55 -0
- package/dist/react/components/react/DetailModal/DetailModal.d.ts.map +1 -0
- package/dist/react/components/react/DetailModal/index.d.ts +3 -0
- package/dist/react/components/react/DetailModal/index.d.ts.map +1 -0
- package/dist/react/components/react/FormField/FormField.d.ts +26 -0
- package/dist/react/components/react/FormField/FormField.d.ts.map +1 -0
- package/dist/react/components/react/FormField/index.d.ts +3 -0
- package/dist/react/components/react/FormField/index.d.ts.map +1 -0
- package/dist/react/components/react/FormGrid/FormGrid.d.ts +20 -0
- package/dist/react/components/react/FormGrid/FormGrid.d.ts.map +1 -0
- package/dist/react/components/react/FormGrid/index.d.ts +3 -0
- package/dist/react/components/react/FormGrid/index.d.ts.map +1 -0
- package/dist/react/components/react/FormModal/FormModal.d.ts +58 -0
- package/dist/react/components/react/FormModal/FormModal.d.ts.map +1 -0
- package/dist/react/components/react/FormModal/index.d.ts +3 -0
- package/dist/react/components/react/FormModal/index.d.ts.map +1 -0
- package/dist/react/components/react/FormSection/FormSection.d.ts +20 -0
- package/dist/react/components/react/FormSection/FormSection.d.ts.map +1 -0
- package/dist/react/components/react/FormSection/index.d.ts +3 -0
- package/dist/react/components/react/FormSection/index.d.ts.map +1 -0
- package/dist/react/components/react/GlassCard/GlassCard.d.ts +56 -6
- package/dist/react/components/react/GlassCard/GlassCard.d.ts.map +1 -1
- package/dist/react/components/react/GlassCard/index.d.ts +1 -1
- package/dist/react/components/react/GlassCard/index.d.ts.map +1 -1
- package/dist/react/components/react/InfoBox/InfoBox.d.ts +46 -0
- package/dist/react/components/react/InfoBox/InfoBox.d.ts.map +1 -0
- package/dist/react/components/react/InfoBox/index.d.ts +3 -0
- package/dist/react/components/react/InfoBox/index.d.ts.map +1 -0
- package/dist/react/components/react/Modal/Modal.d.ts.map +1 -1
- package/dist/react/components/react/Modal/ModalHeader.d.ts.map +1 -1
- package/dist/react/components/react/ProfileCard/ProfileCard.d.ts +55 -0
- package/dist/react/components/react/ProfileCard/ProfileCard.d.ts.map +1 -0
- package/dist/react/components/react/ProfileCard/index.d.ts +3 -0
- package/dist/react/components/react/ProfileCard/index.d.ts.map +1 -0
- package/dist/react/components/react/Select/Select.d.ts +61 -10
- package/dist/react/components/react/Select/Select.d.ts.map +1 -1
- package/dist/react/components/react/index.d.ts +15 -1
- package/dist/react/components/react/index.d.ts.map +1 -1
- package/dist/react/index.d.ts +32 -18
- package/dist/react/index.esm.js +826 -77
- package/dist/react/index.esm.js.map +1 -1
- package/dist/react/index.js +832 -75
- package/dist/react/index.js.map +1 -1
- package/package.json +5 -2
package/dist/react/index.js
CHANGED
|
@@ -1372,12 +1372,47 @@ function cn(...classes) {
|
|
|
1372
1372
|
/**
|
|
1373
1373
|
* Glass Card Component
|
|
1374
1374
|
*
|
|
1375
|
-
* Componente de cartão com efeito glassmorphism
|
|
1376
|
-
*
|
|
1375
|
+
* Componente de cartão com efeito glassmorphism ou Liquid Glass (iOS 26 style).
|
|
1376
|
+
*
|
|
1377
|
+
* @example
|
|
1378
|
+
* ```tsx
|
|
1379
|
+
* // Liquid Glass (novo padrão)
|
|
1380
|
+
* <GlassCard glassStyle="liquid" intensity="md">
|
|
1381
|
+
* Content here
|
|
1382
|
+
* </GlassCard>
|
|
1383
|
+
*
|
|
1384
|
+
* // Glassmorphism tradicional (retrocompatível)
|
|
1385
|
+
* <GlassCard glassStyle="glass" variant="dark">
|
|
1386
|
+
* Content here
|
|
1387
|
+
* </GlassCard>
|
|
1388
|
+
* ```
|
|
1377
1389
|
*/
|
|
1378
|
-
const GlassCard = require$$0.forwardRef(({
|
|
1390
|
+
const GlassCard = require$$0.forwardRef(({ glassStyle = 'liquid', intensity = 'md', theme, variant = 'light', blur, opacity, children, className, enableHover = true, cardVariant = 'default', style, ...props }, ref) => {
|
|
1391
|
+
// Resolve theme from new prop or deprecated variant
|
|
1392
|
+
const resolvedTheme = theme ?? variant;
|
|
1393
|
+
// =====================
|
|
1394
|
+
// LIQUID GLASS MODE
|
|
1395
|
+
// =====================
|
|
1396
|
+
if (glassStyle === 'liquid') {
|
|
1397
|
+
// PROC-007: Card variant styles
|
|
1398
|
+
const variantStyles = {
|
|
1399
|
+
default: {},
|
|
1400
|
+
highlight: {
|
|
1401
|
+
borderLeft: '4px solid var(--mds-color-brand-primary, #0055FF)',
|
|
1402
|
+
boxShadow: '0 4px 20px rgba(0, 85, 255, 0.15)'
|
|
1403
|
+
},
|
|
1404
|
+
subtle: {
|
|
1405
|
+
background: 'rgba(255, 255, 255, 0.02)',
|
|
1406
|
+
border: '1px solid rgba(255, 255, 255, 0.05)'
|
|
1407
|
+
}
|
|
1408
|
+
};
|
|
1409
|
+
return (jsxRuntimeExports.jsx("div", { ref: ref, className: cn('mds-liquid-glass', `mds-liquid-glass--${intensity}`, `mds-liquid-glass--${cardVariant}`, !enableHover && 'mds-liquid-glass--no-hover', className), style: { ...variantStyles[cardVariant], ...style }, ...props, children: children }));
|
|
1410
|
+
}
|
|
1411
|
+
// =====================
|
|
1412
|
+
// GLASS MODE (legacy)
|
|
1413
|
+
// =====================
|
|
1379
1414
|
// Default opacities baseadas no design existente
|
|
1380
|
-
const defaultOpacity =
|
|
1415
|
+
const defaultOpacity = resolvedTheme === 'light' ? 0.15 : 0.8;
|
|
1381
1416
|
const finalOpacity = opacity ?? defaultOpacity;
|
|
1382
1417
|
// Use CSS classes for base styles to avoid hydration mismatches
|
|
1383
1418
|
const baseStyles = {
|
|
@@ -1385,12 +1420,16 @@ const GlassCard = require$$0.forwardRef(({ variant = 'light', blur = 20, opacity
|
|
|
1385
1420
|
};
|
|
1386
1421
|
// Only apply custom styles for non-default values
|
|
1387
1422
|
const customStyles = {};
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1423
|
+
// Support legacy blur prop or convert from intensity
|
|
1424
|
+
const resolvedBlur = blur ?? (intensity ? {
|
|
1425
|
+
xs: 2, sm: 4, md: 6, lg: 8, xl: 12
|
|
1426
|
+
}[intensity] : 20);
|
|
1427
|
+
if (resolvedBlur !== 20) {
|
|
1428
|
+
customStyles.backdropFilter = `blur(${resolvedBlur}px)`;
|
|
1429
|
+
customStyles.WebkitBackdropFilter = `blur(${resolvedBlur}px)`;
|
|
1391
1430
|
}
|
|
1392
1431
|
if (opacity !== undefined) {
|
|
1393
|
-
customStyles.background =
|
|
1432
|
+
customStyles.background = resolvedTheme === 'light'
|
|
1394
1433
|
? `rgba(255, 255, 255, ${finalOpacity})`
|
|
1395
1434
|
: `rgba(60, 60, 60, ${finalOpacity})`;
|
|
1396
1435
|
}
|
|
@@ -1405,7 +1444,7 @@ const GlassCard = require$$0.forwardRef(({ variant = 'light', blur = 20, opacity
|
|
|
1405
1444
|
borderColor: 'rgba(255, 255, 255, 0.2)',
|
|
1406
1445
|
background: opacity !== undefined ? `rgba(70, 70, 70, ${finalOpacity})` : undefined,
|
|
1407
1446
|
}
|
|
1408
|
-
}[
|
|
1447
|
+
}[resolvedTheme] : {};
|
|
1409
1448
|
const handleMouseEnter = (e) => {
|
|
1410
1449
|
if (!enableHover)
|
|
1411
1450
|
return;
|
|
@@ -1423,7 +1462,7 @@ const GlassCard = require$$0.forwardRef(({ variant = 'light', blur = 20, opacity
|
|
|
1423
1462
|
});
|
|
1424
1463
|
props.onMouseLeave?.(e);
|
|
1425
1464
|
};
|
|
1426
|
-
return (jsxRuntimeExports.jsx("div", { ref: ref, className: cn('mds-glass-card', `mds-glass-card--${
|
|
1465
|
+
return (jsxRuntimeExports.jsx("div", { ref: ref, className: cn('mds-glass-card', `mds-glass-card--${resolvedTheme}`, !enableHover && 'mds-glass-card--no-hover', className), style: {
|
|
1427
1466
|
...baseStyles,
|
|
1428
1467
|
...customStyles,
|
|
1429
1468
|
...style
|
|
@@ -1431,6 +1470,125 @@ const GlassCard = require$$0.forwardRef(({ variant = 'light', blur = 20, opacity
|
|
|
1431
1470
|
});
|
|
1432
1471
|
GlassCard.displayName = 'GlassCard';
|
|
1433
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
|
+
|
|
1434
1592
|
const variantElementMap = {
|
|
1435
1593
|
h1: 'h1',
|
|
1436
1594
|
h2: 'h2',
|
|
@@ -1495,22 +1653,241 @@ const LoadingSpinner = () => (jsxRuntimeExports.jsxs("svg", { className: "mds-sp
|
|
|
1495
1653
|
/**
|
|
1496
1654
|
* Select Component (Design System)
|
|
1497
1655
|
*
|
|
1498
|
-
*
|
|
1499
|
-
*
|
|
1500
|
-
*
|
|
1501
|
-
*
|
|
1656
|
+
* Custom dropdown select that renders consistently across all browsers.
|
|
1657
|
+
* Unlike native <select>, this component renders the dropdown via JavaScript,
|
|
1658
|
+
* ensuring proper theming support on Edge/Chrome Windows.
|
|
1659
|
+
*
|
|
1660
|
+
* @example
|
|
1661
|
+
* ```tsx
|
|
1662
|
+
* <Select
|
|
1663
|
+
* options={[
|
|
1664
|
+
* { label: 'Option 1', value: '1' },
|
|
1665
|
+
* { label: 'Option 2', value: '2' },
|
|
1666
|
+
* ]}
|
|
1667
|
+
* value={selectedValue}
|
|
1668
|
+
* onChange={setSelectedValue}
|
|
1669
|
+
* placeholder="Select an option..."
|
|
1670
|
+
* />
|
|
1671
|
+
* ```
|
|
1502
1672
|
*/
|
|
1503
|
-
const Select = require$$0.forwardRef(({ options,
|
|
1504
|
-
const
|
|
1505
|
-
const
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1673
|
+
const Select = require$$0.forwardRef(({ options, value, onChange, placeholder = 'Select...', variant = 'themed', size = 'md', disabled = false, loading = false, error = false, className, dropdownClassName, id, name, 'aria-label': ariaLabel, fullWidth = false, searchable = false, searchPlaceholder = 'Search...', maxHeight = 300, zIndex = 1050, }, ref) => {
|
|
1674
|
+
const [isOpen, setIsOpen] = require$$0.useState(false);
|
|
1675
|
+
const [searchTerm, setSearchTerm] = require$$0.useState('');
|
|
1676
|
+
const [highlightedIndex, setHighlightedIndex] = require$$0.useState(-1);
|
|
1677
|
+
const [mounted, setMounted] = require$$0.useState(false);
|
|
1678
|
+
const triggerRef = require$$0.useRef(null);
|
|
1679
|
+
const dropdownRef = require$$0.useRef(null);
|
|
1680
|
+
const searchInputRef = require$$0.useRef(null);
|
|
1681
|
+
const listRef = require$$0.useRef(null);
|
|
1682
|
+
// Combine refs
|
|
1683
|
+
const combinedRef = (el) => {
|
|
1684
|
+
triggerRef.current = el;
|
|
1685
|
+
if (typeof ref === 'function') {
|
|
1686
|
+
ref(el);
|
|
1687
|
+
}
|
|
1688
|
+
else if (ref) {
|
|
1689
|
+
ref.current = el;
|
|
1690
|
+
}
|
|
1691
|
+
};
|
|
1692
|
+
// Client-side only
|
|
1693
|
+
require$$0.useEffect(() => {
|
|
1694
|
+
setMounted(true);
|
|
1695
|
+
}, []);
|
|
1696
|
+
// Filter options based on search
|
|
1697
|
+
const filteredOptions = require$$0.useMemo(() => {
|
|
1698
|
+
if (!searchTerm)
|
|
1699
|
+
return options;
|
|
1700
|
+
const term = searchTerm.toLowerCase();
|
|
1701
|
+
return options.filter(opt => {
|
|
1702
|
+
const label = typeof opt.label === 'string' ? opt.label : String(opt.value);
|
|
1703
|
+
return label.toLowerCase().includes(term);
|
|
1704
|
+
});
|
|
1705
|
+
}, [options, searchTerm]);
|
|
1706
|
+
// Get selected option label
|
|
1707
|
+
const selectedOption = require$$0.useMemo(() => {
|
|
1708
|
+
return options.find(opt => opt.value === value);
|
|
1709
|
+
}, [options, value]);
|
|
1710
|
+
// Handle dropdown positioning
|
|
1711
|
+
const [dropdownPosition, setDropdownPosition] = require$$0.useState({ top: 0, left: 0, width: 0 });
|
|
1712
|
+
const updateDropdownPosition = require$$0.useCallback(() => {
|
|
1713
|
+
if (!triggerRef.current)
|
|
1714
|
+
return;
|
|
1715
|
+
const rect = triggerRef.current.getBoundingClientRect();
|
|
1716
|
+
const viewportHeight = window.innerHeight;
|
|
1717
|
+
const spaceBelow = viewportHeight - rect.bottom;
|
|
1718
|
+
const spaceAbove = rect.top;
|
|
1719
|
+
// Determine if dropdown should open above or below
|
|
1720
|
+
const dropdownHeight = Math.min(maxHeight, filteredOptions.length * 40 + (searchable ? 48 : 0));
|
|
1721
|
+
const openAbove = spaceBelow < dropdownHeight && spaceAbove > spaceBelow;
|
|
1722
|
+
setDropdownPosition({
|
|
1723
|
+
top: openAbove ? rect.top - dropdownHeight : rect.bottom + 4,
|
|
1724
|
+
left: rect.left,
|
|
1725
|
+
width: rect.width,
|
|
1726
|
+
});
|
|
1727
|
+
}, [maxHeight, filteredOptions.length, searchable]);
|
|
1728
|
+
// Open dropdown
|
|
1729
|
+
const openDropdown = require$$0.useCallback(() => {
|
|
1730
|
+
if (disabled || loading)
|
|
1731
|
+
return;
|
|
1732
|
+
updateDropdownPosition();
|
|
1733
|
+
setIsOpen(true);
|
|
1734
|
+
setSearchTerm('');
|
|
1735
|
+
setHighlightedIndex(value ? filteredOptions.findIndex(opt => opt.value === value) : 0);
|
|
1736
|
+
}, [disabled, loading, updateDropdownPosition, value, filteredOptions]);
|
|
1737
|
+
// Close dropdown
|
|
1738
|
+
const closeDropdown = require$$0.useCallback(() => {
|
|
1739
|
+
setIsOpen(false);
|
|
1740
|
+
setSearchTerm('');
|
|
1741
|
+
setHighlightedIndex(-1);
|
|
1742
|
+
triggerRef.current?.focus();
|
|
1743
|
+
}, []);
|
|
1744
|
+
// Handle option select
|
|
1745
|
+
const handleSelect = require$$0.useCallback((optionValue) => {
|
|
1746
|
+
// Safety check: ensure we're passing a string, not an object
|
|
1747
|
+
const safeValue = typeof optionValue === 'string' ? optionValue : String(optionValue);
|
|
1748
|
+
onChange?.(safeValue);
|
|
1749
|
+
closeDropdown();
|
|
1750
|
+
}, [onChange, closeDropdown]);
|
|
1751
|
+
// Keyboard navigation
|
|
1752
|
+
const handleKeyDown = require$$0.useCallback((e) => {
|
|
1753
|
+
if (disabled || loading)
|
|
1754
|
+
return;
|
|
1755
|
+
switch (e.key) {
|
|
1756
|
+
case 'Enter':
|
|
1757
|
+
case ' ':
|
|
1758
|
+
e.preventDefault();
|
|
1759
|
+
if (isOpen && highlightedIndex >= 0 && filteredOptions[highlightedIndex]) {
|
|
1760
|
+
const opt = filteredOptions[highlightedIndex];
|
|
1761
|
+
if (!opt.disabled) {
|
|
1762
|
+
handleSelect(opt.value);
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
else if (!isOpen) {
|
|
1766
|
+
openDropdown();
|
|
1767
|
+
}
|
|
1768
|
+
break;
|
|
1769
|
+
case 'ArrowDown':
|
|
1770
|
+
e.preventDefault();
|
|
1771
|
+
if (!isOpen) {
|
|
1772
|
+
openDropdown();
|
|
1773
|
+
}
|
|
1774
|
+
else {
|
|
1775
|
+
setHighlightedIndex(prev => {
|
|
1776
|
+
const next = prev + 1;
|
|
1777
|
+
return next >= filteredOptions.length ? 0 : next;
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
break;
|
|
1781
|
+
case 'ArrowUp':
|
|
1782
|
+
e.preventDefault();
|
|
1783
|
+
if (isOpen) {
|
|
1784
|
+
setHighlightedIndex(prev => {
|
|
1785
|
+
const next = prev - 1;
|
|
1786
|
+
return next < 0 ? filteredOptions.length - 1 : next;
|
|
1787
|
+
});
|
|
1788
|
+
}
|
|
1789
|
+
break;
|
|
1790
|
+
case 'Escape':
|
|
1791
|
+
e.preventDefault();
|
|
1792
|
+
closeDropdown();
|
|
1793
|
+
break;
|
|
1794
|
+
case 'Tab':
|
|
1795
|
+
if (isOpen) {
|
|
1796
|
+
closeDropdown();
|
|
1797
|
+
}
|
|
1798
|
+
break;
|
|
1799
|
+
case 'Home':
|
|
1800
|
+
if (isOpen) {
|
|
1801
|
+
e.preventDefault();
|
|
1802
|
+
setHighlightedIndex(0);
|
|
1803
|
+
}
|
|
1804
|
+
break;
|
|
1805
|
+
case 'End':
|
|
1806
|
+
if (isOpen) {
|
|
1807
|
+
e.preventDefault();
|
|
1808
|
+
setHighlightedIndex(filteredOptions.length - 1);
|
|
1809
|
+
}
|
|
1810
|
+
break;
|
|
1811
|
+
}
|
|
1812
|
+
}, [disabled, loading, isOpen, highlightedIndex, filteredOptions, handleSelect, openDropdown, closeDropdown]);
|
|
1813
|
+
// Click outside to close
|
|
1814
|
+
require$$0.useEffect(() => {
|
|
1815
|
+
if (!isOpen)
|
|
1816
|
+
return;
|
|
1817
|
+
const handleClickOutside = (e) => {
|
|
1818
|
+
if (triggerRef.current?.contains(e.target) ||
|
|
1819
|
+
dropdownRef.current?.contains(e.target)) {
|
|
1820
|
+
return;
|
|
1821
|
+
}
|
|
1822
|
+
closeDropdown();
|
|
1823
|
+
};
|
|
1824
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
1825
|
+
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
1826
|
+
}, [isOpen, closeDropdown]);
|
|
1827
|
+
// Update position on scroll/resize
|
|
1828
|
+
require$$0.useEffect(() => {
|
|
1829
|
+
if (!isOpen)
|
|
1830
|
+
return;
|
|
1831
|
+
const handleUpdate = () => updateDropdownPosition();
|
|
1832
|
+
window.addEventListener('scroll', handleUpdate, true);
|
|
1833
|
+
window.addEventListener('resize', handleUpdate);
|
|
1834
|
+
return () => {
|
|
1835
|
+
window.removeEventListener('scroll', handleUpdate, true);
|
|
1836
|
+
window.removeEventListener('resize', handleUpdate);
|
|
1837
|
+
};
|
|
1838
|
+
}, [isOpen, updateDropdownPosition]);
|
|
1839
|
+
// Focus search input when dropdown opens
|
|
1840
|
+
require$$0.useEffect(() => {
|
|
1841
|
+
if (isOpen && searchable && searchInputRef.current) {
|
|
1842
|
+
searchInputRef.current.focus();
|
|
1843
|
+
}
|
|
1844
|
+
}, [isOpen, searchable]);
|
|
1845
|
+
// Scroll highlighted option into view
|
|
1846
|
+
require$$0.useEffect(() => {
|
|
1847
|
+
if (!isOpen || highlightedIndex < 0 || !listRef.current)
|
|
1848
|
+
return;
|
|
1849
|
+
const highlighted = listRef.current.children[highlightedIndex];
|
|
1850
|
+
if (highlighted) {
|
|
1851
|
+
highlighted.scrollIntoView({ block: 'nearest' });
|
|
1852
|
+
}
|
|
1853
|
+
}, [isOpen, highlightedIndex]);
|
|
1854
|
+
// Size classes
|
|
1855
|
+
const sizeClasses = {
|
|
1856
|
+
sm: 'mds-select--sm',
|
|
1857
|
+
md: 'mds-select--md',
|
|
1858
|
+
lg: 'mds-select--lg',
|
|
1859
|
+
};
|
|
1860
|
+
// Variant classes
|
|
1861
|
+
const variantClasses = {
|
|
1862
|
+
base: 'mds-select--base',
|
|
1863
|
+
themed: 'mds-select--themed',
|
|
1864
|
+
dashboard: 'mds-select--themed',
|
|
1865
|
+
};
|
|
1866
|
+
const triggerClasses = cn('mds-select-trigger', sizeClasses[size], variantClasses[variant], isOpen && 'mds-select-trigger--open', disabled && 'mds-select-trigger--disabled', loading && 'mds-select-trigger--loading', error && 'mds-select-trigger--error', fullWidth && 'mds-select-trigger--full-width', className);
|
|
1867
|
+
const dropdownClasses = cn('mds-select-dropdown', variantClasses[variant], dropdownClassName);
|
|
1868
|
+
// Hidden input for form submission
|
|
1869
|
+
const hiddenInput = name ? (jsxRuntimeExports.jsx("input", { type: "hidden", name: name, value: value || '' })) : null;
|
|
1870
|
+
// Dropdown portal content
|
|
1871
|
+
const dropdownContent = isOpen && mounted ? reactDom.createPortal(jsxRuntimeExports.jsxs("div", { ref: dropdownRef, className: dropdownClasses, style: {
|
|
1872
|
+
position: 'fixed',
|
|
1873
|
+
top: dropdownPosition.top,
|
|
1874
|
+
left: dropdownPosition.left,
|
|
1875
|
+
width: dropdownPosition.width,
|
|
1876
|
+
maxHeight,
|
|
1877
|
+
zIndex,
|
|
1878
|
+
}, role: "listbox", "aria-label": ariaLabel || placeholder, children: [searchable && (jsxRuntimeExports.jsxs("div", { className: "mds-select-search", children: [jsxRuntimeExports.jsx("input", { ref: searchInputRef, type: "text", className: "mds-select-search__input", placeholder: searchPlaceholder, value: searchTerm, onChange: (e) => {
|
|
1879
|
+
setSearchTerm(e.target.value);
|
|
1880
|
+
setHighlightedIndex(0);
|
|
1881
|
+
}, onKeyDown: handleKeyDown, "aria-label": "Search options" }), jsxRuntimeExports.jsx("svg", { className: "mds-select-search__icon", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z", clipRule: "evenodd" }) })] })), jsxRuntimeExports.jsx("ul", { ref: listRef, className: "mds-select-options", children: filteredOptions.length === 0 ? (jsxRuntimeExports.jsx("li", { className: "mds-select-option mds-select-option--empty", children: "No options found" })) : (filteredOptions.map((option, index) => (jsxRuntimeExports.jsxs("li", { className: cn('mds-select-option', option.value === value && 'mds-select-option--selected', index === highlightedIndex && 'mds-select-option--highlighted', option.disabled && 'mds-select-option--disabled'), role: "option", "aria-selected": option.value === value, "aria-disabled": option.disabled, onClick: () => {
|
|
1882
|
+
if (!option.disabled) {
|
|
1883
|
+
handleSelect(option.value);
|
|
1884
|
+
}
|
|
1885
|
+
}, onMouseEnter: () => {
|
|
1886
|
+
if (!option.disabled) {
|
|
1887
|
+
setHighlightedIndex(index);
|
|
1888
|
+
}
|
|
1889
|
+
}, children: [jsxRuntimeExports.jsx("span", { className: "mds-select-option__label", children: option.label }), option.value === value && (jsxRuntimeExports.jsx("svg", { className: "mds-select-option__check", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }))] }, option.value)))) })] }), document.body) : null;
|
|
1890
|
+
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [hiddenInput, jsxRuntimeExports.jsxs("button", { ref: combinedRef, type: "button", id: id, className: triggerClasses, onClick: () => isOpen ? closeDropdown() : openDropdown(), onKeyDown: handleKeyDown, disabled: disabled || loading, "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-label": ariaLabel, "aria-invalid": error, children: [jsxRuntimeExports.jsx("span", { className: cn('mds-select-trigger__value', !selectedOption && 'mds-select-trigger__placeholder'), children: loading ? 'Loading...' : (selectedOption?.label || placeholder) }), jsxRuntimeExports.jsx("span", { className: "mds-select-trigger__icon", children: loading ? (jsxRuntimeExports.jsx("svg", { className: "mds-select-spinner", viewBox: "0 0 24 24", fill: "none", children: jsxRuntimeExports.jsx("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeDasharray: "32", strokeDashoffset: "32", children: jsxRuntimeExports.jsx("animate", { attributeName: "stroke-dashoffset", values: "32;0", dur: "1s", repeatCount: "indefinite" }) }) })) : (jsxRuntimeExports.jsx("svg", { className: "mds-select-chevron", viewBox: "0 0 20 20", fill: "currentColor", children: jsxRuntimeExports.jsx("path", { fillRule: "evenodd", d: "M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z", clipRule: "evenodd" }) })) })] }), dropdownContent] }));
|
|
1514
1891
|
});
|
|
1515
1892
|
Select.displayName = 'Select';
|
|
1516
1893
|
|
|
@@ -1583,36 +1960,43 @@ function ThemeToggle({ size = 'md', className = '', disabled = false, onChange,
|
|
|
1583
1960
|
return (jsxRuntimeExports.jsx("button", { onClick: toggleTheme, className: buttonClasses, disabled: disabled, type: "button", "aria-pressed": isDark, "aria-label": `Switch to ${isDark ? 'light' : 'dark'} mode`, title: `Switch to ${isDark ? 'light' : 'dark'} mode`, "data-theme": isDark ? 'dark' : 'light', style: buttonStyle }));
|
|
1584
1961
|
}
|
|
1585
1962
|
|
|
1586
|
-
const TableHeader = ({ columns, gridTemplate, onSort, sortColumn, sortDirection }) => {
|
|
1587
|
-
return (jsxRuntimeExports.
|
|
1963
|
+
const TableHeader = ({ columns, gridTemplate, onSort, sortColumn, sortDirection, hasActions = false }) => {
|
|
1964
|
+
return (jsxRuntimeExports.jsxs("div", { role: "rowgroup", style: {
|
|
1588
1965
|
display: 'grid',
|
|
1589
1966
|
gridTemplateColumns: gridTemplate,
|
|
1590
1967
|
gap: '16px',
|
|
1591
1968
|
padding: '16px 20px',
|
|
1592
1969
|
borderBottom: '1px solid var(--border-color)',
|
|
1593
1970
|
backgroundColor: 'rgba(255, 255, 255, 0.05)'
|
|
1594
|
-
}, children: columns.map((column) => (jsxRuntimeExports.jsxs("div", { role: "columnheader", style: {
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1971
|
+
}, children: [columns.map((column) => (jsxRuntimeExports.jsxs("div", { role: "columnheader", style: {
|
|
1972
|
+
color: 'var(--text-primary)',
|
|
1973
|
+
fontWeight: '500',
|
|
1974
|
+
fontSize: '14px',
|
|
1975
|
+
display: 'flex',
|
|
1976
|
+
alignItems: 'center',
|
|
1977
|
+
justifyContent: column.align === 'center' ? 'center' :
|
|
1978
|
+
column.align === 'right' ? 'flex-end' : 'flex-start',
|
|
1979
|
+
cursor: column.sortable && onSort ? 'pointer' : 'default',
|
|
1980
|
+
gap: '4px',
|
|
1981
|
+
transition: 'color 0.2s ease'
|
|
1982
|
+
}, onClick: () => column.sortable && onSort && onSort(column.key), onMouseEnter: (e) => {
|
|
1983
|
+
if (column.sortable && onSort) {
|
|
1984
|
+
e.currentTarget.style.color = '#ffffff';
|
|
1985
|
+
}
|
|
1986
|
+
}, onMouseLeave: (e) => {
|
|
1987
|
+
e.currentTarget.style.color = 'var(--text-primary)';
|
|
1988
|
+
}, children: [column.label, column.sortable && onSort && (jsxRuntimeExports.jsx("span", { style: {
|
|
1989
|
+
fontSize: '12px',
|
|
1990
|
+
opacity: sortColumn === column.key ? 1 : 0.5
|
|
1991
|
+
}, children: sortColumn === column.key ?
|
|
1992
|
+
(sortDirection === 'asc' ? '↑' : '↓') : '↕' }))] }, column.key))), hasActions && (jsxRuntimeExports.jsx("div", { role: "columnheader", style: {
|
|
1993
|
+
color: 'var(--text-primary)',
|
|
1994
|
+
fontWeight: '500',
|
|
1995
|
+
fontSize: '14px',
|
|
1996
|
+
display: 'flex',
|
|
1997
|
+
alignItems: 'center',
|
|
1998
|
+
justifyContent: 'center'
|
|
1999
|
+
}, children: "Actions" }))] }));
|
|
1616
2000
|
};
|
|
1617
2001
|
|
|
1618
2002
|
const TableRow = ({ item, index, columns, actions = [], gridTemplate, isLast, variant, onActionClick }) => {
|
|
@@ -1650,10 +2034,9 @@ const TableRow = ({ item, index, columns, actions = [], gridTemplate, isLast, va
|
|
|
1650
2034
|
const isLoading = action.loading?.(item) || false;
|
|
1651
2035
|
return (jsxRuntimeExports.jsxs("button", { onClick: () => !isDisabled && !isLoading && onActionClick(action, item), disabled: isDisabled || isLoading, style: {
|
|
1652
2036
|
background: 'none',
|
|
1653
|
-
border:
|
|
1654
|
-
'1px solid var(--border-color)',
|
|
2037
|
+
border: 'none',
|
|
1655
2038
|
borderRadius: '6px',
|
|
1656
|
-
padding: '6px
|
|
2039
|
+
padding: '6px 8px',
|
|
1657
2040
|
color: action.variant === 'danger' ? '#f87171' : 'var(--text-primary)',
|
|
1658
2041
|
fontSize: '12px',
|
|
1659
2042
|
cursor: isDisabled || isLoading ? 'not-allowed' : 'pointer',
|
|
@@ -1667,18 +2050,14 @@ const TableRow = ({ item, index, columns, actions = [], gridTemplate, isLast, va
|
|
|
1667
2050
|
if (!isDisabled && !isLoading) {
|
|
1668
2051
|
if (action.variant === 'danger') {
|
|
1669
2052
|
e.currentTarget.style.backgroundColor = 'rgba(239, 68, 68, 0.1)';
|
|
1670
|
-
e.currentTarget.style.borderColor = 'rgba(239, 68, 68, 0.5)';
|
|
1671
2053
|
}
|
|
1672
2054
|
else {
|
|
1673
2055
|
e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
|
|
1674
|
-
e.currentTarget.style.borderColor = 'var(--text-primary)';
|
|
1675
2056
|
}
|
|
1676
2057
|
}
|
|
1677
2058
|
}, onMouseLeave: (e) => {
|
|
1678
2059
|
if (!isDisabled && !isLoading) {
|
|
1679
2060
|
e.currentTarget.style.backgroundColor = 'transparent';
|
|
1680
|
-
e.currentTarget.style.borderColor = action.variant === 'danger' ?
|
|
1681
|
-
'rgba(239, 68, 68, 0.3)' : 'var(--border-color)';
|
|
1682
2061
|
}
|
|
1683
2062
|
}, children: [action.icon && action.icon, action.label] }, action.key));
|
|
1684
2063
|
}) }))] }));
|
|
@@ -1778,7 +2157,7 @@ const DataTable = ({ data, columns, loading = false, searchTerm = '', actions =
|
|
|
1778
2157
|
color: 'var(--text-secondary)',
|
|
1779
2158
|
fontSize: '14px',
|
|
1780
2159
|
borderBottom: '1px solid var(--border-color)'
|
|
1781
|
-
}, children: ["Mostrando", ' ', jsxRuntimeExports.jsx("span", { style: { fontWeight: '500', color: 'var(--text-primary)' }, children: filteredData.length }), ' ', "de", ' ', jsxRuntimeExports.jsx("span", { style: { fontWeight: '500', color: 'var(--text-primary)' }, children: data.length }), ' ', "itens"] })), jsxRuntimeExports.jsx(TableHeader, { columns: columns, gridTemplate: gridTemplate, onSort: onSort ? handleSort : undefined, sortColumn: sortColumn, sortDirection: sortDirection }), jsxRuntimeExports.jsx("div", { role: "rowgroup", style: {
|
|
2160
|
+
}, children: ["Mostrando", ' ', jsxRuntimeExports.jsx("span", { style: { fontWeight: '500', color: 'var(--text-primary)' }, children: filteredData.length }), ' ', "de", ' ', jsxRuntimeExports.jsx("span", { style: { fontWeight: '500', color: 'var(--text-primary)' }, children: data.length }), ' ', "itens"] })), jsxRuntimeExports.jsx(TableHeader, { columns: columns, gridTemplate: gridTemplate, onSort: onSort ? handleSort : undefined, sortColumn: sortColumn, sortDirection: sortDirection, hasActions: actions.length > 0 }), jsxRuntimeExports.jsx("div", { role: "rowgroup", style: {
|
|
1782
2161
|
maxHeight,
|
|
1783
2162
|
overflowY: 'auto'
|
|
1784
2163
|
}, children: filteredData.map((item, index) => (jsxRuntimeExports.jsx(TableRow, { item: item, index: index, columns: columns, actions: actions, gridTemplate: gridTemplate, isLast: index === filteredData.length - 1, variant: variant, onActionClick: handleActionClick }, item.id || index))) })] }));
|
|
@@ -2186,12 +2565,233 @@ const getTableConfig = (type) => {
|
|
|
2186
2565
|
}
|
|
2187
2566
|
};
|
|
2188
2567
|
|
|
2568
|
+
/**
|
|
2569
|
+
* FormField - Normalized wrapper for form inputs
|
|
2570
|
+
*
|
|
2571
|
+
* Pattern extracted from AdminUserModal.tsx (backoffice/users)
|
|
2572
|
+
* Provides consistent label, error, and helper text styling
|
|
2573
|
+
*/
|
|
2574
|
+
function FormField({ label, required = false, error, helper, disabled = false, children, className = '' }) {
|
|
2575
|
+
return (jsxRuntimeExports.jsxs("div", { className: `mds-form-field ${className}`, style: { opacity: disabled ? 0.6 : 1 }, children: [jsxRuntimeExports.jsxs("label", { style: {
|
|
2576
|
+
display: 'block',
|
|
2577
|
+
marginBottom: '6px',
|
|
2578
|
+
color: 'var(--mds-color-text-primary, var(--text-primary))',
|
|
2579
|
+
fontSize: '0.9rem',
|
|
2580
|
+
fontWeight: 500
|
|
2581
|
+
}, children: [label, required && (jsxRuntimeExports.jsx("span", { style: { color: 'var(--mds-color-error, #ef4444)', marginLeft: '4px' }, children: "*" }))] }), children, error && (jsxRuntimeExports.jsx("span", { style: {
|
|
2582
|
+
color: 'var(--mds-color-error, #ef4444)',
|
|
2583
|
+
fontSize: '0.8rem',
|
|
2584
|
+
marginTop: '4px',
|
|
2585
|
+
display: 'block'
|
|
2586
|
+
}, children: error })), helper && !error && (jsxRuntimeExports.jsx("span", { style: {
|
|
2587
|
+
color: 'var(--mds-color-text-secondary, var(--text-secondary))',
|
|
2588
|
+
fontSize: '0.75rem',
|
|
2589
|
+
marginTop: '4px',
|
|
2590
|
+
display: 'block'
|
|
2591
|
+
}, children: helper }))] }));
|
|
2592
|
+
}
|
|
2593
|
+
|
|
2594
|
+
const gapValues = {
|
|
2595
|
+
sm: '12px',
|
|
2596
|
+
md: '16px',
|
|
2597
|
+
lg: '24px'
|
|
2598
|
+
};
|
|
2599
|
+
/**
|
|
2600
|
+
* FormGrid - Normalized grid layout for form fields
|
|
2601
|
+
*
|
|
2602
|
+
* Pattern extracted from AdminUserModal.tsx (backoffice/users)
|
|
2603
|
+
* Provides consistent 1 or 2 column layouts with proper gap
|
|
2604
|
+
*/
|
|
2605
|
+
function FormGrid({ columns = 1, gap = 'md', children, className = '' }) {
|
|
2606
|
+
return (jsxRuntimeExports.jsx("div", { className: `mds-form-grid ${className}`, style: {
|
|
2607
|
+
display: 'grid',
|
|
2608
|
+
gridTemplateColumns: columns === 2 ? 'repeat(2, 1fr)' : '1fr',
|
|
2609
|
+
gap: gapValues[gap]
|
|
2610
|
+
}, children: children }));
|
|
2611
|
+
}
|
|
2612
|
+
|
|
2613
|
+
/**
|
|
2614
|
+
* FormSection - Normalized section wrapper for grouping form fields
|
|
2615
|
+
*
|
|
2616
|
+
* Pattern extracted from AdminUserModal.tsx (backoffice/users)
|
|
2617
|
+
* Provides consistent section headers and spacing
|
|
2618
|
+
*/
|
|
2619
|
+
function FormSection({ title, description, children, className = '' }) {
|
|
2620
|
+
return (jsxRuntimeExports.jsxs("div", { className: `mds-form-section ${className}`, style: {
|
|
2621
|
+
marginBottom: '24px'
|
|
2622
|
+
}, children: [title && (jsxRuntimeExports.jsx("h4", { style: {
|
|
2623
|
+
margin: '0 0 8px 0',
|
|
2624
|
+
color: 'var(--mds-color-text-primary, var(--text-primary))',
|
|
2625
|
+
fontSize: '1rem',
|
|
2626
|
+
fontWeight: 600,
|
|
2627
|
+
letterSpacing: '-0.02em'
|
|
2628
|
+
}, children: title })), description && (jsxRuntimeExports.jsx("p", { style: {
|
|
2629
|
+
margin: '0 0 16px 0',
|
|
2630
|
+
color: 'var(--mds-color-text-secondary, var(--text-secondary))',
|
|
2631
|
+
fontSize: '0.85rem',
|
|
2632
|
+
lineHeight: 1.5
|
|
2633
|
+
}, children: description })), jsxRuntimeExports.jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '16px' }, children: children })] }));
|
|
2634
|
+
}
|
|
2635
|
+
|
|
2636
|
+
const variantColors = {
|
|
2637
|
+
default: {
|
|
2638
|
+
bg: 'rgba(255, 255, 255, 0.03)',
|
|
2639
|
+
border: 'rgba(255, 255, 255, 0.1)',
|
|
2640
|
+
accent: 'var(--mds-color-text-secondary, #888)'
|
|
2641
|
+
},
|
|
2642
|
+
info: {
|
|
2643
|
+
bg: 'rgba(59, 130, 246, 0.1)',
|
|
2644
|
+
border: 'rgba(59, 130, 246, 0.2)',
|
|
2645
|
+
accent: 'var(--mds-color-info, #3b82f6)'
|
|
2646
|
+
},
|
|
2647
|
+
success: {
|
|
2648
|
+
bg: 'rgba(16, 185, 129, 0.1)',
|
|
2649
|
+
border: 'rgba(16, 185, 129, 0.2)',
|
|
2650
|
+
accent: 'var(--mds-color-success, #10b981)'
|
|
2651
|
+
},
|
|
2652
|
+
warning: {
|
|
2653
|
+
bg: 'rgba(245, 158, 11, 0.1)',
|
|
2654
|
+
border: 'rgba(245, 158, 11, 0.2)',
|
|
2655
|
+
accent: 'var(--mds-color-warning, #f59e0b)'
|
|
2656
|
+
},
|
|
2657
|
+
danger: {
|
|
2658
|
+
bg: 'rgba(239, 68, 68, 0.1)',
|
|
2659
|
+
border: 'rgba(239, 68, 68, 0.2)',
|
|
2660
|
+
accent: 'var(--mds-color-error, #ef4444)'
|
|
2661
|
+
}
|
|
2662
|
+
};
|
|
2663
|
+
/**
|
|
2664
|
+
* InfoBox - Normalized info/alert box for read-only information
|
|
2665
|
+
*
|
|
2666
|
+
* Pattern extracted from AdminUserModal.tsx (backoffice/users)
|
|
2667
|
+
* Provides consistent info boxes for alerts, status displays, and read-only data
|
|
2668
|
+
*
|
|
2669
|
+
* @example
|
|
2670
|
+
* // Alert style (with accent)
|
|
2671
|
+
* <InfoBox variant="info" accent>
|
|
2672
|
+
* An invitation email will be sent...
|
|
2673
|
+
* </InfoBox>
|
|
2674
|
+
*
|
|
2675
|
+
* @example
|
|
2676
|
+
* // Status display (default)
|
|
2677
|
+
* <InfoBox title="User Information">
|
|
2678
|
+
* <InfoRow label="Status" value="Active" />
|
|
2679
|
+
* <InfoRow label="Created" value="Jan 1, 2024" />
|
|
2680
|
+
* </InfoBox>
|
|
2681
|
+
*/
|
|
2682
|
+
function InfoBox({ title, variant = 'default', accent = false, copyable = false, children, className = '' }) {
|
|
2683
|
+
const colors = variantColors[variant];
|
|
2684
|
+
const handleCopy = () => {
|
|
2685
|
+
if (!copyable)
|
|
2686
|
+
return;
|
|
2687
|
+
const text = typeof children === 'string' ? children : '';
|
|
2688
|
+
if (text) {
|
|
2689
|
+
navigator.clipboard.writeText(text);
|
|
2690
|
+
}
|
|
2691
|
+
};
|
|
2692
|
+
return (jsxRuntimeExports.jsxs("div", { className: `mds-info-box ${className}`, style: {
|
|
2693
|
+
padding: '12px 16px',
|
|
2694
|
+
backgroundColor: colors.bg,
|
|
2695
|
+
borderRadius: '8px',
|
|
2696
|
+
border: `1px solid ${colors.border}`,
|
|
2697
|
+
borderLeft: accent ? `4px solid ${colors.accent}` : `1px solid ${colors.border}`,
|
|
2698
|
+
cursor: copyable ? 'pointer' : 'default'
|
|
2699
|
+
}, onClick: copyable ? handleCopy : undefined, title: copyable ? 'Click to copy' : undefined, children: [title && (jsxRuntimeExports.jsx("div", { style: {
|
|
2700
|
+
color: 'var(--mds-color-text-secondary, var(--text-secondary))',
|
|
2701
|
+
fontSize: '0.85rem',
|
|
2702
|
+
marginBottom: '8px',
|
|
2703
|
+
fontWeight: 500
|
|
2704
|
+
}, children: title })), jsxRuntimeExports.jsx("div", { style: {
|
|
2705
|
+
color: 'var(--mds-color-text-primary, var(--text-primary))',
|
|
2706
|
+
fontSize: '0.9rem',
|
|
2707
|
+
lineHeight: 1.5
|
|
2708
|
+
}, children: children })] }));
|
|
2709
|
+
}
|
|
2710
|
+
function InfoRow({ label, value, valueColor }) {
|
|
2711
|
+
return (jsxRuntimeExports.jsxs("div", { style: {
|
|
2712
|
+
display: 'flex',
|
|
2713
|
+
justifyContent: 'space-between',
|
|
2714
|
+
fontSize: '0.85rem',
|
|
2715
|
+
padding: '2px 0'
|
|
2716
|
+
}, children: [jsxRuntimeExports.jsxs("span", { style: { color: 'var(--mds-color-text-secondary, var(--text-secondary))' }, children: [label, ":"] }), jsxRuntimeExports.jsx("span", { style: { color: valueColor || 'var(--mds-color-text-primary, var(--text-primary))' }, children: value })] }));
|
|
2717
|
+
}
|
|
2718
|
+
|
|
2719
|
+
/**
|
|
2720
|
+
* Theme-aware styles generator - Liquid Glass pattern
|
|
2721
|
+
*
|
|
2722
|
+
* Light theme: White semi-transparent overlay to keep background bright
|
|
2723
|
+
* Dark theme: Dark overlay for contrast
|
|
2724
|
+
*/
|
|
2725
|
+
function getStyles(isDark) {
|
|
2726
|
+
return {
|
|
2727
|
+
// Overlay behind the modal
|
|
2728
|
+
overlay: {
|
|
2729
|
+
position: 'fixed',
|
|
2730
|
+
inset: 0,
|
|
2731
|
+
zIndex: 9999,
|
|
2732
|
+
display: 'flex',
|
|
2733
|
+
alignItems: 'center',
|
|
2734
|
+
justifyContent: 'center',
|
|
2735
|
+
padding: 20,
|
|
2736
|
+
// Light theme: white overlay to keep brightness
|
|
2737
|
+
// Dark theme: dark overlay for contrast
|
|
2738
|
+
backgroundColor: isDark ? 'rgba(0, 0, 0, 0.6)' : 'rgba(255, 255, 255, 0.4)',
|
|
2739
|
+
backdropFilter: 'blur(8px)',
|
|
2740
|
+
WebkitBackdropFilter: 'blur(8px)',
|
|
2741
|
+
},
|
|
2742
|
+
// Modal card - Liquid Glass
|
|
2743
|
+
card: {
|
|
2744
|
+
position: 'relative',
|
|
2745
|
+
maxWidth: 640,
|
|
2746
|
+
width: '100%',
|
|
2747
|
+
borderRadius: 24,
|
|
2748
|
+
overflow: 'hidden',
|
|
2749
|
+
// Light theme: Liquid Glass transparency
|
|
2750
|
+
// Dark theme: subtle glass effect
|
|
2751
|
+
background: isDark
|
|
2752
|
+
? 'rgba(255, 255, 255, 0.03)'
|
|
2753
|
+
: 'rgba(255, 255, 255, 0.45)',
|
|
2754
|
+
// Liquid Glass: Strong blur + saturation
|
|
2755
|
+
backdropFilter: 'blur(var(--mds-liquid-blur-xl, 24px)) saturate(var(--mds-liquid-saturate-vibrant, 140%))',
|
|
2756
|
+
WebkitBackdropFilter: 'blur(var(--mds-liquid-blur-xl, 24px)) saturate(var(--mds-liquid-saturate-vibrant, 140%))',
|
|
2757
|
+
// Liquid Glass: Subtle border for edge definition
|
|
2758
|
+
border: isDark
|
|
2759
|
+
? '1px solid rgba(255, 255, 255, 0.08)'
|
|
2760
|
+
: '1px solid rgba(255, 255, 255, 0.9)',
|
|
2761
|
+
// Liquid Glass: Layered shadows + inner glow
|
|
2762
|
+
boxShadow: isDark
|
|
2763
|
+
? 'var(--mds-liquid-shadow-elevated, 0 12px 40px rgba(0, 0, 0, 0.3)), var(--mds-liquid-glow-edge, inset 0 1px 0 rgba(255, 255, 255, 0.1))'
|
|
2764
|
+
: '0 8px 32px rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 1)',
|
|
2765
|
+
// Liquid Glass: Smooth transition
|
|
2766
|
+
transition: 'var(--mds-liquid-transition, all 0.25s cubic-bezier(0.25, 0.1, 0.25, 1))',
|
|
2767
|
+
},
|
|
2768
|
+
};
|
|
2769
|
+
}
|
|
2189
2770
|
function Modal({ open, onClose, closeOnOverlay = true, children, className, style }) {
|
|
2190
2771
|
const [mounted, setMounted] = require$$0.useState(false);
|
|
2191
2772
|
const [visible, setVisible] = require$$0.useState(false);
|
|
2192
2773
|
const [renderPortal, setRenderPortal] = require$$0.useState(false);
|
|
2774
|
+
const [isDarkTheme, setIsDarkTheme] = require$$0.useState(true);
|
|
2193
2775
|
const containerRef = require$$0.useRef(null);
|
|
2194
2776
|
require$$0.useEffect(() => setMounted(true), []);
|
|
2777
|
+
// Detect theme - EXACT same pattern as ProfileCard.tsx
|
|
2778
|
+
require$$0.useEffect(() => {
|
|
2779
|
+
const checkTheme = () => {
|
|
2780
|
+
const theme = document.documentElement.getAttribute('data-theme');
|
|
2781
|
+
setIsDarkTheme(theme !== 'light');
|
|
2782
|
+
};
|
|
2783
|
+
checkTheme();
|
|
2784
|
+
// Watch for theme changes
|
|
2785
|
+
const observer = new MutationObserver((mutations) => {
|
|
2786
|
+
mutations.forEach((mutation) => {
|
|
2787
|
+
if (mutation.attributeName === 'data-theme') {
|
|
2788
|
+
checkTheme();
|
|
2789
|
+
}
|
|
2790
|
+
});
|
|
2791
|
+
});
|
|
2792
|
+
observer.observe(document.documentElement, { attributes: true });
|
|
2793
|
+
return () => observer.disconnect();
|
|
2794
|
+
}, []);
|
|
2195
2795
|
require$$0.useEffect(() => {
|
|
2196
2796
|
if (!mounted)
|
|
2197
2797
|
return;
|
|
@@ -2217,30 +2817,178 @@ function Modal({ open, onClose, closeOnOverlay = true, children, className, styl
|
|
|
2217
2817
|
}, [open, onClose]);
|
|
2218
2818
|
if (!mounted || (!renderPortal && !open))
|
|
2219
2819
|
return null;
|
|
2820
|
+
// Get theme-aware styles (same pattern as ProfileCard)
|
|
2821
|
+
const styles = getStyles(isDarkTheme);
|
|
2220
2822
|
const overlayStyle = {
|
|
2221
|
-
|
|
2222
|
-
inset: 0,
|
|
2223
|
-
backgroundColor: 'rgba(0, 0, 0, 0.7)',
|
|
2224
|
-
display: 'flex',
|
|
2225
|
-
alignItems: 'center',
|
|
2226
|
-
justifyContent: 'center',
|
|
2227
|
-
zIndex: 1000,
|
|
2228
|
-
padding: '16px',
|
|
2823
|
+
...styles.overlay,
|
|
2229
2824
|
opacity: visible ? 1 : 0,
|
|
2230
|
-
transition: 'opacity 200ms ease'
|
|
2825
|
+
transition: 'opacity 200ms ease',
|
|
2231
2826
|
};
|
|
2232
|
-
const
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
transform: visible ? 'scale(1)' : 'scale(0.98)',
|
|
2827
|
+
const cardStyle = {
|
|
2828
|
+
...styles.card,
|
|
2829
|
+
transform: visible ? 'scale(1)' : 'scale(0.96)',
|
|
2236
2830
|
opacity: visible ? 1 : 0,
|
|
2237
|
-
transition: 'opacity 200ms ease, transform 200ms
|
|
2238
|
-
...style
|
|
2831
|
+
transition: 'opacity 200ms ease, transform 200ms cubic-bezier(0.4, 0, 0.2, 1)',
|
|
2832
|
+
...style,
|
|
2239
2833
|
};
|
|
2240
|
-
const content = (jsxRuntimeExports.jsx("div", { className: "modal-overlay mds-modal-overlay", style: overlayStyle, onClick: closeOnOverlay ? onClose : undefined, "aria-modal": "true", role: "dialog", children: jsxRuntimeExports.jsx("div", { className: className, style:
|
|
2834
|
+
const content = (jsxRuntimeExports.jsx("div", { className: "modal-overlay mds-modal-overlay", style: overlayStyle, onClick: closeOnOverlay ? onClose : undefined, "aria-modal": "true", role: "dialog", children: jsxRuntimeExports.jsx("div", { className: className, style: cardStyle, onClick: (e) => e.stopPropagation(), ref: (el) => (containerRef.current = el), children: children }) }));
|
|
2241
2835
|
return reactDom.createPortal(content, document.body);
|
|
2242
2836
|
}
|
|
2243
2837
|
|
|
2838
|
+
const sizeMap$1 = {
|
|
2839
|
+
sm: '400px',
|
|
2840
|
+
md: '480px',
|
|
2841
|
+
lg: '600px',
|
|
2842
|
+
xl: '800px'
|
|
2843
|
+
};
|
|
2844
|
+
/**
|
|
2845
|
+
* FormModal - Normalized template for CRUD modal forms
|
|
2846
|
+
*
|
|
2847
|
+
* Pattern extracted from AdminUserModal.tsx (backoffice/users)
|
|
2848
|
+
* Provides consistent structure for create/edit entity modals
|
|
2849
|
+
*
|
|
2850
|
+
* @example
|
|
2851
|
+
* <FormModal
|
|
2852
|
+
* open={showModal}
|
|
2853
|
+
* onClose={() => setShowModal(false)}
|
|
2854
|
+
* onSubmit={handleSubmit}
|
|
2855
|
+
* title="Edit User"
|
|
2856
|
+
* info="Changes will be saved immediately."
|
|
2857
|
+
* infoVariant="info"
|
|
2858
|
+
* loading={isSaving}
|
|
2859
|
+
* submitText="Save"
|
|
2860
|
+
* >
|
|
2861
|
+
* <FormField label="Name" required error={errors.name}>
|
|
2862
|
+
* <input className="mds-input" value={name} onChange={...} />
|
|
2863
|
+
* </FormField>
|
|
2864
|
+
* </FormModal>
|
|
2865
|
+
*/
|
|
2866
|
+
function FormModal({ open, onClose, onSubmit, title, icon, subtitle, info, infoVariant = 'info', children, submitText = 'Save', cancelText = 'Cancel', loading = false, submitDisabled = false, size = 'md', className = '' }) {
|
|
2867
|
+
const handleSubmit = (e) => {
|
|
2868
|
+
e.preventDefault();
|
|
2869
|
+
onSubmit(e);
|
|
2870
|
+
};
|
|
2871
|
+
return (jsxRuntimeExports.jsxs(Modal, { open: open, onClose: onClose, closeOnOverlay: !loading, className: className, style: {
|
|
2872
|
+
maxWidth: sizeMap$1[size],
|
|
2873
|
+
maxHeight: '90vh',
|
|
2874
|
+
overflowY: 'auto',
|
|
2875
|
+
padding: '24px'
|
|
2876
|
+
}, children: [jsxRuntimeExports.jsxs("div", { style: {
|
|
2877
|
+
display: 'flex',
|
|
2878
|
+
alignItems: 'center',
|
|
2879
|
+
justifyContent: 'space-between',
|
|
2880
|
+
marginBottom: subtitle ? '8px' : '24px'
|
|
2881
|
+
}, children: [jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '12px' }, children: [icon && (jsxRuntimeExports.jsx("div", { style: {
|
|
2882
|
+
display: 'flex',
|
|
2883
|
+
alignItems: 'center',
|
|
2884
|
+
justifyContent: 'center',
|
|
2885
|
+
width: 32,
|
|
2886
|
+
height: 32,
|
|
2887
|
+
fontSize: '1.25rem',
|
|
2888
|
+
lineHeight: 0,
|
|
2889
|
+
opacity: 0.5
|
|
2890
|
+
}, children: icon })), jsxRuntimeExports.jsx(Typography, { variant: "h3", color: "primary", style: { margin: 0 }, children: title })] }), jsxRuntimeExports.jsx("button", { type: "button", onClick: onClose, disabled: loading, style: {
|
|
2891
|
+
background: 'none',
|
|
2892
|
+
border: 'none',
|
|
2893
|
+
padding: '8px',
|
|
2894
|
+
cursor: loading ? 'not-allowed' : 'pointer',
|
|
2895
|
+
color: 'var(--mds-color-text-secondary)',
|
|
2896
|
+
opacity: loading ? 0.5 : 1,
|
|
2897
|
+
borderRadius: '6px',
|
|
2898
|
+
display: 'flex',
|
|
2899
|
+
alignItems: 'center',
|
|
2900
|
+
justifyContent: 'center',
|
|
2901
|
+
transition: 'all 0.2s ease'
|
|
2902
|
+
}, onMouseEnter: (e) => {
|
|
2903
|
+
if (!loading)
|
|
2904
|
+
e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
|
|
2905
|
+
}, onMouseLeave: (e) => {
|
|
2906
|
+
e.currentTarget.style.backgroundColor = 'transparent';
|
|
2907
|
+
}, "aria-label": "Close modal", children: jsxRuntimeExports.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsxRuntimeExports.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] }), subtitle && (jsxRuntimeExports.jsx(Typography, { variant: "body", color: "secondary", style: { marginBottom: '24px', fontSize: '0.9rem' }, children: subtitle })), info && (jsxRuntimeExports.jsx("div", { style: { marginBottom: '20px' }, children: jsxRuntimeExports.jsx(InfoBox, { variant: infoVariant, accent: true, children: info }) })), jsxRuntimeExports.jsxs("form", { onSubmit: handleSubmit, style: { display: 'flex', flexDirection: 'column', gap: '16px' }, children: [children, jsxRuntimeExports.jsxs("div", { style: {
|
|
2908
|
+
display: 'flex',
|
|
2909
|
+
gap: '12px',
|
|
2910
|
+
justifyContent: 'flex-end',
|
|
2911
|
+
marginTop: '16px',
|
|
2912
|
+
paddingTop: '16px',
|
|
2913
|
+
borderTop: '1px solid rgba(255, 255, 255, 0.1)'
|
|
2914
|
+
}, children: [jsxRuntimeExports.jsx(Button, { variant: "secondary", size: "sm", type: "button", onClick: onClose, disabled: loading, style: { minWidth: '90px' }, children: cancelText }), jsxRuntimeExports.jsx(Button, { variant: "primary", size: "sm", type: "submit", loading: loading, disabled: loading || submitDisabled, style: { minWidth: '110px' }, children: submitText })] })] })] }));
|
|
2915
|
+
}
|
|
2916
|
+
|
|
2917
|
+
const sizeMap = {
|
|
2918
|
+
sm: '400px',
|
|
2919
|
+
md: '480px',
|
|
2920
|
+
lg: '600px',
|
|
2921
|
+
xl: '800px'
|
|
2922
|
+
};
|
|
2923
|
+
/**
|
|
2924
|
+
* DetailModal - Normalized template for read-only detail modals
|
|
2925
|
+
*
|
|
2926
|
+
* Pattern extracted from GeographyDetailsModal, AuditLogDetailModal (backoffice)
|
|
2927
|
+
* Provides consistent structure for viewing entity details
|
|
2928
|
+
*
|
|
2929
|
+
* @example
|
|
2930
|
+
* <DetailModal
|
|
2931
|
+
* open={showDetails}
|
|
2932
|
+
* onClose={() => setShowDetails(false)}
|
|
2933
|
+
* title="User Details"
|
|
2934
|
+
* subtitle="Created on Jan 1, 2024"
|
|
2935
|
+
* action={{
|
|
2936
|
+
* label: 'Edit',
|
|
2937
|
+
* onClick: handleEdit,
|
|
2938
|
+
* variant: 'primary'
|
|
2939
|
+
* }}
|
|
2940
|
+
* >
|
|
2941
|
+
* <InfoBox title="Basic Information">
|
|
2942
|
+
* <InfoRow label="Name" value={user.name} />
|
|
2943
|
+
* <InfoRow label="Email" value={user.email} />
|
|
2944
|
+
* </InfoBox>
|
|
2945
|
+
* </DetailModal>
|
|
2946
|
+
*/
|
|
2947
|
+
function DetailModal({ open, onClose, title, icon, subtitle, children, closeText = 'Close', action, size = 'md', className = '' }) {
|
|
2948
|
+
return (jsxRuntimeExports.jsxs(Modal, { open: open, onClose: onClose, closeOnOverlay: true, className: className, style: {
|
|
2949
|
+
maxWidth: sizeMap[size],
|
|
2950
|
+
maxHeight: '90vh',
|
|
2951
|
+
overflowY: 'auto',
|
|
2952
|
+
padding: '24px'
|
|
2953
|
+
}, children: [jsxRuntimeExports.jsxs("div", { style: {
|
|
2954
|
+
display: 'flex',
|
|
2955
|
+
alignItems: 'center',
|
|
2956
|
+
justifyContent: 'space-between',
|
|
2957
|
+
marginBottom: subtitle ? '8px' : '24px'
|
|
2958
|
+
}, children: [jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '12px' }, children: [icon && (jsxRuntimeExports.jsx("div", { style: {
|
|
2959
|
+
display: 'flex',
|
|
2960
|
+
alignItems: 'center',
|
|
2961
|
+
justifyContent: 'center',
|
|
2962
|
+
width: 32,
|
|
2963
|
+
height: 32,
|
|
2964
|
+
fontSize: '1.25rem',
|
|
2965
|
+
lineHeight: 0,
|
|
2966
|
+
opacity: 0.5
|
|
2967
|
+
}, children: icon })), jsxRuntimeExports.jsx(Typography, { variant: "h3", color: "primary", style: { margin: 0 }, children: title })] }), jsxRuntimeExports.jsx("button", { type: "button", onClick: onClose, style: {
|
|
2968
|
+
background: 'none',
|
|
2969
|
+
border: 'none',
|
|
2970
|
+
padding: '8px',
|
|
2971
|
+
cursor: 'pointer',
|
|
2972
|
+
color: 'var(--mds-color-text-secondary)',
|
|
2973
|
+
borderRadius: '6px',
|
|
2974
|
+
display: 'flex',
|
|
2975
|
+
alignItems: 'center',
|
|
2976
|
+
justifyContent: 'center',
|
|
2977
|
+
transition: 'all 0.2s ease'
|
|
2978
|
+
}, onMouseEnter: (e) => {
|
|
2979
|
+
e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
|
|
2980
|
+
}, onMouseLeave: (e) => {
|
|
2981
|
+
e.currentTarget.style.backgroundColor = 'transparent';
|
|
2982
|
+
}, "aria-label": "Close modal", children: jsxRuntimeExports.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), jsxRuntimeExports.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }) })] }), subtitle && (jsxRuntimeExports.jsx(Typography, { variant: "body", color: "secondary", style: { marginBottom: '24px', fontSize: '0.9rem' }, children: subtitle })), jsxRuntimeExports.jsx("div", { style: { display: 'flex', flexDirection: 'column', gap: '16px' }, children: children }), jsxRuntimeExports.jsxs("div", { style: {
|
|
2983
|
+
display: 'flex',
|
|
2984
|
+
gap: '12px',
|
|
2985
|
+
justifyContent: 'flex-end',
|
|
2986
|
+
marginTop: '24px',
|
|
2987
|
+
paddingTop: '16px',
|
|
2988
|
+
borderTop: '1px solid rgba(255, 255, 255, 0.1)'
|
|
2989
|
+
}, children: [jsxRuntimeExports.jsx(Button, { variant: "secondary", size: "sm", onClick: onClose, children: closeText }), action && (jsxRuntimeExports.jsx(Button, { variant: action.variant || 'primary', size: "sm", onClick: action.onClick, disabled: action.disabled, children: action.label }))] })] }));
|
|
2990
|
+
}
|
|
2991
|
+
|
|
2244
2992
|
function ModalHeader({ title, icon, onClose, closeAriaLabel = 'Fechar', align = 'center' }) {
|
|
2245
2993
|
const CloseIcon = (jsxRuntimeExports.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, children: jsxRuntimeExports.jsx("path", { d: "M18.3 5.71a1 1 0 00-1.41 0L12 10.59 7.11 5.7A1 1 0 105.7 7.11L10.59 12l-4.9 4.89a1 1 0 101.42 1.42L12 13.41l4.89 4.9a1 1 0 001.42-1.42L13.41 12l4.9-4.89a1 1 0 000-1.4z" }) }));
|
|
2246
2994
|
if (align === 'center') {
|
|
@@ -2255,7 +3003,8 @@ function ModalHeader({ title, icon, onClose, closeAriaLabel = 'Fechar', align =
|
|
|
2255
3003
|
alignItems: 'center',
|
|
2256
3004
|
justifyContent: 'center',
|
|
2257
3005
|
fontSize: '1.25rem',
|
|
2258
|
-
lineHeight: 0
|
|
3006
|
+
lineHeight: 0,
|
|
3007
|
+
opacity: 0.5
|
|
2259
3008
|
};
|
|
2260
3009
|
const closeBox = {
|
|
2261
3010
|
position: 'absolute',
|
|
@@ -2287,7 +3036,7 @@ function ModalHeader({ title, icon, onClose, closeAriaLabel = 'Fechar', align =
|
|
|
2287
3036
|
padding: '16px 24px',
|
|
2288
3037
|
marginBottom: 16,
|
|
2289
3038
|
borderBottom: '1px solid var(--border-color)'
|
|
2290
|
-
}, children: [icon && (jsxRuntimeExports.jsx("div", { "aria-hidden": true, style: { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: 32, height: 32, fontSize: '1.25rem', lineHeight: 0 }, children: icon })), jsxRuntimeExports.jsx("div", { style: { margin: 0, fontSize: '1.125rem', fontWeight: 600, flex: 1 }, children: typeof title === 'string' ? (jsxRuntimeExports.jsx("h3", { style: { margin: 0 }, children: title })) : (title) }), onClose && (jsxRuntimeExports.jsx("button", { type: "button", "aria-label": closeAriaLabel, onClick: onClose, style: { marginLeft: 'auto', background: 'transparent', border: 'none', width: 32, height: 32, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', lineHeight: 0 }, children: CloseIcon }))] }));
|
|
3039
|
+
}, children: [icon && (jsxRuntimeExports.jsx("div", { "aria-hidden": true, style: { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: 32, height: 32, fontSize: '1.25rem', lineHeight: 0, opacity: 0.5 }, children: icon })), jsxRuntimeExports.jsx("div", { style: { margin: 0, fontSize: '1.125rem', fontWeight: 600, flex: 1 }, children: typeof title === 'string' ? (jsxRuntimeExports.jsx("h3", { style: { margin: 0 }, children: title })) : (title) }), onClose && (jsxRuntimeExports.jsx("button", { type: "button", "aria-label": closeAriaLabel, onClick: onClose, style: { marginLeft: 'auto', background: 'transparent', border: 'none', width: 32, height: 32, display: 'inline-flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', lineHeight: 0 }, children: CloseIcon }))] }));
|
|
2291
3040
|
}
|
|
2292
3041
|
|
|
2293
3042
|
function ModalBody({ children, style, className }) {
|
|
@@ -2319,11 +3068,19 @@ exports.Button = Button;
|
|
|
2319
3068
|
exports.CellRenderers = CellRenderers;
|
|
2320
3069
|
exports.ConfirmDialog = ConfirmDialog;
|
|
2321
3070
|
exports.DataTable = DataTable;
|
|
3071
|
+
exports.DetailModal = DetailModal;
|
|
3072
|
+
exports.FormField = FormField;
|
|
3073
|
+
exports.FormGrid = FormGrid;
|
|
3074
|
+
exports.FormModal = FormModal;
|
|
3075
|
+
exports.FormSection = FormSection;
|
|
2322
3076
|
exports.GlassCard = GlassCard;
|
|
3077
|
+
exports.InfoBox = InfoBox;
|
|
3078
|
+
exports.InfoRow = InfoRow;
|
|
2323
3079
|
exports.Modal = Modal;
|
|
2324
3080
|
exports.ModalBody = ModalBody;
|
|
2325
3081
|
exports.ModalFooter = ModalFooter;
|
|
2326
3082
|
exports.ModalHeader = ModalHeader;
|
|
3083
|
+
exports.ProfileCard = ProfileCard;
|
|
2327
3084
|
exports.Select = Select;
|
|
2328
3085
|
exports.TableHeader = TableHeader;
|
|
2329
3086
|
exports.TableRow = TableRow;
|