@gitlab/ui 64.6.0 → 64.6.2

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 CHANGED
@@ -1,3 +1,17 @@
1
+ ## [64.6.2](https://gitlab.com/gitlab-org/gitlab-ui/compare/v64.6.1...v64.6.2) (2023-06-13)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **dropdowns:** fix ResizeObserver loop error ([a4797a5](https://gitlab.com/gitlab-org/gitlab-ui/commit/a4797a5624505d6d4aa2d539fd589bbd2b610aee))
7
+
8
+ ## [64.6.1](https://gitlab.com/gitlab-org/gitlab-ui/compare/v64.6.0...v64.6.1) (2023-06-08)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **GlChart:** ResizeObserver loop limit exceeded on responsive charts ([7952ae8](https://gitlab.com/gitlab-org/gitlab-ui/commit/7952ae86a22e200ff2bc4f9f8cf172de8e30b6f2))
14
+
1
15
  # [64.6.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v64.5.0...v64.6.0) (2023-06-08)
2
16
 
3
17
 
@@ -137,6 +137,7 @@ var script = {
137
137
  },
138
138
  data() {
139
139
  return {
140
+ openedYet: false,
140
141
  visible: false,
141
142
  baseDropdownId: uniqueId('base-dropdown-')
142
143
  };
@@ -207,8 +208,8 @@ var script = {
207
208
  return {
208
209
  'gl-display-block!': this.visible,
209
210
  [FIXED_WIDTH_CLASS]: !this.fluidWidth,
210
- 'gl-fixed': this.isFixed,
211
- 'gl-absolute': !this.isFixed
211
+ 'gl-fixed': this.openedYet && this.isFixed,
212
+ 'gl-absolute': this.openedYet && !this.isFixed
212
213
  };
213
214
  },
214
215
  isFixed() {
@@ -271,26 +272,22 @@ var script = {
271
272
  childList: true,
272
273
  subtree: true
273
274
  });
274
- await new Promise(resolve => {
275
- const stopAutoUpdate = autoUpdate(this.toggleElement, this.$refs.content, async () => {
276
- const {
277
- x,
278
- y
279
- } = await computePosition(this.toggleElement, this.$refs.content, this.floatingUIConfig);
275
+ this.stopAutoUpdate = autoUpdate(this.toggleElement, this.$refs.content, async () => {
276
+ const {
277
+ x,
278
+ y
279
+ } = await computePosition(this.toggleElement, this.$refs.content, this.floatingUIConfig);
280
280
 
281
- /**
282
- * Due to the asynchronous nature of computePosition, it's technically possible for the
283
- * component to have been destroyed by the time the promise resolves. In such case, we exit
284
- * early to prevent a TypeError.
285
- */
286
- if (!this.$refs.content) return;
287
- Object.assign(this.$refs.content.style, {
288
- left: `${x}px`,
289
- top: `${y}px`
290
- });
291
- resolve(stopAutoUpdate);
281
+ /**
282
+ * Due to the asynchronous nature of computePosition, it's technically possible for the
283
+ * component to have been destroyed by the time the promise resolves. In such case, we exit
284
+ * early to prevent a TypeError.
285
+ */
286
+ if (!this.$refs.content) return;
287
+ Object.assign(this.$refs.content.style, {
288
+ left: `${x}px`,
289
+ top: `${y}px`
292
290
  });
293
- this.stopAutoUpdate = stopAutoUpdate;
294
291
  });
295
292
  },
296
293
  stopFloating() {
@@ -303,13 +300,13 @@ var script = {
303
300
  if (this.visible) {
304
301
  // The dropdown needs to be actually visible before we compute its position with Floating UI.
305
302
  await this.$nextTick();
306
-
303
+ this.openedYet = true;
307
304
  /**
308
305
  * We wait until the dropdown's position has been computed before emitting the `shown` event.
309
306
  * This ensures that, if the parent component attempts to focus an inner element, the dropdown
310
307
  * is already properly placed in the page. Otherwise, the page would scroll back to the top.
311
308
  */
312
- await this.startFloating();
309
+ this.startFloating();
313
310
  this.$emit(GL_DROPDOWN_SHOWN);
314
311
  } else {
315
312
  this.stopFloating();
@@ -2,6 +2,7 @@ import * as echarts from 'echarts';
2
2
  import { validRenderers, defaultWidth, defaultHeight, toolboxHeight } from '../../../utils/charts/config';
3
3
  import { themeName, createTheme } from '../../../utils/charts/theme';
4
4
  import { GlResizeObserverDirective } from '../../../directives/resize_observer/resize_observer';
5
+ import { debounceByAnimationFrame } from '../../../utils/utils';
5
6
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
6
7
 
7
8
  //
@@ -90,7 +91,8 @@ var script = {
90
91
  },
91
92
  data() {
92
93
  return {
93
- chart: null
94
+ chart: null,
95
+ debouncedHandleResize: debounceByAnimationFrame(this.handleResize)
94
96
  };
95
97
  },
96
98
  computed: {
@@ -169,7 +171,7 @@ var script = {
169
171
  });
170
172
  },
171
173
  handleResize() {
172
- if (this.responsive) this.chart.resize();
174
+ this.chart.resize();
173
175
  }
174
176
  }
175
177
  };
@@ -178,7 +180,7 @@ var script = {
178
180
  const __vue_script__ = script;
179
181
 
180
182
  /* template */
181
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{directives:[{name:"resize-observer",rawName:"v-resize-observer",value:(_vm.handleResize),expression:"handleResize"}],ref:"chart"})};
183
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{directives:[{name:"resize-observer",rawName:"v-resize-observer:[responsive]",value:(_vm.debouncedHandleResize),expression:"debouncedHandleResize",arg:_vm.responsive}],ref:"chart"})};
182
184
  var __vue_staticRenderFns__ = [];
183
185
 
184
186
  /* style */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "64.6.0",
3
+ "version": "64.6.2",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -84,13 +84,13 @@
84
84
  },
85
85
  "devDependencies": {
86
86
  "@arkweid/lefthook": "0.7.7",
87
- "@babel/core": "^7.22.1",
88
- "@babel/preset-env": "^7.22.4",
89
- "@babel/preset-react": "^7.22.3",
87
+ "@babel/core": "^7.22.5",
88
+ "@babel/preset-env": "^7.22.5",
89
+ "@babel/preset-react": "^7.22.5",
90
90
  "@gitlab/eslint-plugin": "19.0.0",
91
91
  "@gitlab/fonts": "^1.2.0",
92
92
  "@gitlab/stylelint-config": "4.1.0",
93
- "@gitlab/svgs": "3.51.0",
93
+ "@gitlab/svgs": "3.53.0",
94
94
  "@rollup/plugin-commonjs": "^11.1.0",
95
95
  "@rollup/plugin-node-resolve": "^7.1.3",
96
96
  "@rollup/plugin-replace": "^2.3.2",
@@ -117,9 +117,9 @@
117
117
  "babel-loader": "^8.0.5",
118
118
  "babel-plugin-require-context-hook": "^1.0.0",
119
119
  "bootstrap": "4.6.2",
120
- "cypress": "12.13.0",
120
+ "cypress": "12.14.0",
121
121
  "emoji-regex": "^10.0.0",
122
- "eslint": "8.41.0",
122
+ "eslint": "8.42.0",
123
123
  "eslint-import-resolver-jest": "3.0.2",
124
124
  "eslint-plugin-cypress": "2.13.3",
125
125
  "eslint-plugin-storybook": "0.6.12",
@@ -163,6 +163,7 @@ describe('base dropdown', () => {
163
163
  buildWrapper();
164
164
 
165
165
  await findDefaultDropdownToggle().trigger('click');
166
+ await nextTick();
166
167
 
167
168
  expect(computePosition).toHaveBeenCalledWith(
168
169
  findDefaultDropdownToggle().element,
@@ -180,6 +181,7 @@ describe('base dropdown', () => {
180
181
  });
181
182
 
182
183
  await findDefaultDropdownToggle().trigger('click');
184
+ await nextTick();
183
185
 
184
186
  expect(computePosition).toHaveBeenCalledWith(
185
187
  findDefaultDropdownToggle().element,
@@ -149,6 +149,7 @@ export default {
149
149
  },
150
150
  data() {
151
151
  return {
152
+ openedYet: false,
152
153
  visible: false,
153
154
  baseDropdownId: uniqueId('base-dropdown-'),
154
155
  };
@@ -221,8 +222,8 @@ export default {
221
222
  return {
222
223
  'gl-display-block!': this.visible,
223
224
  [FIXED_WIDTH_CLASS]: !this.fluidWidth,
224
- 'gl-fixed': this.isFixed,
225
- 'gl-absolute': !this.isFixed,
225
+ 'gl-fixed': this.openedYet && this.isFixed,
226
+ 'gl-absolute': this.openedYet && !this.isFixed,
226
227
  };
227
228
  },
228
229
  isFixed() {
@@ -290,29 +291,24 @@ export default {
290
291
  subtree: true,
291
292
  });
292
293
 
293
- await new Promise((resolve) => {
294
- const stopAutoUpdate = autoUpdate(this.toggleElement, this.$refs.content, async () => {
295
- const { x, y } = await computePosition(
296
- this.toggleElement,
297
- this.$refs.content,
298
- this.floatingUIConfig
299
- );
300
-
301
- /**
302
- * Due to the asynchronous nature of computePosition, it's technically possible for the
303
- * component to have been destroyed by the time the promise resolves. In such case, we exit
304
- * early to prevent a TypeError.
305
- */
306
- if (!this.$refs.content) return;
294
+ this.stopAutoUpdate = autoUpdate(this.toggleElement, this.$refs.content, async () => {
295
+ const { x, y } = await computePosition(
296
+ this.toggleElement,
297
+ this.$refs.content,
298
+ this.floatingUIConfig
299
+ );
307
300
 
308
- Object.assign(this.$refs.content.style, {
309
- left: `${x}px`,
310
- top: `${y}px`,
311
- });
301
+ /**
302
+ * Due to the asynchronous nature of computePosition, it's technically possible for the
303
+ * component to have been destroyed by the time the promise resolves. In such case, we exit
304
+ * early to prevent a TypeError.
305
+ */
306
+ if (!this.$refs.content) return;
312
307
 
313
- resolve(stopAutoUpdate);
308
+ Object.assign(this.$refs.content.style, {
309
+ left: `${x}px`,
310
+ top: `${y}px`,
314
311
  });
315
- this.stopAutoUpdate = stopAutoUpdate;
316
312
  });
317
313
  },
318
314
  stopFloating() {
@@ -325,13 +321,13 @@ export default {
325
321
  if (this.visible) {
326
322
  // The dropdown needs to be actually visible before we compute its position with Floating UI.
327
323
  await this.$nextTick();
328
-
324
+ this.openedYet = true;
329
325
  /**
330
326
  * We wait until the dropdown's position has been computed before emitting the `shown` event.
331
327
  * This ensures that, if the parent component attempts to focus an inner element, the dropdown
332
328
  * is already properly placed in the page. Otherwise, the page would scroll back to the top.
333
329
  */
334
- await this.startFloating();
330
+ this.startFloating();
335
331
 
336
332
  this.$emit(GL_DROPDOWN_SHOWN);
337
333
  } else {
@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
2
2
  import * as echarts from 'echarts';
3
3
  import { toolboxHeight } from '~/utils/charts/config';
4
4
  import { createTheme } from '~/utils/charts/theme';
5
+ import { waitForAnimationFrame } from '~/utils/test_utils';
5
6
  import { useMockResizeObserver } from '~helpers/mock_dom_observer';
6
7
  import Chart from './chart.vue';
7
8
 
@@ -47,15 +48,19 @@ describe('chart component', () => {
47
48
  expect(wrapper.vm.chart.resize).toHaveBeenCalledTimes(1);
48
49
 
49
50
  triggerResize(wrapper.element);
51
+ await waitForAnimationFrame();
52
+
50
53
  expect(wrapper.vm.chart.resize).toHaveBeenCalledTimes(1);
51
54
  });
52
55
 
53
- it('resizes the chart when responsive = true', async () => {
56
+ it('resizes the chart only once per animation frame when responsive = true', async () => {
54
57
  wrapper = shallowMount(Chart, { propsData: { options: {}, responsive: true } });
55
58
  await wrapper.vm.$nextTick();
56
59
  expect(wrapper.vm.chart.resize).toHaveBeenCalledTimes(1);
57
60
 
58
61
  triggerResize(wrapper.element);
62
+ triggerResize(wrapper.element);
63
+ await waitForAnimationFrame();
59
64
 
60
65
  expect(wrapper.vm.chart.resize).toHaveBeenCalledTimes(2);
61
66
  });
@@ -9,6 +9,7 @@ import {
9
9
  } from '../../../utils/charts/config';
10
10
  import { createTheme, themeName } from '../../../utils/charts/theme';
11
11
  import { GlResizeObserverDirective } from '../../../directives/resize_observer/resize_observer';
12
+ import { debounceByAnimationFrame } from '../../../utils/utils';
12
13
 
13
14
  /**
14
15
  * Allowed values by eCharts
@@ -95,6 +96,7 @@ export default {
95
96
  data() {
96
97
  return {
97
98
  chart: null,
99
+ debouncedHandleResize: debounceByAnimationFrame(this.handleResize),
98
100
  };
99
101
  },
100
102
  computed: {
@@ -175,12 +177,12 @@ export default {
175
177
  this.$emit('chartItemClicked', { chart: this.chart, params });
176
178
  },
177
179
  handleResize() {
178
- if (this.responsive) this.chart.resize();
180
+ this.chart.resize();
179
181
  },
180
182
  },
181
183
  };
182
184
  </script>
183
185
 
184
186
  <template>
185
- <div ref="chart" v-resize-observer="handleResize"></div>
187
+ <div ref="chart" v-resize-observer:[responsive]="debouncedHandleResize"></div>
186
188
  </template>