mithril-materialized 2.0.0-beta.11 → 2.0.0-beta.12

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.umd.js CHANGED
@@ -840,6 +840,18 @@
840
840
  'M18.3 5.71a1 1 0 0 0-1.41 0L12 10.59 7.11 5.7A1 1 0 0 0 5.7 7.11L10.59 12l-4.89 4.89a1 1 0 1 0 1.41 1.41L12 13.41l4.89 4.89a1 1 0 0 0 1.41-1.41L13.41 12l4.89-4.89a1 1 0 0 0 0-1.4z',
841
841
  'M0 0h24v24H0z',
842
842
  ],
843
+ chevron: [
844
+ 'M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z', // chevron down
845
+ 'M0 0h24v24H0z', // background
846
+ ],
847
+ expand: [
848
+ 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z', // plus
849
+ 'M0 0h24v24H0z', // background
850
+ ],
851
+ collapse: [
852
+ 'M19 13H5v-2h14v2z', // minus
853
+ 'M0 0h24v24H0z', // background
854
+ ],
843
855
  };
844
856
  const MaterialIcon = () => {
845
857
  return {
@@ -849,8 +861,8 @@
849
861
  const rotationMap = {
850
862
  down: 0,
851
863
  up: 180,
852
- left: -90,
853
- right: 90,
864
+ left: 90,
865
+ right: -90,
854
866
  };
855
867
  const rotation = (_a = rotationMap[direction]) !== null && _a !== void 0 ? _a : 0;
856
868
  const transform = rotation ? `rotate(${rotation}deg)` : undefined;
@@ -1159,7 +1171,7 @@
1159
1171
  const lang = language || 'lang-TypeScript';
1160
1172
  const label = lang.replace('lang-', '');
1161
1173
  const cb = code instanceof Array ? code.join('\n') : code;
1162
- const cn = [newRow ? 'clear' : '', lang, className].filter(Boolean).join(' ').trim();
1174
+ const cn = [newRow ? 'clear' : '', lang, className].filter(Boolean).join(' ').trim() || undefined;
1163
1175
  return m(`pre.codeblock${newRow ? '.clear' : ''}`, attrs, [
1164
1176
  m('div', m('label', label)),
1165
1177
  m('code', Object.assign(Object.assign({}, params), { className: cn }), cb),
@@ -2212,7 +2224,7 @@
2212
2224
  var _a;
2213
2225
  const { className = 'col s12', dataError, dataSuccess, helperText, iconName, id = state.id, initialValue, placeholder, isMandatory, label, maxLength, newRow, oninput, onchange, onkeydown, onkeypress, onkeyup, style, validate } = attrs, params = __rest(attrs, ["className", "dataError", "dataSuccess", "helperText", "iconName", "id", "initialValue", "placeholder", "isMandatory", "label", "maxLength", "newRow", "oninput", "onchange", "onkeydown", "onkeypress", "onkeyup", "style", "validate"]);
2214
2226
  // const attributes = toAttrs(params);
2215
- const cn = [newRow ? 'clear' : '', defaultClass, className].filter(Boolean).join(' ').trim();
2227
+ const cn = [newRow ? 'clear' : '', defaultClass, className].filter(Boolean).join(' ').trim() || undefined;
2216
2228
  const isActive = state.active || ((_a = state.inputElement) === null || _a === void 0 ? void 0 : _a.value) || placeholder || type === 'color' || type === 'range'
2217
2229
  ? true
2218
2230
  : false;
@@ -2488,7 +2500,7 @@
2488
2500
  callback(checkedIds);
2489
2501
  }
2490
2502
  : undefined;
2491
- const cn = [newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim();
2503
+ const cn = [newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim() || undefined;
2492
2504
  const optionsContent = layout === 'horizontal'
2493
2505
  ? m('div.grid-container', options.map((option) => m(InputCheckbox, {
2494
2506
  disabled: disabled || option.disabled,
@@ -3533,7 +3545,7 @@
3533
3545
  view: ({ attrs }) => {
3534
3546
  const { src, alt, width, height, caption, className, style } = attrs, otherAttrs = __rest(attrs, ["src", "alt", "width", "height", "caption", "className", "style"]);
3535
3547
  return m('img.materialboxed', Object.assign(Object.assign({}, otherAttrs), { src, alt: alt || '', width,
3536
- height, className: ['materialboxed', className].filter(Boolean).join(' '), style: Object.assign({ cursor: 'zoom-in', transition: 'opacity 200ms ease' }, style), onclick: (e) => {
3548
+ height, className: ['materialboxed', className].filter(Boolean).join(' ') || undefined, style: Object.assign({ cursor: 'zoom-in', transition: 'opacity 200ms ease' }, style), onclick: (e) => {
3537
3549
  e.preventDefault();
3538
3550
  openBox(e.target, attrs);
3539
3551
  } }));
@@ -3615,7 +3627,7 @@
3615
3627
  .filter(Boolean)
3616
3628
  .join(' ')
3617
3629
  .trim();
3618
- const overlayClasses = ['modal-overlay', state.isOpen ? 'active' : ''].filter(Boolean).join(' ').trim();
3630
+ const overlayClasses = ['modal-overlay', state.isOpen ? 'active' : ''].filter(Boolean).join(' ').trim() || undefined;
3619
3631
  return m('div', { className: 'modal-container' }, [
3620
3632
  // Modal overlay
3621
3633
  m('div', {
@@ -3640,23 +3652,25 @@
3640
3652
  role: 'dialog',
3641
3653
  'aria-labelledby': `${id}-title`,
3642
3654
  'aria-describedby': description ? `${id}-desc` : undefined,
3643
- style: Object.assign(Object.assign({ display: state.isOpen ? 'flex' : 'none', position: 'fixed' }, (bottomSheet ? {
3644
- // Bottom sheet positioning
3645
- top: 'auto',
3646
- bottom: '0',
3647
- left: '0',
3648
- right: '0',
3649
- transform: 'none',
3650
- maxWidth: '100%',
3651
- borderRadius: '8px 8px 0 0',
3652
- } : {
3653
- // Regular modal positioning
3654
- top: '50%',
3655
- left: '50%',
3656
- transform: 'translate(-50%, -50%)',
3657
- maxWidth: '75%',
3658
- borderRadius: '4px',
3659
- })), { backgroundColor: 'var(--mm-modal-background, #fff)', maxHeight: '85%', overflow: 'auto', zIndex: '1003', padding: '0', flexDirection: 'column', boxShadow: '0 24px 38px 3px rgba(0,0,0,0.14), 0 9px 46px 8px rgba(0,0,0,0.12), 0 11px 15px -7px rgba(0,0,0,0.20)' }),
3655
+ style: Object.assign(Object.assign({ display: state.isOpen ? 'flex' : 'none', position: 'fixed' }, (bottomSheet
3656
+ ? {
3657
+ // Bottom sheet positioning
3658
+ top: 'auto',
3659
+ bottom: '0',
3660
+ left: '0',
3661
+ right: '0',
3662
+ transform: 'none',
3663
+ maxWidth: '100%',
3664
+ borderRadius: '8px 8px 0 0',
3665
+ }
3666
+ : {
3667
+ // Regular modal positioning
3668
+ top: '50%',
3669
+ left: '50%',
3670
+ transform: 'translate(-50%, -50%)',
3671
+ maxWidth: '75%',
3672
+ borderRadius: '4px',
3673
+ })), { backgroundColor: 'var(--mm-modal-background, #fff)', maxHeight: '85%', overflow: 'auto', zIndex: '1003', padding: '0', flexDirection: 'column', boxShadow: '0 24px 38px 3px rgba(0,0,0,0.14), 0 9px 46px 8px rgba(0,0,0,0.12), 0 11px 15px -7px rgba(0,0,0,0.20)' }),
3660
3674
  onclick: (e) => e.stopPropagation(), // Prevent backdrop click when clicking inside modal
3661
3675
  }, [
3662
3676
  // Close button
@@ -4694,7 +4708,7 @@
4694
4708
  callback(propId);
4695
4709
  }
4696
4710
  };
4697
- const cn = [newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim();
4711
+ const cn = [newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim() || undefined;
4698
4712
  const optionsContent = layout === 'horizontal'
4699
4713
  ? m('div.grid-container', options.map((r) => m(RadioButton, Object.assign(Object.assign({}, r), { onchange,
4700
4714
  groupId, disabled: disabled || r.disabled, className: checkboxClass, checked: r.id === checkedId, inputId: `${componentId}-${r.id}` }))))
@@ -4967,7 +4981,7 @@
4967
4981
  view: ({ attrs }) => {
4968
4982
  const id = attrs.id || state.id;
4969
4983
  const { label, left, right, disabled, newRow, onchange, isMandatory, className = 'col s12' } = attrs, params = __rest(attrs, ["label", "left", "right", "disabled", "newRow", "onchange", "isMandatory", "className"]);
4970
- const cn = ['input-field', newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim();
4984
+ const cn = ['input-field', newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim() || undefined;
4971
4985
  return m('div', {
4972
4986
  className: cn,
4973
4987
  onclick: (e) => {
@@ -5118,7 +5132,7 @@
5118
5132
  },
5119
5133
  view: ({ attrs }) => {
5120
5134
  const { tabWidth, tabs, className, style, swipeable = false } = attrs;
5121
- const cn = [tabWidth === 'fill' ? 'tabs-fixed-width' : '', className].filter(Boolean).join(' ').trim();
5135
+ const cn = [tabWidth === 'fill' ? 'tabs-fixed-width' : '', className].filter(Boolean).join(' ').trim() || undefined;
5122
5136
  const anchoredTabs = tabs.map(toAnchored());
5123
5137
  const activeTab = setActiveTabId(anchoredTabs, attrs.selectedTabId);
5124
5138
  updateIndicator();
@@ -6104,8 +6118,8 @@
6104
6118
  }
6105
6119
  // Check file type
6106
6120
  if (attrs.accept) {
6107
- const acceptedTypes = attrs.accept.split(',').map(type => type.trim());
6108
- const isAccepted = acceptedTypes.some(acceptedType => {
6121
+ const acceptedTypes = attrs.accept.split(',').map((type) => type.trim());
6122
+ const isAccepted = acceptedTypes.some((acceptedType) => {
6109
6123
  if (acceptedType.startsWith('.')) {
6110
6124
  // Extension check
6111
6125
  return file.name.toLowerCase().endsWith(acceptedType.toLowerCase());
@@ -6165,11 +6179,11 @@
6165
6179
  }
6166
6180
  // Notify parent component
6167
6181
  if (attrs.onFilesSelected) {
6168
- attrs.onFilesSelected(state.files.filter(f => !f.uploadError));
6182
+ attrs.onFilesSelected(state.files.filter((f) => !f.uploadError));
6169
6183
  }
6170
6184
  };
6171
6185
  const removeFile = (fileToRemove, attrs) => {
6172
- state.files = state.files.filter(file => file !== fileToRemove);
6186
+ state.files = state.files.filter((file) => file !== fileToRemove);
6173
6187
  if (attrs.onFileRemoved) {
6174
6188
  attrs.onFileRemoved(fileToRemove);
6175
6189
  }
@@ -6188,11 +6202,11 @@
6188
6202
  id: uniqueId(),
6189
6203
  files: [],
6190
6204
  isDragOver: false,
6191
- isUploading: false
6205
+ isUploading: false,
6192
6206
  };
6193
6207
  },
6194
6208
  view: ({ attrs }) => {
6195
- const { accept, multiple = false, disabled = false, label = 'Choose files or drag them here', helperText, showPreview = true, className = '', error } = attrs;
6209
+ const { accept, multiple = false, disabled = false, label = 'Choose files or drag them here', helperText, showPreview = true, className = '', error, } = attrs;
6196
6210
  return m('.file-upload-container', { class: className }, [
6197
6211
  // Upload area
6198
6212
  m('.file-upload-area', {
@@ -6200,8 +6214,10 @@
6200
6214
  state.isDragOver ? 'drag-over' : '',
6201
6215
  disabled ? 'disabled' : '',
6202
6216
  error ? 'error' : '',
6203
- state.files.length > 0 ? 'has-files' : ''
6204
- ].filter(Boolean).join(' '),
6217
+ state.files.length > 0 ? 'has-files' : '',
6218
+ ]
6219
+ .filter(Boolean)
6220
+ .join(' ') || undefined,
6205
6221
  ondragover: (e) => {
6206
6222
  if (disabled)
6207
6223
  return;
@@ -6232,7 +6248,7 @@
6232
6248
  return;
6233
6249
  const input = document.getElementById(state.id);
6234
6250
  input === null || input === void 0 ? void 0 : input.click();
6235
- }
6251
+ },
6236
6252
  }, [
6237
6253
  m('input[type="file"]', {
6238
6254
  id: state.id,
@@ -6245,57 +6261,55 @@
6245
6261
  if (target.files) {
6246
6262
  handleFiles(target.files, attrs);
6247
6263
  }
6248
- }
6264
+ },
6249
6265
  }),
6250
6266
  m('.file-upload-content', [
6251
6267
  m('i.material-icons.file-upload-icon', 'cloud_upload'),
6252
6268
  m('p.file-upload-label', label),
6253
6269
  helperText && m('p.file-upload-helper', helperText),
6254
- accept && m('p.file-upload-types', `Accepted: ${accept}`)
6255
- ])
6270
+ accept && m('p.file-upload-types', `Accepted: ${accept}`),
6271
+ ]),
6256
6272
  ]),
6257
6273
  // Error message
6258
6274
  error && m('.file-upload-error', error),
6259
6275
  // File list
6260
- state.files.length > 0 && m('.file-upload-list', [
6261
- m('h6', 'Selected Files:'),
6262
- state.files.map(file => m('.file-upload-item', { key: file.name + file.size }, [
6263
- // Preview thumbnail
6264
- showPreview && file.preview && m('.file-preview', [
6265
- m('img', { src: file.preview, alt: file.name })
6266
- ]),
6267
- // File info
6268
- m('.file-info', [
6269
- m('.file-name', file.name),
6270
- m('.file-details', [
6271
- m('span.file-size', formatFileSize(file.size)),
6272
- file.type && m('span.file-type', file.type)
6273
- ]),
6274
- // Progress bar (if uploading)
6275
- file.uploadProgress !== undefined && m('.file-progress', [
6276
- m('.progress', [
6277
- m('.determinate', {
6278
- style: { width: `${file.uploadProgress}%` }
6279
- })
6280
- ])
6276
+ state.files.length > 0 &&
6277
+ m('.file-upload-list', [
6278
+ m('h6', 'Selected Files:'),
6279
+ state.files.map((file) => m('.file-upload-item', { key: file.name + file.size }, [
6280
+ // Preview thumbnail
6281
+ showPreview && file.preview && m('.file-preview', [m('img', { src: file.preview, alt: file.name })]),
6282
+ // File info
6283
+ m('.file-info', [
6284
+ m('.file-name', file.name),
6285
+ m('.file-details', [
6286
+ m('span.file-size', formatFileSize(file.size)),
6287
+ file.type && m('span.file-type', file.type),
6288
+ ]),
6289
+ // Progress bar (if uploading)
6290
+ file.uploadProgress !== undefined &&
6291
+ m('.file-progress', [
6292
+ m('.progress', [
6293
+ m('.determinate', {
6294
+ style: { width: `${file.uploadProgress}%` },
6295
+ }),
6296
+ ]),
6297
+ ]),
6298
+ // Error message
6299
+ file.uploadError && m('.file-error', file.uploadError),
6281
6300
  ]),
6282
- // Error message
6283
- file.uploadError && m('.file-error', file.uploadError)
6284
- ]),
6285
- // Remove button
6286
- m('button.btn-flat.file-remove', {
6287
- onclick: (e) => {
6288
- e.stopPropagation();
6289
- removeFile(file, attrs);
6290
- },
6291
- title: 'Remove file'
6292
- }, [
6293
- m('i.material-icons', 'close')
6294
- ])
6295
- ]))
6296
- ])
6301
+ // Remove button
6302
+ m('button.btn-flat.file-remove', {
6303
+ onclick: (e) => {
6304
+ e.stopPropagation();
6305
+ removeFile(file, attrs);
6306
+ },
6307
+ title: 'Remove file',
6308
+ }, [m('i.material-icons', 'close')]),
6309
+ ])),
6310
+ ]),
6297
6311
  ]);
6298
- }
6312
+ },
6299
6313
  };
6300
6314
  };
6301
6315
 
@@ -6325,7 +6339,7 @@
6325
6339
  state = {
6326
6340
  id: attrs.id || uniqueId(),
6327
6341
  isOpen: attrs.isOpen || false,
6328
- isAnimating: false
6342
+ isAnimating: false,
6329
6343
  };
6330
6344
  // Set up keyboard listener
6331
6345
  if (typeof document !== 'undefined' && attrs.closeOnEscape !== false) {
@@ -6354,34 +6368,33 @@
6354
6368
  }
6355
6369
  },
6356
6370
  view: ({ attrs, children }) => {
6357
- const { position = 'left', mode = 'overlay', width = 300, className = '', showBackdrop = true, animationDuration = 300, fixed = false } = attrs;
6371
+ const { position = 'left', mode = 'overlay', width = 300, className = '', showBackdrop = true, animationDuration = 300, fixed = false, } = attrs;
6358
6372
  const isOpen = state.isOpen;
6359
6373
  return [
6360
6374
  // Backdrop (using existing materialize class)
6361
- showBackdrop && mode === 'overlay' && m('.sidenav-overlay', {
6362
- style: {
6363
- display: isOpen ? 'block' : 'none',
6364
- opacity: isOpen ? '1' : '0'
6365
- },
6366
- onclick: () => handleBackdropClick(attrs)
6367
- }),
6375
+ showBackdrop &&
6376
+ mode === 'overlay' &&
6377
+ m('.sidenav-overlay', {
6378
+ style: {
6379
+ display: isOpen ? 'block' : 'none',
6380
+ opacity: isOpen ? '1' : '0',
6381
+ },
6382
+ onclick: () => handleBackdropClick(attrs),
6383
+ }),
6368
6384
  // Sidenav (using existing materialize structure)
6369
6385
  m('ul.sidenav', {
6370
6386
  id: state.id,
6371
- class: [
6372
- position === 'right' ? 'right-aligned' : '',
6373
- fixed ? 'sidenav-fixed' : '',
6374
- className
6375
- ].filter(Boolean).join(' '),
6387
+ class: [position === 'right' ? 'right-aligned' : '', fixed ? 'sidenav-fixed' : '', className]
6388
+ .filter(Boolean)
6389
+ .join(' ') || undefined,
6376
6390
  style: {
6377
6391
  width: `${width}px`,
6378
- transform: isOpen ? 'translateX(0)' :
6379
- position === 'left' ? 'translateX(-105%)' : 'translateX(105%)',
6380
- 'transition-duration': `${animationDuration}ms`
6381
- }
6382
- }, children)
6392
+ transform: isOpen ? 'translateX(0)' : position === 'left' ? 'translateX(-105%)' : 'translateX(105%)',
6393
+ 'transition-duration': `${animationDuration}ms`,
6394
+ },
6395
+ }, children),
6383
6396
  ];
6384
- }
6397
+ },
6385
6398
  };
6386
6399
  };
6387
6400
  /**
@@ -6391,37 +6404,30 @@
6391
6404
  const SidenavItem = () => {
6392
6405
  return {
6393
6406
  view: ({ attrs, children }) => {
6394
- const { text, icon, active = false, disabled = false, onclick, href, className = '', divider = false, subheader = false } = attrs;
6407
+ const { text, icon, active = false, disabled = false, onclick, href, className = '', divider = false, subheader = false, } = attrs;
6395
6408
  if (divider) {
6396
6409
  return m('li.divider');
6397
6410
  }
6398
6411
  if (subheader) {
6399
6412
  return m('li.subheader', text || children);
6400
6413
  }
6401
- const itemClasses = [
6402
- active ? 'active' : '',
6403
- disabled ? 'disabled' : '',
6404
- className
6405
- ].filter(Boolean).join(' ');
6406
- const content = [
6407
- icon && m('i.material-icons', icon),
6408
- text || children
6409
- ];
6414
+ const itemClasses = [active ? 'active' : '', disabled ? 'disabled' : '', className].filter(Boolean).join(' ') || undefined;
6415
+ const content = [icon && m('i.material-icons', icon), text || children];
6410
6416
  if (href && !disabled) {
6411
6417
  return m('li', { class: itemClasses }, [
6412
6418
  m('a', {
6413
6419
  href,
6414
- onclick: disabled ? undefined : onclick
6415
- }, content)
6420
+ onclick: disabled ? undefined : onclick,
6421
+ }, content),
6416
6422
  ]);
6417
6423
  }
6418
6424
  return m('li', { class: itemClasses }, [
6419
6425
  m('a', {
6420
6426
  onclick: disabled ? undefined : onclick,
6421
- href: '#!'
6422
- }, content)
6427
+ href: '#!',
6428
+ }, content),
6423
6429
  ]);
6424
- }
6430
+ },
6425
6431
  };
6426
6432
  };
6427
6433
  /**
@@ -6472,7 +6478,7 @@
6472
6478
  const Breadcrumb = () => {
6473
6479
  return {
6474
6480
  view: ({ attrs }) => {
6475
- const { items = [], separator = 'chevron_right', className = '', showIcons = false, maxItems, showHome = false } = attrs;
6481
+ const { items = [], separator = 'chevron_right', className = '', showIcons = false, maxItems, showHome = false, } = attrs;
6476
6482
  if (items.length === 0) {
6477
6483
  return null;
6478
6484
  }
@@ -6481,52 +6487,46 @@
6481
6487
  if (maxItems && items.length > maxItems) {
6482
6488
  const firstItem = items[0];
6483
6489
  const lastItems = items.slice(-(maxItems - 2));
6484
- displayItems = [
6485
- firstItem,
6486
- { text: '...', disabled: true, className: 'breadcrumb-ellipsis' },
6487
- ...lastItems
6488
- ];
6490
+ displayItems = [firstItem, { text: '...', disabled: true, className: 'breadcrumb-ellipsis' }, ...lastItems];
6489
6491
  }
6490
6492
  return m('nav.breadcrumb', { class: className }, [
6491
- m('ol.breadcrumb-list', displayItems.map((item, index) => {
6493
+ m('ol.breadcrumb-list', displayItems
6494
+ .map((item, index) => {
6492
6495
  const isLast = index === displayItems.length - 1;
6493
6496
  const isFirst = index === 0;
6494
6497
  return [
6495
6498
  // Breadcrumb item
6496
6499
  m('li.breadcrumb-item', {
6497
- class: [
6498
- item.active || isLast ? 'active' : '',
6499
- item.disabled ? 'disabled' : '',
6500
- item.className || ''
6501
- ].filter(Boolean).join(' ')
6500
+ class: [item.active || isLast ? 'active' : '', item.disabled ? 'disabled' : '', item.className || '']
6501
+ .filter(Boolean)
6502
+ .join(' ') || undefined,
6502
6503
  }, [
6503
- item.href && !item.disabled && !isLast ?
6504
- // Link item
6505
- m('a.breadcrumb-link', {
6506
- href: item.href,
6507
- onclick: item.onclick
6508
- }, [
6509
- (showIcons && item.icon) && m('i.material-icons.breadcrumb-icon', item.icon),
6510
- (showHome && isFirst && !item.icon) && m('i.material-icons.breadcrumb-icon', 'home'),
6511
- m('span.breadcrumb-text', item.text)
6512
- ]) :
6513
- // Text item (active or disabled)
6514
- m('span.breadcrumb-text', {
6515
- onclick: item.disabled ? undefined : item.onclick
6516
- }, [
6517
- (showIcons && item.icon) && m('i.material-icons.breadcrumb-icon', item.icon),
6518
- (showHome && isFirst && !item.icon) && m('i.material-icons.breadcrumb-icon', 'home'),
6519
- item.text
6520
- ])
6504
+ item.href && !item.disabled && !isLast
6505
+ ? // Link item
6506
+ m('a.breadcrumb-link', {
6507
+ href: item.href,
6508
+ onclick: item.onclick,
6509
+ }, [
6510
+ showIcons && item.icon && m('i.material-icons.breadcrumb-icon', item.icon),
6511
+ showHome && isFirst && !item.icon && m('i.material-icons.breadcrumb-icon', 'home'),
6512
+ m('span.breadcrumb-text', item.text),
6513
+ ])
6514
+ : // Text item (active or disabled)
6515
+ m('span.breadcrumb-text', {
6516
+ onclick: item.disabled ? undefined : item.onclick,
6517
+ }, [
6518
+ showIcons && item.icon && m('i.material-icons.breadcrumb-icon', item.icon),
6519
+ showHome && isFirst && !item.icon && m('i.material-icons.breadcrumb-icon', 'home'),
6520
+ item.text,
6521
+ ]),
6521
6522
  ]),
6522
6523
  // Separator (except for last item)
6523
- !isLast && m('li.breadcrumb-separator', [
6524
- m('i.material-icons', separator)
6525
- ])
6524
+ !isLast && m('li.breadcrumb-separator', [m('i.material-icons', separator)]),
6526
6525
  ];
6527
- }).reduce((acc, val) => acc.concat(val), []))
6526
+ })
6527
+ .reduce((acc, val) => acc.concat(val), [])),
6528
6528
  ]);
6529
- }
6529
+ },
6530
6530
  };
6531
6531
  };
6532
6532
  /**
@@ -6539,7 +6539,7 @@
6539
6539
  items.push({
6540
6540
  text: 'Home',
6541
6541
  href: basePath,
6542
- icon: 'home'
6542
+ icon: 'home',
6543
6543
  });
6544
6544
  // Add path segments
6545
6545
  let currentPath = basePath;
@@ -6549,7 +6549,7 @@
6549
6549
  items.push({
6550
6550
  text: segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, ' '),
6551
6551
  href: isLast ? undefined : currentPath,
6552
- active: isLast
6552
+ active: isLast,
6553
6553
  });
6554
6554
  });
6555
6555
  return items;
@@ -6568,19 +6568,18 @@
6568
6568
  items.push({
6569
6569
  text: 'Home',
6570
6570
  href: '/',
6571
- icon: 'home'
6571
+ icon: 'home',
6572
6572
  });
6573
6573
  let currentPath = '';
6574
6574
  segments.forEach((segment, index) => {
6575
6575
  currentPath += '/' + segment;
6576
6576
  const isLast = index === segments.length - 1;
6577
6577
  // Use custom text from config or format segment
6578
- const text = routeConfig[currentPath] ||
6579
- segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, ' ');
6578
+ const text = routeConfig[currentPath] || segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, ' ');
6580
6579
  items.push({
6581
6580
  text,
6582
6581
  href: isLast ? undefined : currentPath,
6583
- active: isLast
6582
+ active: isLast,
6584
6583
  });
6585
6584
  });
6586
6585
  return items;
@@ -6592,7 +6591,7 @@
6592
6591
  return hierarchy.map((item, index) => ({
6593
6592
  text: item[textKey],
6594
6593
  href: index === hierarchy.length - 1 ? undefined : item[pathKey],
6595
- active: index === hierarchy.length - 1
6594
+ active: index === hierarchy.length - 1,
6596
6595
  }));
6597
6596
  }
6598
6597
  }
@@ -6726,7 +6725,7 @@
6726
6725
  hasError ? 'error' : '',
6727
6726
  step.disabled ? 'disabled' : '',
6728
6727
  step.optional ? 'optional' : ''
6729
- ].filter(Boolean).join(' '),
6728
+ ].filter(Boolean).join(' ') || undefined,
6730
6729
  onclick: allowHeaderNavigation && !step.disabled ?
6731
6730
  () => goToStep(index, attrs) : undefined
6732
6731
  }, [
@@ -6800,6 +6799,292 @@
6800
6799
  };
6801
6800
  };
6802
6801
 
6802
+ // Utility function to check if a node is the last in its branch
6803
+ const isNodeLastInBranch = (nodePath, rootNodes) => {
6804
+ // Navigate to the node's position and check if it's the last child at every level
6805
+ let currentNodes = rootNodes;
6806
+ for (let i = 0; i < nodePath.length; i++) {
6807
+ const index = nodePath[i];
6808
+ const isLastAtThisLevel = index === currentNodes.length - 1;
6809
+ // If this is not the last child at this level, then this node is not last in branch
6810
+ if (!isLastAtThisLevel) {
6811
+ return false;
6812
+ }
6813
+ // Move to the next level if it exists
6814
+ if (i < nodePath.length - 1) {
6815
+ const currentNode = currentNodes[index];
6816
+ if (currentNode.children) {
6817
+ currentNodes = currentNode.children;
6818
+ }
6819
+ }
6820
+ }
6821
+ return true;
6822
+ };
6823
+ const TreeNodeComponent = () => {
6824
+ return {
6825
+ view: ({ attrs }) => {
6826
+ const { node, level, isSelected, isExpanded, isFocused, showConnectors, iconType, selectionMode, onToggleExpand, onToggleSelect, onFocus, } = attrs;
6827
+ const hasChildren = node.children && node.children.length > 0;
6828
+ const indentLevel = level * 24; // 24px per level
6829
+ return m('li.tree-node', {
6830
+ class: [
6831
+ isSelected && 'selected',
6832
+ isFocused && 'focused',
6833
+ node.disabled && 'disabled',
6834
+ hasChildren && 'has-children',
6835
+ attrs.isLastInBranch && 'tree-last-in-branch',
6836
+ ]
6837
+ .filter(Boolean)
6838
+ .join(' ') || undefined,
6839
+ 'data-node-id': node.id,
6840
+ 'data-level': level,
6841
+ }, [
6842
+ // Node content
6843
+ m('.tree-node-content', {
6844
+ style: {
6845
+ paddingLeft: `${indentLevel}px`,
6846
+ },
6847
+ onclick: node.disabled
6848
+ ? undefined
6849
+ : () => {
6850
+ if (selectionMode !== 'none') {
6851
+ onToggleSelect(node.id);
6852
+ }
6853
+ onFocus(node.id);
6854
+ },
6855
+ onkeydown: (e) => {
6856
+ if (e.key === 'Enter' || e.key === ' ') {
6857
+ e.preventDefault();
6858
+ if (!node.disabled && selectionMode !== 'none') {
6859
+ onToggleSelect(node.id);
6860
+ }
6861
+ }
6862
+ },
6863
+ tabindex: node.disabled ? -1 : 0,
6864
+ role: selectionMode === 'multiple' ? 'option' : 'treeitem',
6865
+ 'aria-selected': selectionMode !== 'none' ? isSelected.toString() : undefined,
6866
+ 'aria-expanded': hasChildren ? isExpanded.toString() : undefined,
6867
+ 'aria-disabled': node.disabled ? 'true' : undefined,
6868
+ }, [
6869
+ // Connector lines
6870
+ showConnectors &&
6871
+ level > 0 &&
6872
+ m('.tree-connectors', Array.from({ length: level }, (_, i) => m('.tree-connector', {
6873
+ key: i,
6874
+ style: { left: `${i * 24 + 12}px` },
6875
+ }))),
6876
+ // Expand/collapse icon or spacer
6877
+ hasChildren
6878
+ ? m('.tree-expand-icon', {
6879
+ onclick: (e) => {
6880
+ e.stopPropagation();
6881
+ if (!node.disabled) {
6882
+ onToggleExpand(node.id);
6883
+ }
6884
+ },
6885
+ class: iconType,
6886
+ }, [
6887
+ iconType === 'plus-minus'
6888
+ ? m('span.tree-plus-minus', isExpanded ? '−' : '+')
6889
+ : iconType === 'triangle'
6890
+ ? m('span.tree-triangle', { class: isExpanded ? 'expanded' : undefined }, '▶')
6891
+ : iconType === 'chevron'
6892
+ ? m(MaterialIcon, {
6893
+ name: 'chevron',
6894
+ direction: isExpanded ? 'down' : 'right',
6895
+ class: 'tree-chevron-icon',
6896
+ })
6897
+ : m(MaterialIcon, {
6898
+ name: 'caret',
6899
+ direction: isExpanded ? 'down' : 'right',
6900
+ class: 'tree-caret-icon',
6901
+ }),
6902
+ ])
6903
+ : m('.tree-expand-spacer'), // Spacer for alignment
6904
+ // Selection indicator for multiple selection
6905
+ selectionMode === 'multiple' &&
6906
+ m('.tree-selection-indicator', [
6907
+ m('input[type=checkbox]', {
6908
+ checked: isSelected,
6909
+ disabled: node.disabled,
6910
+ onchange: () => {
6911
+ if (!node.disabled) {
6912
+ onToggleSelect(node.id);
6913
+ }
6914
+ },
6915
+ onclick: (e) => e.stopPropagation(),
6916
+ }),
6917
+ ]),
6918
+ // Node icon (optional)
6919
+ node.icon && m('i.tree-node-icon.material-icons', node.icon),
6920
+ // Node label
6921
+ m('span.tree-node-label', node.label),
6922
+ ]),
6923
+ // Children (recursive)
6924
+ hasChildren &&
6925
+ isExpanded &&
6926
+ m('ul.tree-children', {
6927
+ role: 'group',
6928
+ 'aria-expanded': 'true',
6929
+ }, node.children.map((child, childIndex) => {
6930
+ var _a, _b, _c, _d, _e, _f;
6931
+ // Calculate state for each child using treeState
6932
+ const childIsSelected = (_b = (_a = attrs.treeState) === null || _a === void 0 ? void 0 : _a.selectedIds.has(child.id)) !== null && _b !== void 0 ? _b : false;
6933
+ const childIsExpanded = (_d = (_c = attrs.treeState) === null || _c === void 0 ? void 0 : _c.expandedIds.has(child.id)) !== null && _d !== void 0 ? _d : false;
6934
+ const childIsFocused = ((_e = attrs.treeState) === null || _e === void 0 ? void 0 : _e.focusedNodeId) === child.id;
6935
+ // Calculate if this child is last in branch
6936
+ const childPath = [...(attrs.currentPath || []), childIndex];
6937
+ const childIsLastInBranch = ((_f = attrs.treeAttrs) === null || _f === void 0 ? void 0 : _f.data) ?
6938
+ isNodeLastInBranch(childPath, attrs.treeAttrs.data) : false;
6939
+ return m(TreeNodeComponent, {
6940
+ key: child.id,
6941
+ node: child,
6942
+ level: level + 1,
6943
+ isSelected: childIsSelected,
6944
+ isExpanded: childIsExpanded,
6945
+ isFocused: childIsFocused,
6946
+ showConnectors,
6947
+ iconType,
6948
+ selectionMode,
6949
+ onToggleExpand,
6950
+ onToggleSelect,
6951
+ onFocus,
6952
+ isLastInBranch: childIsLastInBranch,
6953
+ currentPath: childPath,
6954
+ treeState: attrs.treeState,
6955
+ treeAttrs: attrs.treeAttrs,
6956
+ });
6957
+ })),
6958
+ ]);
6959
+ },
6960
+ };
6961
+ };
6962
+ const TreeView = () => {
6963
+ const state = {
6964
+ selectedIds: new Set(),
6965
+ expandedIds: new Set(),
6966
+ focusedNodeId: null,
6967
+ treeMap: new Map(),
6968
+ };
6969
+ const buildTreeMap = (nodes, map) => {
6970
+ nodes.forEach((node) => {
6971
+ map.set(node.id, node);
6972
+ if (node.children) {
6973
+ buildTreeMap(node.children, map);
6974
+ }
6975
+ });
6976
+ };
6977
+ const initializeExpandedNodes = (nodes) => {
6978
+ nodes.forEach((node) => {
6979
+ if (node.expanded) {
6980
+ state.expandedIds.add(node.id);
6981
+ }
6982
+ if (node.children) {
6983
+ initializeExpandedNodes(node.children);
6984
+ }
6985
+ });
6986
+ };
6987
+ const handleToggleExpand = (nodeId, attrs) => {
6988
+ var _a;
6989
+ const isExpanded = state.expandedIds.has(nodeId);
6990
+ if (isExpanded) {
6991
+ state.expandedIds.delete(nodeId);
6992
+ }
6993
+ else {
6994
+ state.expandedIds.add(nodeId);
6995
+ }
6996
+ (_a = attrs.onexpand) === null || _a === void 0 ? void 0 : _a.call(attrs, { nodeId, expanded: !isExpanded });
6997
+ };
6998
+ const handleToggleSelect = (nodeId, attrs) => {
6999
+ var _a;
7000
+ const { selectionMode = 'single' } = attrs;
7001
+ if (selectionMode === 'single') {
7002
+ state.selectedIds.clear();
7003
+ state.selectedIds.add(nodeId);
7004
+ }
7005
+ else if (selectionMode === 'multiple') {
7006
+ if (state.selectedIds.has(nodeId)) {
7007
+ state.selectedIds.delete(nodeId);
7008
+ }
7009
+ else {
7010
+ state.selectedIds.add(nodeId);
7011
+ }
7012
+ }
7013
+ (_a = attrs.onselection) === null || _a === void 0 ? void 0 : _a.call(attrs, Array.from(state.selectedIds));
7014
+ };
7015
+ const handleFocus = (nodeId) => {
7016
+ state.focusedNodeId = nodeId;
7017
+ };
7018
+ const renderNodes = (nodes, attrs, level = 0, parentPath = []) => {
7019
+ return nodes.map((node, index) => {
7020
+ var _a, _b, _c;
7021
+ const isSelected = state.selectedIds.has(node.id);
7022
+ const isExpanded = state.expandedIds.has(node.id);
7023
+ const isFocused = state.focusedNodeId === node.id;
7024
+ const currentPath = [...parentPath, index];
7025
+ const isLastInBranch = isNodeLastInBranch(currentPath, attrs.data);
7026
+ return m(TreeNodeComponent, {
7027
+ key: node.id,
7028
+ node,
7029
+ level,
7030
+ isSelected,
7031
+ isExpanded,
7032
+ isFocused,
7033
+ showConnectors: (_a = attrs.showConnectors) !== null && _a !== void 0 ? _a : true,
7034
+ iconType: (_b = attrs.iconType) !== null && _b !== void 0 ? _b : 'caret',
7035
+ selectionMode: (_c = attrs.selectionMode) !== null && _c !== void 0 ? _c : 'single',
7036
+ onToggleExpand: (nodeId) => handleToggleExpand(nodeId, attrs),
7037
+ onToggleSelect: (nodeId) => handleToggleSelect(nodeId, attrs),
7038
+ onFocus: handleFocus,
7039
+ isLastInBranch,
7040
+ currentPath,
7041
+ // Pass state and attrs for recursive rendering
7042
+ treeState: state,
7043
+ treeAttrs: attrs,
7044
+ });
7045
+ });
7046
+ };
7047
+ return {
7048
+ oninit: ({ attrs }) => {
7049
+ // Build internal tree map for efficient lookups
7050
+ buildTreeMap(attrs.data, state.treeMap);
7051
+ // Initialize expanded nodes from data
7052
+ initializeExpandedNodes(attrs.data);
7053
+ // Initialize selected nodes from props
7054
+ if (attrs.selectedIds) {
7055
+ state.selectedIds = new Set(attrs.selectedIds);
7056
+ }
7057
+ },
7058
+ onupdate: ({ attrs }) => {
7059
+ // Sync selectedIds prop with internal state
7060
+ if (attrs.selectedIds) {
7061
+ const newSelection = new Set(attrs.selectedIds);
7062
+ if (newSelection.size !== state.selectedIds.size ||
7063
+ !Array.from(newSelection).every((id) => state.selectedIds.has(id))) {
7064
+ state.selectedIds = newSelection;
7065
+ }
7066
+ }
7067
+ },
7068
+ view: ({ attrs }) => {
7069
+ const { data, className, style, id, selectionMode = 'single', showConnectors = true } = attrs;
7070
+ return m('div.tree-view', {
7071
+ class: [
7072
+ className,
7073
+ showConnectors && 'show-connectors'
7074
+ ].filter(Boolean).join(' ') || undefined,
7075
+ style,
7076
+ id,
7077
+ role: selectionMode === 'multiple' ? 'listbox' : 'tree',
7078
+ 'aria-multiselectable': selectionMode === 'multiple' ? 'true' : 'false',
7079
+ }, [
7080
+ m('ul.tree-root', {
7081
+ role: 'group',
7082
+ }, renderNodes(data, attrs)),
7083
+ ]);
7084
+ },
7085
+ };
7086
+ };
7087
+
6803
7088
  /**
6804
7089
  * @fileoverview Core TypeScript utility types for mithril-materialized library
6805
7090
  * These types improve type safety and developer experience across all components
@@ -6851,6 +7136,7 @@
6851
7136
  exports.ListItem = ListItem;
6852
7137
  exports.Mandatory = Mandatory;
6853
7138
  exports.MaterialBox = MaterialBox;
7139
+ exports.MaterialIcon = MaterialIcon;
6854
7140
  exports.ModalPanel = ModalPanel;
6855
7141
  exports.NumberInput = NumberInput;
6856
7142
  exports.Options = Options;
@@ -6885,6 +7171,7 @@
6885
7171
  exports.ToastComponent = ToastComponent;
6886
7172
  exports.Tooltip = Tooltip;
6887
7173
  exports.TooltipComponent = TooltipComponent;
7174
+ exports.TreeView = TreeView;
6888
7175
  exports.UrlInput = UrlInput;
6889
7176
  exports.Wizard = Wizard;
6890
7177
  exports.createBreadcrumb = createBreadcrumb;