UNPKG

element-plus

Version:

A Component Library for Vue3.0

136 lines (126 loc) 3.93 kB
import { defineComponent, renderSlot, createVNode, createTextVNode, isVNode, } from 'vue' import { PatchFlags, isFragment, isValidElementNode, } from '@element-plus/utils/vnode' import { isArray } from '@element-plus/utils/util' import Item from './item.vue' import { useSpace, defaultProps } from './useSpace' import type { VNode, ExtractPropTypes, Slots } from 'vue' export default defineComponent({ name: 'ElSpace', props: defaultProps, setup(props) { return useSpace(props) }, render( ctx: ReturnType<typeof useSpace> & ExtractPropTypes<typeof defaultProps> & { $slots: Slots; }, ) { const { classes, $slots, containerStyle, itemStyle, spacer, prefixCls, } = ctx const children = renderSlot($slots, 'default', { key: 0 }, () => []) // retrieve the children out via a simple for loop // the edge case here is that when users uses directives like <v-for>, <v-if> // we need to go one layer deeper if (children.children.length === 0) return null // loop the children, if current children is rendered via `renderList` or `<v-for>` if (isArray(children.children)) { let extractedChildren = [] children.children.forEach((child: VNode, loopKey) => { if (isFragment(child)) { if (isArray(child.children)) { child.children.forEach((nested, key) => { extractedChildren.push( createVNode( Item, { style: itemStyle, prefixCls, key: `nested-${key}`, }, { default: () => [nested as VNode], }, PatchFlags.PROPS | PatchFlags.STYLE, ['style', 'prefixCls'], ), ) }) } // if the current child is valid vnode, then append this current vnode // to item as child node. } else if (isValidElementNode(child)) { extractedChildren.push( createVNode( Item, { style: itemStyle, prefixCls, key: `LoopKey${loopKey}`, }, { default: () => [child as VNode], }, PatchFlags.PROPS | PatchFlags.STYLE, ['style', 'prefixCls'], ), ) } }) if (spacer) { // track the current rendering index, when encounters the last element // then no need to add a spacer after it. const len = extractedChildren.length - 1 extractedChildren = extractedChildren.reduce((acc, child, idx) => { return idx === len ? [...acc, child] : [...acc, child, createVNode( 'span', // adding width 100% for vertical alignment, // when the spacer inherit the width from the // parent, this span's width was not set, so space // might disappear { style: [itemStyle, 'width: 100%'], key: idx }, [ // if spacer is already a valid vnode, then append it to the current // span element. // otherwise, treat it as string. isVNode(spacer) ? spacer : createTextVNode(spacer as string, PatchFlags.TEXT), ], PatchFlags.STYLE, ), ] }, []) } // spacer container. return createVNode( 'div', { class: classes, style: containerStyle, }, extractedChildren, PatchFlags.STYLE | PatchFlags.CLASS, ) } return children.children }, })