@gitlab/ui 32.32.0 → 32.35.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/components/base/filtered_search/filtered_search_suggestion_list.js +7 -2
  3. package/dist/components/charts/area/area.js +3 -0
  4. package/dist/components/charts/bar/bar.js +2 -2
  5. package/dist/components/charts/chart/chart.js +20 -21
  6. package/dist/components/charts/legend/legend.js +1 -1
  7. package/dist/components/charts/tooltip/tooltip.js +1 -1
  8. package/dist/components/utilities/truncate/truncate.documentation.js +3 -0
  9. package/dist/components/utilities/truncate/truncate.js +34 -2
  10. package/dist/directives/resize_observer/resize_observer.documentation.js +1 -1
  11. package/dist/directives/resize_observer/resize_observer.js +43 -23
  12. package/dist/utility_classes.css +1 -1
  13. package/dist/utility_classes.css.map +1 -1
  14. package/dist/utils/charts/config.js +4 -3
  15. package/dist/utils/charts/mock_data.js +6 -3
  16. package/dist/utils/charts/theme.js +15 -9
  17. package/package.json +3 -3
  18. package/src/components/base/filtered_search/filtered_search_suggestion_list.spec.js +15 -8
  19. package/src/components/base/filtered_search/filtered_search_suggestion_list.vue +11 -2
  20. package/src/components/charts/area/area.vue +3 -0
  21. package/src/components/charts/bar/__snapshots__/bar.spec.js.snap +2 -2
  22. package/src/components/charts/bar/bar.vue +2 -2
  23. package/src/components/charts/chart/chart.spec.js +3 -1
  24. package/src/components/charts/chart/chart.vue +22 -20
  25. package/src/components/charts/column/__snapshots__/column_chart.spec.js.snap +6 -6
  26. package/src/components/charts/legend/legend.vue +1 -1
  27. package/src/components/charts/stacked_column/__snapshots__/stacked_column.spec.js.snap +26 -26
  28. package/src/components/charts/tooltip/tooltip.vue +1 -1
  29. package/src/components/utilities/truncate/truncate.documentation.js +3 -0
  30. package/src/components/utilities/truncate/truncate.spec.js +8 -0
  31. package/src/components/utilities/truncate/truncate.stories.js +6 -2
  32. package/src/components/utilities/truncate/truncate.vue +57 -7
  33. package/src/directives/resize_observer/resize_observer.js +34 -19
  34. package/src/directives/resize_observer/resize_observer.md +20 -0
  35. package/src/directives/resize_observer/resize_observer.spec.js +33 -1
  36. package/src/scss/utilities.scss +12 -0
  37. package/src/scss/utility-mixins/sizing.scss +6 -0
  38. package/src/utils/charts/config.js +3 -2
  39. package/src/utils/charts/mock_data.js +5 -2
  40. package/src/utils/charts/theme.js +14 -9
@@ -1,7 +1,14 @@
1
1
  <script>
2
+ import { GlTooltipDirective } from '../../../directives/tooltip';
3
+ import { GlResizeObserverDirective } from '../../../directives/resize_observer/resize_observer';
2
4
  import { POSITION } from './constants';
3
5
 
4
6
  export default {
7
+ POSITION,
8
+ directives: {
9
+ GlTooltip: GlTooltipDirective,
10
+ GlResizeObserver: GlResizeObserverDirective,
11
+ },
5
12
  props: {
6
13
  text: {
7
14
  type: String,
@@ -13,10 +20,15 @@ export default {
13
20
  default: POSITION.END,
14
21
  validator: (value) => Object.values(POSITION).includes(value),
15
22
  },
23
+ withTooltip: {
24
+ type: Boolean,
25
+ required: false,
26
+ default: false,
27
+ },
16
28
  },
17
29
  data() {
18
30
  return {
19
- POSITION,
31
+ isTruncated: false,
20
32
  };
21
33
  },
22
34
  computed: {
@@ -30,24 +42,62 @@ export default {
30
42
  last() {
31
43
  return this.text.slice(this.middleIndex);
32
44
  },
45
+ isTooltipDisabled() {
46
+ return !this.withTooltip || !this.isTruncated;
47
+ },
48
+ },
49
+ watch: {
50
+ withTooltip(withTooltip) {
51
+ if (withTooltip) {
52
+ this.checkTruncationState();
53
+ }
54
+ },
55
+ },
56
+ methods: {
57
+ checkTruncationState() {
58
+ if (this.withTooltip) {
59
+ this.isTruncated = this.$refs.text.scrollWidth > this.$refs.text.offsetWidth;
60
+ }
61
+ },
33
62
  },
34
63
  };
35
64
  </script>
36
65
 
37
66
  <template>
38
67
  <!-- START -->
39
- <span v-if="position === POSITION.START" class="gl-truncate" :title="text">
40
- <span class="gl-truncate-start gl-text-overflow-ellipsis!">&lrm;{{ text }}&lrm;</span>
68
+ <span
69
+ v-if="position === $options.POSITION.START"
70
+ v-gl-tooltip="{ disabled: isTooltipDisabled }"
71
+ v-gl-resize-observer:[withTooltip]="checkTruncationState"
72
+ class="gl-truncate"
73
+ :title="text"
74
+ >
75
+ <span ref="text" class="gl-truncate-start gl-text-overflow-ellipsis!"
76
+ >&lrm;{{ text }}&lrm;</span
77
+ >
41
78
  </span>
42
79
 
43
80
  <!-- MIDDLE -->
44
- <span v-else-if="position === POSITION.MIDDLE" class="gl-truncate" :title="text">
45
- <span class="gl-truncate-end">{{ first }}</span
81
+ <span
82
+ v-else-if="position === $options.POSITION.MIDDLE"
83
+ v-gl-tooltip="{ disabled: isTooltipDisabled }"
84
+ v-gl-resize-observer:[withTooltip]="checkTruncationState"
85
+ class="gl-truncate"
86
+ :title="text"
87
+ >
88
+ <span ref="text" class="gl-truncate-end">{{ first }}</span
46
89
  ><span class="gl-truncate-start">&lrm;{{ last }}&lrm;</span>
47
90
  </span>
48
91
 
49
92
  <!-- END -->
50
- <span v-else class="gl-truncate" :title="text">
51
- <span class="gl-truncate-end">{{ text }}</span>
93
+ <span
94
+ v-else
95
+ v-gl-tooltip="{ disabled: isTooltipDisabled }"
96
+ v-gl-resize-observer:[withTooltip]="checkTruncationState"
97
+ class="gl-truncate"
98
+ data-testid="truncate-end-container"
99
+ :title="text"
100
+ >
101
+ <span ref="text" class="gl-truncate-end">{{ text }}</span>
52
102
  </span>
53
103
  </template>
@@ -2,29 +2,44 @@ import isFunction from 'lodash/isFunction';
2
2
 
3
3
  let observer = null;
4
4
 
5
- export const GlResizeObserverDirective = {
6
- bind(el, { value: resizeHandler }) {
7
- if (!isFunction(resizeHandler)) {
8
- throw TypeError('directive value must be a function');
9
- }
5
+ const attachObserver = (el, resizeHandler) => {
6
+ if (!isFunction(resizeHandler)) {
7
+ throw TypeError('directive value must be a function');
8
+ }
10
9
 
11
- if (!observer) {
12
- // the observer instance is shared for performance reasons
13
- // more information: https://github.com/WICG/ResizeObserver/issues/59
14
- observer = new ResizeObserver((entries) => {
15
- entries.forEach((event) => {
16
- event.target.glResizeHandler(event);
17
- });
10
+ if (!observer) {
11
+ // the observer instance is shared for performance reasons
12
+ // more information: https://github.com/WICG/ResizeObserver/issues/59
13
+ observer = new ResizeObserver((entries) => {
14
+ entries.forEach((event) => {
15
+ event.target.glResizeHandler(event);
18
16
  });
19
- }
17
+ });
18
+ }
19
+
20
+ el.glResizeHandler = resizeHandler;
21
+ observer.observe(el);
22
+ };
20
23
 
21
- el.glResizeHandler = resizeHandler;
22
- observer.observe(el);
24
+ const detachObserver = (el) => {
25
+ if (el.glResizeHandler) {
26
+ delete el.glResizeHandler;
27
+ observer?.unobserve(el);
28
+ }
29
+ };
30
+
31
+ export const GlResizeObserverDirective = {
32
+ bind(el, { value: resizeHandler, arg: enabled = true }) {
33
+ if (enabled) {
34
+ attachObserver(el, resizeHandler);
35
+ }
23
36
  },
24
- unbind(el) {
25
- if (el.glResizeHandler) {
26
- delete el.glResizeHandler;
27
- observer?.unobserve(el);
37
+ update(el, { value: resizeHandler, arg: enabled = true }) {
38
+ if (enabled) {
39
+ attachObserver(el, resizeHandler);
40
+ } else {
41
+ detachObserver(el);
28
42
  }
29
43
  },
44
+ unbind: detachObserver,
30
45
  };
@@ -38,3 +38,23 @@ export default {
38
38
  </div>
39
39
  </template>
40
40
  ```
41
+
42
+ The observer can be toggled on or off by passing a boolean argument to the directive:
43
+
44
+ ```html
45
+ <script>
46
+ export default {
47
+ data() {
48
+ return {
49
+ shouldObserve: true,
50
+ };
51
+ },
52
+ methods: {
53
+ handleResize() {},
54
+ },
55
+ };
56
+ </script>
57
+ <template>
58
+ <div v-gl-resize-observer-directive[shouldObserve]="handleResize"></div>
59
+ </template>
60
+ ```
@@ -10,7 +10,7 @@ describe('resize observer directive', () => {
10
10
  const localVue = createLocalVue();
11
11
  let wrapper;
12
12
 
13
- const createComponent = ({ template } = {}) => {
13
+ const createComponent = ({ template, data = {} } = {}) => {
14
14
  const defaultTemplate = `<div v-resize-observer="handleResize"></div>`;
15
15
 
16
16
  const component = {
@@ -21,6 +21,9 @@ describe('resize observer directive', () => {
21
21
  handleResize: mockHandleResize,
22
22
  },
23
23
  template: template || defaultTemplate,
24
+ data() {
25
+ return data;
26
+ },
24
27
  };
25
28
 
26
29
  wrapper = shallowMount(component, { localVue });
@@ -52,6 +55,13 @@ describe('resize observer directive', () => {
52
55
  expect(observesElement(wrapper.element)).toBe(true);
53
56
  });
54
57
 
58
+ it('does not subscribe if the argument is false', () => {
59
+ createComponent({ template: '<div v-resize-observer:[false]="handleResize"></div>' });
60
+
61
+ expect(observersCount()).toBe(0);
62
+ expect(observesElement(wrapper.element)).toBe(false);
63
+ });
64
+
55
65
  it('passes the first entries "contentRect" and "target" to the given handler', () => {
56
66
  createComponent();
57
67
 
@@ -61,6 +71,28 @@ describe('resize observer directive', () => {
61
71
  expect(mockHandleResize).toHaveBeenCalledWith({ contentRect: {}, target: wrapper.element });
62
72
  });
63
73
 
74
+ it("detaches then reattaches observer based on argument's value", async () => {
75
+ expect(observersCount()).toBe(0);
76
+
77
+ createComponent({
78
+ template: '<div v-resize-observer:[isEnabled]="handleResize"></div>',
79
+ data: {
80
+ isEnabled: true,
81
+ },
82
+ });
83
+
84
+ expect(observersCount()).toBe(1);
85
+ expect(wrapper.element.glResizeHandler).not.toBeFalsy();
86
+
87
+ await wrapper.setData({ isEnabled: false });
88
+
89
+ expect(wrapper.element.glResizeHandler).toBeFalsy();
90
+
91
+ await wrapper.setData({ isEnabled: true });
92
+
93
+ expect(wrapper.element.glResizeHandler).not.toBeFalsy();
94
+ });
95
+
64
96
  it('does a clean up when the component is destroyed', () => {
65
97
  createComponent();
66
98
 
@@ -4201,6 +4201,18 @@
4201
4201
  }
4202
4202
  }
4203
4203
 
4204
+ .gl-lg-w-1px {
4205
+ @media (min-width: $breakpoint-lg) {
4206
+ width: 1px;
4207
+ }
4208
+ }
4209
+
4210
+ .gl-lg-w-1px\! {
4211
+ @media (min-width: $breakpoint-lg) {
4212
+ width: 1px !important;
4213
+ }
4214
+ }
4215
+
4204
4216
  .gl-md-w-50p {
4205
4217
  @include gl-media-breakpoint-up(md) {
4206
4218
  width: 50%;
@@ -212,6 +212,12 @@
212
212
  }
213
213
  }
214
214
 
215
+ @mixin gl-lg-w-1px {
216
+ @media (min-width: $breakpoint-lg) {
217
+ width: 1px;
218
+ }
219
+ }
220
+
215
221
  @mixin gl-md-w-50p {
216
222
  @include gl-media-breakpoint-up(md) {
217
223
  width: 50%;
@@ -12,6 +12,7 @@ import { ANNOTATIONS_SERIES_NAME, arrowSymbol, CHART_TYPE_BAR, CHART_TYPE_LINE }
12
12
  export const defaultAreaOpacity = 0.2;
13
13
  export const defaultFontSize = 12;
14
14
  export const defaultHeight = 400;
15
+ export const defaultWidth = 300;
15
16
  export const validRenderers = ['canvas', 'svg'];
16
17
 
17
18
  export const axes = {
@@ -433,8 +434,8 @@ export const generateBarSeries = ({
433
434
  yAxisIndex,
434
435
  itemStyle: {
435
436
  color: hexToRgba(color, 0.2),
436
- barBorderColor: color,
437
- barBorderWidth: 1,
437
+ borderColor: color,
438
+ borderWidth: 1,
438
439
  },
439
440
  emphasis: {
440
441
  itemStyle: {
@@ -43,6 +43,9 @@ export const mockDefaultChartOptions = {
43
43
  axisPointer: {
44
44
  show: true,
45
45
  label: {},
46
+ lineStyle: {
47
+ type: 'solid',
48
+ },
46
49
  },
47
50
  },
48
51
  yAxis: {
@@ -204,8 +207,8 @@ export const mockDefaultBarChartConfig = {
204
207
  yAxisIndex: 0,
205
208
  itemStyle: {
206
209
  color: hexToRgba(color, 0.2),
207
- barBorderColor: color,
208
- barBorderWidth: 1,
210
+ borderColor: color,
211
+ borderWidth: 1,
209
212
  },
210
213
  emphasis: {
211
214
  itemStyle: {
@@ -105,15 +105,14 @@ const axes = {
105
105
  margin: 8,
106
106
  show: true,
107
107
  color: gray600,
108
- textStyle: {
109
- color: gray600,
110
- },
108
+ hideOverlap: true,
111
109
  },
112
110
  axisLine: {
113
111
  show: false,
114
112
  },
115
113
  axisPointer: {
116
114
  lineStyle: {
115
+ type: 'solid',
117
116
  color: gray600,
118
117
  },
119
118
  label: {
@@ -175,6 +174,7 @@ const createTheme = (options = {}) => ({
175
174
  dataZoom: {
176
175
  borderColor: 'transparent',
177
176
  filterMode: 'none',
177
+ brushSelect: false,
178
178
  dataBackground: {
179
179
  lineStyle: {
180
180
  width: 2,
@@ -184,7 +184,7 @@ const createTheme = (options = {}) => ({
184
184
  // render unfilled zoom-graph if the series is a line chart without area styles
185
185
  // more details: https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2364#note_666637306
186
186
  areaStyle: isLineChartWithoutArea(options)
187
- ? null
187
+ ? {} // Use empty object instead of null, see https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2185#note_707711029 for more context
188
188
  : {
189
189
  color: gray50,
190
190
  opacity: 1,
@@ -192,7 +192,10 @@ const createTheme = (options = {}) => ({
192
192
  },
193
193
  fillerColor: hexToRgba(gray200, 0.23),
194
194
  handleIcon: scrollHandleSvgPath,
195
- handleColor: gray500,
195
+ handleStyle: {
196
+ borderColor: 'transparent',
197
+ color: gray500,
198
+ },
196
199
  handleSize: '50%',
197
200
  labelFormatter: () => null,
198
201
  textStyle: {
@@ -203,14 +206,16 @@ const createTheme = (options = {}) => ({
203
206
  top: '-5',
204
207
  left: 'center',
205
208
  itemSize: 14,
206
- iconStyle: {
207
- color: gray200,
208
- borderWidth: 0,
209
- emphasis: {
209
+ emphasis: {
210
+ iconStyle: {
210
211
  borderWidth: 0,
211
212
  color: gray700,
212
213
  },
213
214
  },
215
+ iconStyle: {
216
+ color: gray200,
217
+ borderWidth: 0,
218
+ },
214
219
  itemGap: 8,
215
220
  feature: {
216
221
  dataZoom: {