@angular/cdk-experimental 21.0.0-next.5 → 21.0.0-next.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/{accordion2.mjs → _accordion-chunk.mjs} +4 -3
- package/fesm2022/_accordion-chunk.mjs.map +1 -0
- package/fesm2022/_combobox-chunk.mjs +278 -0
- package/fesm2022/_combobox-chunk.mjs.map +1 -0
- package/fesm2022/{option.mjs → _combobox-listbox-chunk.mjs} +55 -8
- package/fesm2022/_combobox-listbox-chunk.mjs.map +1 -0
- package/fesm2022/_combobox-tree-chunk.mjs +398 -0
- package/fesm2022/_combobox-tree-chunk.mjs.map +1 -0
- package/fesm2022/{expansion.mjs → _expansion-chunk.mjs} +2 -2
- package/fesm2022/_expansion-chunk.mjs.map +1 -0
- package/fesm2022/{list.mjs → _list-chunk.mjs} +9 -5
- package/fesm2022/_list-chunk.mjs.map +1 -0
- package/fesm2022/_list-navigation-chunk.mjs +131 -0
- package/fesm2022/_list-navigation-chunk.mjs.map +1 -0
- package/fesm2022/{list-navigation.mjs → _pointer-event-manager-chunk.mjs} +2 -118
- package/fesm2022/_pointer-event-manager-chunk.mjs.map +1 -0
- package/fesm2022/{polyfill.mjs → _polyfill-chunk.mjs} +1 -1
- package/fesm2022/_polyfill-chunk.mjs.map +1 -0
- package/fesm2022/{tabs2.mjs → _tabs-chunk.mjs} +4 -4
- package/fesm2022/_tabs-chunk.mjs.map +1 -0
- package/fesm2022/_toolbar-chunk.mjs +273 -0
- package/fesm2022/_toolbar-chunk.mjs.map +1 -0
- package/fesm2022/_toolbar-radio-group-chunk.mjs +222 -0
- package/fesm2022/_toolbar-radio-group-chunk.mjs.map +1 -0
- package/fesm2022/accordion.mjs +4 -3
- package/fesm2022/accordion.mjs.map +1 -1
- package/fesm2022/cdk-experimental.mjs +1 -1
- package/fesm2022/cdk-experimental.mjs.map +1 -1
- package/fesm2022/column-resize.mjs +1 -1
- package/fesm2022/column-resize.mjs.map +1 -1
- package/fesm2022/combobox.mjs +99 -308
- package/fesm2022/combobox.mjs.map +1 -1
- package/fesm2022/deferred-content.mjs +3 -3
- package/fesm2022/deferred-content.mjs.map +1 -1
- package/fesm2022/listbox.mjs +53 -12
- package/fesm2022/listbox.mjs.map +1 -1
- package/fesm2022/popover-edit.mjs +1 -1
- package/fesm2022/popover-edit.mjs.map +1 -1
- package/fesm2022/radio-group.mjs +42 -47
- package/fesm2022/radio-group.mjs.map +1 -1
- package/fesm2022/scrolling.mjs.map +1 -1
- package/fesm2022/selection.mjs.map +1 -1
- package/fesm2022/table-scroll-container.mjs.map +1 -1
- package/fesm2022/tabs.mjs +5 -4
- package/fesm2022/tabs.mjs.map +1 -1
- package/fesm2022/toolbar.mjs +69 -19
- package/fesm2022/toolbar.mjs.map +1 -1
- package/fesm2022/tree.mjs +57 -344
- package/fesm2022/tree.mjs.map +1 -1
- package/fesm2022/ui-patterns.mjs +11 -8
- package/fesm2022/ui-patterns.mjs.map +1 -1
- package/package.json +18 -18
- package/{accordion.d.d.ts → types/_accordion-chunk.d.ts} +3 -2
- package/types/_combobox-chunk.d.ts +138 -0
- package/{expansion.d.d.ts → types/_expansion-chunk.d.ts} +2 -2
- package/{list.d.d.ts → types/_list-chunk.d.ts} +4 -2
- package/{pointer-event-manager.d.d.ts → types/_list-navigation-chunk.d.ts} +7 -96
- package/{listbox.d.d.ts → types/_listbox-chunk.d.ts} +8 -4
- package/types/_pointer-event-manager-chunk.d.ts +98 -0
- package/types/_radio-group-chunk.d.ts +92 -0
- package/{tabs.d.d.ts → types/_tabs-chunk.d.ts} +4 -3
- package/types/_toolbar-chunk.d.ts +150 -0
- package/types/_tree-chunk.d.ts +139 -0
- package/{accordion/index.d.ts → types/accordion.d.ts} +4 -3
- package/types/combobox.d.ts +54 -0
- package/{deferred-content/index.d.ts → types/deferred-content.d.ts} +2 -2
- package/{listbox/index.d.ts → types/listbox.d.ts} +15 -5
- package/{radio-group/index.d.ts → types/radio-group.d.ts} +21 -23
- package/{tabs/index.d.ts → types/tabs.d.ts} +5 -4
- package/types/toolbar.d.ts +115 -0
- package/{tree/index.d.ts → types/tree.d.ts} +17 -137
- package/types/ui-patterns.d.ts +157 -0
- package/combobox/index.d.ts +0 -94
- package/fesm2022/accordion2.mjs.map +0 -1
- package/fesm2022/expansion.mjs.map +0 -1
- package/fesm2022/list-navigation.mjs.map +0 -1
- package/fesm2022/list.mjs.map +0 -1
- package/fesm2022/option.mjs.map +0 -1
- package/fesm2022/polyfill.mjs.map +0 -1
- package/fesm2022/radio-group2.mjs +0 -143
- package/fesm2022/radio-group2.mjs.map +0 -1
- package/fesm2022/tabs2.mjs.map +0 -1
- package/fesm2022/toolbar2.mjs +0 -224
- package/fesm2022/toolbar2.mjs.map +0 -1
- package/radio-group.d.d.ts +0 -80
- package/toolbar/index.d.ts +0 -91
- package/toolbar.d.d.ts +0 -136
- package/ui-patterns/index.d.ts +0 -9
- /package/{index.d.ts → types/cdk-experimental.d.ts} +0 -0
- /package/{column-resize/index.d.ts → types/column-resize.d.ts} +0 -0
- /package/{popover-edit/index.d.ts → types/popover-edit.d.ts} +0 -0
- /package/{scrolling/index.d.ts → types/scrolling.d.ts} +0 -0
- /package/{selection/index.d.ts → types/selection.d.ts} +0 -0
- /package/{table-scroll-container/index.d.ts → types/table-scroll-container.d.ts} +0 -0
package/fesm2022/tree.mjs
CHANGED
|
@@ -1,339 +1,16 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { inject, computed, ElementRef, signal, input, booleanAttribute, model, afterRenderEffect, untracked, Directive } from '@angular/core';
|
|
3
3
|
import { _IdGenerator } from '@angular/cdk/a11y';
|
|
4
4
|
import { Directionality } from '@angular/cdk/bidi';
|
|
5
|
-
import * as i1 from '@angular/cdk-experimental/deferred-content';
|
|
5
|
+
import * as i1$1 from '@angular/cdk-experimental/deferred-content';
|
|
6
6
|
import { DeferredContentAware, DeferredContent } from '@angular/cdk-experimental/deferred-content';
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class TreeItemPattern {
|
|
15
|
-
inputs;
|
|
16
|
-
/** The position of this item among its siblings. */
|
|
17
|
-
index = computed(() => this.tree().visibleItems().indexOf(this));
|
|
18
|
-
/** The unique identifier used by the expansion behavior. */
|
|
19
|
-
expansionId;
|
|
20
|
-
/** Controls expansion for child items. */
|
|
21
|
-
expansionManager;
|
|
22
|
-
/** Controls expansion for this item. */
|
|
23
|
-
expansion;
|
|
24
|
-
/** Whether the item is expandable. It's expandable if children item exist. */
|
|
25
|
-
expandable;
|
|
26
|
-
/** The level of the current item in a tree. */
|
|
27
|
-
level = computed(() => this.parent().level() + 1);
|
|
28
|
-
/** Whether this item is currently expanded. */
|
|
29
|
-
expanded = computed(() => this.expansion.isExpanded());
|
|
30
|
-
/** Whether this item is visible. */
|
|
31
|
-
visible = computed(() => this.parent().expanded());
|
|
32
|
-
/** The number of items under the same parent at the same level. */
|
|
33
|
-
setsize = computed(() => this.parent().children().length);
|
|
34
|
-
/** The position of this item among its siblings (1-based). */
|
|
35
|
-
posinset = computed(() => this.parent().children().indexOf(this) + 1);
|
|
36
|
-
/** Whether the item is active. */
|
|
37
|
-
active = computed(() => this.tree().activeItem() === this);
|
|
38
|
-
/** The tabindex of the item. */
|
|
39
|
-
tabindex = computed(() => this.tree().listBehavior.getItemTabindex(this));
|
|
40
|
-
/** Whether the item is selected. */
|
|
41
|
-
selected = computed(() => {
|
|
42
|
-
if (this.tree().nav()) {
|
|
43
|
-
return undefined;
|
|
44
|
-
}
|
|
45
|
-
return this.tree().value().includes(this.value());
|
|
46
|
-
});
|
|
47
|
-
/** The current type of this item. */
|
|
48
|
-
current = computed(() => {
|
|
49
|
-
if (!this.tree().nav()) {
|
|
50
|
-
return undefined;
|
|
51
|
-
}
|
|
52
|
-
return this.tree().value().includes(this.value()) ? this.tree().currentType() : undefined;
|
|
53
|
-
});
|
|
54
|
-
constructor(inputs) {
|
|
55
|
-
this.inputs = inputs;
|
|
56
|
-
this.id = inputs.id;
|
|
57
|
-
this.value = inputs.value;
|
|
58
|
-
this.element = inputs.element;
|
|
59
|
-
this.disabled = inputs.disabled;
|
|
60
|
-
this.searchTerm = inputs.searchTerm;
|
|
61
|
-
this.expansionId = inputs.id;
|
|
62
|
-
this.tree = inputs.tree;
|
|
63
|
-
this.parent = inputs.parent;
|
|
64
|
-
this.children = inputs.children;
|
|
65
|
-
this.expandable = inputs.hasChildren;
|
|
66
|
-
this.expansion = new ExpansionControl({
|
|
67
|
-
...inputs,
|
|
68
|
-
expandable: this.expandable,
|
|
69
|
-
expansionId: this.expansionId,
|
|
70
|
-
expansionManager: this.parent().expansionManager,
|
|
71
|
-
});
|
|
72
|
-
this.expansionManager = new ListExpansion({
|
|
73
|
-
...inputs,
|
|
74
|
-
multiExpandable: () => true,
|
|
75
|
-
// TODO(ok7sai): allow pre-expanded tree items.
|
|
76
|
-
expandedIds: signal([]),
|
|
77
|
-
items: this.children,
|
|
78
|
-
disabled: computed(() => this.tree()?.disabled() ?? false),
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/** Controls the state and interactions of a tree view. */
|
|
83
|
-
class TreePattern {
|
|
84
|
-
inputs;
|
|
85
|
-
/** The list behavior for the tree. */
|
|
86
|
-
listBehavior;
|
|
87
|
-
/** Controls expansion for direct children of the tree root (top-level items). */
|
|
88
|
-
expansionManager;
|
|
89
|
-
/** The root level is 0. */
|
|
90
|
-
level = () => 0;
|
|
91
|
-
/** The root is always expanded. */
|
|
92
|
-
expanded = () => true;
|
|
93
|
-
/** The tabindex of the tree. */
|
|
94
|
-
tabindex = computed(() => this.listBehavior.tabindex());
|
|
95
|
-
/** The id of the current active item. */
|
|
96
|
-
activedescendant = computed(() => this.listBehavior.activedescendant());
|
|
97
|
-
/** The direct children of the root (top-level tree items). */
|
|
98
|
-
children = computed(() => this.inputs.allItems().filter(item => item.level() === this.level() + 1));
|
|
99
|
-
/** All currently visible tree items. An item is visible if their parent is expanded. */
|
|
100
|
-
visibleItems = computed(() => this.inputs.allItems().filter(item => item.visible()));
|
|
101
|
-
/** Whether the tree selection follows focus. */
|
|
102
|
-
followFocus = computed(() => this.inputs.selectionMode() === 'follow');
|
|
103
|
-
/** The key for navigating to the previous item. */
|
|
104
|
-
prevKey = computed(() => {
|
|
105
|
-
if (this.inputs.orientation() === 'vertical') {
|
|
106
|
-
return 'ArrowUp';
|
|
107
|
-
}
|
|
108
|
-
return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
|
|
109
|
-
});
|
|
110
|
-
/** The key for navigating to the next item. */
|
|
111
|
-
nextKey = computed(() => {
|
|
112
|
-
if (this.inputs.orientation() === 'vertical') {
|
|
113
|
-
return 'ArrowDown';
|
|
114
|
-
}
|
|
115
|
-
return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
|
|
116
|
-
});
|
|
117
|
-
/** The key for collapsing an item or moving to its parent. */
|
|
118
|
-
collapseKey = computed(() => {
|
|
119
|
-
if (this.inputs.orientation() === 'horizontal') {
|
|
120
|
-
return 'ArrowUp';
|
|
121
|
-
}
|
|
122
|
-
return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
|
|
123
|
-
});
|
|
124
|
-
/** The key for expanding an item or moving to its first child. */
|
|
125
|
-
expandKey = computed(() => {
|
|
126
|
-
if (this.inputs.orientation() === 'horizontal') {
|
|
127
|
-
return 'ArrowDown';
|
|
128
|
-
}
|
|
129
|
-
return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
|
|
130
|
-
});
|
|
131
|
-
/** Represents the space key. Does nothing when the user is actively using typeahead. */
|
|
132
|
-
dynamicSpaceKey = computed(() => (this.listBehavior.isTyping() ? '' : ' '));
|
|
133
|
-
/** Regular expression to match characters for typeahead. */
|
|
134
|
-
typeaheadRegexp = /^.$/;
|
|
135
|
-
/** The keydown event manager for the tree. */
|
|
136
|
-
keydown = computed(() => {
|
|
137
|
-
const manager = new KeyboardEventManager();
|
|
138
|
-
const list = this.listBehavior;
|
|
139
|
-
manager
|
|
140
|
-
.on(this.prevKey, () => list.prev({ selectOne: this.followFocus() }))
|
|
141
|
-
.on(this.nextKey, () => list.next({ selectOne: this.followFocus() }))
|
|
142
|
-
.on('Home', () => list.first({ selectOne: this.followFocus() }))
|
|
143
|
-
.on('End', () => list.last({ selectOne: this.followFocus() }))
|
|
144
|
-
.on(this.typeaheadRegexp, e => list.search(e.key, { selectOne: this.followFocus() }))
|
|
145
|
-
.on(this.expandKey, () => this.expand({ selectOne: this.followFocus() }))
|
|
146
|
-
.on(this.collapseKey, () => this.collapse({ selectOne: this.followFocus() }))
|
|
147
|
-
.on(Modifier.Shift, '*', () => this.expandSiblings());
|
|
148
|
-
if (this.inputs.multi()) {
|
|
149
|
-
manager
|
|
150
|
-
// TODO: Tracking the anchor by index can break if the
|
|
151
|
-
// tree is expanded or collapsed causing the index to change.
|
|
152
|
-
.on(Modifier.Any, 'Shift', () => list.anchor(this.listBehavior.activeIndex()))
|
|
153
|
-
.on(Modifier.Shift, this.prevKey, () => list.prev({ selectRange: true }))
|
|
154
|
-
.on(Modifier.Shift, this.nextKey, () => list.next({ selectRange: true }))
|
|
155
|
-
.on([Modifier.Ctrl | Modifier.Shift, Modifier.Meta | Modifier.Shift], 'Home', () => list.first({ selectRange: true, anchor: false }))
|
|
156
|
-
.on([Modifier.Ctrl | Modifier.Shift, Modifier.Meta | Modifier.Shift], 'End', () => list.last({ selectRange: true, anchor: false }))
|
|
157
|
-
.on(Modifier.Shift, 'Enter', () => list.updateSelection({ selectRange: true, anchor: false }))
|
|
158
|
-
.on(Modifier.Shift, this.dynamicSpaceKey, () => list.updateSelection({ selectRange: true, anchor: false }));
|
|
159
|
-
}
|
|
160
|
-
if (!this.followFocus() && this.inputs.multi()) {
|
|
161
|
-
manager
|
|
162
|
-
.on(this.dynamicSpaceKey, () => list.toggle())
|
|
163
|
-
.on('Enter', () => list.toggle())
|
|
164
|
-
.on([Modifier.Ctrl, Modifier.Meta], 'A', () => list.toggleAll());
|
|
165
|
-
}
|
|
166
|
-
if (!this.followFocus() && !this.inputs.multi()) {
|
|
167
|
-
manager.on(this.dynamicSpaceKey, () => list.selectOne());
|
|
168
|
-
manager.on('Enter', () => list.selectOne());
|
|
169
|
-
}
|
|
170
|
-
if (this.inputs.multi() && this.followFocus()) {
|
|
171
|
-
manager
|
|
172
|
-
.on([Modifier.Ctrl, Modifier.Meta], this.prevKey, () => list.prev())
|
|
173
|
-
.on([Modifier.Ctrl, Modifier.Meta], this.nextKey, () => list.next())
|
|
174
|
-
.on([Modifier.Ctrl, Modifier.Meta], this.expandKey, () => this.expand())
|
|
175
|
-
.on([Modifier.Ctrl, Modifier.Meta], this.collapseKey, () => this.collapse())
|
|
176
|
-
.on([Modifier.Ctrl, Modifier.Meta], ' ', () => list.toggle())
|
|
177
|
-
.on([Modifier.Ctrl, Modifier.Meta], 'Enter', () => list.toggle())
|
|
178
|
-
.on([Modifier.Ctrl, Modifier.Meta], 'Home', () => list.first())
|
|
179
|
-
.on([Modifier.Ctrl, Modifier.Meta], 'End', () => list.last())
|
|
180
|
-
.on([Modifier.Ctrl, Modifier.Meta], 'A', () => {
|
|
181
|
-
list.toggleAll();
|
|
182
|
-
list.select(); // Ensure the currect item remains selected.
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
return manager;
|
|
186
|
-
});
|
|
187
|
-
/** The pointerdown event manager for the tree. */
|
|
188
|
-
pointerdown = computed(() => {
|
|
189
|
-
const manager = new PointerEventManager();
|
|
190
|
-
if (this.multi()) {
|
|
191
|
-
manager.on(Modifier.Shift, e => this.goto(e, { selectRange: true }));
|
|
192
|
-
}
|
|
193
|
-
if (!this.multi()) {
|
|
194
|
-
return manager.on(e => this.goto(e, { selectOne: true }));
|
|
195
|
-
}
|
|
196
|
-
if (this.multi() && this.followFocus()) {
|
|
197
|
-
return manager
|
|
198
|
-
.on(e => this.goto(e, { selectOne: true }))
|
|
199
|
-
.on(Modifier.Ctrl, e => this.goto(e, { toggle: true }));
|
|
200
|
-
}
|
|
201
|
-
if (this.multi() && !this.followFocus()) {
|
|
202
|
-
return manager.on(e => this.goto(e, { toggle: true }));
|
|
203
|
-
}
|
|
204
|
-
return manager;
|
|
205
|
-
});
|
|
206
|
-
constructor(inputs) {
|
|
207
|
-
this.inputs = inputs;
|
|
208
|
-
this.nav = inputs.nav;
|
|
209
|
-
this.currentType = inputs.currentType;
|
|
210
|
-
this.allItems = inputs.allItems;
|
|
211
|
-
this.focusMode = inputs.focusMode;
|
|
212
|
-
this.disabled = inputs.disabled;
|
|
213
|
-
this.activeItem = inputs.activeItem;
|
|
214
|
-
this.skipDisabled = inputs.skipDisabled;
|
|
215
|
-
this.wrap = inputs.wrap;
|
|
216
|
-
this.orientation = inputs.orientation;
|
|
217
|
-
this.textDirection = inputs.textDirection;
|
|
218
|
-
this.multi = computed(() => (this.nav() ? false : this.inputs.multi()));
|
|
219
|
-
this.selectionMode = inputs.selectionMode;
|
|
220
|
-
this.typeaheadDelay = inputs.typeaheadDelay;
|
|
221
|
-
this.value = inputs.value;
|
|
222
|
-
this.listBehavior = new List({
|
|
223
|
-
...inputs,
|
|
224
|
-
items: this.visibleItems,
|
|
225
|
-
multi: this.multi,
|
|
226
|
-
});
|
|
227
|
-
this.expansionManager = new ListExpansion({
|
|
228
|
-
multiExpandable: () => true,
|
|
229
|
-
// TODO(ok7sai): allow pre-expanded tree items.
|
|
230
|
-
expandedIds: signal([]),
|
|
231
|
-
items: this.children,
|
|
232
|
-
disabled: this.disabled,
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Sets the tree to it's default initial state.
|
|
237
|
-
*
|
|
238
|
-
* Sets the active index of the tree to the first focusable selected tree item if one exists.
|
|
239
|
-
* Otherwise, sets focus to the first focusable tree item.
|
|
240
|
-
*/
|
|
241
|
-
setDefaultState() {
|
|
242
|
-
let firstItem;
|
|
243
|
-
for (const item of this.allItems()) {
|
|
244
|
-
if (!item.visible())
|
|
245
|
-
continue;
|
|
246
|
-
if (!this.listBehavior.isFocusable(item))
|
|
247
|
-
continue;
|
|
248
|
-
if (firstItem === undefined) {
|
|
249
|
-
firstItem = item;
|
|
250
|
-
}
|
|
251
|
-
if (item.selected()) {
|
|
252
|
-
this.activeItem.set(item);
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
if (firstItem !== undefined) {
|
|
257
|
-
this.activeItem.set(firstItem);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
/** Handles keydown events on the tree. */
|
|
261
|
-
onKeydown(event) {
|
|
262
|
-
if (!this.disabled()) {
|
|
263
|
-
this.keydown().handle(event);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
/** Handles pointerdown events on the tree. */
|
|
267
|
-
onPointerdown(event) {
|
|
268
|
-
if (!this.disabled()) {
|
|
269
|
-
this.pointerdown().handle(event);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
/** Navigates to the given tree item in the tree. */
|
|
273
|
-
goto(e, opts) {
|
|
274
|
-
const item = this._getItem(e);
|
|
275
|
-
if (!item)
|
|
276
|
-
return;
|
|
277
|
-
this.listBehavior.goto(item, opts);
|
|
278
|
-
this.toggleExpansion(item);
|
|
279
|
-
}
|
|
280
|
-
/** Toggles to expand or collapse a tree item. */
|
|
281
|
-
toggleExpansion(item) {
|
|
282
|
-
item ??= this.activeItem();
|
|
283
|
-
if (!item || !this.listBehavior.isFocusable(item))
|
|
284
|
-
return;
|
|
285
|
-
if (!item.expandable())
|
|
286
|
-
return;
|
|
287
|
-
if (item.expanded()) {
|
|
288
|
-
this.collapse();
|
|
289
|
-
}
|
|
290
|
-
else {
|
|
291
|
-
item.expansion.open();
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
/** Expands a tree item. */
|
|
295
|
-
expand(opts) {
|
|
296
|
-
const item = this.activeItem();
|
|
297
|
-
if (!item || !this.listBehavior.isFocusable(item))
|
|
298
|
-
return;
|
|
299
|
-
if (item.expandable() && !item.expanded()) {
|
|
300
|
-
item.expansion.open();
|
|
301
|
-
}
|
|
302
|
-
else if (item.expanded() &&
|
|
303
|
-
item.children().some(item => this.listBehavior.isFocusable(item))) {
|
|
304
|
-
this.listBehavior.next(opts);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
/** Expands all sibling tree items including itself. */
|
|
308
|
-
expandSiblings(item) {
|
|
309
|
-
item ??= this.activeItem();
|
|
310
|
-
const siblings = item?.parent()?.children();
|
|
311
|
-
siblings?.forEach(item => item.expansion.open());
|
|
312
|
-
}
|
|
313
|
-
/** Collapses a tree item. */
|
|
314
|
-
collapse(opts) {
|
|
315
|
-
const item = this.activeItem();
|
|
316
|
-
if (!item || !this.listBehavior.isFocusable(item))
|
|
317
|
-
return;
|
|
318
|
-
if (item.expandable() && item.expanded()) {
|
|
319
|
-
item.expansion.close();
|
|
320
|
-
}
|
|
321
|
-
else if (item.parent() && item.parent() !== this) {
|
|
322
|
-
const parentItem = item.parent();
|
|
323
|
-
if (parentItem instanceof TreeItemPattern && this.listBehavior.isFocusable(parentItem)) {
|
|
324
|
-
this.listBehavior.goto(parentItem, opts);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
/** Retrieves the TreeItemPattern associated with a DOM event, if any. */
|
|
329
|
-
_getItem(event) {
|
|
330
|
-
if (!(event.target instanceof HTMLElement)) {
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
const element = event.target.closest('[role="treeitem"]');
|
|
334
|
-
return this.inputs.allItems().find(i => i.element() === element);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
7
|
+
import * as i1 from '@angular/cdk-experimental/combobox';
|
|
8
|
+
import { CdkComboboxPopup } from '@angular/cdk-experimental/combobox';
|
|
9
|
+
import { ComboboxTreePattern, TreePattern, TreeItemPattern } from './_combobox-tree-chunk.mjs';
|
|
10
|
+
import './_list-chunk.mjs';
|
|
11
|
+
import './_list-navigation-chunk.mjs';
|
|
12
|
+
import './_expansion-chunk.mjs';
|
|
13
|
+
import './_pointer-event-manager-chunk.mjs';
|
|
337
14
|
|
|
338
15
|
/**
|
|
339
16
|
* Sort directives by their document order.
|
|
@@ -365,6 +42,15 @@ function sortDirectives(a, b) {
|
|
|
365
42
|
* ```
|
|
366
43
|
*/
|
|
367
44
|
class CdkTree {
|
|
45
|
+
/** A unique identifier for the tree. */
|
|
46
|
+
_generatedId = inject(_IdGenerator).getId('cdk-tree-');
|
|
47
|
+
// TODO(wagnermaciel): https://github.com/angular/components/pull/30495#discussion_r1972601144.
|
|
48
|
+
/** A unique identifier for the tree. */
|
|
49
|
+
id = computed(() => this._generatedId, ...(ngDevMode ? [{ debugName: "id" }] : []));
|
|
50
|
+
/** A reference to the parent combobox popup, if one exists. */
|
|
51
|
+
_popup = inject(CdkComboboxPopup, {
|
|
52
|
+
optional: true,
|
|
53
|
+
});
|
|
368
54
|
/** A reference to the tree element. */
|
|
369
55
|
_elementRef = inject(ElementRef);
|
|
370
56
|
/** All CdkTreeItem instances within this tree. */
|
|
@@ -394,20 +80,43 @@ class CdkTree {
|
|
|
394
80
|
/** The aria-current type. */
|
|
395
81
|
currentType = input('page', ...(ngDevMode ? [{ debugName: "currentType" }] : []));
|
|
396
82
|
/** The UI pattern for the tree. */
|
|
397
|
-
pattern
|
|
398
|
-
...this,
|
|
399
|
-
allItems: computed(() => [...this._unorderedItems()].sort(sortDirectives).map(item => item.pattern)),
|
|
400
|
-
activeItem: signal(undefined),
|
|
401
|
-
element: () => this._elementRef.nativeElement,
|
|
402
|
-
});
|
|
83
|
+
pattern;
|
|
403
84
|
/** Whether the tree has received focus yet. */
|
|
404
85
|
_hasFocused = signal(false, ...(ngDevMode ? [{ debugName: "_hasFocused" }] : []));
|
|
405
86
|
constructor() {
|
|
87
|
+
const inputs = {
|
|
88
|
+
...this,
|
|
89
|
+
id: this.id,
|
|
90
|
+
allItems: computed(() => [...this._unorderedItems()].sort(sortDirectives).map(item => item.pattern)),
|
|
91
|
+
activeItem: signal(undefined),
|
|
92
|
+
element: () => this._elementRef.nativeElement,
|
|
93
|
+
combobox: () => this._popup?.combobox?.pattern,
|
|
94
|
+
};
|
|
95
|
+
this.pattern = this._popup?.combobox
|
|
96
|
+
? new ComboboxTreePattern(inputs)
|
|
97
|
+
: new TreePattern(inputs);
|
|
98
|
+
if (this._popup?.combobox) {
|
|
99
|
+
this._popup?.controls?.set(this.pattern);
|
|
100
|
+
}
|
|
406
101
|
afterRenderEffect(() => {
|
|
407
102
|
if (!this._hasFocused()) {
|
|
408
103
|
this.pattern.setDefaultState();
|
|
409
104
|
}
|
|
410
105
|
});
|
|
106
|
+
afterRenderEffect(() => {
|
|
107
|
+
const items = inputs.allItems();
|
|
108
|
+
const activeItem = untracked(() => inputs.activeItem());
|
|
109
|
+
if (!items.some(i => i === activeItem) && activeItem) {
|
|
110
|
+
this.pattern.listBehavior.unfocus();
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
afterRenderEffect(() => {
|
|
114
|
+
const items = inputs.allItems();
|
|
115
|
+
const value = untracked(() => this.value());
|
|
116
|
+
if (items && value.some(v => !items.some(i => i.value() === v))) {
|
|
117
|
+
this.value.set(value.filter(v => items.some(i => i.value() === v)));
|
|
118
|
+
}
|
|
119
|
+
});
|
|
411
120
|
}
|
|
412
121
|
onFocus() {
|
|
413
122
|
this._hasFocused.set(true);
|
|
@@ -421,7 +130,7 @@ class CdkTree {
|
|
|
421
130
|
this._unorderedItems.set(new Set(this._unorderedItems()));
|
|
422
131
|
}
|
|
423
132
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkTree, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
424
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.2.0-next.2", type: CdkTree, isStandalone: true, selector: "[cdkTree]", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, multi: { classPropertyName: "multi", publicName: "multi", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, focusMode: { classPropertyName: "focusMode", publicName: "focusMode", isSignal: true, isRequired: false, transformFunction: null }, wrap: { classPropertyName: "wrap", publicName: "wrap", isSignal: true, isRequired: false, transformFunction: null }, skipDisabled: { classPropertyName: "skipDisabled", publicName: "skipDisabled", isSignal: true, isRequired: false, transformFunction: null }, typeaheadDelay: { classPropertyName: "typeaheadDelay", publicName: "typeaheadDelay", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, nav: { classPropertyName: "nav", publicName: "nav", isSignal: true, isRequired: false, transformFunction: null }, currentType: { classPropertyName: "currentType", publicName: "currentType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { attributes: { "role": "tree" }, listeners: { "keydown": "pattern.onKeydown($event)", "pointerdown": "pattern.onPointerdown($event)", "focusin": "onFocus()" }, properties: { "attr.aria-orientation": "pattern.orientation()", "attr.aria-multiselectable": "pattern.multi()", "attr.aria-disabled": "pattern.disabled()", "attr.aria-activedescendant": "pattern.activedescendant()", "tabindex": "pattern.tabindex()" }, classAttribute: "cdk-tree" }, exportAs: ["cdkTree"], ngImport: i0 });
|
|
133
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.2.0-next.2", type: CdkTree, isStandalone: true, selector: "[cdkTree]", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, multi: { classPropertyName: "multi", publicName: "multi", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, focusMode: { classPropertyName: "focusMode", publicName: "focusMode", isSignal: true, isRequired: false, transformFunction: null }, wrap: { classPropertyName: "wrap", publicName: "wrap", isSignal: true, isRequired: false, transformFunction: null }, skipDisabled: { classPropertyName: "skipDisabled", publicName: "skipDisabled", isSignal: true, isRequired: false, transformFunction: null }, typeaheadDelay: { classPropertyName: "typeaheadDelay", publicName: "typeaheadDelay", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, nav: { classPropertyName: "nav", publicName: "nav", isSignal: true, isRequired: false, transformFunction: null }, currentType: { classPropertyName: "currentType", publicName: "currentType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { attributes: { "role": "tree" }, listeners: { "keydown": "pattern.onKeydown($event)", "pointerdown": "pattern.onPointerdown($event)", "focusin": "onFocus()" }, properties: { "attr.id": "id()", "attr.aria-orientation": "pattern.orientation()", "attr.aria-multiselectable": "pattern.multi()", "attr.aria-disabled": "pattern.disabled()", "attr.aria-activedescendant": "pattern.activedescendant()", "tabindex": "pattern.tabindex()" }, classAttribute: "cdk-tree" }, exportAs: ["cdkTree"], hostDirectives: [{ directive: i1.CdkComboboxPopup }], ngImport: i0 });
|
|
425
134
|
}
|
|
426
135
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkTree, decorators: [{
|
|
427
136
|
type: Directive,
|
|
@@ -431,6 +140,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0-next.2",
|
|
|
431
140
|
host: {
|
|
432
141
|
'class': 'cdk-tree',
|
|
433
142
|
'role': 'tree',
|
|
143
|
+
'[attr.id]': 'id()',
|
|
434
144
|
'[attr.aria-orientation]': 'pattern.orientation()',
|
|
435
145
|
'[attr.aria-multiselectable]': 'pattern.multi()',
|
|
436
146
|
'[attr.aria-disabled]': 'pattern.disabled()',
|
|
@@ -440,6 +150,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0-next.2",
|
|
|
440
150
|
'(pointerdown)': 'pattern.onPointerdown($event)',
|
|
441
151
|
'(focusin)': 'onFocus()',
|
|
442
152
|
},
|
|
153
|
+
hostDirectives: [{ directive: CdkComboboxPopup }],
|
|
443
154
|
}]
|
|
444
155
|
}], ctorParameters: () => [] });
|
|
445
156
|
/**
|
|
@@ -513,7 +224,7 @@ class CdkTreeItem {
|
|
|
513
224
|
this._group.set(undefined);
|
|
514
225
|
}
|
|
515
226
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkTreeItem, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
516
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.2.0-next.2", type: CdkTreeItem, isStandalone: true, selector: "[cdkTreeItem]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, parent: { classPropertyName: "parent", publicName: "parent", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "treeitem" }, properties: { "class.cdk-active": "pattern.active()", "id": "pattern.id()", "attr.aria-expanded": "pattern.expandable() ? pattern.expanded() : null", "attr.aria-selected": "pattern.selected()", "attr.aria-current": "pattern.current()", "attr.aria-disabled": "pattern.disabled()", "attr.aria-level": "pattern.level()", "attr.aria-owns": "ownsId()", "attr.aria-setsize": "pattern.setsize()", "attr.aria-posinset": "pattern.posinset()", "attr.tabindex": "pattern.tabindex()"
|
|
227
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.2.0-next.2", type: CdkTreeItem, isStandalone: true, selector: "[cdkTreeItem]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, parent: { classPropertyName: "parent", publicName: "parent", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "treeitem" }, properties: { "class.cdk-active": "pattern.active()", "id": "pattern.id()", "attr.aria-expanded": "pattern.expandable() ? pattern.expanded() : null", "attr.aria-selected": "pattern.selected()", "attr.aria-current": "pattern.current()", "attr.aria-disabled": "pattern.disabled()", "attr.aria-level": "pattern.level()", "attr.aria-owns": "ownsId()", "attr.aria-setsize": "pattern.setsize()", "attr.aria-posinset": "pattern.posinset()", "attr.tabindex": "pattern.tabindex()" }, classAttribute: "cdk-treeitem" }, exportAs: ["cdkTreeItem"], ngImport: i0 });
|
|
517
228
|
}
|
|
518
229
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkTreeItem, decorators: [{
|
|
519
230
|
type: Directive,
|
|
@@ -534,7 +245,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0-next.2",
|
|
|
534
245
|
'[attr.aria-setsize]': 'pattern.setsize()',
|
|
535
246
|
'[attr.aria-posinset]': 'pattern.posinset()',
|
|
536
247
|
'[attr.tabindex]': 'pattern.tabindex()',
|
|
537
|
-
'[attr.inert]': 'pattern.visible() ? null : true',
|
|
538
248
|
},
|
|
539
249
|
}]
|
|
540
250
|
}], ctorParameters: () => [] });
|
|
@@ -559,9 +269,12 @@ class CdkTreeItemGroup {
|
|
|
559
269
|
/** Tree item that owns the group. */
|
|
560
270
|
ownedBy = input.required(...(ngDevMode ? [{ debugName: "ownedBy" }] : []));
|
|
561
271
|
constructor() {
|
|
272
|
+
this._deferredContentAware.preserveContent.set(true);
|
|
562
273
|
// Connect the group's hidden state to the DeferredContentAware's visibility.
|
|
563
274
|
afterRenderEffect(() => {
|
|
564
|
-
this.
|
|
275
|
+
this.ownedBy().tree().pattern instanceof ComboboxTreePattern
|
|
276
|
+
? this._deferredContentAware.contentVisible.set(true)
|
|
277
|
+
: this._deferredContentAware.contentVisible.set(this.visible());
|
|
565
278
|
});
|
|
566
279
|
}
|
|
567
280
|
ngOnInit() {
|
|
@@ -579,7 +292,7 @@ class CdkTreeItemGroup {
|
|
|
579
292
|
this._unorderedItems.set(new Set(this._unorderedItems()));
|
|
580
293
|
}
|
|
581
294
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkTreeItemGroup, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
582
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.2.0-next.2", type: CdkTreeItemGroup, isStandalone: true, selector: "[cdkTreeItemGroup]", inputs: { ownedBy: { classPropertyName: "ownedBy", publicName: "ownedBy", isSignal: true, isRequired: true, transformFunction: null } }, host: { attributes: { "role": "group" }, properties: { "id": "id", "attr.inert": "visible() ? null : true" }, classAttribute: "cdk-treeitem-group" }, exportAs: ["cdkTreeItemGroup"], hostDirectives: [{ directive: i1.DeferredContentAware, inputs: ["preserveContent", "preserveContent"] }], ngImport: i0 });
|
|
295
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.2.0-next.2", type: CdkTreeItemGroup, isStandalone: true, selector: "[cdkTreeItemGroup]", inputs: { ownedBy: { classPropertyName: "ownedBy", publicName: "ownedBy", isSignal: true, isRequired: true, transformFunction: null } }, host: { attributes: { "role": "group" }, properties: { "id": "id", "attr.inert": "visible() ? null : true" }, classAttribute: "cdk-treeitem-group" }, exportAs: ["cdkTreeItemGroup"], hostDirectives: [{ directive: i1$1.DeferredContentAware, inputs: ["preserveContent", "preserveContent"] }], ngImport: i0 });
|
|
583
296
|
}
|
|
584
297
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkTreeItemGroup, decorators: [{
|
|
585
298
|
type: Directive,
|
|
@@ -606,7 +319,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0-next.2",
|
|
|
606
319
|
*/
|
|
607
320
|
class CdkTreeItemGroupContent {
|
|
608
321
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkTreeItemGroupContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
609
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.0-next.2", type: CdkTreeItemGroupContent, isStandalone: true, selector: "ng-template[cdkTreeItemGroupContent]", hostDirectives: [{ directive: i1.DeferredContent }], ngImport: i0 });
|
|
322
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.2.0-next.2", type: CdkTreeItemGroupContent, isStandalone: true, selector: "ng-template[cdkTreeItemGroupContent]", hostDirectives: [{ directive: i1$1.DeferredContent }], ngImport: i0 });
|
|
610
323
|
}
|
|
611
324
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.2.0-next.2", ngImport: i0, type: CdkTreeItemGroupContent, decorators: [{
|
|
612
325
|
type: Directive,
|