design-system-next 2.19.3 → 2.19.4

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.
@@ -36,6 +36,10 @@ export const listPropTypes = {
36
36
  type: String,
37
37
  default: '',
38
38
  },
39
+ supportingDisplayText: {
40
+ type: String,
41
+ default: '',
42
+ },
39
43
  menuList: {
40
44
  type: Array as PropType<MenuListType[]>,
41
45
  required: true,
@@ -91,15 +95,24 @@ export const listPropTypes = {
91
95
  type: [String, Number] as PropType<string | number>,
92
96
  default: 0,
93
97
  },
98
+ displayListItemSelected: {
99
+ type: Boolean,
100
+ default: false,
101
+ },
94
102
  itemIcon: {
95
103
  type: String,
96
104
  default: '',
97
105
  },
106
+ disabledUnselectedItems: {
107
+ type: Boolean,
108
+ default: false,
109
+ },
98
110
  };
99
111
 
100
112
  export const listEmitTypes = {
101
113
  'update:modelValue': (value: MenuListType[]) => value,
102
114
  'update:searchValue': (value: string) => typeof value === 'string',
115
+ 'get-single-selected-item': (item: MenuListType) => item,
103
116
  };
104
117
 
105
118
  export type ListPropTypes = ExtractPropTypes<typeof listPropTypes>;
@@ -1,21 +1,36 @@
1
1
  <template>
2
2
  <div class="spr-font-main">
3
- <div
4
- v-if="props.searchableMenu"
5
- :class="[
6
- 'spr-sticky spr-z-20',
7
- 'spr-grid spr-gap-3 spr-bg-white-50 spr-p-size-spacing-3xs',
8
- 'spr-border-color-weak spr-border spr-border-x-0 spr-border-b spr-border-t-0 spr-border-solid',
9
- ]"
10
- :style="{
11
- top:
12
- typeof props.stickySearchOffset === 'number'
13
- ? props.stickySearchOffset + 'px'
14
- : String(props.stickySearchOffset),
15
- }"
16
- >
17
- <spr-input-search v-model="searchText" :placeholder="props.searchableMenuPlaceholder" autocomplete="off" />
18
- </div>
3
+ <template v-if="props.searchableMenu || props.displayListItemSelected">
4
+ <div
5
+ :class="[
6
+ 'spr-sticky spr-z-20',
7
+ 'spr-grid spr-gap-3 spr-bg-white-50 spr-px-size-spacing-3xs spr-py-size-spacing-2xs',
8
+ 'spr-border-color-weak spr-border spr-border-x-0 spr-border-b spr-border-t-0 spr-border-solid',
9
+ ]"
10
+ :style="{
11
+ top:
12
+ typeof props.stickySearchOffset === 'number'
13
+ ? props.stickySearchOffset + 'px'
14
+ : String(props.stickySearchOffset),
15
+ }"
16
+ >
17
+ <spr-input-search
18
+ v-if="props.searchableMenu"
19
+ v-model="searchText"
20
+ :placeholder="props.searchableMenuPlaceholder"
21
+ autocomplete="off"
22
+ />
23
+ <span
24
+ v-if="props.supportingDisplayText || props.displayListItemSelected"
25
+ class="spr-label-sm-medium spr-text-color-base spr-block"
26
+ >
27
+ <template v-if="props.supportingDisplayText">
28
+ {{ props.supportingDisplayText }}
29
+ </template>
30
+ <template v-else> {{ selectedItems.length }} Selected</template>
31
+ </span>
32
+ </div>
33
+ </template>
19
34
 
20
35
  <div class="spr-p-size-spacing-3xs">
21
36
  <template v-if="props.groupItemsBy">
@@ -38,7 +53,11 @@
38
53
  >
39
54
  <template v-if="props.lozenge">
40
55
  <div class="spr-flex spr-items-center spr-gap-1">
41
- <spr-checkbox v-if="props.multiSelect" :disabled="item.disabled" :checked="isItemSelected(item)" />
56
+ <spr-checkbox
57
+ v-if="props.multiSelect"
58
+ :disabled="item.disabled || (props.disabledUnselectedItems && !isItemSelected(item))"
59
+ :checked="isItemSelected(item)"
60
+ />
42
61
  <spr-lozenge
43
62
  v-if="props.lozenge"
44
63
  :label="item.text || (item.lozengeProps?.label as string)"
@@ -52,23 +71,45 @@
52
71
  </template>
53
72
  <template v-else>
54
73
  <div class="spr-flex spr-items-center spr-gap-1">
55
- <spr-checkbox v-if="props.multiSelect" :disabled="item.disabled" :checked="isItemSelected(item)" />
74
+ <spr-checkbox
75
+ v-if="props.multiSelect"
76
+ :disabled="item.disabled || (props.disabledUnselectedItems && !isItemSelected(item))"
77
+ :checked="isItemSelected(item)"
78
+ />
56
79
  <div :class="[item.textColor, 'spr-flex spr-flex-row spr-items-center spr-gap-size-spacing-3xs']">
57
- <span v-if="props.itemIcon || item.icon" :class="[item.iconColor, 'spr-mt-[2px]']">
80
+ <span
81
+ v-if="props.itemIcon || item.icon"
82
+ :class="[
83
+ item.iconColor,
84
+ 'spr-mt-[2px]',
85
+ {
86
+ 'spr-text-color-disabled':
87
+ item.disabled || (props.disabledUnselectedItems && !isItemSelected(item)),
88
+ },
89
+ ]"
90
+ >
58
91
  <icon :icon="(props.itemIcon || item.icon) as string" width="20px" height="20px" />
59
92
  </span>
60
93
  <div
61
94
  :class="[
62
95
  'spr-flex spr-flex-auto spr-flex-col spr-justify-start',
63
- { 'spr-text-color-disabled': item.disabled },
96
+ {
97
+ 'spr-text-color-disabled':
98
+ item.disabled || (props.disabledUnselectedItems && !isItemSelected(item)),
99
+ },
64
100
  ]"
65
101
  >
66
- <span class="spr-text-left spr-text-xs">{{ item.text }}</span>
102
+ <span class="spr-break-words spr-text-left spr-text-xs">
103
+ {{ item.text }}
104
+ </span>
67
105
  <span
68
106
  v-if="item.subtext"
69
107
  :class="[
70
- 'spr-body-xs-regular spr-text-color-base spr-text-left',
71
- { 'spr-text-color-disabled': item.disabled },
108
+ 'spr-body-xs-regular spr-text-color-base spr-break-words spr-text-left',
109
+ {
110
+ 'spr-text-color-disabled':
111
+ item.disabled || (props.disabledUnselectedItems && !isItemSelected(item)),
112
+ },
72
113
  ]"
73
114
  >
74
115
  {{ item.subtext }}
@@ -128,7 +169,11 @@
128
169
  >
129
170
  <template v-if="props.lozenge">
130
171
  <div class="spr-flex spr-items-center spr-gap-1">
131
- <spr-checkbox v-if="props.multiSelect" :disabled="item.disabled" :checked="isItemSelected(item)" />
172
+ <spr-checkbox
173
+ v-if="props.multiSelect"
174
+ :disabled="item.disabled || (props.disabledUnselectedItems && !isItemSelected(item))"
175
+ :checked="isItemSelected(item)"
176
+ />
132
177
  <spr-lozenge
133
178
  v-if="props.lozenge"
134
179
  :label="item.text || (item.lozengeProps?.label as string)"
@@ -142,23 +187,45 @@
142
187
  </template>
143
188
  <template v-else>
144
189
  <div class="spr-flex spr-items-center spr-gap-1">
145
- <spr-checkbox v-if="props.multiSelect" :disabled="item.disabled" :checked="isItemSelected(item)" />
190
+ <spr-checkbox
191
+ v-if="props.multiSelect"
192
+ :disabled="item.disabled || (props.disabledUnselectedItems && !isItemSelected(item))"
193
+ :checked="isItemSelected(item)"
194
+ />
146
195
  <div :class="[item.textColor, 'spr-flex spr-flex-row spr-items-center spr-gap-size-spacing-3xs']">
147
- <span v-if="props.itemIcon || item.icon" :class="[item.iconColor, 'spr-mt-[2px]']">
196
+ <span
197
+ v-if="props.itemIcon || item.icon"
198
+ :class="[
199
+ item.iconColor,
200
+ 'spr-mt-[2px]',
201
+ {
202
+ 'spr-text-color-disabled':
203
+ item.disabled || (props.disabledUnselectedItems && !isItemSelected(item)),
204
+ },
205
+ ]"
206
+ >
148
207
  <icon :icon="(props.itemIcon || item.icon) as string" width="20px" height="20px" />
149
208
  </span>
150
209
  <div
151
210
  :class="[
152
211
  'spr-flex spr-flex-auto spr-flex-col spr-justify-start',
153
- { 'spr-text-color-disabled': item.disabled },
212
+ {
213
+ 'spr-text-color-disabled':
214
+ item.disabled || (props.disabledUnselectedItems && !isItemSelected(item)),
215
+ },
154
216
  ]"
155
217
  >
156
- <span class="spr-text-left spr-text-xs">{{ item.text }}</span>
218
+ <span class="spr-break-words spr-text-left spr-text-xs">
219
+ {{ item.text }}
220
+ </span>
157
221
  <span
158
222
  v-if="item.subtext"
159
223
  :class="[
160
- 'spr-body-xs-regular spr-text-color-base spr-text-left',
161
- { 'spr-text-color-disabled': item.disabled },
224
+ 'spr-body-xs-regular spr-text-color-base spr-break-words spr-text-left',
225
+ {
226
+ 'spr-text-color-disabled':
227
+ item.disabled || (props.disabledUnselectedItems && !isItemSelected(item)),
228
+ },
162
229
  ]"
163
230
  >
164
231
  {{ item.subtext }}
@@ -225,6 +292,13 @@ import { useList } from './use-list';
225
292
  const props = defineProps(listPropTypes);
226
293
  const emit = defineEmits(listEmitTypes);
227
294
 
228
- const { searchText, localizedMenuList, groupedMenuList, isItemSelected, getListItemClasses, handleSelectedItem } =
229
- useList(props, emit);
295
+ const {
296
+ selectedItems,
297
+ searchText,
298
+ localizedMenuList,
299
+ groupedMenuList,
300
+ isItemSelected,
301
+ getListItemClasses,
302
+ handleSelectedItem,
303
+ } = useList(props, emit);
230
304
  </script>
@@ -14,8 +14,16 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
14
14
  const selectedItems = useVModel(props, 'modelValue', emit);
15
15
  const searchString = useVModel(props, 'searchValue', emit);
16
16
 
17
- const { menuList, menuLevel, groupItemsBy, multiSelect, preSelectedItems, disabledLocalSearch, noCheck } =
18
- toRefs(props);
17
+ const {
18
+ menuList,
19
+ menuLevel,
20
+ groupItemsBy,
21
+ multiSelect,
22
+ preSelectedItems,
23
+ disabledLocalSearch,
24
+ noCheck,
25
+ disabledUnselectedItems,
26
+ } = toRefs(props);
19
27
 
20
28
  const listClasses: ComputedRef<ListClasses> = computed(() => {
21
29
  const listItemClasses = classNames(
@@ -161,6 +169,7 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
161
169
 
162
170
  if (previousSelected) {
163
171
  handleSelectedItem(item);
172
+
164
173
  return true;
165
174
  }
166
175
 
@@ -341,10 +350,10 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
341
350
  };
342
351
 
343
352
  const getListItemClasses = (item: MenuListType) => ({
344
- [listClasses.value.listItemClasses]: !item.disabled,
353
+ [listClasses.value.listItemClasses]: !item.disabled && !(disabledUnselectedItems.value && !isItemSelected(item)),
345
354
  'spr-background-color-single-active': isItemSelected(item) && !item.disabled && !noCheck.value,
346
- 'hover:spr-cursor-not-allowed spr-flex spr-cursor-pointer spr-items-center spr-gap-1.5 spr-rounded-lg':
347
- item.disabled,
355
+ 'spr-cursor-not-allowed spr-flex spr-items-center spr-gap-1.5 spr-rounded-lg':
356
+ item.disabled || (disabledUnselectedItems.value && !isItemSelected(item)),
348
357
  'spr-p-size-spacing-3xs': !props.lozenge,
349
358
  'spr-py-size-spacing-3xs spr-px-size-spacing-4xs': props.lozenge,
350
359
  });
@@ -420,6 +429,8 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
420
429
  const handleSelectedItem = (item: MenuListType) => {
421
430
  if (item.disabled) return;
422
431
 
432
+ if (disabledUnselectedItems.value && !isItemSelected(item)) return;
433
+
423
434
  if (multiSelect.value) {
424
435
  // For multi-select, check if item is already selected
425
436
  const index = selectedItems.value.findIndex((selectedItem: MenuListType) => {
@@ -488,8 +499,11 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
488
499
  } else {
489
500
  // For single-select, simply replace the selection
490
501
  selectedItems.value = [item];
502
+
491
503
  if (item.onClickFn) item.onClickFn();
492
504
  }
505
+
506
+ emit('get-single-selected-item', item);
493
507
  };
494
508
  // #endregion - Helper Methods
495
509
 
@@ -567,11 +581,13 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
567
581
 
568
582
  onMounted(() => {
569
583
  searchString.value = searchText.value;
584
+
570
585
  setMenuList();
571
586
  setPreSelectedItems();
572
587
  });
573
588
 
574
589
  return {
590
+ selectedItems,
575
591
  searchText,
576
592
  listClasses,
577
593
  localizedMenuList,
@@ -123,10 +123,22 @@ export const multiSelectPropTypes = {
123
123
  type: String,
124
124
  default: '',
125
125
  },
126
+ supportingDisplayText: {
127
+ type: String,
128
+ default: '',
129
+ },
130
+ persistentDisplayText: {
131
+ type: Boolean,
132
+ default: false,
133
+ },
126
134
  displaySelectedCountOnly: {
127
135
  type: Boolean,
128
136
  default: false,
129
137
  },
138
+ displayListItemSelected: {
139
+ type: Boolean,
140
+ default: false,
141
+ },
130
142
  displayHelper: {
131
143
  type: Boolean,
132
144
  default: false,
@@ -179,14 +191,22 @@ export const multiSelectPropTypes = {
179
191
  type: String,
180
192
  default: '',
181
193
  },
194
+ disabledUnselectedItems: {
195
+ type: Boolean,
196
+ default: false,
197
+ },
182
198
  };
183
199
 
184
200
  export const multiSelectEmitTypes = {
185
201
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
186
202
  'update:modelValue': (_value: unknown) => true,
187
203
  'update:searchValue': (value: string) => typeof value === 'string',
204
+ 'search-string': (value: string) => typeof value === 'string',
188
205
  'infinite-scroll-trigger': Boolean,
189
206
  'popper-state': Boolean,
207
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
208
+ 'get-selected-options': (_value: unknown) => true,
209
+ 'get-single-selected-item': (item: MenuListType) => item,
190
210
  };
191
211
 
192
212
  export type MultiSelectPropTypes = ExtractPropTypes<typeof multiSelectPropTypes>;
@@ -49,9 +49,7 @@
49
49
  class="spr-text-color-supporting spr-px-3"
50
50
  :aria-label="`${multiSelectedListItems.length} selected options`"
51
51
  >
52
- {{ multiSelectedListItems.length }} item{{
53
- multiSelectedListItems.length === 1 ? '' : 's'
54
- }}
52
+ {{ multiSelectedListItems.length }} item{{ multiSelectedListItems.length === 1 ? '' : 's' }}
55
53
  selected
56
54
  </span>
57
55
  </template>
@@ -164,9 +162,13 @@
164
162
  :loading="props.loading"
165
163
  :item-icon="props.itemIcon"
166
164
  :lozenge="props.lozenge"
167
- multi-select
165
+ :supporting-display-text="props.supportingDisplayText"
166
+ :display-list-item-selected="props.displayListItemSelected"
168
167
  :disabled-local-search="props.disabledLocalSearch"
168
+ :disabled-unselected-items="props.disabledUnselectedItems"
169
+ multi-select
169
170
  @update:model-value="handleMultiSelectedItem"
171
+ @get-single-selected-item="emit('get-single-selected-item', $event)"
170
172
  />
171
173
  </div>
172
174
  </template>
@@ -19,7 +19,7 @@ interface MultiSelectClasses {
19
19
  }
20
20
 
21
21
  export const useMultiSelect = (props: MultiSelectPropTypes, emit: SetupContext<MultiSelectEmitTypes>['emit']) => {
22
- const { displayText, options, textField, valueField, active, disabled, error, disabledLocalSearch } = toRefs(props);
22
+ const { displayText, persistentDisplayText, options, textField, valueField, active, disabled, error } = toRefs(props);
23
23
 
24
24
  const multiSelectClasses: ComputedRef<MultiSelectClasses> = computed(() => {
25
25
  const baseClasses = classNames('spr-flex spr-flex-col spr-gap-size-spacing-4xs');
@@ -106,7 +106,6 @@ export const useMultiSelect = (props: MultiSelectPropTypes, emit: SetupContext<M
106
106
  const hasUserSelected = ref(false);
107
107
 
108
108
  const inputText = ref<string | number>('');
109
- const inputTextBackup = ref<string | number>('');
110
109
  const chippedInputTextRef = ref(null);
111
110
 
112
111
  const search = useVModel(props, 'searchValue', emit);
@@ -201,18 +200,15 @@ export const useMultiSelect = (props: MultiSelectPropTypes, emit: SetupContext<M
201
200
  return item.value;
202
201
  }
203
202
  }
204
-
205
203
  return item.value;
206
204
  });
207
205
 
208
206
  hasUserSelected.value = true;
209
207
  multiSelectModel.value = selectedValues;
210
- inputTextBackup.value =
211
- multiSelectedItems.length > 3
212
- ? `${multiSelectedItems.length} items selected`
213
- : multiSelectedItems.map((item) => item.text).join(', ');
214
208
 
215
209
  updateMultiSelectedItemsFromValue();
210
+
211
+ emit('get-selected-options', multiSelectedItems);
216
212
  };
217
213
 
218
214
  /**
@@ -256,64 +252,92 @@ export const useMultiSelect = (props: MultiSelectPropTypes, emit: SetupContext<M
256
252
  * Handles stringified objects and updates the input text accordingly.
257
253
  */
258
254
  const updateMultiSelectedItemsFromValue = () => {
259
- if (!multiSelectOptions.value.length) return;
255
+ const values = normalizedValue.value;
260
256
 
261
- if (!disabledLocalSearch.value) {
262
- const values = normalizedValue.value;
263
- if (!values || !values.length) {
264
- multiSelectedListItems.value = [];
265
- inputText.value = '';
266
- inputTextBackup.value = '';
257
+ if (!values || !values.length) {
258
+ multiSelectedListItems.value = [];
267
259
 
268
- return;
260
+ // Always show displayText if provided and no selected items
261
+ if (displayText.value) {
262
+ inputText.value = displayText.value;
263
+ } else if (!persistentDisplayText.value) {
264
+ inputText.value = '';
269
265
  }
270
- multiSelectedListItems.value = multiSelectOptions.value.filter((item) => {
271
- return values.some((val) => {
272
- let itemVal = item.value;
273
- let valToCompare = val;
274
-
275
- if (typeof itemVal === 'string' && itemVal.startsWith('{') && itemVal.endsWith('}')) {
276
- try {
277
- itemVal = JSON.parse(itemVal);
278
- } catch {
279
- // ignore
280
- }
281
- }
282
266
 
283
- if (typeof valToCompare === 'string' && valToCompare.startsWith('{') && valToCompare.endsWith('}')) {
284
- try {
285
- valToCompare = JSON.parse(valToCompare);
286
- } catch {
287
- // ignore
288
- }
289
- }
267
+ return;
268
+ }
290
269
 
291
- if (typeof itemVal === 'object' && typeof valToCompare === 'object') {
292
- return JSON.stringify(itemVal) === JSON.stringify(valToCompare);
270
+ // Always keep multiSelectedListItems in sync with selected values
271
+ multiSelectedListItems.value = multiSelectOptions.value.filter((item) => {
272
+ return values.some((val) => {
273
+ let itemVal = item.value;
274
+ let valToCompare = val;
275
+
276
+ if (typeof itemVal === 'string' && itemVal.startsWith('{') && itemVal.endsWith('}')) {
277
+ try {
278
+ itemVal = JSON.parse(itemVal);
279
+ } catch {
280
+ // ignore error
293
281
  }
294
-
295
- return itemVal == valToCompare;
296
- });
282
+ }
283
+ if (typeof valToCompare === 'string' && valToCompare.startsWith('{') && valToCompare.endsWith('}')) {
284
+ try {
285
+ valToCompare = JSON.parse(valToCompare);
286
+ } catch {
287
+ // ignore error
288
+ }
289
+ }
290
+ if (typeof itemVal === 'object' && typeof valToCompare === 'object') {
291
+ return JSON.stringify(itemVal) === JSON.stringify(valToCompare);
292
+ }
293
+ return itemVal == valToCompare;
297
294
  });
298
- }
295
+ });
299
296
 
300
297
  // Determine input text based on whether count-only mode is enabled
301
- if (props.displaySelectedCountOnly && multiSelectedListItems.value.length) {
302
- inputText.value = `${multiSelectedListItems.value.length} item${
303
- multiSelectedListItems.value.length === 1 ? '' : 's'
304
- } selected`;
305
- } else if (multiSelectedListItems.value.length > 3) {
306
- inputText.value = `${multiSelectedListItems.value.length} items selected`;
307
- } else {
308
- inputText.value = multiSelectedListItems.value.map((item) => item.text).join(', ');
298
+ if (!persistentDisplayText.value) {
299
+ if (props.displaySelectedCountOnly && values.length) {
300
+ inputText.value = `${values.length} item${values.length === 1 ? '' : 's'} selected`;
301
+ } else if (values.length > 3) {
302
+ inputText.value = `${values.length} items selected`;
303
+ } else {
304
+ // Safely get display text for each value
305
+ inputText.value = values
306
+ .map((val) => {
307
+ // Try to find the corresponding option for display text
308
+ const found = multiSelectOptions.value.find((opt) => {
309
+ let optVal = opt.value;
310
+ let v = val;
311
+ if (typeof optVal === 'string' && optVal.startsWith('{') && optVal.endsWith('}')) {
312
+ try {
313
+ optVal = JSON.parse(optVal);
314
+ } catch {
315
+ // ignore error
316
+ }
317
+ }
318
+ if (typeof v === 'string' && v.startsWith('{') && v.endsWith('}')) {
319
+ try {
320
+ v = JSON.parse(v);
321
+ } catch {
322
+ // ignore error
323
+ }
324
+ }
325
+ if (typeof optVal === 'object' && typeof v === 'object') {
326
+ return JSON.stringify(optVal) === JSON.stringify(v);
327
+ }
328
+ return optVal == v;
329
+ });
330
+ return found ? found.text : typeof val === 'string' || typeof val === 'number' ? String(val) : '';
331
+ })
332
+ .join(', ');
333
+ }
309
334
  }
310
335
 
311
- // Always update backup to match inputText after update
312
- inputTextBackup.value = inputText.value;
313
-
314
- if (displayText.value && !hasUserSelected.value && (!inputText.value || inputText.value === '')) {
336
+ if (
337
+ persistentDisplayText.value ||
338
+ (displayText.value && !hasUserSelected.value && (!inputText.value || inputText.value === ''))
339
+ ) {
315
340
  inputText.value = displayText.value;
316
- inputTextBackup.value = displayText.value;
317
341
  }
318
342
  };
319
343
 
@@ -354,12 +378,22 @@ export const useMultiSelect = (props: MultiSelectPropTypes, emit: SetupContext<M
354
378
 
355
379
  watch(searchInput, () => {
356
380
  search.value = searchInput.value;
381
+
382
+ emit('search-string', searchInput.value);
357
383
  });
358
384
 
359
385
  watch(multiSelectPopperState, (newState) => {
360
386
  emit('popper-state', newState);
361
387
  });
362
388
 
389
+ // Watcher for displayText to update inputText when displayText changes and there are no selected items
390
+ watch(displayText, (newVal) => {
391
+ // Only update inputText if there are no selected items
392
+ if (!multiSelectedListItems.value.length) {
393
+ inputText.value = newVal;
394
+ }
395
+ });
396
+
363
397
  /**
364
398
  * Handles closing the multi-select when clicking outside.
365
399
  */
@@ -395,7 +429,6 @@ export const useMultiSelect = (props: MultiSelectPropTypes, emit: SetupContext<M
395
429
  updateMultiSelectedItemsFromValue();
396
430
  } else if (displayText.value) {
397
431
  inputText.value = displayText.value;
398
- inputTextBackup.value = displayText.value;
399
432
  }
400
433
  });
401
434