softui-css 1.8.6 → 1.10.0
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 +3 -3
- package/dist/softui.css +404 -14
- package/dist/softui.js +197 -29
- package/dist/softui.min.css +1 -1
- package/dist/softui.min.js +1 -1
- package/package.json +1 -1
package/dist/softui.js
CHANGED
|
@@ -294,6 +294,12 @@ const SoftUI = (() => {
|
|
|
294
294
|
// Charts
|
|
295
295
|
initCharts();
|
|
296
296
|
|
|
297
|
+
// Styled Selects
|
|
298
|
+
initStyledSelects();
|
|
299
|
+
|
|
300
|
+
// Selectable pricing
|
|
301
|
+
initSelectablePricing();
|
|
302
|
+
|
|
297
303
|
// Data Tables
|
|
298
304
|
initDataTables();
|
|
299
305
|
|
|
@@ -2534,6 +2540,109 @@ const SoftUI = (() => {
|
|
|
2534
2540
|
});
|
|
2535
2541
|
}
|
|
2536
2542
|
|
|
2543
|
+
function initSelectablePricing() {
|
|
2544
|
+
document.querySelectorAll('.sui-pricing-selectable').forEach(function(container) {
|
|
2545
|
+
var cards = container.querySelectorAll('.sui-pricing-card');
|
|
2546
|
+
cards.forEach(function(card) {
|
|
2547
|
+
card.addEventListener('click', function() {
|
|
2548
|
+
cards.forEach(function(c) { c.classList.remove('selected'); });
|
|
2549
|
+
card.classList.add('selected');
|
|
2550
|
+
container.setAttribute('data-selected', card.getAttribute('data-plan') || '');
|
|
2551
|
+
container.dispatchEvent(new Event('change', { bubbles: true }));
|
|
2552
|
+
});
|
|
2553
|
+
});
|
|
2554
|
+
});
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
function initStyledSelects() {
|
|
2558
|
+
document.querySelectorAll('.sui-styled-select').forEach(function(sel) {
|
|
2559
|
+
var trigger = sel.querySelector('.sui-styled-select-trigger');
|
|
2560
|
+
var menu = sel.querySelector('.sui-styled-select-menu');
|
|
2561
|
+
var valueEl = sel.querySelector('.sui-styled-select-value');
|
|
2562
|
+
var options = sel.querySelectorAll('.sui-styled-select-option');
|
|
2563
|
+
var placeholder = sel.getAttribute('data-placeholder') || '';
|
|
2564
|
+
var focusIdx = -1;
|
|
2565
|
+
|
|
2566
|
+
if (!trigger || !menu) return;
|
|
2567
|
+
|
|
2568
|
+
// Set initial value
|
|
2569
|
+
var selected = sel.querySelector('.sui-styled-select-option.selected');
|
|
2570
|
+
if (selected && valueEl) {
|
|
2571
|
+
valueEl.textContent = selected.textContent;
|
|
2572
|
+
valueEl.classList.remove('sui-styled-select-placeholder');
|
|
2573
|
+
} else if (valueEl && placeholder) {
|
|
2574
|
+
valueEl.textContent = placeholder;
|
|
2575
|
+
valueEl.classList.add('sui-styled-select-placeholder');
|
|
2576
|
+
}
|
|
2577
|
+
|
|
2578
|
+
// Toggle menu
|
|
2579
|
+
trigger.addEventListener('click', function(e) {
|
|
2580
|
+
e.stopPropagation();
|
|
2581
|
+
// Close other open selects
|
|
2582
|
+
document.querySelectorAll('.sui-styled-select.open').forEach(function(s) {
|
|
2583
|
+
if (s !== sel) s.classList.remove('open');
|
|
2584
|
+
});
|
|
2585
|
+
sel.classList.toggle('open');
|
|
2586
|
+
if (sel.classList.contains('open')) {
|
|
2587
|
+
// Focus selected or first option
|
|
2588
|
+
focusIdx = -1;
|
|
2589
|
+
options.forEach(function(o, i) { if (o.classList.contains('selected')) focusIdx = i; });
|
|
2590
|
+
}
|
|
2591
|
+
});
|
|
2592
|
+
|
|
2593
|
+
// Option click
|
|
2594
|
+
options.forEach(function(opt, i) {
|
|
2595
|
+
opt.addEventListener('click', function() {
|
|
2596
|
+
options.forEach(function(o) { o.classList.remove('selected'); });
|
|
2597
|
+
opt.classList.add('selected');
|
|
2598
|
+
if (valueEl) {
|
|
2599
|
+
valueEl.textContent = opt.textContent;
|
|
2600
|
+
valueEl.classList.remove('sui-styled-select-placeholder');
|
|
2601
|
+
}
|
|
2602
|
+
sel.setAttribute('data-value', opt.getAttribute('data-value') || opt.textContent);
|
|
2603
|
+
sel.classList.remove('open');
|
|
2604
|
+
// Dispatch change event for datatable filter integration
|
|
2605
|
+
sel.dispatchEvent(new Event('change', { bubbles: true }));
|
|
2606
|
+
trigger.focus();
|
|
2607
|
+
});
|
|
2608
|
+
});
|
|
2609
|
+
|
|
2610
|
+
// Keyboard navigation
|
|
2611
|
+
trigger.addEventListener('keydown', function(e) {
|
|
2612
|
+
var isOpen = sel.classList.contains('open');
|
|
2613
|
+
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
|
2614
|
+
e.preventDefault();
|
|
2615
|
+
if (!isOpen) { sel.classList.add('open'); focusIdx = -1; }
|
|
2616
|
+
if (e.key === 'ArrowDown') focusIdx = Math.min(focusIdx + 1, options.length - 1);
|
|
2617
|
+
else focusIdx = Math.max(focusIdx - 1, 0);
|
|
2618
|
+
options.forEach(function(o) { o.classList.remove('focused'); });
|
|
2619
|
+
options[focusIdx].classList.add('focused');
|
|
2620
|
+
options[focusIdx].scrollIntoView({ block: 'nearest' });
|
|
2621
|
+
} else if (e.key === 'Enter' || e.key === ' ') {
|
|
2622
|
+
e.preventDefault();
|
|
2623
|
+
if (isOpen && focusIdx >= 0) {
|
|
2624
|
+
options[focusIdx].click();
|
|
2625
|
+
} else {
|
|
2626
|
+
sel.classList.toggle('open');
|
|
2627
|
+
}
|
|
2628
|
+
} else if (e.key === 'Escape') {
|
|
2629
|
+
sel.classList.remove('open');
|
|
2630
|
+
options.forEach(function(o) { o.classList.remove('focused'); });
|
|
2631
|
+
}
|
|
2632
|
+
});
|
|
2633
|
+
});
|
|
2634
|
+
|
|
2635
|
+
// Close on outside click
|
|
2636
|
+
document.addEventListener('click', function(e) {
|
|
2637
|
+
if (!e.target.closest) return;
|
|
2638
|
+
if (!e.target.closest('.sui-styled-select')) {
|
|
2639
|
+
document.querySelectorAll('.sui-styled-select.open').forEach(function(s) {
|
|
2640
|
+
s.classList.remove('open');
|
|
2641
|
+
});
|
|
2642
|
+
}
|
|
2643
|
+
});
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2537
2646
|
function initDataTables() {
|
|
2538
2647
|
document.querySelectorAll('.sui-datatable').forEach(function(dt) {
|
|
2539
2648
|
var table = dt.querySelector('.sui-table');
|
|
@@ -2546,9 +2655,16 @@ const SoftUI = (() => {
|
|
|
2546
2655
|
var filteredRows = allRows.slice();
|
|
2547
2656
|
var currentPage = 1;
|
|
2548
2657
|
|
|
2549
|
-
// Per-page selector
|
|
2550
|
-
var
|
|
2551
|
-
var
|
|
2658
|
+
// Per-page selector (supports native <select> and .sui-styled-select)
|
|
2659
|
+
var perpageNative = dt.querySelector('.sui-datatable-perpage select');
|
|
2660
|
+
var perpageStyled = dt.querySelector('.sui-datatable-perpage .sui-styled-select');
|
|
2661
|
+
var perpageSelect = perpageNative || perpageStyled;
|
|
2662
|
+
function getPerpageValue() {
|
|
2663
|
+
if (perpageNative) return parseInt(perpageNative.value, 10);
|
|
2664
|
+
if (perpageStyled) return parseInt(perpageStyled.getAttribute('data-value') || '', 10);
|
|
2665
|
+
return allRows.length;
|
|
2666
|
+
}
|
|
2667
|
+
var perPage = perpageSelect ? getPerpageValue() : allRows.length;
|
|
2552
2668
|
|
|
2553
2669
|
// Info & pagination elements
|
|
2554
2670
|
var infoEl = dt.querySelector('.sui-datatable-info');
|
|
@@ -2634,56 +2750,108 @@ const SoftUI = (() => {
|
|
|
2634
2750
|
}
|
|
2635
2751
|
}
|
|
2636
2752
|
|
|
2637
|
-
//
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2753
|
+
// Filter elements (supports <select> and .sui-dropdown)
|
|
2754
|
+
var filterEls = dt.querySelectorAll('.sui-datatable-filter');
|
|
2755
|
+
|
|
2756
|
+
function getFilterValue(el) {
|
|
2757
|
+
if (el.tagName === 'SELECT') return el.value;
|
|
2758
|
+
// Dropdown-based filter: read from active item
|
|
2759
|
+
var active = el.querySelector('.sui-dropdown-item.active');
|
|
2760
|
+
return active ? (active.getAttribute('data-value') || '') : '';
|
|
2761
|
+
}
|
|
2762
|
+
|
|
2763
|
+
function applyFilters() {
|
|
2764
|
+
var query = searchInput ? searchInput.value.toLowerCase().trim() : '';
|
|
2765
|
+
filteredRows = allRows.filter(function(row) {
|
|
2766
|
+
if (query && row.textContent.toLowerCase().indexOf(query) === -1) return false;
|
|
2767
|
+
var pass = true;
|
|
2768
|
+
filterEls.forEach(function(el) {
|
|
2769
|
+
var attr = el.getAttribute('data-filter-attr') || 'data-status';
|
|
2770
|
+
var val = getFilterValue(el);
|
|
2771
|
+
if (val && row.getAttribute(attr) !== val) pass = false;
|
|
2643
2772
|
});
|
|
2644
|
-
|
|
2645
|
-
render();
|
|
2773
|
+
return pass;
|
|
2646
2774
|
});
|
|
2775
|
+
currentPage = 1;
|
|
2776
|
+
render();
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
// Search input
|
|
2780
|
+
if (searchInput) {
|
|
2781
|
+
searchInput.addEventListener('input', applyFilters);
|
|
2647
2782
|
}
|
|
2648
2783
|
|
|
2784
|
+
// Wire up filters
|
|
2785
|
+
filterEls.forEach(function(el) {
|
|
2786
|
+
if (el.tagName === 'SELECT') {
|
|
2787
|
+
el.addEventListener('change', applyFilters);
|
|
2788
|
+
} else {
|
|
2789
|
+
// Dropdown-based filter
|
|
2790
|
+
el.querySelectorAll('.sui-dropdown-item').forEach(function(item) {
|
|
2791
|
+
item.addEventListener('click', function() {
|
|
2792
|
+
// Update active state
|
|
2793
|
+
el.querySelectorAll('.sui-dropdown-item').forEach(function(i) { i.classList.remove('active'); });
|
|
2794
|
+
item.classList.add('active');
|
|
2795
|
+
// Update label
|
|
2796
|
+
var label = el.querySelector('.sui-datatable-filter-label');
|
|
2797
|
+
if (label) label.textContent = item.textContent;
|
|
2798
|
+
// Close dropdown
|
|
2799
|
+
el.classList.remove('open');
|
|
2800
|
+
var toggle = el.querySelector('.sui-dropdown-toggle');
|
|
2801
|
+
if (toggle) toggle.setAttribute('aria-expanded', 'false');
|
|
2802
|
+
applyFilters();
|
|
2803
|
+
});
|
|
2804
|
+
});
|
|
2805
|
+
}
|
|
2806
|
+
});
|
|
2807
|
+
|
|
2649
2808
|
// Per-page change
|
|
2650
2809
|
if (perpageSelect) {
|
|
2651
2810
|
perpageSelect.addEventListener('change', function() {
|
|
2652
|
-
perPage =
|
|
2811
|
+
perPage = getPerpageValue();
|
|
2653
2812
|
currentPage = 1;
|
|
2654
2813
|
render();
|
|
2655
2814
|
});
|
|
2656
2815
|
}
|
|
2657
2816
|
|
|
2658
|
-
// Sortable headers
|
|
2817
|
+
// Sortable headers (unsorted → asc → desc → unsorted)
|
|
2659
2818
|
var ths = table.querySelectorAll('th[data-sort]');
|
|
2660
2819
|
ths.forEach(function(th) {
|
|
2661
2820
|
th.addEventListener('click', function() {
|
|
2662
|
-
var col = th.getAttribute('data-sort');
|
|
2663
2821
|
var colIndex = Array.prototype.indexOf.call(th.parentElement.children, th);
|
|
2664
|
-
var type =
|
|
2665
|
-
var dir = 'asc';
|
|
2822
|
+
var type = th.getAttribute('data-sort');
|
|
2666
2823
|
|
|
2824
|
+
// Cycle: unsorted → asc → desc → unsorted
|
|
2825
|
+
var dir;
|
|
2667
2826
|
if (th.classList.contains('sort-asc')) {
|
|
2668
2827
|
dir = 'desc';
|
|
2828
|
+
} else if (th.classList.contains('sort-desc')) {
|
|
2829
|
+
dir = 'none';
|
|
2830
|
+
} else {
|
|
2831
|
+
dir = 'asc';
|
|
2669
2832
|
}
|
|
2670
2833
|
|
|
2671
2834
|
// Reset all headers
|
|
2672
2835
|
ths.forEach(function(h) { h.classList.remove('sort-asc', 'sort-desc'); });
|
|
2673
|
-
th.classList.add(dir === 'asc' ? 'sort-asc' : 'sort-desc');
|
|
2674
|
-
|
|
2675
|
-
filteredRows.sort(function(a, b) {
|
|
2676
|
-
var aText = a.children[colIndex] ? a.children[colIndex].textContent.trim() : '';
|
|
2677
|
-
var bText = b.children[colIndex] ? b.children[colIndex].textContent.trim() : '';
|
|
2678
|
-
|
|
2679
|
-
if (type === 'number') {
|
|
2680
|
-
var aNum = parseFloat(aText.replace(/[^0-9.\-]/g, '')) || 0;
|
|
2681
|
-
var bNum = parseFloat(bText.replace(/[^0-9.\-]/g, '')) || 0;
|
|
2682
|
-
return dir === 'asc' ? aNum - bNum : bNum - aNum;
|
|
2683
|
-
}
|
|
2684
2836
|
|
|
2685
|
-
|
|
2686
|
-
|
|
2837
|
+
if (dir === 'none') {
|
|
2838
|
+
// Restore original order within filtered set
|
|
2839
|
+
filteredRows = allRows.filter(function(row) { return filteredRows.indexOf(row) !== -1; });
|
|
2840
|
+
} else {
|
|
2841
|
+
th.classList.add(dir === 'asc' ? 'sort-asc' : 'sort-desc');
|
|
2842
|
+
filteredRows.sort(function(a, b) {
|
|
2843
|
+
var aText = a.children[colIndex] ? a.children[colIndex].textContent.trim() : '';
|
|
2844
|
+
var bText = b.children[colIndex] ? b.children[colIndex].textContent.trim() : '';
|
|
2845
|
+
|
|
2846
|
+
if (type === 'number') {
|
|
2847
|
+
var aNum = parseFloat(aText.replace(/[^0-9.\-]/g, '')) || 0;
|
|
2848
|
+
var bNum = parseFloat(bText.replace(/[^0-9.\-]/g, '')) || 0;
|
|
2849
|
+
return dir === 'asc' ? aNum - bNum : bNum - aNum;
|
|
2850
|
+
}
|
|
2851
|
+
|
|
2852
|
+
return dir === 'asc' ? aText.localeCompare(bText) : bText.localeCompare(aText);
|
|
2853
|
+
});
|
|
2854
|
+
}
|
|
2687
2855
|
|
|
2688
2856
|
// Re-append sorted rows to DOM
|
|
2689
2857
|
filteredRows.forEach(function(row) { tbody.appendChild(row); });
|