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