ant-design-vue/components/space/index.tsx

136 lines
4.2 KiB
Vue
Raw Normal View History

2021-05-26 09:31:16 +00:00
import {
defineComponent,
PropType,
ExtractPropTypes,
computed,
ref,
watch,
CSSProperties,
} from 'vue';
2020-10-17 04:13:55 +00:00
import PropTypes from '../_util/vue-types';
2020-08-15 06:43:14 +00:00
import { filterEmpty } from '../_util/props-util';
2021-05-26 09:31:16 +00:00
import { SizeType } from '../config-provider';
2020-11-01 07:03:33 +00:00
import { tuple, withInstall } from '../_util/type';
2021-05-26 09:31:16 +00:00
import useConfigInject from '../_util/hooks/useConfigInject';
import useFlexGapSupport from '../_util/hooks/useFlexGapSupport';
import classNames from '../_util/classNames';
2020-08-12 10:22:21 +00:00
2021-05-26 09:31:16 +00:00
export type SpaceSize = SizeType | number;
2020-08-12 10:22:21 +00:00
const spaceSize = {
small: 8,
middle: 16,
large: 24,
};
2021-05-26 09:31:16 +00:00
const spaceProps = {
prefixCls: PropTypes.string,
size: {
type: [String, Number, Array] as PropType<SpaceSize | [SpaceSize, SpaceSize]>,
},
direction: PropTypes.oneOf(tuple('horizontal', 'vertical')).def('horizontal'),
align: PropTypes.oneOf(tuple('start', 'end', 'center', 'baseline')),
wrap: PropTypes.looseBool,
};
export type SpaceProps = Partial<ExtractPropTypes<typeof spaceProps>>;
function getNumberSize(size: SpaceSize) {
return typeof size === 'string' ? spaceSize[size] : size || 0;
}
2020-08-12 10:22:21 +00:00
2020-10-17 04:13:55 +00:00
const Space = defineComponent({
name: 'ASpace',
2021-05-26 09:31:16 +00:00
props: spaceProps,
slots: ['split'],
2020-10-17 04:13:55 +00:00
setup(props, { slots }) {
2021-05-26 09:31:16 +00:00
const { prefixCls, space, direction: directionConfig } = useConfigInject('space', props);
const supportFlexGap = useFlexGapSupport();
const size = computed(() => props.size || space.value?.size || 'small');
const horizontalSize = ref<number>();
const verticalSize = ref<number>();
watch(
size,
() => {
[horizontalSize.value, verticalSize.value] = ((Array.isArray(size.value)
? size.value
: [size.value, size.value]) as [SpaceSize, SpaceSize]).map(item => getNumberSize(item));
},
{ immediate: true },
);
const mergedAlign = computed(() =>
props.align === undefined && props.direction === 'horizontal' ? 'center' : props.align,
);
const cn = computed(() => {
return classNames(prefixCls.value, `${prefixCls.value}-${props.direction}`, {
[`${prefixCls.value}-rtl`]: directionConfig.value === 'rtl',
[`${prefixCls.value}-align-${mergedAlign.value}`]: mergedAlign.value,
});
});
2020-08-12 10:22:21 +00:00
2021-05-26 09:31:16 +00:00
const marginDirection = computed(() =>
directionConfig.value === 'rtl' ? 'marginLeft' : 'marginRight',
);
const style = computed(() => {
const gapStyle: CSSProperties = {};
if (supportFlexGap) {
gapStyle.columnGap = `${horizontalSize.value}px`;
gapStyle.rowGap = `${verticalSize.value}px`;
}
return {
...gapStyle,
...(props.wrap && { flexWrap: 'wrap', marginBottom: `${-verticalSize.value}px` }),
} as CSSProperties;
});
2020-10-17 04:13:55 +00:00
return () => {
2021-05-26 09:31:16 +00:00
const { wrap, direction = 'horizontal' } = props;
2020-10-18 13:49:37 +00:00
2020-10-17 04:13:55 +00:00
const items = filterEmpty(slots.default?.());
const len = items.length;
2020-08-12 10:22:21 +00:00
2020-10-17 04:13:55 +00:00
if (len === 0) {
return null;
}
2021-05-26 09:31:16 +00:00
const split = slots.split?.();
const itemClassName = `${prefixCls.value}-item`;
const horizontalSizeVal = horizontalSize.value;
const latestIndex = len - 1;
2020-10-17 04:13:55 +00:00
return (
2021-05-26 09:31:16 +00:00
<div class={cn.value} style={style.value}>
{items.map((child, index) => {
let itemStyle: CSSProperties = {};
if (!supportFlexGap) {
if (direction === 'vertical') {
if (index < latestIndex) {
itemStyle = { marginBottom: `${horizontalSizeVal / (split ? 2 : 1)}px` };
}
} else {
itemStyle = {
...(index < latestIndex && {
[marginDirection.value]: `${horizontalSizeVal / (split ? 2 : 1)}px`,
}),
...(wrap && { paddingBottom: `${verticalSize.value}px` }),
};
2020-10-17 04:13:55 +00:00
}
2021-05-26 09:31:16 +00:00
}
return (
<>
<div class={itemClassName} style={itemStyle}>
{child}
</div>
{index < latestIndex && split && (
<span class={`${itemClassName}-split`} style={itemStyle}>
{split}
</span>
)}
</>
);
})}
2020-08-12 14:08:06 +00:00
</div>
2020-10-17 04:13:55 +00:00
);
};
},
});
2020-08-12 10:22:21 +00:00
2020-11-01 07:03:33 +00:00
export default withInstall(Space);