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.esm.js CHANGED
@@ -836,6 +836,18 @@ const iconPaths = {
836
836
  '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',
837
837
  'M0 0h24v24H0z',
838
838
  ],
839
+ chevron: [
840
+ 'M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z', // chevron down
841
+ 'M0 0h24v24H0z', // background
842
+ ],
843
+ expand: [
844
+ 'M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z', // plus
845
+ 'M0 0h24v24H0z', // background
846
+ ],
847
+ collapse: [
848
+ 'M19 13H5v-2h14v2z', // minus
849
+ 'M0 0h24v24H0z', // background
850
+ ],
839
851
  };
840
852
  const MaterialIcon = () => {
841
853
  return {
@@ -845,8 +857,8 @@ const MaterialIcon = () => {
845
857
  const rotationMap = {
846
858
  down: 0,
847
859
  up: 180,
848
- left: -90,
849
- right: 90,
860
+ left: 90,
861
+ right: -90,
850
862
  };
851
863
  const rotation = (_a = rotationMap[direction]) !== null && _a !== void 0 ? _a : 0;
852
864
  const transform = rotation ? `rotate(${rotation}deg)` : undefined;
@@ -1155,7 +1167,7 @@ const CodeBlock = () => ({
1155
1167
  const lang = language || 'lang-TypeScript';
1156
1168
  const label = lang.replace('lang-', '');
1157
1169
  const cb = code instanceof Array ? code.join('\n') : code;
1158
- const cn = [newRow ? 'clear' : '', lang, className].filter(Boolean).join(' ').trim();
1170
+ const cn = [newRow ? 'clear' : '', lang, className].filter(Boolean).join(' ').trim() || undefined;
1159
1171
  return m(`pre.codeblock${newRow ? '.clear' : ''}`, attrs, [
1160
1172
  m('div', m('label', label)),
1161
1173
  m('code', Object.assign(Object.assign({}, params), { className: cn }), cb),
@@ -2208,7 +2220,7 @@ const InputField = (type, defaultClass = '') => () => {
2208
2220
  var _a;
2209
2221
  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"]);
2210
2222
  // const attributes = toAttrs(params);
2211
- const cn = [newRow ? 'clear' : '', defaultClass, className].filter(Boolean).join(' ').trim();
2223
+ const cn = [newRow ? 'clear' : '', defaultClass, className].filter(Boolean).join(' ').trim() || undefined;
2212
2224
  const isActive = state.active || ((_a = state.inputElement) === null || _a === void 0 ? void 0 : _a.value) || placeholder || type === 'color' || type === 'range'
2213
2225
  ? true
2214
2226
  : false;
@@ -2484,7 +2496,7 @@ const Options = () => {
2484
2496
  callback(checkedIds);
2485
2497
  }
2486
2498
  : undefined;
2487
- const cn = [newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim();
2499
+ const cn = [newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim() || undefined;
2488
2500
  const optionsContent = layout === 'horizontal'
2489
2501
  ? m('div.grid-container', options.map((option) => m(InputCheckbox, {
2490
2502
  disabled: disabled || option.disabled,
@@ -3529,7 +3541,7 @@ const MaterialBox = () => {
3529
3541
  view: ({ attrs }) => {
3530
3542
  const { src, alt, width, height, caption, className, style } = attrs, otherAttrs = __rest(attrs, ["src", "alt", "width", "height", "caption", "className", "style"]);
3531
3543
  return m('img.materialboxed', Object.assign(Object.assign({}, otherAttrs), { src, alt: alt || '', width,
3532
- height, className: ['materialboxed', className].filter(Boolean).join(' '), style: Object.assign({ cursor: 'zoom-in', transition: 'opacity 200ms ease' }, style), onclick: (e) => {
3544
+ height, className: ['materialboxed', className].filter(Boolean).join(' ') || undefined, style: Object.assign({ cursor: 'zoom-in', transition: 'opacity 200ms ease' }, style), onclick: (e) => {
3533
3545
  e.preventDefault();
3534
3546
  openBox(e.target, attrs);
3535
3547
  } }));
@@ -3611,7 +3623,7 @@ const ModalPanel = () => {
3611
3623
  .filter(Boolean)
3612
3624
  .join(' ')
3613
3625
  .trim();
3614
- const overlayClasses = ['modal-overlay', state.isOpen ? 'active' : ''].filter(Boolean).join(' ').trim();
3626
+ const overlayClasses = ['modal-overlay', state.isOpen ? 'active' : ''].filter(Boolean).join(' ').trim() || undefined;
3615
3627
  return m('div', { className: 'modal-container' }, [
3616
3628
  // Modal overlay
3617
3629
  m('div', {
@@ -3636,23 +3648,25 @@ const ModalPanel = () => {
3636
3648
  role: 'dialog',
3637
3649
  'aria-labelledby': `${id}-title`,
3638
3650
  'aria-describedby': description ? `${id}-desc` : undefined,
3639
- style: Object.assign(Object.assign({ display: state.isOpen ? 'flex' : 'none', position: 'fixed' }, (bottomSheet ? {
3640
- // Bottom sheet positioning
3641
- top: 'auto',
3642
- bottom: '0',
3643
- left: '0',
3644
- right: '0',
3645
- transform: 'none',
3646
- maxWidth: '100%',
3647
- borderRadius: '8px 8px 0 0',
3648
- } : {
3649
- // Regular modal positioning
3650
- top: '50%',
3651
- left: '50%',
3652
- transform: 'translate(-50%, -50%)',
3653
- maxWidth: '75%',
3654
- borderRadius: '4px',
3655
- })), { 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)' }),
3651
+ style: Object.assign(Object.assign({ display: state.isOpen ? 'flex' : 'none', position: 'fixed' }, (bottomSheet
3652
+ ? {
3653
+ // Bottom sheet positioning
3654
+ top: 'auto',
3655
+ bottom: '0',
3656
+ left: '0',
3657
+ right: '0',
3658
+ transform: 'none',
3659
+ maxWidth: '100%',
3660
+ borderRadius: '8px 8px 0 0',
3661
+ }
3662
+ : {
3663
+ // Regular modal positioning
3664
+ top: '50%',
3665
+ left: '50%',
3666
+ transform: 'translate(-50%, -50%)',
3667
+ maxWidth: '75%',
3668
+ borderRadius: '4px',
3669
+ })), { 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)' }),
3656
3670
  onclick: (e) => e.stopPropagation(), // Prevent backdrop click when clicking inside modal
3657
3671
  }, [
3658
3672
  // Close button
@@ -4690,7 +4704,7 @@ const RadioButtons = () => {
4690
4704
  callback(propId);
4691
4705
  }
4692
4706
  };
4693
- const cn = [newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim();
4707
+ const cn = [newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim() || undefined;
4694
4708
  const optionsContent = layout === 'horizontal'
4695
4709
  ? m('div.grid-container', options.map((r) => m(RadioButton, Object.assign(Object.assign({}, r), { onchange,
4696
4710
  groupId, disabled: disabled || r.disabled, className: checkboxClass, checked: r.id === checkedId, inputId: `${componentId}-${r.id}` }))))
@@ -4963,7 +4977,7 @@ const Switch = () => {
4963
4977
  view: ({ attrs }) => {
4964
4978
  const id = attrs.id || state.id;
4965
4979
  const { label, left, right, disabled, newRow, onchange, isMandatory, className = 'col s12' } = attrs, params = __rest(attrs, ["label", "left", "right", "disabled", "newRow", "onchange", "isMandatory", "className"]);
4966
- const cn = ['input-field', newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim();
4980
+ const cn = ['input-field', newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim() || undefined;
4967
4981
  return m('div', {
4968
4982
  className: cn,
4969
4983
  onclick: (e) => {
@@ -5114,7 +5128,7 @@ const Tabs = () => {
5114
5128
  },
5115
5129
  view: ({ attrs }) => {
5116
5130
  const { tabWidth, tabs, className, style, swipeable = false } = attrs;
5117
- const cn = [tabWidth === 'fill' ? 'tabs-fixed-width' : '', className].filter(Boolean).join(' ').trim();
5131
+ const cn = [tabWidth === 'fill' ? 'tabs-fixed-width' : '', className].filter(Boolean).join(' ').trim() || undefined;
5118
5132
  const anchoredTabs = tabs.map(toAnchored());
5119
5133
  const activeTab = setActiveTabId(anchoredTabs, attrs.selectedTabId);
5120
5134
  updateIndicator();
@@ -6100,8 +6114,8 @@ const FileUpload = () => {
6100
6114
  }
6101
6115
  // Check file type
6102
6116
  if (attrs.accept) {
6103
- const acceptedTypes = attrs.accept.split(',').map(type => type.trim());
6104
- const isAccepted = acceptedTypes.some(acceptedType => {
6117
+ const acceptedTypes = attrs.accept.split(',').map((type) => type.trim());
6118
+ const isAccepted = acceptedTypes.some((acceptedType) => {
6105
6119
  if (acceptedType.startsWith('.')) {
6106
6120
  // Extension check
6107
6121
  return file.name.toLowerCase().endsWith(acceptedType.toLowerCase());
@@ -6161,11 +6175,11 @@ const FileUpload = () => {
6161
6175
  }
6162
6176
  // Notify parent component
6163
6177
  if (attrs.onFilesSelected) {
6164
- attrs.onFilesSelected(state.files.filter(f => !f.uploadError));
6178
+ attrs.onFilesSelected(state.files.filter((f) => !f.uploadError));
6165
6179
  }
6166
6180
  };
6167
6181
  const removeFile = (fileToRemove, attrs) => {
6168
- state.files = state.files.filter(file => file !== fileToRemove);
6182
+ state.files = state.files.filter((file) => file !== fileToRemove);
6169
6183
  if (attrs.onFileRemoved) {
6170
6184
  attrs.onFileRemoved(fileToRemove);
6171
6185
  }
@@ -6184,11 +6198,11 @@ const FileUpload = () => {
6184
6198
  id: uniqueId(),
6185
6199
  files: [],
6186
6200
  isDragOver: false,
6187
- isUploading: false
6201
+ isUploading: false,
6188
6202
  };
6189
6203
  },
6190
6204
  view: ({ attrs }) => {
6191
- const { accept, multiple = false, disabled = false, label = 'Choose files or drag them here', helperText, showPreview = true, className = '', error } = attrs;
6205
+ const { accept, multiple = false, disabled = false, label = 'Choose files or drag them here', helperText, showPreview = true, className = '', error, } = attrs;
6192
6206
  return m('.file-upload-container', { class: className }, [
6193
6207
  // Upload area
6194
6208
  m('.file-upload-area', {
@@ -6196,8 +6210,10 @@ const FileUpload = () => {
6196
6210
  state.isDragOver ? 'drag-over' : '',
6197
6211
  disabled ? 'disabled' : '',
6198
6212
  error ? 'error' : '',
6199
- state.files.length > 0 ? 'has-files' : ''
6200
- ].filter(Boolean).join(' '),
6213
+ state.files.length > 0 ? 'has-files' : '',
6214
+ ]
6215
+ .filter(Boolean)
6216
+ .join(' ') || undefined,
6201
6217
  ondragover: (e) => {
6202
6218
  if (disabled)
6203
6219
  return;
@@ -6228,7 +6244,7 @@ const FileUpload = () => {
6228
6244
  return;
6229
6245
  const input = document.getElementById(state.id);
6230
6246
  input === null || input === void 0 ? void 0 : input.click();
6231
- }
6247
+ },
6232
6248
  }, [
6233
6249
  m('input[type="file"]', {
6234
6250
  id: state.id,
@@ -6241,57 +6257,55 @@ const FileUpload = () => {
6241
6257
  if (target.files) {
6242
6258
  handleFiles(target.files, attrs);
6243
6259
  }
6244
- }
6260
+ },
6245
6261
  }),
6246
6262
  m('.file-upload-content', [
6247
6263
  m('i.material-icons.file-upload-icon', 'cloud_upload'),
6248
6264
  m('p.file-upload-label', label),
6249
6265
  helperText && m('p.file-upload-helper', helperText),
6250
- accept && m('p.file-upload-types', `Accepted: ${accept}`)
6251
- ])
6266
+ accept && m('p.file-upload-types', `Accepted: ${accept}`),
6267
+ ]),
6252
6268
  ]),
6253
6269
  // Error message
6254
6270
  error && m('.file-upload-error', error),
6255
6271
  // File list
6256
- state.files.length > 0 && m('.file-upload-list', [
6257
- m('h6', 'Selected Files:'),
6258
- state.files.map(file => m('.file-upload-item', { key: file.name + file.size }, [
6259
- // Preview thumbnail
6260
- showPreview && file.preview && m('.file-preview', [
6261
- m('img', { src: file.preview, alt: file.name })
6262
- ]),
6263
- // File info
6264
- m('.file-info', [
6265
- m('.file-name', file.name),
6266
- m('.file-details', [
6267
- m('span.file-size', formatFileSize(file.size)),
6268
- file.type && m('span.file-type', file.type)
6269
- ]),
6270
- // Progress bar (if uploading)
6271
- file.uploadProgress !== undefined && m('.file-progress', [
6272
- m('.progress', [
6273
- m('.determinate', {
6274
- style: { width: `${file.uploadProgress}%` }
6275
- })
6276
- ])
6272
+ state.files.length > 0 &&
6273
+ m('.file-upload-list', [
6274
+ m('h6', 'Selected Files:'),
6275
+ state.files.map((file) => m('.file-upload-item', { key: file.name + file.size }, [
6276
+ // Preview thumbnail
6277
+ showPreview && file.preview && m('.file-preview', [m('img', { src: file.preview, alt: file.name })]),
6278
+ // File info
6279
+ m('.file-info', [
6280
+ m('.file-name', file.name),
6281
+ m('.file-details', [
6282
+ m('span.file-size', formatFileSize(file.size)),
6283
+ file.type && m('span.file-type', file.type),
6284
+ ]),
6285
+ // Progress bar (if uploading)
6286
+ file.uploadProgress !== undefined &&
6287
+ m('.file-progress', [
6288
+ m('.progress', [
6289
+ m('.determinate', {
6290
+ style: { width: `${file.uploadProgress}%` },
6291
+ }),
6292
+ ]),
6293
+ ]),
6294
+ // Error message
6295
+ file.uploadError && m('.file-error', file.uploadError),
6277
6296
  ]),
6278
- // Error message
6279
- file.uploadError && m('.file-error', file.uploadError)
6280
- ]),
6281
- // Remove button
6282
- m('button.btn-flat.file-remove', {
6283
- onclick: (e) => {
6284
- e.stopPropagation();
6285
- removeFile(file, attrs);
6286
- },
6287
- title: 'Remove file'
6288
- }, [
6289
- m('i.material-icons', 'close')
6290
- ])
6291
- ]))
6292
- ])
6297
+ // Remove button
6298
+ m('button.btn-flat.file-remove', {
6299
+ onclick: (e) => {
6300
+ e.stopPropagation();
6301
+ removeFile(file, attrs);
6302
+ },
6303
+ title: 'Remove file',
6304
+ }, [m('i.material-icons', 'close')]),
6305
+ ])),
6306
+ ]),
6293
6307
  ]);
6294
- }
6308
+ },
6295
6309
  };
6296
6310
  };
6297
6311
 
@@ -6321,7 +6335,7 @@ const Sidenav = () => {
6321
6335
  state = {
6322
6336
  id: attrs.id || uniqueId(),
6323
6337
  isOpen: attrs.isOpen || false,
6324
- isAnimating: false
6338
+ isAnimating: false,
6325
6339
  };
6326
6340
  // Set up keyboard listener
6327
6341
  if (typeof document !== 'undefined' && attrs.closeOnEscape !== false) {
@@ -6350,34 +6364,33 @@ const Sidenav = () => {
6350
6364
  }
6351
6365
  },
6352
6366
  view: ({ attrs, children }) => {
6353
- const { position = 'left', mode = 'overlay', width = 300, className = '', showBackdrop = true, animationDuration = 300, fixed = false } = attrs;
6367
+ const { position = 'left', mode = 'overlay', width = 300, className = '', showBackdrop = true, animationDuration = 300, fixed = false, } = attrs;
6354
6368
  const isOpen = state.isOpen;
6355
6369
  return [
6356
6370
  // Backdrop (using existing materialize class)
6357
- showBackdrop && mode === 'overlay' && m('.sidenav-overlay', {
6358
- style: {
6359
- display: isOpen ? 'block' : 'none',
6360
- opacity: isOpen ? '1' : '0'
6361
- },
6362
- onclick: () => handleBackdropClick(attrs)
6363
- }),
6371
+ showBackdrop &&
6372
+ mode === 'overlay' &&
6373
+ m('.sidenav-overlay', {
6374
+ style: {
6375
+ display: isOpen ? 'block' : 'none',
6376
+ opacity: isOpen ? '1' : '0',
6377
+ },
6378
+ onclick: () => handleBackdropClick(attrs),
6379
+ }),
6364
6380
  // Sidenav (using existing materialize structure)
6365
6381
  m('ul.sidenav', {
6366
6382
  id: state.id,
6367
- class: [
6368
- position === 'right' ? 'right-aligned' : '',
6369
- fixed ? 'sidenav-fixed' : '',
6370
- className
6371
- ].filter(Boolean).join(' '),
6383
+ class: [position === 'right' ? 'right-aligned' : '', fixed ? 'sidenav-fixed' : '', className]
6384
+ .filter(Boolean)
6385
+ .join(' ') || undefined,
6372
6386
  style: {
6373
6387
  width: `${width}px`,
6374
- transform: isOpen ? 'translateX(0)' :
6375
- position === 'left' ? 'translateX(-105%)' : 'translateX(105%)',
6376
- 'transition-duration': `${animationDuration}ms`
6377
- }
6378
- }, children)
6388
+ transform: isOpen ? 'translateX(0)' : position === 'left' ? 'translateX(-105%)' : 'translateX(105%)',
6389
+ 'transition-duration': `${animationDuration}ms`,
6390
+ },
6391
+ }, children),
6379
6392
  ];
6380
- }
6393
+ },
6381
6394
  };
6382
6395
  };
6383
6396
  /**
@@ -6387,37 +6400,30 @@ const Sidenav = () => {
6387
6400
  const SidenavItem = () => {
6388
6401
  return {
6389
6402
  view: ({ attrs, children }) => {
6390
- const { text, icon, active = false, disabled = false, onclick, href, className = '', divider = false, subheader = false } = attrs;
6403
+ const { text, icon, active = false, disabled = false, onclick, href, className = '', divider = false, subheader = false, } = attrs;
6391
6404
  if (divider) {
6392
6405
  return m('li.divider');
6393
6406
  }
6394
6407
  if (subheader) {
6395
6408
  return m('li.subheader', text || children);
6396
6409
  }
6397
- const itemClasses = [
6398
- active ? 'active' : '',
6399
- disabled ? 'disabled' : '',
6400
- className
6401
- ].filter(Boolean).join(' ');
6402
- const content = [
6403
- icon && m('i.material-icons', icon),
6404
- text || children
6405
- ];
6410
+ const itemClasses = [active ? 'active' : '', disabled ? 'disabled' : '', className].filter(Boolean).join(' ') || undefined;
6411
+ const content = [icon && m('i.material-icons', icon), text || children];
6406
6412
  if (href && !disabled) {
6407
6413
  return m('li', { class: itemClasses }, [
6408
6414
  m('a', {
6409
6415
  href,
6410
- onclick: disabled ? undefined : onclick
6411
- }, content)
6416
+ onclick: disabled ? undefined : onclick,
6417
+ }, content),
6412
6418
  ]);
6413
6419
  }
6414
6420
  return m('li', { class: itemClasses }, [
6415
6421
  m('a', {
6416
6422
  onclick: disabled ? undefined : onclick,
6417
- href: '#!'
6418
- }, content)
6423
+ href: '#!',
6424
+ }, content),
6419
6425
  ]);
6420
- }
6426
+ },
6421
6427
  };
6422
6428
  };
6423
6429
  /**
@@ -6468,7 +6474,7 @@ class SidenavManager {
6468
6474
  const Breadcrumb = () => {
6469
6475
  return {
6470
6476
  view: ({ attrs }) => {
6471
- const { items = [], separator = 'chevron_right', className = '', showIcons = false, maxItems, showHome = false } = attrs;
6477
+ const { items = [], separator = 'chevron_right', className = '', showIcons = false, maxItems, showHome = false, } = attrs;
6472
6478
  if (items.length === 0) {
6473
6479
  return null;
6474
6480
  }
@@ -6477,52 +6483,46 @@ const Breadcrumb = () => {
6477
6483
  if (maxItems && items.length > maxItems) {
6478
6484
  const firstItem = items[0];
6479
6485
  const lastItems = items.slice(-(maxItems - 2));
6480
- displayItems = [
6481
- firstItem,
6482
- { text: '...', disabled: true, className: 'breadcrumb-ellipsis' },
6483
- ...lastItems
6484
- ];
6486
+ displayItems = [firstItem, { text: '...', disabled: true, className: 'breadcrumb-ellipsis' }, ...lastItems];
6485
6487
  }
6486
6488
  return m('nav.breadcrumb', { class: className }, [
6487
- m('ol.breadcrumb-list', displayItems.map((item, index) => {
6489
+ m('ol.breadcrumb-list', displayItems
6490
+ .map((item, index) => {
6488
6491
  const isLast = index === displayItems.length - 1;
6489
6492
  const isFirst = index === 0;
6490
6493
  return [
6491
6494
  // Breadcrumb item
6492
6495
  m('li.breadcrumb-item', {
6493
- class: [
6494
- item.active || isLast ? 'active' : '',
6495
- item.disabled ? 'disabled' : '',
6496
- item.className || ''
6497
- ].filter(Boolean).join(' ')
6496
+ class: [item.active || isLast ? 'active' : '', item.disabled ? 'disabled' : '', item.className || '']
6497
+ .filter(Boolean)
6498
+ .join(' ') || undefined,
6498
6499
  }, [
6499
- item.href && !item.disabled && !isLast ?
6500
- // Link item
6501
- m('a.breadcrumb-link', {
6502
- href: item.href,
6503
- onclick: item.onclick
6504
- }, [
6505
- (showIcons && item.icon) && m('i.material-icons.breadcrumb-icon', item.icon),
6506
- (showHome && isFirst && !item.icon) && m('i.material-icons.breadcrumb-icon', 'home'),
6507
- m('span.breadcrumb-text', item.text)
6508
- ]) :
6509
- // Text item (active or disabled)
6510
- m('span.breadcrumb-text', {
6511
- onclick: item.disabled ? undefined : item.onclick
6512
- }, [
6513
- (showIcons && item.icon) && m('i.material-icons.breadcrumb-icon', item.icon),
6514
- (showHome && isFirst && !item.icon) && m('i.material-icons.breadcrumb-icon', 'home'),
6515
- item.text
6516
- ])
6500
+ item.href && !item.disabled && !isLast
6501
+ ? // Link item
6502
+ m('a.breadcrumb-link', {
6503
+ href: item.href,
6504
+ onclick: item.onclick,
6505
+ }, [
6506
+ showIcons && item.icon && m('i.material-icons.breadcrumb-icon', item.icon),
6507
+ showHome && isFirst && !item.icon && m('i.material-icons.breadcrumb-icon', 'home'),
6508
+ m('span.breadcrumb-text', item.text),
6509
+ ])
6510
+ : // Text item (active or disabled)
6511
+ m('span.breadcrumb-text', {
6512
+ onclick: item.disabled ? undefined : item.onclick,
6513
+ }, [
6514
+ showIcons && item.icon && m('i.material-icons.breadcrumb-icon', item.icon),
6515
+ showHome && isFirst && !item.icon && m('i.material-icons.breadcrumb-icon', 'home'),
6516
+ item.text,
6517
+ ]),
6517
6518
  ]),
6518
6519
  // Separator (except for last item)
6519
- !isLast && m('li.breadcrumb-separator', [
6520
- m('i.material-icons', separator)
6521
- ])
6520
+ !isLast && m('li.breadcrumb-separator', [m('i.material-icons', separator)]),
6522
6521
  ];
6523
- }).reduce((acc, val) => acc.concat(val), []))
6522
+ })
6523
+ .reduce((acc, val) => acc.concat(val), [])),
6524
6524
  ]);
6525
- }
6525
+ },
6526
6526
  };
6527
6527
  };
6528
6528
  /**
@@ -6535,7 +6535,7 @@ const createBreadcrumb = (path, basePath = '/') => {
6535
6535
  items.push({
6536
6536
  text: 'Home',
6537
6537
  href: basePath,
6538
- icon: 'home'
6538
+ icon: 'home',
6539
6539
  });
6540
6540
  // Add path segments
6541
6541
  let currentPath = basePath;
@@ -6545,7 +6545,7 @@ const createBreadcrumb = (path, basePath = '/') => {
6545
6545
  items.push({
6546
6546
  text: segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, ' '),
6547
6547
  href: isLast ? undefined : currentPath,
6548
- active: isLast
6548
+ active: isLast,
6549
6549
  });
6550
6550
  });
6551
6551
  return items;
@@ -6564,19 +6564,18 @@ class BreadcrumbManager {
6564
6564
  items.push({
6565
6565
  text: 'Home',
6566
6566
  href: '/',
6567
- icon: 'home'
6567
+ icon: 'home',
6568
6568
  });
6569
6569
  let currentPath = '';
6570
6570
  segments.forEach((segment, index) => {
6571
6571
  currentPath += '/' + segment;
6572
6572
  const isLast = index === segments.length - 1;
6573
6573
  // Use custom text from config or format segment
6574
- const text = routeConfig[currentPath] ||
6575
- segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, ' ');
6574
+ const text = routeConfig[currentPath] || segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, ' ');
6576
6575
  items.push({
6577
6576
  text,
6578
6577
  href: isLast ? undefined : currentPath,
6579
- active: isLast
6578
+ active: isLast,
6580
6579
  });
6581
6580
  });
6582
6581
  return items;
@@ -6588,7 +6587,7 @@ class BreadcrumbManager {
6588
6587
  return hierarchy.map((item, index) => ({
6589
6588
  text: item[textKey],
6590
6589
  href: index === hierarchy.length - 1 ? undefined : item[pathKey],
6591
- active: index === hierarchy.length - 1
6590
+ active: index === hierarchy.length - 1,
6592
6591
  }));
6593
6592
  }
6594
6593
  }
@@ -6722,7 +6721,7 @@ const Wizard = () => {
6722
6721
  hasError ? 'error' : '',
6723
6722
  step.disabled ? 'disabled' : '',
6724
6723
  step.optional ? 'optional' : ''
6725
- ].filter(Boolean).join(' '),
6724
+ ].filter(Boolean).join(' ') || undefined,
6726
6725
  onclick: allowHeaderNavigation && !step.disabled ?
6727
6726
  () => goToStep(index, attrs) : undefined
6728
6727
  }, [
@@ -6796,6 +6795,292 @@ const Stepper = () => {
6796
6795
  };
6797
6796
  };
6798
6797
 
6798
+ // Utility function to check if a node is the last in its branch
6799
+ const isNodeLastInBranch = (nodePath, rootNodes) => {
6800
+ // Navigate to the node's position and check if it's the last child at every level
6801
+ let currentNodes = rootNodes;
6802
+ for (let i = 0; i < nodePath.length; i++) {
6803
+ const index = nodePath[i];
6804
+ const isLastAtThisLevel = index === currentNodes.length - 1;
6805
+ // If this is not the last child at this level, then this node is not last in branch
6806
+ if (!isLastAtThisLevel) {
6807
+ return false;
6808
+ }
6809
+ // Move to the next level if it exists
6810
+ if (i < nodePath.length - 1) {
6811
+ const currentNode = currentNodes[index];
6812
+ if (currentNode.children) {
6813
+ currentNodes = currentNode.children;
6814
+ }
6815
+ }
6816
+ }
6817
+ return true;
6818
+ };
6819
+ const TreeNodeComponent = () => {
6820
+ return {
6821
+ view: ({ attrs }) => {
6822
+ const { node, level, isSelected, isExpanded, isFocused, showConnectors, iconType, selectionMode, onToggleExpand, onToggleSelect, onFocus, } = attrs;
6823
+ const hasChildren = node.children && node.children.length > 0;
6824
+ const indentLevel = level * 24; // 24px per level
6825
+ return m('li.tree-node', {
6826
+ class: [
6827
+ isSelected && 'selected',
6828
+ isFocused && 'focused',
6829
+ node.disabled && 'disabled',
6830
+ hasChildren && 'has-children',
6831
+ attrs.isLastInBranch && 'tree-last-in-branch',
6832
+ ]
6833
+ .filter(Boolean)
6834
+ .join(' ') || undefined,
6835
+ 'data-node-id': node.id,
6836
+ 'data-level': level,
6837
+ }, [
6838
+ // Node content
6839
+ m('.tree-node-content', {
6840
+ style: {
6841
+ paddingLeft: `${indentLevel}px`,
6842
+ },
6843
+ onclick: node.disabled
6844
+ ? undefined
6845
+ : () => {
6846
+ if (selectionMode !== 'none') {
6847
+ onToggleSelect(node.id);
6848
+ }
6849
+ onFocus(node.id);
6850
+ },
6851
+ onkeydown: (e) => {
6852
+ if (e.key === 'Enter' || e.key === ' ') {
6853
+ e.preventDefault();
6854
+ if (!node.disabled && selectionMode !== 'none') {
6855
+ onToggleSelect(node.id);
6856
+ }
6857
+ }
6858
+ },
6859
+ tabindex: node.disabled ? -1 : 0,
6860
+ role: selectionMode === 'multiple' ? 'option' : 'treeitem',
6861
+ 'aria-selected': selectionMode !== 'none' ? isSelected.toString() : undefined,
6862
+ 'aria-expanded': hasChildren ? isExpanded.toString() : undefined,
6863
+ 'aria-disabled': node.disabled ? 'true' : undefined,
6864
+ }, [
6865
+ // Connector lines
6866
+ showConnectors &&
6867
+ level > 0 &&
6868
+ m('.tree-connectors', Array.from({ length: level }, (_, i) => m('.tree-connector', {
6869
+ key: i,
6870
+ style: { left: `${i * 24 + 12}px` },
6871
+ }))),
6872
+ // Expand/collapse icon or spacer
6873
+ hasChildren
6874
+ ? m('.tree-expand-icon', {
6875
+ onclick: (e) => {
6876
+ e.stopPropagation();
6877
+ if (!node.disabled) {
6878
+ onToggleExpand(node.id);
6879
+ }
6880
+ },
6881
+ class: iconType,
6882
+ }, [
6883
+ iconType === 'plus-minus'
6884
+ ? m('span.tree-plus-minus', isExpanded ? '−' : '+')
6885
+ : iconType === 'triangle'
6886
+ ? m('span.tree-triangle', { class: isExpanded ? 'expanded' : undefined }, '▶')
6887
+ : iconType === 'chevron'
6888
+ ? m(MaterialIcon, {
6889
+ name: 'chevron',
6890
+ direction: isExpanded ? 'down' : 'right',
6891
+ class: 'tree-chevron-icon',
6892
+ })
6893
+ : m(MaterialIcon, {
6894
+ name: 'caret',
6895
+ direction: isExpanded ? 'down' : 'right',
6896
+ class: 'tree-caret-icon',
6897
+ }),
6898
+ ])
6899
+ : m('.tree-expand-spacer'), // Spacer for alignment
6900
+ // Selection indicator for multiple selection
6901
+ selectionMode === 'multiple' &&
6902
+ m('.tree-selection-indicator', [
6903
+ m('input[type=checkbox]', {
6904
+ checked: isSelected,
6905
+ disabled: node.disabled,
6906
+ onchange: () => {
6907
+ if (!node.disabled) {
6908
+ onToggleSelect(node.id);
6909
+ }
6910
+ },
6911
+ onclick: (e) => e.stopPropagation(),
6912
+ }),
6913
+ ]),
6914
+ // Node icon (optional)
6915
+ node.icon && m('i.tree-node-icon.material-icons', node.icon),
6916
+ // Node label
6917
+ m('span.tree-node-label', node.label),
6918
+ ]),
6919
+ // Children (recursive)
6920
+ hasChildren &&
6921
+ isExpanded &&
6922
+ m('ul.tree-children', {
6923
+ role: 'group',
6924
+ 'aria-expanded': 'true',
6925
+ }, node.children.map((child, childIndex) => {
6926
+ var _a, _b, _c, _d, _e, _f;
6927
+ // Calculate state for each child using treeState
6928
+ const childIsSelected = (_b = (_a = attrs.treeState) === null || _a === void 0 ? void 0 : _a.selectedIds.has(child.id)) !== null && _b !== void 0 ? _b : false;
6929
+ const childIsExpanded = (_d = (_c = attrs.treeState) === null || _c === void 0 ? void 0 : _c.expandedIds.has(child.id)) !== null && _d !== void 0 ? _d : false;
6930
+ const childIsFocused = ((_e = attrs.treeState) === null || _e === void 0 ? void 0 : _e.focusedNodeId) === child.id;
6931
+ // Calculate if this child is last in branch
6932
+ const childPath = [...(attrs.currentPath || []), childIndex];
6933
+ const childIsLastInBranch = ((_f = attrs.treeAttrs) === null || _f === void 0 ? void 0 : _f.data) ?
6934
+ isNodeLastInBranch(childPath, attrs.treeAttrs.data) : false;
6935
+ return m(TreeNodeComponent, {
6936
+ key: child.id,
6937
+ node: child,
6938
+ level: level + 1,
6939
+ isSelected: childIsSelected,
6940
+ isExpanded: childIsExpanded,
6941
+ isFocused: childIsFocused,
6942
+ showConnectors,
6943
+ iconType,
6944
+ selectionMode,
6945
+ onToggleExpand,
6946
+ onToggleSelect,
6947
+ onFocus,
6948
+ isLastInBranch: childIsLastInBranch,
6949
+ currentPath: childPath,
6950
+ treeState: attrs.treeState,
6951
+ treeAttrs: attrs.treeAttrs,
6952
+ });
6953
+ })),
6954
+ ]);
6955
+ },
6956
+ };
6957
+ };
6958
+ const TreeView = () => {
6959
+ const state = {
6960
+ selectedIds: new Set(),
6961
+ expandedIds: new Set(),
6962
+ focusedNodeId: null,
6963
+ treeMap: new Map(),
6964
+ };
6965
+ const buildTreeMap = (nodes, map) => {
6966
+ nodes.forEach((node) => {
6967
+ map.set(node.id, node);
6968
+ if (node.children) {
6969
+ buildTreeMap(node.children, map);
6970
+ }
6971
+ });
6972
+ };
6973
+ const initializeExpandedNodes = (nodes) => {
6974
+ nodes.forEach((node) => {
6975
+ if (node.expanded) {
6976
+ state.expandedIds.add(node.id);
6977
+ }
6978
+ if (node.children) {
6979
+ initializeExpandedNodes(node.children);
6980
+ }
6981
+ });
6982
+ };
6983
+ const handleToggleExpand = (nodeId, attrs) => {
6984
+ var _a;
6985
+ const isExpanded = state.expandedIds.has(nodeId);
6986
+ if (isExpanded) {
6987
+ state.expandedIds.delete(nodeId);
6988
+ }
6989
+ else {
6990
+ state.expandedIds.add(nodeId);
6991
+ }
6992
+ (_a = attrs.onexpand) === null || _a === void 0 ? void 0 : _a.call(attrs, { nodeId, expanded: !isExpanded });
6993
+ };
6994
+ const handleToggleSelect = (nodeId, attrs) => {
6995
+ var _a;
6996
+ const { selectionMode = 'single' } = attrs;
6997
+ if (selectionMode === 'single') {
6998
+ state.selectedIds.clear();
6999
+ state.selectedIds.add(nodeId);
7000
+ }
7001
+ else if (selectionMode === 'multiple') {
7002
+ if (state.selectedIds.has(nodeId)) {
7003
+ state.selectedIds.delete(nodeId);
7004
+ }
7005
+ else {
7006
+ state.selectedIds.add(nodeId);
7007
+ }
7008
+ }
7009
+ (_a = attrs.onselection) === null || _a === void 0 ? void 0 : _a.call(attrs, Array.from(state.selectedIds));
7010
+ };
7011
+ const handleFocus = (nodeId) => {
7012
+ state.focusedNodeId = nodeId;
7013
+ };
7014
+ const renderNodes = (nodes, attrs, level = 0, parentPath = []) => {
7015
+ return nodes.map((node, index) => {
7016
+ var _a, _b, _c;
7017
+ const isSelected = state.selectedIds.has(node.id);
7018
+ const isExpanded = state.expandedIds.has(node.id);
7019
+ const isFocused = state.focusedNodeId === node.id;
7020
+ const currentPath = [...parentPath, index];
7021
+ const isLastInBranch = isNodeLastInBranch(currentPath, attrs.data);
7022
+ return m(TreeNodeComponent, {
7023
+ key: node.id,
7024
+ node,
7025
+ level,
7026
+ isSelected,
7027
+ isExpanded,
7028
+ isFocused,
7029
+ showConnectors: (_a = attrs.showConnectors) !== null && _a !== void 0 ? _a : true,
7030
+ iconType: (_b = attrs.iconType) !== null && _b !== void 0 ? _b : 'caret',
7031
+ selectionMode: (_c = attrs.selectionMode) !== null && _c !== void 0 ? _c : 'single',
7032
+ onToggleExpand: (nodeId) => handleToggleExpand(nodeId, attrs),
7033
+ onToggleSelect: (nodeId) => handleToggleSelect(nodeId, attrs),
7034
+ onFocus: handleFocus,
7035
+ isLastInBranch,
7036
+ currentPath,
7037
+ // Pass state and attrs for recursive rendering
7038
+ treeState: state,
7039
+ treeAttrs: attrs,
7040
+ });
7041
+ });
7042
+ };
7043
+ return {
7044
+ oninit: ({ attrs }) => {
7045
+ // Build internal tree map for efficient lookups
7046
+ buildTreeMap(attrs.data, state.treeMap);
7047
+ // Initialize expanded nodes from data
7048
+ initializeExpandedNodes(attrs.data);
7049
+ // Initialize selected nodes from props
7050
+ if (attrs.selectedIds) {
7051
+ state.selectedIds = new Set(attrs.selectedIds);
7052
+ }
7053
+ },
7054
+ onupdate: ({ attrs }) => {
7055
+ // Sync selectedIds prop with internal state
7056
+ if (attrs.selectedIds) {
7057
+ const newSelection = new Set(attrs.selectedIds);
7058
+ if (newSelection.size !== state.selectedIds.size ||
7059
+ !Array.from(newSelection).every((id) => state.selectedIds.has(id))) {
7060
+ state.selectedIds = newSelection;
7061
+ }
7062
+ }
7063
+ },
7064
+ view: ({ attrs }) => {
7065
+ const { data, className, style, id, selectionMode = 'single', showConnectors = true } = attrs;
7066
+ return m('div.tree-view', {
7067
+ class: [
7068
+ className,
7069
+ showConnectors && 'show-connectors'
7070
+ ].filter(Boolean).join(' ') || undefined,
7071
+ style,
7072
+ id,
7073
+ role: selectionMode === 'multiple' ? 'listbox' : 'tree',
7074
+ 'aria-multiselectable': selectionMode === 'multiple' ? 'true' : 'false',
7075
+ }, [
7076
+ m('ul.tree-root', {
7077
+ role: 'group',
7078
+ }, renderNodes(data, attrs)),
7079
+ ]);
7080
+ },
7081
+ };
7082
+ };
7083
+
6799
7084
  /**
6800
7085
  * @fileoverview Core TypeScript utility types for mithril-materialized library
6801
7086
  * These types improve type safety and developer experience across all components
@@ -6817,4 +7102,4 @@ const isValidationError = (result) => !isValidationSuccess(result);
6817
7102
  // ============================================================================
6818
7103
  // All types are already exported via individual export declarations above
6819
7104
 
6820
- export { AnchorItem, Autocomplete, Breadcrumb, BreadcrumbManager, Button, ButtonFactory, Carousel, CharacterCounter, Chips, CodeBlock, Collapsible, CollapsibleItem, Collection, CollectionMode, ColorInput, DataTable, DatePicker, Dropdown, EmailInput, FileInput, FileUpload, FlatButton, FloatingActionButton, HelperText, Icon, InputCheckbox, Label, LargeButton, ListItem, Mandatory, MaterialBox, ModalPanel, NumberInput, Options, Pagination, PaginationControls, Parallax, PasswordInput, Pushpin, PushpinComponent, RadioButton, RadioButtons, RangeInput, RoundIconButton, SearchSelect, SecondaryContent, Select, Sidenav, SidenavItem, SidenavManager, SmallButton, Stepper, SubmitButton, Switch, Tabs, TextArea, TextInput, ThemeManager, ThemeSwitcher, ThemeToggle, TimePicker, Toast, ToastComponent, Tooltip, TooltipComponent, UrlInput, Wizard, createBreadcrumb, getDropdownStyles, initPushpins, initTooltips, isNumeric, isValidationError, isValidationSuccess, padLeft, range, toast, uniqueId, uuid4 };
7105
+ export { AnchorItem, Autocomplete, Breadcrumb, BreadcrumbManager, Button, ButtonFactory, Carousel, CharacterCounter, Chips, CodeBlock, Collapsible, CollapsibleItem, Collection, CollectionMode, ColorInput, DataTable, DatePicker, Dropdown, EmailInput, FileInput, FileUpload, FlatButton, FloatingActionButton, HelperText, Icon, InputCheckbox, Label, LargeButton, ListItem, Mandatory, MaterialBox, MaterialIcon, ModalPanel, NumberInput, Options, Pagination, PaginationControls, Parallax, PasswordInput, Pushpin, PushpinComponent, RadioButton, RadioButtons, RangeInput, RoundIconButton, SearchSelect, SecondaryContent, Select, Sidenav, SidenavItem, SidenavManager, SmallButton, Stepper, SubmitButton, Switch, Tabs, TextArea, TextInput, ThemeManager, ThemeSwitcher, ThemeToggle, TimePicker, Toast, ToastComponent, Tooltip, TooltipComponent, TreeView, UrlInput, Wizard, createBreadcrumb, getDropdownStyles, initPushpins, initTooltips, isNumeric, isValidationError, isValidationSuccess, padLeft, range, toast, uniqueId, uuid4 };