@gitlab/ui 91.14.0 → 92.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 (36) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu.js +83 -15
  3. package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu_search_items.js +8 -2
  4. package/dist/components/experimental/duo/chat/components/duo_chat_context/utils.js +12 -1
  5. package/dist/index.css +2 -2
  6. package/dist/index.css.map +1 -1
  7. package/dist/tokens/build/js/tokens.dark.js +3 -4
  8. package/dist/tokens/build/js/tokens.js +2 -3
  9. package/dist/tokens/css/tokens.css +1 -2
  10. package/dist/tokens/css/tokens.dark.css +2 -3
  11. package/dist/tokens/js/tokens.dark.js +2 -3
  12. package/dist/tokens/js/tokens.js +1 -2
  13. package/dist/tokens/json/tokens.dark.json +4 -36
  14. package/dist/tokens/json/tokens.json +3 -35
  15. package/dist/tokens/scss/_tokens.dark.scss +2 -3
  16. package/dist/tokens/scss/_tokens.scss +1 -2
  17. package/dist/tokens/scss/_tokens_custom_properties.scss +0 -1
  18. package/package.json +1 -1
  19. package/src/components/base/modal/modal.scss +1 -1
  20. package/src/components/base/popover/popover.scss +10 -10
  21. package/src/components/base/toast/toast.scss +2 -1
  22. package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu.vue +86 -13
  23. package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu_search_items.vue +8 -1
  24. package/src/components/experimental/duo/chat/components/duo_chat_context/utils.js +11 -0
  25. package/src/scss/variables.scss +0 -1
  26. package/src/tokens/build/css/tokens.css +1 -2
  27. package/src/tokens/build/css/tokens.dark.css +2 -3
  28. package/src/tokens/build/js/tokens.dark.js +2 -3
  29. package/src/tokens/build/js/tokens.js +1 -2
  30. package/src/tokens/build/json/tokens.dark.json +4 -36
  31. package/src/tokens/build/json/tokens.json +3 -35
  32. package/src/tokens/build/scss/_tokens.dark.scss +2 -3
  33. package/src/tokens/build/scss/_tokens.scss +1 -2
  34. package/src/tokens/build/scss/_tokens_custom_properties.scss +0 -1
  35. package/src/tokens/feedback.tokens.json +2 -8
  36. package/src/tokens/contextual/popover.tokens.json +0 -14
package/CHANGELOG.md CHANGED
@@ -1,3 +1,26 @@
1
+ # [92.0.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v91.15.0...v92.0.0) (2024-09-10)
2
+
3
+
4
+ ### Features
5
+
6
+ * **Feedback:** Update feedback tokens ([2f47efa](https://gitlab.com/gitlab-org/gitlab-ui/commit/2f47efa9e71154b7567f59d4c2029095ea35d91b))
7
+ * **Modal:** Use new semantic bg tokens ([bf79388](https://gitlab.com/gitlab-org/gitlab-ui/commit/bf79388fc22d83a85408d9184b1072f288b144ac))
8
+ * **Popover:** Use new semantic bg tokens ([6113aa2](https://gitlab.com/gitlab-org/gitlab-ui/commit/6113aa2e62a1c898ab484ae6ef0ca3047405de25))
9
+ * **Toast:** Remove SCSS var ([fe32492](https://gitlab.com/gitlab-org/gitlab-ui/commit/fe3249273e048ace87c2e98398711032e3afc58a))
10
+
11
+
12
+ ### BREAKING CHANGES
13
+
14
+ * **Popover:** Update the popover to use new semantic overlap design
15
+ tokens and remove the contextual ones.
16
+
17
+ # [91.15.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v91.14.0...v91.15.0) (2024-09-10)
18
+
19
+
20
+ ### Features
21
+
22
+ * add duo chat context menu keyboard interactions ([a031d8c](https://gitlab.com/gitlab-org/gitlab-ui/commit/a031d8c823757e7a22138c3bdc7de9ff24c25da9))
23
+
1
24
  # [91.14.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v91.13.0...v91.14.0) (2024-09-10)
2
25
 
3
26
 
@@ -1,8 +1,8 @@
1
1
  import debounce from 'lodash/debounce';
2
2
  import { translate } from '../../../../../../../utils/i18n';
3
3
  import GlCard from '../../../../../../base/card/card';
4
- import { contextItemsValidator, categoriesValidator } from '../utils';
5
4
  import GlDuoChatContextItemSelections from '../duo_chat_context_item_selections/duo_chat_context_item_selections';
5
+ import { contextItemsValidator, categoriesValidator, wrapIndex } from '../utils';
6
6
  import GlDuoChatContextItemMenuCategoryItems from './duo_chat_context_item_menu_category_items';
7
7
  import GlDuoChatContextItemMenuSearchItems from './duo_chat_context_item_menu_search_items';
8
8
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
@@ -66,14 +66,17 @@ var script = {
66
66
  },
67
67
  data() {
68
68
  return {
69
- activeIndex: 0,
69
+ selectedCategory: null,
70
70
  searchQuery: '',
71
- selectedCategory: null
71
+ activeIndex: 0
72
72
  };
73
73
  },
74
74
  computed: {
75
75
  showCategorySelection() {
76
76
  return this.open && !this.selectedCategory;
77
+ },
78
+ allResultsAreDisabled() {
79
+ return this.results.every(result => !result.isEnabled);
77
80
  }
78
81
  },
79
82
  watch: {
@@ -84,14 +87,22 @@ var script = {
84
87
  },
85
88
  searchQuery(query) {
86
89
  this.debouncedSearch(query);
90
+ },
91
+ results(newResults) {
92
+ const firstEnabledIndex = newResults.findIndex(result => result.isEnabled);
93
+ this.activeIndex = firstEnabledIndex >= 0 ? firstEnabledIndex : 0;
87
94
  }
88
95
  },
89
96
  methods: {
90
97
  selectCategory(category) {
91
- this.activeIndex = 0;
92
98
  this.searchQuery = '';
93
99
  this.selectedCategory = category;
94
-
100
+ this.$emit('search', {
101
+ category: category.value,
102
+ query: ''
103
+ });
104
+ },
105
+ debouncedSearch: debounce(function search(query) {
95
106
  /**
96
107
  * Emitted when a search should be performed.
97
108
  * @property {Object} filter
@@ -99,10 +110,10 @@ var script = {
99
110
  * @property {string} filter.query - The search query
100
111
  */
101
112
  this.$emit('search', {
102
- category: category.value,
103
- query: ''
113
+ category: this.selectedCategory.value,
114
+ query
104
115
  });
105
- },
116
+ }, SEARCH_DEBOUNCE_MS),
106
117
  selectItem(item) {
107
118
  if (!item.isEnabled) {
108
119
  return;
@@ -127,15 +138,72 @@ var script = {
127
138
  */
128
139
  this.$emit('remove', item);
129
140
  },
130
- debouncedSearch: debounce(function search(query) {
131
- this.$emit('search', {
132
- category: this.selectedCategory.value,
133
- query
134
- });
135
- }, SEARCH_DEBOUNCE_MS),
136
141
  resetSelection() {
137
142
  this.selectedCategory = null;
143
+ this.searchQuery = '';
138
144
  this.activeIndex = 0;
145
+ },
146
+ async scrollActiveItemIntoView() {
147
+ await this.$nextTick();
148
+ const activeItem = document.getElementById(`dropdown-item-${this.activeIndex}`);
149
+ if (activeItem) {
150
+ activeItem.scrollIntoView({
151
+ block: 'nearest',
152
+ inline: 'start'
153
+ });
154
+ }
155
+ },
156
+ handleKeyUp(e) {
157
+ switch (e.key) {
158
+ case 'ArrowDown':
159
+ case 'ArrowUp':
160
+ e.preventDefault();
161
+ this.moveActiveIndex(e.key === 'ArrowDown' ? 1 : -1);
162
+ this.scrollActiveItemIntoView();
163
+ break;
164
+ case 'Enter':
165
+ e.preventDefault();
166
+ if (this.showCategorySelection) {
167
+ this.selectCategory(this.categories[this.activeIndex]);
168
+ return;
169
+ }
170
+ if (!this.results.length) {
171
+ return;
172
+ }
173
+ this.selectItem(this.results[this.activeIndex]);
174
+ break;
175
+ case 'Escape':
176
+ e.preventDefault();
177
+ if (this.showCategorySelection) {
178
+ this.$emit('close');
179
+ return;
180
+ }
181
+ this.selectedCategory = null;
182
+ break;
183
+ }
184
+ },
185
+ moveActiveIndex(step) {
186
+ if (this.showCategorySelection) {
187
+ // Categories cannot be disabled, so just loop to the next/prev one
188
+ this.activeIndex = wrapIndex(this.activeIndex, step, this.categories.length);
189
+ return;
190
+ }
191
+
192
+ // Return early if there are no results or all results are disabled
193
+ if (!this.results.length || this.allResultsAreDisabled) {
194
+ return;
195
+ }
196
+
197
+ // contextItems CAN be disabled, so loop to next/prev but ensure we don't land on a disabled one
198
+ let newIndex = this.activeIndex;
199
+ do {
200
+ newIndex = wrapIndex(newIndex, step, this.results.length);
201
+ if (newIndex === this.activeIndex) {
202
+ // If we've looped through all items and found no enabled ones, keep the current index
203
+ return;
204
+ }
205
+ } while (!this.results[newIndex].isEnabled);
206
+ this.activeIndex = newIndex;
139
207
  }
140
208
  },
141
209
  i18n: {
@@ -147,7 +215,7 @@ var script = {
147
215
  const __vue_script__ = script;
148
216
 
149
217
  /* template */
150
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[(_vm.selections.length)?_c('gl-duo-chat-context-item-selections',{staticClass:"gl-mb-3",attrs:{"selections":_vm.selections,"removable":true,"title":_vm.$options.i18n.selectedContextItemsTitle,"default-collapsed":false},on:{"remove":_vm.removeItem}}):_vm._e(),_vm._v(" "),(_vm.open)?_c('gl-card',{staticClass:"slash-commands !gl-absolute gl-bottom-0 gl-w-full gl-pl-0 gl-shadow-md",attrs:{"body-class":"!gl-p-2","data-testid":"context-item-menu"}},[(_vm.showCategorySelection)?_c('gl-duo-chat-context-item-menu-category-items',{attrs:{"active-index":_vm.activeIndex,"categories":_vm.categories},on:{"select":_vm.selectCategory,"active-index-change":function($event){_vm.activeIndex = $event;}}}):_c('gl-duo-chat-context-item-menu-search-items',{attrs:{"active-index":_vm.activeIndex,"category":_vm.selectedCategory,"loading":_vm.loading,"error":_vm.error,"results":_vm.results},on:{"select":_vm.selectItem,"active-index-change":function($event){_vm.activeIndex = $event;}},model:{value:(_vm.searchQuery),callback:function ($$v) {_vm.searchQuery=$$v;},expression:"searchQuery"}})],1):_vm._e()],1)};
218
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[(_vm.selections.length)?_c('gl-duo-chat-context-item-selections',{staticClass:"gl-mb-3",attrs:{"selections":_vm.selections,"removable":true,"title":_vm.$options.i18n.selectedContextItemsTitle,"default-collapsed":false},on:{"remove":_vm.removeItem}}):_vm._e(),_vm._v(" "),(_vm.open)?_c('gl-card',{staticClass:"slash-commands !gl-absolute gl-bottom-0 gl-w-full gl-pl-0 gl-shadow-md",attrs:{"body-class":"!gl-p-2","data-testid":"context-item-menu"}},[(_vm.showCategorySelection)?_c('gl-duo-chat-context-item-menu-category-items',{attrs:{"active-index":_vm.activeIndex,"categories":_vm.categories},on:{"select":_vm.selectCategory,"active-index-change":function($event){_vm.activeIndex = $event;}}}):_c('gl-duo-chat-context-item-menu-search-items',{attrs:{"active-index":_vm.activeIndex,"category":_vm.selectedCategory,"loading":_vm.loading,"error":_vm.error,"results":_vm.results},on:{"select":_vm.selectItem,"keyup":_vm.handleKeyUp,"active-index-change":function($event){_vm.activeIndex = $event;}},model:{value:(_vm.searchQuery),callback:function ($$v) {_vm.searchQuery=$$v;},expression:"searchQuery"}})],1):_vm._e()],1)};
151
219
  var __vue_staticRenderFns__ = [];
152
220
 
153
221
  /* style */
@@ -78,11 +78,17 @@ var script = {
78
78
  this.$emit('select', contextItem);
79
79
  this.userInitiatedSearch = false;
80
80
  },
81
+ handleKeyUp(e) {
82
+ this.$emit('keyup', e);
83
+ },
81
84
  setActiveIndex(index) {
82
85
  var _this$results$index;
83
86
  if ((_this$results$index = this.results[index]) !== null && _this$results$index !== void 0 && _this$results$index.isEnabled) {
84
87
  this.$emit('active-index-change', index);
85
88
  }
89
+ },
90
+ isActiveItem(contextItem, index) {
91
+ return index === this.activeIndex && contextItem.isEnabled;
86
92
  }
87
93
  },
88
94
  i18n: {
@@ -95,9 +101,9 @@ const __vue_script__ = script;
95
101
 
96
102
  /* template */
97
103
  var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('div',{staticClass:"gl-max-h-31 gl-overflow-y-scroll"},[(_vm.loading)?_c('gl-duo-chat-context-item-menu-search-items-loading',{attrs:{"rows":_vm.numLoadingItems}}):(_vm.error)?_c('gl-alert',{staticClass:"gl-m-3",attrs:{"variant":"danger","dismissible":false,"data-testid":"search-results-error"}},[_vm._v("\n "+_vm._s(_vm.error)+"\n ")]):(_vm.showEmptyState)?_c('div',{staticClass:"gl-rounded-base gl-p-3 gl-text-center gl-text-secondary",attrs:{"data-testid":"search-results-empty-state"}},[_vm._v("\n "+_vm._s(_vm.$options.i18n.emptyStateMessage)+"\n ")]):_c('ul',{staticClass:"gl-mb-1 gl-list-none gl-flex-row gl-pl-0"},_vm._l((_vm.results),function(contextItem,index){return _c('gl-dropdown-item',{key:contextItem.id,staticClass:"duo-chat-context-search-result-item",class:{
98
- 'active-command': index === _vm.activeIndex,
104
+ 'active-command': _vm.isActiveItem(contextItem, index),
99
105
  'gl-cursor-not-allowed [&>button]:focus-within:!gl-shadow-none': !contextItem.isEnabled,
100
- },attrs:{"id":("dropdown-item-" + index),"tabindex":!contextItem.isEnabled ? -1 : undefined,"data-testid":"search-result-item"},on:{"click":function($event){return _vm.selectItem(contextItem)}}},[_c('div',{on:{"mouseenter":function($event){return _vm.setActiveIndex(index)}}},[_c('gl-duo-chat-context-item-menu-search-item',{class:{ 'gl-text-secondary': !contextItem.isEnabled },attrs:{"context-item":contextItem,"category":_vm.category,"data-testid":"search-result-item-details"}})],1)])}),1)],1),_vm._v(" "),_c('gl-form-input',{ref:"contextMenuSearchInput",attrs:{"value":_vm.searchQuery,"placeholder":_vm.searchInputPlaceholder,"autofocus":"","data-testid":"context-menu-search-input"},on:{"input":function($event){return _vm.$emit('update:searchQuery', $event)}}})],1)};
106
+ },attrs:{"id":("dropdown-item-" + index),"tabindex":!contextItem.isEnabled ? -1 : undefined,"data-testid":"search-result-item"},on:{"click":function($event){return _vm.selectItem(contextItem)}}},[_c('div',{on:{"mouseenter":function($event){return _vm.setActiveIndex(index)}}},[_c('gl-duo-chat-context-item-menu-search-item',{class:{ 'gl-text-secondary': !contextItem.isEnabled },attrs:{"context-item":contextItem,"category":_vm.category,"data-testid":"search-result-item-details"}})],1)])}),1)],1),_vm._v(" "),_c('gl-form-input',{ref:"contextMenuSearchInput",attrs:{"value":_vm.searchQuery,"placeholder":_vm.searchInputPlaceholder,"autofocus":"","data-testid":"context-menu-search-input"},on:{"input":function($event){return _vm.$emit('update:searchQuery', $event)},"keyup":_vm.handleKeyUp}})],1)};
101
107
  var __vue_staticRenderFns__ = [];
102
108
 
103
109
  /* style */
@@ -22,4 +22,15 @@ function formatMergeRequestId(iid) {
22
22
  return `!${iid}`;
23
23
  }
24
24
 
25
- export { categoriesValidator, categoryValidator, contextItemValidator, contextItemsValidator, formatIssueId, formatMergeRequestId };
25
+ /**
26
+ * Calculates a new index within a range. If the new index would fall out of bounds, wraps to the start/end of the range.
27
+ * @param {number} currentIndex - The starting index.
28
+ * @param {number} step - The number of steps to move (positive or negative).
29
+ * @param {number} totalLength - The total number of items in the range.
30
+ * @returns {number} The new index.
31
+ */
32
+ function wrapIndex(currentIndex, step, totalLength) {
33
+ return (currentIndex + step + totalLength) % totalLength;
34
+ }
35
+
36
+ export { categoriesValidator, categoryValidator, contextItemValidator, contextItemsValidator, formatIssueId, formatMergeRequestId, wrapIndex };