@angular/aria 21.0.0-rc.0 → 21.0.0-rc.2
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/_adev_assets/aria-accordion.json +443 -59
- package/_adev_assets/aria-combobox.json +345 -37
- package/_adev_assets/aria-grid.json +408 -71
- package/_adev_assets/aria-listbox.json +115 -35
- package/_adev_assets/aria-menu.json +492 -167
- package/_adev_assets/aria-tabs.json +272 -88
- package/_adev_assets/aria-toolbar.json +151 -133
- package/_adev_assets/aria-tree.json +182 -35
- package/fesm2022/_widget-chunk.mjs +643 -190
- package/fesm2022/_widget-chunk.mjs.map +1 -1
- package/fesm2022/accordion.mjs +129 -77
- package/fesm2022/accordion.mjs.map +1 -1
- package/fesm2022/aria.mjs +1 -1
- package/fesm2022/aria.mjs.map +1 -1
- package/fesm2022/combobox.mjs +140 -27
- package/fesm2022/combobox.mjs.map +1 -1
- package/fesm2022/grid.mjs +254 -68
- package/fesm2022/grid.mjs.map +1 -1
- package/fesm2022/listbox.mjs +54 -44
- package/fesm2022/listbox.mjs.map +1 -1
- package/fesm2022/menu.mjs +270 -108
- package/fesm2022/menu.mjs.map +1 -1
- package/fesm2022/private.mjs +752 -785
- package/fesm2022/private.mjs.map +1 -1
- package/fesm2022/tabs.mjs +101 -71
- package/fesm2022/tabs.mjs.map +1 -1
- package/fesm2022/toolbar.mjs +87 -64
- package/fesm2022/toolbar.mjs.map +1 -1
- package/fesm2022/tree.mjs +105 -60
- package/fesm2022/tree.mjs.map +1 -1
- package/package.json +2 -10
- package/types/_grid-chunk.d.ts +326 -83
- package/types/accordion.d.ts +134 -35
- package/types/combobox.d.ts +146 -13
- package/types/grid.d.ts +159 -32
- package/types/listbox.d.ts +59 -28
- package/types/menu.d.ts +151 -55
- package/types/private.d.ts +449 -567
- package/types/tabs.d.ts +121 -41
- package/types/toolbar.d.ts +74 -51
- package/types/tree.d.ts +116 -45
- package/_adev_assets/aria-radio-group.json +0 -389
- package/fesm2022/deferred-content.mjs +0 -99
- package/fesm2022/deferred-content.mjs.map +0 -1
- package/fesm2022/radio-group.mjs +0 -338
- package/fesm2022/radio-group.mjs.map +0 -1
- package/types/deferred-content.d.ts +0 -38
- package/types/radio-group.d.ts +0 -84
package/fesm2022/private.mjs
CHANGED
|
@@ -1,117 +1,199 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { signal, computed, model, Directive, inject, TemplateRef, ViewContainerRef, afterRenderEffect } from '@angular/core';
|
|
3
|
+
import { PointerEventManager, KeyboardEventManager, ListFocus, ListNavigation, Modifier } from './_widget-chunk.mjs';
|
|
3
4
|
export { GridCellPattern, GridCellWidgetPattern, GridPattern, GridRowPattern } from './_widget-chunk.mjs';
|
|
4
5
|
|
|
5
6
|
class ComboboxPattern {
|
|
6
7
|
inputs;
|
|
7
8
|
expanded = signal(false);
|
|
8
|
-
|
|
9
|
+
disabled = () => this.inputs.disabled();
|
|
10
|
+
activeDescendant = computed(() => {
|
|
11
|
+
const popupControls = this.inputs.popupControls();
|
|
12
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return popupControls?.activeId() ?? null;
|
|
16
|
+
});
|
|
9
17
|
highlightedItem = signal(undefined);
|
|
10
18
|
isDeleting = false;
|
|
11
19
|
isFocused = signal(false);
|
|
20
|
+
hasBeenFocused = signal(false);
|
|
12
21
|
expandKey = computed(() => this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight');
|
|
13
22
|
collapseKey = computed(() => this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft');
|
|
14
23
|
popupId = computed(() => this.inputs.popupControls()?.id() || null);
|
|
15
24
|
autocomplete = computed(() => this.inputs.filterMode() === 'highlight' ? 'both' : 'list');
|
|
16
25
|
hasPopup = computed(() => this.inputs.popupControls()?.role() || null);
|
|
17
|
-
|
|
26
|
+
readonly = computed(() => this.inputs.readonly() || this.inputs.disabled() || null);
|
|
27
|
+
listControls = () => {
|
|
28
|
+
const popupControls = this.inputs.popupControls();
|
|
29
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return popupControls;
|
|
33
|
+
};
|
|
34
|
+
treeControls = () => {
|
|
35
|
+
const popupControls = this.inputs.popupControls();
|
|
36
|
+
if (popupControls?.role() === 'tree') {
|
|
37
|
+
return popupControls;
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
};
|
|
18
41
|
keydown = computed(() => {
|
|
42
|
+
const manager = new KeyboardEventManager();
|
|
43
|
+
const popupControls = this.inputs.popupControls();
|
|
44
|
+
if (!popupControls) {
|
|
45
|
+
return manager;
|
|
46
|
+
}
|
|
47
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
48
|
+
if (!this.expanded()) {
|
|
49
|
+
manager.on('ArrowUp', () => this.open()).on('ArrowDown', () => this.open());
|
|
50
|
+
if (this.readonly()) {
|
|
51
|
+
manager.on('Enter', () => this.open()).on(' ', () => this.open());
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return manager;
|
|
55
|
+
}
|
|
56
|
+
if (!this.inputs.alwaysExpanded()) {
|
|
57
|
+
manager.on('Escape', () => this.close({
|
|
58
|
+
reset: !this.readonly()
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
19
61
|
if (!this.expanded()) {
|
|
20
|
-
|
|
62
|
+
manager.on('ArrowDown', () => this.open({
|
|
21
63
|
first: true
|
|
22
64
|
})).on('ArrowUp', () => this.open({
|
|
23
65
|
last: true
|
|
24
66
|
}));
|
|
67
|
+
if (this.readonly()) {
|
|
68
|
+
manager.on('Enter', () => this.open({
|
|
69
|
+
selected: true
|
|
70
|
+
})).on(' ', () => this.open({
|
|
71
|
+
selected: true
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
return manager;
|
|
25
75
|
}
|
|
26
|
-
|
|
27
|
-
if (
|
|
28
|
-
|
|
76
|
+
manager.on('ArrowDown', () => this.next()).on('ArrowUp', () => this.prev()).on('Home', () => this.first()).on('End', () => this.last());
|
|
77
|
+
if (this.readonly()) {
|
|
78
|
+
manager.on(' ', () => this.select({
|
|
79
|
+
commit: true,
|
|
80
|
+
close: !popupControls.multi()
|
|
81
|
+
}));
|
|
29
82
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
manager.on(this.collapseKey(), () => this.collapseItem());
|
|
50
|
-
}
|
|
51
|
-
if (treeControls.isItemExpandable()) {
|
|
52
|
-
manager.on(this.expandKey(), () => this.expandItem());
|
|
83
|
+
if (popupControls.role() === 'listbox') {
|
|
84
|
+
manager.on('Enter', () => {
|
|
85
|
+
this.select({
|
|
86
|
+
commit: true,
|
|
87
|
+
close: !popupControls.multi()
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
const treeControls = this.treeControls();
|
|
92
|
+
if (treeControls?.isItemSelectable()) {
|
|
93
|
+
manager.on('Enter', () => this.select({
|
|
94
|
+
commit: true,
|
|
95
|
+
close: true
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
if (treeControls?.isItemExpandable()) {
|
|
99
|
+
manager.on(this.expandKey(), () => this.expandItem()).on(this.collapseKey(), () => this.collapseItem());
|
|
100
|
+
if (!treeControls.isItemSelectable()) {
|
|
101
|
+
manager.on('Enter', () => this.expandItem());
|
|
53
102
|
}
|
|
54
103
|
}
|
|
104
|
+
if (treeControls?.isItemCollapsible()) {
|
|
105
|
+
manager.on(this.collapseKey(), () => this.collapseItem());
|
|
106
|
+
}
|
|
55
107
|
return manager;
|
|
56
108
|
});
|
|
57
|
-
|
|
58
|
-
|
|
109
|
+
click = computed(() => new PointerEventManager().on(e => {
|
|
110
|
+
if (e.target === this.inputs.inputEl()) {
|
|
111
|
+
if (this.readonly()) {
|
|
112
|
+
this.expanded() ? this.close() : this.open({
|
|
113
|
+
selected: true
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
const controls = this.inputs.popupControls();
|
|
118
|
+
if (controls instanceof ComboboxDialogPattern) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const item = controls?.getItem(e);
|
|
59
122
|
if (item) {
|
|
123
|
+
if (controls?.role() === 'tree') {
|
|
124
|
+
const treeControls = controls;
|
|
125
|
+
if (treeControls.isItemExpandable(item) && !treeControls.isItemSelectable(item)) {
|
|
126
|
+
treeControls.toggleExpansion(item);
|
|
127
|
+
this.inputs.inputEl()?.focus();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
60
131
|
this.select({
|
|
61
132
|
item,
|
|
62
133
|
commit: true,
|
|
63
|
-
close:
|
|
134
|
+
close: !controls?.multi()
|
|
64
135
|
});
|
|
65
136
|
this.inputs.inputEl()?.focus();
|
|
66
137
|
}
|
|
67
|
-
if (e.target === this.inputs.inputEl()) {
|
|
68
|
-
this.open();
|
|
69
|
-
}
|
|
70
138
|
}));
|
|
71
139
|
constructor(inputs) {
|
|
72
140
|
this.inputs = inputs;
|
|
73
141
|
}
|
|
74
142
|
onKeydown(event) {
|
|
75
|
-
if (this.
|
|
143
|
+
if (!this.inputs.disabled()) {
|
|
76
144
|
this.keydown().handle(event);
|
|
77
145
|
}
|
|
78
146
|
}
|
|
79
|
-
|
|
80
|
-
if (this.
|
|
81
|
-
this.
|
|
147
|
+
onClick(event) {
|
|
148
|
+
if (!this.inputs.disabled()) {
|
|
149
|
+
this.click().handle(event);
|
|
82
150
|
}
|
|
83
151
|
}
|
|
84
152
|
onInput(event) {
|
|
85
|
-
if (
|
|
153
|
+
if (this.inputs.disabled() || this.inputs.readonly()) {
|
|
86
154
|
return;
|
|
87
155
|
}
|
|
88
156
|
const inputEl = this.inputs.inputEl();
|
|
89
157
|
if (!inputEl) {
|
|
90
158
|
return;
|
|
91
159
|
}
|
|
160
|
+
const popupControls = this.inputs.popupControls();
|
|
161
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
92
164
|
this.open();
|
|
93
165
|
this.inputs.inputValue?.set(inputEl.value);
|
|
94
166
|
this.isDeleting = event instanceof InputEvent && !!event.inputType.match(/^delete/);
|
|
95
|
-
if (this.inputs.filterMode() === '
|
|
96
|
-
|
|
97
|
-
if (searchTerm && this.inputs.inputValue() !== searchTerm) {
|
|
98
|
-
this.inputs.popupControls()?.clearSelection();
|
|
99
|
-
}
|
|
167
|
+
if (this.inputs.filterMode() === 'highlight' && !this.isDeleting) {
|
|
168
|
+
this.highlight();
|
|
100
169
|
}
|
|
101
170
|
}
|
|
102
171
|
onFocusIn() {
|
|
172
|
+
if (this.inputs.alwaysExpanded() && !this.hasBeenFocused()) {
|
|
173
|
+
const firstSelectedItem = this.listControls()?.getSelectedItems()[0];
|
|
174
|
+
firstSelectedItem ? this.listControls()?.focus(firstSelectedItem) : this.first();
|
|
175
|
+
}
|
|
103
176
|
this.isFocused.set(true);
|
|
177
|
+
this.hasBeenFocused.set(true);
|
|
104
178
|
}
|
|
105
179
|
onFocusOut(event) {
|
|
106
|
-
if (this.inputs.disabled()
|
|
180
|
+
if (this.inputs.disabled()) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const popupControls = this.inputs.popupControls();
|
|
184
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
107
185
|
return;
|
|
108
186
|
}
|
|
109
187
|
if (!(event.relatedTarget instanceof HTMLElement) || !this.inputs.containerEl()?.contains(event.relatedTarget)) {
|
|
110
188
|
this.isFocused.set(false);
|
|
189
|
+
if (this.readonly()) {
|
|
190
|
+
this.close();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
111
193
|
if (this.inputs.filterMode() !== 'manual') {
|
|
112
194
|
this.commit();
|
|
113
195
|
} else {
|
|
114
|
-
const item =
|
|
196
|
+
const item = popupControls?.items().find(i => i.searchTerm() === this.inputs.inputEl()?.value);
|
|
115
197
|
if (item) {
|
|
116
198
|
this.select({
|
|
117
199
|
item
|
|
@@ -122,12 +204,19 @@ class ComboboxPattern {
|
|
|
122
204
|
}
|
|
123
205
|
}
|
|
124
206
|
firstMatch = computed(() => {
|
|
125
|
-
if (this.
|
|
126
|
-
return this.
|
|
207
|
+
if (this.listControls()?.role() === 'listbox') {
|
|
208
|
+
return this.listControls()?.items()[0];
|
|
127
209
|
}
|
|
128
|
-
return this.
|
|
210
|
+
return this.listControls()?.items().find(i => i.value() === this.inputs.firstMatch());
|
|
129
211
|
});
|
|
130
212
|
onFilter() {
|
|
213
|
+
if (this.readonly()) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const popupControls = this.inputs.popupControls();
|
|
217
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
131
220
|
const isInitialRender = !this.inputs.inputValue?.().length && !this.isDeleting;
|
|
132
221
|
if (isInitialRender) {
|
|
133
222
|
return;
|
|
@@ -141,11 +230,11 @@ class ComboboxPattern {
|
|
|
141
230
|
}
|
|
142
231
|
const item = this.firstMatch();
|
|
143
232
|
if (!item) {
|
|
144
|
-
|
|
145
|
-
|
|
233
|
+
popupControls?.clearSelection();
|
|
234
|
+
popupControls?.unfocus();
|
|
146
235
|
return;
|
|
147
236
|
}
|
|
148
|
-
|
|
237
|
+
popupControls?.focus(item);
|
|
149
238
|
if (this.inputs.filterMode() !== 'manual') {
|
|
150
239
|
this.select({
|
|
151
240
|
item
|
|
@@ -157,7 +246,8 @@ class ComboboxPattern {
|
|
|
157
246
|
}
|
|
158
247
|
highlight() {
|
|
159
248
|
const inputEl = this.inputs.inputEl();
|
|
160
|
-
const
|
|
249
|
+
const selectedItems = this.listControls()?.getSelectedItems();
|
|
250
|
+
const item = selectedItems?.[0];
|
|
161
251
|
if (!inputEl || !item) {
|
|
162
252
|
return;
|
|
163
253
|
}
|
|
@@ -168,30 +258,85 @@ class ComboboxPattern {
|
|
|
168
258
|
this.highlightedItem.set(item);
|
|
169
259
|
}
|
|
170
260
|
}
|
|
171
|
-
close() {
|
|
172
|
-
this.
|
|
173
|
-
this.inputs.
|
|
261
|
+
close(opts) {
|
|
262
|
+
const popupControls = this.inputs.popupControls();
|
|
263
|
+
if (this.inputs.alwaysExpanded()) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
267
|
+
this.expanded.set(false);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
if (this.readonly()) {
|
|
271
|
+
this.expanded.set(false);
|
|
272
|
+
popupControls?.unfocus();
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (!opts?.reset) {
|
|
276
|
+
if (this.inputs.filterMode() === 'manual') {
|
|
277
|
+
if (!this.listControls()?.items().some(i => i.searchTerm() === this.inputs.inputEl()?.value)) {
|
|
278
|
+
this.listControls()?.clearSelection();
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
this.expanded.set(false);
|
|
282
|
+
popupControls?.unfocus();
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
if (!this.expanded()) {
|
|
286
|
+
this.inputs.inputValue?.set('');
|
|
287
|
+
popupControls?.clearSelection();
|
|
288
|
+
const inputEl = this.inputs.inputEl();
|
|
289
|
+
if (inputEl) {
|
|
290
|
+
inputEl.value = '';
|
|
291
|
+
}
|
|
292
|
+
} else if (this.expanded()) {
|
|
293
|
+
this.close();
|
|
294
|
+
const selectedItem = popupControls?.getSelectedItems()?.[0];
|
|
295
|
+
if (selectedItem?.searchTerm() !== this.inputs.inputValue()) {
|
|
296
|
+
popupControls?.clearSelection();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
this.close();
|
|
300
|
+
if (!this.readonly()) {
|
|
301
|
+
popupControls?.clearSelection();
|
|
302
|
+
}
|
|
174
303
|
}
|
|
175
304
|
open(nav) {
|
|
176
305
|
this.expanded.set(true);
|
|
306
|
+
const popupControls = this.inputs.popupControls();
|
|
307
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const inputEl = this.inputs.inputEl();
|
|
311
|
+
if (inputEl && this.inputs.filterMode() === 'highlight') {
|
|
312
|
+
const isHighlighting = inputEl.selectionStart !== inputEl.value.length;
|
|
313
|
+
this.inputs.inputValue?.set(inputEl.value.slice(0, inputEl.selectionStart || 0));
|
|
314
|
+
if (!isHighlighting) {
|
|
315
|
+
this.highlightedItem.set(undefined);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
177
318
|
if (nav?.first) {
|
|
178
319
|
this.first();
|
|
179
320
|
}
|
|
180
321
|
if (nav?.last) {
|
|
181
322
|
this.last();
|
|
182
323
|
}
|
|
324
|
+
if (nav?.selected) {
|
|
325
|
+
const selectedItem = popupControls?.items().find(i => popupControls?.getSelectedItems().includes(i));
|
|
326
|
+
selectedItem ? popupControls?.focus(selectedItem) : this.first();
|
|
327
|
+
}
|
|
183
328
|
}
|
|
184
329
|
next() {
|
|
185
|
-
this._navigate(() => this.
|
|
330
|
+
this._navigate(() => this.listControls()?.next());
|
|
186
331
|
}
|
|
187
332
|
prev() {
|
|
188
|
-
this._navigate(() => this.
|
|
333
|
+
this._navigate(() => this.listControls()?.prev());
|
|
189
334
|
}
|
|
190
335
|
first() {
|
|
191
|
-
this._navigate(() => this.
|
|
336
|
+
this._navigate(() => this.listControls()?.first());
|
|
192
337
|
}
|
|
193
338
|
last() {
|
|
194
|
-
this._navigate(() => this.
|
|
339
|
+
this._navigate(() => this.listControls()?.last());
|
|
195
340
|
}
|
|
196
341
|
collapseItem() {
|
|
197
342
|
const controls = this.inputs.popupControls();
|
|
@@ -202,7 +347,13 @@ class ComboboxPattern {
|
|
|
202
347
|
this._navigate(() => controls?.expandItem());
|
|
203
348
|
}
|
|
204
349
|
select(opts = {}) {
|
|
205
|
-
this.
|
|
350
|
+
const controls = this.listControls();
|
|
351
|
+
if (opts.item) {
|
|
352
|
+
controls?.focus(opts.item, {
|
|
353
|
+
focusElement: false
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
controls?.multi() ? controls.toggle(opts.item) : controls?.select(opts.item);
|
|
206
357
|
if (opts.commit) {
|
|
207
358
|
this.commit();
|
|
208
359
|
}
|
|
@@ -212,14 +363,15 @@ class ComboboxPattern {
|
|
|
212
363
|
}
|
|
213
364
|
commit() {
|
|
214
365
|
const inputEl = this.inputs.inputEl();
|
|
215
|
-
const
|
|
216
|
-
if (inputEl
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
366
|
+
const selectedItems = this.listControls()?.getSelectedItems();
|
|
367
|
+
if (!inputEl) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
inputEl.value = selectedItems?.map(i => i.searchTerm()).join(', ') || '';
|
|
371
|
+
this.inputs.inputValue?.set(inputEl.value);
|
|
372
|
+
if (this.inputs.filterMode() === 'highlight' && !this.readonly()) {
|
|
373
|
+
const length = inputEl.value.length;
|
|
374
|
+
inputEl.setSelectionRange(length, length);
|
|
223
375
|
}
|
|
224
376
|
}
|
|
225
377
|
_navigate(operation) {
|
|
@@ -228,7 +380,7 @@ class ComboboxPattern {
|
|
|
228
380
|
this.select();
|
|
229
381
|
}
|
|
230
382
|
if (this.inputs.filterMode() === 'highlight') {
|
|
231
|
-
const selectedItem = this.
|
|
383
|
+
const selectedItem = this.listControls()?.getSelectedItems()[0];
|
|
232
384
|
if (!selectedItem) {
|
|
233
385
|
return;
|
|
234
386
|
}
|
|
@@ -241,110 +393,23 @@ class ComboboxPattern {
|
|
|
241
393
|
}
|
|
242
394
|
}
|
|
243
395
|
}
|
|
244
|
-
|
|
245
|
-
class ListFocus {
|
|
396
|
+
class ComboboxDialogPattern {
|
|
246
397
|
inputs;
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
activeIndex = computed(() => {
|
|
252
|
-
return this.inputs.activeItem() ? this.inputs.items().indexOf(this.inputs.activeItem()) : -1;
|
|
398
|
+
id = () => this.inputs.id();
|
|
399
|
+
role = () => 'dialog';
|
|
400
|
+
keydown = computed(() => {
|
|
401
|
+
return new KeyboardEventManager().on('Escape', () => this.inputs.combobox.close());
|
|
253
402
|
});
|
|
254
403
|
constructor(inputs) {
|
|
255
404
|
this.inputs = inputs;
|
|
256
405
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
getActiveDescendant() {
|
|
261
|
-
if (this.isListDisabled()) {
|
|
262
|
-
return undefined;
|
|
263
|
-
}
|
|
264
|
-
if (this.inputs.focusMode() === 'roving') {
|
|
265
|
-
return undefined;
|
|
266
|
-
}
|
|
267
|
-
return this.inputs.activeItem()?.id() ?? undefined;
|
|
268
|
-
}
|
|
269
|
-
getListTabindex() {
|
|
270
|
-
if (this.isListDisabled()) {
|
|
271
|
-
return 0;
|
|
272
|
-
}
|
|
273
|
-
return this.inputs.focusMode() === 'activedescendant' ? 0 : -1;
|
|
274
|
-
}
|
|
275
|
-
getItemTabindex(item) {
|
|
276
|
-
if (this.isListDisabled()) {
|
|
277
|
-
return -1;
|
|
278
|
-
}
|
|
279
|
-
if (this.inputs.focusMode() === 'activedescendant') {
|
|
280
|
-
return -1;
|
|
281
|
-
}
|
|
282
|
-
return this.inputs.activeItem() === item ? 0 : -1;
|
|
283
|
-
}
|
|
284
|
-
focus(item, opts) {
|
|
285
|
-
if (this.isListDisabled() || !this.isFocusable(item)) {
|
|
286
|
-
return false;
|
|
287
|
-
}
|
|
288
|
-
this.prevActiveItem.set(this.inputs.activeItem());
|
|
289
|
-
this.inputs.activeItem.set(item);
|
|
290
|
-
if (opts?.focusElement || opts?.focusElement === undefined) {
|
|
291
|
-
this.inputs.focusMode() === 'roving' ? item.element().focus() : this.inputs.element()?.focus();
|
|
292
|
-
}
|
|
293
|
-
return true;
|
|
294
|
-
}
|
|
295
|
-
isFocusable(item) {
|
|
296
|
-
return !item.disabled() || !this.inputs.skipDisabled();
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
class ListNavigation {
|
|
301
|
-
inputs;
|
|
302
|
-
constructor(inputs) {
|
|
303
|
-
this.inputs = inputs;
|
|
304
|
-
}
|
|
305
|
-
goto(item, opts) {
|
|
306
|
-
return item ? this.inputs.focusManager.focus(item, opts) : false;
|
|
307
|
-
}
|
|
308
|
-
next(opts) {
|
|
309
|
-
return this._advance(1, opts);
|
|
310
|
-
}
|
|
311
|
-
peekNext() {
|
|
312
|
-
return this._peek(1);
|
|
313
|
-
}
|
|
314
|
-
prev(opts) {
|
|
315
|
-
return this._advance(-1, opts);
|
|
316
|
-
}
|
|
317
|
-
peekPrev() {
|
|
318
|
-
return this._peek(-1);
|
|
319
|
-
}
|
|
320
|
-
first(opts) {
|
|
321
|
-
const item = this.inputs.items().find(i => this.inputs.focusManager.isFocusable(i));
|
|
322
|
-
return item ? this.goto(item, opts) : false;
|
|
323
|
-
}
|
|
324
|
-
last(opts) {
|
|
325
|
-
const items = this.inputs.items();
|
|
326
|
-
for (let i = items.length - 1; i >= 0; i--) {
|
|
327
|
-
if (this.inputs.focusManager.isFocusable(items[i])) {
|
|
328
|
-
return this.goto(items[i], opts);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
return false;
|
|
406
|
+
onKeydown(event) {
|
|
407
|
+
this.keydown().handle(event);
|
|
332
408
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
_peek(delta) {
|
|
338
|
-
const items = this.inputs.items();
|
|
339
|
-
const itemCount = items.length;
|
|
340
|
-
const startIndex = this.inputs.focusManager.activeIndex();
|
|
341
|
-
const step = i => this.inputs.wrap() ? (i + delta + itemCount) % itemCount : i + delta;
|
|
342
|
-
for (let i = step(startIndex); i !== startIndex && i < itemCount && i >= 0; i = step(i)) {
|
|
343
|
-
if (this.inputs.focusManager.isFocusable(items[i])) {
|
|
344
|
-
return items[i];
|
|
345
|
-
}
|
|
409
|
+
onClick(event) {
|
|
410
|
+
if (event.target === this.inputs.element()) {
|
|
411
|
+
this.inputs.combobox.close();
|
|
346
412
|
}
|
|
347
|
-
return;
|
|
348
413
|
}
|
|
349
414
|
}
|
|
350
415
|
|
|
@@ -352,7 +417,7 @@ class ListSelection {
|
|
|
352
417
|
inputs;
|
|
353
418
|
rangeStartIndex = signal(0);
|
|
354
419
|
rangeEndIndex = signal(0);
|
|
355
|
-
selectedItems = computed(() => this.inputs.items().filter(item => this.inputs.
|
|
420
|
+
selectedItems = computed(() => this.inputs.items().filter(item => this.inputs.values().includes(item.value())));
|
|
356
421
|
constructor(inputs) {
|
|
357
422
|
this.inputs = inputs;
|
|
358
423
|
}
|
|
@@ -360,7 +425,7 @@ class ListSelection {
|
|
|
360
425
|
anchor: true
|
|
361
426
|
}) {
|
|
362
427
|
item = item ?? this.inputs.focusManager.inputs.activeItem();
|
|
363
|
-
if (!item || item.disabled() || !item.selectable() || this.inputs.
|
|
428
|
+
if (!item || item.disabled() || !item.selectable() || this.inputs.values().includes(item.value())) {
|
|
364
429
|
return;
|
|
365
430
|
}
|
|
366
431
|
if (!this.inputs.multi()) {
|
|
@@ -370,24 +435,24 @@ class ListSelection {
|
|
|
370
435
|
if (opts.anchor) {
|
|
371
436
|
this.beginRangeSelection(index);
|
|
372
437
|
}
|
|
373
|
-
this.inputs.
|
|
438
|
+
this.inputs.values.update(values => values.concat(item.value()));
|
|
374
439
|
}
|
|
375
440
|
deselect(item) {
|
|
376
441
|
item = item ?? this.inputs.focusManager.inputs.activeItem();
|
|
377
442
|
if (item && !item.disabled() && item.selectable()) {
|
|
378
|
-
this.inputs.
|
|
443
|
+
this.inputs.values.update(values => values.filter(value => value !== item.value()));
|
|
379
444
|
}
|
|
380
445
|
}
|
|
381
|
-
toggle() {
|
|
382
|
-
|
|
446
|
+
toggle(item) {
|
|
447
|
+
item = item ?? this.inputs.focusManager.inputs.activeItem();
|
|
383
448
|
if (item) {
|
|
384
|
-
this.inputs.
|
|
449
|
+
this.inputs.values().includes(item.value()) ? this.deselect(item) : this.select(item);
|
|
385
450
|
}
|
|
386
451
|
}
|
|
387
452
|
toggleOne() {
|
|
388
453
|
const item = this.inputs.focusManager.inputs.activeItem();
|
|
389
454
|
if (item) {
|
|
390
|
-
this.inputs.
|
|
455
|
+
this.inputs.values().includes(item.value()) ? this.deselect() : this.selectOne();
|
|
391
456
|
}
|
|
392
457
|
}
|
|
393
458
|
selectAll() {
|
|
@@ -402,14 +467,14 @@ class ListSelection {
|
|
|
402
467
|
this.beginRangeSelection();
|
|
403
468
|
}
|
|
404
469
|
deselectAll() {
|
|
405
|
-
for (const value of this.inputs.
|
|
470
|
+
for (const value of this.inputs.values()) {
|
|
406
471
|
const item = this.inputs.items().find(i => i.value() === value);
|
|
407
|
-
item ? this.deselect(item) : this.inputs.
|
|
472
|
+
item ? this.deselect(item) : this.inputs.values.update(values => values.filter(v => v !== value));
|
|
408
473
|
}
|
|
409
474
|
}
|
|
410
475
|
toggleAll() {
|
|
411
476
|
const selectableValues = this.inputs.items().filter(i => !i.disabled() && i.selectable()).map(i => i.value());
|
|
412
|
-
selectableValues.every(i => this.inputs.
|
|
477
|
+
selectableValues.every(i => this.inputs.values().includes(i)) ? this.deselectAll() : this.selectAll();
|
|
413
478
|
}
|
|
414
479
|
selectOne() {
|
|
415
480
|
const item = this.inputs.focusManager.inputs.activeItem();
|
|
@@ -417,7 +482,7 @@ class ListSelection {
|
|
|
417
482
|
return;
|
|
418
483
|
}
|
|
419
484
|
this.deselectAll();
|
|
420
|
-
if (this.inputs.
|
|
485
|
+
if (this.inputs.values().length > 0 && !this.inputs.multi()) {
|
|
421
486
|
return;
|
|
422
487
|
}
|
|
423
488
|
this.select();
|
|
@@ -496,7 +561,7 @@ class ListTypeahead {
|
|
|
496
561
|
this.timeout = setTimeout(() => {
|
|
497
562
|
this._query.set('');
|
|
498
563
|
this._startIndex.set(undefined);
|
|
499
|
-
}, this.inputs.typeaheadDelay()
|
|
564
|
+
}, this.inputs.typeaheadDelay());
|
|
500
565
|
return true;
|
|
501
566
|
}
|
|
502
567
|
_getItem() {
|
|
@@ -522,8 +587,8 @@ class List {
|
|
|
522
587
|
typeaheadBehavior;
|
|
523
588
|
focusBehavior;
|
|
524
589
|
disabled = computed(() => this.focusBehavior.isListDisabled());
|
|
525
|
-
|
|
526
|
-
|
|
590
|
+
activeDescendant = computed(() => this.focusBehavior.getActiveDescendant());
|
|
591
|
+
tabIndex = computed(() => this.focusBehavior.getListTabIndex());
|
|
527
592
|
activeIndex = computed(() => this.focusBehavior.activeIndex());
|
|
528
593
|
_anchorIndex = signal(0);
|
|
529
594
|
_wrap = signal(true);
|
|
@@ -545,7 +610,7 @@ class List {
|
|
|
545
610
|
});
|
|
546
611
|
}
|
|
547
612
|
getItemTabindex(item) {
|
|
548
|
-
return this.focusBehavior.
|
|
613
|
+
return this.focusBehavior.getItemTabIndex(item);
|
|
549
614
|
}
|
|
550
615
|
first(opts) {
|
|
551
616
|
this._navigate(opts, () => this.navigationBehavior.first(opts));
|
|
@@ -580,14 +645,14 @@ class List {
|
|
|
580
645
|
selectOne() {
|
|
581
646
|
this.selectionBehavior.selectOne();
|
|
582
647
|
}
|
|
583
|
-
deselect() {
|
|
584
|
-
this.selectionBehavior.deselect();
|
|
648
|
+
deselect(item) {
|
|
649
|
+
this.selectionBehavior.deselect(item);
|
|
585
650
|
}
|
|
586
651
|
deselectAll() {
|
|
587
652
|
this.selectionBehavior.deselectAll();
|
|
588
653
|
}
|
|
589
|
-
toggle() {
|
|
590
|
-
this.selectionBehavior.toggle();
|
|
654
|
+
toggle(item) {
|
|
655
|
+
this.selectionBehavior.toggle(item);
|
|
591
656
|
}
|
|
592
657
|
toggleOne() {
|
|
593
658
|
this.selectionBehavior.toggleOne();
|
|
@@ -636,8 +701,8 @@ class ListboxPattern {
|
|
|
636
701
|
orientation;
|
|
637
702
|
disabled = computed(() => this.listBehavior.disabled());
|
|
638
703
|
readonly;
|
|
639
|
-
|
|
640
|
-
|
|
704
|
+
tabIndex = computed(() => this.listBehavior.tabIndex());
|
|
705
|
+
activeDescendant = computed(() => this.listBehavior.activeDescendant());
|
|
641
706
|
multi;
|
|
642
707
|
setsize = computed(() => this.inputs.items().length);
|
|
643
708
|
followFocus = computed(() => this.inputs.selectionMode() === 'follow');
|
|
@@ -754,8 +819,8 @@ class ListboxPattern {
|
|
|
754
819
|
}
|
|
755
820
|
validate() {
|
|
756
821
|
const violations = [];
|
|
757
|
-
if (!this.inputs.multi() && this.inputs.
|
|
758
|
-
violations.push(`A single-select listbox should not have multiple selected options. Selected options: ${this.inputs.
|
|
822
|
+
if (!this.inputs.multi() && this.inputs.values().length > 1) {
|
|
823
|
+
violations.push(`A single-select listbox should not have multiple selected options. Selected options: ${this.inputs.values().join(', ')}`);
|
|
759
824
|
}
|
|
760
825
|
return violations;
|
|
761
826
|
}
|
|
@@ -800,12 +865,12 @@ class OptionPattern {
|
|
|
800
865
|
value;
|
|
801
866
|
index = computed(() => this.listbox()?.inputs.items().indexOf(this) ?? -1);
|
|
802
867
|
active = computed(() => this.listbox()?.inputs.activeItem() === this);
|
|
803
|
-
selected = computed(() => this.listbox()?.inputs.
|
|
868
|
+
selected = computed(() => this.listbox()?.inputs.values().includes(this.value()));
|
|
804
869
|
selectable = () => true;
|
|
805
870
|
disabled;
|
|
806
871
|
searchTerm;
|
|
807
872
|
listbox;
|
|
808
|
-
|
|
873
|
+
tabIndex = computed(() => this.listbox()?.listBehavior.getItemTabindex(this));
|
|
809
874
|
element;
|
|
810
875
|
constructor(args) {
|
|
811
876
|
this.id = args.id;
|
|
@@ -821,12 +886,14 @@ class ComboboxListboxPattern extends ListboxPattern {
|
|
|
821
886
|
inputs;
|
|
822
887
|
id = computed(() => this.inputs.id());
|
|
823
888
|
role = computed(() => 'listbox');
|
|
824
|
-
activeId = computed(() => this.listBehavior.
|
|
889
|
+
activeId = computed(() => this.listBehavior.activeDescendant());
|
|
825
890
|
items = computed(() => this.inputs.items());
|
|
826
|
-
|
|
891
|
+
tabIndex = () => -1;
|
|
892
|
+
multi = computed(() => {
|
|
893
|
+
return this.inputs.combobox()?.readonly() ? this.inputs.multi() : false;
|
|
894
|
+
});
|
|
827
895
|
constructor(inputs) {
|
|
828
896
|
if (inputs.combobox()) {
|
|
829
|
-
inputs.multi = () => false;
|
|
830
897
|
inputs.focusMode = () => 'activedescendant';
|
|
831
898
|
inputs.element = inputs.combobox().inputs.inputEl;
|
|
832
899
|
}
|
|
@@ -836,27 +903,44 @@ class ComboboxListboxPattern extends ListboxPattern {
|
|
|
836
903
|
onKeydown(_) {}
|
|
837
904
|
onPointerdown(_) {}
|
|
838
905
|
setDefaultState() {}
|
|
839
|
-
focus = item =>
|
|
906
|
+
focus = (item, opts) => {
|
|
907
|
+
this.listBehavior.goto(item, opts);
|
|
908
|
+
};
|
|
909
|
+
getActiveItem = () => this.inputs.activeItem();
|
|
840
910
|
next = () => this.listBehavior.next();
|
|
841
911
|
prev = () => this.listBehavior.prev();
|
|
842
912
|
last = () => this.listBehavior.last();
|
|
843
913
|
first = () => this.listBehavior.first();
|
|
844
914
|
unfocus = () => this.listBehavior.unfocus();
|
|
845
915
|
select = item => this.listBehavior.select(item);
|
|
916
|
+
toggle = item => this.listBehavior.toggle(item);
|
|
846
917
|
clearSelection = () => this.listBehavior.deselectAll();
|
|
847
918
|
getItem = e => this._getItem(e);
|
|
848
|
-
|
|
849
|
-
|
|
919
|
+
getSelectedItems = () => {
|
|
920
|
+
const items = [];
|
|
921
|
+
for (const value of this.inputs.values()) {
|
|
922
|
+
const item = this.items().find(i => i.value() === value);
|
|
923
|
+
if (item) {
|
|
924
|
+
items.push(item);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
return items;
|
|
928
|
+
};
|
|
929
|
+
setValue = value => this.inputs.values.set(value ? [value] : []);
|
|
850
930
|
}
|
|
851
931
|
|
|
852
932
|
class MenuPattern {
|
|
853
933
|
inputs;
|
|
854
934
|
id;
|
|
855
935
|
role = () => 'menu';
|
|
856
|
-
|
|
936
|
+
disabled = () => this.inputs.disabled();
|
|
937
|
+
visible = computed(() => this.inputs.parent() ? !!this.inputs.parent()?.expanded() : true);
|
|
857
938
|
listBehavior;
|
|
858
939
|
isFocused = signal(false);
|
|
859
940
|
hasBeenFocused = signal(false);
|
|
941
|
+
_openTimeout;
|
|
942
|
+
_closeTimeout;
|
|
943
|
+
tabIndex = () => this.listBehavior.tabIndex();
|
|
860
944
|
shouldFocus = computed(() => {
|
|
861
945
|
const root = this.root();
|
|
862
946
|
if (root instanceof MenuTriggerPattern) {
|
|
@@ -897,40 +981,67 @@ class MenuPattern {
|
|
|
897
981
|
this.id = inputs.id;
|
|
898
982
|
this.listBehavior = new List({
|
|
899
983
|
...inputs,
|
|
900
|
-
|
|
901
|
-
disabled: () => false
|
|
984
|
+
values: signal([])
|
|
902
985
|
});
|
|
903
986
|
}
|
|
904
987
|
setDefaultState() {
|
|
905
988
|
if (!this.inputs.parent()) {
|
|
906
|
-
this.
|
|
989
|
+
this.listBehavior.goto(this.inputs.items()[0], {
|
|
990
|
+
focusElement: false
|
|
991
|
+
});
|
|
907
992
|
}
|
|
908
993
|
}
|
|
909
994
|
onKeydown(event) {
|
|
910
995
|
this.keydownManager().handle(event);
|
|
911
996
|
}
|
|
912
997
|
onMouseOver(event) {
|
|
913
|
-
if (!this.
|
|
998
|
+
if (!this.visible()) {
|
|
914
999
|
return;
|
|
915
1000
|
}
|
|
916
1001
|
const item = this.inputs.items().find(i => i.element()?.contains(event.target));
|
|
917
1002
|
if (!item) {
|
|
918
1003
|
return;
|
|
919
1004
|
}
|
|
1005
|
+
const parent = this.inputs.parent();
|
|
920
1006
|
const activeItem = this?.inputs.activeItem();
|
|
1007
|
+
if (parent instanceof MenuItemPattern) {
|
|
1008
|
+
const grandparent = parent.inputs.parent();
|
|
1009
|
+
if (grandparent instanceof MenuPattern) {
|
|
1010
|
+
grandparent._clearTimeouts();
|
|
1011
|
+
grandparent.listBehavior.goto(parent, {
|
|
1012
|
+
focusElement: false
|
|
1013
|
+
});
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
921
1016
|
if (activeItem && activeItem !== item) {
|
|
922
|
-
|
|
1017
|
+
this._closeItem(activeItem);
|
|
923
1018
|
}
|
|
924
|
-
if (item.expanded()
|
|
925
|
-
|
|
926
|
-
item.submenu()?.listBehavior.unfocus();
|
|
1019
|
+
if (item.expanded()) {
|
|
1020
|
+
this._clearCloseTimeout();
|
|
927
1021
|
}
|
|
928
|
-
|
|
1022
|
+
this._openItem(item);
|
|
929
1023
|
this.listBehavior.goto(item, {
|
|
930
1024
|
focusElement: this.shouldFocus()
|
|
931
1025
|
});
|
|
932
1026
|
}
|
|
1027
|
+
_closeItem(item) {
|
|
1028
|
+
this._clearOpenTimeout();
|
|
1029
|
+
if (!this._closeTimeout) {
|
|
1030
|
+
this._closeTimeout = setTimeout(() => {
|
|
1031
|
+
item.close();
|
|
1032
|
+
this._closeTimeout = undefined;
|
|
1033
|
+
}, this.inputs.expansionDelay());
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
_openItem(item) {
|
|
1037
|
+
this._clearOpenTimeout();
|
|
1038
|
+
this._openTimeout = setTimeout(() => {
|
|
1039
|
+
item.open();
|
|
1040
|
+
this._openTimeout = undefined;
|
|
1041
|
+
}, this.inputs.expansionDelay());
|
|
1042
|
+
}
|
|
933
1043
|
onMouseOut(event) {
|
|
1044
|
+
this._clearOpenTimeout();
|
|
934
1045
|
if (this.isFocused()) {
|
|
935
1046
|
return;
|
|
936
1047
|
}
|
|
@@ -974,12 +1085,12 @@ class MenuPattern {
|
|
|
974
1085
|
if (parent instanceof MenuItemPattern) {
|
|
975
1086
|
const grandparent = parent.inputs.parent();
|
|
976
1087
|
const siblings = grandparent?.inputs.items().filter(i => i !== parent);
|
|
977
|
-
const item = siblings?.find(i => i.element()
|
|
1088
|
+
const item = siblings?.find(i => i.element()?.contains(relatedTarget));
|
|
978
1089
|
if (item) {
|
|
979
1090
|
return;
|
|
980
1091
|
}
|
|
981
1092
|
}
|
|
982
|
-
if (this.
|
|
1093
|
+
if (this.visible() && !parentEl?.contains(relatedTarget) && !this.inputs.element()?.contains(relatedTarget)) {
|
|
983
1094
|
this.isFocused.set(false);
|
|
984
1095
|
this.inputs.parent()?.close();
|
|
985
1096
|
}
|
|
@@ -1011,17 +1122,20 @@ class MenuPattern {
|
|
|
1011
1122
|
const isMenu = root instanceof MenuPattern;
|
|
1012
1123
|
const isMenuBar = root instanceof MenuBarPattern;
|
|
1013
1124
|
const isMenuTrigger = root instanceof MenuTriggerPattern;
|
|
1014
|
-
if (!item.submenu() &&
|
|
1125
|
+
if (!item.submenu() && isMenuTrigger) {
|
|
1015
1126
|
root.close({
|
|
1016
1127
|
refocus: true
|
|
1017
1128
|
});
|
|
1018
|
-
|
|
1129
|
+
}
|
|
1130
|
+
if (!item.submenu() && isMenuBar) {
|
|
1131
|
+
root.close();
|
|
1132
|
+
root?.inputs.onSelect?.(item.value());
|
|
1019
1133
|
}
|
|
1020
1134
|
if (!item.submenu() && isMenu) {
|
|
1021
1135
|
root.inputs.activeItem()?.close({
|
|
1022
1136
|
refocus: true
|
|
1023
1137
|
});
|
|
1024
|
-
root?.inputs.
|
|
1138
|
+
root?.inputs.onSelect?.(item.value());
|
|
1025
1139
|
}
|
|
1026
1140
|
}
|
|
1027
1141
|
}
|
|
@@ -1047,6 +1161,9 @@ class MenuPattern {
|
|
|
1047
1161
|
root.next();
|
|
1048
1162
|
}
|
|
1049
1163
|
}
|
|
1164
|
+
close() {
|
|
1165
|
+
this.inputs.parent()?.close();
|
|
1166
|
+
}
|
|
1050
1167
|
closeAll() {
|
|
1051
1168
|
const root = this.root();
|
|
1052
1169
|
if (root instanceof MenuTriggerPattern) {
|
|
@@ -1063,10 +1180,27 @@ class MenuPattern {
|
|
|
1063
1180
|
});
|
|
1064
1181
|
}
|
|
1065
1182
|
}
|
|
1183
|
+
_clearTimeouts() {
|
|
1184
|
+
this._clearOpenTimeout();
|
|
1185
|
+
this._clearCloseTimeout();
|
|
1186
|
+
}
|
|
1187
|
+
_clearOpenTimeout() {
|
|
1188
|
+
if (this._openTimeout) {
|
|
1189
|
+
clearTimeout(this._openTimeout);
|
|
1190
|
+
this._openTimeout = undefined;
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
_clearCloseTimeout() {
|
|
1194
|
+
if (this._closeTimeout) {
|
|
1195
|
+
clearTimeout(this._closeTimeout);
|
|
1196
|
+
this._closeTimeout = undefined;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1066
1199
|
}
|
|
1067
1200
|
class MenuBarPattern {
|
|
1068
1201
|
inputs;
|
|
1069
1202
|
listBehavior;
|
|
1203
|
+
tabIndex = () => this.listBehavior.tabIndex();
|
|
1070
1204
|
_nextKey = computed(() => {
|
|
1071
1205
|
return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
|
|
1072
1206
|
});
|
|
@@ -1077,6 +1211,7 @@ class MenuBarPattern {
|
|
|
1077
1211
|
typeaheadRegexp = /^.$/;
|
|
1078
1212
|
isFocused = signal(false);
|
|
1079
1213
|
hasBeenFocused = signal(false);
|
|
1214
|
+
disabled = () => this.inputs.disabled();
|
|
1080
1215
|
keydownManager = computed(() => {
|
|
1081
1216
|
return new KeyboardEventManager().on(this._nextKey, () => this.next()).on(this._previousKey, () => this.prev()).on('End', () => this.listBehavior.last()).on('Home', () => this.listBehavior.first()).on('Enter', () => this.inputs.activeItem()?.open({
|
|
1082
1217
|
first: true
|
|
@@ -1090,10 +1225,7 @@ class MenuBarPattern {
|
|
|
1090
1225
|
});
|
|
1091
1226
|
constructor(inputs) {
|
|
1092
1227
|
this.inputs = inputs;
|
|
1093
|
-
this.listBehavior = new List(
|
|
1094
|
-
...inputs,
|
|
1095
|
-
disabled: () => false
|
|
1096
|
-
});
|
|
1228
|
+
this.listBehavior = new List(inputs);
|
|
1097
1229
|
}
|
|
1098
1230
|
setDefaultState() {
|
|
1099
1231
|
this.inputs.activeItem.set(this.inputs.items()[0]);
|
|
@@ -1171,10 +1303,12 @@ class MenuBarPattern {
|
|
|
1171
1303
|
class MenuTriggerPattern {
|
|
1172
1304
|
inputs;
|
|
1173
1305
|
expanded = signal(false);
|
|
1306
|
+
hasBeenFocused = signal(false);
|
|
1174
1307
|
role = () => 'button';
|
|
1175
1308
|
hasPopup = () => true;
|
|
1176
|
-
|
|
1177
|
-
|
|
1309
|
+
menu;
|
|
1310
|
+
tabIndex = computed(() => this.expanded() && this.menu()?.inputs.activeItem() ? -1 : 0);
|
|
1311
|
+
disabled = () => this.inputs.disabled();
|
|
1178
1312
|
keydownManager = computed(() => {
|
|
1179
1313
|
return new KeyboardEventManager().on(' ', () => this.open({
|
|
1180
1314
|
first: true
|
|
@@ -1190,38 +1324,45 @@ class MenuTriggerPattern {
|
|
|
1190
1324
|
});
|
|
1191
1325
|
constructor(inputs) {
|
|
1192
1326
|
this.inputs = inputs;
|
|
1193
|
-
this.
|
|
1327
|
+
this.menu = this.inputs.menu;
|
|
1194
1328
|
}
|
|
1195
1329
|
onKeydown(event) {
|
|
1196
|
-
this.
|
|
1330
|
+
if (!this.inputs.disabled()) {
|
|
1331
|
+
this.keydownManager().handle(event);
|
|
1332
|
+
}
|
|
1197
1333
|
}
|
|
1198
1334
|
onClick() {
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1335
|
+
if (!this.inputs.disabled()) {
|
|
1336
|
+
this.expanded() ? this.close() : this.open({
|
|
1337
|
+
first: true
|
|
1338
|
+
});
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
onFocusIn() {
|
|
1342
|
+
this.hasBeenFocused.set(true);
|
|
1202
1343
|
}
|
|
1203
1344
|
onFocusOut(event) {
|
|
1204
1345
|
const element = this.inputs.element();
|
|
1205
1346
|
const relatedTarget = event.relatedTarget;
|
|
1206
|
-
if (this.expanded() && !element?.contains(relatedTarget) && !this.inputs.
|
|
1347
|
+
if (this.expanded() && !element?.contains(relatedTarget) && !this.inputs.menu()?.inputs.element()?.contains(relatedTarget)) {
|
|
1207
1348
|
this.close();
|
|
1208
1349
|
}
|
|
1209
1350
|
}
|
|
1210
1351
|
open(opts) {
|
|
1211
1352
|
this.expanded.set(true);
|
|
1212
1353
|
if (opts?.first) {
|
|
1213
|
-
this.inputs.
|
|
1354
|
+
this.inputs.menu()?.first();
|
|
1214
1355
|
} else if (opts?.last) {
|
|
1215
|
-
this.inputs.
|
|
1356
|
+
this.inputs.menu()?.last();
|
|
1216
1357
|
}
|
|
1217
1358
|
}
|
|
1218
1359
|
close(opts = {}) {
|
|
1219
1360
|
this.expanded.set(false);
|
|
1220
|
-
this.
|
|
1361
|
+
this.menu()?.listBehavior.unfocus();
|
|
1221
1362
|
if (opts.refocus) {
|
|
1222
1363
|
this.inputs.element()?.focus();
|
|
1223
1364
|
}
|
|
1224
|
-
let menuitems = this.inputs.
|
|
1365
|
+
let menuitems = this.inputs.menu()?.inputs.items() ?? [];
|
|
1225
1366
|
while (menuitems.length) {
|
|
1226
1367
|
const menuitem = menuitems.pop();
|
|
1227
1368
|
menuitem?._expanded.set(false);
|
|
@@ -1234,11 +1375,12 @@ class MenuItemPattern {
|
|
|
1234
1375
|
inputs;
|
|
1235
1376
|
value;
|
|
1236
1377
|
id;
|
|
1237
|
-
disabled;
|
|
1378
|
+
disabled = () => this.inputs.parent()?.disabled() || this.inputs.disabled();
|
|
1238
1379
|
searchTerm;
|
|
1239
1380
|
element;
|
|
1240
|
-
|
|
1241
|
-
|
|
1381
|
+
active = computed(() => this.inputs.parent()?.inputs.activeItem() === this);
|
|
1382
|
+
hasBeenFocused = signal(false);
|
|
1383
|
+
tabIndex = computed(() => {
|
|
1242
1384
|
if (this.submenu() && this.submenu()?.inputs.activeItem()) {
|
|
1243
1385
|
return -1;
|
|
1244
1386
|
}
|
|
@@ -1257,12 +1399,14 @@ class MenuItemPattern {
|
|
|
1257
1399
|
this.id = inputs.id;
|
|
1258
1400
|
this.value = inputs.value;
|
|
1259
1401
|
this.element = inputs.element;
|
|
1260
|
-
this.disabled = inputs.disabled;
|
|
1261
1402
|
this.submenu = this.inputs.submenu;
|
|
1262
1403
|
this.searchTerm = inputs.searchTerm;
|
|
1263
1404
|
this.selectable = computed(() => !this.submenu());
|
|
1264
1405
|
}
|
|
1265
1406
|
open(opts) {
|
|
1407
|
+
if (this.disabled()) {
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1266
1410
|
this._expanded.set(true);
|
|
1267
1411
|
if (opts?.first) {
|
|
1268
1412
|
this.submenu()?.first();
|
|
@@ -1282,224 +1426,45 @@ class MenuItemPattern {
|
|
|
1282
1426
|
menuitem?._expanded.set(false);
|
|
1283
1427
|
menuitem?.inputs.parent()?.listBehavior.unfocus();
|
|
1284
1428
|
menuitems = menuitems.concat(menuitem?.submenu()?.inputs.items() ?? []);
|
|
1429
|
+
const parent = menuitem?.inputs.parent();
|
|
1430
|
+
if (parent instanceof MenuPattern) {
|
|
1431
|
+
parent._clearTimeouts();
|
|
1432
|
+
}
|
|
1285
1433
|
}
|
|
1286
1434
|
}
|
|
1435
|
+
onFocusIn() {
|
|
1436
|
+
this.hasBeenFocused.set(true);
|
|
1437
|
+
}
|
|
1287
1438
|
}
|
|
1288
1439
|
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
wrap = signal(false);
|
|
1294
|
-
selectionMode = signal('follow');
|
|
1295
|
-
disabled = computed(() => this.inputs.disabled() || this.listBehavior.disabled());
|
|
1296
|
-
selectedItem = computed(() => this.listBehavior.selectionBehavior.selectedItems()[0]);
|
|
1297
|
-
readonly = computed(() => this.selectedItem()?.disabled() || this.inputs.readonly());
|
|
1298
|
-
tabindex = computed(() => this.listBehavior.tabindex());
|
|
1299
|
-
activedescendant = computed(() => this.listBehavior.activedescendant());
|
|
1300
|
-
_prevKey = computed(() => {
|
|
1301
|
-
if (this.inputs.orientation() === 'vertical') {
|
|
1302
|
-
return 'ArrowUp';
|
|
1303
|
-
}
|
|
1304
|
-
return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
|
|
1305
|
-
});
|
|
1306
|
-
_nextKey = computed(() => {
|
|
1307
|
-
if (this.inputs.orientation() === 'vertical') {
|
|
1308
|
-
return 'ArrowDown';
|
|
1309
|
-
}
|
|
1310
|
-
return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
|
|
1311
|
-
});
|
|
1312
|
-
keydown = computed(() => {
|
|
1313
|
-
const manager = new KeyboardEventManager();
|
|
1314
|
-
if (this.readonly()) {
|
|
1315
|
-
return manager.on(this._prevKey, () => this.listBehavior.prev()).on(this._nextKey, () => this.listBehavior.next()).on('Home', () => this.listBehavior.first()).on('End', () => this.listBehavior.last());
|
|
1316
|
-
}
|
|
1317
|
-
return manager.on(this._prevKey, () => this.listBehavior.prev({
|
|
1318
|
-
selectOne: true
|
|
1319
|
-
})).on(this._nextKey, () => this.listBehavior.next({
|
|
1320
|
-
selectOne: true
|
|
1321
|
-
})).on('Home', () => this.listBehavior.first({
|
|
1322
|
-
selectOne: true
|
|
1323
|
-
})).on('End', () => this.listBehavior.last({
|
|
1324
|
-
selectOne: true
|
|
1325
|
-
})).on(' ', () => this.listBehavior.selectOne()).on('Enter', () => this.listBehavior.selectOne());
|
|
1326
|
-
});
|
|
1327
|
-
pointerdown = computed(() => {
|
|
1328
|
-
const manager = new PointerEventManager();
|
|
1329
|
-
if (this.readonly()) {
|
|
1330
|
-
return manager.on(e => this.listBehavior.goto(this.inputs.getItem(e)));
|
|
1331
|
-
}
|
|
1332
|
-
return manager.on(e => this.listBehavior.goto(this.inputs.getItem(e), {
|
|
1333
|
-
selectOne: true
|
|
1334
|
-
}));
|
|
1440
|
+
function convertGetterSetterToWritableSignalLike(getter, setter) {
|
|
1441
|
+
return Object.assign(getter, {
|
|
1442
|
+
set: setter,
|
|
1443
|
+
update: updateCallback => setter(updateCallback(getter()))
|
|
1335
1444
|
});
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
class ListExpansion {
|
|
1448
|
+
inputs;
|
|
1336
1449
|
constructor(inputs) {
|
|
1337
1450
|
this.inputs = inputs;
|
|
1338
|
-
this.orientation = inputs.orientation;
|
|
1339
|
-
this.listBehavior = new List({
|
|
1340
|
-
...inputs,
|
|
1341
|
-
wrap: this.wrap,
|
|
1342
|
-
selectionMode: this.selectionMode,
|
|
1343
|
-
multi: () => false,
|
|
1344
|
-
typeaheadDelay: () => 0
|
|
1345
|
-
});
|
|
1346
|
-
}
|
|
1347
|
-
onKeydown(event) {
|
|
1348
|
-
if (!this.disabled()) {
|
|
1349
|
-
this.keydown().handle(event);
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
onPointerdown(event) {
|
|
1353
|
-
if (!this.disabled()) {
|
|
1354
|
-
this.pointerdown().handle(event);
|
|
1355
|
-
}
|
|
1356
|
-
}
|
|
1357
|
-
setDefaultState() {
|
|
1358
|
-
let firstItem = null;
|
|
1359
|
-
for (const item of this.inputs.items()) {
|
|
1360
|
-
if (this.listBehavior.isFocusable(item)) {
|
|
1361
|
-
if (!firstItem) {
|
|
1362
|
-
firstItem = item;
|
|
1363
|
-
}
|
|
1364
|
-
if (item.selected()) {
|
|
1365
|
-
this.inputs.activeItem.set(item);
|
|
1366
|
-
return;
|
|
1367
|
-
}
|
|
1368
|
-
}
|
|
1369
|
-
}
|
|
1370
|
-
if (firstItem) {
|
|
1371
|
-
this.inputs.activeItem.set(firstItem);
|
|
1372
|
-
}
|
|
1373
|
-
}
|
|
1374
|
-
validate() {
|
|
1375
|
-
const violations = [];
|
|
1376
|
-
if (this.selectedItem()?.disabled() && this.inputs.skipDisabled()) {
|
|
1377
|
-
violations.push("Accessibility Violation: The selected radio button is disabled while 'skipDisabled' is true, making the selection unreachable via keyboard.");
|
|
1378
|
-
}
|
|
1379
|
-
return violations;
|
|
1380
|
-
}
|
|
1381
|
-
}
|
|
1382
|
-
|
|
1383
|
-
class RadioButtonPattern {
|
|
1384
|
-
inputs;
|
|
1385
|
-
id;
|
|
1386
|
-
value;
|
|
1387
|
-
index = computed(() => this.group()?.listBehavior.inputs.items().indexOf(this) ?? -1);
|
|
1388
|
-
active = computed(() => this.group()?.listBehavior.inputs.activeItem() === this);
|
|
1389
|
-
selected = computed(() => !!this.group()?.listBehavior.inputs.value().includes(this.value()));
|
|
1390
|
-
selectable = () => true;
|
|
1391
|
-
disabled;
|
|
1392
|
-
group;
|
|
1393
|
-
tabindex = computed(() => this.group()?.listBehavior.getItemTabindex(this));
|
|
1394
|
-
element;
|
|
1395
|
-
searchTerm = () => '';
|
|
1396
|
-
constructor(inputs) {
|
|
1397
|
-
this.inputs = inputs;
|
|
1398
|
-
this.id = inputs.id;
|
|
1399
|
-
this.value = inputs.value;
|
|
1400
|
-
this.group = inputs.group;
|
|
1401
|
-
this.element = inputs.element;
|
|
1402
|
-
this.disabled = inputs.disabled;
|
|
1403
|
-
}
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
class ToolbarRadioGroupPattern extends RadioGroupPattern {
|
|
1407
|
-
inputs;
|
|
1408
|
-
constructor(inputs) {
|
|
1409
|
-
if (!!inputs.toolbar()) {
|
|
1410
|
-
inputs.orientation = inputs.toolbar().orientation;
|
|
1411
|
-
inputs.skipDisabled = inputs.toolbar().skipDisabled;
|
|
1412
|
-
}
|
|
1413
|
-
super(inputs);
|
|
1414
|
-
this.inputs = inputs;
|
|
1415
|
-
}
|
|
1416
|
-
onKeydown(_) {}
|
|
1417
|
-
onPointerdown(_) {}
|
|
1418
|
-
isOnFirstItem() {
|
|
1419
|
-
return this.listBehavior.navigationBehavior.peekPrev() === undefined;
|
|
1420
|
-
}
|
|
1421
|
-
isOnLastItem() {
|
|
1422
|
-
return this.listBehavior.navigationBehavior.peekNext() === undefined;
|
|
1423
|
-
}
|
|
1424
|
-
next(wrap) {
|
|
1425
|
-
this.wrap.set(wrap);
|
|
1426
|
-
this.listBehavior.next();
|
|
1427
|
-
this.wrap.set(false);
|
|
1428
|
-
}
|
|
1429
|
-
prev(wrap) {
|
|
1430
|
-
this.wrap.set(wrap);
|
|
1431
|
-
this.listBehavior.prev();
|
|
1432
|
-
this.wrap.set(false);
|
|
1433
|
-
}
|
|
1434
|
-
first() {
|
|
1435
|
-
this.listBehavior.first();
|
|
1436
|
-
}
|
|
1437
|
-
last() {
|
|
1438
|
-
this.listBehavior.last();
|
|
1439
|
-
}
|
|
1440
|
-
unfocus() {
|
|
1441
|
-
this.inputs.activeItem.set(undefined);
|
|
1442
|
-
}
|
|
1443
|
-
trigger() {
|
|
1444
|
-
if (this.readonly()) return;
|
|
1445
|
-
this.listBehavior.selectOne();
|
|
1446
|
-
}
|
|
1447
|
-
goto(e) {
|
|
1448
|
-
this.listBehavior.goto(this.inputs.getItem(e), {
|
|
1449
|
-
selectOne: !this.readonly()
|
|
1450
|
-
});
|
|
1451
|
-
}
|
|
1452
|
-
}
|
|
1453
|
-
|
|
1454
|
-
function convertGetterSetterToWritableSignalLike(getter, setter) {
|
|
1455
|
-
return Object.assign(getter, {
|
|
1456
|
-
set: setter,
|
|
1457
|
-
update: updateCallback => setter(updateCallback(getter()))
|
|
1458
|
-
});
|
|
1459
|
-
}
|
|
1460
|
-
|
|
1461
|
-
class ExpansionControl {
|
|
1462
|
-
inputs;
|
|
1463
|
-
isExpanded = computed(() => this.inputs.expansionManager.isExpanded(this));
|
|
1464
|
-
isExpandable = computed(() => this.inputs.expansionManager.isExpandable(this));
|
|
1465
|
-
constructor(inputs) {
|
|
1466
|
-
this.inputs = inputs;
|
|
1467
|
-
this.expansionId = inputs.expansionId;
|
|
1468
|
-
this.expandable = inputs.expandable;
|
|
1469
|
-
this.disabled = inputs.disabled;
|
|
1470
|
-
}
|
|
1471
|
-
open() {
|
|
1472
|
-
this.inputs.expansionManager.open(this);
|
|
1473
|
-
}
|
|
1474
|
-
close() {
|
|
1475
|
-
this.inputs.expansionManager.close(this);
|
|
1476
|
-
}
|
|
1477
|
-
toggle() {
|
|
1478
|
-
this.inputs.expansionManager.toggle(this);
|
|
1479
|
-
}
|
|
1480
|
-
}
|
|
1481
|
-
class ListExpansion {
|
|
1482
|
-
inputs;
|
|
1483
|
-
expandedIds;
|
|
1484
|
-
constructor(inputs) {
|
|
1485
|
-
this.inputs = inputs;
|
|
1486
|
-
this.expandedIds = inputs.expandedIds;
|
|
1487
1451
|
}
|
|
1488
1452
|
open(item) {
|
|
1489
|
-
if (!this.isExpandable(item)) return;
|
|
1490
|
-
if (
|
|
1453
|
+
if (!this.isExpandable(item)) return false;
|
|
1454
|
+
if (item.expanded()) return false;
|
|
1491
1455
|
if (!this.inputs.multiExpandable()) {
|
|
1492
1456
|
this.closeAll();
|
|
1493
1457
|
}
|
|
1494
|
-
|
|
1458
|
+
item.expanded.set(true);
|
|
1459
|
+
return true;
|
|
1495
1460
|
}
|
|
1496
1461
|
close(item) {
|
|
1497
|
-
if (this.isExpandable(item))
|
|
1498
|
-
|
|
1499
|
-
|
|
1462
|
+
if (!this.isExpandable(item)) return false;
|
|
1463
|
+
item.expanded.set(false);
|
|
1464
|
+
return true;
|
|
1500
1465
|
}
|
|
1501
1466
|
toggle(item) {
|
|
1502
|
-
|
|
1467
|
+
return item.expanded() ? this.close(item) : this.open(item);
|
|
1503
1468
|
}
|
|
1504
1469
|
openAll() {
|
|
1505
1470
|
if (this.inputs.multiExpandable()) {
|
|
@@ -1516,9 +1481,6 @@ class ListExpansion {
|
|
|
1516
1481
|
isExpandable(item) {
|
|
1517
1482
|
return !this.inputs.disabled() && !item.disabled() && item.expandable();
|
|
1518
1483
|
}
|
|
1519
|
-
isExpanded(item) {
|
|
1520
|
-
return this.expandedIds().includes(item.expansionId());
|
|
1521
|
-
}
|
|
1522
1484
|
}
|
|
1523
1485
|
|
|
1524
1486
|
class LabelControl {
|
|
@@ -1543,47 +1505,35 @@ class LabelControl {
|
|
|
1543
1505
|
|
|
1544
1506
|
class TabPattern {
|
|
1545
1507
|
inputs;
|
|
1546
|
-
|
|
1547
|
-
id;
|
|
1508
|
+
id = () => this.inputs.id();
|
|
1548
1509
|
index = computed(() => this.inputs.tablist().inputs.items().indexOf(this));
|
|
1549
|
-
value;
|
|
1550
|
-
disabled;
|
|
1551
|
-
element;
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
expandable = computed(() => this.expansion.expandable());
|
|
1555
|
-
expansionId = computed(() => this.expansion.expansionId());
|
|
1556
|
-
expanded = computed(() => this.expansion.isExpanded());
|
|
1510
|
+
value = () => this.inputs.value();
|
|
1511
|
+
disabled = () => this.inputs.disabled();
|
|
1512
|
+
element = () => this.inputs.element();
|
|
1513
|
+
expandable = () => true;
|
|
1514
|
+
expanded;
|
|
1557
1515
|
active = computed(() => this.inputs.tablist().inputs.activeItem() === this);
|
|
1558
|
-
selected = computed(() =>
|
|
1559
|
-
|
|
1516
|
+
selected = computed(() => this.inputs.tablist().selectedTab() === this);
|
|
1517
|
+
tabIndex = computed(() => this.inputs.tablist().focusBehavior.getItemTabIndex(this));
|
|
1560
1518
|
controls = computed(() => this.inputs.tabpanel()?.id());
|
|
1561
1519
|
constructor(inputs) {
|
|
1562
1520
|
this.inputs = inputs;
|
|
1563
|
-
this.
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
this.
|
|
1567
|
-
this.expansion = new ExpansionControl({
|
|
1568
|
-
...inputs,
|
|
1569
|
-
expansionId: inputs.value,
|
|
1570
|
-
expandable: () => true,
|
|
1571
|
-
expansionManager: inputs.tablist().expansionManager
|
|
1572
|
-
});
|
|
1521
|
+
this.expanded = inputs.expanded;
|
|
1522
|
+
}
|
|
1523
|
+
open() {
|
|
1524
|
+
return this.inputs.tablist().open(this);
|
|
1573
1525
|
}
|
|
1574
1526
|
}
|
|
1575
1527
|
class TabPanelPattern {
|
|
1576
1528
|
inputs;
|
|
1577
|
-
id;
|
|
1578
|
-
value;
|
|
1529
|
+
id = () => this.inputs.id();
|
|
1530
|
+
value = () => this.inputs.value();
|
|
1579
1531
|
labelManager;
|
|
1580
1532
|
hidden = computed(() => this.inputs.tab()?.expanded() === false);
|
|
1581
|
-
|
|
1533
|
+
tabIndex = computed(() => this.hidden() ? -1 : 0);
|
|
1582
1534
|
labelledBy = computed(() => this.labelManager.labelledBy().length > 0 ? this.labelManager.labelledBy().join(' ') : undefined);
|
|
1583
1535
|
constructor(inputs) {
|
|
1584
1536
|
this.inputs = inputs;
|
|
1585
|
-
this.id = inputs.id;
|
|
1586
|
-
this.value = inputs.value;
|
|
1587
1537
|
this.labelManager = new LabelControl({
|
|
1588
1538
|
...inputs,
|
|
1589
1539
|
defaultLabelledBy: computed(() => this.inputs.tab() ? [this.inputs.tab().id()] : [])
|
|
@@ -1592,12 +1542,15 @@ class TabPanelPattern {
|
|
|
1592
1542
|
}
|
|
1593
1543
|
class TabListPattern {
|
|
1594
1544
|
inputs;
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1545
|
+
focusBehavior;
|
|
1546
|
+
navigationBehavior;
|
|
1547
|
+
expansionBehavior;
|
|
1548
|
+
activeTab = () => this.inputs.activeItem();
|
|
1549
|
+
selectedTab = signal(undefined);
|
|
1550
|
+
orientation = () => this.inputs.orientation();
|
|
1551
|
+
disabled = () => this.inputs.disabled();
|
|
1552
|
+
tabIndex = computed(() => this.focusBehavior.getListTabIndex());
|
|
1553
|
+
activeDescendant = computed(() => this.focusBehavior.getActiveDescendant());
|
|
1601
1554
|
followFocus = computed(() => this.inputs.selectionMode() === 'follow');
|
|
1602
1555
|
prevKey = computed(() => {
|
|
1603
1556
|
if (this.inputs.orientation() === 'vertical') {
|
|
@@ -1612,40 +1565,27 @@ class TabListPattern {
|
|
|
1612
1565
|
return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
|
|
1613
1566
|
});
|
|
1614
1567
|
keydown = computed(() => {
|
|
1615
|
-
return new KeyboardEventManager().on(this.prevKey, () => this.
|
|
1616
|
-
select: this.followFocus()
|
|
1617
|
-
})).on(this.nextKey, () => this.listBehavior.next({
|
|
1618
|
-
select: this.followFocus()
|
|
1619
|
-
})).on('Home', () => this.listBehavior.first({
|
|
1620
|
-
select: this.followFocus()
|
|
1621
|
-
})).on('End', () => this.listBehavior.last({
|
|
1622
|
-
select: this.followFocus()
|
|
1623
|
-
})).on(' ', () => this.listBehavior.select()).on('Enter', () => this.listBehavior.select());
|
|
1568
|
+
return new KeyboardEventManager().on(this.prevKey, () => this._navigate(() => this.navigationBehavior.prev(), this.followFocus())).on(this.nextKey, () => this._navigate(() => this.navigationBehavior.next(), this.followFocus())).on('Home', () => this._navigate(() => this.navigationBehavior.first(), this.followFocus())).on('End', () => this._navigate(() => this.navigationBehavior.last(), this.followFocus())).on(' ', () => this.open()).on('Enter', () => this.open());
|
|
1624
1569
|
});
|
|
1625
1570
|
pointerdown = computed(() => {
|
|
1626
|
-
return new PointerEventManager().on(e => this.
|
|
1627
|
-
select: true
|
|
1628
|
-
}));
|
|
1571
|
+
return new PointerEventManager().on(e => this._navigate(() => this.navigationBehavior.goto(this._getItem(e)), true));
|
|
1629
1572
|
});
|
|
1630
1573
|
constructor(inputs) {
|
|
1631
1574
|
this.inputs = inputs;
|
|
1632
|
-
this.
|
|
1633
|
-
this.
|
|
1634
|
-
this.listBehavior = new List({
|
|
1575
|
+
this.focusBehavior = new ListFocus(inputs);
|
|
1576
|
+
this.navigationBehavior = new ListNavigation({
|
|
1635
1577
|
...inputs,
|
|
1636
|
-
|
|
1637
|
-
typeaheadDelay: () => 0
|
|
1578
|
+
focusManager: this.focusBehavior
|
|
1638
1579
|
});
|
|
1639
|
-
this.
|
|
1580
|
+
this.expansionBehavior = new ListExpansion({
|
|
1640
1581
|
...inputs,
|
|
1641
|
-
multiExpandable: () => false
|
|
1642
|
-
expandedIds: this.inputs.value
|
|
1582
|
+
multiExpandable: () => false
|
|
1643
1583
|
});
|
|
1644
1584
|
}
|
|
1645
1585
|
setDefaultState() {
|
|
1646
1586
|
let firstItem;
|
|
1647
1587
|
for (const item of this.inputs.items()) {
|
|
1648
|
-
if (!this.
|
|
1588
|
+
if (!this.focusBehavior.isFocusable(item)) continue;
|
|
1649
1589
|
if (firstItem === undefined) {
|
|
1650
1590
|
firstItem = item;
|
|
1651
1591
|
}
|
|
@@ -1668,6 +1608,24 @@ class TabListPattern {
|
|
|
1668
1608
|
this.pointerdown().handle(event);
|
|
1669
1609
|
}
|
|
1670
1610
|
}
|
|
1611
|
+
open(tab) {
|
|
1612
|
+
tab ??= this.activeTab();
|
|
1613
|
+
if (typeof tab === 'string') {
|
|
1614
|
+
tab = this.inputs.items().find(t => t.value() === tab);
|
|
1615
|
+
}
|
|
1616
|
+
if (tab === undefined) return false;
|
|
1617
|
+
const success = this.expansionBehavior.open(tab);
|
|
1618
|
+
if (success) {
|
|
1619
|
+
this.selectedTab.set(tab);
|
|
1620
|
+
}
|
|
1621
|
+
return success;
|
|
1622
|
+
}
|
|
1623
|
+
_navigate(op, shouldExpand = false) {
|
|
1624
|
+
const success = op();
|
|
1625
|
+
if (success && shouldExpand) {
|
|
1626
|
+
this.open();
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1671
1629
|
_getItem(e) {
|
|
1672
1630
|
if (!(e.target instanceof HTMLElement)) {
|
|
1673
1631
|
return;
|
|
@@ -1677,67 +1635,15 @@ class TabListPattern {
|
|
|
1677
1635
|
}
|
|
1678
1636
|
}
|
|
1679
1637
|
|
|
1680
|
-
class ToolbarWidgetPattern {
|
|
1681
|
-
inputs;
|
|
1682
|
-
id;
|
|
1683
|
-
element;
|
|
1684
|
-
disabled;
|
|
1685
|
-
toolbar;
|
|
1686
|
-
tabindex = computed(() => this.toolbar().listBehavior.getItemTabindex(this));
|
|
1687
|
-
searchTerm = () => '';
|
|
1688
|
-
value = () => '';
|
|
1689
|
-
selectable = () => true;
|
|
1690
|
-
index = computed(() => this.toolbar().inputs.items().indexOf(this) ?? -1);
|
|
1691
|
-
active = computed(() => this.toolbar().inputs.activeItem() === this);
|
|
1692
|
-
constructor(inputs) {
|
|
1693
|
-
this.inputs = inputs;
|
|
1694
|
-
this.id = inputs.id;
|
|
1695
|
-
this.element = inputs.element;
|
|
1696
|
-
this.disabled = inputs.disabled;
|
|
1697
|
-
this.toolbar = inputs.toolbar;
|
|
1698
|
-
}
|
|
1699
|
-
}
|
|
1700
|
-
|
|
1701
|
-
class ToolbarWidgetGroupPattern {
|
|
1702
|
-
inputs;
|
|
1703
|
-
id;
|
|
1704
|
-
element;
|
|
1705
|
-
disabled;
|
|
1706
|
-
toolbar;
|
|
1707
|
-
searchTerm = () => '';
|
|
1708
|
-
value = () => '';
|
|
1709
|
-
selectable = () => true;
|
|
1710
|
-
index = computed(() => this.toolbar()?.inputs.items().indexOf(this) ?? -1);
|
|
1711
|
-
controls = computed(() => this.inputs.controls() ?? this._defaultControls);
|
|
1712
|
-
_defaultControls = {
|
|
1713
|
-
isOnFirstItem: () => true,
|
|
1714
|
-
isOnLastItem: () => true,
|
|
1715
|
-
next: () => {},
|
|
1716
|
-
prev: () => {},
|
|
1717
|
-
first: () => {},
|
|
1718
|
-
last: () => {},
|
|
1719
|
-
unfocus: () => {},
|
|
1720
|
-
trigger: () => {},
|
|
1721
|
-
goto: () => {},
|
|
1722
|
-
setDefaultState: () => {}
|
|
1723
|
-
};
|
|
1724
|
-
constructor(inputs) {
|
|
1725
|
-
this.inputs = inputs;
|
|
1726
|
-
this.id = inputs.id;
|
|
1727
|
-
this.element = inputs.element;
|
|
1728
|
-
this.disabled = inputs.disabled;
|
|
1729
|
-
this.toolbar = inputs.toolbar;
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
|
|
1733
1638
|
class ToolbarPattern {
|
|
1734
1639
|
inputs;
|
|
1735
1640
|
listBehavior;
|
|
1736
1641
|
orientation;
|
|
1737
|
-
|
|
1642
|
+
softDisabled;
|
|
1738
1643
|
disabled = computed(() => this.listBehavior.disabled());
|
|
1739
|
-
|
|
1740
|
-
|
|
1644
|
+
tabIndex = computed(() => this.listBehavior.tabIndex());
|
|
1645
|
+
activeDescendant = computed(() => this.listBehavior.activeDescendant());
|
|
1646
|
+
activeItem = () => this.listBehavior.inputs.activeItem();
|
|
1741
1647
|
_prevKey = computed(() => {
|
|
1742
1648
|
if (this.inputs.orientation() === 'vertical') {
|
|
1743
1649
|
return 'ArrowUp';
|
|
@@ -1764,95 +1670,56 @@ class ToolbarPattern {
|
|
|
1764
1670
|
});
|
|
1765
1671
|
_keydown = computed(() => {
|
|
1766
1672
|
const manager = new KeyboardEventManager();
|
|
1767
|
-
return manager.on(this._nextKey, () => this.
|
|
1673
|
+
return manager.on(this._nextKey, () => this.listBehavior.next()).on(this._prevKey, () => this.listBehavior.prev()).on(this._altNextKey, () => this._groupNext()).on(this._altPrevKey, () => this._groupPrev()).on(' ', () => this.select()).on('Enter', () => this.select()).on('Home', () => this.listBehavior.first()).on('End', () => this.listBehavior.last());
|
|
1768
1674
|
});
|
|
1769
|
-
_pointerdown = computed(() => new PointerEventManager().on(e => this._goto(e)));
|
|
1770
|
-
_next() {
|
|
1771
|
-
const item = this.inputs.activeItem();
|
|
1772
|
-
if (item instanceof ToolbarWidgetGroupPattern) {
|
|
1773
|
-
if (!item.disabled() && !item.controls().isOnLastItem()) {
|
|
1774
|
-
item.controls().next(false);
|
|
1775
|
-
return;
|
|
1776
|
-
}
|
|
1777
|
-
item.controls().unfocus();
|
|
1778
|
-
}
|
|
1779
|
-
this.listBehavior.next();
|
|
1780
|
-
const newItem = this.inputs.activeItem();
|
|
1781
|
-
if (newItem instanceof ToolbarWidgetGroupPattern) {
|
|
1782
|
-
newItem.controls().first();
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
_prev() {
|
|
1786
|
-
const item = this.inputs.activeItem();
|
|
1787
|
-
if (item instanceof ToolbarWidgetGroupPattern) {
|
|
1788
|
-
if (!item.disabled() && !item.controls().isOnFirstItem()) {
|
|
1789
|
-
item.controls().prev(false);
|
|
1790
|
-
return;
|
|
1791
|
-
}
|
|
1792
|
-
item.controls().unfocus();
|
|
1793
|
-
}
|
|
1794
|
-
this.listBehavior.prev();
|
|
1795
|
-
const newItem = this.inputs.activeItem();
|
|
1796
|
-
if (newItem instanceof ToolbarWidgetGroupPattern) {
|
|
1797
|
-
newItem.controls().last();
|
|
1798
|
-
}
|
|
1799
|
-
}
|
|
1800
1675
|
_groupNext() {
|
|
1801
|
-
const
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
_groupPrev() {
|
|
1806
|
-
const item = this.inputs.activeItem();
|
|
1807
|
-
if (item instanceof ToolbarWidgetPattern) return;
|
|
1808
|
-
item?.controls().prev(true);
|
|
1809
|
-
}
|
|
1810
|
-
_trigger() {
|
|
1811
|
-
const item = this.inputs.activeItem();
|
|
1812
|
-
if (item instanceof ToolbarWidgetGroupPattern) {
|
|
1813
|
-
item.controls().trigger();
|
|
1814
|
-
}
|
|
1815
|
-
}
|
|
1816
|
-
_first() {
|
|
1817
|
-
const item = this.inputs.activeItem();
|
|
1818
|
-
if (item instanceof ToolbarWidgetGroupPattern) {
|
|
1819
|
-
item.controls().unfocus();
|
|
1676
|
+
const currGroup = this.inputs.activeItem()?.group();
|
|
1677
|
+
const nextGroup = this.listBehavior.navigationBehavior.peekNext()?.group();
|
|
1678
|
+
if (!currGroup) {
|
|
1679
|
+
return;
|
|
1820
1680
|
}
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
newItem.controls().first();
|
|
1681
|
+
if (currGroup !== nextGroup) {
|
|
1682
|
+
this.listBehavior.goto(this.listBehavior.navigationBehavior.peekFirst(currGroup.inputs.items()));
|
|
1683
|
+
return;
|
|
1825
1684
|
}
|
|
1685
|
+
this.listBehavior.next();
|
|
1826
1686
|
}
|
|
1827
|
-
|
|
1828
|
-
const
|
|
1829
|
-
|
|
1830
|
-
|
|
1687
|
+
_groupPrev() {
|
|
1688
|
+
const currGroup = this.inputs.activeItem()?.group();
|
|
1689
|
+
const nextGroup = this.listBehavior.navigationBehavior.peekPrev()?.group();
|
|
1690
|
+
if (!currGroup) {
|
|
1691
|
+
return;
|
|
1831
1692
|
}
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
newItem.controls().last();
|
|
1693
|
+
if (currGroup !== nextGroup) {
|
|
1694
|
+
this.listBehavior.goto(this.listBehavior.navigationBehavior.peekLast(currGroup.inputs.items()));
|
|
1695
|
+
return;
|
|
1836
1696
|
}
|
|
1697
|
+
this.listBehavior.prev();
|
|
1837
1698
|
}
|
|
1838
1699
|
_goto(e) {
|
|
1839
1700
|
const item = this.inputs.getItem(e.target);
|
|
1840
|
-
if (
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
item.controls().goto(e);
|
|
1701
|
+
if (item) {
|
|
1702
|
+
this.listBehavior.goto(item);
|
|
1703
|
+
this.select();
|
|
1844
1704
|
}
|
|
1845
1705
|
}
|
|
1706
|
+
select() {
|
|
1707
|
+
const group = this.inputs.activeItem()?.group();
|
|
1708
|
+
if (!group?.multi()) {
|
|
1709
|
+
group?.inputs.items().forEach(i => this.listBehavior.deselect(i));
|
|
1710
|
+
}
|
|
1711
|
+
this.listBehavior.toggle();
|
|
1712
|
+
}
|
|
1846
1713
|
constructor(inputs) {
|
|
1847
1714
|
this.inputs = inputs;
|
|
1848
1715
|
this.orientation = inputs.orientation;
|
|
1849
|
-
this.
|
|
1716
|
+
this.softDisabled = inputs.softDisabled;
|
|
1850
1717
|
this.listBehavior = new List({
|
|
1851
1718
|
...inputs,
|
|
1852
|
-
multi: () =>
|
|
1719
|
+
multi: () => true,
|
|
1853
1720
|
focusMode: () => 'roving',
|
|
1854
1721
|
selectionMode: () => 'explicit',
|
|
1855
|
-
|
|
1722
|
+
values: signal([]),
|
|
1856
1723
|
typeaheadDelay: () => 0
|
|
1857
1724
|
});
|
|
1858
1725
|
}
|
|
@@ -1861,24 +1728,17 @@ class ToolbarPattern {
|
|
|
1861
1728
|
this._keydown().handle(event);
|
|
1862
1729
|
}
|
|
1863
1730
|
onPointerdown(event) {
|
|
1731
|
+
event.preventDefault();
|
|
1732
|
+
}
|
|
1733
|
+
onClick(event) {
|
|
1864
1734
|
if (this.disabled()) return;
|
|
1865
|
-
this.
|
|
1735
|
+
this._goto(event);
|
|
1866
1736
|
}
|
|
1867
1737
|
setDefaultState() {
|
|
1868
|
-
|
|
1869
|
-
for (const item of this.inputs.items()) {
|
|
1870
|
-
if (this.listBehavior.isFocusable(item)) {
|
|
1871
|
-
if (!firstItem) {
|
|
1872
|
-
firstItem = item;
|
|
1873
|
-
}
|
|
1874
|
-
}
|
|
1875
|
-
}
|
|
1738
|
+
const firstItem = this.listBehavior.navigationBehavior.peekFirst(this.inputs.items());
|
|
1876
1739
|
if (firstItem) {
|
|
1877
1740
|
this.inputs.activeItem.set(firstItem);
|
|
1878
1741
|
}
|
|
1879
|
-
if (firstItem instanceof ToolbarWidgetGroupPattern) {
|
|
1880
|
-
firstItem.controls().setDefaultState();
|
|
1881
|
-
}
|
|
1882
1742
|
}
|
|
1883
1743
|
validate() {
|
|
1884
1744
|
const violations = [];
|
|
@@ -1886,85 +1746,81 @@ class ToolbarPattern {
|
|
|
1886
1746
|
}
|
|
1887
1747
|
}
|
|
1888
1748
|
|
|
1749
|
+
class ToolbarWidgetPattern {
|
|
1750
|
+
inputs;
|
|
1751
|
+
id = () => this.inputs.id();
|
|
1752
|
+
element = () => this.inputs.element();
|
|
1753
|
+
disabled = () => this.inputs.disabled() || this.group()?.disabled() || false;
|
|
1754
|
+
group = () => this.inputs.group();
|
|
1755
|
+
toolbar = () => this.inputs.toolbar();
|
|
1756
|
+
tabIndex = computed(() => this.toolbar().listBehavior.getItemTabindex(this));
|
|
1757
|
+
searchTerm = () => '';
|
|
1758
|
+
value = () => this.inputs.value();
|
|
1759
|
+
selectable = () => true;
|
|
1760
|
+
index = computed(() => this.toolbar().inputs.items().indexOf(this) ?? -1);
|
|
1761
|
+
selected = computed(() => this.toolbar().listBehavior.inputs.values().includes(this.value()));
|
|
1762
|
+
active = computed(() => this.toolbar().activeItem() === this);
|
|
1763
|
+
constructor(inputs) {
|
|
1764
|
+
this.inputs = inputs;
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
class ToolbarWidgetGroupPattern {
|
|
1769
|
+
inputs;
|
|
1770
|
+
disabled = () => this.inputs.disabled();
|
|
1771
|
+
toolbar = () => this.inputs.toolbar();
|
|
1772
|
+
multi = () => this.inputs.multi();
|
|
1773
|
+
searchTerm = () => '';
|
|
1774
|
+
value = () => '';
|
|
1775
|
+
selectable = () => true;
|
|
1776
|
+
element = () => undefined;
|
|
1777
|
+
constructor(inputs) {
|
|
1778
|
+
this.inputs = inputs;
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1889
1782
|
const focusMode = () => 'roving';
|
|
1890
1783
|
class AccordionGroupPattern {
|
|
1891
1784
|
inputs;
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1785
|
+
navigationBehavior;
|
|
1786
|
+
focusBehavior;
|
|
1787
|
+
expansionBehavior;
|
|
1895
1788
|
constructor(inputs) {
|
|
1896
1789
|
this.inputs = inputs;
|
|
1897
|
-
this.
|
|
1898
|
-
this.orientation = inputs.orientation;
|
|
1899
|
-
this.textDirection = inputs.textDirection;
|
|
1900
|
-
this.activeItem = inputs.activeItem;
|
|
1901
|
-
this.disabled = inputs.disabled;
|
|
1902
|
-
this.multiExpandable = inputs.multiExpandable;
|
|
1903
|
-
this.items = inputs.items;
|
|
1904
|
-
this.expandedIds = inputs.expandedIds;
|
|
1905
|
-
this.skipDisabled = inputs.skipDisabled;
|
|
1906
|
-
this.focusManager = new ListFocus({
|
|
1790
|
+
this.focusBehavior = new ListFocus({
|
|
1907
1791
|
...inputs,
|
|
1908
1792
|
focusMode
|
|
1909
1793
|
});
|
|
1910
|
-
this.
|
|
1794
|
+
this.navigationBehavior = new ListNavigation({
|
|
1911
1795
|
...inputs,
|
|
1912
1796
|
focusMode,
|
|
1913
|
-
focusManager: this.
|
|
1797
|
+
focusManager: this.focusBehavior
|
|
1914
1798
|
});
|
|
1915
|
-
this.
|
|
1799
|
+
this.expansionBehavior = new ListExpansion({
|
|
1916
1800
|
...inputs
|
|
1917
1801
|
});
|
|
1918
1802
|
}
|
|
1919
|
-
}
|
|
1920
|
-
class AccordionTriggerPattern {
|
|
1921
|
-
inputs;
|
|
1922
|
-
expandable;
|
|
1923
|
-
expansionId;
|
|
1924
|
-
expanded;
|
|
1925
|
-
expansionControl;
|
|
1926
|
-
active = computed(() => this.inputs.accordionGroup().activeItem() === this);
|
|
1927
|
-
controls = computed(() => this.inputs.accordionPanel()?.id());
|
|
1928
|
-
tabindex = computed(() => this.inputs.accordionGroup().focusManager.isFocusable(this) ? 0 : -1);
|
|
1929
|
-
disabled = computed(() => this.inputs.disabled() || this.inputs.accordionGroup().disabled());
|
|
1930
|
-
index = computed(() => this.inputs.accordionGroup().items().indexOf(this));
|
|
1931
|
-
constructor(inputs) {
|
|
1932
|
-
this.inputs = inputs;
|
|
1933
|
-
this.id = inputs.id;
|
|
1934
|
-
this.element = inputs.element;
|
|
1935
|
-
this.value = inputs.value;
|
|
1936
|
-
this.expansionControl = new ExpansionControl({
|
|
1937
|
-
...inputs,
|
|
1938
|
-
expansionId: inputs.value,
|
|
1939
|
-
expandable: () => true,
|
|
1940
|
-
expansionManager: inputs.accordionGroup().expansionManager
|
|
1941
|
-
});
|
|
1942
|
-
this.expandable = this.expansionControl.isExpandable;
|
|
1943
|
-
this.expansionId = this.expansionControl.expansionId;
|
|
1944
|
-
this.expanded = this.expansionControl.isExpanded;
|
|
1945
|
-
}
|
|
1946
1803
|
prevKey = computed(() => {
|
|
1947
|
-
if (this.inputs.
|
|
1804
|
+
if (this.inputs.orientation() === 'vertical') {
|
|
1948
1805
|
return 'ArrowUp';
|
|
1949
1806
|
}
|
|
1950
|
-
return this.inputs.
|
|
1807
|
+
return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
|
|
1951
1808
|
});
|
|
1952
1809
|
nextKey = computed(() => {
|
|
1953
|
-
if (this.inputs.
|
|
1810
|
+
if (this.inputs.orientation() === 'vertical') {
|
|
1954
1811
|
return 'ArrowDown';
|
|
1955
1812
|
}
|
|
1956
|
-
return this.inputs.
|
|
1813
|
+
return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
|
|
1957
1814
|
});
|
|
1958
1815
|
keydown = computed(() => {
|
|
1959
|
-
return new KeyboardEventManager().on(this.prevKey, () => this.
|
|
1816
|
+
return new KeyboardEventManager().on(this.prevKey, () => this.navigationBehavior.prev()).on(this.nextKey, () => this.navigationBehavior.next()).on('Home', () => this.navigationBehavior.first()).on('End', () => this.navigationBehavior.last()).on(' ', () => this.toggle()).on('Enter', () => this.toggle());
|
|
1960
1817
|
});
|
|
1961
1818
|
pointerdown = computed(() => {
|
|
1962
1819
|
return new PointerEventManager().on(e => {
|
|
1963
|
-
const item = this.
|
|
1964
|
-
if (item)
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
}
|
|
1820
|
+
const item = this.inputs.getItem(e.target);
|
|
1821
|
+
if (!item) return;
|
|
1822
|
+
this.navigationBehavior.goto(item);
|
|
1823
|
+
this.expansionBehavior.toggle(item);
|
|
1968
1824
|
});
|
|
1969
1825
|
});
|
|
1970
1826
|
onKeydown(event) {
|
|
@@ -1974,26 +1830,51 @@ class AccordionTriggerPattern {
|
|
|
1974
1830
|
this.pointerdown().handle(event);
|
|
1975
1831
|
}
|
|
1976
1832
|
onFocus(event) {
|
|
1977
|
-
const item = this.
|
|
1978
|
-
if (item
|
|
1979
|
-
|
|
1980
|
-
|
|
1833
|
+
const item = this.inputs.getItem(event.target);
|
|
1834
|
+
if (!item) return;
|
|
1835
|
+
if (!this.focusBehavior.isFocusable(item)) return;
|
|
1836
|
+
this.focusBehavior.focus(item);
|
|
1981
1837
|
}
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1838
|
+
toggle() {
|
|
1839
|
+
const activeItem = this.inputs.activeItem();
|
|
1840
|
+
if (activeItem === undefined) return;
|
|
1841
|
+
this.expansionBehavior.toggle(activeItem);
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
class AccordionTriggerPattern {
|
|
1845
|
+
inputs;
|
|
1846
|
+
id = () => this.inputs.id();
|
|
1847
|
+
element = () => this.inputs.element();
|
|
1848
|
+
expandable = () => true;
|
|
1849
|
+
expanded;
|
|
1850
|
+
active = computed(() => this.inputs.accordionGroup().inputs.activeItem() === this);
|
|
1851
|
+
controls = computed(() => this.inputs.accordionPanel()?.inputs.id());
|
|
1852
|
+
tabIndex = computed(() => this.inputs.accordionGroup().focusBehavior.isFocusable(this) ? 0 : -1);
|
|
1853
|
+
disabled = computed(() => this.inputs.disabled() || this.inputs.accordionGroup().inputs.disabled());
|
|
1854
|
+
hardDisabled = computed(() => this.disabled() && !this.inputs.accordionGroup().inputs.softDisabled());
|
|
1855
|
+
index = computed(() => this.inputs.accordionGroup().inputs.items().indexOf(this));
|
|
1856
|
+
constructor(inputs) {
|
|
1857
|
+
this.inputs = inputs;
|
|
1858
|
+
this.expanded = inputs.expanded;
|
|
1859
|
+
}
|
|
1860
|
+
open() {
|
|
1861
|
+
this.inputs.accordionGroup().expansionBehavior.open(this);
|
|
1862
|
+
}
|
|
1863
|
+
close() {
|
|
1864
|
+
this.inputs.accordionGroup().expansionBehavior.close(this);
|
|
1865
|
+
}
|
|
1866
|
+
toggle() {
|
|
1867
|
+
this.inputs.accordionGroup().expansionBehavior.toggle(this);
|
|
1988
1868
|
}
|
|
1989
1869
|
}
|
|
1990
1870
|
class AccordionPanelPattern {
|
|
1991
1871
|
inputs;
|
|
1872
|
+
id;
|
|
1873
|
+
accordionTrigger;
|
|
1992
1874
|
hidden;
|
|
1993
1875
|
constructor(inputs) {
|
|
1994
1876
|
this.inputs = inputs;
|
|
1995
1877
|
this.id = inputs.id;
|
|
1996
|
-
this.value = inputs.value;
|
|
1997
1878
|
this.accordionTrigger = inputs.accordionTrigger;
|
|
1998
1879
|
this.hidden = computed(() => inputs.accordionTrigger()?.expanded() === false);
|
|
1999
1880
|
}
|
|
@@ -2001,27 +1882,25 @@ class AccordionPanelPattern {
|
|
|
2001
1882
|
|
|
2002
1883
|
class TreeItemPattern {
|
|
2003
1884
|
inputs;
|
|
2004
|
-
id;
|
|
2005
|
-
value;
|
|
2006
|
-
element;
|
|
2007
|
-
disabled;
|
|
2008
|
-
searchTerm;
|
|
2009
|
-
tree;
|
|
2010
|
-
parent;
|
|
2011
|
-
children;
|
|
1885
|
+
id = () => this.inputs.id();
|
|
1886
|
+
value = () => this.inputs.value();
|
|
1887
|
+
element = () => this.inputs.element();
|
|
1888
|
+
disabled = () => this.inputs.disabled();
|
|
1889
|
+
searchTerm = () => this.inputs.searchTerm();
|
|
1890
|
+
tree = () => this.inputs.tree();
|
|
1891
|
+
parent = () => this.inputs.parent();
|
|
1892
|
+
children = () => this.inputs.children();
|
|
2012
1893
|
index = computed(() => this.tree().visibleItems().indexOf(this));
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
selectable;
|
|
1894
|
+
expansionBehavior;
|
|
1895
|
+
expandable = () => this.inputs.hasChildren();
|
|
1896
|
+
selectable = () => this.inputs.selectable();
|
|
1897
|
+
expanded;
|
|
2018
1898
|
level = computed(() => this.parent().level() + 1);
|
|
2019
|
-
|
|
2020
|
-
visible = computed(() => this.parent().expanded());
|
|
1899
|
+
visible = computed(() => this.parent().expanded() && this.parent().visible());
|
|
2021
1900
|
setsize = computed(() => this.parent().children().length);
|
|
2022
1901
|
posinset = computed(() => this.parent().children().indexOf(this) + 1);
|
|
2023
1902
|
active = computed(() => this.tree().activeItem() === this);
|
|
2024
|
-
|
|
1903
|
+
tabIndex = computed(() => this.tree().listBehavior.getItemTabindex(this));
|
|
2025
1904
|
selected = computed(() => {
|
|
2026
1905
|
if (this.tree().nav()) {
|
|
2027
1906
|
return undefined;
|
|
@@ -2029,7 +1908,7 @@ class TreeItemPattern {
|
|
|
2029
1908
|
if (!this.selectable()) {
|
|
2030
1909
|
return undefined;
|
|
2031
1910
|
}
|
|
2032
|
-
return this.tree().
|
|
1911
|
+
return this.tree().values().includes(this.value());
|
|
2033
1912
|
});
|
|
2034
1913
|
current = computed(() => {
|
|
2035
1914
|
if (!this.tree().nav()) {
|
|
@@ -2038,31 +1917,14 @@ class TreeItemPattern {
|
|
|
2038
1917
|
if (!this.selectable()) {
|
|
2039
1918
|
return undefined;
|
|
2040
1919
|
}
|
|
2041
|
-
return this.tree().
|
|
1920
|
+
return this.tree().values().includes(this.value()) ? this.tree().currentType() : undefined;
|
|
2042
1921
|
});
|
|
2043
1922
|
constructor(inputs) {
|
|
2044
1923
|
this.inputs = inputs;
|
|
2045
|
-
this.
|
|
2046
|
-
this.
|
|
2047
|
-
this.element = inputs.element;
|
|
2048
|
-
this.disabled = inputs.disabled;
|
|
2049
|
-
this.searchTerm = inputs.searchTerm;
|
|
2050
|
-
this.expansionId = inputs.id;
|
|
2051
|
-
this.tree = inputs.tree;
|
|
2052
|
-
this.parent = inputs.parent;
|
|
2053
|
-
this.children = inputs.children;
|
|
2054
|
-
this.expandable = inputs.hasChildren;
|
|
2055
|
-
this.selectable = inputs.selectable;
|
|
2056
|
-
this.expansion = new ExpansionControl({
|
|
2057
|
-
...inputs,
|
|
2058
|
-
expandable: this.expandable,
|
|
2059
|
-
expansionId: this.expansionId,
|
|
2060
|
-
expansionManager: this.parent().expansionManager
|
|
2061
|
-
});
|
|
2062
|
-
this.expansionManager = new ListExpansion({
|
|
1924
|
+
this.expanded = inputs.expanded;
|
|
1925
|
+
this.expansionBehavior = new ListExpansion({
|
|
2063
1926
|
...inputs,
|
|
2064
1927
|
multiExpandable: () => true,
|
|
2065
|
-
expandedIds: signal([]),
|
|
2066
1928
|
items: this.children,
|
|
2067
1929
|
disabled: computed(() => this.tree()?.disabled() ?? false)
|
|
2068
1930
|
});
|
|
@@ -2071,37 +1933,39 @@ class TreeItemPattern {
|
|
|
2071
1933
|
class TreePattern {
|
|
2072
1934
|
inputs;
|
|
2073
1935
|
listBehavior;
|
|
2074
|
-
|
|
1936
|
+
expansionBehavior;
|
|
2075
1937
|
level = () => 0;
|
|
2076
1938
|
expanded = () => true;
|
|
2077
|
-
|
|
2078
|
-
|
|
1939
|
+
visible = () => true;
|
|
1940
|
+
tabIndex = computed(() => this.listBehavior.tabIndex());
|
|
1941
|
+
activeDescendant = computed(() => this.listBehavior.activeDescendant());
|
|
2079
1942
|
children = computed(() => this.inputs.allItems().filter(item => item.level() === this.level() + 1));
|
|
2080
1943
|
visibleItems = computed(() => this.inputs.allItems().filter(item => item.visible()));
|
|
2081
1944
|
followFocus = computed(() => this.inputs.selectionMode() === 'follow');
|
|
1945
|
+
isRtl = computed(() => this.inputs.textDirection() === 'rtl');
|
|
2082
1946
|
prevKey = computed(() => {
|
|
2083
1947
|
if (this.inputs.orientation() === 'vertical') {
|
|
2084
1948
|
return 'ArrowUp';
|
|
2085
1949
|
}
|
|
2086
|
-
return this.
|
|
1950
|
+
return this.isRtl() ? 'ArrowRight' : 'ArrowLeft';
|
|
2087
1951
|
});
|
|
2088
1952
|
nextKey = computed(() => {
|
|
2089
1953
|
if (this.inputs.orientation() === 'vertical') {
|
|
2090
1954
|
return 'ArrowDown';
|
|
2091
1955
|
}
|
|
2092
|
-
return this.
|
|
1956
|
+
return this.isRtl() ? 'ArrowLeft' : 'ArrowRight';
|
|
2093
1957
|
});
|
|
2094
1958
|
collapseKey = computed(() => {
|
|
2095
1959
|
if (this.inputs.orientation() === 'horizontal') {
|
|
2096
1960
|
return 'ArrowUp';
|
|
2097
1961
|
}
|
|
2098
|
-
return this.
|
|
1962
|
+
return this.isRtl() ? 'ArrowRight' : 'ArrowLeft';
|
|
2099
1963
|
});
|
|
2100
1964
|
expandKey = computed(() => {
|
|
2101
1965
|
if (this.inputs.orientation() === 'horizontal') {
|
|
2102
1966
|
return 'ArrowDown';
|
|
2103
1967
|
}
|
|
2104
|
-
return this.
|
|
1968
|
+
return this.isRtl() ? 'ArrowLeft' : 'ArrowRight';
|
|
2105
1969
|
});
|
|
2106
1970
|
dynamicSpaceKey = computed(() => this.listBehavior.isTyping() ? '' : ' ');
|
|
2107
1971
|
typeaheadRegexp = /^.$/;
|
|
@@ -2143,11 +2007,15 @@ class TreePattern {
|
|
|
2143
2007
|
}));
|
|
2144
2008
|
}
|
|
2145
2009
|
if (!this.followFocus() && this.inputs.multi()) {
|
|
2146
|
-
manager.on(this.dynamicSpaceKey, () => list.toggle()).on('Enter', () => list.toggle()
|
|
2010
|
+
manager.on(this.dynamicSpaceKey, () => list.toggle()).on('Enter', () => list.toggle(), {
|
|
2011
|
+
preventDefault: !this.nav()
|
|
2012
|
+
}).on([Modifier.Ctrl, Modifier.Meta], 'A', () => list.toggleAll());
|
|
2147
2013
|
}
|
|
2148
2014
|
if (!this.followFocus() && !this.inputs.multi()) {
|
|
2149
2015
|
manager.on(this.dynamicSpaceKey, () => list.selectOne());
|
|
2150
|
-
manager.on('Enter', () => list.selectOne()
|
|
2016
|
+
manager.on('Enter', () => list.selectOne(), {
|
|
2017
|
+
preventDefault: !this.nav()
|
|
2018
|
+
});
|
|
2151
2019
|
}
|
|
2152
2020
|
if (this.inputs.multi() && this.followFocus()) {
|
|
2153
2021
|
manager.on([Modifier.Ctrl, Modifier.Meta], this.prevKey, () => list.prev()).on([Modifier.Ctrl, Modifier.Meta], this.nextKey, () => list.next()).on([Modifier.Ctrl, Modifier.Meta], this.expandKey, () => this.expand()).on([Modifier.Ctrl, Modifier.Meta], this.collapseKey, () => this.collapse()).on([Modifier.Ctrl, Modifier.Meta], ' ', () => list.toggle()).on([Modifier.Ctrl, Modifier.Meta], 'Enter', () => list.toggle()).on([Modifier.Ctrl, Modifier.Meta], 'Home', () => list.first()).on([Modifier.Ctrl, Modifier.Meta], 'End', () => list.last()).on([Modifier.Ctrl, Modifier.Meta], 'A', () => {
|
|
@@ -2183,45 +2051,33 @@ class TreePattern {
|
|
|
2183
2051
|
}
|
|
2184
2052
|
return manager;
|
|
2185
2053
|
});
|
|
2186
|
-
id;
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2054
|
+
id = () => this.inputs.id();
|
|
2055
|
+
element = () => this.inputs.element();
|
|
2056
|
+
nav = () => this.inputs.nav();
|
|
2057
|
+
currentType = () => this.inputs.currentType();
|
|
2058
|
+
allItems = () => this.inputs.allItems();
|
|
2059
|
+
focusMode = () => this.inputs.focusMode();
|
|
2060
|
+
disabled = () => this.inputs.disabled();
|
|
2061
|
+
activeItem;
|
|
2062
|
+
softDisabled = () => this.inputs.softDisabled();
|
|
2063
|
+
wrap = () => this.inputs.wrap();
|
|
2064
|
+
orientation = () => this.inputs.orientation();
|
|
2065
|
+
textDirection = () => this.textDirection();
|
|
2066
|
+
multi = computed(() => this.nav() ? false : this.inputs.multi());
|
|
2067
|
+
selectionMode = () => this.inputs.selectionMode();
|
|
2068
|
+
typeaheadDelay = () => this.inputs.typeaheadDelay();
|
|
2069
|
+
values;
|
|
2200
2070
|
constructor(inputs) {
|
|
2201
2071
|
this.inputs = inputs;
|
|
2202
|
-
this.id = inputs.id;
|
|
2203
|
-
this.nav = inputs.nav;
|
|
2204
|
-
this.currentType = inputs.currentType;
|
|
2205
|
-
this.allItems = inputs.allItems;
|
|
2206
|
-
this.focusMode = inputs.focusMode;
|
|
2207
|
-
this.disabled = inputs.disabled;
|
|
2208
2072
|
this.activeItem = inputs.activeItem;
|
|
2209
|
-
this.
|
|
2210
|
-
this.wrap = inputs.wrap;
|
|
2211
|
-
this.orientation = inputs.orientation;
|
|
2212
|
-
this.textDirection = inputs.textDirection;
|
|
2213
|
-
this.multi = computed(() => this.nav() ? false : this.inputs.multi());
|
|
2214
|
-
this.selectionMode = inputs.selectionMode;
|
|
2215
|
-
this.typeaheadDelay = inputs.typeaheadDelay;
|
|
2216
|
-
this.value = inputs.value;
|
|
2073
|
+
this.values = inputs.values;
|
|
2217
2074
|
this.listBehavior = new List({
|
|
2218
2075
|
...inputs,
|
|
2219
2076
|
items: this.visibleItems,
|
|
2220
2077
|
multi: this.multi
|
|
2221
2078
|
});
|
|
2222
|
-
this.
|
|
2079
|
+
this.expansionBehavior = new ListExpansion({
|
|
2223
2080
|
multiExpandable: () => true,
|
|
2224
|
-
expandedIds: signal([]),
|
|
2225
2081
|
items: this.children,
|
|
2226
2082
|
disabled: this.disabled
|
|
2227
2083
|
});
|
|
@@ -2266,14 +2122,14 @@ class TreePattern {
|
|
|
2266
2122
|
if (item.expanded()) {
|
|
2267
2123
|
this.collapse();
|
|
2268
2124
|
} else {
|
|
2269
|
-
|
|
2125
|
+
this.expansionBehavior.open(item);
|
|
2270
2126
|
}
|
|
2271
2127
|
}
|
|
2272
2128
|
expand(opts) {
|
|
2273
2129
|
const item = this.activeItem();
|
|
2274
2130
|
if (!item || !this.listBehavior.isFocusable(item)) return;
|
|
2275
2131
|
if (item.expandable() && !item.expanded()) {
|
|
2276
|
-
|
|
2132
|
+
this.expansionBehavior.open(item);
|
|
2277
2133
|
} else if (item.expanded() && item.children().some(item => this.listBehavior.isFocusable(item))) {
|
|
2278
2134
|
this.listBehavior.next(opts);
|
|
2279
2135
|
}
|
|
@@ -2281,13 +2137,13 @@ class TreePattern {
|
|
|
2281
2137
|
expandSiblings(item) {
|
|
2282
2138
|
item ??= this.activeItem();
|
|
2283
2139
|
const siblings = item?.parent()?.children();
|
|
2284
|
-
siblings?.forEach(item =>
|
|
2140
|
+
siblings?.forEach(item => this.expansionBehavior.open(item));
|
|
2285
2141
|
}
|
|
2286
2142
|
collapse(opts) {
|
|
2287
2143
|
const item = this.activeItem();
|
|
2288
2144
|
if (!item || !this.listBehavior.isFocusable(item)) return;
|
|
2289
2145
|
if (item.expandable() && item.expanded()) {
|
|
2290
|
-
|
|
2146
|
+
this.expansionBehavior.close(item);
|
|
2291
2147
|
} else if (item.parent() && item.parent() !== this) {
|
|
2292
2148
|
const parentItem = item.parent();
|
|
2293
2149
|
if (parentItem instanceof TreeItemPattern && this.listBehavior.isFocusable(parentItem)) {
|
|
@@ -2308,9 +2164,10 @@ class ComboboxTreePattern extends TreePattern {
|
|
|
2308
2164
|
inputs;
|
|
2309
2165
|
isItemCollapsible = () => this.inputs.activeItem()?.parent() instanceof TreeItemPattern;
|
|
2310
2166
|
role = () => 'tree';
|
|
2311
|
-
activeId = computed(() => this.listBehavior.
|
|
2167
|
+
activeId = computed(() => this.listBehavior.activeDescendant());
|
|
2168
|
+
getActiveItem = () => this.inputs.activeItem();
|
|
2312
2169
|
items = computed(() => this.inputs.allItems());
|
|
2313
|
-
|
|
2170
|
+
tabIndex = () => -1;
|
|
2314
2171
|
constructor(inputs) {
|
|
2315
2172
|
if (inputs.combobox()) {
|
|
2316
2173
|
inputs.multi = () => false;
|
|
@@ -2330,18 +2187,128 @@ class ComboboxTreePattern extends TreePattern {
|
|
|
2330
2187
|
first = () => this.listBehavior.first();
|
|
2331
2188
|
unfocus = () => this.listBehavior.unfocus();
|
|
2332
2189
|
select = item => this.listBehavior.select(item);
|
|
2190
|
+
toggle = item => this.listBehavior.toggle(item);
|
|
2333
2191
|
clearSelection = () => this.listBehavior.deselectAll();
|
|
2334
2192
|
getItem = e => this._getItem(e);
|
|
2335
|
-
|
|
2336
|
-
setValue = value => this.inputs.
|
|
2193
|
+
getSelectedItems = () => this.inputs.allItems().filter(item => item.selected());
|
|
2194
|
+
setValue = value => this.inputs.values.set(value ? [value] : []);
|
|
2337
2195
|
expandItem = () => this.expand();
|
|
2338
2196
|
collapseItem = () => this.collapse();
|
|
2339
2197
|
isItemExpandable(item = this.inputs.activeItem()) {
|
|
2340
2198
|
return item ? item.expandable() : false;
|
|
2341
2199
|
}
|
|
2342
|
-
expandAll = () => this.items().forEach(item =>
|
|
2343
|
-
collapseAll = () => this.items().forEach(item => item.
|
|
2200
|
+
expandAll = () => this.items().forEach(item => this.expansionBehavior.open(item));
|
|
2201
|
+
collapseAll = () => this.items().forEach(item => item.expansionBehavior.close(item));
|
|
2202
|
+
isItemSelectable = (item = this.inputs.activeItem()) => {
|
|
2203
|
+
return item ? item.selectable() : false;
|
|
2204
|
+
};
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
class DeferredContentAware {
|
|
2208
|
+
contentVisible = signal(false, ...(ngDevMode ? [{
|
|
2209
|
+
debugName: "contentVisible"
|
|
2210
|
+
}] : []));
|
|
2211
|
+
preserveContent = model(false, ...(ngDevMode ? [{
|
|
2212
|
+
debugName: "preserveContent"
|
|
2213
|
+
}] : []));
|
|
2214
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
2215
|
+
minVersion: "12.0.0",
|
|
2216
|
+
version: "20.2.0-next.2",
|
|
2217
|
+
ngImport: i0,
|
|
2218
|
+
type: DeferredContentAware,
|
|
2219
|
+
deps: [],
|
|
2220
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
2221
|
+
});
|
|
2222
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
2223
|
+
minVersion: "17.1.0",
|
|
2224
|
+
version: "20.2.0-next.2",
|
|
2225
|
+
type: DeferredContentAware,
|
|
2226
|
+
isStandalone: true,
|
|
2227
|
+
inputs: {
|
|
2228
|
+
preserveContent: {
|
|
2229
|
+
classPropertyName: "preserveContent",
|
|
2230
|
+
publicName: "preserveContent",
|
|
2231
|
+
isSignal: true,
|
|
2232
|
+
isRequired: false,
|
|
2233
|
+
transformFunction: null
|
|
2234
|
+
}
|
|
2235
|
+
},
|
|
2236
|
+
outputs: {
|
|
2237
|
+
preserveContent: "preserveContentChange"
|
|
2238
|
+
},
|
|
2239
|
+
ngImport: i0
|
|
2240
|
+
});
|
|
2241
|
+
}
|
|
2242
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
2243
|
+
minVersion: "12.0.0",
|
|
2244
|
+
version: "20.2.0-next.2",
|
|
2245
|
+
ngImport: i0,
|
|
2246
|
+
type: DeferredContentAware,
|
|
2247
|
+
decorators: [{
|
|
2248
|
+
type: Directive
|
|
2249
|
+
}]
|
|
2250
|
+
});
|
|
2251
|
+
class DeferredContent {
|
|
2252
|
+
_deferredContentAware = inject(DeferredContentAware, {
|
|
2253
|
+
optional: true
|
|
2254
|
+
});
|
|
2255
|
+
_templateRef = inject(TemplateRef);
|
|
2256
|
+
_viewContainerRef = inject(ViewContainerRef);
|
|
2257
|
+
_currentViewRef = null;
|
|
2258
|
+
_isRendered = false;
|
|
2259
|
+
deferredContentAware = signal(this._deferredContentAware, ...(ngDevMode ? [{
|
|
2260
|
+
debugName: "deferredContentAware"
|
|
2261
|
+
}] : []));
|
|
2262
|
+
constructor() {
|
|
2263
|
+
afterRenderEffect(() => {
|
|
2264
|
+
if (this.deferredContentAware()?.contentVisible()) {
|
|
2265
|
+
if (!this._isRendered) {
|
|
2266
|
+
this._destroyContent();
|
|
2267
|
+
this._currentViewRef = this._viewContainerRef.createEmbeddedView(this._templateRef);
|
|
2268
|
+
this._isRendered = true;
|
|
2269
|
+
}
|
|
2270
|
+
} else if (!this.deferredContentAware()?.preserveContent()) {
|
|
2271
|
+
this._destroyContent();
|
|
2272
|
+
this._isRendered = false;
|
|
2273
|
+
}
|
|
2274
|
+
});
|
|
2275
|
+
}
|
|
2276
|
+
ngOnDestroy() {
|
|
2277
|
+
this._destroyContent();
|
|
2278
|
+
}
|
|
2279
|
+
_destroyContent() {
|
|
2280
|
+
const ref = this._currentViewRef;
|
|
2281
|
+
if (ref && !ref.destroyed) {
|
|
2282
|
+
ref.destroy();
|
|
2283
|
+
this._currentViewRef = null;
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
2287
|
+
minVersion: "12.0.0",
|
|
2288
|
+
version: "20.2.0-next.2",
|
|
2289
|
+
ngImport: i0,
|
|
2290
|
+
type: DeferredContent,
|
|
2291
|
+
deps: [],
|
|
2292
|
+
target: i0.ɵɵFactoryTarget.Directive
|
|
2293
|
+
});
|
|
2294
|
+
static ɵdir = i0.ɵɵngDeclareDirective({
|
|
2295
|
+
minVersion: "14.0.0",
|
|
2296
|
+
version: "20.2.0-next.2",
|
|
2297
|
+
type: DeferredContent,
|
|
2298
|
+
isStandalone: true,
|
|
2299
|
+
ngImport: i0
|
|
2300
|
+
});
|
|
2344
2301
|
}
|
|
2302
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
2303
|
+
minVersion: "12.0.0",
|
|
2304
|
+
version: "20.2.0-next.2",
|
|
2305
|
+
ngImport: i0,
|
|
2306
|
+
type: DeferredContent,
|
|
2307
|
+
decorators: [{
|
|
2308
|
+
type: Directive
|
|
2309
|
+
}],
|
|
2310
|
+
ctorParameters: () => []
|
|
2311
|
+
});
|
|
2345
2312
|
|
|
2346
|
-
export { AccordionGroupPattern, AccordionPanelPattern, AccordionTriggerPattern, ComboboxListboxPattern, ComboboxPattern, ComboboxTreePattern, ListboxPattern, MenuBarPattern, MenuItemPattern, MenuPattern, MenuTriggerPattern, OptionPattern,
|
|
2313
|
+
export { AccordionGroupPattern, AccordionPanelPattern, AccordionTriggerPattern, ComboboxDialogPattern, ComboboxListboxPattern, ComboboxPattern, ComboboxTreePattern, DeferredContent, DeferredContentAware, ListboxPattern, MenuBarPattern, MenuItemPattern, MenuPattern, MenuTriggerPattern, OptionPattern, TabListPattern, TabPanelPattern, TabPattern, ToolbarPattern, ToolbarWidgetGroupPattern, ToolbarWidgetPattern, TreeItemPattern, TreePattern, convertGetterSetterToWritableSignalLike };
|
|
2347
2314
|
//# sourceMappingURL=private.mjs.map
|