@perses-dev/components 0.3.0 → 0.3.1

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.
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StatChart = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ // Copyright 2021 The Perses Authors
6
+ // Licensed under the Apache License, Version 2.0 (the "License");
7
+ // you may not use this file except in compliance with the License.
8
+ // You may obtain a copy of the License at
9
+ //
10
+ // http://www.apache.org/licenses/LICENSE-2.0
11
+ //
12
+ // Unless required by applicable law or agreed to in writing, software
13
+ // distributed under the License is distributed on an "AS IS" BASIS,
14
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ // See the License for the specific language governing permissions and
16
+ // limitations under the License.
17
+ const react_1 = require("react");
18
+ const lodash_es_1 = require("lodash-es");
19
+ const core_1 = require("echarts/core");
20
+ const charts_1 = require("echarts/charts");
21
+ const charts_2 = require("echarts/charts");
22
+ const components_1 = require("echarts/components");
23
+ const renderers_1 = require("echarts/renderers");
24
+ const units_1 = require("./model/units");
25
+ const ECharts_1 = require("./ECharts");
26
+ (0, core_1.use)([
27
+ charts_1.GaugeChart,
28
+ charts_2.LineChart,
29
+ components_1.GridComponent,
30
+ components_1.DatasetComponent,
31
+ components_1.TitleComponent,
32
+ components_1.TooltipComponent,
33
+ renderers_1.CanvasRenderer,
34
+ ]);
35
+ const noDataOption = {
36
+ title: {
37
+ show: true,
38
+ textStyle: {
39
+ color: 'grey',
40
+ fontSize: 16,
41
+ fontWeight: 400,
42
+ },
43
+ text: 'No data',
44
+ left: 'center',
45
+ top: 'center',
46
+ },
47
+ xAxis: {
48
+ show: false,
49
+ },
50
+ yAxis: {
51
+ show: false,
52
+ },
53
+ series: [],
54
+ };
55
+ function StatChart(props) {
56
+ const { width, height, data, unit, backgroundColor, sparkline } = props;
57
+ const option = (0, react_1.useMemo)(() => {
58
+ var _a;
59
+ if (data.seriesData === undefined)
60
+ return {};
61
+ if (data.seriesData === null || data.calculatedValue === undefined)
62
+ return noDataOption;
63
+ const series = data.seriesData;
64
+ const calculatedValue = (_a = data.calculatedValue) !== null && _a !== void 0 ? _a : 0;
65
+ const isLargePanel = width > 250 ? true : false;
66
+ const showName = isLargePanel;
67
+ const name = showName === true ? data.name : '';
68
+ const smallestSide = Math.min(width, height * 1.2);
69
+ const baseFontSize = Math.min((smallestSide / 4) * 0.65, 72);
70
+ const nameFontSize = baseFontSize * 0.5;
71
+ const statSeries = [
72
+ {
73
+ type: 'gauge',
74
+ data: [
75
+ {
76
+ value: calculatedValue,
77
+ name: name,
78
+ },
79
+ ],
80
+ detail: {
81
+ show: true,
82
+ offsetCenter: ['0%', '-65%'],
83
+ formatter: [`{name|${name}}`, `{value|${(0, units_1.formatValue)(calculatedValue, unit)}}`].join('\n'),
84
+ rich: {
85
+ name: {
86
+ padding: showName === true ? [0, 0, 5, 0] : 0,
87
+ fontSize: nameFontSize,
88
+ lineHeight: nameFontSize * 2.5,
89
+ fontWeight: 500,
90
+ },
91
+ value: {},
92
+ },
93
+ },
94
+ center: ['50%', '60%'],
95
+ animation: false,
96
+ silent: true,
97
+ title: { show: false },
98
+ progress: { show: false },
99
+ pointer: { show: false },
100
+ axisLine: { show: false },
101
+ axisTick: { show: false },
102
+ splitLine: { show: false },
103
+ axisLabel: { show: false },
104
+ anchor: { show: false },
105
+ zlevel: 2,
106
+ },
107
+ ];
108
+ if (sparkline !== undefined) {
109
+ const lineSeries = {
110
+ type: 'line',
111
+ data: [...series.values],
112
+ zlevel: 1,
113
+ symbol: 'none',
114
+ animation: false,
115
+ lineStyle: {
116
+ color: '#FFFFFF',
117
+ opacity: 0.6,
118
+ },
119
+ areaStyle: {
120
+ color: '#FFFFFF',
121
+ opacity: 0.3,
122
+ },
123
+ silent: true,
124
+ };
125
+ const mergedSeries = (0, lodash_es_1.merge)(lineSeries, sparkline);
126
+ statSeries.push(mergedSeries);
127
+ }
128
+ const option = {
129
+ title: {
130
+ show: false,
131
+ },
132
+ grid: [
133
+ {
134
+ show: true,
135
+ backgroundColor: backgroundColor,
136
+ top: 0,
137
+ right: 0,
138
+ bottom: 0,
139
+ left: 0,
140
+ containLabel: false,
141
+ borderWidth: 0,
142
+ },
143
+ {
144
+ show: false,
145
+ top: '45%',
146
+ right: 0,
147
+ bottom: 0,
148
+ left: 0,
149
+ containLabel: false,
150
+ },
151
+ ],
152
+ xAxis: {
153
+ type: 'time',
154
+ show: false,
155
+ boundaryGap: false,
156
+ gridIndex: 1, // sparkline grid
157
+ },
158
+ yAxis: {
159
+ type: 'value',
160
+ show: false,
161
+ gridIndex: 1,
162
+ },
163
+ tooltip: {
164
+ show: false,
165
+ },
166
+ series: statSeries,
167
+ textStyle: {
168
+ color: backgroundColor === 'transparent' ? '#000000' : '#FFFFFF',
169
+ fontSize: 25,
170
+ lineHeight: 18,
171
+ fontFamily: '"Lato", sans-serif',
172
+ fontWeight: 'bold',
173
+ },
174
+ media: [
175
+ {
176
+ query: {
177
+ maxWidth: 150,
178
+ },
179
+ option: {
180
+ textStyle: {
181
+ fontSize: 12,
182
+ },
183
+ },
184
+ },
185
+ {
186
+ query: {
187
+ minWidth: 150,
188
+ },
189
+ option: {
190
+ textStyle: {
191
+ fontSize: `max(14px, ${baseFontSize}px)`,
192
+ lineHeight: Math.min(16, baseFontSize * 1.2),
193
+ },
194
+ },
195
+ },
196
+ ],
197
+ };
198
+ return option;
199
+ }, [data, height, unit, width, sparkline, backgroundColor]);
200
+ return ((0, jsx_runtime_1.jsx)(ECharts_1.ECharts, { sx: {
201
+ width: width,
202
+ height: height,
203
+ }, option: option }));
204
+ }
205
+ exports.StatChart = StatChart;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ // Copyright 2021 The Perses Authors
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ var desc = Object.getOwnPropertyDescriptor(m, k);
17
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
18
+ desc = { enumerable: true, get: function() { return m[k]; } };
19
+ }
20
+ Object.defineProperty(o, k2, desc);
21
+ }) : (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ o[k2] = m[k];
24
+ }));
25
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
26
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ __exportStar(require("./ECharts"), exports);
30
+ __exportStar(require("./ErrorAlert"), exports);
31
+ __exportStar(require("./ErrorBoundary"), exports);
32
+ __exportStar(require("./GaugeChart"), exports);
33
+ __exportStar(require("./LineChart"), exports);
34
+ __exportStar(require("./StatChart"), exports);
35
+ __exportStar(require("./utils/combine-sx"), exports);
36
+ __exportStar(require("./model/graph-model"), exports);
37
+ __exportStar(require("./model/units"), exports);
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ // Copyright 2021 The Perses Authors
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.PROGRESSIVE_MODE_SERIES_LIMIT = void 0;
16
+ exports.PROGRESSIVE_MODE_SERIES_LIMIT = 500;
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ // Copyright 2021 The Perses Authors
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.SIMPLE_UNITS = exports.removeUnitNamespace = exports.SANCTIONED_UNITS = exports.isSanctionedSimpleUnitIdentifier = exports.abbreviateLargeNumber = exports.formatValue = void 0;
16
+ const date_fns_1 = require("date-fns");
17
+ function formatValue(value, unitOptions) {
18
+ if (unitOptions === undefined) {
19
+ return value.toString();
20
+ }
21
+ if (isTimeUnit(unitOptions)) {
22
+ return formatTime(value, unitOptions);
23
+ }
24
+ if (isPercentUnit(unitOptions)) {
25
+ return formatPercent(value, unitOptions);
26
+ }
27
+ if (isDecimalUnit(unitOptions)) {
28
+ return formatDecimal(value, unitOptions);
29
+ }
30
+ const exhaustive = unitOptions;
31
+ throw new Error(`Unknown unit options ${exhaustive}`);
32
+ }
33
+ exports.formatValue = formatValue;
34
+ const timeUnitKinds = ['Milliseconds', 'Seconds', 'Minutes', 'Hours', 'Days', 'Weeks', 'Months', 'Years'];
35
+ const timeUnitKindsSet = new Set(timeUnitKinds);
36
+ function isTimeUnit(unitOptions) {
37
+ return timeUnitKindsSet.has(unitOptions.kind);
38
+ }
39
+ function formatTime(value, unitOptions) {
40
+ // Create a Duration from the value based on what time unit it is
41
+ const duration = {};
42
+ switch (unitOptions.kind) {
43
+ case 'Milliseconds':
44
+ duration.seconds = value / 1000;
45
+ break;
46
+ case 'Seconds':
47
+ duration.seconds = value;
48
+ break;
49
+ case 'Minutes':
50
+ duration.minutes = value;
51
+ break;
52
+ case 'Hours':
53
+ duration.hours = value;
54
+ break;
55
+ case 'Days':
56
+ duration.days = value;
57
+ break;
58
+ case 'Weeks':
59
+ duration.weeks = value;
60
+ break;
61
+ case 'Months':
62
+ duration.months = value;
63
+ break;
64
+ case 'Years':
65
+ duration.years = value;
66
+ break;
67
+ default:
68
+ const exhaustive = unitOptions.kind;
69
+ throw new Error(`Unknown time unit type ${exhaustive}`);
70
+ }
71
+ // Find the largest whole time unit we can display the value in and use it
72
+ const ms = (0, date_fns_1.milliseconds)(duration);
73
+ const seconds = ms / 1000;
74
+ if (seconds < 1) {
75
+ return `${ms.toFixed()} milliseconds`;
76
+ }
77
+ const minutes = seconds / 60;
78
+ if (minutes < 1) {
79
+ return `${seconds.toFixed()} seconds`;
80
+ }
81
+ const hours = minutes / 60;
82
+ if (hours < 1) {
83
+ return `${minutes.toFixed()} minutes`;
84
+ }
85
+ const days = hours / 24;
86
+ if (days < 1) {
87
+ return `${hours.toFixed()} hours`;
88
+ }
89
+ const weeks = days / 7;
90
+ if (weeks < 1) {
91
+ return `${days.toFixed()} days`;
92
+ }
93
+ const years = weeks / 52;
94
+ if (years < 1) {
95
+ return `${weeks.toFixed()} weeks`;
96
+ }
97
+ return `${years.toFixed()} years`;
98
+ }
99
+ const percentUnitKinds = ['Percent', 'PercentDecimal'];
100
+ const percentUnitKindsSet = new Set(percentUnitKinds);
101
+ function isPercentUnit(unitOptions) {
102
+ return percentUnitKindsSet.has(unitOptions.kind);
103
+ }
104
+ function formatPercent(value, unitOptions) {
105
+ if (unitOptions.kind === 'PercentDecimal') {
106
+ value = value * 100;
107
+ }
108
+ return value.toFixed(unitOptions.decimal_places) + '%';
109
+ }
110
+ const decimalUnitKinds = ['Decimal'];
111
+ const decimalUnitKindsSet = new Set(decimalUnitKinds);
112
+ function isDecimalUnit(unitOptions) {
113
+ return decimalUnitKindsSet.has(unitOptions.kind);
114
+ }
115
+ function formatDecimal(value, unitOptions) {
116
+ var _a, _b;
117
+ const maximumFractionDigits = (_a = unitOptions.decimal_places) !== null && _a !== void 0 ? _a : 2;
118
+ if (unitOptions.suffix !== undefined) {
119
+ if (isSanctionedSimpleUnitIdentifier(unitOptions.suffix)) {
120
+ const formatParams = {
121
+ style: 'unit',
122
+ minimumFractionDigits: 0,
123
+ maximumFractionDigits: maximumFractionDigits,
124
+ useGrouping: true,
125
+ unit: unitOptions.suffix,
126
+ unitDisplay: (_b = unitOptions.unitDisplay) !== null && _b !== void 0 ? _b : 'narrow',
127
+ };
128
+ const unitFormatter = new Intl.NumberFormat('en-US', formatParams);
129
+ return unitFormatter.format(value);
130
+ }
131
+ }
132
+ const formatParams = {
133
+ style: 'decimal',
134
+ minimumFractionDigits: 0,
135
+ maximumFractionDigits: maximumFractionDigits,
136
+ useGrouping: true,
137
+ };
138
+ const decimalFormatter = new Intl.NumberFormat('en-US', formatParams);
139
+ return decimalFormatter.format(value);
140
+ }
141
+ // Take a large number and abbreviate appropriate suffix
142
+ // ex) 10000 -> 10k, 1000000 -> 1M
143
+ function abbreviateLargeNumber(num) {
144
+ return num >= 1e12
145
+ ? num / 1e12 + 'T'
146
+ : num >= 1e9
147
+ ? num / 1e9 + 'B'
148
+ : num >= 1e6
149
+ ? num / 1e6 + 'M'
150
+ : num >= 1e3
151
+ ? num / 1e3 + 'k'
152
+ : num;
153
+ }
154
+ exports.abbreviateLargeNumber = abbreviateLargeNumber;
155
+ // Util to check unit name against ECMA standard: https://tc39.es/ecma402/#sec-issanctionedsimpleunitidentifier
156
+ function isSanctionedSimpleUnitIdentifier(unitIdentifier) {
157
+ return exports.SIMPLE_UNITS.indexOf(unitIdentifier) > -1;
158
+ }
159
+ exports.isSanctionedSimpleUnitIdentifier = isSanctionedSimpleUnitIdentifier;
160
+ // https://tc39.es/ecma402/#table-sanctioned-simple-unit-identifiers
161
+ exports.SANCTIONED_UNITS = [
162
+ 'angle-degree',
163
+ 'area-acre',
164
+ 'area-hectare',
165
+ 'concentr-percent',
166
+ 'digital-bit',
167
+ 'digital-byte',
168
+ 'digital-gigabit',
169
+ 'digital-gigabyte',
170
+ 'digital-kilobit',
171
+ 'digital-kilobyte',
172
+ 'digital-megabit',
173
+ 'digital-megabyte',
174
+ 'digital-petabyte',
175
+ 'digital-terabit',
176
+ 'digital-terabyte',
177
+ 'duration-day',
178
+ 'duration-hour',
179
+ 'duration-millisecond',
180
+ 'duration-minute',
181
+ 'duration-month',
182
+ 'duration-second',
183
+ 'duration-week',
184
+ 'duration-year',
185
+ 'length-centimeter',
186
+ 'length-foot',
187
+ 'length-inch',
188
+ 'length-kilometer',
189
+ 'length-meter',
190
+ 'length-mile-scandinavian',
191
+ 'length-mile',
192
+ 'length-millimeter',
193
+ 'length-yard',
194
+ 'mass-gram',
195
+ 'mass-kilogram',
196
+ 'mass-ounce',
197
+ 'mass-pound',
198
+ 'mass-stone',
199
+ 'temperature-celsius',
200
+ 'temperature-fahrenheit',
201
+ 'volume-fluid-ounce',
202
+ 'volume-gallon',
203
+ 'volume-liter',
204
+ 'volume-milliliter',
205
+ ];
206
+ // removes the namespace prefix, ex: duration-hour -> hour
207
+ function removeUnitNamespace(unit) {
208
+ return unit.slice(unit.indexOf('-') + 1);
209
+ }
210
+ exports.removeUnitNamespace = removeUnitNamespace;
211
+ exports.SIMPLE_UNITS = exports.SANCTIONED_UNITS.map(removeUnitNamespace);
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SeriesInfo = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ // Copyright 2021 The Perses Authors
6
+ // Licensed under the Apache License, Version 2.0 (the "License");
7
+ // you may not use this file except in compliance with the License.
8
+ // You may obtain a copy of the License at
9
+ //
10
+ // http://www.apache.org/licenses/LICENSE-2.0
11
+ //
12
+ // Unless required by applicable law or agreed to in writing, software
13
+ // distributed under the License is distributed on an "AS IS" BASIS,
14
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ // See the License for the specific language governing permissions and
16
+ // limitations under the License.
17
+ const material_1 = require("@mui/material");
18
+ const SeriesMarker_1 = require("./SeriesMarker");
19
+ const tooltip_model_1 = require("./tooltip-model");
20
+ function SeriesInfo(props) {
21
+ const { seriesName, y, markerColor, totalSeries, wrapLabels } = props;
22
+ // TODO (sjcobb): regex to remove __name__, improve series labels
23
+ const formattedSeriesLabels = seriesName.replace(/[{}"]/g, '');
24
+ if (totalSeries === 1) {
25
+ const jsonFormattedSeries = seriesName[0] === '{' ? true : false;
26
+ return ((0, jsx_runtime_1.jsxs)(material_1.Stack, { spacing: 0.5, children: [(0, jsx_runtime_1.jsxs)(material_1.Box, { sx: (theme) => ({
27
+ height: '16px',
28
+ display: 'flex',
29
+ flexDirection: 'row',
30
+ alignItems: 'center',
31
+ justifyContent: 'left',
32
+ color: theme.palette.common.white,
33
+ fontSize: '11px',
34
+ }), children: [(0, jsx_runtime_1.jsx)(SeriesMarker_1.SeriesMarker, { markerColor: markerColor }), (0, jsx_runtime_1.jsxs)(material_1.Box, { component: "span", children: ["value:", (0, jsx_runtime_1.jsx)(material_1.Box, { component: "span", sx: (theme) => ({
35
+ color: theme.palette.common.white,
36
+ fontWeight: 700,
37
+ paddingLeft: '2px',
38
+ }), children: y })] })] }), (0, jsx_runtime_1.jsx)(material_1.Divider, { sx: (theme) => ({
39
+ borderColor: theme.palette.grey['500'],
40
+ }) }), (0, jsx_runtime_1.jsx)(material_1.Box, { sx: (theme) => ({
41
+ color: theme.palette.common.white,
42
+ }), children: formattedSeriesLabels.split(',').map((name) => {
43
+ if (name) {
44
+ const [key, value] = jsonFormattedSeries ? name.split(':') : name.split('=');
45
+ return ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { display: 'flex', gap: '4px' }, children: [(0, jsx_runtime_1.jsxs)(material_1.Typography, { sx: { fontSize: '11px' }, children: [key, ":"] }), (0, jsx_runtime_1.jsx)(material_1.Typography, { sx: (theme) => ({
46
+ color: theme.palette.common.white,
47
+ fontWeight: 700,
48
+ fontSize: '11px',
49
+ }), children: value })] }, name));
50
+ }
51
+ }) })] }));
52
+ }
53
+ const inlineSeriesLabels = formattedSeriesLabels.replace(/[,]/g, ', ').replace(/[:=]/g, ': ');
54
+ return ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: {
55
+ display: 'table-row',
56
+ paddingTop: 0.5,
57
+ }, children: [(0, jsx_runtime_1.jsxs)(material_1.Box, { sx: {
58
+ display: 'table-cell',
59
+ maxWidth: '520px',
60
+ }, children: [(0, jsx_runtime_1.jsx)(SeriesMarker_1.SeriesMarker, { markerColor: markerColor }), (0, jsx_runtime_1.jsx)(material_1.Box, { component: "span", sx: (theme) => ({
61
+ color: theme.palette.common.white,
62
+ display: 'inline-block',
63
+ maxWidth: tooltip_model_1.TOOLTIP_LABELS_MAX_WIDTH,
64
+ overflow: 'hidden',
65
+ textOverflow: 'ellipsis',
66
+ whiteSpace: wrapLabels ? 'normal' : 'nowrap',
67
+ width: 'calc(100% - 20px)',
68
+ }), children: inlineSeriesLabels })] }), (0, jsx_runtime_1.jsx)(material_1.Box, { sx: {
69
+ display: 'table-cell',
70
+ fontWeight: '700',
71
+ paddingLeft: 1.5,
72
+ textAlign: 'right',
73
+ verticalAlign: 'top',
74
+ }, children: y })] }));
75
+ }
76
+ exports.SeriesInfo = SeriesInfo;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SeriesMarker = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ // Copyright 2021 The Perses Authors
6
+ // Licensed under the Apache License, Version 2.0 (the "License");
7
+ // you may not use this file except in compliance with the License.
8
+ // You may obtain a copy of the License at
9
+ //
10
+ // http://www.apache.org/licenses/LICENSE-2.0
11
+ //
12
+ // Unless required by applicable law or agreed to in writing, software
13
+ // distributed under the License is distributed on an "AS IS" BASIS,
14
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ // See the License for the specific language governing permissions and
16
+ // limitations under the License.
17
+ const material_1 = require("@mui/material");
18
+ function SeriesMarker(props) {
19
+ const { markerColor } = props;
20
+ return ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: {
21
+ display: 'inline-block',
22
+ width: '12px',
23
+ borderRadius: '2px',
24
+ height: '12px',
25
+ marginTop: 0.25,
26
+ marginRight: 1,
27
+ verticalAlign: 'top',
28
+ }, style: { backgroundColor: markerColor } }));
29
+ }
30
+ exports.SeriesMarker = SeriesMarker;
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Tooltip = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ // Copyright 2021 The Perses Authors
6
+ // Licensed under the Apache License, Version 2.0 (the "License");
7
+ // you may not use this file except in compliance with the License.
8
+ // You may obtain a copy of the License at
9
+ //
10
+ // http://www.apache.org/licenses/LICENSE-2.0
11
+ //
12
+ // Unless required by applicable law or agreed to in writing, software
13
+ // distributed under the License is distributed on an "AS IS" BASIS,
14
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ // See the License for the specific language governing permissions and
16
+ // limitations under the License.
17
+ const react_1 = require("react");
18
+ const material_1 = require("@mui/material");
19
+ const focused_series_1 = require("./focused-series");
20
+ const tooltip_model_1 = require("./tooltip-model");
21
+ const TooltipContent_1 = require("./TooltipContent");
22
+ function Tooltip(props) {
23
+ var _a, _b;
24
+ const { chartRef, chartData } = props;
25
+ const [pinnedPos, setPinnedPos] = (0, react_1.useState)(null);
26
+ const mousePos = (0, tooltip_model_1.useMousePosition)();
27
+ if (mousePos === null)
28
+ return null;
29
+ const chart = chartRef.current;
30
+ const focusedSeries = (0, focused_series_1.getFocusedSeriesData)(mousePos, chartData, pinnedPos, chart);
31
+ const chartWidth = (_a = chart === null || chart === void 0 ? void 0 : chart.getWidth()) !== null && _a !== void 0 ? _a : 750;
32
+ const chartHeight = (_b = chart === null || chart === void 0 ? void 0 : chart.getHeight()) !== null && _b !== void 0 ? _b : 230;
33
+ const cursorTransform = assembleTransform(mousePos, focusedSeries.length, chartWidth, chartHeight, pinnedPos);
34
+ function handleMouseEnter() {
35
+ if (mousePos !== null) {
36
+ setPinnedPos(mousePos);
37
+ }
38
+ }
39
+ function handleMouseLeave() {
40
+ if (pinnedPos !== null) {
41
+ setPinnedPos(null);
42
+ }
43
+ }
44
+ if (focusedSeries.length === 0) {
45
+ return null;
46
+ }
47
+ return ((0, jsx_runtime_1.jsx)(material_1.Portal, { children: (0, jsx_runtime_1.jsx)(material_1.Box, { sx: (theme) => ({
48
+ maxWidth: tooltip_model_1.TOOLTIP_MAX_WIDTH,
49
+ maxHeight: tooltip_model_1.TOOLTIP_MAX_HEIGHT,
50
+ position: 'absolute',
51
+ top: 0,
52
+ left: 0,
53
+ overflowY: 'scroll',
54
+ backgroundColor: '#000',
55
+ borderRadius: '6px',
56
+ color: '#fff',
57
+ fontSize: '11px',
58
+ visibility: 'visible',
59
+ opacity: 1,
60
+ transition: 'all 0.1s ease-out',
61
+ zIndex: theme.zIndex.tooltip,
62
+ }), style: {
63
+ transform: cursorTransform,
64
+ }, onMouseEnter: () => handleMouseEnter(), onMouseLeave: () => handleMouseLeave(), children: (0, jsx_runtime_1.jsx)(TooltipContent_1.TooltipContent, { focusedSeries: focusedSeries, wrapLabels: props.wrapLabels }) }) }));
65
+ }
66
+ exports.Tooltip = Tooltip;
67
+ function assembleTransform(mousePos, seriesNum, chartWidth, chartHeight, pinnedPos) {
68
+ if (mousePos === null) {
69
+ return 'translate3d(0, 0)';
70
+ }
71
+ if (pinnedPos !== null) {
72
+ mousePos = pinnedPos;
73
+ }
74
+ const cursorPaddingX = 32;
75
+ const cursorPaddingY = 16;
76
+ const x = mousePos.viewport.x;
77
+ let y = mousePos.viewport.y + cursorPaddingY;
78
+ const isCloseToBottom = mousePos.viewport.y > window.innerHeight * 0.8;
79
+ const yPosAdjustThreshold = chartHeight * 0.75;
80
+ // adjust so tooltip does not get cut off at bottom of chart, reduce multiplier to move up
81
+ if (isCloseToBottom === true) {
82
+ if (seriesNum > 6) {
83
+ y = mousePos.viewport.y * 0.65;
84
+ }
85
+ else {
86
+ y = mousePos.viewport.y * 0.75;
87
+ }
88
+ }
89
+ else if (mousePos.plotCanvas.y > yPosAdjustThreshold) {
90
+ y = mousePos.viewport.y * 0.85;
91
+ }
92
+ // use tooltip width to determine when to repos from right to left (width is narrower when only 1 focused series since labels wrap)
93
+ const tooltipWidth = seriesNum > 1 ? tooltip_model_1.TOOLTIP_MAX_WIDTH : tooltip_model_1.TOOLTIP_MAX_WIDTH / 2;
94
+ const xPosAdjustThreshold = chartWidth - tooltipWidth * 0.9;
95
+ // reposition so tooltip is never too close to right side of chart or left side of browser window
96
+ return mousePos.plotCanvas.x > xPosAdjustThreshold && x > tooltip_model_1.TOOLTIP_MAX_WIDTH
97
+ ? `translate3d(${x - cursorPaddingX}px, ${y}px, 0) translateX(-100%)`
98
+ : `translate3d(${x + cursorPaddingX}px, ${y}px, 0)`;
99
+ }