ant-design-vue/components/list/Item.tsx

106 lines
3.4 KiB
Vue

import PropTypes from '../_util/vue-types';
import classNames from '../_util/classNames';
import { isStringElement, isEmptyElement, flattenChildren } from '../_util/props-util';
import { Col } from '../grid';
import { cloneElement } from '../_util/vnode';
import type { CSSProperties, ExtractPropTypes, PropType } from 'vue';
import { defineComponent, inject, ref } from 'vue';
import ItemMeta from './ItemMeta';
import useConfigInject from '../_util/hooks/useConfigInject';
import { ListContextKey } from './contextKey';
import type { ListGridType } from '.';
export const listItemProps = () => ({
prefixCls: String,
extra: PropTypes.any,
actions: PropTypes.array,
grid: Object as PropType<ListGridType>,
colStyle: { type: Object as PropType<CSSProperties>, default: undefined as CSSProperties },
});
export type ListItemProps = Partial<ExtractPropTypes<ReturnType<typeof listItemProps>>>;
export default defineComponent({
name: 'AListItem',
inheritAttrs: false,
Meta: ItemMeta,
props: listItemProps(),
slots: ['actions', 'extra'],
setup(props, { slots, attrs }) {
const { itemLayout, grid } = inject(ListContextKey, {
grid: ref(),
itemLayout: ref(),
});
const { prefixCls } = useConfigInject('list', props);
const isItemContainsTextNodeAndNotSingular = () => {
const children = slots.default?.() || [];
let result;
children.forEach(element => {
if (isStringElement(element) && !isEmptyElement(element)) {
result = true;
}
});
return result && children.length > 1;
};
const isFlexMode = () => {
const extra = props.extra ?? slots.extra?.();
if (itemLayout.value === 'vertical') {
return !!extra;
}
return !isItemContainsTextNodeAndNotSingular();
};
return () => {
const { class: className, ...restAttrs } = attrs;
const pre = prefixCls.value;
const extra = props.extra ?? slots.extra?.();
const children = slots.default?.();
let actions = props.actions ?? flattenChildren(slots.actions?.());
actions = actions && !Array.isArray(actions) ? [actions] : actions;
const actionsContent = actions && actions.length > 0 && (
<ul class={`${pre}-item-action`} key="actions">
{actions.map((action, i) => (
<li key={`${pre}-item-action-${i}`}>
{action}
{i !== actions.length - 1 && <em class={`${pre}-item-action-split`} />}
</li>
))}
</ul>
);
const Element = grid.value ? 'div' : 'li';
const itemChildren = (
<Element
{...(restAttrs as any)} // `li` element `onCopy` prop args is not same as `div`
class={classNames(
`${pre}-item`,
{
[`${pre}-item-no-flex`]: !isFlexMode(),
},
className,
)}
>
{itemLayout.value === 'vertical' && extra
? [
<div class={`${pre}-item-main`} key="content">
{children}
{actionsContent}
</div>,
<div class={`${pre}-item-extra`} key="extra">
{extra}
</div>,
]
: [children, actionsContent, cloneElement(extra, { key: 'extra' })]}
</Element>
);
return grid.value ? (
<Col flex={1} style={props.colStyle}>
{itemChildren}
</Col>
) : (
itemChildren
);
};
},
});