diff --git a/apps/pigment-css-vite-app/src/pages/grid.tsx b/apps/pigment-css-vite-app/src/pages/grid.tsx
index e0ec1d75..ee70440f 100644
--- a/apps/pigment-css-vite-app/src/pages/grid.tsx
+++ b/apps/pigment-css-vite-app/src/pages/grid.tsx
@@ -1,8 +1,9 @@
import * as React from 'react';
+import Box from '@pigment-css/react/Box';
import Grid from '@pigment-css/react/Grid';
import { styled } from '@pigment-css/react';
-const Card = styled.div`
+const Item = styled.div`
background-color: #fff;
border: 1px solid #ced7e0;
padding: 8px;
@@ -10,25 +11,293 @@ const Card = styled.div`
text-align: center;
`;
-const items = [
- { id: '1', size: 2},
- { id: '2', size: 2},
-]
+function GridDemo1() {
+ return (
+
+
+ - size=8
+
+
+ - size=4
+
+
+ - size=4
+
+
+ - size=8
+
+
+ )
+}
-export default function InteractiveGrid() {
+function GridDemo2() {
+ return (
+
+
+ - xs=6 md=8
+
+
+ - xs=6 md=4
+
+
+ - xs=6 md=4
+
+
+ - xs=6 md=8
+
+
+ )
+}
+function GridDemo3() {
+ const [spacing, setSpacing] = React.useState(2);
return (
-
-
- {items.map(({ id, size, offset, extraText}) => (
- Item {id}{extraText}
+
+
+ {[0, 1, 2].map((value) => (
+
+
+
+ ))}
+
+
+ Spacing:
+ {[0, 0.5, 1, 2, 3, 4, 8, 12].map((value) => (
+
+
+
))}
+
+
+ )
+}
+
+function GridDemo4() {
+ return (
+
+
+ - 1
+
+
+ - 2
+
+
+ - 3
+
+
+ - 4
+
+
+ )
+}
+
+function GridDemo5() {
+ return (
+
+ {Array.from(Array(6)).map((_, index) => (
+
+ - {index + 1}
+
+ ))}
+
+ )
+}
+
+function GridDemo6() {
+ return (
+
+
+ - grow
+
+
+ - size=6
+
+
+ - grow
-
+
+ )
+}
+
+function GridDemo7() {
+ return (
+
+
+ - Variable width item
+
+
+ - size=6
+
+
+ - grow
+
+
+ )
+}
+
+function GridDemo8() {
+ return (
+
+
+
+ - Email subscribe section
+
+
+
+ -
+
+ Category A
+
+
+ Link 1.1
+ Link 1.2
+ Link 1.3
+
+
+
+
+ -
+
+ Category B
+
+
+ Link 2.1
+ Link 2.2
+ Link 2.3
+
+
+
+
+ -
+
+ Category C
+
+
+ Link 3.1
+ Link 3.2
+ Link 3.3
+
+
+
+
+ -
+
+ Category D
+
+
+ Link 4.1
+ Link 4.2
+ Link 4.3
+
+
+
+
+
+
+ - © Copyright
+
+
+
+ - Link A
+
+
+ - Link B
+
+
+ - Link C
+
+
+
+
+
+ )
+}
+
+function GridDemo9() {
+ return (
+
+
+ - size=8
+
+
+ - size=8
+
+
+ )
+}
+
+function GridDemo10() {
+ return (
+
+
+ - 1
+
+
+ - 2
+
+
+ - 3
+
+
+ - 4
+
+
+ )
+}
+
+const demos = [
+ { id: '1', component: GridDemo1 },
+ { id: '2', component: GridDemo2 },
+ { id: '3', component: GridDemo3 },
+ { id: '4', component: GridDemo4 },
+ { id: '5', component: GridDemo5 },
+ { id: '6', component: GridDemo6 },
+ { id: '7', component: GridDemo7 },
+ { id: '8', component: GridDemo8 },
+ { id: '9', component: GridDemo9 },
+ { id: '10', component: GridDemo10 },
+]
+
+export default function InteractiveGrid() {
+
+ return (
+
+
Benchmark v5
+
Benchmark next
+ {demos.map(demo => {
+ const Demo = demo.component;
+ return (
+
+
Grid Demo {demo.id}
+
+
+ );
+ })}
+
);
}
diff --git a/packages/pigment-css-react/src/Grid.d.ts b/packages/pigment-css-react/src/Grid.d.ts
index ee6e31d5..262d8c85 100644
--- a/packages/pigment-css-react/src/Grid.d.ts
+++ b/packages/pigment-css-react/src/Grid.d.ts
@@ -6,13 +6,15 @@ import { PolymorphicComponent } from './Box';
type CssProperty = T | Array | Partial>;
type GridBaseProps = {
- display?: CssProperty<'flex' | 'inline-flex'>;
- spacing?: CssProperty;
- direction?: CssProperty;
- justifyContent?: CssProperty;
- alignItems?: CssProperty;
- divider?: React.ReactNode;
className?: string;
+ columns?: CssProperty;
+ columnSpacing?: CssProperty;
+ container?: boolean;
+ direction?: CssProperty;
+ offset?: CssProperty;
+ rowSpacing?: CssProperty;
+ size?: CssProperty;
+ spacing?: CssProperty;
};
declare const Grid: PolymorphicComponent;
diff --git a/packages/pigment-css-react/src/Grid.jsx b/packages/pigment-css-react/src/Grid.jsx
index c8ed9cd5..200b192d 100644
--- a/packages/pigment-css-react/src/Grid.jsx
+++ b/packages/pigment-css-react/src/Grid.jsx
@@ -7,79 +7,104 @@ import * as React from 'react';
import { gridAtomics } from './baseAtomics';
import styled from './styled';
+function isGridComponent(element) {
+ // For server components `muiName` is avaialble in element.type._payload.value.muiName
+ // relevant info - https://github.com/facebook/react/blob/2807d781a08db8e9873687fccc25c0f12b4fb3d4/packages/react/src/ReactLazy.js#L45
+ // eslint-disable-next-line no-underscore-dangle
+ return element.type.muiName === 'Grid' || element.type?._payload?.value?.muiName === 'Grid';
+}
+
const GridComponent = styled('div')({
- width: 'var(--Column-width)',
- maxWidth: 'var(--Column-max-width)',
- flex: 'var(--Column-flex)',
- marginLeft: 'var(--Item-margin-left)',
variants: [
{
props: { container: true },
style: {
display: 'flex',
- gap: 'var(--Row-gap) var(--Column-gap)',
+ flexWrap: 'wrap',
+ gap: 'var(--Grid-self-row-spacing) var(--Grid-self-column-spacing)',
}
},
+ {
+ props: ({ size }) => size !== undefined,
+ style: {
+ width: 'var(--Grid-self-width)',
+ maxWidth: 'var(--Grid-self-max-width)',
+ flex: 'var(--Grid-self-flex)',
+ }
+ },
+ {
+ props: ({ offset }) => offset !== undefined,
+ style: {
+ marginLeft: 'var(--Grid-self-margin-left)',
+ }
+ }
]
})
const Grid = React.forwardRef(function Grid(
{
children,
- spacing = 0,
+ columns,
+ spacing,
columnSpacing,
rowSpacing,
+ direction = 'row',
style,
className,
component = 'div',
- direction = 'row',
- flexWrap = 'wrap',
- columns = 12,
container = false,
size,
offset,
- alignItems,
- justifyContent,
+ // internal props
+ // eslint-disable-next-line react/prop-types
+ unstable_parent_columns,
+ // eslint-disable-next-line react/prop-types
+ unstable_parent_column_spacing,
+ // eslint-disable-next-line react/prop-types
+ unstable_parent_row_spacing,
...rest
},
ref,
) {
+
+ const selfColumns = columns ?? unstable_parent_columns ?? 12;
+ const selfColumnSpacing = columnSpacing ?? spacing ?? unstable_parent_column_spacing ?? 0;
+ const selfRowSpacing = rowSpacing ?? spacing ?? unstable_parent_row_spacing ?? 0;
+
const GridAtomicsObj = {
direction,
- flexWrap,
};
- if (alignItems) {
- GridAtomicsObj.alignItems = alignItems;
+
+ if (unstable_parent_columns !== undefined) {
+ GridAtomicsObj['--Grid-parent-column-count'] = unstable_parent_columns;
}
- if (justifyContent) {
- GridAtomicsObj.justifyContent = justifyContent;
+
+ if (unstable_parent_column_spacing !== undefined) {
+ GridAtomicsObj['--Grid-parent-column-spacing'] = unstable_parent_column_spacing;
}
- if (container) {
- GridAtomicsObj['--Column-count'] = columns;
- GridAtomicsObj['--Column-gap'] = spacing;
- GridAtomicsObj['--Row-gap'] = spacing;
- if (columnSpacing) {
- GridAtomicsObj['--Column-gap'] = columnSpacing;
- }
+ if (unstable_parent_row_spacing !== undefined) {
+ GridAtomicsObj['--Grid-parent-row-spacing'] = unstable_parent_row_spacing;
+ }
- if (rowSpacing) {
- GridAtomicsObj['--Row-gap'] = rowSpacing;
- }
+ if (container) {
+ GridAtomicsObj['--Grid-self-column-spacing'] = selfColumnSpacing;
+ GridAtomicsObj['--Grid-self-row-spacing'] = selfRowSpacing;
}
+
if (size) {
- GridAtomicsObj['--Column-span'] = size;
- GridAtomicsObj['--Column-width'] = size;
- GridAtomicsObj['--Column-max-width'] = size;
- GridAtomicsObj['--Column-flex'] = size;
+ GridAtomicsObj['--Grid-self-column-span'] = size;
+ GridAtomicsObj['--Grid-self-width'] = size;
+ GridAtomicsObj['--Grid-self-max-width'] = size;
+ GridAtomicsObj['--Grid-self-flex'] = size;
}
if (offset) {
- GridAtomicsObj['--Item-offset'] = offset;
- GridAtomicsObj['--Item-margin-left'] = offset;
+ GridAtomicsObj['--Grid-self-offset'] = offset;
+ GridAtomicsObj['--Grid-self-margin-left'] = offset;
}
- const ownerState = { container };
+ const ownerState = { container, size, offset };
const GridClasses = gridAtomics(GridAtomicsObj);
return (
@@ -91,49 +116,28 @@ const Grid = React.forwardRef(function Grid(
{...rest}
ownerState={ownerState}
>
- {children}
+ {React.Children.map(children, (child) => {
+ if (React.isValidElement(child) && isGridComponent(child)) {
+ return React.cloneElement(child, {
+ unstable_parent_columns: selfColumns,
+ unstable_parent_column_spacing: selfColumnSpacing,
+ unstable_parent_row_spacing: selfRowSpacing,
+ });
+ }
+ return child;
+ })}
);
});
+Grid.muiName = 'Grid';
+
process.env.NODE_ENV !== 'production'
- ? (Grid.propTypes /* remove-proptypes */ = {
+ && (Grid.propTypes /* remove-proptypes */ = {
// ┌────────────────────────────── Warning ──────────────────────────────┐
// │ These PropTypes are generated from the TypeScript type definitions. │
// │ To update them, edit the d.ts file and run `pnpm proptypes`. │
// └─────────────────────────────────────────────────────────────────────┘
- /**
- * @ignore
- */
- alignItems: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
- PropTypes.oneOf([
- 'center',
- 'end',
- 'flex-end',
- 'flex-start',
- 'self-end',
- 'self-start',
- 'start',
- 'baseline',
- 'normal',
- 'stretch',
- ]),
- PropTypes.arrayOf(
- PropTypes.oneOf([
- 'center',
- 'end',
- 'flex-end',
- 'flex-start',
- 'self-end',
- 'self-start',
- 'start',
- 'baseline',
- 'normal',
- 'stretch',
- ]),
- ),
- PropTypes.object,
- ]),
/**
* The content of the component.
*/
@@ -142,11 +146,32 @@ process.env.NODE_ENV !== 'production'
* @ignore
*/
className: PropTypes.string,
+ /**
+ * @ignore
+ */
+ columns: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
+ PropTypes.arrayOf(PropTypes.number),
+ PropTypes.number,
+ PropTypes.object,
+ ]),
+ /**
+ * @ignore
+ */
+ columnSpacing: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
+ PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired),
+ PropTypes.number,
+ PropTypes.object,
+ PropTypes.string,
+ ]),
/**
* The component used for the root node.
* Either a string to use a HTML element or a component.
*/
component: PropTypes.elementType,
+ /**
+ * @ignore
+ */
+ container: PropTypes.bool,
/**
* @ignore
*/
@@ -158,41 +183,26 @@ process.env.NODE_ENV !== 'production'
/**
* @ignore
*/
- display: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
- PropTypes.oneOf(['flex', 'inline-flex']),
- PropTypes.arrayOf(PropTypes.oneOf(['flex', 'inline-flex']).isRequired),
+ offset: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
+ PropTypes.arrayOf(PropTypes.number),
+ PropTypes.number,
PropTypes.object,
]),
/**
* @ignore
*/
- divider: PropTypes.node,
+ rowSpacing: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
+ PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired),
+ PropTypes.number,
+ PropTypes.object,
+ PropTypes.string,
+ ]),
/**
* @ignore
*/
- justifyContent: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
- PropTypes.oneOf([
- 'end',
- 'start',
- 'flex-end',
- 'flex-start',
- 'center',
- 'space-between',
- 'space-around',
- 'space-evenly',
- ]),
- PropTypes.arrayOf(
- PropTypes.oneOf([
- 'end',
- 'start',
- 'flex-end',
- 'flex-start',
- 'center',
- 'space-between',
- 'space-around',
- 'space-evenly',
- ]),
- ),
+ size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
+ PropTypes.arrayOf(PropTypes.number),
+ PropTypes.number,
PropTypes.object,
]),
/**
@@ -204,8 +214,12 @@ process.env.NODE_ENV !== 'production'
PropTypes.object,
PropTypes.string,
]),
+ /**
+ * @ignore
+ */
+ style: PropTypes.object,
+
})
- : void 0;
Grid.displayName = 'Grid';
diff --git a/packages/pigment-css-react/src/baseAtomics.js b/packages/pigment-css-react/src/baseAtomics.js
index 7a05e0ce..9a2bd815 100644
--- a/packages/pigment-css-react/src/baseAtomics.js
+++ b/packages/pigment-css-react/src/baseAtomics.js
@@ -53,51 +53,31 @@ export const gridAtomics = generateAtomics(({ theme }) => ({
}, {}),
defaultCondition: theme.breakpoints?.keys?.[0] ?? 'xs',
properties: {
- display: ['flex', 'inline-flex'],
flexDirection: ['column', 'column-reverse', 'row', 'row-reverse'],
- flexWrap: ['wrap', 'nowrap', 'wrap-reverse'],
- justifyContent: [
- 'end',
- 'start',
- 'flex-end',
- 'flex-start',
- 'center',
- 'space-between',
- 'space-around',
- 'space-evenly',
- ],
- alignItems: [
- 'center',
- 'end',
- 'flex-end',
- 'flex-start',
- 'self-end',
- 'self-start',
- 'start',
- 'baseline',
- 'normal',
- 'stretch',
- ],
- '--Column-width': ['--Column-width'],
- '--Column-max-width': ['--Column-max-width'],
- '--Column-flex': ['--Column-flex'],
- '--Column-count': ['--Column-count'],
- '--Column-span': ['--Column-span'],
- '--Column-gap': ['--Column-gap'],
- '--Row-gap': ['--Row-gap'],
- '--Item-offset': ['--Item-offset'],
- '--Item-margin-left': ['--Item-margin-left'],
+ '--Grid-parent-column-count': ['--Grid-parent-column-count'],
+ '--Grid-parent-column-spacing': ['--Grid-parent-column-spacing'],
+ '--Grid-parent-row-spacing': ['--Grid-parent-row-spacing'],
+ '--Grid-self-column-span': ['--Grid-self-column-span'],
+ '--Grid-self-width': ['--Grid-self-width'],
+ '--Grid-self-max-width': ['--Grid-self-max-width'],
+ '--Grid-self-flex': ['--Grid-self-flex'],
+ '--Grid-self-column-spacing': ['--Grid-self-column-spacing'],
+ '--Grid-self-row-spacing': ['--Grid-self-row-spacing'],
+ '--Grid-self-offset': ['--Grid-self-offset'],
+ '--Grid-self-margin-left': ['--Grid-self-margin-left'],
},
shorthands: {
direction: ['flexDirection'],
},
- unitless: ['--Column-count', '--Column-span', '--Item-offset'],
+ unitless: ['--Grid-parent-column-count', '--Grid-self-column-span', '--Grid-self-offset'],
multipliers: {
- '--Column-gap': 8,
- '--Row-gap': 8,
+ '--Grid-parent-column-spacing': 8,
+ '--Grid-parent-row-spacing': 8,
+ '--Grid-self-column-spacing': 8,
+ '--Grid-self-row-spacing': 8,
},
inlineGetters: {
- '--Column-width': (value) => {
+ '--Grid-self-width': (value) => {
if (value === 'grow') {
return 'unset';
}
@@ -106,9 +86,9 @@ export const gridAtomics = generateAtomics(({ theme }) => ({
return 'auto';
}
- return 'calc(100% * var(--Column-span) / var(--Column-count) - (var(--Column-count) - var(--Column-span)) * var(--Column-gap) / var(--Column-count))';
+ return 'calc(100% * var(--Grid-self-column-span) / var(--Grid-parent-column-count) - (var(--Grid-parent-column-count) - var(--Grid-self-column-span)) * var(--Grid-parent-column-spacing) / var(--Grid-parent-column-count))';
},
- '--Column-max-width': (value) => {
+ '--Grid-self-max-width': (value) => {
if (value === 'grow') {
return '100%';
}
@@ -119,7 +99,7 @@ export const gridAtomics = generateAtomics(({ theme }) => ({
return 'unset';
},
- '--Column-flex': (value) => {
+ '--Grid-self-flex': (value) => {
if (value === 'grow') {
return '1 1 0';
}
@@ -130,12 +110,12 @@ export const gridAtomics = generateAtomics(({ theme }) => ({
return '0 1 auto';
},
- '--Item-margin-left': (value) => {
+ '--Grid-self-margin-left': (value) => {
if (value === 'auto') {
return 'auto';
}
- return 'calc(100% * var(--Item-offset) / var(--Column-count) + var(--Column-gap) * var(--Item-offset) / var(--Column-count))';
+ return 'calc(100% * var(--Grid-self-offset) / var(--Grid-parent-column-count) + var(--Grid-parent-column-spacing) * var(--Grid-self-offset) / var(--Grid-parent-column-count))';
},
},
}));
diff --git a/packages/pigment-css-react/src/generateAtomics.js b/packages/pigment-css-react/src/generateAtomics.js
index 765fd71b..6c59fd29 100644
--- a/packages/pigment-css-react/src/generateAtomics.js
+++ b/packages/pigment-css-react/src/generateAtomics.js
@@ -89,12 +89,7 @@ export function atomics({
);
return;
}
- handlePrimitive(
- propertyClasses[condition],
- multipliers[cssProperty],
- inlineGetters[cssProperty],
- condition,
- );
+ classes.push(propertyClasses[condition]);
});
}
}