@gitlab/ui 37.10.0 → 38.1.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 (67) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +1 -1
  3. package/dist/components/base/breadcrumb/breadcrumb.js +10 -5
  4. package/dist/components/base/{filtered_search/examples/filtered_search.single_unique.example.js → breadcrumb/breadcrumb_item.js} +32 -28
  5. package/dist/components/base/filtered_search/filtered_search.documentation.js +2 -66
  6. package/dist/components/base/filtered_search/filtered_search.js +38 -11
  7. package/dist/components/base/filtered_search/filtered_search_suggestion.documentation.js +2 -8
  8. package/dist/components/base/filtered_search/filtered_search_suggestion.js +4 -0
  9. package/dist/components/base/filtered_search/filtered_search_suggestion_list.documentation.js +2 -7
  10. package/dist/components/base/filtered_search/filtered_search_suggestion_list.js +4 -0
  11. package/dist/components/base/filtered_search/filtered_search_term.documentation.js +2 -44
  12. package/dist/components/base/filtered_search/filtered_search_term.js +37 -0
  13. package/dist/components/base/filtered_search/filtered_search_token.documentation.js +2 -31
  14. package/dist/components/base/filtered_search/filtered_search_token.js +49 -0
  15. package/dist/components/base/filtered_search/filtered_search_token_segment.documentation.js +2 -46
  16. package/dist/components/base/filtered_search/filtered_search_token_segment.js +48 -0
  17. package/dist/components/base/form/form_radio/form_radio.js +1 -1
  18. package/dist/components/charts/series_label/series_label.js +6 -1
  19. package/dist/components/utilities/truncate/truncate.js +2 -2
  20. package/documentation/documented_stories.js +6 -0
  21. package/package.json +9 -7
  22. package/src/components/base/breadcrumb/breadcrumb.spec.js +24 -10
  23. package/src/components/base/breadcrumb/breadcrumb.vue +11 -6
  24. package/src/components/base/breadcrumb/breadcrumb_item.spec.js +45 -0
  25. package/src/components/base/breadcrumb/breadcrumb_item.vue +43 -0
  26. package/src/components/base/filtered_search/filtered_search.documentation.js +0 -76
  27. package/src/components/base/filtered_search/filtered_search.md +3 -4
  28. package/src/components/base/filtered_search/filtered_search.stories.js +248 -13
  29. package/src/components/base/filtered_search/filtered_search.vue +47 -10
  30. package/src/components/base/filtered_search/filtered_search_suggestion.documentation.js +0 -6
  31. package/src/components/base/filtered_search/filtered_search_suggestion.md +1 -7
  32. package/src/components/base/filtered_search/filtered_search_suggestion.stories.js +26 -18
  33. package/src/components/base/filtered_search/filtered_search_suggestion.vue +5 -0
  34. package/src/components/base/filtered_search/filtered_search_suggestion_list.documentation.js +0 -5
  35. package/src/components/base/filtered_search/filtered_search_suggestion_list.md +1 -7
  36. package/src/components/base/filtered_search/filtered_search_suggestion_list.stories.js +33 -25
  37. package/src/components/base/filtered_search/filtered_search_suggestion_list.vue +5 -0
  38. package/src/components/base/filtered_search/filtered_search_term.documentation.js +0 -41
  39. package/src/components/base/filtered_search/filtered_search_term.md +0 -2
  40. package/src/components/base/filtered_search/filtered_search_term.stories.js +33 -26
  41. package/src/components/base/filtered_search/filtered_search_term.vue +54 -0
  42. package/src/components/base/filtered_search/filtered_search_token.documentation.js +0 -26
  43. package/src/components/base/filtered_search/filtered_search_token.md +1 -3
  44. package/src/components/base/filtered_search/filtered_search_token.stories.js +136 -132
  45. package/src/components/base/filtered_search/filtered_search_token.vue +63 -0
  46. package/src/components/base/filtered_search/filtered_search_token_segment.documentation.js +0 -43
  47. package/src/components/base/filtered_search/filtered_search_token_segment.md +0 -2
  48. package/src/components/base/filtered_search/filtered_search_token_segment.stories.js +86 -79
  49. package/src/components/base/filtered_search/filtered_search_token_segment.vue +42 -0
  50. package/src/components/base/form/form_radio/form_radio.spec.js +21 -8
  51. package/src/components/base/form/form_radio/form_radio.vue +0 -1
  52. package/src/components/charts/series_label/series_label.stories.js +6 -3
  53. package/src/components/charts/series_label/series_label.vue +3 -0
  54. package/src/components/utilities/truncate/truncate.spec.js +14 -49
  55. package/src/components/utilities/truncate/truncate.stories.js +1 -59
  56. package/src/components/utilities/truncate/truncate.vue +3 -21
  57. package/dist/components/base/filtered_search/examples/filtered_search.default.example.js +0 -422
  58. package/dist/components/base/filtered_search/examples/filtered_search.friendly.example.js +0 -423
  59. package/dist/components/base/filtered_search/examples/filtered_search.history.example.js +0 -91
  60. package/dist/components/base/filtered_search/examples/filtered_search.multi_select.example.js +0 -196
  61. package/dist/components/base/filtered_search/examples/index.js +0 -32
  62. package/src/components/base/filtered_search/examples/filtered_search.default.example.vue +0 -298
  63. package/src/components/base/filtered_search/examples/filtered_search.friendly.example.vue +0 -300
  64. package/src/components/base/filtered_search/examples/filtered_search.history.example.vue +0 -50
  65. package/src/components/base/filtered_search/examples/filtered_search.multi_select.example.vue +0 -132
  66. package/src/components/base/filtered_search/examples/filtered_search.single_unique.example.vue +0 -31
  67. package/src/components/base/filtered_search/examples/index.js +0 -38
@@ -1,82 +1,6 @@
1
- import examples from './examples';
2
1
  import * as description from './filtered_search.md';
3
2
 
4
3
  export default {
5
4
  description,
6
5
  followsDesignSystem: true,
7
- bootstrapComponent: null,
8
- examples,
9
- propsInfo: {
10
- value: {
11
- additionalInfo: 'If provided, used as value of filtered search',
12
- },
13
- historyItems: {
14
- additionalInfo: 'If provided, used as history items for this component',
15
- },
16
- availableTokens: {
17
- additionalInfo: 'Available tokens',
18
- },
19
- placeholder: {
20
- additionalInfo: 'If provided, used as history items for this component',
21
- },
22
- recentSearchesHeader: {
23
- additionalInfo: 'i18n for recent searches title within history dropdown',
24
- },
25
- clearButtonTitle: {
26
- additionalInfo: 'i18n for clear button title',
27
- },
28
- closeButtonTitle: {
29
- additionalInfo: 'i18n for close button title within history dropdown',
30
- },
31
- clearRecentSearchesText: {
32
- additionalInfo: 'i18n for recent searches clear text',
33
- },
34
- suggestionsListClass: {
35
- additionalInfo:
36
- 'Additional classes to add to the suggestion list menu. NOTE: this not reactive, and the value must be available and fixed when the component is instantiated',
37
- },
38
- searchButtonAttributes: {
39
- additionalInfo: 'HTML attributes to add to the search button',
40
- },
41
- searchInputAttributes: {
42
- additionalInfo: 'HTML attributes to add to the search input',
43
- },
44
- },
45
- events: [
46
- {
47
- event: 'clear',
48
- description: 'Emitted when search is cleared',
49
- },
50
- {
51
- event: 'submit',
52
- args: [
53
- {
54
- arg: 'tokens',
55
- description: '(Array)',
56
- },
57
- ],
58
- description: 'Emitted when search is submitted',
59
- },
60
- {
61
- event: 'history-item-selected',
62
- args: [
63
- {
64
- arg: 'value',
65
- description: 'History item',
66
- },
67
- ],
68
- description: 'Emitted when item from history is selected',
69
- },
70
- {
71
- event: 'clear-history',
72
- description: 'Emitted when clear history button is clicked',
73
- },
74
- ],
75
- slots: [
76
- {
77
- name: 'history-item',
78
- description:
79
- 'Slot to customize history item in history dropdown. Used only if using history items',
80
- },
81
- ],
82
6
  };
@@ -1,5 +1,3 @@
1
- # Filtered Search
2
-
3
1
  The filtered search component is responsible for managing search with possible filters.
4
2
 
5
3
  ## Usage
@@ -61,6 +59,7 @@ const availableTokens = [
61
59
  Pass the list of tokens to the search component. Optionally, you can use `v-model` to receive
62
60
  realtime updates:
63
61
 
64
- ```js
65
- <gl-filtered-search :available-tokens="tokens" v-model="value" />
62
+ ```html
63
+
64
+ <gl-filtered-search :available-tokens="tokens" v-model="value" />
66
65
  ```
@@ -1,14 +1,16 @@
1
- import { withKnobs } from '@storybook/addon-knobs';
2
- import { documentedStoriesOf } from '../../../../documentation/documented_stories';
3
1
  import {
4
2
  GlFilteredSearch,
5
3
  GlFilteredSearchToken,
6
4
  GlFilteredSearchSuggestion,
5
+ GlFilteredSearchSuggestionList,
6
+ GlFilteredSearchTerm,
7
+ GlFilteredSearchTokenSegment,
7
8
  GlLoadingIcon,
8
9
  GlToken,
9
10
  GlAvatar,
10
11
  } from '../../../index';
11
12
  import { setStoryTimeout } from '../../../utils/test_utils';
13
+ import { makeContainer } from '../../../utils/story_decorators/container';
12
14
  import readme from './filtered_search.md';
13
15
 
14
16
  const fakeUsers = [
@@ -296,19 +298,252 @@ const components = {
296
298
  GlFilteredSearch,
297
299
  };
298
300
 
299
- documentedStoriesOf('base/filtered-search', readme)
300
- .addDecorator(withKnobs)
301
- .add('default', () => ({
301
+ export const Default = () => ({
302
+ data() {
303
+ return {
304
+ tokens,
305
+ value: [
306
+ { type: 'author', value: { data: 'beta', operator: '=' } },
307
+ { type: 'label', value: { data: 'Bug', operator: '=' } },
308
+ 'raw text',
309
+ ],
310
+ };
311
+ },
312
+ components,
313
+ template: `<gl-filtered-search :available-tokens="tokens" :value="value" />`,
314
+ });
315
+
316
+ export const WithHistoryItems = () => ({
317
+ components,
318
+ data() {
319
+ return {
320
+ tokens: [
321
+ {
322
+ type: 'demotoken',
323
+ title: 'Unique',
324
+ icon: 'document',
325
+ token: 'gl-filtered-search-token',
326
+ operators: [{ value: '=', description: 'is', default: 'true' }],
327
+ options: [
328
+ { icon: 'heart', title: 'heart', value: 1 },
329
+ { icon: 'hook', title: 'hook', value: 2 },
330
+ ],
331
+ unique: true,
332
+ },
333
+ ],
334
+ value: [],
335
+ historyItems: [
336
+ [{ type: 'demotoken', value: { operator: '=', data: 1 } }, 'item 1'],
337
+ ['item 2', { type: 'demotoken', value: { operator: '=', data: 2 } }],
338
+ ],
339
+ };
340
+ },
341
+ methods: {
342
+ isString(val) {
343
+ return typeof val === 'string';
344
+ },
345
+ },
346
+ mounted() {
347
+ this.$nextTick(() => this.$el.querySelector('.gl-dropdown-toggle').click());
348
+ },
349
+ template: `
350
+ <div>
351
+ {{ value }}
352
+ <gl-filtered-search v-model="value" :available-tokens="tokens" :history-items="historyItems">
353
+ <template #history-item="{ historyItem }">
354
+ <template v-for="(token, idx) in historyItem">
355
+ <span v-if="isString(token)" :key="idx" class="gl-px-1">{{ token }}</span>
356
+ <span v-else :key="idx" class="gl-px-1">
357
+ <strong>{{ token.type }}</strong> {{ token.value.operator }}
358
+ <strong>{{ token.value.data }}</strong>
359
+ </span>
360
+ </template>
361
+ </template>
362
+ </gl-filtered-search>
363
+ </div>
364
+ `,
365
+ });
366
+
367
+ export const WithFriendlyText = () => ({
368
+ components,
369
+ data() {
370
+ return {
371
+ tokens: [
372
+ {
373
+ type: 'weight',
374
+ icon: 'weight',
375
+ title: 'Weight',
376
+ unique: true,
377
+ token: 'gl-filtered-search-token',
378
+ },
379
+ {
380
+ type: 'confidential',
381
+ icon: 'eye-slash',
382
+ title: 'Confidential',
383
+ unique: true,
384
+ token: 'gl-filtered-search-token',
385
+ options: [
386
+ { icon: 'eye-slash', value: 'Yes', title: 'Yes' },
387
+ { icon: 'eye', value: 'No', title: 'No' },
388
+ ],
389
+ },
390
+ ],
391
+ value: [
392
+ { type: 'weight', value: { data: '3', operator: '=' } },
393
+ { type: 'confidential', value: { data: 'Yes', operator: '!=' } },
394
+ ],
395
+ };
396
+ },
397
+ template: `
398
+ <gl-filtered-search
399
+ v-model="value"
400
+ :available-tokens="tokens"
401
+ :show-friendly-text="true"
402
+ />
403
+ `,
404
+ });
405
+
406
+ export const WithMultiSelect = () => {
407
+ const MultiUserToken = {
408
+ props: ['value', 'active', 'config'],
409
+ inheritAttrs: false,
302
410
  data() {
303
411
  return {
304
- tokens,
305
- value: [
306
- { type: 'author', value: { data: 'beta', operator: '=' } },
307
- { type: 'label', value: { data: 'Bug', operator: '=' } },
308
- 'raw text',
309
- ],
412
+ users: fakeUsers,
413
+ selectedUsernames: this.value.data ? this.value.data.split(',') : [],
414
+ activeUser: null,
310
415
  };
311
416
  },
417
+ computed: {
418
+ filteredUsers() {
419
+ return this.users.filter((user) => user.username.includes(this.value.data));
420
+ },
421
+ selectedUsers() {
422
+ return this.config.multiSelect
423
+ ? this.users.filter((user) => this.selectedUsernames.includes(user.username))
424
+ : this.users.filter((user) => user.username === this.activeUser);
425
+ },
426
+ },
427
+ methods: {
428
+ loadView() {
429
+ this.activeUser = fakeUsers.find((u) => u.username === this.value.data);
430
+ },
431
+ loadSuggestions() {
432
+ this.users = fakeUsers;
433
+ },
434
+ handleSelect(username) {
435
+ if (!this.config.multiSelect) {
436
+ return;
437
+ }
438
+
439
+ if (this.selectedUsernames.includes(username)) {
440
+ this.selectedUsernames = this.selectedUsernames.filter((user) => user !== username);
441
+ } else {
442
+ this.selectedUsernames.push(username);
443
+ }
444
+ },
445
+ isLastUser(index) {
446
+ return index === this.selectedUsers.length - 1;
447
+ },
448
+ },
449
+ watch: {
450
+ // eslint-disable-next-line func-names
451
+ 'value.data': function () {
452
+ if (this.active) {
453
+ this.loadSuggestions();
454
+ }
455
+ },
456
+ active: {
457
+ immediate: true,
458
+ handler(newValue) {
459
+ if (!newValue) {
460
+ this.loadView();
461
+ } else {
462
+ this.loadSuggestions();
463
+ }
464
+ },
465
+ },
466
+ },
467
+ template: `
468
+ <gl-filtered-search-token
469
+ v-bind="{ ...this.$props, ...this.$attrs }"
470
+ v-on="$listeners"
471
+ :multi-select-values="selectedUsernames"
472
+ @select="handleSelect"
473
+ >
474
+ <template #view="{ inputValue }">
475
+ <template v-for="(user, index) in selectedUsers">
476
+ <gl-avatar :size="16" :entity-name="user.username" shape="circle" />
477
+ {{ user.name }}
478
+ <span v-if="!isLastUser(index)" class="gl-mx-2">,&nbsp;</span>
479
+ </template>
480
+ </template>
481
+ <template #suggestions>
482
+ <gl-filtered-search-suggestion :key="user.id" v-for="user in filteredUsers" :value="user.username">
483
+ <div class="gl-display-flex gl-align-items-center">
484
+ <gl-icon
485
+ v-if="config.multiSelect"
486
+ name="check"
487
+ class="gl-mr-3 gl-text-gray-700"
488
+ :class="{ 'gl-visibility-hidden': !selectedUsernames.includes(user.username) }"
489
+ />
490
+ <gl-avatar :size="32" :entity-name="user.username" />
491
+ <div>
492
+ <p class="gl-m-0">{{ user.name }}</p>
493
+ <p class="gl-m-0">@{{ user.username }}</p>
494
+ </div>
495
+ </div>
496
+ </gl-filtered-search-suggestion>
497
+ </template>
498
+ </gl-filtered-search-token>
499
+ `,
500
+ };
501
+
502
+ return {
312
503
  components,
313
- template: `<gl-filtered-search :available-tokens="tokens" :value="value" />`,
314
- }));
504
+ data() {
505
+ return {
506
+ tokens: [
507
+ {
508
+ type: 'assignee',
509
+ icon: 'user',
510
+ title: 'Assignee',
511
+ token: MultiUserToken,
512
+ operators: [
513
+ { value: '=', description: 'is', default: 'true' },
514
+ { value: '!=', description: 'is not one of' },
515
+ { value: '||', description: 'is one of' },
516
+ ],
517
+ multiSelect: true,
518
+ },
519
+ ],
520
+ value: [{ type: 'assignee', value: { data: 'alpha,beta', operator: '=' } }],
521
+ };
522
+ },
523
+ template: `
524
+ <gl-filtered-search v-model="value" :available-tokens="tokens" />
525
+ `,
526
+ };
527
+ };
528
+
529
+ export default {
530
+ title: 'base/filtered-search',
531
+ // Make room for suggestion lists
532
+ decorators: [makeContainer({ height: '250px' })],
533
+ component: GlFilteredSearch,
534
+ subcomponents: {
535
+ GlFilteredSearchSuggestion,
536
+ GlFilteredSearchSuggestionList,
537
+ GlFilteredSearchTerm,
538
+ GlFilteredSearchTokenSegment,
539
+ GlFilteredSearchToken,
540
+ },
541
+ parameters: {
542
+ docs: {
543
+ description: {
544
+ component: readme,
545
+ },
546
+ },
547
+ },
548
+ argTypes: {},
549
+ };
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import { cloneDeep, isEqual } from 'lodash';
2
+ import { cloneDeep } from 'lodash';
3
3
  import PortalVue from 'portal-vue';
4
4
  import Vue from 'vue';
5
5
  import { GlTooltipDirective } from '../../../directives/tooltip';
@@ -31,6 +31,7 @@ function initialState() {
31
31
  }
32
32
 
33
33
  export default {
34
+ name: 'GlFilteredSearch',
34
35
  components: {
35
36
  GlSearchBoxByClick,
36
37
  GlIcon,
@@ -51,16 +52,25 @@ export default {
51
52
  },
52
53
  inheritAttrs: false,
53
54
  props: {
55
+ /**
56
+ * If provided, used as value of filtered search
57
+ */
54
58
  value: {
55
59
  required: false,
56
60
  type: Array,
57
61
  default: () => [],
58
62
  },
63
+ /**
64
+ * Available tokens
65
+ */
59
66
  availableTokens: {
60
67
  type: Array,
61
68
  required: false,
62
69
  default: () => [],
63
70
  },
71
+ /**
72
+ * If provided, used as history items for this component
73
+ */
64
74
  placeholder: {
65
75
  type: String,
66
76
  required: false,
@@ -76,21 +86,34 @@ export default {
76
86
  required: false,
77
87
  default: null,
78
88
  },
89
+ /**
90
+ * Additional classes to add to the suggestion list menu. NOTE: this not reactive, and the value
91
+ * must be available and fixed when the component is instantiated
92
+ */
79
93
  suggestionsListClass: {
80
94
  type: [String, Array, Object],
81
95
  required: false,
82
96
  default: null,
83
97
  },
98
+ /**
99
+ * Display operators' descriptions instead of their values (e.g., "is" instead of "=").
100
+ */
84
101
  showFriendlyText: {
85
102
  type: Boolean,
86
103
  required: false,
87
104
  default: false,
88
105
  },
106
+ /**
107
+ * HTML attributes to add to the search button
108
+ */
89
109
  searchButtonAttributes: {
90
110
  type: Object,
91
111
  required: false,
92
112
  default: () => ({}),
93
113
  },
114
+ /**
115
+ * HTML attributes to add to the search input
116
+ */
94
117
  searchInputAttributes: {
95
118
  type: Object,
96
119
  required: false,
@@ -141,26 +164,22 @@ export default {
141
164
  this.tokens.push(createTerm());
142
165
  }
143
166
 
167
+ /**
168
+ * Emitted when the tokens (value) changes
169
+ * @property {array} tokens
170
+ */
144
171
  this.$emit('input', this.tokens);
145
172
  },
146
173
  deep: true,
147
174
  immediate: true,
148
175
  },
149
- value: {
150
- handler(newValue, oldValue) {
151
- if (newValue.length && !isEqual(newValue, oldValue)) {
152
- this.applyNewValue(cloneDeep(newValue));
153
- }
154
- },
155
- deep: true,
156
- immediate: true,
157
- },
158
176
  },
159
177
  mounted() {
160
178
  if (this.value.length) {
161
179
  this.applyNewValue(cloneDeep(this.value));
162
180
  }
163
181
  },
182
+
164
183
  methods: {
165
184
  applyNewValue(newValue) {
166
185
  this.tokens = needDenormalization(newValue) ? denormalizeTokens(newValue) : newValue;
@@ -269,6 +288,10 @@ export default {
269
288
  },
270
289
 
271
290
  submit() {
291
+ /**
292
+ * Emitted when search is submitted
293
+ * @property {array} tokens
294
+ */
272
295
  this.$emit('submit', normalizeTokens(cloneDeep(this.tokens)));
273
296
  },
274
297
 
@@ -281,6 +304,19 @@ export default {
281
304
  </script>
282
305
 
283
306
  <template>
307
+ <!--
308
+ Emitted when search is cleared
309
+ @event clear
310
+ -->
311
+ <!--
312
+ Emitted when item from history is selected
313
+ @event history-item-selected
314
+ @property {object} value History item
315
+ -->
316
+ <!--
317
+ Emitted when clear history button is clicked
318
+ @event clear-history
319
+ -->
284
320
  <gl-search-box-by-click
285
321
  v-bind="$attrs"
286
322
  :value="tokens"
@@ -295,6 +331,7 @@ export default {
295
331
  @clear-history="$emit('clear-history')"
296
332
  >
297
333
  <template #history-item="slotScope">
334
+ <!-- @slot Slot to customize history item in history dropdown. Used only if using history items -->
298
335
  <slot name="history-item" v-bind="slotScope"></slot>
299
336
  </template>
300
337
  <template #input>
@@ -2,10 +2,4 @@ import description from './filtered_search_suggestion.md';
2
2
 
3
3
  export default {
4
4
  description,
5
- bootstrapComponent: 'b-dropdown-item',
6
- propsInfo: {
7
- value: {
8
- additionalInfo: 'Value which will be emitted if this suggestion will be selected in list',
9
- },
10
- },
11
5
  };
@@ -1,13 +1,7 @@
1
- # Filtered Search Suggestion
2
-
3
- <!-- STORY -->
4
-
5
- ## Usage
6
-
7
1
  The filtered search suggestion component is a wrapper around `GlDropdownItem`, which registers
8
2
  suggestions in a top-level suggestion list:
9
3
 
10
- ```js
4
+ ```html
11
5
  <gl-filtered-search-suggestion-list>
12
6
  <gl-filtered-search-suggestion value="foo">Example suggestion</gl-filtered-search-suggestion>
13
7
  <gl-filtered-search-suggestion value="bar">Example suggestion 2</gl-filtered-search-suggestion>
@@ -1,25 +1,33 @@
1
- import { withKnobs } from '@storybook/addon-knobs';
2
1
  import { GlFilteredSearchSuggestion } from '../../../index';
3
- import { documentedStoriesOf } from '../../../../documentation/documented_stories';
4
2
  import readme from './filtered_search_suggestion.md';
5
3
 
6
4
  const noop = () => {};
7
5
 
8
- documentedStoriesOf('base/filtered-search/suggestion', readme)
9
- .addDecorator(withKnobs)
10
- .add('default', () => ({
11
- components: { GlFilteredSearchSuggestion },
12
- provide: {
13
- filteredSearchSuggestionListInstance: {
14
- register: noop,
15
- unregister: noop,
16
- $emit: noop,
17
- activeItem: null,
6
+ export const Default = () => ({
7
+ components: { GlFilteredSearchSuggestion },
8
+ provide: {
9
+ filteredSearchSuggestionListInstance: {
10
+ register: noop,
11
+ unregister: noop,
12
+ $emit: noop,
13
+ activeItem: null,
14
+ },
15
+ },
16
+ template: `
17
+ <ul>
18
+ <gl-filtered-search-suggestion value="demo">Demo suggestion</gl-filtered-search-suggestion>
19
+ </ul>
20
+ `,
21
+ });
22
+
23
+ export default {
24
+ title: 'base/filtered-search/suggestion',
25
+ component: GlFilteredSearchSuggestion,
26
+ parameters: {
27
+ docs: {
28
+ description: {
29
+ component: readme,
18
30
  },
19
31
  },
20
- template: `
21
- <ul>
22
- <gl-filtered-search-suggestion value="demo">Demo suggestion</gl-filtered-search-suggestion>
23
- </ul>
24
- `,
25
- }));
32
+ },
33
+ };
@@ -2,12 +2,16 @@
2
2
  import GlDropdownItem from '../dropdown/dropdown_item.vue';
3
3
 
4
4
  export default {
5
+ name: 'GlFilteredSearchSuggestion',
5
6
  components: {
6
7
  GlDropdownItem,
7
8
  },
8
9
  inject: ['filteredSearchSuggestionListInstance'],
9
10
  inheritAttrs: false,
10
11
  props: {
12
+ /**
13
+ * Value that will be emitted if this suggestion is selected.
14
+ */
11
15
  value: {
12
16
  required: true,
13
17
  validator: () => true,
@@ -52,6 +56,7 @@ export default {
52
56
  href="#"
53
57
  @mousedown.native.prevent="emitValue"
54
58
  >
59
+ <!-- @slot The suggestion content. -->
55
60
  <slot></slot>
56
61
  </gl-dropdown-item>
57
62
  </template>
@@ -2,9 +2,4 @@ import description from './filtered_search_suggestion_list.md';
2
2
 
3
3
  export default {
4
4
  description,
5
- propsInfo: {
6
- initialValue: {
7
- additionalInfo: 'Value to be initially selected in list',
8
- },
9
- },
10
5
  };
@@ -1,9 +1,3 @@
1
- # Filtered Search Suggestion
2
-
3
- <!-- STORY -->
4
-
5
- ## Usage
6
-
7
1
  The filtered search suggestion list component is responsible for managing underlying suggestion instances.
8
2
  You obtain the ref for this component and manage suggestion selection via the component public API:
9
3
 
@@ -11,7 +5,7 @@ You obtain the ref for this component and manage suggestion selection via the co
11
5
  - `nextItem()` - Selects the next suggestion. If last suggestion was selected, selection is cleared.
12
6
  - `prevItem()` - Selects the previous suggestion. If first suggestion was selected, selection is cleared.
13
7
 
14
- ```js
8
+ ```html
15
9
  <gl-filtered-search-suggestion-list ref="suggestions">
16
10
  <gl-filtered-search-suggestion value="foo">Example suggestion</gl-filtered-search-suggestion>
17
11
  <gl-filtered-search-suggestion value="bar">Example suggestion 2</gl-filtered-search-suggestion>