@parca/profile 0.19.144 → 0.19.145
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/MatchersInput/SuggestionsList.d.ts.map +1 -1
- package/dist/MatchersInput/SuggestionsList.js +73 -63
- package/dist/MatchersInput/index.d.ts.map +1 -1
- package/dist/MatchersInput/index.js +4 -5
- package/dist/ProfileTypeSelector/index.d.ts.map +1 -1
- package/dist/ProfileTypeSelector/index.js +33 -52
- package/dist/ProfileView/components/ColorStackLegend.d.ts.map +1 -1
- package/dist/ProfileView/components/ColorStackLegend.js +70 -118
- package/dist/ProfileView/components/ProfileFilters/index.d.ts.map +1 -1
- package/dist/ProfileView/components/ProfileFilters/index.js +0 -1
- package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.d.ts.map +1 -1
- package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.js +319 -123
- package/dist/SelectWithRefresh/index.js +38 -33
- package/dist/SimpleMatchers/Select.d.ts.map +1 -1
- package/dist/SimpleMatchers/Select.js +63 -68
- package/dist/SourceView/Highlighter.d.ts.map +1 -1
- package/dist/SourceView/Highlighter.js +1 -1
- package/package.json +3 -3
- package/src/MatchersInput/SuggestionsList.tsx +71 -86
- package/src/MatchersInput/index.tsx +61 -74
- package/src/ProfileTypeSelector/index.tsx +4 -7
- package/src/ProfileView/components/ColorStackLegend.tsx +15 -23
- package/src/ProfileView/components/ProfileFilters/index.tsx +8 -13
- package/src/ProfileView/components/Toolbars/TableColumnsDropdown.tsx +113 -115
- package/src/SelectWithRefresh/index.tsx +28 -28
- package/src/SimpleMatchers/Select.tsx +29 -37
- package/src/SourceView/Highlighter.tsx +2 -2
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import React
|
|
14
|
+
import React from 'react';
|
|
15
15
|
|
|
16
16
|
import {Icon} from '@iconify/react';
|
|
17
17
|
import cx from 'classnames';
|
|
@@ -41,31 +41,23 @@ const ColorStackLegend = ({mappings, compareMode = false, loading}: Props): Reac
|
|
|
41
41
|
|
|
42
42
|
const {appliedFilters, removeExcludeBinary, excludeBinary} = useProfileFilters();
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
.filter(f => f.type === 'frame' && f.field === 'binary')
|
|
48
|
-
.map(f => f.value);
|
|
49
|
-
}, [appliedFilters]);
|
|
44
|
+
const currentBinaryFilters = (appliedFilters ?? [])
|
|
45
|
+
.filter(f => f.type === 'frame' && f.field === 'binary')
|
|
46
|
+
.map(f => f.value);
|
|
50
47
|
|
|
51
48
|
const mappingsList = useMappingList(mappings);
|
|
52
49
|
|
|
53
|
-
const mappingColors =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return -1;
|
|
65
|
-
}
|
|
66
|
-
return featureA?.localeCompare(featureB ?? '') ?? 0;
|
|
67
|
-
});
|
|
68
|
-
}, [mappingColors]);
|
|
50
|
+
const mappingColors = getMappingColors(mappingsList, isDarkMode, currentColorProfile);
|
|
51
|
+
|
|
52
|
+
const stackColorArray = Object.entries(mappingColors).sort(([featureA], [featureB]) => {
|
|
53
|
+
if (featureA === EVERYTHING_ELSE) {
|
|
54
|
+
return 1;
|
|
55
|
+
}
|
|
56
|
+
if (featureB === EVERYTHING_ELSE) {
|
|
57
|
+
return -1;
|
|
58
|
+
}
|
|
59
|
+
return featureA?.localeCompare(featureB ?? '') ?? 0;
|
|
60
|
+
});
|
|
69
61
|
|
|
70
62
|
if (stackColorArray.length === 0 && loading === false) {
|
|
71
63
|
return <></>;
|
|
@@ -11,8 +11,6 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {useCallback} from 'react';
|
|
15
|
-
|
|
16
14
|
import {Icon} from '@iconify/react';
|
|
17
15
|
import cx from 'classnames';
|
|
18
16
|
|
|
@@ -203,18 +201,15 @@ const ProfileFilters = ({readOnly = false}: ProfileFiltersProps = {}): JSX.Eleme
|
|
|
203
201
|
resetFilters,
|
|
204
202
|
} = useProfileFilters();
|
|
205
203
|
|
|
206
|
-
const handleKeyDown =
|
|
207
|
-
(e
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
onApplyFilters();
|
|
204
|
+
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>): void => {
|
|
205
|
+
if (e.key === 'Enter') {
|
|
206
|
+
e.preventDefault();
|
|
207
|
+
if (e.currentTarget.value.trim() === '') {
|
|
208
|
+
return;
|
|
214
209
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
210
|
+
onApplyFilters();
|
|
211
|
+
}
|
|
212
|
+
};
|
|
218
213
|
|
|
219
214
|
const filtersToRender = localFilters.length > 0 ? localFilters : appliedFilters ?? [];
|
|
220
215
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {useEffect,
|
|
14
|
+
import {useEffect, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import {createColumnHelper, type ColumnDef} from '@tanstack/table-core';
|
|
17
17
|
import {useQueryState} from 'nuqs';
|
|
@@ -37,121 +37,118 @@ const TableColumnsDropdown = ({profileType, total, filtered}: Props): JSX.Elemen
|
|
|
37
37
|
|
|
38
38
|
const columnHelper = createColumnHelper<Row>();
|
|
39
39
|
|
|
40
|
-
const unit: string =
|
|
40
|
+
const unit: string = profileType?.sampleUnit ?? '';
|
|
41
41
|
|
|
42
|
-
const columns
|
|
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
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
154
|
-
}, [profileType, unit]);
|
|
42
|
+
const columns: Array<ColumnDef<Row>> = [
|
|
43
|
+
columnHelper.accessor('flat', {
|
|
44
|
+
id: 'flat',
|
|
45
|
+
header: 'Flat',
|
|
46
|
+
cell: info => valueFormatter(info.getValue(), unit, 2),
|
|
47
|
+
size: 80,
|
|
48
|
+
meta: {
|
|
49
|
+
align: 'right',
|
|
50
|
+
},
|
|
51
|
+
invertSorting: true,
|
|
52
|
+
}),
|
|
53
|
+
columnHelper.accessor('flat', {
|
|
54
|
+
id: 'flatPercentage',
|
|
55
|
+
header: 'Flat (%)',
|
|
56
|
+
cell: info => {
|
|
57
|
+
return getRatioString(info.getValue(), total, filtered);
|
|
58
|
+
},
|
|
59
|
+
size: 120,
|
|
60
|
+
meta: {
|
|
61
|
+
align: 'right',
|
|
62
|
+
},
|
|
63
|
+
invertSorting: true,
|
|
64
|
+
}),
|
|
65
|
+
columnHelper.accessor('flatDiff', {
|
|
66
|
+
id: 'flatDiff',
|
|
67
|
+
header: 'Flat Diff',
|
|
68
|
+
cell: info => addPlusSign(valueFormatter(info.getValue(), unit, 2)),
|
|
69
|
+
size: 120,
|
|
70
|
+
meta: {
|
|
71
|
+
align: 'right',
|
|
72
|
+
},
|
|
73
|
+
invertSorting: true,
|
|
74
|
+
}),
|
|
75
|
+
columnHelper.accessor('flatDiff', {
|
|
76
|
+
id: 'flatDiffPercentage',
|
|
77
|
+
header: 'Flat Diff (%)',
|
|
78
|
+
cell: info => {
|
|
79
|
+
return getRatioString(info.getValue(), total, filtered);
|
|
80
|
+
},
|
|
81
|
+
size: 120,
|
|
82
|
+
meta: {
|
|
83
|
+
align: 'right',
|
|
84
|
+
},
|
|
85
|
+
invertSorting: true,
|
|
86
|
+
}),
|
|
87
|
+
columnHelper.accessor('cumulative', {
|
|
88
|
+
id: 'cumulative',
|
|
89
|
+
header: 'Cumulative',
|
|
90
|
+
cell: info => valueFormatter(info.getValue(), unit, 2),
|
|
91
|
+
size: 150,
|
|
92
|
+
meta: {
|
|
93
|
+
align: 'right',
|
|
94
|
+
},
|
|
95
|
+
invertSorting: true,
|
|
96
|
+
}),
|
|
97
|
+
columnHelper.accessor('cumulative', {
|
|
98
|
+
id: 'cumulativePercentage',
|
|
99
|
+
header: 'Cumulative (%)',
|
|
100
|
+
cell: info => {
|
|
101
|
+
return getRatioString(info.getValue(), total, filtered);
|
|
102
|
+
},
|
|
103
|
+
size: 150,
|
|
104
|
+
meta: {
|
|
105
|
+
align: 'right',
|
|
106
|
+
},
|
|
107
|
+
invertSorting: true,
|
|
108
|
+
}),
|
|
109
|
+
columnHelper.accessor('cumulativeDiff', {
|
|
110
|
+
id: 'cumulativeDiff',
|
|
111
|
+
header: 'Cumulative Diff',
|
|
112
|
+
cell: info => addPlusSign(valueFormatter(info.getValue(), unit, 2)),
|
|
113
|
+
size: 170,
|
|
114
|
+
meta: {
|
|
115
|
+
align: 'right',
|
|
116
|
+
},
|
|
117
|
+
invertSorting: true,
|
|
118
|
+
}),
|
|
119
|
+
columnHelper.accessor('cumulativeDiff', {
|
|
120
|
+
id: 'cumulativeDiffPercentage',
|
|
121
|
+
header: 'Cumulative Diff (%)',
|
|
122
|
+
cell: info => {
|
|
123
|
+
return getRatioString(info.getValue(), total, filtered);
|
|
124
|
+
},
|
|
125
|
+
size: 170,
|
|
126
|
+
meta: {
|
|
127
|
+
align: 'right',
|
|
128
|
+
},
|
|
129
|
+
invertSorting: true,
|
|
130
|
+
}),
|
|
131
|
+
columnHelper.accessor('name', {
|
|
132
|
+
id: 'name',
|
|
133
|
+
header: 'Name',
|
|
134
|
+
cell: info => info.getValue(),
|
|
135
|
+
}),
|
|
136
|
+
columnHelper.accessor('functionSystemName', {
|
|
137
|
+
id: 'functionSystemName',
|
|
138
|
+
header: 'Function System Name',
|
|
139
|
+
cell: info => info.getValue(),
|
|
140
|
+
}),
|
|
141
|
+
columnHelper.accessor('functionFileName', {
|
|
142
|
+
id: 'functionFileName',
|
|
143
|
+
header: 'Function File Name',
|
|
144
|
+
cell: info => info.getValue(),
|
|
145
|
+
}),
|
|
146
|
+
columnHelper.accessor('mappingFile', {
|
|
147
|
+
id: 'mappingFile',
|
|
148
|
+
header: 'Mapping File',
|
|
149
|
+
cell: info => info.getValue(),
|
|
150
|
+
}),
|
|
151
|
+
];
|
|
155
152
|
|
|
156
153
|
const [columnVisibility, setColumnVisibility] = useState(() => {
|
|
157
154
|
return {
|
|
@@ -173,6 +170,7 @@ const TableColumnsDropdown = ({profileType, total, filtered}: Props): JSX.Elemen
|
|
|
173
170
|
|
|
174
171
|
useEffect(() => {
|
|
175
172
|
if (Array.isArray(tableColumns)) {
|
|
173
|
+
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
176
174
|
setColumnVisibility(prevState => {
|
|
177
175
|
const newState = {...prevState};
|
|
178
176
|
(Object.keys(newState) as ColumnName[]).forEach(column => {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import ReactSelect, {type MenuListProps, type Props as ReactSelectProps} from 'react-select';
|
|
17
17
|
|
|
@@ -39,7 +39,7 @@ export function SelectWithRefresh<Option, IsMulti extends boolean = false>(
|
|
|
39
39
|
|
|
40
40
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
|
41
41
|
|
|
42
|
-
const handleRefetch =
|
|
42
|
+
const handleRefetch = async (): Promise<void> => {
|
|
43
43
|
if (onRefresh == null || isRefreshing) return;
|
|
44
44
|
|
|
45
45
|
setIsRefreshing(true);
|
|
@@ -50,35 +50,35 @@ export function SelectWithRefresh<Option, IsMulti extends boolean = false>(
|
|
|
50
50
|
} finally {
|
|
51
51
|
setIsRefreshing(false);
|
|
52
52
|
}
|
|
53
|
-
}
|
|
53
|
+
};
|
|
54
54
|
|
|
55
|
-
const MenuListWithRefresh =
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
const MenuListWithRefresh = ({
|
|
56
|
+
children,
|
|
57
|
+
innerProps,
|
|
58
|
+
}: MenuListProps<Option, IsMulti>): JSX.Element => {
|
|
59
|
+
const testIdProps = menuTestId != null ? {'data-testid': menuTestId} : {};
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
</div>
|
|
69
|
-
{onRefresh != null && (
|
|
70
|
-
<RefreshButton
|
|
71
|
-
onClick={() => void handleRefetch()}
|
|
72
|
-
disabled={isRefreshing}
|
|
73
|
-
title={refreshTitle}
|
|
74
|
-
testId={refreshTestId}
|
|
75
|
-
/>
|
|
76
|
-
)}
|
|
61
|
+
return (
|
|
62
|
+
<div className="flex flex-col" style={{maxHeight: '332px'}}>
|
|
63
|
+
<div
|
|
64
|
+
className="overflow-y-auto flex-1"
|
|
65
|
+
{...innerProps}
|
|
66
|
+
{...testIdProps}
|
|
67
|
+
style={{...innerProps?.style, fontSize: '14px'}}
|
|
68
|
+
>
|
|
69
|
+
{children}
|
|
77
70
|
</div>
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
{onRefresh != null && (
|
|
72
|
+
<RefreshButton
|
|
73
|
+
onClick={() => void handleRefetch()}
|
|
74
|
+
disabled={isRefreshing}
|
|
75
|
+
title={refreshTitle}
|
|
76
|
+
testId={refreshTestId}
|
|
77
|
+
/>
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
82
|
|
|
83
83
|
const combinedLoadingState = isRefreshing || (selectProps.isLoading ?? false);
|
|
84
84
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import React, {
|
|
14
|
+
import React, {useEffect, useMemo, useRef, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import {Icon} from '@iconify/react';
|
|
17
17
|
import {useVirtualizer} from '@tanstack/react-virtual';
|
|
@@ -91,7 +91,7 @@ const CustomSelect: React.FC<CustomSelectProps & Record<string, any>> = ({
|
|
|
91
91
|
const optionsRef = useRef<HTMLDivElement>(null);
|
|
92
92
|
const searchInputRef = useRef<HTMLInputElement | HTMLTextAreaElement>(null);
|
|
93
93
|
|
|
94
|
-
const handleRefetch =
|
|
94
|
+
const handleRefetch = async (): Promise<void> => {
|
|
95
95
|
if (refetchValues == null || isRefetching) return;
|
|
96
96
|
|
|
97
97
|
setIsRefetching(true);
|
|
@@ -100,23 +100,21 @@ const CustomSelect: React.FC<CustomSelectProps & Record<string, any>> = ({
|
|
|
100
100
|
} finally {
|
|
101
101
|
setIsRefetching(false);
|
|
102
102
|
}
|
|
103
|
-
}
|
|
103
|
+
};
|
|
104
104
|
|
|
105
105
|
useEffect(() => {
|
|
106
106
|
const timer = setTimeout(() => setDebouncedSearchTerm(searchTerm), 150);
|
|
107
107
|
return () => clearTimeout(timer);
|
|
108
108
|
}, [searchTerm]);
|
|
109
109
|
|
|
110
|
-
const items
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return (itemsProp as SelectItem[]).map(item => ({...item, type: ''}));
|
|
117
|
-
}, [itemsProp]);
|
|
110
|
+
const items: TypedSelectItem[] =
|
|
111
|
+
itemsProp[0] != null && 'type' in itemsProp[0]
|
|
112
|
+
? (itemsProp as GroupedSelectItem[]).flatMap(item =>
|
|
113
|
+
item.values.map(v => ({...v, type: item.type}))
|
|
114
|
+
)
|
|
115
|
+
: (itemsProp as SelectItem[]).map(item => ({...item, type: ''}));
|
|
118
116
|
|
|
119
|
-
const
|
|
117
|
+
const computeFilteredItems = (): TypedSelectItem[] => {
|
|
120
118
|
if (!searchable) return items;
|
|
121
119
|
const lowerSearch = debouncedSearchTerm.toLowerCase();
|
|
122
120
|
const filtered = items.filter(item =>
|
|
@@ -129,7 +127,8 @@ const CustomSelect: React.FC<CustomSelectProps & Record<string, any>> = ({
|
|
|
129
127
|
(a, b) =>
|
|
130
128
|
levenshtein.get(a.key, debouncedSearchTerm) - levenshtein.get(b.key, debouncedSearchTerm)
|
|
131
129
|
);
|
|
132
|
-
}
|
|
130
|
+
};
|
|
131
|
+
const filteredItems = computeFilteredItems();
|
|
133
132
|
|
|
134
133
|
const selection = editable ? selectedKey : items.find(v => v.key === selectedKey);
|
|
135
134
|
|
|
@@ -228,24 +227,20 @@ const CustomSelect: React.FC<CustomSelectProps & Record<string, any>> = ({
|
|
|
228
227
|
e.target.value = value;
|
|
229
228
|
};
|
|
230
229
|
|
|
231
|
-
const groupedFilteredItems =
|
|
232
|
-
|
|
233
|
-
.
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
const showHeaders = useMemo(
|
|
246
|
-
() => groupedFilteredItems.length > 1 && groupedFilteredItems.every(g => g.type !== ''),
|
|
247
|
-
[groupedFilteredItems]
|
|
248
|
-
);
|
|
230
|
+
const groupedFilteredItems = filteredItems
|
|
231
|
+
.reduce((acc: GroupedSelectItem[], item) => {
|
|
232
|
+
const group = acc.find(g => g.type === item.type);
|
|
233
|
+
if (group != null) {
|
|
234
|
+
group.values.push(item);
|
|
235
|
+
} else {
|
|
236
|
+
acc.push({type: item.type, values: [item]});
|
|
237
|
+
}
|
|
238
|
+
return acc;
|
|
239
|
+
}, [])
|
|
240
|
+
.sort((a, b) => a.values.length - b.values.length);
|
|
241
|
+
|
|
242
|
+
const showHeaders =
|
|
243
|
+
groupedFilteredItems.length > 1 && groupedFilteredItems.every(g => g.type !== '');
|
|
249
244
|
|
|
250
245
|
const flatList = useMemo(() => {
|
|
251
246
|
const list: Array<
|
|
@@ -264,12 +259,9 @@ const CustomSelect: React.FC<CustomSelectProps & Record<string, any>> = ({
|
|
|
264
259
|
return list;
|
|
265
260
|
}, [groupedFilteredItems, showHeaders]);
|
|
266
261
|
|
|
267
|
-
const longestKey =
|
|
268
|
-
() =>
|
|
269
|
-
|
|
270
|
-
?.key ?? '',
|
|
271
|
-
[filteredItems]
|
|
272
|
-
);
|
|
262
|
+
const longestKey =
|
|
263
|
+
filteredItems.reduce((a, b) => (a.key.length > b.key.length ? a : b), filteredItems[0])?.key ??
|
|
264
|
+
'';
|
|
273
265
|
|
|
274
266
|
const rowVirtualizer = useVirtualizer({
|
|
275
267
|
count: flatList.length,
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {MouseEventHandler, useId
|
|
14
|
+
import {MouseEventHandler, useId} from 'react';
|
|
15
15
|
|
|
16
16
|
import cx from 'classnames';
|
|
17
17
|
import {scaleLinear} from 'd3-scale';
|
|
@@ -193,7 +193,7 @@ export const profileAwareRenderer = (
|
|
|
193
193
|
|
|
194
194
|
export const Highlighter = ({file, content, renderer}: HighlighterProps): JSX.Element => {
|
|
195
195
|
const {isDarkMode} = useParcaContext();
|
|
196
|
-
const language =
|
|
196
|
+
const language = langaugeFromFile(file);
|
|
197
197
|
|
|
198
198
|
return (
|
|
199
199
|
<div className="relative">
|