slim-select 2.13.1 → 3.0.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 (55) hide show
  1. package/README.md +184 -43
  2. package/dist/index.d.ts +304 -52
  3. package/dist/react/index.d.ts +304 -0
  4. package/dist/react/index.js +1549 -0
  5. package/dist/react/index.umd.js +22 -0
  6. package/dist/slimselect.cjs.js +1 -2030
  7. package/dist/slimselect.css +1 -1
  8. package/dist/slimselect.css.map +1 -1
  9. package/dist/slimselect.es.js +1224 -2012
  10. package/dist/slimselect.umd.js +1 -2036
  11. package/dist/vue/index.d.ts +304 -0
  12. package/dist/vue/index.js +1341 -0
  13. package/dist/vue/index.umd.js +1 -0
  14. package/index.html +1 -0
  15. package/package.json +58 -36
  16. package/release.js +0 -7
  17. package/src/slim-select/accessibility.test.ts +782 -0
  18. package/src/slim-select/classes.test.ts +7 -6
  19. package/src/slim-select/classes.ts +8 -6
  20. package/src/slim-select/helpers.test.ts +10 -8
  21. package/src/slim-select/index.test.ts +509 -14
  22. package/src/slim-select/index.ts +58 -31
  23. package/src/slim-select/react/index.tsx +9 -0
  24. package/src/slim-select/react/react.tsx +112 -0
  25. package/src/slim-select/render.test.ts +479 -119
  26. package/src/slim-select/render.ts +213 -91
  27. package/src/slim-select/select.test.ts +28 -10
  28. package/src/slim-select/select.ts +35 -12
  29. package/src/slim-select/settings.test.ts +19 -8
  30. package/src/slim-select/settings.ts +2 -4
  31. package/src/slim-select/slimselect.scss +30 -15
  32. package/src/slim-select/store.test.ts +13 -16
  33. package/src/slim-select/store.ts +97 -86
  34. package/src/slim-select/vue/index.ts +9 -0
  35. package/src/slim-select/vue/vue.test.ts +832 -0
  36. package/src/slim-select/{vue.vue → vue/vue.vue} +45 -23
  37. package/tsconfig.json +6 -4
  38. package/{vite.config.mts → vite.config.docs.mts} +10 -0
  39. package/vite.config.lib.mts +42 -0
  40. package/vite.config.react.mts +40 -0
  41. package/vite.config.vue.mts +39 -0
  42. package/vitest.config.ts +29 -0
  43. package/dist/classes.d.ts +0 -43
  44. package/dist/helpers.d.ts +0 -5
  45. package/dist/render.d.ts +0 -81
  46. package/dist/select.d.ts +0 -30
  47. package/dist/settings.d.ts +0 -35
  48. package/dist/slimselect.global.js +0 -2033
  49. package/dist/slimselect.js +0 -2036
  50. package/dist/slimselect.min.js +0 -1
  51. package/dist/slimselect.umd.min.js +0 -1
  52. package/dist/store.d.ts +0 -84
  53. package/jest.config.js +0 -14
  54. package/src/slim-select/rollup.config.mjs +0 -127
  55. package/src/slim-select/tsconfig.json +0 -14
@@ -1,2036 +0,0 @@
1
- (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3
- typeof define === 'function' && define.amd ? define(factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.SlimSelect = factory());
5
- })(this, (function () { 'use strict';
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
-
55
- function generateID() {
56
- return Math.random().toString(36).substring(2, 10);
57
- }
58
- function hasClassInTree(element, className) {
59
- function hasClass(e, c) {
60
- if (c && e && e.classList && e.classList.contains(c)) {
61
- return e;
62
- }
63
- if (c && e && e.dataset && e.dataset.id && e.dataset.id === className) {
64
- return e;
65
- }
66
- return null;
67
- }
68
- function parentByClass(e, c) {
69
- if (!e || e === document) {
70
- return null;
71
- }
72
- else if (hasClass(e, c)) {
73
- return e;
74
- }
75
- else {
76
- return parentByClass(e.parentNode, c);
77
- }
78
- }
79
- return hasClass(element, className) || parentByClass(element, className);
80
- }
81
- function debounce(func, wait = 50, immediate = false) {
82
- let timeout;
83
- return function (...args) {
84
- const context = self;
85
- const later = () => {
86
- timeout = null;
87
- if (!immediate) {
88
- func.apply(context, args);
89
- }
90
- };
91
- const callNow = immediate && !timeout;
92
- clearTimeout(timeout);
93
- timeout = setTimeout(later, wait);
94
- if (callNow) {
95
- func.apply(context, args);
96
- }
97
- };
98
- }
99
- function isEqual(a, b) {
100
- return JSON.stringify(a) === JSON.stringify(b);
101
- }
102
- function kebabCase(str) {
103
- const result = str.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g, (match) => '-' + match.toLowerCase());
104
- return str[0] === str[0].toUpperCase() ? result.substring(1) : result;
105
- }
106
-
107
- class Optgroup {
108
- constructor(optgroup) {
109
- this.id = !optgroup.id || optgroup.id === '' ? generateID() : optgroup.id;
110
- this.label = optgroup.label || '';
111
- this.selectAll = optgroup.selectAll === undefined ? false : optgroup.selectAll;
112
- this.selectAllText = optgroup.selectAllText || 'Select All';
113
- this.closable = optgroup.closable || 'off';
114
- this.options = [];
115
- if (optgroup.options) {
116
- for (const o of optgroup.options) {
117
- this.options.push(new Option(o));
118
- }
119
- }
120
- }
121
- }
122
- class Option {
123
- constructor(option) {
124
- this.id = !option.id || option.id === '' ? generateID() : option.id;
125
- this.value = option.value === undefined ? option.text : option.value;
126
- this.text = option.text || '';
127
- this.html = option.html || '';
128
- this.defaultSelected = option.defaultSelected !== undefined ? option.defaultSelected : false;
129
- this.selected = option.selected !== undefined ? option.selected : false;
130
- this.display = option.display !== undefined ? option.display : true;
131
- this.disabled = option.disabled !== undefined ? option.disabled : false;
132
- this.mandatory = option.mandatory !== undefined ? option.mandatory : false;
133
- this.placeholder = option.placeholder !== undefined ? option.placeholder : false;
134
- this.class = option.class || '';
135
- this.style = option.style || '';
136
- this.data = option.data || {};
137
- }
138
- }
139
- class Store {
140
- constructor(type, data) {
141
- this.selectType = 'single';
142
- this.data = [];
143
- this.selectedOrder = [];
144
- this.selectType = type;
145
- this.setData(data);
146
- }
147
- validateDataArray(data) {
148
- if (!Array.isArray(data)) {
149
- return new Error('Data must be an array');
150
- }
151
- for (let dataObj of data) {
152
- if (dataObj instanceof Optgroup || 'label' in dataObj) {
153
- if (!('label' in dataObj)) {
154
- return new Error('Optgroup must have a label');
155
- }
156
- if ('options' in dataObj && dataObj.options) {
157
- for (let option of dataObj.options) {
158
- const validationError = this.validateOption(option);
159
- if (validationError) {
160
- return validationError;
161
- }
162
- }
163
- }
164
- }
165
- else if (dataObj instanceof Option || 'text' in dataObj) {
166
- const validationError = this.validateOption(dataObj);
167
- if (validationError) {
168
- return validationError;
169
- }
170
- }
171
- else {
172
- return new Error('Data object must be a valid optgroup or option');
173
- }
174
- }
175
- return null;
176
- }
177
- validateOption(option) {
178
- if (!('text' in option)) {
179
- return new Error('Option must have a text');
180
- }
181
- return null;
182
- }
183
- partialToFullData(data) {
184
- let dataFinal = [];
185
- data.forEach((dataObj) => {
186
- if (dataObj instanceof Optgroup || 'label' in dataObj) {
187
- let optOptions = [];
188
- if ('options' in dataObj && dataObj.options) {
189
- dataObj.options.forEach((option) => {
190
- optOptions.push(new Option(option));
191
- });
192
- }
193
- if (optOptions.length > 0) {
194
- dataFinal.push(new Optgroup(dataObj));
195
- }
196
- }
197
- if (dataObj instanceof Option || 'text' in dataObj) {
198
- dataFinal.push(new Option(dataObj));
199
- }
200
- });
201
- return dataFinal;
202
- }
203
- setData(data) {
204
- this.data = this.partialToFullData(data);
205
- if (this.selectType === 'single') {
206
- this.setSelectedBy('id', this.getSelected());
207
- }
208
- }
209
- getData() {
210
- return this.filter(null, true);
211
- }
212
- getDataOptions() {
213
- return this.filter(null, false);
214
- }
215
- addOption(option, addToStart = false) {
216
- if (addToStart) {
217
- let data = [new Option(option)];
218
- this.setData(data.concat(this.getData()));
219
- }
220
- else {
221
- this.setData(this.getData().concat(new Option(option)));
222
- }
223
- }
224
- setSelectedBy(selectedType, selectedValues) {
225
- let firstOption = null;
226
- let hasSelected = false;
227
- const selectedObjects = [];
228
- for (let dataObj of this.data) {
229
- if (dataObj instanceof Optgroup) {
230
- for (let option of dataObj.options) {
231
- if (!firstOption) {
232
- firstOption = option;
233
- }
234
- option.selected = hasSelected ? false : selectedValues.includes(option[selectedType]);
235
- if (option.selected) {
236
- selectedObjects.push(option);
237
- if (this.selectType === 'single') {
238
- hasSelected = true;
239
- }
240
- }
241
- }
242
- }
243
- if (dataObj instanceof Option) {
244
- if (!firstOption) {
245
- firstOption = dataObj;
246
- }
247
- dataObj.selected = hasSelected ? false : selectedValues.includes(dataObj[selectedType]);
248
- if (dataObj.selected) {
249
- selectedObjects.push(dataObj);
250
- if (this.selectType === 'single') {
251
- hasSelected = true;
252
- }
253
- }
254
- }
255
- }
256
- if (this.selectType === 'single' && firstOption && !hasSelected) {
257
- firstOption.selected = true;
258
- selectedObjects.push(firstOption);
259
- }
260
- const selectedIds = selectedValues.map((value) => {
261
- var _a;
262
- return ((_a = selectedObjects.find((option) => option[selectedType] === value)) === null || _a === void 0 ? void 0 : _a.id) || '';
263
- });
264
- this.selectedOrder = selectedIds;
265
- }
266
- getSelected() {
267
- return this.getSelectedOptions().map((option) => option.id);
268
- }
269
- getSelectedValues() {
270
- return this.getSelectedOptions().map((option) => option.value);
271
- }
272
- getSelectedOptions() {
273
- return this.filter((opt) => {
274
- return opt.selected;
275
- }, false);
276
- }
277
- getOptgroupByID(id) {
278
- for (let dataObj of this.data) {
279
- if (dataObj instanceof Optgroup && dataObj.id === id) {
280
- return dataObj;
281
- }
282
- }
283
- return null;
284
- }
285
- getOptionByID(id) {
286
- let options = this.filter((opt) => {
287
- return opt.id === id;
288
- }, false);
289
- return options.length ? options[0] : null;
290
- }
291
- getSelectType() {
292
- return this.selectType;
293
- }
294
- getFirstOption() {
295
- let option = null;
296
- for (let dataObj of this.data) {
297
- if (dataObj instanceof Optgroup) {
298
- option = dataObj.options[0];
299
- }
300
- else if (dataObj instanceof Option) {
301
- option = dataObj;
302
- }
303
- if (option) {
304
- break;
305
- }
306
- }
307
- return option;
308
- }
309
- search(search, searchFilter) {
310
- search = search.trim();
311
- if (search === '') {
312
- return this.getData();
313
- }
314
- return this.filter((opt) => {
315
- return searchFilter(opt, search);
316
- }, true);
317
- }
318
- filter(filter, includeOptgroup) {
319
- const dataSearch = [];
320
- this.data.forEach((dataObj) => {
321
- if (dataObj instanceof Optgroup) {
322
- let optOptions = [];
323
- dataObj.options.forEach((option) => {
324
- if (!filter || filter(option)) {
325
- if (!includeOptgroup) {
326
- dataSearch.push(new Option(option));
327
- }
328
- else {
329
- optOptions.push(new Option(option));
330
- }
331
- }
332
- });
333
- if (optOptions.length > 0) {
334
- let optgroup = new Optgroup(dataObj);
335
- optgroup.options = optOptions;
336
- dataSearch.push(optgroup);
337
- }
338
- }
339
- if (dataObj instanceof Option) {
340
- if (!filter || filter(dataObj)) {
341
- dataSearch.push(new Option(dataObj));
342
- }
343
- }
344
- });
345
- return dataSearch;
346
- }
347
- selectedOrderOptions(options) {
348
- const newOrder = [];
349
- this.selectedOrder.forEach((id) => {
350
- const option = options.find((opt) => opt.id === id);
351
- if (option) {
352
- newOrder.push(option);
353
- }
354
- });
355
- options.forEach((option) => {
356
- let isIn = false;
357
- newOrder.forEach((selectedOption) => {
358
- if (option.id === selectedOption.id) {
359
- isIn = true;
360
- return;
361
- }
362
- });
363
- if (!isIn) {
364
- newOrder.push(option);
365
- }
366
- });
367
- return newOrder;
368
- }
369
- }
370
-
371
- class Render {
372
- constructor(settings, classes, store, callbacks) {
373
- this.store = store;
374
- this.settings = settings;
375
- this.classes = classes;
376
- this.callbacks = callbacks;
377
- this.lastSelectedOption = null;
378
- this.main = this.mainDiv();
379
- this.content = this.contentDiv();
380
- this.updateClassStyles();
381
- this.updateAriaAttributes();
382
- if (this.settings.contentLocation) {
383
- this.settings.contentLocation.appendChild(this.content.main);
384
- }
385
- }
386
- enable() {
387
- this.main.main.classList.remove(this.classes.disabled);
388
- this.content.search.input.disabled = false;
389
- }
390
- disable() {
391
- this.main.main.classList.add(this.classes.disabled);
392
- this.content.search.input.disabled = true;
393
- }
394
- open() {
395
- this.main.arrow.path.setAttribute('d', this.classes.arrowOpen);
396
- this.main.main.classList.add(this.settings.openPosition === 'up' ? this.classes.openAbove : this.classes.openBelow);
397
- this.main.main.setAttribute('aria-expanded', 'true');
398
- this.moveContent();
399
- const selectedOptions = this.store.getSelectedOptions();
400
- if (selectedOptions.length) {
401
- const selectedId = selectedOptions[selectedOptions.length - 1].id;
402
- const selectedOption = this.content.list.querySelector('[data-id="' + selectedId + '"]');
403
- if (selectedOption) {
404
- this.ensureElementInView(this.content.list, selectedOption);
405
- }
406
- }
407
- }
408
- close() {
409
- this.main.main.classList.remove(this.classes.openAbove);
410
- this.main.main.classList.remove(this.classes.openBelow);
411
- this.main.main.setAttribute('aria-expanded', 'false');
412
- this.content.main.classList.remove(this.classes.openAbove);
413
- this.content.main.classList.remove(this.classes.openBelow);
414
- this.main.arrow.path.setAttribute('d', this.classes.arrowClose);
415
- }
416
- updateClassStyles() {
417
- this.main.main.className = '';
418
- this.main.main.removeAttribute('style');
419
- this.content.main.className = '';
420
- this.content.main.removeAttribute('style');
421
- this.main.main.classList.add(this.classes.main);
422
- this.content.main.classList.add(this.classes.content);
423
- if (this.settings.style !== '') {
424
- this.main.main.style.cssText = this.settings.style;
425
- this.content.main.style.cssText = this.settings.style;
426
- }
427
- if (this.settings.class.length) {
428
- for (const c of this.settings.class) {
429
- if (c.trim() !== '') {
430
- this.main.main.classList.add(c.trim());
431
- this.content.main.classList.add(c.trim());
432
- }
433
- }
434
- }
435
- if (this.settings.contentPosition === 'relative' || this.settings.contentPosition === 'fixed') {
436
- this.content.main.classList.add('ss-' + this.settings.contentPosition);
437
- }
438
- }
439
- updateAriaAttributes() {
440
- var _a;
441
- this.main.main.role = 'combobox';
442
- this.main.main.setAttribute('aria-haspopup', 'listbox');
443
- this.main.main.setAttribute('aria-controls', (_a = this.content.main.dataset.id) !== null && _a !== void 0 ? _a : '');
444
- this.main.main.setAttribute('aria-expanded', 'false');
445
- this.content.main.setAttribute('role', 'listbox');
446
- }
447
- mainDiv() {
448
- var _a;
449
- const main = document.createElement('div');
450
- main.dataset.id = this.settings.id;
451
- main.setAttribute('aria-label', this.settings.ariaLabel);
452
- main.tabIndex = 0;
453
- main.onkeydown = (e) => {
454
- switch (e.key) {
455
- case 'ArrowUp':
456
- case 'ArrowDown':
457
- this.callbacks.open();
458
- e.key === 'ArrowDown' ? this.highlight('down') : this.highlight('up');
459
- return false;
460
- case 'Tab':
461
- this.callbacks.close();
462
- return true;
463
- case 'Enter':
464
- case ' ':
465
- this.callbacks.open();
466
- const highlighted = this.content.list.querySelector('.' + this.classes.highlighted);
467
- if (highlighted) {
468
- highlighted.click();
469
- }
470
- return false;
471
- case 'Escape':
472
- this.callbacks.close();
473
- return false;
474
- }
475
- if (e.key.length === 1) {
476
- this.callbacks.open();
477
- }
478
- return true;
479
- };
480
- main.onclick = (e) => {
481
- if (this.settings.disabled) {
482
- return;
483
- }
484
- this.settings.isOpen ? this.callbacks.close() : this.callbacks.open();
485
- };
486
- const values = document.createElement('div');
487
- values.classList.add(this.classes.values);
488
- main.appendChild(values);
489
- const deselect = document.createElement('div');
490
- deselect.classList.add(this.classes.deselect);
491
- const selectedOptions = (_a = this.store) === null || _a === void 0 ? void 0 : _a.getSelectedOptions();
492
- if (!this.settings.allowDeselect || (this.settings.isMultiple && selectedOptions && selectedOptions.length <= 0)) {
493
- deselect.classList.add(this.classes.hide);
494
- }
495
- else {
496
- deselect.classList.remove(this.classes.hide);
497
- }
498
- deselect.onclick = (e) => {
499
- e.stopPropagation();
500
- if (this.settings.disabled) {
501
- return;
502
- }
503
- let shouldDelete = true;
504
- const before = this.store.getSelectedOptions();
505
- const after = [];
506
- if (this.callbacks.beforeChange) {
507
- shouldDelete = this.callbacks.beforeChange(after, before) === true;
508
- }
509
- if (shouldDelete) {
510
- if (this.settings.isMultiple) {
511
- this.callbacks.setSelected([], false);
512
- this.updateDeselectAll();
513
- }
514
- else {
515
- const firstOption = this.store.getFirstOption();
516
- const id = firstOption ? firstOption.id : '';
517
- this.callbacks.setSelected(id, false);
518
- }
519
- if (this.settings.closeOnSelect) {
520
- this.callbacks.close();
521
- }
522
- if (this.callbacks.afterChange) {
523
- this.callbacks.afterChange(this.store.getSelectedOptions());
524
- }
525
- }
526
- };
527
- const deselectSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
528
- deselectSvg.setAttribute('viewBox', '0 0 100 100');
529
- const deselectPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
530
- deselectPath.setAttribute('d', this.classes.deselectPath);
531
- deselectSvg.appendChild(deselectPath);
532
- deselect.appendChild(deselectSvg);
533
- main.appendChild(deselect);
534
- const arrow = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
535
- arrow.classList.add(this.classes.arrow);
536
- arrow.setAttribute('viewBox', '0 0 100 100');
537
- const arrowPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
538
- arrowPath.setAttribute('d', this.classes.arrowClose);
539
- if (this.settings.alwaysOpen) {
540
- arrow.classList.add(this.classes.hide);
541
- }
542
- arrow.appendChild(arrowPath);
543
- main.appendChild(arrow);
544
- return {
545
- main: main,
546
- values: values,
547
- deselect: {
548
- main: deselect,
549
- svg: deselectSvg,
550
- path: deselectPath
551
- },
552
- arrow: {
553
- main: arrow,
554
- path: arrowPath
555
- }
556
- };
557
- }
558
- mainFocus(eventType) {
559
- if (eventType !== 'click') {
560
- this.main.main.focus({ preventScroll: true });
561
- }
562
- }
563
- placeholder() {
564
- const placeholderOption = this.store.filter((o) => o.placeholder, false);
565
- let placeholderText = this.settings.placeholderText;
566
- if (placeholderOption.length) {
567
- if (placeholderOption[0].html !== '') {
568
- placeholderText = placeholderOption[0].html;
569
- }
570
- else if (placeholderOption[0].text !== '') {
571
- placeholderText = placeholderOption[0].text;
572
- }
573
- }
574
- const placeholder = document.createElement('div');
575
- placeholder.classList.add(this.classes.placeholder);
576
- placeholder.innerHTML = placeholderText;
577
- return placeholder;
578
- }
579
- renderValues() {
580
- if (!this.settings.isMultiple) {
581
- this.renderSingleValue();
582
- return;
583
- }
584
- this.renderMultipleValues();
585
- this.updateDeselectAll();
586
- }
587
- renderSingleValue() {
588
- const selected = this.store.filter((o) => {
589
- return o.selected && !o.placeholder;
590
- }, false);
591
- const selectedSingle = selected.length > 0 ? selected[0] : null;
592
- if (!selectedSingle) {
593
- this.main.values.innerHTML = this.placeholder().outerHTML;
594
- }
595
- else {
596
- const singleValue = document.createElement('div');
597
- singleValue.classList.add(this.classes.single);
598
- if (selectedSingle.html) {
599
- singleValue.innerHTML = selectedSingle.html;
600
- }
601
- else {
602
- singleValue.innerText = selectedSingle.text;
603
- }
604
- this.main.values.innerHTML = singleValue.outerHTML;
605
- }
606
- if (!this.settings.allowDeselect || !selected.length) {
607
- this.main.deselect.main.classList.add(this.classes.hide);
608
- }
609
- else {
610
- this.main.deselect.main.classList.remove(this.classes.hide);
611
- }
612
- }
613
- renderMultipleValues() {
614
- let currentNodes = this.main.values.childNodes;
615
- let selectedOptions = this.store.filter((opt) => {
616
- return opt.selected && opt.display;
617
- }, false);
618
- if (selectedOptions.length === 0) {
619
- this.main.values.innerHTML = this.placeholder().outerHTML;
620
- return;
621
- }
622
- else {
623
- const placeholder = this.main.values.querySelector('.' + this.classes.placeholder);
624
- if (placeholder) {
625
- placeholder.remove();
626
- }
627
- }
628
- if (selectedOptions.length > this.settings.maxValuesShown) {
629
- const singleValue = document.createElement('div');
630
- singleValue.classList.add(this.classes.max);
631
- singleValue.textContent = this.settings.maxValuesMessage.replace('{number}', selectedOptions.length.toString());
632
- this.main.values.innerHTML = singleValue.outerHTML;
633
- return;
634
- }
635
- else {
636
- const maxValuesMessage = this.main.values.querySelector('.' + this.classes.max);
637
- if (maxValuesMessage) {
638
- maxValuesMessage.remove();
639
- }
640
- }
641
- if (this.settings.keepOrder) {
642
- selectedOptions = this.store.selectedOrderOptions(selectedOptions);
643
- }
644
- let removeNodes = [];
645
- for (let i = 0; i < currentNodes.length; i++) {
646
- const node = currentNodes[i];
647
- const id = node.getAttribute('data-id');
648
- if (id) {
649
- const found = selectedOptions.filter((opt) => {
650
- return opt.id === id;
651
- }, false);
652
- if (!found.length) {
653
- removeNodes.push(node);
654
- }
655
- }
656
- }
657
- for (const n of removeNodes) {
658
- n.classList.add(this.classes.valueOut);
659
- setTimeout(() => {
660
- if (this.main.values.hasChildNodes() && this.main.values.contains(n)) {
661
- this.main.values.removeChild(n);
662
- }
663
- }, 100);
664
- }
665
- currentNodes = this.main.values.childNodes;
666
- for (let d = 0; d < selectedOptions.length; d++) {
667
- let shouldAdd = true;
668
- for (let i = 0; i < currentNodes.length; i++) {
669
- if (selectedOptions[d].id === String(currentNodes[i].dataset.id)) {
670
- shouldAdd = false;
671
- }
672
- }
673
- if (shouldAdd) {
674
- if (this.settings.keepOrder) {
675
- this.main.values.appendChild(this.multipleValue(selectedOptions[d]));
676
- }
677
- else {
678
- if (currentNodes.length === 0) {
679
- this.main.values.appendChild(this.multipleValue(selectedOptions[d]));
680
- }
681
- else if (d === 0) {
682
- this.main.values.insertBefore(this.multipleValue(selectedOptions[d]), currentNodes[d]);
683
- }
684
- else {
685
- currentNodes[d - 1].insertAdjacentElement('afterend', this.multipleValue(selectedOptions[d]));
686
- }
687
- }
688
- }
689
- }
690
- }
691
- multipleValue(option) {
692
- const value = document.createElement('div');
693
- value.classList.add(this.classes.value);
694
- value.dataset.id = option.id;
695
- const text = document.createElement('div');
696
- text.classList.add(this.classes.valueText);
697
- text.textContent = option.text;
698
- value.appendChild(text);
699
- if (!option.mandatory) {
700
- const deleteDiv = document.createElement('div');
701
- deleteDiv.classList.add(this.classes.valueDelete);
702
- deleteDiv.setAttribute('tabindex', '0');
703
- deleteDiv.onclick = (e) => {
704
- e.preventDefault();
705
- e.stopPropagation();
706
- if (this.settings.disabled) {
707
- return;
708
- }
709
- let shouldDelete = true;
710
- const before = this.store.getSelectedOptions();
711
- const after = before.filter((o) => {
712
- return o.selected && o.id !== option.id;
713
- }, true);
714
- if (this.settings.minSelected && after.length < this.settings.minSelected) {
715
- return;
716
- }
717
- if (this.callbacks.beforeChange) {
718
- shouldDelete = this.callbacks.beforeChange(after, before) === true;
719
- }
720
- if (shouldDelete) {
721
- let selectedIds = [];
722
- for (const o of after) {
723
- if (o instanceof Optgroup) {
724
- for (const c of o.options) {
725
- selectedIds.push(c.id);
726
- }
727
- }
728
- if (o instanceof Option) {
729
- selectedIds.push(o.id);
730
- }
731
- }
732
- this.callbacks.setSelected(selectedIds, false);
733
- if (this.settings.closeOnSelect) {
734
- this.callbacks.close();
735
- }
736
- if (this.callbacks.afterChange) {
737
- this.callbacks.afterChange(after);
738
- }
739
- this.updateDeselectAll();
740
- }
741
- };
742
- const deleteSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
743
- deleteSvg.setAttribute('viewBox', '0 0 100 100');
744
- const deletePath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
745
- deletePath.setAttribute('d', this.classes.optionDelete);
746
- deleteSvg.appendChild(deletePath);
747
- deleteDiv.appendChild(deleteSvg);
748
- value.appendChild(deleteDiv);
749
- deleteDiv.onkeydown = (e) => {
750
- if (e.key === 'Enter') {
751
- deleteDiv.click();
752
- }
753
- };
754
- }
755
- return value;
756
- }
757
- contentDiv() {
758
- const main = document.createElement('div');
759
- main.dataset.id = this.settings.id;
760
- const search = this.searchDiv();
761
- main.appendChild(search.main);
762
- const list = this.listDiv();
763
- main.appendChild(list);
764
- return {
765
- main: main,
766
- search: search,
767
- list: list
768
- };
769
- }
770
- moveContent() {
771
- if (this.settings.contentPosition === 'relative') {
772
- this.moveContentBelow();
773
- return;
774
- }
775
- if (this.settings.openPosition === 'down') {
776
- this.moveContentBelow();
777
- return;
778
- }
779
- else if (this.settings.openPosition === 'up') {
780
- this.moveContentAbove();
781
- return;
782
- }
783
- if (this.putContent() === 'up') {
784
- this.moveContentAbove();
785
- }
786
- else {
787
- this.moveContentBelow();
788
- }
789
- }
790
- searchDiv() {
791
- const main = document.createElement('div');
792
- const input = document.createElement('input');
793
- const addable = document.createElement('div');
794
- main.classList.add(this.classes.search);
795
- const searchReturn = {
796
- main,
797
- input
798
- };
799
- if (!this.settings.showSearch) {
800
- main.classList.add(this.classes.hide);
801
- input.readOnly = true;
802
- }
803
- input.type = 'search';
804
- input.placeholder = this.settings.searchPlaceholder;
805
- input.tabIndex = -1;
806
- input.setAttribute('aria-label', this.settings.searchPlaceholder);
807
- input.setAttribute('autocapitalize', 'off');
808
- input.setAttribute('autocomplete', 'off');
809
- input.setAttribute('autocorrect', 'off');
810
- input.oninput = debounce((e) => {
811
- this.callbacks.search(e.target.value);
812
- }, 100);
813
- input.onkeydown = (e) => {
814
- switch (e.key) {
815
- case 'ArrowUp':
816
- case 'ArrowDown':
817
- e.key === 'ArrowDown' ? this.highlight('down') : this.highlight('up');
818
- return false;
819
- case 'Tab':
820
- this.callbacks.close();
821
- return true;
822
- case 'Escape':
823
- this.callbacks.close();
824
- return false;
825
- case ' ':
826
- const highlighted = this.content.list.querySelector('.' + this.classes.highlighted);
827
- if (highlighted) {
828
- highlighted.click();
829
- return false;
830
- }
831
- return true;
832
- case 'Enter':
833
- if (this.callbacks.addable) {
834
- addable.click();
835
- return false;
836
- }
837
- else {
838
- const highlighted = this.content.list.querySelector('.' + this.classes.highlighted);
839
- if (highlighted) {
840
- highlighted.click();
841
- return false;
842
- }
843
- }
844
- return true;
845
- }
846
- return true;
847
- };
848
- main.appendChild(input);
849
- if (this.callbacks.addable) {
850
- addable.classList.add(this.classes.addable);
851
- const plus = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
852
- plus.setAttribute('viewBox', '0 0 100 100');
853
- const plusPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
854
- plusPath.setAttribute('d', this.classes.addablePath);
855
- plus.appendChild(plusPath);
856
- addable.appendChild(plus);
857
- addable.onclick = (e) => {
858
- e.preventDefault();
859
- e.stopPropagation();
860
- if (!this.callbacks.addable) {
861
- return;
862
- }
863
- const inputValue = this.content.search.input.value.trim();
864
- if (inputValue === '') {
865
- this.content.search.input.focus();
866
- return;
867
- }
868
- const runFinish = (oo) => {
869
- let newOption = new Option(oo);
870
- this.callbacks.addOption(newOption);
871
- if (this.settings.isMultiple) {
872
- let ids = this.store.getSelected();
873
- ids.push(newOption.id);
874
- this.callbacks.setSelected(ids, true);
875
- }
876
- else {
877
- this.callbacks.setSelected([newOption.id], true);
878
- }
879
- this.callbacks.search('');
880
- if (this.settings.closeOnSelect) {
881
- setTimeout(() => {
882
- this.callbacks.close();
883
- }, 100);
884
- }
885
- };
886
- const addableValue = this.callbacks.addable(inputValue);
887
- if (addableValue === false || addableValue === undefined || addableValue === null) {
888
- return;
889
- }
890
- if (addableValue instanceof Promise) {
891
- addableValue.then((value) => {
892
- if (typeof value === 'string') {
893
- runFinish({
894
- text: value,
895
- value: value
896
- });
897
- }
898
- else if (addableValue instanceof Error) {
899
- this.renderError(addableValue.message);
900
- }
901
- else {
902
- runFinish(value);
903
- }
904
- });
905
- }
906
- else if (typeof addableValue === 'string') {
907
- runFinish({
908
- text: addableValue,
909
- value: addableValue
910
- });
911
- }
912
- else if (addableValue instanceof Error) {
913
- this.renderError(addableValue.message);
914
- }
915
- else {
916
- runFinish(addableValue);
917
- }
918
- return;
919
- };
920
- main.appendChild(addable);
921
- searchReturn.addable = {
922
- main: addable,
923
- svg: plus,
924
- path: plusPath
925
- };
926
- }
927
- return searchReturn;
928
- }
929
- searchFocus() {
930
- this.content.search.input.focus();
931
- }
932
- getOptions(notPlaceholder = false, notDisabled = false, notHidden = false) {
933
- let query = '.' + this.classes.option;
934
- if (notPlaceholder) {
935
- query += ':not(.' + this.classes.placeholder + ')';
936
- }
937
- if (notDisabled) {
938
- query += ':not(.' + this.classes.disabled + ')';
939
- }
940
- if (notHidden) {
941
- query += ':not(.' + this.classes.hide + ')';
942
- }
943
- return Array.from(this.content.list.querySelectorAll(query));
944
- }
945
- highlight(dir) {
946
- const options = this.getOptions(true, true, true);
947
- if (options.length === 0) {
948
- return;
949
- }
950
- if (options.length === 1) {
951
- if (!options[0].classList.contains(this.classes.highlighted)) {
952
- options[0].classList.add(this.classes.highlighted);
953
- return;
954
- }
955
- }
956
- let highlighted = false;
957
- for (const o of options) {
958
- if (o.classList.contains(this.classes.highlighted)) {
959
- highlighted = true;
960
- }
961
- }
962
- if (!highlighted) {
963
- for (const o of options) {
964
- if (o.classList.contains(this.classes.selected)) {
965
- o.classList.add(this.classes.highlighted);
966
- break;
967
- }
968
- }
969
- }
970
- for (let i = 0; i < options.length; i++) {
971
- if (options[i].classList.contains(this.classes.highlighted)) {
972
- const prevOption = options[i];
973
- prevOption.classList.remove(this.classes.highlighted);
974
- const prevParent = prevOption.parentElement;
975
- if (prevParent && prevParent.classList.contains(this.classes.open)) {
976
- const optgroupLabel = prevParent.querySelector('.' + this.classes.optgroupLabel);
977
- if (optgroupLabel) {
978
- optgroupLabel.click();
979
- }
980
- }
981
- let selectOption = options[dir === 'down' ? (i + 1 < options.length ? i + 1 : 0) : i - 1 >= 0 ? i - 1 : options.length - 1];
982
- selectOption.classList.add(this.classes.highlighted);
983
- this.ensureElementInView(this.content.list, selectOption);
984
- const selectParent = selectOption.parentElement;
985
- if (selectParent && selectParent.classList.contains(this.classes.close)) {
986
- const optgroupLabel = selectParent.querySelector('.' + this.classes.optgroupLabel);
987
- if (optgroupLabel) {
988
- optgroupLabel.click();
989
- }
990
- }
991
- return;
992
- }
993
- }
994
- options[dir === 'down' ? 0 : options.length - 1].classList.add(this.classes.highlighted);
995
- this.ensureElementInView(this.content.list, options[dir === 'down' ? 0 : options.length - 1]);
996
- }
997
- listDiv() {
998
- const options = document.createElement('div');
999
- options.classList.add(this.classes.list);
1000
- return options;
1001
- }
1002
- renderError(error) {
1003
- this.content.list.innerHTML = '';
1004
- const errorDiv = document.createElement('div');
1005
- errorDiv.classList.add(this.classes.error);
1006
- errorDiv.textContent = error;
1007
- this.content.list.appendChild(errorDiv);
1008
- }
1009
- renderSearching() {
1010
- this.content.list.innerHTML = '';
1011
- const searchingDiv = document.createElement('div');
1012
- searchingDiv.classList.add(this.classes.searching);
1013
- searchingDiv.textContent = this.settings.searchingText;
1014
- this.content.list.appendChild(searchingDiv);
1015
- }
1016
- renderOptions(data) {
1017
- this.content.list.innerHTML = '';
1018
- if (data.length === 0) {
1019
- const noResults = document.createElement('div');
1020
- noResults.classList.add(this.classes.search);
1021
- if (this.callbacks.addable) {
1022
- noResults.innerHTML = this.settings.addableText.replace('{value}', this.content.search.input.value);
1023
- }
1024
- else {
1025
- noResults.innerHTML = this.settings.searchText;
1026
- }
1027
- this.content.list.appendChild(noResults);
1028
- return;
1029
- }
1030
- if (this.settings.allowDeselect && !this.settings.isMultiple) {
1031
- const placeholderOption = this.store.filter((o) => o.placeholder, false);
1032
- if (!placeholderOption.length) {
1033
- this.store.addOption(new Option({
1034
- text: '',
1035
- value: '',
1036
- selected: false,
1037
- placeholder: true
1038
- }), true);
1039
- }
1040
- }
1041
- const fragment = document.createDocumentFragment();
1042
- for (const d of data) {
1043
- if (d instanceof Optgroup) {
1044
- const optgroupEl = document.createElement('div');
1045
- optgroupEl.classList.add(this.classes.optgroup);
1046
- const optgroupLabel = document.createElement('div');
1047
- optgroupLabel.classList.add(this.classes.optgroupLabel);
1048
- optgroupEl.appendChild(optgroupLabel);
1049
- const optgroupLabelText = document.createElement('div');
1050
- optgroupLabelText.classList.add(this.classes.optgroupLabelText);
1051
- optgroupLabelText.textContent = d.label;
1052
- optgroupLabel.appendChild(optgroupLabelText);
1053
- const optgroupActions = document.createElement('div');
1054
- optgroupActions.classList.add(this.classes.optgroupActions);
1055
- optgroupLabel.appendChild(optgroupActions);
1056
- if (this.settings.isMultiple && d.selectAll) {
1057
- const selectAll = document.createElement('div');
1058
- selectAll.classList.add(this.classes.optgroupSelectAll);
1059
- let allSelected = true;
1060
- for (const o of d.options) {
1061
- if (!o.selected) {
1062
- allSelected = false;
1063
- break;
1064
- }
1065
- }
1066
- if (allSelected) {
1067
- selectAll.classList.add(this.classes.selected);
1068
- }
1069
- const selectAllText = document.createElement('span');
1070
- selectAllText.textContent = d.selectAllText;
1071
- selectAll.appendChild(selectAllText);
1072
- const selectAllSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
1073
- selectAllSvg.setAttribute('viewBox', '0 0 100 100');
1074
- selectAll.appendChild(selectAllSvg);
1075
- const selectAllBox = document.createElementNS('http://www.w3.org/2000/svg', 'path');
1076
- selectAllBox.setAttribute('d', this.classes.optgroupSelectAllBox);
1077
- selectAllSvg.appendChild(selectAllBox);
1078
- const selectAllCheck = document.createElementNS('http://www.w3.org/2000/svg', 'path');
1079
- selectAllCheck.setAttribute('d', this.classes.optgroupSelectAllCheck);
1080
- selectAllSvg.appendChild(selectAllCheck);
1081
- selectAll.addEventListener('click', (e) => {
1082
- e.preventDefault();
1083
- e.stopPropagation();
1084
- const currentSelected = this.store.getSelected();
1085
- if (allSelected) {
1086
- const newSelected = currentSelected.filter((s) => {
1087
- for (const o of d.options) {
1088
- if (s === o.id) {
1089
- return false;
1090
- }
1091
- }
1092
- return true;
1093
- });
1094
- this.callbacks.setSelected(newSelected, true);
1095
- return;
1096
- }
1097
- else {
1098
- const newSelected = currentSelected.concat(d.options.map((o) => o.id));
1099
- for (const o of d.options) {
1100
- if (!this.store.getOptionByID(o.id)) {
1101
- this.callbacks.addOption(o);
1102
- }
1103
- }
1104
- this.callbacks.setSelected(newSelected, true);
1105
- return;
1106
- }
1107
- });
1108
- optgroupActions.appendChild(selectAll);
1109
- }
1110
- if (d.closable !== 'off') {
1111
- const optgroupClosable = document.createElement('div');
1112
- optgroupClosable.classList.add(this.classes.optgroupClosable);
1113
- const optgroupClosableSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
1114
- optgroupClosableSvg.setAttribute('viewBox', '0 0 100 100');
1115
- optgroupClosableSvg.classList.add(this.classes.arrow);
1116
- optgroupClosable.appendChild(optgroupClosableSvg);
1117
- const optgroupClosableArrow = document.createElementNS('http://www.w3.org/2000/svg', 'path');
1118
- optgroupClosableSvg.appendChild(optgroupClosableArrow);
1119
- if (d.options.some((o) => o.selected) || this.content.search.input.value.trim() !== '') {
1120
- optgroupClosable.classList.add(this.classes.open);
1121
- optgroupClosableArrow.setAttribute('d', this.classes.arrowOpen);
1122
- }
1123
- else if (d.closable === 'open') {
1124
- optgroupEl.classList.add(this.classes.open);
1125
- optgroupClosableArrow.setAttribute('d', this.classes.arrowOpen);
1126
- }
1127
- else if (d.closable === 'close') {
1128
- optgroupEl.classList.add(this.classes.close);
1129
- optgroupClosableArrow.setAttribute('d', this.classes.arrowClose);
1130
- }
1131
- optgroupLabel.addEventListener('click', (e) => {
1132
- e.preventDefault();
1133
- e.stopPropagation();
1134
- if (optgroupEl.classList.contains(this.classes.close)) {
1135
- optgroupEl.classList.remove(this.classes.close);
1136
- optgroupEl.classList.add(this.classes.open);
1137
- optgroupClosableArrow.setAttribute('d', this.classes.arrowOpen);
1138
- }
1139
- else {
1140
- optgroupEl.classList.remove(this.classes.open);
1141
- optgroupEl.classList.add(this.classes.close);
1142
- optgroupClosableArrow.setAttribute('d', this.classes.arrowClose);
1143
- }
1144
- });
1145
- optgroupActions.appendChild(optgroupClosable);
1146
- }
1147
- optgroupEl.appendChild(optgroupLabel);
1148
- for (const o of d.options) {
1149
- optgroupEl.appendChild(this.option(o));
1150
- fragment.appendChild(optgroupEl);
1151
- }
1152
- }
1153
- if (d instanceof Option) {
1154
- fragment.appendChild(this.option(d));
1155
- }
1156
- }
1157
- this.content.list.appendChild(fragment);
1158
- }
1159
- option(option) {
1160
- if (option.placeholder) {
1161
- const placeholder = document.createElement('div');
1162
- placeholder.classList.add(this.classes.option);
1163
- placeholder.classList.add(this.classes.hide);
1164
- return placeholder;
1165
- }
1166
- const optionEl = document.createElement('div');
1167
- optionEl.dataset.id = option.id;
1168
- optionEl.classList.add(this.classes.option);
1169
- optionEl.setAttribute('role', 'option');
1170
- if (option.class) {
1171
- option.class.split(' ').forEach((dataClass) => {
1172
- optionEl.classList.add(dataClass);
1173
- });
1174
- }
1175
- if (option.style) {
1176
- optionEl.style.cssText = option.style;
1177
- }
1178
- if (this.settings.searchHighlight && this.content.search.input.value.trim() !== '') {
1179
- optionEl.innerHTML = this.highlightText(option.html !== '' ? option.html : option.text, this.content.search.input.value, this.classes.searchHighlighter);
1180
- }
1181
- else if (option.html !== '') {
1182
- optionEl.innerHTML = option.html;
1183
- }
1184
- else {
1185
- optionEl.textContent = option.text;
1186
- }
1187
- if (this.settings.showOptionTooltips && optionEl.textContent) {
1188
- optionEl.setAttribute('title', optionEl.textContent);
1189
- }
1190
- if (!option.display) {
1191
- optionEl.classList.add(this.classes.hide);
1192
- }
1193
- if (option.disabled) {
1194
- optionEl.classList.add(this.classes.disabled);
1195
- }
1196
- if (option.selected && this.settings.hideSelected) {
1197
- optionEl.classList.add(this.classes.hide);
1198
- }
1199
- if (option.selected) {
1200
- optionEl.classList.add(this.classes.selected);
1201
- optionEl.setAttribute('aria-selected', 'true');
1202
- this.main.main.setAttribute('aria-activedescendant', optionEl.id);
1203
- }
1204
- else {
1205
- optionEl.classList.remove(this.classes.selected);
1206
- optionEl.setAttribute('aria-selected', 'false');
1207
- }
1208
- optionEl.addEventListener('click', (e) => {
1209
- e.preventDefault();
1210
- e.stopPropagation();
1211
- const selectedOptions = this.store.getSelected();
1212
- const element = e.currentTarget;
1213
- const elementID = String(element.dataset.id);
1214
- if (option.disabled || (option.selected && !this.settings.allowDeselect)) {
1215
- return;
1216
- }
1217
- if ((this.settings.isMultiple && this.settings.maxSelected <= selectedOptions.length && !option.selected) ||
1218
- (this.settings.isMultiple && this.settings.minSelected >= selectedOptions.length && option.selected)) {
1219
- return;
1220
- }
1221
- let shouldUpdate = false;
1222
- const before = this.store.getSelectedOptions();
1223
- let after = [];
1224
- if (this.settings.isMultiple) {
1225
- if (option.selected) {
1226
- after = before.filter((o) => o.id !== elementID);
1227
- }
1228
- else {
1229
- after = before.concat(option);
1230
- if (!this.settings.closeOnSelect) {
1231
- if (e.shiftKey && this.lastSelectedOption) {
1232
- const options = this.store.getDataOptions();
1233
- let lastClickedOptionIndex = options.findIndex((o) => o.id === this.lastSelectedOption.id);
1234
- let currentOptionIndex = options.findIndex((o) => o.id === option.id);
1235
- if (lastClickedOptionIndex >= 0 && currentOptionIndex >= 0) {
1236
- const startIndex = Math.min(lastClickedOptionIndex, currentOptionIndex);
1237
- const endIndex = Math.max(lastClickedOptionIndex, currentOptionIndex);
1238
- const afterRange = options.slice(startIndex, endIndex + 1);
1239
- if (afterRange.length > 0 && afterRange.length < this.settings.maxSelected) {
1240
- after = before.concat(afterRange.filter((a) => !before.find((b) => b.id === a.id)));
1241
- }
1242
- }
1243
- }
1244
- else if (!option.selected) {
1245
- this.lastSelectedOption = option;
1246
- }
1247
- }
1248
- }
1249
- }
1250
- if (!this.settings.isMultiple) {
1251
- if (option.selected) {
1252
- after = [];
1253
- }
1254
- else {
1255
- after = [option];
1256
- }
1257
- }
1258
- if (!this.callbacks.beforeChange) {
1259
- shouldUpdate = true;
1260
- }
1261
- if (this.callbacks.beforeChange) {
1262
- if (this.callbacks.beforeChange(after, before) === false) {
1263
- shouldUpdate = false;
1264
- }
1265
- else {
1266
- shouldUpdate = true;
1267
- }
1268
- }
1269
- if (shouldUpdate) {
1270
- if (!this.store.getOptionByID(elementID)) {
1271
- this.callbacks.addOption(option);
1272
- }
1273
- this.callbacks.setSelected(after.map((o) => o.id), false);
1274
- if (this.settings.closeOnSelect) {
1275
- this.callbacks.close();
1276
- }
1277
- if (this.callbacks.afterChange) {
1278
- this.callbacks.afterChange(after);
1279
- }
1280
- }
1281
- });
1282
- return optionEl;
1283
- }
1284
- destroy() {
1285
- this.main.main.remove();
1286
- this.content.main.remove();
1287
- }
1288
- highlightText(str, search, className) {
1289
- let completedString = str;
1290
- const regex = new RegExp('(?![^<]*>)(' + search.trim() + ')(?![^<]*>[^<>]*</)', 'i');
1291
- if (!str.match(regex)) {
1292
- return str;
1293
- }
1294
- const matchStartPosition = str.match(regex).index;
1295
- const matchEndPosition = matchStartPosition + str.match(regex)[0].toString().length;
1296
- const originalTextFoundByRegex = str.substring(matchStartPosition, matchEndPosition);
1297
- completedString = completedString.replace(regex, `<mark class="${className}">${originalTextFoundByRegex}</mark>`);
1298
- return completedString;
1299
- }
1300
- moveContentAbove() {
1301
- const mainHeight = this.main.main.offsetHeight;
1302
- const contentHeight = this.content.main.offsetHeight;
1303
- this.main.main.classList.remove(this.classes.openBelow);
1304
- this.main.main.classList.add(this.classes.openAbove);
1305
- this.content.main.classList.remove(this.classes.openBelow);
1306
- this.content.main.classList.add(this.classes.openAbove);
1307
- const containerRect = this.main.main.getBoundingClientRect();
1308
- this.content.main.style.margin = '-' + (mainHeight + contentHeight - 1) + 'px 0px 0px 0px';
1309
- this.content.main.style.top =
1310
- containerRect.top + containerRect.height + (this.settings.contentPosition === 'fixed' ? 0 : window.scrollY) + 'px';
1311
- this.content.main.style.left =
1312
- containerRect.left + (this.settings.contentPosition === 'fixed' ? 0 : window.scrollX) + 'px';
1313
- this.content.main.style.width = containerRect.width + 'px';
1314
- }
1315
- moveContentBelow() {
1316
- this.main.main.classList.remove(this.classes.openAbove);
1317
- this.main.main.classList.add(this.classes.openBelow);
1318
- this.content.main.classList.remove(this.classes.openAbove);
1319
- this.content.main.classList.add(this.classes.openBelow);
1320
- const containerRect = this.main.main.getBoundingClientRect();
1321
- this.content.main.style.margin = '-1px 0px 0px 0px';
1322
- if (this.settings.contentPosition !== 'relative') {
1323
- this.content.main.style.top =
1324
- containerRect.top +
1325
- containerRect.height +
1326
- (this.settings.contentPosition === 'fixed' ? 0 : window.scrollY) +
1327
- 'px';
1328
- this.content.main.style.left =
1329
- containerRect.left + (this.settings.contentPosition === 'fixed' ? 0 : window.scrollX) + 'px';
1330
- this.content.main.style.width = containerRect.width + 'px';
1331
- }
1332
- }
1333
- ensureElementInView(container, element) {
1334
- const cTop = container.scrollTop + container.offsetTop;
1335
- const cBottom = cTop + container.clientHeight;
1336
- const eTop = element.offsetTop;
1337
- const eBottom = eTop + element.clientHeight;
1338
- if (eTop < cTop) {
1339
- container.scrollTop -= cTop - eTop;
1340
- }
1341
- else if (eBottom > cBottom) {
1342
- container.scrollTop += eBottom - cBottom;
1343
- }
1344
- }
1345
- putContent() {
1346
- const mainHeight = this.main.main.offsetHeight;
1347
- const mainRect = this.main.main.getBoundingClientRect();
1348
- const contentHeight = this.content.main.offsetHeight;
1349
- const spaceBelow = window.innerHeight - (mainRect.top + mainHeight);
1350
- if (spaceBelow <= contentHeight) {
1351
- if (mainRect.top > contentHeight) {
1352
- return 'up';
1353
- }
1354
- else {
1355
- return 'down';
1356
- }
1357
- }
1358
- return 'down';
1359
- }
1360
- updateDeselectAll() {
1361
- if (!this.store || !this.settings) {
1362
- return;
1363
- }
1364
- const selected = this.store.getSelectedOptions();
1365
- const hasSelectedItems = selected && selected.length > 0;
1366
- const isMultiple = this.settings.isMultiple;
1367
- const allowDeselect = this.settings.allowDeselect;
1368
- const deselectButton = this.main.deselect.main;
1369
- const hideClass = this.classes.hide;
1370
- if (allowDeselect && !(isMultiple && !hasSelectedItems)) {
1371
- deselectButton.classList.remove(hideClass);
1372
- }
1373
- else {
1374
- deselectButton.classList.add(hideClass);
1375
- }
1376
- }
1377
- }
1378
-
1379
- class Select {
1380
- constructor(select) {
1381
- this.listen = false;
1382
- this.observer = null;
1383
- this.select = select;
1384
- this.valueChange = this.valueChange.bind(this);
1385
- this.select.addEventListener('change', this.valueChange, {
1386
- passive: true
1387
- });
1388
- this.observer = new MutationObserver(this.observeCall.bind(this));
1389
- this.changeListen(true);
1390
- }
1391
- enable() {
1392
- this.select.disabled = false;
1393
- }
1394
- disable() {
1395
- this.select.disabled = true;
1396
- }
1397
- hideUI() {
1398
- this.select.tabIndex = -1;
1399
- this.select.style.display = 'none';
1400
- this.select.setAttribute('aria-hidden', 'true');
1401
- }
1402
- showUI() {
1403
- this.select.removeAttribute('tabindex');
1404
- this.select.style.display = '';
1405
- this.select.removeAttribute('aria-hidden');
1406
- }
1407
- changeListen(listen) {
1408
- this.listen = listen;
1409
- if (listen) {
1410
- if (this.observer) {
1411
- this.observer.observe(this.select, {
1412
- subtree: true,
1413
- childList: true,
1414
- attributes: true
1415
- });
1416
- }
1417
- }
1418
- if (!listen) {
1419
- if (this.observer) {
1420
- this.observer.disconnect();
1421
- }
1422
- }
1423
- }
1424
- valueChange(ev) {
1425
- if (this.listen && this.onValueChange) {
1426
- this.onValueChange(this.getSelectedOptions());
1427
- }
1428
- return true;
1429
- }
1430
- observeCall(mutations) {
1431
- if (!this.listen) {
1432
- return;
1433
- }
1434
- let classChanged = false;
1435
- let disabledChanged = false;
1436
- let optgroupOptionChanged = false;
1437
- for (const m of mutations) {
1438
- if (m.target === this.select) {
1439
- if (m.attributeName === 'disabled') {
1440
- disabledChanged = true;
1441
- }
1442
- if (m.attributeName === 'class') {
1443
- classChanged = true;
1444
- }
1445
- if (m.type === 'childList') {
1446
- for (const n of m.addedNodes) {
1447
- if (n.nodeName === 'OPTION' && n.value === this.select.value) {
1448
- this.select.dispatchEvent(new Event('change'));
1449
- break;
1450
- }
1451
- }
1452
- optgroupOptionChanged = true;
1453
- }
1454
- }
1455
- if (m.target.nodeName === 'OPTGROUP' || m.target.nodeName === 'OPTION') {
1456
- optgroupOptionChanged = true;
1457
- }
1458
- }
1459
- if (classChanged && this.onClassChange) {
1460
- this.onClassChange(this.select.className.split(' '));
1461
- }
1462
- if (disabledChanged && this.onDisabledChange) {
1463
- this.changeListen(false);
1464
- this.onDisabledChange(this.select.disabled);
1465
- this.changeListen(true);
1466
- }
1467
- if (optgroupOptionChanged && this.onOptionsChange) {
1468
- this.changeListen(false);
1469
- this.onOptionsChange(this.getData());
1470
- this.changeListen(true);
1471
- }
1472
- }
1473
- getData() {
1474
- let data = [];
1475
- const nodes = this.select.childNodes;
1476
- for (const n of nodes) {
1477
- if (n.nodeName === 'OPTGROUP') {
1478
- data.push(this.getDataFromOptgroup(n));
1479
- }
1480
- if (n.nodeName === 'OPTION') {
1481
- data.push(this.getDataFromOption(n));
1482
- }
1483
- }
1484
- return data;
1485
- }
1486
- getDataFromOptgroup(optgroup) {
1487
- let data = {
1488
- id: optgroup.id,
1489
- label: optgroup.label,
1490
- selectAll: optgroup.dataset ? optgroup.dataset.selectall === 'true' : false,
1491
- selectAllText: optgroup.dataset ? optgroup.dataset.selectalltext : 'Select all',
1492
- closable: optgroup.dataset ? optgroup.dataset.closable : 'off',
1493
- options: []
1494
- };
1495
- const options = optgroup.childNodes;
1496
- for (const o of options) {
1497
- if (o.nodeName === 'OPTION') {
1498
- data.options.push(this.getDataFromOption(o));
1499
- }
1500
- }
1501
- return data;
1502
- }
1503
- getDataFromOption(option) {
1504
- return {
1505
- id: option.id,
1506
- value: option.value,
1507
- text: option.text,
1508
- html: option.dataset && option.dataset.html ? option.dataset.html : '',
1509
- defaultSelected: option.defaultSelected,
1510
- selected: option.selected,
1511
- display: option.style.display !== 'none',
1512
- disabled: option.disabled,
1513
- mandatory: option.dataset ? option.dataset.mandatory === 'true' : false,
1514
- placeholder: option.dataset.placeholder === 'true',
1515
- class: option.className,
1516
- style: option.style.cssText,
1517
- data: option.dataset
1518
- };
1519
- }
1520
- getSelectedOptions() {
1521
- let options = [];
1522
- const opts = this.select.childNodes;
1523
- for (const o of opts) {
1524
- if (o.nodeName === 'OPTGROUP') {
1525
- const optgroupOptions = o.childNodes;
1526
- for (const oo of optgroupOptions) {
1527
- if (oo.nodeName === 'OPTION') {
1528
- const option = oo;
1529
- if (option.selected) {
1530
- options.push(this.getDataFromOption(option));
1531
- }
1532
- }
1533
- }
1534
- }
1535
- if (o.nodeName === 'OPTION') {
1536
- const option = o;
1537
- if (option.selected) {
1538
- options.push(this.getDataFromOption(option));
1539
- }
1540
- }
1541
- }
1542
- return options;
1543
- }
1544
- getSelectedValues() {
1545
- return this.getSelectedOptions().map((option) => option.value);
1546
- }
1547
- setSelected(ids) {
1548
- this.changeListen(false);
1549
- const options = this.select.childNodes;
1550
- for (const o of options) {
1551
- if (o.nodeName === 'OPTGROUP') {
1552
- const optgroup = o;
1553
- const optgroupOptions = optgroup.childNodes;
1554
- for (const oo of optgroupOptions) {
1555
- if (oo.nodeName === 'OPTION') {
1556
- const option = oo;
1557
- option.selected = ids.includes(option.id);
1558
- }
1559
- }
1560
- }
1561
- if (o.nodeName === 'OPTION') {
1562
- const option = o;
1563
- option.selected = ids.includes(option.id);
1564
- }
1565
- }
1566
- this.changeListen(true);
1567
- }
1568
- setSelectedByValue(values) {
1569
- this.changeListen(false);
1570
- const options = this.select.childNodes;
1571
- for (const o of options) {
1572
- if (o.nodeName === 'OPTGROUP') {
1573
- const optgroup = o;
1574
- const optgroupOptions = optgroup.childNodes;
1575
- for (const oo of optgroupOptions) {
1576
- if (oo.nodeName === 'OPTION') {
1577
- const option = oo;
1578
- option.selected = values.includes(option.value);
1579
- }
1580
- }
1581
- }
1582
- if (o.nodeName === 'OPTION') {
1583
- const option = o;
1584
- option.selected = values.includes(option.value);
1585
- }
1586
- }
1587
- this.changeListen(true);
1588
- }
1589
- updateSelect(id, style, classes) {
1590
- this.changeListen(false);
1591
- if (id) {
1592
- this.select.dataset.id = id;
1593
- }
1594
- if (style) {
1595
- this.select.style.cssText = style;
1596
- }
1597
- if (classes) {
1598
- this.select.className = '';
1599
- classes.forEach((c) => {
1600
- if (c.trim() !== '') {
1601
- this.select.classList.add(c.trim());
1602
- }
1603
- });
1604
- }
1605
- this.changeListen(true);
1606
- }
1607
- updateOptions(data) {
1608
- this.changeListen(false);
1609
- this.select.innerHTML = '';
1610
- for (const d of data) {
1611
- if (d instanceof Optgroup) {
1612
- this.select.appendChild(this.createOptgroup(d));
1613
- }
1614
- if (d instanceof Option) {
1615
- this.select.appendChild(this.createOption(d));
1616
- }
1617
- }
1618
- this.select.dispatchEvent(new Event('change', { bubbles: true }));
1619
- this.changeListen(true);
1620
- }
1621
- createOptgroup(optgroup) {
1622
- const optgroupEl = document.createElement('optgroup');
1623
- optgroupEl.id = optgroup.id;
1624
- optgroupEl.label = optgroup.label;
1625
- if (optgroup.selectAll) {
1626
- optgroupEl.dataset.selectAll = 'true';
1627
- }
1628
- if (optgroup.closable !== 'off') {
1629
- optgroupEl.dataset.closable = optgroup.closable;
1630
- }
1631
- if (optgroup.options) {
1632
- for (const o of optgroup.options) {
1633
- optgroupEl.appendChild(this.createOption(o));
1634
- }
1635
- }
1636
- return optgroupEl;
1637
- }
1638
- createOption(info) {
1639
- const optionEl = document.createElement('option');
1640
- optionEl.id = info.id;
1641
- optionEl.value = info.value;
1642
- optionEl.textContent = info.text;
1643
- if (info.html !== '') {
1644
- optionEl.setAttribute('data-html', info.html);
1645
- }
1646
- optionEl.defaultSelected = info.defaultSelected;
1647
- optionEl.selected = info.selected;
1648
- if (info.disabled) {
1649
- optionEl.disabled = true;
1650
- }
1651
- if (!info.display) {
1652
- optionEl.style.display = 'none';
1653
- }
1654
- if (info.placeholder) {
1655
- optionEl.setAttribute('data-placeholder', 'true');
1656
- }
1657
- if (info.mandatory) {
1658
- optionEl.setAttribute('data-mandatory', 'true');
1659
- }
1660
- if (info.class) {
1661
- info.class.split(' ').forEach((optionClass) => {
1662
- optionEl.classList.add(optionClass);
1663
- });
1664
- }
1665
- if (info.data && typeof info.data === 'object') {
1666
- Object.keys(info.data).forEach((key) => {
1667
- optionEl.setAttribute('data-' + kebabCase(key), info.data[key]);
1668
- });
1669
- }
1670
- return optionEl;
1671
- }
1672
- destroy() {
1673
- this.changeListen(false);
1674
- this.select.removeEventListener('change', this.valueChange);
1675
- if (this.observer) {
1676
- this.observer.disconnect();
1677
- this.observer = null;
1678
- }
1679
- delete this.select.dataset.id;
1680
- this.showUI();
1681
- }
1682
- }
1683
-
1684
- class Settings {
1685
- constructor(settings) {
1686
- this.id = '';
1687
- this.style = '';
1688
- this.class = [];
1689
- this.isMultiple = false;
1690
- this.isOpen = false;
1691
- this.isFullOpen = false;
1692
- this.intervalMove = null;
1693
- if (!settings) {
1694
- settings = {};
1695
- }
1696
- this.id = 'ss-' + generateID();
1697
- this.style = settings.style || '';
1698
- this.class = settings.class || [];
1699
- this.disabled = settings.disabled !== undefined ? settings.disabled : false;
1700
- this.alwaysOpen = settings.alwaysOpen !== undefined ? settings.alwaysOpen : false;
1701
- this.showSearch = settings.showSearch !== undefined ? settings.showSearch : true;
1702
- this.focusSearch = settings.focusSearch !== undefined ? settings.focusSearch : true;
1703
- this.ariaLabel = settings.ariaLabel || 'Combobox';
1704
- this.searchPlaceholder = settings.searchPlaceholder || 'Search';
1705
- this.searchText = settings.searchText || 'No Results';
1706
- this.searchingText = settings.searchingText || 'Searching...';
1707
- this.searchHighlight = settings.searchHighlight !== undefined ? settings.searchHighlight : false;
1708
- this.closeOnSelect = settings.closeOnSelect !== undefined ? settings.closeOnSelect : true;
1709
- this.contentLocation = settings.contentLocation || document.body;
1710
- this.contentPosition = settings.contentPosition || 'absolute';
1711
- this.openPosition = settings.openPosition || 'auto';
1712
- this.placeholderText = settings.placeholderText !== undefined ? settings.placeholderText : 'Select Value';
1713
- this.allowDeselect = settings.allowDeselect !== undefined ? settings.allowDeselect : false;
1714
- this.hideSelected = settings.hideSelected !== undefined ? settings.hideSelected : false;
1715
- this.keepOrder = settings.keepOrder !== undefined ? settings.keepOrder : false;
1716
- this.showOptionTooltips = settings.showOptionTooltips !== undefined ? settings.showOptionTooltips : false;
1717
- this.minSelected = settings.minSelected || 0;
1718
- this.maxSelected = settings.maxSelected || 1000;
1719
- this.timeoutDelay = settings.timeoutDelay || 200;
1720
- this.maxValuesShown = settings.maxValuesShown || 20;
1721
- this.maxValuesMessage = settings.maxValuesMessage || '{number} selected';
1722
- this.addableText = settings.addableText || 'Press "Enter" to add {value}';
1723
- }
1724
- }
1725
-
1726
- class SlimSelect {
1727
- constructor(config) {
1728
- var _a;
1729
- this.events = {
1730
- search: undefined,
1731
- searchFilter: (opt, search) => {
1732
- return opt.text.toLowerCase().indexOf(search.toLowerCase()) !== -1;
1733
- },
1734
- addable: undefined,
1735
- beforeChange: undefined,
1736
- afterChange: undefined,
1737
- beforeOpen: undefined,
1738
- afterOpen: undefined,
1739
- beforeClose: undefined,
1740
- afterClose: undefined
1741
- };
1742
- this.windowResize = debounce(() => {
1743
- if (!this.settings.isOpen && !this.settings.isFullOpen) {
1744
- return;
1745
- }
1746
- this.render.moveContent();
1747
- });
1748
- this.windowScroll = debounce(() => {
1749
- if (!this.settings.isOpen && !this.settings.isFullOpen) {
1750
- return;
1751
- }
1752
- this.render.moveContent();
1753
- });
1754
- this.documentClick = (e) => {
1755
- if (!this.settings.isOpen) {
1756
- return;
1757
- }
1758
- if (e.target && !hasClassInTree(e.target, this.settings.id)) {
1759
- this.close(e.type);
1760
- }
1761
- };
1762
- this.windowVisibilityChange = () => {
1763
- if (document.hidden) {
1764
- this.close();
1765
- }
1766
- };
1767
- this.selectEl = (typeof config.select === 'string' ? document.querySelector(config.select) : config.select);
1768
- if (!this.selectEl) {
1769
- if (config.events && config.events.error) {
1770
- config.events.error(new Error('Could not find select element'));
1771
- }
1772
- return;
1773
- }
1774
- if (this.selectEl.tagName !== 'SELECT') {
1775
- if (config.events && config.events.error) {
1776
- config.events.error(new Error('Element isnt of type select'));
1777
- }
1778
- return;
1779
- }
1780
- if (this.selectEl.dataset.ssid) {
1781
- this.destroy();
1782
- }
1783
- this.settings = new Settings(config.settings);
1784
- this.cssClasses = new CssClasses(config.cssClasses);
1785
- const debounceEvents = ['afterChange', 'beforeOpen', 'afterOpen', 'beforeClose', 'afterClose'];
1786
- for (const key in config.events) {
1787
- if (!config.events.hasOwnProperty(key)) {
1788
- continue;
1789
- }
1790
- if (debounceEvents.indexOf(key) !== -1) {
1791
- this.events[key] = debounce(config.events[key], 100);
1792
- }
1793
- else {
1794
- this.events[key] = config.events[key];
1795
- }
1796
- }
1797
- this.settings.disabled = ((_a = config.settings) === null || _a === void 0 ? void 0 : _a.disabled) ? config.settings.disabled : this.selectEl.disabled;
1798
- this.settings.isMultiple = this.selectEl.multiple;
1799
- this.settings.style = this.selectEl.style.cssText;
1800
- this.settings.class = this.selectEl.className.split(' ');
1801
- this.select = new Select(this.selectEl);
1802
- this.select.updateSelect(this.settings.id, this.settings.style, this.settings.class);
1803
- this.select.hideUI();
1804
- this.select.onValueChange = (options) => {
1805
- this.setSelected(options.map((option) => option.id));
1806
- };
1807
- this.select.onClassChange = (classes) => {
1808
- this.settings.class = classes;
1809
- this.render.updateClassStyles();
1810
- };
1811
- this.select.onDisabledChange = (disabled) => {
1812
- if (disabled) {
1813
- this.disable();
1814
- }
1815
- else {
1816
- this.enable();
1817
- }
1818
- };
1819
- this.select.onOptionsChange = (data) => {
1820
- this.setData(data);
1821
- };
1822
- this.store = new Store(this.settings.isMultiple ? 'multiple' : 'single', config.data ? config.data : this.select.getData());
1823
- if (config.data) {
1824
- this.select.updateOptions(this.store.getData());
1825
- }
1826
- const renderCallbacks = {
1827
- open: this.open.bind(this),
1828
- close: this.close.bind(this),
1829
- addable: this.events.addable ? this.events.addable : undefined,
1830
- setSelected: this.setSelected.bind(this),
1831
- addOption: this.addOption.bind(this),
1832
- search: this.search.bind(this),
1833
- beforeChange: this.events.beforeChange,
1834
- afterChange: this.events.afterChange
1835
- };
1836
- this.render = new Render(this.settings, this.cssClasses, this.store, renderCallbacks);
1837
- this.render.renderValues();
1838
- this.render.renderOptions(this.store.getData());
1839
- const selectAriaLabel = this.selectEl.getAttribute('aria-label');
1840
- const selectAriaLabelledBy = this.selectEl.getAttribute('aria-labelledby');
1841
- if (selectAriaLabel) {
1842
- this.render.main.main.setAttribute('aria-label', selectAriaLabel);
1843
- }
1844
- else if (selectAriaLabelledBy) {
1845
- this.render.main.main.setAttribute('aria-labelledby', selectAriaLabelledBy);
1846
- }
1847
- if (this.selectEl.parentNode) {
1848
- this.selectEl.parentNode.insertBefore(this.render.main.main, this.selectEl.nextSibling);
1849
- }
1850
- window.addEventListener('resize', this.windowResize, false);
1851
- if (this.settings.openPosition === 'auto') {
1852
- window.addEventListener('scroll', this.windowScroll, false);
1853
- }
1854
- document.addEventListener('visibilitychange', this.windowVisibilityChange);
1855
- if (this.settings.disabled) {
1856
- this.disable();
1857
- }
1858
- if (this.settings.alwaysOpen) {
1859
- this.open();
1860
- }
1861
- this.selectEl.slim = this;
1862
- }
1863
- enable() {
1864
- this.settings.disabled = false;
1865
- this.select.enable();
1866
- this.render.enable();
1867
- }
1868
- disable() {
1869
- this.settings.disabled = true;
1870
- this.select.disable();
1871
- this.render.disable();
1872
- }
1873
- getData() {
1874
- return this.store.getData();
1875
- }
1876
- setData(data) {
1877
- const selected = this.store.getSelected();
1878
- const err = this.store.validateDataArray(data);
1879
- if (err) {
1880
- if (this.events.error) {
1881
- this.events.error(err);
1882
- }
1883
- return;
1884
- }
1885
- this.store.setData(data);
1886
- const dataClean = this.store.getData();
1887
- this.select.updateOptions(dataClean);
1888
- this.render.renderValues();
1889
- this.render.renderOptions(dataClean);
1890
- if (this.events.afterChange && !isEqual(selected, this.store.getSelected())) {
1891
- this.events.afterChange(this.store.getSelectedOptions());
1892
- }
1893
- }
1894
- getSelected() {
1895
- let options = this.store.getSelectedOptions();
1896
- if (this.settings.keepOrder) {
1897
- options = this.store.selectedOrderOptions(options);
1898
- }
1899
- return options.map((option) => option.value);
1900
- }
1901
- setSelected(values, runAfterChange = true) {
1902
- const selected = this.store.getSelected();
1903
- const options = this.store.getDataOptions();
1904
- values = Array.isArray(values) ? values : [values];
1905
- const ids = [];
1906
- for (const value of values) {
1907
- if (options.find((option) => option.id == value)) {
1908
- ids.push(value);
1909
- continue;
1910
- }
1911
- for (const option of options.filter((option) => option.value == value)) {
1912
- ids.push(option.id);
1913
- }
1914
- }
1915
- this.store.setSelectedBy('id', ids);
1916
- const data = this.store.getData();
1917
- this.select.updateOptions(data);
1918
- this.render.renderValues();
1919
- if (this.render.content.search.input.value !== '') {
1920
- this.search(this.render.content.search.input.value);
1921
- }
1922
- else {
1923
- this.render.renderOptions(data);
1924
- }
1925
- if (runAfterChange && this.events.afterChange && !isEqual(selected, this.store.getSelected())) {
1926
- this.events.afterChange(this.store.getSelectedOptions());
1927
- }
1928
- }
1929
- addOption(option) {
1930
- const selected = this.store.getSelected();
1931
- if (!this.store.getDataOptions().some((o) => { var _a; return o.value === ((_a = option.value) !== null && _a !== void 0 ? _a : option.text); })) {
1932
- this.store.addOption(option);
1933
- }
1934
- const data = this.store.getData();
1935
- this.select.updateOptions(data);
1936
- this.render.renderValues();
1937
- this.render.renderOptions(data);
1938
- if (this.events.afterChange && !isEqual(selected, this.store.getSelected())) {
1939
- this.events.afterChange(this.store.getSelectedOptions());
1940
- }
1941
- }
1942
- open() {
1943
- if (this.settings.disabled || this.settings.isOpen) {
1944
- return;
1945
- }
1946
- if (this.events.beforeOpen) {
1947
- this.events.beforeOpen();
1948
- }
1949
- this.render.open();
1950
- if (this.settings.showSearch && this.settings.focusSearch) {
1951
- this.render.searchFocus();
1952
- }
1953
- this.settings.isOpen = true;
1954
- setTimeout(() => {
1955
- if (this.events.afterOpen) {
1956
- this.events.afterOpen();
1957
- }
1958
- if (this.settings.isOpen) {
1959
- this.settings.isFullOpen = true;
1960
- }
1961
- document.addEventListener('click', this.documentClick);
1962
- }, this.settings.timeoutDelay);
1963
- if (this.settings.contentPosition === 'absolute') {
1964
- if (this.settings.intervalMove) {
1965
- clearInterval(this.settings.intervalMove);
1966
- }
1967
- this.settings.intervalMove = setInterval(this.render.moveContent.bind(this.render), 500);
1968
- }
1969
- }
1970
- close(eventType = null) {
1971
- if (!this.settings.isOpen || this.settings.alwaysOpen) {
1972
- return;
1973
- }
1974
- if (this.events.beforeClose) {
1975
- this.events.beforeClose();
1976
- }
1977
- this.render.close();
1978
- if (this.render.content.search.input.value !== '') {
1979
- this.search('');
1980
- }
1981
- this.render.mainFocus(eventType);
1982
- this.settings.isOpen = false;
1983
- this.settings.isFullOpen = false;
1984
- setTimeout(() => {
1985
- if (this.events.afterClose) {
1986
- this.events.afterClose();
1987
- }
1988
- document.removeEventListener('click', this.documentClick);
1989
- }, this.settings.timeoutDelay);
1990
- if (this.settings.intervalMove) {
1991
- clearInterval(this.settings.intervalMove);
1992
- }
1993
- }
1994
- search(value) {
1995
- if (this.render.content.search.input.value !== value) {
1996
- this.render.content.search.input.value = value;
1997
- }
1998
- if (!this.events.search) {
1999
- this.render.renderOptions(value === '' ? this.store.getData() : this.store.search(value, this.events.searchFilter));
2000
- return;
2001
- }
2002
- this.render.renderSearching();
2003
- const searchResp = this.events.search(value, this.store.getSelectedOptions());
2004
- if (searchResp instanceof Promise) {
2005
- searchResp
2006
- .then((data) => {
2007
- this.render.renderOptions(this.store.partialToFullData(data));
2008
- })
2009
- .catch((err) => {
2010
- this.render.renderError(typeof err === 'string' ? err : err.message);
2011
- });
2012
- return;
2013
- }
2014
- else if (Array.isArray(searchResp)) {
2015
- this.render.renderOptions(this.store.partialToFullData(searchResp));
2016
- }
2017
- else {
2018
- this.render.renderError('Search event must return a promise or an array of data');
2019
- }
2020
- }
2021
- destroy() {
2022
- document.removeEventListener('click', this.documentClick);
2023
- window.removeEventListener('resize', this.windowResize, false);
2024
- if (this.settings.openPosition === 'auto') {
2025
- window.removeEventListener('scroll', this.windowScroll, false);
2026
- }
2027
- document.removeEventListener('visibilitychange', this.windowVisibilityChange);
2028
- this.store.setData([]);
2029
- this.render.destroy();
2030
- this.select.destroy();
2031
- }
2032
- }
2033
-
2034
- return SlimSelect;
2035
-
2036
- }));