-
Notifications
You must be signed in to change notification settings - Fork 2
/
ExpandableList.tsx
108 lines (95 loc) · 3.28 KB
/
ExpandableList.tsx
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
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Expandable
*/
import classnames from "classnames";
import * as React from "react";
import type { CommonProps } from "../utils/Props";
/** Properties for [[ExpandableList]] component
* @public
* @deprecated in 4.12.x. Props of deprecated component {@link ExpandableList}.
*/
export interface ExpandableListProps extends CommonProps {
/** Index of the default active block */
defaultActiveBlock?: number;
/** Indicates whether to allow only one expanded block */
singleExpandOnly?: boolean;
/** Indicates whether the single expanded block is collapsible */
singleIsCollapsible?: boolean;
/** Content */
children?: React.ReactNode;
}
interface ExpandableListState {
activeBlock: number;
}
/** ExpandableList React component is a container for ExpandableBlock components.
* @public
* @deprecated in 4.12.x. Use a custom container and manage {@link https://itwinui.bentley.com/docs/expandableblock expandable block} state manually.
*/
export class ExpandableList extends React.PureComponent<
// eslint-disable-next-line deprecation/deprecation
ExpandableListProps,
ExpandableListState
> {
// eslint-disable-next-line deprecation/deprecation
constructor(props: ExpandableListProps) {
super(props);
this.state = { activeBlock: this.props.defaultActiveBlock! };
}
// eslint-disable-next-line deprecation/deprecation
public static defaultProps: Partial<ExpandableListProps> = {
singleExpandOnly: false,
defaultActiveBlock: 0,
};
// set active block
private _handleBlockToggle = (
index: number,
onToggle: (isExpanding: boolean) => any
) => {
let activeBlock = index;
if (this.props.singleIsCollapsible && index === this.state.activeBlock)
activeBlock = -1;
this.setState({ activeBlock });
// istanbul ignore else
if (onToggle) {
onToggle(activeBlock === index); // fire the ExpandableBlock onToggle
}
};
private renderBlocks() {
return React.Children.map(this.props.children, (child: any, i) => {
return React.cloneElement(child, {
key: i,
isExpanded: this.props.singleExpandOnly
? i === this.state.activeBlock
: child.props.isExpanded,
onToggle: this._handleBlockToggle.bind(this, i, child.props.onToggle),
});
});
}
/** @internal */
// eslint-disable-next-line deprecation/deprecation
public override componentDidUpdate(prevProps: ExpandableListProps) {
if (
this.props.defaultActiveBlock !== prevProps.defaultActiveBlock &&
this.props.defaultActiveBlock !== this.state.activeBlock
) {
this.setState((_, props) => ({ activeBlock: props.defaultActiveBlock! }));
}
}
public override render(): React.ReactElement {
return (
<div
className={classnames(
"uicore-expandable-blocks-list",
this.props.className
)}
style={this.props.style}
>
{this.renderBlocks()}
</div>
);
}
}