Skip to content

Commit

Permalink
feat(comp:space): add justify prop (#746)
Browse files Browse the repository at this point in the history
  • Loading branch information
danranVm committed Feb 9, 2022
1 parent 9340796 commit af525d9
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 163 deletions.
6 changes: 3 additions & 3 deletions packages/components/grid/docs/Index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ order: 0

| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 |
| --- | --- | --- | --- | --- | --- |
| `align` | `flex` 布局下的垂直对齐方式 | `top \| middle \| bottom` | - | - | - |
| `justify` | flex 布局下的水平排列方式 | `start \| end \| center \| space-around \| space-between` | - | - | - |
| `gutter` | 栅格间隔, 支持配置数字, 对象和数组 | `number \| object \| array` | `0` | - | 对象结构形如 `{ xs: 8, sm: 16 }`, 数组结构同时设置 `[水平间距, 垂直间距]` 形如 `[8, 8]``[{ xs: 8 }, { xs: 8}]` |
| `align` | 垂直对齐方式 | `'start' \| 'center' \| 'end' \| 'baseline' \| 'stretch'` | - | - | - |
| `justify` | 水平对齐方式 | `'start' \| 'center' \| 'end' \| 'space-around' \| 'space-between'` | - | - | - |
| `gutter` | 栅格间隔, 支持配置数字, 对象和数组 | `number \| object \| array` | `0` | - | 对象结构形如 `{ xs: 8, sm: 16 }`, 数组结构同时设置 `[垂直间距, 水平间距]` 形如 `[8, 8]``[{ xs: 8 }, { xs: 8}]` |
| `wrap` | 是否自动换行 | `boolean` | `true` || - |

### IxCol
Expand Down
1 change: 0 additions & 1 deletion packages/components/grid/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export type {
ColInstance,
ColComponent,
ColPublicProps as ColProps,
RowGutter,
RowAlign,
RowJustify,
} from './src/types'
73 changes: 33 additions & 40 deletions packages/components/grid/src/Col.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,72 +5,65 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { ColBreakpointConfig, ColProps } from './types'
import type { CSSProperties, ComputedRef } from 'vue'

import { computed, defineComponent, inject } from 'vue'
import { type CSSProperties, computed, defineComponent, inject, normalizeClass } from 'vue'

import { isNumber, isString, isUndefined } from 'lodash-es'

import { BREAKPOINTS_KEYS } from '@idux/cdk/breakpoint'
import { isNumeric } from '@idux/cdk/utils'
import { useGlobalConfig } from '@idux/components/config'

import { rowToken } from './token'
import { colProps } from './types'
import { type ColBreakpointConfig, type ColProps, colProps } from './types'

export default defineComponent({
name: 'IxCol',
props: colProps,
setup(props, { slots }) {
const { gutter } = inject(rowToken)!
const common = useGlobalConfig('common')
const mergedPrefixCls = computed(() => `${common.prefixCls}-col`)
const { mergedGutters } = inject(rowToken)!

const classes = computed(() => generateAllCls(props, mergedPrefixCls.value))
const style = computed(() => {
const style: CSSProperties = {}

const [verticalGutter, horizontalGutter] = mergedGutters.value

if (verticalGutter > 0) {
style.paddingTop = `${verticalGutter / 2}px`
style.paddingBottom = style.paddingTop
}

if (horizontalGutter > 0) {
style.paddingLeft = `${horizontalGutter / 2}px`
style.paddingRight = style.paddingLeft
}

const classes = useClasses(props)
const style = useStyle(props, gutter)
if (props.flex) {
style.flex = parseFlex(props.flex)
}

return style
})

return () => (
<div class={classes.value} style={style.value}>
{slots.default?.()}
{slots.default && slots.default()}
</div>
)
},
})

function useClasses(props: ColProps) {
return computed(() => generateAllCls(props))
}

function useStyle(props: ColProps, gutter: ComputedRef<[number, number]>) {
return computed(() => {
const style: CSSProperties = {}

const [horizontalGutter, verticalGutter] = gutter.value
if (horizontalGutter > 0) {
style.paddingLeft = `${horizontalGutter / 2}px`
style.paddingRight = style.paddingLeft
}
if (verticalGutter > 0) {
style.paddingTop = `${verticalGutter / 2}px`
style.paddingBottom = style.paddingTop
}

if (props.flex) {
style.flex = parseFlex(props.flex)
}

return style
})
}

const attrKeys = ['span', 'order', 'offset', 'push', 'pull'] as const

function generateAllCls(props: ColProps) {
const clsPrefix = 'ix-col'
const clsMap = new Map<string, boolean>([[clsPrefix, true]])
function generateAllCls(props: ColProps, prefixCLs: string) {
const clsMap = new Map<string, boolean>([[prefixCLs, true]])

const generateSizeCls = (sizeConfig: ColBreakpointConfig, size?: string) => {
attrKeys.forEach(attrKey => {
const attr = sizeConfig[attrKey]
const cls = `${clsPrefix}${size ? `-${size}` : ''}-${attrKey}-${attr}`
const cls = `${prefixCLs}${size ? `-${size}` : ''}-${attrKey}-${attr}`
clsMap.set(cls, !isUndefined(attr))
})
}
Expand All @@ -89,7 +82,7 @@ function generateAllCls(props: ColProps) {
allCls[key] = value
})

return allCls
return normalizeClass(allCls)
}

function normalizeSizeProps(rawProps: number | string | ColBreakpointConfig) {
Expand Down
115 changes: 52 additions & 63 deletions packages/components/grid/src/Row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,93 +5,82 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { RowGutter, RowProps } from './types'
import type { BreakpointKey } from '@idux/cdk/breakpoint'
import type { RowConfig } from '@idux/components/config'
import type { CSSProperties, ComputedRef } from 'vue'
import { type CSSProperties, computed, defineComponent, normalizeClass, provide } from 'vue'

import { computed, defineComponent, provide } from 'vue'

import { isArray, isObject, isUndefined } from 'lodash-es'
import { isArray, isObject } from 'lodash-es'

import { BREAKPOINTS_KEYS, useSharedBreakpoints } from '@idux/cdk/breakpoint'
import { convertNumber } from '@idux/cdk/utils'
import { useGlobalConfig } from '@idux/components/config'

import { rowToken } from './token'
import { rowProps } from './types'
import { type RowProps, rowProps } from './types'

export default defineComponent({
name: 'IxRow',
props: rowProps,
setup(props, { slots }) {
const common = useGlobalConfig('common')
const mergedPrefixCls = computed(() => `${common.prefixCls}-row`)
const config = useGlobalConfig('row')
const classes = useClasses(props, config)

const gutter = useGutter(props)
const style = useStyle(gutter)
const mergedGutters = useGutters(props)
provide(rowToken, { mergedGutters })

const classes = computed(() => {
const { align, justify, wrap = config.wrap } = props
const prefixCls = mergedPrefixCls.value
return normalizeClass({
[prefixCls]: true,
[`${prefixCls}-align-${align}`]: align,
[`${prefixCls}-justify-${justify}`]: justify,
[`${prefixCls}-nowrap`]: !wrap,
})
})

const style = computed(() => {
const [verticalGutter, horizontalGutter] = mergedGutters.value
const style: CSSProperties = {}

provide(rowToken, { gutter })
if (verticalGutter > 0) {
style.marginTop = `${verticalGutter / -2}px`
style.marginBottom = style.marginTop
}
if (horizontalGutter > 0) {
style.marginLeft = `${horizontalGutter / -2}px`
style.marginRight = style.marginLeft
}
return style
})

return () => (
<div class={classes.value} style={style.value}>
{slots.default?.()}
{slots.default && slots.default()}
</div>
)
},
})

function useClasses(props: RowProps, config: RowConfig) {
return computed(() => {
const row = 'ix-row'
return {
[row]: true,
[`${row}-no-wrap`]: !(props.wrap ?? config.wrap),
[`${row}-${props.justify}`]: props.justify,
[`${row}-${props.align}`]: props.align,
}
})
}

function useGutter(props: RowProps) {
function useGutters(props: RowProps) {
const breakpoints = useSharedBreakpoints()
return computed(() => normalizeGutter(props.gutter, breakpoints))
}

function useStyle(gutter: ComputedRef<[number, number]>) {
return computed(() => {
const style: CSSProperties = {}
const [horizontalGutter, verticalGutter] = gutter.value
if (horizontalGutter > 0) {
style.marginLeft = `${horizontalGutter / -2}px`
style.marginRight = style.marginLeft
}
if (verticalGutter > 0) {
style.marginTop = `${verticalGutter / -2}px`
style.marginBottom = style.marginTop
}

return style
})
}

// gutter: RowGutter => [0, 0]
function normalizeGutter(propGutter: RowGutter, breakpoints: Record<BreakpointKey, boolean>) {
const results: [number, number] = [0, 0]

const normalizedGutters = isArray(propGutter) ? propGutter : [propGutter, 0]
normalizedGutters.forEach((gutter, index) => {
if (isObject(gutter)) {
BREAKPOINTS_KEYS.some(key => {
if (!isUndefined(gutter[key]) && breakpoints[key]) {
results[index] = gutter[key]
return true
}
return false
})
} else {
results[index] = convertNumber(gutter)
}
const { gutter } = props
const results: [number, number] = [0, 0]
const gutters = isArray(gutter) ? gutter : [gutter, gutter]
gutters.forEach((item, index) => {
if (isObject(item)) {
BREAKPOINTS_KEYS.some(key => {
const currGutter = item[key]
const isActive = currGutter != null && breakpoints[key]
if (isActive) {
results[index] = convertNumber(currGutter)
}
return isActive
})
} else {
results[index] = convertNumber(item)
}
})
return results
})
return results
}
2 changes: 1 addition & 1 deletion packages/components/grid/src/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import type { ComputedRef, InjectionKey } from 'vue'

export interface RowContext {
gutter: ComputedRef<[number, number]>
mergedGutters: ComputedRef<[number, number]>
}

export const rowToken: InjectionKey<RowContext> = Symbol('rowToken')
33 changes: 10 additions & 23 deletions packages/components/grid/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,22 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { BreakpointKey } from '@idux/cdk/breakpoint'
import type { IxInnerPropTypes, IxPublicPropTypes } from '@idux/cdk/utils'
import type { DefineComponent, HTMLAttributes } from 'vue'
import { type DefineComponent, type HTMLAttributes } from 'vue'

import { IxPropTypes } from '@idux/cdk/utils'
import { type BreakpointKey } from '@idux/cdk/breakpoint'
import { type IxInnerPropTypes, IxPropTypes, type IxPublicPropTypes } from '@idux/cdk/utils'

export type RowAlign = 'top' | 'middle' | 'bottom'
export type RowJustify = 'start' | 'end' | 'center' | 'space-around' | 'space-between'
export type RowGutterRecord = Record<BreakpointKey, number>
export type RowGutter = number | string | Array<number> | RowGutterRecord | [RowGutterRecord, RowGutterRecord]
export type RowAlign = 'start' | 'center' | 'end' | 'baseline' | 'stretch'
export type RowJustify = 'start' | 'center' | 'end' | 'space-around' | 'space-between'

export const rowProps = {
align: IxPropTypes.oneOf<RowAlign>(['top', 'middle', 'bottom']),
align: IxPropTypes.oneOf<RowAlign>(['start', 'center', 'end', 'baseline', 'stretch']),
justify: IxPropTypes.oneOf<RowJustify>(['start', 'end', 'center', 'space-around', 'space-between']),
gutter: IxPropTypes.oneOfType<RowGutter>([
gutter: IxPropTypes.oneOfType([
Number,
String,
IxPropTypes.array<number>(),
IxPropTypes.object<RowGutterRecord>(),
IxPropTypes.array<number | string>(),
IxPropTypes.object<Partial<Record<BreakpointKey, number | string>>>(),
]).def(0),
wrap: IxPropTypes.bool,
}
Expand All @@ -43,17 +40,7 @@ export interface ColBreakpointConfig {

const singleProp = IxPropTypes.oneOfType([Number, String])

const breakpointConfig = IxPropTypes.oneOfType([
Number,
String,
IxPropTypes.shape<ColBreakpointConfig>({
span: Number,
offset: Number,
order: Number,
push: Number,
pull: Number,
}).loose,
])
const breakpointConfig = IxPropTypes.oneOfType([Number, String, IxPropTypes.object<ColBreakpointConfig>()])

export const colProps = {
flex: singleProp,
Expand Down

0 comments on commit af525d9

Please sign in to comment.