/
NonPrimitivePropertyRenderer.tsx
158 lines (142 loc) · 5.12 KB
/
NonPrimitivePropertyRenderer.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module Properties
*/
import "./NonPrimitivePropertyRenderer.scss";
import * as React from "react";
import { PropertyRecord, PropertyValueFormat } from "@itwin/appui-abstract";
import { CommonPropertyRenderer } from "./CommonPropertyRenderer";
import { NonPrimitivePropertyLabelRenderer } from "./label/NonPrimitivePropertyLabelRenderer";
import type { PrimitiveRendererProps } from "./PrimitivePropertyRenderer";
import { PropertyRenderer } from "./PropertyRenderer";
import { PropertyView } from "./PropertyView";
/** Properties of [[NonPrimitivePropertyRenderer]] React component
* @public
*/
export interface NonPrimitivePropertyRendererProps
extends PrimitiveRendererProps {
/** Can struct/array property be collapsed */
isCollapsible?: boolean;
}
/** State of [[NonPrimitivePropertyRenderer]] React component
* @internal
*/
interface NonPrimitivePropertyRendererState {
/** Is struct/array property expanded */
isExpanded?: boolean;
}
/** React Component that renders struct and array properties
* @public
*/
export class NonPrimitivePropertyRenderer extends React.Component<
NonPrimitivePropertyRendererProps,
NonPrimitivePropertyRendererState
> {
/** @internal */
public override readonly state: NonPrimitivePropertyRendererState = {
/** If it's not collapsible, that means it's expanded by default and can't be collapsed */
isExpanded:
!this.props.isCollapsible || this.props.propertyRecord.autoExpand,
};
constructor(props: NonPrimitivePropertyRendererProps) {
super(props);
}
private _onExpanded = () => {
this.setState({ isExpanded: true });
};
private _onCollapsed = () => {
this.setState({ isExpanded: false });
};
private getLabel(
props: NonPrimitivePropertyRendererProps,
state: NonPrimitivePropertyRendererState
): React.ReactNode {
const { orientation, indentation, width, columnRatio, columnInfo } = props;
// istanbul ignore next
const minLabelWidth = columnInfo?.minLabelWidth;
const offset = CommonPropertyRenderer.getLabelOffset(
indentation,
orientation,
width,
columnRatio,
minLabelWidth
);
let displayLabel = props.propertyRecord.property.displayLabel;
if (
this.props.propertyRecord.value.valueFormat === PropertyValueFormat.Array
)
displayLabel = `${displayLabel} (${this.props.propertyRecord.value.items.length})`;
return (
<NonPrimitivePropertyLabelRenderer
isExpanded={!!state.isExpanded}
onExpand={this._onExpanded}
onCollapse={this._onCollapsed}
offset={offset}
renderColon={false}
>
{displayLabel}
</NonPrimitivePropertyLabelRenderer>
);
}
private overrideArrayChildrenNames(items: PropertyRecord[]) {
const modifiedProperties: PropertyRecord[] = items.map(
(item, index): PropertyRecord => {
const newProperty = { ...item.property };
newProperty.displayLabel = `[${index + 1}]`;
newProperty.name = `${newProperty.name}_${index}`;
return new PropertyRecord(item.value, newProperty);
}
);
return modifiedProperties;
}
private _renderPropertyForItem = (item: PropertyRecord) => {
const prefix = this.props.uniqueKey
? this.props.uniqueKey
: this.props.propertyRecord.property.name;
const uniqueKey = `${prefix}_${item.property.name}`;
return (
<PropertyRenderer
key={uniqueKey}
uniqueKey={uniqueKey}
propertyRecord={item}
indentation={this.props.indentation ? this.props.indentation + 1 : 1}
orientation={this.props.orientation}
columnRatio={this.props.columnRatio}
actionButtonRenderers={this.props.actionButtonRenderers}
onColumnRatioChanged={this.props.onColumnRatioChanged}
width={this.props.width}
isResizeHandleHovered={this.props.isResizeHandleHovered}
onResizeHandleHoverChanged={this.props.onResizeHandleHoverChanged}
isResizeHandleBeingDragged={this.props.isResizeHandleBeingDragged}
onResizeHandleDragChanged={this.props.onResizeHandleDragChanged}
columnInfo={this.props.columnInfo}
/>
);
};
/** @internal */
public override render() {
let items: PropertyRecord[] =
this.props.propertyRecord.getChildrenRecords();
if (
this.props.propertyRecord.value.valueFormat === PropertyValueFormat.Array
)
items = this.overrideArrayChildrenNames(items);
const { indentation, ...props } = this.props;
return (
<>
{this.props.isCollapsible ? (
<PropertyView
labelElement={this.getLabel(this.props, this.state)}
{...props}
/>
) : undefined}
{this.state.isExpanded
? items.map(this._renderPropertyForItem)
: undefined}
</>
);
}
}