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