@gitlab/ui 91.4.0 → 91.6.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 (27) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu.js +162 -0
  3. package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_popover/duo_chat_context_item_popover.js +9 -0
  4. package/dist/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_selections/duo_chat_context_item_selections.js +28 -2
  5. package/dist/components/experimental/duo/chat/components/duo_chat_context/mock_context_data.js +26 -11
  6. package/dist/components/experimental/duo/chat/components/duo_chat_context/utils.js +17 -0
  7. package/dist/index.css +1 -1
  8. package/dist/index.css.map +1 -1
  9. package/dist/tokens/build/js/tokens.dark.js +5 -5
  10. package/dist/tokens/css/tokens.dark.css +5 -5
  11. package/dist/tokens/js/tokens.dark.js +5 -5
  12. package/dist/tokens/json/tokens.dark.json +10 -25
  13. package/dist/tokens/json/tokens.json +5 -20
  14. package/dist/tokens/scss/_tokens.dark.scss +5 -5
  15. package/package.json +3 -3
  16. package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_menu/duo_chat_context_item_menu.vue +168 -0
  17. package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_popover/duo_chat_context_item_popover.vue +9 -0
  18. package/src/components/experimental/duo/chat/components/duo_chat_context/duo_chat_context_item_selections/duo_chat_context_item_selections.vue +28 -1
  19. package/src/components/experimental/duo/chat/components/duo_chat_context/mock_context_data.js +22 -10
  20. package/src/components/experimental/duo/chat/components/duo_chat_context/utils.js +29 -0
  21. package/src/tokens/build/css/tokens.dark.css +5 -5
  22. package/src/tokens/build/js/tokens.dark.js +5 -5
  23. package/src/tokens/build/json/tokens.dark.json +10 -25
  24. package/src/tokens/build/json/tokens.json +5 -20
  25. package/src/tokens/build/scss/_tokens.dark.scss +5 -5
  26. package/src/tokens/contextual/alert.tokens.json +5 -20
  27. package/translations.js +1 -0
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [91.6.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v91.5.0...v91.6.0) (2024-09-04)
2
+
3
+
4
+ ### Features
5
+
6
+ * add initial duo chat context item menu component ([40635b0](https://gitlab.com/gitlab-org/gitlab-ui/commit/40635b0afbb33b099f48922a36498bd4b709df00))
7
+
8
+ # [91.5.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v91.4.0...v91.5.0) (2024-09-04)
9
+
10
+
11
+ ### Features
12
+
13
+ * **Alert:** Transparent border bottom ([30f1863](https://gitlab.com/gitlab-org/gitlab-ui/commit/30f1863f6921426ea4b907a3e0c74ed98b41e727))
14
+
1
15
  # [91.4.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v91.3.0...v91.4.0) (2024-09-02)
2
16
 
3
17
 
@@ -0,0 +1,162 @@
1
+ import { translate } from '../../../../../../../utils/i18n';
2
+ import GlCard from '../../../../../../base/card/card';
3
+ import GlDuoChatContextItemSelections from '../duo_chat_context_item_selections/duo_chat_context_item_selections';
4
+ import { contextItemsValidator, categoriesValidator } from '../utils';
5
+ import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
6
+
7
+ var script = {
8
+ name: 'GlDuoChatContextItemMenu',
9
+ components: {
10
+ GlCard,
11
+ GlDuoChatContextItemSelections
12
+ },
13
+ props: {
14
+ /**
15
+ * Whether the menu is open.
16
+ */
17
+ open: {
18
+ type: Boolean,
19
+ required: true
20
+ },
21
+ /**
22
+ * Array of selected context items.
23
+ */
24
+ selections: {
25
+ type: Array,
26
+ required: true,
27
+ validator: contextItemsValidator
28
+ },
29
+ /**
30
+ * Whether the menu is in a loading state.
31
+ */
32
+ loading: {
33
+ type: Boolean,
34
+ required: true
35
+ },
36
+ /**
37
+ * Error message to display, if any.
38
+ */
39
+ error: {
40
+ type: [String, null],
41
+ required: false,
42
+ default: null
43
+ },
44
+ /**
45
+ * Array of available categories for context items.
46
+ */
47
+ categories: {
48
+ type: Array,
49
+ required: true,
50
+ validator: categoriesValidator
51
+ },
52
+ /**
53
+ * Array of search results for context items.
54
+ */
55
+ results: {
56
+ type: Array,
57
+ required: true,
58
+ validator: contextItemsValidator
59
+ }
60
+ },
61
+ data() {
62
+ return {
63
+ selectedCategory: null
64
+ };
65
+ },
66
+ computed: {
67
+ showCategorySelection() {
68
+ return this.open && !this.selectedCategory;
69
+ }
70
+ },
71
+ watch: {
72
+ open(isOpen) {
73
+ if (!isOpen) {
74
+ this.resetSelection();
75
+ }
76
+ }
77
+ },
78
+ methods: {
79
+ selectCategory(category) {
80
+ this.selectedCategory = category;
81
+
82
+ /**
83
+ * Emitted when a search should be performed.
84
+ * @property {Object} filter
85
+ * @property {string} filter.category - The value of the selected category
86
+ * @property {string} filter.query - The search query
87
+ */
88
+ this.$emit('search', {
89
+ category: category.value,
90
+ query: ''
91
+ });
92
+ },
93
+ selectItem(item) {
94
+ if (!item.isEnabled) {
95
+ return;
96
+ }
97
+
98
+ /**
99
+ * Emitted when a context item is selected.
100
+ * @property {Object} item - The selected context item
101
+ */
102
+ this.$emit('select', this.results.find(result => result.id === item.id));
103
+
104
+ /**
105
+ * Emitted when the menu should be closed.
106
+ */
107
+ this.$emit('close');
108
+ this.resetSelection();
109
+ },
110
+ removeItem(item) {
111
+ /**
112
+ * Emitted when a context item should be removed.
113
+ * @property {Object} item - The context item to be removed
114
+ */
115
+ this.$emit('remove', item);
116
+ },
117
+ resetSelection() {
118
+ this.selectedCategory = null;
119
+ }
120
+ },
121
+ i18n: {
122
+ selectedContextItemsTitle: translate('GlDuoChatContextItemMenu.selectedContextItemsTitle', 'Included references')
123
+ }
124
+ };
125
+
126
+ /* script */
127
+ const __vue_script__ = script;
128
+
129
+ /* template */
130
+ 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('ul',{attrs:{"data-testid":"context-menu-category-items"}},_vm._l((_vm.categories),function(category){return _c('li',{key:category.value,on:{"click":function($event){return _vm.selectCategory(category)}}},[_vm._v("\n "+_vm._s(category.label)+"\n ")])}),0):_c('div',{attrs:{"data-testid":"context-menu-search-items"}},[(_vm.loading)?[_vm._v("Loading...")]:(_vm.error)?[_vm._v("Error: "+_vm._s(_vm.error))]:_c('ul',_vm._l((_vm.results),function(result){return _c('li',{key:result.id,on:{"click":function($event){return _vm.selectItem(result)}}},[_vm._v("\n "+_vm._s(result.metadata.name)+" "+_vm._s(result.isEnabled ? '' : '(disabled)')+"\n ")])}),0)],2)]):_vm._e()],1)};
131
+ var __vue_staticRenderFns__ = [];
132
+
133
+ /* style */
134
+ const __vue_inject_styles__ = undefined;
135
+ /* scoped */
136
+ const __vue_scope_id__ = undefined;
137
+ /* module identifier */
138
+ const __vue_module_identifier__ = undefined;
139
+ /* functional template */
140
+ const __vue_is_functional_template__ = false;
141
+ /* style inject */
142
+
143
+ /* style inject SSR */
144
+
145
+ /* style inject shadow dom */
146
+
147
+
148
+
149
+ const __vue_component__ = __vue_normalize__(
150
+ { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ },
151
+ __vue_inject_styles__,
152
+ __vue_script__,
153
+ __vue_scope_id__,
154
+ __vue_is_functional_template__,
155
+ __vue_module_identifier__,
156
+ false,
157
+ undefined,
158
+ undefined,
159
+ undefined
160
+ );
161
+
162
+ export default __vue_component__;
@@ -13,14 +13,23 @@ var script = {
13
13
  GlPopover
14
14
  },
15
15
  props: {
16
+ /**
17
+ * The context item to display in the popover.
18
+ */
16
19
  item: {
17
20
  type: Object,
18
21
  required: true
19
22
  },
23
+ /**
24
+ * The target element ID for the popover.
25
+ */
20
26
  target: {
21
27
  type: String,
22
28
  required: true
23
29
  },
30
+ /**
31
+ * The placement of the popover relative to the target.
32
+ */
24
33
  placement: {
25
34
  type: String,
26
35
  default: 'bottom',
@@ -3,6 +3,7 @@ import GlIcon from '../../../../../../base/icon/icon';
3
3
  import GlToken from '../../../../../../base/token/token';
4
4
  import GlDuoChatContextItemPopover from '../duo_chat_context_item_popover/duo_chat_context_item_popover';
5
5
  import { CONTEXT_ITEM_TYPE_PROJECT_FILE, CONTEXT_ITEM_TYPE_ISSUE, CONTEXT_ITEM_TYPE_MERGE_REQUEST } from '../constants';
6
+ import { contextItemsValidator } from '../utils';
6
7
  import __vue_normalize__ from 'vue-runtime-helpers/dist/normalize-component.js';
7
8
 
8
9
  var script = {
@@ -13,17 +14,35 @@ var script = {
13
14
  GlToken
14
15
  },
15
16
  props: {
17
+ /**
18
+ * Array of selected context items.
19
+ */
16
20
  selections: {
17
21
  type: Array,
18
- required: true
22
+ required: true,
23
+ validator: contextItemsValidator
19
24
  },
25
+ /**
26
+ * The title to display for the selections.
27
+ */
20
28
  title: {
21
29
  type: String,
22
30
  required: true
23
31
  },
32
+ /**
33
+ * Whether the selections should be collapsed by default.
34
+ */
24
35
  defaultCollapsed: {
25
36
  type: Boolean,
26
37
  required: true
38
+ },
39
+ /**
40
+ * Whether the selections can be removed.
41
+ */
42
+ removable: {
43
+ type: Boolean,
44
+ required: false,
45
+ default: false
27
46
  }
28
47
  },
29
48
  data() {
@@ -48,6 +67,13 @@ var script = {
48
67
  },
49
68
  toggleCollapse() {
50
69
  this.isCollapsed = !this.isCollapsed;
70
+ },
71
+ onRemoveItem(item) {
72
+ /**
73
+ * Emitted when a context item should be removed.
74
+ * @property {Object} item - The context item to be removed
75
+ */
76
+ this.$emit('remove', item);
51
77
  }
52
78
  }
53
79
  };
@@ -56,7 +82,7 @@ var script = {
56
82
  const __vue_script__ = script;
57
83
 
58
84
  /* template */
59
- var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-mb-3 gl-flex gl-flex-col"},[_c('button',{staticClass:"gl-flex gl-w-full gl-items-center gl-border-0 gl-bg-transparent gl-p-0 gl-text-left gl-text-xs gl-lowercase gl-text-gray-500",attrs:{"data-testid":"chat-context-selections-title"},on:{"click":_vm.toggleCollapse}},[_c('gl-icon',{attrs:{"name":_vm.collapseIconName,"data-testid":"chat-context-collapse-icon"}}),_vm._v(" "+_vm._s(_vm.title)+"\n ")],1),_vm._v(" "),_c('div',{directives:[{name:"show",rawName:"v-show",value:(!_vm.isCollapsed),expression:"!isCollapsed"}],staticClass:"gl-mt-1 gl-flex gl-grow gl-flex-wrap",attrs:{"data-testid":"chat-context-tokens-wrapper"}},_vm._l((_vm.selections),function(item){return _c('gl-token',{key:item.id,staticClass:"gl-mb-2 gl-mr-2",attrs:{"view-only":true,"variant":"default"}},[_c('div',{staticClass:"gl-flex gl-items-center",attrs:{"id":("context-item-" + (item.id) + "-" + _vm.selectionsId)}},[_c('gl-icon',{staticClass:"gl-mr-1",attrs:{"name":_vm.getIconName(item.type),"size":12}}),_vm._v("\n "+_vm._s(item.metadata.name)+"\n ")],1),_vm._v(" "),_c('gl-duo-chat-context-item-popover',{attrs:{"item":item,"target":("context-item-" + (item.id) + "-" + _vm.selectionsId),"placement":"bottom"}})],1)}),1)])};
85
+ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:"gl-mb-3 gl-flex gl-flex-col"},[_c('button',{staticClass:"gl-flex gl-w-full gl-items-center gl-border-0 gl-bg-transparent gl-p-0 gl-text-left gl-text-xs gl-lowercase gl-text-gray-500",attrs:{"data-testid":"chat-context-selections-title"},on:{"click":_vm.toggleCollapse}},[_c('gl-icon',{attrs:{"name":_vm.collapseIconName,"data-testid":"chat-context-collapse-icon"}}),_vm._v(" "+_vm._s(_vm.title)+"\n ")],1),_vm._v(" "),_c('div',{directives:[{name:"show",rawName:"v-show",value:(!_vm.isCollapsed),expression:"!isCollapsed"}],staticClass:"gl-mt-1 gl-flex gl-grow gl-flex-wrap",attrs:{"data-testid":"chat-context-tokens-wrapper"}},_vm._l((_vm.selections),function(item){return _c('gl-token',{key:item.id,staticClass:"gl-mb-2 gl-mr-2",attrs:{"view-only":!_vm.removable,"variant":"default"},on:{"close":function($event){return _vm.onRemoveItem(item)}}},[_c('div',{staticClass:"gl-flex gl-items-center",attrs:{"id":("context-item-" + (item.id) + "-" + _vm.selectionsId)}},[_c('gl-icon',{staticClass:"gl-mr-1",attrs:{"name":_vm.getIconName(item.type),"size":12}}),_vm._v("\n "+_vm._s(item.metadata.name)+"\n ")],1),_vm._v(" "),_c('gl-duo-chat-context-item-popover',{attrs:{"item":item,"target":("context-item-" + (item.id) + "-" + _vm.selectionsId),"placement":"bottom"}})],1)}),1)])};
60
86
  var __vue_staticRenderFns__ = [];
61
87
 
62
88
  /* style */
@@ -1,3 +1,18 @@
1
+ import { CONTEXT_ITEM_TYPE_PROJECT_FILE, CONTEXT_ITEM_TYPE_ISSUE, CONTEXT_ITEM_TYPE_MERGE_REQUEST } from './constants';
2
+
3
+ const MOCK_CATEGORIES = [{
4
+ label: 'Files',
5
+ value: CONTEXT_ITEM_TYPE_PROJECT_FILE,
6
+ icon: 'document'
7
+ }, {
8
+ label: 'Issues',
9
+ value: CONTEXT_ITEM_TYPE_ISSUE,
10
+ icon: 'issues'
11
+ }, {
12
+ label: 'Merge Requests',
13
+ value: CONTEXT_ITEM_TYPE_MERGE_REQUEST,
14
+ icon: 'merge-request'
15
+ }];
1
16
  const MOCK_CONTEXT_ITEM_FILE = {
2
17
  id: '123e4567-e89b-12d3-a456-426614174000',
3
18
  isEnabled: true,
@@ -8,7 +23,7 @@ const MOCK_CONTEXT_ITEM_FILE = {
8
23
  relFilePath: 'src/plants/strawberry.ts'
9
24
  }
10
25
  },
11
- type: 'project_file'
26
+ type: CONTEXT_ITEM_TYPE_PROJECT_FILE
12
27
  };
13
28
  const MOCK_CONTEXT_ITEM_FILE_DISABLED = {
14
29
  id: '323e4567-e89b-12d3-a456-426614174002',
@@ -20,7 +35,7 @@ const MOCK_CONTEXT_ITEM_FILE_DISABLED = {
20
35
  relFilePath: '/src/VehicleFoo/motorbike.cs'
21
36
  }
22
37
  },
23
- type: 'project_file'
38
+ type: CONTEXT_ITEM_TYPE_PROJECT_FILE
24
39
  };
25
40
  const mockFiles = [MOCK_CONTEXT_ITEM_FILE, {
26
41
  id: '223e4567-e89b-12d3-a456-426614174001',
@@ -32,7 +47,7 @@ const mockFiles = [MOCK_CONTEXT_ITEM_FILE, {
32
47
  relFilePath: '/src/plants/potato.ts'
33
48
  }
34
49
  },
35
- type: 'project_file'
50
+ type: CONTEXT_ITEM_TYPE_PROJECT_FILE
36
51
  }, MOCK_CONTEXT_ITEM_FILE_DISABLED];
37
52
  const MOCK_CONTEXT_ITEM_ISSUE = {
38
53
  id: '423e4567-e89b-12d3-a456-426614174003',
@@ -44,20 +59,20 @@ const MOCK_CONTEXT_ITEM_ISSUE = {
44
59
  iid: 1234
45
60
  }
46
61
  },
47
- type: 'issue'
62
+ type: CONTEXT_ITEM_TYPE_ISSUE
48
63
  };
49
64
  const MOCK_CONTEXT_ITEM_ISSUE_DISABLED = {
50
65
  id: 'c463fb31-2a4c-4f8e-a609-97230ac48ae5',
51
66
  isEnabled: false,
52
67
  metadata: {
53
- name: 'Fix vehicle colours',
68
+ name: `Fix vehicle colours and make them look real nice and colourful won't that be wonderful wow this issue title is really long I sure hope it's gonna wrap OK`,
54
69
  info: {
55
70
  project: 'example/vehicle',
56
71
  iid: 91011
57
72
  }
58
73
  },
59
74
  disabledReasons: ['This foo is not available to bar', 'Lorem something something wow?'],
60
- type: 'issue'
75
+ type: CONTEXT_ITEM_TYPE_ISSUE
61
76
  };
62
77
  const mockIssues = [MOCK_CONTEXT_ITEM_ISSUE, {
63
78
  id: '523e4567-e89b-12d3-a456-426614174004',
@@ -69,7 +84,7 @@ const mockIssues = [MOCK_CONTEXT_ITEM_ISSUE, {
69
84
  iid: 5678
70
85
  }
71
86
  },
72
- type: 'issue'
87
+ type: CONTEXT_ITEM_TYPE_ISSUE
73
88
  }, MOCK_CONTEXT_ITEM_ISSUE_DISABLED];
74
89
  const MOCK_CONTEXT_ITEM_MERGE_REQUEST = {
75
90
  id: '623e4567-e89b-12d3-a456-426614174005',
@@ -81,7 +96,7 @@ const MOCK_CONTEXT_ITEM_MERGE_REQUEST = {
81
96
  iid: 1122
82
97
  }
83
98
  },
84
- type: 'merge_request'
99
+ type: CONTEXT_ITEM_TYPE_MERGE_REQUEST
85
100
  };
86
101
  const MOCK_CONTEXT_ITEM_MERGE_REQUEST_DISABLED = {
87
102
  id: '4eb665fc-e5e1-49b0-9789-2a16964e461a',
@@ -94,7 +109,7 @@ const MOCK_CONTEXT_ITEM_MERGE_REQUEST_DISABLED = {
94
109
  }
95
110
  },
96
111
  disabledReasons: ['This foo is not available to bar', 'Lorem something something wow?'],
97
- type: 'merge_request'
112
+ type: CONTEXT_ITEM_TYPE_MERGE_REQUEST
98
113
  };
99
114
  const mockMergeRequests = [MOCK_CONTEXT_ITEM_MERGE_REQUEST, {
100
115
  id: '723e4567-e89b-12d3-a456-426614174006',
@@ -107,7 +122,7 @@ const mockMergeRequests = [MOCK_CONTEXT_ITEM_MERGE_REQUEST, {
107
122
  }
108
123
  },
109
124
  disabledReasons: ['This foo is not available to bar', 'Lorem something something wow?'],
110
- type: 'merge_request'
125
+ type: CONTEXT_ITEM_TYPE_MERGE_REQUEST
111
126
  }, MOCK_CONTEXT_ITEM_MERGE_REQUEST_DISABLED];
112
127
  const getMockContextItems = () => {
113
128
  const allItems = [...mockFiles, ...mockIssues, ...mockMergeRequests];
@@ -118,4 +133,4 @@ const getMockContextItems = () => {
118
133
  return [...enabledItems, ...disabledItems];
119
134
  };
120
135
 
121
- export { MOCK_CONTEXT_ITEM_FILE, MOCK_CONTEXT_ITEM_FILE_DISABLED, MOCK_CONTEXT_ITEM_ISSUE, MOCK_CONTEXT_ITEM_ISSUE_DISABLED, MOCK_CONTEXT_ITEM_MERGE_REQUEST, MOCK_CONTEXT_ITEM_MERGE_REQUEST_DISABLED, getMockContextItems };
136
+ export { MOCK_CATEGORIES, MOCK_CONTEXT_ITEM_FILE, MOCK_CONTEXT_ITEM_FILE_DISABLED, MOCK_CONTEXT_ITEM_ISSUE, MOCK_CONTEXT_ITEM_ISSUE_DISABLED, MOCK_CONTEXT_ITEM_MERGE_REQUEST, MOCK_CONTEXT_ITEM_MERGE_REQUEST_DISABLED, getMockContextItems };
@@ -0,0 +1,17 @@
1
+ function categoryValidator(category) {
2
+ return Boolean(category && category.value && category.label && category.icon);
3
+ }
4
+ function categoriesValidator(categories) {
5
+ return Array.isArray(categories) && categories.every(category => categoryValidator(category));
6
+ }
7
+ function disabledReasonsValidator(disabledReasons) {
8
+ return disabledReasons === undefined || Array.isArray(disabledReasons) && disabledReasons.every(reason => typeof reason === 'string');
9
+ }
10
+ function contextItemValidator(item) {
11
+ return Boolean(item && item.id && item.type && typeof item.isEnabled === 'boolean' && disabledReasonsValidator(item.disabledReasons));
12
+ }
13
+ function contextItemsValidator(items) {
14
+ return Array.isArray(items) && items.every(item => contextItemValidator(item));
15
+ }
16
+
17
+ export { categoriesValidator, contextItemsValidator };