design-system-next 2.7.44 → 2.7.45

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.
@@ -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
+ });
@@ -1,122 +0,0 @@
1
- // import type { PropType, ExtractPropTypes } from 'vue';
2
- // import type { MenuListType } from '../list/list';
3
-
4
- // export const definePropType = <T>(val: unknown): PropType<T> => val as PropType<T>;
5
-
6
- // const GROUPED_ITEMS_BY_TYPES = ['A-Z', 'Z-A'] as const;
7
-
8
- // const PLACEMENTS_TYPES = [
9
- // 'auto',
10
- // 'auto-start',
11
- // 'auto-end',
12
- // 'top',
13
- // 'top-start',
14
- // 'top-end',
15
- // 'right',
16
- // 'right-start',
17
- // 'right-end',
18
- // 'bottom',
19
- // 'bottom-start',
20
- // 'bottom-end',
21
- // 'left',
22
- // 'left-start',
23
- // 'left-end',
24
- // ] as const;
25
-
26
- // const POPPER_STRATEGY_TYPES = ['fixed', 'absolute'] as const;
27
-
28
- // export const selectPropTypes = {
29
- // id: {
30
- // type: String,
31
- // required: true,
32
- // },
33
- // modelValue: {
34
- // type: [String, Number, Object, Array] as PropType<
35
- // string | number | Record<string, unknown> | (string | number | Record<string, unknown>)[]
36
- // >,
37
- // default: () => [],
38
- // },
39
- // menuList: {
40
- // type: Array as PropType<MenuListType[] | string[] | Record<string, unknown>[]>,
41
- // required: true,
42
- // default: [],
43
- // },
44
- // multiSelect: {
45
- // type: Boolean,
46
- // default: false,
47
- // },
48
- // groupItemsBy: {
49
- // type: String as PropType<(typeof GROUPED_ITEMS_BY_TYPES)[number]>,
50
- // validator: (value: (typeof GROUPED_ITEMS_BY_TYPES)[number] | undefined) => {
51
- // return value === undefined || GROUPED_ITEMS_BY_TYPES.includes(value);
52
- // },
53
- // },
54
- // textField: {
55
- // type: String,
56
- // default: 'text',
57
- // description: 'Field name to use for display text when using dynamic object arrays',
58
- // },
59
- // valueField: {
60
- // type: String,
61
- // default: 'value',
62
- // description: 'Field name to use for value when using dynamic object arrays',
63
- // },
64
- // placeholder: {
65
- // type: String,
66
- // },
67
- // searchString: {
68
- // type: String,
69
- // default: '',
70
- // },
71
- // placement: {
72
- // type: String as PropType<(typeof PLACEMENTS_TYPES)[number]>,
73
- // validator: (value: (typeof PLACEMENTS_TYPES)[number]) => PLACEMENTS_TYPES.includes(value),
74
- // default: 'bottom',
75
- // },
76
- // popperStrategy: {
77
- // type: String,
78
- // validator: (value: 'fixed' | 'absolute') => POPPER_STRATEGY_TYPES.includes(value),
79
- // default: 'absolute',
80
- // },
81
- // popperWidth: {
82
- // type: String,
83
- // default: '100%',
84
- // },
85
- // width: {
86
- // type: String,
87
- // default: '100%',
88
- // },
89
- // wrapperPosition: {
90
- // type: String,
91
- // default: 'relative',
92
- // },
93
- // disabled: {
94
- // type: Boolean,
95
- // default: false,
96
- // },
97
- // readonly: {
98
- // type: Boolean,
99
- // default: false,
100
- // },
101
- // ladderized: {
102
- // type: Boolean,
103
- // default: false,
104
- // },
105
- // removeCurrentLevelInBackLabel: {
106
- // type: Boolean,
107
- // default: false,
108
- // },
109
- // disabled: {
110
- // type: Boolean,
111
- // default: false,
112
- // },
113
- // };
114
-
115
- // export const selectEmitTypes = {
116
- // 'infinite-scroll-trigger': Boolean,
117
- // // eslint-disable-next-line @typescript-eslint/no-unused-vars
118
- // 'update:modelValue': (_value: unknown) => true, // Accept any type of value
119
- // };
120
-
121
- // export type SelectPropTypes = ExtractPropTypes<typeof selectPropTypes>;
122
- // export type SelectEmitTypes = typeof selectEmitTypes;
@@ -1,110 +0,0 @@
1
- <template>
2
- <div></div>
3
- </template>
4
- <!-- <template>
5
- <Menu
6
- :shown="selectPopperState"
7
- aria-id="select-wrapper"
8
- distance="4"
9
- :placement="props.placement"
10
- :triggers="[]"
11
- :popper-hide-triggers="[]"
12
- :auto-hide="false"
13
- :disabled="isSelectPopperDisabled"
14
- :container="`#${props.id}`"
15
- :strategy="
16
- props.popperStrategy === 'fixed' || props.popperStrategy === 'absolute' ? props.popperStrategy : 'absolute'
17
- "
18
- :delay="0"
19
- :style="{
20
- position: props.wrapperPosition,
21
- width: props.width,
22
- }"
23
- >
24
- <div @click="selectPopperState = true">
25
- {{ selectedListItems }}
26
-
27
- <spr-input
28
- v-model="inputText"
29
- label="Select Numbers"
30
- :placeholder="props.placeholder"
31
- :readonly="props.readonly"
32
- :disabled="props.disabled"
33
- autocomplete="off"
34
- />
35
- </div>
36
-
37
- <div
38
- :id="props.id"
39
- :style="{
40
- width: props.popperWidth,
41
- }"
42
- ></div>
43
-
44
- <template #popper>
45
- <div
46
- ref="selectRef"
47
- :class="[
48
- (!props.ladderized || isLadderizedSearch) && 'spr-p-2',
49
- 'spr-grid spr-max-h-[300px] spr-gap-0.5 spr-overflow-y-auto spr-overflow-x-hidden',
50
- ]"
51
- >
52
- <template v-if="selectMenuList.length > 0">
53
- <spr-list
54
- v-if="!props.ladderized || isLadderizedSearch"
55
- v-model="selectedListItems"
56
- :menu-list="selectMenuList"
57
- :group-items-by="props.groupItemsBy"
58
- :multi-select="props.multiSelect"
59
- :pre-selected-items="selectValue"
60
- @update:model-value="handleSelectedItem"
61
- />
62
- <spr-ladderized-list
63
- v-else
64
- v-model="selectValue"
65
- :ladderized="props.ladderized"
66
- :menu-list="selectMenuList"
67
- :remove-current-level-in-back-label="removeCurrentLevelInBackLabel"
68
- @update:model-value="handleSelectedLadderizedItem"
69
- />
70
- </template>
71
- <template v-else>
72
- <div class="spr-flex spr-items-center spr-justify-center spr-p-2 spr-text-center">
73
- <span class="spr-body-sm-regular spr-m-0">No results found</span>
74
- </div>
75
- </template>
76
- </div>
77
- </template>
78
- </Menu>
79
- </template>
80
-
81
- <script lang="ts" setup>
82
- import { Menu } from 'floating-vue';
83
-
84
- import 'floating-vue/dist/style.css';
85
-
86
- import SprInput from '../../input/input.vue';
87
- import SprList from '../../list/list.vue';
88
- import SprLadderizedList from '../../list/ladderized-list/ladderized-list.vue';
89
-
90
- import { selectPropTypes, selectEmitTypes } from './select-laderrized';
91
-
92
- import { useSelect } from './use-select-laderrized';
93
-
94
- const props = defineProps(selectPropTypes);
95
- const emit = defineEmits(selectEmitTypes);
96
-
97
- const {
98
- selectPopperState,
99
- selectRef,
100
- selectMenuList,
101
- isSelectPopperDisabled,
102
- selectedListItems,
103
- handleSelectedItem,
104
- handleSelectedLadderizedItem,
105
- selectValue,
106
- removeCurrentLevelInBackLabel,
107
- isLadderizedSearch,
108
- inputText,
109
- } = useSelect(props, emit);
110
- </script> -->