11import Box , { BoxProps } from '@mui/material/Box' ;
2+ import type { CSSObject } from 'tss-react' ;
23import { makeStyles } from 'tss-react/mui' ;
34
4- const useStyles = makeStyles ( ) ( theme => ( {
5- grid : {
6- display : 'grid' ,
7- gridTemplateColumns : 'repeat(12, 1fr)' ,
8- gridGap : theme . spacing ( 3 ) ,
9- gridAutoFlow : 'dense' ,
10- alignItems : 'start' ,
11- } ,
12- } ) ) ;
5+ const BREAKPOINTS = {
6+ sm : 600 ,
7+ md : 900 ,
8+ lg : 1200 ,
9+ xl : 1536 ,
10+ } as const ;
11+
12+ type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl' ;
13+
14+ type GridColumn = Partial < Record < Breakpoint , number | string > > ;
15+
16+ function normalize ( value ?: number | string ) {
17+ if ( typeof value === 'number' ) return `span ${ value } ` ;
18+ return value ;
19+ }
20+
21+ function extractGridColumn ( sx : BoxProps [ 'sx' ] ) : GridColumn | undefined {
22+ if ( ! sx || typeof sx !== 'object' || Array . isArray ( sx ) ) return undefined ;
23+ const gc = ( sx as any ) . gridColumn ;
24+ if ( ! gc || typeof gc !== 'object' ) return undefined ;
25+ return gc ;
26+ }
27+
28+ function removeGridColumn ( sx : BoxProps [ 'sx' ] ) {
29+ if ( ! sx || typeof sx !== 'object' || Array . isArray ( sx ) ) return sx ;
30+ const next = { ...( sx as any ) } ;
31+ delete next . gridColumn ;
32+ return next ;
33+ }
34+
35+ type StyleProps = {
36+ gridColumn : GridColumn ;
37+ } ;
38+
39+ const useStyles = makeStyles < StyleProps > ( ) ( ( theme , { gridColumn } ) => {
40+ const item : CSSObject = { } ;
41+
42+ // default xs behavior
43+ item . gridColumn = normalize ( gridColumn . xs ?? '1 / -1' ) ;
44+
45+ ( Object . keys ( BREAKPOINTS ) as ( keyof typeof BREAKPOINTS ) [ ] ) . forEach ( bp => {
46+ const value = gridColumn [ bp ] ;
47+ if ( ! value ) return ;
48+
49+ item [ `@container (min-width:${ BREAKPOINTS [ bp ] } px)` ] = {
50+ gridColumn : normalize ( value ) ,
51+ } ;
52+ } ) ;
53+
54+ return {
55+ grid : {
56+ display : 'grid' ,
57+ gridTemplateColumns : 'repeat(12, minmax(0,1fr))' ,
58+ gap : theme . spacing ( 3 ) ,
59+ gridAutoFlow : 'row' ,
60+ containerType : 'inline-size' ,
61+ } ,
62+ item,
63+ } ;
64+ } ) ;
65+
66+ type GridProps = React . PropsWithChildren <
67+ {
68+ container ?: boolean ;
69+ item ?: boolean ;
70+ } & BoxProps
71+ > ;
1372
1473const Grid = ( {
1574 container = false ,
1675 item = true ,
1776 children,
77+ sx,
1878 ...props
19- } : React . PropsWithChildren <
20- { container ?: boolean ; item ?: boolean } & BoxProps
21- > ) => {
22- const { classes } = useStyles ( ) ;
79+ } : GridProps ) => {
80+ const gridColumn = extractGridColumn ( sx ) ?? { } ;
81+
82+ const { classes, cx } = useStyles ( { gridColumn } ) ;
2383
2484 if ( container ) {
2585 return (
26- < Box { ...props } className = { classes . grid } >
86+ < Box { ...props } sx = { sx } className = { cx ( classes . grid , props . className ) } >
2787 { children }
2888 </ Box >
2989 ) ;
3090 }
91+
3192 if ( item ) {
32- return < Box { ...props } > { children } </ Box > ;
93+ const itemSx = removeGridColumn ( sx ) ;
94+
95+ return (
96+ < Box { ...props } sx = { itemSx } className = { cx ( classes . item , props . className ) } >
97+ { children }
98+ </ Box >
99+ ) ;
33100 }
101+
34102 return null ;
35103} ;
36104
37- export default Grid ;
105+ export default Grid ;
0 commit comments