selectic 3.0.19 → 3.0.20

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/.tool-versions ADDED
@@ -0,0 +1,5 @@
1
+ # ASDF configuration file for mmsx repository.
2
+ #
3
+ # https://asdf-vm.com/manage/configuration.html
4
+
5
+ nodejs 12.18.4 system
package/README.md CHANGED
@@ -12,51 +12,66 @@ reverse selection, and many other possibilities.
12
12
 
13
13
  It integrates well with VueJS and is reactive to option changes.
14
14
 
15
+ Typescript types are provided.
16
+
15
17
  There are very few dependencies and code stays very small (~90kB).
16
18
 
19
+ ![example of a Selectic component](./doc/images/selectic_example.png)
20
+
17
21
  ## Example
18
22
 
19
23
  ```html
20
24
  <Selectic
21
- :options="['first choice', 'second choice', 'third choice']"
22
- v-model="selection"
25
+ :options="['first choice', 'second choice', 'third choice']"
26
+ v-model="selection"
23
27
  />
24
28
 
25
29
  <Selectic
26
- value="item2"
27
- :options="[{
28
- id: 'item1',
29
- text: 'The first item',
30
- icon: 'fa fa-thumbs-o-up',
31
- }, {
32
- id: 'item2',
33
- text: 'Another item',
34
- title: 'second choice',
35
- }, {
36
- id: 'item3',
37
- text: 'Disabled item',
38
- disabled: true,
39
- }]"
40
- multiple
41
-
42
- @input="onChange"
30
+ multiple
31
+ value="item2"
32
+ :options="[{
33
+ id: 'item1',
34
+ text: 'The first item',
35
+ icon: 'fa fa-thumbs-o-up',
36
+ }, {
37
+ id: 'item2',
38
+ text: 'Another item',
39
+ title: 'second choice',
40
+ }, {
41
+ id: 'item3',
42
+ text: 'Disabled item',
43
+ disabled: true,
44
+ }]"
45
+
46
+ @input="onChange"
43
47
  />
44
48
 
45
- <Selectic>
46
- <optgroup label="Animals">
47
- <option>Cat</option>
48
- <option value="dog">Dog</option>
49
- <option :value="42">42 goldfishes</option>
50
- </optgroup>
51
- </Selectic>
49
+ <Selectic
50
+ :options="[{
51
+ id: 'animals',
52
+ text: 'Animals',
53
+ options: [{
54
+ id: 'cat',
55
+ text: 'Cat',
56
+ }, {
57
+ id: 'dog',
58
+ text: 'A dog',
59
+ }, {
60
+ id: 42,
61
+ text: '42 goldfishes',
62
+ }],
63
+ }]"
64
+ />
52
65
  ```
53
66
 
67
+ [Full documentation](./doc/main.md)
68
+
54
69
  ## Features
55
70
 
56
71
  * List of items (either string array or object array).
57
72
  * Can load dynamically list from a server and the list can be paginate (with a
58
73
  cache system to avoid reloading previous requests).
59
- * Slots: options may be added from Vue template (by writing explicit `<option>` or `<optgroup>`) in a reactive way _(currently disabled in 3.0.0)_.
74
+ * ~~Slots: options may be added from Vue template (by writing explicit `<option>` or `<optgroup>`) in a reactive way~~ _(currently disabled in 3.0.0+)_.
60
75
  * Multi-sources: Possibility to combine options from different sources (static, dynamic or slots) or to use the other as fallback (if the list is empty).
61
76
  * Supports basic Select properties like `multiple`, `disabled`, `title`
62
77
  * Supports group element (equivalent of optGroup), even for dynamic list.
@@ -111,6 +111,33 @@ function assignObject(obj, ...sourceObjects) {
111
111
  }
112
112
  return result;
113
113
  }
114
+ /** Compare 2 list of options.
115
+ * @returns true if there are no difference
116
+ */
117
+ function compareOptions(oldOptions, newOptions) {
118
+ if (oldOptions.length !== newOptions.length) {
119
+ return false;
120
+ }
121
+ return oldOptions.every((oldOption, idx) => {
122
+ const newOption = newOptions[idx];
123
+ const keys = Object.keys(oldOption);
124
+ if (keys.length !== Object.keys(newOption).length) {
125
+ return false;
126
+ }
127
+ return keys.every((optionKey) => {
128
+ const key = optionKey;
129
+ const oldValue = oldOption[key];
130
+ const newValue = newOption[key];
131
+ if (key === 'options') {
132
+ return compareOptions(oldValue, newValue);
133
+ }
134
+ if (key === 'data') {
135
+ return JSON.stringify(oldValue) === JSON.stringify(newValue);
136
+ }
137
+ return oldValue === newValue;
138
+ });
139
+ });
140
+ }
114
141
 
115
142
  /* File Purpose:
116
143
  * It keeps and computes all states at a single place.
@@ -140,6 +167,7 @@ let messages = {
140
167
  moreSelectedItem: '+1 other',
141
168
  moreSelectedItems: '+%d others',
142
169
  unknownPropertyValue: 'property "%s" has incorrect values.',
170
+ wrongQueryResult: 'Query did not return all results.',
143
171
  };
144
172
  let closePreviousSelectic;
145
173
  /* }}} */
@@ -767,7 +795,7 @@ class SelecticStore {
767
795
  });
768
796
  return childOptions;
769
797
  }
770
- buildAllOptions(keepFetched = false) {
798
+ buildAllOptions(keepFetched = false, stopFetch = false) {
771
799
  const allOptions = [];
772
800
  let listOptions = [];
773
801
  let elementOptions = [];
@@ -838,12 +866,26 @@ class SelecticStore {
838
866
  this.state.totalAllOptions = allOptions.length;
839
867
  }
840
868
  }
841
- this.state.filteredOptions = [];
842
- this.state.totalFilteredOptions = Infinity;
843
- this.buildFilteredOptions().then(() => {
844
- /* XXX: To recompute for strict mode and auto-select */
845
- this.assertCorrectValue();
846
- });
869
+ if (!stopFetch) {
870
+ this.state.filteredOptions = [];
871
+ this.state.totalFilteredOptions = Infinity;
872
+ this.buildFilteredOptions().then(() => {
873
+ /* XXX: To recompute for strict mode and auto-select */
874
+ this.assertCorrectValue();
875
+ });
876
+ }
877
+ else {
878
+ /* Do not fetch again just build filteredOptions */
879
+ const search = this.state.searchText;
880
+ if (!search) {
881
+ this.state.filteredOptions = this.buildGroupItems(allOptions);
882
+ this.state.totalFilteredOptions = this.state.filteredOptions.length;
883
+ return;
884
+ }
885
+ const options = this.filterOptions(allOptions, search);
886
+ this.state.filteredOptions = options;
887
+ this.state.totalFilteredOptions = this.state.filteredOptions.length;
888
+ }
847
889
  }
848
890
  async buildFilteredOptions() {
849
891
  if (!this.state.isOpen) {
@@ -975,6 +1017,7 @@ class SelecticStore {
975
1017
  const requestId = ++this.requestId;
976
1018
  const { total: rTotal, result } = await fetchCallback(search, offset, limit);
977
1019
  let total = rTotal;
1020
+ let errorMessage = '';
978
1021
  /* Assert result is correctly formatted */
979
1022
  if (!Array.isArray(result)) {
980
1023
  throw new Error(labels.wrongFormattedData);
@@ -990,8 +1033,17 @@ class SelecticStore {
990
1033
  if (!search) {
991
1034
  /* update cache */
992
1035
  state.totalDynOptions = total;
993
- state.dynOptions.splice(offset, limit, ...result);
994
- setTimeout(() => this.buildAllOptions(true), 0);
1036
+ const old = state.dynOptions.splice(offset, limit, ...result);
1037
+ if (compareOptions(old, result)) {
1038
+ /* Added options are the same as previous ones.
1039
+ * Stop fetching to avoid infinite loop
1040
+ */
1041
+ errorMessage = labels.wrongQueryResult;
1042
+ setTimeout(() => this.buildAllOptions(true, true), 0);
1043
+ }
1044
+ else {
1045
+ setTimeout(() => this.buildAllOptions(true), 0);
1046
+ }
995
1047
  }
996
1048
  /* Check request is not obsolete */
997
1049
  if (requestId !== this.requestId) {
@@ -1014,13 +1066,13 @@ class SelecticStore {
1014
1066
  if (search && state.totalFilteredOptions <= state.filteredOptions.length) {
1015
1067
  this.addStaticFilteredOptions(true);
1016
1068
  }
1017
- state.status.errorMessage = '';
1069
+ state.status.errorMessage = errorMessage;
1018
1070
  }
1019
1071
  catch (e) {
1020
1072
  state.status.errorMessage = e.message;
1021
1073
  if (!search) {
1022
1074
  state.totalDynOptions = 0;
1023
- this.buildAllOptions(true);
1075
+ this.buildAllOptions(true, true);
1024
1076
  }
1025
1077
  }
1026
1078
  this.state.status.searching = false;
@@ -1220,6 +1272,8 @@ let MainInput = class MainInput extends vtyx.Vue {
1220
1272
  /* }}} */
1221
1273
  /* {{{ data */
1222
1274
  this.nbHiddenItems = 0;
1275
+ /* reactivity non needed */
1276
+ this.domObserver = null;
1223
1277
  }
1224
1278
  /* }}} */
1225
1279
  /* {{{ computed */
@@ -1265,8 +1319,18 @@ let MainInput = class MainInput extends vtyx.Vue {
1265
1319
  get singleSelectedItem() {
1266
1320
  const state = this.store.state;
1267
1321
  const isMultiple = state.multiple;
1268
- const selected = this.selectedOptions;
1269
- return !isMultiple && !!selected && selected.text;
1322
+ if (isMultiple) {
1323
+ return;
1324
+ }
1325
+ return this.selectedOptions;
1326
+ }
1327
+ get singleSelectedItemText() {
1328
+ const item = this.singleSelectedItem;
1329
+ return (item === null || item === void 0 ? void 0 : item.text) || '';
1330
+ }
1331
+ get singleSelectedItemTitle() {
1332
+ const item = this.singleSelectedItem;
1333
+ return (item === null || item === void 0 ? void 0 : item.title) || (item === null || item === void 0 ? void 0 : item.text) || '';
1270
1334
  }
1271
1335
  get singleStyle() {
1272
1336
  const selected = this.selectedOptions;
@@ -1364,6 +1428,11 @@ let MainInput = class MainInput extends vtyx.Vue {
1364
1428
  * currently shown */
1365
1429
  const el = this.$refs.selectedItems;
1366
1430
  const parentEl = el.parentElement;
1431
+ if (!document.contains(parentEl)) {
1432
+ /* The element is currently not in DOM */
1433
+ this.createObserver(parentEl);
1434
+ return;
1435
+ }
1367
1436
  const parentPadding = parseInt(getComputedStyle(parentEl).getPropertyValue('padding-right'), 10);
1368
1437
  const clearEl = parentEl.querySelector('.selectic-input__clear-icon');
1369
1438
  const clearWidth = clearEl ? clearEl.offsetWidth : 0;
@@ -1395,6 +1464,33 @@ let MainInput = class MainInput extends vtyx.Vue {
1395
1464
  idx--;
1396
1465
  this.nbHiddenItems = selectedOptions.length - idx;
1397
1466
  }
1467
+ closeObserver() {
1468
+ const observer = this.domObserver;
1469
+ if (observer) {
1470
+ observer.disconnect();
1471
+ }
1472
+ this.domObserver = null;
1473
+ }
1474
+ createObserver(el) {
1475
+ this.closeObserver();
1476
+ const observer = new MutationObserver((mutationsList) => {
1477
+ for (const mutation of mutationsList) {
1478
+ if (mutation.type === 'childList') {
1479
+ for (const elMutated of Array.from(mutation.addedNodes)) {
1480
+ /* Check that element has been added to DOM */
1481
+ if (elMutated.contains(el)) {
1482
+ this.closeObserver();
1483
+ this.computeSize();
1484
+ return;
1485
+ }
1486
+ }
1487
+ }
1488
+ }
1489
+ });
1490
+ const config = { childList: true, subtree: true };
1491
+ observer.observe(document, config);
1492
+ this.domObserver = observer;
1493
+ }
1398
1494
  /* }}} */
1399
1495
  /* {{{ watch */
1400
1496
  onInternalChange() {
@@ -1405,6 +1501,9 @@ let MainInput = class MainInput extends vtyx.Vue {
1405
1501
  updated() {
1406
1502
  this.computeSize();
1407
1503
  }
1504
+ beforeUnmount() {
1505
+ this.closeObserver();
1506
+ }
1408
1507
  /* }}} */
1409
1508
  render() {
1410
1509
  return (vtyx.h("div", { class: "selectic-container has-feedback", on: {
@@ -1415,14 +1514,14 @@ let MainInput = class MainInput extends vtyx.Vue {
1415
1514
  focused: this.store.state.isOpen,
1416
1515
  disabled: this.store.state.disabled,
1417
1516
  }] },
1418
- this.hasValue && !this.store.state.multiple && (vtyx.h("span", { class: "selectic-item_text", style: this.singleStyle, title: this.singleSelectedItem || '' }, this.singleSelectedItem)),
1517
+ this.hasValue && !this.store.state.multiple && (vtyx.h("span", { class: "selectic-item_text", style: this.singleStyle, title: this.singleSelectedItemTitle }, this.singleSelectedItemText)),
1419
1518
  this.displayPlaceholder && (vtyx.h("span", { class: [
1420
1519
  'selectic-input__selected-items__placeholder',
1421
1520
  'selectic-item_text',
1422
1521
  ], title: this.store.state.placeholder }, this.store.state.placeholder)),
1423
1522
  this.store.state.multiple && (vtyx.h("div", { class: "selectic-input__selected-items", ref: "selectedItems" },
1424
1523
  this.isSelectionReversed && (vtyx.h("span", { class: "fa fa-strikethrough selectic-input__reverse-icon", title: this.reverseSelectionLabel })),
1425
- this.showSelectedOptions.map((item) => (vtyx.h("div", { class: "single-value", style: item.style, title: item.text, on: {
1524
+ this.showSelectedOptions.map((item) => (vtyx.h("div", { class: "single-value", style: item.style, title: item.title || item.text, on: {
1426
1525
  click: () => this.$emit('item:click', item.id),
1427
1526
  } },
1428
1527
  vtyx.h("span", { class: "selectic-input__selected-items__value" }, item.text),
@@ -107,6 +107,33 @@ function assignObject(obj, ...sourceObjects) {
107
107
  }
108
108
  return result;
109
109
  }
110
+ /** Compare 2 list of options.
111
+ * @returns true if there are no difference
112
+ */
113
+ function compareOptions(oldOptions, newOptions) {
114
+ if (oldOptions.length !== newOptions.length) {
115
+ return false;
116
+ }
117
+ return oldOptions.every((oldOption, idx) => {
118
+ const newOption = newOptions[idx];
119
+ const keys = Object.keys(oldOption);
120
+ if (keys.length !== Object.keys(newOption).length) {
121
+ return false;
122
+ }
123
+ return keys.every((optionKey) => {
124
+ const key = optionKey;
125
+ const oldValue = oldOption[key];
126
+ const newValue = newOption[key];
127
+ if (key === 'options') {
128
+ return compareOptions(oldValue, newValue);
129
+ }
130
+ if (key === 'data') {
131
+ return JSON.stringify(oldValue) === JSON.stringify(newValue);
132
+ }
133
+ return oldValue === newValue;
134
+ });
135
+ });
136
+ }
110
137
 
111
138
  /* File Purpose:
112
139
  * It keeps and computes all states at a single place.
@@ -136,6 +163,7 @@ let messages = {
136
163
  moreSelectedItem: '+1 other',
137
164
  moreSelectedItems: '+%d others',
138
165
  unknownPropertyValue: 'property "%s" has incorrect values.',
166
+ wrongQueryResult: 'Query did not return all results.',
139
167
  };
140
168
  let closePreviousSelectic;
141
169
  /* }}} */
@@ -763,7 +791,7 @@ class SelecticStore {
763
791
  });
764
792
  return childOptions;
765
793
  }
766
- buildAllOptions(keepFetched = false) {
794
+ buildAllOptions(keepFetched = false, stopFetch = false) {
767
795
  const allOptions = [];
768
796
  let listOptions = [];
769
797
  let elementOptions = [];
@@ -834,12 +862,26 @@ class SelecticStore {
834
862
  this.state.totalAllOptions = allOptions.length;
835
863
  }
836
864
  }
837
- this.state.filteredOptions = [];
838
- this.state.totalFilteredOptions = Infinity;
839
- this.buildFilteredOptions().then(() => {
840
- /* XXX: To recompute for strict mode and auto-select */
841
- this.assertCorrectValue();
842
- });
865
+ if (!stopFetch) {
866
+ this.state.filteredOptions = [];
867
+ this.state.totalFilteredOptions = Infinity;
868
+ this.buildFilteredOptions().then(() => {
869
+ /* XXX: To recompute for strict mode and auto-select */
870
+ this.assertCorrectValue();
871
+ });
872
+ }
873
+ else {
874
+ /* Do not fetch again just build filteredOptions */
875
+ const search = this.state.searchText;
876
+ if (!search) {
877
+ this.state.filteredOptions = this.buildGroupItems(allOptions);
878
+ this.state.totalFilteredOptions = this.state.filteredOptions.length;
879
+ return;
880
+ }
881
+ const options = this.filterOptions(allOptions, search);
882
+ this.state.filteredOptions = options;
883
+ this.state.totalFilteredOptions = this.state.filteredOptions.length;
884
+ }
843
885
  }
844
886
  async buildFilteredOptions() {
845
887
  if (!this.state.isOpen) {
@@ -971,6 +1013,7 @@ class SelecticStore {
971
1013
  const requestId = ++this.requestId;
972
1014
  const { total: rTotal, result } = await fetchCallback(search, offset, limit);
973
1015
  let total = rTotal;
1016
+ let errorMessage = '';
974
1017
  /* Assert result is correctly formatted */
975
1018
  if (!Array.isArray(result)) {
976
1019
  throw new Error(labels.wrongFormattedData);
@@ -986,8 +1029,17 @@ class SelecticStore {
986
1029
  if (!search) {
987
1030
  /* update cache */
988
1031
  state.totalDynOptions = total;
989
- state.dynOptions.splice(offset, limit, ...result);
990
- setTimeout(() => this.buildAllOptions(true), 0);
1032
+ const old = state.dynOptions.splice(offset, limit, ...result);
1033
+ if (compareOptions(old, result)) {
1034
+ /* Added options are the same as previous ones.
1035
+ * Stop fetching to avoid infinite loop
1036
+ */
1037
+ errorMessage = labels.wrongQueryResult;
1038
+ setTimeout(() => this.buildAllOptions(true, true), 0);
1039
+ }
1040
+ else {
1041
+ setTimeout(() => this.buildAllOptions(true), 0);
1042
+ }
991
1043
  }
992
1044
  /* Check request is not obsolete */
993
1045
  if (requestId !== this.requestId) {
@@ -1010,13 +1062,13 @@ class SelecticStore {
1010
1062
  if (search && state.totalFilteredOptions <= state.filteredOptions.length) {
1011
1063
  this.addStaticFilteredOptions(true);
1012
1064
  }
1013
- state.status.errorMessage = '';
1065
+ state.status.errorMessage = errorMessage;
1014
1066
  }
1015
1067
  catch (e) {
1016
1068
  state.status.errorMessage = e.message;
1017
1069
  if (!search) {
1018
1070
  state.totalDynOptions = 0;
1019
- this.buildAllOptions(true);
1071
+ this.buildAllOptions(true, true);
1020
1072
  }
1021
1073
  }
1022
1074
  this.state.status.searching = false;
@@ -1216,6 +1268,8 @@ let MainInput = class MainInput extends Vue {
1216
1268
  /* }}} */
1217
1269
  /* {{{ data */
1218
1270
  this.nbHiddenItems = 0;
1271
+ /* reactivity non needed */
1272
+ this.domObserver = null;
1219
1273
  }
1220
1274
  /* }}} */
1221
1275
  /* {{{ computed */
@@ -1261,8 +1315,18 @@ let MainInput = class MainInput extends Vue {
1261
1315
  get singleSelectedItem() {
1262
1316
  const state = this.store.state;
1263
1317
  const isMultiple = state.multiple;
1264
- const selected = this.selectedOptions;
1265
- return !isMultiple && !!selected && selected.text;
1318
+ if (isMultiple) {
1319
+ return;
1320
+ }
1321
+ return this.selectedOptions;
1322
+ }
1323
+ get singleSelectedItemText() {
1324
+ const item = this.singleSelectedItem;
1325
+ return (item === null || item === void 0 ? void 0 : item.text) || '';
1326
+ }
1327
+ get singleSelectedItemTitle() {
1328
+ const item = this.singleSelectedItem;
1329
+ return (item === null || item === void 0 ? void 0 : item.title) || (item === null || item === void 0 ? void 0 : item.text) || '';
1266
1330
  }
1267
1331
  get singleStyle() {
1268
1332
  const selected = this.selectedOptions;
@@ -1360,6 +1424,11 @@ let MainInput = class MainInput extends Vue {
1360
1424
  * currently shown */
1361
1425
  const el = this.$refs.selectedItems;
1362
1426
  const parentEl = el.parentElement;
1427
+ if (!document.contains(parentEl)) {
1428
+ /* The element is currently not in DOM */
1429
+ this.createObserver(parentEl);
1430
+ return;
1431
+ }
1363
1432
  const parentPadding = parseInt(getComputedStyle(parentEl).getPropertyValue('padding-right'), 10);
1364
1433
  const clearEl = parentEl.querySelector('.selectic-input__clear-icon');
1365
1434
  const clearWidth = clearEl ? clearEl.offsetWidth : 0;
@@ -1391,6 +1460,33 @@ let MainInput = class MainInput extends Vue {
1391
1460
  idx--;
1392
1461
  this.nbHiddenItems = selectedOptions.length - idx;
1393
1462
  }
1463
+ closeObserver() {
1464
+ const observer = this.domObserver;
1465
+ if (observer) {
1466
+ observer.disconnect();
1467
+ }
1468
+ this.domObserver = null;
1469
+ }
1470
+ createObserver(el) {
1471
+ this.closeObserver();
1472
+ const observer = new MutationObserver((mutationsList) => {
1473
+ for (const mutation of mutationsList) {
1474
+ if (mutation.type === 'childList') {
1475
+ for (const elMutated of Array.from(mutation.addedNodes)) {
1476
+ /* Check that element has been added to DOM */
1477
+ if (elMutated.contains(el)) {
1478
+ this.closeObserver();
1479
+ this.computeSize();
1480
+ return;
1481
+ }
1482
+ }
1483
+ }
1484
+ }
1485
+ });
1486
+ const config = { childList: true, subtree: true };
1487
+ observer.observe(document, config);
1488
+ this.domObserver = observer;
1489
+ }
1394
1490
  /* }}} */
1395
1491
  /* {{{ watch */
1396
1492
  onInternalChange() {
@@ -1401,6 +1497,9 @@ let MainInput = class MainInput extends Vue {
1401
1497
  updated() {
1402
1498
  this.computeSize();
1403
1499
  }
1500
+ beforeUnmount() {
1501
+ this.closeObserver();
1502
+ }
1404
1503
  /* }}} */
1405
1504
  render() {
1406
1505
  return (h("div", { class: "selectic-container has-feedback", on: {
@@ -1411,14 +1510,14 @@ let MainInput = class MainInput extends Vue {
1411
1510
  focused: this.store.state.isOpen,
1412
1511
  disabled: this.store.state.disabled,
1413
1512
  }] },
1414
- this.hasValue && !this.store.state.multiple && (h("span", { class: "selectic-item_text", style: this.singleStyle, title: this.singleSelectedItem || '' }, this.singleSelectedItem)),
1513
+ this.hasValue && !this.store.state.multiple && (h("span", { class: "selectic-item_text", style: this.singleStyle, title: this.singleSelectedItemTitle }, this.singleSelectedItemText)),
1415
1514
  this.displayPlaceholder && (h("span", { class: [
1416
1515
  'selectic-input__selected-items__placeholder',
1417
1516
  'selectic-item_text',
1418
1517
  ], title: this.store.state.placeholder }, this.store.state.placeholder)),
1419
1518
  this.store.state.multiple && (h("div", { class: "selectic-input__selected-items", ref: "selectedItems" },
1420
1519
  this.isSelectionReversed && (h("span", { class: "fa fa-strikethrough selectic-input__reverse-icon", title: this.reverseSelectionLabel })),
1421
- this.showSelectedOptions.map((item) => (h("div", { class: "single-value", style: item.style, title: item.text, on: {
1520
+ this.showSelectedOptions.map((item) => (h("div", { class: "single-value", style: item.style, title: item.title || item.text, on: {
1422
1521
  click: () => this.$emit('item:click', item.id),
1423
1522
  } },
1424
1523
  h("span", { class: "selectic-input__selected-items__value" }, item.text),
package/doc/changeText.md CHANGED
@@ -5,13 +5,13 @@
5
5
  There are some texts in selectic. But sometimes it is useful to change them (because you want to translate them or to be more precise for the context usage).
6
6
 
7
7
  There are 3 ways to changes these texts:
8
- * Call the static `changetexts()` method. It changes texts for all selectic components.
8
+ * Call the static `changeTexts()` method. It changes texts for all selectic components.
9
9
  * Change the `texts` property. It changes texts only for the component.
10
- * Call the `changetexts()` method on the component. It changes texts only for the component.
10
+ * Call the `changeTexts()` method on the component. It changes texts only for the component.
11
11
 
12
12
  _Changes done locally are prioritary on changes done globally_.
13
13
 
14
- Changing texts on the component with property or with `changetexts()` are equivalent.
14
+ Changing texts on the component with property or with `changeTexts()` are equivalent.
15
15
 
16
16
  They accept the same argument: an object which contains keys of sentences.
17
17
 
@@ -19,7 +19,7 @@ It is possible to replace only some sentences.
19
19
 
20
20
  ## Keys
21
21
 
22
- * **noFetchMethod**: This is an error message which is displayed if some options are missing and `fetchcallback` is not defined. _Default value is `'Fetch callback is missing: it is not possible to retrieve data.'`_.
22
+ * **noFetchMethod**: This is an error message which is displayed if some options are missing and `fetchCallback` is not defined. _Default value is `'Fetch callback is missing: it is not possible to retrieve data.'`_.
23
23
 
24
24
  * **searchPlaceholder**: This is the message in the input placeholder to search for options. _Default value is `'Search'`_.
25
25
 
@@ -47,6 +47,8 @@ It is possible to replace only some sentences.
47
47
 
48
48
  * **moreSelectedItems**: This is a message displayed in a badge if there are more selected options than the size of the component. _Default value is `'+%d others'`_.
49
49
 
50
+ * **wrongQueryResult**: This is an error message displayed when result from the `fetchCallback` don't return all expected values. _Default value is `'Query did not return all results.'`_.
51
+
50
52
 
51
53
  ## Example
52
54
 
@@ -64,11 +66,11 @@ this.$refs.selectic.changeTexts({
64
66
  ```
65
67
 
66
68
  ```html
67
- <selectic
68
- texts: {{
69
+ <Selectic
70
+ :texts="{
69
71
  searchPlaceholder: 'Search for specific options?',
70
72
  searching: 'Loading information about this option',
71
- noData: 'oups, I forgot to fill this select',
72
- }}
73
+ noData: 'ouch, I forgot to fill this select',
74
+ }"
73
75
  />
74
76
  ```
package/doc/css.md CHANGED
@@ -74,7 +74,7 @@ body {
74
74
  * **--selectic-active-item-bg** _(default: `#66afe9`)_: Background color of items where cursor is over or the active by the arrow keys.
75
75
 
76
76
  * **--selectic-input-height** _(default: `30px`)_: The height of each items.<br>
77
- **⚠ Currently this value is also hard-coded in javascript, so it can break the scoll height estimation if this value is changed.**
77
+ **:warning: Currently this value is also hard-coded in javascript, so it can break the scroll height estimation if this value is changed.**
78
78
 
79
79
  ### Messages
80
80
 
@@ -10,7 +10,7 @@ It defines a unique identifier (ID) which must be unique in the whole document.
10
10
 
11
11
  ```html
12
12
  <selectic
13
- options={['item1', 'item2']}
13
+ :options="['item1', 'item2']"
14
14
  value="item2"
15
15
  id="example"
16
16
  />
@@ -28,7 +28,7 @@ This is the id of the selected option or an array of id (if `multiple` is set).
28
28
 
29
29
  ```html
30
30
  <selectic
31
- options={['item1', 'item2']}
31
+ :options="['item1', 'item2']"
32
32
  value="item2"
33
33
  />
34
34
  ```
@@ -39,7 +39,7 @@ When disabled is set, `selectic` cannot be open nor changed.
39
39
 
40
40
  ```html
41
41
  <selectic
42
- options={['item1', 'item2']}
42
+ :options="['item1', 'item2']"
43
43
  disabled
44
44
  />
45
45
  ```
@@ -52,7 +52,7 @@ The `value` will be an array.
52
52
 
53
53
  ```html
54
54
  <selectic
55
- options={['item1', 'item2', 'item3']}
55
+ :options="['item1', 'item2', 'item3']"
56
56
  multiple
57
57
  />
58
58
  ```
@@ -65,7 +65,7 @@ It displays the given text if no option is selected.
65
65
 
66
66
  ```html
67
67
  <selectic
68
- options={['item1', 'item2', 'item3']}
68
+ :options="['item1', 'item2', 'item3']"
69
69
  placeholder="choose an item"
70
70
  />
71
71
  ```
@@ -76,7 +76,7 @@ It is added to the main element, and it behaves like `title` attribute of any HT
76
76
 
77
77
  ```html
78
78
  <selectic
79
- options={['item1', 'item2', 'item3']}
79
+ :options="['item1', 'item2', 'item3']"
80
80
  title="An information about this component"
81
81
  />
82
82
  ```
@@ -91,7 +91,7 @@ Note that it will be applied to the inner list element too.
91
91
 
92
92
  ```html
93
93
  <selectic
94
- options={['item1', 'item2']}
94
+ :options="['item1', 'item2']"
95
95
  value="item2"
96
96
  className="my-custom-class another-class"
97
97
  />