@farm-investimentos/front-mfe-components-vue3 0.6.1 → 0.7.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/dist/front-mfe-components.common.js +224 -134
- package/dist/front-mfe-components.common.js.map +1 -1
- package/dist/front-mfe-components.css +1 -1
- package/dist/front-mfe-components.umd.js +224 -134
- package/dist/front-mfe-components.umd.js.map +1 -1
- package/dist/front-mfe-components.umd.min.js +1 -1
- package/dist/front-mfe-components.umd.min.js.map +1 -1
- package/package.json +1 -1
- package/src/components/ChipInviteStatus/keys.ts +9 -9
- package/src/components/ContextMenu/ContextMenu.stories.js +0 -4
- package/src/components/DatePicker/DatePicker.vue +3 -1
- package/src/components/InputDecimalFormatter/__tests__/InputMoney.spec.js +6 -3
- package/src/components/ListItem/ListItem.scss +54 -8
- package/src/components/ListItem/ListItem.vue +2 -2
- package/src/components/MainFilter/MainFilter.vue +1 -0
- package/src/components/Modal/Modal.vue +6 -10
- package/src/components/Modal/__tests__/Modal.spec.js +10 -0
- package/src/components/ModalPromptUser/ModalPromptUser.vue +1 -1
- package/src/components/ModalPromptUser/__tests__/ModalPromptUser.spec.js +1 -1
- package/src/components/RadioGroup/__tests__/RadioGroup.spec.js +1 -1
- package/src/components/Select/Select.scss +5 -5
- package/src/components/Select/Select.stories.js +74 -0
- package/src/components/Select/Select.vue +166 -64
- package/src/components/Select/__tests__/Select.spec.js +62 -1
- package/src/components/Select/__tests__/selectItemHandler.spec.js +93 -0
- package/src/components/Select/composition/buildData.ts +2 -0
- package/src/components/Select/composition/index.ts +3 -1
- package/src/components/Select/composition/selectItemHandler.ts +60 -0
- package/src/components/Select/composition/watchAllChecked.ts +23 -0
- package/src/components/SelectAutoComplete/SelectAutoComplete.vue +1 -1
- package/src/components/SelectAutoComplete/__tests__/SelectAutoComplete.spec.js +1 -1
- package/src/components/TextArea/__tests__/TextArea.spec.js +5 -1
- package/src/interfaces/ISelectItem.ts +5 -0
- package/src/scss/Sticky-table.scss +13 -10
|
@@ -1,55 +1,148 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
2
|
+
<div
|
|
3
|
+
:class="{
|
|
4
|
+
'farm-textfield': true,
|
|
5
|
+
'farm-textfield--validatable': rules.length > 0,
|
|
6
|
+
'farm-textfield--touched': isTouched,
|
|
7
|
+
'farm-textfield--blured': isBlured,
|
|
8
|
+
'farm-textfield--error': hasError,
|
|
9
|
+
'farm-textfield--disabled': disabled,
|
|
10
|
+
'farm-textfield--focused': isFocus || isVisible,
|
|
11
|
+
'farm-textfield--hiddendetails': hideDetails,
|
|
12
|
+
}"
|
|
13
|
+
v-if="!readonly && !disabled"
|
|
14
|
+
:id="customId"
|
|
15
|
+
>
|
|
16
|
+
<farm-contextmenu
|
|
17
|
+
bottom
|
|
18
|
+
v-model="isVisible"
|
|
19
|
+
:stay-open="multiple || clickedDisabledItem"
|
|
20
|
+
ref="contextmenu"
|
|
21
|
+
>
|
|
22
|
+
<farm-list
|
|
23
|
+
v-if="!readonly"
|
|
24
|
+
ref="listRef"
|
|
25
|
+
@keydown="onKeyDown"
|
|
26
|
+
>
|
|
27
|
+
<farm-listitem
|
|
28
|
+
clickable
|
|
29
|
+
v-if="hasAllOption && multiple"
|
|
30
|
+
>
|
|
31
|
+
<farm-checkbox
|
|
32
|
+
class="farm-select__checkbox"
|
|
33
|
+
v-model="allChecked"
|
|
34
|
+
value="1"
|
|
35
|
+
size="sm"
|
|
36
|
+
:indeterminate="allChecked && multipleValues.length !== enabledItems.length"
|
|
37
|
+
/>
|
|
38
|
+
<farm-caption
|
|
39
|
+
bold
|
|
40
|
+
tag="span"
|
|
41
|
+
@click="allChecked = !allChecked"
|
|
42
|
+
>
|
|
43
|
+
Todos
|
|
44
|
+
</farm-caption>
|
|
45
|
+
</farm-listitem>
|
|
46
|
+
<farm-listitem
|
|
47
|
+
v-for="(item, index) in items"
|
|
48
|
+
clickable
|
|
49
|
+
hoverColorVariation="lighten"
|
|
50
|
+
:hover-color="item.disabled ? 'neutral' : 'primary'"
|
|
51
|
+
:key="'contextmenu_item_' + index"
|
|
52
|
+
:class="{
|
|
53
|
+
'farm-listitem--selected': item[itemValue] === innerValue,
|
|
54
|
+
'farm-listitem--disabled': item.disabled,
|
|
55
|
+
}"
|
|
56
|
+
@click:item="event => selectItem(item)"
|
|
57
|
+
>
|
|
58
|
+
<farm-checkbox
|
|
59
|
+
class="farm-select__checkbox"
|
|
60
|
+
v-model="checked"
|
|
61
|
+
value="1"
|
|
62
|
+
size="sm"
|
|
63
|
+
:disabled="item.disabled"
|
|
64
|
+
v-if="isChecked(item)"
|
|
65
|
+
/>
|
|
66
|
+
<farm-checkbox
|
|
67
|
+
class="farm-select__checkbox"
|
|
68
|
+
v-model="checked"
|
|
69
|
+
value="2"
|
|
70
|
+
size="sm"
|
|
71
|
+
:disabled="item.disabled"
|
|
72
|
+
v-else-if="multiple"
|
|
73
|
+
/>
|
|
74
|
+
<farm-caption
|
|
75
|
+
bold
|
|
76
|
+
tag="span"
|
|
77
|
+
:color="item.disabled ? 'neutral' : ''"
|
|
78
|
+
:color-variation="item.disabled ? 'lighten' : 'normal'"
|
|
79
|
+
>
|
|
80
|
+
{{ item[itemText] }}
|
|
81
|
+
</farm-caption>
|
|
22
82
|
</farm-listitem>
|
|
23
83
|
<farm-listitem v-if="!items || items.length === 0">
|
|
24
84
|
{{ noDataText }}
|
|
25
85
|
</farm-listitem>
|
|
26
86
|
</farm-list>
|
|
27
|
-
<template v-slot:activator="{
|
|
28
|
-
<div
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
87
|
+
<template v-slot:activator="{}">
|
|
88
|
+
<div
|
|
89
|
+
class="farm-textfield--input farm-textfield--input--iconed"
|
|
90
|
+
@keydown="onKeyDown"
|
|
91
|
+
>
|
|
92
|
+
<input
|
|
93
|
+
v-bind="$attrs"
|
|
94
|
+
v-model="selectedText"
|
|
95
|
+
ref="inputField"
|
|
96
|
+
readonly
|
|
97
|
+
:id="$props.id"
|
|
98
|
+
@click="clickInput"
|
|
99
|
+
@blur="onBlur"
|
|
100
|
+
@focusin="onFocus(true)"
|
|
101
|
+
@focusout="onFocus(false)"
|
|
102
|
+
/>
|
|
103
|
+
<farm-icon
|
|
104
|
+
color="gray"
|
|
105
|
+
:class="{ 'farm-icon--rotate': isVisible }"
|
|
106
|
+
@click="addFocusToInput"
|
|
107
|
+
>
|
|
32
108
|
menu-down
|
|
33
109
|
</farm-icon>
|
|
34
110
|
</div>
|
|
35
111
|
</template>
|
|
36
112
|
</farm-contextmenu>
|
|
37
|
-
<farm-caption
|
|
113
|
+
<farm-caption
|
|
114
|
+
v-if="showErrorText"
|
|
115
|
+
color="error"
|
|
116
|
+
variation="regular"
|
|
117
|
+
>
|
|
38
118
|
{{ errorBucket[0] }}
|
|
39
119
|
</farm-caption>
|
|
40
|
-
<farm-caption
|
|
41
|
-
|
|
42
|
-
|
|
120
|
+
<farm-caption
|
|
121
|
+
v-if="hint && !showErrorText"
|
|
122
|
+
class="farm-select__hint-text"
|
|
123
|
+
:class="{
|
|
124
|
+
'farm-select__hint-text--show': persistentHint || isFocus,
|
|
125
|
+
}"
|
|
126
|
+
color="gray"
|
|
127
|
+
variation="regular"
|
|
128
|
+
>
|
|
43
129
|
{{ hint }}
|
|
44
130
|
</farm-caption>
|
|
45
131
|
</div>
|
|
46
|
-
<farm-textfield-v2
|
|
132
|
+
<farm-textfield-v2
|
|
133
|
+
v-else
|
|
134
|
+
v-model="selectedText"
|
|
135
|
+
:disabled="disabled"
|
|
136
|
+
:readonly="readonly"
|
|
137
|
+
/>
|
|
47
138
|
</template>
|
|
48
139
|
|
|
49
140
|
<script lang="ts">
|
|
50
141
|
import { computed, onBeforeMount, PropType, ref, toRefs, watch } from 'vue';
|
|
51
142
|
|
|
52
|
-
import { buildData } from './composition';
|
|
143
|
+
import { buildData, selectItemHandler, watchAllChecked } from './composition';
|
|
144
|
+
|
|
145
|
+
import { ISelectItem } from '@/interfaces/ISelectItem';
|
|
53
146
|
|
|
54
147
|
import deepEqual from '../../composition/deepEqual';
|
|
55
148
|
import validateFormFieldBuilder from '../../composition/validateFormFieldBuilder';
|
|
@@ -57,7 +150,6 @@ import validateFormMethodBuilder from '../../composition/validateFormMethodBuild
|
|
|
57
150
|
import validateFormStateBuilder from '../../composition/validateFormStateBuilder';
|
|
58
151
|
import randomId from '../../helpers/randomId';
|
|
59
152
|
|
|
60
|
-
|
|
61
153
|
export default {
|
|
62
154
|
name: 'farm-select',
|
|
63
155
|
inheritAttrs: true,
|
|
@@ -103,7 +195,9 @@ export default {
|
|
|
103
195
|
* This can be changed using the item-text ad item-value
|
|
104
196
|
*/
|
|
105
197
|
items: {
|
|
106
|
-
type: Array
|
|
198
|
+
type: Array as PropType<
|
|
199
|
+
Array<ISelectItem>
|
|
200
|
+
>,
|
|
107
201
|
default: () => [],
|
|
108
202
|
},
|
|
109
203
|
/**
|
|
@@ -155,7 +249,7 @@ export default {
|
|
|
155
249
|
input: {
|
|
156
250
|
type: Function,
|
|
157
251
|
// eslint-disable-next-line
|
|
158
|
-
default: (value: [String, Number, Array<any>]) => {
|
|
252
|
+
default: (value: [String, Number, Array<any>]) => {},
|
|
159
253
|
},
|
|
160
254
|
/**
|
|
161
255
|
* Emitted when the select is changed by user interaction<br />
|
|
@@ -164,7 +258,7 @@ export default {
|
|
|
164
258
|
change: {
|
|
165
259
|
type: Function,
|
|
166
260
|
// eslint-disable-next-line
|
|
167
|
-
default: (value: [String, Number, Array<any>]) => {
|
|
261
|
+
default: (value: [String, Number, Array<any>]) => {},
|
|
168
262
|
},
|
|
169
263
|
/**
|
|
170
264
|
* Emitted when any key is pressed<br />
|
|
@@ -173,7 +267,7 @@ export default {
|
|
|
173
267
|
keyup: {
|
|
174
268
|
type: Function,
|
|
175
269
|
// eslint-disable-next-line
|
|
176
|
-
default: (event: Event) => {
|
|
270
|
+
default: (event: Event) => {},
|
|
177
271
|
},
|
|
178
272
|
/**
|
|
179
273
|
* Emitted when the select is blurred<br />
|
|
@@ -182,11 +276,19 @@ export default {
|
|
|
182
276
|
blur: {
|
|
183
277
|
type: Function,
|
|
184
278
|
// eslint-disable-next-line
|
|
185
|
-
default: (event: Event) => {
|
|
279
|
+
default: (event: Event) => {},
|
|
280
|
+
},
|
|
281
|
+
/**
|
|
282
|
+
* Set "All" as first option to select all other values
|
|
283
|
+
*/
|
|
284
|
+
hasAllOption: {
|
|
285
|
+
type: Boolean,
|
|
286
|
+
default: false,
|
|
186
287
|
},
|
|
187
288
|
},
|
|
188
289
|
setup(props, { emit }) {
|
|
189
|
-
const { rules, items, itemText, itemValue, disabled, multiple } =
|
|
290
|
+
const { rules, items, itemText, itemValue, disabled, multiple, hasAllOption } =
|
|
291
|
+
toRefs(props);
|
|
190
292
|
|
|
191
293
|
const {
|
|
192
294
|
multipleValues,
|
|
@@ -200,9 +302,11 @@ export default {
|
|
|
200
302
|
notChecked,
|
|
201
303
|
inputField,
|
|
202
304
|
keys,
|
|
305
|
+
allChecked,
|
|
203
306
|
} = buildData(props);
|
|
204
307
|
|
|
205
308
|
const listRef = ref();
|
|
309
|
+
const clickedDisabledItem = ref(false);
|
|
206
310
|
|
|
207
311
|
const contextmenu = ref(null);
|
|
208
312
|
|
|
@@ -219,6 +323,8 @@ export default {
|
|
|
219
323
|
|
|
220
324
|
const showErrorText = computed(() => hasError.value && isTouched.value);
|
|
221
325
|
|
|
326
|
+
const enabledItems = computed(() => items.value.filter((item: any) => !item.disabled));
|
|
327
|
+
|
|
222
328
|
watch(
|
|
223
329
|
() => props.modelValue,
|
|
224
330
|
newValue => {
|
|
@@ -288,6 +394,8 @@ export default {
|
|
|
288
394
|
emit('update:modelValue', innerValue.value);
|
|
289
395
|
};
|
|
290
396
|
|
|
397
|
+
watchAllChecked(allChecked, multipleValues, items, innerValue, reset);
|
|
398
|
+
|
|
291
399
|
const onBlur = (event: Event) => {
|
|
292
400
|
isBlured.value = true;
|
|
293
401
|
validate(innerValue.value);
|
|
@@ -298,30 +406,19 @@ export default {
|
|
|
298
406
|
isFocus.value = focus;
|
|
299
407
|
};
|
|
300
408
|
|
|
301
|
-
const selectItem =
|
|
302
|
-
inputField
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
innerValue.value = item[itemValue.value];
|
|
318
|
-
isVisible.value = false;
|
|
319
|
-
|
|
320
|
-
setTimeout(() => {
|
|
321
|
-
emit('change', innerValue.value);
|
|
322
|
-
}, 100);
|
|
323
|
-
|
|
324
|
-
};
|
|
409
|
+
const selectItem = selectItemHandler(
|
|
410
|
+
inputField,
|
|
411
|
+
innerValue,
|
|
412
|
+
itemValue,
|
|
413
|
+
checked,
|
|
414
|
+
multiple,
|
|
415
|
+
multipleValues,
|
|
416
|
+
allChecked,
|
|
417
|
+
enabledItems,
|
|
418
|
+
isVisible,
|
|
419
|
+
clickedDisabledItem,
|
|
420
|
+
emit
|
|
421
|
+
);
|
|
325
422
|
|
|
326
423
|
const clickInput = () => {
|
|
327
424
|
isTouched.value = true;
|
|
@@ -367,8 +464,9 @@ export default {
|
|
|
367
464
|
return;
|
|
368
465
|
}
|
|
369
466
|
|
|
370
|
-
selectedText.value = `${labelItem[itemText.value]} (+${
|
|
371
|
-
|
|
467
|
+
selectedText.value = `${labelItem[itemText.value]} (+${
|
|
468
|
+
innerValue.value.length - 1
|
|
469
|
+
} ${innerValue.value.length - 1 === 1 ? 'outro' : 'outros'})`;
|
|
372
470
|
}
|
|
373
471
|
};
|
|
374
472
|
|
|
@@ -416,6 +514,9 @@ export default {
|
|
|
416
514
|
customId,
|
|
417
515
|
showErrorText,
|
|
418
516
|
contextmenu,
|
|
517
|
+
hasAllOption,
|
|
518
|
+
allChecked,
|
|
519
|
+
enabledItems,
|
|
419
520
|
validate,
|
|
420
521
|
reset,
|
|
421
522
|
selectItem,
|
|
@@ -433,6 +534,7 @@ export default {
|
|
|
433
534
|
onKeyDown,
|
|
434
535
|
addFocusToInput,
|
|
435
536
|
listRef,
|
|
537
|
+
clickedDisabledItem,
|
|
436
538
|
};
|
|
437
539
|
},
|
|
438
540
|
};
|
|
@@ -172,4 +172,65 @@ describe('Select component', () => {
|
|
|
172
172
|
});
|
|
173
173
|
});
|
|
174
174
|
});
|
|
175
|
-
|
|
175
|
+
|
|
176
|
+
describe('disabled items', () => {
|
|
177
|
+
it('should not select a disabled item', async () => {
|
|
178
|
+
const items = [
|
|
179
|
+
{ value: 0, text: 'value 0', disabled: true },
|
|
180
|
+
{ value: 1, text: 'value 1' },
|
|
181
|
+
{ value: 2, text: 'value 2' },
|
|
182
|
+
{ value: 3, text: 'value 3' },
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
await wrapper.setProps({
|
|
186
|
+
items,
|
|
187
|
+
modelValue: 1,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
expect(component.innerValue).toBe(1);
|
|
191
|
+
expect(component.selectedText).toBe('value 1');
|
|
192
|
+
component.selectItem(items[2]);
|
|
193
|
+
setTimeout(() => {
|
|
194
|
+
expect(component.innerValue).toBe(2);
|
|
195
|
+
expect(component.selectedText).toBe('value 2');
|
|
196
|
+
}, 150);
|
|
197
|
+
component.selectItem(items[0]);
|
|
198
|
+
setTimeout(() => {
|
|
199
|
+
expect(component.innerValue).toBe(2);
|
|
200
|
+
expect(component.selectedText).toBe('value 2');
|
|
201
|
+
}, 150);
|
|
202
|
+
component.selectItem(items[3]);
|
|
203
|
+
setTimeout(() => {
|
|
204
|
+
expect(component.innerValue).toBe(3);
|
|
205
|
+
expect(component.selectedText).toBe('value 3');
|
|
206
|
+
}, 150);
|
|
207
|
+
});
|
|
208
|
+
it('should not select a disabled item if is multiple', async () => {
|
|
209
|
+
const items = [
|
|
210
|
+
{ value: 0, text: 'value 0' },
|
|
211
|
+
{ value: 1, text: 'value 1', disabled: true },
|
|
212
|
+
{ value: 2, text: 'value 2' },
|
|
213
|
+
{ value: 3, text: 'value 3', disabled: true },
|
|
214
|
+
];
|
|
215
|
+
|
|
216
|
+
await wrapper.setProps({
|
|
217
|
+
multiple: true,
|
|
218
|
+
items,
|
|
219
|
+
modelValue: [0],
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
expect(component.innerValue).toEqual([0]);
|
|
223
|
+
expect(component.selectedText).toBe('value 0');
|
|
224
|
+
component.selectItem(items[2]);
|
|
225
|
+
setTimeout(() => {
|
|
226
|
+
expect(component.innerValue).toEqual([0, 2]);
|
|
227
|
+
expect(component.selectedText).toBe('value 0 (+1 outro)');
|
|
228
|
+
}, 150);
|
|
229
|
+
component.selectItem(items[1]);
|
|
230
|
+
setTimeout(() => {
|
|
231
|
+
expect(component.innerValue).toEqual([0, 2]);
|
|
232
|
+
expect(component.selectedText).toBe('value 0 (+1 outro)');
|
|
233
|
+
}, 150);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import selectItemHandler from '../composition/selectItemHandler';
|
|
2
|
+
|
|
3
|
+
describe('selectItemHandler', () => {
|
|
4
|
+
let inputField;
|
|
5
|
+
let innerValue;
|
|
6
|
+
let itemValue;
|
|
7
|
+
let checked;
|
|
8
|
+
let multiple;
|
|
9
|
+
let multipleValues;
|
|
10
|
+
let allChecked;
|
|
11
|
+
let enabledItems;
|
|
12
|
+
let isVisible;
|
|
13
|
+
let emit;
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
// Initialize mock values for refs and emit function
|
|
17
|
+
inputField = { value: { focus: jest.fn() } };
|
|
18
|
+
innerValue = { value: null };
|
|
19
|
+
itemValue = { value: 'id' };
|
|
20
|
+
checked = { value: null };
|
|
21
|
+
multiple = { value: false };
|
|
22
|
+
multipleValues = { value: [] };
|
|
23
|
+
allChecked = { value: false };
|
|
24
|
+
enabledItems = { value: [{ id: 1 }, { id: 2 }] };
|
|
25
|
+
isVisible = { value: true };
|
|
26
|
+
emit = jest.fn();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should handle single select', () => {
|
|
30
|
+
const item = { id: 1, name: 'Item 1' };
|
|
31
|
+
|
|
32
|
+
// Call the handler function
|
|
33
|
+
selectItemHandler(
|
|
34
|
+
inputField,
|
|
35
|
+
innerValue,
|
|
36
|
+
itemValue,
|
|
37
|
+
checked,
|
|
38
|
+
multiple,
|
|
39
|
+
multipleValues,
|
|
40
|
+
allChecked,
|
|
41
|
+
enabledItems,
|
|
42
|
+
isVisible,
|
|
43
|
+
emit
|
|
44
|
+
)(item);
|
|
45
|
+
|
|
46
|
+
// Assertions
|
|
47
|
+
expect(inputField.value.focus).toHaveBeenCalled();
|
|
48
|
+
expect(innerValue.value).toEqual(1);
|
|
49
|
+
expect(isVisible.value).toEqual(false);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should handle multiple select', () => {
|
|
53
|
+
multiple.value = true;
|
|
54
|
+
const item = { id: 1, name: 'Item 1' };
|
|
55
|
+
|
|
56
|
+
// Call the handler function
|
|
57
|
+
selectItemHandler(
|
|
58
|
+
inputField,
|
|
59
|
+
innerValue,
|
|
60
|
+
itemValue,
|
|
61
|
+
checked,
|
|
62
|
+
multiple,
|
|
63
|
+
multipleValues,
|
|
64
|
+
allChecked,
|
|
65
|
+
enabledItems,
|
|
66
|
+
isVisible,
|
|
67
|
+
emit
|
|
68
|
+
)(item);
|
|
69
|
+
|
|
70
|
+
// Assertions
|
|
71
|
+
expect(inputField.value.focus).toHaveBeenCalled();
|
|
72
|
+
expect(multipleValues.value).toEqual([1]);
|
|
73
|
+
expect(allChecked.value).toEqual(false);
|
|
74
|
+
|
|
75
|
+
// Call the handler function again with a different item
|
|
76
|
+
selectItemHandler(
|
|
77
|
+
inputField,
|
|
78
|
+
innerValue,
|
|
79
|
+
itemValue,
|
|
80
|
+
checked,
|
|
81
|
+
multiple,
|
|
82
|
+
multipleValues,
|
|
83
|
+
allChecked,
|
|
84
|
+
enabledItems,
|
|
85
|
+
isVisible,
|
|
86
|
+
emit
|
|
87
|
+
)({ id: 2, name: 'Item 2' });
|
|
88
|
+
|
|
89
|
+
// Assertions
|
|
90
|
+
expect(multipleValues.value).toEqual([1, 2]);
|
|
91
|
+
expect(allChecked.value).toEqual(true);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -11,6 +11,7 @@ export default function (props) {
|
|
|
11
11
|
const checked = ref('1');
|
|
12
12
|
const notChecked = ref(false);
|
|
13
13
|
const inputField = ref();
|
|
14
|
+
const allChecked = ref(false);
|
|
14
15
|
const keys = {
|
|
15
16
|
ArrowDown: 'next',
|
|
16
17
|
ArrowUp: 'prev',
|
|
@@ -30,5 +31,6 @@ export default function (props) {
|
|
|
30
31
|
notChecked,
|
|
31
32
|
inputField,
|
|
32
33
|
keys,
|
|
34
|
+
allChecked,
|
|
33
35
|
};
|
|
34
36
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Ref } from 'vue';
|
|
2
|
+
|
|
3
|
+
import { ISelectItem } from '@/interfaces/ISelectItem';
|
|
4
|
+
|
|
5
|
+
export default function (
|
|
6
|
+
inputField: Ref<any>,
|
|
7
|
+
innerValue: Ref<any>,
|
|
8
|
+
itemValue: Ref<string>,
|
|
9
|
+
checked: Ref<string>,
|
|
10
|
+
multiple: Ref<boolean>,
|
|
11
|
+
multipleValues: Ref<Array<any>>,
|
|
12
|
+
allChecked: Ref<boolean>,
|
|
13
|
+
enabledItems,
|
|
14
|
+
isVisible: Ref<boolean>,
|
|
15
|
+
clickedDisabledItem,
|
|
16
|
+
emit: Function
|
|
17
|
+
) {
|
|
18
|
+
return function (item: ISelectItem) {
|
|
19
|
+
if (inputField.value) {
|
|
20
|
+
inputField.value.focus();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (item.disabled) {
|
|
24
|
+
clickedDisabledItem.value = true;
|
|
25
|
+
|
|
26
|
+
// "Schedule" execution to next loop, so the contextMenu won't close immediately if a disabled item is clicked
|
|
27
|
+
setTimeout(() => {
|
|
28
|
+
clickedDisabledItem.value = false;
|
|
29
|
+
});
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (multiple.value) {
|
|
33
|
+
const alreadyAdded = multipleValues.value.findIndex(
|
|
34
|
+
val => val === item[itemValue.value]
|
|
35
|
+
);
|
|
36
|
+
checked.value = '1';
|
|
37
|
+
if (alreadyAdded !== -1) {
|
|
38
|
+
multipleValues.value.splice(alreadyAdded, 1);
|
|
39
|
+
} else {
|
|
40
|
+
multipleValues.value.push(item[itemValue.value]);
|
|
41
|
+
}
|
|
42
|
+
innerValue.value = [...multipleValues.value];
|
|
43
|
+
|
|
44
|
+
if (multipleValues.value.length === 0) {
|
|
45
|
+
allChecked.value = false;
|
|
46
|
+
}
|
|
47
|
+
if (multipleValues.value.length === enabledItems.value.length) {
|
|
48
|
+
allChecked.value = true;
|
|
49
|
+
}
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
innerValue.value = item[itemValue.value];
|
|
54
|
+
isVisible.value = false;
|
|
55
|
+
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
emit('change', innerValue.value);
|
|
58
|
+
}, 100);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Ref, watch } from 'vue';
|
|
2
|
+
|
|
3
|
+
export default function (
|
|
4
|
+
allChecked: Ref<boolean>,
|
|
5
|
+
multipleValues: Ref<Array<any>>,
|
|
6
|
+
items: Ref<Array<unknown>>,
|
|
7
|
+
innerValue: Ref<any>,
|
|
8
|
+
resetFn: Function
|
|
9
|
+
) {
|
|
10
|
+
watch(
|
|
11
|
+
() => allChecked.value,
|
|
12
|
+
newVal => {
|
|
13
|
+
if (newVal) {
|
|
14
|
+
multipleValues.value = (items.value as any)
|
|
15
|
+
.map(item => (!item.disabled ? item.value : null))
|
|
16
|
+
.filter(item => item !== null);
|
|
17
|
+
innerValue.value = [...multipleValues.value];
|
|
18
|
+
} else {
|
|
19
|
+
resetFn();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
}
|