-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathcollapse-panel.tsx
More file actions
executable file
·108 lines (98 loc) · 3.21 KB
/
collapse-panel.tsx
File metadata and controls
executable file
·108 lines (98 loc) · 3.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import React, { useContext, useId, useRef } from 'react';
import classNames from 'classnames';
import { ConfigContext } from '../config-provider/config-context';
import { getPrefixCls } from '../_utils/general';
import { CollapsePanelProps } from './types';
import { ArrowDown } from '../_utils/components';
import CollapseTransition from '../collapse-transition';
import { CollapseContext } from './collapse-context';
/**
* Allow to parse active status to a node
* @param node
* @param isActive
*/
const richNode = (node: React.ReactNode | ((isActive: boolean) => React.ReactNode), isActive: boolean) => {
return typeof node === 'function' ? node(isActive) : node;
};
const CollapsePanel = (props: CollapsePanelProps): React.ReactElement => {
const {
showArrow = true,
itemKey,
header,
disabled,
extra,
deletable,
onHeaderOnClick,
className,
style,
children,
prefixCls: customisedCls,
} = props;
const itemRef = useRef<HTMLDivElement | null>(null);
const panelId = useId();
const headerId = useId();
const configContext = useContext(ConfigContext);
const { activeKeys, onItemClick } = useContext(CollapseContext);
const prefixCls = getPrefixCls('collapse-item', configContext.prefixCls, customisedCls);
const active = activeKeys.includes(itemKey);
const cls = classNames(prefixCls, className, {
[`${prefixCls}_active`]: active,
});
const headerOnClick = (e: React.MouseEvent) => {
if (!disabled) {
onHeaderOnClick && onHeaderOnClick(e);
onItemClick && onItemClick(itemKey);
}
};
/**
* Remove a item from collapse only the header is enabled
* @param e
* @private
*/
const removeItem = (e: React.MouseEvent<HTMLSpanElement>) => {
e.stopPropagation();
if (!disabled) {
const node = itemRef.current;
node && node.parentNode?.removeChild(node);
}
};
const renderHeader = () => {
const headerCls = classNames(`${prefixCls}__header`, {
[`${prefixCls}__header_disabled`]: disabled,
});
const arrowCls = classNames(`${prefixCls}__arrow`, {
[`${prefixCls}__arrow_active`]: active,
});
const hasExtra = deletable || extra;
return (
<div className={headerCls}>
<button
type="button"
id={headerId}
className={`${prefixCls}__toggle`}
onClick={headerOnClick}
aria-expanded={active}
aria-controls={panelId}
aria-disabled={disabled || undefined}>
{showArrow && <ArrowDown size={10} className={arrowCls} />}
<div className={`${prefixCls}__title`}>{richNode(header, active)}</div>
</button>
{hasExtra && (
<div className={`${prefixCls}__extra`}>
{deletable ? <span onClick={removeItem}>✕</span> : richNode(extra, active)}
</div>
)}
</div>
);
};
return (
<div className={cls} style={style} ref={itemRef}>
{renderHeader()}
<CollapseTransition isShow={active}>
<div className={`${prefixCls}__content`} id={panelId} role="region" aria-labelledby={headerId}>{richNode(children, active)}</div>
</CollapseTransition>
</div>
);
};
CollapsePanel.displayName = 'CollapsePanel';
export default CollapsePanel;