@gitlab/ui 127.1.0 → 127.1.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "127.1.0",
3
+ "version": "127.1.1",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -24,6 +24,11 @@ function initialState() {
24
24
  return [createTerm()];
25
25
  }
26
26
 
27
+ function computeTokens(value, termsAsTokens) {
28
+ const resolved = value?.length ? cloneDeep(value) : initialState();
29
+ return needDenormalization(resolved) ? denormalizeTokens(resolved, termsAsTokens) : resolved;
30
+ }
31
+
27
32
  export default {
28
33
  name: 'GlFilteredSearch',
29
34
  components: {
@@ -174,7 +179,7 @@ export default {
174
179
  },
175
180
  data() {
176
181
  return {
177
- tokens: initialState(),
182
+ tokens: computeTokens(this.value, this.termsAsTokens),
178
183
  activeTokenIdx: null,
179
184
  suggestionsStyle: {},
180
185
  intendedCursorPosition: 'end',
@@ -239,20 +244,16 @@ export default {
239
244
  value: {
240
245
  handler(newValue, oldValue) {
241
246
  if (!isEqual(newValue, oldValue)) {
242
- const value = newValue.length ? newValue : initialState();
243
- this.applyNewValue(cloneDeep(value));
247
+ this.applyNewValue(newValue);
244
248
  }
245
249
  },
246
250
  deep: true,
247
- immediate: true,
248
251
  },
249
252
  },
250
253
 
251
254
  methods: {
252
255
  applyNewValue(newValue) {
253
- this.tokens = needDenormalization(newValue)
254
- ? denormalizeTokens(newValue, this.termsAsTokens)
255
- : newValue;
256
+ this.tokens = computeTokens(newValue, this.termsAsTokens);
256
257
  },
257
258
 
258
259
  isActiveToken(idx) {
@@ -1,5 +1,5 @@
1
1
  <script>
2
- import { stepIndexAndWrap } from './filtered_search_utils';
2
+ import { stepIndexAndWrap, FILTERED_SEARCH_SUGGESTIONS_CLASS } from './filtered_search_utils';
3
3
 
4
4
  const DEFER_TO_INITIAL_VALUE = -1;
5
5
  const NO_ACTIVE_ITEM = -2;
@@ -45,7 +45,7 @@ export default {
45
45
  return this.registeredItems[this.activeIdx];
46
46
  },
47
47
  listClasses() {
48
- return [this.suggestionsListClass(), 'dropdown-menu gl-filtered-search-suggestion-list'];
48
+ return [this.suggestionsListClass(), `dropdown-menu ${FILTERED_SEARCH_SUGGESTIONS_CLASS}`];
49
49
  },
50
50
  },
51
51
 
@@ -4,7 +4,13 @@ import { Portal } from 'portal-vue';
4
4
  import { LEFT_MOUSE_BUTTON } from '../../../utils/constants';
5
5
  import GlFilteredSearchSuggestion from './filtered_search_suggestion.vue';
6
6
  import GlFilteredSearchSuggestionList from './filtered_search_suggestion_list.vue';
7
- import { splitOnQuotes, wrapTokenInQuotes, match, TERM_TOKEN_TYPE } from './filtered_search_utils';
7
+ import {
8
+ splitOnQuotes,
9
+ wrapTokenInQuotes,
10
+ match,
11
+ TERM_TOKEN_TYPE,
12
+ FILTERED_SEARCH_SUGGESTIONS_CLASS,
13
+ } from './filtered_search_utils';
8
14
 
9
15
  // We need some helpers to ensure @vue/compat compatibility
10
16
  // @vue/compat will render comment nodes for v-if and comments in HTML
@@ -410,7 +416,14 @@ export default {
410
416
  });
411
417
  },
412
418
 
413
- handleBlur() {
419
+ handleBlur(e) {
420
+ // Keep focus on input when blur event is on same element
421
+ // (e.g. scrollbar in filtered search suggestions list)
422
+ if (e.relatedTarget?.classList.contains(FILTERED_SEARCH_SUGGESTIONS_CLASS)) {
423
+ this.$refs.input?.focus();
424
+ return;
425
+ }
426
+
414
427
  if (this.multiSelect) {
415
428
  this.$emit('complete');
416
429
  } else if (this.active) {
@@ -9,6 +9,8 @@ export const INTENT_ACTIVATE_PREVIOUS = 'intent-activate-previous';
9
9
 
10
10
  export const TOKEN_CLOSE_SELECTOR = '.gl-token-close';
11
11
 
12
+ export const FILTERED_SEARCH_SUGGESTIONS_CLASS = 'gl-filtered-search-suggestion-list';
13
+
12
14
  export function isEmptyTerm(token) {
13
15
  return token.type === TERM_TOKEN_TYPE && token.value.data.trim() === '';
14
16
  }
@@ -9,6 +9,7 @@ const DEFAULT_OPTIONS = {
9
9
  toastClass: 'gl-toast',
10
10
  isStatus: true,
11
11
  toaster: 'b-toaster-bottom-left',
12
+ appendToast: true,
12
13
  };
13
14
 
14
15
  let toastsCount = 0;
@@ -7,13 +7,20 @@
7
7
  .b-toaster-slot {
8
8
  @apply gl-w-auto;
9
9
  @apply gl-flex;
10
+ @apply gl-flex-col;
11
+ @apply gl-gap-4;
10
12
  bottom: $gl-spacing-scale-6;
11
13
  left: $gl-spacing-scale-6;
12
14
  right: auto;
13
- flex-direction: column-reverse;
14
- gap: $gl-spacing-scale-4;
15
15
  view-transition-name: gl-toast;
16
16
 
17
+ // Fallback for Firefox
18
+ // Fixes a bug where the view transition
19
+ // doesn’t work properly
20
+ @supports (-moz-appearance:none) {
21
+ view-transition-name: unset;
22
+ }
23
+
17
24
  @include media-breakpoint-down(xs) {
18
25
  @apply gl-w-full;
19
26
  left: 0;
@@ -22,6 +29,15 @@
22
29
  }
23
30
  }
24
31
 
32
+ .b-toast {
33
+ // Fallback for Firefox
34
+ // Fixes a bug where the view transition
35
+ // doesn’t work properly
36
+ @supports (-moz-appearance:none) {
37
+ transition: all $gl-transition-duration-medium $gl-easing-out-cubic;
38
+ }
39
+ }
40
+
25
41
  .gl-toast {
26
42
  @apply gl-text-base;
27
43
  @apply gl-py-5;