slim-select 2.8.1 → 2.9.0

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.
Files changed (69) hide show
  1. package/.prettierignore +1 -0
  2. package/.prettierrc +4 -3
  3. package/README.md +2 -0
  4. package/dist/classes.d.ts +43 -0
  5. package/dist/helpers.d.ts +1 -1
  6. package/dist/index.d.ts +5 -2
  7. package/dist/render.d.ts +4 -44
  8. package/dist/select.d.ts +4 -2
  9. package/dist/settings.d.ts +2 -1
  10. package/dist/slimselect.cjs.js +248 -120
  11. package/dist/slimselect.css +1 -1
  12. package/dist/slimselect.css.map +1 -1
  13. package/dist/slimselect.es.js +248 -120
  14. package/dist/slimselect.global.js +248 -120
  15. package/dist/slimselect.js +248 -120
  16. package/dist/slimselect.min.js +1 -1
  17. package/dist/slimselect.umd.js +248 -120
  18. package/dist/slimselect.umd.min.js +1 -1
  19. package/dist/store.d.ts +4 -2
  20. package/index.html +1 -4
  21. package/jest.config.js +6 -0
  22. package/package.json +30 -41
  23. package/src/slim-select/classes.test.ts +72 -0
  24. package/src/slim-select/classes.ts +109 -0
  25. package/src/slim-select/helpers.test.ts +160 -0
  26. package/src/slim-select/helpers.ts +3 -12
  27. package/src/slim-select/index.test.ts +109 -16
  28. package/src/slim-select/index.ts +41 -12
  29. package/src/slim-select/render.test.ts +1169 -18
  30. package/src/slim-select/render.ts +75 -96
  31. package/src/slim-select/rollup.config.mjs +28 -28
  32. package/src/slim-select/select.test.ts +306 -156
  33. package/src/slim-select/select.ts +69 -20
  34. package/src/slim-select/settings.test.ts +257 -0
  35. package/src/slim-select/settings.ts +4 -0
  36. package/src/slim-select/slimselect.scss +7 -3
  37. package/src/slim-select/store.test.ts +986 -235
  38. package/src/slim-select/store.ts +70 -28
  39. package/src/{vue/slimselect.vue → slim-select/vue.vue} +19 -17
  40. package/tsconfig.json +2 -3
  41. package/src/react/.eslintignore +0 -2
  42. package/src/react/.eslintrc.cjs +0 -24
  43. package/src/react/index.html +0 -14
  44. package/src/react/jestconfig.json +0 -11
  45. package/src/react/package.json +0 -32
  46. package/src/react/src/frameworkpage.tsx +0 -133
  47. package/src/react/src/index.ts +0 -3
  48. package/src/react/src/slimselect.tsx +0 -148
  49. package/src/react/tests/slimselect.test.tsx +0 -52
  50. package/src/react/tsconfig.json +0 -37
  51. package/src/react/tsconfig.node.json +0 -10
  52. package/src/react/vite.config.ts +0 -55
  53. package/src/vue/README.md +0 -48
  54. package/src/vue/dist/slim-select/helpers.d.ts +0 -5
  55. package/src/vue/dist/slim-select/index.d.ts +0 -46
  56. package/src/vue/dist/slim-select/render.d.ts +0 -120
  57. package/src/vue/dist/slim-select/select.d.ts +0 -28
  58. package/src/vue/dist/slim-select/settings.d.ts +0 -34
  59. package/src/vue/dist/slim-select/store.d.ts +0 -80
  60. package/src/vue/dist/slimselectvue.es.js +0 -1978
  61. package/src/vue/dist/slimselectvue.global.js +0 -1981
  62. package/src/vue/dist/slimselectvue.ssr.js +0 -1980
  63. package/src/vue/dist/vue/hello.d.ts +0 -2
  64. package/src/vue/dist/vue/slimselect.vue.d.ts +0 -326
  65. package/src/vue/hello.ts +0 -5
  66. package/src/vue/package.json +0 -28
  67. package/src/vue/rollup.config.mjs +0 -44
  68. package/src/vue/tsconfig.json +0 -14
  69. /package/{vite.config.ts → vite.config.mts} +0 -0
@@ -4,6 +4,54 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.SlimSelect = factory());
5
5
  })(this, (function () { 'use strict';
6
6
 
7
+ class CssClasses {
8
+ constructor(classes) {
9
+ if (!classes) {
10
+ classes = {};
11
+ }
12
+ this.main = classes.main || 'ss-main';
13
+ this.placeholder = classes.placeholder || 'ss-placeholder';
14
+ this.values = classes.values || 'ss-values';
15
+ this.single = classes.single || 'ss-single';
16
+ this.max = classes.max || 'ss-max';
17
+ this.value = classes.value || 'ss-value';
18
+ this.valueText = classes.valueText || 'ss-value-text';
19
+ this.valueDelete = classes.valueDelete || 'ss-value-delete';
20
+ this.valueOut = classes.valueOut || 'ss-value-out';
21
+ this.deselect = classes.deselect || 'ss-deselect';
22
+ this.deselectPath = classes.deselectPath || 'M10,10 L90,90 M10,90 L90,10';
23
+ this.arrow = classes.arrow || 'ss-arrow';
24
+ this.arrowClose = classes.arrowClose || 'M10,30 L50,70 L90,30';
25
+ this.arrowOpen = classes.arrowOpen || 'M10,70 L50,30 L90,70';
26
+ this.content = classes.content || 'ss-content';
27
+ this.openAbove = classes.openAbove || 'ss-open-above';
28
+ this.openBelow = classes.openBelow || 'ss-open-below';
29
+ this.search = classes.search || 'ss-search';
30
+ this.searchHighlighter = classes.searchHighlighter || 'ss-search-highlight';
31
+ this.searching = classes.searching || 'ss-searching';
32
+ this.addable = classes.addable || 'ss-addable';
33
+ this.addablePath = classes.addablePath || 'M50,10 L50,90 M10,50 L90,50';
34
+ this.list = classes.list || 'ss-list';
35
+ this.optgroup = classes.optgroup || 'ss-optgroup';
36
+ this.optgroupLabel = classes.optgroupLabel || 'ss-optgroup-label';
37
+ this.optgroupLabelText = classes.optgroupLabelText || 'ss-optgroup-label-text';
38
+ this.optgroupActions = classes.optgroupActions || 'ss-optgroup-actions';
39
+ this.optgroupSelectAll = classes.optgroupSelectAll || 'ss-selectall';
40
+ this.optgroupSelectAllBox = classes.optgroupSelectAllBox || 'M60,10 L10,10 L10,90 L90,90 L90,50';
41
+ this.optgroupSelectAllCheck = classes.optgroupSelectAllCheck || 'M30,45 L50,70 L90,10';
42
+ this.optgroupClosable = classes.optgroupClosable || 'ss-closable';
43
+ this.option = classes.option || 'ss-option';
44
+ this.optionDelete = classes.optionDelete || 'M10,10 L90,90 M10,90 L90,10';
45
+ this.highlighted = classes.highlighted || 'ss-highlighted';
46
+ this.open = classes.open || 'ss-open';
47
+ this.close = classes.close || 'ss-close';
48
+ this.selected = classes.selected || 'ss-selected';
49
+ this.error = classes.error || 'ss-error';
50
+ this.disabled = classes.disabled || 'ss-disabled';
51
+ this.hide = classes.hide || 'ss-hide';
52
+ }
53
+ }
54
+
7
55
  function generateID() {
8
56
  return Math.random().toString(36).substring(2, 10);
9
57
  }
@@ -91,6 +139,7 @@
91
139
  constructor(type, data) {
92
140
  this.selectType = 'single';
93
141
  this.data = [];
142
+ this.selectedOrder = [];
94
143
  this.selectType = type;
95
144
  this.setData(data);
96
145
  }
@@ -105,12 +154,18 @@
105
154
  }
106
155
  if ('options' in dataObj && dataObj.options) {
107
156
  for (let option of dataObj.options) {
108
- return this.validateOption(option);
157
+ const validationError = this.validateOption(option);
158
+ if (validationError) {
159
+ return validationError;
160
+ }
109
161
  }
110
162
  }
111
163
  }
112
164
  else if (dataObj instanceof Option || 'text' in dataObj) {
113
- return this.validateOption(dataObj);
165
+ const validationError = this.validateOption(dataObj);
166
+ if (validationError) {
167
+ return validationError;
168
+ }
114
169
  }
115
170
  else {
116
171
  return new Error('Data object must be a valid optgroup or option');
@@ -147,7 +202,7 @@
147
202
  setData(data) {
148
203
  this.data = this.partialToFullData(data);
149
204
  if (this.selectType === 'single') {
150
- this.setSelectedBy('value', this.getSelected());
205
+ this.setSelectedBy('id', this.getSelected());
151
206
  }
152
207
  }
153
208
  getData() {
@@ -156,12 +211,19 @@
156
211
  getDataOptions() {
157
212
  return this.filter(null, false);
158
213
  }
159
- addOption(option) {
160
- this.setData(this.getData().concat(new Option(option)));
214
+ addOption(option, addToStart = false) {
215
+ if (addToStart) {
216
+ let data = [new Option(option)];
217
+ this.setData(data.concat(this.getData()));
218
+ }
219
+ else {
220
+ this.setData(this.getData().concat(new Option(option)));
221
+ }
161
222
  }
162
223
  setSelectedBy(selectedType, selectedValues) {
163
224
  let firstOption = null;
164
225
  let hasSelected = false;
226
+ const selectedObjects = [];
165
227
  for (let dataObj of this.data) {
166
228
  if (dataObj instanceof Optgroup) {
167
229
  for (let option of dataObj.options) {
@@ -169,8 +231,11 @@
169
231
  firstOption = option;
170
232
  }
171
233
  option.selected = hasSelected ? false : selectedValues.includes(option[selectedType]);
172
- if (option.selected && this.selectType === 'single') {
173
- hasSelected = true;
234
+ if (option.selected) {
235
+ selectedObjects.push(option);
236
+ if (this.selectType === 'single') {
237
+ hasSelected = true;
238
+ }
174
239
  }
175
240
  }
176
241
  }
@@ -179,36 +244,35 @@
179
244
  firstOption = dataObj;
180
245
  }
181
246
  dataObj.selected = hasSelected ? false : selectedValues.includes(dataObj[selectedType]);
182
- if (dataObj.selected && this.selectType === 'single') {
183
- hasSelected = true;
247
+ if (dataObj.selected) {
248
+ selectedObjects.push(dataObj);
249
+ if (this.selectType === 'single') {
250
+ hasSelected = true;
251
+ }
184
252
  }
185
253
  }
186
254
  }
187
255
  if (this.selectType === 'single' && firstOption && !hasSelected) {
188
256
  firstOption.selected = true;
257
+ selectedObjects.push(firstOption);
189
258
  }
259
+ const selectedIds = selectedValues.map((value) => {
260
+ var _a;
261
+ return ((_a = selectedObjects.find((option) => option[selectedType] === value)) === null || _a === void 0 ? void 0 : _a.id) || '';
262
+ });
263
+ this.selectedOrder = selectedIds;
190
264
  }
191
265
  getSelected() {
192
- let selectedOptions = this.getSelectedOptions();
193
- let selectedValues = [];
194
- selectedOptions.forEach((option) => {
195
- selectedValues.push(option.value);
196
- });
197
- return selectedValues;
266
+ return this.getSelectedOptions().map((option) => option.id);
267
+ }
268
+ getSelectedValues() {
269
+ return this.getSelectedOptions().map((option) => option.value);
198
270
  }
199
271
  getSelectedOptions() {
200
272
  return this.filter((opt) => {
201
273
  return opt.selected;
202
274
  }, false);
203
275
  }
204
- getSelectedIDs() {
205
- let selectedOptions = this.getSelectedOptions();
206
- let selectedIDs = [];
207
- selectedOptions.forEach((op) => {
208
- selectedIDs.push(op.id);
209
- });
210
- return selectedIDs;
211
- }
212
276
  getOptgroupByID(id) {
213
277
  for (let dataObj of this.data) {
214
278
  if (dataObj instanceof Optgroup && dataObj.id === id) {
@@ -279,54 +343,35 @@
279
343
  });
280
344
  return dataSearch;
281
345
  }
346
+ selectedOrderOptions(options) {
347
+ const newOrder = [];
348
+ this.selectedOrder.forEach((id) => {
349
+ const option = options.find((opt) => opt.id === id);
350
+ if (option) {
351
+ newOrder.push(option);
352
+ }
353
+ });
354
+ options.forEach((option) => {
355
+ let isIn = false;
356
+ newOrder.forEach((selectedOption) => {
357
+ if (option.id === selectedOption.id) {
358
+ isIn = true;
359
+ return;
360
+ }
361
+ });
362
+ if (!isIn) {
363
+ newOrder.push(option);
364
+ }
365
+ });
366
+ return newOrder;
367
+ }
282
368
  }
283
369
 
284
370
  class Render {
285
- constructor(settings, store, callbacks) {
286
- this.classes = {
287
- main: 'ss-main',
288
- placeholder: 'ss-placeholder',
289
- values: 'ss-values',
290
- single: 'ss-single',
291
- max: 'ss-max',
292
- value: 'ss-value',
293
- valueText: 'ss-value-text',
294
- valueDelete: 'ss-value-delete',
295
- valueOut: 'ss-value-out',
296
- deselect: 'ss-deselect',
297
- deselectPath: 'M10,10 L90,90 M10,90 L90,10',
298
- arrow: 'ss-arrow',
299
- arrowClose: 'M10,30 L50,70 L90,30',
300
- arrowOpen: 'M10,70 L50,30 L90,70',
301
- content: 'ss-content',
302
- openAbove: 'ss-open-above',
303
- openBelow: 'ss-open-below',
304
- search: 'ss-search',
305
- searchHighlighter: 'ss-search-highlight',
306
- searching: 'ss-searching',
307
- addable: 'ss-addable',
308
- addablePath: 'M50,10 L50,90 M10,50 L90,50',
309
- list: 'ss-list',
310
- optgroup: 'ss-optgroup',
311
- optgroupLabel: 'ss-optgroup-label',
312
- optgroupLabelText: 'ss-optgroup-label-text',
313
- optgroupActions: 'ss-optgroup-actions',
314
- optgroupSelectAll: 'ss-selectall',
315
- optgroupSelectAllBox: 'M60,10 L10,10 L10,90 L90,90 L90,50',
316
- optgroupSelectAllCheck: 'M30,45 L50,70 L90,10',
317
- optgroupClosable: 'ss-closable',
318
- option: 'ss-option',
319
- optionDelete: 'M10,10 L90,90 M10,90 L90,10',
320
- highlighted: 'ss-highlighted',
321
- open: 'ss-open',
322
- close: 'ss-close',
323
- selected: 'ss-selected',
324
- error: 'ss-error',
325
- disabled: 'ss-disabled',
326
- hide: 'ss-hide',
327
- };
371
+ constructor(settings, classes, store, callbacks) {
328
372
  this.store = store;
329
373
  this.settings = settings;
374
+ this.classes = classes;
330
375
  this.callbacks = callbacks;
331
376
  this.main = this.mainDiv();
332
377
  this.content = this.contentDiv();
@@ -422,7 +467,7 @@
422
467
  this.callbacks.close();
423
468
  return false;
424
469
  }
425
- return false;
470
+ return true;
426
471
  };
427
472
  main.onclick = (e) => {
428
473
  if (this.settings.disabled) {
@@ -460,8 +505,8 @@
460
505
  }
461
506
  else {
462
507
  const firstOption = this.store.getFirstOption();
463
- const value = firstOption ? firstOption.value : '';
464
- this.callbacks.setSelected(value, false);
508
+ const id = firstOption ? firstOption.id : '';
509
+ this.callbacks.setSelected(id, false);
465
510
  }
466
511
  if (this.settings.closeOnSelect) {
467
512
  this.callbacks.close();
@@ -494,12 +539,12 @@
494
539
  deselect: {
495
540
  main: deselect,
496
541
  svg: deselectSvg,
497
- path: deselectPath,
542
+ path: deselectPath
498
543
  },
499
544
  arrow: {
500
545
  main: arrow,
501
- path: arrowPath,
502
- },
546
+ path: arrowPath
547
+ }
503
548
  };
504
549
  }
505
550
  mainFocus(eventType) {
@@ -585,6 +630,9 @@
585
630
  maxValuesMessage.remove();
586
631
  }
587
632
  }
633
+ if (this.settings.keepOrder) {
634
+ selectedOptions = this.store.selectedOrderOptions(selectedOptions);
635
+ }
588
636
  let removeNodes = [];
589
637
  for (let i = 0; i < currentNodes.length; i++) {
590
638
  const node = currentNodes[i];
@@ -638,7 +686,7 @@
638
686
  value.dataset.id = option.id;
639
687
  const text = document.createElement('div');
640
688
  text.classList.add(this.classes.valueText);
641
- text.innerText = option.text;
689
+ text.textContent = option.text;
642
690
  value.appendChild(text);
643
691
  if (!option.mandatory) {
644
692
  const deleteDiv = document.createElement('div');
@@ -661,18 +709,18 @@
661
709
  shouldDelete = this.callbacks.beforeChange(after, before) === true;
662
710
  }
663
711
  if (shouldDelete) {
664
- let selectedValues = [];
712
+ let selectedIds = [];
665
713
  for (const o of after) {
666
714
  if (o instanceof Optgroup) {
667
715
  for (const c of o.options) {
668
- selectedValues.push(c.value);
716
+ selectedIds.push(c.id);
669
717
  }
670
718
  }
671
719
  if (o instanceof Option) {
672
- selectedValues.push(o.value);
720
+ selectedIds.push(o.id);
673
721
  }
674
722
  }
675
- this.callbacks.setSelected(selectedValues, false);
723
+ this.callbacks.setSelected(selectedIds, false);
676
724
  if (this.settings.closeOnSelect) {
677
725
  this.callbacks.close();
678
726
  }
@@ -702,7 +750,7 @@
702
750
  return {
703
751
  main: main,
704
752
  search: search,
705
- list: list,
753
+ list: list
706
754
  };
707
755
  }
708
756
  moveContent() {
@@ -732,7 +780,7 @@
732
780
  main.classList.add(this.classes.search);
733
781
  const searchReturn = {
734
782
  main,
735
- input,
783
+ input
736
784
  };
737
785
  if (!this.settings.showSearch) {
738
786
  main.classList.add(this.classes.hide);
@@ -760,9 +808,15 @@
760
808
  case 'Escape':
761
809
  this.callbacks.close();
762
810
  return false;
763
- case 'Enter':
764
811
  case ' ':
765
- if (this.callbacks.addable && e.ctrlKey) {
812
+ const highlighted = this.content.list.querySelector('.' + this.classes.highlighted);
813
+ if (highlighted) {
814
+ highlighted.click();
815
+ return false;
816
+ }
817
+ return true;
818
+ case 'Enter':
819
+ if (this.callbacks.addable) {
766
820
  addable.click();
767
821
  return false;
768
822
  }
@@ -801,12 +855,12 @@
801
855
  let newOption = new Option(oo);
802
856
  this.callbacks.addOption(newOption);
803
857
  if (this.settings.isMultiple) {
804
- let values = this.store.getSelected();
805
- values.push(newOption.value);
806
- this.callbacks.setSelected(values, true);
858
+ let ids = this.store.getSelected();
859
+ ids.push(newOption.id);
860
+ this.callbacks.setSelected(ids, true);
807
861
  }
808
862
  else {
809
- this.callbacks.setSelected([newOption.value], true);
863
+ this.callbacks.setSelected([newOption.id], true);
810
864
  }
811
865
  this.callbacks.search('');
812
866
  if (this.settings.closeOnSelect) {
@@ -824,9 +878,12 @@
824
878
  if (typeof value === 'string') {
825
879
  runFinish({
826
880
  text: value,
827
- value: value,
881
+ value: value
828
882
  });
829
883
  }
884
+ else if (addableValue instanceof Error) {
885
+ this.renderError(addableValue.message);
886
+ }
830
887
  else {
831
888
  runFinish(value);
832
889
  }
@@ -835,9 +892,12 @@
835
892
  else if (typeof addableValue === 'string') {
836
893
  runFinish({
837
894
  text: addableValue,
838
- value: addableValue,
895
+ value: addableValue
839
896
  });
840
897
  }
898
+ else if (addableValue instanceof Error) {
899
+ this.renderError(addableValue.message);
900
+ }
841
901
  else {
842
902
  runFinish(addableValue);
843
903
  }
@@ -847,7 +907,7 @@
847
907
  searchReturn.addable = {
848
908
  main: addable,
849
909
  svg: plus,
850
- path: plusPath,
910
+ path: plusPath
851
911
  };
852
912
  }
853
913
  return searchReturn;
@@ -944,10 +1004,26 @@
944
1004
  if (data.length === 0) {
945
1005
  const noResults = document.createElement('div');
946
1006
  noResults.classList.add(this.classes.search);
947
- noResults.innerHTML = this.settings.searchText;
1007
+ if (this.callbacks.addable) {
1008
+ noResults.innerHTML = this.settings.addableText.replace('{value}', this.content.search.input.value);
1009
+ }
1010
+ else {
1011
+ noResults.innerHTML = this.settings.searchText;
1012
+ }
948
1013
  this.content.list.appendChild(noResults);
949
1014
  return;
950
1015
  }
1016
+ if (this.settings.allowDeselect && !this.settings.isMultiple) {
1017
+ const placeholderOption = this.store.filter((o) => o.placeholder, false);
1018
+ if (!placeholderOption.length) {
1019
+ this.store.addOption(new Option({
1020
+ text: '',
1021
+ value: '',
1022
+ selected: false,
1023
+ placeholder: true
1024
+ }), true);
1025
+ }
1026
+ }
951
1027
  for (const d of data) {
952
1028
  if (d instanceof Optgroup) {
953
1029
  const optgroupEl = document.createElement('div');
@@ -994,7 +1070,7 @@
994
1070
  if (allSelected) {
995
1071
  const newSelected = currentSelected.filter((s) => {
996
1072
  for (const o of d.options) {
997
- if (s === o.value) {
1073
+ if (s === o.id) {
998
1074
  return false;
999
1075
  }
1000
1076
  }
@@ -1004,7 +1080,7 @@
1004
1080
  return;
1005
1081
  }
1006
1082
  else {
1007
- const newSelected = currentSelected.concat(d.options.map((o) => o.value));
1083
+ const newSelected = currentSelected.concat(d.options.map((o) => o.id));
1008
1084
  for (const o of d.options) {
1009
1085
  if (!this.store.getOptionByID(o.id)) {
1010
1086
  this.callbacks.addOption(o);
@@ -1161,7 +1237,7 @@
1161
1237
  if (!this.store.getOptionByID(elementID)) {
1162
1238
  this.callbacks.addOption(option);
1163
1239
  }
1164
- this.callbacks.setSelected(after.map((o) => o.value), false);
1240
+ this.callbacks.setSelected(after.map((o) => o.id), false);
1165
1241
  if (this.settings.closeOnSelect) {
1166
1242
  this.callbacks.close();
1167
1243
  }
@@ -1178,7 +1254,7 @@
1178
1254
  }
1179
1255
  highlightText(str, search, className) {
1180
1256
  let completedString = str;
1181
- const regex = new RegExp('(' + search.trim() + ')(?![^<]*>[^<>]*</)', 'i');
1257
+ const regex = new RegExp('(?![^<]*>)(' + search.trim() + ')(?![^<]*>[^<>]*</)', 'i');
1182
1258
  if (!str.match(regex)) {
1183
1259
  return str;
1184
1260
  }
@@ -1267,7 +1343,7 @@
1267
1343
  this.select = select;
1268
1344
  this.valueChange = this.valueChange.bind(this);
1269
1345
  this.select.addEventListener('change', this.valueChange, {
1270
- passive: true,
1346
+ passive: true
1271
1347
  });
1272
1348
  this.observer = new MutationObserver(this.observeCall.bind(this));
1273
1349
  this.changeListen(true);
@@ -1295,7 +1371,7 @@
1295
1371
  this.observer.observe(this.select, {
1296
1372
  subtree: true,
1297
1373
  childList: true,
1298
- attributes: true,
1374
+ attributes: true
1299
1375
  });
1300
1376
  }
1301
1377
  }
@@ -1307,7 +1383,7 @@
1307
1383
  }
1308
1384
  valueChange(ev) {
1309
1385
  if (this.listen && this.onValueChange) {
1310
- this.onValueChange(this.getSelectedValues());
1386
+ this.onValueChange(this.getSelectedOptions());
1311
1387
  }
1312
1388
  return true;
1313
1389
  }
@@ -1326,6 +1402,15 @@
1326
1402
  if (m.attributeName === 'class') {
1327
1403
  classChanged = true;
1328
1404
  }
1405
+ if (m.type === 'childList') {
1406
+ for (const n of m.addedNodes) {
1407
+ if (n.nodeName === 'OPTION' && n.value === this.select.value) {
1408
+ this.select.dispatchEvent(new Event('change'));
1409
+ break;
1410
+ }
1411
+ }
1412
+ optgroupOptionChanged = true;
1413
+ }
1329
1414
  }
1330
1415
  if (m.target.nodeName === 'OPTGROUP' || m.target.nodeName === 'OPTION') {
1331
1416
  optgroupOptionChanged = true;
@@ -1365,7 +1450,7 @@
1365
1450
  selectAll: optgroup.dataset ? optgroup.dataset.selectall === 'true' : false,
1366
1451
  selectAllText: optgroup.dataset ? optgroup.dataset.selectalltext : 'Select all',
1367
1452
  closable: optgroup.dataset ? optgroup.dataset.closable : 'off',
1368
- options: [],
1453
+ options: []
1369
1454
  };
1370
1455
  const options = optgroup.childNodes;
1371
1456
  for (const o of options) {
@@ -1382,26 +1467,26 @@
1382
1467
  text: option.text,
1383
1468
  html: option.dataset && option.dataset.html ? option.dataset.html : '',
1384
1469
  selected: option.selected,
1385
- display: option.style.display === 'none' ? false : true,
1470
+ display: option.style.display !== 'none',
1386
1471
  disabled: option.disabled,
1387
1472
  mandatory: option.dataset ? option.dataset.mandatory === 'true' : false,
1388
1473
  placeholder: option.dataset.placeholder === 'true',
1389
1474
  class: option.className,
1390
1475
  style: option.style.cssText,
1391
- data: option.dataset,
1476
+ data: option.dataset
1392
1477
  };
1393
1478
  }
1394
- getSelectedValues() {
1395
- let values = [];
1396
- const options = this.select.childNodes;
1397
- for (const o of options) {
1479
+ getSelectedOptions() {
1480
+ let options = [];
1481
+ const opts = this.select.childNodes;
1482
+ for (const o of opts) {
1398
1483
  if (o.nodeName === 'OPTGROUP') {
1399
1484
  const optgroupOptions = o.childNodes;
1400
1485
  for (const oo of optgroupOptions) {
1401
1486
  if (oo.nodeName === 'OPTION') {
1402
1487
  const option = oo;
1403
1488
  if (option.selected) {
1404
- values.push(option.value);
1489
+ options.push(this.getDataFromOption(option));
1405
1490
  }
1406
1491
  }
1407
1492
  }
@@ -1409,13 +1494,16 @@
1409
1494
  if (o.nodeName === 'OPTION') {
1410
1495
  const option = o;
1411
1496
  if (option.selected) {
1412
- values.push(option.value);
1497
+ options.push(this.getDataFromOption(option));
1413
1498
  }
1414
1499
  }
1415
1500
  }
1416
- return values;
1501
+ return options;
1417
1502
  }
1418
- setSelected(value) {
1503
+ getSelectedValues() {
1504
+ return this.getSelectedOptions().map((option) => option.value);
1505
+ }
1506
+ setSelected(ids) {
1419
1507
  this.changeListen(false);
1420
1508
  const options = this.select.childNodes;
1421
1509
  for (const o of options) {
@@ -1425,13 +1513,34 @@
1425
1513
  for (const oo of optgroupOptions) {
1426
1514
  if (oo.nodeName === 'OPTION') {
1427
1515
  const option = oo;
1428
- option.selected = value.includes(option.value);
1516
+ option.selected = ids.includes(option.id);
1429
1517
  }
1430
1518
  }
1431
1519
  }
1432
1520
  if (o.nodeName === 'OPTION') {
1433
1521
  const option = o;
1434
- option.selected = value.includes(option.value);
1522
+ option.selected = ids.includes(option.id);
1523
+ }
1524
+ }
1525
+ this.changeListen(true);
1526
+ }
1527
+ setSelectedByValue(values) {
1528
+ this.changeListen(false);
1529
+ const options = this.select.childNodes;
1530
+ for (const o of options) {
1531
+ if (o.nodeName === 'OPTGROUP') {
1532
+ const optgroup = o;
1533
+ const optgroupOptions = optgroup.childNodes;
1534
+ for (const oo of optgroupOptions) {
1535
+ if (oo.nodeName === 'OPTION') {
1536
+ const option = oo;
1537
+ option.selected = values.includes(option.value);
1538
+ }
1539
+ }
1540
+ }
1541
+ if (o.nodeName === 'OPTION') {
1542
+ const option = o;
1543
+ option.selected = values.includes(option.value);
1435
1544
  }
1436
1545
  }
1437
1546
  this.changeListen(true);
@@ -1465,7 +1574,7 @@
1465
1574
  this.select.appendChild(this.createOption(d));
1466
1575
  }
1467
1576
  }
1468
- this.select.dispatchEvent(new Event('change'));
1577
+ this.select.dispatchEvent(new Event('change', { bubbles: true }));
1469
1578
  this.changeListen(true);
1470
1579
  }
1471
1580
  createOptgroup(optgroup) {
@@ -1499,7 +1608,7 @@
1499
1608
  if (info.disabled) {
1500
1609
  optionEl.disabled = true;
1501
1610
  }
1502
- if (info.display === false) {
1611
+ if (!info.display) {
1503
1612
  optionEl.style.display = 'none';
1504
1613
  }
1505
1614
  if (info.placeholder) {
@@ -1550,6 +1659,7 @@
1550
1659
  this.disabled = settings.disabled !== undefined ? settings.disabled : false;
1551
1660
  this.alwaysOpen = settings.alwaysOpen !== undefined ? settings.alwaysOpen : false;
1552
1661
  this.showSearch = settings.showSearch !== undefined ? settings.showSearch : true;
1662
+ this.focusSearch = settings.focusSearch !== undefined ? settings.focusSearch : true;
1553
1663
  this.ariaLabel = settings.ariaLabel || 'Combobox';
1554
1664
  this.searchPlaceholder = settings.searchPlaceholder || 'Search';
1555
1665
  this.searchText = settings.searchText || 'No Results';
@@ -1569,6 +1679,7 @@
1569
1679
  this.timeoutDelay = settings.timeoutDelay || 200;
1570
1680
  this.maxValuesShown = settings.maxValuesShown || 20;
1571
1681
  this.maxValuesMessage = settings.maxValuesMessage || '{number} selected';
1682
+ this.addableText = settings.addableText || 'Press "Enter" to add {value}';
1572
1683
  }
1573
1684
  }
1574
1685
 
@@ -1586,7 +1697,7 @@
1586
1697
  beforeOpen: undefined,
1587
1698
  afterOpen: undefined,
1588
1699
  beforeClose: undefined,
1589
- afterClose: undefined,
1700
+ afterClose: undefined
1590
1701
  };
1591
1702
  this.windowResize = debounce(() => {
1592
1703
  if (!this.settings.isOpen && !this.settings.isFullOpen) {
@@ -1630,6 +1741,7 @@
1630
1741
  this.destroy();
1631
1742
  }
1632
1743
  this.settings = new Settings(config.settings);
1744
+ this.cssClasses = new CssClasses(config.cssClasses);
1633
1745
  const debounceEvents = ['afterChange', 'beforeOpen', 'afterOpen', 'beforeClose', 'afterClose'];
1634
1746
  for (const key in config.events) {
1635
1747
  if (!config.events.hasOwnProperty(key)) {
@@ -1649,8 +1761,8 @@
1649
1761
  this.select = new Select(this.selectEl);
1650
1762
  this.select.updateSelect(this.settings.id, this.settings.style, this.settings.class);
1651
1763
  this.select.hideUI();
1652
- this.select.onValueChange = (values) => {
1653
- this.setSelected(values);
1764
+ this.select.onValueChange = (options) => {
1765
+ this.setSelected(options.map((option) => option.id));
1654
1766
  };
1655
1767
  this.select.onClassChange = (classes) => {
1656
1768
  this.settings.class = classes;
@@ -1679,9 +1791,9 @@
1679
1791
  addOption: this.addOption.bind(this),
1680
1792
  search: this.search.bind(this),
1681
1793
  beforeChange: this.events.beforeChange,
1682
- afterChange: this.events.afterChange,
1794
+ afterChange: this.events.afterChange
1683
1795
  };
1684
- this.render = new Render(this.settings, this.store, renderCallbacks);
1796
+ this.render = new Render(this.settings, this.cssClasses, this.store, renderCallbacks);
1685
1797
  this.render.renderValues();
1686
1798
  this.render.renderOptions(this.store.getData());
1687
1799
  const selectAriaLabel = this.selectEl.getAttribute('aria-label');
@@ -1740,11 +1852,27 @@
1740
1852
  }
1741
1853
  }
1742
1854
  getSelected() {
1743
- return this.store.getSelected();
1855
+ let options = this.store.getSelectedOptions();
1856
+ if (this.settings.keepOrder) {
1857
+ options = this.store.selectedOrderOptions(options);
1858
+ }
1859
+ return options.map((option) => option.value);
1744
1860
  }
1745
- setSelected(value, runAfterChange = true) {
1861
+ setSelected(values, runAfterChange = true) {
1746
1862
  const selected = this.store.getSelected();
1747
- this.store.setSelectedBy('value', Array.isArray(value) ? value : [value]);
1863
+ const options = this.store.getDataOptions();
1864
+ values = Array.isArray(values) ? values : [values];
1865
+ const ids = [];
1866
+ for (const value of values) {
1867
+ if (options.find((option) => option.id == value)) {
1868
+ ids.push(value);
1869
+ continue;
1870
+ }
1871
+ for (const option of options.filter((option) => option.value == value)) {
1872
+ ids.push(option.id);
1873
+ }
1874
+ }
1875
+ this.store.setSelectedBy('id', ids);
1748
1876
  const data = this.store.getData();
1749
1877
  this.select.updateOptions(data);
1750
1878
  this.render.renderValues();
@@ -1779,7 +1907,7 @@
1779
1907
  this.events.beforeOpen();
1780
1908
  }
1781
1909
  this.render.open();
1782
- if (this.settings.showSearch) {
1910
+ if (this.settings.showSearch && this.settings.focusSearch) {
1783
1911
  this.render.searchFocus();
1784
1912
  }
1785
1913
  this.settings.isOpen = true;