design-system-next 2.24.2 → 2.26.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.
Files changed (31) hide show
  1. package/dist/design-system-next.es.d.ts +152 -114
  2. package/dist/design-system-next.es.js +10058 -9379
  3. package/dist/design-system-next.es.js.gz +0 -0
  4. package/dist/design-system-next.umd.js +12 -12
  5. package/dist/design-system-next.umd.js.gz +0 -0
  6. package/dist/main.css +1 -1
  7. package/dist/main.css.gz +0 -0
  8. package/package.json +3 -2
  9. package/src/App.vue +1 -89
  10. package/src/components/date-picker/date-picker.ts +9 -12
  11. package/src/components/date-picker/date-picker.vue +1 -1
  12. package/src/components/date-picker/date-range-picker/date-range-picker.ts +9 -12
  13. package/src/components/date-picker/date-range-picker/use-date-range-picker.ts +64 -49
  14. package/src/components/date-picker/month-year-picker/month-year-picker.ts +134 -0
  15. package/src/components/date-picker/month-year-picker/month-year-picker.vue +233 -0
  16. package/src/components/date-picker/month-year-picker/use-month-year-picker.ts +603 -0
  17. package/src/components/date-picker/use-date-picker.ts +88 -147
  18. package/src/components/list/list-item/list-item.ts +60 -60
  19. package/src/components/list/list.ts +5 -0
  20. package/src/components/list/list.vue +2 -0
  21. package/src/components/list/use-list.ts +36 -3
  22. package/src/components/radio-grouped/radio-grouped.ts +65 -65
  23. package/src/components/radio-grouped/use-radio-grouped.ts +62 -62
  24. package/src/components/select/select-multiple/use-select-multiple.ts +7 -3
  25. package/src/components/select/use-select.ts +9 -5
  26. package/src/components/sidepanel/sidepanel.ts +7 -0
  27. package/src/components/sidepanel/sidepanel.vue +24 -4
  28. package/src/components/sidepanel/use-sidepanel.ts +4 -0
  29. package/src/components/table/table-header-dropdown/table-header-dropdown.vue +5 -1
  30. package/src/components/table/table.vue +14 -0
  31. package/src/components/table/use-table.ts +1 -2
@@ -1,5 +1,5 @@
1
1
  import { ref, toRefs, computed, ComputedRef, SetupContext, onMounted, watch, nextTick } from 'vue';
2
- import { useVModel, onClickOutside, useDebounceFn } from '@vueuse/core';
2
+ import { useVModel, onClickOutside } from '@vueuse/core';
3
3
 
4
4
  import dayjs from 'dayjs';
5
5
  import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
@@ -143,8 +143,6 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
143
143
  const dateInput = ref<string>('');
144
144
  const yearInput = ref<string>('');
145
145
 
146
- const datePickerErrors = ref<{ title: string; message: string }[]>([]);
147
-
148
146
  // #region - Calendar Tab
149
147
  const calendarTabPageData = ref({
150
148
  selectedMonth: dayjs().month(),
@@ -295,12 +293,18 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
295
293
  }
296
294
 
297
295
  // Check if date and month are selected, but not year
298
- if (dateInput.value && monthInput && !yearInput.value && !calendarTabIsDateIsDisabled(day)) {
296
+ if (dateInput.value && monthInput.value && !yearInput.value && !calendarTabIsDateIsDisabled(day)) {
299
297
  return day.date.getDate() === Number(dateInput.value) && day.date.getMonth() === monthValue && !day.inactive;
300
298
  }
301
299
 
302
300
  // Check if date, month, and year are selected
303
- if (dateInput.value && monthInput.value && yearInput.value && !calendarTabIsDateIsDisabled(day)) {
301
+ if (
302
+ dateInput.value &&
303
+ monthInput.value &&
304
+ yearInput.value &&
305
+ monthValue !== undefined &&
306
+ !calendarTabIsDateIsDisabled(day)
307
+ ) {
304
308
  return (
305
309
  day.date.getDate() === Number(dateInput.value) &&
306
310
  day.date.getMonth() === monthValue &&
@@ -471,10 +475,6 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
471
475
  emitDateFormats();
472
476
  emitInputValue();
473
477
 
474
- datePickerErrors.value = [];
475
-
476
- emit('getDateErrors', datePickerErrors.value);
477
-
478
478
  setTimeout(() => {
479
479
  datePopperState.value = false;
480
480
  }, 100);
@@ -494,11 +494,7 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
494
494
  handleConvertMonthIfValid();
495
495
  calendarTabUpdateCalendar();
496
496
  emitDateFormats();
497
- emitPartialInputValue();
498
-
499
- datePickerErrors.value = [];
500
-
501
- emit('getDateErrors', datePickerErrors.value);
497
+ emitInputValue();
502
498
  };
503
499
  // #endregion - Month Tab
504
500
 
@@ -564,11 +560,7 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
564
560
  handleConvertMonthIfValid();
565
561
  calendarTabUpdateCalendar();
566
562
  emitDateFormats();
567
- emitPartialInputValue();
568
-
569
- datePickerErrors.value = [];
570
-
571
- emit('getDateErrors', datePickerErrors.value);
563
+ emitInputValue();
572
564
  };
573
565
  // #endregion - Year Tab
574
566
 
@@ -640,8 +632,6 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
640
632
  const date = formattedDate.format('DD');
641
633
  const year = formattedDate.format('YYYY');
642
634
 
643
- handleValidateDate();
644
-
645
635
  monthInput.value = month;
646
636
  dateInput.value = date;
647
637
  yearInput.value = year;
@@ -655,13 +645,7 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
655
645
  handleConvertMonthIfValid();
656
646
  calendarTabUpdateCalendar();
657
647
  emitDateFormats();
658
-
659
- // Use the specified format for the input value
660
- if (!monthInput.value && !dateInput.value && !yearInput.value) {
661
- emit('getInputValue', null);
662
- } else {
663
- emit('getInputValue', formattedDate.format(format.value));
664
- }
648
+ emitInputValue();
665
649
  } else {
666
650
  console.error(`Error: Could not parse date "${modelValue.value}" with format "${format.value}"`);
667
651
  }
@@ -686,48 +670,71 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
686
670
  };
687
671
 
688
672
  const handleMonthInput = () => {
689
- datePopperState.value = false;
690
-
691
673
  monthInput.value = monthInput.value.replace(/[^A-Za-z0-9\s]/g, '').toLocaleUpperCase();
692
674
 
693
- datePickerErrors.value = [];
694
-
695
- emit('getDateErrors', datePickerErrors.value);
696
-
697
675
  handleConvertMonthIfValid();
698
676
 
699
- handleValidateDate();
677
+ // Update calendar if month, date, and year are all provided
678
+ if (monthInput.value && dateInput.value && yearInput.value) {
679
+ const monthValue = getMonthObject('text', monthInput.value)?.monthValue;
680
+ const yearNumber = Number(yearInput.value);
681
+
682
+ if (monthValue !== undefined && yearNumber >= minMaxYear.value.min && yearNumber <= minMaxYear.value.max) {
683
+ calendarTabPageData.value.selectedMonth = monthValue;
684
+ calendarTabPageData.value.selectedYear = yearNumber;
685
+ calendarTabUpdateCalendar();
686
+ }
687
+ } else if (!monthInput.value && !dateInput.value && !yearInput.value) {
688
+ // Clear modelValue when all inputs are empty
689
+ modelValue.value = '';
690
+ }
700
691
 
701
692
  // Emit the partial date value as user types
702
- emitPartialInputValue();
693
+ emitInputValue();
703
694
  };
704
695
 
705
696
  const handleDateInput = () => {
706
- datePopperState.value = false;
707
-
708
697
  dateInput.value = dateInput.value.replace(/[^0-9]/g, '');
709
698
 
710
- datePickerErrors.value = [];
711
-
712
- emit('getDateErrors', datePickerErrors.value);
699
+ // Update calendar if month, date, and year are all provided
700
+ if (monthInput.value && dateInput.value && yearInput.value) {
701
+ const monthValue = getMonthObject('text', monthInput.value)?.monthValue;
702
+ const yearNumber = Number(yearInput.value);
713
703
 
714
- handleValidateDate();
704
+ if (monthValue !== undefined && yearNumber >= minMaxYear.value.min && yearNumber <= minMaxYear.value.max) {
705
+ calendarTabPageData.value.selectedMonth = monthValue;
706
+ calendarTabPageData.value.selectedYear = yearNumber;
707
+ calendarTabUpdateCalendar();
708
+ }
709
+ } else if (!monthInput.value && !dateInput.value && !yearInput.value) {
710
+ // Clear modelValue when all inputs are empty
711
+ modelValue.value = '';
712
+ }
715
713
 
716
714
  // Emit the partial date value as user types
717
- emitPartialInputValue();
715
+ emitInputValue();
718
716
  };
719
717
 
720
718
  const handleYearInput = () => {
721
- datePopperState.value = false;
722
-
723
719
  yearInput.value = yearInput.value.replace(/[^0-9]/g, '');
724
720
 
725
- datePickerErrors.value = [];
721
+ // Update calendar if month, date, and year are all provided
722
+ if (monthInput.value && dateInput.value && yearInput.value) {
723
+ const monthValue = getMonthObject('text', monthInput.value)?.monthValue;
724
+ const yearNumber = Number(yearInput.value);
726
725
 
727
- emit('getDateErrors', datePickerErrors.value);
726
+ if (monthValue !== undefined && yearNumber >= minMaxYear.value.min && yearNumber <= minMaxYear.value.max) {
727
+ calendarTabPageData.value.selectedMonth = monthValue;
728
+ calendarTabPageData.value.selectedYear = yearNumber;
729
+ calendarTabUpdateCalendar();
730
+ }
731
+ } else if (!monthInput.value && !dateInput.value && !yearInput.value) {
732
+ // Clear modelValue when all inputs are empty
733
+ modelValue.value = '';
734
+ }
728
735
 
729
736
  // Emit the partial date value as user types
730
- emitPartialInputValue();
737
+ emitInputValue();
731
738
  };
732
739
 
733
740
  const handleConvertMonthIfValid = () => {
@@ -755,51 +762,6 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
755
762
  }
756
763
  };
757
764
 
758
- const handleValidateDate = useDebounceFn(() => {
759
- if (monthInput.value && dateInput.value && yearInput.value) {
760
- const selectedDate = `${monthInput.value}-${dateInput.value}-${yearInput.value}`;
761
-
762
- const isDateValid = dayjs(selectedDate, 'MM-DD-YYYY').isValid();
763
- const isYearValid =
764
- Number(yearInput.value) >= minMaxYear.value.min && Number(yearInput.value) <= minMaxYear.value.max;
765
-
766
- if (isDateValid && isYearValid) {
767
- datePickerErrors.value = datePickerErrors.value.filter((error) => error.title !== 'Invalid Date');
768
-
769
- const monthValue = getMonthObject('text', monthInput.value)?.monthValue;
770
-
771
- calendarTabPageData.value.selectedMonth = Number(monthValue);
772
- calendarTabPageData.value.selectedYear = Number(yearInput.value);
773
-
774
- calendarTabUpdateCalendar();
775
- emitDateFormats();
776
- } else {
777
- const errorExists = datePickerErrors.value.some((error) => error.title === 'Invalid Date');
778
-
779
- if (!errorExists) {
780
- let errorMessage;
781
-
782
- if (!isYearValid) {
783
- errorMessage = `Year must be between ${minMaxYear.value.min} and ${minMaxYear.value.max}.`;
784
- } else {
785
- errorMessage = `Invalid Date Format. Please use ${format.value}`;
786
- }
787
-
788
- datePickerErrors.value.push({
789
- title: 'Invalid Date',
790
- message: errorMessage,
791
- });
792
-
793
- datePopperState.value = false;
794
-
795
- emit('getDateErrors', datePickerErrors.value);
796
-
797
- console.error(`Invalid Date: "${selectedDate}". ${errorMessage}`);
798
- }
799
- }
800
- }
801
- }, 500);
802
-
803
765
  const handleTabClick = (tab: string) => {
804
766
  if (currentTab.value === tab) {
805
767
  currentTab.value = 'tab-calendar';
@@ -824,34 +786,28 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
824
786
  }
825
787
  };
826
788
 
827
- const emitPartialInputValue = () => {
828
- // Convert month to numeric format if it's text
829
- let emittedMonth = monthInput.value;
830
-
831
- if (monthInput.value) {
832
- const isNumeric = !isNaN(Number(monthInput.value)) && !isNaN(parseFloat(monthInput.value));
833
-
834
- if (!isNumeric) {
835
- const monthIsValid = monthsList.value.find(
836
- (_month: MonthsList) => _month.text.toLowerCase() === monthInput.value.toLowerCase(),
837
- );
789
+ const emitInputValue = () => {
790
+ if (monthInput.value || dateInput.value || yearInput.value) {
791
+ emit('getInputValue', `${monthInput.value}-${dateInput.value}-${yearInput.value}`);
792
+ } else {
793
+ emit('getInputValue', null);
838
794
 
839
- if (monthIsValid) {
840
- emittedMonth =
841
- monthIsValid.monthValue < 10 ? `0${monthIsValid.monthValue + 1}` : `${monthIsValid.monthValue + 1}`;
842
- }
843
- }
795
+ modelValue.value = '';
844
796
  }
845
797
 
846
- // Build the partial date string with zeros for empty fields
847
- const partialMonth = emittedMonth || '0';
848
- const partialDate = dateInput.value || '0';
849
- const partialYear = yearInput.value || '0';
798
+ if (monthInput.value && dateInput.value && yearInput.value) {
799
+ const monthIsValid = monthsList.value.find(
800
+ (_month: MonthsList) => _month.text.toLowerCase() === monthInput.value.toLowerCase(),
801
+ );
850
802
 
851
- const partialDateString = `${partialMonth}-${partialDate}-${partialYear}`;
803
+ const yearIsValid = yearTabPageData.value.yearsArray.find((_year) => _year === Number(yearInput.value));
852
804
 
853
- // Emit the partial date string
854
- emit('getInputValue', partialDateString);
805
+ if (monthIsValid && yearIsValid) {
806
+ const _date = dayjs(`${monthInput.value}-${dateInput.value}-${yearInput.value}`, 'MM-DD-YYYY');
807
+
808
+ modelValue.value = _date.format(format.value);
809
+ }
810
+ }
855
811
  };
856
812
 
857
813
  const emitDateFormats = () => {
@@ -904,28 +860,6 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
904
860
  }
905
861
  };
906
862
 
907
- const emitInputValue = () => {
908
- let emittedMonth = monthInput.value;
909
-
910
- const isNumeric = !isNaN(Number(monthInput.value)) && !isNaN(parseFloat(monthInput.value));
911
-
912
- if (!isNumeric) {
913
- const monthIsValid = monthsList.value.find(
914
- (_month: MonthsList) => _month.text.toLowerCase() === monthInput.value.toLowerCase(),
915
- );
916
-
917
- if (monthIsValid) {
918
- emittedMonth =
919
- monthIsValid.monthValue < 10 ? `0${monthIsValid.monthValue + 1}` : `${monthIsValid.monthValue + 1}`;
920
- }
921
- }
922
- // Format the date according to the format prop
923
- const dateObj = dayjs(`${emittedMonth}-${dateInput.value}-${yearInput.value}`, 'MM-DD-YYYY');
924
-
925
- // Use the specified format for the input value
926
- emit('getInputValue', (modelValue.value = dateObj.format(format.value)));
927
- };
928
-
929
863
  const emitMonthList = () => {
930
864
  emit('getMonthList', monthsList.value);
931
865
  };
@@ -939,6 +873,9 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
939
873
  monthInput.value = '';
940
874
  dateInput.value = '';
941
875
  yearInput.value = '';
876
+ modelValue.value = '';
877
+
878
+ emitInputValue();
942
879
  };
943
880
 
944
881
  const handleSlotClick = () => {
@@ -972,14 +909,19 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
972
909
  }
973
910
  });
974
911
 
975
- watch(minMaxYear, () => {
976
- yearTabPageData.value.yearsArray = Array.from(
977
- { length: minMaxYear.value.max - minMaxYear.value.min + 1 },
978
- (_, index) => minMaxYear.value.min + index,
979
- ).filter((year) => year <= minMaxYear.value.max && year >= minMaxYear.value.min);
980
-
981
- yearTabPageData.value.currentPage = 0;
982
- });
912
+ watch(
913
+ minMaxYear,
914
+ () => {
915
+ yearTabPageData.value.yearsArray = Array.from(
916
+ { length: minMaxYear.value.max - minMaxYear.value.min + 1 },
917
+ (_, index) => minMaxYear.value.min + index,
918
+ ).filter((year) => year <= minMaxYear.value.max && year >= minMaxYear.value.min);
919
+
920
+ yearTabPageData.value.currentPage = 0;
921
+ emitYearList();
922
+ },
923
+ { deep: true },
924
+ );
983
925
 
984
926
  onClickOutside(datePickerRef, () => {
985
927
  datePopperState.value = false;
@@ -1014,7 +956,6 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
1014
956
  dateInput,
1015
957
  monthInput,
1016
958
  yearInput,
1017
- datePickerErrors,
1018
959
  calendarTabPageData,
1019
960
  calendarTabIsMinMonth,
1020
961
  calendarTabIsMaxMonth,
@@ -1,60 +1,60 @@
1
- import type { PropType, ExtractPropTypes } from 'vue';
2
- import type { MenuListType } from '../list';
3
-
4
- export const listItemPropTypes = {
5
- item: {
6
- type: Object as PropType<MenuListType>,
7
- required: true,
8
- },
9
- isSelected: {
10
- type: Boolean,
11
- required: true,
12
- },
13
- classes: {
14
- type: [String, Array, Object] as PropType<string | string[] | Record<string, boolean>>,
15
- required: true,
16
- },
17
- multiSelect: {
18
- type: Boolean,
19
- default: false,
20
- },
21
- lozenge: {
22
- type: Boolean,
23
- default: false,
24
- },
25
- ladderized: {
26
- type: Boolean,
27
- default: false,
28
- },
29
- noCheck: {
30
- type: Boolean,
31
- default: false,
32
- },
33
- itemIcon: {
34
- type: String,
35
- default: '',
36
- },
37
- itemIconTone: {
38
- type: String,
39
- default: 'plain',
40
- },
41
- itemIconFill: {
42
- type: Boolean,
43
- default: false,
44
- },
45
- disabledUnselectedItems: {
46
- type: Boolean,
47
- default: false,
48
- },
49
- radioList: {
50
- type: Boolean,
51
- default: false,
52
- },
53
- };
54
-
55
- export const listItemEmitTypes = {
56
- select: () => true,
57
- };
58
-
59
- export type ListItemPropTypes = ExtractPropTypes<typeof listItemPropTypes>;
60
- export type ListItemEmitTypes = typeof listItemEmitTypes;
1
+ import type { PropType, ExtractPropTypes } from 'vue';
2
+ import type { MenuListType } from '../list';
3
+
4
+ export const listItemPropTypes = {
5
+ item: {
6
+ type: Object as PropType<MenuListType>,
7
+ required: true,
8
+ },
9
+ isSelected: {
10
+ type: Boolean,
11
+ required: true,
12
+ },
13
+ classes: {
14
+ type: [String, Array, Object] as PropType<string | string[] | Record<string, boolean>>,
15
+ required: true,
16
+ },
17
+ multiSelect: {
18
+ type: Boolean,
19
+ default: false,
20
+ },
21
+ lozenge: {
22
+ type: Boolean,
23
+ default: false,
24
+ },
25
+ ladderized: {
26
+ type: Boolean,
27
+ default: false,
28
+ },
29
+ noCheck: {
30
+ type: Boolean,
31
+ default: false,
32
+ },
33
+ itemIcon: {
34
+ type: String,
35
+ default: '',
36
+ },
37
+ itemIconTone: {
38
+ type: String,
39
+ default: 'plain',
40
+ },
41
+ itemIconFill: {
42
+ type: Boolean,
43
+ default: false,
44
+ },
45
+ disabledUnselectedItems: {
46
+ type: Boolean,
47
+ default: false,
48
+ },
49
+ radioList: {
50
+ type: Boolean,
51
+ default: false,
52
+ },
53
+ };
54
+
55
+ export const listItemEmitTypes = {
56
+ select: () => true,
57
+ };
58
+
59
+ export type ListItemPropTypes = ExtractPropTypes<typeof listItemPropTypes>;
60
+ export type ListItemEmitTypes = typeof listItemEmitTypes;
@@ -123,12 +123,17 @@ export const listPropTypes = {
123
123
  type: Boolean,
124
124
  default: false,
125
125
  },
126
+ allowDeselect: {
127
+ type: Boolean,
128
+ default: false
129
+ }
126
130
  };
127
131
 
128
132
  export const listEmitTypes = {
129
133
  'update:modelValue': (value: MenuListType[]) => value,
130
134
  'update:searchValue': (value: string) => typeof value === 'string',
131
135
  'get-single-selected-item': (item: MenuListType) => item,
136
+ 'get-single-deselected-item': (item: MenuListType) => item,
132
137
  };
133
138
 
134
139
  export type ListPropTypes = ExtractPropTypes<typeof listPropTypes>;
@@ -8,6 +8,7 @@
8
8
  v-model="searchText"
9
9
  :placeholder="props.searchableMenuPlaceholder"
10
10
  autocomplete="off"
11
+ @keyup="handleSearchKeyup"
11
12
  />
12
13
  <span
13
14
  v-if="props.supportingDisplayText || props.displayListItemSelected"
@@ -121,5 +122,6 @@ const {
121
122
  isItemSelected,
122
123
  getListItemClasses,
123
124
  handleSelectedItem,
125
+ handleSearchKeyup,
124
126
  } = useList(props, emit);
125
127
  </script>
@@ -22,6 +22,7 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
22
22
  noCheck,
23
23
  disabledUnselectedItems,
24
24
  stickySearchOffset,
25
+ allowDeselect,
25
26
  } = toRefs(props);
26
27
 
27
28
  const listClasses: ComputedRef<ListClasses> = computed(() => {
@@ -518,14 +519,31 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
518
519
  // Track the deselection but DON'T add items back to selectedItems when deselecting
519
520
  trackNewlySelectedItems(item, true);
520
521
  }
522
+ emit('get-single-selected-item', item);
521
523
  } else {
522
524
  // For single-select, simply replace the selection
523
- selectedItems.value = [item];
525
+ if (allowDeselect.value) {
526
+ handleDeselect(item);
527
+ } else {
528
+ handleSingleSelect(item);
529
+ }
530
+ }
531
+ };
524
532
 
525
- if (item.onClickFn) item.onClickFn();
533
+ const handleDeselect = (item: MenuListType) => {
534
+ if (selectedItems.value.length === 0 || !isItemSelected(item)) {
535
+ selectedItems.value = [item];
536
+ emit('get-single-selected-item', item);
537
+ } else {
538
+ selectedItems.value = [];
539
+ emit('get-single-deselected-item', item);
526
540
  }
541
+ };
527
542
 
528
- emit('get-single-selected-item', item);
543
+ const handleSingleSelect = (item: MenuListType) => {
544
+ selectedItems.value = [item];
545
+ if (item.onClickFn) item.onClickFn();
546
+ emit('get-single-selected-item', item);
529
547
  };
530
548
  // #endregion - Helper Methods
531
549
 
@@ -608,6 +626,20 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
608
626
  setPreSelectedItems();
609
627
  });
610
628
 
629
+ // Handle search keyup to ignore modifier-only keys
630
+ const handleSearchKeyup = (event: KeyboardEvent) => {
631
+ // Ignore pure modifier keys: Shift, Control, Alt, Meta (Command/Windows), CapsLock
632
+ const modifierOnlyKeys = ['Shift', 'Control', 'Alt', 'Meta', 'CapsLock'];
633
+
634
+ if (!modifierOnlyKeys.includes(event.key)) {
635
+ // Allow the search to proceed - v-model will handle the actual update
636
+ return;
637
+ }
638
+
639
+ // For modifier-only keys, prevent default behavior if needed
640
+ event.preventDefault();
641
+ };
642
+
611
643
  return {
612
644
  listClasses,
613
645
  stickyOffsetStyle,
@@ -623,5 +655,6 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
623
655
  handleSearch,
624
656
  handleSelectedItem,
625
657
  trackNewlySelectedItems,
658
+ handleSearchKeyup,
626
659
  };
627
660
  };