design-system-next 2.7.36 → 2.7.40
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/dist/design-system-next.js +5506 -5394
- package/dist/design-system-next.js.gz +0 -0
- package/dist/main.css +1 -1
- package/dist/main.css.gz +0 -0
- package/package.json +1 -1
- package/src/components/date-picker/__tests__/date-picker.test.ts +112 -0
- package/src/components/date-picker/date-picker.ts +5 -0
- package/src/components/date-picker/date-picker.vue +5 -5
- package/src/components/date-picker/use-date-picker.ts +55 -19
- package/src/components/dropdown/__tests__/dropdown-fixes.spec.ts +106 -0
- package/src/components/dropdown/__tests__/dropdown-value-types.spec.ts +213 -0
- package/src/components/dropdown/dropdown.ts +14 -3
- package/src/components/dropdown/fix-multi-number.ts +92 -0
- package/src/components/dropdown/use-dropdown.ts +328 -23
- package/src/components/filter/filter.vue +3 -3
- package/src/components/filter/use-filter.ts +3 -6
- package/src/components/list/list.ts +4 -3
- package/src/components/list/use-list.ts +158 -7
- package/src/components/table/table-pagination/use-table-pagination.ts +1 -1
- package/src/examples/dropdown-number-multi-select.vue +76 -0
|
@@ -29,7 +29,7 @@ interface MonthsList {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<DatePickerEmitTypes>['emit']) => {
|
|
32
|
-
const { active, disabled, readonly, error, currentYear, minMaxYear, restDays, disabledDates } = toRefs(props);
|
|
32
|
+
const { active, disabled, readonly, error, currentYear, minMaxYear, restDays, disabledDates, format } = toRefs(props);
|
|
33
33
|
|
|
34
34
|
const modelValue = useVModel(props, 'modelValue', emit);
|
|
35
35
|
|
|
@@ -450,7 +450,7 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
450
450
|
};
|
|
451
451
|
|
|
452
452
|
const calendarTabHandleDateInput = (day: { date: Date }) => {
|
|
453
|
-
const selectedDate = dayjs(day.date
|
|
453
|
+
const selectedDate = dayjs(day.date);
|
|
454
454
|
|
|
455
455
|
const formattedMonth = selectedDate.format('MM');
|
|
456
456
|
const formattedDate = selectedDate.format('DD');
|
|
@@ -460,6 +460,9 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
460
460
|
dateInput.value = formattedDate;
|
|
461
461
|
yearInput.value = formattedYear;
|
|
462
462
|
|
|
463
|
+
// Update the model value with the formatted date using the specified format
|
|
464
|
+
modelValue.value = selectedDate.format(format.value);
|
|
465
|
+
|
|
463
466
|
calendarTabPageData.value.selectedMonth = day.date.getMonth();
|
|
464
467
|
calendarTabPageData.value.selectedYear = day.date.getFullYear();
|
|
465
468
|
|
|
@@ -610,28 +613,52 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
610
613
|
|
|
611
614
|
const setModelValue = () => {
|
|
612
615
|
if (modelValue.value) {
|
|
613
|
-
|
|
616
|
+
// First try to parse with the specified format, then try default format as fallback
|
|
617
|
+
let formattedDate = dayjs(modelValue.value, format.value);
|
|
618
|
+
|
|
619
|
+
// If the date is not valid with the specified format, try with the default format
|
|
620
|
+
if (!formattedDate.isValid()) {
|
|
621
|
+
formattedDate = dayjs(modelValue.value, 'MM-DD-YYYY');
|
|
622
|
+
}
|
|
614
623
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
624
|
+
// If still not valid, try other common formats
|
|
625
|
+
if (!formattedDate.isValid()) {
|
|
626
|
+
const commonFormats = ['YYYY-MM-DD', 'MM/DD/YYYY', 'DD/MM/YYYY', 'YYYY/MM/DD'];
|
|
627
|
+
for (const fmt of commonFormats) {
|
|
628
|
+
const tempDate = dayjs(modelValue.value, fmt);
|
|
629
|
+
if (tempDate.isValid()) {
|
|
630
|
+
formattedDate = tempDate;
|
|
631
|
+
break;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
618
635
|
|
|
619
|
-
|
|
636
|
+
if (formattedDate.isValid()) {
|
|
637
|
+
const month = formattedDate.format('MM');
|
|
638
|
+
const date = formattedDate.format('DD');
|
|
639
|
+
const year = formattedDate.format('YYYY');
|
|
620
640
|
|
|
621
|
-
|
|
622
|
-
dateInput.value = date;
|
|
623
|
-
yearInput.value = year;
|
|
641
|
+
handleValidateDate();
|
|
624
642
|
|
|
625
|
-
|
|
643
|
+
monthInput.value = month;
|
|
644
|
+
dateInput.value = date;
|
|
645
|
+
yearInput.value = year;
|
|
626
646
|
|
|
627
|
-
|
|
628
|
-
|
|
647
|
+
// Apply the specified format for the model value
|
|
648
|
+
modelValue.value = formattedDate.format(format.value);
|
|
629
649
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
emitDateFormats();
|
|
650
|
+
calendarTabPageData.value.selectedMonth = formattedDate.get('month');
|
|
651
|
+
calendarTabPageData.value.selectedYear = formattedDate.get('year');
|
|
633
652
|
|
|
634
|
-
|
|
653
|
+
handleConvertMonthIfValid();
|
|
654
|
+
calendarTabUpdateCalendar();
|
|
655
|
+
emitDateFormats();
|
|
656
|
+
|
|
657
|
+
// Use the specified format for the input value
|
|
658
|
+
emit('getInputValue', formattedDate.format(format.value));
|
|
659
|
+
} else {
|
|
660
|
+
console.error(`Error: Could not parse date "${modelValue.value}" with format "${format.value}"`);
|
|
661
|
+
}
|
|
635
662
|
}
|
|
636
663
|
};
|
|
637
664
|
|
|
@@ -742,7 +769,7 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
742
769
|
if (!isYearValid) {
|
|
743
770
|
errorMessage = `Year must be between ${minMaxYear.value.min} and ${minMaxYear.value.max}.`;
|
|
744
771
|
} else {
|
|
745
|
-
errorMessage =
|
|
772
|
+
errorMessage = `Invalid Date Format. Please use ${format.value}`;
|
|
746
773
|
}
|
|
747
774
|
|
|
748
775
|
datePickerErrors.value.push({
|
|
@@ -850,7 +877,16 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
850
877
|
}
|
|
851
878
|
}
|
|
852
879
|
|
|
853
|
-
|
|
880
|
+
// Format the date according to the format prop
|
|
881
|
+
const dateObj = dayjs(`${emittedMonth}-${dateInput.value}-${yearInput.value}`, 'MM-DD-YYYY');
|
|
882
|
+
|
|
883
|
+
// Use the specified format for the input value
|
|
884
|
+
emit('getInputValue', dateObj.format(format.value));
|
|
885
|
+
|
|
886
|
+
// Update the model value with the formatted date
|
|
887
|
+
if (dateObj.isValid()) {
|
|
888
|
+
modelValue.value = dateObj.format(format.value);
|
|
889
|
+
}
|
|
854
890
|
};
|
|
855
891
|
|
|
856
892
|
const emitMonthList = () => {
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Test script for dropdown component
|
|
2
|
+
|
|
3
|
+
import { describe, it, expect } from 'vitest';
|
|
4
|
+
import { ref } from 'vue';
|
|
5
|
+
import { useDropdown } from '../use-dropdown';
|
|
6
|
+
|
|
7
|
+
describe('Dropdown Component Fixes', () => {
|
|
8
|
+
describe('Value handling', () => {
|
|
9
|
+
it('should handle string value selection correctly', () => {
|
|
10
|
+
// Setup single-select dropdown with string value
|
|
11
|
+
const modelValue = ref('');
|
|
12
|
+
const menuList = [
|
|
13
|
+
{ text: 'Apple', value: 'apple' },
|
|
14
|
+
{ text: 'Banana', value: 'banana' }
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const { handleSelectedItem } = useDropdown({
|
|
18
|
+
id: 'test',
|
|
19
|
+
modelValue,
|
|
20
|
+
menuList
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Simulate selecting an item
|
|
24
|
+
handleSelectedItem([{ text: 'Apple', value: 'apple' }]);
|
|
25
|
+
|
|
26
|
+
// Verify correct value is set
|
|
27
|
+
expect(modelValue.value).toBe('apple');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should handle multiple selection correctly', () => {
|
|
31
|
+
// Setup multi-select dropdown
|
|
32
|
+
const modelValue = ref([]);
|
|
33
|
+
const menuList = [
|
|
34
|
+
{ text: 'Apple', value: 'apple' },
|
|
35
|
+
{ text: 'Banana', value: 'banana' }
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
const { handleSelectedItem } = useDropdown({
|
|
39
|
+
id: 'test',
|
|
40
|
+
modelValue,
|
|
41
|
+
menuList,
|
|
42
|
+
multiSelect: true
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Simulate selecting multiple items
|
|
46
|
+
handleSelectedItem([
|
|
47
|
+
{ text: 'Apple', value: 'apple' },
|
|
48
|
+
{ text: 'Banana', value: 'banana' }
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
// Verify correct values are set
|
|
52
|
+
expect(modelValue.value).toEqual(['apple', 'banana']);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
describe('Ladderized dropdown', () => {
|
|
57
|
+
it('should handle ladderized dropdown selection', () => {
|
|
58
|
+
// Setup ladderized dropdown
|
|
59
|
+
const modelValue = ref([]);
|
|
60
|
+
const menuList = [
|
|
61
|
+
{
|
|
62
|
+
text: 'Lion',
|
|
63
|
+
value: 'lion',
|
|
64
|
+
sublevel: [
|
|
65
|
+
{ text: 'Cub', value: 'cub' }
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const { handleSelectedItem } = useDropdown({
|
|
71
|
+
id: 'test',
|
|
72
|
+
modelValue,
|
|
73
|
+
menuList,
|
|
74
|
+
ladderized: true
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Simulate selecting an item
|
|
78
|
+
handleSelectedItem([{ text: 'Cub', value: 'cub', subvalue: 'lion' }]);
|
|
79
|
+
|
|
80
|
+
// Verify correct values are set for ladderized dropdown
|
|
81
|
+
expect(modelValue.value).toEqual(['lion', 'cub']);
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe('Edge cases', () => {
|
|
86
|
+
it('should handle empty selection', () => {
|
|
87
|
+
const modelValue = ref('apple');
|
|
88
|
+
const menuList = [
|
|
89
|
+
{ text: 'Apple', value: 'apple' },
|
|
90
|
+
{ text: 'Banana', value: 'banana' }
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
const { handleSelectedItem } = useDropdown({
|
|
94
|
+
id: 'test',
|
|
95
|
+
modelValue,
|
|
96
|
+
menuList
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Simulate clearing selection
|
|
100
|
+
handleSelectedItem([]);
|
|
101
|
+
|
|
102
|
+
// Verify value is cleared
|
|
103
|
+
expect(modelValue.value).toBeUndefined();
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { ref } from 'vue';
|
|
3
|
+
import { useDropdown } from '../use-dropdown';
|
|
4
|
+
|
|
5
|
+
describe('Dropdown Value Types', () => {
|
|
6
|
+
describe('Single primitive values', () => {
|
|
7
|
+
it('should handle string values', () => {
|
|
8
|
+
const modelValue = 'apple';
|
|
9
|
+
const menuList = ['apple', 'banana', 'cherry'];
|
|
10
|
+
|
|
11
|
+
const { dropdownMenuList, normalizedValue } = useDropdown({
|
|
12
|
+
id: 'test',
|
|
13
|
+
modelValue,
|
|
14
|
+
menuList
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
expect(normalizedValue.value).toEqual(['apple']);
|
|
18
|
+
expect(dropdownMenuList.value).toEqual([
|
|
19
|
+
{ text: 'apple', value: 'apple' },
|
|
20
|
+
{ text: 'banana', value: 'banana' },
|
|
21
|
+
{ text: 'cherry', value: 'cherry' }
|
|
22
|
+
]);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should handle number values', () => {
|
|
26
|
+
const modelValue = 42;
|
|
27
|
+
const menuList = [42, 55, 67];
|
|
28
|
+
|
|
29
|
+
const { dropdownMenuList, normalizedValue } = useDropdown({
|
|
30
|
+
id: 'test',
|
|
31
|
+
modelValue,
|
|
32
|
+
menuList
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
expect(normalizedValue.value).toEqual([42]);
|
|
36
|
+
expect(dropdownMenuList.value).toEqual([
|
|
37
|
+
{ text: '42', value: '42' },
|
|
38
|
+
{ text: '55', value: '55' },
|
|
39
|
+
{ text: '67', value: '67' }
|
|
40
|
+
]);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('Single object values', () => {
|
|
45
|
+
it('should handle object values', () => {
|
|
46
|
+
const employee = { systemId: 1, firstName: 'John', lastName: 'Doe' };
|
|
47
|
+
const modelValue = employee;
|
|
48
|
+
const menuList = [
|
|
49
|
+
{ systemId: 1, firstName: 'John', lastName: 'Doe' },
|
|
50
|
+
{ systemId: 2, firstName: 'Jane', lastName: 'Smith' }
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
const { dropdownMenuList, normalizedValue } = useDropdown({
|
|
54
|
+
id: 'test',
|
|
55
|
+
modelValue,
|
|
56
|
+
menuList,
|
|
57
|
+
textField: 'firstName',
|
|
58
|
+
valueField: 'systemId'
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
expect(normalizedValue.value).toEqual([employee]);
|
|
62
|
+
expect(dropdownMenuList.value[0].text).toBe('John');
|
|
63
|
+
expect(dropdownMenuList.value[1].text).toBe('Jane');
|
|
64
|
+
expect(dropdownMenuList.value[0].value).toBe('1');
|
|
65
|
+
expect(dropdownMenuList.value[0]._originalObject).toEqual(menuList[0]);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('Multiple primitive values', () => {
|
|
70
|
+
it('should handle string arrays', () => {
|
|
71
|
+
const modelValue = ['apple', 'banana'];
|
|
72
|
+
const menuList = ['apple', 'banana', 'cherry'];
|
|
73
|
+
|
|
74
|
+
const { dropdownMenuList, normalizedValue } = useDropdown({
|
|
75
|
+
id: 'test',
|
|
76
|
+
modelValue,
|
|
77
|
+
menuList,
|
|
78
|
+
multiSelect: true
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
expect(normalizedValue.value).toEqual(['apple', 'banana']);
|
|
82
|
+
expect(dropdownMenuList.value).toEqual([
|
|
83
|
+
{ text: 'apple', value: 'apple' },
|
|
84
|
+
{ text: 'banana', value: 'banana' },
|
|
85
|
+
{ text: 'cherry', value: 'cherry' }
|
|
86
|
+
]);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should handle number arrays', () => {
|
|
90
|
+
const modelValue = [42, 55];
|
|
91
|
+
const menuList = [42, 55, 67];
|
|
92
|
+
|
|
93
|
+
const { dropdownMenuList, normalizedValue } = useDropdown({
|
|
94
|
+
id: 'test',
|
|
95
|
+
modelValue,
|
|
96
|
+
menuList,
|
|
97
|
+
multiSelect: true
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
expect(normalizedValue.value).toEqual([42, 55]);
|
|
101
|
+
expect(dropdownMenuList.value).toEqual([
|
|
102
|
+
{ text: '42', value: '42' },
|
|
103
|
+
{ text: '55', value: '55' },
|
|
104
|
+
{ text: '67', value: '67' }
|
|
105
|
+
]);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('Multiple object values', () => {
|
|
110
|
+
it('should handle object arrays', () => {
|
|
111
|
+
const employees = [
|
|
112
|
+
{ systemId: 1, firstName: 'John', lastName: 'Doe' },
|
|
113
|
+
{ systemId: 2, firstName: 'Jane', lastName: 'Smith' }
|
|
114
|
+
];
|
|
115
|
+
const modelValue = employees;
|
|
116
|
+
const menuList = [
|
|
117
|
+
{ systemId: 1, firstName: 'John', lastName: 'Doe' },
|
|
118
|
+
{ systemId: 2, firstName: 'Jane', lastName: 'Smith' },
|
|
119
|
+
{ systemId: 3, firstName: 'Mike', lastName: 'Johnson' }
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
const { dropdownMenuList, normalizedValue } = useDropdown({
|
|
123
|
+
id: 'test',
|
|
124
|
+
modelValue,
|
|
125
|
+
menuList,
|
|
126
|
+
textField: 'firstName',
|
|
127
|
+
valueField: 'systemId',
|
|
128
|
+
multiSelect: true
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
expect(normalizedValue.value).toEqual(employees);
|
|
132
|
+
expect(dropdownMenuList.value[0].text).toBe('John');
|
|
133
|
+
expect(dropdownMenuList.value[1].text).toBe('Jane');
|
|
134
|
+
expect(dropdownMenuList.value[0].value).toBe('1');
|
|
135
|
+
expect(dropdownMenuList.value[0]._originalObject).toEqual(menuList[0]);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
describe('Handle selected items', () => {
|
|
140
|
+
it('should output string for string selection', () => {
|
|
141
|
+
const modelValue = ref(undefined);
|
|
142
|
+
const menuList = ['apple', 'banana', 'cherry'];
|
|
143
|
+
|
|
144
|
+
const { handleSelectedItem } = useDropdown({
|
|
145
|
+
id: 'test',
|
|
146
|
+
modelValue,
|
|
147
|
+
menuList,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
handleSelectedItem([{ text: 'apple', value: 'apple' }]);
|
|
151
|
+
expect(modelValue.value).toBe('apple');
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('should output number for number selection', () => {
|
|
155
|
+
const modelValue = ref(undefined);
|
|
156
|
+
const menuList = [42, 55, 67];
|
|
157
|
+
|
|
158
|
+
const { handleSelectedItem } = useDropdown({
|
|
159
|
+
id: 'test',
|
|
160
|
+
modelValue,
|
|
161
|
+
menuList,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
handleSelectedItem([{ text: '42', value: '42' }]);
|
|
165
|
+
expect(modelValue.value).toBe(42);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should output original object for object selection', () => {
|
|
169
|
+
const modelValue = ref(undefined);
|
|
170
|
+
const employeeObj = { systemId: 1, firstName: 'John', lastName: 'Doe' };
|
|
171
|
+
const menuList = [
|
|
172
|
+
employeeObj,
|
|
173
|
+
{ systemId: 2, firstName: 'Jane', lastName: 'Smith' }
|
|
174
|
+
];
|
|
175
|
+
|
|
176
|
+
const { handleSelectedItem, dropdownMenuList } = useDropdown({
|
|
177
|
+
id: 'test',
|
|
178
|
+
modelValue,
|
|
179
|
+
menuList,
|
|
180
|
+
textField: 'firstName',
|
|
181
|
+
valueField: 'systemId'
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Process menu list first to get _originalObject
|
|
185
|
+
dropdownMenuList.value.forEach(item => {
|
|
186
|
+
if (item.value === '1') {
|
|
187
|
+
handleSelectedItem([item]);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
expect(modelValue.value).toEqual(employeeObj);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('should output array for multi-select', () => {
|
|
195
|
+
const modelValue = ref([]);
|
|
196
|
+
const menuList = ['apple', 'banana', 'cherry'];
|
|
197
|
+
|
|
198
|
+
const { handleSelectedItem } = useDropdown({
|
|
199
|
+
id: 'test',
|
|
200
|
+
modelValue,
|
|
201
|
+
menuList,
|
|
202
|
+
multiSelect: true
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
handleSelectedItem([
|
|
206
|
+
{ text: 'apple', value: 'apple' },
|
|
207
|
+
{ text: 'banana', value: 'banana' }
|
|
208
|
+
]);
|
|
209
|
+
|
|
210
|
+
expect(modelValue.value).toEqual(['apple', 'banana']);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
});
|
|
@@ -31,14 +31,24 @@ export const dropdownPropTypes = {
|
|
|
31
31
|
required: true,
|
|
32
32
|
},
|
|
33
33
|
modelValue: {
|
|
34
|
-
type: Array as PropType<string[]>,
|
|
34
|
+
type: [String, Number, Object, Array] as PropType<string | number | Record<string, unknown> | (string | number | Record<string, unknown>)[]>,
|
|
35
35
|
default: () => [],
|
|
36
36
|
},
|
|
37
37
|
menuList: {
|
|
38
|
-
type: Array as PropType<MenuListType[]>,
|
|
38
|
+
type: Array as PropType<MenuListType[] | string[] | Record<string, unknown>[]>,
|
|
39
39
|
required: true,
|
|
40
40
|
default: [],
|
|
41
41
|
},
|
|
42
|
+
textField: {
|
|
43
|
+
type: String,
|
|
44
|
+
default: 'text',
|
|
45
|
+
description: 'Field name to use for display text when using dynamic object arrays',
|
|
46
|
+
},
|
|
47
|
+
valueField: {
|
|
48
|
+
type: String,
|
|
49
|
+
default: 'value',
|
|
50
|
+
description: 'Field name to use for value when using dynamic object arrays',
|
|
51
|
+
},
|
|
42
52
|
searchString: {
|
|
43
53
|
type: String,
|
|
44
54
|
default: '',
|
|
@@ -91,7 +101,8 @@ export const dropdownPropTypes = {
|
|
|
91
101
|
|
|
92
102
|
export const dropdownEmitTypes = {
|
|
93
103
|
'infinite-scroll-trigger': Boolean,
|
|
94
|
-
|
|
104
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
105
|
+
'update:modelValue': (_value: unknown) => true, // Accept any type of value
|
|
95
106
|
};
|
|
96
107
|
|
|
97
108
|
export type DropdownPropTypes = ExtractPropTypes<typeof dropdownPropTypes>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// This file contains the fixed version of the handleSelectedItem function
|
|
2
|
+
// for handling multiple primitive number values in dropdowns
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fixed version of the handleSelectedItem function that properly handles number values in multi-select mode
|
|
6
|
+
* This is designed to be copied into the use-dropdown.ts file
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Handle selected item for simple list component
|
|
10
|
+
// This function is exported to be used as a reference for implementation
|
|
11
|
+
export const handleSelectedItem = (selectedItems: MenuListType[]) => {
|
|
12
|
+
if (!props.ladderized) {
|
|
13
|
+
// Determine the type of value to emit based on the original data type and multiSelect
|
|
14
|
+
if (multiSelect.value) {
|
|
15
|
+
// For multi-select, always return an array
|
|
16
|
+
const values = selectedItems.map(item => {
|
|
17
|
+
// If we stored the original object, use it
|
|
18
|
+
if ('_originalObject' in item) {
|
|
19
|
+
return item._originalObject;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// For simple types, handle value type conversion properly
|
|
23
|
+
const val = item.value;
|
|
24
|
+
|
|
25
|
+
// If it's already a number, keep it as a number
|
|
26
|
+
if (typeof val === 'number') {
|
|
27
|
+
return val;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// For strings that look like numbers, convert them
|
|
31
|
+
if (typeof val === 'string' && !isNaN(Number(val)) && val.trim() !== '') {
|
|
32
|
+
// Only convert if it looks like a proper number format
|
|
33
|
+
if (/^-?\d+(\.\d+)?$/.test(val)) {
|
|
34
|
+
return Number(val);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Return the original value for all other cases
|
|
39
|
+
return val;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Set the dropdown value
|
|
43
|
+
dropdownValue.value = values as (string | number | Record<string, unknown>)[];
|
|
44
|
+
} else {
|
|
45
|
+
// For single-select
|
|
46
|
+
if (selectedItems.length === 0) {
|
|
47
|
+
dropdownValue.value = props.multiSelect ? [] : '';
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const item = selectedItems[0];
|
|
52
|
+
|
|
53
|
+
// If we stored the original object, use it
|
|
54
|
+
if ('_originalObject' in item) {
|
|
55
|
+
dropdownValue.value = item._originalObject as Record<string, unknown>;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// For simple types, return the value (try to convert number strings to numbers)
|
|
60
|
+
const val = item.value;
|
|
61
|
+
if (typeof val === 'string' && !isNaN(Number(val)) && val.trim() !== '') {
|
|
62
|
+
dropdownValue.value = Number(val);
|
|
63
|
+
} else {
|
|
64
|
+
dropdownValue.value = val;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
} else if (props.ladderized) {
|
|
68
|
+
if (props.searchString !== '') {
|
|
69
|
+
// generate dropdown value if ladderized with search string
|
|
70
|
+
const subvalue = selectedItems[0]?.subvalue;
|
|
71
|
+
const value = selectedItems[0]?.value;
|
|
72
|
+
if (subvalue !== undefined && value !== undefined) {
|
|
73
|
+
dropdownValue.value = [subvalue, value] as [string, string | number];
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
// For regular ladderized dropdown selection without search
|
|
77
|
+
if (selectedItems.length > 0) {
|
|
78
|
+
const item = selectedItems[0];
|
|
79
|
+
// Use the value directly for ladderized items
|
|
80
|
+
if (item && item.value) {
|
|
81
|
+
dropdownValue.value = item.value;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!multiSelect.value) {
|
|
88
|
+
setTimeout(() => {
|
|
89
|
+
dropdownPopperState.value = false;
|
|
90
|
+
}, 10);
|
|
91
|
+
}
|
|
92
|
+
};
|