Skip to content

Commit 6707138

Browse files
committed
feat: support items & add deprecated warning
1 parent aac303a commit 6707138

5 files changed

Lines changed: 119 additions & 3 deletions

File tree

docs/demo/basic.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: Basic
3+
nav:
4+
title: Demo
5+
path: /demo
6+
---
7+
8+
<code src="../examples/basic.tsx"></code>

docs/examples/basic.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import type { CollapseProps } from 'rc-collapse';
2+
import Collapse from 'rc-collapse';
3+
import * as React from 'react';
4+
import '../../assets/index.less';
5+
6+
const App = () => {
7+
const items: CollapseProps['items'] = [
8+
{
9+
header: 'title',
10+
children: 'content',
11+
},
12+
{
13+
header: 'title 2',
14+
children: 'content 2',
15+
collapsible: 'disabled',
16+
},
17+
{
18+
header: 'title 3',
19+
children: 'content 3',
20+
onItemClick: console.log,
21+
},
22+
{
23+
header: 'title 4',
24+
children: 'content 4',
25+
expandIcon: () => <i>custom icon</i>,
26+
},
27+
];
28+
29+
return <Collapse items={items} />;
30+
};
31+
32+
export default App;

src/Collapse.tsx

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import classNames from 'classnames';
22
import toArray from 'rc-util/lib/Children/toArray';
33
import useMergedState from 'rc-util/lib/hooks/useMergedState';
4+
import warning from 'rc-util/lib/warning';
45
import React from 'react';
5-
import type { CollapsePanelProps, CollapseProps, CollapsibleType } from './interface';
6+
import type { CollapsePanelProps, CollapseProps, CollapsibleType, ItemType } from './interface';
67
import CollapsePanel from './Panel';
78

89
function getActiveKeysArray(activeKey: React.Key | React.Key[]) {
@@ -29,6 +30,7 @@ const Collapse = React.forwardRef<HTMLDivElement, CollapseProps>((props, ref) =>
2930
activeKey: rawActiveKey,
3031
defaultActiveKey,
3132
onChange,
33+
items,
3234
} = props;
3335

3436
const collapseClassName = classNames(prefixCls, className);
@@ -56,6 +58,11 @@ const Collapse = React.forwardRef<HTMLDivElement, CollapseProps>((props, ref) =>
5658
});
5759

5860
// ======================== Children ========================
61+
warning(
62+
!rawChildren,
63+
'`children` will be removed in next major version. Please use `items` instead.',
64+
);
65+
5966
const getNewChild = (child: React.ReactElement<CollapsePanelProps>, index: number) => {
6067
if (!child) return null;
6168

@@ -114,7 +121,54 @@ const Collapse = React.forwardRef<HTMLDivElement, CollapseProps>((props, ref) =>
114121
return React.cloneElement(child, childProps);
115122
};
116123

117-
const children = toArray(rawChildren).map(getNewChild);
124+
// eslint-disable-next-line @typescript-eslint/no-shadow
125+
const convertItemsToNodes = (items: ItemType[]) =>
126+
items.map((item, index) => {
127+
const {
128+
children,
129+
key: rawKey,
130+
collapsible: rawCollapsible,
131+
onItemClick: rawOnItemClick,
132+
destroyInactivePanel: rawDestroyInactivePanel,
133+
...restProps
134+
} = item;
135+
136+
const key = rawKey || String(index);
137+
const mergeCollapsible = rawCollapsible ?? collapsible;
138+
const mergeDestroyInactivePanel = rawDestroyInactivePanel ?? destroyInactivePanel;
139+
140+
const handleItemClick = (value: React.Key) => {
141+
if (mergeCollapsible === 'disabled') return;
142+
onClickItem(value);
143+
rawOnItemClick?.(value);
144+
};
145+
146+
let isActive = false;
147+
if (accordion) {
148+
isActive = activeKey[0] === key;
149+
} else {
150+
isActive = activeKey.indexOf(key) > -1;
151+
}
152+
153+
return (
154+
<CollapsePanel
155+
prefixCls={prefixCls}
156+
key={key}
157+
panelKey={key}
158+
isActive={isActive}
159+
collapsible={mergeCollapsible}
160+
onItemClick={handleItemClick}
161+
destroyInactivePanel={mergeDestroyInactivePanel}
162+
{...restProps}
163+
>
164+
{children}
165+
</CollapsePanel>
166+
);
167+
});
168+
169+
const children = Array.isArray(items)
170+
? convertItemsToNodes(items)
171+
: toArray(rawChildren).map(getNewChild);
118172

119173
// ======================== Render ========================
120174
return (
@@ -129,4 +183,9 @@ const Collapse = React.forwardRef<HTMLDivElement, CollapseProps>((props, ref) =>
129183
);
130184
});
131185

132-
export default Object.assign(Collapse, { Panel: CollapsePanel });
186+
export default Object.assign(Collapse, {
187+
/**
188+
* @deprecated use `items` instead, will be removed in `v4.0.0`
189+
*/
190+
Panel: CollapsePanel,
191+
});

src/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@ import Collapse from './Collapse';
33
export type { CollapsePanelProps, CollapseProps } from './interface';
44

55
export default Collapse;
6+
7+
/**
8+
* @deprecated use `items` instead, will be removed in `v4.0.0`
9+
*/
610
export const { Panel } = Collapse;

src/interface.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ import type * as React from 'react';
33

44
export type CollapsibleType = 'header' | 'icon' | 'disabled';
55

6+
export interface ItemType extends Omit<CollapsePanelProps, 'prefixCls' | 'panelKey' | 'isActive'> {
7+
ref?: React.RefObject<HTMLDivElement>;
8+
key?: React.Key;
9+
}
10+
611
export interface CollapseProps {
712
prefixCls?: string;
813
activeKey?: React.Key | React.Key[];
@@ -15,7 +20,15 @@ export interface CollapseProps {
1520
destroyInactivePanel?: boolean;
1621
expandIcon?: (props: object) => React.ReactNode;
1722
collapsible?: CollapsibleType;
23+
/**
24+
* @deprecated use `items` instead, will be removed in `v4.0.0`
25+
*/
1826
children?: React.ReactNode;
27+
/**
28+
* Collapse items content
29+
* @since 3.6.0
30+
*/
31+
items?: ItemType[];
1932
}
2033

2134
export interface CollapsePanelProps extends React.DOMAttributes<HTMLDivElement> {

0 commit comments

Comments
 (0)