@agorapulse/ui-components 18.0.8 → 18.0.10

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.
Files changed (92) hide show
  1. package/agorapulse-ui-components-18.0.10.tgz +0 -0
  2. package/avatar/avatar.component.d.ts +1 -1
  3. package/checkbox/checkbox.component.d.ts +3 -3
  4. package/close-button/close-button.component.d.ts +4 -4
  5. package/datepicker/datepicker.component.d.ts +1 -1
  6. package/esm2022/avatar/avatar.component.mjs +4 -3
  7. package/esm2022/checkbox/checkbox.component.mjs +7 -7
  8. package/esm2022/close-button/close-button.component.mjs +6 -6
  9. package/esm2022/datepicker/datepicker.component.mjs +2 -2
  10. package/esm2022/index.mjs +2 -1
  11. package/esm2022/infobox/infobox.component.mjs +1 -1
  12. package/esm2022/input-search/input-search.component.mjs +5 -4
  13. package/esm2022/labels/label.component.mjs +1 -1
  14. package/esm2022/nav-selector/agorapulse-ui-components-nav-selector.mjs +5 -0
  15. package/esm2022/nav-selector/directives/tree-node-accessibility.directive.mjs +30 -0
  16. package/esm2022/nav-selector/nav-selector-category/nav-selector-category.component.mjs +81 -0
  17. package/esm2022/nav-selector/nav-selector-category/nav-selector-category.presenter.mjs +29 -0
  18. package/esm2022/nav-selector/nav-selector-group/nav-selector-group.component.mjs +142 -0
  19. package/esm2022/nav-selector/nav-selector-group/nav-selector-group.presenter.mjs +31 -0
  20. package/esm2022/nav-selector/nav-selector-leaf/nav-selector-leaf.component.mjs +240 -0
  21. package/esm2022/nav-selector/nav-selector-leaf/nav-selector-leaf.presenter.mjs +35 -0
  22. package/esm2022/nav-selector/nav-selector-leaf-detail/nav-selector-leaf-detail.component.mjs +39 -0
  23. package/esm2022/nav-selector/nav-selector-leaf-detail/nav-selector-leaf-detail.presenter.mjs +18 -0
  24. package/esm2022/nav-selector/nav-selector-leaf-details/nav-selector-leaf-details.component.mjs +92 -0
  25. package/esm2022/nav-selector/nav-selector-leaf-details/nav-selector-leaf-details.presenter.mjs +31 -0
  26. package/esm2022/nav-selector/nav-selector.component.mjs +123 -0
  27. package/esm2022/nav-selector/nav-selector.mjs +9 -0
  28. package/esm2022/nav-selector/nav-selector.state.mjs +173 -0
  29. package/esm2022/nav-selector/public_api.mjs +2 -0
  30. package/esm2022/nav-selector/utils/leaf.utils.mjs +10 -0
  31. package/esm2022/nav-selector/utils/nav-selector.accessibility.mjs +171 -0
  32. package/esm2022/nav-selector/utils/nav-selector.builder.mjs +263 -0
  33. package/esm2022/nav-selector/utils/nav-selector.filter.mjs +102 -0
  34. package/esm2022/nav-selector/utils/nav-selector.folding.mjs +219 -0
  35. package/esm2022/nav-selector/utils/nav-selector.minifying.mjs +50 -0
  36. package/esm2022/nav-selector/utils/nav-selector.multi-select.mjs +208 -0
  37. package/esm2022/nav-selector/utils/nav-selector.single-select.mjs +91 -0
  38. package/esm2022/nav-selector/utils/nav-selector.view-more.mjs +98 -0
  39. package/esm2022/snackbars-thread/component/snackbars-thread.component.mjs +2 -2
  40. package/esm2022/tag/tag.component.mjs +7 -5
  41. package/fesm2022/agorapulse-ui-components-avatar.mjs +3 -2
  42. package/fesm2022/agorapulse-ui-components-avatar.mjs.map +1 -1
  43. package/fesm2022/agorapulse-ui-components-checkbox.mjs +6 -6
  44. package/fesm2022/agorapulse-ui-components-checkbox.mjs.map +1 -1
  45. package/fesm2022/agorapulse-ui-components-close-button.mjs +5 -5
  46. package/fesm2022/agorapulse-ui-components-close-button.mjs.map +1 -1
  47. package/fesm2022/agorapulse-ui-components-datepicker.mjs +1 -1
  48. package/fesm2022/agorapulse-ui-components-datepicker.mjs.map +1 -1
  49. package/fesm2022/agorapulse-ui-components-infobox.mjs +1 -1
  50. package/fesm2022/agorapulse-ui-components-infobox.mjs.map +1 -1
  51. package/fesm2022/agorapulse-ui-components-input-search.mjs +4 -3
  52. package/fesm2022/agorapulse-ui-components-input-search.mjs.map +1 -1
  53. package/fesm2022/agorapulse-ui-components-labels.mjs +1 -1
  54. package/fesm2022/agorapulse-ui-components-labels.mjs.map +1 -1
  55. package/fesm2022/agorapulse-ui-components-nav-selector.mjs +2198 -0
  56. package/fesm2022/agorapulse-ui-components-nav-selector.mjs.map +1 -0
  57. package/fesm2022/agorapulse-ui-components-snackbars-thread.mjs +1 -1
  58. package/fesm2022/agorapulse-ui-components-snackbars-thread.mjs.map +1 -1
  59. package/fesm2022/agorapulse-ui-components-tag.mjs +6 -4
  60. package/fesm2022/agorapulse-ui-components-tag.mjs.map +1 -1
  61. package/fesm2022/agorapulse-ui-components.mjs +1 -0
  62. package/fesm2022/agorapulse-ui-components.mjs.map +1 -1
  63. package/index.d.ts +1 -0
  64. package/input-search/input-search.component.d.ts +1 -1
  65. package/nav-selector/directives/tree-node-accessibility.directive.d.ts +9 -0
  66. package/nav-selector/index.d.ts +5 -0
  67. package/nav-selector/nav-selector-category/nav-selector-category.component.d.ts +16 -0
  68. package/nav-selector/nav-selector-category/nav-selector-category.presenter.d.ts +14 -0
  69. package/nav-selector/nav-selector-group/nav-selector-group.component.d.ts +29 -0
  70. package/nav-selector/nav-selector-group/nav-selector-group.presenter.d.ts +17 -0
  71. package/nav-selector/nav-selector-leaf/nav-selector-leaf.component.d.ts +51 -0
  72. package/nav-selector/nav-selector-leaf/nav-selector-leaf.presenter.d.ts +19 -0
  73. package/nav-selector/nav-selector-leaf-detail/nav-selector-leaf-detail.component.d.ts +13 -0
  74. package/nav-selector/nav-selector-leaf-detail/nav-selector-leaf-detail.presenter.d.ts +10 -0
  75. package/nav-selector/nav-selector-leaf-details/nav-selector-leaf-details.component.d.ts +24 -0
  76. package/nav-selector/nav-selector-leaf-details/nav-selector-leaf-details.presenter.d.ts +14 -0
  77. package/nav-selector/nav-selector.component.d.ts +29 -0
  78. package/nav-selector/nav-selector.d.ts +220 -0
  79. package/nav-selector/nav-selector.state.d.ts +47 -0
  80. package/nav-selector/public_api.d.ts +2 -0
  81. package/nav-selector/utils/leaf.utils.d.ts +5 -0
  82. package/nav-selector/utils/nav-selector.accessibility.d.ts +52 -0
  83. package/nav-selector/utils/nav-selector.builder.d.ts +32 -0
  84. package/nav-selector/utils/nav-selector.filter.d.ts +30 -0
  85. package/nav-selector/utils/nav-selector.folding.d.ts +47 -0
  86. package/nav-selector/utils/nav-selector.minifying.d.ts +27 -0
  87. package/nav-selector/utils/nav-selector.multi-select.d.ts +54 -0
  88. package/nav-selector/utils/nav-selector.single-select.d.ts +15 -0
  89. package/nav-selector/utils/nav-selector.view-more.d.ts +30 -0
  90. package/package.json +7 -1
  91. package/tag/tag.component.d.ts +3 -1
  92. package/agorapulse-ui-components-18.0.8.tgz +0 -0
@@ -0,0 +1,2198 @@
1
+ import { IconButtonComponent } from '@agorapulse/ui-components/icon-button';
2
+ import { InputSearchComponent } from '@agorapulse/ui-components/input-search';
3
+ import { SymbolComponent, withSymbols, apErrorFill, apFeatureLock, apChevronDown, apChevronUp, apFolder, apArrowExpand, apArrowReduce, apSearch } from '@agorapulse/ui-symbol';
4
+ import { trigger, state, transition, style, animate, keyframes } from '@angular/animations';
5
+ import { NgTemplateOutlet } from '@angular/common';
6
+ import * as i0 from '@angular/core';
7
+ import { input, afterRender, Directive, signal, computed, effect, Injectable, ChangeDetectionStrategy, Component, viewChild, afterNextRender, model, contentChild, contentChildren, TemplateRef } from '@angular/core';
8
+ import * as i2 from '@angular/forms';
9
+ import { FormsModule } from '@angular/forms';
10
+ import { EventPluginsModule } from '@tinkoff/ng-event-plugins';
11
+ import { AvatarComponent } from '@agorapulse/ui-components/avatar';
12
+ import { CheckboxComponent } from '@agorapulse/ui-components/checkbox';
13
+ import { CounterComponent } from '@agorapulse/ui-components/counter';
14
+ import { TooltipDirective } from '@agorapulse/ui-components/tooltip';
15
+ import { apMore } from '@agorapulse/ui-symbol/icons';
16
+ import { MatMenu, MatMenuTrigger, MatMenuItem } from '@angular/material/menu';
17
+
18
+ class TreeNodeAccessibilityDirective {
19
+ apTreeNodeAccessibility = input.required();
20
+ constructor(el, renderer) {
21
+ afterRender(() => {
22
+ const nativeEl = el.nativeElement;
23
+ const entry = this.apTreeNodeAccessibility();
24
+ renderer.setAttribute(nativeEl, 'aria-level', `${entry.accessibility.ariaLevel}`);
25
+ renderer.setAttribute(nativeEl, 'aria-setsize', `${entry.accessibility.ariaSetsize}`);
26
+ renderer.setAttribute(nativeEl, 'aria-posinset', `${entry.accessibility.ariaPosinset}`);
27
+ renderer.setAttribute(nativeEl, 'tabindex', `${entry.accessibility.tabIndex}`);
28
+ renderer.setAttribute(nativeEl, 'aria-label', `${entry.alias}`);
29
+ if ('folded' in entry) {
30
+ renderer.setAttribute(nativeEl, 'aria-expanded', `${entry.folded}`);
31
+ }
32
+ renderer.setAttribute(nativeEl, 'role', 'treeitem');
33
+ });
34
+ }
35
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TreeNodeAccessibilityDirective, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
36
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.9", type: TreeNodeAccessibilityDirective, isStandalone: true, selector: "[apTreeNodeAccessibility]", inputs: { apTreeNodeAccessibility: { classPropertyName: "apTreeNodeAccessibility", publicName: "apTreeNodeAccessibility", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
37
+ }
38
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: TreeNodeAccessibilityDirective, decorators: [{
39
+ type: Directive,
40
+ args: [{
41
+ selector: '[apTreeNodeAccessibility]',
42
+ standalone: true,
43
+ }]
44
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }] });
45
+
46
+ const isNavSelectorEntryALeaf = (entry) => entry.type === 'LEAF';
47
+ const isNavSelectorEntryAGroup = (entry) => entry.type === 'GROUP';
48
+ const isNavSelectorEntryACategory = (entry) => entry.type === 'CATEGORY';
49
+ const isInternalNavSelectorEntryALeaf = (entry) => entry.type === 'LEAF';
50
+ const isInternalNavSelectorEntryANode = (entry) => `children` in entry;
51
+ const isInternalNavSelectorEntryACategory = (entry) => entry.type === 'CATEGORY';
52
+ const isInternalNavSelectorEntryAGroup = (entry) => entry.type === 'GROUP';
53
+ const isInternalNavSelectorEntryALeafDetails = (entry) => entry.type === 'LEAF_DETAILS';
54
+
55
+ /**
56
+ * NavSelectorAccessibility is a utility class that provides methods to manage the accessibility and the focusability of nav selector entries.
57
+ */
58
+ class NavSelectorAccessibility {
59
+ /**
60
+ * Set tabIndex to 0 for the first focusable entry and -1 for all other entries
61
+ * @param entries nav selector entries
62
+ */
63
+ static resetFocus(entries) {
64
+ return entries.reduce((acc, entry) => {
65
+ if (!acc.length) {
66
+ return [{ ...entry, accessibility: { ...entry.accessibility, tabIndex: entry.focusable ? 0 : -1 } }];
67
+ }
68
+ if (acc.every(({ focusable }) => !focusable)) {
69
+ return [...acc, { ...entry, accessibility: { ...entry.accessibility, tabIndex: entry.focusable ? 0 : -1 } }];
70
+ }
71
+ return [...acc, entry];
72
+ }, []);
73
+ }
74
+ /**
75
+ * Focus the given entry and set tabIndex to 0 for the given uid and -1 for all other entries
76
+ * @param entries nav selector entries
77
+ * @param uid the uid of the entry to focus
78
+ */
79
+ static focus(entries, uid) {
80
+ return entries.map(entry => {
81
+ if (isInternalNavSelectorEntryAGroup(entry) || isInternalNavSelectorEntryACategory(entry)) {
82
+ return {
83
+ ...this.focusAnEntry(entry, uid),
84
+ children: NavSelectorAccessibility.focus(entry.children, uid),
85
+ };
86
+ }
87
+ if (isInternalNavSelectorEntryALeaf(entry)) {
88
+ return {
89
+ ...this.focusAnEntry(entry, uid),
90
+ details: entry.details.map(detail => this.focusAnEntry(detail, uid)),
91
+ };
92
+ }
93
+ return this.focusAnEntry(entry, uid);
94
+ });
95
+ }
96
+ /**
97
+ * Unfocus the given entry and set tabIndex to -1 for the given uid and 0 for all other entries
98
+ * @param entries nav selector entries
99
+ * @param uid the uid of the entry to unfocus
100
+ */
101
+ static unfocus(entries, uid) {
102
+ return entries.map(entry => {
103
+ if (isInternalNavSelectorEntryAGroup(entry) || isInternalNavSelectorEntryACategory(entry)) {
104
+ return {
105
+ ...this.unfocusAnEntry(entry, uid),
106
+ children: NavSelectorAccessibility.unfocus(entry.children, uid),
107
+ };
108
+ }
109
+ if (isInternalNavSelectorEntryALeaf(entry)) {
110
+ return {
111
+ ...this.unfocusAnEntry(entry, uid),
112
+ details: entry.details.map(detail => this.unfocusAnEntry(detail, uid)),
113
+ };
114
+ }
115
+ return this.unfocusAnEntry(entry, uid);
116
+ });
117
+ }
118
+ /**
119
+ * Focus the previous entry focusable and set tabIndex to 0 for the previous focusable entry and -1 for all other entries
120
+ *
121
+ * If not previous entries are focusable, entries will not be modified
122
+ *
123
+ * @param entries nav selector entries
124
+ */
125
+ static focusPrevious(entries) {
126
+ const flattenEntries = this.flatten(entries);
127
+ const idxFocusedId = flattenEntries.findIndex(({ accessibility }) => accessibility.tabIndex === 0);
128
+ if (idxFocusedId === 0 || this.previousEntryIsFirstAndNotFocusable(flattenEntries, idxFocusedId)) {
129
+ return entries;
130
+ }
131
+ const focusedEntry = flattenEntries[idxFocusedId];
132
+ focusedEntry.accessibility.tabIndex = -1;
133
+ for (let i = idxFocusedId - 1; i >= 0; i--) {
134
+ const entry = flattenEntries[i];
135
+ if (entry.focusable) {
136
+ entry.accessibility.tabIndex = 0;
137
+ break;
138
+ }
139
+ }
140
+ return this.unflatten(flattenEntries);
141
+ }
142
+ /**
143
+ * Focus the next entry focusable and set tabIndex to 0 for the next focusable entry and -1 for all other entries
144
+ *
145
+ * If not next entries are focusable, entries will not be modified
146
+ *
147
+ * @param entries nav selector entries
148
+ */
149
+ static focusNext(entries) {
150
+ const flattenEntries = this.flatten(entries);
151
+ const focusableFlattenEntries = flattenEntries.filter(entry => entry.focusable);
152
+ const idxFocusedId = focusableFlattenEntries.findIndex(({ accessibility }) => accessibility.tabIndex === 0);
153
+ if (focusableFlattenEntries.length - 1 <= idxFocusedId) {
154
+ return entries;
155
+ }
156
+ focusableFlattenEntries[idxFocusedId].accessibility.tabIndex = -1;
157
+ focusableFlattenEntries[idxFocusedId + 1].accessibility.tabIndex = 0;
158
+ return this.unflatten(flattenEntries);
159
+ }
160
+ static previousEntryIsFirstAndNotFocusable(flattenEntries, idxFocusedId) {
161
+ if (idxFocusedId - 1 === 0) {
162
+ const previous = flattenEntries[0];
163
+ return !previous.focusable;
164
+ }
165
+ return false;
166
+ }
167
+ static focusAnEntry(entry, uid) {
168
+ return { ...entry, accessibility: { ...entry.accessibility, tabIndex: entry.uid === uid ? 0 : -1 } };
169
+ }
170
+ static unfocusAnEntry(entry, uid) {
171
+ return { ...entry, accessibility: { ...entry.accessibility, tabIndex: entry.uid === uid ? -1 : entry.accessibility.tabIndex } };
172
+ }
173
+ /**
174
+ * Flatten the nav selector entries. It is easier to work with flat entries for the focus management as we need to know which is the previous or the next entry
175
+ * @param entries nav selector entries
176
+ */
177
+ static flatten(entries) {
178
+ return entries.flatMap(entry => {
179
+ if (isInternalNavSelectorEntryAGroup(entry) || isInternalNavSelectorEntryACategory(entry)) {
180
+ return [{ ...entry, children: [] }, ...this.flatten(entry.children)];
181
+ }
182
+ if (isInternalNavSelectorEntryALeaf(entry)) {
183
+ return [{ ...entry, details: [] }, ...entry.details.map(detail => ({ ...detail }))];
184
+ }
185
+ return [{ ...entry }];
186
+ });
187
+ }
188
+ /**
189
+ * Unflatten the nav selector entries
190
+ * @param entries nav selector entries
191
+ */
192
+ static unflatten(entries) {
193
+ return entries.reduceRight((acc, entry) => {
194
+ if (!acc.length) {
195
+ return [entry];
196
+ }
197
+ if (entry.accessibility.ariaLevel < acc[0].accessibility.ariaLevel) {
198
+ if (isInternalNavSelectorEntryALeaf(entry)) {
199
+ return [
200
+ {
201
+ ...entry,
202
+ details: acc
203
+ .filter(it => isInternalNavSelectorEntryALeafDetails(it))
204
+ // Force destroying the reference to the original object else Angular will not detect the change
205
+ .map(it => ({ ...it })),
206
+ },
207
+ ...acc.filter(it => !isInternalNavSelectorEntryALeafDetails(it)),
208
+ ];
209
+ }
210
+ else if (isInternalNavSelectorEntryAGroup(entry) || isInternalNavSelectorEntryACategory(entry)) {
211
+ return [
212
+ {
213
+ ...entry,
214
+ children: acc.filter(({ accessibility }) => accessibility.ariaLevel > entry.accessibility.ariaLevel),
215
+ },
216
+ ...acc.filter(({ accessibility }) => accessibility.ariaLevel <= entry.accessibility.ariaLevel),
217
+ ];
218
+ }
219
+ }
220
+ return [entry, ...acc];
221
+ }, []);
222
+ }
223
+ }
224
+
225
+ /**
226
+ * NavSelectorMultiSelect is a utility class that provides methods to select an entry in multiple mode.
227
+ */
228
+ class NavSelectorMultiSelect {
229
+ /**
230
+ * Select an entry in multiple mode.
231
+ *
232
+ * Categories are not selectable.
233
+ *
234
+ * Groups and leaves are selectable.
235
+ *
236
+ * Groups may be in undetermined state if some of their children are selected and some are not.
237
+ * @param entries nav selector entries
238
+ * @param entryUid the entry uid to select
239
+ */
240
+ static selectInMultipleMode(entries, entryUid) {
241
+ return entries.map(entry => {
242
+ if (isInternalNavSelectorEntryALeaf(entry)) {
243
+ return this.selectALeafInMultipleMode(entry, entryUid);
244
+ }
245
+ else if (isInternalNavSelectorEntryAGroup(entry)) {
246
+ return this.selectAGroupInMultipleMode(entry, entryUid);
247
+ }
248
+ else if (isInternalNavSelectorEntryACategory(entry)) {
249
+ return this.selectACategoryInMultipleMode(entry, entryUid);
250
+ }
251
+ return entry;
252
+ });
253
+ }
254
+ /**
255
+ * Select only a leaf in multiple mode.
256
+ *
257
+ * Categories are not selectable.
258
+ *
259
+ * Groups may be in undetermined state if some of their children are selected and some are not.
260
+ * @param entries nav selector entries
261
+ * @param entryUid the entry uid to select
262
+ */
263
+ static selectOnlyALeafInMultipleMode(entries, entryUid) {
264
+ return entries.map(entry => {
265
+ if (isInternalNavSelectorEntryALeaf(entry)) {
266
+ return {
267
+ ...entry,
268
+ selected: entry.uid === entryUid,
269
+ };
270
+ }
271
+ else if (isInternalNavSelectorEntryACategory(entry)) {
272
+ return {
273
+ ...entry,
274
+ children: this.selectOnlyALeafInMultipleMode(entry.children, entryUid),
275
+ };
276
+ }
277
+ else if (isInternalNavSelectorEntryAGroup(entry)) {
278
+ const children = entry.children.flatMap(child => this.selectOnlyALeafInMultipleMode([child], entryUid));
279
+ const selected = children.every(child => child.selected || (isInternalNavSelectorEntryALeaf(child) && !child.selectable));
280
+ return {
281
+ ...entry,
282
+ children,
283
+ selected,
284
+ undeterminedSelection: !selected && children.some(child => child.selected),
285
+ };
286
+ }
287
+ return entry;
288
+ });
289
+ }
290
+ /**
291
+ * Select all entries in multiple mode.
292
+ *
293
+ * Categories are not selectable.
294
+ *
295
+ * Groups and leaves are selectable.
296
+ * @param entries nav selector entries
297
+ */
298
+ static selectAll(entries) {
299
+ return this.selectChildren(entries);
300
+ }
301
+ /**
302
+ * Unselect all entries in multiple mode.
303
+ *
304
+ * Categories are not selectable.
305
+ *
306
+ * Groups and leaves are selectable.
307
+ * @param entries nav selector entries
308
+ */
309
+ static unselectAll(entries) {
310
+ return this.unselectChildren(entries);
311
+ }
312
+ static selectALeafInMultipleMode(leaf, entryUid) {
313
+ let selected = false;
314
+ if (leaf.selectable) {
315
+ selected = leaf.uid === entryUid ? !leaf.selected : leaf.selected;
316
+ }
317
+ return {
318
+ ...leaf,
319
+ selected,
320
+ };
321
+ }
322
+ static selectACategoryInMultipleMode(entry, entryUid) {
323
+ return {
324
+ ...entry,
325
+ children: entry.children.map(child => {
326
+ if (isInternalNavSelectorEntryALeaf(child)) {
327
+ return this.selectALeafInMultipleMode(child, entryUid);
328
+ }
329
+ return this.selectAGroupInMultipleMode(child, entryUid);
330
+ }),
331
+ };
332
+ }
333
+ static selectAGroupInMultipleMode(entry, entryUid) {
334
+ if (!entry.selectable) {
335
+ return entry;
336
+ }
337
+ let selected;
338
+ let children;
339
+ let undeterminedSelection = false;
340
+ if (entry.uid === entryUid) {
341
+ selected = !entry.selected;
342
+ if (selected) {
343
+ children = this.selectLeafs(entry.children);
344
+ }
345
+ else {
346
+ children = this.unselectLeafs(entry.children);
347
+ }
348
+ }
349
+ else {
350
+ children = entry.children.map(child => this.toggleSelectLeaf(child, entryUid));
351
+ selected = children.every(child => child.selected || (isInternalNavSelectorEntryALeaf(child) && !child.selectable));
352
+ undeterminedSelection = !selected && children.some(child => child.selected);
353
+ }
354
+ return {
355
+ ...entry,
356
+ children,
357
+ selected,
358
+ undeterminedSelection,
359
+ };
360
+ }
361
+ static toggleSelectLeaf(leaf, uid) {
362
+ if (leaf.uid === uid) {
363
+ return {
364
+ ...leaf,
365
+ selected: !leaf.selected,
366
+ };
367
+ }
368
+ return leaf;
369
+ }
370
+ static selectLeafs(leafs) {
371
+ return leafs.map(leaf => ({
372
+ ...leaf,
373
+ selected: true,
374
+ }));
375
+ }
376
+ static unselectLeafs(leafs) {
377
+ return leafs.map(leaf => ({
378
+ ...leaf,
379
+ selected: false,
380
+ }));
381
+ }
382
+ static unselectChildren(entry) {
383
+ return entry.map(child => {
384
+ if (isInternalNavSelectorEntryALeaf(child)) {
385
+ return {
386
+ ...child,
387
+ selected: false,
388
+ };
389
+ }
390
+ else if (isInternalNavSelectorEntryACategory(child)) {
391
+ return {
392
+ ...child,
393
+ children: this.unselectChildren(child.children),
394
+ };
395
+ }
396
+ else if (isInternalNavSelectorEntryANode(child)) {
397
+ return {
398
+ ...child,
399
+ children: this.unselectChildren(child.children),
400
+ selected: false,
401
+ };
402
+ }
403
+ return child;
404
+ });
405
+ }
406
+ static selectChildren(entry) {
407
+ return entry.map(child => {
408
+ if (isInternalNavSelectorEntryALeaf(child)) {
409
+ return {
410
+ ...child,
411
+ selected: child.selectable,
412
+ };
413
+ }
414
+ else if (isInternalNavSelectorEntryACategory(child)) {
415
+ return {
416
+ ...child,
417
+ children: this.selectChildren(child.children),
418
+ };
419
+ }
420
+ else if (isInternalNavSelectorEntryAGroup(child)) {
421
+ return {
422
+ ...child,
423
+ children: this.selectChildren(child.children),
424
+ selected: true,
425
+ };
426
+ }
427
+ return child;
428
+ });
429
+ }
430
+ }
431
+
432
+ /**
433
+ * NavSelectorSingleSelect is a utility class that provides methods to select a single entry in a nav selector.
434
+ */
435
+ class NavSelectorSingleSelect {
436
+ /**
437
+ * Selects a single entry in the nav selector.
438
+ * @param entries nav selector entries
439
+ * @param entryUid the entry uid to select
440
+ */
441
+ static select(entries, entryUid) {
442
+ return entries.map(entry => {
443
+ if (isInternalNavSelectorEntryALeaf(entry)) {
444
+ return this.selectALeaf(entry, entryUid);
445
+ }
446
+ else if (isInternalNavSelectorEntryANode(entry)) {
447
+ return {
448
+ ...entry,
449
+ children: entry.children.flatMap(child => this.select([child], entryUid)),
450
+ };
451
+ }
452
+ return entry;
453
+ });
454
+ }
455
+ static selectALeaf(leaf, entryUid) {
456
+ if (!!leaf.details.length) {
457
+ return this.selectALeafWithDetails(leaf, entryUid);
458
+ }
459
+ return this.selectALeafWithoutDetails(leaf, entryUid);
460
+ }
461
+ static selectALeafWithDetails(leaf, entryUid) {
462
+ if (leaf.uid === entryUid) {
463
+ const leafSelected = !leaf.detailsDisplayable && leaf.selectable;
464
+ return {
465
+ ...leaf,
466
+ selected: leafSelected,
467
+ accessibility: {
468
+ ...leaf.accessibility,
469
+ tabIndex: leafSelected ? 0 : -1,
470
+ },
471
+ folded: !leaf.detailsDisplayable,
472
+ details: leaf.details.reduce((details, detail, idx) => {
473
+ const detailSelected = leaf.detailsDisplayable && !detail.displayError && (idx === 0 || !details[idx - 1].selected);
474
+ details.push({
475
+ ...detail,
476
+ selected: detailSelected,
477
+ accessibility: {
478
+ ...detail.accessibility,
479
+ tabIndex: detailSelected ? 0 : -1,
480
+ },
481
+ });
482
+ return details;
483
+ }, []),
484
+ };
485
+ }
486
+ const details = leaf.details.map(detail => {
487
+ const detailSelected = detail.uid === entryUid && !detail.displayError;
488
+ return {
489
+ ...detail,
490
+ selected: detailSelected,
491
+ accessibility: {
492
+ ...detail.accessibility,
493
+ tabIndex: detailSelected ? 0 : -1,
494
+ },
495
+ };
496
+ });
497
+ return {
498
+ ...leaf,
499
+ accessibility: {
500
+ ...leaf.accessibility,
501
+ tabIndex: -1,
502
+ },
503
+ selected: false,
504
+ folded: !leaf.folded ? false : details.every(detail => !detail.selected),
505
+ details,
506
+ };
507
+ }
508
+ static selectALeafWithoutDetails(leaf, entryUid) {
509
+ const selected = leaf.selectable && leaf.uid === entryUid;
510
+ return {
511
+ ...leaf,
512
+ selected,
513
+ accessibility: {
514
+ ...leaf.accessibility,
515
+ tabIndex: selected ? 0 : -1,
516
+ },
517
+ folded: true,
518
+ };
519
+ }
520
+ }
521
+
522
+ const LeafLogics = {
523
+ DISABLED: 'DISABLED',
524
+ FEATURE_LOCKED: 'FEATURE_LOCKED',
525
+ TOKEN_INVALID: 'TOKEN_INVALID',
526
+ COUNTER: 'COUNTER',
527
+ };
528
+ /**
529
+ * NavSelectorBuilder is a utility class that builds the NavSelector entries for single and multiple select modes.
530
+ * It also checks the structure of the entries to ensure they are valid.
531
+ */
532
+ class NavSelectorBuilder {
533
+ // /!\/!\ Order of logics is important /!\/!\
534
+ static LEAF_LOGICS_PRIORITY = {
535
+ [LeafLogics.DISABLED]: (leaf) => leaf.disableReason !== null,
536
+ [LeafLogics.FEATURE_LOCKED]: (leaf) => leaf.featureLocked,
537
+ [LeafLogics.TOKEN_INVALID]: (leaf) => leaf.tokenInvalid,
538
+ [LeafLogics.COUNTER]: (leaf) => leaf.counter !== null,
539
+ };
540
+ /**
541
+ * Builds the NavSelector entries for single select mode.
542
+ * @param entries nav selector entries
543
+ * @param selectedEntryUid selected entry uid
544
+ * @param detailsDisplayedLimit number of details displayed limit
545
+ */
546
+ static build(entries, selectedEntryUid, detailsDisplayedLimit) {
547
+ this.structureChecker(entries);
548
+ const builtEntries = this.buildEntries(entries, false, 1, detailsDisplayedLimit);
549
+ if (selectedEntryUid) {
550
+ return NavSelectorSingleSelect.select(builtEntries, selectedEntryUid);
551
+ }
552
+ return builtEntries;
553
+ }
554
+ /**
555
+ * Builds the NavSelector entries for multiple select mode.
556
+ * @param entries nav selector entries
557
+ * @param selectedEntryUids selected entry uids
558
+ * @param detailsDisplayedLimit number of details displayed limit
559
+ */
560
+ static buildInMultipleMode(entries, selectedEntryUids, detailsDisplayedLimit) {
561
+ this.structureChecker(entries, true);
562
+ let builtEntries = this.buildEntries(entries, true, 1, detailsDisplayedLimit);
563
+ if (selectedEntryUids) {
564
+ for (const selectedEntryUid of selectedEntryUids) {
565
+ builtEntries = NavSelectorMultiSelect.selectInMultipleMode(builtEntries, selectedEntryUid);
566
+ }
567
+ }
568
+ return builtEntries;
569
+ }
570
+ static structureChecker(entries, multipleModeEnabled = false) {
571
+ entries.forEach(entry => {
572
+ if (isNavSelectorEntryAGroup(entry) || isNavSelectorEntryACategory(entry)) {
573
+ this.structureChecker(entry.children, multipleModeEnabled);
574
+ }
575
+ else if (isNavSelectorEntryALeaf(entry)) {
576
+ if (entry.details.length && multipleModeEnabled) {
577
+ console.error(`NavSelectorBuilder: Leaf ${entry.uid} with details is not allowed in multiple mode`);
578
+ }
579
+ }
580
+ });
581
+ }
582
+ static buildEntries(entries, multipleModeEnabled, level = 1, detailsDisplayedLimit) {
583
+ const newEntries = entries
584
+ .map((entry, idx) => this.buildEntry(entry, { multipleModeEnabled, level, idx, totalNumberOfEntry: entries.length, detailsDisplayedLimit }))
585
+ .filter(it => it !== null);
586
+ return NavSelectorAccessibility.resetFocus(newEntries);
587
+ }
588
+ static buildEntry(entry, { multipleModeEnabled, level, idx, totalNumberOfEntry, detailsDisplayedLimit, }) {
589
+ if (isNavSelectorEntryALeaf(entry)) {
590
+ return this.buildLeaf(entry, {
591
+ multipleModeEnabled,
592
+ level,
593
+ idx,
594
+ totalNumberOfLeaf: totalNumberOfEntry,
595
+ focusable: true,
596
+ detailsDisplayedLimit,
597
+ });
598
+ }
599
+ else if (isNavSelectorEntryACategory(entry)) {
600
+ return this.buildCategory(entry, {
601
+ multipleModeEnabled,
602
+ level,
603
+ idx,
604
+ totalNumberOfCategory: totalNumberOfEntry,
605
+ detailsDisplayedLimit,
606
+ });
607
+ }
608
+ else {
609
+ return this.buildGroup(entry, {
610
+ multipleModeEnabled,
611
+ level,
612
+ idx,
613
+ totalNumberOfGroups: totalNumberOfEntry,
614
+ focusable: true,
615
+ detailsDisplayedLimit,
616
+ });
617
+ }
618
+ }
619
+ static buildCategoryChildren(entry, { focusable, multipleModeEnabled, categoryLevel, detailsDisplayedLimit, }) {
620
+ return entry.children
621
+ .map((child, idx) => {
622
+ if (isNavSelectorEntryALeaf(child)) {
623
+ return this.buildLeaf(child, {
624
+ focusable,
625
+ multipleModeEnabled,
626
+ level: categoryLevel + 1,
627
+ idx,
628
+ totalNumberOfLeaf: entry.children.length,
629
+ detailsDisplayedLimit,
630
+ });
631
+ }
632
+ else {
633
+ return this.buildGroup(child, {
634
+ focusable,
635
+ multipleModeEnabled,
636
+ level: categoryLevel + 1,
637
+ idx,
638
+ totalNumberOfGroups: entry.children.length,
639
+ detailsDisplayedLimit,
640
+ });
641
+ }
642
+ })
643
+ .filter(it => it !== null);
644
+ }
645
+ static buildCategory(node, { multipleModeEnabled, level, idx, totalNumberOfCategory, detailsDisplayedLimit, }) {
646
+ const children = this.buildCategoryChildren(node, {
647
+ focusable: !node.folded,
648
+ multipleModeEnabled,
649
+ categoryLevel: level,
650
+ detailsDisplayedLimit,
651
+ });
652
+ return {
653
+ uid: node.uid,
654
+ alias: node.alias,
655
+ children,
656
+ hidden: false,
657
+ focusable: true,
658
+ accessibility: {
659
+ tabIndex: -1,
660
+ ariaLevel: level,
661
+ ariaPosinset: idx + 1,
662
+ ariaSetsize: totalNumberOfCategory,
663
+ },
664
+ folded: node.folded,
665
+ type: node.type,
666
+ };
667
+ }
668
+ static buildGroupChildren(entry, { multipleModeEnabled, groupLevel, focusable, detailsDisplayedLimit, }) {
669
+ return entry.children
670
+ .map((child, idx) => this.buildLeaf(child, {
671
+ multipleModeEnabled,
672
+ level: groupLevel + 1,
673
+ idx,
674
+ totalNumberOfLeaf: entry.children.length,
675
+ focusable: focusable && !entry.folded,
676
+ detailsDisplayedLimit,
677
+ }))
678
+ .filter(it => it !== null);
679
+ }
680
+ static buildGroup(node, { focusable, multipleModeEnabled, level, idx, totalNumberOfGroups, detailsDisplayedLimit, }) {
681
+ const children = this.buildGroupChildren(node, { multipleModeEnabled, groupLevel: level, focusable, detailsDisplayedLimit });
682
+ const displayTokenInvalid = children.some(({ displayTokenInvalid }) => displayTokenInvalid);
683
+ const selectedChildrenCount = children.filter(({ selected }) => selected).length;
684
+ return {
685
+ uid: node.uid,
686
+ alias: node.alias,
687
+ children,
688
+ childrenPictureUrlSample: children
689
+ .map((child, idx) => isInternalNavSelectorEntryALeaf(child) && idx < 4 ? { url: child.pictureUrl, initial: child.alias[0] } : null)
690
+ .filter(it => it !== null),
691
+ hidden: false,
692
+ accessibility: {
693
+ tabIndex: -1,
694
+ ariaPosinset: idx + 1,
695
+ ariaLevel: level,
696
+ ariaSetsize: totalNumberOfGroups,
697
+ },
698
+ focusable,
699
+ displayCounter: node.folded && children.some(child => isInternalNavSelectorEntryALeaf(child) && child.counter !== 0),
700
+ counter: children.reduce((acc, { counter }) => acc + counter, 0),
701
+ displayTokenInvalid,
702
+ selected: false,
703
+ selectable: multipleModeEnabled && children.some(({ selectable }) => selectable),
704
+ undeterminedSelection: selectedChildrenCount !== children.length && selectedChildrenCount > 0,
705
+ folded: node.folded,
706
+ type: node.type,
707
+ };
708
+ }
709
+ static buildLeaf(leaf, { focusable, multipleModeEnabled, level, idx, totalNumberOfLeaf, detailsDisplayedLimit, }) {
710
+ if (leaf.missingPermission) {
711
+ return null;
712
+ }
713
+ const detailsDisplayable = this.isLeafLogicValid(leaf, LeafLogics.COUNTER) && !!leaf.details.length;
714
+ const foldable = !!leaf.details.length && detailsDisplayable;
715
+ const folded = true;
716
+ const counter = (leaf.details.reduce((acc, detail) => acc + (detail.counter ?? 0), 0) || leaf.counter) ?? 0;
717
+ const counterDisplayable = counter !== 0 && this.isLeafLogicValid(leaf, LeafLogics.COUNTER);
718
+ const disabled = leaf.disableReason !== null;
719
+ const viewMoreDisplayable = leaf.details.length > detailsDisplayedLimit;
720
+ return {
721
+ uid: leaf.uid,
722
+ alias: leaf.alias,
723
+ pictureUrl: leaf.pictureUrl,
724
+ disabled,
725
+ disableReason: leaf.disableReason,
726
+ hidden: false,
727
+ focusable: focusable && !disabled,
728
+ accessibility: {
729
+ tabIndex: -1,
730
+ ariaPosinset: idx + 1,
731
+ ariaLevel: level,
732
+ ariaSetsize: totalNumberOfLeaf,
733
+ },
734
+ foldable,
735
+ folded,
736
+ displayCounter: folded && counterDisplayable,
737
+ counterDisplayable,
738
+ counter,
739
+ network: leaf.network,
740
+ displayTokenInvalid: leaf.tokenInvalid && this.isLeafLogicValid(leaf, LeafLogics.TOKEN_INVALID, LeafLogics.COUNTER),
741
+ displayFeatureLocked: leaf.featureLocked && this.isLeafLogicValid(leaf, LeafLogics.FEATURE_LOCKED, LeafLogics.TOKEN_INVALID, LeafLogics.COUNTER),
742
+ selected: false,
743
+ selectable: multipleModeEnabled
744
+ ? this.isLeafLogicValid(leaf, LeafLogics.COUNTER)
745
+ : this.isLeafLogicValid(leaf, LeafLogics.FEATURE_LOCKED, LeafLogics.TOKEN_INVALID, LeafLogics.COUNTER),
746
+ detailsDisplayable,
747
+ details: leaf.details.map(detail => this.buildLeafDetail(detail, level + 1, focusable && !folded)),
748
+ type: 'LEAF',
749
+ viewMoreDisplayable,
750
+ viewMoreDisplayed: viewMoreDisplayable,
751
+ viewMoreDetailsDisplayedLimit: detailsDisplayedLimit,
752
+ };
753
+ }
754
+ static buildLeafDetail(detail, level, focusable) {
755
+ return {
756
+ uid: detail.uid,
757
+ counter: detail.counter ?? 0,
758
+ displayCounter: detail.counter !== null,
759
+ alias: detail.name,
760
+ hidden: false,
761
+ accessibility: {
762
+ tabIndex: -1,
763
+ ariaPosinset: 1,
764
+ ariaLevel: level,
765
+ ariaSetsize: 1,
766
+ },
767
+ focusable,
768
+ selected: false,
769
+ errorReason: detail.errorReason,
770
+ displayError: detail.errorReason !== null,
771
+ type: 'LEAF_DETAILS',
772
+ };
773
+ }
774
+ static isLeafLogicValid(leaf, ...excludes) {
775
+ return Object.entries(this.LEAF_LOGICS_PRIORITY)
776
+ .filter(([key]) => !excludes.includes(key))
777
+ .every(([, logic]) => !logic(leaf));
778
+ }
779
+ }
780
+
781
+ const isInternalNavSelectorEntryALeafFocusable = (leaf, { parentFolded, minified }) => {
782
+ if (parentFolded) {
783
+ return false;
784
+ }
785
+ if (minified) {
786
+ return !leaf.disabled && !leaf.displayTokenInvalid && !leaf.displayFeatureLocked;
787
+ }
788
+ return !leaf.disabled;
789
+ };
790
+
791
+ /**
792
+ * NavSelectorFilter is a utility class that provides methods to filter entries
793
+ */
794
+ class NavSelectorFilter {
795
+ /**
796
+ * Filters the entries based on the search string
797
+ *
798
+ * The search string is normalized and lowercase and trimmed.
799
+ *
800
+ * If a category matches the search string, all its children are unfolded, marked as focusable, and not hidden.
801
+ *
802
+ * If a group matches the search string, the group is unfolded and all its children are unfolded, marked as focusable, and not hidden.
803
+ *
804
+ * If a leaf matches the search string, it is marked as not hidden and focusable.
805
+ *
806
+ * Else the entry marked as hidden and not focusable.
807
+ *
808
+ * It also determines whenever counter and token invalid should be displayed on groups and leaves.
809
+ *
810
+ * @param entries The entries to filter.
811
+ * @param search The search string.
812
+ * @returns The filtered entries.
813
+ */
814
+ static filter(entries, search) {
815
+ const formattedSearch = this.cleanValue(search);
816
+ if (!formattedSearch) {
817
+ return entries;
818
+ }
819
+ return this.filterEntries(entries, formattedSearch);
820
+ }
821
+ static filterEntries(entries, formattedSearch) {
822
+ const newEntries = entries.map(entry => {
823
+ if (this.matches(entry.alias, formattedSearch)) {
824
+ return this.recursivelyUnfoldEntry(entry);
825
+ }
826
+ if (isInternalNavSelectorEntryANode(entry)) {
827
+ const children = this.filterEntries(entry.children, formattedSearch);
828
+ if (children.every(({ hidden }) => hidden)) {
829
+ return {
830
+ ...entry,
831
+ children,
832
+ hidden: true,
833
+ };
834
+ }
835
+ return {
836
+ ...entry,
837
+ hidden: false,
838
+ displayCounter: false,
839
+ displayTokenInvalid: false,
840
+ folded: false,
841
+ children,
842
+ };
843
+ }
844
+ return {
845
+ ...entry,
846
+ focusable: false,
847
+ hidden: true,
848
+ };
849
+ });
850
+ return NavSelectorAccessibility.resetFocus(newEntries);
851
+ }
852
+ static recursivelyUnfoldEntry(entry) {
853
+ if (isInternalNavSelectorEntryAGroup(entry)) {
854
+ const children = entry.children.map(child => this.recursivelyUnfoldEntry(child));
855
+ return {
856
+ ...entry,
857
+ folded: false,
858
+ children,
859
+ displayCounter: false,
860
+ displayTokenInvalid: false,
861
+ };
862
+ }
863
+ else if (isInternalNavSelectorEntryALeaf(entry)) {
864
+ return {
865
+ ...entry,
866
+ hidden: false,
867
+ focusable: isInternalNavSelectorEntryALeafFocusable(entry, { parentFolded: false, minified: false }),
868
+ displayCounter: entry.counterDisplayable,
869
+ };
870
+ }
871
+ else if (isInternalNavSelectorEntryACategory(entry)) {
872
+ const children = entry.children.map(child => this.recursivelyUnfoldEntry(child));
873
+ return {
874
+ ...entry,
875
+ folded: false,
876
+ hidden: false,
877
+ children,
878
+ };
879
+ }
880
+ return entry;
881
+ }
882
+ static matches(alias, formattedSearch) {
883
+ return this.cleanValue(alias).includes(formattedSearch);
884
+ }
885
+ static cleanValue(value) {
886
+ return value.trim().normalize('NFKC').toLowerCase();
887
+ }
888
+ }
889
+
890
+ /**
891
+ * Class to handle the folding and unfolding of nav selector entries.
892
+ */
893
+ class NavSelectorFolding {
894
+ /**
895
+ * Toggle the folding state of an entry.
896
+ *
897
+ * @see {@link NavSelectorFolding.fold} and {@link NavSelectorFolding.unfold} for more information on folding and unfolding.
898
+ *
899
+ * @param entries nav selector entries
900
+ * @param entryUid the entry uid to toggle
901
+ * @param minified true if the nav selector is minified. Needed for leaf as they are not foldable in minified mode
902
+ */
903
+ static toggleFolding(entries, entryUid, minified) {
904
+ return this.toggleEntryFolding(entries, entryUid, minified);
905
+ }
906
+ /**
907
+ * Fold an entry.
908
+ *
909
+ * Set unfocusable on all children of the folded entry.
910
+ * Compute whenever the counter and token invalid should be displayed on groups and leaves.
911
+ *
912
+ * @param entries nav selector entries
913
+ * @param entryUid the entry uid to fold
914
+ * @param minified true if the nav selector is minified. Needed for leaf as they are not foldable in minified mode
915
+ */
916
+ static fold(entries, entryUid, minified) {
917
+ return this.foldEntry(entries, entryUid, minified);
918
+ }
919
+ /**
920
+ * Unfold an entry.
921
+ *
922
+ * Set focusable on all children of the folded entry.
923
+ * Compute whenever the counter and token invalid should be displayed on groups and leaves.
924
+ *
925
+ * @param entries nav selector entries
926
+ * @param entryUid the entry uid to unfold
927
+ * @param minified true if the nav selector is minified. Needed for leaf as they are not foldable in minified mode
928
+ */
929
+ static unfold(entries, entryUid, minified) {
930
+ return this.unfoldEntry(entries, entryUid, minified);
931
+ }
932
+ static toggleEntryFolding(entries, entryUid, minified, parentFolded = false) {
933
+ return entries.map(entry => {
934
+ if (isInternalNavSelectorEntryACategory(entry)) {
935
+ if (entry.uid === entryUid) {
936
+ const folded = !entry.folded;
937
+ if (folded) {
938
+ return this.foldCategory(entry, minified);
939
+ }
940
+ else {
941
+ return this.unfoldCategory(entry, minified);
942
+ }
943
+ }
944
+ return {
945
+ ...entry,
946
+ children: this.toggleEntryFolding(entry.children, entryUid, minified, entry.folded),
947
+ };
948
+ }
949
+ if (isInternalNavSelectorEntryAGroup(entry)) {
950
+ if (entry.uid === entryUid) {
951
+ const folded = !entry.folded;
952
+ if (folded) {
953
+ return this.foldGroup(entry, minified);
954
+ }
955
+ else {
956
+ return this.unfoldGroup(entry, minified);
957
+ }
958
+ }
959
+ return {
960
+ ...entry,
961
+ children: this.toggleEntryFolding(entry.children, entryUid, minified, parentFolded || entry.folded),
962
+ };
963
+ }
964
+ if (isInternalNavSelectorEntryALeaf(entry)) {
965
+ if (entry.uid === entryUid) {
966
+ const folded = !entry.folded;
967
+ if (folded) {
968
+ return this.foldLeaf(entry, minified);
969
+ }
970
+ else {
971
+ return this.unfoldLeaf(entry, minified);
972
+ }
973
+ }
974
+ return {
975
+ ...entry,
976
+ focusable: isInternalNavSelectorEntryALeafFocusable(entry, { minified, parentFolded }),
977
+ };
978
+ }
979
+ return { ...entry, focusable: !parentFolded };
980
+ });
981
+ }
982
+ static foldEntry(entries, entryUid, minified, parentFolded = false) {
983
+ return entries.map(entry => {
984
+ if (isInternalNavSelectorEntryACategory(entry)) {
985
+ if (entry.uid === entryUid) {
986
+ return this.foldCategory(entry, minified);
987
+ }
988
+ return {
989
+ ...entry,
990
+ children: this.foldEntry(entry.children, entryUid, minified, entry.folded),
991
+ };
992
+ }
993
+ if (isInternalNavSelectorEntryAGroup(entry)) {
994
+ if (entry.uid === entryUid) {
995
+ return this.foldGroup(entry, minified);
996
+ }
997
+ return {
998
+ ...entry,
999
+ focusable: !parentFolded,
1000
+ children: this.foldEntry(entry.children, entryUid, minified, parentFolded || entry.folded),
1001
+ };
1002
+ }
1003
+ if (isInternalNavSelectorEntryALeaf(entry)) {
1004
+ if (entry.uid === entryUid) {
1005
+ return this.foldLeaf(entry, minified);
1006
+ }
1007
+ return {
1008
+ ...entry,
1009
+ focusable: isInternalNavSelectorEntryALeafFocusable(entry, { minified, parentFolded }),
1010
+ };
1011
+ }
1012
+ return { ...entry, focusable: !parentFolded };
1013
+ });
1014
+ }
1015
+ static unfoldEntry(entries, entryUid, minified, parentFolded = false) {
1016
+ return entries.map(entry => {
1017
+ if (isInternalNavSelectorEntryACategory(entry)) {
1018
+ if (entry.uid === entryUid) {
1019
+ return this.unfoldCategory(entry, minified);
1020
+ }
1021
+ return {
1022
+ ...entry,
1023
+ children: this.unfoldEntry(entry.children, entryUid, minified, entry.folded),
1024
+ };
1025
+ }
1026
+ if (isInternalNavSelectorEntryAGroup(entry)) {
1027
+ if (entry.uid === entryUid) {
1028
+ return this.unfoldGroup(entry, minified);
1029
+ }
1030
+ return {
1031
+ ...entry,
1032
+ children: this.unfoldEntry(entry.children, entryUid, minified, parentFolded || entry.folded),
1033
+ focusable: !parentFolded,
1034
+ };
1035
+ }
1036
+ if (isInternalNavSelectorEntryALeaf(entry)) {
1037
+ if (entry.uid === entryUid) {
1038
+ return this.unfoldLeaf(entry, minified);
1039
+ }
1040
+ return {
1041
+ ...entry,
1042
+ focusable: isInternalNavSelectorEntryALeafFocusable(entry, { minified, parentFolded }),
1043
+ };
1044
+ }
1045
+ return { ...entry, focusable: !parentFolded };
1046
+ });
1047
+ }
1048
+ static foldCategory(category, minified) {
1049
+ return {
1050
+ ...category,
1051
+ folded: true,
1052
+ children: this.foldEntry(category.children, category.uid, minified, true),
1053
+ };
1054
+ }
1055
+ static unfoldCategory(category, minified) {
1056
+ return {
1057
+ ...category,
1058
+ folded: false,
1059
+ children: this.unfoldEntry(category.children, category.uid, minified, false),
1060
+ };
1061
+ }
1062
+ static foldGroup(group, minified) {
1063
+ return {
1064
+ ...group,
1065
+ folded: true,
1066
+ children: this.foldEntry(group.children, group.uid, minified, true),
1067
+ displayCounter: !!group.counter,
1068
+ displayTokenInvalid: group.children.some(({ displayTokenInvalid }) => displayTokenInvalid),
1069
+ };
1070
+ }
1071
+ static unfoldGroup(group, minified) {
1072
+ return {
1073
+ ...group,
1074
+ folded: false,
1075
+ children: this.unfoldEntry(group.children, group.uid, minified, false),
1076
+ displayCounter: false,
1077
+ displayTokenInvalid: false,
1078
+ };
1079
+ }
1080
+ static foldLeaf(leaf, minified) {
1081
+ if (!leaf.foldable || minified) {
1082
+ return leaf;
1083
+ }
1084
+ return {
1085
+ ...leaf,
1086
+ displayCounter: true,
1087
+ folded: true,
1088
+ details: leaf.details.map(detail => ({ ...detail, focusable: false })),
1089
+ };
1090
+ }
1091
+ static unfoldLeaf(leaf, minified) {
1092
+ if (!leaf.foldable || minified) {
1093
+ return leaf;
1094
+ }
1095
+ return {
1096
+ ...leaf,
1097
+ displayCounter: false,
1098
+ folded: false,
1099
+ details: leaf.details.map((detail, idx) => ({
1100
+ ...detail,
1101
+ focusable: idx < leaf.viewMoreDetailsDisplayedLimit,
1102
+ })),
1103
+ };
1104
+ }
1105
+ }
1106
+
1107
+ /**
1108
+ * NavSelectorMinifying is a utility class that provides methods to apply rules on entries when minifying or expanded nav selector.
1109
+ */
1110
+ class NavSelectorMinifying {
1111
+ /**
1112
+ * When minifying the nav selector, compute the focusable state of the entries.
1113
+ *
1114
+ * Leaf are not focusable in any error state when minified.
1115
+ * Detail are not focusable when minified.
1116
+ *
1117
+ * @param entries The entries to minify.
1118
+ * @returns The modified entries.
1119
+ */
1120
+ static minify(entries) {
1121
+ return this.compute(entries, true);
1122
+ }
1123
+ /**
1124
+ * When expanding the nav selector, compute the focusable state of the entries.
1125
+ *
1126
+ * Leaf are not focusable in disabled state when expanded.
1127
+ * Detail are focusable when expanded.
1128
+ *
1129
+ * @param entries The entries to minify.
1130
+ * @returns The modified entries.
1131
+ */
1132
+ static expand(entries) {
1133
+ return this.compute(entries, false);
1134
+ }
1135
+ static compute(entries, minified, parent = null) {
1136
+ return entries.map(entry => {
1137
+ if (isInternalNavSelectorEntryALeafDetails(entry)) {
1138
+ return { ...entry, focusable: !minified };
1139
+ }
1140
+ if (isInternalNavSelectorEntryANode(entry)) {
1141
+ return {
1142
+ ...entry,
1143
+ children: this.compute(entry.children, minified, entry),
1144
+ };
1145
+ }
1146
+ return {
1147
+ ...entry,
1148
+ focusable: isInternalNavSelectorEntryALeafFocusable(entry, { parentFolded: parent?.folded === true, minified: minified }),
1149
+ details: this.compute(entry.details, minified),
1150
+ };
1151
+ });
1152
+ }
1153
+ }
1154
+
1155
+ /**
1156
+ * Utility class to handle the view more functionality on leaves
1157
+ */
1158
+ class NavSelectorViewMore {
1159
+ /**
1160
+ * Change the view more details displayed limit on leaves
1161
+ * @param entries nav selector entries
1162
+ * @param limit the number of details we want to display by default
1163
+ */
1164
+ static changeViewMoreDetailsDisplayedLimit(entries, limit) {
1165
+ return entries.map(entry => {
1166
+ if (isInternalNavSelectorEntryANode(entry)) {
1167
+ return {
1168
+ ...entry,
1169
+ children: this.changeViewMoreDetailsDisplayedLimit(entry.children, limit),
1170
+ };
1171
+ }
1172
+ if (isInternalNavSelectorEntryALeaf(entry)) {
1173
+ const viewMoreDisplayable = entry.details.length > limit;
1174
+ return {
1175
+ ...entry,
1176
+ viewMoreDisplayed: viewMoreDisplayable,
1177
+ viewMoreDisplayable,
1178
+ viewMoreDetailsDisplayedLimit: limit,
1179
+ details: entry.details.map((detail, idx) => ({
1180
+ ...detail,
1181
+ focusable: entry.focusable && !entry.folded && idx < limit,
1182
+ })),
1183
+ };
1184
+ }
1185
+ return entry;
1186
+ });
1187
+ }
1188
+ /**
1189
+ * We want to display all details of the leaf
1190
+ *
1191
+ * set viewMoreDisplayed to false and set all details as focusable
1192
+ *
1193
+ * @param entries nav selector entries
1194
+ * @param leafUid the uid of the leaf we want to view all details
1195
+ */
1196
+ static viewMore(entries, leafUid) {
1197
+ return entries.map(entry => {
1198
+ if (isInternalNavSelectorEntryANode(entry)) {
1199
+ return {
1200
+ ...entry,
1201
+ children: this.viewMore(entry.children, leafUid),
1202
+ };
1203
+ }
1204
+ if (isInternalNavSelectorEntryALeaf(entry)) {
1205
+ if (entry.uid === leafUid) {
1206
+ return {
1207
+ ...entry,
1208
+ viewMoreDisplayed: false,
1209
+ details: entry.details.map(detail => ({
1210
+ ...detail,
1211
+ focusable: true,
1212
+ })),
1213
+ };
1214
+ }
1215
+ }
1216
+ return entry;
1217
+ });
1218
+ }
1219
+ /**
1220
+ * We want to display only the number of details of the leaf corresponding to the viewMoreDetailsDisplayedLimit
1221
+ *
1222
+ * set viewMoreDisplayed to true and set only the details with an index lower than the limit as focusable
1223
+ *
1224
+ * @param entries nav selector entries
1225
+ * @param uid the uid of the leaf we want to view all details
1226
+ */
1227
+ static viewLess(entries, uid) {
1228
+ return entries.map(entry => {
1229
+ if (isInternalNavSelectorEntryANode(entry)) {
1230
+ return {
1231
+ ...entry,
1232
+ children: this.viewLess(entry.children, uid),
1233
+ };
1234
+ }
1235
+ if (isInternalNavSelectorEntryALeaf(entry)) {
1236
+ if (entry.uid === uid) {
1237
+ return {
1238
+ ...entry,
1239
+ viewMoreDisplayed: true,
1240
+ details: entry.details.map((detail, idx) => ({
1241
+ ...detail,
1242
+ focusable: idx < entry.viewMoreDetailsDisplayedLimit,
1243
+ })),
1244
+ };
1245
+ }
1246
+ }
1247
+ return entry;
1248
+ });
1249
+ }
1250
+ }
1251
+
1252
+ /**
1253
+ * NavSelectorState is a service that manages the state of the nav selector.
1254
+ *
1255
+ * It should be provided by the component to ensure that if many nav selectors are used in the same page, they don't share the same state.
1256
+ */
1257
+ class NavSelectorState {
1258
+ entries = signal([]);
1259
+ multipleModeEnabled = signal(false);
1260
+ _texts = signal({
1261
+ title: '',
1262
+ only: '',
1263
+ tokenInvalid: '',
1264
+ featureLocked: '',
1265
+ searchPlaceholder: '',
1266
+ noResults: '',
1267
+ viewMore: '',
1268
+ viewLess: '',
1269
+ });
1270
+ lastSelectedUids = signal([]);
1271
+ isMultipleModeEnabled = this.multipleModeEnabled;
1272
+ search = signal('');
1273
+ filteredEntries = computed(() => NavSelectorFilter.filter(this.entries(), this.search()));
1274
+ noResults = computed(() => this.filteredEntries().every(({ hidden }) => hidden));
1275
+ texts = this._texts.asReadonly();
1276
+ leafActionProjection = signal(undefined);
1277
+ expanded = signal(true);
1278
+ expandedAfterDelay = signal(true);
1279
+ selectedUidsChangeCallback = null;
1280
+ constructor() {
1281
+ effect(() => {
1282
+ const newSelectedUids = this.collectSelectedUids(this.entries());
1283
+ if (this.selectedUidsChangeCallback) {
1284
+ this.selectedUidsChangeCallback(newSelectedUids);
1285
+ }
1286
+ }, { allowSignalWrites: true });
1287
+ }
1288
+ updateMultiModeEnabled(enabled) {
1289
+ this.multipleModeEnabled.set(enabled);
1290
+ }
1291
+ updateEntries(entries, initialSelectedEntryUids, detailsDisplayedLimit) {
1292
+ if (this.multipleModeEnabled()) {
1293
+ this.entries.set(NavSelectorBuilder.buildInMultipleMode(entries, initialSelectedEntryUids, detailsDisplayedLimit));
1294
+ }
1295
+ else {
1296
+ this.entries.set(NavSelectorBuilder.build(entries, initialSelectedEntryUids?.[0] ?? null, detailsDisplayedLimit));
1297
+ }
1298
+ }
1299
+ onGroupToggleFolding(group) {
1300
+ this.entries.update(entries => NavSelectorFolding.toggleFolding(entries, group.uid, !this.expanded()));
1301
+ }
1302
+ onNodeSelect(node) {
1303
+ this.entries.update(entries => NavSelectorMultiSelect.selectInMultipleMode(entries, node.uid));
1304
+ }
1305
+ onLeafClicked(leaf) {
1306
+ if (!leaf.selectable) {
1307
+ return;
1308
+ }
1309
+ if (this.multipleModeEnabled()) {
1310
+ this.entries.update(entries => NavSelectorMultiSelect.selectInMultipleMode(entries, leaf.uid));
1311
+ }
1312
+ else {
1313
+ this.entries.update(entries => NavSelectorSingleSelect.select(entries, leaf.uid));
1314
+ }
1315
+ }
1316
+ onLeafToggleFolding(leaf) {
1317
+ this.entries.update(entries => NavSelectorFolding.toggleFolding(entries, leaf.uid, !this.expanded()));
1318
+ }
1319
+ onLeafDetailClicked(leafDetail) {
1320
+ this.entries.update(entries => NavSelectorSingleSelect.select(entries, leafDetail.uid));
1321
+ }
1322
+ updateTexts(texts) {
1323
+ this._texts.set(texts);
1324
+ }
1325
+ selectOnlyLeaf(leaf) {
1326
+ this.entries.update(entries => NavSelectorMultiSelect.selectOnlyALeafInMultipleMode(entries, leaf.uid));
1327
+ }
1328
+ toggleExpanded() {
1329
+ this.expanded.update(expanded => !expanded);
1330
+ this.entries.update(entries => {
1331
+ if (this.expanded()) {
1332
+ return NavSelectorMinifying.expand(entries);
1333
+ }
1334
+ return NavSelectorMinifying.minify(entries);
1335
+ });
1336
+ if (!this.expanded()) {
1337
+ setTimeout(() => this.expandedAfterDelay.set(this.expanded()), 150);
1338
+ }
1339
+ else {
1340
+ this.expandedAfterDelay.set(this.expanded());
1341
+ }
1342
+ }
1343
+ onSelectionChange(uids) {
1344
+ // Avoid infinite loop if you put unexisting uids as select will generate the same entries but with different reference
1345
+ if (JSON.stringify(uids) === JSON.stringify(this.lastSelectedUids())) {
1346
+ return;
1347
+ }
1348
+ this.lastSelectedUids.set(uids);
1349
+ const selectedUids = this.collectSelectedUids(this.entries());
1350
+ const uidToSelect = uids.filter(uid => selectedUids.every(selectedUid => selectedUid !== uid));
1351
+ const uidToUnselect = selectedUids.filter(uid => uids.every(selectedUid => selectedUid !== uid));
1352
+ if (!uidToSelect.length && !uidToUnselect.length) {
1353
+ return;
1354
+ }
1355
+ let entries = this.entries();
1356
+ if (this.multipleModeEnabled()) {
1357
+ for (const uid of [...uidToSelect, ...uidToUnselect]) {
1358
+ entries = NavSelectorMultiSelect.selectInMultipleMode(entries, uid);
1359
+ }
1360
+ }
1361
+ else {
1362
+ entries = NavSelectorSingleSelect.select(entries, uids[0]);
1363
+ }
1364
+ this.entries.set(entries);
1365
+ }
1366
+ registerOnSelectedUidsChange(callback) {
1367
+ this.selectedUidsChangeCallback = callback;
1368
+ }
1369
+ onArrowDown() {
1370
+ this.entries.update(entries => NavSelectorAccessibility.focusNext(entries));
1371
+ }
1372
+ onArrowUp() {
1373
+ this.entries.update(entries => NavSelectorAccessibility.focusPrevious(entries));
1374
+ }
1375
+ collectSelectedUids(entries) {
1376
+ return entries.flatMap(entry => {
1377
+ if (isInternalNavSelectorEntryALeaf(entry)) {
1378
+ if (entry.details.length) {
1379
+ return entry.details.flatMap(detail => (detail.selected ? [detail.uid] : []));
1380
+ }
1381
+ return entry.selected ? [entry.uid] : [];
1382
+ }
1383
+ else if (isInternalNavSelectorEntryANode(entry)) {
1384
+ return this.collectSelectedUids(entry.children);
1385
+ }
1386
+ return [];
1387
+ });
1388
+ }
1389
+ updateLeafAction(leafActionProjection) {
1390
+ this.leafActionProjection.set(leafActionProjection);
1391
+ }
1392
+ fold(entry) {
1393
+ this.entries.update(entries => NavSelectorFolding.fold(entries, entry.uid, !this.expanded()));
1394
+ }
1395
+ unfold(entry) {
1396
+ this.entries.update(entries => NavSelectorFolding.unfold(entries, entry.uid, !this.expanded()));
1397
+ }
1398
+ updateDetailsDisplayedLimit(detailsDisplayedLimit) {
1399
+ this.entries.update(entries => NavSelectorViewMore.changeViewMoreDetailsDisplayedLimit(entries, detailsDisplayedLimit));
1400
+ }
1401
+ viewMore(leaf) {
1402
+ this.entries.update(entries => NavSelectorViewMore.viewMore(entries, leaf.uid));
1403
+ }
1404
+ viewLess(leaf) {
1405
+ this.entries.update(entries => NavSelectorViewMore.viewLess(entries, leaf.uid));
1406
+ }
1407
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorState, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1408
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorState });
1409
+ }
1410
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorState, decorators: [{
1411
+ type: Injectable
1412
+ }], ctorParameters: () => [] });
1413
+
1414
+ class NavSelectorLeafDetailPresenter {
1415
+ navSelectorState;
1416
+ constructor(navSelectorState) {
1417
+ this.navSelectorState = navSelectorState;
1418
+ }
1419
+ onLeafDetailClicked(detail) {
1420
+ this.navSelectorState.onLeafDetailClicked(detail);
1421
+ }
1422
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafDetailPresenter, deps: [{ token: NavSelectorState }], target: i0.ɵɵFactoryTarget.Injectable });
1423
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafDetailPresenter });
1424
+ }
1425
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafDetailPresenter, decorators: [{
1426
+ type: Injectable
1427
+ }], ctorParameters: () => [{ type: NavSelectorState }] });
1428
+
1429
+ class NavSelectorLeafDetailComponent {
1430
+ navSelectorLeafDetailPresenter;
1431
+ detail = input.required();
1432
+ embedded = input(false);
1433
+ constructor(navSelectorLeafDetailPresenter) {
1434
+ this.navSelectorLeafDetailPresenter = navSelectorLeafDetailPresenter;
1435
+ }
1436
+ onClick($event) {
1437
+ $event.stopImmediatePropagation();
1438
+ this.navSelectorLeafDetailPresenter.onLeafDetailClicked(this.detail());
1439
+ }
1440
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafDetailComponent, deps: [{ token: NavSelectorLeafDetailPresenter }], target: i0.ɵɵFactoryTarget.Component });
1441
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.9", type: NavSelectorLeafDetailComponent, isStandalone: true, selector: "ap-nav-selector-leaf-detail", inputs: { detail: { classPropertyName: "detail", publicName: "detail", isSignal: true, isRequired: true, transformFunction: null }, embedded: { classPropertyName: "embedded", publicName: "embedded", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "onClick($event)", "keydown.enter": "onClick($event)", "keydown.space": "onClick($event)" }, properties: { "class.selected": "detail().selected && !embedded()", "class.embedded": "embedded()" } }, providers: [withSymbols(apErrorFill), NavSelectorLeafDetailPresenter], hostDirectives: [{ directive: TreeNodeAccessibilityDirective, inputs: ["apTreeNodeAccessibility", "detail"] }], ngImport: i0, template: "<span class=\"caption\">\n {{ detail().alias }}\n</span>\n\n@if (detail().displayCounter) {\n <ap-counter\n color=\"orange\"\n size=\"normal\"\n [background]=\"false\">\n {{ detail().counter }}\n </ap-counter>\n}\n@if (detail().displayError) {\n <ap-symbol\n size=\"sm\"\n symbolId=\"error_fill\" />\n}\n", styles: [":host{display:flex;height:32px;padding:0 var(--ref-spacing-xxs);align-items:center;gap:var(--ref-spacing-xxs);align-self:stretch;flex-grow:1}:host.embedded{padding:0}:host ap-symbol[symbol-id=error_fill]{color:var(--ref-color-red-100)}:host:not(.disabled):not(.embedded){cursor:pointer}:host:not(.disabled):not(.embedded):hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10)}:host:not(.disabled):not(.embedded):active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host:not(.disabled):not(.embedded):focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10);box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host:not(.disabled):not(.embedded).selected{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host:not(.disabled):not(.embedded).selected:focus{box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host .caption{flex-grow:1;overflow:hidden;color:var(--ref-color-grey-100);text-overflow:ellipsis;white-space:nowrap;font-family:Averta;font-size:var(--ref-font-size-xs);font-style:normal;font-weight:var(--ref-font-weight-regular);line-height:var(--ref-font-line-height-xs)}\n"], dependencies: [{ kind: "component", type: CounterComponent, selector: "ap-counter", inputs: ["color", "size", "background", "notif"] }, { kind: "component", type: SymbolComponent, selector: "ap-symbol", inputs: ["symbolId", "color", "size"], outputs: ["sizeChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1442
+ }
1443
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafDetailComponent, decorators: [{
1444
+ type: Component,
1445
+ args: [{ selector: 'ap-nav-selector-leaf-detail', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CounterComponent, SymbolComponent], providers: [withSymbols(apErrorFill), NavSelectorLeafDetailPresenter], host: {
1446
+ '(click)': 'onClick($event)',
1447
+ '[class.selected]': 'detail().selected && !embedded()',
1448
+ '[class.embedded]': 'embedded()',
1449
+ '(keydown.enter)': 'onClick($event)',
1450
+ '(keydown.space)': 'onClick($event)',
1451
+ }, hostDirectives: [
1452
+ {
1453
+ directive: TreeNodeAccessibilityDirective,
1454
+ // Alias the input of the directive to detail the input detail will be used in the directive and in the component as well
1455
+ inputs: ['apTreeNodeAccessibility: detail'],
1456
+ },
1457
+ ], template: "<span class=\"caption\">\n {{ detail().alias }}\n</span>\n\n@if (detail().displayCounter) {\n <ap-counter\n color=\"orange\"\n size=\"normal\"\n [background]=\"false\">\n {{ detail().counter }}\n </ap-counter>\n}\n@if (detail().displayError) {\n <ap-symbol\n size=\"sm\"\n symbolId=\"error_fill\" />\n}\n", styles: [":host{display:flex;height:32px;padding:0 var(--ref-spacing-xxs);align-items:center;gap:var(--ref-spacing-xxs);align-self:stretch;flex-grow:1}:host.embedded{padding:0}:host ap-symbol[symbol-id=error_fill]{color:var(--ref-color-red-100)}:host:not(.disabled):not(.embedded){cursor:pointer}:host:not(.disabled):not(.embedded):hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10)}:host:not(.disabled):not(.embedded):active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host:not(.disabled):not(.embedded):focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10);box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host:not(.disabled):not(.embedded).selected{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host:not(.disabled):not(.embedded).selected:focus{box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host .caption{flex-grow:1;overflow:hidden;color:var(--ref-color-grey-100);text-overflow:ellipsis;white-space:nowrap;font-family:Averta;font-size:var(--ref-font-size-xs);font-style:normal;font-weight:var(--ref-font-weight-regular);line-height:var(--ref-font-line-height-xs)}\n"] }]
1458
+ }], ctorParameters: () => [{ type: NavSelectorLeafDetailPresenter }] });
1459
+
1460
+ class NavSelectorLeafDetailsPresenter {
1461
+ navSelectorState;
1462
+ viewMoreText = computed(() => this.navSelectorState.texts().viewMore);
1463
+ viewLessText = computed(() => this.navSelectorState.texts().viewLess);
1464
+ constructor(navSelectorState) {
1465
+ this.navSelectorState = navSelectorState;
1466
+ }
1467
+ toggleViewMore(leaf) {
1468
+ if (leaf.viewMoreDisplayed) {
1469
+ this.viewMore(leaf);
1470
+ }
1471
+ else {
1472
+ this.viewLess(leaf);
1473
+ }
1474
+ }
1475
+ viewMore(leaf) {
1476
+ this.navSelectorState.viewMore(leaf);
1477
+ }
1478
+ viewLess(leaf) {
1479
+ this.navSelectorState.viewLess(leaf);
1480
+ }
1481
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafDetailsPresenter, deps: [{ token: NavSelectorState }], target: i0.ɵɵFactoryTarget.Injectable });
1482
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafDetailsPresenter });
1483
+ }
1484
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafDetailsPresenter, decorators: [{
1485
+ type: Injectable
1486
+ }], ctorParameters: () => [{ type: NavSelectorState }] });
1487
+
1488
+ class NavSelectorLeafDetailsComponent {
1489
+ el;
1490
+ navSelectorLeafDetailsPresenter;
1491
+ leaf = input.required();
1492
+ details = input.required();
1493
+ firstDetails = computed(() => this.details().slice(0, this.leaf().viewMoreDetailsDisplayedLimit));
1494
+ lastDetails = computed(() => this.details().slice(this.leaf().viewMoreDetailsDisplayedLimit));
1495
+ viewMoreDelay = signal(false);
1496
+ animationState = computed(() => (this.leaf().viewMoreDisplayable && this.leaf().viewMoreDisplayed ? 'collapsed' : 'expanded'));
1497
+ /**
1498
+ * The height when details are all displayed
1499
+ */
1500
+ maxHeight = signal('0px');
1501
+ constructor(el, navSelectorLeafDetailsPresenter) {
1502
+ this.el = el;
1503
+ this.navSelectorLeafDetailsPresenter = navSelectorLeafDetailsPresenter;
1504
+ effect(() => {
1505
+ if (this.leaf().viewMoreDisplayed) {
1506
+ setTimeout(() => this.viewMoreDelay.set(false), 150);
1507
+ }
1508
+ else {
1509
+ this.viewMoreDelay.set(true);
1510
+ }
1511
+ }, { allowSignalWrites: true });
1512
+ }
1513
+ ngAfterViewInit() {
1514
+ // scrollHeight = leaf + first details displayed when there is a limit
1515
+ const height = this.el.nativeElement.scrollHeight;
1516
+ // cross multiplication to determine height of remaining details
1517
+ this.maxHeight.set(`${(height * this.lastDetails().length) / this.firstDetails().length}px`);
1518
+ }
1519
+ toggleViewMore() {
1520
+ this.navSelectorLeafDetailsPresenter.toggleViewMore(this.leaf());
1521
+ }
1522
+ onSpaceOrEnter(event) {
1523
+ event.stopImmediatePropagation();
1524
+ this.toggleViewMore();
1525
+ }
1526
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafDetailsComponent, deps: [{ token: i0.ElementRef }, { token: NavSelectorLeafDetailsPresenter }], target: i0.ɵɵFactoryTarget.Component });
1527
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.9", type: NavSelectorLeafDetailsComponent, isStandalone: true, selector: "ap-nav-selector-leaf-details", inputs: { leaf: { classPropertyName: "leaf", publicName: "leaf", isSignal: true, isRequired: true, transformFunction: null }, details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "attr.aria-expanded": "!leaf().viewMoreDisplayable || leaf().viewMoreDisplayed" } }, providers: [NavSelectorLeafDetailsPresenter], ngImport: i0, template: "@for (detail of firstDetails(); track detail.uid) {\n <div class=\"detail\">\n <div class=\"separator\">\n <div class=\"rectangle\"></div>\n </div>\n <ap-nav-selector-leaf-detail [detail]=\"detail\" />\n </div>\n}\n\n@if (leaf().viewMoreDisplayable) {\n <div\n class=\"details-container\"\n [@accordion]=\"{\n value: animationState(),\n params: {\n maxHeight: maxHeight()\n }\n }\">\n @if (viewMoreDelay()) {\n @for (detail of lastDetails(); track detail.uid) {\n <div class=\"detail\">\n <div class=\"separator\">\n <div class=\"rectangle\"></div>\n </div>\n <ap-nav-selector-leaf-detail [detail]=\"detail\" />\n </div>\n }\n }\n </div>\n\n <div class=\"detail\">\n <div class=\"separator\">\n <div class=\"rectangle\"></div>\n </div>\n <a\n tabindex=\"0\"\n role=\"button\"\n class=\"standalone view-more\"\n (keydown.space)=\"onSpaceOrEnter($event)\"\n (keydown.enter)=\"onSpaceOrEnter($event)\"\n (click)=\"toggleViewMore()\">\n @if (leaf().viewMoreDisplayed) {\n {{ navSelectorLeafDetailsPresenter.viewMoreText() }}\n } @else {\n {{ navSelectorLeafDetailsPresenter.viewLessText() }}\n }\n </a>\n </div>\n}\n", styles: [":host{display:flex;flex-direction:column;align-items:flex-start;flex:1 0 0}:host .detail{display:flex;align-self:stretch}:host .separator{display:flex;padding:0 11px 0 20px;align-items:center;align-self:stretch}:host .rectangle{width:1px;align-self:stretch;background:var(--ref-color-grey-10)}:host .view-more{display:flex;padding:8px;align-items:center;align-self:stretch}:host .details-container{display:flex;flex-direction:column;align-self:stretch}\n"], dependencies: [{ kind: "component", type: NavSelectorLeafDetailComponent, selector: "ap-nav-selector-leaf-detail", inputs: ["detail", "embedded"] }], animations: [
1528
+ /**
1529
+ * Overflow hidden is put only during the animation and on the collapsed state because if it is put on the expanded state then children’s border will be cut (hover / focus)
1530
+ */
1531
+ trigger('accordion', [
1532
+ state('collapsed', style({
1533
+ maxHeight: '0',
1534
+ overflow: 'hidden',
1535
+ })),
1536
+ state('expanded', style({
1537
+ maxHeight: 'initial',
1538
+ })),
1539
+ transition('collapsed => expanded', [
1540
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', style({ overflow: 'hidden', maxHeight: '{{maxHeight}}' })),
1541
+ ]),
1542
+ transition('expanded => collapsed', [
1543
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', keyframes([style({ overflow: 'hidden', maxHeight: '{{maxHeight}}' }), style({ maxHeight: 0 })])),
1544
+ ]),
1545
+ ]),
1546
+ ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1547
+ }
1548
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafDetailsComponent, decorators: [{
1549
+ type: Component,
1550
+ args: [{ selector: 'ap-nav-selector-leaf-details', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NavSelectorLeafDetailComponent], providers: [NavSelectorLeafDetailsPresenter], host: {
1551
+ '[attr.aria-expanded]': '!leaf().viewMoreDisplayable || leaf().viewMoreDisplayed',
1552
+ }, animations: [
1553
+ /**
1554
+ * Overflow hidden is put only during the animation and on the collapsed state because if it is put on the expanded state then children’s border will be cut (hover / focus)
1555
+ */
1556
+ trigger('accordion', [
1557
+ state('collapsed', style({
1558
+ maxHeight: '0',
1559
+ overflow: 'hidden',
1560
+ })),
1561
+ state('expanded', style({
1562
+ maxHeight: 'initial',
1563
+ })),
1564
+ transition('collapsed => expanded', [
1565
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', style({ overflow: 'hidden', maxHeight: '{{maxHeight}}' })),
1566
+ ]),
1567
+ transition('expanded => collapsed', [
1568
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', keyframes([style({ overflow: 'hidden', maxHeight: '{{maxHeight}}' }), style({ maxHeight: 0 })])),
1569
+ ]),
1570
+ ]),
1571
+ ], template: "@for (detail of firstDetails(); track detail.uid) {\n <div class=\"detail\">\n <div class=\"separator\">\n <div class=\"rectangle\"></div>\n </div>\n <ap-nav-selector-leaf-detail [detail]=\"detail\" />\n </div>\n}\n\n@if (leaf().viewMoreDisplayable) {\n <div\n class=\"details-container\"\n [@accordion]=\"{\n value: animationState(),\n params: {\n maxHeight: maxHeight()\n }\n }\">\n @if (viewMoreDelay()) {\n @for (detail of lastDetails(); track detail.uid) {\n <div class=\"detail\">\n <div class=\"separator\">\n <div class=\"rectangle\"></div>\n </div>\n <ap-nav-selector-leaf-detail [detail]=\"detail\" />\n </div>\n }\n }\n </div>\n\n <div class=\"detail\">\n <div class=\"separator\">\n <div class=\"rectangle\"></div>\n </div>\n <a\n tabindex=\"0\"\n role=\"button\"\n class=\"standalone view-more\"\n (keydown.space)=\"onSpaceOrEnter($event)\"\n (keydown.enter)=\"onSpaceOrEnter($event)\"\n (click)=\"toggleViewMore()\">\n @if (leaf().viewMoreDisplayed) {\n {{ navSelectorLeafDetailsPresenter.viewMoreText() }}\n } @else {\n {{ navSelectorLeafDetailsPresenter.viewLessText() }}\n }\n </a>\n </div>\n}\n", styles: [":host{display:flex;flex-direction:column;align-items:flex-start;flex:1 0 0}:host .detail{display:flex;align-self:stretch}:host .separator{display:flex;padding:0 11px 0 20px;align-items:center;align-self:stretch}:host .rectangle{width:1px;align-self:stretch;background:var(--ref-color-grey-10)}:host .view-more{display:flex;padding:8px;align-items:center;align-self:stretch}:host .details-container{display:flex;flex-direction:column;align-self:stretch}\n"] }]
1572
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: NavSelectorLeafDetailsPresenter }] });
1573
+
1574
+ class NavSelectorLeafPresenter {
1575
+ navSelectorState;
1576
+ expanded = computed(() => this.navSelectorState.expanded());
1577
+ texts = computed(() => this.navSelectorState.texts());
1578
+ isMultipleModeEnabled = computed(() => this.navSelectorState.isMultipleModeEnabled());
1579
+ leafActionProjection = computed(() => this.navSelectorState.leafActionProjection());
1580
+ expandedAfterDelay = computed(() => this.navSelectorState.expandedAfterDelay());
1581
+ constructor(navSelectorState) {
1582
+ this.navSelectorState = navSelectorState;
1583
+ }
1584
+ onLeafClicked(leaf) {
1585
+ this.navSelectorState.onLeafClicked(leaf);
1586
+ }
1587
+ onLeafToggleFolding(leaf) {
1588
+ this.navSelectorState.onLeafToggleFolding(leaf);
1589
+ }
1590
+ selectOnlyLeaf(leaf) {
1591
+ this.navSelectorState.selectOnlyLeaf(leaf);
1592
+ }
1593
+ fold(leaf) {
1594
+ this.navSelectorState.fold(leaf);
1595
+ }
1596
+ unfold(leaf) {
1597
+ this.navSelectorState.unfold(leaf);
1598
+ }
1599
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafPresenter, deps: [{ token: NavSelectorState }], target: i0.ɵɵFactoryTarget.Injectable });
1600
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafPresenter });
1601
+ }
1602
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafPresenter, decorators: [{
1603
+ type: Injectable
1604
+ }], ctorParameters: () => [{ type: NavSelectorState }] });
1605
+
1606
+ class NavSelectorLeafComponent {
1607
+ el;
1608
+ navSelectorLeafPresenter;
1609
+ leaf = input.required();
1610
+ initial = computed(() => this.leaf().alias[0].toUpperCase());
1611
+ foldSymbol = computed(() => (this.leaf().folded ? 'chevron-down' : 'chevron-up'));
1612
+ hovering = signal(false);
1613
+ hoveringMenu = signal(false);
1614
+ onlyButtonDisplayed = computed(() => this.navSelectorLeafPresenter.isMultipleModeEnabled() &&
1615
+ (this.hovering() || this.leaf().accessibility.tabIndex === 0) &&
1616
+ this.leaf().selectable);
1617
+ aliasEl = viewChild('alias');
1618
+ aliasBoundedClientRect = signal({
1619
+ offsetWidth: 0,
1620
+ offsetHeight: 0,
1621
+ scrollWidth: 0,
1622
+ scrollHeight: 0,
1623
+ });
1624
+ tooltipContent = computed(() => {
1625
+ const content = [];
1626
+ const el = this.aliasBoundedClientRect();
1627
+ if (!this.navSelectorLeafPresenter.expanded() || el.offsetWidth < el.scrollWidth || el.offsetHeight < el.scrollHeight) {
1628
+ content.push(this.leaf().alias);
1629
+ }
1630
+ const disableReason = this.leaf().disableReason;
1631
+ if (disableReason) {
1632
+ content.push(disableReason);
1633
+ }
1634
+ if (this.leaf().displayFeatureLocked) {
1635
+ content.push(this.navSelectorLeafPresenter.texts().featureLocked);
1636
+ }
1637
+ if (this.leaf().displayTokenInvalid) {
1638
+ content.push(this.navSelectorLeafPresenter.texts().tokenInvalid);
1639
+ }
1640
+ return content.join('<br>');
1641
+ });
1642
+ tooltipDisabled = computed(() => !this.tooltipContent().length || this.leaf().detailsDisplayable);
1643
+ minifiedEl = viewChild('minified');
1644
+ menuEl = viewChild('menuContainer');
1645
+ menuTriggerEl = viewChild('menuTrigger');
1646
+ actionMenuTriggerEl = viewChild('actionMenuTrigger');
1647
+ foldedWithDelay = signal(false);
1648
+ network = computed(() => (this.leaf().network ? this.leaf().network : undefined));
1649
+ constructor(el, navSelectorLeafPresenter) {
1650
+ this.el = el;
1651
+ this.navSelectorLeafPresenter = navSelectorLeafPresenter;
1652
+ afterNextRender(() => {
1653
+ this.maxHeight.set(`${this.el.nativeElement.scrollHeight}px`);
1654
+ const el = this.aliasEl()?.nativeElement;
1655
+ if (el) {
1656
+ this.aliasBoundedClientRect.set({
1657
+ offsetWidth: el.offsetWidth,
1658
+ offsetHeight: el.offsetHeight,
1659
+ scrollWidth: el.scrollWidth,
1660
+ scrollHeight: el.scrollHeight,
1661
+ });
1662
+ }
1663
+ });
1664
+ effect(() => {
1665
+ if (this.leaf().folded) {
1666
+ setTimeout(() => this.foldedWithDelay.set(true), 150);
1667
+ }
1668
+ else {
1669
+ this.foldedWithDelay.set(false);
1670
+ }
1671
+ }, { allowSignalWrites: true });
1672
+ }
1673
+ animationState = computed(() => (this.leaf().folded ? 'collapsed' : 'expanded'));
1674
+ maxHeight = signal('0px');
1675
+ onClick($event) {
1676
+ $event.stopImmediatePropagation();
1677
+ this.navSelectorLeafPresenter.onLeafClicked(this.leaf());
1678
+ }
1679
+ toggleFolding(event) {
1680
+ event.stopImmediatePropagation();
1681
+ this.navSelectorLeafPresenter.onLeafToggleFolding(this.leaf());
1682
+ }
1683
+ mouseEntered() {
1684
+ this.hovering.set(true);
1685
+ const menuTrigger = this.menuTriggerEl();
1686
+ if (menuTrigger && this.leaf().detailsDisplayable) {
1687
+ menuTrigger.openMenu();
1688
+ }
1689
+ }
1690
+ mouseLeft($event) {
1691
+ this.hovering.set(false);
1692
+ const menuTrigger = this.menuTriggerEl();
1693
+ if (menuTrigger) {
1694
+ setTimeout(() => {
1695
+ this.tryCloseMenu(menuTrigger, $event);
1696
+ }, 100);
1697
+ }
1698
+ }
1699
+ mouseEnteredMenu() {
1700
+ this.hoveringMenu.set(true);
1701
+ }
1702
+ mouseLeftMenu(menuTrigger, $event) {
1703
+ this.hoveringMenu.set(false);
1704
+ this.tryCloseMenu(menuTrigger, $event);
1705
+ }
1706
+ menuOpened() {
1707
+ if (!this.leaf().detailsDisplayable) {
1708
+ this.menuTriggerEl()?.closeMenu();
1709
+ }
1710
+ }
1711
+ onActionButtonClick($event) {
1712
+ $event.stopImmediatePropagation();
1713
+ }
1714
+ onActionButtonKeyDownSpaceOrEnter($event) {
1715
+ $event.stopImmediatePropagation();
1716
+ this.actionMenuTriggerEl()?.openMenu();
1717
+ }
1718
+ selectOnly(event) {
1719
+ event.stopImmediatePropagation();
1720
+ this.navSelectorLeafPresenter.selectOnlyLeaf(this.leaf());
1721
+ }
1722
+ onCheckboxToggle() {
1723
+ this.navSelectorLeafPresenter.onLeafClicked(this.leaf());
1724
+ }
1725
+ onSpaceOrEnterPressed($event) {
1726
+ $event.stopImmediatePropagation();
1727
+ if (document.activeElement === this.el.nativeElement.querySelector('.nav-selector-leaf')) {
1728
+ if (this.leaf().foldable) {
1729
+ this.toggleFolding($event);
1730
+ }
1731
+ else {
1732
+ this.navSelectorLeafPresenter.onLeafClicked(this.leaf());
1733
+ }
1734
+ }
1735
+ }
1736
+ fold(event) {
1737
+ event.stopImmediatePropagation();
1738
+ this.navSelectorLeafPresenter.fold(this.leaf());
1739
+ }
1740
+ unfold(event) {
1741
+ event.stopImmediatePropagation();
1742
+ this.navSelectorLeafPresenter.unfold(this.leaf());
1743
+ }
1744
+ tryCloseMenu(menuTrigger, $event) {
1745
+ if (!this.hoveringMenu()) {
1746
+ const minifiedEl = this.minifiedEl();
1747
+ const minifiedBoundedClientRect = minifiedEl.nativeElement.getBoundingClientRect();
1748
+ const mouseHoveringLeaf = this.mouseIsHovering($event, minifiedBoundedClientRect);
1749
+ const menuEl = this.menuEl();
1750
+ const menuBoundedClientRect = menuEl.nativeElement.getBoundingClientRect();
1751
+ const mouseHoveringMenu = this.mouseIsHovering($event, menuBoundedClientRect);
1752
+ if (!mouseHoveringLeaf && !mouseHoveringMenu) {
1753
+ menuTrigger.closeMenu();
1754
+ }
1755
+ }
1756
+ }
1757
+ mouseIsHovering($event, boundingClientRect) {
1758
+ return (boundingClientRect.left <= $event.clientX &&
1759
+ $event.clientX <= boundingClientRect.right &&
1760
+ boundingClientRect.top <= $event.clientY &&
1761
+ $event.clientY <= boundingClientRect.bottom);
1762
+ }
1763
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafComponent, deps: [{ token: i0.ElementRef }, { token: NavSelectorLeafPresenter }], target: i0.ɵɵFactoryTarget.Component });
1764
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.9", type: NavSelectorLeafComponent, isStandalone: true, selector: "ap-nav-selector-leaf", inputs: { leaf: { classPropertyName: "leaf", publicName: "leaf", isSignal: true, isRequired: true, transformFunction: null } }, host: { attributes: { "role": "treeitem" }, listeners: { "mouseenter": "mouseEntered()", "mouseleave": "mouseLeft($event)", "keydown.arrowLeft": "fold($event)", "keydown.arrowRight": "unfold($event)" }, properties: { "class.minified": "!navSelectorLeafPresenter.expanded()" } }, providers: [withSymbols(apErrorFill, apFeatureLock, apChevronDown, apChevronUp, apMore), NavSelectorLeafPresenter], viewQueries: [{ propertyName: "aliasEl", first: true, predicate: ["alias"], descendants: true, isSignal: true }, { propertyName: "minifiedEl", first: true, predicate: ["minified"], descendants: true, isSignal: true }, { propertyName: "menuEl", first: true, predicate: ["menuContainer"], descendants: true, isSignal: true }, { propertyName: "menuTriggerEl", first: true, predicate: ["menuTrigger"], descendants: true, isSignal: true }, { propertyName: "actionMenuTriggerEl", first: true, predicate: ["actionMenuTrigger"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (navSelectorLeafPresenter.expandedAfterDelay()) {\n <div\n class=\"nav-selector-leaf\"\n apTooltipPosition=\"right\"\n role=\"treeitem\"\n [apTooltip]=\"tooltipContent()\"\n [apTooltipDisabled]=\"tooltipDisabled()\"\n [class.feature-locked]=\"leaf().displayFeatureLocked\"\n [class.selected]=\"leaf().selected\"\n [class.token-error]=\"leaf().displayTokenInvalid\"\n [class.disabled]=\"leaf().disabled\"\n [apTreeNodeAccessibility]=\"leaf()\"\n (keydown.space)=\"onSpaceOrEnterPressed($event)\"\n (keydown.enter)=\"onSpaceOrEnterPressed($event)\"\n (click)=\"onClick($event)\">\n @if (navSelectorLeafPresenter.isMultipleModeEnabled()) {\n <ap-checkbox\n [name]=\"leaf().uid\"\n [checked]=\"leaf().selected\"\n [disabled]=\"!leaf().selectable\"\n (change)=\"onCheckboxToggle()\" />\n }\n <ap-avatar\n size=\"24\"\n [profilePicture]=\"leaf().pictureUrl ?? undefined\"\n [network]=\"$any(leaf().network)\"\n [showInitials]=\"initial()\" />\n\n <span\n #alias\n class=\"caption\">\n {{ leaf().alias }}\n </span>\n\n @if (onlyButtonDisplayed()) {\n <a\n class=\"standalone\"\n role=\"button\"\n [attr.aria-label]=\"'Select only ' + leaf().alias\"\n [attr.tabindex]=\"leaf().accessibility.tabIndex\"\n (keydown.space)=\"selectOnly($event)\"\n (keydown.enter)=\"selectOnly($event)\"\n (click)=\"selectOnly($event)\">\n {{ navSelectorLeafPresenter.texts().only }}\n </a>\n } @else {\n @if (leaf().displayCounter) {\n <ap-counter\n color=\"orange\"\n size=\"normal\"\n [background]=\"false\">\n {{ leaf().counter }}\n </ap-counter>\n }\n @if (leaf().displayTokenInvalid) {\n <ap-symbol\n size=\"sm\"\n symbolId=\"error_fill\" />\n }\n @if (leaf().displayFeatureLocked) {\n <ap-symbol\n size=\"sm\"\n symbolId=\"feature-lock\" />\n }\n\n @let actionProjection = navSelectorLeafPresenter.leafActionProjection();\n @if (actionProjection?.length) {\n <ap-symbol\n #actionMenuTrigger=\"matMenuTrigger\"\n class=\"actions-menu\"\n size=\"sm\"\n symbolId=\"more\"\n [tabindex]=\"leaf().accessibility.tabIndex\"\n [attr.aria-label]=\"'Action menu ' + leaf().alias\"\n [matMenuTriggerFor]=\"actionMenu\"\n (click)=\"onActionButtonClick($event)\"\n (keydown.space)=\"onActionButtonKeyDownSpaceOrEnter($event)\"\n (keydown.enter)=\"onActionButtonKeyDownSpaceOrEnter($event)\" />\n\n <mat-menu #actionMenu=\"matMenu\">\n @for (action of actionProjection; track action) {\n <button mat-menu-item>\n <ng-container\n [ngTemplateOutlet]=\"action\"\n [ngTemplateOutletContext]=\"{\n uid: leaf().uid\n }\" />\n </button>\n }\n </mat-menu>\n }\n\n @if (leaf().foldable) {\n <ap-symbol\n class=\"folding-button\"\n size=\"sm\"\n role=\"button\"\n [tabindex]=\"leaf().accessibility.tabIndex\"\n [attr.aria-label]=\"'Toggle ' + leaf().alias\"\n [symbolId]=\"foldSymbol()\"\n (click)=\"toggleFolding($event)\"\n (keydown.space)=\"toggleFolding($event)\"\n (keydown.enter)=\"toggleFolding($event)\" />\n }\n }\n </div>\n\n <div\n class=\"details-container\"\n [@accordion]=\"{\n value: animationState(),\n params: {\n maxHeight: maxHeight()\n }\n }\">\n @if (!foldedWithDelay()) {\n <ap-nav-selector-leaf-details [details]=\"leaf().details\" [leaf]=\"leaf()\"/>\n }\n </div>\n} @else {\n <div\n #menuTrigger=\"matMenuTrigger\"\n #minified\n class=\"nav-selector-leaf\"\n apTooltipPosition=\"right\"\n [matMenuTriggerFor]=\"menu\"\n [class.feature-locked]=\"leaf().displayFeatureLocked\"\n [class.selected]=\"leaf().selected\"\n [class.token-error]=\"leaf().displayTokenInvalid\"\n [class.disabled]=\"leaf().disabled\"\n [apTooltip]=\"tooltipContent()\"\n [apTooltipDisabled]=\"tooltipDisabled()\"\n [apTreeNodeAccessibility]=\"leaf()\"\n (menuOpened)=\"menuOpened()\"\n (keydown.space)=\"onSpaceOrEnterPressed($event)\"\n (keydown.enter)=\"onSpaceOrEnterPressed($event)\"\n (click)=\"onClick($event)\">\n @if (navSelectorLeafPresenter.isMultipleModeEnabled()) {\n <ap-checkbox\n [name]=\"leaf().uid\"\n [checked]=\"leaf().selected\"\n [disabled]=\"!leaf().selectable\" />\n }\n\n <div class=\"avatar-container\">\n <ap-avatar\n size=\"24\"\n [profilePicture]=\"leaf().pictureUrl ?? undefined\"\n [network]=\"$any(leaf().network)\"\n [showInitials]=\"initial()\" />\n\n <div class=\"status\">\n @if (leaf().displayCounter) {\n <ap-counter\n color=\"orange\"\n size=\"normal\"\n [notif]=\"true\"\n [background]=\"true\">\n {{ leaf().counter }}\n </ap-counter>\n }\n @if (leaf().displayTokenInvalid) {\n <ap-symbol\n size=\"sm\"\n symbolId=\"error_fill\" />\n }\n @if (leaf().displayFeatureLocked) {\n <ap-symbol\n size=\"sm\"\n symbolId=\"feature-lock\" />\n }\n </div>\n </div>\n <mat-menu\n #menu=\"matMenu\"\n class=\"nav-selector-leaf-menu\"\n xPosition=\"after\"\n [hasBackdrop]=\"false\">\n <div\n #menuContainer\n [class.not-displayable]=\"!leaf().detailsDisplayable\"\n (mouseenter)=\"mouseEnteredMenu()\"\n (mouseleave)=\"mouseLeftMenu(menuTrigger, $event)\">\n <button mat-menu-item>\n <span class=\"caption-bold\">{{ leaf().alias }}</span>\n </button>\n @for (detail of leaf().details; track detail.uid) {\n <button\n mat-menu-item\n [class.selected]=\"detail.selected\">\n <ap-nav-selector-leaf-detail\n [embedded]=\"true\"\n [detail]=\"detail\" />\n </button>\n }\n </div>\n </mat-menu>\n </div>\n}\n", styles: [":host{display:flex;gap:2px;flex-shrink:0;align-self:stretch;flex-direction:column}:host .details-container{align-self:stretch}:host .nav-selector-leaf{position:relative;display:flex;padding:0 var(--ref-spacing-xxs);height:36px;align-items:center;gap:var(--ref-spacing-xxs);flex-shrink:0;flex-grow:1;align-self:stretch}:host .caption{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;flex:1 0 0;overflow:hidden;color:var(--ref-color-grey-100);text-overflow:ellipsis;font-family:Averta;font-size:var(--ref-font-size-xs);font-style:normal;font-weight:var(--ref-font-weight-regular);line-height:var(--ref-font-line-height-xs)}:host ap-symbol[symbol-id=error_fill]{color:var(--ref-color-red-100)}:host ap-symbol[symbol-id=feature-lock]{color:var(--ref-color-purple-100)}:host ap-symbol[symbol-id=chevron-down],:host ap-symbol[symbol-id=chevron-up]{color:var(--ref-color-grey-80)}:host .folding-button,:host .actions-menu{display:flex;width:24px;height:24px;justify-content:center;align-items:center;flex-shrink:0}:host .folding-button:hover,:host .actions-menu:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .folding-button:active,:host .actions-menu:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-40)}:host .folding-button:focus,:host .actions-menu:focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20);box-shadow:0 0 0 1px #fff,0 0 0 3px #178dfe}:host .nav-selector-leaf:not(.disabled){cursor:pointer}:host .nav-selector-leaf:not(.disabled):hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10)}:host .nav-selector-leaf:not(.disabled):active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .nav-selector-leaf:not(.disabled):focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10);box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host .nav-selector-leaf:not(.disabled):focus-within{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .nav-selector-leaf:not(.disabled).selected{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .nav-selector-leaf:not(.disabled).selected:focus{box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host .nav-selector-leaf.feature-locked{border-radius:var(--ref-border-radius-sm)}:host .nav-selector-leaf.feature-locked:hover{background:var(--ref-color-purple-10)}:host .nav-selector-leaf.feature-locked:active{background:var(--ref-color-purple-20)}:host .nav-selector-leaf.feature-locked:focus{background:var(--ref-color-purple-10);box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-purple-100)}:host .nav-selector-leaf.feature-locked.selected{background:var(--ref-color-purple-20)}:host .nav-selector-leaf.feature-locked.selected:focus{box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host .nav-selector-leaf.disabled{opacity:.5}:host .status{position:absolute;right:-4px;top:-6px}:host .avatar-container{position:relative}:host.minified .nav-selector-leaf{gap:var(--ref-spacing-xxxs);justify-content:center}:host.minified ::ng-deep ap-checkbox .checkbox .checkbox-container{padding:0}::ng-deep .nav-selector-leaf-menu{position:absolute;left:55px;top:-20%;width:225px}::ng-deep .nav-selector-leaf-menu .not-displayable{display:none}::ng-deep .nav-selector-leaf-menu .caption-bold{color:var(--ref-color-grey-100);font-family:Averta;font-size:var(--ref-font-size-xs);font-style:normal;font-weight:var(--ref-font-weight-bold);line-height:var(--ref-font-line-height-xs)}::ng-deep .nav-selector-leaf-menu.mat-mdc-menu-panel:not(.pop-menu) .mat-mdc-menu-item.selected{background:var(--ref-color-electric-blue-20)}::ng-deep .nav-selector-leaf-menu.mat-mdc-menu-panel:not(.pop-menu) .mat-mdc-menu-item ap-symbol{padding-right:0}\n"], dependencies: [{ kind: "component", type: AvatarComponent, selector: "ap-avatar", inputs: ["profilePicture", "alt", "network", "size", "username", "showInitials", "bigNetwork", "anonymous", "online", "youtubeAvatarMode", "rounded"] }, { kind: "component", type: CounterComponent, selector: "ap-counter", inputs: ["color", "size", "background", "notif"] }, { kind: "component", type: SymbolComponent, selector: "ap-symbol", inputs: ["symbolId", "color", "size"], outputs: ["sizeChange"] }, { kind: "component", type: NavSelectorLeafDetailsComponent, selector: "ap-nav-selector-leaf-details", inputs: ["leaf", "details"] }, { kind: "component", type: CheckboxComponent, selector: "ap-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "disabled", "indeterminate", "checked", "required", "name"], outputs: ["change"] }, { kind: "directive", type: TooltipDirective, selector: "[apTooltip]", inputs: ["apTooltip", "apTooltipPosition", "apTooltipShowDelay", "apTooltipHideDelay", "apTooltipDuration", "apTooltipDisabled", "apTooltipTruncatedTextOnly", "apTooltipTemplateContext", "apTooltipVirtualScrollElement"] }, { kind: "component", type: MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "directive", type: MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "component", type: NavSelectorLeafDetailComponent, selector: "ap-nav-selector-leaf-detail", inputs: ["detail", "embedded"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TreeNodeAccessibilityDirective, selector: "[apTreeNodeAccessibility]", inputs: ["apTreeNodeAccessibility"] }], animations: [
1765
+ /**
1766
+ * Overflow hidden is put only during the animation and on the collapsed state because if it is put on the expanded state then children’s border will be cut (hover / focus)
1767
+ */
1768
+ trigger('accordion', [
1769
+ state('collapsed', style({
1770
+ maxHeight: 0,
1771
+ overflow: 'hidden',
1772
+ })),
1773
+ state('expanded', style({
1774
+ maxHeight: 'initial',
1775
+ })),
1776
+ transition('collapsed => expanded', [
1777
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', style({ overflow: 'hidden', maxHeight: '{{maxHeight}}' })),
1778
+ ]),
1779
+ transition('expanded => collapsed', [
1780
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', keyframes([style({ overflow: 'hidden', maxHeight: '{{maxHeight}}' }), style({ maxHeight: 0 })])),
1781
+ ]),
1782
+ ]),
1783
+ ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1784
+ }
1785
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorLeafComponent, decorators: [{
1786
+ type: Component,
1787
+ args: [{ selector: 'ap-nav-selector-leaf', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1788
+ AvatarComponent,
1789
+ CounterComponent,
1790
+ SymbolComponent,
1791
+ NavSelectorLeafDetailsComponent,
1792
+ CheckboxComponent,
1793
+ TooltipDirective,
1794
+ MatMenu,
1795
+ MatMenuTrigger,
1796
+ MatMenuItem,
1797
+ NavSelectorLeafDetailComponent,
1798
+ NavSelectorLeafDetailComponent,
1799
+ NgTemplateOutlet,
1800
+ TreeNodeAccessibilityDirective,
1801
+ ], providers: [withSymbols(apErrorFill, apFeatureLock, apChevronDown, apChevronUp, apMore), NavSelectorLeafPresenter], host: {
1802
+ '[class.minified]': '!navSelectorLeafPresenter.expanded()',
1803
+ role: 'treeitem',
1804
+ '(mouseenter)': 'mouseEntered()',
1805
+ '(mouseleave)': 'mouseLeft($event)',
1806
+ '(keydown.arrowLeft)': 'fold($event)',
1807
+ '(keydown.arrowRight)': 'unfold($event)',
1808
+ }, animations: [
1809
+ /**
1810
+ * Overflow hidden is put only during the animation and on the collapsed state because if it is put on the expanded state then children’s border will be cut (hover / focus)
1811
+ */
1812
+ trigger('accordion', [
1813
+ state('collapsed', style({
1814
+ maxHeight: 0,
1815
+ overflow: 'hidden',
1816
+ })),
1817
+ state('expanded', style({
1818
+ maxHeight: 'initial',
1819
+ })),
1820
+ transition('collapsed => expanded', [
1821
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', style({ overflow: 'hidden', maxHeight: '{{maxHeight}}' })),
1822
+ ]),
1823
+ transition('expanded => collapsed', [
1824
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', keyframes([style({ overflow: 'hidden', maxHeight: '{{maxHeight}}' }), style({ maxHeight: 0 })])),
1825
+ ]),
1826
+ ]),
1827
+ ], template: "@if (navSelectorLeafPresenter.expandedAfterDelay()) {\n <div\n class=\"nav-selector-leaf\"\n apTooltipPosition=\"right\"\n role=\"treeitem\"\n [apTooltip]=\"tooltipContent()\"\n [apTooltipDisabled]=\"tooltipDisabled()\"\n [class.feature-locked]=\"leaf().displayFeatureLocked\"\n [class.selected]=\"leaf().selected\"\n [class.token-error]=\"leaf().displayTokenInvalid\"\n [class.disabled]=\"leaf().disabled\"\n [apTreeNodeAccessibility]=\"leaf()\"\n (keydown.space)=\"onSpaceOrEnterPressed($event)\"\n (keydown.enter)=\"onSpaceOrEnterPressed($event)\"\n (click)=\"onClick($event)\">\n @if (navSelectorLeafPresenter.isMultipleModeEnabled()) {\n <ap-checkbox\n [name]=\"leaf().uid\"\n [checked]=\"leaf().selected\"\n [disabled]=\"!leaf().selectable\"\n (change)=\"onCheckboxToggle()\" />\n }\n <ap-avatar\n size=\"24\"\n [profilePicture]=\"leaf().pictureUrl ?? undefined\"\n [network]=\"$any(leaf().network)\"\n [showInitials]=\"initial()\" />\n\n <span\n #alias\n class=\"caption\">\n {{ leaf().alias }}\n </span>\n\n @if (onlyButtonDisplayed()) {\n <a\n class=\"standalone\"\n role=\"button\"\n [attr.aria-label]=\"'Select only ' + leaf().alias\"\n [attr.tabindex]=\"leaf().accessibility.tabIndex\"\n (keydown.space)=\"selectOnly($event)\"\n (keydown.enter)=\"selectOnly($event)\"\n (click)=\"selectOnly($event)\">\n {{ navSelectorLeafPresenter.texts().only }}\n </a>\n } @else {\n @if (leaf().displayCounter) {\n <ap-counter\n color=\"orange\"\n size=\"normal\"\n [background]=\"false\">\n {{ leaf().counter }}\n </ap-counter>\n }\n @if (leaf().displayTokenInvalid) {\n <ap-symbol\n size=\"sm\"\n symbolId=\"error_fill\" />\n }\n @if (leaf().displayFeatureLocked) {\n <ap-symbol\n size=\"sm\"\n symbolId=\"feature-lock\" />\n }\n\n @let actionProjection = navSelectorLeafPresenter.leafActionProjection();\n @if (actionProjection?.length) {\n <ap-symbol\n #actionMenuTrigger=\"matMenuTrigger\"\n class=\"actions-menu\"\n size=\"sm\"\n symbolId=\"more\"\n [tabindex]=\"leaf().accessibility.tabIndex\"\n [attr.aria-label]=\"'Action menu ' + leaf().alias\"\n [matMenuTriggerFor]=\"actionMenu\"\n (click)=\"onActionButtonClick($event)\"\n (keydown.space)=\"onActionButtonKeyDownSpaceOrEnter($event)\"\n (keydown.enter)=\"onActionButtonKeyDownSpaceOrEnter($event)\" />\n\n <mat-menu #actionMenu=\"matMenu\">\n @for (action of actionProjection; track action) {\n <button mat-menu-item>\n <ng-container\n [ngTemplateOutlet]=\"action\"\n [ngTemplateOutletContext]=\"{\n uid: leaf().uid\n }\" />\n </button>\n }\n </mat-menu>\n }\n\n @if (leaf().foldable) {\n <ap-symbol\n class=\"folding-button\"\n size=\"sm\"\n role=\"button\"\n [tabindex]=\"leaf().accessibility.tabIndex\"\n [attr.aria-label]=\"'Toggle ' + leaf().alias\"\n [symbolId]=\"foldSymbol()\"\n (click)=\"toggleFolding($event)\"\n (keydown.space)=\"toggleFolding($event)\"\n (keydown.enter)=\"toggleFolding($event)\" />\n }\n }\n </div>\n\n <div\n class=\"details-container\"\n [@accordion]=\"{\n value: animationState(),\n params: {\n maxHeight: maxHeight()\n }\n }\">\n @if (!foldedWithDelay()) {\n <ap-nav-selector-leaf-details [details]=\"leaf().details\" [leaf]=\"leaf()\"/>\n }\n </div>\n} @else {\n <div\n #menuTrigger=\"matMenuTrigger\"\n #minified\n class=\"nav-selector-leaf\"\n apTooltipPosition=\"right\"\n [matMenuTriggerFor]=\"menu\"\n [class.feature-locked]=\"leaf().displayFeatureLocked\"\n [class.selected]=\"leaf().selected\"\n [class.token-error]=\"leaf().displayTokenInvalid\"\n [class.disabled]=\"leaf().disabled\"\n [apTooltip]=\"tooltipContent()\"\n [apTooltipDisabled]=\"tooltipDisabled()\"\n [apTreeNodeAccessibility]=\"leaf()\"\n (menuOpened)=\"menuOpened()\"\n (keydown.space)=\"onSpaceOrEnterPressed($event)\"\n (keydown.enter)=\"onSpaceOrEnterPressed($event)\"\n (click)=\"onClick($event)\">\n @if (navSelectorLeafPresenter.isMultipleModeEnabled()) {\n <ap-checkbox\n [name]=\"leaf().uid\"\n [checked]=\"leaf().selected\"\n [disabled]=\"!leaf().selectable\" />\n }\n\n <div class=\"avatar-container\">\n <ap-avatar\n size=\"24\"\n [profilePicture]=\"leaf().pictureUrl ?? undefined\"\n [network]=\"$any(leaf().network)\"\n [showInitials]=\"initial()\" />\n\n <div class=\"status\">\n @if (leaf().displayCounter) {\n <ap-counter\n color=\"orange\"\n size=\"normal\"\n [notif]=\"true\"\n [background]=\"true\">\n {{ leaf().counter }}\n </ap-counter>\n }\n @if (leaf().displayTokenInvalid) {\n <ap-symbol\n size=\"sm\"\n symbolId=\"error_fill\" />\n }\n @if (leaf().displayFeatureLocked) {\n <ap-symbol\n size=\"sm\"\n symbolId=\"feature-lock\" />\n }\n </div>\n </div>\n <mat-menu\n #menu=\"matMenu\"\n class=\"nav-selector-leaf-menu\"\n xPosition=\"after\"\n [hasBackdrop]=\"false\">\n <div\n #menuContainer\n [class.not-displayable]=\"!leaf().detailsDisplayable\"\n (mouseenter)=\"mouseEnteredMenu()\"\n (mouseleave)=\"mouseLeftMenu(menuTrigger, $event)\">\n <button mat-menu-item>\n <span class=\"caption-bold\">{{ leaf().alias }}</span>\n </button>\n @for (detail of leaf().details; track detail.uid) {\n <button\n mat-menu-item\n [class.selected]=\"detail.selected\">\n <ap-nav-selector-leaf-detail\n [embedded]=\"true\"\n [detail]=\"detail\" />\n </button>\n }\n </div>\n </mat-menu>\n </div>\n}\n", styles: [":host{display:flex;gap:2px;flex-shrink:0;align-self:stretch;flex-direction:column}:host .details-container{align-self:stretch}:host .nav-selector-leaf{position:relative;display:flex;padding:0 var(--ref-spacing-xxs);height:36px;align-items:center;gap:var(--ref-spacing-xxs);flex-shrink:0;flex-grow:1;align-self:stretch}:host .caption{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;flex:1 0 0;overflow:hidden;color:var(--ref-color-grey-100);text-overflow:ellipsis;font-family:Averta;font-size:var(--ref-font-size-xs);font-style:normal;font-weight:var(--ref-font-weight-regular);line-height:var(--ref-font-line-height-xs)}:host ap-symbol[symbol-id=error_fill]{color:var(--ref-color-red-100)}:host ap-symbol[symbol-id=feature-lock]{color:var(--ref-color-purple-100)}:host ap-symbol[symbol-id=chevron-down],:host ap-symbol[symbol-id=chevron-up]{color:var(--ref-color-grey-80)}:host .folding-button,:host .actions-menu{display:flex;width:24px;height:24px;justify-content:center;align-items:center;flex-shrink:0}:host .folding-button:hover,:host .actions-menu:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .folding-button:active,:host .actions-menu:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-40)}:host .folding-button:focus,:host .actions-menu:focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20);box-shadow:0 0 0 1px #fff,0 0 0 3px #178dfe}:host .nav-selector-leaf:not(.disabled){cursor:pointer}:host .nav-selector-leaf:not(.disabled):hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10)}:host .nav-selector-leaf:not(.disabled):active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .nav-selector-leaf:not(.disabled):focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10);box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host .nav-selector-leaf:not(.disabled):focus-within{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .nav-selector-leaf:not(.disabled).selected{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .nav-selector-leaf:not(.disabled).selected:focus{box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host .nav-selector-leaf.feature-locked{border-radius:var(--ref-border-radius-sm)}:host .nav-selector-leaf.feature-locked:hover{background:var(--ref-color-purple-10)}:host .nav-selector-leaf.feature-locked:active{background:var(--ref-color-purple-20)}:host .nav-selector-leaf.feature-locked:focus{background:var(--ref-color-purple-10);box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-purple-100)}:host .nav-selector-leaf.feature-locked.selected{background:var(--ref-color-purple-20)}:host .nav-selector-leaf.feature-locked.selected:focus{box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host .nav-selector-leaf.disabled{opacity:.5}:host .status{position:absolute;right:-4px;top:-6px}:host .avatar-container{position:relative}:host.minified .nav-selector-leaf{gap:var(--ref-spacing-xxxs);justify-content:center}:host.minified ::ng-deep ap-checkbox .checkbox .checkbox-container{padding:0}::ng-deep .nav-selector-leaf-menu{position:absolute;left:55px;top:-20%;width:225px}::ng-deep .nav-selector-leaf-menu .not-displayable{display:none}::ng-deep .nav-selector-leaf-menu .caption-bold{color:var(--ref-color-grey-100);font-family:Averta;font-size:var(--ref-font-size-xs);font-style:normal;font-weight:var(--ref-font-weight-bold);line-height:var(--ref-font-line-height-xs)}::ng-deep .nav-selector-leaf-menu.mat-mdc-menu-panel:not(.pop-menu) .mat-mdc-menu-item.selected{background:var(--ref-color-electric-blue-20)}::ng-deep .nav-selector-leaf-menu.mat-mdc-menu-panel:not(.pop-menu) .mat-mdc-menu-item ap-symbol{padding-right:0}\n"] }]
1828
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: NavSelectorLeafPresenter }] });
1829
+
1830
+ class NavSelectorGroupPresenter {
1831
+ navSelectorState;
1832
+ expanded = computed(() => this.navSelectorState.expanded());
1833
+ texts = computed(() => this.navSelectorState.texts());
1834
+ isMultipleModeEnabled = computed(() => this.navSelectorState.isMultipleModeEnabled());
1835
+ expandedAfterDelay = computed(() => this.navSelectorState.expandedAfterDelay());
1836
+ constructor(navSelectorState) {
1837
+ this.navSelectorState = navSelectorState;
1838
+ }
1839
+ onGroupSelected(group) {
1840
+ this.navSelectorState.onNodeSelect(group);
1841
+ }
1842
+ onGroupToggleFolding(group) {
1843
+ this.navSelectorState.onGroupToggleFolding(group);
1844
+ }
1845
+ fold(group) {
1846
+ this.navSelectorState.fold(group);
1847
+ }
1848
+ unfold(group) {
1849
+ this.navSelectorState.unfold(group);
1850
+ }
1851
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorGroupPresenter, deps: [{ token: NavSelectorState }], target: i0.ɵɵFactoryTarget.Injectable });
1852
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorGroupPresenter });
1853
+ }
1854
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorGroupPresenter, decorators: [{
1855
+ type: Injectable
1856
+ }], ctorParameters: () => [{ type: NavSelectorState }] });
1857
+
1858
+ class NavSelectorGroupComponent {
1859
+ el;
1860
+ navSelectorGroupPresenter;
1861
+ group = input.required();
1862
+ foldSymbol = computed(() => (this.group().folded ? 'chevron-down' : 'chevron-up'));
1863
+ aliasEl = viewChild('alias');
1864
+ aliasBoundedClientRect = signal({
1865
+ offsetWidth: 0,
1866
+ offsetHeight: 0,
1867
+ scrollWidth: 0,
1868
+ scrollHeight: 0,
1869
+ });
1870
+ tooltipContent = computed(() => {
1871
+ const content = [];
1872
+ const el = this.aliasBoundedClientRect();
1873
+ if (!this.navSelectorGroupPresenter.expanded() || el.offsetWidth < el.scrollWidth || el.offsetHeight < el.scrollHeight) {
1874
+ content.push(this.group().alias);
1875
+ }
1876
+ if (this.group().displayTokenInvalid) {
1877
+ content.push(this.navSelectorGroupPresenter.texts().tokenInvalid);
1878
+ }
1879
+ return content.join('<br>');
1880
+ });
1881
+ tooltipDisabled = computed(() => !this.tooltipContent().length);
1882
+ foldedWithDelay = signal(false);
1883
+ animationState = computed(() => (this.group().folded ? 'collapsed' : 'expanded'));
1884
+ constructor(el, navSelectorGroupPresenter) {
1885
+ this.el = el;
1886
+ this.navSelectorGroupPresenter = navSelectorGroupPresenter;
1887
+ afterNextRender(() => {
1888
+ this.maxHeight.set(`${this.el.nativeElement.scrollHeight}px`);
1889
+ const el = this.aliasEl()?.nativeElement;
1890
+ if (el) {
1891
+ this.aliasBoundedClientRect.set({
1892
+ offsetWidth: el.offsetWidth,
1893
+ offsetHeight: el.offsetHeight,
1894
+ scrollWidth: el.scrollWidth,
1895
+ scrollHeight: el.scrollHeight,
1896
+ });
1897
+ }
1898
+ });
1899
+ effect(() => {
1900
+ if (this.group().folded) {
1901
+ setTimeout(() => this.foldedWithDelay.set(true), 150);
1902
+ }
1903
+ else {
1904
+ this.foldedWithDelay.set(false);
1905
+ }
1906
+ }, { allowSignalWrites: true });
1907
+ }
1908
+ maxHeight = signal('0px');
1909
+ onKeydownSpaceOrEnter($event) {
1910
+ // Prevent to toggle folding when focus is on the checkbox
1911
+ if (document.activeElement === this.el.nativeElement.querySelector('.content')) {
1912
+ this.toggleFolding($event);
1913
+ }
1914
+ else {
1915
+ this.navSelectorGroupPresenter.onGroupSelected(this.group());
1916
+ }
1917
+ }
1918
+ toggleFolding(event) {
1919
+ event.stopImmediatePropagation();
1920
+ this.navSelectorGroupPresenter.onGroupToggleFolding(this.group());
1921
+ }
1922
+ fold(event) {
1923
+ event.stopImmediatePropagation();
1924
+ this.navSelectorGroupPresenter.fold(this.group());
1925
+ }
1926
+ unfold(event) {
1927
+ event.stopImmediatePropagation();
1928
+ this.navSelectorGroupPresenter.unfold(this.group());
1929
+ }
1930
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorGroupComponent, deps: [{ token: i0.ElementRef }, { token: NavSelectorGroupPresenter }], target: i0.ɵɵFactoryTarget.Component });
1931
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.9", type: NavSelectorGroupComponent, isStandalone: true, selector: "ap-nav-selector-group", inputs: { group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "keydown.arrowLeft": "fold($event)", "keydown.arrowRight": "unfold($event)" }, properties: { "class.minified": "!navSelectorGroupPresenter.expanded()" } }, providers: [withSymbols(apFolder, apErrorFill, apChevronDown, apChevronUp), NavSelectorGroupPresenter], viewQueries: [{ propertyName: "aliasEl", first: true, predicate: ["alias"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (navSelectorGroupPresenter.expandedAfterDelay()) {\n <div\n class=\"content\"\n apTooltipPosition=\"right\"\n [apTooltip]=\"tooltipContent()\"\n [apTooltipDisabled]=\"tooltipDisabled()\"\n [apTreeNodeAccessibility]=\"group()\"\n (keydown.space)=\"onKeydownSpaceOrEnter($event)\"\n (keydown.enter)=\"onKeydownSpaceOrEnter($event)\">\n @if (navSelectorGroupPresenter.isMultipleModeEnabled()) {\n <ap-checkbox\n [name]=\"group().uid\"\n [checked]=\"group().selected\"\n [disabled]=\"!group().selectable\"\n [indeterminate]=\"group().undeterminedSelection\"\n (change)=\"navSelectorGroupPresenter.onGroupSelected(group())\" />\n }\n\n <ap-symbol\n symbolId=\"folder\"\n size=\"sm\" />\n\n <span\n #alias\n class=\"caption\">\n {{ group().alias }}\n </span>\n\n @if (group().displayTokenInvalid) {\n <ap-symbol\n symbolId=\"error_fill\"\n size=\"sm\" />\n }\n\n @if (group().displayCounter) {\n <ap-counter\n color=\"orange\"\n size=\"normal\"\n [background]=\"false\">\n {{ group().counter }}\n </ap-counter>\n }\n\n <ap-symbol\n size=\"sm\"\n class=\"folding-button\"\n [tabindex]=\"group().accessibility.tabIndex\"\n [attr.aria-label]=\"'Toggle ' + group().alias\"\n [symbolId]=\"foldSymbol()\"\n (keydown.space)=\"toggleFolding($event)\"\n (keydown.enter)=\"toggleFolding($event)\"\n (click)=\"toggleFolding($event)\" />\n </div>\n\n <div\n class=\"children-container\"\n [@accordion]=\"{\n value: animationState(),\n params: {\n maxHeight: maxHeight()\n }\n }\">\n @if (!foldedWithDelay()) {\n <div class=\"children\">\n @for (child of group().children; track child.uid) {\n @if (!child.hidden) {\n <ap-nav-selector-leaf [leaf]=\"child\" />\n }\n }\n </div>\n }\n </div>\n} @else {\n <div\n class=\"content\"\n apTooltipPosition=\"right\"\n [apTooltip]=\"tooltipContent()\"\n [apTooltipDisabled]=\"tooltipDisabled()\"\n [apTreeNodeAccessibility]=\"group()\"\n (click)=\"toggleFolding($event)\"\n (keydown.space)=\"onKeydownSpaceOrEnter($event)\"\n (keydown.enter)=\"onKeydownSpaceOrEnter($event)\">\n @if (navSelectorGroupPresenter.isMultipleModeEnabled()) {\n <ap-checkbox\n [name]=\"group().uid\"\n [checked]=\"group().selected\"\n [disabled]=\"!group().selectable\"\n [indeterminate]=\"group().undeterminedSelection\"\n (change)=\"navSelectorGroupPresenter.onGroupSelected(group())\" />\n }\n\n <div class=\"picture-url-sample-container\">\n <div class=\"picture-url-sample\">\n @for (pictureUrlSample of group().childrenPictureUrlSample; track pictureUrlSample) {\n <ap-avatar\n [size]=\"$any(12)\"\n [profilePicture]=\"pictureUrlSample.url ?? undefined\"\n [showInitials]=\"pictureUrlSample.initial\" />\n }\n\n <div class=\"status\">\n @if (group().displayCounter) {\n <ap-counter\n color=\"orange\"\n size=\"normal\"\n [notif]=\"true\"\n [background]=\"true\">\n {{ group().counter }}\n </ap-counter>\n }\n </div>\n </div>\n\n <div class=\"toggle\">\n <ap-symbol\n size=\"sm\"\n [symbolId]=\"foldSymbol()\" />\n </div>\n </div>\n </div>\n\n <div\n class=\"details-container\"\n [@accordion]=\"{\n value: animationState(),\n params: {\n maxHeight: maxHeight()\n }\n }\">\n @if (!foldedWithDelay()) {\n <div class=\"children\">\n @for (child of group().children; track child.uid) {\n @if (!child.hidden) {\n <ap-nav-selector-leaf [leaf]=\"child\" />\n }\n }\n </div>\n }\n </div>\n}\n", styles: [":host{display:flex;align-items:center;flex-shrink:0;align-self:stretch;flex-direction:column}:host .children-container{align-self:stretch}:host .content{padding:0 var(--ref-spacing-xxs);display:flex;height:36px;align-items:center;gap:var(--ref-spacing-xxs);flex-shrink:0;flex-grow:1;align-self:stretch;cursor:pointer}:host .content:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10)}:host .content:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .content:focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10);box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host .content:focus-within{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host:not(.minified) ap-symbol[symbol-id=chevron-down],:host:not(.minified) ap-symbol[symbol-id=chevron-up]{color:var(--ref-color-grey-80)}:host:not(.minified) ap-symbol[symbol-id=chevron-down]:hover,:host:not(.minified) ap-symbol[symbol-id=chevron-up]:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host:not(.minified) ap-symbol[symbol-id=chevron-down]:active,:host:not(.minified) ap-symbol[symbol-id=chevron-up]:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-40)}:host:not(.minified) ap-symbol[symbol-id=chevron-down]:focus,:host:not(.minified) ap-symbol[symbol-id=chevron-up]:focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20);box-shadow:0 0 0 1px #fff,0 0 0 3px #178dfe}:host ap-symbol[symbol-id=error_fill]{color:var(--ref-color-red-100)}:host ap-symbol[symbol-id=folder]{color:var(--ref-color-grey-100)}:host ap-symbol[symbol-id=chevron-down],:host ap-symbol[symbol-id=chevron-up]{color:var(--ref-color-grey-80)}:host .folding-button{display:flex;width:24px;height:24px;justify-content:center;align-items:center;flex-shrink:0}:host .folding-button:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .folding-button:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-40)}:host .caption{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;flex:1 0 0;overflow:hidden;color:var(--ref-color-grey-100);text-overflow:ellipsis;font-family:Averta;font-size:var(--ref-font-size-xs);font-style:normal;font-weight:var(--ref-font-weight-bold);line-height:var(--ref-font-line-height-xs)}:host .children{display:flex;flex-direction:column;align-items:flex-start;flex:1 0 0;align-self:stretch}:host .picture-url-sample-container{position:relative;width:26px}:host .picture-url-sample{display:flex;width:26px;align-items:center;align-content:center;gap:2px;flex-wrap:wrap}:host.minified .content{gap:var(--ref-spacing-xxxs);position:relative;justify-content:center}:host.minified .content .toggle{position:absolute;display:none}:host.minified .content:hover .toggle,:host.minified .content:focus .toggle{inset:0;display:flex;justify-content:center;align-items:center}:host.minified .content:hover .picture-url-sample,:host.minified .content:focus .picture-url-sample{display:none}:host.minified ::ng-deep ap-checkbox .checkbox .checkbox-container{padding:0}:host.minified .status{position:absolute;right:-4px;top:-6px}\n"], dependencies: [{ kind: "component", type: SymbolComponent, selector: "ap-symbol", inputs: ["symbolId", "color", "size"], outputs: ["sizeChange"] }, { kind: "component", type: CounterComponent, selector: "ap-counter", inputs: ["color", "size", "background", "notif"] }, { kind: "component", type: NavSelectorLeafComponent, selector: "ap-nav-selector-leaf", inputs: ["leaf"] }, { kind: "component", type: CheckboxComponent, selector: "ap-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "disabled", "indeterminate", "checked", "required", "name"], outputs: ["change"] }, { kind: "component", type: AvatarComponent, selector: "ap-avatar", inputs: ["profilePicture", "alt", "network", "size", "username", "showInitials", "bigNetwork", "anonymous", "online", "youtubeAvatarMode", "rounded"] }, { kind: "directive", type: TooltipDirective, selector: "[apTooltip]", inputs: ["apTooltip", "apTooltipPosition", "apTooltipShowDelay", "apTooltipHideDelay", "apTooltipDuration", "apTooltipDisabled", "apTooltipTruncatedTextOnly", "apTooltipTemplateContext", "apTooltipVirtualScrollElement"] }, { kind: "directive", type: TreeNodeAccessibilityDirective, selector: "[apTreeNodeAccessibility]", inputs: ["apTreeNodeAccessibility"] }], animations: [
1932
+ /**
1933
+ * Overflow hidden is put only during the animation and on the collapsed state because if it is put on the expanded state then children’s border will be cut (hover / focus)
1934
+ */
1935
+ trigger('accordion', [
1936
+ state('collapsed', style({
1937
+ maxHeight: 0,
1938
+ overflow: 'hidden',
1939
+ })),
1940
+ state('expanded', style({
1941
+ maxHeight: 'initial',
1942
+ })),
1943
+ transition('collapsed => expanded', [
1944
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', style({ maxHeight: '{{maxHeight}}', overflow: 'hidden' })),
1945
+ ]),
1946
+ transition('expanded => collapsed', [
1947
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', keyframes([style({ maxHeight: '{{maxHeight}}', overflow: 'hidden' }), style({ maxHeight: 0, overflow: 'hidden' })])),
1948
+ ]),
1949
+ ]),
1950
+ ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1951
+ }
1952
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorGroupComponent, decorators: [{
1953
+ type: Component,
1954
+ args: [{ selector: 'ap-nav-selector-group', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [withSymbols(apFolder, apErrorFill, apChevronDown, apChevronUp), NavSelectorGroupPresenter], imports: [
1955
+ SymbolComponent,
1956
+ CounterComponent,
1957
+ NavSelectorLeafComponent,
1958
+ CheckboxComponent,
1959
+ AvatarComponent,
1960
+ TooltipDirective,
1961
+ TreeNodeAccessibilityDirective,
1962
+ ], host: {
1963
+ '[class.minified]': '!navSelectorGroupPresenter.expanded()',
1964
+ '(keydown.arrowLeft)': 'fold($event)',
1965
+ '(keydown.arrowRight)': 'unfold($event)',
1966
+ }, animations: [
1967
+ /**
1968
+ * Overflow hidden is put only during the animation and on the collapsed state because if it is put on the expanded state then children’s border will be cut (hover / focus)
1969
+ */
1970
+ trigger('accordion', [
1971
+ state('collapsed', style({
1972
+ maxHeight: 0,
1973
+ overflow: 'hidden',
1974
+ })),
1975
+ state('expanded', style({
1976
+ maxHeight: 'initial',
1977
+ })),
1978
+ transition('collapsed => expanded', [
1979
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', style({ maxHeight: '{{maxHeight}}', overflow: 'hidden' })),
1980
+ ]),
1981
+ transition('expanded => collapsed', [
1982
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', keyframes([style({ maxHeight: '{{maxHeight}}', overflow: 'hidden' }), style({ maxHeight: 0, overflow: 'hidden' })])),
1983
+ ]),
1984
+ ]),
1985
+ ], template: "@if (navSelectorGroupPresenter.expandedAfterDelay()) {\n <div\n class=\"content\"\n apTooltipPosition=\"right\"\n [apTooltip]=\"tooltipContent()\"\n [apTooltipDisabled]=\"tooltipDisabled()\"\n [apTreeNodeAccessibility]=\"group()\"\n (keydown.space)=\"onKeydownSpaceOrEnter($event)\"\n (keydown.enter)=\"onKeydownSpaceOrEnter($event)\">\n @if (navSelectorGroupPresenter.isMultipleModeEnabled()) {\n <ap-checkbox\n [name]=\"group().uid\"\n [checked]=\"group().selected\"\n [disabled]=\"!group().selectable\"\n [indeterminate]=\"group().undeterminedSelection\"\n (change)=\"navSelectorGroupPresenter.onGroupSelected(group())\" />\n }\n\n <ap-symbol\n symbolId=\"folder\"\n size=\"sm\" />\n\n <span\n #alias\n class=\"caption\">\n {{ group().alias }}\n </span>\n\n @if (group().displayTokenInvalid) {\n <ap-symbol\n symbolId=\"error_fill\"\n size=\"sm\" />\n }\n\n @if (group().displayCounter) {\n <ap-counter\n color=\"orange\"\n size=\"normal\"\n [background]=\"false\">\n {{ group().counter }}\n </ap-counter>\n }\n\n <ap-symbol\n size=\"sm\"\n class=\"folding-button\"\n [tabindex]=\"group().accessibility.tabIndex\"\n [attr.aria-label]=\"'Toggle ' + group().alias\"\n [symbolId]=\"foldSymbol()\"\n (keydown.space)=\"toggleFolding($event)\"\n (keydown.enter)=\"toggleFolding($event)\"\n (click)=\"toggleFolding($event)\" />\n </div>\n\n <div\n class=\"children-container\"\n [@accordion]=\"{\n value: animationState(),\n params: {\n maxHeight: maxHeight()\n }\n }\">\n @if (!foldedWithDelay()) {\n <div class=\"children\">\n @for (child of group().children; track child.uid) {\n @if (!child.hidden) {\n <ap-nav-selector-leaf [leaf]=\"child\" />\n }\n }\n </div>\n }\n </div>\n} @else {\n <div\n class=\"content\"\n apTooltipPosition=\"right\"\n [apTooltip]=\"tooltipContent()\"\n [apTooltipDisabled]=\"tooltipDisabled()\"\n [apTreeNodeAccessibility]=\"group()\"\n (click)=\"toggleFolding($event)\"\n (keydown.space)=\"onKeydownSpaceOrEnter($event)\"\n (keydown.enter)=\"onKeydownSpaceOrEnter($event)\">\n @if (navSelectorGroupPresenter.isMultipleModeEnabled()) {\n <ap-checkbox\n [name]=\"group().uid\"\n [checked]=\"group().selected\"\n [disabled]=\"!group().selectable\"\n [indeterminate]=\"group().undeterminedSelection\"\n (change)=\"navSelectorGroupPresenter.onGroupSelected(group())\" />\n }\n\n <div class=\"picture-url-sample-container\">\n <div class=\"picture-url-sample\">\n @for (pictureUrlSample of group().childrenPictureUrlSample; track pictureUrlSample) {\n <ap-avatar\n [size]=\"$any(12)\"\n [profilePicture]=\"pictureUrlSample.url ?? undefined\"\n [showInitials]=\"pictureUrlSample.initial\" />\n }\n\n <div class=\"status\">\n @if (group().displayCounter) {\n <ap-counter\n color=\"orange\"\n size=\"normal\"\n [notif]=\"true\"\n [background]=\"true\">\n {{ group().counter }}\n </ap-counter>\n }\n </div>\n </div>\n\n <div class=\"toggle\">\n <ap-symbol\n size=\"sm\"\n [symbolId]=\"foldSymbol()\" />\n </div>\n </div>\n </div>\n\n <div\n class=\"details-container\"\n [@accordion]=\"{\n value: animationState(),\n params: {\n maxHeight: maxHeight()\n }\n }\">\n @if (!foldedWithDelay()) {\n <div class=\"children\">\n @for (child of group().children; track child.uid) {\n @if (!child.hidden) {\n <ap-nav-selector-leaf [leaf]=\"child\" />\n }\n }\n </div>\n }\n </div>\n}\n", styles: [":host{display:flex;align-items:center;flex-shrink:0;align-self:stretch;flex-direction:column}:host .children-container{align-self:stretch}:host .content{padding:0 var(--ref-spacing-xxs);display:flex;height:36px;align-items:center;gap:var(--ref-spacing-xxs);flex-shrink:0;flex-grow:1;align-self:stretch;cursor:pointer}:host .content:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10)}:host .content:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .content:focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10);box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host .content:focus-within{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host:not(.minified) ap-symbol[symbol-id=chevron-down],:host:not(.minified) ap-symbol[symbol-id=chevron-up]{color:var(--ref-color-grey-80)}:host:not(.minified) ap-symbol[symbol-id=chevron-down]:hover,:host:not(.minified) ap-symbol[symbol-id=chevron-up]:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host:not(.minified) ap-symbol[symbol-id=chevron-down]:active,:host:not(.minified) ap-symbol[symbol-id=chevron-up]:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-40)}:host:not(.minified) ap-symbol[symbol-id=chevron-down]:focus,:host:not(.minified) ap-symbol[symbol-id=chevron-up]:focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20);box-shadow:0 0 0 1px #fff,0 0 0 3px #178dfe}:host ap-symbol[symbol-id=error_fill]{color:var(--ref-color-red-100)}:host ap-symbol[symbol-id=folder]{color:var(--ref-color-grey-100)}:host ap-symbol[symbol-id=chevron-down],:host ap-symbol[symbol-id=chevron-up]{color:var(--ref-color-grey-80)}:host .folding-button{display:flex;width:24px;height:24px;justify-content:center;align-items:center;flex-shrink:0}:host .folding-button:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .folding-button:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-40)}:host .caption{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;flex:1 0 0;overflow:hidden;color:var(--ref-color-grey-100);text-overflow:ellipsis;font-family:Averta;font-size:var(--ref-font-size-xs);font-style:normal;font-weight:var(--ref-font-weight-bold);line-height:var(--ref-font-line-height-xs)}:host .children{display:flex;flex-direction:column;align-items:flex-start;flex:1 0 0;align-self:stretch}:host .picture-url-sample-container{position:relative;width:26px}:host .picture-url-sample{display:flex;width:26px;align-items:center;align-content:center;gap:2px;flex-wrap:wrap}:host.minified .content{gap:var(--ref-spacing-xxxs);position:relative;justify-content:center}:host.minified .content .toggle{position:absolute;display:none}:host.minified .content:hover .toggle,:host.minified .content:focus .toggle{inset:0;display:flex;justify-content:center;align-items:center}:host.minified .content:hover .picture-url-sample,:host.minified .content:focus .picture-url-sample{display:none}:host.minified ::ng-deep ap-checkbox .checkbox .checkbox-container{padding:0}:host.minified .status{position:absolute;right:-4px;top:-6px}\n"] }]
1986
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: NavSelectorGroupPresenter }] });
1987
+
1988
+ class NavSelectorCategoryPresenter {
1989
+ navSelectorState;
1990
+ expanded = computed(() => this.navSelectorState.expanded());
1991
+ expandedAfterDelay = computed(() => this.navSelectorState.expandedAfterDelay());
1992
+ constructor(navSelectorState) {
1993
+ this.navSelectorState = navSelectorState;
1994
+ }
1995
+ toggleFolding(event, category) {
1996
+ event.stopImmediatePropagation();
1997
+ this.navSelectorState.onGroupToggleFolding(category);
1998
+ }
1999
+ fold(event, category) {
2000
+ event.stopImmediatePropagation();
2001
+ this.navSelectorState.fold(category);
2002
+ }
2003
+ unfold(event, category) {
2004
+ event.stopImmediatePropagation();
2005
+ this.navSelectorState.unfold(category);
2006
+ }
2007
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorCategoryPresenter, deps: [{ token: NavSelectorState }], target: i0.ɵɵFactoryTarget.Injectable });
2008
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorCategoryPresenter });
2009
+ }
2010
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorCategoryPresenter, decorators: [{
2011
+ type: Injectable
2012
+ }], ctorParameters: () => [{ type: NavSelectorState }] });
2013
+
2014
+ class NavSelectorCategoryComponent {
2015
+ el;
2016
+ navSelectorCategoryPresenter;
2017
+ category = input.required();
2018
+ foldSymbol = computed(() => (this.category().folded ? 'chevron-down' : 'chevron-up'));
2019
+ foldedWithDelay = signal(false);
2020
+ animationState = computed(() => (this.category().folded ? 'collapsed' : 'expanded'));
2021
+ constructor(el, navSelectorCategoryPresenter) {
2022
+ this.el = el;
2023
+ this.navSelectorCategoryPresenter = navSelectorCategoryPresenter;
2024
+ afterNextRender(() => this.maxHeight.set(`${this.el.nativeElement.scrollHeight}px`));
2025
+ effect(() => {
2026
+ if (this.category().folded) {
2027
+ setTimeout(() => this.foldedWithDelay.set(true), 150);
2028
+ }
2029
+ else {
2030
+ this.foldedWithDelay.set(false);
2031
+ }
2032
+ }, { allowSignalWrites: true });
2033
+ }
2034
+ maxHeight = signal('0px');
2035
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorCategoryComponent, deps: [{ token: i0.ElementRef }, { token: NavSelectorCategoryPresenter }], target: i0.ɵɵFactoryTarget.Component });
2036
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.9", type: NavSelectorCategoryComponent, isStandalone: true, selector: "ap-nav-selector-category", inputs: { category: { classPropertyName: "category", publicName: "category", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "keydown.arrowLeft": "navSelectorCategoryPresenter.fold($event, this.category())", "keydown.arrowRight": "navSelectorCategoryPresenter.unfold($event, this.category())" }, properties: { "class.minified": "!navSelectorCategoryPresenter.expanded()" } }, providers: [withSymbols(apChevronDown, apChevronUp), NavSelectorCategoryPresenter], ngImport: i0, template: "@if (navSelectorCategoryPresenter.expandedAfterDelay()) {\n <div\n class=\"content\"\n [apTreeNodeAccessibility]=\"category()\"\n (keydown.space.stop)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\"\n (keydown.enter)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\">\n <span class=\"caption\">{{ category().alias }}</span>\n\n <ap-symbol\n class=\"folding-button\"\n size=\"sm\"\n [attr.aria-label]=\"'Toggle ' + category().alias\"\n [symbolId]=\"foldSymbol()\"\n (click)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\"\n (keydown.space)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\"\n (keydown.enter)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\" />\n </div>\n\n <div\n class=\"children-container\"\n [@accordion]=\"{\n value: animationState(),\n params: {\n maxHeight: maxHeight()\n }\n }\">\n @if (!foldedWithDelay()) {\n <div class=\"children\">\n @for (child of category().children; track child.uid) {\n @if (!child.hidden) {\n @if (child.type === 'LEAF') {\n <ap-nav-selector-leaf [leaf]=\"child\" />\n } @else if (child.type === 'GROUP') {\n <ap-nav-selector-group [group]=\"child\" />\n }\n }\n }\n </div>\n }\n </div>\n} @else {\n <div\n class=\"content\"\n [apTreeNodeAccessibility]=\"category()\"\n (click)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\"\n (keydown.space)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\"\n (keydown.enter)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\">\n <div class=\"name-container\">\n <span class=\"caption\">{{ category().alias }}</span>\n <span>.</span>\n </div>\n\n <div class=\"toggle\">\n <ap-symbol\n size=\"sm\"\n [symbolId]=\"foldSymbol()\" />\n </div>\n </div>\n\n <div\n class=\"children-container\"\n [@accordion]=\"{\n value: animationState(),\n params: {\n maxHeight: maxHeight()\n }\n }\">\n @if (!foldedWithDelay()) {\n <div class=\"children\">\n @for (child of category().children; track child.uid) {\n @if (!child.hidden) {\n @if (child.type === 'LEAF') {\n <ap-nav-selector-leaf [leaf]=\"child\" />\n } @else if (child.type === 'GROUP') {\n <ap-nav-selector-group [group]=\"child\" />\n }\n }\n }\n </div>\n }\n </div>\n}\n", styles: [":host{display:flex;align-items:center;flex-shrink:0;align-self:stretch;flex-direction:column}:host .children-container{align-self:stretch}:host .folding-button{display:flex;width:24px;height:24px;justify-content:center;align-items:center;flex-shrink:0}:host .folding-button:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .folding-button:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-40)}:host .content{padding:0 var(--ref-spacing-xxs);display:flex;height:36px;align-items:center;gap:var(--ref-spacing-xxs);flex-shrink:0;flex-grow:1;align-self:stretch;cursor:pointer}:host .content:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10)}:host .content:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .content:focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10);box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host .content:focus-within{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host:not(.minified) ap-symbol[symbol-id=chevron-down],:host:not(.minified) ap-symbol[symbol-id=chevron-up]{color:var(--ref-color-grey-80)}:host:not(.minified) ap-symbol[symbol-id=chevron-down]:hover,:host:not(.minified) ap-symbol[symbol-id=chevron-up]:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host:not(.minified) ap-symbol[symbol-id=chevron-down]:active,:host:not(.minified) ap-symbol[symbol-id=chevron-up]:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-40)}:host:not(.minified) ap-symbol[symbol-id=chevron-down]:focus,:host:not(.minified) ap-symbol[symbol-id=chevron-up]:focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20);box-shadow:0 0 0 1px #fff,0 0 0 3px #178dfe}:host ap-symbol[symbol-id=chevron-down],:host ap-symbol[symbol-id=chevron-up]{color:var(--ref-color-grey-80)}:host .caption{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;flex:1 0 0;overflow:hidden;color:var(--ref-color-grey-100);text-overflow:ellipsis;font-family:Averta;font-size:var(--sys-text-style-h4-size);font-style:normal;font-weight:var(--ref-font-weight-bold);line-height:var(--ref-font-line-height-md)}:host .children{display:flex;flex-direction:column;align-items:flex-start;flex:1 0 0;align-self:stretch}:host.minified .name-container{overflow:hidden;display:flex}:host.minified .content{position:relative}:host.minified .content .toggle{position:absolute;display:none}:host.minified .content:hover .toggle,:host.minified .content:focus .toggle{inset:0;display:flex;justify-content:center;align-items:center}:host.minified .content:hover .name-container,:host.minified .content:focus .name-container{display:none}\n"], dependencies: [{ kind: "component", type: NavSelectorLeafComponent, selector: "ap-nav-selector-leaf", inputs: ["leaf"] }, { kind: "component", type: SymbolComponent, selector: "ap-symbol", inputs: ["symbolId", "color", "size"], outputs: ["sizeChange"] }, { kind: "component", type: NavSelectorGroupComponent, selector: "ap-nav-selector-group", inputs: ["group"] }, { kind: "ngmodule", type: EventPluginsModule }, { kind: "directive", type: TreeNodeAccessibilityDirective, selector: "[apTreeNodeAccessibility]", inputs: ["apTreeNodeAccessibility"] }], animations: [
2037
+ /**
2038
+ * Overflow hidden is put only during the animation and on the collapsed state because if it is put on the expanded state then children’s border will be cut (hover / focus)
2039
+ */
2040
+ trigger('accordion', [
2041
+ state('collapsed', style({
2042
+ maxHeight: 0,
2043
+ overflow: 'hidden',
2044
+ })),
2045
+ state('expanded', style({
2046
+ maxHeight: 'initial',
2047
+ })),
2048
+ transition('collapsed => expanded', [
2049
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', style({ overflow: 'hidden', maxHeight: '{{maxHeight}}' })),
2050
+ ]),
2051
+ transition('expanded => collapsed', [
2052
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', keyframes([style({ maxHeight: '{{maxHeight}}' }), style({ overflow: 'hidden', maxHeight: 0 })])),
2053
+ ]),
2054
+ ]),
2055
+ ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2056
+ }
2057
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorCategoryComponent, decorators: [{
2058
+ type: Component,
2059
+ args: [{ selector: 'ap-nav-selector-category', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NavSelectorLeafComponent, SymbolComponent, NavSelectorGroupComponent, EventPluginsModule, TreeNodeAccessibilityDirective], providers: [withSymbols(apChevronDown, apChevronUp), NavSelectorCategoryPresenter], host: {
2060
+ '[class.minified]': '!navSelectorCategoryPresenter.expanded()',
2061
+ '(keydown.arrowLeft)': 'navSelectorCategoryPresenter.fold($event, this.category())',
2062
+ '(keydown.arrowRight)': 'navSelectorCategoryPresenter.unfold($event, this.category())',
2063
+ }, animations: [
2064
+ /**
2065
+ * Overflow hidden is put only during the animation and on the collapsed state because if it is put on the expanded state then children’s border will be cut (hover / focus)
2066
+ */
2067
+ trigger('accordion', [
2068
+ state('collapsed', style({
2069
+ maxHeight: 0,
2070
+ overflow: 'hidden',
2071
+ })),
2072
+ state('expanded', style({
2073
+ maxHeight: 'initial',
2074
+ })),
2075
+ transition('collapsed => expanded', [
2076
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', style({ overflow: 'hidden', maxHeight: '{{maxHeight}}' })),
2077
+ ]),
2078
+ transition('expanded => collapsed', [
2079
+ animate('250ms cubic-bezier(.4, 0, .3, 1)', keyframes([style({ maxHeight: '{{maxHeight}}' }), style({ overflow: 'hidden', maxHeight: 0 })])),
2080
+ ]),
2081
+ ]),
2082
+ ], template: "@if (navSelectorCategoryPresenter.expandedAfterDelay()) {\n <div\n class=\"content\"\n [apTreeNodeAccessibility]=\"category()\"\n (keydown.space.stop)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\"\n (keydown.enter)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\">\n <span class=\"caption\">{{ category().alias }}</span>\n\n <ap-symbol\n class=\"folding-button\"\n size=\"sm\"\n [attr.aria-label]=\"'Toggle ' + category().alias\"\n [symbolId]=\"foldSymbol()\"\n (click)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\"\n (keydown.space)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\"\n (keydown.enter)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\" />\n </div>\n\n <div\n class=\"children-container\"\n [@accordion]=\"{\n value: animationState(),\n params: {\n maxHeight: maxHeight()\n }\n }\">\n @if (!foldedWithDelay()) {\n <div class=\"children\">\n @for (child of category().children; track child.uid) {\n @if (!child.hidden) {\n @if (child.type === 'LEAF') {\n <ap-nav-selector-leaf [leaf]=\"child\" />\n } @else if (child.type === 'GROUP') {\n <ap-nav-selector-group [group]=\"child\" />\n }\n }\n }\n </div>\n }\n </div>\n} @else {\n <div\n class=\"content\"\n [apTreeNodeAccessibility]=\"category()\"\n (click)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\"\n (keydown.space)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\"\n (keydown.enter)=\"navSelectorCategoryPresenter.toggleFolding($event, this.category())\">\n <div class=\"name-container\">\n <span class=\"caption\">{{ category().alias }}</span>\n <span>.</span>\n </div>\n\n <div class=\"toggle\">\n <ap-symbol\n size=\"sm\"\n [symbolId]=\"foldSymbol()\" />\n </div>\n </div>\n\n <div\n class=\"children-container\"\n [@accordion]=\"{\n value: animationState(),\n params: {\n maxHeight: maxHeight()\n }\n }\">\n @if (!foldedWithDelay()) {\n <div class=\"children\">\n @for (child of category().children; track child.uid) {\n @if (!child.hidden) {\n @if (child.type === 'LEAF') {\n <ap-nav-selector-leaf [leaf]=\"child\" />\n } @else if (child.type === 'GROUP') {\n <ap-nav-selector-group [group]=\"child\" />\n }\n }\n }\n </div>\n }\n </div>\n}\n", styles: [":host{display:flex;align-items:center;flex-shrink:0;align-self:stretch;flex-direction:column}:host .children-container{align-self:stretch}:host .folding-button{display:flex;width:24px;height:24px;justify-content:center;align-items:center;flex-shrink:0}:host .folding-button:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .folding-button:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-40)}:host .content{padding:0 var(--ref-spacing-xxs);display:flex;height:36px;align-items:center;gap:var(--ref-spacing-xxs);flex-shrink:0;flex-grow:1;align-self:stretch;cursor:pointer}:host .content:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10)}:host .content:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host .content:focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-10);box-shadow:0 0 0 1px var(--ref-color-white),0 0 0 3px var(--ref-color-electric-blue-100)}:host .content:focus-within{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host:not(.minified) ap-symbol[symbol-id=chevron-down],:host:not(.minified) ap-symbol[symbol-id=chevron-up]{color:var(--ref-color-grey-80)}:host:not(.minified) ap-symbol[symbol-id=chevron-down]:hover,:host:not(.minified) ap-symbol[symbol-id=chevron-up]:hover{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20)}:host:not(.minified) ap-symbol[symbol-id=chevron-down]:active,:host:not(.minified) ap-symbol[symbol-id=chevron-up]:active{border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-40)}:host:not(.minified) ap-symbol[symbol-id=chevron-down]:focus,:host:not(.minified) ap-symbol[symbol-id=chevron-up]:focus{outline:none;border-radius:var(--ref-border-radius-sm);background:var(--ref-color-electric-blue-20);box-shadow:0 0 0 1px #fff,0 0 0 3px #178dfe}:host ap-symbol[symbol-id=chevron-down],:host ap-symbol[symbol-id=chevron-up]{color:var(--ref-color-grey-80)}:host .caption{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;flex:1 0 0;overflow:hidden;color:var(--ref-color-grey-100);text-overflow:ellipsis;font-family:Averta;font-size:var(--sys-text-style-h4-size);font-style:normal;font-weight:var(--ref-font-weight-bold);line-height:var(--ref-font-line-height-md)}:host .children{display:flex;flex-direction:column;align-items:flex-start;flex:1 0 0;align-self:stretch}:host.minified .name-container{overflow:hidden;display:flex}:host.minified .content{position:relative}:host.minified .content .toggle{position:absolute;display:none}:host.minified .content:hover .toggle,:host.minified .content:focus .toggle{inset:0;display:flex;justify-content:center;align-items:center}:host.minified .content:hover .name-container,:host.minified .content:focus .name-container{display:none}\n"] }]
2083
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: NavSelectorCategoryPresenter }] });
2084
+
2085
+ let nextUniqueId = 0;
2086
+ class NavSelectorComponent {
2087
+ navSelectorState;
2088
+ el;
2089
+ navSelectorEntries = input.required();
2090
+ translatedTexts = input.required();
2091
+ multipleModeEnabled = input(false);
2092
+ detailsDisplayedLimit = input(Number.MAX_SAFE_INTEGER);
2093
+ /**
2094
+ * If true, the nav selector will be expanded by default. Even if the width of the screen is smaller than 1280px.
2095
+ */
2096
+ forceExpanded = input(false);
2097
+ selectedEntryUids = model.required();
2098
+ headerProjection = contentChild('header');
2099
+ footerProjection = contentChild('footer');
2100
+ displayFooter = computed(() => this.footerProjection() !== undefined);
2101
+ leafActionProjection = contentChildren('leafAction');
2102
+ expansionState = computed(() => (this.navSelectorState.expanded() ? 'expanded' : 'minified'));
2103
+ componentUid = `nav-selector-${nextUniqueId++}`;
2104
+ constructor(navSelectorState, el) {
2105
+ this.navSelectorState = navSelectorState;
2106
+ this.el = el;
2107
+ navSelectorState.registerOnSelectedUidsChange(selectedUids => {
2108
+ this.selectedEntryUids.set(selectedUids);
2109
+ });
2110
+ afterNextRender(() => {
2111
+ if (!this.forceExpanded() && document.body.clientWidth < 1200) {
2112
+ this.navSelectorState.toggleExpanded();
2113
+ }
2114
+ });
2115
+ effect(() => {
2116
+ this.navSelectorState.updateMultiModeEnabled(this.multipleModeEnabled());
2117
+ if (!this.navSelectorState.filteredEntries().length) {
2118
+ this.navSelectorState.updateEntries(this.navSelectorEntries(), this.selectedEntryUids(), this.detailsDisplayedLimit());
2119
+ }
2120
+ }, { allowSignalWrites: true });
2121
+ effect(() => {
2122
+ this.navSelectorState.updateDetailsDisplayedLimit(this.detailsDisplayedLimit());
2123
+ }, { allowSignalWrites: true });
2124
+ const leafActionProjectionEffect = effect(() => {
2125
+ if (this.leafActionProjection()) {
2126
+ this.navSelectorState.updateLeafAction(this.leafActionProjection());
2127
+ leafActionProjectionEffect.destroy();
2128
+ }
2129
+ }, { manualCleanup: true, allowSignalWrites: true });
2130
+ effect(() => {
2131
+ this.navSelectorState.onSelectionChange(this.selectedEntryUids());
2132
+ }, { allowSignalWrites: true });
2133
+ effect(() => {
2134
+ this.navSelectorState.updateTexts(this.translatedTexts());
2135
+ }, { allowSignalWrites: true });
2136
+ }
2137
+ onArrowDown($event) {
2138
+ if (this.el.nativeElement.querySelector('.nav-selector__content').contains(document.activeElement)) {
2139
+ $event.stopImmediatePropagation();
2140
+ this.navSelectorState.onArrowDown();
2141
+ setTimeout(() => this.el.nativeElement.querySelector('[role="treeitem"][tabindex="0"]').focus());
2142
+ }
2143
+ }
2144
+ onArrowUp($event) {
2145
+ if (this.el.nativeElement.querySelector('.nav-selector__content').contains(document.activeElement)) {
2146
+ $event.stopImmediatePropagation();
2147
+ this.navSelectorState.onArrowUp();
2148
+ setTimeout(() => this.el.nativeElement.querySelector('[role="treeitem"][tabindex="0"]').focus());
2149
+ }
2150
+ }
2151
+ TemplateRef = TemplateRef;
2152
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorComponent, deps: [{ token: NavSelectorState }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
2153
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.9", type: NavSelectorComponent, isStandalone: true, selector: "ap-nav-selector", inputs: { navSelectorEntries: { classPropertyName: "navSelectorEntries", publicName: "navSelectorEntries", isSignal: true, isRequired: true, transformFunction: null }, translatedTexts: { classPropertyName: "translatedTexts", publicName: "translatedTexts", isSignal: true, isRequired: true, transformFunction: null }, multipleModeEnabled: { classPropertyName: "multipleModeEnabled", publicName: "multipleModeEnabled", isSignal: true, isRequired: false, transformFunction: null }, detailsDisplayedLimit: { classPropertyName: "detailsDisplayedLimit", publicName: "detailsDisplayedLimit", isSignal: true, isRequired: false, transformFunction: null }, forceExpanded: { classPropertyName: "forceExpanded", publicName: "forceExpanded", isSignal: true, isRequired: false, transformFunction: null }, selectedEntryUids: { classPropertyName: "selectedEntryUids", publicName: "selectedEntryUids", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { selectedEntryUids: "selectedEntryUidsChange" }, host: { attributes: { "role": "tree" }, listeners: { "keydown.arrowDown": "onArrowDown($event)", "keydown.arrowUp": "onArrowUp($event)" }, properties: { "class.minified": "!navSelectorState.expanded()" } }, providers: [NavSelectorState, withSymbols(apArrowExpand, apArrowReduce, apSearch)], queries: [{ propertyName: "headerProjection", first: true, predicate: ["header"], descendants: true, isSignal: true }, { propertyName: "footerProjection", first: true, predicate: ["footer"], descendants: true, isSignal: true }, { propertyName: "leafActionProjection", predicate: ["leafAction"], isSignal: true }], ngImport: i0, template: "<nav [@expand]=\"expansionState()\">\n @let headerProjectionNotNull = headerProjection();\n @let footerProjectionNotNull = footerProjection();\n\n @if (navSelectorState.expandedAfterDelay()) {\n <div class=\"nav-selector__header\">\n <span class=\"h3\">{{ translatedTexts().title }}</span>\n\n <button\n type=\"button\"\n class=\"expand-button expanded\"\n (click)=\"navSelectorState.toggleExpanded()\">\n <ap-symbol\n size=\"sm\"\n symbolId=\"arrow-reduce\" />\n </button>\n\n\n @if (headerProjectionNotNull) {\n <ng-container\n [ngTemplateOutlet]=\"headerProjectionNotNull\"\n [ngTemplateOutletContext]=\"{\n expanded: navSelectorState.expanded()\n }\" />\n }\n\n <ap-input-search\n [id]=\"componentUid + '_search'\"\n class=\"nav-selector-search\"\n [placeholder]=\"translatedTexts().searchPlaceholder\"\n [ngModel]=\"navSelectorState.search()\"\n (ngModelChange)=\"navSelectorState.search.set($event ?? '')\" />\n </div>\n\n <div\n class=\"nav-selector__content\"\n role=\"tree\">\n @for (entry of navSelectorState.filteredEntries(); track entry.uid) {\n @if (!entry.hidden) {\n <div class=\"entry\">\n @if (entry.type === 'LEAF') {\n <ap-nav-selector-leaf [leaf]=\"entry\" />\n } @else if (entry.type === 'GROUP') {\n <ap-nav-selector-group [group]=\"entry\" />\n } @else if (entry.type === 'CATEGORY') {\n <ap-nav-selector-category [category]=\"$any(entry)\" />\n }\n </div>\n }\n }\n @if (navSelectorState.noResults()) {\n <div class=\"no-result\">{{ translatedTexts().noResults }}</div>\n }\n </div>\n\n @if (displayFooter() && footerProjectionNotNull) {\n <div class=\"nav-selector__footer\">\n <ng-container\n [ngTemplateOutlet]=\"footerProjectionNotNull\"\n [ngTemplateOutletContext]=\"{\n expanded: navSelectorState.expanded()\n }\" />\n </div>\n }\n } @else {\n <div class=\"nav-selector__header\">\n <button\n type=\"button\"\n class=\"expand-button\"\n (click)=\"navSelectorState.toggleExpanded()\">\n <ap-symbol\n size=\"sm\"\n symbolId=\"arrow-expand\" />\n </button>\n @if (headerProjectionNotNull) {\n <ng-container\n [ngTemplateOutlet]=\"headerProjectionNotNull\"\n [ngTemplateOutletContext]=\"{\n expanded: navSelectorState.expanded()\n }\" />\n }\n\n <ap-icon-button (onClick)=\"navSelectorState.toggleExpanded()\">\n <ap-symbol symbolId=\"search\" />\n </ap-icon-button>\n </div>\n\n <div class=\"nav-selector__content\">\n @for (entry of navSelectorState.filteredEntries(); track entry.uid) {\n @if (!entry.hidden) {\n <div class=\"entry\">\n @if (entry.type === 'LEAF') {\n <ap-nav-selector-leaf [leaf]=\"entry\" />\n } @else if (entry.type === 'GROUP') {\n <ap-nav-selector-group [group]=\"entry\" />\n } @else if (entry.type === 'CATEGORY') {\n <ap-nav-selector-category [category]=\"entry\" />\n }\n </div>\n }\n }\n </div>\n\n @if (displayFooter() && footerProjectionNotNull) {\n <div class=\"nav-selector__footer\">\n <ng-container\n [ngTemplateOutlet]=\"footerProjectionNotNull\"\n [ngTemplateOutletContext]=\"{\n expanded: navSelectorState.expanded()\n }\" />\n </div>\n }\n }\n</nav>\n", styles: [":host{display:flex;height:100%;flex-direction:column;align-items:flex-start;flex-shrink:0;width:224px;max-width:224px}@media only screen and (min-device-width: 1400px){:host{width:100%;max-width:250px}}:host :hover .expand-button.expanded{animation-name:translateExpandButton}:host nav{display:flex;height:100%;width:100%;flex-direction:column;align-items:flex-start;flex-shrink:0;overflow:hidden;border-right:1px solid var(--ref-color-grey-10);background:var(--ref-color-white)}:host .nav-selector__header{position:relative;display:flex;padding:var(--ref-spacing-xs) var(--ref-spacing-sm);flex-direction:column;align-items:flex-start;gap:8px;align-self:stretch;border-bottom:1px solid var(--ref-color-grey-10);background:var(--ref-color-white)}:host .nav-selector__header .h3{color:var(--ref-color-grey-100);font-family:Averta;font-size:var(--sys-text-h3-size);font-style:normal;font-weight:var(--ref-font-weight-bold);line-height:var(--ref-font-line-height-lg)}:host .nav-selector__header .expand-button-container{position:absolute;right:0;top:var(--ref-spacing-xs)}:host .nav-selector__header .expand-button{animation-duration:70ms;animation-timing-function:cubic-bezier(0,0,.2,1);animation-fill-mode:forwards;display:flex;width:24px;height:24px;justify-content:center;align-items:center;background:none;border:1px solid var(--ref-color-grey-20);border-top-left-radius:var(--ref-border-radius-sm);border-bottom-left-radius:var(--ref-border-radius-sm);cursor:pointer}@keyframes translateExpandButton{0%{transform:translate(100%)}to{transform:translate(0)}}:host .nav-selector__header .expand-button.expanded{position:absolute;right:0;top:12px;transform:translate(100%)}:host .nav-selector__header .expand-button ap-symbol[symbol-id=arrow-reduce],:host .nav-selector__header .expand-button ap-symbol[symbol-id=arrow-expand]{color:var(--ref-color-grey-80)}:host .nav-selector__header .expand-button:focus{border-radius:var(--ref-border-radius-sm) 0px 0px var(--ref-border-radius-sm);border-top:1px solid var(--ref-color-grey-20);border-bottom:1px solid var(--ref-color-grey-20);border-left:1px solid var(--ref-color-grey-20);background:var(--ref-color-grey-10);box-shadow:0 0 0 1px #fff,0 0 0 3px #178dfe}:host .nav-selector__header .expand-button:focus.expanded{animation-name:translateExpandButton}:host .nav-selector__header .expand-button:hover{background-color:var(--ref-color-grey-10)}:host .nav-selector__header .expand-button:active{background-color:var(--ref-color-grey-20)}:host .nav-selector__header .nav-selector-search{width:100%}:host .nav-selector__content{display:flex;flex-direction:column;align-items:flex-start;flex:1 0 0;align-self:stretch;overflow:auto}:host .nav-selector__content .entry{padding:var(--ref-spacing-xxs);align-self:stretch;display:flex;flex-direction:column}:host .nav-selector__content .entry+.entry{border-top:1px solid var(--sys-border-color-default)}:host .nav-selector__content .no-result{display:flex;padding:var(--ref-spacing-sm);flex-direction:column;align-items:flex-start;flex:1 0 0;align-self:stretch;color:var(--ref-color-grey-80);font-family:Averta;font-size:var(--ref-font-size-sm);font-style:italic;font-weight:400;line-height:var(--ref-font-line-height-sm)}:host .nav-selector__footer{display:flex;padding:var(--ref-spacing-xs);flex-direction:column;align-items:flex-start;gap:var(--ref-spacing-xxs);align-self:stretch;border-top:1px solid var(--sys-border-color-default);background:var(--ref-color-white)}:host.minified nav{width:64px}:host.minified nav .nav-selector__header{align-items:center}:host.minified nav .nav-selector__content .entry{padding:var(--ref-spacing-xxxs)}:host.minified nav .nav-selector__footer{padding:var(--ref-spacing-xs) var(--ref-spacing-xxxs) var(--ref-spacing-xs) var(--ref-spacing-xxxs)}\n"], dependencies: [{ kind: "component", type: NavSelectorLeafComponent, selector: "ap-nav-selector-leaf", inputs: ["leaf"] }, { kind: "component", type: NavSelectorGroupComponent, selector: "ap-nav-selector-group", inputs: ["group"] }, { kind: "component", type: NavSelectorCategoryComponent, selector: "ap-nav-selector-category", inputs: ["category"] }, { kind: "component", type: InputSearchComponent, selector: "ap-input-search", inputs: ["id", "placeholder", "clearable"], outputs: ["focus", "blur", "keyup"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: SymbolComponent, selector: "ap-symbol", inputs: ["symbolId", "color", "size"], outputs: ["sizeChange"] }, { kind: "component", type: IconButtonComponent, selector: "ap-icon-button", inputs: ["ariaLabel", "name", "color", "disabled", "menuTrigger", "locked", "loading", "type"], outputs: ["onClick", "onFocus", "onBlur", "menuOpened", "menuClosed"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: EventPluginsModule }], animations: [
2154
+ trigger('expand', [
2155
+ state('expanded', style({ width: '100%' })),
2156
+ state('minified', style({ with: '64px' })),
2157
+ transition('expanded => minified', animate('250ms cubic-bezier(.4, 0, .3, 1)')),
2158
+ transition('minified => expanded', animate('250ms cubic-bezier(.4, 0, .3, 1)',
2159
+ // Force animation to do not be with 100% instantly
2160
+ keyframes([style({ width: '64px' }), style({ width: '50%' }), style({ width: '100%' })]))),
2161
+ ]),
2162
+ ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2163
+ }
2164
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: NavSelectorComponent, decorators: [{
2165
+ type: Component,
2166
+ args: [{ selector: 'ap-nav-selector', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2167
+ NavSelectorLeafComponent,
2168
+ NavSelectorGroupComponent,
2169
+ NavSelectorCategoryComponent,
2170
+ InputSearchComponent,
2171
+ FormsModule,
2172
+ SymbolComponent,
2173
+ IconButtonComponent,
2174
+ NgTemplateOutlet,
2175
+ EventPluginsModule,
2176
+ ], providers: [NavSelectorState, withSymbols(apArrowExpand, apArrowReduce, apSearch)], host: {
2177
+ '[class.minified]': '!navSelectorState.expanded()',
2178
+ role: 'tree',
2179
+ '(keydown.arrowDown)': 'onArrowDown($event)',
2180
+ '(keydown.arrowUp)': 'onArrowUp($event)',
2181
+ }, animations: [
2182
+ trigger('expand', [
2183
+ state('expanded', style({ width: '100%' })),
2184
+ state('minified', style({ with: '64px' })),
2185
+ transition('expanded => minified', animate('250ms cubic-bezier(.4, 0, .3, 1)')),
2186
+ transition('minified => expanded', animate('250ms cubic-bezier(.4, 0, .3, 1)',
2187
+ // Force animation to do not be with 100% instantly
2188
+ keyframes([style({ width: '64px' }), style({ width: '50%' }), style({ width: '100%' })]))),
2189
+ ]),
2190
+ ], template: "<nav [@expand]=\"expansionState()\">\n @let headerProjectionNotNull = headerProjection();\n @let footerProjectionNotNull = footerProjection();\n\n @if (navSelectorState.expandedAfterDelay()) {\n <div class=\"nav-selector__header\">\n <span class=\"h3\">{{ translatedTexts().title }}</span>\n\n <button\n type=\"button\"\n class=\"expand-button expanded\"\n (click)=\"navSelectorState.toggleExpanded()\">\n <ap-symbol\n size=\"sm\"\n symbolId=\"arrow-reduce\" />\n </button>\n\n\n @if (headerProjectionNotNull) {\n <ng-container\n [ngTemplateOutlet]=\"headerProjectionNotNull\"\n [ngTemplateOutletContext]=\"{\n expanded: navSelectorState.expanded()\n }\" />\n }\n\n <ap-input-search\n [id]=\"componentUid + '_search'\"\n class=\"nav-selector-search\"\n [placeholder]=\"translatedTexts().searchPlaceholder\"\n [ngModel]=\"navSelectorState.search()\"\n (ngModelChange)=\"navSelectorState.search.set($event ?? '')\" />\n </div>\n\n <div\n class=\"nav-selector__content\"\n role=\"tree\">\n @for (entry of navSelectorState.filteredEntries(); track entry.uid) {\n @if (!entry.hidden) {\n <div class=\"entry\">\n @if (entry.type === 'LEAF') {\n <ap-nav-selector-leaf [leaf]=\"entry\" />\n } @else if (entry.type === 'GROUP') {\n <ap-nav-selector-group [group]=\"entry\" />\n } @else if (entry.type === 'CATEGORY') {\n <ap-nav-selector-category [category]=\"$any(entry)\" />\n }\n </div>\n }\n }\n @if (navSelectorState.noResults()) {\n <div class=\"no-result\">{{ translatedTexts().noResults }}</div>\n }\n </div>\n\n @if (displayFooter() && footerProjectionNotNull) {\n <div class=\"nav-selector__footer\">\n <ng-container\n [ngTemplateOutlet]=\"footerProjectionNotNull\"\n [ngTemplateOutletContext]=\"{\n expanded: navSelectorState.expanded()\n }\" />\n </div>\n }\n } @else {\n <div class=\"nav-selector__header\">\n <button\n type=\"button\"\n class=\"expand-button\"\n (click)=\"navSelectorState.toggleExpanded()\">\n <ap-symbol\n size=\"sm\"\n symbolId=\"arrow-expand\" />\n </button>\n @if (headerProjectionNotNull) {\n <ng-container\n [ngTemplateOutlet]=\"headerProjectionNotNull\"\n [ngTemplateOutletContext]=\"{\n expanded: navSelectorState.expanded()\n }\" />\n }\n\n <ap-icon-button (onClick)=\"navSelectorState.toggleExpanded()\">\n <ap-symbol symbolId=\"search\" />\n </ap-icon-button>\n </div>\n\n <div class=\"nav-selector__content\">\n @for (entry of navSelectorState.filteredEntries(); track entry.uid) {\n @if (!entry.hidden) {\n <div class=\"entry\">\n @if (entry.type === 'LEAF') {\n <ap-nav-selector-leaf [leaf]=\"entry\" />\n } @else if (entry.type === 'GROUP') {\n <ap-nav-selector-group [group]=\"entry\" />\n } @else if (entry.type === 'CATEGORY') {\n <ap-nav-selector-category [category]=\"entry\" />\n }\n </div>\n }\n }\n </div>\n\n @if (displayFooter() && footerProjectionNotNull) {\n <div class=\"nav-selector__footer\">\n <ng-container\n [ngTemplateOutlet]=\"footerProjectionNotNull\"\n [ngTemplateOutletContext]=\"{\n expanded: navSelectorState.expanded()\n }\" />\n </div>\n }\n }\n</nav>\n", styles: [":host{display:flex;height:100%;flex-direction:column;align-items:flex-start;flex-shrink:0;width:224px;max-width:224px}@media only screen and (min-device-width: 1400px){:host{width:100%;max-width:250px}}:host :hover .expand-button.expanded{animation-name:translateExpandButton}:host nav{display:flex;height:100%;width:100%;flex-direction:column;align-items:flex-start;flex-shrink:0;overflow:hidden;border-right:1px solid var(--ref-color-grey-10);background:var(--ref-color-white)}:host .nav-selector__header{position:relative;display:flex;padding:var(--ref-spacing-xs) var(--ref-spacing-sm);flex-direction:column;align-items:flex-start;gap:8px;align-self:stretch;border-bottom:1px solid var(--ref-color-grey-10);background:var(--ref-color-white)}:host .nav-selector__header .h3{color:var(--ref-color-grey-100);font-family:Averta;font-size:var(--sys-text-h3-size);font-style:normal;font-weight:var(--ref-font-weight-bold);line-height:var(--ref-font-line-height-lg)}:host .nav-selector__header .expand-button-container{position:absolute;right:0;top:var(--ref-spacing-xs)}:host .nav-selector__header .expand-button{animation-duration:70ms;animation-timing-function:cubic-bezier(0,0,.2,1);animation-fill-mode:forwards;display:flex;width:24px;height:24px;justify-content:center;align-items:center;background:none;border:1px solid var(--ref-color-grey-20);border-top-left-radius:var(--ref-border-radius-sm);border-bottom-left-radius:var(--ref-border-radius-sm);cursor:pointer}@keyframes translateExpandButton{0%{transform:translate(100%)}to{transform:translate(0)}}:host .nav-selector__header .expand-button.expanded{position:absolute;right:0;top:12px;transform:translate(100%)}:host .nav-selector__header .expand-button ap-symbol[symbol-id=arrow-reduce],:host .nav-selector__header .expand-button ap-symbol[symbol-id=arrow-expand]{color:var(--ref-color-grey-80)}:host .nav-selector__header .expand-button:focus{border-radius:var(--ref-border-radius-sm) 0px 0px var(--ref-border-radius-sm);border-top:1px solid var(--ref-color-grey-20);border-bottom:1px solid var(--ref-color-grey-20);border-left:1px solid var(--ref-color-grey-20);background:var(--ref-color-grey-10);box-shadow:0 0 0 1px #fff,0 0 0 3px #178dfe}:host .nav-selector__header .expand-button:focus.expanded{animation-name:translateExpandButton}:host .nav-selector__header .expand-button:hover{background-color:var(--ref-color-grey-10)}:host .nav-selector__header .expand-button:active{background-color:var(--ref-color-grey-20)}:host .nav-selector__header .nav-selector-search{width:100%}:host .nav-selector__content{display:flex;flex-direction:column;align-items:flex-start;flex:1 0 0;align-self:stretch;overflow:auto}:host .nav-selector__content .entry{padding:var(--ref-spacing-xxs);align-self:stretch;display:flex;flex-direction:column}:host .nav-selector__content .entry+.entry{border-top:1px solid var(--sys-border-color-default)}:host .nav-selector__content .no-result{display:flex;padding:var(--ref-spacing-sm);flex-direction:column;align-items:flex-start;flex:1 0 0;align-self:stretch;color:var(--ref-color-grey-80);font-family:Averta;font-size:var(--ref-font-size-sm);font-style:italic;font-weight:400;line-height:var(--ref-font-line-height-sm)}:host .nav-selector__footer{display:flex;padding:var(--ref-spacing-xs);flex-direction:column;align-items:flex-start;gap:var(--ref-spacing-xxs);align-self:stretch;border-top:1px solid var(--sys-border-color-default);background:var(--ref-color-white)}:host.minified nav{width:64px}:host.minified nav .nav-selector__header{align-items:center}:host.minified nav .nav-selector__content .entry{padding:var(--ref-spacing-xxxs)}:host.minified nav .nav-selector__footer{padding:var(--ref-spacing-xs) var(--ref-spacing-xxxs) var(--ref-spacing-xs) var(--ref-spacing-xxxs)}\n"] }]
2191
+ }], ctorParameters: () => [{ type: NavSelectorState }, { type: i0.ElementRef }] });
2192
+
2193
+ /**
2194
+ * Generated bundle index. Do not edit.
2195
+ */
2196
+
2197
+ export { NavSelectorComponent };
2198
+ //# sourceMappingURL=agorapulse-ui-components-nav-selector.mjs.map