import { React, PropTypes, classnames } from '@gravityforms/libraries';
import { spacerClasses } from '@gravityforms/utils';
const { forwardRef } = React;
/**
* @module Grid
* @description A grid component in react.
*
* @since 1.1.18
*
* @param {object} props Component props.
* @param {string} props.alignItems The `align-items` CSS property, only applies if grid is container.
* @param {JSX.Element|null} props.children The React children to contain in the grid component.
* @param {number} props.columnSpacing The column spacing between grid items.
* @param {boolean} props.container Whether the grid component is a container or not.
* @param {object} props.customAttributes Custom attributes for the component.
* @param {string|Array|object} props.customClasses Custom classes for the component.
* @param {string} props.direction The `flex-direction` CSS property, only applies if grid is container.
* @param {string} props.elementType The element type, one of `list` or `div`.
* @param {boolean} props.item Whether the grid component is an item or not.
* @param {string} props.justifyContent The `justify-content` CSS property, only applies if grid is container.
* @param {number} props.rowSpacing The row spacing between grid items.
* @param {string|number|Array|object} props.spacing The spacing for the component, as a string, number, array, or object.
* @param {string} props.type The grid type, one of `fixed` or `fluid`, only applies if grid is container.
* @param {number} props.width The width of the grid item in a 12-column grid, from 1 to 12.
* @param {boolean} props.wrap Whether to wrap grid items or not, only applies if grid is container.
* @param {object|null} ref Ref to the component.
*
* @return {JSX.Element} The functional grid component in React.
*
* @example
* import Grid from '@gravityforms/components/react/admin/elements/Grid';
*
* return (
* <Grid container columnSpacing={ 4 } rowSpacing={ 4 }>
* <Grid item>
* { 'Grid item 1' }
* </Grid>
* <Grid item>
* { 'Grid item 2' }
* </Grid>
* <Grid item>
* { 'Grid item 3' }
* </Grid>
* </Grid>
* );
*
*/
const Grid = forwardRef( ( {
alignItems = 'center',
children = null,
columnSpacing = 0,
container,
customAttributes = {},
customClasses = [],
direction = 'row',
elementType = 'list',
item,
justifyContent = 'center',
rowSpacing = 0,
spacing = '',
type = 'fixed',
width = 0,
wrap,
}, ref ) => {
const attributes = {
className: classnames( {
'gform-grid': true,
[ `gform-grid--${ elementType }` ]: elementType,
[ `gform-grid--${ type }` ]: container,
'gform-grid--wrap': container && wrap,
'gform-grid--container': container,
'gform-grid--item': item,
[ `gform-grid--col-spacing-${ columnSpacing }` ]: container && columnSpacing && Number.isInteger( columnSpacing ),
[ `gform-grid--row-spacing-${ rowSpacing }` ]: container && rowSpacing && Number.isInteger( rowSpacing ),
...spacerClasses( spacing ),
}, customClasses ),
ref,
...customAttributes,
};
if ( container ) {
attributes.style = {
alignItems,
flexDirection: direction,
justifyContent,
};
} else {
const isFixed = 'fixed' === type;
if ( width && ! isFixed ) {
attributes.style.flexBasis = `${ width * 100 / 12 }%`;
}
}
const isList = 'list' === elementType;
let Component = 'div';
if ( container && isList ) {
Component = 'ul';
} else if ( item && isList ) {
Component = 'li';
}
return (
<Component { ...attributes }>
{ children }
</Component>
);
} );
Grid.propTypes = {
alignItems: PropTypes.string,
children: PropTypes.oneOfType( [
PropTypes.arrayOf( PropTypes.node ),
PropTypes.node,
] ),
columnSpacing: PropTypes.number,
container: PropTypes.bool,
customAttributes: PropTypes.object,
customClasses: PropTypes.oneOfType( [
PropTypes.string,
PropTypes.array,
PropTypes.object,
] ),
direction: PropTypes.string,
elementType: PropTypes.oneOf( [ 'list', 'div' ] ),
item: PropTypes.bool,
justifyContent: PropTypes.string,
rowSpacing: PropTypes.number,
spacing: PropTypes.oneOfType( [
PropTypes.string,
PropTypes.number,
PropTypes.array,
PropTypes.object,
] ),
type: PropTypes.oneOf( [ 'fixed', 'fluid' ] ),
width: PropTypes.number,
wrap: PropTypes.bool,
};
Grid.displayName = 'Grid';
export default Grid;