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