selectic 3.0.2 → 3.0.6
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/.package.json.un~ +0 -0
- package/dist/selectic.common.js +70 -39
- package/dist/selectic.esm.js +70 -39
- package/doc/params.md +5 -2
- package/package.json +6 -5
- package/src/Filter.tsx +18 -6
- package/src/Store.tsx +62 -44
- package/src/index.tsx +29 -8
- package/test/Store/Store_creation.spec.js +50 -0
- package/test/Store/Store_props.spec.js +33 -0
- package/test/helper.js +1 -0
- package/types/List.d.ts +2 -26
- package/types/Store.d.ts +4 -135
- package/types/index.d.ts +3 -3
|
Binary file
|
package/dist/selectic.common.js
CHANGED
|
@@ -101,12 +101,33 @@ let closePreviousSelectic;
|
|
|
101
101
|
let uid = 0;
|
|
102
102
|
class SelecticStore {
|
|
103
103
|
constructor(props = {}) {
|
|
104
|
+
/* Do not need reactivity */
|
|
105
|
+
this.requestId = 0;
|
|
106
|
+
this._uid = ++uid;
|
|
107
|
+
/* {{{ Props */
|
|
108
|
+
const defaultProps = {
|
|
109
|
+
value: null,
|
|
110
|
+
selectionIsExcluded: false,
|
|
111
|
+
disabled: false,
|
|
112
|
+
options: null,
|
|
113
|
+
childOptions: [],
|
|
114
|
+
groups: [],
|
|
115
|
+
texts: null,
|
|
116
|
+
params: {},
|
|
117
|
+
fetchCallback: null,
|
|
118
|
+
getItemsCallback: null,
|
|
119
|
+
keepOpenWithOtherSelectic: false,
|
|
120
|
+
};
|
|
121
|
+
const propsVal = assignObject(defaultProps, props);
|
|
122
|
+
this.props = vue.reactive(propsVal);
|
|
123
|
+
/* }}} */
|
|
104
124
|
/* {{{ data */
|
|
105
125
|
this.state = vue.reactive({
|
|
106
126
|
multiple: false,
|
|
107
127
|
disabled: false,
|
|
108
128
|
placeholder: '',
|
|
109
129
|
hideFilter: false,
|
|
130
|
+
keepFilterOpen: false,
|
|
110
131
|
allowRevert: undefined,
|
|
111
132
|
allowClearSelection: false,
|
|
112
133
|
autoSelect: true,
|
|
@@ -140,27 +161,6 @@ class SelecticStore {
|
|
|
140
161
|
automaticClose: false,
|
|
141
162
|
},
|
|
142
163
|
});
|
|
143
|
-
/* Do not need reactivity */
|
|
144
|
-
this.requestId = 0;
|
|
145
|
-
this._uid = ++uid;
|
|
146
|
-
/* {{{ Props */
|
|
147
|
-
const defaultProps = {
|
|
148
|
-
value: null,
|
|
149
|
-
selectionIsExcluded: false,
|
|
150
|
-
disabled: false,
|
|
151
|
-
options: null,
|
|
152
|
-
childOptions: [],
|
|
153
|
-
groups: [],
|
|
154
|
-
texts: null,
|
|
155
|
-
params: {},
|
|
156
|
-
fetchCallback: null,
|
|
157
|
-
getItemsCallback: null,
|
|
158
|
-
keepOpenWithOtherSelectic: false,
|
|
159
|
-
};
|
|
160
|
-
const propsVal = assignObject(defaultProps, props);
|
|
161
|
-
this.props = vue.reactive(propsVal);
|
|
162
|
-
/* }}} */
|
|
163
|
-
/* {{{ data */
|
|
164
164
|
this.data = vue.reactive({
|
|
165
165
|
labels: Object.assign({}, messages),
|
|
166
166
|
itemsPerPage: 10,
|
|
@@ -264,14 +264,18 @@ class SelecticStore {
|
|
|
264
264
|
if (stateParam.hideFilter === 'auto') {
|
|
265
265
|
delete stateParam.hideFilter;
|
|
266
266
|
}
|
|
267
|
+
else if (stateParam.hideFilter === 'open') {
|
|
268
|
+
this.state.keepFilterOpen = true;
|
|
269
|
+
delete stateParam.hideFilter;
|
|
270
|
+
}
|
|
267
271
|
/* Update state */
|
|
268
272
|
assignObject(this.state, stateParam);
|
|
269
273
|
/* XXX: should be done in 2 lines, in order to set the multiple state
|
|
270
274
|
* and ensure convertValue run with correct state */
|
|
271
275
|
assignObject(this.state, {
|
|
272
276
|
internalValue: this.convertTypeValue(value),
|
|
273
|
-
selectionIsExcluded: props.selectionIsExcluded,
|
|
274
|
-
disabled: props.disabled,
|
|
277
|
+
selectionIsExcluded: !!props.selectionIsExcluded,
|
|
278
|
+
disabled: !!props.disabled, /* XXX: !! is needed to copy value and not proxy reference */
|
|
275
279
|
});
|
|
276
280
|
this.checkHideFilter();
|
|
277
281
|
if (this.props.texts) {
|
|
@@ -1468,6 +1472,10 @@ let FilterPanel = class FilterPanel extends vtyx.Vue {
|
|
|
1468
1472
|
this.store.commit('selectionIsExcluded', !this.selectionIsExcluded);
|
|
1469
1473
|
}
|
|
1470
1474
|
togglePanel() {
|
|
1475
|
+
if (this.store.state.keepFilterOpen === true) {
|
|
1476
|
+
this.closed = false;
|
|
1477
|
+
return;
|
|
1478
|
+
}
|
|
1471
1479
|
this.closed = !this.closed;
|
|
1472
1480
|
}
|
|
1473
1481
|
getFocus() {
|
|
@@ -1484,7 +1492,8 @@ let FilterPanel = class FilterPanel extends vtyx.Vue {
|
|
|
1484
1492
|
/* }}} */
|
|
1485
1493
|
/* {{{ Life cycle */
|
|
1486
1494
|
mounted() {
|
|
1487
|
-
|
|
1495
|
+
const state = this.store.state;
|
|
1496
|
+
this.closed = !state.keepFilterOpen && !state.searchText;
|
|
1488
1497
|
document.addEventListener('keypress', this.onKeyPressed);
|
|
1489
1498
|
this.getFocus();
|
|
1490
1499
|
}
|
|
@@ -1493,24 +1502,27 @@ let FilterPanel = class FilterPanel extends vtyx.Vue {
|
|
|
1493
1502
|
}
|
|
1494
1503
|
/* }}} */
|
|
1495
1504
|
render() {
|
|
1505
|
+
const store = this.store;
|
|
1506
|
+
const state = store.state;
|
|
1507
|
+
const labels = store.data.labels;
|
|
1496
1508
|
return (vtyx.h("div", { class: "filter-panel" },
|
|
1497
1509
|
vtyx.h("div", { class: {
|
|
1498
1510
|
panelclosed: this.closed,
|
|
1499
1511
|
panelopened: !this.closed,
|
|
1500
1512
|
} },
|
|
1501
1513
|
vtyx.h("div", { class: "filter-panel__input form-group has-feedback" },
|
|
1502
|
-
vtyx.h("input", { type: "text", class: "form-control filter-input", placeholder: this.searchPlaceholder, value:
|
|
1514
|
+
vtyx.h("input", { type: "text", class: "form-control filter-input", placeholder: this.searchPlaceholder, value: state.searchText, on: {
|
|
1503
1515
|
'input.stop.prevent': this.onInput,
|
|
1504
1516
|
}, ref: "filterInput" }),
|
|
1505
1517
|
vtyx.h("span", { class: "fa fa-search selectic-search-scope\n form-control-feedback" })),
|
|
1506
|
-
|
|
1518
|
+
state.multiple && (vtyx.h("div", { class: "toggle-selectic" },
|
|
1507
1519
|
vtyx.h("label", { class: ['control-label', {
|
|
1508
1520
|
'selectic__label-disabled': this.disableSelectAll,
|
|
1509
1521
|
}] },
|
|
1510
|
-
vtyx.h("input", { type: "checkbox", checked:
|
|
1522
|
+
vtyx.h("input", { type: "checkbox", checked: state.status.areAllSelected, disabled: this.disableSelectAll, on: {
|
|
1511
1523
|
change: this.onSelectAll,
|
|
1512
1524
|
} }),
|
|
1513
|
-
|
|
1525
|
+
labels.selectAll))),
|
|
1514
1526
|
this.enableRevert && (vtyx.h("div", { class: ['toggle-selectic', {
|
|
1515
1527
|
'selectic__label-disabled': this.disableRevert,
|
|
1516
1528
|
}] },
|
|
@@ -1518,8 +1530,8 @@ let FilterPanel = class FilterPanel extends vtyx.Vue {
|
|
|
1518
1530
|
vtyx.h("input", { type: "checkbox", checked: this.selectionIsExcluded, disabled: this.disableRevert, on: {
|
|
1519
1531
|
change: this.onExclude,
|
|
1520
1532
|
} }),
|
|
1521
|
-
|
|
1522
|
-
vtyx.h("div", { class: "curtain-handler", on: {
|
|
1533
|
+
labels.excludeResult)))),
|
|
1534
|
+
!state.keepFilterOpen && (vtyx.h("div", { class: "curtain-handler", on: {
|
|
1523
1535
|
'click.prevent.stop': this.togglePanel,
|
|
1524
1536
|
} },
|
|
1525
1537
|
vtyx.h("span", { class: "fa fa-search" }),
|
|
@@ -1527,7 +1539,7 @@ let FilterPanel = class FilterPanel extends vtyx.Vue {
|
|
|
1527
1539
|
'fa': true,
|
|
1528
1540
|
'fa-caret-down': this.closed,
|
|
1529
1541
|
'fa-caret-up': !this.closed,
|
|
1530
|
-
} }))));
|
|
1542
|
+
} })))));
|
|
1531
1543
|
}
|
|
1532
1544
|
};
|
|
1533
1545
|
__decorate$3([
|
|
@@ -2012,15 +2024,26 @@ let Selectic = class Selectic extends vtyx.Vue {
|
|
|
2012
2024
|
}
|
|
2013
2025
|
get outsideListener() {
|
|
2014
2026
|
return (evt) => {
|
|
2015
|
-
const target = evt.target;
|
|
2016
2027
|
if (!this.$refs) {
|
|
2017
2028
|
/* this component should have been destroyed */
|
|
2018
2029
|
this.removeListeners();
|
|
2019
2030
|
this.store.commit('isOpen', false);
|
|
2020
2031
|
return;
|
|
2021
2032
|
}
|
|
2022
|
-
|
|
2023
|
-
|
|
2033
|
+
const store = this.store;
|
|
2034
|
+
const keepOpenWithOtherSelectic = this.params.keepOpenWithOtherSelectic;
|
|
2035
|
+
const extendedList = this.$refs.extendedList;
|
|
2036
|
+
if (!extendedList) {
|
|
2037
|
+
/* this component is not focused anymore */
|
|
2038
|
+
if (!keepOpenWithOtherSelectic) {
|
|
2039
|
+
this.removeListeners();
|
|
2040
|
+
this.store.commit('isOpen', false);
|
|
2041
|
+
}
|
|
2042
|
+
return;
|
|
2043
|
+
}
|
|
2044
|
+
const target = evt.target;
|
|
2045
|
+
if (!extendedList.$el.contains(target) && !this.$el.contains(target)) {
|
|
2046
|
+
store.commit('isOpen', false);
|
|
2024
2047
|
}
|
|
2025
2048
|
};
|
|
2026
2049
|
}
|
|
@@ -2370,7 +2393,7 @@ let Selectic = class Selectic extends vtyx.Vue {
|
|
|
2370
2393
|
/* }}} */
|
|
2371
2394
|
/* {{{ Life cycle */
|
|
2372
2395
|
created() {
|
|
2373
|
-
var _a, _b;
|
|
2396
|
+
var _a, _b, _c;
|
|
2374
2397
|
this._elementsListeners = [];
|
|
2375
2398
|
this.store = new SelecticStore({
|
|
2376
2399
|
options: this.options,
|
|
@@ -2383,8 +2406,7 @@ let Selectic = class Selectic extends vtyx.Vue {
|
|
|
2383
2406
|
params: {
|
|
2384
2407
|
multiple: ((_a = this.multiple) !== null && _a !== void 0 ? _a : false) !== false,
|
|
2385
2408
|
pageSize: this.params.pageSize || 100,
|
|
2386
|
-
hideFilter: this.params.hideFilter !==
|
|
2387
|
-
? this.params.hideFilter : 'auto',
|
|
2409
|
+
hideFilter: (_b = this.params.hideFilter) !== null && _b !== void 0 ? _b : 'auto',
|
|
2388
2410
|
allowRevert: this.params.allowRevert,
|
|
2389
2411
|
allowClearSelection: this.params.allowClearSelection || false,
|
|
2390
2412
|
autoSelect: this.params.autoSelect === undefined
|
|
@@ -2399,7 +2421,7 @@ let Selectic = class Selectic extends vtyx.Vue {
|
|
|
2399
2421
|
formatSelection: this.params.formatSelection,
|
|
2400
2422
|
listPosition: this.params.listPosition || 'auto',
|
|
2401
2423
|
optionBehavior: this.params.optionBehavior,
|
|
2402
|
-
isOpen: ((
|
|
2424
|
+
isOpen: ((_c = this.open) !== null && _c !== void 0 ? _c : false) !== false,
|
|
2403
2425
|
},
|
|
2404
2426
|
fetchCallback: this.params.fetchCallback,
|
|
2405
2427
|
getItemsCallback: this.params.getItemsCallback,
|
|
@@ -2545,10 +2567,19 @@ __decorate([
|
|
|
2545
2567
|
__decorate([
|
|
2546
2568
|
vtyx.Watch('store.state.internalValue')
|
|
2547
2569
|
], Selectic.prototype, "onInternalValueChange", null);
|
|
2570
|
+
__decorate([
|
|
2571
|
+
vtyx.Emit('input'),
|
|
2572
|
+
vtyx.Emit('change'),
|
|
2573
|
+
vtyx.Emit('open'),
|
|
2574
|
+
vtyx.Emit('focus'),
|
|
2575
|
+
vtyx.Emit('close'),
|
|
2576
|
+
vtyx.Emit('blur'),
|
|
2577
|
+
vtyx.Emit('item:click')
|
|
2578
|
+
], Selectic.prototype, "render", null);
|
|
2548
2579
|
Selectic = __decorate([
|
|
2549
2580
|
vtyx.Component
|
|
2550
2581
|
], Selectic);
|
|
2551
2582
|
var Selectic$1 = Selectic;
|
|
2552
2583
|
|
|
2553
2584
|
exports.changeTexts = changeTexts;
|
|
2554
|
-
exports[
|
|
2585
|
+
exports["default"] = Selectic$1;
|
package/dist/selectic.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Prop, Watch, Component, Vue, h } from 'vtyx';
|
|
1
|
+
import { Prop, Watch, Component, Vue, h, Emit } from 'vtyx';
|
|
2
2
|
import { reactive, computed, unref, watch } from 'vue';
|
|
3
3
|
|
|
4
4
|
function styleInject(css, ref) {
|
|
@@ -97,12 +97,33 @@ let closePreviousSelectic;
|
|
|
97
97
|
let uid = 0;
|
|
98
98
|
class SelecticStore {
|
|
99
99
|
constructor(props = {}) {
|
|
100
|
+
/* Do not need reactivity */
|
|
101
|
+
this.requestId = 0;
|
|
102
|
+
this._uid = ++uid;
|
|
103
|
+
/* {{{ Props */
|
|
104
|
+
const defaultProps = {
|
|
105
|
+
value: null,
|
|
106
|
+
selectionIsExcluded: false,
|
|
107
|
+
disabled: false,
|
|
108
|
+
options: null,
|
|
109
|
+
childOptions: [],
|
|
110
|
+
groups: [],
|
|
111
|
+
texts: null,
|
|
112
|
+
params: {},
|
|
113
|
+
fetchCallback: null,
|
|
114
|
+
getItemsCallback: null,
|
|
115
|
+
keepOpenWithOtherSelectic: false,
|
|
116
|
+
};
|
|
117
|
+
const propsVal = assignObject(defaultProps, props);
|
|
118
|
+
this.props = reactive(propsVal);
|
|
119
|
+
/* }}} */
|
|
100
120
|
/* {{{ data */
|
|
101
121
|
this.state = reactive({
|
|
102
122
|
multiple: false,
|
|
103
123
|
disabled: false,
|
|
104
124
|
placeholder: '',
|
|
105
125
|
hideFilter: false,
|
|
126
|
+
keepFilterOpen: false,
|
|
106
127
|
allowRevert: undefined,
|
|
107
128
|
allowClearSelection: false,
|
|
108
129
|
autoSelect: true,
|
|
@@ -136,27 +157,6 @@ class SelecticStore {
|
|
|
136
157
|
automaticClose: false,
|
|
137
158
|
},
|
|
138
159
|
});
|
|
139
|
-
/* Do not need reactivity */
|
|
140
|
-
this.requestId = 0;
|
|
141
|
-
this._uid = ++uid;
|
|
142
|
-
/* {{{ Props */
|
|
143
|
-
const defaultProps = {
|
|
144
|
-
value: null,
|
|
145
|
-
selectionIsExcluded: false,
|
|
146
|
-
disabled: false,
|
|
147
|
-
options: null,
|
|
148
|
-
childOptions: [],
|
|
149
|
-
groups: [],
|
|
150
|
-
texts: null,
|
|
151
|
-
params: {},
|
|
152
|
-
fetchCallback: null,
|
|
153
|
-
getItemsCallback: null,
|
|
154
|
-
keepOpenWithOtherSelectic: false,
|
|
155
|
-
};
|
|
156
|
-
const propsVal = assignObject(defaultProps, props);
|
|
157
|
-
this.props = reactive(propsVal);
|
|
158
|
-
/* }}} */
|
|
159
|
-
/* {{{ data */
|
|
160
160
|
this.data = reactive({
|
|
161
161
|
labels: Object.assign({}, messages),
|
|
162
162
|
itemsPerPage: 10,
|
|
@@ -260,14 +260,18 @@ class SelecticStore {
|
|
|
260
260
|
if (stateParam.hideFilter === 'auto') {
|
|
261
261
|
delete stateParam.hideFilter;
|
|
262
262
|
}
|
|
263
|
+
else if (stateParam.hideFilter === 'open') {
|
|
264
|
+
this.state.keepFilterOpen = true;
|
|
265
|
+
delete stateParam.hideFilter;
|
|
266
|
+
}
|
|
263
267
|
/* Update state */
|
|
264
268
|
assignObject(this.state, stateParam);
|
|
265
269
|
/* XXX: should be done in 2 lines, in order to set the multiple state
|
|
266
270
|
* and ensure convertValue run with correct state */
|
|
267
271
|
assignObject(this.state, {
|
|
268
272
|
internalValue: this.convertTypeValue(value),
|
|
269
|
-
selectionIsExcluded: props.selectionIsExcluded,
|
|
270
|
-
disabled: props.disabled,
|
|
273
|
+
selectionIsExcluded: !!props.selectionIsExcluded,
|
|
274
|
+
disabled: !!props.disabled, /* XXX: !! is needed to copy value and not proxy reference */
|
|
271
275
|
});
|
|
272
276
|
this.checkHideFilter();
|
|
273
277
|
if (this.props.texts) {
|
|
@@ -1464,6 +1468,10 @@ let FilterPanel = class FilterPanel extends Vue {
|
|
|
1464
1468
|
this.store.commit('selectionIsExcluded', !this.selectionIsExcluded);
|
|
1465
1469
|
}
|
|
1466
1470
|
togglePanel() {
|
|
1471
|
+
if (this.store.state.keepFilterOpen === true) {
|
|
1472
|
+
this.closed = false;
|
|
1473
|
+
return;
|
|
1474
|
+
}
|
|
1467
1475
|
this.closed = !this.closed;
|
|
1468
1476
|
}
|
|
1469
1477
|
getFocus() {
|
|
@@ -1480,7 +1488,8 @@ let FilterPanel = class FilterPanel extends Vue {
|
|
|
1480
1488
|
/* }}} */
|
|
1481
1489
|
/* {{{ Life cycle */
|
|
1482
1490
|
mounted() {
|
|
1483
|
-
|
|
1491
|
+
const state = this.store.state;
|
|
1492
|
+
this.closed = !state.keepFilterOpen && !state.searchText;
|
|
1484
1493
|
document.addEventListener('keypress', this.onKeyPressed);
|
|
1485
1494
|
this.getFocus();
|
|
1486
1495
|
}
|
|
@@ -1489,24 +1498,27 @@ let FilterPanel = class FilterPanel extends Vue {
|
|
|
1489
1498
|
}
|
|
1490
1499
|
/* }}} */
|
|
1491
1500
|
render() {
|
|
1501
|
+
const store = this.store;
|
|
1502
|
+
const state = store.state;
|
|
1503
|
+
const labels = store.data.labels;
|
|
1492
1504
|
return (h("div", { class: "filter-panel" },
|
|
1493
1505
|
h("div", { class: {
|
|
1494
1506
|
panelclosed: this.closed,
|
|
1495
1507
|
panelopened: !this.closed,
|
|
1496
1508
|
} },
|
|
1497
1509
|
h("div", { class: "filter-panel__input form-group has-feedback" },
|
|
1498
|
-
h("input", { type: "text", class: "form-control filter-input", placeholder: this.searchPlaceholder, value:
|
|
1510
|
+
h("input", { type: "text", class: "form-control filter-input", placeholder: this.searchPlaceholder, value: state.searchText, on: {
|
|
1499
1511
|
'input.stop.prevent': this.onInput,
|
|
1500
1512
|
}, ref: "filterInput" }),
|
|
1501
1513
|
h("span", { class: "fa fa-search selectic-search-scope\n form-control-feedback" })),
|
|
1502
|
-
|
|
1514
|
+
state.multiple && (h("div", { class: "toggle-selectic" },
|
|
1503
1515
|
h("label", { class: ['control-label', {
|
|
1504
1516
|
'selectic__label-disabled': this.disableSelectAll,
|
|
1505
1517
|
}] },
|
|
1506
|
-
h("input", { type: "checkbox", checked:
|
|
1518
|
+
h("input", { type: "checkbox", checked: state.status.areAllSelected, disabled: this.disableSelectAll, on: {
|
|
1507
1519
|
change: this.onSelectAll,
|
|
1508
1520
|
} }),
|
|
1509
|
-
|
|
1521
|
+
labels.selectAll))),
|
|
1510
1522
|
this.enableRevert && (h("div", { class: ['toggle-selectic', {
|
|
1511
1523
|
'selectic__label-disabled': this.disableRevert,
|
|
1512
1524
|
}] },
|
|
@@ -1514,8 +1526,8 @@ let FilterPanel = class FilterPanel extends Vue {
|
|
|
1514
1526
|
h("input", { type: "checkbox", checked: this.selectionIsExcluded, disabled: this.disableRevert, on: {
|
|
1515
1527
|
change: this.onExclude,
|
|
1516
1528
|
} }),
|
|
1517
|
-
|
|
1518
|
-
h("div", { class: "curtain-handler", on: {
|
|
1529
|
+
labels.excludeResult)))),
|
|
1530
|
+
!state.keepFilterOpen && (h("div", { class: "curtain-handler", on: {
|
|
1519
1531
|
'click.prevent.stop': this.togglePanel,
|
|
1520
1532
|
} },
|
|
1521
1533
|
h("span", { class: "fa fa-search" }),
|
|
@@ -1523,7 +1535,7 @@ let FilterPanel = class FilterPanel extends Vue {
|
|
|
1523
1535
|
'fa': true,
|
|
1524
1536
|
'fa-caret-down': this.closed,
|
|
1525
1537
|
'fa-caret-up': !this.closed,
|
|
1526
|
-
} }))));
|
|
1538
|
+
} })))));
|
|
1527
1539
|
}
|
|
1528
1540
|
};
|
|
1529
1541
|
__decorate$3([
|
|
@@ -2008,15 +2020,26 @@ let Selectic = class Selectic extends Vue {
|
|
|
2008
2020
|
}
|
|
2009
2021
|
get outsideListener() {
|
|
2010
2022
|
return (evt) => {
|
|
2011
|
-
const target = evt.target;
|
|
2012
2023
|
if (!this.$refs) {
|
|
2013
2024
|
/* this component should have been destroyed */
|
|
2014
2025
|
this.removeListeners();
|
|
2015
2026
|
this.store.commit('isOpen', false);
|
|
2016
2027
|
return;
|
|
2017
2028
|
}
|
|
2018
|
-
|
|
2019
|
-
|
|
2029
|
+
const store = this.store;
|
|
2030
|
+
const keepOpenWithOtherSelectic = this.params.keepOpenWithOtherSelectic;
|
|
2031
|
+
const extendedList = this.$refs.extendedList;
|
|
2032
|
+
if (!extendedList) {
|
|
2033
|
+
/* this component is not focused anymore */
|
|
2034
|
+
if (!keepOpenWithOtherSelectic) {
|
|
2035
|
+
this.removeListeners();
|
|
2036
|
+
this.store.commit('isOpen', false);
|
|
2037
|
+
}
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
const target = evt.target;
|
|
2041
|
+
if (!extendedList.$el.contains(target) && !this.$el.contains(target)) {
|
|
2042
|
+
store.commit('isOpen', false);
|
|
2020
2043
|
}
|
|
2021
2044
|
};
|
|
2022
2045
|
}
|
|
@@ -2366,7 +2389,7 @@ let Selectic = class Selectic extends Vue {
|
|
|
2366
2389
|
/* }}} */
|
|
2367
2390
|
/* {{{ Life cycle */
|
|
2368
2391
|
created() {
|
|
2369
|
-
var _a, _b;
|
|
2392
|
+
var _a, _b, _c;
|
|
2370
2393
|
this._elementsListeners = [];
|
|
2371
2394
|
this.store = new SelecticStore({
|
|
2372
2395
|
options: this.options,
|
|
@@ -2379,8 +2402,7 @@ let Selectic = class Selectic extends Vue {
|
|
|
2379
2402
|
params: {
|
|
2380
2403
|
multiple: ((_a = this.multiple) !== null && _a !== void 0 ? _a : false) !== false,
|
|
2381
2404
|
pageSize: this.params.pageSize || 100,
|
|
2382
|
-
hideFilter: this.params.hideFilter !==
|
|
2383
|
-
? this.params.hideFilter : 'auto',
|
|
2405
|
+
hideFilter: (_b = this.params.hideFilter) !== null && _b !== void 0 ? _b : 'auto',
|
|
2384
2406
|
allowRevert: this.params.allowRevert,
|
|
2385
2407
|
allowClearSelection: this.params.allowClearSelection || false,
|
|
2386
2408
|
autoSelect: this.params.autoSelect === undefined
|
|
@@ -2395,7 +2417,7 @@ let Selectic = class Selectic extends Vue {
|
|
|
2395
2417
|
formatSelection: this.params.formatSelection,
|
|
2396
2418
|
listPosition: this.params.listPosition || 'auto',
|
|
2397
2419
|
optionBehavior: this.params.optionBehavior,
|
|
2398
|
-
isOpen: ((
|
|
2420
|
+
isOpen: ((_c = this.open) !== null && _c !== void 0 ? _c : false) !== false,
|
|
2399
2421
|
},
|
|
2400
2422
|
fetchCallback: this.params.fetchCallback,
|
|
2401
2423
|
getItemsCallback: this.params.getItemsCallback,
|
|
@@ -2541,6 +2563,15 @@ __decorate([
|
|
|
2541
2563
|
__decorate([
|
|
2542
2564
|
Watch('store.state.internalValue')
|
|
2543
2565
|
], Selectic.prototype, "onInternalValueChange", null);
|
|
2566
|
+
__decorate([
|
|
2567
|
+
Emit('input'),
|
|
2568
|
+
Emit('change'),
|
|
2569
|
+
Emit('open'),
|
|
2570
|
+
Emit('focus'),
|
|
2571
|
+
Emit('close'),
|
|
2572
|
+
Emit('blur'),
|
|
2573
|
+
Emit('item:click')
|
|
2574
|
+
], Selectic.prototype, "render", null);
|
|
2544
2575
|
Selectic = __decorate([
|
|
2545
2576
|
Component
|
|
2546
2577
|
], Selectic);
|
package/doc/params.md
CHANGED
|
@@ -10,13 +10,16 @@ This property is an object with several attributes which are listed below.
|
|
|
10
10
|
|
|
11
11
|
## hideFilter
|
|
12
12
|
|
|
13
|
-
Type: `boolean` | `'auto'`
|
|
13
|
+
Type: `boolean` | `'auto'` | `'open'`
|
|
14
14
|
|
|
15
15
|
If `hideFilter` is set to `true`, the handler to open the filter panel is hidden and it will not be possible to search for options.
|
|
16
16
|
|
|
17
17
|
If `hideFilter` is set to `'auto`, the handler to open the filter panel is hidden only if there is less than 10 options (when there is no scroll), and is displayed otherwise. _This is the default value_.
|
|
18
18
|
|
|
19
|
-
If `hideFilter` is set to `
|
|
19
|
+
If `hideFilter` is set to `false`, the handler to open the filter panel is always displayed.
|
|
20
|
+
|
|
21
|
+
If `hideFilter` is set to `'open'`, the handler to open or close the filter panel
|
|
22
|
+
will not be displayed and the filter panel is always open.
|
|
20
23
|
|
|
21
24
|
```html
|
|
22
25
|
<selectic
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "selectic",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.6",
|
|
4
4
|
"description": "Smart Select for VueJS 3.x",
|
|
5
5
|
"main": "dist/selectic.common.js",
|
|
6
6
|
"module": "dist/selectic.esm.js",
|
|
@@ -36,12 +36,13 @@
|
|
|
36
36
|
"test": "npm run build && tape test/**/*.spec.js"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"vtyx": "4.0.
|
|
39
|
+
"vtyx": "4.0.3"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"
|
|
42
|
+
"@babel/types": "^7.16.7",
|
|
43
|
+
"rollup": "^2.63.0",
|
|
43
44
|
"rollup-plugin-postcss": "^3.1.8",
|
|
44
|
-
"tape": "^4.
|
|
45
|
-
"typescript": "~4.
|
|
45
|
+
"tape": "^4.14.0",
|
|
46
|
+
"typescript": "~4.5"
|
|
46
47
|
}
|
|
47
48
|
}
|
package/src/Filter.tsx
CHANGED
|
@@ -100,6 +100,10 @@ export default class FilterPanel extends Vue<Props> {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
private togglePanel() {
|
|
103
|
+
if (this.store.state.keepFilterOpen === true) {
|
|
104
|
+
this.closed = false;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
103
107
|
this.closed = !this.closed;
|
|
104
108
|
}
|
|
105
109
|
|
|
@@ -122,7 +126,8 @@ export default class FilterPanel extends Vue<Props> {
|
|
|
122
126
|
/* {{{ Life cycle */
|
|
123
127
|
|
|
124
128
|
public mounted() {
|
|
125
|
-
|
|
129
|
+
const state = this.store.state;
|
|
130
|
+
this.closed = !state.keepFilterOpen && !state.searchText;
|
|
126
131
|
document.addEventListener('keypress', this.onKeyPressed);
|
|
127
132
|
|
|
128
133
|
this.getFocus();
|
|
@@ -135,6 +140,10 @@ export default class FilterPanel extends Vue<Props> {
|
|
|
135
140
|
/* }}} */
|
|
136
141
|
|
|
137
142
|
public render() {
|
|
143
|
+
const store = this.store;
|
|
144
|
+
const state = store.state;
|
|
145
|
+
const labels = store.data.labels;
|
|
146
|
+
|
|
138
147
|
return (
|
|
139
148
|
<div class="filter-panel">
|
|
140
149
|
<div
|
|
@@ -148,7 +157,7 @@ export default class FilterPanel extends Vue<Props> {
|
|
|
148
157
|
type="text"
|
|
149
158
|
class="form-control filter-input"
|
|
150
159
|
placeholder={this.searchPlaceholder}
|
|
151
|
-
value={
|
|
160
|
+
value={state.searchText}
|
|
152
161
|
on={{
|
|
153
162
|
'input.stop.prevent': this.onInput,
|
|
154
163
|
}}
|
|
@@ -158,7 +167,7 @@ export default class FilterPanel extends Vue<Props> {
|
|
|
158
167
|
form-control-feedback"
|
|
159
168
|
></span>
|
|
160
169
|
</div>
|
|
161
|
-
{
|
|
170
|
+
{state.multiple && (
|
|
162
171
|
<div class="toggle-selectic">
|
|
163
172
|
<label
|
|
164
173
|
class={['control-label', {
|
|
@@ -167,13 +176,13 @@ export default class FilterPanel extends Vue<Props> {
|
|
|
167
176
|
>
|
|
168
177
|
<input
|
|
169
178
|
type="checkbox"
|
|
170
|
-
checked={
|
|
179
|
+
checked={state.status.areAllSelected}
|
|
171
180
|
disabled={this.disableSelectAll}
|
|
172
181
|
on={{
|
|
173
182
|
change: this.onSelectAll,
|
|
174
183
|
}}
|
|
175
184
|
/>
|
|
176
|
-
{
|
|
185
|
+
{labels.selectAll}
|
|
177
186
|
</label>
|
|
178
187
|
</div>
|
|
179
188
|
)}
|
|
@@ -192,11 +201,13 @@ export default class FilterPanel extends Vue<Props> {
|
|
|
192
201
|
change: this.onExclude,
|
|
193
202
|
}}
|
|
194
203
|
/>
|
|
195
|
-
{
|
|
204
|
+
{labels.excludeResult}
|
|
196
205
|
</label>
|
|
197
206
|
</div>
|
|
198
207
|
)}
|
|
199
208
|
</div>
|
|
209
|
+
|
|
210
|
+
{!state.keepFilterOpen && (
|
|
200
211
|
<div class="curtain-handler"
|
|
201
212
|
on={{
|
|
202
213
|
'click.prevent.stop': this.togglePanel,
|
|
@@ -209,6 +220,7 @@ export default class FilterPanel extends Vue<Props> {
|
|
|
209
220
|
'fa-caret-up': !this.closed,
|
|
210
221
|
}}></span>
|
|
211
222
|
</div>
|
|
223
|
+
)}
|
|
212
224
|
</div>
|
|
213
225
|
);
|
|
214
226
|
}
|
package/src/Store.tsx
CHANGED
|
@@ -72,6 +72,15 @@ export type ListPosition =
|
|
|
72
72
|
/* Display the list at bottom but if there is not enough space, display it at top */
|
|
73
73
|
| 'auto';
|
|
74
74
|
|
|
75
|
+
export type HideFilter =
|
|
76
|
+
/* Display or hide the filter panel */
|
|
77
|
+
boolean
|
|
78
|
+
/* The handler to open the filter panel is hidden only if there is less
|
|
79
|
+
* than 10 options */
|
|
80
|
+
| 'auto'
|
|
81
|
+
/* The panel filter is always open */
|
|
82
|
+
| 'open';
|
|
83
|
+
|
|
75
84
|
export interface SelecticStoreStateParams {
|
|
76
85
|
/* Equivalent of <select>'s "multiple" attribute */
|
|
77
86
|
multiple?: boolean;
|
|
@@ -80,7 +89,7 @@ export interface SelecticStoreStateParams {
|
|
|
80
89
|
placeholder?: string;
|
|
81
90
|
|
|
82
91
|
/* Hide filter component when enabled */
|
|
83
|
-
hideFilter?:
|
|
92
|
+
hideFilter?: HideFilter;
|
|
84
93
|
|
|
85
94
|
/* Allow to reverse selection.
|
|
86
95
|
* If true, parent should support the selectionIsExcluded property.
|
|
@@ -203,6 +212,9 @@ export interface SelecticStoreState {
|
|
|
203
212
|
/* If true, filters and controls are hidden */
|
|
204
213
|
hideFilter: boolean;
|
|
205
214
|
|
|
215
|
+
/* If true, the filter panel is always open */
|
|
216
|
+
keepFilterOpen: boolean;
|
|
217
|
+
|
|
206
218
|
/* Allow to reverse selection.
|
|
207
219
|
* If true, parent should support the selectionIsExcluded property.
|
|
208
220
|
* If false, the action is never available.
|
|
@@ -399,47 +411,7 @@ export default class SelecticStore {
|
|
|
399
411
|
|
|
400
412
|
/* {{{ data */
|
|
401
413
|
|
|
402
|
-
public state
|
|
403
|
-
multiple: false,
|
|
404
|
-
disabled: false,
|
|
405
|
-
placeholder: '',
|
|
406
|
-
hideFilter: false,
|
|
407
|
-
allowRevert: undefined,
|
|
408
|
-
allowClearSelection: false,
|
|
409
|
-
autoSelect: true,
|
|
410
|
-
autoDisabled: true,
|
|
411
|
-
strictValue: false,
|
|
412
|
-
selectionOverflow: 'collapsed',
|
|
413
|
-
|
|
414
|
-
internalValue: null,
|
|
415
|
-
isOpen: false,
|
|
416
|
-
searchText: '',
|
|
417
|
-
selectionIsExcluded: false,
|
|
418
|
-
allOptions: [],
|
|
419
|
-
dynOptions: [],
|
|
420
|
-
filteredOptions: [],
|
|
421
|
-
selectedOptions: null,
|
|
422
|
-
totalAllOptions: Infinity,
|
|
423
|
-
totalDynOptions: Infinity,
|
|
424
|
-
totalFilteredOptions: Infinity,
|
|
425
|
-
groups: new Map(),
|
|
426
|
-
offsetItem: 0,
|
|
427
|
-
activeItemIdx: -1,
|
|
428
|
-
pageSize: 100,
|
|
429
|
-
listPosition: 'auto',
|
|
430
|
-
|
|
431
|
-
optionBehaviorOperation: 'sort',
|
|
432
|
-
optionBehaviorOrder: ['O', 'D', 'E'],
|
|
433
|
-
|
|
434
|
-
status: {
|
|
435
|
-
searching: false,
|
|
436
|
-
errorMessage: '',
|
|
437
|
-
areAllSelected: false,
|
|
438
|
-
hasChanged: false,
|
|
439
|
-
automaticChange: false,
|
|
440
|
-
automaticClose: false,
|
|
441
|
-
},
|
|
442
|
-
});
|
|
414
|
+
public state: SelecticStoreState;
|
|
443
415
|
public data: Data;
|
|
444
416
|
|
|
445
417
|
/* Do not need reactivity */
|
|
@@ -487,6 +459,49 @@ export default class SelecticStore {
|
|
|
487
459
|
/* }}} */
|
|
488
460
|
/* {{{ data */
|
|
489
461
|
|
|
462
|
+
this.state = reactive<SelecticStoreState>({
|
|
463
|
+
multiple: false,
|
|
464
|
+
disabled: false,
|
|
465
|
+
placeholder: '',
|
|
466
|
+
hideFilter: false,
|
|
467
|
+
keepFilterOpen: false,
|
|
468
|
+
allowRevert: undefined,
|
|
469
|
+
allowClearSelection: false,
|
|
470
|
+
autoSelect: true,
|
|
471
|
+
autoDisabled: true,
|
|
472
|
+
strictValue: false,
|
|
473
|
+
selectionOverflow: 'collapsed',
|
|
474
|
+
|
|
475
|
+
internalValue: null,
|
|
476
|
+
isOpen: false,
|
|
477
|
+
searchText: '',
|
|
478
|
+
selectionIsExcluded: false,
|
|
479
|
+
allOptions: [],
|
|
480
|
+
dynOptions: [],
|
|
481
|
+
filteredOptions: [],
|
|
482
|
+
selectedOptions: null,
|
|
483
|
+
totalAllOptions: Infinity,
|
|
484
|
+
totalDynOptions: Infinity,
|
|
485
|
+
totalFilteredOptions: Infinity,
|
|
486
|
+
groups: new Map(),
|
|
487
|
+
offsetItem: 0,
|
|
488
|
+
activeItemIdx: -1,
|
|
489
|
+
pageSize: 100,
|
|
490
|
+
listPosition: 'auto',
|
|
491
|
+
|
|
492
|
+
optionBehaviorOperation: 'sort',
|
|
493
|
+
optionBehaviorOrder: ['O', 'D', 'E'],
|
|
494
|
+
|
|
495
|
+
status: {
|
|
496
|
+
searching: false,
|
|
497
|
+
errorMessage: '',
|
|
498
|
+
areAllSelected: false,
|
|
499
|
+
hasChanged: false,
|
|
500
|
+
automaticChange: false,
|
|
501
|
+
automaticClose: false,
|
|
502
|
+
},
|
|
503
|
+
});
|
|
504
|
+
|
|
490
505
|
this.data = reactive({
|
|
491
506
|
labels: Object.assign({}, messages),
|
|
492
507
|
itemsPerPage: 10,
|
|
@@ -625,6 +640,9 @@ export default class SelecticStore {
|
|
|
625
640
|
|
|
626
641
|
if (stateParam.hideFilter === 'auto') {
|
|
627
642
|
delete stateParam.hideFilter;
|
|
643
|
+
} else if (stateParam.hideFilter === 'open') {
|
|
644
|
+
this.state.keepFilterOpen = true;
|
|
645
|
+
delete stateParam.hideFilter;
|
|
628
646
|
}
|
|
629
647
|
|
|
630
648
|
/* Update state */
|
|
@@ -633,8 +651,8 @@ export default class SelecticStore {
|
|
|
633
651
|
* and ensure convertValue run with correct state */
|
|
634
652
|
assignObject(this.state, {
|
|
635
653
|
internalValue: this.convertTypeValue(value),
|
|
636
|
-
selectionIsExcluded: props.selectionIsExcluded,
|
|
637
|
-
disabled: props.disabled,
|
|
654
|
+
selectionIsExcluded: !!props.selectionIsExcluded,
|
|
655
|
+
disabled: !!props.disabled, /* XXX: !! is needed to copy value and not proxy reference */
|
|
638
656
|
});
|
|
639
657
|
|
|
640
658
|
this.checkHideFilter();
|
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,6 +56,7 @@ export {
|
|
|
55
56
|
FormatCallback,
|
|
56
57
|
SelectionOverflow,
|
|
57
58
|
ListPosition,
|
|
59
|
+
HideFilter,
|
|
58
60
|
};
|
|
59
61
|
|
|
60
62
|
type EventType = 'input' | 'change' | 'open' | 'close' | 'focus' | 'blur' | 'item:click';
|
|
@@ -83,7 +85,7 @@ export interface ParamProps {
|
|
|
83
85
|
pageSize?: number;
|
|
84
86
|
|
|
85
87
|
/* Hide the search control */
|
|
86
|
-
hideFilter?:
|
|
88
|
+
hideFilter?: HideFilter;
|
|
87
89
|
|
|
88
90
|
/* Allow to reverse selection.
|
|
89
91
|
* If true, parent should support the selectionIsExcluded property.
|
|
@@ -307,8 +309,6 @@ export default class Selectic extends Vue<Props> {
|
|
|
307
309
|
|
|
308
310
|
get outsideListener() {
|
|
309
311
|
return (evt: MouseEvent) => {
|
|
310
|
-
const target = evt.target as Node;
|
|
311
|
-
|
|
312
312
|
if (!this.$refs) {
|
|
313
313
|
/* this component should have been destroyed */
|
|
314
314
|
this.removeListeners();
|
|
@@ -316,8 +316,23 @@ export default class Selectic extends Vue<Props> {
|
|
|
316
316
|
return;
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
-
|
|
320
|
-
|
|
319
|
+
const store = this.store;
|
|
320
|
+
const keepOpenWithOtherSelectic = this.params.keepOpenWithOtherSelectic;
|
|
321
|
+
const extendedList = this.$refs.extendedList;
|
|
322
|
+
|
|
323
|
+
if (!extendedList) {
|
|
324
|
+
/* this component is not focused anymore */
|
|
325
|
+
if (!keepOpenWithOtherSelectic) {
|
|
326
|
+
this.removeListeners();
|
|
327
|
+
this.store.commit('isOpen', false);
|
|
328
|
+
}
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const target = evt.target as Node;
|
|
333
|
+
|
|
334
|
+
if (!extendedList.$el.contains(target) && !this.$el.contains(target)) {
|
|
335
|
+
store.commit('isOpen', false);
|
|
321
336
|
}
|
|
322
337
|
};
|
|
323
338
|
}
|
|
@@ -774,8 +789,7 @@ export default class Selectic extends Vue<Props> {
|
|
|
774
789
|
params: {
|
|
775
790
|
multiple: (this.multiple ?? false) !== false,
|
|
776
791
|
pageSize: this.params.pageSize || 100,
|
|
777
|
-
hideFilter: this.params.hideFilter
|
|
778
|
-
? this.params.hideFilter : 'auto',
|
|
792
|
+
hideFilter: this.params.hideFilter ?? 'auto',
|
|
779
793
|
allowRevert: this.params.allowRevert, /* it can be undefined */
|
|
780
794
|
allowClearSelection: this.params.allowClearSelection || false,
|
|
781
795
|
autoSelect: this.params.autoSelect === undefined
|
|
@@ -843,6 +857,13 @@ export default class Selectic extends Vue<Props> {
|
|
|
843
857
|
|
|
844
858
|
/* }}} */
|
|
845
859
|
|
|
860
|
+
@Emit('input')
|
|
861
|
+
@Emit('change')
|
|
862
|
+
@Emit('open')
|
|
863
|
+
@Emit('focus')
|
|
864
|
+
@Emit('close')
|
|
865
|
+
@Emit('blur')
|
|
866
|
+
@Emit('item:click')
|
|
846
867
|
public render() {
|
|
847
868
|
const id = this.id || undefined;
|
|
848
869
|
const store = this.store;
|
|
@@ -943,6 +943,7 @@ tape.test('Store creation', (subT) => {
|
|
|
943
943
|
await sleep(0);
|
|
944
944
|
|
|
945
945
|
t.is(store.state.hideFilter, true);
|
|
946
|
+
t.is(store.state.keepFilterOpen, false);
|
|
946
947
|
t.end();
|
|
947
948
|
});
|
|
948
949
|
|
|
@@ -956,6 +957,7 @@ tape.test('Store creation', (subT) => {
|
|
|
956
957
|
await sleep(0);
|
|
957
958
|
|
|
958
959
|
t.is(store.state.hideFilter, false);
|
|
960
|
+
t.is(store.state.keepFilterOpen, false);
|
|
959
961
|
t.end();
|
|
960
962
|
});
|
|
961
963
|
|
|
@@ -994,6 +996,7 @@ tape.test('Store creation', (subT) => {
|
|
|
994
996
|
await sleep(0);
|
|
995
997
|
|
|
996
998
|
t.is(store.state.hideFilter, false);
|
|
999
|
+
t.is(store.state.keepFilterOpen, false);
|
|
997
1000
|
t.end();
|
|
998
1001
|
});
|
|
999
1002
|
});
|
|
@@ -1009,6 +1012,7 @@ tape.test('Store creation', (subT) => {
|
|
|
1009
1012
|
await sleep(0);
|
|
1010
1013
|
|
|
1011
1014
|
t.is(store.state.hideFilter, false);
|
|
1015
|
+
t.is(store.state.keepFilterOpen, false);
|
|
1012
1016
|
t.end();
|
|
1013
1017
|
});
|
|
1014
1018
|
|
|
@@ -1022,17 +1026,20 @@ tape.test('Store creation', (subT) => {
|
|
|
1022
1026
|
await sleep(0);
|
|
1023
1027
|
|
|
1024
1028
|
t.is(store.state.hideFilter, false);
|
|
1029
|
+
t.is(store.state.keepFilterOpen, false);
|
|
1025
1030
|
|
|
1026
1031
|
/* Assert it doesn't change after fetching data */
|
|
1027
1032
|
store.commit('isOpen', true);
|
|
1028
1033
|
await sleep(0);
|
|
1029
1034
|
|
|
1030
1035
|
t.is(store.state.hideFilter, false);
|
|
1036
|
+
t.is(store.state.keepFilterOpen, false);
|
|
1031
1037
|
|
|
1032
1038
|
store.commit('isOpen', false);
|
|
1033
1039
|
await sleep(0);
|
|
1034
1040
|
|
|
1035
1041
|
t.is(store.state.hideFilter, false);
|
|
1042
|
+
t.is(store.state.keepFilterOpen, false);
|
|
1036
1043
|
t.end();
|
|
1037
1044
|
});
|
|
1038
1045
|
});
|
|
@@ -1089,6 +1096,49 @@ tape.test('Store creation', (subT) => {
|
|
|
1089
1096
|
t.end();
|
|
1090
1097
|
});
|
|
1091
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
|
+
});
|
|
1092
1142
|
});
|
|
1093
1143
|
|
|
1094
1144
|
subT.test('"optionBehavior" property', (st) => {
|
|
@@ -223,6 +223,7 @@ tape.test('change props', (subT) => {
|
|
|
223
223
|
const store = new Store({
|
|
224
224
|
value: 2,
|
|
225
225
|
options: getOptions(5, 'alpha'),
|
|
226
|
+
disabled: false,
|
|
226
227
|
params: {
|
|
227
228
|
autoDisabled: true,
|
|
228
229
|
},
|
|
@@ -249,6 +250,7 @@ tape.test('change props', (subT) => {
|
|
|
249
250
|
const store = new Store({
|
|
250
251
|
value: 2,
|
|
251
252
|
options: getOptions(5, 'alpha'),
|
|
253
|
+
disabled: false,
|
|
252
254
|
params: {
|
|
253
255
|
autoDisabled: true,
|
|
254
256
|
strictValue: true,
|
|
@@ -298,6 +300,37 @@ tape.test('change props', (subT) => {
|
|
|
298
300
|
t.end();
|
|
299
301
|
});
|
|
300
302
|
|
|
303
|
+
sTest.test('should re-enable the select when data are loaded', async (t) => {
|
|
304
|
+
const store = new Store({
|
|
305
|
+
options: [],
|
|
306
|
+
disabled: false,
|
|
307
|
+
params: {
|
|
308
|
+
autoDisabled: true,
|
|
309
|
+
},
|
|
310
|
+
});
|
|
311
|
+
await _.nextVueTick(store);
|
|
312
|
+
|
|
313
|
+
store.commit('isOpen', true);
|
|
314
|
+
await _.nextVueTick(store);
|
|
315
|
+
|
|
316
|
+
t.is(store.state.internalValue, null);
|
|
317
|
+
t.is(store.state.disabled, true);
|
|
318
|
+
t.is(store.state.isOpen, false);
|
|
319
|
+
|
|
320
|
+
store.props.options = getOptions(0, 'alpha');
|
|
321
|
+
await _.nextVueTick(store);
|
|
322
|
+
|
|
323
|
+
t.is(store.state.internalValue, null);
|
|
324
|
+
t.is(store.state.disabled, true), 'should be disabled';
|
|
325
|
+
|
|
326
|
+
store.props.options = getOptions(5, 'beta');
|
|
327
|
+
await _.nextVueTick(store);
|
|
328
|
+
|
|
329
|
+
t.is(store.state.internalValue, 0);
|
|
330
|
+
t.is(store.state.disabled, false), 'should be enabled';
|
|
331
|
+
t.end();
|
|
332
|
+
});
|
|
333
|
+
|
|
301
334
|
sTest.test('should not re-enable the select if disable is set', async (t) => {
|
|
302
335
|
const store = new Store({
|
|
303
336
|
options: getOptions(1, 'alpha'),
|
package/test/helper.js
CHANGED
package/types/List.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Vue, h } from 'vtyx';
|
|
2
|
-
import Store, { OptionItem
|
|
2
|
+
import Store, { OptionItem } from './Store';
|
|
3
3
|
export interface Props {
|
|
4
4
|
store: Store;
|
|
5
5
|
options?: any[];
|
|
@@ -14,31 +14,7 @@ export default class List extends Vue<Props> {
|
|
|
14
14
|
private itemHeight;
|
|
15
15
|
private groupId;
|
|
16
16
|
private doNotScroll;
|
|
17
|
-
get filteredOptions():
|
|
18
|
-
selected: boolean;
|
|
19
|
-
disabled: boolean;
|
|
20
|
-
isGroup: boolean;
|
|
21
|
-
id: OptionId;
|
|
22
|
-
text: string;
|
|
23
|
-
title?: string | undefined;
|
|
24
|
-
group?: import("./Store").StrictOptionId | undefined;
|
|
25
|
-
className?: string | undefined;
|
|
26
|
-
style?: string | undefined;
|
|
27
|
-
icon?: string | undefined;
|
|
28
|
-
options?: {
|
|
29
|
-
id: OptionId;
|
|
30
|
-
text: string;
|
|
31
|
-
title?: string | undefined;
|
|
32
|
-
disabled?: boolean | undefined;
|
|
33
|
-
group?: import("./Store").StrictOptionId | undefined;
|
|
34
|
-
className?: string | undefined;
|
|
35
|
-
style?: string | undefined;
|
|
36
|
-
icon?: string | undefined;
|
|
37
|
-
options?: any[] | undefined;
|
|
38
|
-
data?: any;
|
|
39
|
-
}[] | undefined;
|
|
40
|
-
data?: any;
|
|
41
|
-
}[];
|
|
17
|
+
get filteredOptions(): OptionItem[];
|
|
42
18
|
get isMultiple(): boolean;
|
|
43
19
|
get itemsMargin(): number;
|
|
44
20
|
get shortOptions(): OptionItem[];
|
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;
|
|
@@ -140,140 +142,7 @@ export declare type PartialMessages = {
|
|
|
140
142
|
export declare function changeTexts(texts: PartialMessages): void;
|
|
141
143
|
export default class SelecticStore {
|
|
142
144
|
props: InternalProps;
|
|
143
|
-
state:
|
|
144
|
-
internalValue: OptionId | StrictOptionId[];
|
|
145
|
-
selectionIsExcluded: boolean;
|
|
146
|
-
multiple: boolean;
|
|
147
|
-
disabled: boolean;
|
|
148
|
-
placeholder: string;
|
|
149
|
-
hideFilter: boolean;
|
|
150
|
-
allowRevert?: boolean | undefined;
|
|
151
|
-
allowClearSelection: boolean;
|
|
152
|
-
autoSelect: boolean;
|
|
153
|
-
autoDisabled: boolean;
|
|
154
|
-
strictValue: boolean;
|
|
155
|
-
selectionOverflow: SelectionOverflow;
|
|
156
|
-
isOpen: boolean;
|
|
157
|
-
searchText: string;
|
|
158
|
-
allOptions: {
|
|
159
|
-
id: OptionId;
|
|
160
|
-
text: string;
|
|
161
|
-
title?: string | undefined;
|
|
162
|
-
disabled?: boolean | undefined;
|
|
163
|
-
group?: StrictOptionId | undefined;
|
|
164
|
-
className?: string | undefined;
|
|
165
|
-
style?: string | undefined;
|
|
166
|
-
icon?: string | undefined;
|
|
167
|
-
options?: any[] | undefined;
|
|
168
|
-
data?: any;
|
|
169
|
-
}[];
|
|
170
|
-
dynOptions: {
|
|
171
|
-
id: OptionId;
|
|
172
|
-
text: string;
|
|
173
|
-
title?: string | undefined;
|
|
174
|
-
disabled?: boolean | undefined;
|
|
175
|
-
group?: StrictOptionId | undefined;
|
|
176
|
-
className?: string | undefined;
|
|
177
|
-
style?: string | undefined;
|
|
178
|
-
icon?: string | undefined;
|
|
179
|
-
options?: any[] | undefined;
|
|
180
|
-
data?: any;
|
|
181
|
-
}[];
|
|
182
|
-
filteredOptions: {
|
|
183
|
-
selected: boolean;
|
|
184
|
-
disabled: boolean;
|
|
185
|
-
isGroup: boolean;
|
|
186
|
-
id: OptionId;
|
|
187
|
-
text: string;
|
|
188
|
-
title?: string | undefined;
|
|
189
|
-
group?: StrictOptionId | undefined;
|
|
190
|
-
className?: string | undefined;
|
|
191
|
-
style?: string | undefined;
|
|
192
|
-
icon?: string | undefined;
|
|
193
|
-
options?: {
|
|
194
|
-
id: OptionId;
|
|
195
|
-
text: string;
|
|
196
|
-
title?: string | undefined;
|
|
197
|
-
disabled?: boolean | undefined;
|
|
198
|
-
group?: StrictOptionId | undefined;
|
|
199
|
-
className?: string | undefined;
|
|
200
|
-
style?: string | undefined;
|
|
201
|
-
icon?: string | undefined;
|
|
202
|
-
options?: any[] | undefined;
|
|
203
|
-
data?: any;
|
|
204
|
-
}[] | undefined;
|
|
205
|
-
data?: any;
|
|
206
|
-
}[];
|
|
207
|
-
selectedOptions: {
|
|
208
|
-
selected: boolean;
|
|
209
|
-
disabled: boolean;
|
|
210
|
-
isGroup: boolean;
|
|
211
|
-
id: OptionId;
|
|
212
|
-
text: string;
|
|
213
|
-
title?: string | undefined;
|
|
214
|
-
group?: StrictOptionId | undefined;
|
|
215
|
-
className?: string | undefined;
|
|
216
|
-
style?: string | undefined;
|
|
217
|
-
icon?: string | undefined;
|
|
218
|
-
options?: {
|
|
219
|
-
id: OptionId;
|
|
220
|
-
text: string;
|
|
221
|
-
title?: string | undefined;
|
|
222
|
-
disabled?: boolean | undefined;
|
|
223
|
-
group?: StrictOptionId | undefined;
|
|
224
|
-
className?: string | undefined;
|
|
225
|
-
style?: string | undefined;
|
|
226
|
-
icon?: string | undefined;
|
|
227
|
-
options?: any[] | undefined;
|
|
228
|
-
data?: any;
|
|
229
|
-
}[] | undefined;
|
|
230
|
-
data?: any;
|
|
231
|
-
} | {
|
|
232
|
-
selected: boolean;
|
|
233
|
-
disabled: boolean;
|
|
234
|
-
isGroup: boolean;
|
|
235
|
-
id: OptionId;
|
|
236
|
-
text: string;
|
|
237
|
-
title?: string | undefined;
|
|
238
|
-
group?: StrictOptionId | undefined;
|
|
239
|
-
className?: string | undefined;
|
|
240
|
-
style?: string | undefined;
|
|
241
|
-
icon?: string | undefined;
|
|
242
|
-
options?: {
|
|
243
|
-
id: OptionId;
|
|
244
|
-
text: string;
|
|
245
|
-
title?: string | undefined;
|
|
246
|
-
disabled?: boolean | undefined;
|
|
247
|
-
group?: StrictOptionId | undefined;
|
|
248
|
-
className?: string | undefined;
|
|
249
|
-
style?: string | undefined;
|
|
250
|
-
icon?: string | undefined;
|
|
251
|
-
options?: any[] | undefined;
|
|
252
|
-
data?: any;
|
|
253
|
-
}[] | undefined;
|
|
254
|
-
data?: any;
|
|
255
|
-
}[] | null;
|
|
256
|
-
totalAllOptions: number;
|
|
257
|
-
totalDynOptions: number;
|
|
258
|
-
totalFilteredOptions: number;
|
|
259
|
-
groups: Map<OptionId, string>;
|
|
260
|
-
offsetItem: number;
|
|
261
|
-
activeItemIdx: number;
|
|
262
|
-
pageSize: number;
|
|
263
|
-
formatOption?: FormatCallback | undefined;
|
|
264
|
-
formatSelection?: FormatCallback | undefined;
|
|
265
|
-
optionBehaviorOperation: OptionBehaviorOperation;
|
|
266
|
-
optionBehaviorOrder: OptionBehaviorOrder[];
|
|
267
|
-
listPosition: ListPosition;
|
|
268
|
-
status: {
|
|
269
|
-
searching: boolean;
|
|
270
|
-
errorMessage: string;
|
|
271
|
-
areAllSelected: boolean;
|
|
272
|
-
hasChanged: boolean;
|
|
273
|
-
automaticChange: boolean;
|
|
274
|
-
automaticClose: boolean;
|
|
275
|
-
};
|
|
276
|
-
};
|
|
145
|
+
state: SelecticStoreState;
|
|
277
146
|
data: Data;
|
|
278
147
|
private requestId;
|
|
279
148
|
private cacheRequest;
|
package/types/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
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
7
|
declare type EventType = 'input' | 'change' | 'open' | 'close' | 'focus' | 'blur' | 'item:click';
|
|
8
8
|
export interface EventOptions {
|
|
9
9
|
instance: Selectic;
|
|
@@ -17,7 +17,7 @@ export interface ParamProps {
|
|
|
17
17
|
fetchCallback?: FetchCallback;
|
|
18
18
|
getItemsCallback?: GetCallback;
|
|
19
19
|
pageSize?: number;
|
|
20
|
-
hideFilter?:
|
|
20
|
+
hideFilter?: HideFilter;
|
|
21
21
|
allowRevert?: boolean;
|
|
22
22
|
allowClearSelection?: boolean;
|
|
23
23
|
autoSelect?: boolean;
|