mithril-materialized 2.0.0-beta.5 → 2.0.0-beta.6
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/advanced.css +1888 -0
- package/dist/breadcrumb.d.ts +53 -0
- package/dist/components.css +2310 -0
- package/dist/core.css +3402 -0
- package/dist/file-upload.d.ts +34 -0
- package/dist/forms.css +2284 -0
- package/dist/index.css +1262 -83
- package/dist/index.d.ts +5 -0
- package/dist/index.esm.js +864 -17
- package/dist/index.js +875 -16
- package/dist/index.min.css +2 -2
- package/dist/index.umd.js +875 -16
- package/dist/pickers.css +487 -0
- package/dist/sidenav.d.ts +76 -0
- package/dist/theme-switcher.d.ts +49 -0
- package/dist/utilities.css +3197 -0
- package/dist/wizard.d.ts +58 -0
- package/package.json +11 -5
- package/sass/components/_breadcrumb.scss +248 -0
- package/sass/components/_buttons.scss +3 -3
- package/sass/components/_collapsible.scss +8 -8
- package/sass/components/_datepicker.scss +17 -15
- package/sass/components/_file-upload.scss +228 -0
- package/sass/components/_global.scss +7 -5
- package/sass/components/_modal.scss +5 -2
- package/sass/components/_navbar.scss +13 -5
- package/sass/components/_sidenav.scss +164 -7
- package/sass/components/_tabs.scss +5 -4
- package/sass/components/_theme-switcher.scss +120 -0
- package/sass/components/_theme-variables.scss +187 -0
- package/sass/components/_timepicker.scss +5 -5
- package/sass/components/_wizard.scss +416 -0
- package/sass/components/forms/_input-fields.scss +34 -12
- package/sass/components/forms/_radio-buttons.scss +10 -10
- package/sass/components/forms/_switches.scss +6 -6
- package/sass/materialize.scss +7 -0
package/dist/index.umd.js
CHANGED
|
@@ -1162,23 +1162,8 @@
|
|
|
1162
1162
|
header || iconName
|
|
1163
1163
|
? m('.collapsible-header', {
|
|
1164
1164
|
onclick: onToggle,
|
|
1165
|
-
style: {
|
|
1166
|
-
cursor: 'pointer',
|
|
1167
|
-
padding: '1rem',
|
|
1168
|
-
backgroundColor: '#fff',
|
|
1169
|
-
borderBottom: '1px solid #ddd',
|
|
1170
|
-
display: 'flex',
|
|
1171
|
-
alignItems: 'center',
|
|
1172
|
-
transition: 'background-color 0.2s ease',
|
|
1173
|
-
},
|
|
1174
|
-
onmouseover: (e) => {
|
|
1175
|
-
e.target.style.backgroundColor = '#f5f5f5';
|
|
1176
|
-
},
|
|
1177
|
-
onmouseleave: (e) => {
|
|
1178
|
-
e.target.style.backgroundColor = '#fff';
|
|
1179
|
-
},
|
|
1180
1165
|
}, [
|
|
1181
|
-
iconName ? m('i.material-icons',
|
|
1166
|
+
iconName ? m('i.material-icons', iconName) : undefined,
|
|
1182
1167
|
header ? (typeof header === 'string' ? m('span', header) : header) : undefined,
|
|
1183
1168
|
])
|
|
1184
1169
|
: undefined,
|
|
@@ -5343,8 +5328,872 @@
|
|
|
5343
5328
|
return tooltips;
|
|
5344
5329
|
};
|
|
5345
5330
|
|
|
5331
|
+
/**
|
|
5332
|
+
* Theme switching utilities and component
|
|
5333
|
+
*/
|
|
5334
|
+
class ThemeManager {
|
|
5335
|
+
/**
|
|
5336
|
+
* Set the theme for the entire application
|
|
5337
|
+
*/
|
|
5338
|
+
static setTheme(theme) {
|
|
5339
|
+
this.currentTheme = theme;
|
|
5340
|
+
const root = document.documentElement;
|
|
5341
|
+
if (theme === 'auto') {
|
|
5342
|
+
// Remove explicit theme, let CSS media query handle it
|
|
5343
|
+
root.removeAttribute('data-theme');
|
|
5344
|
+
}
|
|
5345
|
+
else {
|
|
5346
|
+
// Set explicit theme
|
|
5347
|
+
root.setAttribute('data-theme', theme);
|
|
5348
|
+
}
|
|
5349
|
+
// Store preference in localStorage
|
|
5350
|
+
try {
|
|
5351
|
+
localStorage.setItem('mm-theme', theme);
|
|
5352
|
+
}
|
|
5353
|
+
catch (e) {
|
|
5354
|
+
// localStorage might not be available
|
|
5355
|
+
}
|
|
5356
|
+
}
|
|
5357
|
+
/**
|
|
5358
|
+
* Get the current theme
|
|
5359
|
+
*/
|
|
5360
|
+
static getTheme() {
|
|
5361
|
+
return this.currentTheme;
|
|
5362
|
+
}
|
|
5363
|
+
/**
|
|
5364
|
+
* Get the effective theme (resolves 'auto' to actual theme)
|
|
5365
|
+
*/
|
|
5366
|
+
static getEffectiveTheme() {
|
|
5367
|
+
if (this.currentTheme !== 'auto') {
|
|
5368
|
+
return this.currentTheme;
|
|
5369
|
+
}
|
|
5370
|
+
// Check CSS media query for auto mode
|
|
5371
|
+
if (typeof window !== 'undefined' && window.matchMedia) {
|
|
5372
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
5373
|
+
}
|
|
5374
|
+
return 'light';
|
|
5375
|
+
}
|
|
5376
|
+
/**
|
|
5377
|
+
* Initialize theme from localStorage or system preference
|
|
5378
|
+
*/
|
|
5379
|
+
static initialize() {
|
|
5380
|
+
let savedTheme = 'auto';
|
|
5381
|
+
try {
|
|
5382
|
+
const stored = localStorage.getItem('mm-theme');
|
|
5383
|
+
if (stored && ['light', 'dark', 'auto'].includes(stored)) {
|
|
5384
|
+
savedTheme = stored;
|
|
5385
|
+
}
|
|
5386
|
+
}
|
|
5387
|
+
catch (e) {
|
|
5388
|
+
// localStorage might not be available
|
|
5389
|
+
}
|
|
5390
|
+
this.setTheme(savedTheme);
|
|
5391
|
+
}
|
|
5392
|
+
/**
|
|
5393
|
+
* Toggle between light and dark themes
|
|
5394
|
+
*/
|
|
5395
|
+
static toggle() {
|
|
5396
|
+
const current = this.getEffectiveTheme();
|
|
5397
|
+
this.setTheme(current === 'light' ? 'dark' : 'light');
|
|
5398
|
+
}
|
|
5399
|
+
}
|
|
5400
|
+
ThemeManager.currentTheme = 'auto';
|
|
5401
|
+
/**
|
|
5402
|
+
* Theme Switcher Component
|
|
5403
|
+
* Provides UI controls for changing themes
|
|
5404
|
+
*/
|
|
5405
|
+
const ThemeSwitcher = () => {
|
|
5406
|
+
return {
|
|
5407
|
+
oninit: () => {
|
|
5408
|
+
// Initialize theme manager if not already done
|
|
5409
|
+
if (typeof window !== 'undefined') {
|
|
5410
|
+
ThemeManager.initialize();
|
|
5411
|
+
}
|
|
5412
|
+
},
|
|
5413
|
+
view: ({ attrs }) => {
|
|
5414
|
+
const { theme = ThemeManager.getTheme(), onThemeChange, showLabels = true, className = '' } = attrs;
|
|
5415
|
+
const handleThemeChange = (newTheme) => {
|
|
5416
|
+
ThemeManager.setTheme(newTheme);
|
|
5417
|
+
if (onThemeChange) {
|
|
5418
|
+
onThemeChange(newTheme);
|
|
5419
|
+
}
|
|
5420
|
+
};
|
|
5421
|
+
return m('.theme-switcher', { class: className }, [
|
|
5422
|
+
showLabels && m('span.theme-switcher-label', 'Theme:'),
|
|
5423
|
+
m('.theme-switcher-buttons', [
|
|
5424
|
+
m('button.btn-flat', {
|
|
5425
|
+
class: theme === 'light' ? 'active' : '',
|
|
5426
|
+
onclick: () => handleThemeChange('light'),
|
|
5427
|
+
title: 'Light theme'
|
|
5428
|
+
}, [
|
|
5429
|
+
m('i.material-icons', 'light_mode'),
|
|
5430
|
+
showLabels && m('span', 'Light')
|
|
5431
|
+
]),
|
|
5432
|
+
m('button.btn-flat', {
|
|
5433
|
+
class: theme === 'auto' ? 'active' : '',
|
|
5434
|
+
onclick: () => handleThemeChange('auto'),
|
|
5435
|
+
title: 'Auto theme (system preference)'
|
|
5436
|
+
}, [
|
|
5437
|
+
m('i.material-icons', 'brightness_auto'),
|
|
5438
|
+
showLabels && m('span', 'Auto')
|
|
5439
|
+
]),
|
|
5440
|
+
m('button.btn-flat', {
|
|
5441
|
+
class: theme === 'dark' ? 'active' : '',
|
|
5442
|
+
onclick: () => handleThemeChange('dark'),
|
|
5443
|
+
title: 'Dark theme'
|
|
5444
|
+
}, [
|
|
5445
|
+
m('i.material-icons', 'dark_mode'),
|
|
5446
|
+
showLabels && m('span', 'Dark')
|
|
5447
|
+
])
|
|
5448
|
+
])
|
|
5449
|
+
]);
|
|
5450
|
+
}
|
|
5451
|
+
};
|
|
5452
|
+
};
|
|
5453
|
+
/**
|
|
5454
|
+
* Simple theme toggle button (just switches between light/dark)
|
|
5455
|
+
*/
|
|
5456
|
+
const ThemeToggle = () => {
|
|
5457
|
+
return {
|
|
5458
|
+
oninit: () => {
|
|
5459
|
+
// Initialize theme manager if not already done
|
|
5460
|
+
if (typeof window !== 'undefined') {
|
|
5461
|
+
ThemeManager.initialize();
|
|
5462
|
+
}
|
|
5463
|
+
},
|
|
5464
|
+
view: ({ attrs }) => {
|
|
5465
|
+
const currentTheme = ThemeManager.getEffectiveTheme();
|
|
5466
|
+
return m('button.btn-flat.theme-toggle', {
|
|
5467
|
+
class: attrs.className || '',
|
|
5468
|
+
onclick: () => {
|
|
5469
|
+
ThemeManager.toggle();
|
|
5470
|
+
m.redraw();
|
|
5471
|
+
},
|
|
5472
|
+
title: `Switch to ${currentTheme === 'light' ? 'dark' : 'light'} theme`,
|
|
5473
|
+
style: 'margin: 0; height: 64px; line-height: 64px; border-radius: 0; min-width: 64px; padding: 0;'
|
|
5474
|
+
}, [
|
|
5475
|
+
m('i.material-icons', {
|
|
5476
|
+
style: 'color: inherit; font-size: 24px;'
|
|
5477
|
+
}, currentTheme === 'light' ? 'dark_mode' : 'light_mode')
|
|
5478
|
+
]);
|
|
5479
|
+
}
|
|
5480
|
+
};
|
|
5481
|
+
};
|
|
5482
|
+
|
|
5483
|
+
/**
|
|
5484
|
+
* File Upload Component with Drag and Drop
|
|
5485
|
+
* Supports multiple files, file type validation, size limits, and image preview
|
|
5486
|
+
*/
|
|
5487
|
+
const FileUpload = () => {
|
|
5488
|
+
let state;
|
|
5489
|
+
const validateFile = (file, attrs) => {
|
|
5490
|
+
// Check file size
|
|
5491
|
+
if (attrs.maxSize && file.size > attrs.maxSize) {
|
|
5492
|
+
const maxSizeMB = (attrs.maxSize / (1024 * 1024)).toFixed(1);
|
|
5493
|
+
return `File size exceeds ${maxSizeMB}MB limit`;
|
|
5494
|
+
}
|
|
5495
|
+
// Check file type
|
|
5496
|
+
if (attrs.accept) {
|
|
5497
|
+
const acceptedTypes = attrs.accept.split(',').map(type => type.trim());
|
|
5498
|
+
const isAccepted = acceptedTypes.some(acceptedType => {
|
|
5499
|
+
if (acceptedType.startsWith('.')) {
|
|
5500
|
+
// Extension check
|
|
5501
|
+
return file.name.toLowerCase().endsWith(acceptedType.toLowerCase());
|
|
5502
|
+
}
|
|
5503
|
+
else {
|
|
5504
|
+
// MIME type check
|
|
5505
|
+
return file.type.match(acceptedType.replace('*', '.*'));
|
|
5506
|
+
}
|
|
5507
|
+
});
|
|
5508
|
+
if (!isAccepted) {
|
|
5509
|
+
return `File type not accepted. Accepted: ${attrs.accept}`;
|
|
5510
|
+
}
|
|
5511
|
+
}
|
|
5512
|
+
return null;
|
|
5513
|
+
};
|
|
5514
|
+
const createFilePreview = (file) => {
|
|
5515
|
+
if (file.type.startsWith('image/')) {
|
|
5516
|
+
const reader = new FileReader();
|
|
5517
|
+
reader.onload = (e) => {
|
|
5518
|
+
var _a;
|
|
5519
|
+
file.preview = (_a = e.target) === null || _a === void 0 ? void 0 : _a.result;
|
|
5520
|
+
m.redraw();
|
|
5521
|
+
};
|
|
5522
|
+
reader.readAsDataURL(file);
|
|
5523
|
+
}
|
|
5524
|
+
};
|
|
5525
|
+
const handleFiles = (fileList, attrs) => {
|
|
5526
|
+
const newFiles = Array.from(fileList);
|
|
5527
|
+
const validFiles = [];
|
|
5528
|
+
// Validate each file
|
|
5529
|
+
for (const file of newFiles) {
|
|
5530
|
+
const error = validateFile(file, attrs);
|
|
5531
|
+
if (error) {
|
|
5532
|
+
file.uploadError = error;
|
|
5533
|
+
}
|
|
5534
|
+
else {
|
|
5535
|
+
validFiles.push(file);
|
|
5536
|
+
if (attrs.showPreview) {
|
|
5537
|
+
createFilePreview(file);
|
|
5538
|
+
}
|
|
5539
|
+
}
|
|
5540
|
+
}
|
|
5541
|
+
// Check max files limit
|
|
5542
|
+
if (attrs.maxFiles) {
|
|
5543
|
+
const totalFiles = state.files.length + validFiles.length;
|
|
5544
|
+
if (totalFiles > attrs.maxFiles) {
|
|
5545
|
+
const allowedCount = attrs.maxFiles - state.files.length;
|
|
5546
|
+
validFiles.splice(allowedCount);
|
|
5547
|
+
}
|
|
5548
|
+
}
|
|
5549
|
+
// Add valid files to state
|
|
5550
|
+
if (attrs.multiple) {
|
|
5551
|
+
state.files = [...state.files, ...validFiles];
|
|
5552
|
+
}
|
|
5553
|
+
else {
|
|
5554
|
+
state.files = validFiles.slice(0, 1);
|
|
5555
|
+
}
|
|
5556
|
+
// Notify parent component
|
|
5557
|
+
if (attrs.onFilesSelected) {
|
|
5558
|
+
attrs.onFilesSelected(state.files.filter(f => !f.uploadError));
|
|
5559
|
+
}
|
|
5560
|
+
};
|
|
5561
|
+
const removeFile = (fileToRemove, attrs) => {
|
|
5562
|
+
state.files = state.files.filter(file => file !== fileToRemove);
|
|
5563
|
+
if (attrs.onFileRemoved) {
|
|
5564
|
+
attrs.onFileRemoved(fileToRemove);
|
|
5565
|
+
}
|
|
5566
|
+
};
|
|
5567
|
+
const formatFileSize = (bytes) => {
|
|
5568
|
+
if (bytes === 0)
|
|
5569
|
+
return '0 B';
|
|
5570
|
+
const k = 1024;
|
|
5571
|
+
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
5572
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
5573
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
|
|
5574
|
+
};
|
|
5575
|
+
return {
|
|
5576
|
+
oninit: () => {
|
|
5577
|
+
state = {
|
|
5578
|
+
id: uniqueId(),
|
|
5579
|
+
files: [],
|
|
5580
|
+
isDragOver: false,
|
|
5581
|
+
isUploading: false
|
|
5582
|
+
};
|
|
5583
|
+
},
|
|
5584
|
+
view: ({ attrs }) => {
|
|
5585
|
+
const { accept, multiple = false, disabled = false, label = 'Choose files or drag them here', helperText, showPreview = true, className = '', error } = attrs;
|
|
5586
|
+
return m('.file-upload-container', { class: className }, [
|
|
5587
|
+
// Upload area
|
|
5588
|
+
m('.file-upload-area', {
|
|
5589
|
+
class: [
|
|
5590
|
+
state.isDragOver ? 'drag-over' : '',
|
|
5591
|
+
disabled ? 'disabled' : '',
|
|
5592
|
+
error ? 'error' : '',
|
|
5593
|
+
state.files.length > 0 ? 'has-files' : ''
|
|
5594
|
+
].filter(Boolean).join(' '),
|
|
5595
|
+
ondragover: (e) => {
|
|
5596
|
+
if (disabled)
|
|
5597
|
+
return;
|
|
5598
|
+
e.preventDefault();
|
|
5599
|
+
e.stopPropagation();
|
|
5600
|
+
state.isDragOver = true;
|
|
5601
|
+
},
|
|
5602
|
+
ondragleave: (e) => {
|
|
5603
|
+
if (disabled)
|
|
5604
|
+
return;
|
|
5605
|
+
e.preventDefault();
|
|
5606
|
+
e.stopPropagation();
|
|
5607
|
+
state.isDragOver = false;
|
|
5608
|
+
},
|
|
5609
|
+
ondrop: (e) => {
|
|
5610
|
+
var _a;
|
|
5611
|
+
if (disabled)
|
|
5612
|
+
return;
|
|
5613
|
+
e.preventDefault();
|
|
5614
|
+
e.stopPropagation();
|
|
5615
|
+
state.isDragOver = false;
|
|
5616
|
+
if ((_a = e.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) {
|
|
5617
|
+
handleFiles(e.dataTransfer.files, attrs);
|
|
5618
|
+
}
|
|
5619
|
+
},
|
|
5620
|
+
onclick: () => {
|
|
5621
|
+
if (disabled)
|
|
5622
|
+
return;
|
|
5623
|
+
const input = document.getElementById(state.id);
|
|
5624
|
+
input === null || input === void 0 ? void 0 : input.click();
|
|
5625
|
+
}
|
|
5626
|
+
}, [
|
|
5627
|
+
m('input[type="file"]', {
|
|
5628
|
+
id: state.id,
|
|
5629
|
+
accept,
|
|
5630
|
+
multiple,
|
|
5631
|
+
disabled,
|
|
5632
|
+
style: { display: 'none' },
|
|
5633
|
+
onchange: (e) => {
|
|
5634
|
+
const target = e.target;
|
|
5635
|
+
if (target.files) {
|
|
5636
|
+
handleFiles(target.files, attrs);
|
|
5637
|
+
}
|
|
5638
|
+
}
|
|
5639
|
+
}),
|
|
5640
|
+
m('.file-upload-content', [
|
|
5641
|
+
m('i.material-icons.file-upload-icon', 'cloud_upload'),
|
|
5642
|
+
m('p.file-upload-label', label),
|
|
5643
|
+
helperText && m('p.file-upload-helper', helperText),
|
|
5644
|
+
accept && m('p.file-upload-types', `Accepted: ${accept}`)
|
|
5645
|
+
])
|
|
5646
|
+
]),
|
|
5647
|
+
// Error message
|
|
5648
|
+
error && m('.file-upload-error', error),
|
|
5649
|
+
// File list
|
|
5650
|
+
state.files.length > 0 && m('.file-upload-list', [
|
|
5651
|
+
m('h6', 'Selected Files:'),
|
|
5652
|
+
state.files.map(file => m('.file-upload-item', { key: file.name + file.size }, [
|
|
5653
|
+
// Preview thumbnail
|
|
5654
|
+
showPreview && file.preview && m('.file-preview', [
|
|
5655
|
+
m('img', { src: file.preview, alt: file.name })
|
|
5656
|
+
]),
|
|
5657
|
+
// File info
|
|
5658
|
+
m('.file-info', [
|
|
5659
|
+
m('.file-name', file.name),
|
|
5660
|
+
m('.file-details', [
|
|
5661
|
+
m('span.file-size', formatFileSize(file.size)),
|
|
5662
|
+
file.type && m('span.file-type', file.type)
|
|
5663
|
+
]),
|
|
5664
|
+
// Progress bar (if uploading)
|
|
5665
|
+
file.uploadProgress !== undefined && m('.file-progress', [
|
|
5666
|
+
m('.progress', [
|
|
5667
|
+
m('.determinate', {
|
|
5668
|
+
style: { width: `${file.uploadProgress}%` }
|
|
5669
|
+
})
|
|
5670
|
+
])
|
|
5671
|
+
]),
|
|
5672
|
+
// Error message
|
|
5673
|
+
file.uploadError && m('.file-error', file.uploadError)
|
|
5674
|
+
]),
|
|
5675
|
+
// Remove button
|
|
5676
|
+
m('button.btn-flat.file-remove', {
|
|
5677
|
+
onclick: (e) => {
|
|
5678
|
+
e.stopPropagation();
|
|
5679
|
+
removeFile(file, attrs);
|
|
5680
|
+
},
|
|
5681
|
+
title: 'Remove file'
|
|
5682
|
+
}, [
|
|
5683
|
+
m('i.material-icons', 'close')
|
|
5684
|
+
])
|
|
5685
|
+
]))
|
|
5686
|
+
])
|
|
5687
|
+
]);
|
|
5688
|
+
}
|
|
5689
|
+
};
|
|
5690
|
+
};
|
|
5691
|
+
|
|
5692
|
+
/**
|
|
5693
|
+
* Sidenav Component
|
|
5694
|
+
* A responsive navigation drawer that slides in from the side
|
|
5695
|
+
*/
|
|
5696
|
+
const Sidenav = () => {
|
|
5697
|
+
let state;
|
|
5698
|
+
const handleBackdropClick = (attrs) => {
|
|
5699
|
+
if (attrs.closeOnBackdropClick !== false && attrs.onToggle) {
|
|
5700
|
+
attrs.onToggle(false);
|
|
5701
|
+
}
|
|
5702
|
+
};
|
|
5703
|
+
const handleEscapeKey = (e, attrs) => {
|
|
5704
|
+
if (e.key === 'Escape' && attrs.closeOnEscape !== false && attrs.onToggle) {
|
|
5705
|
+
attrs.onToggle(false);
|
|
5706
|
+
}
|
|
5707
|
+
};
|
|
5708
|
+
const setBodyOverflow = (isOpen, mode) => {
|
|
5709
|
+
if (typeof document !== 'undefined') {
|
|
5710
|
+
document.body.style.overflow = isOpen && mode === 'overlay' ? 'hidden' : '';
|
|
5711
|
+
}
|
|
5712
|
+
};
|
|
5713
|
+
return {
|
|
5714
|
+
oninit: ({ attrs }) => {
|
|
5715
|
+
state = {
|
|
5716
|
+
id: attrs.id || uniqueId(),
|
|
5717
|
+
isOpen: attrs.isOpen || false,
|
|
5718
|
+
isAnimating: false
|
|
5719
|
+
};
|
|
5720
|
+
// Set up keyboard listener
|
|
5721
|
+
if (typeof document !== 'undefined' && attrs.closeOnEscape !== false) {
|
|
5722
|
+
document.addEventListener('keydown', (e) => handleEscapeKey(e, attrs));
|
|
5723
|
+
}
|
|
5724
|
+
},
|
|
5725
|
+
onbeforeupdate: ({ attrs }) => {
|
|
5726
|
+
const wasOpen = state.isOpen;
|
|
5727
|
+
const isOpen = attrs.isOpen || false;
|
|
5728
|
+
if (wasOpen !== isOpen) {
|
|
5729
|
+
state.isOpen = isOpen;
|
|
5730
|
+
state.isAnimating = true;
|
|
5731
|
+
setBodyOverflow(isOpen, attrs.mode || 'overlay');
|
|
5732
|
+
// Clear animation state after animation completes
|
|
5733
|
+
setTimeout(() => {
|
|
5734
|
+
state.isAnimating = false;
|
|
5735
|
+
m.redraw();
|
|
5736
|
+
}, attrs.animationDuration || 300);
|
|
5737
|
+
}
|
|
5738
|
+
},
|
|
5739
|
+
onremove: ({ attrs }) => {
|
|
5740
|
+
// Clean up
|
|
5741
|
+
setBodyOverflow(false, attrs.mode || 'overlay');
|
|
5742
|
+
if (typeof document !== 'undefined' && attrs.closeOnEscape !== false) {
|
|
5743
|
+
document.removeEventListener('keydown', (e) => handleEscapeKey(e, attrs));
|
|
5744
|
+
}
|
|
5745
|
+
},
|
|
5746
|
+
view: ({ attrs, children }) => {
|
|
5747
|
+
const { position = 'left', mode = 'overlay', width = 300, className = '', showBackdrop = true, animationDuration = 300, fixed = false } = attrs;
|
|
5748
|
+
const isOpen = state.isOpen;
|
|
5749
|
+
return [
|
|
5750
|
+
// Backdrop (using existing materialize class)
|
|
5751
|
+
showBackdrop && mode === 'overlay' && m('.sidenav-overlay', {
|
|
5752
|
+
style: {
|
|
5753
|
+
display: isOpen ? 'block' : 'none',
|
|
5754
|
+
opacity: isOpen ? '1' : '0'
|
|
5755
|
+
},
|
|
5756
|
+
onclick: () => handleBackdropClick(attrs)
|
|
5757
|
+
}),
|
|
5758
|
+
// Sidenav (using existing materialize structure)
|
|
5759
|
+
m('ul.sidenav', {
|
|
5760
|
+
id: state.id,
|
|
5761
|
+
class: [
|
|
5762
|
+
position === 'right' ? 'right-aligned' : '',
|
|
5763
|
+
fixed ? 'sidenav-fixed' : '',
|
|
5764
|
+
className
|
|
5765
|
+
].filter(Boolean).join(' '),
|
|
5766
|
+
style: {
|
|
5767
|
+
width: `${width}px`,
|
|
5768
|
+
transform: isOpen ? 'translateX(0)' :
|
|
5769
|
+
position === 'left' ? 'translateX(-105%)' : 'translateX(105%)',
|
|
5770
|
+
'transition-duration': `${animationDuration}ms`
|
|
5771
|
+
}
|
|
5772
|
+
}, children)
|
|
5773
|
+
];
|
|
5774
|
+
}
|
|
5775
|
+
};
|
|
5776
|
+
};
|
|
5777
|
+
/**
|
|
5778
|
+
* Sidenav Item Component
|
|
5779
|
+
* Individual items for the sidenav menu
|
|
5780
|
+
*/
|
|
5781
|
+
const SidenavItem = () => {
|
|
5782
|
+
return {
|
|
5783
|
+
view: ({ attrs, children }) => {
|
|
5784
|
+
const { text, icon, active = false, disabled = false, onclick, href, className = '', divider = false, subheader = false } = attrs;
|
|
5785
|
+
if (divider) {
|
|
5786
|
+
return m('li.divider');
|
|
5787
|
+
}
|
|
5788
|
+
if (subheader) {
|
|
5789
|
+
return m('li.subheader', text || children);
|
|
5790
|
+
}
|
|
5791
|
+
const itemClasses = [
|
|
5792
|
+
active ? 'active' : '',
|
|
5793
|
+
disabled ? 'disabled' : '',
|
|
5794
|
+
className
|
|
5795
|
+
].filter(Boolean).join(' ');
|
|
5796
|
+
const content = [
|
|
5797
|
+
icon && m('i.material-icons', icon),
|
|
5798
|
+
text || children
|
|
5799
|
+
];
|
|
5800
|
+
if (href && !disabled) {
|
|
5801
|
+
return m('li', { class: itemClasses }, [
|
|
5802
|
+
m('a', {
|
|
5803
|
+
href,
|
|
5804
|
+
onclick: disabled ? undefined : onclick
|
|
5805
|
+
}, content)
|
|
5806
|
+
]);
|
|
5807
|
+
}
|
|
5808
|
+
return m('li', { class: itemClasses }, [
|
|
5809
|
+
m('a', {
|
|
5810
|
+
onclick: disabled ? undefined : onclick,
|
|
5811
|
+
href: '#!'
|
|
5812
|
+
}, content)
|
|
5813
|
+
]);
|
|
5814
|
+
}
|
|
5815
|
+
};
|
|
5816
|
+
};
|
|
5817
|
+
/**
|
|
5818
|
+
* Sidenav utilities for programmatic control
|
|
5819
|
+
*/
|
|
5820
|
+
class SidenavManager {
|
|
5821
|
+
/**
|
|
5822
|
+
* Open a sidenav by ID
|
|
5823
|
+
*/
|
|
5824
|
+
static open(id) {
|
|
5825
|
+
const element = document.getElementById(id);
|
|
5826
|
+
if (element) {
|
|
5827
|
+
element.classList.add('open');
|
|
5828
|
+
element.classList.remove('closed');
|
|
5829
|
+
}
|
|
5830
|
+
}
|
|
5831
|
+
/**
|
|
5832
|
+
* Close a sidenav by ID
|
|
5833
|
+
*/
|
|
5834
|
+
static close(id) {
|
|
5835
|
+
const element = document.getElementById(id);
|
|
5836
|
+
if (element) {
|
|
5837
|
+
element.classList.remove('open');
|
|
5838
|
+
element.classList.add('closed');
|
|
5839
|
+
}
|
|
5840
|
+
}
|
|
5841
|
+
/**
|
|
5842
|
+
* Toggle a sidenav by ID
|
|
5843
|
+
*/
|
|
5844
|
+
static toggle(id) {
|
|
5845
|
+
const element = document.getElementById(id);
|
|
5846
|
+
if (element) {
|
|
5847
|
+
const isOpen = element.classList.contains('open');
|
|
5848
|
+
if (isOpen) {
|
|
5849
|
+
this.close(id);
|
|
5850
|
+
}
|
|
5851
|
+
else {
|
|
5852
|
+
this.open(id);
|
|
5853
|
+
}
|
|
5854
|
+
}
|
|
5855
|
+
}
|
|
5856
|
+
}
|
|
5857
|
+
|
|
5858
|
+
/**
|
|
5859
|
+
* Breadcrumb Component
|
|
5860
|
+
* Displays a navigation path showing the user's location within a site hierarchy
|
|
5861
|
+
*/
|
|
5862
|
+
const Breadcrumb = () => {
|
|
5863
|
+
return {
|
|
5864
|
+
view: ({ attrs }) => {
|
|
5865
|
+
const { items = [], separator = 'chevron_right', className = '', showIcons = false, maxItems, showHome = false } = attrs;
|
|
5866
|
+
if (items.length === 0) {
|
|
5867
|
+
return null;
|
|
5868
|
+
}
|
|
5869
|
+
let displayItems = [...items];
|
|
5870
|
+
// Handle max items with ellipsis
|
|
5871
|
+
if (maxItems && items.length > maxItems) {
|
|
5872
|
+
const firstItem = items[0];
|
|
5873
|
+
const lastItems = items.slice(-(maxItems - 2));
|
|
5874
|
+
displayItems = [
|
|
5875
|
+
firstItem,
|
|
5876
|
+
{ text: '...', disabled: true, className: 'breadcrumb-ellipsis' },
|
|
5877
|
+
...lastItems
|
|
5878
|
+
];
|
|
5879
|
+
}
|
|
5880
|
+
return m('nav.breadcrumb', { class: className }, [
|
|
5881
|
+
m('ol.breadcrumb-list', displayItems.map((item, index) => {
|
|
5882
|
+
const isLast = index === displayItems.length - 1;
|
|
5883
|
+
const isFirst = index === 0;
|
|
5884
|
+
return [
|
|
5885
|
+
// Breadcrumb item
|
|
5886
|
+
m('li.breadcrumb-item', {
|
|
5887
|
+
class: [
|
|
5888
|
+
item.active || isLast ? 'active' : '',
|
|
5889
|
+
item.disabled ? 'disabled' : '',
|
|
5890
|
+
item.className || ''
|
|
5891
|
+
].filter(Boolean).join(' ')
|
|
5892
|
+
}, [
|
|
5893
|
+
item.href && !item.disabled && !isLast ?
|
|
5894
|
+
// Link item
|
|
5895
|
+
m('a.breadcrumb-link', {
|
|
5896
|
+
href: item.href,
|
|
5897
|
+
onclick: item.onclick
|
|
5898
|
+
}, [
|
|
5899
|
+
(showIcons && item.icon) && m('i.material-icons.breadcrumb-icon', item.icon),
|
|
5900
|
+
(showHome && isFirst && !item.icon) && m('i.material-icons.breadcrumb-icon', 'home'),
|
|
5901
|
+
m('span.breadcrumb-text', item.text)
|
|
5902
|
+
]) :
|
|
5903
|
+
// Text item (active or disabled)
|
|
5904
|
+
m('span.breadcrumb-text', {
|
|
5905
|
+
onclick: item.disabled ? undefined : item.onclick
|
|
5906
|
+
}, [
|
|
5907
|
+
(showIcons && item.icon) && m('i.material-icons.breadcrumb-icon', item.icon),
|
|
5908
|
+
(showHome && isFirst && !item.icon) && m('i.material-icons.breadcrumb-icon', 'home'),
|
|
5909
|
+
item.text
|
|
5910
|
+
])
|
|
5911
|
+
]),
|
|
5912
|
+
// Separator (except for last item)
|
|
5913
|
+
!isLast && m('li.breadcrumb-separator', [
|
|
5914
|
+
m('i.material-icons', separator)
|
|
5915
|
+
])
|
|
5916
|
+
];
|
|
5917
|
+
}).reduce((acc, val) => acc.concat(val), []))
|
|
5918
|
+
]);
|
|
5919
|
+
}
|
|
5920
|
+
};
|
|
5921
|
+
};
|
|
5922
|
+
/**
|
|
5923
|
+
* Simple Breadcrumb utility for common use cases
|
|
5924
|
+
*/
|
|
5925
|
+
const createBreadcrumb = (path, basePath = '/') => {
|
|
5926
|
+
const segments = path.split('/').filter(Boolean);
|
|
5927
|
+
const items = [];
|
|
5928
|
+
// Add home item
|
|
5929
|
+
items.push({
|
|
5930
|
+
text: 'Home',
|
|
5931
|
+
href: basePath,
|
|
5932
|
+
icon: 'home'
|
|
5933
|
+
});
|
|
5934
|
+
// Add path segments
|
|
5935
|
+
let currentPath = basePath;
|
|
5936
|
+
segments.forEach((segment, index) => {
|
|
5937
|
+
currentPath += (currentPath.endsWith('/') ? '' : '/') + segment;
|
|
5938
|
+
const isLast = index === segments.length - 1;
|
|
5939
|
+
items.push({
|
|
5940
|
+
text: segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, ' '),
|
|
5941
|
+
href: isLast ? undefined : currentPath,
|
|
5942
|
+
active: isLast
|
|
5943
|
+
});
|
|
5944
|
+
});
|
|
5945
|
+
return items;
|
|
5946
|
+
};
|
|
5947
|
+
/**
|
|
5948
|
+
* Breadcrumb utilities
|
|
5949
|
+
*/
|
|
5950
|
+
class BreadcrumbManager {
|
|
5951
|
+
/**
|
|
5952
|
+
* Create breadcrumb items from a route path
|
|
5953
|
+
*/
|
|
5954
|
+
static fromRoute(route, routeConfig = {}) {
|
|
5955
|
+
const segments = route.split('/').filter(Boolean);
|
|
5956
|
+
const items = [];
|
|
5957
|
+
// Add home
|
|
5958
|
+
items.push({
|
|
5959
|
+
text: 'Home',
|
|
5960
|
+
href: '/',
|
|
5961
|
+
icon: 'home'
|
|
5962
|
+
});
|
|
5963
|
+
let currentPath = '';
|
|
5964
|
+
segments.forEach((segment, index) => {
|
|
5965
|
+
currentPath += '/' + segment;
|
|
5966
|
+
const isLast = index === segments.length - 1;
|
|
5967
|
+
// Use custom text from config or format segment
|
|
5968
|
+
const text = routeConfig[currentPath] ||
|
|
5969
|
+
segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, ' ');
|
|
5970
|
+
items.push({
|
|
5971
|
+
text,
|
|
5972
|
+
href: isLast ? undefined : currentPath,
|
|
5973
|
+
active: isLast
|
|
5974
|
+
});
|
|
5975
|
+
});
|
|
5976
|
+
return items;
|
|
5977
|
+
}
|
|
5978
|
+
/**
|
|
5979
|
+
* Create breadcrumb items from a hierarchical object
|
|
5980
|
+
*/
|
|
5981
|
+
static fromHierarchy(hierarchy, textKey = 'name', pathKey = 'path') {
|
|
5982
|
+
return hierarchy.map((item, index) => ({
|
|
5983
|
+
text: item[textKey],
|
|
5984
|
+
href: index === hierarchy.length - 1 ? undefined : item[pathKey],
|
|
5985
|
+
active: index === hierarchy.length - 1
|
|
5986
|
+
}));
|
|
5987
|
+
}
|
|
5988
|
+
}
|
|
5989
|
+
|
|
5990
|
+
/**
|
|
5991
|
+
* Wizard/Stepper Component
|
|
5992
|
+
* A multi-step interface for guiding users through a process
|
|
5993
|
+
*/
|
|
5994
|
+
const Wizard = () => {
|
|
5995
|
+
let state;
|
|
5996
|
+
const validateStep = async (stepIndex, steps) => {
|
|
5997
|
+
const step = steps[stepIndex];
|
|
5998
|
+
if (!step || !step.validate)
|
|
5999
|
+
return true;
|
|
6000
|
+
state.isValidating = true;
|
|
6001
|
+
try {
|
|
6002
|
+
const isValid = await step.validate();
|
|
6003
|
+
if (isValid) {
|
|
6004
|
+
state.completedSteps.add(stepIndex);
|
|
6005
|
+
state.errorSteps.delete(stepIndex);
|
|
6006
|
+
}
|
|
6007
|
+
else {
|
|
6008
|
+
state.errorSteps.add(stepIndex);
|
|
6009
|
+
state.completedSteps.delete(stepIndex);
|
|
6010
|
+
}
|
|
6011
|
+
return isValid;
|
|
6012
|
+
}
|
|
6013
|
+
catch (error) {
|
|
6014
|
+
state.errorSteps.add(stepIndex);
|
|
6015
|
+
state.completedSteps.delete(stepIndex);
|
|
6016
|
+
return false;
|
|
6017
|
+
}
|
|
6018
|
+
finally {
|
|
6019
|
+
state.isValidating = false;
|
|
6020
|
+
m.redraw();
|
|
6021
|
+
}
|
|
6022
|
+
};
|
|
6023
|
+
const goToStep = async (stepIndex, attrs) => {
|
|
6024
|
+
const { linear = true, onStepChange, steps } = attrs;
|
|
6025
|
+
if (stepIndex < 0 || stepIndex >= steps.length)
|
|
6026
|
+
return false;
|
|
6027
|
+
// Check if step is disabled
|
|
6028
|
+
if (steps[stepIndex].disabled)
|
|
6029
|
+
return false;
|
|
6030
|
+
// In linear mode, validate all previous steps
|
|
6031
|
+
if (linear && stepIndex > state.currentStep) {
|
|
6032
|
+
for (let i = state.currentStep; i < stepIndex; i++) {
|
|
6033
|
+
const isValid = await validateStep(i, steps);
|
|
6034
|
+
if (!isValid && !steps[i].optional) {
|
|
6035
|
+
return false;
|
|
6036
|
+
}
|
|
6037
|
+
}
|
|
6038
|
+
}
|
|
6039
|
+
// Validate current step before moving forward
|
|
6040
|
+
if (stepIndex > state.currentStep) {
|
|
6041
|
+
const isValid = await validateStep(state.currentStep, steps);
|
|
6042
|
+
if (!isValid && !steps[state.currentStep].optional) {
|
|
6043
|
+
return false;
|
|
6044
|
+
}
|
|
6045
|
+
}
|
|
6046
|
+
const oldStep = state.currentStep;
|
|
6047
|
+
state.currentStep = stepIndex;
|
|
6048
|
+
// Always call onStepChange when step changes
|
|
6049
|
+
if (onStepChange && oldStep !== stepIndex) {
|
|
6050
|
+
onStepChange(stepIndex, steps[stepIndex].id || `step-${stepIndex}`);
|
|
6051
|
+
}
|
|
6052
|
+
// Force redraw to update UI
|
|
6053
|
+
m.redraw();
|
|
6054
|
+
return true;
|
|
6055
|
+
};
|
|
6056
|
+
const nextStep = async (attrs) => {
|
|
6057
|
+
const { steps } = attrs;
|
|
6058
|
+
// Check if we're on the last step
|
|
6059
|
+
if (state.currentStep === steps.length - 1) {
|
|
6060
|
+
// This is the complete action
|
|
6061
|
+
if (attrs.onComplete) {
|
|
6062
|
+
attrs.onComplete();
|
|
6063
|
+
}
|
|
6064
|
+
return;
|
|
6065
|
+
}
|
|
6066
|
+
// Try to move to next step
|
|
6067
|
+
await goToStep(state.currentStep + 1, attrs);
|
|
6068
|
+
};
|
|
6069
|
+
const previousStep = (attrs) => {
|
|
6070
|
+
goToStep(state.currentStep - 1, attrs);
|
|
6071
|
+
};
|
|
6072
|
+
const skipStep = (attrs) => {
|
|
6073
|
+
const { steps } = attrs;
|
|
6074
|
+
const currentStepData = steps[state.currentStep];
|
|
6075
|
+
if (currentStepData && currentStepData.optional) {
|
|
6076
|
+
goToStep(state.currentStep + 1, attrs);
|
|
6077
|
+
}
|
|
6078
|
+
};
|
|
6079
|
+
return {
|
|
6080
|
+
oninit: ({ attrs }) => {
|
|
6081
|
+
state = {
|
|
6082
|
+
id: uniqueId(),
|
|
6083
|
+
currentStep: attrs.currentStep || 0,
|
|
6084
|
+
isValidating: false,
|
|
6085
|
+
completedSteps: new Set(),
|
|
6086
|
+
errorSteps: new Set()
|
|
6087
|
+
};
|
|
6088
|
+
},
|
|
6089
|
+
onbeforeupdate: ({ attrs }) => {
|
|
6090
|
+
// Sync external currentStep changes
|
|
6091
|
+
if (typeof attrs.currentStep === 'number' && attrs.currentStep !== state.currentStep) {
|
|
6092
|
+
state.currentStep = Math.max(0, attrs.currentStep);
|
|
6093
|
+
}
|
|
6094
|
+
},
|
|
6095
|
+
view: ({ attrs }) => {
|
|
6096
|
+
const { steps, showStepNumbers = true, className = '', showNavigation = true, labels = {}, orientation = 'horizontal', allowHeaderNavigation = false } = attrs;
|
|
6097
|
+
// Ensure currentStep is within bounds
|
|
6098
|
+
if (state.currentStep >= steps.length) {
|
|
6099
|
+
state.currentStep = Math.max(0, steps.length - 1);
|
|
6100
|
+
}
|
|
6101
|
+
const currentStepData = steps[state.currentStep];
|
|
6102
|
+
const isFirstStep = state.currentStep === 0;
|
|
6103
|
+
const isLastStep = state.currentStep === steps.length - 1;
|
|
6104
|
+
const activeContent = (currentStepData === null || currentStepData === void 0 ? void 0 : currentStepData.vnode) ? currentStepData.vnode() : null;
|
|
6105
|
+
return m('.wizard', { class: `${orientation} ${className}` }, [
|
|
6106
|
+
// Step indicator
|
|
6107
|
+
m('.wizard-header', [
|
|
6108
|
+
m('.wizard-steps', steps.map((step, index) => {
|
|
6109
|
+
const isActive = index === state.currentStep;
|
|
6110
|
+
const isCompleted = state.completedSteps.has(index);
|
|
6111
|
+
const hasError = state.errorSteps.has(index);
|
|
6112
|
+
return m('.wizard-step', {
|
|
6113
|
+
class: [
|
|
6114
|
+
isActive ? 'active' : '',
|
|
6115
|
+
isCompleted ? 'completed' : '',
|
|
6116
|
+
hasError ? 'error' : '',
|
|
6117
|
+
step.disabled ? 'disabled' : '',
|
|
6118
|
+
step.optional ? 'optional' : ''
|
|
6119
|
+
].filter(Boolean).join(' '),
|
|
6120
|
+
onclick: allowHeaderNavigation && !step.disabled ?
|
|
6121
|
+
() => goToStep(index, attrs) : undefined
|
|
6122
|
+
}, [
|
|
6123
|
+
// Step number/icon
|
|
6124
|
+
m('.wizard-step-indicator', [
|
|
6125
|
+
isCompleted ?
|
|
6126
|
+
m('i.material-icons', 'check') :
|
|
6127
|
+
hasError ?
|
|
6128
|
+
m('i.material-icons', 'error') :
|
|
6129
|
+
step.icon ?
|
|
6130
|
+
m('i.material-icons', step.icon) :
|
|
6131
|
+
showStepNumbers ?
|
|
6132
|
+
m('span.wizard-step-number', index + 1) :
|
|
6133
|
+
null
|
|
6134
|
+
]),
|
|
6135
|
+
// Step content
|
|
6136
|
+
m('.wizard-step-content', [
|
|
6137
|
+
m('.wizard-step-title', step.title),
|
|
6138
|
+
step.subtitle && m('.wizard-step-subtitle', step.subtitle),
|
|
6139
|
+
step.optional && m('.wizard-step-optional', labels.optional || 'Optional')
|
|
6140
|
+
]),
|
|
6141
|
+
// Connector line (except for last step in horizontal mode)
|
|
6142
|
+
orientation === 'horizontal' && index < steps.length - 1 &&
|
|
6143
|
+
m('.wizard-step-connector')
|
|
6144
|
+
]);
|
|
6145
|
+
}))
|
|
6146
|
+
]),
|
|
6147
|
+
// Step content
|
|
6148
|
+
m('.wizard-body', [
|
|
6149
|
+
activeContent && m('.wizard-step-panel', {
|
|
6150
|
+
key: (currentStepData === null || currentStepData === void 0 ? void 0 : currentStepData.id) || `step-${state.currentStep}`
|
|
6151
|
+
}, activeContent)
|
|
6152
|
+
]),
|
|
6153
|
+
// Navigation
|
|
6154
|
+
showNavigation && m('.wizard-footer', [
|
|
6155
|
+
m('.wizard-navigation', [
|
|
6156
|
+
// Previous button
|
|
6157
|
+
!isFirstStep && m('button.btn-flat.wizard-btn-previous', {
|
|
6158
|
+
onclick: () => previousStep(attrs),
|
|
6159
|
+
disabled: state.isValidating
|
|
6160
|
+
}, labels.previous || 'Previous'),
|
|
6161
|
+
// Skip button (for optional steps)
|
|
6162
|
+
currentStepData && currentStepData.optional && !isLastStep &&
|
|
6163
|
+
m('button.btn-flat.wizard-btn-skip', {
|
|
6164
|
+
onclick: () => skipStep(attrs),
|
|
6165
|
+
disabled: state.isValidating
|
|
6166
|
+
}, labels.skip || 'Skip'),
|
|
6167
|
+
// Next/Complete button
|
|
6168
|
+
m('button.btn.wizard-btn-next', {
|
|
6169
|
+
onclick: () => nextStep(attrs),
|
|
6170
|
+
disabled: state.isValidating,
|
|
6171
|
+
class: isLastStep ? 'wizard-btn-complete' : ''
|
|
6172
|
+
}, [
|
|
6173
|
+
state.isValidating && m('i.material-icons.left', 'hourglass_empty'),
|
|
6174
|
+
isLastStep ? (labels.complete || 'Complete') : (labels.next || 'Next')
|
|
6175
|
+
])
|
|
6176
|
+
])
|
|
6177
|
+
])
|
|
6178
|
+
]);
|
|
6179
|
+
}
|
|
6180
|
+
};
|
|
6181
|
+
};
|
|
6182
|
+
/**
|
|
6183
|
+
* Simple linear stepper for forms
|
|
6184
|
+
*/
|
|
6185
|
+
const Stepper = () => {
|
|
6186
|
+
return {
|
|
6187
|
+
view: ({ attrs }) => {
|
|
6188
|
+
return m(Wizard, Object.assign(Object.assign({}, attrs), { linear: true, showNavigation: false, allowHeaderNavigation: false, orientation: 'horizontal' }));
|
|
6189
|
+
}
|
|
6190
|
+
};
|
|
6191
|
+
};
|
|
6192
|
+
|
|
5346
6193
|
exports.AnchorItem = AnchorItem;
|
|
5347
6194
|
exports.Autocomplete = Autocomplete;
|
|
6195
|
+
exports.Breadcrumb = Breadcrumb;
|
|
6196
|
+
exports.BreadcrumbManager = BreadcrumbManager;
|
|
5348
6197
|
exports.Button = Button;
|
|
5349
6198
|
exports.ButtonFactory = ButtonFactory;
|
|
5350
6199
|
exports.Carousel = Carousel;
|
|
@@ -5359,6 +6208,7 @@
|
|
|
5359
6208
|
exports.Dropdown = Dropdown;
|
|
5360
6209
|
exports.EmailInput = EmailInput;
|
|
5361
6210
|
exports.FileInput = FileInput;
|
|
6211
|
+
exports.FileUpload = FileUpload;
|
|
5362
6212
|
exports.FlatButton = FlatButton;
|
|
5363
6213
|
exports.FloatingActionButton = FloatingActionButton;
|
|
5364
6214
|
exports.HelperText = HelperText;
|
|
@@ -5384,18 +6234,27 @@
|
|
|
5384
6234
|
exports.SearchSelect = SearchSelect;
|
|
5385
6235
|
exports.SecondaryContent = SecondaryContent;
|
|
5386
6236
|
exports.Select = Select;
|
|
6237
|
+
exports.Sidenav = Sidenav;
|
|
6238
|
+
exports.SidenavItem = SidenavItem;
|
|
6239
|
+
exports.SidenavManager = SidenavManager;
|
|
5387
6240
|
exports.SmallButton = SmallButton;
|
|
6241
|
+
exports.Stepper = Stepper;
|
|
5388
6242
|
exports.SubmitButton = SubmitButton;
|
|
5389
6243
|
exports.Switch = Switch;
|
|
5390
6244
|
exports.Tabs = Tabs;
|
|
5391
6245
|
exports.TextArea = TextArea;
|
|
5392
6246
|
exports.TextInput = TextInput;
|
|
6247
|
+
exports.ThemeManager = ThemeManager;
|
|
6248
|
+
exports.ThemeSwitcher = ThemeSwitcher;
|
|
6249
|
+
exports.ThemeToggle = ThemeToggle;
|
|
5393
6250
|
exports.TimePicker = TimePicker;
|
|
5394
6251
|
exports.Toast = Toast;
|
|
5395
6252
|
exports.ToastComponent = ToastComponent;
|
|
5396
6253
|
exports.Tooltip = Tooltip;
|
|
5397
6254
|
exports.TooltipComponent = TooltipComponent;
|
|
5398
6255
|
exports.UrlInput = UrlInput;
|
|
6256
|
+
exports.Wizard = Wizard;
|
|
6257
|
+
exports.createBreadcrumb = createBreadcrumb;
|
|
5399
6258
|
exports.getDropdownStyles = getDropdownStyles;
|
|
5400
6259
|
exports.initPushpins = initPushpins;
|
|
5401
6260
|
exports.initTooltips = initTooltips;
|