@gitlab/ui 69.0.0 → 70.0.0
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 +20 -0
- package/dist/components/charts/area/area.js +3 -30
- package/dist/components/charts/bar/bar.js +2 -2
- package/dist/components/charts/column/column.js +2 -2
- package/dist/components/charts/discrete_scatter/discrete_scatter.js +1 -0
- package/dist/components/charts/heatmap/heatmap.js +2 -2
- package/dist/components/charts/line/line.js +3 -3
- package/dist/components/charts/stacked_column/stacked_column.js +2 -2
- package/dist/components/charts/tooltip/tooltip.js +121 -12
- package/dist/tokens/css/tokens.css +1 -1
- package/dist/tokens/css/tokens.dark.css +1 -1
- package/dist/tokens/js/tokens.dark.js +1 -1
- package/dist/tokens/js/tokens.js +1 -1
- package/dist/tokens/scss/_tokens.dark.scss +1 -1
- package/dist/tokens/scss/_tokens.scss +1 -1
- package/dist/utility_classes.css +1 -1
- package/dist/utility_classes.css.map +1 -1
- package/dist/utils/charts/constants.js +4 -12
- package/dist/utils/charts/theme.js +2 -3
- package/dist/utils/constants.js +1 -3
- package/package.json +8 -10
- package/src/components/charts/area/area.spec.js +2 -19
- package/src/components/charts/area/area.vue +3 -40
- package/src/components/charts/bar/bar.vue +2 -2
- package/src/components/charts/column/column.vue +2 -6
- package/src/components/charts/discrete_scatter/discrete_scatter.vue +1 -0
- package/src/components/charts/heatmap/heatmap.spec.js +1 -2
- package/src/components/charts/heatmap/heatmap.vue +2 -2
- package/src/components/charts/line/line.vue +2 -4
- package/src/components/charts/sparkline/sparkline.spec.js +6 -6
- package/src/components/charts/stacked_column/stacked_column.vue +1 -2
- package/src/components/charts/tooltip/tooltip.spec.js +158 -11
- package/src/components/charts/tooltip/tooltip.vue +117 -23
- package/src/scss/utilities.scss +20 -0
- package/src/scss/utility-mixins/spacing.scss +12 -0
- package/src/utils/charts/constants.js +3 -11
- package/src/utils/charts/theme.js +3 -2
- package/src/utils/constants.js +1 -3
- package/scss_to_js/scss_variables.js +0 -386
- package/scss_to_js/scss_variables.json +0 -2192
|
@@ -17,13 +17,6 @@ const ANNOTATIONS_SERIES_NAME = 'annotations';
|
|
|
17
17
|
*/
|
|
18
18
|
const ANNOTATIONS_COMPONENT_TYPE = 'markPoint';
|
|
19
19
|
|
|
20
|
-
/**
|
|
21
|
-
* This is so that the mouse doesn't go over the
|
|
22
|
-
* tooltip and call mouseout which will hide the
|
|
23
|
-
* tooltip.
|
|
24
|
-
*/
|
|
25
|
-
const ANNOTATION_TOOLTIP_TOP_OFFSET = 10;
|
|
26
|
-
|
|
27
20
|
/**
|
|
28
21
|
* This is a slight offset that gets applied to the left
|
|
29
22
|
* of the chart tooltips to ensure a correct position.
|
|
@@ -31,11 +24,10 @@ const ANNOTATION_TOOLTIP_TOP_OFFSET = 10;
|
|
|
31
24
|
const TOOLTIP_LEFT_OFFSET = 2;
|
|
32
25
|
|
|
33
26
|
/**
|
|
34
|
-
* This is
|
|
35
|
-
*
|
|
36
|
-
* some spacing.
|
|
27
|
+
* This is a slight offset that gets applied to the left
|
|
28
|
+
* of the chart tooltips to ensure a correct position.
|
|
37
29
|
*/
|
|
38
|
-
const
|
|
30
|
+
const TOOLTIP_TOP_OFFSET = 10;
|
|
39
31
|
|
|
40
32
|
/**
|
|
41
33
|
* These are the accepted values for the layout prop
|
|
@@ -68,4 +60,4 @@ const CHART_TYPE_LINE = 'line';
|
|
|
68
60
|
const HEIGHT_AUTO_CLASSES = 'gl-chart-h-auto gl-display-flex gl-flex-direction-column gl-h-full';
|
|
69
61
|
const HEIGHT_AUTO_HORIZONTAL_LAYOUT_CLASSES = 'gl-display-flex gl-h-full';
|
|
70
62
|
|
|
71
|
-
export { ANNOTATIONS_COMPONENT_TYPE, ANNOTATIONS_SERIES_NAME,
|
|
63
|
+
export { ANNOTATIONS_COMPONENT_TYPE, ANNOTATIONS_SERIES_NAME, CHART_TYPE_BAR, CHART_TYPE_LINE, HEIGHT_AUTO_CLASSES, HEIGHT_AUTO_HORIZONTAL_LAYOUT_CLASSES, LEGEND_AVERAGE_TEXT, LEGEND_CURRENT_TEXT, LEGEND_LAYOUT_INLINE, LEGEND_LAYOUT_TABLE, LEGEND_MAX_TEXT, LEGEND_MIN_TEXT, TOOLTIP_LEFT_OFFSET, TOOLTIP_TOP_OFFSET, arrowSymbol };
|
|
@@ -2,8 +2,7 @@ import { GRAY_600, GRAY_200, GRAY_50, GRAY_300, GRAY_100, DATA_VIZ_BLUE_200, DAT
|
|
|
2
2
|
import { scrollHandleSvgPath } from '../svgs/svg_paths';
|
|
3
3
|
import { hexToRgba } from '../utils';
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
|
|
5
|
+
const GL_BORDER_RADIUS_BASE = '0.25rem';
|
|
7
6
|
const themeName = 'gitlab';
|
|
8
7
|
const heatmapHues = [GRAY_100, DATA_VIZ_BLUE_200, DATA_VIZ_BLUE_400, DATA_VIZ_BLUE_600, DATA_VIZ_BLUE_800];
|
|
9
8
|
const gaugeNeutralHues = [GRAY_900, GRAY_500];
|
|
@@ -128,7 +127,7 @@ const createTheme = function () {
|
|
|
128
127
|
borderWidth: 0,
|
|
129
128
|
color: GRAY_900,
|
|
130
129
|
textBackgroundColor: WHITE,
|
|
131
|
-
textBorderRadius:
|
|
130
|
+
textBorderRadius: GL_BORDER_RADIUS_BASE,
|
|
132
131
|
textPadding: [8, 12]
|
|
133
132
|
}
|
|
134
133
|
},
|
package/dist/utils/constants.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { POSITION } from '../components/utilities/truncate/constants';
|
|
2
2
|
|
|
3
|
-
const glIconSizes = '8 12 14 16 24 32 48 72';
|
|
4
|
-
|
|
5
3
|
function appendDefaultOption(options) {
|
|
6
4
|
return {
|
|
7
5
|
...options,
|
|
@@ -131,7 +129,7 @@ const datepickerWidthOptionsMap = {
|
|
|
131
129
|
};
|
|
132
130
|
|
|
133
131
|
// size options all have corresponding styles (e.g. .s12 defined in icon.scss)
|
|
134
|
-
const iconSizeOptions =
|
|
132
|
+
const iconSizeOptions = [8, 12, 14, 16, 24, 32, 48, 72];
|
|
135
133
|
const triggerVariantOptions = {
|
|
136
134
|
click: 'click',
|
|
137
135
|
hover: 'hover',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "70.0.0",
|
|
4
4
|
"description": "GitLab UI Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,27 +17,25 @@
|
|
|
17
17
|
"files": [
|
|
18
18
|
"src",
|
|
19
19
|
"dist",
|
|
20
|
-
"scss_to_js",
|
|
21
20
|
"translations.json"
|
|
22
21
|
],
|
|
23
22
|
"scripts": {
|
|
24
23
|
"build": "NODE_ENV=production rollup -c",
|
|
25
|
-
"prebuild": "run-s build-tokens
|
|
26
|
-
"prepare": "run-s build-tokens
|
|
24
|
+
"prebuild": "run-s build-tokens generate-utilities",
|
|
25
|
+
"prepare": "run-s build-tokens generate-utilities",
|
|
27
26
|
"generate-utilities": "make src/scss/utilities.scss",
|
|
28
27
|
"copy-fonts": "make copy-fonts",
|
|
29
|
-
"build-scss-variables": "make scss_to_js/scss_variables.js",
|
|
30
28
|
"build-tokens": "node ./bin/build_tokens.js",
|
|
31
|
-
"clean": "rm -r dist storybook
|
|
29
|
+
"clean": "rm -r dist storybook src/scss/utilities.scss",
|
|
32
30
|
"cy:a11y": "cypress run --browser chrome --env grepTags=@a11y",
|
|
33
31
|
"cy:edge": "cypress run --browser edge --env grepTags=-@a11y",
|
|
34
32
|
"cy:run": "cypress run --browser firefox --env grepTags=-@a11y",
|
|
35
33
|
"start": "yarn storybook",
|
|
36
34
|
"storybook": "yarn storybook-prep && storybook dev --ci --host ${STORYBOOK_HOST:-localhost} --port 9001 -c .storybook",
|
|
37
35
|
"storybook-vue3": "yarn storybook-prep && VUE_VERSION=3 storybook dev --ci --host ${STORYBOOK_HOST:-localhost} --port 9001 -c .storybook",
|
|
38
|
-
"storybook-prep": "run-s copy-fonts build-tokens generate-utilities
|
|
36
|
+
"storybook-prep": "run-s copy-fonts build-tokens generate-utilities",
|
|
39
37
|
"storybook-static": "yarn storybook-prep && storybook build -c .storybook -o storybook",
|
|
40
|
-
"pretest:unit": "yarn build-tokens
|
|
38
|
+
"pretest:unit": "yarn build-tokens",
|
|
41
39
|
"test": "run-s test:unit test:visual",
|
|
42
40
|
"test:integration": "NODE_ENV=test start-server-and-test start http://${STORYBOOK_HOST:-localhost}:9001/iframe.html 'yarn cy:run && yarn cy:a11y'",
|
|
43
41
|
"test:unit": "NODE_ENV=test jest --testPathIgnorePatterns storyshots.spec.js",
|
|
@@ -124,12 +122,12 @@
|
|
|
124
122
|
"babel-loader": "^8.0.5",
|
|
125
123
|
"babel-plugin-require-context-hook": "^1.0.0",
|
|
126
124
|
"bootstrap": "4.6.2",
|
|
127
|
-
"cypress": "13.5.
|
|
125
|
+
"cypress": "13.5.1",
|
|
128
126
|
"cypress-axe": "^1.4.0",
|
|
129
127
|
"cypress-real-events": "^1.11.0",
|
|
130
128
|
"dompurify": "^3.0.0",
|
|
131
129
|
"emoji-regex": "^10.0.0",
|
|
132
|
-
"eslint": "8.
|
|
130
|
+
"eslint": "8.54.0",
|
|
133
131
|
"eslint-import-resolver-jest": "3.0.2",
|
|
134
132
|
"eslint-plugin-cypress": "2.15.1",
|
|
135
133
|
"eslint-plugin-storybook": "0.6.15",
|
|
@@ -136,30 +136,13 @@ describe('area component', () => {
|
|
|
136
136
|
});
|
|
137
137
|
});
|
|
138
138
|
|
|
139
|
-
describe('tooltip
|
|
140
|
-
const dataTooltipTitle = 'FooBar';
|
|
141
|
-
|
|
139
|
+
describe('data tooltip is set', () => {
|
|
142
140
|
beforeEach(() => {
|
|
143
141
|
createShallowWrapper();
|
|
144
142
|
});
|
|
145
143
|
|
|
146
144
|
it('is initialized', () => {
|
|
147
|
-
expect(findDataTooltip().
|
|
148
|
-
expect(findDataTooltip().props('top')).toBe('0');
|
|
149
|
-
expect(findDataTooltip().text()).not.toContain(dataTooltipTitle);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it('is reset when mouse moves', async () => {
|
|
153
|
-
const left = '10px';
|
|
154
|
-
const top = '30px';
|
|
155
|
-
|
|
156
|
-
wrapper.setData({ dataTooltipPosition: { left, top }, dataTooltipTitle });
|
|
157
|
-
|
|
158
|
-
await nextTick();
|
|
159
|
-
|
|
160
|
-
expect(findDataTooltip().props('left')).toBe(`${left}`);
|
|
161
|
-
expect(findDataTooltip().props('top')).toBe(`${top}`);
|
|
162
|
-
expect(findDataTooltip().text()).toContain(dataTooltipTitle);
|
|
145
|
+
expect(findDataTooltip().exists()).toBe(true);
|
|
163
146
|
});
|
|
164
147
|
});
|
|
165
148
|
|
|
@@ -30,8 +30,6 @@ import {
|
|
|
30
30
|
getDefaultTooltipContent,
|
|
31
31
|
} from '../../../utils/charts/config';
|
|
32
32
|
import {
|
|
33
|
-
ANNOTATION_TOOLTIP_TOP_OFFSET,
|
|
34
|
-
DATA_TOOLTIP_LEFT_OFFSET,
|
|
35
33
|
LEGEND_LAYOUT_INLINE,
|
|
36
34
|
LEGEND_LAYOUT_TABLE,
|
|
37
35
|
LEGEND_AVERAGE_TEXT,
|
|
@@ -42,7 +40,6 @@ import {
|
|
|
42
40
|
} from '../../../utils/charts/constants';
|
|
43
41
|
import { colorFromDefaultPalette } from '../../../utils/charts/theme';
|
|
44
42
|
import { seriesHasAnnotations, isDataPointAnnotation } from '../../../utils/charts/utils';
|
|
45
|
-
import { debounceByAnimationFrame } from '../../../utils/utils';
|
|
46
43
|
import TooltipDefaultFormat from '../../shared_components/charts/tooltip_default_format.vue';
|
|
47
44
|
import Chart from '../chart/chart.vue';
|
|
48
45
|
import ChartLegend from '../legend/legend.vue';
|
|
@@ -141,13 +138,8 @@ export default {
|
|
|
141
138
|
// https://gitlab.com/gitlab-org/gitlab-ui/-/issues/618
|
|
142
139
|
return {
|
|
143
140
|
chart: null,
|
|
144
|
-
showDataTooltip: false,
|
|
145
141
|
dataTooltipTitle: '',
|
|
146
142
|
dataTooltipContent: {},
|
|
147
|
-
dataTooltipPosition: {
|
|
148
|
-
left: '0',
|
|
149
|
-
top: '0',
|
|
150
|
-
},
|
|
151
143
|
showAnnotationsTooltip: false,
|
|
152
144
|
annotationsTooltipTitle: '',
|
|
153
145
|
annotationsTooltipContent: '',
|
|
@@ -155,7 +147,6 @@ export default {
|
|
|
155
147
|
left: '0',
|
|
156
148
|
top: '0',
|
|
157
149
|
},
|
|
158
|
-
debouncedShowHideTooltip: debounceByAnimationFrame(this.showHideTooltip),
|
|
159
150
|
selectedFormatTooltipText: this.formatTooltipText || this.defaultFormatTooltipText,
|
|
160
151
|
};
|
|
161
152
|
},
|
|
@@ -269,9 +260,6 @@ export default {
|
|
|
269
260
|
},
|
|
270
261
|
},
|
|
271
262
|
beforeDestroy() {
|
|
272
|
-
this.chart.getZr().off('mousemove', this.debouncedShowHideTooltip);
|
|
273
|
-
this.chart.getZr().off('mouseout', this.debouncedShowHideTooltip);
|
|
274
|
-
|
|
275
263
|
this.chart.off('mouseout', this.hideAnnotationsTooltip);
|
|
276
264
|
this.chart.off('mouseover', this.onChartMouseOver);
|
|
277
265
|
},
|
|
@@ -289,13 +277,6 @@ export default {
|
|
|
289
277
|
};
|
|
290
278
|
},
|
|
291
279
|
onCreated(chart) {
|
|
292
|
-
// These listeners are used to show/hide data tooltips
|
|
293
|
-
// when the mouse is hovered over the parent container
|
|
294
|
-
// of echarts' svg element. This works only for data points
|
|
295
|
-
// and not markPoints.
|
|
296
|
-
chart.getZr().on('mousemove', this.debouncedShowHideTooltip);
|
|
297
|
-
chart.getZr().on('mouseout', this.debouncedShowHideTooltip);
|
|
298
|
-
|
|
299
280
|
// eCharts inbuild mouse events
|
|
300
281
|
// https://echarts.apache.org/en/api.html#events.Mouse%20events
|
|
301
282
|
// is used to attach listeners to markPoints. These listeners
|
|
@@ -305,7 +286,6 @@ export default {
|
|
|
305
286
|
// sections of the charts with their own mouseovers and mouseouts,
|
|
306
287
|
// there shouldn't be an overlapping situation where both tooltips
|
|
307
288
|
// are visible.
|
|
308
|
-
|
|
309
289
|
if (this.hasAnnotations) {
|
|
310
290
|
chart.on('mouseout', this.onChartDataPointMouseOut);
|
|
311
291
|
chart.on('mouseover', this.onChartDataPointMouseOver);
|
|
@@ -314,14 +294,6 @@ export default {
|
|
|
314
294
|
this.chart = chart;
|
|
315
295
|
this.$emit('created', chart);
|
|
316
296
|
},
|
|
317
|
-
showHideTooltip({ event: mouseEvent }) {
|
|
318
|
-
this.showDataTooltip = this.chart.containPixel('grid', [mouseEvent.zrX, mouseEvent.zrY]);
|
|
319
|
-
|
|
320
|
-
this.dataTooltipPosition = {
|
|
321
|
-
left: `${mouseEvent.zrX + DATA_TOOLTIP_LEFT_OFFSET}px`,
|
|
322
|
-
top: `${mouseEvent.zrY}px`,
|
|
323
|
-
};
|
|
324
|
-
},
|
|
325
297
|
onChartDataPointMouseOut() {
|
|
326
298
|
this.showAnnotationsTooltip = false;
|
|
327
299
|
},
|
|
@@ -340,7 +312,7 @@ export default {
|
|
|
340
312
|
this.annotationsTooltipContent = content;
|
|
341
313
|
this.annotationsTooltipPosition = {
|
|
342
314
|
left: `${event.event.zrX}px`,
|
|
343
|
-
top: `${event.event.zrY
|
|
315
|
+
top: `${event.event.zrY}px`,
|
|
344
316
|
};
|
|
345
317
|
}
|
|
346
318
|
},
|
|
@@ -367,9 +339,9 @@ export default {
|
|
|
367
339
|
id="annotationsTooltip"
|
|
368
340
|
ref="annotationsTooltip"
|
|
369
341
|
:show="showAnnotationsTooltip"
|
|
370
|
-
:chart="chart"
|
|
371
342
|
:top="annotationsTooltipPosition.top"
|
|
372
343
|
:left="annotationsTooltipPosition.left"
|
|
344
|
+
:chart="chart"
|
|
373
345
|
placement="bottom"
|
|
374
346
|
>
|
|
375
347
|
<template #title>
|
|
@@ -377,16 +349,7 @@ export default {
|
|
|
377
349
|
</template>
|
|
378
350
|
<div>{{ annotationsTooltipContent }}</div>
|
|
379
351
|
</chart-tooltip>
|
|
380
|
-
<chart-tooltip
|
|
381
|
-
v-if="chart"
|
|
382
|
-
id="dataTooltip"
|
|
383
|
-
ref="dataTooltip"
|
|
384
|
-
class="gl-pointer-events-none"
|
|
385
|
-
:show="showDataTooltip"
|
|
386
|
-
:chart="chart"
|
|
387
|
-
:top="dataTooltipPosition.top"
|
|
388
|
-
:left="dataTooltipPosition.left"
|
|
389
|
-
>
|
|
352
|
+
<chart-tooltip v-if="chart" ref="dataTooltip" :chart="chart">
|
|
390
353
|
<template #title>
|
|
391
354
|
<slot v-if="formatTooltipText" name="tooltip-title"></slot>
|
|
392
355
|
<template v-else>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import merge from 'lodash/merge';
|
|
4
4
|
import truncate from 'lodash/truncate';
|
|
5
5
|
import { grid, dataZoomAdjustments, mergeSeriesToOptions } from '../../../utils/charts/config';
|
|
6
|
-
import {
|
|
6
|
+
import { HEIGHT_AUTO_CLASSES } from '../../../utils/charts/constants';
|
|
7
7
|
import { colorFromDefaultPalette } from '../../../utils/charts/theme';
|
|
8
8
|
import { engineeringNotation } from '../../../utils/number_utils';
|
|
9
9
|
import { hexToRgba, debounceByAnimationFrame } from '../../../utils/utils';
|
|
@@ -182,7 +182,7 @@ export default {
|
|
|
182
182
|
methods: {
|
|
183
183
|
moveShowTooltip({ event: mouseEvent }) {
|
|
184
184
|
this.tooltipPosition = {
|
|
185
|
-
left: `${mouseEvent.zrX
|
|
185
|
+
left: `${mouseEvent.zrX}px`,
|
|
186
186
|
top: `${mouseEvent.zrY}px`,
|
|
187
187
|
};
|
|
188
188
|
this.showTooltip = this.chart.containPixel('grid', [mouseEvent.zrX, mouseEvent.zrY]);
|
|
@@ -12,11 +12,7 @@ import {
|
|
|
12
12
|
generateBarSeries,
|
|
13
13
|
generateLineSeries,
|
|
14
14
|
} from '../../../utils/charts/config';
|
|
15
|
-
import {
|
|
16
|
-
TOOLTIP_LEFT_OFFSET,
|
|
17
|
-
CHART_TYPE_LINE,
|
|
18
|
-
HEIGHT_AUTO_CLASSES,
|
|
19
|
-
} from '../../../utils/charts/constants';
|
|
15
|
+
import { CHART_TYPE_LINE, HEIGHT_AUTO_CLASSES } from '../../../utils/charts/constants';
|
|
20
16
|
import { colorFromDefaultPalette } from '../../../utils/charts/theme';
|
|
21
17
|
import { columnOptions } from '../../../utils/constants';
|
|
22
18
|
import { debounceByAnimationFrame } from '../../../utils/utils';
|
|
@@ -192,7 +188,7 @@ export default {
|
|
|
192
188
|
methods: {
|
|
193
189
|
moveShowTooltip(mouseEvent) {
|
|
194
190
|
this.tooltipPosition = {
|
|
195
|
-
left: `${mouseEvent.zrX
|
|
191
|
+
left: `${mouseEvent.zrX}px`,
|
|
196
192
|
top: `${mouseEvent.zrY}px`,
|
|
197
193
|
};
|
|
198
194
|
this.showTooltip = this.chart.containPixel('grid', [mouseEvent.zrX, mouseEvent.zrY]);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { shallowMount } from '@vue/test-utils';
|
|
2
2
|
|
|
3
|
-
import { TOOLTIP_LEFT_OFFSET } from '~/utils/charts/constants';
|
|
4
3
|
import { createMockChartInstance } from '~helpers/chart_stubs';
|
|
5
4
|
import { expectHeightAutoClasses } from '~helpers/chart_height';
|
|
6
5
|
import Chart from '../chart/chart.vue';
|
|
@@ -71,7 +70,7 @@ describe('heatmap component', () => {
|
|
|
71
70
|
return wrapper.vm.$nextTick(() => {
|
|
72
71
|
expect(mockChartInstance.convertToPixel).toHaveBeenCalledWith({ seriesId }, value);
|
|
73
72
|
|
|
74
|
-
expect(findChartTooltip().props('left')).toBe(`${pixel[0]
|
|
73
|
+
expect(findChartTooltip().props('left')).toBe(`${pixel[0]}px`);
|
|
75
74
|
expect(findChartTooltip().props('top')).toBe(`${pixel[1]}px`);
|
|
76
75
|
});
|
|
77
76
|
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import merge from 'lodash/merge';
|
|
4
4
|
import { WHITE, GRAY_100 } from '../../../../dist/tokens/js/tokens';
|
|
5
5
|
import { getDefaultTooltipContent } from '../../../utils/charts/config';
|
|
6
|
-
import {
|
|
6
|
+
import { HEIGHT_AUTO_CLASSES } from '../../../utils/charts/constants';
|
|
7
7
|
import { heatmapHues } from '../../../utils/charts/theme';
|
|
8
8
|
import { engineeringNotation } from '../../../utils/number_utils';
|
|
9
9
|
import { debounceByAnimationFrame } from '../../../utils/utils';
|
|
@@ -255,7 +255,7 @@ export default {
|
|
|
255
255
|
|
|
256
256
|
this.tooltip = {
|
|
257
257
|
...this.tooltip,
|
|
258
|
-
left: `${left
|
|
258
|
+
left: `${left}px`,
|
|
259
259
|
top: `${top}px`,
|
|
260
260
|
};
|
|
261
261
|
}
|
|
@@ -33,8 +33,6 @@ import {
|
|
|
33
33
|
getDefaultTooltipContent,
|
|
34
34
|
} from '../../../utils/charts/config';
|
|
35
35
|
import {
|
|
36
|
-
ANNOTATION_TOOLTIP_TOP_OFFSET,
|
|
37
|
-
DATA_TOOLTIP_LEFT_OFFSET,
|
|
38
36
|
LEGEND_LAYOUT_INLINE,
|
|
39
37
|
LEGEND_LAYOUT_TABLE,
|
|
40
38
|
LEGEND_AVERAGE_TEXT,
|
|
@@ -313,7 +311,7 @@ export default {
|
|
|
313
311
|
this.showDataTooltip = this.chart.containPixel('grid', [mouseEvent.zrX, mouseEvent.zrY]);
|
|
314
312
|
|
|
315
313
|
this.dataTooltipPosition = {
|
|
316
|
-
left: `${mouseEvent.zrX
|
|
314
|
+
left: `${mouseEvent.zrX}px`,
|
|
317
315
|
top: `${mouseEvent.zrY}px`,
|
|
318
316
|
};
|
|
319
317
|
},
|
|
@@ -335,7 +333,7 @@ export default {
|
|
|
335
333
|
this.annotationsTooltipContent = content;
|
|
336
334
|
this.annotationsTooltipPosition = {
|
|
337
335
|
left: `${event.event.zrX}px`,
|
|
338
|
-
top: `${event.event.zrY
|
|
336
|
+
top: `${event.event.zrY}px`,
|
|
339
337
|
};
|
|
340
338
|
}
|
|
341
339
|
},
|
|
@@ -128,25 +128,25 @@ describe('sparkline chart component', () => {
|
|
|
128
128
|
});
|
|
129
129
|
|
|
130
130
|
it('shows the tooltip when mousing over an axis point in the component', async () => {
|
|
131
|
-
expect(getTooltip().
|
|
131
|
+
expect(getTooltip().props('show')).toBe(false);
|
|
132
132
|
|
|
133
133
|
const mockData = { seriesData: [{ data: [5, 8] }] };
|
|
134
134
|
getXAxisLabelFormatter()(mockData);
|
|
135
135
|
|
|
136
136
|
await wrapper.vm.$nextTick();
|
|
137
|
-
expect(getTooltip().
|
|
137
|
+
expect(getTooltip().props('show')).toBe(true);
|
|
138
138
|
});
|
|
139
139
|
|
|
140
140
|
it('hides the tooltip when the mouse leaves the component', async () => {
|
|
141
141
|
wrapper.setData({ tooltip: { show: true } });
|
|
142
142
|
await wrapper.vm.$nextTick();
|
|
143
143
|
|
|
144
|
-
expect(getTooltip().
|
|
144
|
+
expect(getTooltip().props('show')).toBe(true);
|
|
145
145
|
|
|
146
146
|
wrapper.trigger('mouseleave');
|
|
147
147
|
await wrapper.vm.$nextTick();
|
|
148
148
|
|
|
149
|
-
expect(getTooltip().
|
|
149
|
+
expect(getTooltip().props('show')).toBe(false);
|
|
150
150
|
});
|
|
151
151
|
|
|
152
152
|
it.each`
|
|
@@ -156,13 +156,13 @@ describe('sparkline chart component', () => {
|
|
|
156
156
|
${undefined} | ${0}
|
|
157
157
|
${-10} | ${undefined}
|
|
158
158
|
`(`hides the tooltip when seriesData = ($label, $content)`, async ({ label, content }) => {
|
|
159
|
-
expect(getTooltip().
|
|
159
|
+
expect(getTooltip().props('show')).toBe(false);
|
|
160
160
|
|
|
161
161
|
const mockData = { seriesData: [{ data: [label, content] }] };
|
|
162
162
|
getXAxisLabelFormatter()(mockData);
|
|
163
163
|
|
|
164
164
|
await wrapper.vm.$nextTick();
|
|
165
|
-
expect(getTooltip().
|
|
165
|
+
expect(getTooltip().props('show')).toBe(false);
|
|
166
166
|
});
|
|
167
167
|
|
|
168
168
|
it('adds the right content to the tooltip', async () => {
|
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
LEGEND_MIN_TEXT,
|
|
19
19
|
LEGEND_MAX_TEXT,
|
|
20
20
|
CHART_TYPE_LINE,
|
|
21
|
-
ANNOTATION_TOOLTIP_TOP_OFFSET,
|
|
22
21
|
HEIGHT_AUTO_CLASSES,
|
|
23
22
|
} from '../../../utils/charts/constants';
|
|
24
23
|
import { colorFromDefaultPalette } from '../../../utils/charts/theme';
|
|
@@ -271,7 +270,7 @@ export default {
|
|
|
271
270
|
moveShowTooltip({ event: mouseEvent }) {
|
|
272
271
|
this.tooltipPosition = {
|
|
273
272
|
left: `${mouseEvent.zrX}px`,
|
|
274
|
-
top: `${mouseEvent.zrY
|
|
273
|
+
top: `${mouseEvent.zrY}px`,
|
|
275
274
|
};
|
|
276
275
|
this.showTooltip = this.chart.containPixel('grid', [mouseEvent.zrX, mouseEvent.zrY]);
|
|
277
276
|
},
|
|
@@ -2,6 +2,8 @@ import { shallowMount } from '@vue/test-utils';
|
|
|
2
2
|
import { createMockChartInstance } from '~helpers/chart_stubs';
|
|
3
3
|
import GlPopover from '../../base/popover/popover.vue';
|
|
4
4
|
import { popoverPlacements } from '../../../utils/constants';
|
|
5
|
+
import { waitForAnimationFrame } from '../../../utils/test_utils';
|
|
6
|
+
|
|
5
7
|
import ChartTooltip from './tooltip.vue';
|
|
6
8
|
|
|
7
9
|
let mockChartInstance;
|
|
@@ -12,31 +14,176 @@ jest.mock('echarts', () => ({
|
|
|
12
14
|
|
|
13
15
|
describe('ChartTooltip', () => {
|
|
14
16
|
let wrapper;
|
|
17
|
+
let mockContainPixel;
|
|
18
|
+
|
|
19
|
+
const findPopover = () => wrapper.findComponent(GlPopover);
|
|
20
|
+
const findPopoverTarget = () => wrapper.find(`#${findPopover().attributes('target')}`);
|
|
21
|
+
const getPopoverTargetStyle = (name) => findPopoverTarget().element.style.getPropertyValue(name);
|
|
15
22
|
|
|
16
|
-
const
|
|
23
|
+
const getMouseHandler = () => mockChartInstance.getZr().on.mock.calls[0][1];
|
|
24
|
+
const triggerMouseHandler = async (event) => {
|
|
25
|
+
getMouseHandler()({ event });
|
|
26
|
+
await waitForAnimationFrame();
|
|
27
|
+
};
|
|
17
28
|
|
|
18
|
-
const createWrapper = (props = {}) => {
|
|
19
|
-
mockChartInstance =
|
|
29
|
+
const createWrapper = (props = {}, ...options) => {
|
|
30
|
+
mockChartInstance = {
|
|
31
|
+
...createMockChartInstance(),
|
|
32
|
+
containPixel: mockContainPixel,
|
|
33
|
+
};
|
|
20
34
|
wrapper = shallowMount(ChartTooltip, {
|
|
21
35
|
propsData: {
|
|
22
36
|
chart: mockChartInstance,
|
|
23
37
|
...props,
|
|
24
38
|
},
|
|
39
|
+
...options,
|
|
25
40
|
});
|
|
26
41
|
};
|
|
27
42
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
43
|
+
beforeEach(() => {
|
|
44
|
+
mockContainPixel = jest.fn();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('sets target as container instead of a trigger', () => {
|
|
48
|
+
createWrapper();
|
|
49
|
+
|
|
50
|
+
expect(findPopover().props('triggers')).toBe('');
|
|
51
|
+
expect(findPopover().props('container')).toEqual(findPopover().props('target'));
|
|
52
|
+
|
|
53
|
+
expect(findPopoverTarget().exists()).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('is right-positioned by default', () => {
|
|
57
|
+
createWrapper();
|
|
58
|
+
|
|
59
|
+
expect(findPopover().props('placement')).toBe(popoverPlacements.right);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('applies placement if any', () => {
|
|
63
|
+
createWrapper({ placement: popoverPlacements.bottom });
|
|
64
|
+
|
|
65
|
+
expect(findPopover().props('placement')).toBe(popoverPlacements.bottom);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('applies initial position and updates it', async () => {
|
|
69
|
+
createWrapper({ show: true, left: '0', top: '50%' });
|
|
70
|
+
|
|
71
|
+
expect(findPopover().attributes('show')).toBe('true');
|
|
72
|
+
expect(getPopoverTargetStyle('left')).toBe('0px');
|
|
73
|
+
expect(getPopoverTargetStyle('top')).toBe('50%');
|
|
74
|
+
|
|
75
|
+
wrapper.setProps({ left: '100px', top: '200px' });
|
|
76
|
+
|
|
77
|
+
await waitForAnimationFrame();
|
|
78
|
+
|
|
79
|
+
expect(findPopover().attributes('show')).toBe('true');
|
|
80
|
+
expect(getPopoverTargetStyle('left')).toBe('100px');
|
|
81
|
+
expect(getPopoverTargetStyle('top')).toBe('200px');
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('reacts to `mousemove` and `mouseout` in chart dom', () => {
|
|
85
|
+
createWrapper();
|
|
86
|
+
|
|
87
|
+
const zr = mockChartInstance.getZr();
|
|
88
|
+
const handler = getMouseHandler();
|
|
89
|
+
|
|
90
|
+
expect(zr.on).toHaveBeenCalledWith('mousemove', handler);
|
|
91
|
+
expect(zr.on).toHaveBeenCalledWith('mouseout', handler);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('tooltip target has default offset', () => {
|
|
95
|
+
createWrapper();
|
|
96
|
+
|
|
97
|
+
expect(getPopoverTargetStyle('margin-top')).toBe('-10px');
|
|
98
|
+
expect(getPopoverTargetStyle('height')).toBe('20px');
|
|
31
99
|
|
|
32
|
-
|
|
100
|
+
expect(getPopoverTargetStyle('margin-left')).toBe('-2px');
|
|
101
|
+
expect(getPopoverTargetStyle('width')).toBe('4px');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('tooltip target defines offsets', () => {
|
|
105
|
+
const xOffset = 7;
|
|
106
|
+
const yOffset = 12;
|
|
107
|
+
|
|
108
|
+
createWrapper({
|
|
109
|
+
xOffset,
|
|
110
|
+
yOffset,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
expect(getPopoverTargetStyle('margin-top')).toBe('-12px');
|
|
114
|
+
expect(getPopoverTargetStyle('height')).toBe('24px');
|
|
115
|
+
|
|
116
|
+
expect(getPopoverTargetStyle('margin-left')).toBe('-7px');
|
|
117
|
+
expect(getPopoverTargetStyle('width')).toBe('14px');
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe('when setting a `show` value', () => {
|
|
121
|
+
it('applies initial `show` value and updates it', async () => {
|
|
122
|
+
createWrapper({ show: true });
|
|
123
|
+
|
|
124
|
+
expect(findPopover().attributes('show')).toBe('true');
|
|
125
|
+
|
|
126
|
+
wrapper.setProps({ show: false });
|
|
127
|
+
await waitForAnimationFrame();
|
|
128
|
+
|
|
129
|
+
expect(findPopover().attributes('show')).toBe(undefined);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe('when not setting a `show` value', () => {
|
|
134
|
+
describe('with no position defined', () => {
|
|
135
|
+
beforeEach(() => {
|
|
136
|
+
createWrapper();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('when mouse moves outside of chart', async () => {
|
|
140
|
+
mockContainPixel.mockReturnValueOnce(false);
|
|
141
|
+
|
|
142
|
+
await triggerMouseHandler({ zrX: 1, zrY: 2.3 });
|
|
143
|
+
|
|
144
|
+
expect(mockContainPixel).toHaveBeenCalledWith('grid', [1, 2]);
|
|
145
|
+
|
|
146
|
+
expect(findPopover().attributes('show')).toBe(undefined);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('when mouse moves inside chart', async () => {
|
|
150
|
+
mockContainPixel.mockReturnValueOnce(true);
|
|
151
|
+
|
|
152
|
+
await triggerMouseHandler({ zrX: 3, zrY: 4.3 });
|
|
153
|
+
|
|
154
|
+
expect(mockContainPixel).toHaveBeenCalledWith('grid', [3, 4]);
|
|
155
|
+
|
|
156
|
+
expect(findPopover().attributes('show')).toBe('true');
|
|
157
|
+
expect(getPopoverTargetStyle('left')).toBe('3px');
|
|
158
|
+
expect(getPopoverTargetStyle('top')).toBe('4px');
|
|
159
|
+
});
|
|
33
160
|
});
|
|
34
161
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
162
|
+
describe('with position defined', () => {
|
|
163
|
+
beforeEach(() => {
|
|
164
|
+
createWrapper({ right: '50px', bottom: '100px' });
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('when mouse moves outside of chart', async () => {
|
|
168
|
+
mockContainPixel.mockReturnValueOnce(false);
|
|
169
|
+
await triggerMouseHandler({ zrX: 1, zrY: 2.3 });
|
|
170
|
+
|
|
171
|
+
expect(mockContainPixel).toHaveBeenCalledWith('grid', [1, 2]);
|
|
172
|
+
expect(findPopover().attributes('show')).toBe(undefined);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('when mouse moves inside chart', async () => {
|
|
176
|
+
mockContainPixel.mockReturnValueOnce(true);
|
|
177
|
+
await triggerMouseHandler({ zrX: 3, zrY: 4.3 });
|
|
178
|
+
|
|
179
|
+
expect(mockContainPixel).toHaveBeenCalledWith('grid', [3, 4]);
|
|
180
|
+
expect(findPopover().attributes('show')).toBe('true');
|
|
38
181
|
|
|
39
|
-
|
|
182
|
+
expect(getPopoverTargetStyle('left')).toBe('');
|
|
183
|
+
expect(getPopoverTargetStyle('top')).toBe('');
|
|
184
|
+
expect(getPopoverTargetStyle('right')).toBe('50px');
|
|
185
|
+
expect(getPopoverTargetStyle('bottom')).toBe('100px');
|
|
186
|
+
});
|
|
40
187
|
});
|
|
41
188
|
});
|
|
42
189
|
});
|