mithril-materialized 3.3.8 → 3.4.1
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/README.md +1 -1
- package/dist/button.d.ts +1 -0
- package/dist/components.css +22 -0
- package/dist/core.css +0 -3
- package/dist/forms.css +8 -3
- package/dist/index.css +23 -3
- package/dist/index.esm.js +342 -101
- package/dist/index.js +342 -100
- package/dist/index.min.css +2 -2
- package/dist/index.umd.js +342 -100
- package/dist/utilities.css +1 -0
- package/dist/waves.d.ts +16 -0
- package/package.json +1 -1
- package/sass/components/_buttons.scss +21 -0
- package/sass/components/_chips.scss +1 -0
- package/sass/components/_theme-switcher.scss +10 -0
- package/sass/components/forms/_select.scss +3 -3
package/dist/index.js
CHANGED
|
@@ -230,8 +230,6 @@ const Autocomplete = () => {
|
|
|
230
230
|
if (attrs.onAutocomplete) {
|
|
231
231
|
attrs.onAutocomplete(suggestion.key);
|
|
232
232
|
}
|
|
233
|
-
// Force redraw to update label state
|
|
234
|
-
m.redraw();
|
|
235
233
|
};
|
|
236
234
|
const handleKeydown = (e, attrs) => {
|
|
237
235
|
if (!state.isOpen)
|
|
@@ -310,7 +308,7 @@ const Autocomplete = () => {
|
|
|
310
308
|
const id = attrs.id || state.id;
|
|
311
309
|
const { label, helperText, onchange, newRow, className = 'col s12', style, iconName, isMandatory, data = {}, limit = Infinity, minLength = 1 } = attrs, params = __rest(attrs, ["label", "helperText", "onchange", "newRow", "className", "style", "iconName", "isMandatory", "data", "limit", "minLength"]);
|
|
312
310
|
const controlled = isControlled(attrs);
|
|
313
|
-
const currentValue = controlled ?
|
|
311
|
+
const currentValue = controlled ? attrs.value || '' : state.internalValue;
|
|
314
312
|
const cn = newRow ? className + ' clear' : className;
|
|
315
313
|
// Update suggestions when input changes
|
|
316
314
|
state.suggestions = filterSuggestions(currentValue, data, limit, minLength);
|
|
@@ -325,7 +323,7 @@ const Autocomplete = () => {
|
|
|
325
323
|
style,
|
|
326
324
|
}, [
|
|
327
325
|
iconName ? m('i.material-icons.prefix', iconName) : '',
|
|
328
|
-
m('input', Object.assign(Object.assign({}, params), { className: 'autocomplete', type: 'text', tabindex: 0, id, value:
|
|
326
|
+
m('input', Object.assign(Object.assign({}, params), { className: 'autocomplete', type: 'text', tabindex: 0, id, value: currentValue, oncreate: (vnode) => {
|
|
329
327
|
state.inputElement = vnode.dom;
|
|
330
328
|
// Set initial value for uncontrolled mode
|
|
331
329
|
if (!controlled && attrs.defaultValue) {
|
|
@@ -361,14 +359,10 @@ const Autocomplete = () => {
|
|
|
361
359
|
}
|
|
362
360
|
}, onblur: (e) => {
|
|
363
361
|
state.isActive = false;
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
state.selectedIndex = -1;
|
|
369
|
-
m.redraw();
|
|
370
|
-
}
|
|
371
|
-
}, 150);
|
|
362
|
+
if (!e.relatedTarget || !e.relatedTarget.closest('.autocomplete-content')) {
|
|
363
|
+
state.isOpen = false;
|
|
364
|
+
state.selectedIndex = -1;
|
|
365
|
+
}
|
|
372
366
|
} })),
|
|
373
367
|
// Autocomplete dropdown
|
|
374
368
|
state.isOpen &&
|
|
@@ -384,7 +378,6 @@ const Autocomplete = () => {
|
|
|
384
378
|
},
|
|
385
379
|
onmouseover: () => {
|
|
386
380
|
state.selectedIndex = index;
|
|
387
|
-
m.redraw();
|
|
388
381
|
},
|
|
389
382
|
}, [
|
|
390
383
|
// Check if value contains image URL or icon
|
|
@@ -434,6 +427,103 @@ const Icon = () => ({
|
|
|
434
427
|
},
|
|
435
428
|
});
|
|
436
429
|
|
|
430
|
+
/*!
|
|
431
|
+
* Waves Effect for Mithril Materialized
|
|
432
|
+
* Based on Waves v0.6.4 by Alfiana E. Sibuea
|
|
433
|
+
* Adapted for TypeScript and Mithril integration
|
|
434
|
+
*/
|
|
435
|
+
class WavesEffect {
|
|
436
|
+
static offset(elem) {
|
|
437
|
+
const rect = elem.getBoundingClientRect();
|
|
438
|
+
return {
|
|
439
|
+
top: rect.top + window.pageYOffset,
|
|
440
|
+
left: rect.left + window.pageXOffset
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
static createRipple(e, element) {
|
|
444
|
+
// Disable right click
|
|
445
|
+
if (e.button === 2) {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
// Create ripple element
|
|
449
|
+
const ripple = document.createElement('div');
|
|
450
|
+
ripple.className = 'waves-ripple';
|
|
451
|
+
// Get click position relative to element
|
|
452
|
+
const pos = this.offset(element);
|
|
453
|
+
const relativeY = e.pageY - pos.top;
|
|
454
|
+
const relativeX = e.pageX - pos.left;
|
|
455
|
+
// Calculate scale based on element size
|
|
456
|
+
const scale = (element.clientWidth / 100) * 10;
|
|
457
|
+
// Set initial ripple position and style
|
|
458
|
+
ripple.style.cssText = `
|
|
459
|
+
top: ${relativeY}px;
|
|
460
|
+
left: ${relativeX}px;
|
|
461
|
+
transform: scale(0);
|
|
462
|
+
opacity: 1;
|
|
463
|
+
`;
|
|
464
|
+
// Add ripple to element
|
|
465
|
+
element.appendChild(ripple);
|
|
466
|
+
// Force reflow and animate
|
|
467
|
+
ripple.offsetHeight;
|
|
468
|
+
ripple.style.transform = `scale(${scale})`;
|
|
469
|
+
ripple.style.opacity = '1';
|
|
470
|
+
// Store reference for cleanup
|
|
471
|
+
ripple.setAttribute('data-created', Date.now().toString());
|
|
472
|
+
}
|
|
473
|
+
static removeRipples(element) {
|
|
474
|
+
const ripples = element.querySelectorAll('.waves-ripple');
|
|
475
|
+
ripples.forEach((ripple) => {
|
|
476
|
+
const created = parseInt(ripple.getAttribute('data-created') || '0');
|
|
477
|
+
const age = Date.now() - created;
|
|
478
|
+
const fadeOut = () => {
|
|
479
|
+
ripple.style.opacity = '0';
|
|
480
|
+
setTimeout(() => {
|
|
481
|
+
if (ripple.parentNode) {
|
|
482
|
+
ripple.parentNode.removeChild(ripple);
|
|
483
|
+
}
|
|
484
|
+
}, this.duration);
|
|
485
|
+
};
|
|
486
|
+
if (age >= 350) {
|
|
487
|
+
fadeOut();
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
setTimeout(fadeOut, 350 - age);
|
|
491
|
+
}
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
WavesEffect.duration = 750;
|
|
496
|
+
WavesEffect.onMouseDown = (e) => {
|
|
497
|
+
const element = e.currentTarget;
|
|
498
|
+
if (element && element.classList.contains('waves-effect')) {
|
|
499
|
+
WavesEffect.createRipple(e, element);
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
WavesEffect.onMouseUp = (e) => {
|
|
503
|
+
const element = e.currentTarget;
|
|
504
|
+
if (element && element.classList.contains('waves-effect')) {
|
|
505
|
+
WavesEffect.removeRipples(element);
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
WavesEffect.onMouseLeave = (e) => {
|
|
509
|
+
const element = e.currentTarget;
|
|
510
|
+
if (element && element.classList.contains('waves-effect')) {
|
|
511
|
+
WavesEffect.removeRipples(element);
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
WavesEffect.onTouchStart = (e) => {
|
|
515
|
+
const element = e.currentTarget;
|
|
516
|
+
if (element && element.classList.contains('waves-effect')) {
|
|
517
|
+
WavesEffect.createRipple(e, element);
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
WavesEffect.onTouchEnd = (e) => {
|
|
521
|
+
const element = e.currentTarget;
|
|
522
|
+
if (element && element.classList.contains('waves-effect')) {
|
|
523
|
+
WavesEffect.removeRipples(element);
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
|
|
437
527
|
/**
|
|
438
528
|
* A factory to create new buttons.
|
|
439
529
|
*
|
|
@@ -447,13 +537,18 @@ const ButtonFactory = (element, defaultClassNames, type = '') => {
|
|
|
447
537
|
iconName, iconClass, label, className, variant } = attrs, params = __rest(attrs, ["tooltip", "tooltipPosition", "tooltipPostion", "iconName", "iconClass", "label", "className", "variant"]);
|
|
448
538
|
// Use variant or fallback to factory type
|
|
449
539
|
const buttonType = variant || type || 'button';
|
|
450
|
-
const cn = [tooltip ? 'tooltipped' : '', defaultClassNames, className]
|
|
451
|
-
.filter(Boolean)
|
|
452
|
-
.join(' ')
|
|
453
|
-
.trim();
|
|
540
|
+
const cn = [tooltip ? 'tooltipped' : '', defaultClassNames, className].filter(Boolean).join(' ').trim();
|
|
454
541
|
// Use tooltipPosition if available, fallback to legacy tooltipPostion
|
|
455
542
|
const position = tooltipPosition || tooltipPostion || 'top';
|
|
456
|
-
|
|
543
|
+
// Add waves effect event handlers if waves-effect class is present
|
|
544
|
+
const wavesHandlers = cn.includes('waves-effect') ? {
|
|
545
|
+
onmousedown: WavesEffect.onMouseDown,
|
|
546
|
+
onmouseup: WavesEffect.onMouseUp,
|
|
547
|
+
onmouseleave: WavesEffect.onMouseLeave,
|
|
548
|
+
ontouchstart: WavesEffect.onTouchStart,
|
|
549
|
+
ontouchend: WavesEffect.onTouchEnd
|
|
550
|
+
} : {};
|
|
551
|
+
return m(element, Object.assign(Object.assign(Object.assign({}, params), wavesHandlers), { className: cn, 'data-position': tooltip ? position : undefined, 'data-tooltip': tooltip || undefined, type: buttonType }), iconName ? m(Icon, { iconName, className: iconClass || 'left' }) : undefined, label ? label : undefined);
|
|
457
552
|
},
|
|
458
553
|
};
|
|
459
554
|
};
|
|
@@ -462,6 +557,7 @@ const Button = ButtonFactory('a', 'waves-effect waves-light btn', 'button');
|
|
|
462
557
|
const LargeButton = ButtonFactory('a', 'waves-effect waves-light btn-large', 'button');
|
|
463
558
|
const SmallButton = ButtonFactory('a', 'waves-effect waves-light btn-small', 'button');
|
|
464
559
|
const FlatButton = ButtonFactory('a', 'waves-effect waves-teal btn-flat', 'button');
|
|
560
|
+
const IconButton = ButtonFactory('button', 'btn-flat btn-icon waves-effect waves-teal', 'button');
|
|
465
561
|
const RoundIconButton = ButtonFactory('button', 'btn-floating btn-large waves-effect waves-light', 'button');
|
|
466
562
|
const SubmitButton = ButtonFactory('button', 'btn waves-effect waves-light', 'submit');
|
|
467
563
|
|
|
@@ -898,7 +994,7 @@ const MaterialIcon = () => {
|
|
|
898
994
|
};
|
|
899
995
|
const rotation = (_a = rotationMap[direction]) !== null && _a !== void 0 ? _a : 0;
|
|
900
996
|
const transform = rotation ? `rotate(${rotation}deg)` : undefined;
|
|
901
|
-
return m('svg', Object.assign(Object.assign({}, props), { style: Object.assign({ transform }, style), height: '
|
|
997
|
+
return m('svg', Object.assign(Object.assign({}, props), { style: Object.assign({ transform }, style), height: '24px', width: '24px', viewBox: '0 0 24 24', xmlns: 'http://www.w3.org/2000/svg' }), iconPaths[name].map((d) => m('path', {
|
|
902
998
|
d,
|
|
903
999
|
fill: d.includes('M0 0h24v24H0z') ? 'none' : 'currentColor',
|
|
904
1000
|
})));
|
|
@@ -2382,36 +2478,52 @@ const handleKeyboardNavigation = (key, currentValue, min, max, step) => {
|
|
|
2382
2478
|
return null;
|
|
2383
2479
|
}
|
|
2384
2480
|
};
|
|
2481
|
+
const isControlled = (attrs) => {
|
|
2482
|
+
return attrs.value !== undefined && typeof attrs.oninput === 'function';
|
|
2483
|
+
};
|
|
2484
|
+
const isRangeControlled = (attrs) => {
|
|
2485
|
+
return (attrs.minValue !== undefined || attrs.maxValue !== undefined) && typeof attrs.oninput === 'function';
|
|
2486
|
+
};
|
|
2385
2487
|
const initRangeState = (state, attrs) => {
|
|
2386
|
-
const { min = 0, max = 100, value, minValue, maxValue } = attrs;
|
|
2488
|
+
const { min = 0, max = 100, value, minValue, maxValue, defaultValue } = attrs;
|
|
2387
2489
|
// Initialize single range value
|
|
2388
|
-
if (
|
|
2389
|
-
|
|
2490
|
+
if (isControlled(attrs)) {
|
|
2491
|
+
// Always use value from props in controlled mode
|
|
2492
|
+
state.singleValue = value !== undefined ? value : min;
|
|
2493
|
+
}
|
|
2494
|
+
else {
|
|
2495
|
+
// Use internal state for uncontrolled mode
|
|
2390
2496
|
if (state.singleValue === undefined) {
|
|
2391
|
-
state.singleValue =
|
|
2497
|
+
state.singleValue = defaultValue !== undefined ? defaultValue : value !== undefined ? value : min;
|
|
2392
2498
|
}
|
|
2393
|
-
|
|
2499
|
+
// Only update internal state if props changed and user hasn't interacted
|
|
2500
|
+
if (state.lastValue !== value && !state.hasUserInteracted && value !== undefined) {
|
|
2394
2501
|
state.singleValue = value;
|
|
2395
2502
|
state.lastValue = value;
|
|
2396
2503
|
}
|
|
2397
2504
|
}
|
|
2398
|
-
else if (state.singleValue === undefined) {
|
|
2399
|
-
state.singleValue = min;
|
|
2400
|
-
}
|
|
2401
2505
|
// Initialize range values
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
state.
|
|
2406
|
-
state.rangeMaxValue = currentMaxValue;
|
|
2506
|
+
if (isRangeControlled(attrs)) {
|
|
2507
|
+
// Always use values from props in controlled mode
|
|
2508
|
+
state.rangeMinValue = minValue !== undefined ? minValue : min;
|
|
2509
|
+
state.rangeMaxValue = maxValue !== undefined ? maxValue : max;
|
|
2407
2510
|
}
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
state.rangeMaxValue
|
|
2413
|
-
|
|
2414
|
-
|
|
2511
|
+
else {
|
|
2512
|
+
// Use internal state for uncontrolled mode
|
|
2513
|
+
const currentMinValue = minValue !== undefined ? minValue : min;
|
|
2514
|
+
const currentMaxValue = maxValue !== undefined ? maxValue : max;
|
|
2515
|
+
if (state.rangeMinValue === undefined || state.rangeMaxValue === undefined) {
|
|
2516
|
+
state.rangeMinValue = currentMinValue;
|
|
2517
|
+
state.rangeMaxValue = currentMaxValue;
|
|
2518
|
+
}
|
|
2519
|
+
if (!state.hasUserInteracted &&
|
|
2520
|
+
((minValue !== undefined && state.lastMinValue !== minValue) ||
|
|
2521
|
+
(maxValue !== undefined && state.lastMaxValue !== maxValue))) {
|
|
2522
|
+
state.rangeMinValue = currentMinValue;
|
|
2523
|
+
state.rangeMaxValue = currentMaxValue;
|
|
2524
|
+
state.lastMinValue = minValue;
|
|
2525
|
+
state.lastMaxValue = maxValue;
|
|
2526
|
+
}
|
|
2415
2527
|
}
|
|
2416
2528
|
// Initialize active thumb if not set
|
|
2417
2529
|
if (state.activeThumb === null) {
|
|
@@ -2428,15 +2540,18 @@ const updateRangeValues = (minValue, maxValue, attrs, state, immediate) => {
|
|
|
2428
2540
|
minValue = maxValue;
|
|
2429
2541
|
if (maxValue < minValue)
|
|
2430
2542
|
maxValue = minValue;
|
|
2431
|
-
state
|
|
2432
|
-
|
|
2543
|
+
// Only update internal state for uncontrolled mode
|
|
2544
|
+
if (!isRangeControlled(attrs)) {
|
|
2545
|
+
state.rangeMinValue = minValue;
|
|
2546
|
+
state.rangeMaxValue = maxValue;
|
|
2547
|
+
}
|
|
2433
2548
|
state.hasUserInteracted = true;
|
|
2434
|
-
// Call
|
|
2549
|
+
// Call appropriate handler based on interaction type, not control mode
|
|
2435
2550
|
if (immediate && attrs.oninput) {
|
|
2436
|
-
attrs.oninput(minValue, maxValue);
|
|
2551
|
+
attrs.oninput(minValue, maxValue); // Immediate feedback during drag
|
|
2437
2552
|
}
|
|
2438
|
-
|
|
2439
|
-
attrs.onchange(minValue, maxValue);
|
|
2553
|
+
if (!immediate && attrs.onchange) {
|
|
2554
|
+
attrs.onchange(minValue, maxValue); // Final value on interaction end (blur/mouseup)
|
|
2440
2555
|
}
|
|
2441
2556
|
};
|
|
2442
2557
|
// Single Range Slider Component
|
|
@@ -2470,19 +2585,24 @@ const SingleRangeSlider = {
|
|
|
2470
2585
|
: tooltipPos
|
|
2471
2586
|
: tooltipPos;
|
|
2472
2587
|
const updateSingleValue = (newValue, immediate = false) => {
|
|
2473
|
-
state
|
|
2588
|
+
// Only update internal state for uncontrolled mode
|
|
2589
|
+
if (!isControlled(attrs)) {
|
|
2590
|
+
state.singleValue = newValue;
|
|
2591
|
+
}
|
|
2474
2592
|
state.hasUserInteracted = true;
|
|
2593
|
+
// Call appropriate handler based on interaction type, not control mode
|
|
2475
2594
|
if (immediate && oninput) {
|
|
2476
|
-
oninput(newValue);
|
|
2595
|
+
oninput(newValue); // Immediate feedback during drag
|
|
2477
2596
|
}
|
|
2478
|
-
|
|
2479
|
-
onchange(newValue);
|
|
2597
|
+
if (!immediate && onchange) {
|
|
2598
|
+
onchange(newValue); // Final value on interaction end (blur/mouseup)
|
|
2480
2599
|
}
|
|
2481
2600
|
};
|
|
2482
2601
|
const handleMouseDown = (e) => {
|
|
2483
2602
|
if (disabled)
|
|
2484
2603
|
return;
|
|
2485
2604
|
e.preventDefault();
|
|
2605
|
+
e.stopPropagation();
|
|
2486
2606
|
state.isDragging = true;
|
|
2487
2607
|
if (finalValueDisplay === 'auto') {
|
|
2488
2608
|
m.redraw();
|
|
@@ -2557,6 +2677,11 @@ const SingleRangeSlider = {
|
|
|
2557
2677
|
updateSingleValue(newValue, false);
|
|
2558
2678
|
}
|
|
2559
2679
|
},
|
|
2680
|
+
onblur: () => {
|
|
2681
|
+
if (disabled || !onchange)
|
|
2682
|
+
return;
|
|
2683
|
+
onchange(state.singleValue);
|
|
2684
|
+
},
|
|
2560
2685
|
}, [
|
|
2561
2686
|
m(`.track.${orientation}`),
|
|
2562
2687
|
m(`.range-progress.${orientation}`, { style: progressStyle }),
|
|
@@ -2615,6 +2740,7 @@ const DoubleRangeSlider = {
|
|
|
2615
2740
|
if (disabled)
|
|
2616
2741
|
return;
|
|
2617
2742
|
e.preventDefault();
|
|
2743
|
+
e.stopPropagation();
|
|
2618
2744
|
state.isDragging = true;
|
|
2619
2745
|
state.activeThumb = thumb;
|
|
2620
2746
|
if (finalValueDisplay === 'auto') {
|
|
@@ -2705,6 +2831,11 @@ const DoubleRangeSlider = {
|
|
|
2705
2831
|
maxThumb.focus();
|
|
2706
2832
|
}
|
|
2707
2833
|
},
|
|
2834
|
+
onblur: () => {
|
|
2835
|
+
if (disabled || !attrs.onchange)
|
|
2836
|
+
return;
|
|
2837
|
+
attrs.onchange(state.rangeMinValue, state.rangeMaxValue);
|
|
2838
|
+
},
|
|
2708
2839
|
}, [
|
|
2709
2840
|
m(`.track.${orientation}`),
|
|
2710
2841
|
m(`.range.${orientation}`, { style: rangeStyle }),
|
|
@@ -2910,13 +3041,13 @@ const TextArea = () => {
|
|
|
2910
3041
|
overflowWrap: 'break-word',
|
|
2911
3042
|
},
|
|
2912
3043
|
oncreate: ({ dom }) => {
|
|
2913
|
-
const hiddenDiv = state.hiddenDiv = dom;
|
|
3044
|
+
const hiddenDiv = (state.hiddenDiv = dom);
|
|
2914
3045
|
if (state.textarea) {
|
|
2915
3046
|
updateHeight(state.textarea, hiddenDiv);
|
|
2916
3047
|
}
|
|
2917
3048
|
},
|
|
2918
3049
|
onupdate: ({ dom }) => {
|
|
2919
|
-
const hiddenDiv = state.hiddenDiv = dom;
|
|
3050
|
+
const hiddenDiv = (state.hiddenDiv = dom);
|
|
2920
3051
|
if (state.textarea) {
|
|
2921
3052
|
updateHeight(state.textarea, hiddenDiv);
|
|
2922
3053
|
}
|
|
@@ -3029,8 +3160,7 @@ const InputField = (type, defaultClass = '') => () => {
|
|
|
3029
3160
|
isDragging: false,
|
|
3030
3161
|
activeThumb: null,
|
|
3031
3162
|
};
|
|
3032
|
-
const isControlled = (attrs) => 'value' in attrs && typeof attrs.value !== 'undefined' &&
|
|
3033
|
-
(typeof attrs.oninput === 'function' || typeof attrs.onchange === 'function');
|
|
3163
|
+
const isControlled = (attrs) => 'value' in attrs && typeof attrs.value !== 'undefined' && typeof attrs.oninput === 'function';
|
|
3034
3164
|
const getValue = (target) => {
|
|
3035
3165
|
const val = target.value;
|
|
3036
3166
|
return (val ? (type === 'number' || type === 'range' ? +val : val) : val);
|
|
@@ -3080,7 +3210,7 @@ const InputField = (type, defaultClass = '') => () => {
|
|
|
3080
3210
|
const isNonInteractive = attrs.readonly || attrs.disabled;
|
|
3081
3211
|
// Warn developer for improper controlled usage
|
|
3082
3212
|
if (attrs.value !== undefined && !controlled && !isNonInteractive) {
|
|
3083
|
-
console.warn(`${type} input received 'value' prop without 'oninput'
|
|
3213
|
+
console.warn(`${type} input with label '${attrs.label}' received 'value' prop without 'oninput' handler. ` +
|
|
3084
3214
|
`Use 'defaultValue' for uncontrolled components or add an event handler for controlled components.`);
|
|
3085
3215
|
}
|
|
3086
3216
|
// Initialize internal value if not in controlled mode
|
|
@@ -4107,14 +4237,12 @@ const Dropdown = () => {
|
|
|
4107
4237
|
inputRef: null,
|
|
4108
4238
|
dropdownRef: null,
|
|
4109
4239
|
internalCheckedId: undefined,
|
|
4240
|
+
isInsideModal: false,
|
|
4110
4241
|
};
|
|
4111
4242
|
const isControlled = (attrs) => attrs.checkedId !== undefined && typeof attrs.onchange === 'function';
|
|
4112
|
-
const closeDropdown = (
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
state.isOpen = false;
|
|
4116
|
-
m.redraw();
|
|
4117
|
-
}
|
|
4243
|
+
const closeDropdown = () => {
|
|
4244
|
+
state.isOpen = false;
|
|
4245
|
+
m.redraw(); // Needed to remove the dropdown options list (potentially added to document root)
|
|
4118
4246
|
};
|
|
4119
4247
|
const handleKeyDown = (e, items) => {
|
|
4120
4248
|
const availableItems = items.filter((item) => !item.divider && !item.disabled);
|
|
@@ -4159,6 +4287,83 @@ const Dropdown = () => {
|
|
|
4159
4287
|
return undefined;
|
|
4160
4288
|
}
|
|
4161
4289
|
};
|
|
4290
|
+
const getPortalStyles = (inputRef) => {
|
|
4291
|
+
if (!inputRef)
|
|
4292
|
+
return {};
|
|
4293
|
+
const rect = inputRef.getBoundingClientRect();
|
|
4294
|
+
const viewportHeight = window.innerHeight;
|
|
4295
|
+
const spaceBelow = viewportHeight - rect.bottom;
|
|
4296
|
+
const spaceAbove = rect.top;
|
|
4297
|
+
// Choose whether to show above or below based on available space
|
|
4298
|
+
const showAbove = spaceBelow < 200 && spaceAbove > spaceBelow;
|
|
4299
|
+
return {
|
|
4300
|
+
position: 'fixed',
|
|
4301
|
+
top: showAbove ? 'auto' : `${rect.bottom}px`,
|
|
4302
|
+
bottom: showAbove ? `${viewportHeight - rect.top}px` : 'auto',
|
|
4303
|
+
left: `${rect.left}px`,
|
|
4304
|
+
width: `${rect.width}px`,
|
|
4305
|
+
zIndex: 10000,
|
|
4306
|
+
maxHeight: showAbove ? `${spaceAbove - 20}px` : `${spaceBelow - 20}px`,
|
|
4307
|
+
overflow: 'auto',
|
|
4308
|
+
display: 'block',
|
|
4309
|
+
opacity: 1,
|
|
4310
|
+
};
|
|
4311
|
+
};
|
|
4312
|
+
const updatePortalDropdown = (items, selectedLabel, onSelectItem) => {
|
|
4313
|
+
if (!state.isInsideModal)
|
|
4314
|
+
return;
|
|
4315
|
+
// Clean up existing portal
|
|
4316
|
+
const existingPortal = document.getElementById(`${state.id}-dropdown`);
|
|
4317
|
+
if (existingPortal) {
|
|
4318
|
+
existingPortal.remove();
|
|
4319
|
+
}
|
|
4320
|
+
if (!state.isOpen || !state.inputRef)
|
|
4321
|
+
return;
|
|
4322
|
+
// Create portal element
|
|
4323
|
+
const portalElement = document.createElement('div');
|
|
4324
|
+
portalElement.id = `${state.id}-dropdown`;
|
|
4325
|
+
document.body.appendChild(portalElement);
|
|
4326
|
+
// Create dropdown content
|
|
4327
|
+
const availableItems = items.filter((item) => !item.divider && !item.disabled);
|
|
4328
|
+
const dropdownContent = items.map((item) => {
|
|
4329
|
+
if (item.divider) {
|
|
4330
|
+
return m('li.divider');
|
|
4331
|
+
}
|
|
4332
|
+
const itemIndex = availableItems.indexOf(item);
|
|
4333
|
+
const isSelected = selectedLabel === item.label;
|
|
4334
|
+
const isFocused = state.focusedIndex === itemIndex;
|
|
4335
|
+
return m('li', {
|
|
4336
|
+
class: `${isSelected ? 'selected' : ''} ${isFocused ? 'focused' : ''}${item.disabled ? ' disabled' : ''}`,
|
|
4337
|
+
onclick: item.disabled ? undefined : () => onSelectItem(item),
|
|
4338
|
+
}, m('span', {
|
|
4339
|
+
style: {
|
|
4340
|
+
display: 'flex',
|
|
4341
|
+
alignItems: 'center',
|
|
4342
|
+
padding: '14px 16px',
|
|
4343
|
+
},
|
|
4344
|
+
}, [
|
|
4345
|
+
item.iconName
|
|
4346
|
+
? m('i.material-icons', {
|
|
4347
|
+
style: { marginRight: '32px' },
|
|
4348
|
+
}, item.iconName)
|
|
4349
|
+
: undefined,
|
|
4350
|
+
item.label,
|
|
4351
|
+
]));
|
|
4352
|
+
});
|
|
4353
|
+
// Create dropdown with proper positioning
|
|
4354
|
+
const dropdownVnode = m('ul.dropdown-content.select-dropdown', {
|
|
4355
|
+
tabindex: 0,
|
|
4356
|
+
style: getPortalStyles(state.inputRef),
|
|
4357
|
+
oncreate: ({ dom }) => {
|
|
4358
|
+
state.dropdownRef = dom;
|
|
4359
|
+
},
|
|
4360
|
+
onremove: () => {
|
|
4361
|
+
state.dropdownRef = null;
|
|
4362
|
+
},
|
|
4363
|
+
}, dropdownContent);
|
|
4364
|
+
// Render to portal
|
|
4365
|
+
m.render(portalElement, dropdownVnode);
|
|
4366
|
+
};
|
|
4162
4367
|
return {
|
|
4163
4368
|
oninit: ({ attrs }) => {
|
|
4164
4369
|
var _a;
|
|
@@ -4170,9 +4375,18 @@ const Dropdown = () => {
|
|
|
4170
4375
|
// Add global click listener to close dropdown
|
|
4171
4376
|
document.addEventListener('click', closeDropdown);
|
|
4172
4377
|
},
|
|
4378
|
+
oncreate: ({ dom }) => {
|
|
4379
|
+
// Detect if component is inside a modal
|
|
4380
|
+
state.isInsideModal = !!dom.closest('.modal');
|
|
4381
|
+
},
|
|
4173
4382
|
onremove: () => {
|
|
4174
4383
|
// Cleanup global listener
|
|
4175
4384
|
document.removeEventListener('click', closeDropdown);
|
|
4385
|
+
// Cleanup portal
|
|
4386
|
+
const portalElement = document.getElementById(`${state.id}-dropdown`);
|
|
4387
|
+
if (portalElement) {
|
|
4388
|
+
portalElement.remove();
|
|
4389
|
+
}
|
|
4176
4390
|
},
|
|
4177
4391
|
view: ({ attrs }) => {
|
|
4178
4392
|
const { checkedId, key, label, onchange, disabled = false, items, iconName, helperText, style, className = 'col s12', } = attrs;
|
|
@@ -4195,6 +4409,16 @@ const Dropdown = () => {
|
|
|
4195
4409
|
: undefined;
|
|
4196
4410
|
const title = selectedItem ? selectedItem.label : label || 'Select';
|
|
4197
4411
|
const availableItems = items.filter((item) => !item.divider && !item.disabled);
|
|
4412
|
+
// Update portal dropdown when inside modal
|
|
4413
|
+
if (state.isInsideModal) {
|
|
4414
|
+
updatePortalDropdown(items, title, (item) => {
|
|
4415
|
+
if (item.id) {
|
|
4416
|
+
state.isOpen = false;
|
|
4417
|
+
state.focusedIndex = -1;
|
|
4418
|
+
handleSelection(item.id);
|
|
4419
|
+
}
|
|
4420
|
+
});
|
|
4421
|
+
}
|
|
4198
4422
|
return m('.dropdown-wrapper.input-field', { className, key, style }, [
|
|
4199
4423
|
iconName ? m('i.material-icons.prefix', iconName) : undefined,
|
|
4200
4424
|
m(HelperText, { helperText }),
|
|
@@ -4228,8 +4452,9 @@ const Dropdown = () => {
|
|
|
4228
4452
|
}
|
|
4229
4453
|
},
|
|
4230
4454
|
}),
|
|
4231
|
-
// Dropdown Menu
|
|
4455
|
+
// Dropdown Menu - render inline only when NOT inside modal
|
|
4232
4456
|
state.isOpen &&
|
|
4457
|
+
!state.isInsideModal &&
|
|
4233
4458
|
m('ul.dropdown-content.select-dropdown', {
|
|
4234
4459
|
tabindex: 0,
|
|
4235
4460
|
role: 'listbox',
|
|
@@ -4346,12 +4571,17 @@ const FloatingActionButton = () => {
|
|
|
4346
4571
|
}
|
|
4347
4572
|
: undefined,
|
|
4348
4573
|
}, [
|
|
4349
|
-
m('a.btn-floating.btn-large', {
|
|
4574
|
+
m('a.btn-floating.btn-large.waves-effect.waves-light', {
|
|
4350
4575
|
className,
|
|
4576
|
+
onmousedown: WavesEffect.onMouseDown,
|
|
4577
|
+
onmouseup: WavesEffect.onMouseUp,
|
|
4578
|
+
onmouseleave: WavesEffect.onMouseLeave,
|
|
4579
|
+
ontouchstart: WavesEffect.onTouchStart,
|
|
4580
|
+
ontouchend: WavesEffect.onTouchEnd,
|
|
4351
4581
|
}, m('i.material-icons', { className: iconClass }, iconName)),
|
|
4352
4582
|
buttons &&
|
|
4353
4583
|
buttons.length > 0 &&
|
|
4354
|
-
m('ul', buttons.map((button, index) => m('li', m(`a.btn-floating.${button.className || 'red'}`, {
|
|
4584
|
+
m('ul', buttons.map((button, index) => m('li', m(`a.btn-floating.waves-effect.waves-light.${button.className || 'red'}`, {
|
|
4355
4585
|
style: {
|
|
4356
4586
|
opacity: state.isOpen ? '1' : '0',
|
|
4357
4587
|
transform: state.isOpen ? 'scale(1)' : 'scale(0.4)',
|
|
@@ -4362,6 +4592,11 @@ const FloatingActionButton = () => {
|
|
|
4362
4592
|
if (button.onclick)
|
|
4363
4593
|
button.onclick(e);
|
|
4364
4594
|
},
|
|
4595
|
+
onmousedown: WavesEffect.onMouseDown,
|
|
4596
|
+
onmouseup: WavesEffect.onMouseUp,
|
|
4597
|
+
onmouseleave: WavesEffect.onMouseLeave,
|
|
4598
|
+
ontouchstart: WavesEffect.onTouchStart,
|
|
4599
|
+
ontouchend: WavesEffect.onTouchEnd,
|
|
4365
4600
|
}, m('i.material-icons', { className: button.iconClass }, button.iconName))))),
|
|
4366
4601
|
]));
|
|
4367
4602
|
},
|
|
@@ -4669,7 +4904,7 @@ const ModalPanel = () => {
|
|
|
4669
4904
|
maxWidth: '75%',
|
|
4670
4905
|
borderRadius: '4px',
|
|
4671
4906
|
})), { 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)' }),
|
|
4672
|
-
onclick: (e) => e.stopPropagation(), // Prevent backdrop click when clicking inside modal
|
|
4907
|
+
// onclick: (e: Event) => e.stopPropagation(), // Prevent backdrop click when clicking inside modal
|
|
4673
4908
|
}, [
|
|
4674
4909
|
// Close button
|
|
4675
4910
|
showCloseButton &&
|
|
@@ -5765,6 +6000,7 @@ const Select = () => {
|
|
|
5765
6000
|
dropdownRef: null,
|
|
5766
6001
|
internalSelectedIds: [],
|
|
5767
6002
|
isInsideModal: false,
|
|
6003
|
+
isMultiple: false,
|
|
5768
6004
|
};
|
|
5769
6005
|
const isControlled = (attrs) => attrs.checkedId !== undefined && attrs.onchange !== undefined;
|
|
5770
6006
|
const isSelected = (id, selectedIds) => {
|
|
@@ -5847,10 +6083,18 @@ const Select = () => {
|
|
|
5847
6083
|
}
|
|
5848
6084
|
};
|
|
5849
6085
|
const closeDropdown = (e) => {
|
|
6086
|
+
console.log('select closeDropdown called');
|
|
6087
|
+
if (!state.isMultiple) {
|
|
6088
|
+
state.isOpen = false;
|
|
6089
|
+
return;
|
|
6090
|
+
}
|
|
5850
6091
|
const target = e.target;
|
|
5851
|
-
|
|
6092
|
+
// When inside modal, check both the select component AND the portaled dropdown
|
|
6093
|
+
const isClickInsideSelect = target.closest('.input-field.select-space');
|
|
6094
|
+
const isClickInsidePortalDropdown = state.isInsideModal && state.dropdownRef && (state.dropdownRef.contains(target) || target === state.dropdownRef);
|
|
6095
|
+
if (!isClickInsideSelect && !isClickInsidePortalDropdown) {
|
|
6096
|
+
console.log('select closeDropdown called: set state');
|
|
5852
6097
|
state.isOpen = false;
|
|
5853
|
-
m.redraw();
|
|
5854
6098
|
}
|
|
5855
6099
|
};
|
|
5856
6100
|
const getPortalStyles = (inputRef) => {
|
|
@@ -5858,13 +6102,21 @@ const Select = () => {
|
|
|
5858
6102
|
return {};
|
|
5859
6103
|
const rect = inputRef.getBoundingClientRect();
|
|
5860
6104
|
const viewportHeight = window.innerHeight;
|
|
6105
|
+
const spaceBelow = viewportHeight - rect.bottom;
|
|
6106
|
+
const spaceAbove = rect.top;
|
|
6107
|
+
// Choose whether to show above or below based on available space
|
|
6108
|
+
const showAbove = spaceBelow < 200 && spaceAbove > spaceBelow;
|
|
5861
6109
|
return {
|
|
5862
6110
|
position: 'fixed',
|
|
5863
|
-
top: `${rect.bottom}px`,
|
|
6111
|
+
top: showAbove ? 'auto' : `${rect.bottom}px`,
|
|
6112
|
+
bottom: showAbove ? `${viewportHeight - rect.top}px` : 'auto',
|
|
5864
6113
|
left: `${rect.left}px`,
|
|
5865
6114
|
width: `${rect.width}px`,
|
|
5866
6115
|
zIndex: 10000, // Higher than modal z-index
|
|
5867
|
-
maxHeight: `${
|
|
6116
|
+
maxHeight: showAbove ? `${spaceAbove - 20}px` : `${spaceBelow - 20}px`, // Leave 20px margin
|
|
6117
|
+
overflow: 'auto',
|
|
6118
|
+
display: 'block',
|
|
6119
|
+
opacity: 1,
|
|
5868
6120
|
};
|
|
5869
6121
|
};
|
|
5870
6122
|
const renderDropdownContent = (attrs, selectedIds, multiple, placeholder) => [
|
|
@@ -5872,15 +6124,10 @@ const Select = () => {
|
|
|
5872
6124
|
// Render ungrouped options first
|
|
5873
6125
|
attrs.options
|
|
5874
6126
|
.filter((option) => !option.group)
|
|
5875
|
-
.map((option) => m('li', Object.assign({
|
|
5876
|
-
? 'disabled'
|
|
5877
|
-
: state.focusedIndex === attrs.options.indexOf(option)
|
|
5878
|
-
? 'focused'
|
|
5879
|
-
: '' }, (option.disabled
|
|
6127
|
+
.map((option) => m('li', Object.assign({ class: option.disabled ? 'disabled' : state.focusedIndex === attrs.options.indexOf(option) ? 'focused' : '' }, (option.disabled
|
|
5880
6128
|
? {}
|
|
5881
6129
|
: {
|
|
5882
|
-
onclick: (
|
|
5883
|
-
e.stopPropagation();
|
|
6130
|
+
onclick: () => {
|
|
5884
6131
|
toggleOption(option.id, multiple, attrs);
|
|
5885
6132
|
},
|
|
5886
6133
|
})), [
|
|
@@ -5910,8 +6157,8 @@ const Select = () => {
|
|
|
5910
6157
|
return groups;
|
|
5911
6158
|
}, {}))
|
|
5912
6159
|
.map(([groupName, groupOptions]) => [
|
|
5913
|
-
m('li.optgroup', {
|
|
5914
|
-
...groupOptions.map((option) => m('li', Object.assign({
|
|
6160
|
+
m('li.optgroup', { tabindex: 0 }, m('span', groupName)),
|
|
6161
|
+
...groupOptions.map((option) => m('li', Object.assign({ class: `optgroup-option${option.disabled ? ' disabled' : ''}${isSelected(option.id, selectedIds) ? ' selected' : ''}${state.focusedIndex === attrs.options.indexOf(option) ? ' focused' : ''}` }, (option.disabled
|
|
5915
6162
|
? {}
|
|
5916
6163
|
: {
|
|
5917
6164
|
onclick: (e) => {
|
|
@@ -5938,23 +6185,20 @@ const Select = () => {
|
|
|
5938
6185
|
.reduce((acc, val) => acc.concat(val), []),
|
|
5939
6186
|
];
|
|
5940
6187
|
const updatePortalDropdown = (attrs, selectedIds, multiple, placeholder) => {
|
|
5941
|
-
var _a;
|
|
5942
6188
|
if (!state.isInsideModal)
|
|
5943
6189
|
return;
|
|
5944
|
-
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
m.render(portalElement, []);
|
|
5949
|
-
(_a = portalElement.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(portalElement);
|
|
5950
|
-
}
|
|
5951
|
-
return;
|
|
5952
|
-
}
|
|
5953
|
-
if (!portalElement) {
|
|
5954
|
-
portalElement = document.createElement('div');
|
|
5955
|
-
portalElement.id = state.dropdownId;
|
|
5956
|
-
document.body.appendChild(portalElement);
|
|
6190
|
+
// Clean up existing portal
|
|
6191
|
+
const existingPortal = document.getElementById(state.dropdownId);
|
|
6192
|
+
if (existingPortal) {
|
|
6193
|
+
existingPortal.remove();
|
|
5957
6194
|
}
|
|
6195
|
+
if (!state.isOpen || !state.inputRef)
|
|
6196
|
+
return;
|
|
6197
|
+
// Create portal element
|
|
6198
|
+
const portalElement = document.createElement('div');
|
|
6199
|
+
portalElement.id = state.dropdownId;
|
|
6200
|
+
document.body.appendChild(portalElement);
|
|
6201
|
+
// Create dropdown with proper positioning
|
|
5958
6202
|
const dropdownVnode = m('ul.dropdown-content.select-dropdown', {
|
|
5959
6203
|
tabindex: 0,
|
|
5960
6204
|
style: getPortalStyles(state.inputRef),
|
|
@@ -5965,6 +6209,7 @@ const Select = () => {
|
|
|
5965
6209
|
state.dropdownRef = null;
|
|
5966
6210
|
},
|
|
5967
6211
|
}, renderDropdownContent(attrs, selectedIds, multiple, placeholder));
|
|
6212
|
+
// Render to portal
|
|
5968
6213
|
m.render(portalElement, dropdownVnode);
|
|
5969
6214
|
};
|
|
5970
6215
|
return {
|
|
@@ -6007,7 +6252,8 @@ const Select = () => {
|
|
|
6007
6252
|
view: ({ attrs }) => {
|
|
6008
6253
|
var _a;
|
|
6009
6254
|
const controlled = isControlled(attrs);
|
|
6010
|
-
const { disabled } = attrs;
|
|
6255
|
+
const { newRow, className = 'col s12', key, options, multiple = false, label, helperText, placeholder = '', isMandatory, iconName, style, disabled, } = attrs;
|
|
6256
|
+
state.isMultiple = multiple;
|
|
6011
6257
|
// Get selected IDs from props or internal state
|
|
6012
6258
|
let selectedIds;
|
|
6013
6259
|
if (controlled) {
|
|
@@ -6023,7 +6269,6 @@ const Select = () => {
|
|
|
6023
6269
|
// Interactive uncontrolled: use internal state
|
|
6024
6270
|
selectedIds = state.internalSelectedIds;
|
|
6025
6271
|
}
|
|
6026
|
-
const { newRow, className = 'col s12', key, options, multiple = false, label, helperText, placeholder = '', isMandatory, iconName, style, } = attrs;
|
|
6027
6272
|
const finalClassName = newRow ? `${className} clear` : className;
|
|
6028
6273
|
const selectedOptions = options.filter((opt) => isSelected(opt.id, selectedIds));
|
|
6029
6274
|
// Update portal dropdown when inside modal
|
|
@@ -6060,7 +6305,8 @@ const Select = () => {
|
|
|
6060
6305
|
},
|
|
6061
6306
|
}),
|
|
6062
6307
|
// Dropdown Menu - render inline only when NOT inside modal
|
|
6063
|
-
state.isOpen &&
|
|
6308
|
+
state.isOpen &&
|
|
6309
|
+
!state.isInsideModal &&
|
|
6064
6310
|
m('ul.dropdown-content.select-dropdown', {
|
|
6065
6311
|
tabindex: 0,
|
|
6066
6312
|
oncreate: ({ dom }) => {
|
|
@@ -6218,7 +6464,6 @@ const Tabs = () => {
|
|
|
6218
6464
|
}
|
|
6219
6465
|
state.isDragging = false;
|
|
6220
6466
|
state.translateX = 0;
|
|
6221
|
-
// m.redraw();
|
|
6222
6467
|
};
|
|
6223
6468
|
/** Initialize active tab - selectedTabId takes precedence, next active property or first available tab */
|
|
6224
6469
|
const setActiveTabId = (anchoredTabs, selectedTabId) => {
|
|
@@ -6245,7 +6490,6 @@ const Tabs = () => {
|
|
|
6245
6490
|
},
|
|
6246
6491
|
oncreate: () => {
|
|
6247
6492
|
updateIndicator();
|
|
6248
|
-
m.redraw();
|
|
6249
6493
|
},
|
|
6250
6494
|
view: ({ attrs }) => {
|
|
6251
6495
|
const { tabWidth, tabs, className, style, swipeable = false } = attrs;
|
|
@@ -6379,7 +6623,6 @@ const SearchSelect = () => {
|
|
|
6379
6623
|
else {
|
|
6380
6624
|
// Click outside, close dropdown
|
|
6381
6625
|
state.isOpen = false;
|
|
6382
|
-
m.redraw();
|
|
6383
6626
|
}
|
|
6384
6627
|
};
|
|
6385
6628
|
// Handle keyboard navigation
|
|
@@ -6614,9 +6857,7 @@ const SearchSelect = () => {
|
|
|
6614
6857
|
]),
|
|
6615
6858
|
// No options found message or list of options
|
|
6616
6859
|
...(filteredOptions.length === 0 && !showAddNew
|
|
6617
|
-
? [
|
|
6618
|
-
m('li.search-select-no-options', texts.noOptionsFound),
|
|
6619
|
-
]
|
|
6860
|
+
? [m('li.search-select-no-options', texts.noOptionsFound)]
|
|
6620
6861
|
: []),
|
|
6621
6862
|
// Add new option item
|
|
6622
6863
|
...(showAddNew
|
|
@@ -9015,6 +9256,7 @@ exports.FlatButton = FlatButton;
|
|
|
9015
9256
|
exports.FloatingActionButton = FloatingActionButton;
|
|
9016
9257
|
exports.HelperText = HelperText;
|
|
9017
9258
|
exports.Icon = Icon;
|
|
9259
|
+
exports.IconButton = IconButton;
|
|
9018
9260
|
exports.ImageList = ImageList;
|
|
9019
9261
|
exports.InputCheckbox = InputCheckbox;
|
|
9020
9262
|
exports.Label = Label;
|