import { Card, Col, Row } from "antd"; import { Children, isValidElement } from "react"; import "./layout-form-row.styles.scss"; export default function LayoutFormRow({ header, children, grow = false, noDivider = false, gutter = [16, 16], // Responsive gutter: horizontal, vertical rowProps, // Optional overrides if you ever need per-section customization surface = true, surfaceBg, surfaceHeaderBg, ...cardProps }) { const items = Children.toArray(children).filter(Boolean); if (items.length === 0) return null; const title = !noDivider && header ? header : undefined; const bg = surfaceBg ?? (surface ? "var(--imex-form-surface)" : undefined); const headBg = surfaceHeaderBg ?? (surface ? "var(--imex-form-surface-head)" : undefined); const mergedStyles = mergeSemanticStyles( { header: { paddingInline: 16, background: headBg }, body: { padding: 16, background: bg } }, cardProps.styles ); const baseCardStyle = { marginBottom: ".8rem", ...(bg ? { background: bg } : null), // ensures the “circled area” is tinted ...cardProps.style }; // single child => just render it if (items.length === 1) { return ( {items[0]} ); } const count = items.length; // Modern responsive strategy leveraging Ant Design 6: // - xs (phone <576px): Always stack vertically // - sm (tablet 576-768px): 2 columns for better readability // - md (tablet 768-992px): 3 columns for tablets // - lg+ (desktop >992px): Dynamic flex-based columns that adapt to screen width // Target: 1366px → 4 cols, 1920px → 6 cols, 2560px → 8 cols, 4K → capped at 8-9 cols // Note: xxl uses higher min-width to naturally cap maximum columns const baseCol = (() => { if (grow) { // Grow mode: use flex with reasonable min-widths return { xs: 24, sm: 12, // Fixed 2 cols on small tablets md: 8, // Fixed 3 cols on large tablets lg: { flex: `1 1 320px` }, // Dynamic: ~3 cols at 1200px xl: { flex: `1 1 280px` }, // Dynamic: ~4 cols at 1366px, ~6 cols at 1920px xxl: { flex: `1 1 380px` } // Dynamic: ~6 cols at 2560px, ~9 cols at 4K (capped) }; } else { // Fixed mode: Use flex without grow to maintain uniform widths across rows // xxl uses larger min-width to cap maximum columns on 4K/ultrawide const minWidthLg = count <= 2 ? 500 : count === 3 ? 380 : 320; // 3 cols at 1200px const minWidthXl = count <= 2 ? 480 : count === 3 ? 360 : 280; // 4 cols at 1366px, ~6 at 1920px const minWidthXxl = count <= 2 ? 500 : count === 3 ? 400 : 380; // ~6 cols at 2560px, ~9 at 4K (natural cap) return { xs: 24, sm: 12, // Fixed 2 columns on tablet md: count === 1 ? 24 : count === 2 ? 12 : 8, // Fixed 1-3 cols on large tablet lg: count === 1 ? 24 : { flex: `0 0 ${minWidthLg}px` }, // Fixed width on desktop xl: count === 1 ? 24 : { flex: `0 0 ${minWidthXl}px` }, // Fixed width on large desktop xxl: count === 1 ? 24 : { flex: `0 0 ${minWidthXxl}px` } // Fixed width on ultrawide }; } })(); const getColPropsForChild = (child) => { if (!isValidElement(child)) return baseCol; // Back-compat: child.props.span can override Col sizing const spanOverride = child.props?.span; if (typeof spanOverride === "number") return { span: spanOverride }; if (spanOverride && typeof spanOverride === "object") return spanOverride; // Explicit override: const colOverride = child.props?.col; if (colOverride && typeof colOverride === "object") { // Deep merge: allow partial overrides while keeping baseCol defaults const merged = { ...baseCol }; Object.keys(colOverride).forEach((bp) => { merged[bp] = typeof colOverride[bp] === "object" ? { ...baseCol[bp], ...colOverride[bp] } : colOverride[bp]; }); return merged; } return baseCol; }; return ( {items.map((child, idx) => ( {child} ))} ); } function mergeSemanticStyles(defaults, userStyles) { if (!userStyles) return defaults; if (typeof userStyles === "function") { return (info) => { const computed = userStyles(info) || {}; return { ...defaults, ...computed, header: { ...defaults.header, ...(computed.header || {}) }, body: { ...defaults.body, ...(computed.body || {}) } }; }; } return { ...defaults, ...userStyles, header: { ...defaults.header, ...(userStyles.header || {}) }, body: { ...defaults.body, ...(userStyles.body || {}) } }; }