|
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