@gitlab/ui 41.9.0 → 42.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.
Files changed (92) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/components/base/tabs/tab/tab.js +1 -10
  3. package/dist/components/base/token_selector/token_container.js +6 -1
  4. package/dist/components/base/token_selector/token_selector.js +15 -2
  5. package/dist/index.css +1 -1
  6. package/dist/index.css.map +1 -1
  7. package/dist/utils/constants.js +0 -2
  8. package/package.json +13 -14
  9. package/src/components/base/accordion/accordion.stories.js +0 -1
  10. package/src/components/base/accordion/accordion_item.stories.js +0 -1
  11. package/src/components/base/avatar/avatar.stories.js +0 -1
  12. package/src/components/base/avatar_labeled/avatar_labeled.stories.js +0 -1
  13. package/src/components/base/avatar_link/avatar_link.stories.js +0 -1
  14. package/src/components/base/avatars_inline/avatars_inline.stories.js +0 -1
  15. package/src/components/base/banner/banner.stories.js +0 -1
  16. package/src/components/base/breadcrumb/breadcrumb.stories.js +0 -1
  17. package/src/components/base/broadcast_message/broadcast_message.stories.js +0 -1
  18. package/src/components/base/button/button.scss +3 -60
  19. package/src/components/base/button/button.spec.js +0 -3
  20. package/src/components/base/button/button.stories.js +0 -3
  21. package/src/components/base/button_group/button_group.stories.js +0 -3
  22. package/src/components/base/card/card.stories.js +0 -1
  23. package/src/components/base/carousel/carousel.stories.js +0 -1
  24. package/src/components/base/collapse/collapse.stories.js +0 -3
  25. package/src/components/base/daterange_picker/daterange_picker.stories.js +0 -1
  26. package/src/components/base/drawer/drawer.stories.js +0 -1
  27. package/src/components/base/dropdown/dropdown.scss +1 -2
  28. package/src/components/base/form/form.stories.js +0 -1
  29. package/src/components/base/form/form_checkbox/form_checkbox.stories.js +0 -1
  30. package/src/components/base/form/form_combobox/form_combobox.stories.js +0 -1
  31. package/src/components/base/form/form_input/form_input.stories.js +0 -1
  32. package/src/components/base/form/form_input_group/form_input_group.stories.js +0 -2
  33. package/src/components/base/form/form_radio/form_radio.stories.js +0 -1
  34. package/src/components/base/form/form_radio_group/form_radio_group.stories.js +0 -1
  35. package/src/components/base/form/form_select/form_select.stories.js +0 -1
  36. package/src/components/base/form/form_text/form_text.stories.js +0 -1
  37. package/src/components/base/form/form_textarea/form_textarea.stories.js +0 -1
  38. package/src/components/base/form/input_group_text/input_group_text.stories.js +0 -1
  39. package/src/components/base/icon/icon.stories.js +0 -1
  40. package/src/components/base/infinite_scroll/infinite_scroll.stories.js +0 -1
  41. package/src/components/base/keyset_pagination/keyset_pagination.stories.js +0 -1
  42. package/src/components/base/label/label.stories.js +0 -1
  43. package/src/components/base/loading_icon/loading_icon.stories.js +0 -3
  44. package/src/components/base/markdown/markdown.stories.js +0 -1
  45. package/src/components/base/modal/modal.stories.js +0 -1
  46. package/src/components/base/nav/nav.stories.js +0 -1
  47. package/src/components/base/new_dropdowns/listbox/listbox.stories.js +0 -1
  48. package/src/components/base/paginated_list/paginated_list.stories.js +0 -1
  49. package/src/components/base/pagination/pagination.stories.js +0 -1
  50. package/src/components/base/path/path.stories.js +0 -1
  51. package/src/components/base/popover/popover.stories.js +0 -1
  52. package/src/components/base/progress_bar/progress_bar.stories.js +0 -1
  53. package/src/components/base/search_box_by_click/search_box_by_click.stories.js +0 -1
  54. package/src/components/base/search_box_by_type/search_box_by_type.stories.js +0 -1
  55. package/src/components/base/segmented_control/segmented_control.stories.js +0 -1
  56. package/src/components/base/skeleton_loader/skeleton_loader.stories.js +0 -1
  57. package/src/components/base/skeleton_loading/skeleton_loading.stories.js +0 -1
  58. package/src/components/base/sorting/sorting.stories.js +0 -1
  59. package/src/components/base/sorting/sorting_item.stories.js +0 -1
  60. package/src/components/base/table/table.stories.js +0 -1
  61. package/src/components/base/table_lite/table_lite.stories.js +0 -1
  62. package/src/components/base/tabs/tab/tab.spec.js +9 -19
  63. package/src/components/base/tabs/tab/tab.vue +0 -9
  64. package/src/components/base/tabs/tabs/tabs.stories.js +0 -14
  65. package/src/components/base/toast/toast.stories.js +0 -1
  66. package/src/components/base/token_selector/token_container.spec.js +9 -0
  67. package/src/components/base/token_selector/token_container.vue +6 -0
  68. package/src/components/base/token_selector/token_selector.spec.js +60 -0
  69. package/src/components/base/token_selector/token_selector.stories.js +0 -1
  70. package/src/components/base/token_selector/token_selector.vue +17 -1
  71. package/src/components/base/tooltip/tooltip.stories.js +0 -1
  72. package/src/components/charts/area/area.stories.js +0 -3
  73. package/src/components/charts/bar/bar.stories.js +0 -1
  74. package/src/components/charts/discrete_scatter/discrete_scatter.stories.js +0 -3
  75. package/src/components/charts/gauge/gauge.stories.js +0 -1
  76. package/src/components/charts/heatmap/heatmap.stories.js +0 -3
  77. package/src/components/charts/legend/legend.stories.js +0 -1
  78. package/src/components/charts/series_label/series_label.stories.js +0 -1
  79. package/src/components/charts/single_stat/single_stat.stories.js +0 -1
  80. package/src/components/charts/sparkline/sparkline.stories.js +0 -1
  81. package/src/components/charts/stacked_column/stacked_column.stories.js +0 -1
  82. package/src/components/charts/tooltip/tooltip.stories.js +0 -1
  83. package/src/components/regions/empty_state/empty_state.stories.js +0 -1
  84. package/src/components/utilities/friendly_wrap/friendly_wrap.stories.js +0 -1
  85. package/src/components/utilities/intersection_observer/intersection_observer.stories.js +0 -1
  86. package/src/components/utilities/intersperse/intersperse.stories.js +0 -1
  87. package/src/components/utilities/truncate/truncate.stories.js +0 -1
  88. package/src/directives/outside/outside.stories.js +0 -1
  89. package/src/directives/resize_observer/resize_observer.stories.js +0 -1
  90. package/src/directives/safe_html/safe_html.stories.js +0 -1
  91. package/src/directives/safe_link/safe_link.stories.js +0 -1
  92. package/src/utils/constants.js +0 -2
@@ -1,5 +1,4 @@
1
1
  import { shallowMount } from '@vue/test-utils';
2
- import { BTab } from 'bootstrap-vue';
3
2
  import { DEFAULT_TAB_TITLE_LINK_CLASS } from '../constants';
4
3
  import GlTab from './tab.vue';
5
4
 
@@ -7,7 +6,9 @@ describe('Tab component', () => {
7
6
  let wrapper;
8
7
 
9
8
  const createComponent = (options) => {
10
- wrapper = shallowMount(GlTab, { ...options });
9
+ wrapper = shallowMount(GlTab, {
10
+ ...options,
11
+ });
11
12
  };
12
13
 
13
14
  it.each`
@@ -21,25 +22,14 @@ describe('Tab component', () => {
21
22
  'computed title link class is $expectedProp when titleLinkClass is $titleLinkClass',
22
23
  ({ titleLinkClass, expectedProp }) => {
23
24
  createComponent({
24
- propsData: { titleLinkClass },
25
+ propsData: {
26
+ titleLinkClass,
27
+ },
25
28
  });
26
29
 
27
- expect(wrapper.findComponent(BTab).props('titleLinkClass')).toEqual(expectedProp);
30
+ expect(wrapper.html()).toBe(
31
+ `<b-tab-stub tag="div" title="" titlelinkclass="${expectedProp}"></b-tab-stub>`
32
+ );
28
33
  }
29
34
  );
30
-
31
- it('passes title-link-attributes to b-tab when href is explicitly passed', () => {
32
- const titleLinkAttributes = 'href-example';
33
- const expectedProp = { href: titleLinkAttributes };
34
- createComponent({
35
- propsData: { href: titleLinkAttributes },
36
- });
37
- expect(wrapper.findComponent(BTab).props('titleLinkAttributes')).toEqual(expectedProp);
38
- });
39
-
40
- it('passes # as href to b-tab when href is not passed', () => {
41
- const expectedProp = { href: '#' };
42
- createComponent();
43
- expect(wrapper.findComponent(BTab).props('titleLinkAttributes')).toEqual(expectedProp);
44
- });
45
35
  });
@@ -24,14 +24,6 @@ export default {
24
24
  required: false,
25
25
  default: null,
26
26
  },
27
- /**
28
- * Provide an `href` for the tab, for example to associate the tab with the tab panel's ID
29
- */
30
- href: {
31
- type: String,
32
- required: false,
33
- default: '#',
34
- },
35
27
  },
36
28
  computed: {
37
29
  linkClass() {
@@ -54,7 +46,6 @@ export default {
54
46
  :title-link-class="linkClass"
55
47
  :query-param-value="queryParamValue"
56
48
  v-bind="$attrs"
57
- :title-link-attributes="{ href }"
58
49
  v-on="$listeners"
59
50
  >
60
51
  <template v-for="slot in Object.keys($slots)" #[slot]>
@@ -226,20 +226,6 @@ WithScrollAndGrowing.parameters = {
226
226
  storyshots: { disable: true },
227
227
  };
228
228
 
229
- export const WithHref = (_args, { argTypes }) => ({
230
- props: Object.keys(argTypes),
231
- components: { ...components, GlBadge },
232
- template: wrap(`
233
- <gl-tab href="#tab-1" title="Tab 1">
234
- <h2 id="tab-1">Tab panel 1</h2>
235
- <p>Some paragraph text<p>
236
- </gl-tab>
237
- <gl-tab href="#tab-2" title="Tab 2">
238
- <h2 id="tab-2">Tab panel 2</h2>
239
- <p>Some paragraph text<p>
240
- </gl-tab>`),
241
- });
242
-
243
229
  export default {
244
230
  title: 'base/tabs',
245
231
  component: GlTabs,
@@ -74,7 +74,6 @@ export default {
74
74
  component: GlToast,
75
75
  parameters: {
76
76
  bootstrapComponent: 'toast',
77
- knobs: { disable: true },
78
77
  docs: {
79
78
  description: {
80
79
  component: readme,
@@ -62,6 +62,15 @@ describe('GlTokenContainer', () => {
62
62
  });
63
63
  });
64
64
 
65
+ describe('viewOnly', () => {
66
+ it('passes viewOnly prop to tokens correctly', () => {
67
+ createComponent({ propsData: { viewOnly: true } });
68
+ const tokenWrappers = wrapper.findAllComponents(GlToken);
69
+
70
+ expect(tokenWrappers.wrappers.every((token) => token.props('viewOnly'))).toBe(true);
71
+ });
72
+ });
73
+
65
74
  describe('state', () => {
66
75
  describe('when `state` is `false`', () => {
67
76
  it('adds `aria-invalid="true"` attribute`', () => {
@@ -21,6 +21,11 @@ export default {
21
21
  type: Function,
22
22
  required: true,
23
23
  },
24
+ viewOnly: {
25
+ type: Boolean,
26
+ required: false,
27
+ default: false,
28
+ },
24
29
  },
25
30
  data() {
26
31
  return {
@@ -143,6 +148,7 @@ export default {
143
148
  class="gl-cursor-default"
144
149
  :class="token.class"
145
150
  :style="token.style"
151
+ :view-only="viewOnly"
146
152
  @close="handleClose(token)"
147
153
  >
148
154
  <slot name="token-content" :token="token">
@@ -46,6 +46,8 @@ describe('GlTokenSelector', () => {
46
46
  },
47
47
  ];
48
48
 
49
+ const placeholderText = 'Test placeholder';
50
+
49
51
  let wrapper;
50
52
 
51
53
  const defaultProps = { selectedTokens: [] };
@@ -141,6 +143,22 @@ describe('GlTokenSelector', () => {
141
143
  });
142
144
  });
143
145
 
146
+ describe('viewOnly', () => {
147
+ beforeEach(() => {
148
+ createComponent({ propsData: { viewOnly: true } });
149
+ });
150
+
151
+ it('passes `viewOnly` prop to GlTokenContainer', () => {
152
+ expect(wrapper.findComponent(GlTokenContainer).props('viewOnly')).toBe(true);
153
+ });
154
+
155
+ it('disables input field if viewOnly is true', () => {
156
+ findTextInput().trigger('focus');
157
+
158
+ expect(findTextInput().attributes('disabled')).toBe('disabled');
159
+ });
160
+ });
161
+
144
162
  describe('containerClass', () => {
145
163
  it('renders passed CSS classes', () => {
146
164
  createComponent({
@@ -302,6 +320,48 @@ describe('GlTokenSelector', () => {
302
320
 
303
321
  expect(wrapper.findComponent(component).vm.$scopedSlots).toHaveProperty(slot);
304
322
  });
323
+
324
+ it('renders empty-placeholder slot if tokens list is empty and input is not focused', () => {
325
+ createComponent({
326
+ propsData: {
327
+ selectedTokens: [],
328
+ },
329
+ slots: {
330
+ 'empty-placeholder': placeholderText,
331
+ },
332
+ });
333
+
334
+ expect(wrapper.text()).toContain(placeholderText);
335
+ });
336
+
337
+ it('does not render empty-placeholder slot if token list is not empty', () => {
338
+ createComponent({
339
+ propsData: {
340
+ selectedTokens: tokens,
341
+ },
342
+ slots: {
343
+ 'empty-placeholder': placeholderText,
344
+ },
345
+ });
346
+
347
+ expect(wrapper.text()).not.toContain(placeholderText);
348
+ });
349
+
350
+ it('hides empty-placeholder slot if input is focused', async () => {
351
+ createComponent({
352
+ propsData: {
353
+ selectedTokens: [],
354
+ },
355
+ slots: {
356
+ 'empty-placeholder': placeholderText,
357
+ },
358
+ });
359
+
360
+ expect(wrapper.text()).toContain(placeholderText);
361
+
362
+ await findTextInput().trigger('focus');
363
+ expect(wrapper.text()).not.toContain(placeholderText);
364
+ });
305
365
  });
306
366
 
307
367
  describe('text input events', () => {
@@ -95,7 +95,6 @@ export default {
95
95
  title: 'base/token_selector',
96
96
  component: GlTokenSelector,
97
97
  parameters: {
98
- knobs: { disable: true },
99
98
  docs: {
100
99
  description: {
101
100
  component: readme,
@@ -113,6 +113,14 @@ export default {
113
113
  validator: tokensValidator,
114
114
  required: true,
115
115
  },
116
+ /**
117
+ * Controls the `view-only` mode for the tokens
118
+ */
119
+ viewOnly: {
120
+ type: Boolean,
121
+ required: false,
122
+ default: false,
123
+ },
116
124
  },
117
125
  data() {
118
126
  return {
@@ -165,6 +173,9 @@ export default {
165
173
  ? 'is-valid gl-inset-border-1-gray-400!'
166
174
  : 'is-invalid gl-inset-border-1-red-500!';
167
175
  },
176
+ showEmptyPlaceholder() {
177
+ return this.selectedTokens.length === 0 && !this.inputFocused;
178
+ },
168
179
  },
169
180
  watch: {
170
181
  inputText(newValue, oldValue) {
@@ -354,14 +365,18 @@ export default {
354
365
  <div>
355
366
  <div
356
367
  ref="container"
357
- class="gl-token-selector gl-form-input form-control form-control-plaintext gl-cursor-text! gl-py-2! gl-px-3!"
368
+ class="gl-token-selector gl-form-input gl-display-flex gl-align-items-center form-control form-control-plaintext gl-cursor-text! gl-py-2! gl-px-3!"
358
369
  :class="[inputFocused ? 'gl-token-selector-focus-glow' : '', containerClass, stateClass]"
359
370
  @click="handleContainerClick"
360
371
  >
372
+ <!-- @slot Optional content to display a placeholder when tokens list is empty
373
+ and user doesn't edit tokens -->
374
+ <slot v-if="showEmptyPlaceholder" name="empty-placeholder"></slot>
361
375
  <gl-token-container
362
376
  :tokens="selectedTokens"
363
377
  :state="state"
364
378
  :register-focus-on-token="registerFocusOnToken"
379
+ :view-only="viewOnly"
365
380
  @token-remove="removeToken"
366
381
  @cancel-focus="cancelTokenFocus"
367
382
  >
@@ -383,6 +398,7 @@ export default {
383
398
  :autocomplete="autocomplete"
384
399
  :aria-labelledby="ariaLabelledby"
385
400
  :placeholder="placeholder"
401
+ :disabled="viewOnly"
386
402
  v-bind="textInputAttrs"
387
403
  @input="inputText = $event.target.value"
388
404
  @focus="handleFocus"
@@ -49,7 +49,6 @@ export default {
49
49
  component: GlTooltip,
50
50
  parameters: {
51
51
  bootstrapComponent: 'b-tooltip',
52
- knobs: { disable: true },
53
52
  docs: {
54
53
  description: {
55
54
  component: readme,
@@ -153,9 +153,6 @@ MultSeries.args = generateProps({
153
153
  export default {
154
154
  title: 'charts/area-chart',
155
155
  component: GlAreaChart,
156
- parameters: {
157
- knobs: { disable: true },
158
- },
159
156
  argTypes: {
160
157
  ...disableControls([
161
158
  'showToolbox',
@@ -59,7 +59,6 @@ export default {
59
59
  ]),
60
60
  },
61
61
  parameters: {
62
- knobs: { disable: true },
63
62
  docs: {
64
63
  description: {
65
64
  component: readme,
@@ -57,7 +57,4 @@ WithZoomAndScroll.args = generateProps({
57
57
  export default {
58
58
  title: 'charts/discrete-scatter-chart',
59
59
  component: GlDiscreteScatterChart,
60
- parameters: {
61
- knobs: { disable: true },
62
- },
63
60
  };
@@ -85,7 +85,6 @@ export default {
85
85
  title: 'charts/gauge-chart',
86
86
  component: GlGauge,
87
87
  parameters: {
88
- knobs: { disable: true },
89
88
  docs: {
90
89
  description: {
91
90
  component: readme,
@@ -60,9 +60,6 @@ WithToolbox.args = generateProps({ options: { toolbox } });
60
60
  export default {
61
61
  title: 'charts/heatmap',
62
62
  component: GlHeatmap,
63
- parameters: {
64
- knobs: { disable: true },
65
- },
66
63
  argTypes: {
67
64
  ...disableControls([
68
65
  'showToolbox',
@@ -107,6 +107,5 @@ export default {
107
107
  component: GlChartLegend,
108
108
  parameters: {
109
109
  controls: { disable: true },
110
- knobs: { disable: true },
111
110
  },
112
111
  };
@@ -64,7 +64,6 @@ export default {
64
64
  title: 'charts/chart-series-label',
65
65
  component: GlChartSeriesLabel,
66
66
  parameters: {
67
- knobs: { disable: true },
68
67
  docs: {
69
68
  description: {
70
69
  component: readme,
@@ -64,7 +64,6 @@ export default {
64
64
  title: 'charts/single-stat',
65
65
  component: GlSingleStat,
66
66
  parameters: {
67
- knobs: { disable: true },
68
67
  docs: {
69
68
  description: {
70
69
  component: readme,
@@ -44,7 +44,6 @@ export default {
44
44
  title: 'charts/sparkline-chart',
45
45
  component: GlSparklineChart,
46
46
  parameters: {
47
- knobs: { disable: true },
48
47
  docs: {
49
48
  description: {
50
49
  component: readme,
@@ -104,7 +104,6 @@ export default {
104
104
  title: 'charts/stacked-column-chart',
105
105
  component: GlStackedColumnChart,
106
106
  parameters: {
107
- knobs: { disable: true },
108
107
  docs: {
109
108
  description: {
110
109
  component: readme,
@@ -103,7 +103,6 @@ export default {
103
103
  component: GlChartTooltip,
104
104
  parameters: {
105
105
  bootstrapComponent: 'b-popover',
106
- knobs: { disable: true },
107
106
  controls: { disable: true },
108
107
  docs: {
109
108
  description: {
@@ -143,7 +143,6 @@ export default {
143
143
  title: 'regions/empty-state',
144
144
  component: GlEmptyState,
145
145
  parameters: {
146
- knobs: { disable: true },
147
146
  docs: {
148
147
  description: {
149
148
  component: readme,
@@ -47,7 +47,6 @@ export default {
47
47
  title: 'utilities/friendly-wrap',
48
48
  component: GlFriendlyWrap,
49
49
  parameters: {
50
- knobs: { disabled: true },
51
50
  docs: {
52
51
  description: {
53
52
  component: readme,
@@ -152,7 +152,6 @@ export default {
152
152
  title: 'utilities/intersection-observer',
153
153
  component: GlIntersectionObserver,
154
154
  parameters: {
155
- knobs: { disable: true },
156
155
  storyshots: { disable: true },
157
156
  docs: {
158
157
  description: {
@@ -34,7 +34,6 @@ export default {
34
34
  title: 'utilities/intersperse',
35
35
  component: GlIntersperse,
36
36
  parameters: {
37
- knobs: { disable: true },
38
37
  docs: {
39
38
  description: {
40
39
  component: readme,
@@ -28,7 +28,6 @@ export default {
28
28
  title: 'utilities/truncate',
29
29
  component: GlTruncate,
30
30
  parameters: {
31
- knobs: { disable: true },
32
31
  storyshots: { disable: true },
33
32
  docs: {
34
33
  description: {
@@ -28,7 +28,6 @@ export default {
28
28
  title: 'directives/outside-directive',
29
29
  component: GlOutsideDirective,
30
30
  parameters: {
31
- knobs: { disable: true },
32
31
  docs: {
33
32
  description: {
34
33
  component: readme,
@@ -62,7 +62,6 @@ export default {
62
62
  title: 'directives/resize-observer-directive',
63
63
  component: GlResizeObserver,
64
64
  parameters: {
65
- knobs: { disable: true },
66
65
  storyshots: { disable: true },
67
66
  docs: {
68
67
  description: {
@@ -49,7 +49,6 @@ export default {
49
49
  component: GlSafeHtml,
50
50
  parameters: {
51
51
  storyshots: { disable: true },
52
- knobs: { disable: true },
53
52
  docs: {
54
53
  description: {
55
54
  component: readme,
@@ -29,7 +29,6 @@ export default {
29
29
  title: 'directives/safe-link-directive',
30
30
  component: SafeLink,
31
31
  parameters: {
32
- knobs: { disable: true },
33
32
  storyshots: { disable: true },
34
33
  docs: {
35
34
  description: {
@@ -97,7 +97,6 @@ export const buttonVariantOptions = {
97
97
  confirm: 'confirm',
98
98
  info: 'info (deprecated)',
99
99
  success: 'success (deprecated)',
100
- warning: 'warning (deprecated)',
101
100
  danger: 'danger',
102
101
  dashed: 'dashed',
103
102
  link: 'link',
@@ -121,7 +120,6 @@ export const dropdownVariantOptions = {
121
120
  confirm: 'confirm',
122
121
  info: 'info (deprecated)',
123
122
  success: 'success (deprecated)',
124
- warning: 'warning (deprecated)',
125
123
  danger: 'danger',
126
124
  link: 'link',
127
125
  };