selectic 3.0.0 → 3.0.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.
- package/README.md +2 -0
- package/dist/selectic.common.js +177 -90
- package/dist/selectic.esm.js +178 -91
- package/doc/breakingChanges.md +55 -0
- package/doc/events.md +68 -17
- package/doc/main.md +7 -0
- package/doc/params.md +5 -2
- package/package.json +6 -5
- package/src/Filter.tsx +21 -8
- package/src/List.tsx +2 -1
- package/src/Store.tsx +136 -57
- package/src/index.tsx +69 -11
- package/test/Store/Store_creation.spec.js +93 -0
- package/test/Store/clearCache.spec.js +20 -0
- package/test/Store/commit.spec.js +188 -1
- package/test/helper.js +3 -0
- package/types/Store.d.ts +13 -1
- package/types/index.d.ts +13 -3
package/src/index.tsx
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* close [component]: triggered when the list closes.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import {Vue, Component, Prop, Watch, h} from 'vtyx';
|
|
21
|
+
import {Vue, Component, Emit, Prop, Watch, h} from 'vtyx';
|
|
22
22
|
import './css/selectic.css';
|
|
23
23
|
|
|
24
24
|
import Store, {
|
|
@@ -36,6 +36,7 @@ import Store, {
|
|
|
36
36
|
FormatCallback,
|
|
37
37
|
SelectionOverflow,
|
|
38
38
|
ListPosition,
|
|
39
|
+
HideFilter,
|
|
39
40
|
} from './Store';
|
|
40
41
|
import MainInput from './MainInput';
|
|
41
42
|
import ExtendedList from './ExtendedList';
|
|
@@ -55,8 +56,21 @@ export {
|
|
|
55
56
|
FormatCallback,
|
|
56
57
|
SelectionOverflow,
|
|
57
58
|
ListPosition,
|
|
59
|
+
HideFilter,
|
|
58
60
|
};
|
|
59
61
|
|
|
62
|
+
type EventType = 'input' | 'change' | 'open' | 'close' | 'focus' | 'blur' | 'item:click';
|
|
63
|
+
|
|
64
|
+
export interface EventOptions {
|
|
65
|
+
instance: Selectic;
|
|
66
|
+
eventType: EventType;
|
|
67
|
+
automatic: boolean;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface EventChangeOptions extends EventOptions {
|
|
71
|
+
isExcluded: boolean;
|
|
72
|
+
}
|
|
73
|
+
|
|
60
74
|
export interface ParamProps {
|
|
61
75
|
/* Method to call to fetch extra data */
|
|
62
76
|
fetchCallback?: FetchCallback;
|
|
@@ -71,7 +85,7 @@ export interface ParamProps {
|
|
|
71
85
|
pageSize?: number;
|
|
72
86
|
|
|
73
87
|
/* Hide the search control */
|
|
74
|
-
hideFilter?:
|
|
88
|
+
hideFilter?: HideFilter;
|
|
75
89
|
|
|
76
90
|
/* Allow to reverse selection.
|
|
77
91
|
* If true, parent should support the selectionIsExcluded property.
|
|
@@ -483,14 +497,14 @@ export default class Selectic extends Vue<Props> {
|
|
|
483
497
|
window.addEventListener('resize', this.windowResize, false);
|
|
484
498
|
document.addEventListener('click', this.outsideListener, true);
|
|
485
499
|
this.computeOffset();
|
|
486
|
-
this
|
|
500
|
+
this.emit('open');
|
|
487
501
|
} else {
|
|
488
502
|
this.removeListeners();
|
|
489
503
|
if (state.status.hasChanged) {
|
|
490
504
|
this.$emit('change', this.getValue(), state.selectionIsExcluded, this);
|
|
491
505
|
this.store.resetChange();
|
|
492
506
|
}
|
|
493
|
-
this
|
|
507
|
+
this.emit('close');
|
|
494
508
|
}
|
|
495
509
|
}
|
|
496
510
|
|
|
@@ -531,7 +545,7 @@ export default class Selectic extends Vue<Props> {
|
|
|
531
545
|
|
|
532
546
|
@Watch('options')
|
|
533
547
|
public onOptionsChange() {
|
|
534
|
-
this.store.props.options = this.options;
|
|
548
|
+
this.store.props.options = Array.from(this.options);
|
|
535
549
|
}
|
|
536
550
|
|
|
537
551
|
@Watch('texts')
|
|
@@ -580,10 +594,10 @@ export default class Selectic extends Vue<Props> {
|
|
|
580
594
|
if (canTrigger) {
|
|
581
595
|
const selectionIsExcluded = this.store.state.selectionIsExcluded;
|
|
582
596
|
|
|
583
|
-
this
|
|
597
|
+
this.emit('input', value, selectionIsExcluded);
|
|
584
598
|
|
|
585
599
|
if (!this.isFocused) {
|
|
586
|
-
this
|
|
600
|
+
this.emit('change', value, selectionIsExcluded);
|
|
587
601
|
this.store.resetChange();
|
|
588
602
|
}
|
|
589
603
|
}
|
|
@@ -613,7 +627,11 @@ export default class Selectic extends Vue<Props> {
|
|
|
613
627
|
}, 0);
|
|
614
628
|
}
|
|
615
629
|
|
|
616
|
-
|
|
630
|
+
/* This method is only to emit the events and to replicate them */
|
|
631
|
+
private _emit(event: 'input' | 'change', value: SelectedValue, options: EventChangeOptions): void;
|
|
632
|
+
private _emit(event: 'open' | 'close' | 'focus' | 'blur', options: EventOptions): void;
|
|
633
|
+
private _emit(event: 'item:click', value: OptionId, options: EventOptions): void;
|
|
634
|
+
private _emit(event: EventType, ...args: any[]) {
|
|
617
635
|
this.$emit(event, ...args);
|
|
618
636
|
|
|
619
637
|
if (typeof this._on === 'function') {
|
|
@@ -621,6 +639,40 @@ export default class Selectic extends Vue<Props> {
|
|
|
621
639
|
}
|
|
622
640
|
}
|
|
623
641
|
|
|
642
|
+
private emit(event: 'input' | 'change', value: SelectedValue, isExcluded: boolean): void;
|
|
643
|
+
private emit(event: 'open' | 'close' | 'focus' | 'blur'): void;
|
|
644
|
+
private emit(event: 'item:click', value: OptionId): void;
|
|
645
|
+
private emit(event: EventType, value?: SelectedValue | OptionId, isExcluded?: boolean) {
|
|
646
|
+
const automatic = this.store.state.status.automaticChange;
|
|
647
|
+
const options: EventOptions = {
|
|
648
|
+
instance: this,
|
|
649
|
+
eventType: event,
|
|
650
|
+
automatic,
|
|
651
|
+
};
|
|
652
|
+
switch (event) {
|
|
653
|
+
case 'input':
|
|
654
|
+
case 'change':
|
|
655
|
+
const changeOptions: EventChangeOptions = Object.assign({
|
|
656
|
+
isExcluded: isExcluded!,
|
|
657
|
+
}, options);
|
|
658
|
+
this._emit(event, value as SelectedValue, changeOptions);
|
|
659
|
+
break;
|
|
660
|
+
case 'open':
|
|
661
|
+
case 'focus':
|
|
662
|
+
this._emit('open', options);
|
|
663
|
+
this._emit('focus', options);
|
|
664
|
+
break;
|
|
665
|
+
case 'close':
|
|
666
|
+
case 'blur':
|
|
667
|
+
this._emit('close', options);
|
|
668
|
+
this._emit('blur', options);
|
|
669
|
+
break;
|
|
670
|
+
case 'item:click':
|
|
671
|
+
this._emit(event, value as OptionId, options);
|
|
672
|
+
break;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
624
676
|
// private extractFromNode(node: Vue.VNode, text = ''): OptionValue {
|
|
625
677
|
// function styleToString(staticStyle?: {[key: string]: string}): string | undefined {
|
|
626
678
|
// if (!staticStyle) {
|
|
@@ -724,8 +776,7 @@ export default class Selectic extends Vue<Props> {
|
|
|
724
776
|
params: {
|
|
725
777
|
multiple: (this.multiple ?? false) !== false,
|
|
726
778
|
pageSize: this.params.pageSize || 100,
|
|
727
|
-
hideFilter: this.params.hideFilter
|
|
728
|
-
? this.params.hideFilter : 'auto',
|
|
779
|
+
hideFilter: this.params.hideFilter ?? 'auto',
|
|
729
780
|
allowRevert: this.params.allowRevert, /* it can be undefined */
|
|
730
781
|
allowClearSelection: this.params.allowClearSelection || false,
|
|
731
782
|
autoSelect: this.params.autoSelect === undefined
|
|
@@ -793,6 +844,13 @@ export default class Selectic extends Vue<Props> {
|
|
|
793
844
|
|
|
794
845
|
/* }}} */
|
|
795
846
|
|
|
847
|
+
@Emit('input')
|
|
848
|
+
@Emit('change')
|
|
849
|
+
@Emit('open')
|
|
850
|
+
@Emit('focus')
|
|
851
|
+
@Emit('close')
|
|
852
|
+
@Emit('blur')
|
|
853
|
+
@Emit('item:click')
|
|
796
854
|
public render() {
|
|
797
855
|
const id = this.id || undefined;
|
|
798
856
|
const store = this.store;
|
|
@@ -825,7 +883,7 @@ export default class Selectic extends Vue<Props> {
|
|
|
825
883
|
store={store}
|
|
826
884
|
id={id}
|
|
827
885
|
on={{
|
|
828
|
-
'item:click': (id: OptionId) => this.emit('item:click', id
|
|
886
|
+
'item:click': (id: OptionId) => this.emit('item:click', id),
|
|
829
887
|
}}
|
|
830
888
|
ref="mainInput"
|
|
831
889
|
/>
|
|
@@ -33,6 +33,9 @@ tape.test('Store creation', (subT) => {
|
|
|
33
33
|
|
|
34
34
|
t.deepEqual(defaultStore.state, getInitialState({
|
|
35
35
|
disabled: true,
|
|
36
|
+
status: {
|
|
37
|
+
automaticClose: true,
|
|
38
|
+
},
|
|
36
39
|
}));
|
|
37
40
|
|
|
38
41
|
const store = new Store({
|
|
@@ -62,11 +65,51 @@ tape.test('Store creation', (subT) => {
|
|
|
62
65
|
}],
|
|
63
66
|
autoSelect: false,
|
|
64
67
|
disabled: true,
|
|
68
|
+
status: {
|
|
69
|
+
automaticClose: true,
|
|
70
|
+
},
|
|
65
71
|
}));
|
|
66
72
|
|
|
67
73
|
t.end();
|
|
68
74
|
});
|
|
69
75
|
|
|
76
|
+
subT.test('"value" property', (sTest) => {
|
|
77
|
+
sTest.test('should initialize the value', async (t) => {
|
|
78
|
+
const propOptions = getOptions(5);
|
|
79
|
+
const store = new Store({
|
|
80
|
+
value: 2,
|
|
81
|
+
options: propOptions,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
await sleep(0);
|
|
85
|
+
|
|
86
|
+
const state = store.state;
|
|
87
|
+
|
|
88
|
+
t.is(state.internalValue, 2);
|
|
89
|
+
|
|
90
|
+
t.end();
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
sTest.test('should set the correct value type', async (t) => {
|
|
94
|
+
const propOptions = getOptions(5);
|
|
95
|
+
const store = new Store({
|
|
96
|
+
value: 2,
|
|
97
|
+
params: {
|
|
98
|
+
multiple: true,
|
|
99
|
+
},
|
|
100
|
+
options: propOptions,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
await sleep(0);
|
|
104
|
+
|
|
105
|
+
const state = store.state;
|
|
106
|
+
|
|
107
|
+
t.deepEqual(state.internalValue, [2]);
|
|
108
|
+
|
|
109
|
+
t.end();
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
70
113
|
subT.test('"options" property', (sTest) => {
|
|
71
114
|
sTest.test('should handle short options list', async (t) => {
|
|
72
115
|
const propOptions = getOptions(5);
|
|
@@ -900,6 +943,7 @@ tape.test('Store creation', (subT) => {
|
|
|
900
943
|
await sleep(0);
|
|
901
944
|
|
|
902
945
|
t.is(store.state.hideFilter, true);
|
|
946
|
+
t.is(store.state.keepFilterOpen, false);
|
|
903
947
|
t.end();
|
|
904
948
|
});
|
|
905
949
|
|
|
@@ -913,6 +957,7 @@ tape.test('Store creation', (subT) => {
|
|
|
913
957
|
await sleep(0);
|
|
914
958
|
|
|
915
959
|
t.is(store.state.hideFilter, false);
|
|
960
|
+
t.is(store.state.keepFilterOpen, false);
|
|
916
961
|
t.end();
|
|
917
962
|
});
|
|
918
963
|
|
|
@@ -951,6 +996,7 @@ tape.test('Store creation', (subT) => {
|
|
|
951
996
|
await sleep(0);
|
|
952
997
|
|
|
953
998
|
t.is(store.state.hideFilter, false);
|
|
999
|
+
t.is(store.state.keepFilterOpen, false);
|
|
954
1000
|
t.end();
|
|
955
1001
|
});
|
|
956
1002
|
});
|
|
@@ -966,6 +1012,7 @@ tape.test('Store creation', (subT) => {
|
|
|
966
1012
|
await sleep(0);
|
|
967
1013
|
|
|
968
1014
|
t.is(store.state.hideFilter, false);
|
|
1015
|
+
t.is(store.state.keepFilterOpen, false);
|
|
969
1016
|
t.end();
|
|
970
1017
|
});
|
|
971
1018
|
|
|
@@ -979,17 +1026,20 @@ tape.test('Store creation', (subT) => {
|
|
|
979
1026
|
await sleep(0);
|
|
980
1027
|
|
|
981
1028
|
t.is(store.state.hideFilter, false);
|
|
1029
|
+
t.is(store.state.keepFilterOpen, false);
|
|
982
1030
|
|
|
983
1031
|
/* Assert it doesn't change after fetching data */
|
|
984
1032
|
store.commit('isOpen', true);
|
|
985
1033
|
await sleep(0);
|
|
986
1034
|
|
|
987
1035
|
t.is(store.state.hideFilter, false);
|
|
1036
|
+
t.is(store.state.keepFilterOpen, false);
|
|
988
1037
|
|
|
989
1038
|
store.commit('isOpen', false);
|
|
990
1039
|
await sleep(0);
|
|
991
1040
|
|
|
992
1041
|
t.is(store.state.hideFilter, false);
|
|
1042
|
+
t.is(store.state.keepFilterOpen, false);
|
|
993
1043
|
t.end();
|
|
994
1044
|
});
|
|
995
1045
|
});
|
|
@@ -1046,6 +1096,49 @@ tape.test('Store creation', (subT) => {
|
|
|
1046
1096
|
t.end();
|
|
1047
1097
|
});
|
|
1048
1098
|
});
|
|
1099
|
+
|
|
1100
|
+
st.test('having value "open"', (sTest) => {
|
|
1101
|
+
sTest.test('should show filter with few options', async (t) => {
|
|
1102
|
+
const store = new Store({
|
|
1103
|
+
options: getOptions(3),
|
|
1104
|
+
params: {
|
|
1105
|
+
hideFilter: 'open',
|
|
1106
|
+
},
|
|
1107
|
+
});
|
|
1108
|
+
await sleep(0);
|
|
1109
|
+
|
|
1110
|
+
t.is(store.state.hideFilter, false);
|
|
1111
|
+
t.is(store.state.keepFilterOpen, true);
|
|
1112
|
+
t.end();
|
|
1113
|
+
});
|
|
1114
|
+
|
|
1115
|
+
sTest.test('should show filter with dynamic options', async (t) => {
|
|
1116
|
+
const store = new Store({
|
|
1117
|
+
fetchCallback: buildFetchCb({ total: 5 }),
|
|
1118
|
+
params: {
|
|
1119
|
+
hideFilter: 'open',
|
|
1120
|
+
},
|
|
1121
|
+
});
|
|
1122
|
+
await sleep(0);
|
|
1123
|
+
|
|
1124
|
+
t.is(store.state.hideFilter, false);
|
|
1125
|
+
t.is(store.state.keepFilterOpen, true);
|
|
1126
|
+
|
|
1127
|
+
/* Assert it doesn't change after fetching data */
|
|
1128
|
+
store.commit('isOpen', true);
|
|
1129
|
+
await sleep(0);
|
|
1130
|
+
|
|
1131
|
+
t.is(store.state.hideFilter, false);
|
|
1132
|
+
t.is(store.state.keepFilterOpen, true);
|
|
1133
|
+
|
|
1134
|
+
store.commit('isOpen', false);
|
|
1135
|
+
await sleep(0);
|
|
1136
|
+
|
|
1137
|
+
t.is(store.state.hideFilter, false);
|
|
1138
|
+
t.is(store.state.keepFilterOpen, true);
|
|
1139
|
+
t.end();
|
|
1140
|
+
});
|
|
1141
|
+
});
|
|
1049
1142
|
});
|
|
1050
1143
|
|
|
1051
1144
|
subT.test('"optionBehavior" property', (st) => {
|
|
@@ -23,6 +23,26 @@ tape.test('clearCache()', (sTest) => {
|
|
|
23
23
|
t.end();
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
+
sTest.test('should clear all options already loaded in multiple mode', (t) => {
|
|
27
|
+
const store = new Store({
|
|
28
|
+
options: getOptions(10),
|
|
29
|
+
params: {
|
|
30
|
+
multiple: true,
|
|
31
|
+
},
|
|
32
|
+
value: [2, 4],
|
|
33
|
+
});
|
|
34
|
+
store.state.status.errorMessage = 'a message';
|
|
35
|
+
|
|
36
|
+
store.clearCache(true);
|
|
37
|
+
|
|
38
|
+
t.deepEqual(store.state.allOptions, []);
|
|
39
|
+
t.is(store.state.totalAllOptions, 0);
|
|
40
|
+
t.deepEqual(store.state.filteredOptions, []);
|
|
41
|
+
t.is(store.state.status.errorMessage, '');
|
|
42
|
+
t.deepEqual(store.state.internalValue, []);
|
|
43
|
+
t.end();
|
|
44
|
+
});
|
|
45
|
+
|
|
26
46
|
sTest.test('should rebuild all options', (t) => {
|
|
27
47
|
const options = getOptions(10);
|
|
28
48
|
const store = new Store({
|
|
@@ -45,6 +45,9 @@ tape.test('commit()', (st) => {
|
|
|
45
45
|
hideFilter: true,
|
|
46
46
|
allowClearSelection: true,
|
|
47
47
|
disabled: true,
|
|
48
|
+
status: {
|
|
49
|
+
automaticClose: true,
|
|
50
|
+
},
|
|
48
51
|
}));
|
|
49
52
|
|
|
50
53
|
store.commit('searchText', 'hello2');
|
|
@@ -945,15 +948,22 @@ tape.test('commit()', (st) => {
|
|
|
945
948
|
t.end();
|
|
946
949
|
});
|
|
947
950
|
|
|
948
|
-
sTest.test('should close the select list', (t) => {
|
|
951
|
+
sTest.test('should close the select list', async (t) => {
|
|
949
952
|
const store = new Store({
|
|
950
953
|
options: getOptions(5),
|
|
951
954
|
});
|
|
952
955
|
|
|
956
|
+
|
|
953
957
|
store.commit('isOpen', true);
|
|
958
|
+
await sleep(0);
|
|
954
959
|
store.commit('disabled', true);
|
|
955
960
|
|
|
956
961
|
t.deepEqual(store.state.isOpen, false);
|
|
962
|
+
t.deepEqual(store.state.status.automaticClose, true);
|
|
963
|
+
|
|
964
|
+
await sleep(10);
|
|
965
|
+
t.deepEqual(store.state.status.automaticClose, false);
|
|
966
|
+
|
|
957
967
|
t.end();
|
|
958
968
|
});
|
|
959
969
|
});
|
|
@@ -1063,4 +1073,181 @@ tape.test('commit()', (st) => {
|
|
|
1063
1073
|
t.end();
|
|
1064
1074
|
});
|
|
1065
1075
|
});
|
|
1076
|
+
|
|
1077
|
+
st.test('when changing "internalValue"', (sTest) => {
|
|
1078
|
+
sTest.test('should change the value', async (t) => {
|
|
1079
|
+
const store1 = new Store({
|
|
1080
|
+
options: getOptions(5),
|
|
1081
|
+
params: {
|
|
1082
|
+
autoSelect: false,
|
|
1083
|
+
},
|
|
1084
|
+
});
|
|
1085
|
+
const store2 = new Store({
|
|
1086
|
+
options: getOptions(5),
|
|
1087
|
+
params: {
|
|
1088
|
+
autoSelect: false,
|
|
1089
|
+
multiple: true,
|
|
1090
|
+
},
|
|
1091
|
+
});
|
|
1092
|
+
|
|
1093
|
+
await sleep(0);
|
|
1094
|
+
store1.commit('internalValue', 3);
|
|
1095
|
+
store2.commit('internalValue', [1, 2]);
|
|
1096
|
+
|
|
1097
|
+
t.is(store1.state.internalValue, 3);
|
|
1098
|
+
t.deepEqual(store2.state.internalValue, [1, 2]);
|
|
1099
|
+
t.is(store1.state.status.automaticChange, false);
|
|
1100
|
+
t.is(store2.state.status.automaticChange, false);
|
|
1101
|
+
|
|
1102
|
+
await sleep(0);
|
|
1103
|
+
store1.commit('internalValue', 1);
|
|
1104
|
+
store2.commit('internalValue', [3, 4, 5]);
|
|
1105
|
+
|
|
1106
|
+
t.is(store1.state.internalValue, 1);
|
|
1107
|
+
t.deepEqual(store2.state.internalValue, [3, 4, 5]);
|
|
1108
|
+
t.is(store1.state.status.automaticChange, false);
|
|
1109
|
+
t.is(store2.state.status.automaticChange, false);
|
|
1110
|
+
|
|
1111
|
+
await sleep(0);
|
|
1112
|
+
store1.commit('internalValue', null);
|
|
1113
|
+
store2.commit('internalValue', []);
|
|
1114
|
+
|
|
1115
|
+
t.is(store1.state.internalValue, null);
|
|
1116
|
+
t.deepEqual(store2.state.internalValue, []);
|
|
1117
|
+
t.is(store1.state.status.automaticChange, false);
|
|
1118
|
+
t.is(store2.state.status.automaticChange, false);
|
|
1119
|
+
|
|
1120
|
+
t.end();
|
|
1121
|
+
});
|
|
1122
|
+
|
|
1123
|
+
sTest.test('should convert values', async (t) => {
|
|
1124
|
+
const store1 = new Store({
|
|
1125
|
+
options: getOptions(5),
|
|
1126
|
+
params: {
|
|
1127
|
+
autoSelect: false,
|
|
1128
|
+
},
|
|
1129
|
+
});
|
|
1130
|
+
const store2 = new Store({
|
|
1131
|
+
options: getOptions(5),
|
|
1132
|
+
params: {
|
|
1133
|
+
autoSelect: false,
|
|
1134
|
+
multiple: true,
|
|
1135
|
+
},
|
|
1136
|
+
});
|
|
1137
|
+
await sleep(0);
|
|
1138
|
+
|
|
1139
|
+
store1.commit('internalValue', [3]);
|
|
1140
|
+
store2.commit('internalValue', 1);
|
|
1141
|
+
|
|
1142
|
+
t.is(store1.state.internalValue, 3);
|
|
1143
|
+
t.deepEqual(store2.state.internalValue, [1]);
|
|
1144
|
+
t.is(store1.state.status.automaticChange, true);
|
|
1145
|
+
t.is(store2.state.status.automaticChange, true);
|
|
1146
|
+
|
|
1147
|
+
await sleep(0);
|
|
1148
|
+
|
|
1149
|
+
store1.commit('internalValue', [1, 2, 3]);
|
|
1150
|
+
store2.commit('internalValue', 3);
|
|
1151
|
+
|
|
1152
|
+
t.is(store1.state.internalValue, 1);
|
|
1153
|
+
t.deepEqual(store2.state.internalValue, [3]);
|
|
1154
|
+
t.is(store1.state.status.automaticChange, true);
|
|
1155
|
+
t.is(store2.state.status.automaticChange, true);
|
|
1156
|
+
|
|
1157
|
+
await sleep(0);
|
|
1158
|
+
|
|
1159
|
+
store1.commit('internalValue', []);
|
|
1160
|
+
store2.commit('internalValue', null);
|
|
1161
|
+
|
|
1162
|
+
t.is(store1.state.internalValue, null, 'should not select anything');
|
|
1163
|
+
t.deepEqual(store2.state.internalValue, [], 'should have no selection');
|
|
1164
|
+
t.is(store1.state.status.automaticChange, true);
|
|
1165
|
+
t.is(store2.state.status.automaticChange, true);
|
|
1166
|
+
|
|
1167
|
+
await sleep(0);
|
|
1168
|
+
t.is(store1.state.status.automaticChange, false);
|
|
1169
|
+
t.is(store2.state.status.automaticChange, false);
|
|
1170
|
+
|
|
1171
|
+
t.end();
|
|
1172
|
+
});
|
|
1173
|
+
|
|
1174
|
+
sTest.test('should be changed to the first option', async (t) => {
|
|
1175
|
+
const store1 = new Store({
|
|
1176
|
+
options: getOptions(5),
|
|
1177
|
+
params: {
|
|
1178
|
+
autoSelect: true,
|
|
1179
|
+
},
|
|
1180
|
+
value: 2,
|
|
1181
|
+
});
|
|
1182
|
+
|
|
1183
|
+
store1.commit('internalValue', 3);
|
|
1184
|
+
|
|
1185
|
+
t.is(store1.state.internalValue, 3);
|
|
1186
|
+
t.is(store1.state.status.automaticChange, false);
|
|
1187
|
+
|
|
1188
|
+
await sleep(0);
|
|
1189
|
+
store1.commit('internalValue', null);
|
|
1190
|
+
|
|
1191
|
+
t.is(store1.state.internalValue, 0);
|
|
1192
|
+
t.is(store1.state.status.automaticChange, true);
|
|
1193
|
+
|
|
1194
|
+
await sleep(0);
|
|
1195
|
+
|
|
1196
|
+
t.is(store1.state.status.automaticChange, false);
|
|
1197
|
+
|
|
1198
|
+
t.end();
|
|
1199
|
+
});
|
|
1200
|
+
|
|
1201
|
+
sTest.test('should be changed to the first remaining option', async (t) => {
|
|
1202
|
+
const store1 = new Store({
|
|
1203
|
+
options: [{
|
|
1204
|
+
id: 0,
|
|
1205
|
+
}, {
|
|
1206
|
+
id: 1,
|
|
1207
|
+
disabled: true,
|
|
1208
|
+
}, {
|
|
1209
|
+
id: 2,
|
|
1210
|
+
}, {
|
|
1211
|
+
id: 3,
|
|
1212
|
+
}, {
|
|
1213
|
+
id: 4,
|
|
1214
|
+
}],
|
|
1215
|
+
params: {
|
|
1216
|
+
autoSelect: true,
|
|
1217
|
+
strictValue: true,
|
|
1218
|
+
},
|
|
1219
|
+
value: 2,
|
|
1220
|
+
});
|
|
1221
|
+
|
|
1222
|
+
store1.commit('internalValue', 0);
|
|
1223
|
+
await _.nextVueTick(store1);
|
|
1224
|
+
|
|
1225
|
+
t.is(store1.state.internalValue, 0);
|
|
1226
|
+
|
|
1227
|
+
store1.props.options = [{
|
|
1228
|
+
id: 1,
|
|
1229
|
+
disabled: true,
|
|
1230
|
+
}, {
|
|
1231
|
+
id: 2,
|
|
1232
|
+
}, {
|
|
1233
|
+
id: 3,
|
|
1234
|
+
}, {
|
|
1235
|
+
id: 4,
|
|
1236
|
+
}];
|
|
1237
|
+
|
|
1238
|
+
await _.nextVueTick(store1);
|
|
1239
|
+
|
|
1240
|
+
t.is(store1.state.internalValue, 2, 'should change to the first available option');
|
|
1241
|
+
|
|
1242
|
+
store1.commit('internalValue', 3);
|
|
1243
|
+
await _.nextVueTick(store1);
|
|
1244
|
+
|
|
1245
|
+
store1.commit('internalValue', null);
|
|
1246
|
+
await _.nextVueTick(store1);
|
|
1247
|
+
|
|
1248
|
+
t.is(store1.state.internalValue, 2, 'should select the first available option');
|
|
1249
|
+
|
|
1250
|
+
t.end();
|
|
1251
|
+
});
|
|
1252
|
+
});
|
|
1066
1253
|
});
|
package/test/helper.js
CHANGED
|
@@ -8,6 +8,7 @@ function getInitialState(replacedAttributes) {
|
|
|
8
8
|
disabled: false,
|
|
9
9
|
placeholder: '',
|
|
10
10
|
hideFilter: false,
|
|
11
|
+
keepFilterOpen: false,
|
|
11
12
|
allowRevert: undefined,
|
|
12
13
|
allowClearSelection: false,
|
|
13
14
|
autoSelect: true,
|
|
@@ -40,6 +41,8 @@ function getInitialState(replacedAttributes) {
|
|
|
40
41
|
errorMessage: '',
|
|
41
42
|
areAllSelected: false,
|
|
42
43
|
hasChanged: false,
|
|
44
|
+
automaticChange: false,
|
|
45
|
+
automaticClose: false,
|
|
43
46
|
},
|
|
44
47
|
}, replacedAttributes);
|
|
45
48
|
}
|
package/types/Store.d.ts
CHANGED
|
@@ -37,10 +37,11 @@ export declare type GetCallback = (_ids: OptionId[]) => Promise<OptionValue[]>;
|
|
|
37
37
|
export declare type FormatCallback = (_option: OptionItem) => OptionItem;
|
|
38
38
|
export declare type SelectionOverflow = 'collapsed' | 'multiline';
|
|
39
39
|
export declare type ListPosition = 'bottom' | 'top' | 'auto';
|
|
40
|
+
export declare type HideFilter = boolean | 'auto' | 'open';
|
|
40
41
|
export interface SelecticStoreStateParams {
|
|
41
42
|
multiple?: boolean;
|
|
42
43
|
placeholder?: string;
|
|
43
|
-
hideFilter?:
|
|
44
|
+
hideFilter?: HideFilter;
|
|
44
45
|
allowRevert?: boolean;
|
|
45
46
|
allowClearSelection?: boolean;
|
|
46
47
|
pageSize?: number;
|
|
@@ -83,6 +84,7 @@ export interface SelecticStoreState {
|
|
|
83
84
|
disabled: boolean;
|
|
84
85
|
placeholder: string;
|
|
85
86
|
hideFilter: boolean;
|
|
87
|
+
keepFilterOpen: boolean;
|
|
86
88
|
allowRevert?: boolean;
|
|
87
89
|
allowClearSelection: boolean;
|
|
88
90
|
autoSelect: boolean;
|
|
@@ -112,6 +114,8 @@ export interface SelecticStoreState {
|
|
|
112
114
|
errorMessage: string;
|
|
113
115
|
areAllSelected: boolean;
|
|
114
116
|
hasChanged: boolean;
|
|
117
|
+
automaticChange: boolean;
|
|
118
|
+
automaticClose: boolean;
|
|
115
119
|
};
|
|
116
120
|
}
|
|
117
121
|
interface Messages {
|
|
@@ -145,6 +149,7 @@ export default class SelecticStore {
|
|
|
145
149
|
disabled: boolean;
|
|
146
150
|
placeholder: string;
|
|
147
151
|
hideFilter: boolean;
|
|
152
|
+
keepFilterOpen: boolean;
|
|
148
153
|
allowRevert?: boolean | undefined;
|
|
149
154
|
allowClearSelection: boolean;
|
|
150
155
|
autoSelect: boolean;
|
|
@@ -268,6 +273,8 @@ export default class SelecticStore {
|
|
|
268
273
|
errorMessage: string;
|
|
269
274
|
areAllSelected: boolean;
|
|
270
275
|
hasChanged: boolean;
|
|
276
|
+
automaticChange: boolean;
|
|
277
|
+
automaticClose: boolean;
|
|
271
278
|
};
|
|
272
279
|
};
|
|
273
280
|
data: Data;
|
|
@@ -278,9 +285,13 @@ export default class SelecticStore {
|
|
|
278
285
|
isPartial: ComputedRef<boolean>;
|
|
279
286
|
hasAllItems: ComputedRef<boolean>;
|
|
280
287
|
hasFetchedAllItems: ComputedRef<boolean>;
|
|
288
|
+
private listOptions;
|
|
289
|
+
private elementOptions;
|
|
281
290
|
_uid: number;
|
|
282
291
|
constructor(props?: Props);
|
|
283
292
|
commit<N extends keyof SelecticStoreState, V extends SelecticStoreState[N]>(name: N, value: V): void;
|
|
293
|
+
setAutomaticChange(): void;
|
|
294
|
+
setAutomaticClose(): void;
|
|
284
295
|
getItem(id: OptionId): OptionValue;
|
|
285
296
|
getItems(ids: OptionId[]): Promise<OptionItem[]>;
|
|
286
297
|
selectItem(id: OptionId, selected?: boolean, keepOpen?: boolean): void;
|
|
@@ -292,6 +303,7 @@ export default class SelecticStore {
|
|
|
292
303
|
changeTexts(texts: PartialMessages): void;
|
|
293
304
|
private hasValue;
|
|
294
305
|
private getValue;
|
|
306
|
+
private convertTypeValue;
|
|
295
307
|
private assertValueType;
|
|
296
308
|
private assertCorrectValue;
|
|
297
309
|
private updateFilteredOptions;
|
package/types/index.d.ts
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
import { Vue, h } from 'vtyx';
|
|
2
2
|
import './css/selectic.css';
|
|
3
|
-
import { OptionProp, OptionId, StrictOptionId, GroupValue, SelectedValue, FetchCallback, GetCallback, PartialMessages, OptionValue, OptionItem, FormatCallback, SelectionOverflow, ListPosition } from './Store';
|
|
3
|
+
import { OptionProp, OptionId, StrictOptionId, GroupValue, SelectedValue, FetchCallback, GetCallback, PartialMessages, OptionValue, OptionItem, FormatCallback, SelectionOverflow, ListPosition, HideFilter } from './Store';
|
|
4
4
|
import MainInput from './MainInput';
|
|
5
5
|
import ExtendedList from './ExtendedList';
|
|
6
|
-
export { GroupValue, OptionValue, OptionItem, OptionProp, OptionId, StrictOptionId, SelectedValue, PartialMessages, GetCallback, FetchCallback, FormatCallback, SelectionOverflow, ListPosition, };
|
|
6
|
+
export { GroupValue, OptionValue, OptionItem, OptionProp, OptionId, StrictOptionId, SelectedValue, PartialMessages, GetCallback, FetchCallback, FormatCallback, SelectionOverflow, ListPosition, HideFilter, };
|
|
7
|
+
declare type EventType = 'input' | 'change' | 'open' | 'close' | 'focus' | 'blur' | 'item:click';
|
|
8
|
+
export interface EventOptions {
|
|
9
|
+
instance: Selectic;
|
|
10
|
+
eventType: EventType;
|
|
11
|
+
automatic: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface EventChangeOptions extends EventOptions {
|
|
14
|
+
isExcluded: boolean;
|
|
15
|
+
}
|
|
7
16
|
export interface ParamProps {
|
|
8
17
|
fetchCallback?: FetchCallback;
|
|
9
18
|
getItemsCallback?: GetCallback;
|
|
10
19
|
pageSize?: number;
|
|
11
|
-
hideFilter?:
|
|
20
|
+
hideFilter?: HideFilter;
|
|
12
21
|
allowRevert?: boolean;
|
|
13
22
|
allowClearSelection?: boolean;
|
|
14
23
|
autoSelect?: boolean;
|
|
@@ -122,6 +131,7 @@ export default class Selectic extends Vue<Props> {
|
|
|
122
131
|
onFocusChanged(): void;
|
|
123
132
|
onInternalValueChange(): void;
|
|
124
133
|
private checkFocus;
|
|
134
|
+
private _emit;
|
|
125
135
|
private emit;
|
|
126
136
|
created(): void;
|
|
127
137
|
mounted(): void;
|