|
1 | 1 | import PropTypes from '../_util/vue-types';
|
2 | 2 | import classNames from '../_util/classNames';
|
3 |
| -import { getComponent, isStringElement, isEmptyElement, getSlot } from '../_util/props-util'; |
| 3 | +import { isStringElement, isEmptyElement, flattenChildren } from '../_util/props-util'; |
4 | 4 | import { Col } from '../grid';
|
5 |
| -import { defaultConfigProvider } from '../config-provider'; |
6 | 5 | import { cloneElement } from '../_util/vnode';
|
7 |
| -import { defineComponent, ExtractPropTypes, FunctionalComponent, inject } from 'vue'; |
| 6 | +import { defineComponent, inject, ref } from 'vue'; |
| 7 | +import ItemMeta from './ItemMeta'; |
| 8 | +import useConfigInject from '../_util/hooks/useConfigInject'; |
| 9 | +import { ListContextKey } from '.'; |
8 | 10 |
|
9 | 11 | export const ListItemProps = {
|
10 | 12 | prefixCls: PropTypes.string,
|
11 | 13 | extra: PropTypes.any,
|
12 | 14 | actions: PropTypes.array,
|
13 | 15 | grid: PropTypes.any,
|
| 16 | + colStyle: PropTypes.style, |
14 | 17 | };
|
15 | 18 |
|
16 |
| -export const ListItemMetaProps = { |
17 |
| - avatar: PropTypes.any, |
18 |
| - description: PropTypes.any, |
19 |
| - prefixCls: PropTypes.string, |
20 |
| - title: PropTypes.any, |
21 |
| -}; |
22 |
| - |
23 |
| -export const ListItemMeta: FunctionalComponent<Partial< |
24 |
| - ExtractPropTypes<typeof ListItemMetaProps> |
25 |
| ->> = (props, { slots }) => { |
26 |
| - const configProvider = inject('configProvider', defaultConfigProvider); |
27 |
| - const { getPrefixCls } = configProvider; |
28 |
| - const { prefixCls: customizePrefixCls } = props; |
29 |
| - const prefixCls = getPrefixCls('list', customizePrefixCls); |
30 |
| - const avatar = props.avatar || slots.avatar?.(); |
31 |
| - const title = props.title || slots.title?.(); |
32 |
| - const description = props.description || slots.description?.(); |
33 |
| - const content = ( |
34 |
| - <div class={`${prefixCls}-item-meta-content`}> |
35 |
| - {title && <h4 class={`${prefixCls}-item-meta-title`}>{title}</h4>} |
36 |
| - {description && <div class={`${prefixCls}-item-meta-description`}>{description}</div>} |
37 |
| - </div> |
38 |
| - ); |
39 |
| - return ( |
40 |
| - <div class={`${prefixCls}-item-meta`}> |
41 |
| - {avatar && <div class={`${prefixCls}-item-meta-avatar`}>{avatar}</div>} |
42 |
| - {(title || description) && content} |
43 |
| - </div> |
44 |
| - ); |
45 |
| -}; |
46 |
| - |
47 |
| -Object.assign(ListItemMeta, { |
48 |
| - props: ListItemMetaProps, |
49 |
| - __ANT_LIST_ITEM_META: true, |
50 |
| - displayName: 'AListItemMeta', |
51 |
| -}); |
52 |
| - |
53 |
| -function getGrid(grid, t) { |
54 |
| - return grid[t] && Math.floor(24 / grid[t]); |
55 |
| -} |
56 |
| - |
57 |
| -export interface ListContext { |
58 |
| - grid?: any; |
59 |
| - itemLayout?: string; |
60 |
| -} |
61 |
| - |
62 | 19 | export default defineComponent({
|
63 | 20 | name: 'AListItem',
|
64 | 21 | inheritAttrs: false,
|
65 |
| - Meta: ListItemMeta, |
| 22 | + Meta: ItemMeta, |
66 | 23 | props: ListItemProps,
|
67 |
| - setup() { |
68 |
| - const listContext = inject<ListContext>('listContext', {}); |
69 |
| - const configProvider = inject('configProvider', defaultConfigProvider); |
70 |
| - return { |
71 |
| - listContext, |
72 |
| - configProvider, |
73 |
| - }; |
74 |
| - }, |
75 |
| - methods: { |
76 |
| - isItemContainsTextNodeAndNotSingular() { |
77 |
| - const children = getSlot(this) || []; |
| 24 | + slots: ['actions', 'extra'], |
| 25 | + setup(props, { slots, attrs }) { |
| 26 | + const { itemLayout, grid } = inject(ListContextKey, { |
| 27 | + grid: ref(), |
| 28 | + itemLayout: ref(), |
| 29 | + }); |
| 30 | + const { prefixCls } = useConfigInject('list', props); |
| 31 | + |
| 32 | + const isItemContainsTextNodeAndNotSingular = () => { |
| 33 | + const children = slots.default?.() || []; |
78 | 34 | let result;
|
79 | 35 | children.forEach(element => {
|
80 | 36 | if (isStringElement(element) && !isEmptyElement(element)) {
|
81 | 37 | result = true;
|
82 | 38 | }
|
83 | 39 | });
|
84 | 40 | return result && children.length > 1;
|
85 |
| - }, |
| 41 | + }; |
86 | 42 |
|
87 |
| - isFlexMode() { |
88 |
| - const extra = getComponent(this, 'extra'); |
89 |
| - const { itemLayout } = this.listContext; |
90 |
| - if (itemLayout === 'vertical') { |
| 43 | + const isFlexMode = () => { |
| 44 | + const extra = props.extra ?? slots.extra?.(); |
| 45 | + if (itemLayout.value === 'vertical') { |
91 | 46 | return !!extra;
|
92 | 47 | }
|
93 |
| - return !this.isItemContainsTextNodeAndNotSingular(); |
94 |
| - }, |
95 |
| - }, |
96 |
| - render() { |
97 |
| - const { grid, itemLayout } = this.listContext; |
98 |
| - const { prefixCls: customizePrefixCls, $attrs } = this; |
99 |
| - const { class: _className, ...restAttrs } = $attrs; |
100 |
| - const getPrefixCls = this.configProvider.getPrefixCls; |
101 |
| - const prefixCls = getPrefixCls('list', customizePrefixCls); |
102 |
| - const extra = getComponent(this, 'extra'); |
103 |
| - let actions = getComponent(this, 'actions'); |
104 |
| - actions = actions && !Array.isArray(actions) ? [actions] : actions; |
105 |
| - const actionsContent = actions && actions.length > 0 && ( |
106 |
| - <ul class={`${prefixCls}-item-action`} key="actions"> |
107 |
| - {actions.map((action, i) => ( |
108 |
| - <li key={`${prefixCls}-item-action-${i}`}> |
109 |
| - {action} |
110 |
| - {i !== actions.length - 1 && <em class={`${prefixCls}-item-action-split`} />} |
111 |
| - </li> |
112 |
| - ))} |
113 |
| - </ul> |
114 |
| - ); |
115 |
| - const children = getSlot(this); |
116 |
| - const Tag = grid ? 'div' : 'li'; |
117 |
| - const itemChildren = ( |
118 |
| - <Tag |
119 |
| - {...restAttrs} |
120 |
| - class={classNames(`${prefixCls}-item`, _className, { |
121 |
| - [`${prefixCls}-item-no-flex`]: !this.isFlexMode(), |
122 |
| - })} |
123 |
| - > |
124 |
| - {itemLayout === 'vertical' && extra |
125 |
| - ? [ |
126 |
| - <div class={`${prefixCls}-item-main`} key="content"> |
127 |
| - {children} |
128 |
| - {actionsContent} |
129 |
| - </div>, |
130 |
| - <div class={`${prefixCls}-item-extra`} key="extra"> |
131 |
| - {extra} |
132 |
| - </div>, |
133 |
| - ] |
134 |
| - : [children, actionsContent, cloneElement(extra, { key: 'extra' })]} |
135 |
| - </Tag> |
136 |
| - ); |
137 |
| - |
138 |
| - const mainContent = grid ? ( |
139 |
| - <Col |
140 |
| - span={getGrid(grid, 'column')} |
141 |
| - xs={getGrid(grid, 'xs')} |
142 |
| - sm={getGrid(grid, 'sm')} |
143 |
| - md={getGrid(grid, 'md')} |
144 |
| - lg={getGrid(grid, 'lg')} |
145 |
| - xl={getGrid(grid, 'xl')} |
146 |
| - xxl={getGrid(grid, 'xxl')} |
147 |
| - > |
148 |
| - {itemChildren} |
149 |
| - </Col> |
150 |
| - ) : ( |
151 |
| - itemChildren |
152 |
| - ); |
| 48 | + return !isItemContainsTextNodeAndNotSingular(); |
| 49 | + }; |
153 | 50 |
|
154 |
| - return mainContent; |
| 51 | + return () => { |
| 52 | + const { class: className, ...restAttrs } = attrs; |
| 53 | + const pre = prefixCls.value; |
| 54 | + const extra = props.extra ?? slots.extra?.(); |
| 55 | + const children = slots.default?.(); |
| 56 | + let actions = props.actions ?? flattenChildren(slots.actions?.()); |
| 57 | + actions = actions && !Array.isArray(actions) ? [actions] : actions; |
| 58 | + const actionsContent = actions && actions.length > 0 && ( |
| 59 | + <ul class={`${pre}-item-action`} key="actions"> |
| 60 | + {actions.map((action, i) => ( |
| 61 | + <li key={`${pre}-item-action-${i}`}> |
| 62 | + {action} |
| 63 | + {i !== actions.length - 1 && <em class={`${pre}-item-action-split`} />} |
| 64 | + </li> |
| 65 | + ))} |
| 66 | + </ul> |
| 67 | + ); |
| 68 | + const Element = grid.value ? 'div' : 'li'; |
| 69 | + const itemChildren = ( |
| 70 | + <Element |
| 71 | + {...(restAttrs as any)} // `li` element `onCopy` prop args is not same as `div` |
| 72 | + class={classNames( |
| 73 | + `${pre}-item`, |
| 74 | + { |
| 75 | + [`${pre}-item-no-flex`]: !isFlexMode(), |
| 76 | + }, |
| 77 | + className, |
| 78 | + )} |
| 79 | + > |
| 80 | + {itemLayout.value === 'vertical' && extra |
| 81 | + ? [ |
| 82 | + <div class={`${pre}-item-main`} key="content"> |
| 83 | + {children} |
| 84 | + {actionsContent} |
| 85 | + </div>, |
| 86 | + <div class={`${pre}-item-extra`} key="extra"> |
| 87 | + {extra} |
| 88 | + </div>, |
| 89 | + ] |
| 90 | + : [children, actionsContent, cloneElement(extra, { key: 'extra' })]} |
| 91 | + </Element> |
| 92 | + ); |
| 93 | + return grid.value ? ( |
| 94 | + <Col flex={1} style={props.colStyle}> |
| 95 | + {itemChildren} |
| 96 | + </Col> |
| 97 | + ) : ( |
| 98 | + itemChildren |
| 99 | + ); |
| 100 | + }; |
155 | 101 | },
|
156 | 102 | });
|
0 commit comments