@metropolle/design-system 1.2025.1-2.5.1903 → 1.2026.0-1.1.1728

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.
@@ -1372,12 +1372,35 @@ function cn(...classes) {
1372
1372
  /**
1373
1373
  * Glass Card Component
1374
1374
  *
1375
- * Componente de cartão com efeito glassmorphism baseado na identidade Metropolle.
1376
- * Migrado dos componentes Angular existentes com melhorias.
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(({ variant = 'light', blur = 20, opacity, children, className, enableHover = true, style, ...props }, ref) => {
1390
+ const GlassCard = require$$0.forwardRef(({ glassStyle = 'liquid', intensity = 'md', theme, variant = 'light', blur, opacity, children, className, enableHover = true, 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
+ return (jsxRuntimeExports.jsx("div", { ref: ref, className: cn('mds-liquid-glass', `mds-liquid-glass--${intensity}`, !enableHover && 'mds-liquid-glass--no-hover', className), style: style, ...props, children: children }));
1398
+ }
1399
+ // =====================
1400
+ // GLASS MODE (legacy)
1401
+ // =====================
1379
1402
  // Default opacities baseadas no design existente
1380
- const defaultOpacity = variant === 'light' ? 0.15 : 0.8;
1403
+ const defaultOpacity = resolvedTheme === 'light' ? 0.15 : 0.8;
1381
1404
  const finalOpacity = opacity ?? defaultOpacity;
1382
1405
  // Use CSS classes for base styles to avoid hydration mismatches
1383
1406
  const baseStyles = {
@@ -1385,12 +1408,16 @@ const GlassCard = require$$0.forwardRef(({ variant = 'light', blur = 20, opacity
1385
1408
  };
1386
1409
  // Only apply custom styles for non-default values
1387
1410
  const customStyles = {};
1388
- if (blur !== 20) {
1389
- customStyles.backdropFilter = `blur(${blur}px)`;
1390
- customStyles.WebkitBackdropFilter = `blur(${blur}px)`;
1411
+ // Support legacy blur prop or convert from intensity
1412
+ const resolvedBlur = blur ?? (intensity ? {
1413
+ xs: 2, sm: 4, md: 6, lg: 8, xl: 12
1414
+ }[intensity] : 20);
1415
+ if (resolvedBlur !== 20) {
1416
+ customStyles.backdropFilter = `blur(${resolvedBlur}px)`;
1417
+ customStyles.WebkitBackdropFilter = `blur(${resolvedBlur}px)`;
1391
1418
  }
1392
1419
  if (opacity !== undefined) {
1393
- customStyles.background = variant === 'light'
1420
+ customStyles.background = resolvedTheme === 'light'
1394
1421
  ? `rgba(255, 255, 255, ${finalOpacity})`
1395
1422
  : `rgba(60, 60, 60, ${finalOpacity})`;
1396
1423
  }
@@ -1405,7 +1432,7 @@ const GlassCard = require$$0.forwardRef(({ variant = 'light', blur = 20, opacity
1405
1432
  borderColor: 'rgba(255, 255, 255, 0.2)',
1406
1433
  background: opacity !== undefined ? `rgba(70, 70, 70, ${finalOpacity})` : undefined,
1407
1434
  }
1408
- }[variant] : {};
1435
+ }[resolvedTheme] : {};
1409
1436
  const handleMouseEnter = (e) => {
1410
1437
  if (!enableHover)
1411
1438
  return;
@@ -1423,7 +1450,7 @@ const GlassCard = require$$0.forwardRef(({ variant = 'light', blur = 20, opacity
1423
1450
  });
1424
1451
  props.onMouseLeave?.(e);
1425
1452
  };
1426
- return (jsxRuntimeExports.jsx("div", { ref: ref, className: cn('mds-glass-card', `mds-glass-card--${variant}`, !enableHover && 'mds-glass-card--no-hover', className), style: {
1453
+ return (jsxRuntimeExports.jsx("div", { ref: ref, className: cn('mds-glass-card', `mds-glass-card--${resolvedTheme}`, !enableHover && 'mds-glass-card--no-hover', className), style: {
1427
1454
  ...baseStyles,
1428
1455
  ...customStyles,
1429
1456
  ...style
@@ -1495,22 +1522,241 @@ const LoadingSpinner = () => (jsxRuntimeExports.jsxs("svg", { className: "mds-sp
1495
1522
  /**
1496
1523
  * Select Component (Design System)
1497
1524
  *
1498
- * Provides a themed select element with multiple variants:
1499
- * - `base`: Standard form select with mds-input styling
1500
- * - `themed`: Generic themed select with dashboard control styling (recommended)
1501
- * - `dashboard`: Legacy alias for themed variant (backward compatibility)
1525
+ * Custom dropdown select that renders consistently across all browsers.
1526
+ * Unlike native <select>, this component renders the dropdown via JavaScript,
1527
+ * ensuring proper theming support on Edge/Chrome Windows.
1528
+ *
1529
+ * @example
1530
+ * ```tsx
1531
+ * <Select
1532
+ * options={[
1533
+ * { label: 'Option 1', value: '1' },
1534
+ * { label: 'Option 2', value: '2' },
1535
+ * ]}
1536
+ * value={selectedValue}
1537
+ * onChange={setSelectedValue}
1538
+ * placeholder="Select an option..."
1539
+ * />
1540
+ * ```
1502
1541
  */
1503
- const Select = require$$0.forwardRef(({ options, children, className, containerClassName, variant = 'themed', ...rest }, ref) => {
1504
- const isThemed = variant === 'themed' || variant === 'dashboard';
1505
- const selectEl = (jsxRuntimeExports.jsx("select", { ref: ref, className: cn(isThemed
1506
- ? 'mds-select-themed'
1507
- : 'mds-input mds-select', className), ...rest, children: options
1508
- ? options.map(opt => (jsxRuntimeExports.jsx("option", { value: opt.value, children: opt.label }, opt.value)))
1509
- : children }));
1510
- if (isThemed) {
1511
- return (jsxRuntimeExports.jsx("div", { className: cn('mds-dropdown', containerClassName), children: selectEl }));
1512
- }
1513
- return selectEl;
1542
+ 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) => {
1543
+ const [isOpen, setIsOpen] = require$$0.useState(false);
1544
+ const [searchTerm, setSearchTerm] = require$$0.useState('');
1545
+ const [highlightedIndex, setHighlightedIndex] = require$$0.useState(-1);
1546
+ const [mounted, setMounted] = require$$0.useState(false);
1547
+ const triggerRef = require$$0.useRef(null);
1548
+ const dropdownRef = require$$0.useRef(null);
1549
+ const searchInputRef = require$$0.useRef(null);
1550
+ const listRef = require$$0.useRef(null);
1551
+ // Combine refs
1552
+ const combinedRef = (el) => {
1553
+ triggerRef.current = el;
1554
+ if (typeof ref === 'function') {
1555
+ ref(el);
1556
+ }
1557
+ else if (ref) {
1558
+ ref.current = el;
1559
+ }
1560
+ };
1561
+ // Client-side only
1562
+ require$$0.useEffect(() => {
1563
+ setMounted(true);
1564
+ }, []);
1565
+ // Filter options based on search
1566
+ const filteredOptions = require$$0.useMemo(() => {
1567
+ if (!searchTerm)
1568
+ return options;
1569
+ const term = searchTerm.toLowerCase();
1570
+ return options.filter(opt => {
1571
+ const label = typeof opt.label === 'string' ? opt.label : String(opt.value);
1572
+ return label.toLowerCase().includes(term);
1573
+ });
1574
+ }, [options, searchTerm]);
1575
+ // Get selected option label
1576
+ const selectedOption = require$$0.useMemo(() => {
1577
+ return options.find(opt => opt.value === value);
1578
+ }, [options, value]);
1579
+ // Handle dropdown positioning
1580
+ const [dropdownPosition, setDropdownPosition] = require$$0.useState({ top: 0, left: 0, width: 0 });
1581
+ const updateDropdownPosition = require$$0.useCallback(() => {
1582
+ if (!triggerRef.current)
1583
+ return;
1584
+ const rect = triggerRef.current.getBoundingClientRect();
1585
+ const viewportHeight = window.innerHeight;
1586
+ const spaceBelow = viewportHeight - rect.bottom;
1587
+ const spaceAbove = rect.top;
1588
+ // Determine if dropdown should open above or below
1589
+ const dropdownHeight = Math.min(maxHeight, filteredOptions.length * 40 + (searchable ? 48 : 0));
1590
+ const openAbove = spaceBelow < dropdownHeight && spaceAbove > spaceBelow;
1591
+ setDropdownPosition({
1592
+ top: openAbove ? rect.top - dropdownHeight : rect.bottom + 4,
1593
+ left: rect.left,
1594
+ width: rect.width,
1595
+ });
1596
+ }, [maxHeight, filteredOptions.length, searchable]);
1597
+ // Open dropdown
1598
+ const openDropdown = require$$0.useCallback(() => {
1599
+ if (disabled || loading)
1600
+ return;
1601
+ updateDropdownPosition();
1602
+ setIsOpen(true);
1603
+ setSearchTerm('');
1604
+ setHighlightedIndex(value ? filteredOptions.findIndex(opt => opt.value === value) : 0);
1605
+ }, [disabled, loading, updateDropdownPosition, value, filteredOptions]);
1606
+ // Close dropdown
1607
+ const closeDropdown = require$$0.useCallback(() => {
1608
+ setIsOpen(false);
1609
+ setSearchTerm('');
1610
+ setHighlightedIndex(-1);
1611
+ triggerRef.current?.focus();
1612
+ }, []);
1613
+ // Handle option select
1614
+ const handleSelect = require$$0.useCallback((optionValue) => {
1615
+ // Safety check: ensure we're passing a string, not an object
1616
+ const safeValue = typeof optionValue === 'string' ? optionValue : String(optionValue);
1617
+ onChange?.(safeValue);
1618
+ closeDropdown();
1619
+ }, [onChange, closeDropdown]);
1620
+ // Keyboard navigation
1621
+ const handleKeyDown = require$$0.useCallback((e) => {
1622
+ if (disabled || loading)
1623
+ return;
1624
+ switch (e.key) {
1625
+ case 'Enter':
1626
+ case ' ':
1627
+ e.preventDefault();
1628
+ if (isOpen && highlightedIndex >= 0 && filteredOptions[highlightedIndex]) {
1629
+ const opt = filteredOptions[highlightedIndex];
1630
+ if (!opt.disabled) {
1631
+ handleSelect(opt.value);
1632
+ }
1633
+ }
1634
+ else if (!isOpen) {
1635
+ openDropdown();
1636
+ }
1637
+ break;
1638
+ case 'ArrowDown':
1639
+ e.preventDefault();
1640
+ if (!isOpen) {
1641
+ openDropdown();
1642
+ }
1643
+ else {
1644
+ setHighlightedIndex(prev => {
1645
+ const next = prev + 1;
1646
+ return next >= filteredOptions.length ? 0 : next;
1647
+ });
1648
+ }
1649
+ break;
1650
+ case 'ArrowUp':
1651
+ e.preventDefault();
1652
+ if (isOpen) {
1653
+ setHighlightedIndex(prev => {
1654
+ const next = prev - 1;
1655
+ return next < 0 ? filteredOptions.length - 1 : next;
1656
+ });
1657
+ }
1658
+ break;
1659
+ case 'Escape':
1660
+ e.preventDefault();
1661
+ closeDropdown();
1662
+ break;
1663
+ case 'Tab':
1664
+ if (isOpen) {
1665
+ closeDropdown();
1666
+ }
1667
+ break;
1668
+ case 'Home':
1669
+ if (isOpen) {
1670
+ e.preventDefault();
1671
+ setHighlightedIndex(0);
1672
+ }
1673
+ break;
1674
+ case 'End':
1675
+ if (isOpen) {
1676
+ e.preventDefault();
1677
+ setHighlightedIndex(filteredOptions.length - 1);
1678
+ }
1679
+ break;
1680
+ }
1681
+ }, [disabled, loading, isOpen, highlightedIndex, filteredOptions, handleSelect, openDropdown, closeDropdown]);
1682
+ // Click outside to close
1683
+ require$$0.useEffect(() => {
1684
+ if (!isOpen)
1685
+ return;
1686
+ const handleClickOutside = (e) => {
1687
+ if (triggerRef.current?.contains(e.target) ||
1688
+ dropdownRef.current?.contains(e.target)) {
1689
+ return;
1690
+ }
1691
+ closeDropdown();
1692
+ };
1693
+ document.addEventListener('mousedown', handleClickOutside);
1694
+ return () => document.removeEventListener('mousedown', handleClickOutside);
1695
+ }, [isOpen, closeDropdown]);
1696
+ // Update position on scroll/resize
1697
+ require$$0.useEffect(() => {
1698
+ if (!isOpen)
1699
+ return;
1700
+ const handleUpdate = () => updateDropdownPosition();
1701
+ window.addEventListener('scroll', handleUpdate, true);
1702
+ window.addEventListener('resize', handleUpdate);
1703
+ return () => {
1704
+ window.removeEventListener('scroll', handleUpdate, true);
1705
+ window.removeEventListener('resize', handleUpdate);
1706
+ };
1707
+ }, [isOpen, updateDropdownPosition]);
1708
+ // Focus search input when dropdown opens
1709
+ require$$0.useEffect(() => {
1710
+ if (isOpen && searchable && searchInputRef.current) {
1711
+ searchInputRef.current.focus();
1712
+ }
1713
+ }, [isOpen, searchable]);
1714
+ // Scroll highlighted option into view
1715
+ require$$0.useEffect(() => {
1716
+ if (!isOpen || highlightedIndex < 0 || !listRef.current)
1717
+ return;
1718
+ const highlighted = listRef.current.children[highlightedIndex];
1719
+ if (highlighted) {
1720
+ highlighted.scrollIntoView({ block: 'nearest' });
1721
+ }
1722
+ }, [isOpen, highlightedIndex]);
1723
+ // Size classes
1724
+ const sizeClasses = {
1725
+ sm: 'mds-select--sm',
1726
+ md: 'mds-select--md',
1727
+ lg: 'mds-select--lg',
1728
+ };
1729
+ // Variant classes
1730
+ const variantClasses = {
1731
+ base: 'mds-select--base',
1732
+ themed: 'mds-select--themed',
1733
+ dashboard: 'mds-select--themed',
1734
+ };
1735
+ 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);
1736
+ const dropdownClasses = cn('mds-select-dropdown', variantClasses[variant], dropdownClassName);
1737
+ // Hidden input for form submission
1738
+ const hiddenInput = name ? (jsxRuntimeExports.jsx("input", { type: "hidden", name: name, value: value || '' })) : null;
1739
+ // Dropdown portal content
1740
+ const dropdownContent = isOpen && mounted ? reactDom.createPortal(jsxRuntimeExports.jsxs("div", { ref: dropdownRef, className: dropdownClasses, style: {
1741
+ position: 'fixed',
1742
+ top: dropdownPosition.top,
1743
+ left: dropdownPosition.left,
1744
+ width: dropdownPosition.width,
1745
+ maxHeight,
1746
+ zIndex,
1747
+ }, 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) => {
1748
+ setSearchTerm(e.target.value);
1749
+ setHighlightedIndex(0);
1750
+ }, 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: () => {
1751
+ if (!option.disabled) {
1752
+ handleSelect(option.value);
1753
+ }
1754
+ }, onMouseEnter: () => {
1755
+ if (!option.disabled) {
1756
+ setHighlightedIndex(index);
1757
+ }
1758
+ }, 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;
1759
+ 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
1760
  });
1515
1761
  Select.displayName = 'Select';
1516
1762
 
@@ -2186,12 +2432,82 @@ const getTableConfig = (type) => {
2186
2432
  }
2187
2433
  };
2188
2434
 
2435
+ /**
2436
+ * Theme-aware styles generator - Liquid Glass pattern
2437
+ *
2438
+ * Light theme: White semi-transparent overlay to keep background bright
2439
+ * Dark theme: Dark overlay for contrast
2440
+ */
2441
+ function getStyles(isDark) {
2442
+ return {
2443
+ // Overlay behind the modal
2444
+ overlay: {
2445
+ position: 'fixed',
2446
+ inset: 0,
2447
+ zIndex: 9999,
2448
+ display: 'flex',
2449
+ alignItems: 'center',
2450
+ justifyContent: 'center',
2451
+ padding: 20,
2452
+ // Light theme: white overlay to keep brightness
2453
+ // Dark theme: dark overlay for contrast
2454
+ backgroundColor: isDark ? 'rgba(0, 0, 0, 0.6)' : 'rgba(255, 255, 255, 0.4)',
2455
+ backdropFilter: 'blur(8px)',
2456
+ WebkitBackdropFilter: 'blur(8px)',
2457
+ },
2458
+ // Modal card - Liquid Glass
2459
+ card: {
2460
+ position: 'relative',
2461
+ maxWidth: 640,
2462
+ width: '100%',
2463
+ borderRadius: 24,
2464
+ overflow: 'hidden',
2465
+ // Light theme: Liquid Glass transparency
2466
+ // Dark theme: subtle glass effect
2467
+ background: isDark
2468
+ ? 'rgba(255, 255, 255, 0.03)'
2469
+ : 'rgba(255, 255, 255, 0.55)',
2470
+ // Liquid Glass: Strong blur + saturation
2471
+ backdropFilter: 'blur(var(--mds-liquid-blur-xl, 24px)) saturate(var(--mds-liquid-saturate-vibrant, 140%))',
2472
+ WebkitBackdropFilter: 'blur(var(--mds-liquid-blur-xl, 24px)) saturate(var(--mds-liquid-saturate-vibrant, 140%))',
2473
+ // Liquid Glass: Subtle border for edge definition
2474
+ border: isDark
2475
+ ? '1px solid rgba(255, 255, 255, 0.08)'
2476
+ : '1px solid rgba(255, 255, 255, 0.9)',
2477
+ // Liquid Glass: Layered shadows + inner glow
2478
+ boxShadow: isDark
2479
+ ? '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))'
2480
+ : '0 8px 32px rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 1)',
2481
+ // Liquid Glass: Smooth transition
2482
+ transition: 'var(--mds-liquid-transition, all 0.25s cubic-bezier(0.25, 0.1, 0.25, 1))',
2483
+ },
2484
+ };
2485
+ }
2189
2486
  function Modal({ open, onClose, closeOnOverlay = true, children, className, style }) {
2190
2487
  const [mounted, setMounted] = require$$0.useState(false);
2191
2488
  const [visible, setVisible] = require$$0.useState(false);
2192
2489
  const [renderPortal, setRenderPortal] = require$$0.useState(false);
2490
+ const [isDarkTheme, setIsDarkTheme] = require$$0.useState(true);
2193
2491
  const containerRef = require$$0.useRef(null);
2194
2492
  require$$0.useEffect(() => setMounted(true), []);
2493
+ // Detect theme - EXACT same pattern as ProfileCard.tsx
2494
+ require$$0.useEffect(() => {
2495
+ const checkTheme = () => {
2496
+ const theme = document.documentElement.getAttribute('data-theme');
2497
+ setIsDarkTheme(theme !== 'light');
2498
+ };
2499
+ checkTheme();
2500
+ // Watch for theme changes
2501
+ const observer = new MutationObserver((mutations) => {
2502
+ mutations.forEach((mutation) => {
2503
+ if (mutation.attributeName === 'data-theme') {
2504
+ checkTheme();
2505
+ }
2506
+ });
2507
+ });
2508
+ observer.observe(document.documentElement, { attributes: true });
2509
+ return () => observer.disconnect();
2510
+ }, []);
2195
2511
  require$$0.useEffect(() => {
2196
2512
  if (!mounted)
2197
2513
  return;
@@ -2217,27 +2533,21 @@ function Modal({ open, onClose, closeOnOverlay = true, children, className, styl
2217
2533
  }, [open, onClose]);
2218
2534
  if (!mounted || (!renderPortal && !open))
2219
2535
  return null;
2536
+ // Get theme-aware styles (same pattern as ProfileCard)
2537
+ const styles = getStyles(isDarkTheme);
2220
2538
  const overlayStyle = {
2221
- position: 'fixed',
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',
2539
+ ...styles.overlay,
2229
2540
  opacity: visible ? 1 : 0,
2230
- transition: 'opacity 200ms ease'
2541
+ transition: 'opacity 200ms ease',
2231
2542
  };
2232
- const innerStyle = {
2233
- maxWidth: '640px',
2234
- width: '100%',
2235
- transform: visible ? 'scale(1)' : 'scale(0.98)',
2543
+ const cardStyle = {
2544
+ ...styles.card,
2545
+ transform: visible ? 'scale(1)' : 'scale(0.96)',
2236
2546
  opacity: visible ? 1 : 0,
2237
- transition: 'opacity 200ms ease, transform 200ms ease',
2238
- ...style
2547
+ transition: 'opacity 200ms ease, transform 200ms cubic-bezier(0.4, 0, 0.2, 1)',
2548
+ ...style,
2239
2549
  };
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: innerStyle, onClick: (e) => e.stopPropagation(), ref: (el) => (containerRef.current = el), children: children }) }));
2550
+ 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
2551
  return reactDom.createPortal(content, document.body);
2242
2552
  }
2243
2553