selectic 3.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -196,6 +196,12 @@ class SelecticStore {
196
196
  const state = this.state;
197
197
  return state.dynOptions.length === state.totalDynOptions;
198
198
  });
199
+ this.listOptions = vue.computed(() => {
200
+ return this.getListOptions();
201
+ });
202
+ this.elementOptions = vue.computed(() => {
203
+ return this.getElementOptions();
204
+ });
199
205
  /* }}} */
200
206
  /* {{{ watch */
201
207
  vue.watch(() => [this.props.options, this.props.childOptions], () => {
@@ -204,6 +210,11 @@ class SelecticStore {
204
210
  this.buildAllOptions(true);
205
211
  this.buildSelectedOptions();
206
212
  });
213
+ vue.watch(() => [this.listOptions, this.elementOptions], () => {
214
+ /* TODO: transform allOptions as a computed properties and this
215
+ * watcher become useless */
216
+ this.buildAllOptions(true);
217
+ });
207
218
  vue.watch(() => this.props.value, () => {
208
219
  var _a;
209
220
  const value = (_a = this.props.value) !== null && _a !== void 0 ? _a : null;
@@ -252,8 +263,11 @@ class SelecticStore {
252
263
  delete stateParam.hideFilter;
253
264
  }
254
265
  /* Update state */
255
- assignObject(this.state, stateParam, {
256
- internalValue: value,
266
+ assignObject(this.state, stateParam);
267
+ /* XXX: should be done in 2 lines, in order to set the multiple state
268
+ * and ensure convertValue run with correct state */
269
+ assignObject(this.state, {
270
+ internalValue: this.convertTypeValue(value),
257
271
  selectionIsExcluded: props.selectionIsExcluded,
258
272
  disabled: props.disabled,
259
273
  });
@@ -512,42 +526,50 @@ class SelecticStore {
512
526
  return !!this.getValue(id);
513
527
  }
514
528
  getValue(id) {
529
+ var _a, _b;
515
530
  function findId(option) {
516
531
  return option.id === id;
517
532
  }
518
533
  return this.state.filteredOptions.find(findId) ||
519
534
  this.state.dynOptions.find(findId) ||
520
- this.getListOptions().find(findId) ||
521
- this.getElementOptions().find(findId);
535
+ ((_a = this.listOptions.value) !== null && _a !== void 0 ? _a : this.listOptions).find(findId) ||
536
+ ((_b = this.elementOptions.value) !== null && _b !== void 0 ? _b : this.elementOptions).find(findId);
522
537
  }
523
- assertValueType() {
538
+ convertTypeValue(oldValue) {
524
539
  const state = this.state;
525
- const internalValue = state.internalValue;
526
540
  const isMultiple = state.multiple;
527
- let newValue = internalValue;
541
+ let newValue = oldValue;
528
542
  if (isMultiple) {
529
- if (!Array.isArray(internalValue)) {
530
- newValue = internalValue === null ? [] : [internalValue];
543
+ if (!Array.isArray(oldValue)) {
544
+ newValue = oldValue === null ? [] : [oldValue];
531
545
  }
532
546
  }
533
547
  else {
534
- if (Array.isArray(internalValue)) {
535
- const value = internalValue[0];
548
+ if (Array.isArray(oldValue)) {
549
+ const value = oldValue[0];
536
550
  newValue = typeof value === 'undefined' ? null : value;
537
551
  }
538
552
  }
539
- state.internalValue = newValue;
553
+ return newValue;
554
+ }
555
+ assertValueType() {
556
+ const state = this.state;
557
+ const internalValue = state.internalValue;
558
+ const newValue = this.convertTypeValue(internalValue);
559
+ if (newValue !== internalValue) {
560
+ state.internalValue = newValue;
561
+ }
540
562
  }
541
563
  assertCorrectValue(applyStrict = false) {
542
564
  var _a, _b;
543
565
  const state = this.state;
566
+ this.assertValueType();
544
567
  const internalValue = state.internalValue;
545
568
  const selectionIsExcluded = state.selectionIsExcluded;
546
569
  const isMultiple = state.multiple;
547
570
  const checkStrict = state.strictValue;
548
571
  let newValue = internalValue;
549
572
  const isPartial = (_a = this.isPartial.value) !== null && _a !== void 0 ? _a : this.isPartial;
550
- this.assertValueType();
551
573
  if (isMultiple) {
552
574
  const hasFetchedAllItems = (_b = this.hasFetchedAllItems.value) !== null && _b !== void 0 ? _b : this.hasFetchedAllItems;
553
575
  if (selectionIsExcluded && hasFetchedAllItems) {
@@ -577,7 +599,7 @@ class SelecticStore {
577
599
  return;
578
600
  }
579
601
  }
580
- else if (!this.hasItemInStore(newValue)) {
602
+ else if (newValue !== null && !this.hasItemInStore(newValue)) {
581
603
  filteredValue = null;
582
604
  isDifferent = true;
583
605
  if (isPartial && !applyStrict) {
@@ -606,13 +628,14 @@ class SelecticStore {
606
628
  this.state.groups.set(group.id, group.text);
607
629
  });
608
630
  }
609
- /* XXX: This is not a computed property to avoid consuming more memory */
631
+ /* This method is for the computed property listOptions */
610
632
  getListOptions() {
611
633
  const options = this.props.options;
612
634
  const listOptions = [];
613
635
  if (!Array.isArray(options)) {
614
636
  return listOptions;
615
637
  }
638
+ const state = this.state;
616
639
  options.forEach((option) => {
617
640
  /* manage simple string */
618
641
  if (typeof option === 'string') {
@@ -625,13 +648,13 @@ class SelecticStore {
625
648
  const group = option.group;
626
649
  const subOptions = option.options;
627
650
  /* check for groups */
628
- if (group && !this.state.groups.has(group)) {
629
- this.state.groups.set(group, String(group));
651
+ if (group && !state.groups.has(group)) {
652
+ state.groups.set(group, String(group));
630
653
  }
631
654
  /* check for sub options */
632
655
  if (subOptions) {
633
656
  const groupId = option.id;
634
- this.state.groups.set(groupId, option.text);
657
+ state.groups.set(groupId, option.text);
635
658
  subOptions.forEach((subOpt) => {
636
659
  subOpt.group = groupId;
637
660
  });
@@ -642,24 +665,25 @@ class SelecticStore {
642
665
  });
643
666
  return listOptions;
644
667
  }
645
- /* XXX: This is not a computed property to avoid consuming more memory */
668
+ /* This method is for the computed property elementOptions */
646
669
  getElementOptions() {
647
670
  const options = this.props.childOptions;
648
671
  const childOptions = [];
649
672
  if (!Array.isArray(options) || options.length === 0) {
650
673
  return childOptions;
651
674
  }
675
+ const state = this.state;
652
676
  options.forEach((option) => {
653
677
  const group = option.group;
654
678
  const subOptions = option.options;
655
679
  /* check for groups */
656
- if (group && !this.state.groups.has(group)) {
657
- this.state.groups.set(group, String(group));
680
+ if (group && !state.groups.has(group)) {
681
+ state.groups.set(group, String(group));
658
682
  }
659
683
  /* check for sub options */
660
684
  if (subOptions) {
661
685
  const groupId = option.id;
662
- this.state.groups.set(groupId, option.text);
686
+ state.groups.set(groupId, option.text);
663
687
  const sOpts = subOptions.map((subOpt) => {
664
688
  return Object.assign({}, subOpt, {
665
689
  group: groupId,
@@ -673,7 +697,7 @@ class SelecticStore {
673
697
  return childOptions;
674
698
  }
675
699
  buildAllOptions(keepFetched = false) {
676
- var _a;
700
+ var _a, _b, _c;
677
701
  const allOptions = [];
678
702
  let listOptions = [];
679
703
  let elementOptions = [];
@@ -705,8 +729,8 @@ class SelecticStore {
705
729
  this.state.totalDynOptions = 0;
706
730
  }
707
731
  }
708
- listOptions = this.getListOptions();
709
- elementOptions = this.getElementOptions();
732
+ listOptions = (_b = this.listOptions.value) !== null && _b !== void 0 ? _b : this.listOptions;
733
+ elementOptions = (_c = this.elementOptions.value) !== null && _c !== void 0 ? _c : this.elementOptions;
710
734
  if (this.state.optionBehaviorOperation === 'force') {
711
735
  const orderValue = optionBehaviorOrder.find((value) => lengthFromOrder(value) > 0);
712
736
  allOptions.push(...arrayFromOrder(orderValue));
@@ -808,21 +832,22 @@ class SelecticStore {
808
832
  }
809
833
  async buildSelectedOptions() {
810
834
  const internalValue = this.state.internalValue;
811
- if (this.state.multiple) {
835
+ const state = this.state;
836
+ if (state.multiple) {
812
837
  /* display partial information about selected items */
813
- this.state.selectedOptions = this.buildSelectedItems(internalValue);
838
+ state.selectedOptions = this.buildSelectedItems(internalValue);
814
839
  const items = await this.getItems(internalValue).catch(() => []);
815
- if (internalValue !== this.state.internalValue) {
840
+ if (internalValue !== state.internalValue) {
816
841
  /* Values have been deprecated */
817
842
  return;
818
843
  }
819
844
  if (items.length !== internalValue.length) {
820
- if (!this.state.strictValue) {
821
- const updatedItems = this.state.selectedOptions.map((option) => {
845
+ if (!state.strictValue) {
846
+ const updatedItems = state.selectedOptions.map((option) => {
822
847
  const foundItem = items.find((item) => item.id === option.id);
823
848
  return foundItem || option;
824
849
  });
825
- this.state.selectedOptions = updatedItems;
850
+ state.selectedOptions = updatedItems;
826
851
  }
827
852
  else {
828
853
  const itemIds = items.map((item) => item.id);
@@ -831,27 +856,27 @@ class SelecticStore {
831
856
  return;
832
857
  }
833
858
  /* display full information about selected items */
834
- this.state.selectedOptions = items;
859
+ state.selectedOptions = items;
835
860
  }
836
861
  else if (internalValue === null) {
837
- this.state.selectedOptions = null;
862
+ state.selectedOptions = null;
838
863
  }
839
864
  else {
840
865
  /* display partial information about selected items */
841
- this.state.selectedOptions = this.buildSelectedItems([internalValue])[0];
866
+ state.selectedOptions = this.buildSelectedItems([internalValue])[0];
842
867
  const items = await this.getItems([internalValue]).catch(() => []);
843
- if (internalValue !== this.state.internalValue) {
868
+ if (internalValue !== state.internalValue) {
844
869
  /* Values have been deprecated */
845
870
  return;
846
871
  }
847
872
  if (!items.length) {
848
- if (this.state.strictValue) {
873
+ if (state.strictValue) {
849
874
  this.commit('internalValue', null);
850
875
  }
851
876
  return;
852
877
  }
853
878
  /* display full information about selected items */
854
- this.state.selectedOptions = items[0];
879
+ state.selectedOptions = items[0];
855
880
  }
856
881
  }
857
882
  async fetchData() {
@@ -939,6 +964,7 @@ class SelecticStore {
939
964
  return this.buildGroupItems(options.filter((option) => rgx.test(option.text)));
940
965
  }
941
966
  addStaticFilteredOptions(fromDynamic = false) {
967
+ var _a, _b;
942
968
  const search = this.state.searchText;
943
969
  let continueLoop = fromDynamic;
944
970
  if (this.state.optionBehaviorOperation !== 'sort') {
@@ -958,10 +984,10 @@ class SelecticStore {
958
984
  }
959
985
  switch (order) {
960
986
  case 'O':
961
- options = this.filterOptions(this.getListOptions(), search);
987
+ options = this.filterOptions((_a = this.listOptions.value) !== null && _a !== void 0 ? _a : this.listOptions, search);
962
988
  break;
963
989
  case 'E':
964
- options = this.filterOptions(this.getElementOptions(), search);
990
+ options = this.filterOptions((_b = this.elementOptions.value) !== null && _b !== void 0 ? _b : this.elementOptions, search);
965
991
  break;
966
992
  }
967
993
  this.state.filteredOptions.push(...options);
@@ -2162,7 +2188,7 @@ let Selectic = class Selectic extends vtyx.Vue {
2162
2188
  this.store.props.selectionIsExcluded = this.selectionIsExcluded;
2163
2189
  }
2164
2190
  onOptionsChange() {
2165
- this.store.props.options = this.options;
2191
+ this.store.props.options = Array.from(this.options);
2166
2192
  }
2167
2193
  onTextsChange() {
2168
2194
  const texts = this.texts;
@@ -192,6 +192,12 @@ class SelecticStore {
192
192
  const state = this.state;
193
193
  return state.dynOptions.length === state.totalDynOptions;
194
194
  });
195
+ this.listOptions = computed(() => {
196
+ return this.getListOptions();
197
+ });
198
+ this.elementOptions = computed(() => {
199
+ return this.getElementOptions();
200
+ });
195
201
  /* }}} */
196
202
  /* {{{ watch */
197
203
  watch(() => [this.props.options, this.props.childOptions], () => {
@@ -200,6 +206,11 @@ class SelecticStore {
200
206
  this.buildAllOptions(true);
201
207
  this.buildSelectedOptions();
202
208
  });
209
+ watch(() => [this.listOptions, this.elementOptions], () => {
210
+ /* TODO: transform allOptions as a computed properties and this
211
+ * watcher become useless */
212
+ this.buildAllOptions(true);
213
+ });
203
214
  watch(() => this.props.value, () => {
204
215
  var _a;
205
216
  const value = (_a = this.props.value) !== null && _a !== void 0 ? _a : null;
@@ -248,8 +259,11 @@ class SelecticStore {
248
259
  delete stateParam.hideFilter;
249
260
  }
250
261
  /* Update state */
251
- assignObject(this.state, stateParam, {
252
- internalValue: value,
262
+ assignObject(this.state, stateParam);
263
+ /* XXX: should be done in 2 lines, in order to set the multiple state
264
+ * and ensure convertValue run with correct state */
265
+ assignObject(this.state, {
266
+ internalValue: this.convertTypeValue(value),
253
267
  selectionIsExcluded: props.selectionIsExcluded,
254
268
  disabled: props.disabled,
255
269
  });
@@ -508,42 +522,50 @@ class SelecticStore {
508
522
  return !!this.getValue(id);
509
523
  }
510
524
  getValue(id) {
525
+ var _a, _b;
511
526
  function findId(option) {
512
527
  return option.id === id;
513
528
  }
514
529
  return this.state.filteredOptions.find(findId) ||
515
530
  this.state.dynOptions.find(findId) ||
516
- this.getListOptions().find(findId) ||
517
- this.getElementOptions().find(findId);
531
+ ((_a = this.listOptions.value) !== null && _a !== void 0 ? _a : this.listOptions).find(findId) ||
532
+ ((_b = this.elementOptions.value) !== null && _b !== void 0 ? _b : this.elementOptions).find(findId);
518
533
  }
519
- assertValueType() {
534
+ convertTypeValue(oldValue) {
520
535
  const state = this.state;
521
- const internalValue = state.internalValue;
522
536
  const isMultiple = state.multiple;
523
- let newValue = internalValue;
537
+ let newValue = oldValue;
524
538
  if (isMultiple) {
525
- if (!Array.isArray(internalValue)) {
526
- newValue = internalValue === null ? [] : [internalValue];
539
+ if (!Array.isArray(oldValue)) {
540
+ newValue = oldValue === null ? [] : [oldValue];
527
541
  }
528
542
  }
529
543
  else {
530
- if (Array.isArray(internalValue)) {
531
- const value = internalValue[0];
544
+ if (Array.isArray(oldValue)) {
545
+ const value = oldValue[0];
532
546
  newValue = typeof value === 'undefined' ? null : value;
533
547
  }
534
548
  }
535
- state.internalValue = newValue;
549
+ return newValue;
550
+ }
551
+ assertValueType() {
552
+ const state = this.state;
553
+ const internalValue = state.internalValue;
554
+ const newValue = this.convertTypeValue(internalValue);
555
+ if (newValue !== internalValue) {
556
+ state.internalValue = newValue;
557
+ }
536
558
  }
537
559
  assertCorrectValue(applyStrict = false) {
538
560
  var _a, _b;
539
561
  const state = this.state;
562
+ this.assertValueType();
540
563
  const internalValue = state.internalValue;
541
564
  const selectionIsExcluded = state.selectionIsExcluded;
542
565
  const isMultiple = state.multiple;
543
566
  const checkStrict = state.strictValue;
544
567
  let newValue = internalValue;
545
568
  const isPartial = (_a = this.isPartial.value) !== null && _a !== void 0 ? _a : this.isPartial;
546
- this.assertValueType();
547
569
  if (isMultiple) {
548
570
  const hasFetchedAllItems = (_b = this.hasFetchedAllItems.value) !== null && _b !== void 0 ? _b : this.hasFetchedAllItems;
549
571
  if (selectionIsExcluded && hasFetchedAllItems) {
@@ -573,7 +595,7 @@ class SelecticStore {
573
595
  return;
574
596
  }
575
597
  }
576
- else if (!this.hasItemInStore(newValue)) {
598
+ else if (newValue !== null && !this.hasItemInStore(newValue)) {
577
599
  filteredValue = null;
578
600
  isDifferent = true;
579
601
  if (isPartial && !applyStrict) {
@@ -602,13 +624,14 @@ class SelecticStore {
602
624
  this.state.groups.set(group.id, group.text);
603
625
  });
604
626
  }
605
- /* XXX: This is not a computed property to avoid consuming more memory */
627
+ /* This method is for the computed property listOptions */
606
628
  getListOptions() {
607
629
  const options = this.props.options;
608
630
  const listOptions = [];
609
631
  if (!Array.isArray(options)) {
610
632
  return listOptions;
611
633
  }
634
+ const state = this.state;
612
635
  options.forEach((option) => {
613
636
  /* manage simple string */
614
637
  if (typeof option === 'string') {
@@ -621,13 +644,13 @@ class SelecticStore {
621
644
  const group = option.group;
622
645
  const subOptions = option.options;
623
646
  /* check for groups */
624
- if (group && !this.state.groups.has(group)) {
625
- this.state.groups.set(group, String(group));
647
+ if (group && !state.groups.has(group)) {
648
+ state.groups.set(group, String(group));
626
649
  }
627
650
  /* check for sub options */
628
651
  if (subOptions) {
629
652
  const groupId = option.id;
630
- this.state.groups.set(groupId, option.text);
653
+ state.groups.set(groupId, option.text);
631
654
  subOptions.forEach((subOpt) => {
632
655
  subOpt.group = groupId;
633
656
  });
@@ -638,24 +661,25 @@ class SelecticStore {
638
661
  });
639
662
  return listOptions;
640
663
  }
641
- /* XXX: This is not a computed property to avoid consuming more memory */
664
+ /* This method is for the computed property elementOptions */
642
665
  getElementOptions() {
643
666
  const options = this.props.childOptions;
644
667
  const childOptions = [];
645
668
  if (!Array.isArray(options) || options.length === 0) {
646
669
  return childOptions;
647
670
  }
671
+ const state = this.state;
648
672
  options.forEach((option) => {
649
673
  const group = option.group;
650
674
  const subOptions = option.options;
651
675
  /* check for groups */
652
- if (group && !this.state.groups.has(group)) {
653
- this.state.groups.set(group, String(group));
676
+ if (group && !state.groups.has(group)) {
677
+ state.groups.set(group, String(group));
654
678
  }
655
679
  /* check for sub options */
656
680
  if (subOptions) {
657
681
  const groupId = option.id;
658
- this.state.groups.set(groupId, option.text);
682
+ state.groups.set(groupId, option.text);
659
683
  const sOpts = subOptions.map((subOpt) => {
660
684
  return Object.assign({}, subOpt, {
661
685
  group: groupId,
@@ -669,7 +693,7 @@ class SelecticStore {
669
693
  return childOptions;
670
694
  }
671
695
  buildAllOptions(keepFetched = false) {
672
- var _a;
696
+ var _a, _b, _c;
673
697
  const allOptions = [];
674
698
  let listOptions = [];
675
699
  let elementOptions = [];
@@ -701,8 +725,8 @@ class SelecticStore {
701
725
  this.state.totalDynOptions = 0;
702
726
  }
703
727
  }
704
- listOptions = this.getListOptions();
705
- elementOptions = this.getElementOptions();
728
+ listOptions = (_b = this.listOptions.value) !== null && _b !== void 0 ? _b : this.listOptions;
729
+ elementOptions = (_c = this.elementOptions.value) !== null && _c !== void 0 ? _c : this.elementOptions;
706
730
  if (this.state.optionBehaviorOperation === 'force') {
707
731
  const orderValue = optionBehaviorOrder.find((value) => lengthFromOrder(value) > 0);
708
732
  allOptions.push(...arrayFromOrder(orderValue));
@@ -804,21 +828,22 @@ class SelecticStore {
804
828
  }
805
829
  async buildSelectedOptions() {
806
830
  const internalValue = this.state.internalValue;
807
- if (this.state.multiple) {
831
+ const state = this.state;
832
+ if (state.multiple) {
808
833
  /* display partial information about selected items */
809
- this.state.selectedOptions = this.buildSelectedItems(internalValue);
834
+ state.selectedOptions = this.buildSelectedItems(internalValue);
810
835
  const items = await this.getItems(internalValue).catch(() => []);
811
- if (internalValue !== this.state.internalValue) {
836
+ if (internalValue !== state.internalValue) {
812
837
  /* Values have been deprecated */
813
838
  return;
814
839
  }
815
840
  if (items.length !== internalValue.length) {
816
- if (!this.state.strictValue) {
817
- const updatedItems = this.state.selectedOptions.map((option) => {
841
+ if (!state.strictValue) {
842
+ const updatedItems = state.selectedOptions.map((option) => {
818
843
  const foundItem = items.find((item) => item.id === option.id);
819
844
  return foundItem || option;
820
845
  });
821
- this.state.selectedOptions = updatedItems;
846
+ state.selectedOptions = updatedItems;
822
847
  }
823
848
  else {
824
849
  const itemIds = items.map((item) => item.id);
@@ -827,27 +852,27 @@ class SelecticStore {
827
852
  return;
828
853
  }
829
854
  /* display full information about selected items */
830
- this.state.selectedOptions = items;
855
+ state.selectedOptions = items;
831
856
  }
832
857
  else if (internalValue === null) {
833
- this.state.selectedOptions = null;
858
+ state.selectedOptions = null;
834
859
  }
835
860
  else {
836
861
  /* display partial information about selected items */
837
- this.state.selectedOptions = this.buildSelectedItems([internalValue])[0];
862
+ state.selectedOptions = this.buildSelectedItems([internalValue])[0];
838
863
  const items = await this.getItems([internalValue]).catch(() => []);
839
- if (internalValue !== this.state.internalValue) {
864
+ if (internalValue !== state.internalValue) {
840
865
  /* Values have been deprecated */
841
866
  return;
842
867
  }
843
868
  if (!items.length) {
844
- if (this.state.strictValue) {
869
+ if (state.strictValue) {
845
870
  this.commit('internalValue', null);
846
871
  }
847
872
  return;
848
873
  }
849
874
  /* display full information about selected items */
850
- this.state.selectedOptions = items[0];
875
+ state.selectedOptions = items[0];
851
876
  }
852
877
  }
853
878
  async fetchData() {
@@ -935,6 +960,7 @@ class SelecticStore {
935
960
  return this.buildGroupItems(options.filter((option) => rgx.test(option.text)));
936
961
  }
937
962
  addStaticFilteredOptions(fromDynamic = false) {
963
+ var _a, _b;
938
964
  const search = this.state.searchText;
939
965
  let continueLoop = fromDynamic;
940
966
  if (this.state.optionBehaviorOperation !== 'sort') {
@@ -954,10 +980,10 @@ class SelecticStore {
954
980
  }
955
981
  switch (order) {
956
982
  case 'O':
957
- options = this.filterOptions(this.getListOptions(), search);
983
+ options = this.filterOptions((_a = this.listOptions.value) !== null && _a !== void 0 ? _a : this.listOptions, search);
958
984
  break;
959
985
  case 'E':
960
- options = this.filterOptions(this.getElementOptions(), search);
986
+ options = this.filterOptions((_b = this.elementOptions.value) !== null && _b !== void 0 ? _b : this.elementOptions, search);
961
987
  break;
962
988
  }
963
989
  this.state.filteredOptions.push(...options);
@@ -2158,7 +2184,7 @@ let Selectic = class Selectic extends Vue {
2158
2184
  this.store.props.selectionIsExcluded = this.selectionIsExcluded;
2159
2185
  }
2160
2186
  onOptionsChange() {
2161
- this.store.props.options = this.options;
2187
+ this.store.props.options = Array.from(this.options);
2162
2188
  }
2163
2189
  onTextsChange() {
2164
2190
  const texts = this.texts;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selectic",
3
- "version": "3.0.0",
3
+ "version": "3.0.1",
4
4
  "description": "Smart Select for VueJS 3.x",
5
5
  "main": "dist/selectic.common.js",
6
6
  "module": "dist/selectic.esm.js",
package/src/Store.tsx CHANGED
@@ -448,6 +448,8 @@ export default class SelecticStore {
448
448
  public isPartial: ComputedRef<boolean>;
449
449
  public hasAllItems: ComputedRef<boolean>;
450
450
  public hasFetchedAllItems: ComputedRef<boolean>;
451
+ private listOptions: ComputedRef<OptionValue[]>;
452
+ private elementOptions: ComputedRef<OptionValue[]>;
451
453
 
452
454
  /* }}} */
453
455
 
@@ -525,6 +527,14 @@ export default class SelecticStore {
525
527
  return state.dynOptions.length === state.totalDynOptions;
526
528
  });
527
529
 
530
+ this.listOptions = computed(() => {
531
+ return this.getListOptions();
532
+ });
533
+
534
+ this.elementOptions = computed(() => {
535
+ return this.getElementOptions();
536
+ });
537
+
528
538
  /* }}} */
529
539
  /* {{{ watch */
530
540
 
@@ -535,6 +545,12 @@ export default class SelecticStore {
535
545
  this.buildSelectedOptions();
536
546
  });
537
547
 
548
+ watch(() => [this.listOptions, this.elementOptions], () => {
549
+ /* TODO: transform allOptions as a computed properties and this
550
+ * watcher become useless */
551
+ this.buildAllOptions(true);
552
+ });
553
+
538
554
  watch(() => this.props.value, () => {
539
555
  const value = this.props.value ?? null;
540
556
  this.commit('internalValue', value);
@@ -602,8 +618,11 @@ export default class SelecticStore {
602
618
  }
603
619
 
604
620
  /* Update state */
605
- assignObject(this.state, stateParam as SelecticStoreState, {
606
- internalValue: value,
621
+ assignObject(this.state, stateParam as SelecticStoreState);
622
+ /* XXX: should be done in 2 lines, in order to set the multiple state
623
+ * and ensure convertValue run with correct state */
624
+ assignObject(this.state, {
625
+ internalValue: this.convertTypeValue(value),
607
626
  selectionIsExcluded: props.selectionIsExcluded,
608
627
  disabled: props.disabled,
609
628
  });
@@ -917,31 +936,41 @@ export default class SelecticStore {
917
936
 
918
937
  return this.state.filteredOptions.find(findId) ||
919
938
  this.state.dynOptions.find(findId) ||
920
- this.getListOptions().find(findId) ||
921
- this.getElementOptions().find(findId);
939
+ (this.listOptions.value ?? this.listOptions).find(findId) ||
940
+ (this.elementOptions.value ?? this.elementOptions).find(findId);
922
941
  }
923
942
 
924
- private assertValueType() {
943
+ private convertTypeValue(oldValue: OptionId | StrictOptionId[]) {
925
944
  const state = this.state;
926
- const internalValue = state.internalValue;
927
945
  const isMultiple = state.multiple;
928
- let newValue = internalValue;
946
+ let newValue = oldValue;
929
947
 
930
948
  if (isMultiple) {
931
- if (!Array.isArray(internalValue)) {
932
- newValue = internalValue === null ? [] : [internalValue];
949
+ if (!Array.isArray(oldValue)) {
950
+ newValue = oldValue === null ? [] : [oldValue];
933
951
  }
934
952
  } else {
935
- if (Array.isArray(internalValue)) {
936
- const value = internalValue[0];
953
+ if (Array.isArray(oldValue)) {
954
+ const value = oldValue[0];
937
955
  newValue = typeof value === 'undefined' ? null : value;
938
956
  }
939
957
  }
940
- state.internalValue = newValue;
958
+ return newValue;
959
+ }
960
+
961
+ private assertValueType() {
962
+ const state = this.state;
963
+ const internalValue = state.internalValue;
964
+ const newValue = this.convertTypeValue(internalValue);
965
+
966
+ if (newValue !== internalValue) {
967
+ state.internalValue = newValue;
968
+ }
941
969
  }
942
970
 
943
971
  private assertCorrectValue(applyStrict = false) {
944
972
  const state = this.state;
973
+ this.assertValueType();
945
974
  const internalValue = state.internalValue;
946
975
  const selectionIsExcluded = state.selectionIsExcluded;
947
976
  const isMultiple = state.multiple;
@@ -949,7 +978,6 @@ export default class SelecticStore {
949
978
  let newValue = internalValue;
950
979
  const isPartial = this.isPartial.value ?? this.isPartial;
951
980
 
952
- this.assertValueType();
953
981
  if (isMultiple) {
954
982
  const hasFetchedAllItems = this.hasFetchedAllItems.value ?? this.hasFetchedAllItems;
955
983
 
@@ -984,7 +1012,7 @@ export default class SelecticStore {
984
1012
  return;
985
1013
  }
986
1014
  } else
987
- if (!this.hasItemInStore(newValue as OptionId)) {
1015
+ if (newValue !== null && !this.hasItemInStore(newValue as OptionId)) {
988
1016
  filteredValue = null;
989
1017
  isDifferent = true;
990
1018
 
@@ -1020,7 +1048,7 @@ export default class SelecticStore {
1020
1048
  });
1021
1049
  }
1022
1050
 
1023
- /* XXX: This is not a computed property to avoid consuming more memory */
1051
+ /* This method is for the computed property listOptions */
1024
1052
  private getListOptions(): OptionValue[] {
1025
1053
  const options = this.props.options;
1026
1054
  const listOptions: OptionValue[] = [];
@@ -1028,6 +1056,7 @@ export default class SelecticStore {
1028
1056
  if (!Array.isArray(options)) {
1029
1057
  return listOptions;
1030
1058
  }
1059
+ const state = this.state;
1031
1060
 
1032
1061
  options.forEach((option) => {
1033
1062
  /* manage simple string */
@@ -1043,14 +1072,14 @@ export default class SelecticStore {
1043
1072
  const subOptions = option.options;
1044
1073
 
1045
1074
  /* check for groups */
1046
- if (group && !this.state.groups.has(group)) {
1047
- this.state.groups.set(group, String(group));
1075
+ if (group && !state.groups.has(group)) {
1076
+ state.groups.set(group, String(group));
1048
1077
  }
1049
1078
 
1050
1079
  /* check for sub options */
1051
1080
  if (subOptions) {
1052
1081
  const groupId = option.id as StrictOptionId;
1053
- this.state.groups.set(groupId, option.text);
1082
+ state.groups.set(groupId, option.text);
1054
1083
 
1055
1084
  subOptions.forEach((subOpt) => {
1056
1085
  subOpt.group = groupId;
@@ -1065,7 +1094,7 @@ export default class SelecticStore {
1065
1094
  return listOptions;
1066
1095
  }
1067
1096
 
1068
- /* XXX: This is not a computed property to avoid consuming more memory */
1097
+ /* This method is for the computed property elementOptions */
1069
1098
  private getElementOptions(): OptionValue[] {
1070
1099
  const options = this.props.childOptions;
1071
1100
  const childOptions: OptionValue[] = [];
@@ -1073,20 +1102,21 @@ export default class SelecticStore {
1073
1102
  if (!Array.isArray(options) || options.length === 0) {
1074
1103
  return childOptions;
1075
1104
  }
1105
+ const state = this.state;
1076
1106
 
1077
1107
  options.forEach((option) => {
1078
1108
  const group = option.group;
1079
1109
  const subOptions = option.options;
1080
1110
 
1081
1111
  /* check for groups */
1082
- if (group && !this.state.groups.has(group)) {
1083
- this.state.groups.set(group, String(group));
1112
+ if (group && !state.groups.has(group)) {
1113
+ state.groups.set(group, String(group));
1084
1114
  }
1085
1115
 
1086
1116
  /* check for sub options */
1087
1117
  if (subOptions) {
1088
1118
  const groupId = option.id as StrictOptionId;
1089
- this.state.groups.set(groupId, option.text);
1119
+ state.groups.set(groupId, option.text);
1090
1120
 
1091
1121
  const sOpts: OptionValue[] = subOptions.map((subOpt) => {
1092
1122
  return Object.assign({}, subOpt, {
@@ -1138,8 +1168,8 @@ export default class SelecticStore {
1138
1168
  }
1139
1169
  }
1140
1170
 
1141
- listOptions = this.getListOptions();
1142
- elementOptions = this.getElementOptions();
1171
+ listOptions = this.listOptions.value ?? this.listOptions;
1172
+ elementOptions = this.elementOptions.value ?? this.elementOptions;
1143
1173
 
1144
1174
  if (this.state.optionBehaviorOperation === 'force') {
1145
1175
  const orderValue = optionBehaviorOrder.find((value) => lengthFromOrder(value) > 0)!;
@@ -1257,26 +1287,27 @@ export default class SelecticStore {
1257
1287
 
1258
1288
  private async buildSelectedOptions() {
1259
1289
  const internalValue = this.state.internalValue;
1290
+ const state = this.state;
1260
1291
 
1261
- if (this.state.multiple) {
1292
+ if (state.multiple) {
1262
1293
  /* display partial information about selected items */
1263
- this.state.selectedOptions = this.buildSelectedItems(internalValue as StrictOptionId[]);
1294
+ state.selectedOptions = this.buildSelectedItems(internalValue as StrictOptionId[]);
1264
1295
 
1265
1296
  const items: OptionItem[] = await this.getItems(internalValue as StrictOptionId[]).catch(() => []);
1266
- if (internalValue !== this.state.internalValue) {
1297
+ if (internalValue !== state.internalValue) {
1267
1298
  /* Values have been deprecated */
1268
1299
  return;
1269
1300
  }
1270
1301
 
1271
1302
  if (items.length !== (internalValue as StrictOptionId[]).length) {
1272
- if (!this.state.strictValue) {
1273
- const updatedItems = this.state.selectedOptions.map((option) => {
1303
+ if (!state.strictValue) {
1304
+ const updatedItems = state.selectedOptions.map((option) => {
1274
1305
  const foundItem = items.find((item) => item.id === option.id);
1275
1306
 
1276
1307
  return foundItem || option;
1277
1308
  });
1278
1309
 
1279
- this.state.selectedOptions = updatedItems;
1310
+ state.selectedOptions = updatedItems;
1280
1311
  } else {
1281
1312
  const itemIds = items.map((item) => item.id as StrictOptionId) ;
1282
1313
 
@@ -1286,29 +1317,29 @@ export default class SelecticStore {
1286
1317
  }
1287
1318
 
1288
1319
  /* display full information about selected items */
1289
- this.state.selectedOptions = items;
1320
+ state.selectedOptions = items;
1290
1321
  } else
1291
1322
  if (internalValue === null) {
1292
- this.state.selectedOptions = null;
1323
+ state.selectedOptions = null;
1293
1324
  } else {
1294
1325
  /* display partial information about selected items */
1295
- this.state.selectedOptions = this.buildSelectedItems([internalValue as OptionId])[0];
1326
+ state.selectedOptions = this.buildSelectedItems([internalValue as OptionId])[0];
1296
1327
 
1297
1328
  const items = await this.getItems([internalValue as OptionId]).catch(() => []);
1298
- if (internalValue !== this.state.internalValue) {
1329
+ if (internalValue !== state.internalValue) {
1299
1330
  /* Values have been deprecated */
1300
1331
  return;
1301
1332
  }
1302
1333
 
1303
1334
  if (!items.length) {
1304
- if (this.state.strictValue) {
1335
+ if (state.strictValue) {
1305
1336
  this.commit('internalValue', null);
1306
1337
  }
1307
1338
  return;
1308
1339
  }
1309
1340
 
1310
1341
  /* display full information about selected items */
1311
- this.state.selectedOptions = items[0];
1342
+ state.selectedOptions = items[0];
1312
1343
  }
1313
1344
  }
1314
1345
 
@@ -1437,10 +1468,10 @@ export default class SelecticStore {
1437
1468
 
1438
1469
  switch (order) {
1439
1470
  case 'O':
1440
- options = this.filterOptions(this.getListOptions(), search);
1471
+ options = this.filterOptions(this.listOptions.value ?? this.listOptions, search);
1441
1472
  break;
1442
1473
  case 'E':
1443
- options = this.filterOptions(this.getElementOptions(), search);
1474
+ options = this.filterOptions(this.elementOptions.value ?? this.elementOptions, search);
1444
1475
  break;
1445
1476
  }
1446
1477
  this.state.filteredOptions.push(...options);
package/src/index.tsx CHANGED
@@ -531,7 +531,7 @@ export default class Selectic extends Vue<Props> {
531
531
 
532
532
  @Watch('options')
533
533
  public onOptionsChange() {
534
- this.store.props.options = this.options;
534
+ this.store.props.options = Array.from(this.options);
535
535
  }
536
536
 
537
537
  @Watch('texts')
@@ -67,6 +67,43 @@ tape.test('Store creation', (subT) => {
67
67
  t.end();
68
68
  });
69
69
 
70
+ subT.test('"value" property', (sTest) => {
71
+ sTest.test('should initialize the value', async (t) => {
72
+ const propOptions = getOptions(5);
73
+ const store = new Store({
74
+ value: 2,
75
+ options: propOptions,
76
+ });
77
+
78
+ await sleep(0);
79
+
80
+ const state = store.state;
81
+
82
+ t.is(state.internalValue, 2);
83
+
84
+ t.end();
85
+ });
86
+
87
+ sTest.test('should set the correct value type', async (t) => {
88
+ const propOptions = getOptions(5);
89
+ const store = new Store({
90
+ value: 2,
91
+ params: {
92
+ multiple: true,
93
+ },
94
+ options: propOptions,
95
+ });
96
+
97
+ await sleep(0);
98
+
99
+ const state = store.state;
100
+
101
+ t.deepEqual(state.internalValue, [2]);
102
+
103
+ t.end();
104
+ });
105
+ });
106
+
70
107
  subT.test('"options" property', (sTest) => {
71
108
  sTest.test('should handle short options list', async (t) => {
72
109
  const propOptions = getOptions(5);
@@ -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({
@@ -1063,4 +1063,158 @@ tape.test('commit()', (st) => {
1063
1063
  t.end();
1064
1064
  });
1065
1065
  });
1066
+
1067
+ st.test('when changing "internalValue"', (sTest) => {
1068
+ sTest.test('should change the value', async (t) => {
1069
+ const store1 = new Store({
1070
+ options: getOptions(5),
1071
+ params: {
1072
+ autoSelect: false,
1073
+ },
1074
+ });
1075
+ const store2 = new Store({
1076
+ options: getOptions(5),
1077
+ params: {
1078
+ autoSelect: false,
1079
+ multiple: true,
1080
+ },
1081
+ });
1082
+
1083
+ store1.commit('internalValue', 3);
1084
+ store2.commit('internalValue', [1, 2]);
1085
+ await Promise.all([_.nextVueTick(store1), _.nextVueTick(store2)]);
1086
+
1087
+ t.is(store1.state.internalValue, 3);
1088
+ t.deepEqual(store2.state.internalValue, [1, 2]);
1089
+
1090
+ store1.commit('internalValue', 1);
1091
+ store2.commit('internalValue', [3, 4, 5]);
1092
+ await Promise.all([_.nextVueTick(store1), _.nextVueTick(store2)]);
1093
+
1094
+ t.is(store1.state.internalValue, 1);
1095
+ t.deepEqual(store2.state.internalValue, [3, 4, 5]);
1096
+
1097
+ store1.commit('internalValue', null);
1098
+ store2.commit('internalValue', []);
1099
+ await Promise.all([_.nextVueTick(store1), _.nextVueTick(store2)]);
1100
+
1101
+ t.is(store1.state.internalValue, null);
1102
+ t.deepEqual(store2.state.internalValue, []);
1103
+
1104
+ t.end();
1105
+ });
1106
+
1107
+ sTest.test('should convert values', async (t) => {
1108
+ const store1 = new Store({
1109
+ options: getOptions(5),
1110
+ params: {
1111
+ autoSelect: false,
1112
+ },
1113
+ });
1114
+ const store2 = new Store({
1115
+ options: getOptions(5),
1116
+ params: {
1117
+ autoSelect: false,
1118
+ multiple: true,
1119
+ },
1120
+ });
1121
+
1122
+ store1.commit('internalValue', [3]);
1123
+ store2.commit('internalValue', 1);
1124
+ await Promise.all([_.nextVueTick(store1), _.nextVueTick(store2)]);
1125
+
1126
+ t.is(store1.state.internalValue, 3);
1127
+ t.deepEqual(store2.state.internalValue, [1]);
1128
+
1129
+ store1.commit('internalValue', [1, 2, 3]);
1130
+ store2.commit('internalValue', 3);
1131
+ await Promise.all([_.nextVueTick(store1), _.nextVueTick(store2)]);
1132
+
1133
+ t.is(store1.state.internalValue, 1);
1134
+ t.deepEqual(store2.state.internalValue, [3]);
1135
+
1136
+ store1.commit('internalValue', []);
1137
+ store2.commit('internalValue', null);
1138
+ await Promise.all([_.nextVueTick(store1), _.nextVueTick(store2)]);
1139
+
1140
+ t.is(store1.state.internalValue, null, 'should not select anything');
1141
+ t.deepEqual(store2.state.internalValue, [], 'should have no selection');
1142
+
1143
+ t.end();
1144
+ });
1145
+
1146
+ sTest.test('should be changed to the first option', async (t) => {
1147
+ const store1 = new Store({
1148
+ options: getOptions(5),
1149
+ params: {
1150
+ autoSelect: true,
1151
+ },
1152
+ value: 2,
1153
+ });
1154
+
1155
+ store1.commit('internalValue', 3);
1156
+ await _.nextVueTick(store1);
1157
+
1158
+ t.is(store1.state.internalValue, 3);
1159
+
1160
+ store1.commit('internalValue', null);
1161
+ await _.nextVueTick(store1);
1162
+
1163
+ t.is(store1.state.internalValue, 0);
1164
+
1165
+ t.end();
1166
+ });
1167
+
1168
+ sTest.test('should be changed to the first remaining option', async (t) => {
1169
+ const store1 = new Store({
1170
+ options: [{
1171
+ id: 0,
1172
+ }, {
1173
+ id: 1,
1174
+ disabled: true,
1175
+ }, {
1176
+ id: 2,
1177
+ }, {
1178
+ id: 3,
1179
+ }, {
1180
+ id: 4,
1181
+ }],
1182
+ params: {
1183
+ autoSelect: true,
1184
+ strictValue: true,
1185
+ },
1186
+ value: 2,
1187
+ });
1188
+
1189
+ store1.commit('internalValue', 0);
1190
+ await _.nextVueTick(store1);
1191
+
1192
+ t.is(store1.state.internalValue, 0);
1193
+
1194
+ store1.props.options = [{
1195
+ id: 1,
1196
+ disabled: true,
1197
+ }, {
1198
+ id: 2,
1199
+ }, {
1200
+ id: 3,
1201
+ }, {
1202
+ id: 4,
1203
+ }];
1204
+
1205
+ await _.nextVueTick(store1);
1206
+
1207
+ t.is(store1.state.internalValue, 2, 'should change to the first available option');
1208
+
1209
+ store1.commit('internalValue', 3);
1210
+ await _.nextVueTick(store1);
1211
+
1212
+ store1.commit('internalValue', null);
1213
+ await _.nextVueTick(store1);
1214
+
1215
+ t.is(store1.state.internalValue, 2, 'should select the first available option');
1216
+
1217
+ t.end();
1218
+ });
1219
+ });
1066
1220
  });
package/types/Store.d.ts CHANGED
@@ -278,6 +278,8 @@ export default class SelecticStore {
278
278
  isPartial: ComputedRef<boolean>;
279
279
  hasAllItems: ComputedRef<boolean>;
280
280
  hasFetchedAllItems: ComputedRef<boolean>;
281
+ private listOptions;
282
+ private elementOptions;
281
283
  _uid: number;
282
284
  constructor(props?: Props);
283
285
  commit<N extends keyof SelecticStoreState, V extends SelecticStoreState[N]>(name: N, value: V): void;
@@ -292,6 +294,7 @@ export default class SelecticStore {
292
294
  changeTexts(texts: PartialMessages): void;
293
295
  private hasValue;
294
296
  private getValue;
297
+ private convertTypeValue;
295
298
  private assertValueType;
296
299
  private assertCorrectValue;
297
300
  private updateFilteredOptions;