import * as React from 'react'; import {CSSProperties} from 'react'; import {isArray} from 'lodash'; import componentLoader from '../../../util/componentLoader'; import {BasicConfig, BasicContainer, BasicContainerPropsInterface} from '../../Container/types'; import {createChild} from '../../../util/createChild'; export type gridPositionItems = 'top-left' | 'top-center' | 'top-right' | 'middle-left' | 'middle-center' | 'middle-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'; export class GridItem extends BasicConfig { gridCount?: number; gridPosition?: gridPositionItems; gridPaddingLeft?: number; gridPaddingRight?: number; gridLeft?: number; gridTop?: number; gridWidth?: number | string; gridHeight?: number | string; } type alignCenterItems = 'flex-start' | 'flex-end' | 'center' | 'baseline' | 'stretch' | 'initial' | 'inherit' | 'unset'; type justifyContentItems = 'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly' | 'initial' | 'inherit' | 'unset'; type CssCombo = { justifyContent: justifyContentItems; alignItems: alignCenterItems }; function getCssCombo(position?: gridPositionItems): CssCombo { switch (position) { case 'top-left': return { justifyContent: 'initial', alignItems: 'initial' }; case 'top-center': return { justifyContent: 'center', alignItems: 'initial' }; case 'top-right': return { justifyContent: 'flex-end', alignItems: 'initial' }; default: case 'middle-left': return { justifyContent: 'initial', alignItems: 'center' }; case 'middle-center': return { justifyContent: 'center', alignItems: 'center' }; case 'middle-right': return { justifyContent: 'flex-end', alignItems: 'center' }; case 'bottom-left': return { justifyContent: 'initial', alignItems: 'flex-end' }; case 'bottom-center': return { alignItems: 'flex-end', justifyContent: 'center' }; case 'bottom-right': return { alignItems: 'flex-end', justifyContent: 'flex-end' }; } } export type flexDirectionItems = 'row' | 'row-reverse' | 'column' | 'column-reverse'; export class RowConfig extends BasicConfig { /** * 每行最小高度 */ minHeight?: string; /** * 宽度 */ width?: number | string; /** * 高度 */ height?: number | string; /** * 测试使用, 显示网格 */ showBorder?: boolean; /** * CSS Class */ className?: string; /** * 内联CSS属性 */ style?: CSSProperties; /** * 排列顺序 */ flexDirection?: flexDirectionItems; /** * 子级元素 */ children: GridItem[]; } export class RowPropsInterface extends BasicContainerPropsInterface { info: RowConfig; } export default class Row extends BasicContainer { private static isRowDirection(flexDirection: flexDirectionItems = 'row') { return flexDirection === 'row' || flexDirection === 'row-reverse'; } constructor(props: RowPropsInterface) { super(props); } private getDefaultGridCount(children: GridItem[]) { let cookedGridCount = 0; let unCookedCount = 0; if (children.length === 0) { return 6; } children.forEach(child => { if (child.gridCount) { cookedGridCount += child.gridCount; } else if (!child.gridWidth) { unCookedCount++; } }); return (12 - cookedGridCount) / unCookedCount; } render() { let info = this.getPropsInfo(this.props.info); let children = info.children; let showBorder = info.showBorder || this.context.debug; if (!isArray(children)) { return
children props is required in Row Component
; } const defaultGridCount = this.getDefaultGridCount(children); let childElements = children.map((childInfo, index) => { childInfo = this.getPropsInfo(childInfo, this.props, [], false, [ 'gridWidth', 'gridHeight', 'gridCount', 'gridPosition', 'gridPaddingLeft', 'gridPaddingRight', 'gridTop', 'gridLeft', 'hidden', 'show' ]); let gridCount = childInfo.gridCount || defaultGridCount; let positionStyle = getCssCombo(childInfo.gridPosition); let gridStyles; let width = childInfo.gridWidth; if (width && childInfo.gridPaddingLeft && typeof width === 'number') { width -= childInfo.gridPaddingLeft; } if (width && childInfo.gridPaddingRight && typeof width === 'number') { width -= childInfo.gridPaddingRight; } if (Row.isRowDirection(info.flexDirection)) { gridStyles = { width: childInfo.gridWidth || `${100 / 12 * gridCount}%`, height: childInfo.gridHeight || 'auto', display: 'flex', border: showBorder ? `1px dashed blue` : '' }; } else { gridStyles = { width: childInfo.gridWidth || '100%', height: childInfo.gridHeight || `${100 / 12 * gridCount}%`, display: 'flex', border: showBorder ? `1px dashed blue` : '' }; } let innerGridStyle = { marginTop: `${childInfo.gridTop || 0}px`, marginLeft: `${childInfo.gridLeft || 0}px`, paddingLeft: childInfo.gridPaddingLeft, paddingRight: childInfo.gridPaddingRight, width: width || '100%', height: childInfo.gridHeight || '100%', display: 'flex', ...positionStyle }; let child = createChild(childInfo, { ...this.props, info: childInfo }, this.props.children); let childElement = (
{child}
); return this.renderChildren(childInfo, childElement); }); const rowStyles = { display: 'flex', width: info.width || '100%', height: info.height || '100%', minHeight: info.minHeight || '30px', flexDirection: info.flexDirection || 'row', border: showBorder ? '1px dashed #333' : '', ...info.style }; let rowElement = (
{childElements}
); return this.renderChildren(info, rowElement); } } componentLoader.addComponent('row', Row, RowPropsInterface);