import React, { forwardRef, HTMLAttributes } from 'react'
import PropTypes from 'prop-types'
import classNames from 'classnames'
export type BPObject = {
cols?: 'auto' | number | string | null
gutter?: number | string | null
gutterX?: number | string | null
gutterY?: number | string | null
}
export interface CRowProps extends HTMLAttributes {
/**
* A string of all className you want applied to the base component.
*/
className?: string
/**
* The number of columns/offset/order on extra small devices (<576px).
*
* @type {{ cols: 'auto' | number | string } | { gutter: number | string } | { gutterX: number | string } | { gutterY: number | string }}
*/
xs?: BPObject
/**
* The number of columns/offset/order on small devices (<768px).
*
* @type {{ cols: 'auto' | number | string } | { gutter: number | string } | { gutterX: number | string } | { gutterY: number | string }}
*/
sm?: BPObject
/**
* The number of columns/offset/order on medium devices (<992px).
*
* @type {{ cols: 'auto' | number | string } | { gutter: number | string } | { gutterX: number | string } | { gutterY: number | string }}
*/
md?: BPObject
/**
* The number of columns/offset/order on large devices (<1200px).
*
* @type {{ cols: 'auto' | number | string } | { gutter: number | string } | { gutterX: number | string } | { gutterY: number | string }}
*/
lg?: BPObject
/**
* The number of columns/offset/order on X-Large devices (<1400px).
*
* @type {{ cols: 'auto' | number | string } | { gutter: number | string } | { gutterX: number | string } | { gutterY: number | string }}
*/
xl?: BPObject
/**
* The number of columns/offset/order on XX-Large devices (≥1400px).
*
* @type {{ cols: 'auto' | number | string } | { gutter: number | string } | { gutterX: number | string } | { gutterY: number | string }}
*/
xxl?: BPObject
}
const BREAKPOINTS = [
'xxl' as const,
'xl' as const,
'lg' as const,
'md' as const,
'sm' as const,
'xs' as const,
]
export const CRow = forwardRef(
({ children, className, ...rest }, ref) => {
const repsonsiveClassNames: string[] = []
BREAKPOINTS.forEach((bp) => {
const breakpoint = rest[bp]
delete rest[bp]
const infix = bp === 'xs' ? '' : `-${bp}`
if (typeof breakpoint === 'object') {
if (breakpoint.cols) {
repsonsiveClassNames.push(`row-cols${infix}-${breakpoint.cols}`)
}
if (typeof breakpoint.gutter === 'number') {
repsonsiveClassNames.push(`g${infix}-${breakpoint.gutter}`)
}
if (typeof breakpoint.gutterX === 'number') {
repsonsiveClassNames.push(`gx${infix}-${breakpoint.gutterX}`)
}
if (typeof breakpoint.gutterY === 'number') {
repsonsiveClassNames.push(`gy${infix}-${breakpoint.gutterY}`)
}
}
})
return (
{children}
)
}
)
const bp = PropTypes.shape({
cols: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number, PropTypes.string]),
gutter: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
gutterX: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
gutterY: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
})
CRow.propTypes = {
children: PropTypes.node,
className: PropTypes.string,
xs: bp,
sm: bp,
md: bp,
lg: bp,
xl: bp,
xxl: bp,
}
CRow.displayName = 'CRow'