@agorapulse/ui-components 20.3.26-beta.1 → 20.3.28
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/agorapulse-ui-components-20.3.28.tgz +0 -0
- package/fesm2022/agorapulse-ui-components-nav-selector.mjs +100 -37
- package/fesm2022/agorapulse-ui-components-nav-selector.mjs.map +1 -1
- package/nav-selector/index.d.ts +6 -1
- package/package.json +1 -1
- package/agorapulse-ui-components-20.3.26-beta.1.tgz +0 -0
|
Binary file
|
|
@@ -1036,6 +1036,9 @@ class NavSelectorBuilder {
|
|
|
1036
1036
|
}
|
|
1037
1037
|
const displayTokenInvalid = children.some(({ displayTokenInvalid }) => displayTokenInvalid);
|
|
1038
1038
|
const selectedChildrenCount = children.filter(({ selected }) => selected).length;
|
|
1039
|
+
// A group is selected if all children are either selected or not selectable
|
|
1040
|
+
// (disabled children must still be selected to count)
|
|
1041
|
+
const selected = children.every(c => c.selected || !c.selectable);
|
|
1039
1042
|
return {
|
|
1040
1043
|
uid: node.uid,
|
|
1041
1044
|
alias: node.alias,
|
|
@@ -1054,9 +1057,9 @@ class NavSelectorBuilder {
|
|
|
1054
1057
|
displayCounter: node.folded && children.some(child => isInternalNavSelectorEntryALeaf(child) && child.counter !== 0),
|
|
1055
1058
|
counter: children.reduce((acc, { counter }) => acc + counter, 0),
|
|
1056
1059
|
displayTokenInvalid,
|
|
1057
|
-
selected
|
|
1060
|
+
selected,
|
|
1058
1061
|
selectable: multipleModeEnabled && children.some(child => child.selectable && !child.disabled),
|
|
1059
|
-
undeterminedSelection:
|
|
1062
|
+
undeterminedSelection: !selected && selectedChildrenCount > 0,
|
|
1060
1063
|
folded: node.folded,
|
|
1061
1064
|
type: node.type,
|
|
1062
1065
|
};
|
|
@@ -1156,11 +1159,10 @@ class NavSelectorBuilder {
|
|
|
1156
1159
|
}
|
|
1157
1160
|
else if (isInternalNavSelectorEntryAGroup(entry)) {
|
|
1158
1161
|
const children = this.setInitialSelection(entry.children, selectedEntryUids);
|
|
1159
|
-
// A group is selected if all
|
|
1160
|
-
|
|
1161
|
-
const
|
|
1162
|
-
const
|
|
1163
|
-
const undeterminedSelection = !selected && selectedChildren.length > 0;
|
|
1162
|
+
// A group is selected if all children are either selected or not selectable
|
|
1163
|
+
// (disabled children must still be selected to count)
|
|
1164
|
+
const selected = children.every(c => c.selected || !c.selectable);
|
|
1165
|
+
const undeterminedSelection = !selected && children.some(c => c.selected);
|
|
1164
1166
|
return {
|
|
1165
1167
|
...entry,
|
|
1166
1168
|
children,
|
|
@@ -1367,14 +1369,14 @@ class NavSelectorMerger {
|
|
|
1367
1369
|
newLeaf.viewMoreDisplayed = oldLeaf.viewMoreDisplayed;
|
|
1368
1370
|
newLeaf.folded = oldLeaf.folded;
|
|
1369
1371
|
newLeaf.displayCounter = newLeaf.folded && newLeaf.counterDisplayable;
|
|
1370
|
-
|
|
1372
|
+
// Don't copy selected state - it's set by the builder based on initialSelectedEntryUids
|
|
1371
1373
|
newLeaf.accessibility.tabIndex = oldLeaf.accessibility.tabIndex;
|
|
1372
1374
|
const oldDetailByUId = associateBy(oldLeaf.details, 'uid');
|
|
1373
1375
|
newLeaf.details.forEach(newDetail => {
|
|
1374
1376
|
if (!oldDetailByUId[newDetail.uid] || newDetail.errorReason) {
|
|
1375
1377
|
return;
|
|
1376
1378
|
}
|
|
1377
|
-
|
|
1379
|
+
// Don't copy selected state - it's set by the builder based on initialSelectedEntryUids
|
|
1378
1380
|
newDetail.accessibility.tabIndex = oldDetailByUId[newDetail.uid].accessibility.tabIndex;
|
|
1379
1381
|
});
|
|
1380
1382
|
}
|
|
@@ -1574,14 +1576,16 @@ class NavSelectorMultiSelect {
|
|
|
1574
1576
|
}
|
|
1575
1577
|
// Recalculate selected and undeterminedSelection based on children
|
|
1576
1578
|
// because disabled items may have retained their selected state.
|
|
1577
|
-
// A group is selected if all children are either
|
|
1578
|
-
|
|
1579
|
+
// A group is selected if all children are either selected or not selectable
|
|
1580
|
+
// (disabled children must still be selected to count)
|
|
1581
|
+
selected = children.every(child => child.selected || (isInternalNavSelectorEntryALeaf(child) && !child.selectable));
|
|
1579
1582
|
undeterminedSelection = !selected && children.some(child => child.selected);
|
|
1580
1583
|
}
|
|
1581
1584
|
else {
|
|
1582
1585
|
children = entry.children.map(child => this.toggleSelectLeaf(child, entryUid));
|
|
1583
|
-
// A group is selected if all children are either
|
|
1584
|
-
|
|
1586
|
+
// A group is selected if all children are either selected or not selectable
|
|
1587
|
+
// (disabled children must still be selected to count)
|
|
1588
|
+
selected = children.every(child => child.selected || (isInternalNavSelectorEntryALeaf(child) && !child.selectable));
|
|
1585
1589
|
undeterminedSelection = !selected && children.some(child => child.selected);
|
|
1586
1590
|
}
|
|
1587
1591
|
return {
|
|
@@ -1619,7 +1623,8 @@ class NavSelectorMultiSelect {
|
|
|
1619
1623
|
if (isInternalNavSelectorEntryALeaf(child)) {
|
|
1620
1624
|
return {
|
|
1621
1625
|
...child,
|
|
1622
|
-
selected
|
|
1626
|
+
// Disabled or non-selectable leafs retain their current selected state
|
|
1627
|
+
selected: child.disabled || !child.selectable ? child.selected : false,
|
|
1623
1628
|
};
|
|
1624
1629
|
}
|
|
1625
1630
|
else if (isInternalNavSelectorEntryACategory(child)) {
|
|
@@ -1628,11 +1633,18 @@ class NavSelectorMultiSelect {
|
|
|
1628
1633
|
children: this.unselectChildren(child.children),
|
|
1629
1634
|
};
|
|
1630
1635
|
}
|
|
1631
|
-
else if (
|
|
1636
|
+
else if (isInternalNavSelectorEntryAGroup(child)) {
|
|
1637
|
+
const children = this.unselectChildren(child.children);
|
|
1638
|
+
// Recalculate group state based on children
|
|
1639
|
+
// A group is selected if all children are either selected or not selectable
|
|
1640
|
+
// (disabled children must still be selected to count)
|
|
1641
|
+
const selected = children.every(c => c.selected || (isInternalNavSelectorEntryALeaf(c) && !c.selectable));
|
|
1642
|
+
const undeterminedSelection = !selected && children.some(c => c.selected);
|
|
1632
1643
|
return {
|
|
1633
1644
|
...child,
|
|
1634
|
-
children
|
|
1635
|
-
selected
|
|
1645
|
+
children,
|
|
1646
|
+
selected,
|
|
1647
|
+
undeterminedSelection,
|
|
1636
1648
|
};
|
|
1637
1649
|
}
|
|
1638
1650
|
return child;
|
|
@@ -1643,7 +1655,8 @@ class NavSelectorMultiSelect {
|
|
|
1643
1655
|
if (isInternalNavSelectorEntryALeaf(child)) {
|
|
1644
1656
|
return {
|
|
1645
1657
|
...child,
|
|
1646
|
-
selected
|
|
1658
|
+
// Disabled or non-selectable leafs retain their current selected state
|
|
1659
|
+
selected: child.disabled || !child.selectable ? child.selected : child.selectable,
|
|
1647
1660
|
};
|
|
1648
1661
|
}
|
|
1649
1662
|
else if (isInternalNavSelectorEntryACategory(child)) {
|
|
@@ -1653,10 +1666,17 @@ class NavSelectorMultiSelect {
|
|
|
1653
1666
|
};
|
|
1654
1667
|
}
|
|
1655
1668
|
else if (isInternalNavSelectorEntryAGroup(child)) {
|
|
1669
|
+
const children = this.selectChildren(child.children);
|
|
1670
|
+
// Recalculate group state based on children
|
|
1671
|
+
// A group is selected if all children are either selected or not selectable
|
|
1672
|
+
// (disabled children must still be selected to count)
|
|
1673
|
+
const selected = children.every(c => c.selected || (isInternalNavSelectorEntryALeaf(c) && !c.selectable));
|
|
1674
|
+
const undeterminedSelection = !selected && children.some(c => c.selected);
|
|
1656
1675
|
return {
|
|
1657
1676
|
...child,
|
|
1658
|
-
children
|
|
1659
|
-
selected
|
|
1677
|
+
children,
|
|
1678
|
+
selected,
|
|
1679
|
+
undeterminedSelection,
|
|
1660
1680
|
};
|
|
1661
1681
|
}
|
|
1662
1682
|
return child;
|
|
@@ -1786,6 +1806,27 @@ class NavSelectorState {
|
|
|
1786
1806
|
search = signal('', ...(ngDevMode ? [{ debugName: "search" }] : []));
|
|
1787
1807
|
noResults = computed(() => this._entries().every(({ hidden }) => hidden), ...(ngDevMode ? [{ debugName: "noResults" }] : []));
|
|
1788
1808
|
texts = this._texts.asReadonly();
|
|
1809
|
+
isAllSelected = computed(() => {
|
|
1810
|
+
if (!this.multipleModeEnabled()) {
|
|
1811
|
+
return false;
|
|
1812
|
+
}
|
|
1813
|
+
const entries = this._entries();
|
|
1814
|
+
return this.areAllSelectableItemsSelected(entries);
|
|
1815
|
+
}, ...(ngDevMode ? [{ debugName: "isAllSelected" }] : []));
|
|
1816
|
+
isSelectAllIndeterminate = computed(() => {
|
|
1817
|
+
if (!this.multipleModeEnabled()) {
|
|
1818
|
+
return false;
|
|
1819
|
+
}
|
|
1820
|
+
const entries = this._entries();
|
|
1821
|
+
const allSelected = this.areAllSelectableItemsSelected(entries);
|
|
1822
|
+
if (allSelected) {
|
|
1823
|
+
return false;
|
|
1824
|
+
}
|
|
1825
|
+
// Check if ANY item is selected (including disabled/mandatory items)
|
|
1826
|
+
// This matches the behavior of group checkboxes
|
|
1827
|
+
const selectedUids = this.collectSelectedUids(entries);
|
|
1828
|
+
return selectedUids.length > 0;
|
|
1829
|
+
}, ...(ngDevMode ? [{ debugName: "isSelectAllIndeterminate" }] : []));
|
|
1789
1830
|
expanded = signal(true, ...(ngDevMode ? [{ debugName: "expanded" }] : []));
|
|
1790
1831
|
previousSelectedUids = [];
|
|
1791
1832
|
selectedUidsChangeCallback = null;
|
|
@@ -1998,6 +2039,35 @@ class NavSelectorState {
|
|
|
1998
2039
|
resetFocus() {
|
|
1999
2040
|
this._entries.update(entries => NavSelectorAccessibility.resetFocus(entries));
|
|
2000
2041
|
}
|
|
2042
|
+
toggleSelectAll() {
|
|
2043
|
+
if (!this.multipleModeEnabled()) {
|
|
2044
|
+
return;
|
|
2045
|
+
}
|
|
2046
|
+
this._entries.update(entries => {
|
|
2047
|
+
const allSelected = this.areAllSelectableItemsSelected(entries);
|
|
2048
|
+
return allSelected ? NavSelectorMultiSelect.unselectAll(entries) : NavSelectorMultiSelect.selectAll(entries);
|
|
2049
|
+
});
|
|
2050
|
+
}
|
|
2051
|
+
areAllSelectableItemsSelected(entries) {
|
|
2052
|
+
const selectableNonDisabledUids = this.collectSelectableNonDisabledUids(entries);
|
|
2053
|
+
const selectedUids = this.collectSelectedUids(entries);
|
|
2054
|
+
if (selectableNonDisabledUids.length === 0) {
|
|
2055
|
+
return false;
|
|
2056
|
+
}
|
|
2057
|
+
return selectableNonDisabledUids.every(uid => selectedUids.includes(uid));
|
|
2058
|
+
}
|
|
2059
|
+
collectSelectableNonDisabledUids(entries) {
|
|
2060
|
+
return entries.flatMap(entry => {
|
|
2061
|
+
if (isInternalNavSelectorEntryALeaf(entry)) {
|
|
2062
|
+
// Only include selectable and non-disabled items (user-interactable)
|
|
2063
|
+
return entry.selectable && !entry.disabled ? [entry.uid] : [];
|
|
2064
|
+
}
|
|
2065
|
+
else if (isInternalNavSelectorEntryANode(entry)) {
|
|
2066
|
+
return this.collectSelectableNonDisabledUids(entry.children);
|
|
2067
|
+
}
|
|
2068
|
+
return [];
|
|
2069
|
+
});
|
|
2070
|
+
}
|
|
2001
2071
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: NavSelectorState, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2002
2072
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: NavSelectorState });
|
|
2003
2073
|
}
|
|
@@ -2934,12 +3004,10 @@ class NavSelectorComponent {
|
|
|
2934
3004
|
el = inject(ElementRef);
|
|
2935
3005
|
componentUid = `nav-selector-${nextUniqueId++}`;
|
|
2936
3006
|
ready = signal(false, ...(ngDevMode ? [{ debugName: "ready" }] : []));
|
|
3007
|
+
stableNavSelectorEntries = computed(() => this.navSelectorEntries(), ...(ngDevMode ? [{ debugName: "stableNavSelectorEntries", equal: isEqual }] : [{ equal: isEqual }]));
|
|
2937
3008
|
expanded = this.navSelectorState.expanded.asReadonly();
|
|
2938
3009
|
entries = computed(() => this.navSelectorState.entries(), ...(ngDevMode ? [{ debugName: "entries", equal: isEqual }] : [{ equal: isEqual }]));
|
|
2939
3010
|
selectableEntryUids = computed(() => computeSelectableUids(this.entries()), ...(ngDevMode ? [{ debugName: "selectableEntryUids", equal: isEqual }] : [{ equal: isEqual }]));
|
|
2940
|
-
existingSelectableUids = computed(() => this.selectedEntryUids().filter(uid => this.selectableEntryUids().includes(uid)), ...(ngDevMode ? [{ debugName: "existingSelectableUids", equal: isEqual }] : [{
|
|
2941
|
-
equal: isEqual,
|
|
2942
|
-
}]));
|
|
2943
3011
|
visibleEntryUids = computed(() => computeVisibleUids(this.entries()), ...(ngDevMode ? [{ debugName: "visibleEntryUids", equal: isEqual }] : [{ equal: isEqual }]));
|
|
2944
3012
|
visibleAccountsChange = outputFromObservable(toObservable(this.visibleEntryUids).pipe(map(visibleAccountUids => ({ visibleAccountUids }))));
|
|
2945
3013
|
constructor() {
|
|
@@ -2962,17 +3030,19 @@ class NavSelectorComponent {
|
|
|
2962
3030
|
const expanded = this.expanded();
|
|
2963
3031
|
untracked(() => this.onExpansionStateChange.emit({ expanded }));
|
|
2964
3032
|
});
|
|
3033
|
+
// When inputs change, rebuild entries with current selected uids
|
|
2965
3034
|
effect(() => {
|
|
2966
|
-
// When AS inputs changes, rebuild AS with current initial selected uids
|
|
2967
3035
|
const multipleModeEnabled = this.multipleModeEnabled();
|
|
2968
|
-
const newEntries = this.
|
|
3036
|
+
const newEntries = this.stableNavSelectorEntries();
|
|
3037
|
+
const selectedUids = this.selectedEntryUids();
|
|
2969
3038
|
untracked(() => {
|
|
2970
3039
|
this.navSelectorState.updateMultiModeEnabled(multipleModeEnabled);
|
|
3040
|
+
const limit = this.detailsDisplayedLimit();
|
|
2971
3041
|
if (!this.entries().length) {
|
|
2972
|
-
this.navSelectorState.initEntries(newEntries,
|
|
3042
|
+
this.navSelectorState.initEntries(newEntries, selectedUids, limit);
|
|
2973
3043
|
}
|
|
2974
3044
|
else {
|
|
2975
|
-
this.navSelectorState.updateEntries(newEntries,
|
|
3045
|
+
this.navSelectorState.updateEntries(newEntries, selectedUids, limit);
|
|
2976
3046
|
}
|
|
2977
3047
|
});
|
|
2978
3048
|
});
|
|
@@ -2980,16 +3050,9 @@ class NavSelectorComponent {
|
|
|
2980
3050
|
const detailsDisplayedLimit = this.detailsDisplayedLimit();
|
|
2981
3051
|
untracked(() => this.navSelectorState.updateDetailsDisplayedLimit(detailsDisplayedLimit));
|
|
2982
3052
|
});
|
|
2983
|
-
effect
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
untracked(() => {
|
|
2987
|
-
if (isInit) {
|
|
2988
|
-
// Trigger selection change when initial selectedEntryUids model changes
|
|
2989
|
-
this.navSelectorState.onSelectionChange(existingSelectableUids);
|
|
2990
|
-
}
|
|
2991
|
-
});
|
|
2992
|
-
});
|
|
3053
|
+
// Note: No longer need of a separate effect for selectedEntryUids changes
|
|
3054
|
+
// The effect above (line 166) now watches selectedEntryUids and calls updateEntries
|
|
3055
|
+
// which properly handles disabled items through the builder
|
|
2993
3056
|
effect(() => {
|
|
2994
3057
|
const translatedTexts = this.translatedTexts();
|
|
2995
3058
|
untracked(() => this.navSelectorState.updateTexts(translatedTexts));
|