/** * Grid Component - Lynx 版 MUI Grid * 一比一对应 MUI Grid v2 * * 12 列响应式网格布局系统 * 支持: * - container: 容器模式 * - size: 栅格大小 (1-12, 'auto', 'grow') * - spacing: 间距 * - direction: 排列方向 * - wrap: 换行模式 * - offset: 偏移量 */ import './Grid.css' // ============================================= // Grid 类型定义 // ============================================= export type GridSize = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 'auto' | 'grow' | boolean export type GridDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse' export type GridWrap = 'nowrap' | 'wrap' | 'wrap-reverse' export interface GridProps { /** 子元素 */ children?: any /** 自定义类名 */ className?: string /** 内联样式 */ style?: Record /** 是否为容器 */ container?: boolean /** 栅格大小 */ size?: GridSize | { xs?: GridSize; sm?: GridSize; md?: GridSize; lg?: GridSize; xl?: GridSize } /** 列数 */ columns?: number /** 间距 */ spacing?: number | string /** 行间距 */ rowSpacing?: number | string /** 列间距 */ columnSpacing?: number | string /** 排列方向 */ direction?: GridDirection /** 换行模式 */ wrap?: GridWrap /** 偏移量 */ offset?: number | 'auto' /** sx 属性 */ sx?: Record } // ============================================= // Grid 类名 // ============================================= export const gridClasses = { root: 'MuiGrid-root', container: 'MuiGrid-container', item: 'MuiGrid-item', directionRow: 'MuiGrid-direction-row', directionColumn: 'MuiGrid-direction-column', wrapWrap: 'MuiGrid-wrap-wrap', wrapNowrap: 'MuiGrid-wrap-nowrap', } // ============================================= // 间距单位 // ============================================= const spacingUnit = 8 // ============================================= // Grid 组件实现 // ============================================= export function Grid(props: GridProps) { const { children, className, style, container = false, size, columns = 12, spacing = 0, rowSpacing, columnSpacing, direction = 'row', wrap = 'wrap', offset, sx, ...other } = props // 计算间距值 const getSpacingValue = (value: number | string | undefined) => { if (value === undefined) return undefined return typeof value === 'number' ? `${value * spacingUnit}px` : value } const gapValue = getSpacingValue(spacing) const rowGapValue = getSpacingValue(rowSpacing) || gapValue const columnGapValue = getSpacingValue(columnSpacing) || gapValue // 计算栅格宽度 const getGridSize = (sizeValue: GridSize | undefined): string | undefined => { if (sizeValue === undefined) return undefined if (sizeValue === true || sizeValue === 'grow') return '1' if (sizeValue === 'auto') return 'auto' if (typeof sizeValue === 'number') { return `${(sizeValue / columns) * 100}%` } return undefined } // 获取 size 值 const sizeValue = typeof size === 'object' ? size.xs : size const gridWidth = getGridSize(sizeValue) // 构建类名 const classes = [ gridClasses.root, container && gridClasses.container, !container && gridClasses.item, `MuiGrid-direction-${direction}`, `MuiGrid-wrap-${wrap}`, size && typeof size === 'number' && `MuiGrid-size-${size}`, className, ].filter(Boolean).join(' ') // 计算样式 const computedStyle: Record = { ...(container && { display: 'flex', flexDirection: direction, flexWrap: wrap, ...(gapValue && { gap: gapValue }), ...(rowGapValue && columnGapValue && rowGapValue !== columnGapValue && { rowGap: rowGapValue, columnGap: columnGapValue, }), }), ...(!container && { ...(gridWidth && { flexBasis: gridWidth, flexGrow: sizeValue === 'grow' || sizeValue === true ? 1 : 0, maxWidth: gridWidth !== 'auto' ? gridWidth : undefined, }), ...(offset !== undefined && { marginLeft: offset === 'auto' ? 'auto' : `${(offset / columns) * 100}%`, }), }), ...sx, ...style, } return ( {children} ) } export default Grid