mithril-materialized 3.3.7 → 3.4.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.
package/dist/index.js CHANGED
@@ -434,6 +434,103 @@ const Icon = () => ({
434
434
  },
435
435
  });
436
436
 
437
+ /*!
438
+ * Waves Effect for Mithril Materialized
439
+ * Based on Waves v0.6.4 by Alfiana E. Sibuea
440
+ * Adapted for TypeScript and Mithril integration
441
+ */
442
+ class WavesEffect {
443
+ static offset(elem) {
444
+ const rect = elem.getBoundingClientRect();
445
+ return {
446
+ top: rect.top + window.pageYOffset,
447
+ left: rect.left + window.pageXOffset
448
+ };
449
+ }
450
+ static createRipple(e, element) {
451
+ // Disable right click
452
+ if (e.button === 2) {
453
+ return;
454
+ }
455
+ // Create ripple element
456
+ const ripple = document.createElement('div');
457
+ ripple.className = 'waves-ripple';
458
+ // Get click position relative to element
459
+ const pos = this.offset(element);
460
+ const relativeY = e.pageY - pos.top;
461
+ const relativeX = e.pageX - pos.left;
462
+ // Calculate scale based on element size
463
+ const scale = (element.clientWidth / 100) * 10;
464
+ // Set initial ripple position and style
465
+ ripple.style.cssText = `
466
+ top: ${relativeY}px;
467
+ left: ${relativeX}px;
468
+ transform: scale(0);
469
+ opacity: 1;
470
+ `;
471
+ // Add ripple to element
472
+ element.appendChild(ripple);
473
+ // Force reflow and animate
474
+ ripple.offsetHeight;
475
+ ripple.style.transform = `scale(${scale})`;
476
+ ripple.style.opacity = '1';
477
+ // Store reference for cleanup
478
+ ripple.setAttribute('data-created', Date.now().toString());
479
+ }
480
+ static removeRipples(element) {
481
+ const ripples = element.querySelectorAll('.waves-ripple');
482
+ ripples.forEach((ripple) => {
483
+ const created = parseInt(ripple.getAttribute('data-created') || '0');
484
+ const age = Date.now() - created;
485
+ const fadeOut = () => {
486
+ ripple.style.opacity = '0';
487
+ setTimeout(() => {
488
+ if (ripple.parentNode) {
489
+ ripple.parentNode.removeChild(ripple);
490
+ }
491
+ }, this.duration);
492
+ };
493
+ if (age >= 350) {
494
+ fadeOut();
495
+ }
496
+ else {
497
+ setTimeout(fadeOut, 350 - age);
498
+ }
499
+ });
500
+ }
501
+ }
502
+ WavesEffect.duration = 750;
503
+ WavesEffect.onMouseDown = (e) => {
504
+ const element = e.currentTarget;
505
+ if (element && element.classList.contains('waves-effect')) {
506
+ WavesEffect.createRipple(e, element);
507
+ }
508
+ };
509
+ WavesEffect.onMouseUp = (e) => {
510
+ const element = e.currentTarget;
511
+ if (element && element.classList.contains('waves-effect')) {
512
+ WavesEffect.removeRipples(element);
513
+ }
514
+ };
515
+ WavesEffect.onMouseLeave = (e) => {
516
+ const element = e.currentTarget;
517
+ if (element && element.classList.contains('waves-effect')) {
518
+ WavesEffect.removeRipples(element);
519
+ }
520
+ };
521
+ WavesEffect.onTouchStart = (e) => {
522
+ const element = e.currentTarget;
523
+ if (element && element.classList.contains('waves-effect')) {
524
+ WavesEffect.createRipple(e, element);
525
+ }
526
+ };
527
+ WavesEffect.onTouchEnd = (e) => {
528
+ const element = e.currentTarget;
529
+ if (element && element.classList.contains('waves-effect')) {
530
+ WavesEffect.removeRipples(element);
531
+ }
532
+ };
533
+
437
534
  /**
438
535
  * A factory to create new buttons.
439
536
  *
@@ -447,13 +544,18 @@ const ButtonFactory = (element, defaultClassNames, type = '') => {
447
544
  iconName, iconClass, label, className, variant } = attrs, params = __rest(attrs, ["tooltip", "tooltipPosition", "tooltipPostion", "iconName", "iconClass", "label", "className", "variant"]);
448
545
  // Use variant or fallback to factory type
449
546
  const buttonType = variant || type || 'button';
450
- const cn = [tooltip ? 'tooltipped' : '', defaultClassNames, className]
451
- .filter(Boolean)
452
- .join(' ')
453
- .trim();
547
+ const cn = [tooltip ? 'tooltipped' : '', defaultClassNames, className].filter(Boolean).join(' ').trim();
454
548
  // Use tooltipPosition if available, fallback to legacy tooltipPostion
455
549
  const position = tooltipPosition || tooltipPostion || 'top';
456
- return m(element, Object.assign(Object.assign({}, params), { className: cn, 'data-position': tooltip ? position : undefined, 'data-tooltip': tooltip || undefined, type: buttonType }), iconName ? m(Icon, { iconName, className: iconClass || 'left' }) : undefined, label ? label : undefined);
550
+ // Add waves effect event handlers if waves-effect class is present
551
+ const wavesHandlers = cn.includes('waves-effect') ? {
552
+ onmousedown: WavesEffect.onMouseDown,
553
+ onmouseup: WavesEffect.onMouseUp,
554
+ onmouseleave: WavesEffect.onMouseLeave,
555
+ ontouchstart: WavesEffect.onTouchStart,
556
+ ontouchend: WavesEffect.onTouchEnd
557
+ } : {};
558
+ return m(element, Object.assign(Object.assign(Object.assign({}, params), wavesHandlers), { className: cn, 'data-position': tooltip ? position : undefined, 'data-tooltip': tooltip || undefined, type: buttonType }), iconName ? m(Icon, { iconName, className: iconClass || 'left' }) : undefined, label ? label : undefined);
457
559
  },
458
560
  };
459
561
  };
@@ -462,6 +564,7 @@ const Button = ButtonFactory('a', 'waves-effect waves-light btn', 'button');
462
564
  const LargeButton = ButtonFactory('a', 'waves-effect waves-light btn-large', 'button');
463
565
  const SmallButton = ButtonFactory('a', 'waves-effect waves-light btn-small', 'button');
464
566
  const FlatButton = ButtonFactory('a', 'waves-effect waves-teal btn-flat', 'button');
567
+ const IconButton = ButtonFactory('button', 'btn-flat btn-icon waves-effect waves-teal', 'button');
465
568
  const RoundIconButton = ButtonFactory('button', 'btn-floating btn-large waves-effect waves-light', 'button');
466
569
  const SubmitButton = ButtonFactory('button', 'btn waves-effect waves-light', 'submit');
467
570
 
@@ -898,7 +1001,7 @@ const MaterialIcon = () => {
898
1001
  };
899
1002
  const rotation = (_a = rotationMap[direction]) !== null && _a !== void 0 ? _a : 0;
900
1003
  const transform = rotation ? `rotate(${rotation}deg)` : undefined;
901
- return m('svg', Object.assign(Object.assign({}, props), { style: Object.assign({ transform }, style), height: '1lh', width: '24', viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' }), iconPaths[name].map((d) => m('path', {
1004
+ return m('svg', Object.assign(Object.assign({}, props), { style: Object.assign({ transform }, style), height: '24px', width: '24px', viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' }), iconPaths[name].map((d) => m('path', {
902
1005
  d,
903
1006
  fill: d.includes('M0 0h24v24H0z') ? 'none' : 'currentColor',
904
1007
  })));
@@ -2813,6 +2916,7 @@ const TextArea = () => {
2813
2916
  height: undefined,
2814
2917
  active: false,
2815
2918
  textarea: undefined,
2919
+ hiddenDiv: undefined,
2816
2920
  internalValue: '',
2817
2921
  };
2818
2922
  const updateHeight = (textarea, hiddenDiv) => {
@@ -2909,13 +3013,13 @@ const TextArea = () => {
2909
3013
  overflowWrap: 'break-word',
2910
3014
  },
2911
3015
  oncreate: ({ dom }) => {
2912
- const hiddenDiv = dom;
3016
+ const hiddenDiv = state.hiddenDiv = dom;
2913
3017
  if (state.textarea) {
2914
3018
  updateHeight(state.textarea, hiddenDiv);
2915
3019
  }
2916
3020
  },
2917
3021
  onupdate: ({ dom }) => {
2918
- const hiddenDiv = dom;
3022
+ const hiddenDiv = state.hiddenDiv = dom;
2919
3023
  if (state.textarea) {
2920
3024
  updateHeight(state.textarea, hiddenDiv);
2921
3025
  }
@@ -2940,7 +3044,10 @@ const TextArea = () => {
2940
3044
  const textarea = dom;
2941
3045
  if (state.height)
2942
3046
  textarea.style.height = state.height;
2943
- // No need to manually sync in onupdate since value attribute handles it
3047
+ // Trigger height recalculation when value changes programmatically
3048
+ if (state.hiddenDiv) {
3049
+ updateHeight(textarea, state.hiddenDiv);
3050
+ }
2944
3051
  }, onfocus: () => {
2945
3052
  state.active = true;
2946
3053
  }, oninput: (e) => {
@@ -3100,9 +3207,6 @@ const InputField = (type, defaultClass = '') => () => {
3100
3207
  const { className = 'col s12', dataError, dataSuccess, helperText, iconName, id = state.id, placeholder, isMandatory, label, maxLength, newRow, oninput, onchange, onkeydown, onkeypress, onkeyup, style, validate, canClear } = attrs, params = __rest(attrs, ["className", "dataError", "dataSuccess", "helperText", "iconName", "id", "placeholder", "isMandatory", "label", "maxLength", "newRow", "oninput", "onchange", "onkeydown", "onkeypress", "onkeyup", "style", "validate", "canClear"]);
3101
3208
  // const attributes = toAttrs(params);
3102
3209
  const cn = [newRow ? 'clear' : '', defaultClass, className].filter(Boolean).join(' ').trim() || undefined;
3103
- const isActive = state.active || ((_a = state.inputElement) === null || _a === void 0 ? void 0 : _a.value) || placeholder || type === 'color' || type === 'range'
3104
- ? true
3105
- : false;
3106
3210
  // Special rendering for minmax range sliders
3107
3211
  if (type === 'range' && (attrs.minmax || attrs.valueDisplay)) {
3108
3212
  return m(attrs.minmax ? DoubleRangeSlider : SingleRangeSlider, Object.assign(Object.assign({}, attrs), { state,
@@ -3123,12 +3227,15 @@ const InputField = (type, defaultClass = '') => () => {
3123
3227
  }
3124
3228
  else if (isNonInteractive) {
3125
3229
  // Non-interactive components: prefer defaultValue, fallback to value
3126
- value = ((_c = (_b = attrs.defaultValue) !== null && _b !== void 0 ? _b : attrs.value) !== null && _c !== void 0 ? _c : (isNumeric ? 0 : ''));
3230
+ value = ((_b = (_a = attrs.defaultValue) !== null && _a !== void 0 ? _a : attrs.value) !== null && _b !== void 0 ? _b : (isNumeric ? 0 : ''));
3127
3231
  }
3128
3232
  else {
3129
3233
  // Interactive uncontrolled: use internal state
3130
- value = ((_e = (_d = state.internalValue) !== null && _d !== void 0 ? _d : attrs.defaultValue) !== null && _e !== void 0 ? _e : (isNumeric ? 0 : ''));
3234
+ value = ((_d = (_c = state.internalValue) !== null && _c !== void 0 ? _c : attrs.defaultValue) !== null && _d !== void 0 ? _d : (isNumeric ? 0 : ''));
3131
3235
  }
3236
+ const isActive = state.active || ((_e = state.inputElement) === null || _e === void 0 ? void 0 : _e.value) || value || placeholder || type === 'color' || type === 'range'
3237
+ ? true
3238
+ : false;
3132
3239
  const rangeType = type === 'range' && !attrs.minmax;
3133
3240
  return m('.input-field', { className: cn, style }, [
3134
3241
  iconName ? m('i.material-icons.prefix', iconName) : undefined,
@@ -4342,12 +4449,17 @@ const FloatingActionButton = () => {
4342
4449
  }
4343
4450
  : undefined,
4344
4451
  }, [
4345
- m('a.btn-floating.btn-large', {
4452
+ m('a.btn-floating.btn-large.waves-effect.waves-light', {
4346
4453
  className,
4454
+ onmousedown: WavesEffect.onMouseDown,
4455
+ onmouseup: WavesEffect.onMouseUp,
4456
+ onmouseleave: WavesEffect.onMouseLeave,
4457
+ ontouchstart: WavesEffect.onTouchStart,
4458
+ ontouchend: WavesEffect.onTouchEnd,
4347
4459
  }, m('i.material-icons', { className: iconClass }, iconName)),
4348
4460
  buttons &&
4349
4461
  buttons.length > 0 &&
4350
- m('ul', buttons.map((button, index) => m('li', m(`a.btn-floating.${button.className || 'red'}`, {
4462
+ m('ul', buttons.map((button, index) => m('li', m(`a.btn-floating.waves-effect.waves-light.${button.className || 'red'}`, {
4351
4463
  style: {
4352
4464
  opacity: state.isOpen ? '1' : '0',
4353
4465
  transform: state.isOpen ? 'scale(1)' : 'scale(0.4)',
@@ -4358,6 +4470,11 @@ const FloatingActionButton = () => {
4358
4470
  if (button.onclick)
4359
4471
  button.onclick(e);
4360
4472
  },
4473
+ onmousedown: WavesEffect.onMouseDown,
4474
+ onmouseup: WavesEffect.onMouseUp,
4475
+ onmouseleave: WavesEffect.onMouseLeave,
4476
+ ontouchstart: WavesEffect.onTouchStart,
4477
+ ontouchend: WavesEffect.onTouchEnd,
4361
4478
  }, m('i.material-icons', { className: button.iconClass }, button.iconName))))),
4362
4479
  ]));
4363
4480
  },
@@ -5754,11 +5871,13 @@ const RadioButtons = () => {
5754
5871
  const Select = () => {
5755
5872
  const state = {
5756
5873
  id: '',
5874
+ dropdownId: '',
5757
5875
  isOpen: false,
5758
5876
  focusedIndex: -1,
5759
5877
  inputRef: null,
5760
5878
  dropdownRef: null,
5761
5879
  internalSelectedIds: [],
5880
+ isInsideModal: false,
5762
5881
  };
5763
5882
  const isControlled = (attrs) => attrs.checkedId !== undefined && attrs.onchange !== undefined;
5764
5883
  const isSelected = (id, selectedIds) => {
@@ -5847,9 +5966,124 @@ const Select = () => {
5847
5966
  m.redraw();
5848
5967
  }
5849
5968
  };
5969
+ const getPortalStyles = (inputRef) => {
5970
+ if (!inputRef)
5971
+ return {};
5972
+ const rect = inputRef.getBoundingClientRect();
5973
+ const viewportHeight = window.innerHeight;
5974
+ return {
5975
+ position: 'fixed',
5976
+ top: `${rect.bottom}px`,
5977
+ left: `${rect.left}px`,
5978
+ width: `${rect.width}px`,
5979
+ zIndex: 10000, // Higher than modal z-index
5980
+ maxHeight: `${viewportHeight - rect.bottom - 20}px`, // Leave 20px margin from bottom
5981
+ };
5982
+ };
5983
+ const renderDropdownContent = (attrs, selectedIds, multiple, placeholder) => [
5984
+ placeholder && m('li.disabled', { tabindex: 0 }, m('span', placeholder)),
5985
+ // Render ungrouped options first
5986
+ attrs.options
5987
+ .filter((option) => !option.group)
5988
+ .map((option) => m('li', Object.assign({ key: option.id, class: option.disabled
5989
+ ? 'disabled'
5990
+ : state.focusedIndex === attrs.options.indexOf(option)
5991
+ ? 'focused'
5992
+ : '' }, (option.disabled
5993
+ ? {}
5994
+ : {
5995
+ onclick: (e) => {
5996
+ e.stopPropagation();
5997
+ toggleOption(option.id, multiple, attrs);
5998
+ },
5999
+ })), [
6000
+ option.img && m('img', { src: option.img, alt: option.label }),
6001
+ m('span', [
6002
+ multiple
6003
+ ? m('label', { for: option.id }, m('input', {
6004
+ id: option.id,
6005
+ type: 'checkbox',
6006
+ checked: selectedIds.includes(option.id),
6007
+ disabled: option.disabled ? true : undefined,
6008
+ onclick: (e) => {
6009
+ e.stopPropagation();
6010
+ },
6011
+ }), m('span', option.label))
6012
+ : m('span', option.label),
6013
+ ].filter(Boolean)),
6014
+ ])),
6015
+ // Render grouped options
6016
+ Object.entries(attrs.options
6017
+ .filter((option) => option.group)
6018
+ .reduce((groups, option) => {
6019
+ const group = option.group;
6020
+ if (!groups[group])
6021
+ groups[group] = [];
6022
+ groups[group].push(option);
6023
+ return groups;
6024
+ }, {}))
6025
+ .map(([groupName, groupOptions]) => [
6026
+ m('li.optgroup', { key: `group-${groupName}`, tabindex: 0 }, m('span', groupName)),
6027
+ ...groupOptions.map((option) => m('li', Object.assign({ key: option.id, class: `optgroup-option${option.disabled ? ' disabled' : ''}${isSelected(option.id, selectedIds) ? ' selected' : ''}${state.focusedIndex === attrs.options.indexOf(option) ? ' focused' : ''}` }, (option.disabled
6028
+ ? {}
6029
+ : {
6030
+ onclick: (e) => {
6031
+ e.stopPropagation();
6032
+ toggleOption(option.id, multiple, attrs);
6033
+ },
6034
+ })), [
6035
+ option.img && m('img', { src: option.img, alt: option.label }),
6036
+ m('span', [
6037
+ multiple
6038
+ ? m('label', { for: option.id }, m('input', {
6039
+ id: option.id,
6040
+ type: 'checkbox',
6041
+ checked: selectedIds.includes(option.id),
6042
+ disabled: option.disabled ? true : undefined,
6043
+ onclick: (e) => {
6044
+ e.stopPropagation();
6045
+ },
6046
+ }), m('span', option.label))
6047
+ : m('span', option.label),
6048
+ ].filter(Boolean)),
6049
+ ])),
6050
+ ])
6051
+ .reduce((acc, val) => acc.concat(val), []),
6052
+ ];
6053
+ const updatePortalDropdown = (attrs, selectedIds, multiple, placeholder) => {
6054
+ var _a;
6055
+ if (!state.isInsideModal)
6056
+ return;
6057
+ let portalElement = document.getElementById(state.dropdownId);
6058
+ if (!state.isOpen) {
6059
+ // Clean up portal when dropdown is closed
6060
+ if (portalElement) {
6061
+ m.render(portalElement, []);
6062
+ (_a = portalElement.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(portalElement);
6063
+ }
6064
+ return;
6065
+ }
6066
+ if (!portalElement) {
6067
+ portalElement = document.createElement('div');
6068
+ portalElement.id = state.dropdownId;
6069
+ document.body.appendChild(portalElement);
6070
+ }
6071
+ const dropdownVnode = m('ul.dropdown-content.select-dropdown', {
6072
+ tabindex: 0,
6073
+ style: getPortalStyles(state.inputRef),
6074
+ oncreate: ({ dom }) => {
6075
+ state.dropdownRef = dom;
6076
+ },
6077
+ onremove: () => {
6078
+ state.dropdownRef = null;
6079
+ },
6080
+ }, renderDropdownContent(attrs, selectedIds, multiple, placeholder));
6081
+ m.render(portalElement, dropdownVnode);
6082
+ };
5850
6083
  return {
5851
6084
  oninit: ({ attrs }) => {
5852
6085
  state.id = attrs.id || uniqueId();
6086
+ state.dropdownId = `${state.id}-dropdown`;
5853
6087
  const controlled = isControlled(attrs);
5854
6088
  // Warn developer for improper controlled usage
5855
6089
  if (attrs.checkedId !== undefined && !controlled && !attrs.disabled) {
@@ -5868,9 +6102,20 @@ const Select = () => {
5868
6102
  // Add global click listener to close dropdown
5869
6103
  document.addEventListener('click', closeDropdown);
5870
6104
  },
6105
+ oncreate: ({ dom }) => {
6106
+ // Detect if component is inside a modal
6107
+ state.isInsideModal = !!dom.closest('.modal');
6108
+ },
5871
6109
  onremove: () => {
5872
6110
  // Cleanup global listener
5873
6111
  document.removeEventListener('click', closeDropdown);
6112
+ // Cleanup portaled dropdown if it exists
6113
+ if (state.isInsideModal && state.dropdownRef) {
6114
+ const portalElement = document.getElementById(state.dropdownId);
6115
+ if (portalElement && portalElement.parentNode) {
6116
+ portalElement.parentNode.removeChild(portalElement);
6117
+ }
6118
+ }
5874
6119
  },
5875
6120
  view: ({ attrs }) => {
5876
6121
  var _a;
@@ -5894,6 +6139,10 @@ const Select = () => {
5894
6139
  const { newRow, className = 'col s12', key, options, multiple = false, label, helperText, placeholder = '', isMandatory, iconName, style, } = attrs;
5895
6140
  const finalClassName = newRow ? `${className} clear` : className;
5896
6141
  const selectedOptions = options.filter((opt) => isSelected(opt.id, selectedIds));
6142
+ // Update portal dropdown when inside modal
6143
+ if (state.isInsideModal) {
6144
+ updatePortalDropdown(attrs, selectedIds, multiple, placeholder);
6145
+ }
5897
6146
  return m('.input-field.select-space', {
5898
6147
  className: finalClassName,
5899
6148
  key,
@@ -5906,6 +6155,7 @@ const Select = () => {
5906
6155
  tabindex: disabled ? -1 : 0,
5907
6156
  'aria-expanded': state.isOpen ? 'true' : 'false',
5908
6157
  'aria-haspopup': 'listbox',
6158
+ 'aria-controls': state.dropdownId,
5909
6159
  role: 'combobox',
5910
6160
  }, [
5911
6161
  m('input[type=text][readonly=true].select-dropdown.dropdown-trigger', {
@@ -5922,8 +6172,8 @@ const Select = () => {
5922
6172
  }
5923
6173
  },
5924
6174
  }),
5925
- // Dropdown Menu
5926
- state.isOpen &&
6175
+ // Dropdown Menu - render inline only when NOT inside modal
6176
+ state.isOpen && !state.isInsideModal &&
5927
6177
  m('ul.dropdown-content.select-dropdown', {
5928
6178
  tabindex: 0,
5929
6179
  oncreate: ({ dom }) => {
@@ -5933,76 +6183,7 @@ const Select = () => {
5933
6183
  state.dropdownRef = null;
5934
6184
  },
5935
6185
  style: getDropdownStyles(state.inputRef, true, options),
5936
- }, [
5937
- placeholder && m('li.disabled', { tabindex: 0 }, m('span', placeholder)),
5938
- // Render ungrouped options first
5939
- options
5940
- .filter((option) => !option.group)
5941
- .map((option) => m('li', Object.assign({ key: option.id, class: option.disabled
5942
- ? 'disabled'
5943
- : state.focusedIndex === options.indexOf(option)
5944
- ? 'focused'
5945
- : '' }, (option.disabled
5946
- ? {}
5947
- : {
5948
- onclick: (e) => {
5949
- e.stopPropagation();
5950
- toggleOption(option.id, multiple, attrs);
5951
- },
5952
- })), [
5953
- option.img && m('img', { src: option.img, alt: option.label }),
5954
- m('span', [
5955
- multiple
5956
- ? m('label', { for: option.id }, m('input', {
5957
- id: option.id,
5958
- type: 'checkbox',
5959
- checked: selectedIds.includes(option.id),
5960
- disabled: option.disabled ? true : undefined,
5961
- onclick: (e) => {
5962
- e.stopPropagation();
5963
- },
5964
- }), m('span', option.label))
5965
- : m('span', option.label),
5966
- ].filter(Boolean)),
5967
- ])),
5968
- // Render grouped options
5969
- Object.entries(options
5970
- .filter((option) => option.group)
5971
- .reduce((groups, option) => {
5972
- const group = option.group;
5973
- if (!groups[group])
5974
- groups[group] = [];
5975
- groups[group].push(option);
5976
- return groups;
5977
- }, {}))
5978
- .map(([groupName, groupOptions]) => [
5979
- m('li.optgroup', { key: `group-${groupName}`, tabindex: 0 }, m('span', groupName)),
5980
- ...groupOptions.map((option) => m('li', Object.assign({ key: option.id, class: `optgroup-option${option.disabled ? ' disabled' : ''}${isSelected(option.id, selectedIds) ? ' selected' : ''}${state.focusedIndex === options.indexOf(option) ? ' focused' : ''}` }, (option.disabled
5981
- ? {}
5982
- : {
5983
- onclick: (e) => {
5984
- e.stopPropagation();
5985
- toggleOption(option.id, multiple, attrs);
5986
- },
5987
- })), [
5988
- option.img && m('img', { src: option.img, alt: option.label }),
5989
- m('span', [
5990
- multiple
5991
- ? m('label', { for: option.id }, m('input', {
5992
- id: option.id,
5993
- type: 'checkbox',
5994
- checked: selectedIds.includes(option.id),
5995
- disabled: option.disabled ? true : undefined,
5996
- onclick: (e) => {
5997
- e.stopPropagation();
5998
- },
5999
- }), m('span', option.label))
6000
- : m('span', option.label),
6001
- ].filter(Boolean)),
6002
- ])),
6003
- ])
6004
- .reduce((acc, val) => acc.concat(val), []),
6005
- ]),
6186
+ }, renderDropdownContent(attrs, selectedIds, multiple, placeholder)),
6006
6187
  m(MaterialIcon, {
6007
6188
  name: 'caret',
6008
6189
  direction: 'down',
@@ -8947,6 +9128,7 @@ exports.FlatButton = FlatButton;
8947
9128
  exports.FloatingActionButton = FloatingActionButton;
8948
9129
  exports.HelperText = HelperText;
8949
9130
  exports.Icon = Icon;
9131
+ exports.IconButton = IconButton;
8950
9132
  exports.ImageList = ImageList;
8951
9133
  exports.InputCheckbox = InputCheckbox;
8952
9134
  exports.Label = Label;