@materializecss/materialize 2.0.1-alpha → 2.0.2-alpha

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 (45) hide show
  1. package/Gruntfile.js +5 -2
  2. package/dist/css/materialize.css +90 -86
  3. package/dist/css/materialize.min.css +2 -2
  4. package/dist/js/materialize.js +2797 -2705
  5. package/dist/js/materialize.min.js +2 -8967
  6. package/dist/js/materialize.min.js.map +1 -1
  7. package/package.json +1 -1
  8. package/sass/components/_collapsible.scss +0 -41
  9. package/sass/components/_global.scss +3 -2
  10. package/sass/components/_icons-material-design.scss +2 -1
  11. package/sass/components/_navbar.scss +6 -3
  12. package/sass/components/_sidenav.scss +66 -37
  13. package/sass/components/_theme_variables.scss +2 -2
  14. package/sass/components/_typography.scss +2 -2
  15. package/sass/components/forms/_input-fields.scss +4 -10
  16. package/sass/materialize.scss +0 -4
  17. package/src/autocomplete.ts +188 -94
  18. package/src/buttons.ts +225 -260
  19. package/src/cards.ts +5 -6
  20. package/src/carousel.ts +611 -542
  21. package/src/characterCounter.ts +50 -21
  22. package/src/chips.ts +152 -63
  23. package/src/collapsible.ts +97 -32
  24. package/src/component.ts +99 -10
  25. package/src/datepicker.ts +905 -726
  26. package/src/dropdown.ts +576 -484
  27. package/src/edges.ts +4 -4
  28. package/src/forms.ts +17 -14
  29. package/src/global.ts +55 -324
  30. package/src/materialbox.ts +354 -298
  31. package/src/modal.ts +296 -211
  32. package/src/parallax.ts +129 -105
  33. package/src/pushpin.ts +148 -103
  34. package/src/range.ts +166 -150
  35. package/src/scrollspy.ts +214 -174
  36. package/src/select.ts +434 -398
  37. package/src/sidenav.ts +447 -381
  38. package/src/slider.ts +421 -362
  39. package/src/tabs.ts +276 -222
  40. package/src/tapTarget.ts +246 -213
  41. package/src/timepicker.ts +738 -614
  42. package/src/toasts.ts +254 -230
  43. package/src/tooltip.ts +315 -252
  44. package/src/utils.ts +271 -0
  45. package/src/waves.ts +10 -10
@@ -1,8 +1,74 @@
1
- import { Component } from "./component";
2
- import { M } from "./global";
3
- import { Dropdown } from "./dropdown";
1
+ import { Utils } from "./utils";
2
+ import { Dropdown, DropdownOptions } from "./dropdown";
3
+ import { Component, BaseOptions, InitElements, MElement } from "./component";
4
+
5
+ export interface AutocompleteData {
6
+ /**
7
+ * A primitive value that can be converted to string.
8
+ * If "text" is not provided, it will also be used as "option text" as well
9
+ */
10
+ id: string | number;
11
+ /**
12
+ * This optional attribute is used as "display value" for the current entry.
13
+ * When provided, it will also be taken into consideration by the standard search function.
14
+ */
15
+ text?: string;
16
+ /**
17
+ * This optional attribute is used to provide a valid image URL to the current option.
18
+ */
19
+ image?: string;
20
+ /**
21
+ * Optional attributes which describes the option.
22
+ */
23
+ description?: string;
24
+ }
25
+
26
+ export interface AutocompleteOptions extends BaseOptions {
27
+ /**
28
+ * Data object defining autocomplete options with
29
+ * optional icon strings.
30
+ */
31
+ data: AutocompleteData[];
32
+ /**
33
+ * Flag which can be set if multiple values can be selected. The Result will be an Array.
34
+ * @default false
35
+ */
36
+ isMultiSelect: boolean;
37
+ /**
38
+ * Callback for when autocompleted.
39
+ */
40
+ onAutocomplete: (entries: AutocompleteData[]) => void;
41
+ /**
42
+ * Minimum number of characters before autocomplete starts.
43
+ * @default 1
44
+ */
45
+ minLength: number;
46
+ /**
47
+ * The height of the Menu which can be set via css-property.
48
+ * @default '300px'
49
+ */
50
+ maxDropDownHeight: string;
51
+ /**
52
+ * Function is called when the input text is altered and data can also be loaded asynchronously.
53
+ * If the results are collected the items in the list can be updated via the function setMenuItems(collectedItems).
54
+ * @param text Searched text.
55
+ * @param autocomplete Current autocomplete instance.
56
+ */
57
+ onSearch: (text: string, autocomplete: Autocomplete) => void;
58
+ /**
59
+ * If true will render the key from each item directly as HTML.
60
+ * User input MUST be properly sanitized first.
61
+ * @default false
62
+ */
63
+ allowUnsafeHTML: boolean;
64
+ /**
65
+ * Pass options object to select dropdown initialization.
66
+ * @default {}
67
+ */
68
+ dropdownOptions: Partial<DropdownOptions>;
69
+ };
4
70
 
5
- let _defaults = {
71
+ let _defaults: AutocompleteOptions = {
6
72
  data: [], // Autocomplete data set
7
73
  onAutocomplete: null, // Callback for when autocompleted
8
74
  dropdownOptions: {
@@ -13,49 +79,52 @@ let _defaults = {
13
79
  },
14
80
  minLength: 1, // Min characters before autocomplete starts
15
81
  isMultiSelect: false,
16
- onSearch: function(text, autocomplete) {
17
- const filteredData = autocomplete.options.data.filter(item => {
18
- return Object.keys(item)
19
- .map(key => item[key].toString().toLowerCase().indexOf(text.toLowerCase()) >= 0)
20
- .some(isMatch => isMatch);
21
- });
22
- autocomplete.setMenuItems(filteredData);
82
+ onSearch: (text: string, autocomplete: Autocomplete) => {
83
+ const normSearch = text.toLocaleLowerCase();
84
+ autocomplete.setMenuItems(
85
+ autocomplete.options.data.filter((option) =>
86
+ option.id.toString().toLocaleLowerCase().includes(normSearch)
87
+ || option.text?.toLocaleLowerCase().includes(normSearch)
88
+ )
89
+ );
23
90
  },
24
91
  maxDropDownHeight: '300px',
25
92
  allowUnsafeHTML: false
26
93
  };
27
94
 
28
95
 
29
- export class Autocomplete extends Component {
30
- el: HTMLInputElement;
96
+ export class Autocomplete extends Component<AutocompleteOptions> {
97
+ declare el: HTMLInputElement;
98
+ /** If the autocomplete is open. */
31
99
  isOpen: boolean;
100
+ /** Number of matching autocomplete options. */
32
101
  count: number;
102
+ /** Index of the current selected option. */
33
103
  activeIndex: number;
34
- private oldVal: any;
35
- private $inputField: any;
104
+ private oldVal: string;
36
105
  private $active: HTMLElement|null;
37
106
  private _mousedown: boolean;
38
- private _handleInputBlurBound: any;
39
- private _handleInputKeyupAndFocusBound: any;
40
- private _handleInputKeydownBound: any;
41
- private _handleInputClickBound: any;
42
- private _handleContainerMousedownAndTouchstartBound: any;
43
- private _handleContainerMouseupAndTouchendBound: any;
44
107
  container: HTMLElement;
108
+ /** Instance of the dropdown plugin for this autocomplete. */
45
109
  dropdown: Dropdown;
46
110
  static _keydown: boolean;
47
- selectedValues: any[];
48
- menuItems: any[];
111
+ selectedValues: AutocompleteData[];
112
+ menuItems: AutocompleteData[];
49
113
 
50
114
 
51
- constructor(el, options) {
52
- super(Autocomplete, el, options);
115
+ constructor(el: HTMLInputElement, options: Partial<AutocompleteOptions>) {
116
+ super(el, options, Autocomplete);
53
117
  (this.el as any).M_Autocomplete = this;
54
- this.options = {...Autocomplete.defaults, ...options};
118
+
119
+ this.options = {
120
+ ...Autocomplete.defaults,
121
+ ...options
122
+ };
123
+
55
124
  this.isOpen = false;
56
125
  this.count = 0;
57
126
  this.activeIndex = -1;
58
- this.oldVal;
127
+ this.oldVal = "";
59
128
  this.selectedValues = [];
60
129
  this.menuItems = [];
61
130
  this.$active = null;
@@ -63,15 +132,34 @@ export class Autocomplete extends Component {
63
132
  this._setupDropdown();
64
133
  this._setupEventHandlers();
65
134
  }
66
- static get defaults() {
135
+
136
+ static get defaults(): AutocompleteOptions {
67
137
  return _defaults;
68
138
  }
69
- static init(els, options) {
70
- return super.init(this, els, options);
139
+
140
+ /**
141
+ * Initializes instance of Autocomplete.
142
+ * @param el HTML element.
143
+ * @param options Component options.
144
+ */
145
+ static init(el: HTMLInputElement, options?: Partial<AutocompleteOptions>): Autocomplete;
146
+ /**
147
+ * Initializes instances of Autocomplete.
148
+ * @param els HTML elements.
149
+ * @param options Component options.
150
+ */
151
+ static init(els: InitElements<HTMLInputElement | MElement>, options?: Partial<AutocompleteOptions>): Autocomplete[];
152
+ /**
153
+ * Initializes instances of Autocomplete.
154
+ * @param els HTML elements.
155
+ * @param options Component options.
156
+ */
157
+ static init(els: HTMLInputElement | InitElements<HTMLInputElement | MElement>, options: Partial<AutocompleteOptions> = {}): Autocomplete | Autocomplete[] {
158
+ return super.init(els, options, Autocomplete);
71
159
  }
72
- static getInstance(el) {
73
- let domElem = el.jquery ? el[0] : el;
74
- return domElem.M_Autocomplete;
160
+
161
+ static getInstance(el: HTMLElement): Autocomplete {
162
+ return (el as any).M_Autocomplete;
75
163
  }
76
164
 
77
165
  destroy() {
@@ -81,68 +169,58 @@ export class Autocomplete extends Component {
81
169
  }
82
170
 
83
171
  _setupEventHandlers() {
84
- this._handleInputBlurBound = this._handleInputBlur.bind(this);
85
- this._handleInputKeyupAndFocusBound = this._handleInputKeyupAndFocus.bind(this);
86
- this._handleInputKeydownBound = this._handleInputKeydown.bind(this);
87
- this._handleInputClickBound = this._handleInputClick.bind(this);
88
- this._handleContainerMousedownAndTouchstartBound = this._handleContainerMousedownAndTouchstart.bind(
89
- this
90
- );
91
- this._handleContainerMouseupAndTouchendBound = this._handleContainerMouseupAndTouchend.bind(
92
- this
93
- );
94
- this.el.addEventListener('blur', this._handleInputBlurBound);
95
- this.el.addEventListener('keyup', this._handleInputKeyupAndFocusBound);
96
- this.el.addEventListener('focus', this._handleInputKeyupAndFocusBound);
97
- this.el.addEventListener('keydown', this._handleInputKeydownBound);
98
- this.el.addEventListener('click', this._handleInputClickBound);
172
+ this.el.addEventListener('blur', this._handleInputBlur);
173
+ this.el.addEventListener('keyup', this._handleInputKeyupAndFocus);
174
+ this.el.addEventListener('focus', this._handleInputKeyupAndFocus);
175
+ this.el.addEventListener('keydown', this._handleInputKeydown);
176
+ this.el.addEventListener('click', this._handleInputClick);
99
177
  this.container.addEventListener(
100
178
  'mousedown',
101
- this._handleContainerMousedownAndTouchstartBound
179
+ this._handleContainerMousedownAndTouchstart
102
180
  );
103
- this.container.addEventListener('mouseup', this._handleContainerMouseupAndTouchendBound);
181
+ this.container.addEventListener('mouseup', this._handleContainerMouseupAndTouchend);
104
182
  if (typeof window.ontouchstart !== 'undefined') {
105
183
  this.container.addEventListener(
106
184
  'touchstart',
107
- this._handleContainerMousedownAndTouchstartBound
185
+ this._handleContainerMousedownAndTouchstart
108
186
  );
109
- this.container.addEventListener('touchend', this._handleContainerMouseupAndTouchendBound);
187
+ this.container.addEventListener('touchend', this._handleContainerMouseupAndTouchend);
110
188
  }
111
189
  }
112
190
 
113
191
  _removeEventHandlers() {
114
- this.el.removeEventListener('blur', this._handleInputBlurBound);
115
- this.el.removeEventListener('keyup', this._handleInputKeyupAndFocusBound);
116
- this.el.removeEventListener('focus', this._handleInputKeyupAndFocusBound);
117
- this.el.removeEventListener('keydown', this._handleInputKeydownBound);
118
- this.el.removeEventListener('click', this._handleInputClickBound);
192
+ this.el.removeEventListener('blur', this._handleInputBlur);
193
+ this.el.removeEventListener('keyup', this._handleInputKeyupAndFocus);
194
+ this.el.removeEventListener('focus', this._handleInputKeyupAndFocus);
195
+ this.el.removeEventListener('keydown', this._handleInputKeydown);
196
+ this.el.removeEventListener('click', this._handleInputClick);
119
197
  this.container.removeEventListener(
120
198
  'mousedown',
121
- this._handleContainerMousedownAndTouchstartBound
199
+ this._handleContainerMousedownAndTouchstart
122
200
  );
123
- this.container.removeEventListener('mouseup', this._handleContainerMouseupAndTouchendBound);
201
+ this.container.removeEventListener('mouseup', this._handleContainerMouseupAndTouchend);
124
202
 
125
203
  if (typeof window.ontouchstart !== 'undefined') {
126
204
  this.container.removeEventListener(
127
205
  'touchstart',
128
- this._handleContainerMousedownAndTouchstartBound
206
+ this._handleContainerMousedownAndTouchstart
129
207
  );
130
208
  this.container.removeEventListener(
131
209
  'touchend',
132
- this._handleContainerMouseupAndTouchendBound
210
+ this._handleContainerMouseupAndTouchend
133
211
  );
134
212
  }
135
213
  }
136
214
 
137
- _setupDropdown() {
215
+ _setupDropdown() {
138
216
  this.container = document.createElement('ul');
139
217
  this.container.style.maxHeight = this.options.maxDropDownHeight;
140
- this.container.id = `autocomplete-options-${M.guid()}`;
218
+ this.container.id = `autocomplete-options-${Utils.guid()}`;
141
219
  this.container.classList.add('autocomplete-content', 'dropdown-content');
142
220
  this.el.setAttribute('data-target', this.container.id);
143
221
 
144
222
  // ! Issue in Component Dropdown: _placeDropdown moves dom-position
145
- this.el.parentElement.appendChild(this.container);
223
+ this.el.parentElement.appendChild(this.container);
146
224
 
147
225
  // Initialize dropdown
148
226
  let dropdownOptions = {
@@ -159,7 +237,7 @@ export class Autocomplete extends Component {
159
237
  if (userOnItemClick && typeof userOnItemClick === 'function')
160
238
  userOnItemClick.call(this.dropdown, this.el);
161
239
  };
162
- this.dropdown = M.Dropdown.init(this.el, dropdownOptions);
240
+ this.dropdown = Dropdown.init(this.el, dropdownOptions);
163
241
 
164
242
  // ! Workaround for Label: move label up again
165
243
  // TODO: Just use PopperJS in future!
@@ -167,14 +245,14 @@ export class Autocomplete extends Component {
167
245
  if (label) this.el.after(label);
168
246
 
169
247
  // Sketchy removal of dropdown click handler
170
- this.el.removeEventListener('click', this.dropdown._handleClickBound);
248
+ this.el.removeEventListener('click', this.dropdown._handleClick);
171
249
  // Set Value if already set in HTML
172
250
  if (this.el.value) this.selectOption(this.el.value);
173
251
  // Add StatusInfo
174
252
  const div = document.createElement('div');
175
253
  div.classList.add('status-info');
176
254
  div.setAttribute('style', 'position: absolute;right:0;top:0;');
177
- this.el.parentElement.appendChild(div);
255
+ this.el.parentElement.appendChild(div);
178
256
  this._updateSelectedInfo();
179
257
  }
180
258
 
@@ -182,22 +260,22 @@ export class Autocomplete extends Component {
182
260
  this.container.parentNode.removeChild(this.container);
183
261
  }
184
262
 
185
- _handleInputBlur() {
263
+ _handleInputBlur = () => {
186
264
  if (!this._mousedown) {
187
265
  this.close();
188
266
  this._resetAutocomplete();
189
267
  }
190
268
  }
191
269
 
192
- _handleInputKeyupAndFocus(e) {
270
+ _handleInputKeyupAndFocus = (e: KeyboardEvent) => {
193
271
  if (e.type === 'keyup') Autocomplete._keydown = false;
194
272
  this.count = 0;
195
- const actualValue = this.el.value.toLowerCase();
273
+ const actualValue = this.el.value.toLocaleLowerCase();
196
274
  // Don't capture enter or arrow key usage.
197
- if (e.keyCode === 13 || e.keyCode === 38 || e.keyCode === 40) return;
275
+ if (Utils.keys.ENTER.includes(e.key) || Utils.keys.ARROW_UP.includes(e.key) || Utils.keys.ARROW_DOWN.includes(e.key)) return;
198
276
  // Check if the input isn't empty
199
277
  // Check if focus triggered by tab
200
- if (this.oldVal !== actualValue && (M.tabPressed || e.type !== 'focus')) {
278
+ if (this.oldVal !== actualValue && (Utils.tabPressed || e.type !== 'focus')) {
201
279
  this.open();
202
280
  }
203
281
  // Value has changed!
@@ -213,13 +291,12 @@ export class Autocomplete extends Component {
213
291
  this.oldVal = actualValue;
214
292
  }
215
293
 
216
- _handleInputKeydown(e) {
294
+ _handleInputKeydown = (e: KeyboardEvent) => {
217
295
  Autocomplete._keydown = true;
218
296
  // Arrow keys and enter key usage
219
- const keyCode = e.keyCode;
220
297
  const numItems = this.container.querySelectorAll('li').length;
221
298
  // select element on Enter
222
- if (keyCode === M.keys.ENTER && this.activeIndex >= 0) {
299
+ if (Utils.keys.ENTER.includes(e.key) && this.activeIndex >= 0) {
223
300
  const liElement = this.container.querySelectorAll('li')[this.activeIndex];
224
301
  if (liElement) {
225
302
  this.selectOption(liElement.getAttribute('data-id'));
@@ -228,10 +305,10 @@ export class Autocomplete extends Component {
228
305
  return;
229
306
  }
230
307
  // Capture up and down key
231
- if (keyCode === M.keys.ARROW_UP || keyCode === M.keys.ARROW_DOWN) {
308
+ if (Utils.keys.ARROW_UP.includes(e.key) || Utils.keys.ARROW_DOWN.includes(e.key)) {
232
309
  e.preventDefault();
233
- if (keyCode === M.keys.ARROW_UP && this.activeIndex > 0) this.activeIndex--;
234
- if (keyCode === M.keys.ARROW_DOWN && this.activeIndex < numItems - 1) this.activeIndex++;
310
+ if (Utils.keys.ARROW_UP.includes(e.key) && this.activeIndex > 0) this.activeIndex--;
311
+ if (Utils.keys.ARROW_DOWN.includes(e.key) && this.activeIndex < numItems - 1) this.activeIndex++;
235
312
  this.$active?.classList.remove('active');
236
313
  if (this.activeIndex >= 0) {
237
314
  this.$active = this.container.querySelectorAll('li')[this.activeIndex];
@@ -246,15 +323,15 @@ export class Autocomplete extends Component {
246
323
  }
247
324
  }
248
325
 
249
- _handleInputClick(e) {
326
+ _handleInputClick = () => {
250
327
  this.open();
251
328
  }
252
329
 
253
- _handleContainerMousedownAndTouchstart(e) {
330
+ _handleContainerMousedownAndTouchstart = () => {
254
331
  this._mousedown = true;
255
332
  }
256
333
 
257
- _handleContainerMouseupAndTouchend(e) {
334
+ _handleContainerMouseupAndTouchend = () => {
258
335
  this._mousedown = false;
259
336
  }
260
337
 
@@ -271,8 +348,8 @@ export class Autocomplete extends Component {
271
348
  this._mousedown = false;
272
349
  }
273
350
 
274
- _highlightPartialText(input, label) {
275
- const start = label.toLowerCase().indexOf('' + input.toLowerCase() + '');
351
+ _highlightPartialText(input: string, label: string) {
352
+ const start = label.toLocaleLowerCase().indexOf('' + input.toLocaleLowerCase() + '');
276
353
  const end = start + input.length - 1;
277
354
  //custom filters may return results where the string does not match any part
278
355
  if (start == -1 || end == -1) {
@@ -281,9 +358,9 @@ export class Autocomplete extends Component {
281
358
  return [label.slice(0, start), label.slice(start, end + 1), label.slice(end + 1)];
282
359
  }
283
360
 
284
- _createDropdownItem(entry) {
361
+ _createDropdownItem(entry: AutocompleteData) {
285
362
  const item = document.createElement('li');
286
- item.setAttribute('data-id', entry.id);
363
+ item.setAttribute('data-id', <string>entry.id);
287
364
  item.setAttribute(
288
365
  'style',
289
366
  'display:grid; grid-auto-flow: column; user-select: none; align-items: center;'
@@ -306,7 +383,7 @@ export class Autocomplete extends Component {
306
383
  }
307
384
 
308
385
  // Text
309
- const inputText = this.el.value.toLowerCase();
386
+ const inputText = this.el.value.toLocaleLowerCase();
310
387
  const parts = this._highlightPartialText(inputText, (entry.text || entry.id).toString());
311
388
  const div = document.createElement('div');
312
389
  div.setAttribute('style', 'line-height:1.2;font-weight:500;');
@@ -384,7 +461,7 @@ export class Autocomplete extends Component {
384
461
  _refreshInputText() {
385
462
  if (this.selectedValues.length === 1) {
386
463
  const entry = this.selectedValues[0];
387
- this.el.value = entry.text || entry.id; // Write Text to Input
464
+ this.el.value = entry.text || <string>entry.id; // Write Text to Input
388
465
  }
389
466
  }
390
467
 
@@ -395,8 +472,11 @@ export class Autocomplete extends Component {
395
472
  this.options.onAutocomplete.call(this, this.selectedValues);
396
473
  }
397
474
 
398
- open() {
399
- const inputText = this.el.value.toLowerCase();
475
+ /**
476
+ * Show autocomplete.
477
+ */
478
+ open = () => {
479
+ const inputText = this.el.value.toLocaleLowerCase();
400
480
  this._resetAutocomplete();
401
481
  if (inputText.length >= this.options.minLength) {
402
482
  this.isOpen = true;
@@ -411,17 +491,28 @@ export class Autocomplete extends Component {
411
491
  else this.dropdown.recalculateDimensions(); // Recalculate dropdown when its already open
412
492
  }
413
493
 
414
- close() {
494
+ /**
495
+ * Hide autocomplete.
496
+ */
497
+ close = () => {
415
498
  this.dropdown.close();
416
499
  }
417
500
 
418
- setMenuItems(menuItems) {
501
+ /**
502
+ * Updates the visible or selectable items shown in the menu.
503
+ * @param menuItems Items to be available.
504
+ */
505
+ setMenuItems(menuItems: AutocompleteData[]) {
419
506
  this.menuItems = menuItems;
420
507
  this.open();
421
508
  this._updateSelectedInfo();
422
509
  }
423
510
 
424
- setValues(entries) {
511
+ /**
512
+ * Sets selected values.
513
+ * @param entries
514
+ */
515
+ setValues(entries: AutocompleteData[]) {
425
516
  this.selectedValues = entries;
426
517
  this._updateSelectedInfo();
427
518
  if (!this.options.isMultiSelect) {
@@ -430,7 +521,11 @@ export class Autocomplete extends Component {
430
521
  this._triggerChanged();
431
522
  }
432
523
 
433
- selectOption(id) {
524
+ /**
525
+ * Select a specific autocomplete option via id-property.
526
+ * @param id The id of a data-entry.
527
+ */
528
+ selectOption(id: number | string) {
434
529
  const entry = this.menuItems.find((item) => item.id == id);
435
530
  if (!entry) return;
436
531
  // Toggle Checkbox
@@ -456,4 +551,3 @@ export class Autocomplete extends Component {
456
551
  this._triggerChanged();
457
552
  }
458
553
  }
459
-