102 lines
3.0 KiB
TypeScript
102 lines
3.0 KiB
TypeScript
import { ReactNode } from 'react';
|
|
import { getResponsiveClasses, defaultLayoutConfig, type LayoutConfig } from '~/lib/layout-utils';
|
|
|
|
interface FlexProps {
|
|
children: ReactNode;
|
|
className?: string;
|
|
config?: Partial<LayoutConfig>;
|
|
direction?: 'row' | 'col' | 'row-reverse' | 'col-reverse';
|
|
align?: 'start' | 'center' | 'end' | 'stretch' | 'baseline';
|
|
justify?: 'start' | 'center' | 'end' | 'between' | 'around' | 'evenly';
|
|
wrap?: boolean;
|
|
gap?: 'sm' | 'md' | 'lg' | 'xl';
|
|
responsive?: {
|
|
sm?: Partial<Pick<FlexProps, 'direction' | 'align' | 'justify'>>;
|
|
md?: Partial<Pick<FlexProps, 'direction' | 'align' | 'justify'>>;
|
|
lg?: Partial<Pick<FlexProps, 'direction' | 'align' | 'justify'>>;
|
|
xl?: Partial<Pick<FlexProps, 'direction' | 'align' | 'justify'>>;
|
|
};
|
|
}
|
|
|
|
export function Flex({
|
|
children,
|
|
className = '',
|
|
config = {},
|
|
direction = 'row',
|
|
align = 'start',
|
|
justify = 'start',
|
|
wrap = false,
|
|
gap = 'md',
|
|
responsive = {}
|
|
}: FlexProps) {
|
|
const layoutConfig = { ...defaultLayoutConfig, ...config };
|
|
const classes = getResponsiveClasses(layoutConfig);
|
|
|
|
const directionClasses = {
|
|
row: layoutConfig.direction === 'rtl' ? 'flex-row-reverse' : 'flex-row',
|
|
col: 'flex-col',
|
|
'row-reverse': layoutConfig.direction === 'rtl' ? 'flex-row' : 'flex-row-reverse',
|
|
'col-reverse': 'flex-col-reverse',
|
|
};
|
|
|
|
const alignClasses = {
|
|
start: 'items-start',
|
|
center: 'items-center',
|
|
end: 'items-end',
|
|
stretch: 'items-stretch',
|
|
baseline: 'items-baseline',
|
|
};
|
|
|
|
const justifyClasses = {
|
|
start: 'justify-start',
|
|
center: 'justify-center',
|
|
end: 'justify-end',
|
|
between: 'justify-between',
|
|
around: 'justify-around',
|
|
evenly: 'justify-evenly',
|
|
};
|
|
|
|
const gapClasses = {
|
|
sm: 'gap-2',
|
|
md: 'gap-4',
|
|
lg: 'gap-6',
|
|
xl: 'gap-8',
|
|
};
|
|
|
|
const wrapClass = wrap ? 'flex-wrap' : '';
|
|
|
|
// Build responsive classes
|
|
const responsiveClasses = Object.entries(responsive)
|
|
.map(([breakpoint, props]) => {
|
|
const responsiveClassList = [];
|
|
|
|
if (props.direction) {
|
|
const responsiveDirection = props.direction === 'row' && layoutConfig.direction === 'rtl'
|
|
? 'flex-row-reverse'
|
|
: props.direction === 'row-reverse' && layoutConfig.direction === 'rtl'
|
|
? 'flex-row'
|
|
: directionClasses[props.direction];
|
|
responsiveClassList.push(`${breakpoint}:${responsiveDirection}`);
|
|
}
|
|
|
|
if (props.align) {
|
|
responsiveClassList.push(`${breakpoint}:${alignClasses[props.align]}`);
|
|
}
|
|
|
|
if (props.justify) {
|
|
responsiveClassList.push(`${breakpoint}:${justifyClasses[props.justify]}`);
|
|
}
|
|
|
|
return responsiveClassList.join(' ');
|
|
})
|
|
.join(' ');
|
|
|
|
return (
|
|
<div
|
|
className={`flex ${directionClasses[direction]} ${alignClasses[align]} ${justifyClasses[justify]} ${gapClasses[gap]} ${wrapClass} ${responsiveClasses} ${className}`}
|
|
dir={layoutConfig.direction}
|
|
>
|
|
{children}
|
|
</div>
|
|
);
|
|
} |