kmaterialize 2.0.0 → 2.3.3-1.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 (150) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +55 -91
  3. package/components/appbar/_navbar.old.scss +223 -0
  4. package/components/appbar/appbar.css +235 -0
  5. package/components/appbar/appbar.mjs +54 -0
  6. package/components/appbar/appbar.test.mjs +9 -0
  7. package/components/atomic/atomic.mjs +19 -0
  8. package/components/atomic/component.mjs +67 -0
  9. package/components/badge/_badges.scss +75 -0
  10. package/components/badge/badge.mjs +11 -0
  11. package/components/breadcrumb/_breadcrumb.scss +27 -0
  12. package/components/button/_buttons.scss +352 -0
  13. package/components/button/button.mjs +11 -0
  14. package/components/button/buttons.stories.ts +150 -0
  15. package/components/button/buttons.ts +282 -0
  16. package/components/button/examples.iso.js +18 -0
  17. package/components/button/fabSpec.js +65 -0
  18. package/components/button/test-button.mjs +16 -0
  19. package/components/card/_cards.scss +229 -0
  20. package/components/card/card.mjs +10 -0
  21. package/components/card/cards.ts +185 -0
  22. package/components/card/cardsSpec.js +269 -0
  23. package/components/carousel/_carousel.scss +93 -0
  24. package/components/carousel/_slider.scss +119 -0
  25. package/components/carousel/carousel.ts +693 -0
  26. package/components/carousel/carouselSpec.js +61 -0
  27. package/components/carousel/slider.ts +431 -0
  28. package/components/carousel/sliderSpec.js +99 -0
  29. package/components/checkbox/_checkboxes.scss +281 -0
  30. package/components/checkbox/checkbox.mdx +24 -0
  31. package/components/checkbox/checkbox.stories.ts +120 -0
  32. package/components/chip/chip.mjs +37 -0
  33. package/components/chip/chip.test.mjs +10 -0
  34. package/components/chip/chips.css +126 -0
  35. package/components/chip/chips.mdx +33 -0
  36. package/components/chip/chips.ts +440 -0
  37. package/components/chip/chipsSpec.js +165 -0
  38. package/components/chip/readme.md +323 -0
  39. package/components/collapsible/_collapsible.scss +82 -0
  40. package/components/collapsible/collapsible.ts +230 -0
  41. package/components/collapsible/collapsibleSpec.js +240 -0
  42. package/components/datepicker/_datepicker.scss +268 -0
  43. package/components/datepicker/datepicker.ts +1450 -0
  44. package/components/datepicker/datepickerSpec.js +162 -0
  45. package/components/dialog/_materialbox.scss +42 -0
  46. package/components/dialog/_modal.scss +79 -0
  47. package/components/dialog/materialbox.ts +446 -0
  48. package/components/dialog/materialboxSpec.js +37 -0
  49. package/components/dialog/modal.ts +111 -0
  50. package/components/dialog/modalSpec.js +83 -0
  51. package/components/dialog/readme.md +5 -0
  52. package/components/divider/readme.md +15 -0
  53. package/components/dropdown/_dropdown.scss +83 -0
  54. package/components/dropdown/dropdown.ts +653 -0
  55. package/components/dropdown/dropdownSpec.js +108 -0
  56. package/components/list/_collection.scss +114 -0
  57. package/components/list/_list.scss +6 -0
  58. package/components/list/list.mjs +58 -0
  59. package/components/list/list.test.mjs +16 -0
  60. package/components/loading/loading.mjs +26 -0
  61. package/components/loading/loading.test.mjs +10 -0
  62. package/components/navigation-bar/_old +582 -0
  63. package/components/navigation-bar/navigation-bar.mdx +20 -0
  64. package/components/navigation-bar/navigation-bar.stories.ts +39 -0
  65. package/components/navigation-drawer/_sidenav.scss +247 -0
  66. package/components/navigation-drawer/sidenav.ts +546 -0
  67. package/components/navigation-drawer/sidenavSpec.js +124 -0
  68. package/components/pagination/_pagination.scss +47 -0
  69. package/components/progress/_preloader.scss +416 -0
  70. package/components/radio-button/_radio-buttons.scss +112 -0
  71. package/components/radio-button/radio-buttons.mdx +28 -0
  72. package/components/radio-button/radio-buttons.stories.ts +51 -0
  73. package/components/search/autocomplete.ts +620 -0
  74. package/components/search/autocompleteSpec.js +321 -0
  75. package/components/slider/_range.scss +157 -0
  76. package/components/slider/range.ts +216 -0
  77. package/components/snackbar/_toast.scss +68 -0
  78. package/components/snackbar/toastSpec.js +132 -0
  79. package/components/snackbar/toasts.ts +312 -0
  80. package/components/switch/_switches.scss +121 -0
  81. package/components/tabs/_tabs.scss +171 -0
  82. package/components/tabs/tabs.mjs +31 -0
  83. package/components/tabs/tabs.ts +358 -0
  84. package/components/tabs/tabsSpec.js +180 -0
  85. package/components/textfield/_file-input.scss +41 -0
  86. package/components/textfield/_input-fields.scss +368 -0
  87. package/components/textfield/_select.scss +104 -0
  88. package/components/textfield/formfields.css +311 -0
  89. package/components/textfield/forms.ts +182 -0
  90. package/components/textfield/formsSpec.js +142 -0
  91. package/components/textfield/select.ts +472 -0
  92. package/components/textfield/selectSpec.js +390 -0
  93. package/components/textfield/textfield.mjs +29 -0
  94. package/components/textfield/textfield.test.mjs +10 -0
  95. package/components/timepicker/_timepicker.scss +362 -0
  96. package/components/timepicker/timepicker.ts +905 -0
  97. package/components/tooltip/_tooltip.scss +40 -0
  98. package/components/tooltip/tooltip.ts +380 -0
  99. package/components/tooltip/tooltipSpec.js +145 -0
  100. package/dist/css/materialize.colors.min.css +6 -0
  101. package/dist/css/materialize.css +7578 -6326
  102. package/dist/css/materialize.min.css +6 -13
  103. package/dist/css/materialize.min.css.map +1 -0
  104. package/dist/js/materialize.cjs.js +8410 -0
  105. package/dist/js/materialize.d.ts +2625 -0
  106. package/dist/js/materialize.js +8415 -12374
  107. package/dist/js/materialize.min.js +6 -6
  108. package/dist/js/materialize.mjs +8382 -0
  109. package/package.json +82 -47
  110. package/sass/_colors.scss +417 -0
  111. package/sass/_global.scss +490 -0
  112. package/sass/_grid.scss +172 -0
  113. package/sass/_table_of_contents.scss +28 -0
  114. package/sass/_tapTarget.scss +102 -0
  115. package/sass/_typography.scss +58 -0
  116. package/sass/_variables.scss +56 -0
  117. package/sass/materialize.scss +51 -0
  118. package/sass/mixins.module.scss +168 -0
  119. package/extras/noUiSlider/nouislider.css +0 -406
  120. package/extras/noUiSlider/nouislider.js +0 -2147
  121. package/extras/noUiSlider/nouislider.min.js +0 -1
  122. package/js/anime.min.js +0 -34
  123. package/js/autocomplete.js +0 -448
  124. package/js/buttons.js +0 -354
  125. package/js/cards.js +0 -40
  126. package/js/carousel.js +0 -717
  127. package/js/cash.js +0 -960
  128. package/js/characterCounter.js +0 -136
  129. package/js/chips.js +0 -481
  130. package/js/collapsible.js +0 -275
  131. package/js/component.js +0 -44
  132. package/js/datepicker.js +0 -975
  133. package/js/dropdown.js +0 -635
  134. package/js/forms.js +0 -275
  135. package/js/global.js +0 -444
  136. package/js/materialbox.js +0 -453
  137. package/js/modal.js +0 -382
  138. package/js/parallax.js +0 -138
  139. package/js/pushpin.js +0 -148
  140. package/js/range.js +0 -263
  141. package/js/scrollspy.js +0 -295
  142. package/js/select.js +0 -450
  143. package/js/sidenav.js +0 -580
  144. package/js/slider.js +0 -359
  145. package/js/tabs.js +0 -402
  146. package/js/tapTarget.js +0 -314
  147. package/js/timepicker.js +0 -647
  148. package/js/toasts.js +0 -310
  149. package/js/tooltip.js +0 -303
  150. package/js/waves.js +0 -335
@@ -0,0 +1,472 @@
1
+ import { Utils } from '../../src/utils';
2
+ import { Dropdown, DropdownOptions } from '../dropdown/dropdown';
3
+ import { Component, BaseOptions, InitElements, MElement } from '../../src/component';
4
+
5
+ export interface FormSelectOptions extends BaseOptions {
6
+ /**
7
+ * Classes to be added to the select wrapper element.
8
+ * @default ""
9
+ */
10
+ classes: string;
11
+ /**
12
+ * Pass options object to select dropdown initialization.
13
+ * @default {}
14
+ */
15
+ dropdownOptions: Partial<DropdownOptions>;
16
+ }
17
+
18
+ const _defaults: FormSelectOptions = {
19
+ classes: '',
20
+ dropdownOptions: {}
21
+ };
22
+
23
+ type ValueStruct = {
24
+ el: HTMLOptionElement;
25
+ optionEl: HTMLElement;
26
+ };
27
+
28
+ export class FormSelect extends Component<FormSelectOptions> {
29
+ declare el: HTMLSelectElement;
30
+ /** If this is a multiple select. */
31
+ isMultiple: boolean;
32
+ /**
33
+ * Label associated with the current select element.
34
+ * Is "null", if not detected.
35
+ */
36
+ labelEl: HTMLLabelElement;
37
+ /** Dropdown UL element. */
38
+ dropdownOptions: HTMLUListElement;
39
+ /** Text input that shows current selected option. */
40
+ input: HTMLInputElement;
41
+ /** Instance of the dropdown plugin for this select. */
42
+ dropdown: Dropdown;
43
+ /** The select wrapper element. */
44
+ wrapper: HTMLDivElement;
45
+ selectOptions: (HTMLOptionElement | HTMLOptGroupElement)[];
46
+ private _values: ValueStruct[];
47
+ nativeTabIndex: number;
48
+
49
+ constructor(el: HTMLSelectElement, options: FormSelectOptions) {
50
+ super(el, options, FormSelect);
51
+ if (this.el.classList.contains('browser-default')) return;
52
+ this.el['M_FormSelect'] = this;
53
+
54
+ this.options = {
55
+ ...FormSelect.defaults,
56
+ ...options
57
+ };
58
+
59
+ this.isMultiple = this.el.multiple;
60
+ this.nativeTabIndex = this.el.tabIndex ?? -1;
61
+ this.el.tabIndex = -1;
62
+ this._values = [];
63
+ this._setupDropdown();
64
+ this._setupEventHandlers();
65
+ }
66
+
67
+ static get defaults(): FormSelectOptions {
68
+ return _defaults;
69
+ }
70
+
71
+ /**
72
+ * Initializes instance of FormSelect.
73
+ * @param el HTML element.
74
+ * @param options Component options.
75
+ */
76
+ static init(el: HTMLSelectElement, options?: Partial<FormSelectOptions>): FormSelect;
77
+ /**
78
+ * Initializes instances of FormSelect.
79
+ * @param els HTML elements.
80
+ * @param options Component options.
81
+ */
82
+ static init(
83
+ els: InitElements<HTMLSelectElement | MElement>,
84
+ options?: Partial<FormSelectOptions>
85
+ ): FormSelect[];
86
+ /**
87
+ * Initializes instances of FormSelect.
88
+ * @param els HTML elements.
89
+ * @param options Component options.
90
+ */
91
+ static init(
92
+ els: HTMLSelectElement | InitElements<HTMLSelectElement | MElement>,
93
+ options: Partial<FormSelectOptions> = {}
94
+ ): FormSelect | FormSelect[] {
95
+ return super.init(els, options, FormSelect);
96
+ }
97
+
98
+ static getInstance(el: HTMLElement): FormSelect {
99
+ return el['M_FormSelect'];
100
+ }
101
+
102
+ destroy() {
103
+ this._removeEventHandlers();
104
+ this._removeDropdown();
105
+ this.el['M_FormSelect'] = undefined;
106
+ }
107
+
108
+ _setupEventHandlers() {
109
+ this.dropdownOptions.querySelectorAll('li:not(.optgroup)').forEach((el) => {
110
+ el.addEventListener('click', this._handleOptionClick);
111
+ el.addEventListener('keydown', (e: KeyboardEvent) => {
112
+ if (e.key === ' ' || e.key === 'Enter') this._handleOptionClick(e);
113
+ });
114
+ });
115
+ this.el.addEventListener('change', this._handleSelectChange);
116
+ this.input.addEventListener('click', this._handleInputClick);
117
+ }
118
+
119
+ _removeEventHandlers() {
120
+ this.dropdownOptions.querySelectorAll('li:not(.optgroup)').forEach((el) => {
121
+ el.removeEventListener('click', this._handleOptionClick);
122
+ });
123
+ this.el.removeEventListener('change', this._handleSelectChange);
124
+ this.input.removeEventListener('click', this._handleInputClick);
125
+ }
126
+
127
+ _handleSelectChange = () => {
128
+ this._setValueToInput();
129
+ };
130
+
131
+ _handleOptionClick = (e: MouseEvent | KeyboardEvent) => {
132
+ e.preventDefault();
133
+ const virtualOption = (e.target as HTMLLIElement).closest('li');
134
+ this._selectOptionElement(virtualOption);
135
+ e.stopPropagation();
136
+ };
137
+
138
+ _arraysEqual<T, E>(a: T[], b: (E | T)[]) {
139
+ if (a === b) return true;
140
+ if (a == null || b == null) return false;
141
+ if (a.length !== b.length) return false;
142
+ for (let i = 0; i < a.length; ++i) if (a[i] !== b[i]) return false;
143
+ return true;
144
+ }
145
+
146
+ _selectOptionElement(virtualOption: HTMLElement) {
147
+ if (
148
+ !virtualOption.classList.contains('disabled') &&
149
+ !virtualOption.classList.contains('optgroup')
150
+ ) {
151
+ const value = this._values.find((value) => value.optionEl === virtualOption);
152
+ const previousSelectedValues = this.getSelectedValues();
153
+ if (this.isMultiple) {
154
+ // Multi-Select
155
+ this._toggleEntryFromArray(value);
156
+ } else {
157
+ // Single-Select
158
+ this._deselectAll();
159
+ this._selectValue(value);
160
+ }
161
+ // Refresh Input-Text
162
+ this._setValueToInput();
163
+ // Trigger Change-Event only when data is different
164
+ const actualSelectedValues = this.getSelectedValues();
165
+ const selectionHasChanged = !this._arraysEqual(previousSelectedValues, actualSelectedValues);
166
+ if (selectionHasChanged)
167
+ this.el.dispatchEvent(
168
+ new Event('change', { bubbles: true, cancelable: true, composed: true })
169
+ ); // trigger('change');
170
+ }
171
+ if (!this.isMultiple) this.dropdown.close();
172
+ }
173
+
174
+ _handleInputClick = () => {
175
+ if (this.dropdown && this.dropdown.isOpen) {
176
+ this._setValueToInput();
177
+ this._setSelectedStates();
178
+ }
179
+ };
180
+
181
+ _setupDropdown() {
182
+ this.labelEl = document.querySelector('[for="' + this.el.id + '"]');
183
+
184
+ this.wrapper = document.createElement('div');
185
+ this.wrapper.classList.add('select-wrapper', 'input-field');
186
+ if (this.options.classes.length > 0) {
187
+ this.wrapper.classList.add(...this.options.classes.split(' '));
188
+ }
189
+ this.el.before(this.wrapper);
190
+
191
+ // Move actual select element into overflow hidden wrapper
192
+ const hiddenDiv = document.createElement('div');
193
+ hiddenDiv.classList.add('hide-select');
194
+ this.wrapper.append(hiddenDiv);
195
+ hiddenDiv.appendChild(this.el);
196
+
197
+ if (this.el.disabled) this.wrapper.classList.add('disabled');
198
+
199
+ this.selectOptions = <(HTMLOptGroupElement | HTMLOptionElement)[]>(
200
+ Array.from(this.el.children).filter((el) => ['OPTION', 'OPTGROUP'].includes(el.tagName))
201
+ );
202
+
203
+ // Create dropdown
204
+ this.dropdownOptions = document.createElement('ul');
205
+ this.dropdownOptions.id = `select-options-${Utils.guid()}`;
206
+ this.dropdownOptions.setAttribute('popover', 'auto');
207
+ this.dropdownOptions.classList.add('dropdown-content', 'select-dropdown');
208
+ this.dropdownOptions.setAttribute('role', 'listbox');
209
+ this.dropdownOptions.ariaMultiSelectable = this.isMultiple.toString();
210
+ if (this.isMultiple) this.dropdownOptions.classList.add('multiple-select-dropdown');
211
+
212
+ // Create dropdown structure
213
+ if (this.selectOptions.length > 0) {
214
+ this.selectOptions.forEach((realOption) => {
215
+ if (realOption.tagName === 'OPTION') {
216
+ // Option
217
+ const virtualOption = this._createAndAppendOptionWithIcon(
218
+ realOption,
219
+ this.isMultiple ? 'multiple' : undefined
220
+ );
221
+ this._addOptionToValues(realOption as HTMLOptionElement, virtualOption);
222
+ } else if (realOption.tagName === 'OPTGROUP') {
223
+ // Optgroup
224
+ const groupId = 'opt-group-' + Utils.guid();
225
+ const groupParent = document.createElement('li');
226
+ groupParent.classList.add('optgroup');
227
+ groupParent.tabIndex = -1;
228
+ groupParent.setAttribute('role', 'group');
229
+ groupParent.setAttribute('aria-labelledby', groupId);
230
+ groupParent.innerHTML = `<span id="${groupId}" role="presentation">${realOption.getAttribute(
231
+ 'label'
232
+ )}</span>`;
233
+ this.dropdownOptions.append(groupParent);
234
+
235
+ const groupChildren = [];
236
+ const selectOptions = <HTMLOptionElement[]>(
237
+ Array.from(realOption.children).filter((el) => el.tagName === 'OPTION')
238
+ );
239
+ selectOptions.forEach((realOption) => {
240
+ const virtualOption = this._createAndAppendOptionWithIcon(
241
+ realOption,
242
+ 'optgroup-option'
243
+ );
244
+ const childId = 'opt-child-' + Utils.guid();
245
+ virtualOption.id = childId;
246
+ groupChildren.push(childId);
247
+ this._addOptionToValues(realOption, virtualOption);
248
+ });
249
+ groupParent.setAttribute('aria-owns', groupChildren.join(' '));
250
+ }
251
+ });
252
+ }
253
+ this.wrapper.append(this.dropdownOptions);
254
+
255
+ // Add input dropdown
256
+ this.input = document.createElement('input');
257
+ this.input.id = 'm_select-input-' + Utils.guid();
258
+ this.input.classList.add('select-dropdown', 'dropdown-trigger');
259
+ this.input.type = 'text';
260
+ this.input.readOnly = true;
261
+ this.input.setAttribute('data-target', this.dropdownOptions.id);
262
+ this.input.ariaReadOnly = 'true';
263
+ this.input.ariaRequired = this.el.hasAttribute('required').toString(); //setAttribute("aria-required", this.el.hasAttribute("required"));
264
+ if (this.el.disabled) this.input.disabled = true; // 'true');
265
+ this.input.setAttribute('tabindex', this.nativeTabIndex.toString());
266
+
267
+ const attrs = this.el.attributes;
268
+ for (let i = 0; i < attrs.length; ++i) {
269
+ const attr = attrs[i];
270
+ if (attr.name.startsWith('aria-')) this.input.setAttribute(attr.name, attr.value);
271
+ }
272
+
273
+ // Adds aria-attributes to input element
274
+ this.input.setAttribute('role', 'combobox');
275
+ this.input.ariaExpanded = 'false';
276
+ this.input.setAttribute('aria-owns', this.dropdownOptions.id);
277
+ this.input.setAttribute('aria-controls', this.dropdownOptions.id);
278
+ this.input.placeholder = ' ';
279
+
280
+ this.wrapper.prepend(this.input);
281
+ this._setValueToInput();
282
+
283
+ // Add caret
284
+ const dropdownIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); //document.createElement('svg')
285
+ dropdownIcon.classList.add('caret');
286
+ dropdownIcon.setAttribute('height', '24');
287
+ dropdownIcon.setAttribute('width', '24');
288
+ dropdownIcon.setAttribute('viewBox', '0 0 24 24');
289
+ dropdownIcon.ariaHidden = 'true';
290
+ dropdownIcon.innerHTML = `<path d="M7 10l5 5 5-5z"/><path d="M0 0h24v24H0z" fill="none"/>`;
291
+ this.wrapper.prepend(dropdownIcon);
292
+
293
+ // Initialize dropdown
294
+ if (!this.el.disabled) {
295
+ const dropdownOptions = { ...this.options.dropdownOptions };
296
+ dropdownOptions.coverTrigger = false;
297
+ const userOnOpenEnd = dropdownOptions.onOpenEnd;
298
+ const userOnCloseEnd = dropdownOptions.onCloseEnd;
299
+ // Add callback for centering selected option when dropdown content is scrollable
300
+ dropdownOptions.onOpenEnd = () => {
301
+ const selectedOption = this.dropdownOptions.querySelector('.selected');
302
+ if (selectedOption) {
303
+ // Focus selected option in dropdown
304
+ Utils.keyDown = true;
305
+ this.dropdown.focusedIndex = [...selectedOption.parentNode.children].indexOf(
306
+ selectedOption
307
+ );
308
+ this.dropdown._focusFocusedItem();
309
+ Utils.keyDown = false;
310
+ // Handle scrolling to selected option
311
+ if (this.dropdown.isScrollable) {
312
+ let scrollOffset =
313
+ selectedOption.getBoundingClientRect().top -
314
+ (this.dropdownOptions as HTMLElement).getBoundingClientRect().top; // scroll to selected option
315
+ scrollOffset -= this.dropdownOptions.clientHeight / 2; // center in dropdown
316
+ this.dropdownOptions.scrollTop = scrollOffset;
317
+ }
318
+ }
319
+ this.input.ariaExpanded = 'true';
320
+ // Handle user declared onOpenEnd if needed
321
+ if (userOnOpenEnd && typeof userOnOpenEnd === 'function')
322
+ userOnOpenEnd.call(this.dropdown, this.el);
323
+ };
324
+ // Add callback for reseting "expanded" state
325
+ dropdownOptions.onCloseEnd = () => {
326
+ this.input.ariaExpanded = 'false';
327
+ // Handle user declared onOpenEnd if needed
328
+ if (userOnCloseEnd && typeof userOnCloseEnd === 'function')
329
+ userOnCloseEnd.call(this.dropdown, this.el);
330
+ };
331
+ // Prevent dropdown from closing too early
332
+ dropdownOptions.closeOnClick = false;
333
+ this.dropdown = Dropdown.init(this.input, dropdownOptions);
334
+ }
335
+ // Add initial selections
336
+ this._setSelectedStates();
337
+ // move label
338
+ if (this.labelEl) this.input.after(this.labelEl);
339
+ }
340
+
341
+ _addOptionToValues(realOption: HTMLOptionElement, virtualOption: HTMLElement) {
342
+ this._values.push({ el: realOption, optionEl: virtualOption });
343
+ }
344
+
345
+ _removeDropdown() {
346
+ this.wrapper.querySelector('.caret').remove();
347
+ this.input.remove();
348
+ this.dropdownOptions.remove();
349
+ this.wrapper.before(this.el);
350
+ this.wrapper.remove();
351
+ }
352
+
353
+ _createAndAppendOptionWithIcon(
354
+ realOption: HTMLOptionElement | HTMLOptGroupElement,
355
+ type: string
356
+ ) {
357
+ const li = document.createElement('li');
358
+ li.setAttribute('role', 'option');
359
+ if (realOption.disabled) {
360
+ li.classList.add('disabled');
361
+ li.ariaDisabled = 'true';
362
+ }
363
+ if (type === 'optgroup-option') li.classList.add(type);
364
+
365
+ // Text / Checkbox
366
+ const span = document.createElement('span');
367
+ span.innerHTML = realOption.innerHTML;
368
+ if (this.isMultiple && !realOption.disabled) {
369
+ span.innerHTML = `<label><input type="checkbox"><span>${realOption.innerHTML}</span></label>`;
370
+ }
371
+ li.appendChild(span);
372
+
373
+ // add Icon
374
+ const iconUrl = realOption.getAttribute('data-icon');
375
+ const classes = realOption.getAttribute('class')?.split(' ');
376
+ if (iconUrl) {
377
+ const img = document.createElement('img');
378
+ if (classes) img.classList.add(...classes);
379
+ img.src = iconUrl;
380
+ img.ariaHidden = 'true';
381
+ li.prepend(img);
382
+ }
383
+ // Check for multiple type
384
+ this.dropdownOptions.append(li);
385
+ return li;
386
+ }
387
+
388
+ _selectValue(value: ValueStruct) {
389
+ value.el.selected = true;
390
+ value.optionEl.classList.add('selected');
391
+ value.optionEl.ariaSelected = 'true'; // setAttribute("aria-selected", true);
392
+ const checkbox = <HTMLInputElement>value.optionEl.querySelector('input[type="checkbox"]');
393
+ if (checkbox) checkbox.checked = true;
394
+ }
395
+
396
+ _deselectValue(value: ValueStruct) {
397
+ value.el.selected = false;
398
+ value.optionEl.classList.remove('selected');
399
+ value.optionEl.ariaSelected = 'false'; //setAttribute("aria-selected", false);
400
+ const checkbox = <HTMLInputElement>value.optionEl.querySelector('input[type="checkbox"]');
401
+ if (checkbox) checkbox.checked = false;
402
+ }
403
+
404
+ _deselectAll() {
405
+ this._values.forEach((value) => this._deselectValue(value));
406
+ }
407
+
408
+ _isValueSelected(value: ValueStruct) {
409
+ const realValues = this.getSelectedValues();
410
+ return realValues.some((realValue) => realValue === value.el.value);
411
+ }
412
+
413
+ _toggleEntryFromArray(value: ValueStruct) {
414
+ if (this._isValueSelected(value)) this._deselectValue(value);
415
+ else this._selectValue(value);
416
+ }
417
+
418
+ _getSelectedOptions(): HTMLOptionElement[] {
419
+ // remove null, false, ... values
420
+ return Array.prototype.filter.call(
421
+ this.el.selectedOptions,
422
+ (realOption: HTMLOptionElement) => realOption
423
+ );
424
+ }
425
+
426
+ _setValueToInput() {
427
+ const selectedRealOptions = this._getSelectedOptions();
428
+ const selectedOptionPairs = this._values.filter(
429
+ (value) => selectedRealOptions.indexOf(value.el) >= 0
430
+ );
431
+ // Filter not disabled
432
+ const notDisabledOptionPairs = selectedOptionPairs.filter((op) => !op.el.disabled);
433
+ const texts = notDisabledOptionPairs.map((value) =>
434
+ value.optionEl.querySelector('span').innerText.trim()
435
+ );
436
+ // Set input-text to first Option with empty value which indicates a description like "choose your option"
437
+ if (texts.length === 0) {
438
+ const firstDisabledOption = <HTMLOptionElement>this.el.querySelector('option:disabled');
439
+ if (firstDisabledOption && firstDisabledOption.value === '') {
440
+ this.input.value = firstDisabledOption.innerText;
441
+ return;
442
+ }
443
+ }
444
+ this.input.value = texts.join(', ');
445
+ }
446
+
447
+ _setSelectedStates() {
448
+ this._values.forEach((value) => {
449
+ const optionIsSelected = value.el.selected;
450
+ const cb = <HTMLInputElement>value.optionEl.querySelector('input[type="checkbox"]');
451
+ if (cb) cb.checked = optionIsSelected;
452
+ if (optionIsSelected) {
453
+ this._activateOption(this.dropdownOptions, value.optionEl);
454
+ } else {
455
+ value.optionEl.classList.remove('selected');
456
+ value.optionEl.ariaSelected = 'false'; // attr("aria-selected", 'false');
457
+ }
458
+ });
459
+ }
460
+
461
+ _activateOption(ul: HTMLElement, li: HTMLElement) {
462
+ if (!li) return;
463
+ if (!this.isMultiple)
464
+ ul.querySelectorAll('li.selected').forEach((li) => li.classList.remove('selected'));
465
+ li.classList.add('selected');
466
+ li.ariaSelected = 'true';
467
+ }
468
+
469
+ getSelectedValues() {
470
+ return this._getSelectedOptions().map((realOption) => realOption.value);
471
+ }
472
+ }