'use client'; import React, { forwardRef } from 'react'; import { cn, Surface, useEffectiveSurface, surfaceClasses } from '../common'; import { stackGap, StackGapKey } from '../tokens'; type ColCount = 1 | 2 | 3 | 4 | 5 | 6 | 12; type RowCount = 1 | 2 | 3 | 4 | 5 | 6; type ResponsiveCols = { base?: ColCount; sm?: ColCount; md?: ColCount; lg?: ColCount; xl?: ColCount; }; const baseColsMap: Record = { 1: 'grid-cols-1', 2: 'grid-cols-2', 3: 'grid-cols-3', 4: 'grid-cols-4', 5: 'grid-cols-5', 6: 'grid-cols-6', 12: 'grid-cols-12', }; const smColsMap: Record = { 1: 'sm:grid-cols-1', 2: 'sm:grid-cols-2', 3: 'sm:grid-cols-3', 4: 'sm:grid-cols-4', 5: 'sm:grid-cols-5', 6: 'sm:grid-cols-6', 12: 'sm:grid-cols-12', }; const mdColsMap: Record = { 1: 'md:grid-cols-1', 2: 'md:grid-cols-2', 3: 'md:grid-cols-3', 4: 'md:grid-cols-4', 5: 'md:grid-cols-5', 6: 'md:grid-cols-6', 12: 'md:grid-cols-12', }; const lgColsMap: Record = { 1: 'lg:grid-cols-1', 2: 'lg:grid-cols-2', 3: 'lg:grid-cols-3', 4: 'lg:grid-cols-4', 5: 'lg:grid-cols-5', 6: 'lg:grid-cols-6', 12: 'lg:grid-cols-12', }; const xlColsMap: Record = { 1: 'xl:grid-cols-1', 2: 'xl:grid-cols-2', 3: 'xl:grid-cols-3', 4: 'xl:grid-cols-4', 5: 'xl:grid-cols-5', 6: 'xl:grid-cols-6', 12: 'xl:grid-cols-12', }; const rowsMap: Record = { 1: 'grid-rows-1', 2: 'grid-rows-2', 3: 'grid-rows-3', 4: 'grid-rows-4', 5: 'grid-rows-5', 6: 'grid-rows-6', }; const colGapMap: Record = { 0: 'gap-x-0', 1: 'gap-x-1', 2: 'gap-x-2', 3: 'gap-x-3', 4: 'gap-x-4', 5: 'gap-x-5', 6: 'gap-x-6', 8: 'gap-x-8', 10: 'gap-x-10', 12: 'gap-x-12', 16: 'gap-x-16', }; const rowGapMap: Record = { 0: 'gap-y-0', 1: 'gap-y-1', 2: 'gap-y-2', 3: 'gap-y-3', 4: 'gap-y-4', 5: 'gap-y-5', 6: 'gap-y-6', 8: 'gap-y-8', 10: 'gap-y-10', 12: 'gap-y-12', 16: 'gap-y-16', }; const alignMap = { start: 'items-start', center: 'items-center', end: 'items-end', stretch: 'items-stretch', } as const; const justifyMap = { start: 'justify-items-start', center: 'justify-items-center', end: 'justify-items-end', stretch: 'justify-items-stretch', } as const; export interface PixelGridProps extends React.HTMLAttributes { cols?: ColCount | ResponsiveCols; rows?: RowCount; gap?: StackGapKey; colGap?: StackGapKey; rowGap?: StackGapKey; autoFit?: boolean; autoFill?: boolean; minColWidth?: string; align?: 'start' | 'center' | 'end' | 'stretch'; justify?: 'start' | 'center' | 'end' | 'stretch'; as?: keyof React.JSX.IntrinsicElements; surface?: Surface; } export const PixelGrid = forwardRef(function PixelGrid( { cols, rows, gap = 4, colGap, rowGap, autoFit = false, autoFill = false, minColWidth = '16rem', align, justify, as, surface: surfaceProp, className, style, children, ...rest }, ref, ) { const surface = useEffectiveSurface(surfaceProp); const s = surfaceClasses(surface); const Comp = (as ?? 'div') as 'div'; const useAuto = autoFit || autoFill; const autoMode = autoFit ? 'auto-fit' : 'auto-fill'; let colsClasses = ''; if (!useAuto && cols !== undefined) { if (typeof cols === 'number') { colsClasses = baseColsMap[cols] ?? ''; } else { const parts: string[] = []; if (cols.base !== undefined && baseColsMap[cols.base]) parts.push(baseColsMap[cols.base]); if (cols.sm !== undefined && smColsMap[cols.sm]) parts.push(smColsMap[cols.sm]); if (cols.md !== undefined && mdColsMap[cols.md]) parts.push(mdColsMap[cols.md]); if (cols.lg !== undefined && lgColsMap[cols.lg]) parts.push(lgColsMap[cols.lg]); if (cols.xl !== undefined && xlColsMap[cols.xl]) parts.push(xlColsMap[cols.xl]); colsClasses = parts.join(' '); } } const gapClass = colGap || rowGap ? '' : stackGap[gap]; const colGapClass = colGap ? colGapMap[colGap] : ''; const rowGapClass = rowGap ? rowGapMap[rowGap] : ''; const inlineStyle: React.CSSProperties = { ...style }; if (useAuto) { inlineStyle.gridTemplateColumns = `repeat(${autoMode}, minmax(min(${minColWidth}, 100%), 1fr))`; } return ( {children} ); }); PixelGrid.displayName = 'PixelGrid';