mithril-materialized 2.0.0-beta.11 → 2.0.0-beta.14
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 +58 -2
- package/dist/components.css +595 -0
- package/dist/forms.css +325 -0
- package/dist/icon.d.ts +2 -2
- package/dist/index.css +607 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.esm.js +1271 -157
- package/dist/index.js +1274 -156
- package/dist/index.min.css +1 -1
- package/dist/index.umd.js +1274 -156
- package/dist/input-options.d.ts +18 -4
- package/dist/material-icon.d.ts +3 -0
- package/dist/range-slider.d.ts +4 -0
- package/dist/treeview.d.ts +39 -0
- package/package.json +1 -1
- package/sass/components/_treeview.scss +353 -0
- package/sass/components/forms/_forms.scss +1 -1
- package/sass/components/forms/_range-enhanced.scss +393 -0
- package/sass/materialize.scss +2 -0
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:
|
|
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),
|
|
@@ -2180,6 +2192,12 @@ const InputField = (type, defaultClass = '') => () => {
|
|
|
2180
2192
|
isValid: true,
|
|
2181
2193
|
active: false,
|
|
2182
2194
|
inputElement: null,
|
|
2195
|
+
// Range-specific state
|
|
2196
|
+
rangeMinValue: undefined,
|
|
2197
|
+
rangeMaxValue: undefined,
|
|
2198
|
+
singleValue: undefined,
|
|
2199
|
+
isDragging: false,
|
|
2200
|
+
activeThumb: null,
|
|
2183
2201
|
};
|
|
2184
2202
|
// let labelManager: { updateLabelState: () => void; cleanup: () => void } | null = null;
|
|
2185
2203
|
// let lengthUpdateHandler: (() => void) | null = null;
|
|
@@ -2205,19 +2223,425 @@ const InputField = (type, defaultClass = '') => () => {
|
|
|
2205
2223
|
state.hasInteracted = length > 0;
|
|
2206
2224
|
}
|
|
2207
2225
|
};
|
|
2226
|
+
// Range slider helper functions
|
|
2227
|
+
const getPercentage = (value, min, max) => {
|
|
2228
|
+
return ((value - min) / (max - min)) * 100;
|
|
2229
|
+
};
|
|
2230
|
+
const updateRangeValues = (minValue, maxValue, attrs, immediate = false) => {
|
|
2231
|
+
// Ensure min doesn't exceed max and vice versa
|
|
2232
|
+
if (minValue > maxValue)
|
|
2233
|
+
minValue = maxValue;
|
|
2234
|
+
if (maxValue < minValue)
|
|
2235
|
+
maxValue = minValue;
|
|
2236
|
+
state.rangeMinValue = minValue;
|
|
2237
|
+
state.rangeMaxValue = maxValue;
|
|
2238
|
+
// Call oninput for immediate feedback or onchange for final changes
|
|
2239
|
+
if (immediate && attrs.oninput) {
|
|
2240
|
+
attrs.oninput(minValue, maxValue);
|
|
2241
|
+
}
|
|
2242
|
+
else if (!immediate && attrs.onchange) {
|
|
2243
|
+
attrs.onchange(minValue, maxValue);
|
|
2244
|
+
}
|
|
2245
|
+
};
|
|
2246
|
+
// Render function for single range slider with tooltip
|
|
2247
|
+
const renderSingleRangeWithTooltip = (attrs, state, cn, style, iconName, id, label, isMandatory, helperText) => {
|
|
2248
|
+
const { min = 0, max = 100, step = 1, initialValue, vertical = false, showValue = false, height = '200px', disabled = false, oninput, onchange, } = attrs;
|
|
2249
|
+
// Initialize single range value
|
|
2250
|
+
const currentValue = initialValue !== undefined ? initialValue : state.singleValue || min;
|
|
2251
|
+
if (state.singleValue === undefined) {
|
|
2252
|
+
state.singleValue = currentValue;
|
|
2253
|
+
}
|
|
2254
|
+
const percentage = getPercentage(state.singleValue, min, max);
|
|
2255
|
+
// Only keep dynamic styles as inline, use CSS classes for static styles
|
|
2256
|
+
const containerStyle = vertical ? { height } : {};
|
|
2257
|
+
const progressStyle = vertical
|
|
2258
|
+
? {
|
|
2259
|
+
height: `${percentage}%`,
|
|
2260
|
+
}
|
|
2261
|
+
: {
|
|
2262
|
+
width: `${percentage}%`,
|
|
2263
|
+
};
|
|
2264
|
+
const thumbStyle = vertical
|
|
2265
|
+
? {
|
|
2266
|
+
bottom: `${percentage}%`,
|
|
2267
|
+
}
|
|
2268
|
+
: {
|
|
2269
|
+
left: `${percentage}%`,
|
|
2270
|
+
marginLeft: '-10px', // Half of thumb size (20px)
|
|
2271
|
+
};
|
|
2272
|
+
const updateSingleValue = (newValue, immediate = false) => {
|
|
2273
|
+
state.singleValue = newValue;
|
|
2274
|
+
if (immediate && oninput) {
|
|
2275
|
+
oninput(newValue);
|
|
2276
|
+
}
|
|
2277
|
+
else if (!immediate && onchange) {
|
|
2278
|
+
onchange(newValue);
|
|
2279
|
+
}
|
|
2280
|
+
};
|
|
2281
|
+
const handleMouseDown = (e) => {
|
|
2282
|
+
if (disabled)
|
|
2283
|
+
return;
|
|
2284
|
+
e.preventDefault();
|
|
2285
|
+
state.isDragging = true;
|
|
2286
|
+
// Get container reference from the current target's parent
|
|
2287
|
+
const thumbElement = e.currentTarget;
|
|
2288
|
+
const container = thumbElement.parentElement;
|
|
2289
|
+
if (!container)
|
|
2290
|
+
return;
|
|
2291
|
+
const handleMouseMove = (e) => {
|
|
2292
|
+
if (!state.isDragging || !container)
|
|
2293
|
+
return;
|
|
2294
|
+
const rect = container.getBoundingClientRect();
|
|
2295
|
+
let percentage;
|
|
2296
|
+
if (vertical) {
|
|
2297
|
+
percentage = ((rect.bottom - e.clientY) / rect.height) * 100;
|
|
2298
|
+
}
|
|
2299
|
+
else {
|
|
2300
|
+
percentage = ((e.clientX - rect.left) / rect.width) * 100;
|
|
2301
|
+
}
|
|
2302
|
+
percentage = Math.max(0, Math.min(100, percentage));
|
|
2303
|
+
const value = min + (percentage / 100) * (max - min);
|
|
2304
|
+
const steppedValue = Math.round(value / step) * step;
|
|
2305
|
+
updateSingleValue(steppedValue, true);
|
|
2306
|
+
// Redraw to update the UI
|
|
2307
|
+
m.redraw();
|
|
2308
|
+
};
|
|
2309
|
+
const handleMouseUp = () => {
|
|
2310
|
+
state.isDragging = false;
|
|
2311
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
2312
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
|
2313
|
+
// Fire onchange when dragging ends
|
|
2314
|
+
updateSingleValue(state.singleValue, false);
|
|
2315
|
+
};
|
|
2316
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
2317
|
+
document.addEventListener('mouseup', handleMouseUp);
|
|
2318
|
+
};
|
|
2319
|
+
const fieldClass = vertical ? 'range-field vertical' : 'range-field';
|
|
2320
|
+
const orientation = vertical ? 'vertical' : 'horizontal';
|
|
2321
|
+
return m('.input-field', { className: cn, style }, [
|
|
2322
|
+
iconName ? m('i.material-icons.prefix', iconName) : undefined,
|
|
2323
|
+
// Hidden input for label association and accessibility
|
|
2324
|
+
m('input[type=range]', {
|
|
2325
|
+
id,
|
|
2326
|
+
value: state.singleValue,
|
|
2327
|
+
min,
|
|
2328
|
+
max,
|
|
2329
|
+
step,
|
|
2330
|
+
style: { display: 'none' },
|
|
2331
|
+
disabled,
|
|
2332
|
+
tabindex: -1,
|
|
2333
|
+
}),
|
|
2334
|
+
m('div', { class: fieldClass, style: containerStyle }, [
|
|
2335
|
+
m(`.single-range-slider.${orientation}`, {
|
|
2336
|
+
tabindex: disabled ? -1 : 0,
|
|
2337
|
+
role: 'slider',
|
|
2338
|
+
'aria-valuemin': min,
|
|
2339
|
+
'aria-valuemax': max,
|
|
2340
|
+
'aria-valuenow': state.singleValue,
|
|
2341
|
+
'aria-label': label || 'Range slider',
|
|
2342
|
+
onclick: (e) => {
|
|
2343
|
+
// Focus the slider when clicked
|
|
2344
|
+
e.currentTarget.focus();
|
|
2345
|
+
},
|
|
2346
|
+
onkeydown: (e) => {
|
|
2347
|
+
if (disabled)
|
|
2348
|
+
return;
|
|
2349
|
+
let newValue = state.singleValue;
|
|
2350
|
+
switch (e.key) {
|
|
2351
|
+
case 'ArrowLeft':
|
|
2352
|
+
case 'ArrowDown':
|
|
2353
|
+
e.preventDefault();
|
|
2354
|
+
newValue = Math.max(min, newValue - step);
|
|
2355
|
+
updateSingleValue(newValue, false);
|
|
2356
|
+
m.redraw();
|
|
2357
|
+
break;
|
|
2358
|
+
case 'ArrowRight':
|
|
2359
|
+
case 'ArrowUp':
|
|
2360
|
+
e.preventDefault();
|
|
2361
|
+
newValue = Math.min(max, newValue + step);
|
|
2362
|
+
updateSingleValue(newValue, false);
|
|
2363
|
+
m.redraw();
|
|
2364
|
+
break;
|
|
2365
|
+
case 'Home':
|
|
2366
|
+
e.preventDefault();
|
|
2367
|
+
updateSingleValue(min, false);
|
|
2368
|
+
m.redraw();
|
|
2369
|
+
break;
|
|
2370
|
+
case 'End':
|
|
2371
|
+
e.preventDefault();
|
|
2372
|
+
updateSingleValue(max, false);
|
|
2373
|
+
m.redraw();
|
|
2374
|
+
break;
|
|
2375
|
+
}
|
|
2376
|
+
},
|
|
2377
|
+
}, [
|
|
2378
|
+
// Track
|
|
2379
|
+
m(`.track.${orientation}`),
|
|
2380
|
+
// Progress
|
|
2381
|
+
m(`.range-progress.${orientation}`, { style: progressStyle }),
|
|
2382
|
+
// Thumb
|
|
2383
|
+
m(`.thumb.${orientation}`, {
|
|
2384
|
+
style: thumbStyle,
|
|
2385
|
+
onmousedown: handleMouseDown,
|
|
2386
|
+
}, showValue
|
|
2387
|
+
? m(`.value-tooltip.${vertical ? 'right' : 'top'}`, state.singleValue.toFixed(0))
|
|
2388
|
+
: null),
|
|
2389
|
+
]),
|
|
2390
|
+
]),
|
|
2391
|
+
label
|
|
2392
|
+
? m(Label, {
|
|
2393
|
+
label,
|
|
2394
|
+
id,
|
|
2395
|
+
isMandatory,
|
|
2396
|
+
isActive: true, // Range sliders always have active labels
|
|
2397
|
+
})
|
|
2398
|
+
: null,
|
|
2399
|
+
helperText ? m(HelperText, { helperText }) : null,
|
|
2400
|
+
]);
|
|
2401
|
+
};
|
|
2402
|
+
// Render function for minmax range slider
|
|
2403
|
+
const renderMinMaxRange = (attrs, state, cn, style, iconName, id, label, isMandatory, helperText) => {
|
|
2404
|
+
const { min = 0, max = 100, step = 1, minValue, maxValue, vertical = false, showValue = false, height = '200px', disabled = false, } = attrs;
|
|
2405
|
+
// Initialize range values
|
|
2406
|
+
const currentMinValue = minValue !== undefined ? minValue : attrs.minValue || min;
|
|
2407
|
+
const currentMaxValue = maxValue !== undefined ? maxValue : attrs.maxValue || max;
|
|
2408
|
+
if (state.rangeMinValue === undefined || state.rangeMaxValue === undefined) {
|
|
2409
|
+
state.rangeMinValue = currentMinValue;
|
|
2410
|
+
state.rangeMaxValue = currentMaxValue;
|
|
2411
|
+
}
|
|
2412
|
+
// Initialize active thumb if not set
|
|
2413
|
+
if (state.activeThumb === null) {
|
|
2414
|
+
state.activeThumb = 'min';
|
|
2415
|
+
}
|
|
2416
|
+
const minPercentage = getPercentage(state.rangeMinValue, min, max);
|
|
2417
|
+
const maxPercentage = getPercentage(state.rangeMaxValue, min, max);
|
|
2418
|
+
// Only keep dynamic styles as inline, use CSS classes for static styles
|
|
2419
|
+
const containerStyle = vertical ? { height } : {};
|
|
2420
|
+
const rangeStyle = vertical
|
|
2421
|
+
? {
|
|
2422
|
+
bottom: `${minPercentage}%`,
|
|
2423
|
+
height: `${maxPercentage - minPercentage}%`,
|
|
2424
|
+
}
|
|
2425
|
+
: {
|
|
2426
|
+
left: `${minPercentage}%`,
|
|
2427
|
+
width: `${maxPercentage - minPercentage}%`,
|
|
2428
|
+
};
|
|
2429
|
+
// Only keep dynamic positioning and z-index as inline styles
|
|
2430
|
+
const createThumbStyle = (percentage, isActive) => vertical
|
|
2431
|
+
? {
|
|
2432
|
+
bottom: `${percentage}%`,
|
|
2433
|
+
zIndex: isActive ? 10 : 5,
|
|
2434
|
+
}
|
|
2435
|
+
: {
|
|
2436
|
+
left: `${percentage}%`,
|
|
2437
|
+
marginLeft: '-10px', // Half of thumb size (20px)
|
|
2438
|
+
zIndex: isActive ? 10 : 5,
|
|
2439
|
+
};
|
|
2440
|
+
const handleMouseDown = (thumb) => (e) => {
|
|
2441
|
+
if (disabled)
|
|
2442
|
+
return;
|
|
2443
|
+
e.preventDefault();
|
|
2444
|
+
state.isDragging = true;
|
|
2445
|
+
state.activeThumb = thumb;
|
|
2446
|
+
// Get container reference from the current target's parent
|
|
2447
|
+
const thumbElement = e.currentTarget;
|
|
2448
|
+
const container = thumbElement.parentElement;
|
|
2449
|
+
if (!container)
|
|
2450
|
+
return;
|
|
2451
|
+
const handleMouseMove = (e) => {
|
|
2452
|
+
if (!state.isDragging || !container)
|
|
2453
|
+
return;
|
|
2454
|
+
const rect = container.getBoundingClientRect();
|
|
2455
|
+
let percentage;
|
|
2456
|
+
if (vertical) {
|
|
2457
|
+
percentage = ((rect.bottom - e.clientY) / rect.height) * 100;
|
|
2458
|
+
}
|
|
2459
|
+
else {
|
|
2460
|
+
percentage = ((e.clientX - rect.left) / rect.width) * 100;
|
|
2461
|
+
}
|
|
2462
|
+
percentage = Math.max(0, Math.min(100, percentage));
|
|
2463
|
+
const value = min + (percentage / 100) * (max - min);
|
|
2464
|
+
const steppedValue = Math.round(value / step) * step;
|
|
2465
|
+
if (thumb === 'min') {
|
|
2466
|
+
updateRangeValues(Math.min(steppedValue, state.rangeMaxValue), state.rangeMaxValue, attrs, true);
|
|
2467
|
+
}
|
|
2468
|
+
else {
|
|
2469
|
+
updateRangeValues(state.rangeMinValue, Math.max(steppedValue, state.rangeMinValue), attrs, true);
|
|
2470
|
+
}
|
|
2471
|
+
// Redraw to update the UI
|
|
2472
|
+
m.redraw();
|
|
2473
|
+
};
|
|
2474
|
+
const handleMouseUp = () => {
|
|
2475
|
+
state.isDragging = false;
|
|
2476
|
+
state.activeThumb = null;
|
|
2477
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
2478
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
|
2479
|
+
// Fire onchange when dragging ends
|
|
2480
|
+
updateRangeValues(state.rangeMinValue, state.rangeMaxValue, attrs, false);
|
|
2481
|
+
};
|
|
2482
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
2483
|
+
document.addEventListener('mouseup', handleMouseUp);
|
|
2484
|
+
};
|
|
2485
|
+
const fieldClass = vertical ? 'range-field vertical' : 'range-field';
|
|
2486
|
+
const orientation = vertical ? 'vertical' : 'horizontal';
|
|
2487
|
+
return m('.input-field', { className: cn, style }, [
|
|
2488
|
+
iconName ? m('i.material-icons.prefix', iconName) : undefined,
|
|
2489
|
+
// Hidden inputs for label association and accessibility
|
|
2490
|
+
m('input[type=range]', {
|
|
2491
|
+
id,
|
|
2492
|
+
value: state.rangeMinValue,
|
|
2493
|
+
min,
|
|
2494
|
+
max,
|
|
2495
|
+
step,
|
|
2496
|
+
style: { display: 'none' },
|
|
2497
|
+
disabled,
|
|
2498
|
+
tabindex: -1,
|
|
2499
|
+
}),
|
|
2500
|
+
m('input[type=range]', {
|
|
2501
|
+
id: `${id}_max`,
|
|
2502
|
+
value: state.rangeMaxValue,
|
|
2503
|
+
min,
|
|
2504
|
+
max,
|
|
2505
|
+
step,
|
|
2506
|
+
style: { display: 'none' },
|
|
2507
|
+
disabled,
|
|
2508
|
+
tabindex: -1,
|
|
2509
|
+
}),
|
|
2510
|
+
m(`.${fieldClass}`, [
|
|
2511
|
+
m(`.double-range-slider.${orientation}`, {
|
|
2512
|
+
style: containerStyle,
|
|
2513
|
+
tabindex: disabled ? -1 : 0,
|
|
2514
|
+
role: 'slider',
|
|
2515
|
+
'aria-valuemin': min,
|
|
2516
|
+
'aria-valuemax': max,
|
|
2517
|
+
'aria-valuenow': state.rangeMinValue,
|
|
2518
|
+
'aria-valuetext': `${state.rangeMinValue} to ${state.rangeMaxValue}`,
|
|
2519
|
+
'aria-label': label || 'Range slider',
|
|
2520
|
+
onclick: (e) => {
|
|
2521
|
+
// Focus the slider when clicked
|
|
2522
|
+
e.currentTarget.focus();
|
|
2523
|
+
},
|
|
2524
|
+
onkeydown: (e) => {
|
|
2525
|
+
if (disabled)
|
|
2526
|
+
return;
|
|
2527
|
+
let newMinValue = state.rangeMinValue;
|
|
2528
|
+
let newMaxValue = state.rangeMaxValue;
|
|
2529
|
+
const activeThumb = state.activeThumb || 'min';
|
|
2530
|
+
switch (e.key) {
|
|
2531
|
+
case 'ArrowLeft':
|
|
2532
|
+
case 'ArrowDown':
|
|
2533
|
+
e.preventDefault();
|
|
2534
|
+
if (activeThumb === 'min') {
|
|
2535
|
+
newMinValue = Math.max(min, newMinValue - step);
|
|
2536
|
+
updateRangeValues(newMinValue, newMaxValue, attrs, false);
|
|
2537
|
+
}
|
|
2538
|
+
else {
|
|
2539
|
+
newMaxValue = Math.max(newMinValue, newMaxValue - step);
|
|
2540
|
+
updateRangeValues(newMinValue, newMaxValue, attrs, false);
|
|
2541
|
+
}
|
|
2542
|
+
m.redraw();
|
|
2543
|
+
break;
|
|
2544
|
+
case 'ArrowRight':
|
|
2545
|
+
case 'ArrowUp':
|
|
2546
|
+
e.preventDefault();
|
|
2547
|
+
if (activeThumb === 'min') {
|
|
2548
|
+
newMinValue = Math.min(newMaxValue, newMinValue + step);
|
|
2549
|
+
updateRangeValues(newMinValue, newMaxValue, attrs, false);
|
|
2550
|
+
}
|
|
2551
|
+
else {
|
|
2552
|
+
newMaxValue = Math.min(max, newMaxValue + step);
|
|
2553
|
+
updateRangeValues(newMinValue, newMaxValue, attrs, false);
|
|
2554
|
+
}
|
|
2555
|
+
m.redraw();
|
|
2556
|
+
break;
|
|
2557
|
+
// Remove Tab case - let normal tab navigation work
|
|
2558
|
+
// Users can click on specific thumbs to activate them
|
|
2559
|
+
case 'Home':
|
|
2560
|
+
e.preventDefault();
|
|
2561
|
+
if (activeThumb === 'min') {
|
|
2562
|
+
updateRangeValues(min, newMaxValue, attrs, false);
|
|
2563
|
+
}
|
|
2564
|
+
else {
|
|
2565
|
+
updateRangeValues(newMinValue, newMinValue, attrs, false);
|
|
2566
|
+
}
|
|
2567
|
+
m.redraw();
|
|
2568
|
+
break;
|
|
2569
|
+
case 'End':
|
|
2570
|
+
e.preventDefault();
|
|
2571
|
+
if (activeThumb === 'min') {
|
|
2572
|
+
updateRangeValues(newMaxValue, newMaxValue, attrs, false);
|
|
2573
|
+
}
|
|
2574
|
+
else {
|
|
2575
|
+
updateRangeValues(newMinValue, max, attrs, false);
|
|
2576
|
+
}
|
|
2577
|
+
m.redraw();
|
|
2578
|
+
break;
|
|
2579
|
+
}
|
|
2580
|
+
},
|
|
2581
|
+
}, [
|
|
2582
|
+
// Track
|
|
2583
|
+
m(`.track.${orientation}`),
|
|
2584
|
+
// Range
|
|
2585
|
+
m(`.range.${orientation}`, { style: rangeStyle }),
|
|
2586
|
+
// Min thumb
|
|
2587
|
+
m(`.thumb.${orientation}.min-thumb${state.activeThumb === 'min' ? '.active' : ''}`, {
|
|
2588
|
+
style: createThumbStyle(minPercentage, state.activeThumb === 'min'),
|
|
2589
|
+
onmousedown: handleMouseDown('min'),
|
|
2590
|
+
onclick: () => {
|
|
2591
|
+
state.activeThumb = 'min';
|
|
2592
|
+
m.redraw();
|
|
2593
|
+
},
|
|
2594
|
+
}, showValue ? m(`.value.${orientation}`, state.rangeMinValue.toFixed(0)) : null),
|
|
2595
|
+
// Max thumb
|
|
2596
|
+
m(`.thumb.${orientation}.max-thumb${state.activeThumb === 'max' ? '.active' : ''}`, {
|
|
2597
|
+
style: createThumbStyle(maxPercentage, state.activeThumb === 'max'),
|
|
2598
|
+
onmousedown: handleMouseDown('max'),
|
|
2599
|
+
onclick: () => {
|
|
2600
|
+
state.activeThumb = 'max';
|
|
2601
|
+
m.redraw();
|
|
2602
|
+
},
|
|
2603
|
+
}, showValue ? m(`.value.${orientation}`, state.rangeMaxValue.toFixed(0)) : null),
|
|
2604
|
+
]),
|
|
2605
|
+
]),
|
|
2606
|
+
label
|
|
2607
|
+
? m(Label, {
|
|
2608
|
+
label,
|
|
2609
|
+
id,
|
|
2610
|
+
isMandatory,
|
|
2611
|
+
isActive: true, // Range sliders always have active labels
|
|
2612
|
+
})
|
|
2613
|
+
: null,
|
|
2614
|
+
helperText ? m(HelperText, { helperText }) : null,
|
|
2615
|
+
]);
|
|
2616
|
+
};
|
|
2208
2617
|
return {
|
|
2209
2618
|
view: ({ attrs }) => {
|
|
2210
2619
|
var _a;
|
|
2211
2620
|
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
2621
|
// const attributes = toAttrs(params);
|
|
2213
|
-
const cn = [newRow ? 'clear' : '', defaultClass, className].filter(Boolean).join(' ').trim();
|
|
2622
|
+
const cn = [newRow ? 'clear' : '', defaultClass, className].filter(Boolean).join(' ').trim() || undefined;
|
|
2214
2623
|
const isActive = state.active || ((_a = state.inputElement) === null || _a === void 0 ? void 0 : _a.value) || placeholder || type === 'color' || type === 'range'
|
|
2215
2624
|
? true
|
|
2216
2625
|
: false;
|
|
2626
|
+
// Special rendering for minmax range sliders
|
|
2627
|
+
if (type === 'range' && attrs.minmax) {
|
|
2628
|
+
return renderMinMaxRange(attrs, state, cn, style, iconName, id, label, isMandatory, helperText);
|
|
2629
|
+
}
|
|
2630
|
+
// Special rendering for single range sliders with tooltips
|
|
2631
|
+
if (type === 'range' && attrs.showValue) {
|
|
2632
|
+
return renderSingleRangeWithTooltip(attrs, state, cn, style, iconName, id, label, isMandatory, helperText);
|
|
2633
|
+
}
|
|
2217
2634
|
return m('.input-field', { className: cn, style }, [
|
|
2218
2635
|
iconName ? m('i.material-icons.prefix', iconName) : undefined,
|
|
2219
2636
|
m('input.validate', Object.assign(Object.assign({}, params), { type, tabindex: 0, id,
|
|
2220
|
-
placeholder,
|
|
2637
|
+
placeholder, class: type === 'range' && attrs.vertical ? 'range-slider vertical' : undefined, style: type === 'range' && attrs.vertical
|
|
2638
|
+
? {
|
|
2639
|
+
height: attrs.height || '200px',
|
|
2640
|
+
width: '6px',
|
|
2641
|
+
writingMode: 'vertical-lr',
|
|
2642
|
+
direction: 'rtl',
|
|
2643
|
+
}
|
|
2644
|
+
: undefined,
|
|
2221
2645
|
// attributes,
|
|
2222
2646
|
oncreate: ({ dom }) => {
|
|
2223
2647
|
const input = (state.inputElement = dom);
|
|
@@ -2233,7 +2657,7 @@ const InputField = (type, defaultClass = '') => () => {
|
|
|
2233
2657
|
state.currentLength = input.value.length; // Initial count
|
|
2234
2658
|
}
|
|
2235
2659
|
// Range input functionality
|
|
2236
|
-
if (type === 'range') {
|
|
2660
|
+
if (type === 'range' && !attrs.minmax) {
|
|
2237
2661
|
const updateThumb = () => {
|
|
2238
2662
|
const value = input.value;
|
|
2239
2663
|
const min = input.min || '0';
|
|
@@ -2486,7 +2910,7 @@ const Options = () => {
|
|
|
2486
2910
|
callback(checkedIds);
|
|
2487
2911
|
}
|
|
2488
2912
|
: undefined;
|
|
2489
|
-
const cn = [newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim();
|
|
2913
|
+
const cn = [newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim() || undefined;
|
|
2490
2914
|
const optionsContent = layout === 'horizontal'
|
|
2491
2915
|
? m('div.grid-container', options.map((option) => m(InputCheckbox, {
|
|
2492
2916
|
disabled: disabled || option.disabled,
|
|
@@ -3357,6 +3781,423 @@ const FloatingActionButton = () => {
|
|
|
3357
3781
|
};
|
|
3358
3782
|
};
|
|
3359
3783
|
|
|
3784
|
+
// Utility functions
|
|
3785
|
+
const getPercentage = (value, min, max) => {
|
|
3786
|
+
return ((value - min) / (max - min)) * 100;
|
|
3787
|
+
};
|
|
3788
|
+
const updateRangeValues = (minValue, maxValue, attrs, state, immediate) => {
|
|
3789
|
+
// Ensure min doesn't exceed max and vice versa
|
|
3790
|
+
if (minValue > maxValue)
|
|
3791
|
+
minValue = maxValue;
|
|
3792
|
+
if (maxValue < minValue)
|
|
3793
|
+
maxValue = minValue;
|
|
3794
|
+
state.rangeMinValue = minValue;
|
|
3795
|
+
state.rangeMaxValue = maxValue;
|
|
3796
|
+
// Call oninput for immediate feedback or onchange for final changes
|
|
3797
|
+
if (immediate && attrs.oninput) {
|
|
3798
|
+
attrs.oninput(minValue, maxValue);
|
|
3799
|
+
}
|
|
3800
|
+
else if (!immediate && attrs.onchange) {
|
|
3801
|
+
attrs.onchange(minValue, maxValue);
|
|
3802
|
+
}
|
|
3803
|
+
};
|
|
3804
|
+
// Single Range Slider with Tooltip
|
|
3805
|
+
const renderSingleRangeWithTooltip = (attrs, state, cn, style, iconName, id, label, isMandatory, helperText) => {
|
|
3806
|
+
const { min = 0, max = 100, step = 1, initialValue, vertical = false, showValue = false, height = '200px', disabled = false, tooltipPos = 'top', oninput, onchange, } = attrs;
|
|
3807
|
+
// Initialize single range value
|
|
3808
|
+
const currentValue = initialValue !== undefined ? initialValue : state.singleValue || min;
|
|
3809
|
+
if (state.singleValue === undefined) {
|
|
3810
|
+
state.singleValue = currentValue;
|
|
3811
|
+
}
|
|
3812
|
+
const percentage = getPercentage(state.singleValue, min, max);
|
|
3813
|
+
// Only keep dynamic styles as inline, use CSS classes for static styles
|
|
3814
|
+
const containerStyle = vertical ? { height } : {};
|
|
3815
|
+
const progressStyle = vertical
|
|
3816
|
+
? {
|
|
3817
|
+
height: `${percentage}%`,
|
|
3818
|
+
}
|
|
3819
|
+
: {
|
|
3820
|
+
width: `${percentage}%`,
|
|
3821
|
+
};
|
|
3822
|
+
const thumbStyle = vertical
|
|
3823
|
+
? {
|
|
3824
|
+
bottom: `${percentage}%`,
|
|
3825
|
+
}
|
|
3826
|
+
: {
|
|
3827
|
+
left: `${percentage}%`,
|
|
3828
|
+
marginLeft: '-10px', // Half of thumb size (20px)
|
|
3829
|
+
};
|
|
3830
|
+
const updateSingleValue = (newValue, immediate = false) => {
|
|
3831
|
+
state.singleValue = newValue;
|
|
3832
|
+
if (immediate && oninput) {
|
|
3833
|
+
oninput(newValue);
|
|
3834
|
+
}
|
|
3835
|
+
else if (!immediate && onchange) {
|
|
3836
|
+
onchange(newValue);
|
|
3837
|
+
}
|
|
3838
|
+
};
|
|
3839
|
+
const handleMouseDown = (e) => {
|
|
3840
|
+
if (disabled)
|
|
3841
|
+
return;
|
|
3842
|
+
e.preventDefault();
|
|
3843
|
+
state.isDragging = true;
|
|
3844
|
+
// Get container reference from the current target's parent
|
|
3845
|
+
const thumbElement = e.currentTarget;
|
|
3846
|
+
const container = thumbElement.parentElement;
|
|
3847
|
+
if (!container)
|
|
3848
|
+
return;
|
|
3849
|
+
const handleMouseMove = (e) => {
|
|
3850
|
+
if (!state.isDragging || !container)
|
|
3851
|
+
return;
|
|
3852
|
+
const rect = container.getBoundingClientRect();
|
|
3853
|
+
let percentage;
|
|
3854
|
+
if (vertical) {
|
|
3855
|
+
percentage = ((rect.bottom - e.clientY) / rect.height) * 100;
|
|
3856
|
+
}
|
|
3857
|
+
else {
|
|
3858
|
+
percentage = ((e.clientX - rect.left) / rect.width) * 100;
|
|
3859
|
+
}
|
|
3860
|
+
percentage = Math.max(0, Math.min(100, percentage));
|
|
3861
|
+
const value = min + (percentage / 100) * (max - min);
|
|
3862
|
+
const steppedValue = Math.round(value / step) * step;
|
|
3863
|
+
updateSingleValue(steppedValue, true);
|
|
3864
|
+
// Redraw to update the UI during drag
|
|
3865
|
+
m.redraw();
|
|
3866
|
+
};
|
|
3867
|
+
const handleMouseUp = () => {
|
|
3868
|
+
state.isDragging = false;
|
|
3869
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
3870
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
|
3871
|
+
// Fire onchange when dragging ends
|
|
3872
|
+
updateSingleValue(state.singleValue, false);
|
|
3873
|
+
};
|
|
3874
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
3875
|
+
document.addEventListener('mouseup', handleMouseUp);
|
|
3876
|
+
};
|
|
3877
|
+
const fieldClass = vertical ? 'range-field vertical' : 'range-field';
|
|
3878
|
+
const orientation = vertical ? 'vertical' : 'horizontal';
|
|
3879
|
+
// Determine tooltip position for vertical sliders
|
|
3880
|
+
const tooltipPosition = vertical ? (tooltipPos === 'top' || tooltipPos === 'bottom' ? 'right' : tooltipPos) : tooltipPos;
|
|
3881
|
+
return m('.input-field', { className: cn, style }, [
|
|
3882
|
+
iconName ? m('i.material-icons.prefix', iconName) : undefined,
|
|
3883
|
+
// Hidden input for label association and accessibility
|
|
3884
|
+
m('input[type=range]', {
|
|
3885
|
+
id,
|
|
3886
|
+
value: state.singleValue,
|
|
3887
|
+
min,
|
|
3888
|
+
max,
|
|
3889
|
+
step,
|
|
3890
|
+
style: { display: 'none' },
|
|
3891
|
+
disabled,
|
|
3892
|
+
tabindex: -1,
|
|
3893
|
+
}),
|
|
3894
|
+
m('div', { class: fieldClass, style: containerStyle }, [
|
|
3895
|
+
m(`.single-range-slider.${orientation}`, {
|
|
3896
|
+
tabindex: disabled ? -1 : 0,
|
|
3897
|
+
role: 'slider',
|
|
3898
|
+
'aria-valuemin': min,
|
|
3899
|
+
'aria-valuemax': max,
|
|
3900
|
+
'aria-valuenow': state.singleValue,
|
|
3901
|
+
'aria-label': label || 'Range slider',
|
|
3902
|
+
onclick: (e) => {
|
|
3903
|
+
// Focus the slider when clicked
|
|
3904
|
+
e.currentTarget.focus();
|
|
3905
|
+
},
|
|
3906
|
+
onkeydown: (e) => {
|
|
3907
|
+
if (disabled)
|
|
3908
|
+
return;
|
|
3909
|
+
let newValue = state.singleValue;
|
|
3910
|
+
switch (e.key) {
|
|
3911
|
+
case 'ArrowLeft':
|
|
3912
|
+
case 'ArrowDown':
|
|
3913
|
+
e.preventDefault();
|
|
3914
|
+
newValue = Math.max(min, newValue - step);
|
|
3915
|
+
updateSingleValue(newValue, false);
|
|
3916
|
+
// m.redraw();
|
|
3917
|
+
break;
|
|
3918
|
+
case 'ArrowRight':
|
|
3919
|
+
case 'ArrowUp':
|
|
3920
|
+
e.preventDefault();
|
|
3921
|
+
newValue = Math.min(max, newValue + step);
|
|
3922
|
+
updateSingleValue(newValue, false);
|
|
3923
|
+
// m.redraw();
|
|
3924
|
+
break;
|
|
3925
|
+
case 'Home':
|
|
3926
|
+
e.preventDefault();
|
|
3927
|
+
updateSingleValue(min, false);
|
|
3928
|
+
// m.redraw();
|
|
3929
|
+
break;
|
|
3930
|
+
case 'End':
|
|
3931
|
+
e.preventDefault();
|
|
3932
|
+
updateSingleValue(max, false);
|
|
3933
|
+
// m.redraw();
|
|
3934
|
+
break;
|
|
3935
|
+
}
|
|
3936
|
+
},
|
|
3937
|
+
}, [
|
|
3938
|
+
// Track
|
|
3939
|
+
m(`.track.${orientation}`),
|
|
3940
|
+
// Progress
|
|
3941
|
+
m(`.range-progress.${orientation}`, { style: progressStyle }),
|
|
3942
|
+
// Thumb
|
|
3943
|
+
m(`.thumb.${orientation}`, {
|
|
3944
|
+
style: thumbStyle,
|
|
3945
|
+
onmousedown: handleMouseDown,
|
|
3946
|
+
}, showValue
|
|
3947
|
+
? m(`.value-tooltip.${tooltipPosition}`, state.singleValue.toFixed(0))
|
|
3948
|
+
: null),
|
|
3949
|
+
]),
|
|
3950
|
+
]),
|
|
3951
|
+
label
|
|
3952
|
+
? m(Label, {
|
|
3953
|
+
label,
|
|
3954
|
+
id,
|
|
3955
|
+
isMandatory,
|
|
3956
|
+
isActive: true, // Range sliders always have active labels
|
|
3957
|
+
})
|
|
3958
|
+
: null,
|
|
3959
|
+
helperText ? m(HelperText, { helperText }) : null,
|
|
3960
|
+
]);
|
|
3961
|
+
};
|
|
3962
|
+
// Double Range Slider (Min/Max)
|
|
3963
|
+
const renderMinMaxRange = (attrs, state, cn, style, iconName, id, label, isMandatory, helperText) => {
|
|
3964
|
+
const { min = 0, max = 100, step = 1, minValue, maxValue, vertical = false, showValue = false, height = '200px', disabled = false, } = attrs;
|
|
3965
|
+
// Initialize range values
|
|
3966
|
+
const currentMinValue = minValue !== undefined ? minValue : attrs.minValue || min;
|
|
3967
|
+
const currentMaxValue = maxValue !== undefined ? maxValue : attrs.maxValue || max;
|
|
3968
|
+
if (state.rangeMinValue === undefined || state.rangeMaxValue === undefined) {
|
|
3969
|
+
state.rangeMinValue = currentMinValue;
|
|
3970
|
+
state.rangeMaxValue = currentMaxValue;
|
|
3971
|
+
}
|
|
3972
|
+
// Initialize active thumb if not set
|
|
3973
|
+
if (state.activeThumb === null) {
|
|
3974
|
+
state.activeThumb = 'min';
|
|
3975
|
+
}
|
|
3976
|
+
const minPercentage = getPercentage(state.rangeMinValue, min, max);
|
|
3977
|
+
const maxPercentage = getPercentage(state.rangeMaxValue, min, max);
|
|
3978
|
+
// Only keep dynamic styles as inline, use CSS classes for static styles
|
|
3979
|
+
const containerStyle = vertical ? { height } : {};
|
|
3980
|
+
const rangeStyle = vertical
|
|
3981
|
+
? {
|
|
3982
|
+
bottom: `${minPercentage}%`,
|
|
3983
|
+
height: `${maxPercentage - minPercentage}%`,
|
|
3984
|
+
}
|
|
3985
|
+
: {
|
|
3986
|
+
left: `${minPercentage}%`,
|
|
3987
|
+
width: `${maxPercentage - minPercentage}%`,
|
|
3988
|
+
};
|
|
3989
|
+
// Only keep dynamic positioning and z-index as inline styles
|
|
3990
|
+
const createThumbStyle = (percentage, isActive) => vertical
|
|
3991
|
+
? {
|
|
3992
|
+
bottom: `${percentage}%`,
|
|
3993
|
+
zIndex: isActive ? 10 : 5,
|
|
3994
|
+
}
|
|
3995
|
+
: {
|
|
3996
|
+
left: `${percentage}%`,
|
|
3997
|
+
marginLeft: '-10px', // Half of thumb size (20px)
|
|
3998
|
+
zIndex: isActive ? 10 : 5,
|
|
3999
|
+
};
|
|
4000
|
+
const handleMouseDown = (thumb) => (e) => {
|
|
4001
|
+
if (disabled)
|
|
4002
|
+
return;
|
|
4003
|
+
e.preventDefault();
|
|
4004
|
+
state.isDragging = true;
|
|
4005
|
+
state.activeThumb = thumb;
|
|
4006
|
+
// Get container reference from the current target's parent
|
|
4007
|
+
const thumbElement = e.currentTarget;
|
|
4008
|
+
const container = thumbElement.parentElement;
|
|
4009
|
+
if (!container)
|
|
4010
|
+
return;
|
|
4011
|
+
const handleMouseMove = (e) => {
|
|
4012
|
+
if (!state.isDragging || !container)
|
|
4013
|
+
return;
|
|
4014
|
+
const rect = container.getBoundingClientRect();
|
|
4015
|
+
let percentage;
|
|
4016
|
+
if (vertical) {
|
|
4017
|
+
percentage = ((rect.bottom - e.clientY) / rect.height) * 100;
|
|
4018
|
+
}
|
|
4019
|
+
else {
|
|
4020
|
+
percentage = ((e.clientX - rect.left) / rect.width) * 100;
|
|
4021
|
+
}
|
|
4022
|
+
percentage = Math.max(0, Math.min(100, percentage));
|
|
4023
|
+
const value = min + (percentage / 100) * (max - min);
|
|
4024
|
+
const steppedValue = Math.round(value / step) * step;
|
|
4025
|
+
if (thumb === 'min') {
|
|
4026
|
+
updateRangeValues(Math.min(steppedValue, state.rangeMaxValue), state.rangeMaxValue, attrs, state, true);
|
|
4027
|
+
}
|
|
4028
|
+
else {
|
|
4029
|
+
updateRangeValues(state.rangeMinValue, Math.max(steppedValue, state.rangeMinValue), attrs, state, true);
|
|
4030
|
+
}
|
|
4031
|
+
// Redraw to update the UI during drag
|
|
4032
|
+
m.redraw();
|
|
4033
|
+
};
|
|
4034
|
+
const handleMouseUp = () => {
|
|
4035
|
+
state.isDragging = false;
|
|
4036
|
+
state.activeThumb = null;
|
|
4037
|
+
document.removeEventListener('mousemove', handleMouseMove);
|
|
4038
|
+
document.removeEventListener('mouseup', handleMouseUp);
|
|
4039
|
+
// Fire onchange when dragging ends
|
|
4040
|
+
updateRangeValues(state.rangeMinValue, state.rangeMaxValue, attrs, state, false);
|
|
4041
|
+
};
|
|
4042
|
+
document.addEventListener('mousemove', handleMouseMove);
|
|
4043
|
+
document.addEventListener('mouseup', handleMouseUp);
|
|
4044
|
+
};
|
|
4045
|
+
const fieldClass = vertical ? 'range-field vertical' : 'range-field';
|
|
4046
|
+
const orientation = vertical ? 'vertical' : 'horizontal';
|
|
4047
|
+
return m('.input-field', { className: cn, style }, [
|
|
4048
|
+
iconName ? m('i.material-icons.prefix', iconName) : undefined,
|
|
4049
|
+
// Hidden inputs for label association and accessibility
|
|
4050
|
+
m('input[type=range]', {
|
|
4051
|
+
id,
|
|
4052
|
+
value: state.rangeMinValue,
|
|
4053
|
+
min,
|
|
4054
|
+
max,
|
|
4055
|
+
step,
|
|
4056
|
+
style: { display: 'none' },
|
|
4057
|
+
disabled,
|
|
4058
|
+
tabindex: -1,
|
|
4059
|
+
}),
|
|
4060
|
+
m('input[type=range]', {
|
|
4061
|
+
id: `${id}_max`,
|
|
4062
|
+
value: state.rangeMaxValue,
|
|
4063
|
+
min,
|
|
4064
|
+
max,
|
|
4065
|
+
step,
|
|
4066
|
+
style: { display: 'none' },
|
|
4067
|
+
disabled,
|
|
4068
|
+
tabindex: -1,
|
|
4069
|
+
}),
|
|
4070
|
+
m(`div`, { className: fieldClass }, [
|
|
4071
|
+
m(`.double-range-slider.${orientation}`, {
|
|
4072
|
+
style: containerStyle,
|
|
4073
|
+
tabindex: disabled ? -1 : 0,
|
|
4074
|
+
role: 'slider',
|
|
4075
|
+
'aria-valuemin': min,
|
|
4076
|
+
'aria-valuemax': max,
|
|
4077
|
+
'aria-valuenow': state.rangeMinValue,
|
|
4078
|
+
'aria-valuetext': `${state.rangeMinValue} to ${state.rangeMaxValue}`,
|
|
4079
|
+
'aria-label': label || 'Range slider',
|
|
4080
|
+
onclick: (e) => {
|
|
4081
|
+
// Focus the slider when clicked
|
|
4082
|
+
e.currentTarget.focus();
|
|
4083
|
+
},
|
|
4084
|
+
onkeydown: (e) => {
|
|
4085
|
+
if (disabled)
|
|
4086
|
+
return;
|
|
4087
|
+
let newMinValue = state.rangeMinValue;
|
|
4088
|
+
let newMaxValue = state.rangeMaxValue;
|
|
4089
|
+
const activeThumb = state.activeThumb || 'min';
|
|
4090
|
+
switch (e.key) {
|
|
4091
|
+
case 'ArrowLeft':
|
|
4092
|
+
case 'ArrowDown':
|
|
4093
|
+
e.preventDefault();
|
|
4094
|
+
if (activeThumb === 'min') {
|
|
4095
|
+
newMinValue = Math.max(min, newMinValue - step);
|
|
4096
|
+
updateRangeValues(newMinValue, newMaxValue, attrs, state, false);
|
|
4097
|
+
}
|
|
4098
|
+
else {
|
|
4099
|
+
newMaxValue = Math.max(newMinValue, newMaxValue - step);
|
|
4100
|
+
updateRangeValues(newMinValue, newMaxValue, attrs, state, false);
|
|
4101
|
+
}
|
|
4102
|
+
// m.redraw();
|
|
4103
|
+
break;
|
|
4104
|
+
case 'ArrowRight':
|
|
4105
|
+
case 'ArrowUp':
|
|
4106
|
+
e.preventDefault();
|
|
4107
|
+
if (activeThumb === 'min') {
|
|
4108
|
+
newMinValue = Math.min(newMaxValue, newMinValue + step);
|
|
4109
|
+
updateRangeValues(newMinValue, newMaxValue, attrs, state, false);
|
|
4110
|
+
}
|
|
4111
|
+
else {
|
|
4112
|
+
newMaxValue = Math.min(max, newMaxValue + step);
|
|
4113
|
+
updateRangeValues(newMinValue, newMaxValue, attrs, state, false);
|
|
4114
|
+
}
|
|
4115
|
+
// m.redraw();
|
|
4116
|
+
break;
|
|
4117
|
+
case 'Tab':
|
|
4118
|
+
// Handle Tab navigation properly
|
|
4119
|
+
if (activeThumb === 'min') {
|
|
4120
|
+
if (e.shiftKey) {
|
|
4121
|
+
// Shift+Tab from min thumb: go to previous element (let browser handle)
|
|
4122
|
+
return; // Don't prevent default
|
|
4123
|
+
}
|
|
4124
|
+
else {
|
|
4125
|
+
// Tab from min thumb: go to max thumb
|
|
4126
|
+
e.preventDefault();
|
|
4127
|
+
state.activeThumb = 'max';
|
|
4128
|
+
}
|
|
4129
|
+
}
|
|
4130
|
+
else { // activeThumb === 'max'
|
|
4131
|
+
if (e.shiftKey) {
|
|
4132
|
+
// Shift+Tab from max thumb: go to min thumb
|
|
4133
|
+
e.preventDefault();
|
|
4134
|
+
state.activeThumb = 'min';
|
|
4135
|
+
}
|
|
4136
|
+
else {
|
|
4137
|
+
// Tab from max thumb: go to next element (let browser handle)
|
|
4138
|
+
return; // Don't prevent default
|
|
4139
|
+
}
|
|
4140
|
+
}
|
|
4141
|
+
break;
|
|
4142
|
+
case 'Home':
|
|
4143
|
+
e.preventDefault();
|
|
4144
|
+
if (activeThumb === 'min') {
|
|
4145
|
+
updateRangeValues(min, newMaxValue, attrs, state, false);
|
|
4146
|
+
}
|
|
4147
|
+
else {
|
|
4148
|
+
updateRangeValues(newMinValue, newMinValue, attrs, state, false);
|
|
4149
|
+
}
|
|
4150
|
+
// m.redraw();
|
|
4151
|
+
break;
|
|
4152
|
+
case 'End':
|
|
4153
|
+
e.preventDefault();
|
|
4154
|
+
if (activeThumb === 'min') {
|
|
4155
|
+
updateRangeValues(newMaxValue, newMaxValue, attrs, state, false);
|
|
4156
|
+
}
|
|
4157
|
+
else {
|
|
4158
|
+
updateRangeValues(newMinValue, max, attrs, state, false);
|
|
4159
|
+
}
|
|
4160
|
+
// m.redraw();
|
|
4161
|
+
break;
|
|
4162
|
+
}
|
|
4163
|
+
},
|
|
4164
|
+
}, [
|
|
4165
|
+
// Track
|
|
4166
|
+
m(`.track.${orientation}`),
|
|
4167
|
+
// Range
|
|
4168
|
+
m(`.range.${orientation}`, { style: rangeStyle }),
|
|
4169
|
+
// Min thumb
|
|
4170
|
+
m(`.thumb.${orientation}.min-thumb${state.activeThumb === 'min' ? '.active' : ''}`, {
|
|
4171
|
+
style: createThumbStyle(minPercentage, state.activeThumb === 'min'),
|
|
4172
|
+
onmousedown: handleMouseDown('min'),
|
|
4173
|
+
onclick: () => {
|
|
4174
|
+
state.activeThumb = 'min';
|
|
4175
|
+
// m.redraw();
|
|
4176
|
+
},
|
|
4177
|
+
}, showValue ? m(`.value.${orientation}`, state.rangeMinValue.toFixed(0)) : null),
|
|
4178
|
+
// Max thumb
|
|
4179
|
+
m(`.thumb.${orientation}.max-thumb${state.activeThumb === 'max' ? '.active' : ''}`, {
|
|
4180
|
+
style: createThumbStyle(maxPercentage, state.activeThumb === 'max'),
|
|
4181
|
+
onmousedown: handleMouseDown('max'),
|
|
4182
|
+
onclick: () => {
|
|
4183
|
+
state.activeThumb = 'max';
|
|
4184
|
+
// m.redraw();
|
|
4185
|
+
},
|
|
4186
|
+
}, showValue ? m(`.value.${orientation}`, state.rangeMaxValue.toFixed(0)) : null),
|
|
4187
|
+
]),
|
|
4188
|
+
]),
|
|
4189
|
+
label
|
|
4190
|
+
? m(Label, {
|
|
4191
|
+
label,
|
|
4192
|
+
id,
|
|
4193
|
+
isMandatory,
|
|
4194
|
+
isActive: true, // Range sliders always have active labels
|
|
4195
|
+
})
|
|
4196
|
+
: null,
|
|
4197
|
+
helperText ? m(HelperText, { helperText }) : null,
|
|
4198
|
+
]);
|
|
4199
|
+
};
|
|
4200
|
+
|
|
3360
4201
|
/**
|
|
3361
4202
|
* Pure TypeScript MaterialBox - creates an image lightbox that fills the screen when clicked
|
|
3362
4203
|
* No MaterializeCSS dependencies
|
|
@@ -3531,7 +4372,7 @@ const MaterialBox = () => {
|
|
|
3531
4372
|
view: ({ attrs }) => {
|
|
3532
4373
|
const { src, alt, width, height, caption, className, style } = attrs, otherAttrs = __rest(attrs, ["src", "alt", "width", "height", "caption", "className", "style"]);
|
|
3533
4374
|
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) => {
|
|
4375
|
+
height, className: ['materialboxed', className].filter(Boolean).join(' ') || undefined, style: Object.assign({ cursor: 'zoom-in', transition: 'opacity 200ms ease' }, style), onclick: (e) => {
|
|
3535
4376
|
e.preventDefault();
|
|
3536
4377
|
openBox(e.target, attrs);
|
|
3537
4378
|
} }));
|
|
@@ -3613,7 +4454,7 @@ const ModalPanel = () => {
|
|
|
3613
4454
|
.filter(Boolean)
|
|
3614
4455
|
.join(' ')
|
|
3615
4456
|
.trim();
|
|
3616
|
-
const overlayClasses = ['modal-overlay', state.isOpen ? 'active' : ''].filter(Boolean).join(' ').trim();
|
|
4457
|
+
const overlayClasses = ['modal-overlay', state.isOpen ? 'active' : ''].filter(Boolean).join(' ').trim() || undefined;
|
|
3617
4458
|
return m('div', { className: 'modal-container' }, [
|
|
3618
4459
|
// Modal overlay
|
|
3619
4460
|
m('div', {
|
|
@@ -3638,23 +4479,25 @@ const ModalPanel = () => {
|
|
|
3638
4479
|
role: 'dialog',
|
|
3639
4480
|
'aria-labelledby': `${id}-title`,
|
|
3640
4481
|
'aria-describedby': description ? `${id}-desc` : undefined,
|
|
3641
|
-
style: Object.assign(Object.assign({ display: state.isOpen ? 'flex' : 'none', position: 'fixed' }, (bottomSheet
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
4482
|
+
style: Object.assign(Object.assign({ display: state.isOpen ? 'flex' : 'none', position: 'fixed' }, (bottomSheet
|
|
4483
|
+
? {
|
|
4484
|
+
// Bottom sheet positioning
|
|
4485
|
+
top: 'auto',
|
|
4486
|
+
bottom: '0',
|
|
4487
|
+
left: '0',
|
|
4488
|
+
right: '0',
|
|
4489
|
+
transform: 'none',
|
|
4490
|
+
maxWidth: '100%',
|
|
4491
|
+
borderRadius: '8px 8px 0 0',
|
|
4492
|
+
}
|
|
4493
|
+
: {
|
|
4494
|
+
// Regular modal positioning
|
|
4495
|
+
top: '50%',
|
|
4496
|
+
left: '50%',
|
|
4497
|
+
transform: 'translate(-50%, -50%)',
|
|
4498
|
+
maxWidth: '75%',
|
|
4499
|
+
borderRadius: '4px',
|
|
4500
|
+
})), { 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
4501
|
onclick: (e) => e.stopPropagation(), // Prevent backdrop click when clicking inside modal
|
|
3659
4502
|
}, [
|
|
3660
4503
|
// Close button
|
|
@@ -4692,7 +5535,7 @@ const RadioButtons = () => {
|
|
|
4692
5535
|
callback(propId);
|
|
4693
5536
|
}
|
|
4694
5537
|
};
|
|
4695
|
-
const cn = [newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim();
|
|
5538
|
+
const cn = [newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim() || undefined;
|
|
4696
5539
|
const optionsContent = layout === 'horizontal'
|
|
4697
5540
|
? m('div.grid-container', options.map((r) => m(RadioButton, Object.assign(Object.assign({}, r), { onchange,
|
|
4698
5541
|
groupId, disabled: disabled || r.disabled, className: checkboxClass, checked: r.id === checkedId, inputId: `${componentId}-${r.id}` }))))
|
|
@@ -4965,7 +5808,7 @@ const Switch = () => {
|
|
|
4965
5808
|
view: ({ attrs }) => {
|
|
4966
5809
|
const id = attrs.id || state.id;
|
|
4967
5810
|
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();
|
|
5811
|
+
const cn = ['input-field', newRow ? 'clear' : '', className].filter(Boolean).join(' ').trim() || undefined;
|
|
4969
5812
|
return m('div', {
|
|
4970
5813
|
className: cn,
|
|
4971
5814
|
onclick: (e) => {
|
|
@@ -5116,7 +5959,7 @@ const Tabs = () => {
|
|
|
5116
5959
|
},
|
|
5117
5960
|
view: ({ attrs }) => {
|
|
5118
5961
|
const { tabWidth, tabs, className, style, swipeable = false } = attrs;
|
|
5119
|
-
const cn = [tabWidth === 'fill' ? 'tabs-fixed-width' : '', className].filter(Boolean).join(' ').trim();
|
|
5962
|
+
const cn = [tabWidth === 'fill' ? 'tabs-fixed-width' : '', className].filter(Boolean).join(' ').trim() || undefined;
|
|
5120
5963
|
const anchoredTabs = tabs.map(toAnchored());
|
|
5121
5964
|
const activeTab = setActiveTabId(anchoredTabs, attrs.selectedTabId);
|
|
5122
5965
|
updateIndicator();
|
|
@@ -6102,8 +6945,8 @@ const FileUpload = () => {
|
|
|
6102
6945
|
}
|
|
6103
6946
|
// Check file type
|
|
6104
6947
|
if (attrs.accept) {
|
|
6105
|
-
const acceptedTypes = attrs.accept.split(',').map(type => type.trim());
|
|
6106
|
-
const isAccepted = acceptedTypes.some(acceptedType => {
|
|
6948
|
+
const acceptedTypes = attrs.accept.split(',').map((type) => type.trim());
|
|
6949
|
+
const isAccepted = acceptedTypes.some((acceptedType) => {
|
|
6107
6950
|
if (acceptedType.startsWith('.')) {
|
|
6108
6951
|
// Extension check
|
|
6109
6952
|
return file.name.toLowerCase().endsWith(acceptedType.toLowerCase());
|
|
@@ -6163,11 +7006,11 @@ const FileUpload = () => {
|
|
|
6163
7006
|
}
|
|
6164
7007
|
// Notify parent component
|
|
6165
7008
|
if (attrs.onFilesSelected) {
|
|
6166
|
-
attrs.onFilesSelected(state.files.filter(f => !f.uploadError));
|
|
7009
|
+
attrs.onFilesSelected(state.files.filter((f) => !f.uploadError));
|
|
6167
7010
|
}
|
|
6168
7011
|
};
|
|
6169
7012
|
const removeFile = (fileToRemove, attrs) => {
|
|
6170
|
-
state.files = state.files.filter(file => file !== fileToRemove);
|
|
7013
|
+
state.files = state.files.filter((file) => file !== fileToRemove);
|
|
6171
7014
|
if (attrs.onFileRemoved) {
|
|
6172
7015
|
attrs.onFileRemoved(fileToRemove);
|
|
6173
7016
|
}
|
|
@@ -6186,11 +7029,11 @@ const FileUpload = () => {
|
|
|
6186
7029
|
id: uniqueId(),
|
|
6187
7030
|
files: [],
|
|
6188
7031
|
isDragOver: false,
|
|
6189
|
-
isUploading: false
|
|
7032
|
+
isUploading: false,
|
|
6190
7033
|
};
|
|
6191
7034
|
},
|
|
6192
7035
|
view: ({ attrs }) => {
|
|
6193
|
-
const { accept, multiple = false, disabled = false, label = 'Choose files or drag them here', helperText, showPreview = true, className = '', error } = attrs;
|
|
7036
|
+
const { accept, multiple = false, disabled = false, label = 'Choose files or drag them here', helperText, showPreview = true, className = '', error, } = attrs;
|
|
6194
7037
|
return m('.file-upload-container', { class: className }, [
|
|
6195
7038
|
// Upload area
|
|
6196
7039
|
m('.file-upload-area', {
|
|
@@ -6198,8 +7041,10 @@ const FileUpload = () => {
|
|
|
6198
7041
|
state.isDragOver ? 'drag-over' : '',
|
|
6199
7042
|
disabled ? 'disabled' : '',
|
|
6200
7043
|
error ? 'error' : '',
|
|
6201
|
-
state.files.length > 0 ? 'has-files' : ''
|
|
6202
|
-
]
|
|
7044
|
+
state.files.length > 0 ? 'has-files' : '',
|
|
7045
|
+
]
|
|
7046
|
+
.filter(Boolean)
|
|
7047
|
+
.join(' ') || undefined,
|
|
6203
7048
|
ondragover: (e) => {
|
|
6204
7049
|
if (disabled)
|
|
6205
7050
|
return;
|
|
@@ -6230,7 +7075,7 @@ const FileUpload = () => {
|
|
|
6230
7075
|
return;
|
|
6231
7076
|
const input = document.getElementById(state.id);
|
|
6232
7077
|
input === null || input === void 0 ? void 0 : input.click();
|
|
6233
|
-
}
|
|
7078
|
+
},
|
|
6234
7079
|
}, [
|
|
6235
7080
|
m('input[type="file"]', {
|
|
6236
7081
|
id: state.id,
|
|
@@ -6243,57 +7088,55 @@ const FileUpload = () => {
|
|
|
6243
7088
|
if (target.files) {
|
|
6244
7089
|
handleFiles(target.files, attrs);
|
|
6245
7090
|
}
|
|
6246
|
-
}
|
|
7091
|
+
},
|
|
6247
7092
|
}),
|
|
6248
7093
|
m('.file-upload-content', [
|
|
6249
7094
|
m('i.material-icons.file-upload-icon', 'cloud_upload'),
|
|
6250
7095
|
m('p.file-upload-label', label),
|
|
6251
7096
|
helperText && m('p.file-upload-helper', helperText),
|
|
6252
|
-
accept && m('p.file-upload-types', `Accepted: ${accept}`)
|
|
6253
|
-
])
|
|
7097
|
+
accept && m('p.file-upload-types', `Accepted: ${accept}`),
|
|
7098
|
+
]),
|
|
6254
7099
|
]),
|
|
6255
7100
|
// Error message
|
|
6256
7101
|
error && m('.file-upload-error', error),
|
|
6257
7102
|
// File list
|
|
6258
|
-
state.files.length > 0 &&
|
|
6259
|
-
m('
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
m('img', { src: file.preview, alt: file.name })
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
7103
|
+
state.files.length > 0 &&
|
|
7104
|
+
m('.file-upload-list', [
|
|
7105
|
+
m('h6', 'Selected Files:'),
|
|
7106
|
+
state.files.map((file) => m('.file-upload-item', { key: file.name + file.size }, [
|
|
7107
|
+
// Preview thumbnail
|
|
7108
|
+
showPreview && file.preview && m('.file-preview', [m('img', { src: file.preview, alt: file.name })]),
|
|
7109
|
+
// File info
|
|
7110
|
+
m('.file-info', [
|
|
7111
|
+
m('.file-name', file.name),
|
|
7112
|
+
m('.file-details', [
|
|
7113
|
+
m('span.file-size', formatFileSize(file.size)),
|
|
7114
|
+
file.type && m('span.file-type', file.type),
|
|
7115
|
+
]),
|
|
7116
|
+
// Progress bar (if uploading)
|
|
7117
|
+
file.uploadProgress !== undefined &&
|
|
7118
|
+
m('.file-progress', [
|
|
7119
|
+
m('.progress', [
|
|
7120
|
+
m('.determinate', {
|
|
7121
|
+
style: { width: `${file.uploadProgress}%` },
|
|
7122
|
+
}),
|
|
7123
|
+
]),
|
|
7124
|
+
]),
|
|
7125
|
+
// Error message
|
|
7126
|
+
file.uploadError && m('.file-error', file.uploadError),
|
|
6279
7127
|
]),
|
|
6280
|
-
//
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6290
|
-
}, [
|
|
6291
|
-
m('i.material-icons', 'close')
|
|
6292
|
-
])
|
|
6293
|
-
]))
|
|
6294
|
-
])
|
|
7128
|
+
// Remove button
|
|
7129
|
+
m('button.btn-flat.file-remove', {
|
|
7130
|
+
onclick: (e) => {
|
|
7131
|
+
e.stopPropagation();
|
|
7132
|
+
removeFile(file, attrs);
|
|
7133
|
+
},
|
|
7134
|
+
title: 'Remove file',
|
|
7135
|
+
}, [m('i.material-icons', 'close')]),
|
|
7136
|
+
])),
|
|
7137
|
+
]),
|
|
6295
7138
|
]);
|
|
6296
|
-
}
|
|
7139
|
+
},
|
|
6297
7140
|
};
|
|
6298
7141
|
};
|
|
6299
7142
|
|
|
@@ -6323,7 +7166,7 @@ const Sidenav = () => {
|
|
|
6323
7166
|
state = {
|
|
6324
7167
|
id: attrs.id || uniqueId(),
|
|
6325
7168
|
isOpen: attrs.isOpen || false,
|
|
6326
|
-
isAnimating: false
|
|
7169
|
+
isAnimating: false,
|
|
6327
7170
|
};
|
|
6328
7171
|
// Set up keyboard listener
|
|
6329
7172
|
if (typeof document !== 'undefined' && attrs.closeOnEscape !== false) {
|
|
@@ -6352,34 +7195,33 @@ const Sidenav = () => {
|
|
|
6352
7195
|
}
|
|
6353
7196
|
},
|
|
6354
7197
|
view: ({ attrs, children }) => {
|
|
6355
|
-
const { position = 'left', mode = 'overlay', width = 300, className = '', showBackdrop = true, animationDuration = 300, fixed = false } = attrs;
|
|
7198
|
+
const { position = 'left', mode = 'overlay', width = 300, className = '', showBackdrop = true, animationDuration = 300, fixed = false, } = attrs;
|
|
6356
7199
|
const isOpen = state.isOpen;
|
|
6357
7200
|
return [
|
|
6358
7201
|
// Backdrop (using existing materialize class)
|
|
6359
|
-
showBackdrop &&
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
7202
|
+
showBackdrop &&
|
|
7203
|
+
mode === 'overlay' &&
|
|
7204
|
+
m('.sidenav-overlay', {
|
|
7205
|
+
style: {
|
|
7206
|
+
display: isOpen ? 'block' : 'none',
|
|
7207
|
+
opacity: isOpen ? '1' : '0',
|
|
7208
|
+
},
|
|
7209
|
+
onclick: () => handleBackdropClick(attrs),
|
|
7210
|
+
}),
|
|
6366
7211
|
// Sidenav (using existing materialize structure)
|
|
6367
7212
|
m('ul.sidenav', {
|
|
6368
7213
|
id: state.id,
|
|
6369
|
-
class: [
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
className
|
|
6373
|
-
].filter(Boolean).join(' '),
|
|
7214
|
+
class: [position === 'right' ? 'right-aligned' : '', fixed ? 'sidenav-fixed' : '', className]
|
|
7215
|
+
.filter(Boolean)
|
|
7216
|
+
.join(' ') || undefined,
|
|
6374
7217
|
style: {
|
|
6375
7218
|
width: `${width}px`,
|
|
6376
|
-
transform: isOpen ? 'translateX(0)' :
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
}, children)
|
|
7219
|
+
transform: isOpen ? 'translateX(0)' : position === 'left' ? 'translateX(-105%)' : 'translateX(105%)',
|
|
7220
|
+
'transition-duration': `${animationDuration}ms`,
|
|
7221
|
+
},
|
|
7222
|
+
}, children),
|
|
6381
7223
|
];
|
|
6382
|
-
}
|
|
7224
|
+
},
|
|
6383
7225
|
};
|
|
6384
7226
|
};
|
|
6385
7227
|
/**
|
|
@@ -6389,37 +7231,30 @@ const Sidenav = () => {
|
|
|
6389
7231
|
const SidenavItem = () => {
|
|
6390
7232
|
return {
|
|
6391
7233
|
view: ({ attrs, children }) => {
|
|
6392
|
-
const { text, icon, active = false, disabled = false, onclick, href, className = '', divider = false, subheader = false } = attrs;
|
|
7234
|
+
const { text, icon, active = false, disabled = false, onclick, href, className = '', divider = false, subheader = false, } = attrs;
|
|
6393
7235
|
if (divider) {
|
|
6394
7236
|
return m('li.divider');
|
|
6395
7237
|
}
|
|
6396
7238
|
if (subheader) {
|
|
6397
7239
|
return m('li.subheader', text || children);
|
|
6398
7240
|
}
|
|
6399
|
-
const itemClasses = [
|
|
6400
|
-
|
|
6401
|
-
disabled ? 'disabled' : '',
|
|
6402
|
-
className
|
|
6403
|
-
].filter(Boolean).join(' ');
|
|
6404
|
-
const content = [
|
|
6405
|
-
icon && m('i.material-icons', icon),
|
|
6406
|
-
text || children
|
|
6407
|
-
];
|
|
7241
|
+
const itemClasses = [active ? 'active' : '', disabled ? 'disabled' : '', className].filter(Boolean).join(' ') || undefined;
|
|
7242
|
+
const content = [icon && m('i.material-icons', icon), text || children];
|
|
6408
7243
|
if (href && !disabled) {
|
|
6409
7244
|
return m('li', { class: itemClasses }, [
|
|
6410
7245
|
m('a', {
|
|
6411
7246
|
href,
|
|
6412
|
-
onclick: disabled ? undefined : onclick
|
|
6413
|
-
}, content)
|
|
7247
|
+
onclick: disabled ? undefined : onclick,
|
|
7248
|
+
}, content),
|
|
6414
7249
|
]);
|
|
6415
7250
|
}
|
|
6416
7251
|
return m('li', { class: itemClasses }, [
|
|
6417
7252
|
m('a', {
|
|
6418
7253
|
onclick: disabled ? undefined : onclick,
|
|
6419
|
-
href: '#!'
|
|
6420
|
-
}, content)
|
|
7254
|
+
href: '#!',
|
|
7255
|
+
}, content),
|
|
6421
7256
|
]);
|
|
6422
|
-
}
|
|
7257
|
+
},
|
|
6423
7258
|
};
|
|
6424
7259
|
};
|
|
6425
7260
|
/**
|
|
@@ -6470,7 +7305,7 @@ class SidenavManager {
|
|
|
6470
7305
|
const Breadcrumb = () => {
|
|
6471
7306
|
return {
|
|
6472
7307
|
view: ({ attrs }) => {
|
|
6473
|
-
const { items = [], separator = 'chevron_right', className = '', showIcons = false, maxItems, showHome = false } = attrs;
|
|
7308
|
+
const { items = [], separator = 'chevron_right', className = '', showIcons = false, maxItems, showHome = false, } = attrs;
|
|
6474
7309
|
if (items.length === 0) {
|
|
6475
7310
|
return null;
|
|
6476
7311
|
}
|
|
@@ -6479,52 +7314,46 @@ const Breadcrumb = () => {
|
|
|
6479
7314
|
if (maxItems && items.length > maxItems) {
|
|
6480
7315
|
const firstItem = items[0];
|
|
6481
7316
|
const lastItems = items.slice(-(maxItems - 2));
|
|
6482
|
-
displayItems = [
|
|
6483
|
-
firstItem,
|
|
6484
|
-
{ text: '...', disabled: true, className: 'breadcrumb-ellipsis' },
|
|
6485
|
-
...lastItems
|
|
6486
|
-
];
|
|
7317
|
+
displayItems = [firstItem, { text: '...', disabled: true, className: 'breadcrumb-ellipsis' }, ...lastItems];
|
|
6487
7318
|
}
|
|
6488
7319
|
return m('nav.breadcrumb', { class: className }, [
|
|
6489
|
-
m('ol.breadcrumb-list', displayItems
|
|
7320
|
+
m('ol.breadcrumb-list', displayItems
|
|
7321
|
+
.map((item, index) => {
|
|
6490
7322
|
const isLast = index === displayItems.length - 1;
|
|
6491
7323
|
const isFirst = index === 0;
|
|
6492
7324
|
return [
|
|
6493
7325
|
// Breadcrumb item
|
|
6494
7326
|
m('li.breadcrumb-item', {
|
|
6495
|
-
class: [
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
item.className || ''
|
|
6499
|
-
].filter(Boolean).join(' ')
|
|
7327
|
+
class: [item.active || isLast ? 'active' : '', item.disabled ? 'disabled' : '', item.className || '']
|
|
7328
|
+
.filter(Boolean)
|
|
7329
|
+
.join(' ') || undefined,
|
|
6500
7330
|
}, [
|
|
6501
|
-
item.href && !item.disabled && !isLast
|
|
6502
|
-
// Link item
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
// Text item (active or disabled)
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
7331
|
+
item.href && !item.disabled && !isLast
|
|
7332
|
+
? // Link item
|
|
7333
|
+
m('a.breadcrumb-link', {
|
|
7334
|
+
href: item.href,
|
|
7335
|
+
onclick: item.onclick,
|
|
7336
|
+
}, [
|
|
7337
|
+
showIcons && item.icon && m('i.material-icons.breadcrumb-icon', item.icon),
|
|
7338
|
+
showHome && isFirst && !item.icon && m('i.material-icons.breadcrumb-icon', 'home'),
|
|
7339
|
+
m('span.breadcrumb-text', item.text),
|
|
7340
|
+
])
|
|
7341
|
+
: // Text item (active or disabled)
|
|
7342
|
+
m('span.breadcrumb-text', {
|
|
7343
|
+
onclick: item.disabled ? undefined : item.onclick,
|
|
7344
|
+
}, [
|
|
7345
|
+
showIcons && item.icon && m('i.material-icons.breadcrumb-icon', item.icon),
|
|
7346
|
+
showHome && isFirst && !item.icon && m('i.material-icons.breadcrumb-icon', 'home'),
|
|
7347
|
+
item.text,
|
|
7348
|
+
]),
|
|
6519
7349
|
]),
|
|
6520
7350
|
// Separator (except for last item)
|
|
6521
|
-
!isLast && m('li.breadcrumb-separator', [
|
|
6522
|
-
m('i.material-icons', separator)
|
|
6523
|
-
])
|
|
7351
|
+
!isLast && m('li.breadcrumb-separator', [m('i.material-icons', separator)]),
|
|
6524
7352
|
];
|
|
6525
|
-
})
|
|
7353
|
+
})
|
|
7354
|
+
.reduce((acc, val) => acc.concat(val), [])),
|
|
6526
7355
|
]);
|
|
6527
|
-
}
|
|
7356
|
+
},
|
|
6528
7357
|
};
|
|
6529
7358
|
};
|
|
6530
7359
|
/**
|
|
@@ -6537,7 +7366,7 @@ const createBreadcrumb = (path, basePath = '/') => {
|
|
|
6537
7366
|
items.push({
|
|
6538
7367
|
text: 'Home',
|
|
6539
7368
|
href: basePath,
|
|
6540
|
-
icon: 'home'
|
|
7369
|
+
icon: 'home',
|
|
6541
7370
|
});
|
|
6542
7371
|
// Add path segments
|
|
6543
7372
|
let currentPath = basePath;
|
|
@@ -6547,7 +7376,7 @@ const createBreadcrumb = (path, basePath = '/') => {
|
|
|
6547
7376
|
items.push({
|
|
6548
7377
|
text: segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, ' '),
|
|
6549
7378
|
href: isLast ? undefined : currentPath,
|
|
6550
|
-
active: isLast
|
|
7379
|
+
active: isLast,
|
|
6551
7380
|
});
|
|
6552
7381
|
});
|
|
6553
7382
|
return items;
|
|
@@ -6566,19 +7395,18 @@ class BreadcrumbManager {
|
|
|
6566
7395
|
items.push({
|
|
6567
7396
|
text: 'Home',
|
|
6568
7397
|
href: '/',
|
|
6569
|
-
icon: 'home'
|
|
7398
|
+
icon: 'home',
|
|
6570
7399
|
});
|
|
6571
7400
|
let currentPath = '';
|
|
6572
7401
|
segments.forEach((segment, index) => {
|
|
6573
7402
|
currentPath += '/' + segment;
|
|
6574
7403
|
const isLast = index === segments.length - 1;
|
|
6575
7404
|
// Use custom text from config or format segment
|
|
6576
|
-
const text = routeConfig[currentPath] ||
|
|
6577
|
-
segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, ' ');
|
|
7405
|
+
const text = routeConfig[currentPath] || segment.charAt(0).toUpperCase() + segment.slice(1).replace(/-/g, ' ');
|
|
6578
7406
|
items.push({
|
|
6579
7407
|
text,
|
|
6580
7408
|
href: isLast ? undefined : currentPath,
|
|
6581
|
-
active: isLast
|
|
7409
|
+
active: isLast,
|
|
6582
7410
|
});
|
|
6583
7411
|
});
|
|
6584
7412
|
return items;
|
|
@@ -6590,7 +7418,7 @@ class BreadcrumbManager {
|
|
|
6590
7418
|
return hierarchy.map((item, index) => ({
|
|
6591
7419
|
text: item[textKey],
|
|
6592
7420
|
href: index === hierarchy.length - 1 ? undefined : item[pathKey],
|
|
6593
|
-
active: index === hierarchy.length - 1
|
|
7421
|
+
active: index === hierarchy.length - 1,
|
|
6594
7422
|
}));
|
|
6595
7423
|
}
|
|
6596
7424
|
}
|
|
@@ -6724,7 +7552,7 @@ const Wizard = () => {
|
|
|
6724
7552
|
hasError ? 'error' : '',
|
|
6725
7553
|
step.disabled ? 'disabled' : '',
|
|
6726
7554
|
step.optional ? 'optional' : ''
|
|
6727
|
-
].filter(Boolean).join(' '),
|
|
7555
|
+
].filter(Boolean).join(' ') || undefined,
|
|
6728
7556
|
onclick: allowHeaderNavigation && !step.disabled ?
|
|
6729
7557
|
() => goToStep(index, attrs) : undefined
|
|
6730
7558
|
}, [
|
|
@@ -6798,6 +7626,292 @@ const Stepper = () => {
|
|
|
6798
7626
|
};
|
|
6799
7627
|
};
|
|
6800
7628
|
|
|
7629
|
+
// Utility function to check if a node is the last in its branch
|
|
7630
|
+
const isNodeLastInBranch = (nodePath, rootNodes) => {
|
|
7631
|
+
// Navigate to the node's position and check if it's the last child at every level
|
|
7632
|
+
let currentNodes = rootNodes;
|
|
7633
|
+
for (let i = 0; i < nodePath.length; i++) {
|
|
7634
|
+
const index = nodePath[i];
|
|
7635
|
+
const isLastAtThisLevel = index === currentNodes.length - 1;
|
|
7636
|
+
// If this is not the last child at this level, then this node is not last in branch
|
|
7637
|
+
if (!isLastAtThisLevel) {
|
|
7638
|
+
return false;
|
|
7639
|
+
}
|
|
7640
|
+
// Move to the next level if it exists
|
|
7641
|
+
if (i < nodePath.length - 1) {
|
|
7642
|
+
const currentNode = currentNodes[index];
|
|
7643
|
+
if (currentNode.children) {
|
|
7644
|
+
currentNodes = currentNode.children;
|
|
7645
|
+
}
|
|
7646
|
+
}
|
|
7647
|
+
}
|
|
7648
|
+
return true;
|
|
7649
|
+
};
|
|
7650
|
+
const TreeNodeComponent = () => {
|
|
7651
|
+
return {
|
|
7652
|
+
view: ({ attrs }) => {
|
|
7653
|
+
const { node, level, isSelected, isExpanded, isFocused, showConnectors, iconType, selectionMode, onToggleExpand, onToggleSelect, onFocus, } = attrs;
|
|
7654
|
+
const hasChildren = node.children && node.children.length > 0;
|
|
7655
|
+
const indentLevel = level * 24; // 24px per level
|
|
7656
|
+
return m('li.tree-node', {
|
|
7657
|
+
class: [
|
|
7658
|
+
isSelected && 'selected',
|
|
7659
|
+
isFocused && 'focused',
|
|
7660
|
+
node.disabled && 'disabled',
|
|
7661
|
+
hasChildren && 'has-children',
|
|
7662
|
+
attrs.isLastInBranch && 'tree-last-in-branch',
|
|
7663
|
+
]
|
|
7664
|
+
.filter(Boolean)
|
|
7665
|
+
.join(' ') || undefined,
|
|
7666
|
+
'data-node-id': node.id,
|
|
7667
|
+
'data-level': level,
|
|
7668
|
+
}, [
|
|
7669
|
+
// Node content
|
|
7670
|
+
m('.tree-node-content', {
|
|
7671
|
+
style: {
|
|
7672
|
+
paddingLeft: `${indentLevel}px`,
|
|
7673
|
+
},
|
|
7674
|
+
onclick: node.disabled
|
|
7675
|
+
? undefined
|
|
7676
|
+
: () => {
|
|
7677
|
+
if (selectionMode !== 'none') {
|
|
7678
|
+
onToggleSelect(node.id);
|
|
7679
|
+
}
|
|
7680
|
+
onFocus(node.id);
|
|
7681
|
+
},
|
|
7682
|
+
onkeydown: (e) => {
|
|
7683
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
7684
|
+
e.preventDefault();
|
|
7685
|
+
if (!node.disabled && selectionMode !== 'none') {
|
|
7686
|
+
onToggleSelect(node.id);
|
|
7687
|
+
}
|
|
7688
|
+
}
|
|
7689
|
+
},
|
|
7690
|
+
tabindex: node.disabled ? -1 : 0,
|
|
7691
|
+
role: selectionMode === 'multiple' ? 'option' : 'treeitem',
|
|
7692
|
+
'aria-selected': selectionMode !== 'none' ? isSelected.toString() : undefined,
|
|
7693
|
+
'aria-expanded': hasChildren ? isExpanded.toString() : undefined,
|
|
7694
|
+
'aria-disabled': node.disabled ? 'true' : undefined,
|
|
7695
|
+
}, [
|
|
7696
|
+
// Connector lines
|
|
7697
|
+
showConnectors &&
|
|
7698
|
+
level > 0 &&
|
|
7699
|
+
m('.tree-connectors', Array.from({ length: level }, (_, i) => m('.tree-connector', {
|
|
7700
|
+
key: i,
|
|
7701
|
+
style: { left: `${i * 24 + 12}px` },
|
|
7702
|
+
}))),
|
|
7703
|
+
// Expand/collapse icon or spacer
|
|
7704
|
+
hasChildren
|
|
7705
|
+
? m('.tree-expand-icon', {
|
|
7706
|
+
onclick: (e) => {
|
|
7707
|
+
e.stopPropagation();
|
|
7708
|
+
if (!node.disabled) {
|
|
7709
|
+
onToggleExpand(node.id);
|
|
7710
|
+
}
|
|
7711
|
+
},
|
|
7712
|
+
class: iconType,
|
|
7713
|
+
}, [
|
|
7714
|
+
iconType === 'plus-minus'
|
|
7715
|
+
? m('span.tree-plus-minus', isExpanded ? '−' : '+')
|
|
7716
|
+
: iconType === 'triangle'
|
|
7717
|
+
? m('span.tree-triangle', { class: isExpanded ? 'expanded' : undefined }, '▶')
|
|
7718
|
+
: iconType === 'chevron'
|
|
7719
|
+
? m(MaterialIcon, {
|
|
7720
|
+
name: 'chevron',
|
|
7721
|
+
direction: isExpanded ? 'down' : 'right',
|
|
7722
|
+
class: 'tree-chevron-icon',
|
|
7723
|
+
})
|
|
7724
|
+
: m(MaterialIcon, {
|
|
7725
|
+
name: 'caret',
|
|
7726
|
+
direction: isExpanded ? 'down' : 'right',
|
|
7727
|
+
class: 'tree-caret-icon',
|
|
7728
|
+
}),
|
|
7729
|
+
])
|
|
7730
|
+
: m('.tree-expand-spacer'), // Spacer for alignment
|
|
7731
|
+
// Selection indicator for multiple selection
|
|
7732
|
+
selectionMode === 'multiple' &&
|
|
7733
|
+
m('.tree-selection-indicator', [
|
|
7734
|
+
m('input[type=checkbox]', {
|
|
7735
|
+
checked: isSelected,
|
|
7736
|
+
disabled: node.disabled,
|
|
7737
|
+
onchange: () => {
|
|
7738
|
+
if (!node.disabled) {
|
|
7739
|
+
onToggleSelect(node.id);
|
|
7740
|
+
}
|
|
7741
|
+
},
|
|
7742
|
+
onclick: (e) => e.stopPropagation(),
|
|
7743
|
+
}),
|
|
7744
|
+
]),
|
|
7745
|
+
// Node icon (optional)
|
|
7746
|
+
node.icon && m('i.tree-node-icon.material-icons', node.icon),
|
|
7747
|
+
// Node label
|
|
7748
|
+
m('span.tree-node-label', node.label),
|
|
7749
|
+
]),
|
|
7750
|
+
// Children (recursive)
|
|
7751
|
+
hasChildren &&
|
|
7752
|
+
isExpanded &&
|
|
7753
|
+
m('ul.tree-children', {
|
|
7754
|
+
role: 'group',
|
|
7755
|
+
'aria-expanded': 'true',
|
|
7756
|
+
}, node.children.map((child, childIndex) => {
|
|
7757
|
+
var _a, _b, _c, _d, _e, _f;
|
|
7758
|
+
// Calculate state for each child using treeState
|
|
7759
|
+
const childIsSelected = (_b = (_a = attrs.treeState) === null || _a === void 0 ? void 0 : _a.selectedIds.has(child.id)) !== null && _b !== void 0 ? _b : false;
|
|
7760
|
+
const childIsExpanded = (_d = (_c = attrs.treeState) === null || _c === void 0 ? void 0 : _c.expandedIds.has(child.id)) !== null && _d !== void 0 ? _d : false;
|
|
7761
|
+
const childIsFocused = ((_e = attrs.treeState) === null || _e === void 0 ? void 0 : _e.focusedNodeId) === child.id;
|
|
7762
|
+
// Calculate if this child is last in branch
|
|
7763
|
+
const childPath = [...(attrs.currentPath || []), childIndex];
|
|
7764
|
+
const childIsLastInBranch = ((_f = attrs.treeAttrs) === null || _f === void 0 ? void 0 : _f.data) ?
|
|
7765
|
+
isNodeLastInBranch(childPath, attrs.treeAttrs.data) : false;
|
|
7766
|
+
return m(TreeNodeComponent, {
|
|
7767
|
+
key: child.id,
|
|
7768
|
+
node: child,
|
|
7769
|
+
level: level + 1,
|
|
7770
|
+
isSelected: childIsSelected,
|
|
7771
|
+
isExpanded: childIsExpanded,
|
|
7772
|
+
isFocused: childIsFocused,
|
|
7773
|
+
showConnectors,
|
|
7774
|
+
iconType,
|
|
7775
|
+
selectionMode,
|
|
7776
|
+
onToggleExpand,
|
|
7777
|
+
onToggleSelect,
|
|
7778
|
+
onFocus,
|
|
7779
|
+
isLastInBranch: childIsLastInBranch,
|
|
7780
|
+
currentPath: childPath,
|
|
7781
|
+
treeState: attrs.treeState,
|
|
7782
|
+
treeAttrs: attrs.treeAttrs,
|
|
7783
|
+
});
|
|
7784
|
+
})),
|
|
7785
|
+
]);
|
|
7786
|
+
},
|
|
7787
|
+
};
|
|
7788
|
+
};
|
|
7789
|
+
const TreeView = () => {
|
|
7790
|
+
const state = {
|
|
7791
|
+
selectedIds: new Set(),
|
|
7792
|
+
expandedIds: new Set(),
|
|
7793
|
+
focusedNodeId: null,
|
|
7794
|
+
treeMap: new Map(),
|
|
7795
|
+
};
|
|
7796
|
+
const buildTreeMap = (nodes, map) => {
|
|
7797
|
+
nodes.forEach((node) => {
|
|
7798
|
+
map.set(node.id, node);
|
|
7799
|
+
if (node.children) {
|
|
7800
|
+
buildTreeMap(node.children, map);
|
|
7801
|
+
}
|
|
7802
|
+
});
|
|
7803
|
+
};
|
|
7804
|
+
const initializeExpandedNodes = (nodes) => {
|
|
7805
|
+
nodes.forEach((node) => {
|
|
7806
|
+
if (node.expanded) {
|
|
7807
|
+
state.expandedIds.add(node.id);
|
|
7808
|
+
}
|
|
7809
|
+
if (node.children) {
|
|
7810
|
+
initializeExpandedNodes(node.children);
|
|
7811
|
+
}
|
|
7812
|
+
});
|
|
7813
|
+
};
|
|
7814
|
+
const handleToggleExpand = (nodeId, attrs) => {
|
|
7815
|
+
var _a;
|
|
7816
|
+
const isExpanded = state.expandedIds.has(nodeId);
|
|
7817
|
+
if (isExpanded) {
|
|
7818
|
+
state.expandedIds.delete(nodeId);
|
|
7819
|
+
}
|
|
7820
|
+
else {
|
|
7821
|
+
state.expandedIds.add(nodeId);
|
|
7822
|
+
}
|
|
7823
|
+
(_a = attrs.onexpand) === null || _a === void 0 ? void 0 : _a.call(attrs, { nodeId, expanded: !isExpanded });
|
|
7824
|
+
};
|
|
7825
|
+
const handleToggleSelect = (nodeId, attrs) => {
|
|
7826
|
+
var _a;
|
|
7827
|
+
const { selectionMode = 'single' } = attrs;
|
|
7828
|
+
if (selectionMode === 'single') {
|
|
7829
|
+
state.selectedIds.clear();
|
|
7830
|
+
state.selectedIds.add(nodeId);
|
|
7831
|
+
}
|
|
7832
|
+
else if (selectionMode === 'multiple') {
|
|
7833
|
+
if (state.selectedIds.has(nodeId)) {
|
|
7834
|
+
state.selectedIds.delete(nodeId);
|
|
7835
|
+
}
|
|
7836
|
+
else {
|
|
7837
|
+
state.selectedIds.add(nodeId);
|
|
7838
|
+
}
|
|
7839
|
+
}
|
|
7840
|
+
(_a = attrs.onselection) === null || _a === void 0 ? void 0 : _a.call(attrs, Array.from(state.selectedIds));
|
|
7841
|
+
};
|
|
7842
|
+
const handleFocus = (nodeId) => {
|
|
7843
|
+
state.focusedNodeId = nodeId;
|
|
7844
|
+
};
|
|
7845
|
+
const renderNodes = (nodes, attrs, level = 0, parentPath = []) => {
|
|
7846
|
+
return nodes.map((node, index) => {
|
|
7847
|
+
var _a, _b, _c;
|
|
7848
|
+
const isSelected = state.selectedIds.has(node.id);
|
|
7849
|
+
const isExpanded = state.expandedIds.has(node.id);
|
|
7850
|
+
const isFocused = state.focusedNodeId === node.id;
|
|
7851
|
+
const currentPath = [...parentPath, index];
|
|
7852
|
+
const isLastInBranch = isNodeLastInBranch(currentPath, attrs.data);
|
|
7853
|
+
return m(TreeNodeComponent, {
|
|
7854
|
+
key: node.id,
|
|
7855
|
+
node,
|
|
7856
|
+
level,
|
|
7857
|
+
isSelected,
|
|
7858
|
+
isExpanded,
|
|
7859
|
+
isFocused,
|
|
7860
|
+
showConnectors: (_a = attrs.showConnectors) !== null && _a !== void 0 ? _a : true,
|
|
7861
|
+
iconType: (_b = attrs.iconType) !== null && _b !== void 0 ? _b : 'caret',
|
|
7862
|
+
selectionMode: (_c = attrs.selectionMode) !== null && _c !== void 0 ? _c : 'single',
|
|
7863
|
+
onToggleExpand: (nodeId) => handleToggleExpand(nodeId, attrs),
|
|
7864
|
+
onToggleSelect: (nodeId) => handleToggleSelect(nodeId, attrs),
|
|
7865
|
+
onFocus: handleFocus,
|
|
7866
|
+
isLastInBranch,
|
|
7867
|
+
currentPath,
|
|
7868
|
+
// Pass state and attrs for recursive rendering
|
|
7869
|
+
treeState: state,
|
|
7870
|
+
treeAttrs: attrs,
|
|
7871
|
+
});
|
|
7872
|
+
});
|
|
7873
|
+
};
|
|
7874
|
+
return {
|
|
7875
|
+
oninit: ({ attrs }) => {
|
|
7876
|
+
// Build internal tree map for efficient lookups
|
|
7877
|
+
buildTreeMap(attrs.data, state.treeMap);
|
|
7878
|
+
// Initialize expanded nodes from data
|
|
7879
|
+
initializeExpandedNodes(attrs.data);
|
|
7880
|
+
// Initialize selected nodes from props
|
|
7881
|
+
if (attrs.selectedIds) {
|
|
7882
|
+
state.selectedIds = new Set(attrs.selectedIds);
|
|
7883
|
+
}
|
|
7884
|
+
},
|
|
7885
|
+
onupdate: ({ attrs }) => {
|
|
7886
|
+
// Sync selectedIds prop with internal state
|
|
7887
|
+
if (attrs.selectedIds) {
|
|
7888
|
+
const newSelection = new Set(attrs.selectedIds);
|
|
7889
|
+
if (newSelection.size !== state.selectedIds.size ||
|
|
7890
|
+
!Array.from(newSelection).every((id) => state.selectedIds.has(id))) {
|
|
7891
|
+
state.selectedIds = newSelection;
|
|
7892
|
+
}
|
|
7893
|
+
}
|
|
7894
|
+
},
|
|
7895
|
+
view: ({ attrs }) => {
|
|
7896
|
+
const { data, className, style, id, selectionMode = 'single', showConnectors = true } = attrs;
|
|
7897
|
+
return m('div.tree-view', {
|
|
7898
|
+
class: [
|
|
7899
|
+
className,
|
|
7900
|
+
showConnectors && 'show-connectors'
|
|
7901
|
+
].filter(Boolean).join(' ') || undefined,
|
|
7902
|
+
style,
|
|
7903
|
+
id,
|
|
7904
|
+
role: selectionMode === 'multiple' ? 'listbox' : 'tree',
|
|
7905
|
+
'aria-multiselectable': selectionMode === 'multiple' ? 'true' : 'false',
|
|
7906
|
+
}, [
|
|
7907
|
+
m('ul.tree-root', {
|
|
7908
|
+
role: 'group',
|
|
7909
|
+
}, renderNodes(data, attrs)),
|
|
7910
|
+
]);
|
|
7911
|
+
},
|
|
7912
|
+
};
|
|
7913
|
+
};
|
|
7914
|
+
|
|
6801
7915
|
/**
|
|
6802
7916
|
* @fileoverview Core TypeScript utility types for mithril-materialized library
|
|
6803
7917
|
* These types improve type safety and developer experience across all components
|
|
@@ -6849,6 +7963,7 @@ exports.LargeButton = LargeButton;
|
|
|
6849
7963
|
exports.ListItem = ListItem;
|
|
6850
7964
|
exports.Mandatory = Mandatory;
|
|
6851
7965
|
exports.MaterialBox = MaterialBox;
|
|
7966
|
+
exports.MaterialIcon = MaterialIcon;
|
|
6852
7967
|
exports.ModalPanel = ModalPanel;
|
|
6853
7968
|
exports.NumberInput = NumberInput;
|
|
6854
7969
|
exports.Options = Options;
|
|
@@ -6883,6 +7998,7 @@ exports.Toast = Toast;
|
|
|
6883
7998
|
exports.ToastComponent = ToastComponent;
|
|
6884
7999
|
exports.Tooltip = Tooltip;
|
|
6885
8000
|
exports.TooltipComponent = TooltipComponent;
|
|
8001
|
+
exports.TreeView = TreeView;
|
|
6886
8002
|
exports.UrlInput = UrlInput;
|
|
6887
8003
|
exports.Wizard = Wizard;
|
|
6888
8004
|
exports.createBreadcrumb = createBreadcrumb;
|
|
@@ -6894,6 +8010,8 @@ exports.isValidationError = isValidationError;
|
|
|
6894
8010
|
exports.isValidationSuccess = isValidationSuccess;
|
|
6895
8011
|
exports.padLeft = padLeft;
|
|
6896
8012
|
exports.range = range;
|
|
8013
|
+
exports.renderMinMaxRange = renderMinMaxRange;
|
|
8014
|
+
exports.renderSingleRangeWithTooltip = renderSingleRangeWithTooltip;
|
|
6897
8015
|
exports.toast = toast;
|
|
6898
8016
|
exports.uniqueId = uniqueId;
|
|
6899
8017
|
exports.uuid4 = uuid4;
|