refactor: space
parent
a049a66ffe
commit
42916f50f5
|
@ -15,6 +15,7 @@ export default (
|
||||||
direction: ComputedRef<Direction>;
|
direction: ComputedRef<Direction>;
|
||||||
size: ComputedRef<SizeType>;
|
size: ComputedRef<SizeType>;
|
||||||
getTargetContainer: ComputedRef<() => HTMLElement>;
|
getTargetContainer: ComputedRef<() => HTMLElement>;
|
||||||
|
space: ComputedRef<{ size: SizeType | number }>;
|
||||||
} => {
|
} => {
|
||||||
const configProvider = inject<UnwrapRef<ConfigProviderProps>>(
|
const configProvider = inject<UnwrapRef<ConfigProviderProps>>(
|
||||||
'configProvider',
|
'configProvider',
|
||||||
|
@ -22,7 +23,8 @@ export default (
|
||||||
);
|
);
|
||||||
const prefixCls = computed(() => configProvider.getPrefixCls(name, props.prefixCls));
|
const prefixCls = computed(() => configProvider.getPrefixCls(name, props.prefixCls));
|
||||||
const direction = computed(() => configProvider.direction);
|
const direction = computed(() => configProvider.direction);
|
||||||
|
const space = computed(() => configProvider.space);
|
||||||
const size = computed(() => props.size || configProvider.componentSize);
|
const size = computed(() => props.size || configProvider.componentSize);
|
||||||
const getTargetContainer = computed(() => props.getTargetContainer);
|
const getTargetContainer = computed(() => props.getTargetContainer);
|
||||||
return { configProvider, prefixCls, direction, size, getTargetContainer };
|
return { configProvider, prefixCls, direction, size, getTargetContainer, space };
|
||||||
};
|
};
|
||||||
|
|
|
@ -95,7 +95,7 @@ export const configProviderProps = {
|
||||||
type: String as PropType<'ltr' | 'rtl'>,
|
type: String as PropType<'ltr' | 'rtl'>,
|
||||||
},
|
},
|
||||||
space: {
|
space: {
|
||||||
type: [String, Number] as PropType<SizeType | number>,
|
type: Object as PropType<{ size: SizeType | number }>,
|
||||||
},
|
},
|
||||||
virtual: PropTypes.looseBool,
|
virtual: PropTypes.looseBool,
|
||||||
dropdownMatchSelectWidth: PropTypes.looseBool,
|
dropdownMatchSelectWidth: PropTypes.looseBool,
|
||||||
|
|
|
@ -1,74 +1,131 @@
|
||||||
import { inject, defineComponent, PropType } from 'vue';
|
import {
|
||||||
|
defineComponent,
|
||||||
|
PropType,
|
||||||
|
ExtractPropTypes,
|
||||||
|
computed,
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
CSSProperties,
|
||||||
|
} from 'vue';
|
||||||
import PropTypes from '../_util/vue-types';
|
import PropTypes from '../_util/vue-types';
|
||||||
import { filterEmpty } from '../_util/props-util';
|
import { filterEmpty } from '../_util/props-util';
|
||||||
import { defaultConfigProvider, SizeType } from '../config-provider';
|
import { SizeType } from '../config-provider';
|
||||||
import { tuple, withInstall } from '../_util/type';
|
import { tuple, withInstall } from '../_util/type';
|
||||||
|
import useConfigInject from '../_util/hooks/useConfigInject';
|
||||||
|
import useFlexGapSupport from '../_util/hooks/useFlexGapSupport';
|
||||||
|
import classNames from '../_util/classNames';
|
||||||
|
|
||||||
|
export type SpaceSize = SizeType | number;
|
||||||
const spaceSize = {
|
const spaceSize = {
|
||||||
small: 8,
|
small: 8,
|
||||||
middle: 16,
|
middle: 16,
|
||||||
large: 24,
|
large: 24,
|
||||||
};
|
};
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
const Space = defineComponent({
|
const Space = defineComponent({
|
||||||
name: 'ASpace',
|
name: 'ASpace',
|
||||||
props: {
|
props: spaceProps,
|
||||||
prefixCls: PropTypes.string,
|
slots: ['split'],
|
||||||
size: {
|
|
||||||
type: [String, Number] as PropType<number | SizeType>,
|
|
||||||
},
|
|
||||||
direction: PropTypes.oneOf(tuple('horizontal', 'vertical')),
|
|
||||||
align: PropTypes.oneOf(tuple('start', 'end', 'center', 'baseline')),
|
|
||||||
},
|
|
||||||
setup(props, { slots }) {
|
setup(props, { slots }) {
|
||||||
const configProvider = inject('configProvider', defaultConfigProvider);
|
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,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
});
|
||||||
return () => {
|
return () => {
|
||||||
const {
|
const { wrap, direction = 'horizontal' } = props;
|
||||||
align,
|
|
||||||
size = 'small',
|
|
||||||
direction = 'horizontal',
|
|
||||||
prefixCls: customizePrefixCls,
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
const { getPrefixCls } = configProvider;
|
|
||||||
const prefixCls = getPrefixCls('space', customizePrefixCls);
|
|
||||||
const items = filterEmpty(slots.default?.());
|
const items = filterEmpty(slots.default?.());
|
||||||
const len = items.length;
|
const len = items.length;
|
||||||
|
|
||||||
if (len === 0) {
|
if (len === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
const split = slots.split?.();
|
||||||
const mergedAlign = align === undefined && direction === 'horizontal' ? 'center' : align;
|
const itemClassName = `${prefixCls.value}-item`;
|
||||||
|
const horizontalSizeVal = horizontalSize.value;
|
||||||
const someSpaceClass = {
|
const latestIndex = len - 1;
|
||||||
[prefixCls]: true,
|
|
||||||
[`${prefixCls}-${direction}`]: true,
|
|
||||||
[`${prefixCls}-align-${mergedAlign}`]: mergedAlign,
|
|
||||||
};
|
|
||||||
|
|
||||||
const itemClassName = `${prefixCls}-item`;
|
|
||||||
const marginDirection = 'marginRight'; // directionConfig === 'rtl' ? 'marginLeft' : 'marginRight';
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={someSpaceClass}>
|
<div class={cn.value} style={style.value}>
|
||||||
{items.map((child, i) => (
|
{items.map((child, index) => {
|
||||||
<div
|
let itemStyle: CSSProperties = {};
|
||||||
class={itemClassName}
|
if (!supportFlexGap) {
|
||||||
key={`${itemClassName}-${i}`}
|
if (direction === 'vertical') {
|
||||||
style={
|
if (index < latestIndex) {
|
||||||
i === len - 1
|
itemStyle = { marginBottom: `${horizontalSizeVal / (split ? 2 : 1)}px` };
|
||||||
? {}
|
}
|
||||||
: {
|
} else {
|
||||||
[direction === 'vertical' ? 'marginBottom' : marginDirection]:
|
itemStyle = {
|
||||||
typeof size === 'string' ? `${spaceSize[size]}px` : `${size}px`,
|
...(index < latestIndex && {
|
||||||
}
|
[marginDirection.value]: `${horizontalSizeVal / (split ? 2 : 1)}px`,
|
||||||
|
}),
|
||||||
|
...(wrap && { paddingBottom: `${verticalSize.value}px` }),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
>
|
}
|
||||||
{child}
|
|
||||||
</div>
|
return (
|
||||||
))}
|
<>
|
||||||
|
<div class={itemClassName} style={itemStyle}>
|
||||||
|
{child}
|
||||||
|
</div>
|
||||||
|
{index < latestIndex && split && (
|
||||||
|
<span class={`${itemClassName}-split`} style={itemStyle}>
|
||||||
|
{split}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
@import '../../style/mixins/index';
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
@space-prefix-cls: ~'@{ant-prefix}-space';
|
@space-prefix-cls: ~'@{ant-prefix}-space';
|
||||||
|
@space-item-prefix-cls: ~'@{ant-prefix}-space-item';
|
||||||
|
|
||||||
.@{space-prefix-cls} {
|
.@{space-prefix-cls} {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
@ -25,4 +26,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @import './rtl';
|
.@{space-item-prefix-cls} {
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@import './rtl';
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
@import '../../style/themes/index';
|
||||||
|
@import '../../style/mixins/index';
|
||||||
|
|
||||||
|
@space-prefix-cls: ~'@{ant-prefix}-space';
|
||||||
|
|
||||||
|
.@{space-prefix-cls} {
|
||||||
|
&-rtl {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue