selectic 3.0.4 → 3.0.8

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.
Binary file
@@ -101,6 +101,26 @@ 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,
@@ -141,27 +161,6 @@ class SelecticStore {
141
161
  automaticClose: false,
142
162
  },
143
163
  });
144
- /* Do not need reactivity */
145
- this.requestId = 0;
146
- this._uid = ++uid;
147
- /* {{{ Props */
148
- const defaultProps = {
149
- value: null,
150
- selectionIsExcluded: false,
151
- disabled: false,
152
- options: null,
153
- childOptions: [],
154
- groups: [],
155
- texts: null,
156
- params: {},
157
- fetchCallback: null,
158
- getItemsCallback: null,
159
- keepOpenWithOtherSelectic: false,
160
- };
161
- const propsVal = assignObject(defaultProps, props);
162
- this.props = vue.reactive(propsVal);
163
- /* }}} */
164
- /* {{{ data */
165
164
  this.data = vue.reactive({
166
165
  labels: Object.assign({}, messages),
167
166
  itemsPerPage: 10,
@@ -212,17 +211,17 @@ class SelecticStore {
212
211
  this.commit('isOpen', false);
213
212
  this.buildAllOptions(true);
214
213
  this.buildSelectedOptions();
215
- });
214
+ }, { deep: true });
216
215
  vue.watch(() => [this.listOptions, this.elementOptions], () => {
217
216
  /* TODO: transform allOptions as a computed properties and this
218
217
  * watcher become useless */
219
218
  this.buildAllOptions(true);
220
- });
219
+ }, { deep: true });
221
220
  vue.watch(() => this.props.value, () => {
222
221
  var _a;
223
222
  const value = (_a = this.props.value) !== null && _a !== void 0 ? _a : null;
224
223
  this.commit('internalValue', value);
225
- });
224
+ }, { deep: true });
226
225
  vue.watch(() => this.props.selectionIsExcluded, () => {
227
226
  this.commit('selectionIsExcluded', this.props.selectionIsExcluded);
228
227
  });
@@ -238,14 +237,14 @@ class SelecticStore {
238
237
  areAllSelected = this.state.filteredOptions.every((item) => !!(+item.selected ^ selectionIsExcluded));
239
238
  }
240
239
  this.state.status.areAllSelected = areAllSelected;
241
- });
240
+ }, { deep: true });
242
241
  vue.watch(() => this.state.internalValue, () => {
243
242
  this.buildSelectedOptions();
244
- });
243
+ }, { deep: true });
245
244
  vue.watch(() => this.state.allOptions, () => {
246
245
  this.checkAutoSelect();
247
246
  this.checkAutoDisabled();
248
- });
247
+ }, { deep: true });
249
248
  vue.watch(() => this.state.totalAllOptions, () => {
250
249
  this.checkHideFilter();
251
250
  });
@@ -275,8 +274,8 @@ class SelecticStore {
275
274
  * and ensure convertValue run with correct state */
276
275
  assignObject(this.state, {
277
276
  internalValue: this.convertTypeValue(value),
278
- selectionIsExcluded: props.selectionIsExcluded,
279
- disabled: props.disabled,
277
+ selectionIsExcluded: !!this.props.selectionIsExcluded,
278
+ disabled: !!this.props.disabled, /* XXX: !! is needed to copy value and not proxy reference */
280
279
  });
281
280
  this.checkHideFilter();
282
281
  if (this.props.texts) {
@@ -1394,7 +1393,7 @@ __decorate$4([
1394
1393
  vtyx.Prop({ default: '' })
1395
1394
  ], MainInput.prototype, "id", void 0);
1396
1395
  __decorate$4([
1397
- vtyx.Watch('store.state.internalValue')
1396
+ vtyx.Watch('store.state.internalValue', { deep: true })
1398
1397
  ], MainInput.prototype, "onInternalChange", null);
1399
1398
  MainInput = __decorate$4([
1400
1399
  vtyx.Component
@@ -1498,7 +1497,7 @@ let FilterPanel = class FilterPanel extends vtyx.Vue {
1498
1497
  document.addEventListener('keypress', this.onKeyPressed);
1499
1498
  this.getFocus();
1500
1499
  }
1501
- destroyed() {
1500
+ unmounted() {
1502
1501
  document.removeEventListener('keypress', this.onKeyPressed);
1503
1502
  }
1504
1503
  /* }}} */
@@ -1758,7 +1757,7 @@ __decorate$2([
1758
1757
  vtyx.Watch('store.state.offsetItem')
1759
1758
  ], List.prototype, "onOffsetChange", null);
1760
1759
  __decorate$2([
1761
- vtyx.Watch('filteredOptions')
1760
+ vtyx.Watch('filteredOptions', { deep: true })
1762
1761
  ], List.prototype, "onFilteredOptionsChange", null);
1763
1762
  __decorate$2([
1764
1763
  vtyx.Watch('groupId')
@@ -1929,7 +1928,7 @@ let ExtendedList = class ExtendedList extends vtyx.Vue {
1929
1928
  document.body.addEventListener('keydown', this.onKeyDown);
1930
1929
  this.computeListSize();
1931
1930
  }
1932
- destroyed() {
1931
+ unmounted() {
1933
1932
  document.body.removeEventListener('keydown', this.onKeyDown);
1934
1933
  /* force the element to be removed from DOM */
1935
1934
  if (this.$el.parentNode) {
@@ -1974,7 +1973,7 @@ __decorate$1([
1974
1973
  vtyx.Prop({ default: 300 })
1975
1974
  ], ExtendedList.prototype, "width", void 0);
1976
1975
  __decorate$1([
1977
- vtyx.Watch('store.state.filteredOptions')
1976
+ vtyx.Watch('store.state.filteredOptions', { deep: true })
1978
1977
  ], ExtendedList.prototype, "onFilteredOptionsChange", null);
1979
1978
  __decorate$1([
1980
1979
  vtyx.Watch('store.state.hideFilter')
@@ -2025,15 +2024,26 @@ let Selectic = class Selectic extends vtyx.Vue {
2025
2024
  }
2026
2025
  get outsideListener() {
2027
2026
  return (evt) => {
2028
- const target = evt.target;
2029
2027
  if (!this.$refs) {
2030
2028
  /* this component should have been destroyed */
2031
2029
  this.removeListeners();
2032
2030
  this.store.commit('isOpen', false);
2033
2031
  return;
2034
2032
  }
2035
- if (!this.$refs.extendedList.$el.contains(target) && !this.$el.contains(target)) {
2036
- this.store.commit('isOpen', false);
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);
2037
2047
  }
2038
2048
  };
2039
2049
  }
@@ -2452,7 +2462,7 @@ let Selectic = class Selectic extends vtyx.Vue {
2452
2462
  // }
2453
2463
  // this.store.childOptions = options;
2454
2464
  }
2455
- beforeDestroy() {
2465
+ beforeUnmount() {
2456
2466
  this.removeListeners();
2457
2467
  }
2458
2468
  /* }}} */
@@ -2528,22 +2538,22 @@ __decorate([
2528
2538
  vtyx.Prop()
2529
2539
  ], Selectic.prototype, "_getMethods", void 0);
2530
2540
  __decorate([
2531
- vtyx.Watch('value')
2541
+ vtyx.Watch('value', { deep: true })
2532
2542
  ], Selectic.prototype, "onValueChange", null);
2533
2543
  __decorate([
2534
2544
  vtyx.Watch('selectionIsExcluded')
2535
2545
  ], Selectic.prototype, "onExcludedChange", null);
2536
2546
  __decorate([
2537
- vtyx.Watch('options')
2547
+ vtyx.Watch('options', { deep: true })
2538
2548
  ], Selectic.prototype, "onOptionsChange", null);
2539
2549
  __decorate([
2540
- vtyx.Watch('texts')
2550
+ vtyx.Watch('texts', { deep: true })
2541
2551
  ], Selectic.prototype, "onTextsChange", null);
2542
2552
  __decorate([
2543
2553
  vtyx.Watch('disabled')
2544
2554
  ], Selectic.prototype, "onDisabledChange", null);
2545
2555
  __decorate([
2546
- vtyx.Watch('groups')
2556
+ vtyx.Watch('groups', { deep: true })
2547
2557
  ], Selectic.prototype, "onGroupsChanged", null);
2548
2558
  __decorate([
2549
2559
  vtyx.Watch('placeholder')
@@ -2555,7 +2565,7 @@ __decorate([
2555
2565
  vtyx.Watch('isFocused')
2556
2566
  ], Selectic.prototype, "onFocusChanged", null);
2557
2567
  __decorate([
2558
- vtyx.Watch('store.state.internalValue')
2568
+ vtyx.Watch('store.state.internalValue', { deep: true })
2559
2569
  ], Selectic.prototype, "onInternalValueChange", null);
2560
2570
  __decorate([
2561
2571
  vtyx.Emit('input'),
@@ -97,6 +97,26 @@ 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,
@@ -137,27 +157,6 @@ class SelecticStore {
137
157
  automaticClose: false,
138
158
  },
139
159
  });
140
- /* Do not need reactivity */
141
- this.requestId = 0;
142
- this._uid = ++uid;
143
- /* {{{ Props */
144
- const defaultProps = {
145
- value: null,
146
- selectionIsExcluded: false,
147
- disabled: false,
148
- options: null,
149
- childOptions: [],
150
- groups: [],
151
- texts: null,
152
- params: {},
153
- fetchCallback: null,
154
- getItemsCallback: null,
155
- keepOpenWithOtherSelectic: false,
156
- };
157
- const propsVal = assignObject(defaultProps, props);
158
- this.props = reactive(propsVal);
159
- /* }}} */
160
- /* {{{ data */
161
160
  this.data = reactive({
162
161
  labels: Object.assign({}, messages),
163
162
  itemsPerPage: 10,
@@ -208,17 +207,17 @@ class SelecticStore {
208
207
  this.commit('isOpen', false);
209
208
  this.buildAllOptions(true);
210
209
  this.buildSelectedOptions();
211
- });
210
+ }, { deep: true });
212
211
  watch(() => [this.listOptions, this.elementOptions], () => {
213
212
  /* TODO: transform allOptions as a computed properties and this
214
213
  * watcher become useless */
215
214
  this.buildAllOptions(true);
216
- });
215
+ }, { deep: true });
217
216
  watch(() => this.props.value, () => {
218
217
  var _a;
219
218
  const value = (_a = this.props.value) !== null && _a !== void 0 ? _a : null;
220
219
  this.commit('internalValue', value);
221
- });
220
+ }, { deep: true });
222
221
  watch(() => this.props.selectionIsExcluded, () => {
223
222
  this.commit('selectionIsExcluded', this.props.selectionIsExcluded);
224
223
  });
@@ -234,14 +233,14 @@ class SelecticStore {
234
233
  areAllSelected = this.state.filteredOptions.every((item) => !!(+item.selected ^ selectionIsExcluded));
235
234
  }
236
235
  this.state.status.areAllSelected = areAllSelected;
237
- });
236
+ }, { deep: true });
238
237
  watch(() => this.state.internalValue, () => {
239
238
  this.buildSelectedOptions();
240
- });
239
+ }, { deep: true });
241
240
  watch(() => this.state.allOptions, () => {
242
241
  this.checkAutoSelect();
243
242
  this.checkAutoDisabled();
244
- });
243
+ }, { deep: true });
245
244
  watch(() => this.state.totalAllOptions, () => {
246
245
  this.checkHideFilter();
247
246
  });
@@ -271,8 +270,8 @@ class SelecticStore {
271
270
  * and ensure convertValue run with correct state */
272
271
  assignObject(this.state, {
273
272
  internalValue: this.convertTypeValue(value),
274
- selectionIsExcluded: props.selectionIsExcluded,
275
- disabled: props.disabled,
273
+ selectionIsExcluded: !!this.props.selectionIsExcluded,
274
+ disabled: !!this.props.disabled, /* XXX: !! is needed to copy value and not proxy reference */
276
275
  });
277
276
  this.checkHideFilter();
278
277
  if (this.props.texts) {
@@ -1390,7 +1389,7 @@ __decorate$4([
1390
1389
  Prop({ default: '' })
1391
1390
  ], MainInput.prototype, "id", void 0);
1392
1391
  __decorate$4([
1393
- Watch('store.state.internalValue')
1392
+ Watch('store.state.internalValue', { deep: true })
1394
1393
  ], MainInput.prototype, "onInternalChange", null);
1395
1394
  MainInput = __decorate$4([
1396
1395
  Component
@@ -1494,7 +1493,7 @@ let FilterPanel = class FilterPanel extends Vue {
1494
1493
  document.addEventListener('keypress', this.onKeyPressed);
1495
1494
  this.getFocus();
1496
1495
  }
1497
- destroyed() {
1496
+ unmounted() {
1498
1497
  document.removeEventListener('keypress', this.onKeyPressed);
1499
1498
  }
1500
1499
  /* }}} */
@@ -1754,7 +1753,7 @@ __decorate$2([
1754
1753
  Watch('store.state.offsetItem')
1755
1754
  ], List.prototype, "onOffsetChange", null);
1756
1755
  __decorate$2([
1757
- Watch('filteredOptions')
1756
+ Watch('filteredOptions', { deep: true })
1758
1757
  ], List.prototype, "onFilteredOptionsChange", null);
1759
1758
  __decorate$2([
1760
1759
  Watch('groupId')
@@ -1925,7 +1924,7 @@ let ExtendedList = class ExtendedList extends Vue {
1925
1924
  document.body.addEventListener('keydown', this.onKeyDown);
1926
1925
  this.computeListSize();
1927
1926
  }
1928
- destroyed() {
1927
+ unmounted() {
1929
1928
  document.body.removeEventListener('keydown', this.onKeyDown);
1930
1929
  /* force the element to be removed from DOM */
1931
1930
  if (this.$el.parentNode) {
@@ -1970,7 +1969,7 @@ __decorate$1([
1970
1969
  Prop({ default: 300 })
1971
1970
  ], ExtendedList.prototype, "width", void 0);
1972
1971
  __decorate$1([
1973
- Watch('store.state.filteredOptions')
1972
+ Watch('store.state.filteredOptions', { deep: true })
1974
1973
  ], ExtendedList.prototype, "onFilteredOptionsChange", null);
1975
1974
  __decorate$1([
1976
1975
  Watch('store.state.hideFilter')
@@ -2021,15 +2020,26 @@ let Selectic = class Selectic extends Vue {
2021
2020
  }
2022
2021
  get outsideListener() {
2023
2022
  return (evt) => {
2024
- const target = evt.target;
2025
2023
  if (!this.$refs) {
2026
2024
  /* this component should have been destroyed */
2027
2025
  this.removeListeners();
2028
2026
  this.store.commit('isOpen', false);
2029
2027
  return;
2030
2028
  }
2031
- if (!this.$refs.extendedList.$el.contains(target) && !this.$el.contains(target)) {
2032
- this.store.commit('isOpen', false);
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);
2033
2043
  }
2034
2044
  };
2035
2045
  }
@@ -2448,7 +2458,7 @@ let Selectic = class Selectic extends Vue {
2448
2458
  // }
2449
2459
  // this.store.childOptions = options;
2450
2460
  }
2451
- beforeDestroy() {
2461
+ beforeUnmount() {
2452
2462
  this.removeListeners();
2453
2463
  }
2454
2464
  /* }}} */
@@ -2524,22 +2534,22 @@ __decorate([
2524
2534
  Prop()
2525
2535
  ], Selectic.prototype, "_getMethods", void 0);
2526
2536
  __decorate([
2527
- Watch('value')
2537
+ Watch('value', { deep: true })
2528
2538
  ], Selectic.prototype, "onValueChange", null);
2529
2539
  __decorate([
2530
2540
  Watch('selectionIsExcluded')
2531
2541
  ], Selectic.prototype, "onExcludedChange", null);
2532
2542
  __decorate([
2533
- Watch('options')
2543
+ Watch('options', { deep: true })
2534
2544
  ], Selectic.prototype, "onOptionsChange", null);
2535
2545
  __decorate([
2536
- Watch('texts')
2546
+ Watch('texts', { deep: true })
2537
2547
  ], Selectic.prototype, "onTextsChange", null);
2538
2548
  __decorate([
2539
2549
  Watch('disabled')
2540
2550
  ], Selectic.prototype, "onDisabledChange", null);
2541
2551
  __decorate([
2542
- Watch('groups')
2552
+ Watch('groups', { deep: true })
2543
2553
  ], Selectic.prototype, "onGroupsChanged", null);
2544
2554
  __decorate([
2545
2555
  Watch('placeholder')
@@ -2551,7 +2561,7 @@ __decorate([
2551
2561
  Watch('isFocused')
2552
2562
  ], Selectic.prototype, "onFocusChanged", null);
2553
2563
  __decorate([
2554
- Watch('store.state.internalValue')
2564
+ Watch('store.state.internalValue', { deep: true })
2555
2565
  ], Selectic.prototype, "onInternalValueChange", null);
2556
2566
  __decorate([
2557
2567
  Emit('input'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selectic",
3
- "version": "3.0.4",
3
+ "version": "3.0.8",
4
4
  "description": "Smart Select for VueJS 3.x",
5
5
  "main": "dist/selectic.common.js",
6
6
  "module": "dist/selectic.esm.js",
@@ -192,7 +192,7 @@ export default class ExtendedList extends Vue<Props> {
192
192
  /* }}} */
193
193
  /* {{{ watch */
194
194
 
195
- @Watch('store.state.filteredOptions')
195
+ @Watch('store.state.filteredOptions', { deep: true })
196
196
  public onFilteredOptionsChange() {
197
197
  this.$nextTick(this.computeListSize);
198
198
  }
@@ -228,7 +228,7 @@ export default class ExtendedList extends Vue<Props> {
228
228
  this.computeListSize();
229
229
  }
230
230
 
231
- public destroyed() {
231
+ public unmounted() {
232
232
  document.body.removeEventListener('keydown', this.onKeyDown);
233
233
 
234
234
  /* force the element to be removed from DOM */
package/src/Filter.tsx CHANGED
@@ -133,7 +133,7 @@ export default class FilterPanel extends Vue<Props> {
133
133
  this.getFocus();
134
134
  }
135
135
 
136
- public destroyed() {
136
+ public unmounted() {
137
137
  document.removeEventListener('keypress', this.onKeyPressed);
138
138
  }
139
139
 
package/src/List.tsx CHANGED
@@ -220,7 +220,7 @@ export default class List extends Vue<Props> {
220
220
  this.checkOffset();
221
221
  }
222
222
 
223
- @Watch('filteredOptions')
223
+ @Watch('filteredOptions', { deep: true })
224
224
  public onFilteredOptionsChange() {
225
225
  this.checkOffset();
226
226
  }
package/src/MainInput.tsx CHANGED
@@ -264,7 +264,7 @@ export default class MainInput extends Vue<Props> {
264
264
  /* }}} */
265
265
  /* {{{ watch */
266
266
 
267
- @Watch('store.state.internalValue')
267
+ @Watch('store.state.internalValue', { deep: true })
268
268
  public onInternalChange() {
269
269
  this.nbHiddenItems = 0;
270
270
  }
package/src/Store.tsx CHANGED
@@ -411,48 +411,7 @@ export default class SelecticStore {
411
411
 
412
412
  /* {{{ data */
413
413
 
414
- public state = reactive<SelecticStoreState>({
415
- multiple: false,
416
- disabled: false,
417
- placeholder: '',
418
- hideFilter: false,
419
- keepFilterOpen: false,
420
- allowRevert: undefined,
421
- allowClearSelection: false,
422
- autoSelect: true,
423
- autoDisabled: true,
424
- strictValue: false,
425
- selectionOverflow: 'collapsed',
426
-
427
- internalValue: null,
428
- isOpen: false,
429
- searchText: '',
430
- selectionIsExcluded: false,
431
- allOptions: [],
432
- dynOptions: [],
433
- filteredOptions: [],
434
- selectedOptions: null,
435
- totalAllOptions: Infinity,
436
- totalDynOptions: Infinity,
437
- totalFilteredOptions: Infinity,
438
- groups: new Map(),
439
- offsetItem: 0,
440
- activeItemIdx: -1,
441
- pageSize: 100,
442
- listPosition: 'auto',
443
-
444
- optionBehaviorOperation: 'sort',
445
- optionBehaviorOrder: ['O', 'D', 'E'],
446
-
447
- status: {
448
- searching: false,
449
- errorMessage: '',
450
- areAllSelected: false,
451
- hasChanged: false,
452
- automaticChange: false,
453
- automaticClose: false,
454
- },
455
- });
414
+ public state: SelecticStoreState;
456
415
  public data: Data;
457
416
 
458
417
  /* Do not need reactivity */
@@ -500,6 +459,49 @@ export default class SelecticStore {
500
459
  /* }}} */
501
460
  /* {{{ data */
502
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
+
503
505
  this.data = reactive({
504
506
  labels: Object.assign({}, messages),
505
507
  itemsPerPage: 10,
@@ -565,18 +567,18 @@ export default class SelecticStore {
565
567
  this.commit('isOpen', false);
566
568
  this.buildAllOptions(true);
567
569
  this.buildSelectedOptions();
568
- });
570
+ }, { deep: true });
569
571
 
570
572
  watch(() => [this.listOptions, this.elementOptions], () => {
571
573
  /* TODO: transform allOptions as a computed properties and this
572
574
  * watcher become useless */
573
575
  this.buildAllOptions(true);
574
- });
576
+ }, { deep: true });
575
577
 
576
578
  watch(() => this.props.value, () => {
577
579
  const value = this.props.value ?? null;
578
580
  this.commit('internalValue', value);
579
- });
581
+ }, { deep: true });
580
582
 
581
583
  watch(() => this.props.selectionIsExcluded, () => {
582
584
  this.commit('selectionIsExcluded', this.props.selectionIsExcluded);
@@ -598,16 +600,16 @@ export default class SelecticStore {
598
600
  }
599
601
 
600
602
  this.state.status.areAllSelected = areAllSelected;
601
- });
603
+ }, { deep: true });
602
604
 
603
605
  watch(() => this.state.internalValue, () => {
604
606
  this.buildSelectedOptions();
605
- });
607
+ }, { deep: true });
606
608
 
607
609
  watch(() => this.state.allOptions, () => {
608
610
  this.checkAutoSelect();
609
611
  this.checkAutoDisabled();
610
- });
612
+ }, { deep: true });
611
613
 
612
614
  watch(() => this.state.totalAllOptions, () => {
613
615
  this.checkHideFilter();
@@ -649,8 +651,8 @@ export default class SelecticStore {
649
651
  * and ensure convertValue run with correct state */
650
652
  assignObject(this.state, {
651
653
  internalValue: this.convertTypeValue(value),
652
- selectionIsExcluded: props.selectionIsExcluded,
653
- disabled: props.disabled,
654
+ selectionIsExcluded: !!this.props.selectionIsExcluded,
655
+ disabled: !!this.props.disabled, /* XXX: !! is needed to copy value and not proxy reference */
654
656
  });
655
657
 
656
658
  this.checkHideFilter();
package/src/index.tsx CHANGED
@@ -309,8 +309,6 @@ export default class Selectic extends Vue<Props> {
309
309
 
310
310
  get outsideListener() {
311
311
  return (evt: MouseEvent) => {
312
- const target = evt.target as Node;
313
-
314
312
  if (!this.$refs) {
315
313
  /* this component should have been destroyed */
316
314
  this.removeListeners();
@@ -318,8 +316,23 @@ export default class Selectic extends Vue<Props> {
318
316
  return;
319
317
  }
320
318
 
321
- if (!this.$refs.extendedList.$el.contains(target) && !this.$el.contains(target)) {
322
- this.store.commit('isOpen', false);
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);
323
336
  }
324
337
  };
325
338
  }
@@ -524,7 +537,7 @@ export default class Selectic extends Vue<Props> {
524
537
  /* }}} */
525
538
  /* {{{ watch */
526
539
 
527
- @Watch('value')
540
+ @Watch('value', { deep: true })
528
541
  public onValueChange() {
529
542
  const currentValue = this.store.state.internalValue;
530
543
  const newValue = this.value ?? null;
@@ -543,12 +556,12 @@ export default class Selectic extends Vue<Props> {
543
556
  this.store.props.selectionIsExcluded = this.selectionIsExcluded;
544
557
  }
545
558
 
546
- @Watch('options')
559
+ @Watch('options', { deep: true })
547
560
  public onOptionsChange() {
548
561
  this.store.props.options = Array.from(this.options);
549
562
  }
550
563
 
551
- @Watch('texts')
564
+ @Watch('texts', { deep: true })
552
565
  public onTextsChange() {
553
566
  const texts = this.texts;
554
567
 
@@ -562,7 +575,7 @@ export default class Selectic extends Vue<Props> {
562
575
  this.store.props.disabled = this.disabled;
563
576
  }
564
577
 
565
- @Watch('groups')
578
+ @Watch('groups', { deep: true })
566
579
  public onGroupsChanged() {
567
580
  this.store.changeGroups(this.groups);
568
581
  }
@@ -582,7 +595,7 @@ export default class Selectic extends Vue<Props> {
582
595
  this.focusToggled();
583
596
  }
584
597
 
585
- @Watch('store.state.internalValue')
598
+ @Watch('store.state.internalValue', { deep: true })
586
599
  public onInternalValueChange() {
587
600
  const oldValue = this._oldValue;
588
601
  const value = this.getValue();
@@ -838,7 +851,7 @@ export default class Selectic extends Vue<Props> {
838
851
  // this.store.childOptions = options;
839
852
  }
840
853
 
841
- public beforeDestroy() {
854
+ public beforeUnmount() {
842
855
  this.removeListeners();
843
856
  }
844
857
 
@@ -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'),
@@ -31,6 +31,6 @@ export default class ExtendedList extends Vue<Props> {
31
31
  private getGroup;
32
32
  private computeListSize;
33
33
  mounted(): void;
34
- destroyed(): void;
34
+ unmounted(): void;
35
35
  render(): h.JSX.Element;
36
36
  }
package/types/Filter.d.ts CHANGED
@@ -23,6 +23,6 @@ export default class FilterPanel extends Vue<Props> {
23
23
  private getFocus;
24
24
  onClosed(): void;
25
25
  mounted(): void;
26
- destroyed(): void;
26
+ unmounted(): void;
27
27
  render(): h.JSX.Element;
28
28
  }
package/types/List.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Vue, h } from 'vtyx';
2
- import Store, { OptionItem, OptionId } from './Store';
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
@@ -142,141 +142,7 @@ export declare type PartialMessages = {
142
142
  export declare function changeTexts(texts: PartialMessages): void;
143
143
  export default class SelecticStore {
144
144
  props: InternalProps;
145
- state: {
146
- internalValue: OptionId | StrictOptionId[];
147
- selectionIsExcluded: boolean;
148
- multiple: boolean;
149
- disabled: boolean;
150
- placeholder: string;
151
- hideFilter: boolean;
152
- keepFilterOpen: boolean;
153
- allowRevert?: boolean | undefined;
154
- allowClearSelection: boolean;
155
- autoSelect: boolean;
156
- autoDisabled: boolean;
157
- strictValue: boolean;
158
- selectionOverflow: SelectionOverflow;
159
- isOpen: boolean;
160
- searchText: string;
161
- allOptions: {
162
- id: OptionId;
163
- text: string;
164
- title?: string | undefined;
165
- disabled?: boolean | undefined;
166
- group?: StrictOptionId | undefined;
167
- className?: string | undefined;
168
- style?: string | undefined;
169
- icon?: string | undefined;
170
- options?: any[] | undefined;
171
- data?: any;
172
- }[];
173
- dynOptions: {
174
- id: OptionId;
175
- text: string;
176
- title?: string | undefined;
177
- disabled?: boolean | undefined;
178
- group?: StrictOptionId | undefined;
179
- className?: string | undefined;
180
- style?: string | undefined;
181
- icon?: string | undefined;
182
- options?: any[] | undefined;
183
- data?: any;
184
- }[];
185
- filteredOptions: {
186
- selected: boolean;
187
- disabled: boolean;
188
- isGroup: boolean;
189
- id: OptionId;
190
- text: string;
191
- title?: string | undefined;
192
- group?: StrictOptionId | undefined;
193
- className?: string | undefined;
194
- style?: string | undefined;
195
- icon?: string | undefined;
196
- options?: {
197
- id: OptionId;
198
- text: string;
199
- title?: string | undefined;
200
- disabled?: boolean | undefined;
201
- group?: StrictOptionId | undefined;
202
- className?: string | undefined;
203
- style?: string | undefined;
204
- icon?: string | undefined;
205
- options?: any[] | undefined;
206
- data?: any;
207
- }[] | undefined;
208
- data?: any;
209
- }[];
210
- selectedOptions: {
211
- selected: boolean;
212
- disabled: boolean;
213
- isGroup: boolean;
214
- id: OptionId;
215
- text: string;
216
- title?: string | undefined;
217
- group?: StrictOptionId | undefined;
218
- className?: string | undefined;
219
- style?: string | undefined;
220
- icon?: string | undefined;
221
- options?: {
222
- id: OptionId;
223
- text: string;
224
- title?: string | undefined;
225
- disabled?: boolean | undefined;
226
- group?: StrictOptionId | undefined;
227
- className?: string | undefined;
228
- style?: string | undefined;
229
- icon?: string | undefined;
230
- options?: any[] | undefined;
231
- data?: any;
232
- }[] | undefined;
233
- data?: any;
234
- } | {
235
- selected: boolean;
236
- disabled: boolean;
237
- isGroup: boolean;
238
- id: OptionId;
239
- text: string;
240
- title?: string | undefined;
241
- group?: StrictOptionId | undefined;
242
- className?: string | undefined;
243
- style?: string | undefined;
244
- icon?: string | undefined;
245
- options?: {
246
- id: OptionId;
247
- text: string;
248
- title?: string | undefined;
249
- disabled?: boolean | undefined;
250
- group?: StrictOptionId | undefined;
251
- className?: string | undefined;
252
- style?: string | undefined;
253
- icon?: string | undefined;
254
- options?: any[] | undefined;
255
- data?: any;
256
- }[] | undefined;
257
- data?: any;
258
- }[] | null;
259
- totalAllOptions: number;
260
- totalDynOptions: number;
261
- totalFilteredOptions: number;
262
- groups: Map<OptionId, string>;
263
- offsetItem: number;
264
- activeItemIdx: number;
265
- pageSize: number;
266
- formatOption?: FormatCallback | undefined;
267
- formatSelection?: FormatCallback | undefined;
268
- optionBehaviorOperation: OptionBehaviorOperation;
269
- optionBehaviorOrder: OptionBehaviorOrder[];
270
- listPosition: ListPosition;
271
- status: {
272
- searching: boolean;
273
- errorMessage: string;
274
- areAllSelected: boolean;
275
- hasChanged: boolean;
276
- automaticChange: boolean;
277
- automaticClose: boolean;
278
- };
279
- };
145
+ state: SelecticStoreState;
280
146
  data: Data;
281
147
  private requestId;
282
148
  private cacheRequest;
package/types/index.d.ts CHANGED
@@ -136,6 +136,6 @@ export default class Selectic extends Vue<Props> {
136
136
  created(): void;
137
137
  mounted(): void;
138
138
  beforeUpdate(): void;
139
- beforeDestroy(): void;
139
+ beforeUnmount(): void;
140
140
  render(): h.JSX.Element | undefined;
141
141
  }