@angular/aria 21.0.0-rc.1 → 21.0.0-rc.3
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 +429 -59
- package/_adev_assets/aria-combobox.json +261 -41
- package/_adev_assets/aria-grid.json +339 -85
- package/_adev_assets/aria-listbox.json +99 -70
- package/_adev_assets/aria-menu.json +355 -158
- package/_adev_assets/aria-tabs.json +198 -305
- package/_adev_assets/aria-toolbar.json +70 -221
- package/_adev_assets/aria-tree.json +153 -363
- package/fesm2022/_widget-chunk.mjs +388 -57
- package/fesm2022/_widget-chunk.mjs.map +1 -1
- package/fesm2022/accordion.mjs +125 -72
- package/fesm2022/accordion.mjs.map +1 -1
- package/fesm2022/aria.mjs +1 -1
- package/fesm2022/aria.mjs.map +1 -1
- package/fesm2022/combobox.mjs +129 -24
- package/fesm2022/combobox.mjs.map +1 -1
- package/fesm2022/grid.mjs +203 -65
- package/fesm2022/grid.mjs.map +1 -1
- package/fesm2022/listbox.mjs +50 -39
- package/fesm2022/listbox.mjs.map +1 -1
- package/fesm2022/menu.mjs +179 -71
- package/fesm2022/menu.mjs.map +1 -1
- package/fesm2022/private.mjs +418 -440
- package/fesm2022/private.mjs.map +1 -1
- package/fesm2022/tabs.mjs +105 -73
- package/fesm2022/tabs.mjs.map +1 -1
- package/fesm2022/toolbar.mjs +52 -44
- package/fesm2022/toolbar.mjs.map +1 -1
- package/fesm2022/tree.mjs +106 -63
- package/fesm2022/tree.mjs.map +1 -1
- package/package.json +2 -2
- package/types/_grid-chunk.d.ts +216 -35
- package/types/accordion.d.ts +134 -35
- package/types/combobox.d.ts +141 -12
- package/types/grid.d.ts +150 -32
- package/types/listbox.d.ts +60 -28
- package/types/menu.d.ts +133 -49
- package/types/private.d.ts +210 -250
- package/types/tabs.d.ts +124 -44
- package/types/toolbar.d.ts +58 -36
- package/types/tree.d.ts +121 -49
package/fesm2022/private.mjs
CHANGED
|
@@ -1,29 +1,68 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { signal, computed, model, Directive, inject, TemplateRef, ViewContainerRef, afterRenderEffect } from '@angular/core';
|
|
3
|
-
import { KeyboardEventManager,
|
|
3
|
+
import { PointerEventManager, KeyboardEventManager, ListFocus, ListNavigation, Modifier } from './_widget-chunk.mjs';
|
|
4
4
|
export { GridCellPattern, GridCellWidgetPattern, GridPattern, GridRowPattern } from './_widget-chunk.mjs';
|
|
5
5
|
|
|
6
6
|
class ComboboxPattern {
|
|
7
7
|
inputs;
|
|
8
8
|
expanded = signal(false);
|
|
9
|
-
|
|
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
|
+
});
|
|
10
17
|
highlightedItem = signal(undefined);
|
|
11
18
|
isDeleting = false;
|
|
12
19
|
isFocused = signal(false);
|
|
20
|
+
hasBeenFocused = signal(false);
|
|
13
21
|
expandKey = computed(() => this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight');
|
|
14
22
|
collapseKey = computed(() => this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft');
|
|
15
23
|
popupId = computed(() => this.inputs.popupControls()?.id() || null);
|
|
16
24
|
autocomplete = computed(() => this.inputs.filterMode() === 'highlight' ? 'both' : 'list');
|
|
17
25
|
hasPopup = computed(() => this.inputs.popupControls()?.role() || null);
|
|
18
|
-
readonly = computed(() => this.inputs.readonly() || null);
|
|
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
|
+
};
|
|
19
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
|
+
}
|
|
20
61
|
if (!this.expanded()) {
|
|
21
|
-
|
|
62
|
+
manager.on('ArrowDown', () => this.open({
|
|
22
63
|
first: true
|
|
23
64
|
})).on('ArrowUp', () => this.open({
|
|
24
65
|
last: true
|
|
25
|
-
})).on('Escape', () => this.close({
|
|
26
|
-
reset: !this.readonly()
|
|
27
66
|
}));
|
|
28
67
|
if (this.readonly()) {
|
|
29
68
|
manager.on('Enter', () => this.open({
|
|
@@ -34,13 +73,7 @@ class ComboboxPattern {
|
|
|
34
73
|
}
|
|
35
74
|
return manager;
|
|
36
75
|
}
|
|
37
|
-
|
|
38
|
-
if (!popupControls) {
|
|
39
|
-
return new KeyboardEventManager();
|
|
40
|
-
}
|
|
41
|
-
const manager = new KeyboardEventManager().on('ArrowDown', () => this.next()).on('ArrowUp', () => this.prev()).on('Home', () => this.first()).on('End', () => this.last()).on('Escape', () => this.close({
|
|
42
|
-
reset: !this.readonly()
|
|
43
|
-
}));
|
|
76
|
+
manager.on('ArrowDown', () => this.next()).on('ArrowUp', () => this.prev()).on('Home', () => this.first()).on('End', () => this.last());
|
|
44
77
|
if (this.readonly()) {
|
|
45
78
|
manager.on(' ', () => this.select({
|
|
46
79
|
commit: true,
|
|
@@ -48,35 +81,47 @@ class ComboboxPattern {
|
|
|
48
81
|
}));
|
|
49
82
|
}
|
|
50
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()) {
|
|
51
93
|
manager.on('Enter', () => this.select({
|
|
52
94
|
commit: true,
|
|
53
|
-
close:
|
|
95
|
+
close: true
|
|
54
96
|
}));
|
|
55
97
|
}
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
if (treeControls.isItemSelectable()) {
|
|
59
|
-
manager.on('Enter', () => this.select({
|
|
60
|
-
commit: true,
|
|
61
|
-
close: true
|
|
62
|
-
}));
|
|
63
|
-
} else if (treeControls.isItemExpandable()) {
|
|
98
|
+
if (treeControls?.isItemExpandable()) {
|
|
99
|
+
manager.on(this.expandKey(), () => this.expandItem()).on(this.collapseKey(), () => this.collapseItem());
|
|
100
|
+
if (!treeControls.isItemSelectable()) {
|
|
64
101
|
manager.on('Enter', () => this.expandItem());
|
|
65
102
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
if (treeControls.isItemExpandable()) {
|
|
70
|
-
manager.on(this.expandKey(), () => this.expandItem());
|
|
71
|
-
}
|
|
103
|
+
}
|
|
104
|
+
if (treeControls?.isItemCollapsible()) {
|
|
105
|
+
manager.on(this.collapseKey(), () => this.collapseItem());
|
|
72
106
|
}
|
|
73
107
|
return manager;
|
|
74
108
|
});
|
|
75
|
-
|
|
76
|
-
|
|
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);
|
|
77
122
|
if (item) {
|
|
78
|
-
if (
|
|
79
|
-
const treeControls =
|
|
123
|
+
if (controls?.role() === 'tree') {
|
|
124
|
+
const treeControls = controls;
|
|
80
125
|
if (treeControls.isItemExpandable(item) && !treeControls.isItemSelectable(item)) {
|
|
81
126
|
treeControls.toggleExpansion(item);
|
|
82
127
|
this.inputs.inputEl()?.focus();
|
|
@@ -86,17 +131,10 @@ class ComboboxPattern {
|
|
|
86
131
|
this.select({
|
|
87
132
|
item,
|
|
88
133
|
commit: true,
|
|
89
|
-
close: !
|
|
134
|
+
close: !controls?.multi()
|
|
90
135
|
});
|
|
91
136
|
this.inputs.inputEl()?.focus();
|
|
92
137
|
}
|
|
93
|
-
if (e.target === this.inputs.inputEl()) {
|
|
94
|
-
if (this.readonly()) {
|
|
95
|
-
this.expanded() ? this.close() : this.open({
|
|
96
|
-
selected: true
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
138
|
}));
|
|
101
139
|
constructor(inputs) {
|
|
102
140
|
this.inputs = inputs;
|
|
@@ -106,9 +144,9 @@ class ComboboxPattern {
|
|
|
106
144
|
this.keydown().handle(event);
|
|
107
145
|
}
|
|
108
146
|
}
|
|
109
|
-
|
|
147
|
+
onClick(event) {
|
|
110
148
|
if (!this.inputs.disabled()) {
|
|
111
|
-
this.
|
|
149
|
+
this.click().handle(event);
|
|
112
150
|
}
|
|
113
151
|
}
|
|
114
152
|
onInput(event) {
|
|
@@ -119,27 +157,33 @@ class ComboboxPattern {
|
|
|
119
157
|
if (!inputEl) {
|
|
120
158
|
return;
|
|
121
159
|
}
|
|
160
|
+
const popupControls = this.inputs.popupControls();
|
|
161
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
122
164
|
this.open();
|
|
123
165
|
this.inputs.inputValue?.set(inputEl.value);
|
|
124
166
|
this.isDeleting = event instanceof InputEvent && !!event.inputType.match(/^delete/);
|
|
125
|
-
if (this.inputs.filterMode() === 'manual') {
|
|
126
|
-
const selectedItems = this.inputs.popupControls()?.getSelectedItems();
|
|
127
|
-
const searchTerm = selectedItems?.[0]?.searchTerm();
|
|
128
|
-
if (searchTerm && this.inputs.inputValue() !== searchTerm) {
|
|
129
|
-
this.inputs.popupControls()?.clearSelection();
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
167
|
if (this.inputs.filterMode() === 'highlight' && !this.isDeleting) {
|
|
133
168
|
this.highlight();
|
|
134
169
|
}
|
|
135
170
|
}
|
|
136
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
|
+
}
|
|
137
176
|
this.isFocused.set(true);
|
|
177
|
+
this.hasBeenFocused.set(true);
|
|
138
178
|
}
|
|
139
179
|
onFocusOut(event) {
|
|
140
180
|
if (this.inputs.disabled()) {
|
|
141
181
|
return;
|
|
142
182
|
}
|
|
183
|
+
const popupControls = this.inputs.popupControls();
|
|
184
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
143
187
|
if (!(event.relatedTarget instanceof HTMLElement) || !this.inputs.containerEl()?.contains(event.relatedTarget)) {
|
|
144
188
|
this.isFocused.set(false);
|
|
145
189
|
if (this.readonly()) {
|
|
@@ -149,7 +193,7 @@ class ComboboxPattern {
|
|
|
149
193
|
if (this.inputs.filterMode() !== 'manual') {
|
|
150
194
|
this.commit();
|
|
151
195
|
} else {
|
|
152
|
-
const item =
|
|
196
|
+
const item = popupControls?.items().find(i => i.searchTerm() === this.inputs.inputEl()?.value);
|
|
153
197
|
if (item) {
|
|
154
198
|
this.select({
|
|
155
199
|
item
|
|
@@ -160,15 +204,19 @@ class ComboboxPattern {
|
|
|
160
204
|
}
|
|
161
205
|
}
|
|
162
206
|
firstMatch = computed(() => {
|
|
163
|
-
if (this.
|
|
164
|
-
return this.
|
|
207
|
+
if (this.listControls()?.role() === 'listbox') {
|
|
208
|
+
return this.listControls()?.items()[0];
|
|
165
209
|
}
|
|
166
|
-
return this.
|
|
210
|
+
return this.listControls()?.items().find(i => i.value() === this.inputs.firstMatch());
|
|
167
211
|
});
|
|
168
212
|
onFilter() {
|
|
169
213
|
if (this.readonly()) {
|
|
170
214
|
return;
|
|
171
215
|
}
|
|
216
|
+
const popupControls = this.inputs.popupControls();
|
|
217
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
172
220
|
const isInitialRender = !this.inputs.inputValue?.().length && !this.isDeleting;
|
|
173
221
|
if (isInitialRender) {
|
|
174
222
|
return;
|
|
@@ -182,11 +230,11 @@ class ComboboxPattern {
|
|
|
182
230
|
}
|
|
183
231
|
const item = this.firstMatch();
|
|
184
232
|
if (!item) {
|
|
185
|
-
|
|
186
|
-
|
|
233
|
+
popupControls?.clearSelection();
|
|
234
|
+
popupControls?.unfocus();
|
|
187
235
|
return;
|
|
188
236
|
}
|
|
189
|
-
|
|
237
|
+
popupControls?.focus(item);
|
|
190
238
|
if (this.inputs.filterMode() !== 'manual') {
|
|
191
239
|
this.select({
|
|
192
240
|
item
|
|
@@ -198,7 +246,7 @@ class ComboboxPattern {
|
|
|
198
246
|
}
|
|
199
247
|
highlight() {
|
|
200
248
|
const inputEl = this.inputs.inputEl();
|
|
201
|
-
const selectedItems = this.
|
|
249
|
+
const selectedItems = this.listControls()?.getSelectedItems();
|
|
202
250
|
const item = selectedItems?.[0];
|
|
203
251
|
if (!inputEl || !item) {
|
|
204
252
|
return;
|
|
@@ -211,12 +259,29 @@ class ComboboxPattern {
|
|
|
211
259
|
}
|
|
212
260
|
}
|
|
213
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
|
+
}
|
|
214
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
|
+
}
|
|
215
281
|
this.expanded.set(false);
|
|
216
|
-
|
|
282
|
+
popupControls?.unfocus();
|
|
217
283
|
return;
|
|
218
284
|
}
|
|
219
|
-
const popupControls = this.inputs.popupControls();
|
|
220
285
|
if (!this.expanded()) {
|
|
221
286
|
this.inputs.inputValue?.set('');
|
|
222
287
|
popupControls?.clearSelection();
|
|
@@ -225,19 +290,24 @@ class ComboboxPattern {
|
|
|
225
290
|
inputEl.value = '';
|
|
226
291
|
}
|
|
227
292
|
} else if (this.expanded()) {
|
|
228
|
-
this.
|
|
293
|
+
this.expanded.set(false);
|
|
229
294
|
const selectedItem = popupControls?.getSelectedItems()?.[0];
|
|
230
295
|
if (selectedItem?.searchTerm() !== this.inputs.inputValue()) {
|
|
231
296
|
popupControls?.clearSelection();
|
|
232
297
|
}
|
|
298
|
+
return;
|
|
233
299
|
}
|
|
234
300
|
this.close();
|
|
235
301
|
if (!this.readonly()) {
|
|
236
|
-
|
|
302
|
+
popupControls?.clearSelection();
|
|
237
303
|
}
|
|
238
304
|
}
|
|
239
305
|
open(nav) {
|
|
240
306
|
this.expanded.set(true);
|
|
307
|
+
const popupControls = this.inputs.popupControls();
|
|
308
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
241
311
|
const inputEl = this.inputs.inputEl();
|
|
242
312
|
if (inputEl && this.inputs.filterMode() === 'highlight') {
|
|
243
313
|
const isHighlighting = inputEl.selectionStart !== inputEl.value.length;
|
|
@@ -253,21 +323,23 @@ class ComboboxPattern {
|
|
|
253
323
|
this.last();
|
|
254
324
|
}
|
|
255
325
|
if (nav?.selected) {
|
|
256
|
-
const selectedItem =
|
|
257
|
-
|
|
326
|
+
const selectedItem = popupControls?.items().find(i => popupControls?.getSelectedItems().includes(i));
|
|
327
|
+
if (selectedItem) {
|
|
328
|
+
popupControls?.focus(selectedItem);
|
|
329
|
+
}
|
|
258
330
|
}
|
|
259
331
|
}
|
|
260
332
|
next() {
|
|
261
|
-
this._navigate(() => this.
|
|
333
|
+
this._navigate(() => this.listControls()?.next());
|
|
262
334
|
}
|
|
263
335
|
prev() {
|
|
264
|
-
this._navigate(() => this.
|
|
336
|
+
this._navigate(() => this.listControls()?.prev());
|
|
265
337
|
}
|
|
266
338
|
first() {
|
|
267
|
-
this._navigate(() => this.
|
|
339
|
+
this._navigate(() => this.listControls()?.first());
|
|
268
340
|
}
|
|
269
341
|
last() {
|
|
270
|
-
this._navigate(() => this.
|
|
342
|
+
this._navigate(() => this.listControls()?.last());
|
|
271
343
|
}
|
|
272
344
|
collapseItem() {
|
|
273
345
|
const controls = this.inputs.popupControls();
|
|
@@ -278,7 +350,7 @@ class ComboboxPattern {
|
|
|
278
350
|
this._navigate(() => controls?.expandItem());
|
|
279
351
|
}
|
|
280
352
|
select(opts = {}) {
|
|
281
|
-
const controls = this.
|
|
353
|
+
const controls = this.listControls();
|
|
282
354
|
if (opts.item) {
|
|
283
355
|
controls?.focus(opts.item, {
|
|
284
356
|
focusElement: false
|
|
@@ -294,7 +366,7 @@ class ComboboxPattern {
|
|
|
294
366
|
}
|
|
295
367
|
commit() {
|
|
296
368
|
const inputEl = this.inputs.inputEl();
|
|
297
|
-
const selectedItems = this.
|
|
369
|
+
const selectedItems = this.listControls()?.getSelectedItems();
|
|
298
370
|
if (!inputEl) {
|
|
299
371
|
return;
|
|
300
372
|
}
|
|
@@ -311,7 +383,7 @@ class ComboboxPattern {
|
|
|
311
383
|
this.select();
|
|
312
384
|
}
|
|
313
385
|
if (this.inputs.filterMode() === 'highlight') {
|
|
314
|
-
const selectedItem = this.
|
|
386
|
+
const selectedItem = this.listControls()?.getSelectedItems()[0];
|
|
315
387
|
if (!selectedItem) {
|
|
316
388
|
return;
|
|
317
389
|
}
|
|
@@ -324,116 +396,23 @@ class ComboboxPattern {
|
|
|
324
396
|
}
|
|
325
397
|
}
|
|
326
398
|
}
|
|
327
|
-
|
|
328
|
-
class ListFocus {
|
|
399
|
+
class ComboboxDialogPattern {
|
|
329
400
|
inputs;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
activeIndex = computed(() => {
|
|
335
|
-
return this.inputs.activeItem() ? this.inputs.items().indexOf(this.inputs.activeItem()) : -1;
|
|
401
|
+
id = () => this.inputs.id();
|
|
402
|
+
role = () => 'dialog';
|
|
403
|
+
keydown = computed(() => {
|
|
404
|
+
return new KeyboardEventManager().on('Escape', () => this.inputs.combobox.close());
|
|
336
405
|
});
|
|
337
406
|
constructor(inputs) {
|
|
338
407
|
this.inputs = inputs;
|
|
339
408
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
getActiveDescendant() {
|
|
344
|
-
if (this.isListDisabled()) {
|
|
345
|
-
return undefined;
|
|
346
|
-
}
|
|
347
|
-
if (this.inputs.focusMode() === 'roving') {
|
|
348
|
-
return undefined;
|
|
349
|
-
}
|
|
350
|
-
return this.inputs.activeItem()?.id() ?? undefined;
|
|
351
|
-
}
|
|
352
|
-
getListTabIndex() {
|
|
353
|
-
if (this.isListDisabled()) {
|
|
354
|
-
return 0;
|
|
355
|
-
}
|
|
356
|
-
return this.inputs.focusMode() === 'activedescendant' ? 0 : -1;
|
|
357
|
-
}
|
|
358
|
-
getItemTabIndex(item) {
|
|
359
|
-
if (this.isListDisabled()) {
|
|
360
|
-
return -1;
|
|
361
|
-
}
|
|
362
|
-
if (this.inputs.focusMode() === 'activedescendant') {
|
|
363
|
-
return -1;
|
|
364
|
-
}
|
|
365
|
-
return this.inputs.activeItem() === item ? 0 : -1;
|
|
366
|
-
}
|
|
367
|
-
focus(item, opts) {
|
|
368
|
-
if (this.isListDisabled() || !this.isFocusable(item)) {
|
|
369
|
-
return false;
|
|
370
|
-
}
|
|
371
|
-
this.prevActiveItem.set(this.inputs.activeItem());
|
|
372
|
-
this.inputs.activeItem.set(item);
|
|
373
|
-
if (opts?.focusElement || opts?.focusElement === undefined) {
|
|
374
|
-
this.inputs.focusMode() === 'roving' ? item.element()?.focus() : this.inputs.element()?.focus();
|
|
375
|
-
}
|
|
376
|
-
return true;
|
|
377
|
-
}
|
|
378
|
-
isFocusable(item) {
|
|
379
|
-
return !item.disabled() || this.inputs.softDisabled();
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
class ListNavigation {
|
|
384
|
-
inputs;
|
|
385
|
-
constructor(inputs) {
|
|
386
|
-
this.inputs = inputs;
|
|
387
|
-
}
|
|
388
|
-
goto(item, opts) {
|
|
389
|
-
return item ? this.inputs.focusManager.focus(item, opts) : false;
|
|
390
|
-
}
|
|
391
|
-
next(opts) {
|
|
392
|
-
return this._advance(1, opts);
|
|
393
|
-
}
|
|
394
|
-
peekNext() {
|
|
395
|
-
return this._peek(1);
|
|
396
|
-
}
|
|
397
|
-
prev(opts) {
|
|
398
|
-
return this._advance(-1, opts);
|
|
399
|
-
}
|
|
400
|
-
peekPrev() {
|
|
401
|
-
return this._peek(-1);
|
|
402
|
-
}
|
|
403
|
-
first(opts) {
|
|
404
|
-
const item = this.peekFirst();
|
|
405
|
-
return item ? this.goto(item, opts) : false;
|
|
406
|
-
}
|
|
407
|
-
last(opts) {
|
|
408
|
-
const item = this.peekLast();
|
|
409
|
-
return item ? this.goto(item, opts) : false;
|
|
410
|
-
}
|
|
411
|
-
peekFirst(items = this.inputs.items()) {
|
|
412
|
-
return items.find(i => this.inputs.focusManager.isFocusable(i));
|
|
413
|
-
}
|
|
414
|
-
peekLast(items = this.inputs.items()) {
|
|
415
|
-
for (let i = items.length - 1; i >= 0; i--) {
|
|
416
|
-
if (this.inputs.focusManager.isFocusable(items[i])) {
|
|
417
|
-
return items[i];
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
_advance(delta, opts) {
|
|
423
|
-
const item = this._peek(delta);
|
|
424
|
-
return item ? this.goto(item, opts) : false;
|
|
409
|
+
onKeydown(event) {
|
|
410
|
+
this.keydown().handle(event);
|
|
425
411
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
const startIndex = this.inputs.focusManager.activeIndex();
|
|
430
|
-
const step = i => this.inputs.wrap() ? (i + delta + itemCount) % itemCount : i + delta;
|
|
431
|
-
for (let i = step(startIndex); i !== startIndex && i < itemCount && i >= 0; i = step(i)) {
|
|
432
|
-
if (this.inputs.focusManager.isFocusable(items[i])) {
|
|
433
|
-
return items[i];
|
|
434
|
-
}
|
|
412
|
+
onClick(event) {
|
|
413
|
+
if (event.target === this.inputs.element()) {
|
|
414
|
+
this.inputs.combobox.close();
|
|
435
415
|
}
|
|
436
|
-
return;
|
|
437
416
|
}
|
|
438
417
|
}
|
|
439
418
|
|
|
@@ -441,7 +420,7 @@ class ListSelection {
|
|
|
441
420
|
inputs;
|
|
442
421
|
rangeStartIndex = signal(0);
|
|
443
422
|
rangeEndIndex = signal(0);
|
|
444
|
-
selectedItems = computed(() => this.inputs.items().filter(item => this.inputs.
|
|
423
|
+
selectedItems = computed(() => this.inputs.items().filter(item => this.inputs.values().includes(item.value())));
|
|
445
424
|
constructor(inputs) {
|
|
446
425
|
this.inputs = inputs;
|
|
447
426
|
}
|
|
@@ -449,7 +428,7 @@ class ListSelection {
|
|
|
449
428
|
anchor: true
|
|
450
429
|
}) {
|
|
451
430
|
item = item ?? this.inputs.focusManager.inputs.activeItem();
|
|
452
|
-
if (!item || item.disabled() || !item.selectable() || this.inputs.
|
|
431
|
+
if (!item || item.disabled() || !item.selectable() || this.inputs.values().includes(item.value())) {
|
|
453
432
|
return;
|
|
454
433
|
}
|
|
455
434
|
if (!this.inputs.multi()) {
|
|
@@ -459,24 +438,24 @@ class ListSelection {
|
|
|
459
438
|
if (opts.anchor) {
|
|
460
439
|
this.beginRangeSelection(index);
|
|
461
440
|
}
|
|
462
|
-
this.inputs.
|
|
441
|
+
this.inputs.values.update(values => values.concat(item.value()));
|
|
463
442
|
}
|
|
464
443
|
deselect(item) {
|
|
465
444
|
item = item ?? this.inputs.focusManager.inputs.activeItem();
|
|
466
445
|
if (item && !item.disabled() && item.selectable()) {
|
|
467
|
-
this.inputs.
|
|
446
|
+
this.inputs.values.update(values => values.filter(value => value !== item.value()));
|
|
468
447
|
}
|
|
469
448
|
}
|
|
470
449
|
toggle(item) {
|
|
471
450
|
item = item ?? this.inputs.focusManager.inputs.activeItem();
|
|
472
451
|
if (item) {
|
|
473
|
-
this.inputs.
|
|
452
|
+
this.inputs.values().includes(item.value()) ? this.deselect(item) : this.select(item);
|
|
474
453
|
}
|
|
475
454
|
}
|
|
476
455
|
toggleOne() {
|
|
477
456
|
const item = this.inputs.focusManager.inputs.activeItem();
|
|
478
457
|
if (item) {
|
|
479
|
-
this.inputs.
|
|
458
|
+
this.inputs.values().includes(item.value()) ? this.deselect() : this.selectOne();
|
|
480
459
|
}
|
|
481
460
|
}
|
|
482
461
|
selectAll() {
|
|
@@ -491,14 +470,14 @@ class ListSelection {
|
|
|
491
470
|
this.beginRangeSelection();
|
|
492
471
|
}
|
|
493
472
|
deselectAll() {
|
|
494
|
-
for (const value of this.inputs.
|
|
473
|
+
for (const value of this.inputs.values()) {
|
|
495
474
|
const item = this.inputs.items().find(i => i.value() === value);
|
|
496
|
-
item ? this.deselect(item) : this.inputs.
|
|
475
|
+
item ? this.deselect(item) : this.inputs.values.update(values => values.filter(v => v !== value));
|
|
497
476
|
}
|
|
498
477
|
}
|
|
499
478
|
toggleAll() {
|
|
500
479
|
const selectableValues = this.inputs.items().filter(i => !i.disabled() && i.selectable()).map(i => i.value());
|
|
501
|
-
selectableValues.every(i => this.inputs.
|
|
480
|
+
selectableValues.every(i => this.inputs.values().includes(i)) ? this.deselectAll() : this.selectAll();
|
|
502
481
|
}
|
|
503
482
|
selectOne() {
|
|
504
483
|
const item = this.inputs.focusManager.inputs.activeItem();
|
|
@@ -506,7 +485,7 @@ class ListSelection {
|
|
|
506
485
|
return;
|
|
507
486
|
}
|
|
508
487
|
this.deselectAll();
|
|
509
|
-
if (this.inputs.
|
|
488
|
+
if (this.inputs.values().length > 0 && !this.inputs.multi()) {
|
|
510
489
|
return;
|
|
511
490
|
}
|
|
512
491
|
this.select();
|
|
@@ -585,7 +564,7 @@ class ListTypeahead {
|
|
|
585
564
|
this.timeout = setTimeout(() => {
|
|
586
565
|
this._query.set('');
|
|
587
566
|
this._startIndex.set(undefined);
|
|
588
|
-
}, this.inputs.typeaheadDelay()
|
|
567
|
+
}, this.inputs.typeaheadDelay());
|
|
589
568
|
return true;
|
|
590
569
|
}
|
|
591
570
|
_getItem() {
|
|
@@ -843,8 +822,8 @@ class ListboxPattern {
|
|
|
843
822
|
}
|
|
844
823
|
validate() {
|
|
845
824
|
const violations = [];
|
|
846
|
-
if (!this.inputs.multi() && this.inputs.
|
|
847
|
-
violations.push(`A single-select listbox should not have multiple selected options. Selected options: ${this.inputs.
|
|
825
|
+
if (!this.inputs.multi() && this.inputs.values().length > 1) {
|
|
826
|
+
violations.push(`A single-select listbox should not have multiple selected options. Selected options: ${this.inputs.values().join(', ')}`);
|
|
848
827
|
}
|
|
849
828
|
return violations;
|
|
850
829
|
}
|
|
@@ -889,7 +868,7 @@ class OptionPattern {
|
|
|
889
868
|
value;
|
|
890
869
|
index = computed(() => this.listbox()?.inputs.items().indexOf(this) ?? -1);
|
|
891
870
|
active = computed(() => this.listbox()?.inputs.activeItem() === this);
|
|
892
|
-
selected = computed(() => this.listbox()?.inputs.
|
|
871
|
+
selected = computed(() => this.listbox()?.inputs.values().includes(this.value()));
|
|
893
872
|
selectable = () => true;
|
|
894
873
|
disabled;
|
|
895
874
|
searchTerm;
|
|
@@ -930,6 +909,7 @@ class ComboboxListboxPattern extends ListboxPattern {
|
|
|
930
909
|
focus = (item, opts) => {
|
|
931
910
|
this.listBehavior.goto(item, opts);
|
|
932
911
|
};
|
|
912
|
+
getActiveItem = () => this.inputs.activeItem();
|
|
933
913
|
next = () => this.listBehavior.next();
|
|
934
914
|
prev = () => this.listBehavior.prev();
|
|
935
915
|
last = () => this.listBehavior.last();
|
|
@@ -941,7 +921,7 @@ class ComboboxListboxPattern extends ListboxPattern {
|
|
|
941
921
|
getItem = e => this._getItem(e);
|
|
942
922
|
getSelectedItems = () => {
|
|
943
923
|
const items = [];
|
|
944
|
-
for (const value of this.inputs.
|
|
924
|
+
for (const value of this.inputs.values()) {
|
|
945
925
|
const item = this.items().find(i => i.value() === value);
|
|
946
926
|
if (item) {
|
|
947
927
|
items.push(item);
|
|
@@ -949,17 +929,21 @@ class ComboboxListboxPattern extends ListboxPattern {
|
|
|
949
929
|
}
|
|
950
930
|
return items;
|
|
951
931
|
};
|
|
952
|
-
setValue = value => this.inputs.
|
|
932
|
+
setValue = value => this.inputs.values.set(value ? [value] : []);
|
|
953
933
|
}
|
|
954
934
|
|
|
955
935
|
class MenuPattern {
|
|
956
936
|
inputs;
|
|
957
937
|
id;
|
|
958
938
|
role = () => 'menu';
|
|
959
|
-
|
|
939
|
+
disabled = () => this.inputs.disabled();
|
|
940
|
+
visible = computed(() => this.inputs.parent() ? !!this.inputs.parent()?.expanded() : true);
|
|
960
941
|
listBehavior;
|
|
961
942
|
isFocused = signal(false);
|
|
962
943
|
hasBeenFocused = signal(false);
|
|
944
|
+
_openTimeout;
|
|
945
|
+
_closeTimeout;
|
|
946
|
+
tabIndex = () => this.listBehavior.tabIndex();
|
|
963
947
|
shouldFocus = computed(() => {
|
|
964
948
|
const root = this.root();
|
|
965
949
|
if (root instanceof MenuTriggerPattern) {
|
|
@@ -1000,40 +984,67 @@ class MenuPattern {
|
|
|
1000
984
|
this.id = inputs.id;
|
|
1001
985
|
this.listBehavior = new List({
|
|
1002
986
|
...inputs,
|
|
1003
|
-
|
|
1004
|
-
disabled: () => false
|
|
987
|
+
values: signal([])
|
|
1005
988
|
});
|
|
1006
989
|
}
|
|
1007
990
|
setDefaultState() {
|
|
1008
991
|
if (!this.inputs.parent()) {
|
|
1009
|
-
this.
|
|
992
|
+
this.listBehavior.goto(this.inputs.items()[0], {
|
|
993
|
+
focusElement: false
|
|
994
|
+
});
|
|
1010
995
|
}
|
|
1011
996
|
}
|
|
1012
997
|
onKeydown(event) {
|
|
1013
998
|
this.keydownManager().handle(event);
|
|
1014
999
|
}
|
|
1015
1000
|
onMouseOver(event) {
|
|
1016
|
-
if (!this.
|
|
1001
|
+
if (!this.visible()) {
|
|
1017
1002
|
return;
|
|
1018
1003
|
}
|
|
1019
1004
|
const item = this.inputs.items().find(i => i.element()?.contains(event.target));
|
|
1020
1005
|
if (!item) {
|
|
1021
1006
|
return;
|
|
1022
1007
|
}
|
|
1008
|
+
const parent = this.inputs.parent();
|
|
1023
1009
|
const activeItem = this?.inputs.activeItem();
|
|
1010
|
+
if (parent instanceof MenuItemPattern) {
|
|
1011
|
+
const grandparent = parent.inputs.parent();
|
|
1012
|
+
if (grandparent instanceof MenuPattern) {
|
|
1013
|
+
grandparent._clearTimeouts();
|
|
1014
|
+
grandparent.listBehavior.goto(parent, {
|
|
1015
|
+
focusElement: false
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1024
1019
|
if (activeItem && activeItem !== item) {
|
|
1025
|
-
|
|
1020
|
+
this._closeItem(activeItem);
|
|
1026
1021
|
}
|
|
1027
|
-
if (item.expanded()
|
|
1028
|
-
|
|
1029
|
-
item.submenu()?.listBehavior.unfocus();
|
|
1022
|
+
if (item.expanded()) {
|
|
1023
|
+
this._clearCloseTimeout();
|
|
1030
1024
|
}
|
|
1031
|
-
|
|
1025
|
+
this._openItem(item);
|
|
1032
1026
|
this.listBehavior.goto(item, {
|
|
1033
1027
|
focusElement: this.shouldFocus()
|
|
1034
1028
|
});
|
|
1035
1029
|
}
|
|
1030
|
+
_closeItem(item) {
|
|
1031
|
+
this._clearOpenTimeout();
|
|
1032
|
+
if (!this._closeTimeout) {
|
|
1033
|
+
this._closeTimeout = setTimeout(() => {
|
|
1034
|
+
item.close();
|
|
1035
|
+
this._closeTimeout = undefined;
|
|
1036
|
+
}, this.inputs.expansionDelay());
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
_openItem(item) {
|
|
1040
|
+
this._clearOpenTimeout();
|
|
1041
|
+
this._openTimeout = setTimeout(() => {
|
|
1042
|
+
item.open();
|
|
1043
|
+
this._openTimeout = undefined;
|
|
1044
|
+
}, this.inputs.expansionDelay());
|
|
1045
|
+
}
|
|
1036
1046
|
onMouseOut(event) {
|
|
1047
|
+
this._clearOpenTimeout();
|
|
1037
1048
|
if (this.isFocused()) {
|
|
1038
1049
|
return;
|
|
1039
1050
|
}
|
|
@@ -1082,7 +1093,7 @@ class MenuPattern {
|
|
|
1082
1093
|
return;
|
|
1083
1094
|
}
|
|
1084
1095
|
}
|
|
1085
|
-
if (this.
|
|
1096
|
+
if (this.visible() && !parentEl?.contains(relatedTarget) && !this.inputs.element()?.contains(relatedTarget)) {
|
|
1086
1097
|
this.isFocused.set(false);
|
|
1087
1098
|
this.inputs.parent()?.close();
|
|
1088
1099
|
}
|
|
@@ -1153,6 +1164,9 @@ class MenuPattern {
|
|
|
1153
1164
|
root.next();
|
|
1154
1165
|
}
|
|
1155
1166
|
}
|
|
1167
|
+
close() {
|
|
1168
|
+
this.inputs.parent()?.close();
|
|
1169
|
+
}
|
|
1156
1170
|
closeAll() {
|
|
1157
1171
|
const root = this.root();
|
|
1158
1172
|
if (root instanceof MenuTriggerPattern) {
|
|
@@ -1169,10 +1183,27 @@ class MenuPattern {
|
|
|
1169
1183
|
});
|
|
1170
1184
|
}
|
|
1171
1185
|
}
|
|
1186
|
+
_clearTimeouts() {
|
|
1187
|
+
this._clearOpenTimeout();
|
|
1188
|
+
this._clearCloseTimeout();
|
|
1189
|
+
}
|
|
1190
|
+
_clearOpenTimeout() {
|
|
1191
|
+
if (this._openTimeout) {
|
|
1192
|
+
clearTimeout(this._openTimeout);
|
|
1193
|
+
this._openTimeout = undefined;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
_clearCloseTimeout() {
|
|
1197
|
+
if (this._closeTimeout) {
|
|
1198
|
+
clearTimeout(this._closeTimeout);
|
|
1199
|
+
this._closeTimeout = undefined;
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1172
1202
|
}
|
|
1173
1203
|
class MenuBarPattern {
|
|
1174
1204
|
inputs;
|
|
1175
1205
|
listBehavior;
|
|
1206
|
+
tabIndex = () => this.listBehavior.tabIndex();
|
|
1176
1207
|
_nextKey = computed(() => {
|
|
1177
1208
|
return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
|
|
1178
1209
|
});
|
|
@@ -1183,6 +1214,7 @@ class MenuBarPattern {
|
|
|
1183
1214
|
typeaheadRegexp = /^.$/;
|
|
1184
1215
|
isFocused = signal(false);
|
|
1185
1216
|
hasBeenFocused = signal(false);
|
|
1217
|
+
disabled = () => this.inputs.disabled();
|
|
1186
1218
|
keydownManager = computed(() => {
|
|
1187
1219
|
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({
|
|
1188
1220
|
first: true
|
|
@@ -1196,10 +1228,7 @@ class MenuBarPattern {
|
|
|
1196
1228
|
});
|
|
1197
1229
|
constructor(inputs) {
|
|
1198
1230
|
this.inputs = inputs;
|
|
1199
|
-
this.listBehavior = new List(
|
|
1200
|
-
...inputs,
|
|
1201
|
-
disabled: () => false
|
|
1202
|
-
});
|
|
1231
|
+
this.listBehavior = new List(inputs);
|
|
1203
1232
|
}
|
|
1204
1233
|
setDefaultState() {
|
|
1205
1234
|
this.inputs.activeItem.set(this.inputs.items()[0]);
|
|
@@ -1277,10 +1306,12 @@ class MenuBarPattern {
|
|
|
1277
1306
|
class MenuTriggerPattern {
|
|
1278
1307
|
inputs;
|
|
1279
1308
|
expanded = signal(false);
|
|
1309
|
+
hasBeenFocused = signal(false);
|
|
1280
1310
|
role = () => 'button';
|
|
1281
1311
|
hasPopup = () => true;
|
|
1282
1312
|
menu;
|
|
1283
1313
|
tabIndex = computed(() => this.expanded() && this.menu()?.inputs.activeItem() ? -1 : 0);
|
|
1314
|
+
disabled = () => this.inputs.disabled();
|
|
1284
1315
|
keydownManager = computed(() => {
|
|
1285
1316
|
return new KeyboardEventManager().on(' ', () => this.open({
|
|
1286
1317
|
first: true
|
|
@@ -1299,12 +1330,19 @@ class MenuTriggerPattern {
|
|
|
1299
1330
|
this.menu = this.inputs.menu;
|
|
1300
1331
|
}
|
|
1301
1332
|
onKeydown(event) {
|
|
1302
|
-
this.
|
|
1333
|
+
if (!this.inputs.disabled()) {
|
|
1334
|
+
this.keydownManager().handle(event);
|
|
1335
|
+
}
|
|
1303
1336
|
}
|
|
1304
1337
|
onClick() {
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1338
|
+
if (!this.inputs.disabled()) {
|
|
1339
|
+
this.expanded() ? this.close() : this.open({
|
|
1340
|
+
first: true
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
onFocusIn() {
|
|
1345
|
+
this.hasBeenFocused.set(true);
|
|
1308
1346
|
}
|
|
1309
1347
|
onFocusOut(event) {
|
|
1310
1348
|
const element = this.inputs.element();
|
|
@@ -1340,10 +1378,11 @@ class MenuItemPattern {
|
|
|
1340
1378
|
inputs;
|
|
1341
1379
|
value;
|
|
1342
1380
|
id;
|
|
1343
|
-
disabled;
|
|
1381
|
+
disabled = () => this.inputs.parent()?.disabled() || this.inputs.disabled();
|
|
1344
1382
|
searchTerm;
|
|
1345
1383
|
element;
|
|
1346
|
-
|
|
1384
|
+
active = computed(() => this.inputs.parent()?.inputs.activeItem() === this);
|
|
1385
|
+
hasBeenFocused = signal(false);
|
|
1347
1386
|
tabIndex = computed(() => {
|
|
1348
1387
|
if (this.submenu() && this.submenu()?.inputs.activeItem()) {
|
|
1349
1388
|
return -1;
|
|
@@ -1363,12 +1402,14 @@ class MenuItemPattern {
|
|
|
1363
1402
|
this.id = inputs.id;
|
|
1364
1403
|
this.value = inputs.value;
|
|
1365
1404
|
this.element = inputs.element;
|
|
1366
|
-
this.disabled = inputs.disabled;
|
|
1367
1405
|
this.submenu = this.inputs.submenu;
|
|
1368
1406
|
this.searchTerm = inputs.searchTerm;
|
|
1369
1407
|
this.selectable = computed(() => !this.submenu());
|
|
1370
1408
|
}
|
|
1371
1409
|
open(opts) {
|
|
1410
|
+
if (this.disabled()) {
|
|
1411
|
+
return;
|
|
1412
|
+
}
|
|
1372
1413
|
this._expanded.set(true);
|
|
1373
1414
|
if (opts?.first) {
|
|
1374
1415
|
this.submenu()?.first();
|
|
@@ -1388,8 +1429,15 @@ class MenuItemPattern {
|
|
|
1388
1429
|
menuitem?._expanded.set(false);
|
|
1389
1430
|
menuitem?.inputs.parent()?.listBehavior.unfocus();
|
|
1390
1431
|
menuitems = menuitems.concat(menuitem?.submenu()?.inputs.items() ?? []);
|
|
1432
|
+
const parent = menuitem?.inputs.parent();
|
|
1433
|
+
if (parent instanceof MenuPattern) {
|
|
1434
|
+
parent._clearTimeouts();
|
|
1435
|
+
}
|
|
1391
1436
|
}
|
|
1392
1437
|
}
|
|
1438
|
+
onFocusIn() {
|
|
1439
|
+
this.hasBeenFocused.set(true);
|
|
1440
|
+
}
|
|
1393
1441
|
}
|
|
1394
1442
|
|
|
1395
1443
|
function convertGetterSetterToWritableSignalLike(getter, setter) {
|
|
@@ -1399,48 +1447,27 @@ function convertGetterSetterToWritableSignalLike(getter, setter) {
|
|
|
1399
1447
|
});
|
|
1400
1448
|
}
|
|
1401
1449
|
|
|
1402
|
-
class ExpansionControl {
|
|
1403
|
-
inputs;
|
|
1404
|
-
isExpanded = computed(() => this.inputs.expansionManager.isExpanded(this));
|
|
1405
|
-
isExpandable = computed(() => this.inputs.expansionManager.isExpandable(this));
|
|
1406
|
-
constructor(inputs) {
|
|
1407
|
-
this.inputs = inputs;
|
|
1408
|
-
this.expansionId = inputs.expansionId;
|
|
1409
|
-
this.expandable = inputs.expandable;
|
|
1410
|
-
this.disabled = inputs.disabled;
|
|
1411
|
-
}
|
|
1412
|
-
open() {
|
|
1413
|
-
this.inputs.expansionManager.open(this);
|
|
1414
|
-
}
|
|
1415
|
-
close() {
|
|
1416
|
-
this.inputs.expansionManager.close(this);
|
|
1417
|
-
}
|
|
1418
|
-
toggle() {
|
|
1419
|
-
this.inputs.expansionManager.toggle(this);
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
1450
|
class ListExpansion {
|
|
1423
1451
|
inputs;
|
|
1424
|
-
expandedIds;
|
|
1425
1452
|
constructor(inputs) {
|
|
1426
1453
|
this.inputs = inputs;
|
|
1427
|
-
this.expandedIds = inputs.expandedIds;
|
|
1428
1454
|
}
|
|
1429
1455
|
open(item) {
|
|
1430
|
-
if (!this.isExpandable(item)) return;
|
|
1431
|
-
if (
|
|
1456
|
+
if (!this.isExpandable(item)) return false;
|
|
1457
|
+
if (item.expanded()) return false;
|
|
1432
1458
|
if (!this.inputs.multiExpandable()) {
|
|
1433
1459
|
this.closeAll();
|
|
1434
1460
|
}
|
|
1435
|
-
|
|
1461
|
+
item.expanded.set(true);
|
|
1462
|
+
return true;
|
|
1436
1463
|
}
|
|
1437
1464
|
close(item) {
|
|
1438
|
-
if (this.isExpandable(item))
|
|
1439
|
-
|
|
1440
|
-
|
|
1465
|
+
if (!this.isExpandable(item)) return false;
|
|
1466
|
+
item.expanded.set(false);
|
|
1467
|
+
return true;
|
|
1441
1468
|
}
|
|
1442
1469
|
toggle(item) {
|
|
1443
|
-
|
|
1470
|
+
return item.expanded() ? this.close(item) : this.open(item);
|
|
1444
1471
|
}
|
|
1445
1472
|
openAll() {
|
|
1446
1473
|
if (this.inputs.multiExpandable()) {
|
|
@@ -1457,9 +1484,6 @@ class ListExpansion {
|
|
|
1457
1484
|
isExpandable(item) {
|
|
1458
1485
|
return !this.inputs.disabled() && !item.disabled() && item.expandable();
|
|
1459
1486
|
}
|
|
1460
|
-
isExpanded(item) {
|
|
1461
|
-
return this.expandedIds().includes(item.expansionId());
|
|
1462
|
-
}
|
|
1463
1487
|
}
|
|
1464
1488
|
|
|
1465
1489
|
class LabelControl {
|
|
@@ -1484,47 +1508,35 @@ class LabelControl {
|
|
|
1484
1508
|
|
|
1485
1509
|
class TabPattern {
|
|
1486
1510
|
inputs;
|
|
1487
|
-
|
|
1488
|
-
id;
|
|
1511
|
+
id = () => this.inputs.id();
|
|
1489
1512
|
index = computed(() => this.inputs.tablist().inputs.items().indexOf(this));
|
|
1490
|
-
value;
|
|
1491
|
-
disabled;
|
|
1492
|
-
element;
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
expandable = computed(() => this.expansion.expandable());
|
|
1496
|
-
expansionId = computed(() => this.expansion.expansionId());
|
|
1497
|
-
expanded = computed(() => this.expansion.isExpanded());
|
|
1513
|
+
value = () => this.inputs.value();
|
|
1514
|
+
disabled = () => this.inputs.disabled();
|
|
1515
|
+
element = () => this.inputs.element();
|
|
1516
|
+
expandable = () => true;
|
|
1517
|
+
expanded;
|
|
1498
1518
|
active = computed(() => this.inputs.tablist().inputs.activeItem() === this);
|
|
1499
|
-
selected = computed(() =>
|
|
1500
|
-
tabIndex = computed(() => this.inputs.tablist().
|
|
1519
|
+
selected = computed(() => this.inputs.tablist().selectedTab() === this);
|
|
1520
|
+
tabIndex = computed(() => this.inputs.tablist().focusBehavior.getItemTabIndex(this));
|
|
1501
1521
|
controls = computed(() => this.inputs.tabpanel()?.id());
|
|
1502
1522
|
constructor(inputs) {
|
|
1503
1523
|
this.inputs = inputs;
|
|
1504
|
-
this.
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
this.
|
|
1508
|
-
this.expansion = new ExpansionControl({
|
|
1509
|
-
...inputs,
|
|
1510
|
-
expansionId: inputs.value,
|
|
1511
|
-
expandable: () => true,
|
|
1512
|
-
expansionManager: inputs.tablist().expansionManager
|
|
1513
|
-
});
|
|
1524
|
+
this.expanded = inputs.expanded;
|
|
1525
|
+
}
|
|
1526
|
+
open() {
|
|
1527
|
+
return this.inputs.tablist().open(this);
|
|
1514
1528
|
}
|
|
1515
1529
|
}
|
|
1516
1530
|
class TabPanelPattern {
|
|
1517
1531
|
inputs;
|
|
1518
|
-
id;
|
|
1519
|
-
value;
|
|
1532
|
+
id = () => this.inputs.id();
|
|
1533
|
+
value = () => this.inputs.value();
|
|
1520
1534
|
labelManager;
|
|
1521
1535
|
hidden = computed(() => this.inputs.tab()?.expanded() === false);
|
|
1522
1536
|
tabIndex = computed(() => this.hidden() ? -1 : 0);
|
|
1523
1537
|
labelledBy = computed(() => this.labelManager.labelledBy().length > 0 ? this.labelManager.labelledBy().join(' ') : undefined);
|
|
1524
1538
|
constructor(inputs) {
|
|
1525
1539
|
this.inputs = inputs;
|
|
1526
|
-
this.id = inputs.id;
|
|
1527
|
-
this.value = inputs.value;
|
|
1528
1540
|
this.labelManager = new LabelControl({
|
|
1529
1541
|
...inputs,
|
|
1530
1542
|
defaultLabelledBy: computed(() => this.inputs.tab() ? [this.inputs.tab().id()] : [])
|
|
@@ -1533,12 +1545,15 @@ class TabPanelPattern {
|
|
|
1533
1545
|
}
|
|
1534
1546
|
class TabListPattern {
|
|
1535
1547
|
inputs;
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1548
|
+
focusBehavior;
|
|
1549
|
+
navigationBehavior;
|
|
1550
|
+
expansionBehavior;
|
|
1551
|
+
activeTab = () => this.inputs.activeItem();
|
|
1552
|
+
selectedTab = signal(undefined);
|
|
1553
|
+
orientation = () => this.inputs.orientation();
|
|
1554
|
+
disabled = () => this.inputs.disabled();
|
|
1555
|
+
tabIndex = computed(() => this.focusBehavior.getListTabIndex());
|
|
1556
|
+
activeDescendant = computed(() => this.focusBehavior.getActiveDescendant());
|
|
1542
1557
|
followFocus = computed(() => this.inputs.selectionMode() === 'follow');
|
|
1543
1558
|
prevKey = computed(() => {
|
|
1544
1559
|
if (this.inputs.orientation() === 'vertical') {
|
|
@@ -1553,40 +1568,27 @@ class TabListPattern {
|
|
|
1553
1568
|
return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
|
|
1554
1569
|
});
|
|
1555
1570
|
keydown = computed(() => {
|
|
1556
|
-
return new KeyboardEventManager().on(this.prevKey, () => this.
|
|
1557
|
-
select: this.followFocus()
|
|
1558
|
-
})).on(this.nextKey, () => this.listBehavior.next({
|
|
1559
|
-
select: this.followFocus()
|
|
1560
|
-
})).on('Home', () => this.listBehavior.first({
|
|
1561
|
-
select: this.followFocus()
|
|
1562
|
-
})).on('End', () => this.listBehavior.last({
|
|
1563
|
-
select: this.followFocus()
|
|
1564
|
-
})).on(' ', () => this.listBehavior.select()).on('Enter', () => this.listBehavior.select());
|
|
1571
|
+
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());
|
|
1565
1572
|
});
|
|
1566
1573
|
pointerdown = computed(() => {
|
|
1567
|
-
return new PointerEventManager().on(e => this.
|
|
1568
|
-
select: true
|
|
1569
|
-
}));
|
|
1574
|
+
return new PointerEventManager().on(e => this._navigate(() => this.navigationBehavior.goto(this._getItem(e)), true));
|
|
1570
1575
|
});
|
|
1571
1576
|
constructor(inputs) {
|
|
1572
1577
|
this.inputs = inputs;
|
|
1573
|
-
this.
|
|
1574
|
-
this.
|
|
1575
|
-
this.listBehavior = new List({
|
|
1578
|
+
this.focusBehavior = new ListFocus(inputs);
|
|
1579
|
+
this.navigationBehavior = new ListNavigation({
|
|
1576
1580
|
...inputs,
|
|
1577
|
-
|
|
1578
|
-
typeaheadDelay: () => 0
|
|
1581
|
+
focusManager: this.focusBehavior
|
|
1579
1582
|
});
|
|
1580
|
-
this.
|
|
1583
|
+
this.expansionBehavior = new ListExpansion({
|
|
1581
1584
|
...inputs,
|
|
1582
|
-
multiExpandable: () => false
|
|
1583
|
-
expandedIds: this.inputs.value
|
|
1585
|
+
multiExpandable: () => false
|
|
1584
1586
|
});
|
|
1585
1587
|
}
|
|
1586
1588
|
setDefaultState() {
|
|
1587
1589
|
let firstItem;
|
|
1588
1590
|
for (const item of this.inputs.items()) {
|
|
1589
|
-
if (!this.
|
|
1591
|
+
if (!this.focusBehavior.isFocusable(item)) continue;
|
|
1590
1592
|
if (firstItem === undefined) {
|
|
1591
1593
|
firstItem = item;
|
|
1592
1594
|
}
|
|
@@ -1609,6 +1611,24 @@ class TabListPattern {
|
|
|
1609
1611
|
this.pointerdown().handle(event);
|
|
1610
1612
|
}
|
|
1611
1613
|
}
|
|
1614
|
+
open(tab) {
|
|
1615
|
+
tab ??= this.activeTab();
|
|
1616
|
+
if (typeof tab === 'string') {
|
|
1617
|
+
tab = this.inputs.items().find(t => t.value() === tab);
|
|
1618
|
+
}
|
|
1619
|
+
if (tab === undefined) return false;
|
|
1620
|
+
const success = this.expansionBehavior.open(tab);
|
|
1621
|
+
if (success) {
|
|
1622
|
+
this.selectedTab.set(tab);
|
|
1623
|
+
}
|
|
1624
|
+
return success;
|
|
1625
|
+
}
|
|
1626
|
+
_navigate(op, shouldExpand = false) {
|
|
1627
|
+
const success = op();
|
|
1628
|
+
if (success && shouldExpand) {
|
|
1629
|
+
this.open();
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1612
1632
|
_getItem(e) {
|
|
1613
1633
|
if (!(e.target instanceof HTMLElement)) {
|
|
1614
1634
|
return;
|
|
@@ -1702,7 +1722,6 @@ class ToolbarPattern {
|
|
|
1702
1722
|
multi: () => true,
|
|
1703
1723
|
focusMode: () => 'roving',
|
|
1704
1724
|
selectionMode: () => 'explicit',
|
|
1705
|
-
value: signal([]),
|
|
1706
1725
|
typeaheadDelay: () => 0
|
|
1707
1726
|
});
|
|
1708
1727
|
}
|
|
@@ -1741,7 +1760,7 @@ class ToolbarWidgetPattern {
|
|
|
1741
1760
|
value = () => this.inputs.value();
|
|
1742
1761
|
selectable = () => true;
|
|
1743
1762
|
index = computed(() => this.toolbar().inputs.items().indexOf(this) ?? -1);
|
|
1744
|
-
selected = computed(() => this.toolbar().listBehavior.inputs.
|
|
1763
|
+
selected = computed(() => this.toolbar().listBehavior.inputs.values().includes(this.value()));
|
|
1745
1764
|
active = computed(() => this.toolbar().activeItem() === this);
|
|
1746
1765
|
constructor(inputs) {
|
|
1747
1766
|
this.inputs = inputs;
|
|
@@ -1765,82 +1784,45 @@ class ToolbarWidgetGroupPattern {
|
|
|
1765
1784
|
const focusMode = () => 'roving';
|
|
1766
1785
|
class AccordionGroupPattern {
|
|
1767
1786
|
inputs;
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1787
|
+
navigationBehavior;
|
|
1788
|
+
focusBehavior;
|
|
1789
|
+
expansionBehavior;
|
|
1771
1790
|
constructor(inputs) {
|
|
1772
1791
|
this.inputs = inputs;
|
|
1773
|
-
this.
|
|
1774
|
-
this.orientation = inputs.orientation;
|
|
1775
|
-
this.textDirection = inputs.textDirection;
|
|
1776
|
-
this.activeItem = inputs.activeItem;
|
|
1777
|
-
this.disabled = inputs.disabled;
|
|
1778
|
-
this.multiExpandable = inputs.multiExpandable;
|
|
1779
|
-
this.items = inputs.items;
|
|
1780
|
-
this.expandedIds = inputs.expandedIds;
|
|
1781
|
-
this.softDisabled = inputs.softDisabled;
|
|
1782
|
-
this.focusManager = new ListFocus({
|
|
1792
|
+
this.focusBehavior = new ListFocus({
|
|
1783
1793
|
...inputs,
|
|
1784
1794
|
focusMode
|
|
1785
1795
|
});
|
|
1786
|
-
this.
|
|
1796
|
+
this.navigationBehavior = new ListNavigation({
|
|
1787
1797
|
...inputs,
|
|
1788
1798
|
focusMode,
|
|
1789
|
-
focusManager: this.
|
|
1799
|
+
focusManager: this.focusBehavior
|
|
1790
1800
|
});
|
|
1791
|
-
this.
|
|
1801
|
+
this.expansionBehavior = new ListExpansion({
|
|
1792
1802
|
...inputs
|
|
1793
1803
|
});
|
|
1794
1804
|
}
|
|
1795
|
-
}
|
|
1796
|
-
class AccordionTriggerPattern {
|
|
1797
|
-
inputs;
|
|
1798
|
-
expandable;
|
|
1799
|
-
expansionId;
|
|
1800
|
-
expanded;
|
|
1801
|
-
expansionControl;
|
|
1802
|
-
active = computed(() => this.inputs.accordionGroup().activeItem() === this);
|
|
1803
|
-
controls = computed(() => this.inputs.accordionPanel()?.id());
|
|
1804
|
-
tabIndex = computed(() => this.inputs.accordionGroup().focusManager.isFocusable(this) ? 0 : -1);
|
|
1805
|
-
disabled = computed(() => this.inputs.disabled() || this.inputs.accordionGroup().disabled());
|
|
1806
|
-
index = computed(() => this.inputs.accordionGroup().items().indexOf(this));
|
|
1807
|
-
constructor(inputs) {
|
|
1808
|
-
this.inputs = inputs;
|
|
1809
|
-
this.id = inputs.id;
|
|
1810
|
-
this.element = inputs.element;
|
|
1811
|
-
this.value = inputs.value;
|
|
1812
|
-
this.expansionControl = new ExpansionControl({
|
|
1813
|
-
...inputs,
|
|
1814
|
-
expansionId: inputs.value,
|
|
1815
|
-
expandable: () => true,
|
|
1816
|
-
expansionManager: inputs.accordionGroup().expansionManager
|
|
1817
|
-
});
|
|
1818
|
-
this.expandable = this.expansionControl.isExpandable;
|
|
1819
|
-
this.expansionId = this.expansionControl.expansionId;
|
|
1820
|
-
this.expanded = this.expansionControl.isExpanded;
|
|
1821
|
-
}
|
|
1822
1805
|
prevKey = computed(() => {
|
|
1823
|
-
if (this.inputs.
|
|
1806
|
+
if (this.inputs.orientation() === 'vertical') {
|
|
1824
1807
|
return 'ArrowUp';
|
|
1825
1808
|
}
|
|
1826
|
-
return this.inputs.
|
|
1809
|
+
return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
|
|
1827
1810
|
});
|
|
1828
1811
|
nextKey = computed(() => {
|
|
1829
|
-
if (this.inputs.
|
|
1812
|
+
if (this.inputs.orientation() === 'vertical') {
|
|
1830
1813
|
return 'ArrowDown';
|
|
1831
1814
|
}
|
|
1832
|
-
return this.inputs.
|
|
1815
|
+
return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
|
|
1833
1816
|
});
|
|
1834
1817
|
keydown = computed(() => {
|
|
1835
|
-
return new KeyboardEventManager().on(this.prevKey, () => this.
|
|
1818
|
+
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());
|
|
1836
1819
|
});
|
|
1837
1820
|
pointerdown = computed(() => {
|
|
1838
1821
|
return new PointerEventManager().on(e => {
|
|
1839
|
-
const item = this.
|
|
1840
|
-
if (item)
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
}
|
|
1822
|
+
const item = this.inputs.getItem(e.target);
|
|
1823
|
+
if (!item) return;
|
|
1824
|
+
this.navigationBehavior.goto(item);
|
|
1825
|
+
this.expansionBehavior.toggle(item);
|
|
1844
1826
|
});
|
|
1845
1827
|
});
|
|
1846
1828
|
onKeydown(event) {
|
|
@@ -1850,26 +1832,51 @@ class AccordionTriggerPattern {
|
|
|
1850
1832
|
this.pointerdown().handle(event);
|
|
1851
1833
|
}
|
|
1852
1834
|
onFocus(event) {
|
|
1853
|
-
const item = this.
|
|
1854
|
-
if (item
|
|
1855
|
-
|
|
1856
|
-
|
|
1835
|
+
const item = this.inputs.getItem(event.target);
|
|
1836
|
+
if (!item) return;
|
|
1837
|
+
if (!this.focusBehavior.isFocusable(item)) return;
|
|
1838
|
+
this.focusBehavior.focus(item);
|
|
1857
1839
|
}
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1840
|
+
toggle() {
|
|
1841
|
+
const activeItem = this.inputs.activeItem();
|
|
1842
|
+
if (activeItem === undefined) return;
|
|
1843
|
+
this.expansionBehavior.toggle(activeItem);
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
class AccordionTriggerPattern {
|
|
1847
|
+
inputs;
|
|
1848
|
+
id = () => this.inputs.id();
|
|
1849
|
+
element = () => this.inputs.element();
|
|
1850
|
+
expandable = () => true;
|
|
1851
|
+
expanded;
|
|
1852
|
+
active = computed(() => this.inputs.accordionGroup().inputs.activeItem() === this);
|
|
1853
|
+
controls = computed(() => this.inputs.accordionPanel()?.inputs.id());
|
|
1854
|
+
tabIndex = computed(() => this.inputs.accordionGroup().focusBehavior.isFocusable(this) ? 0 : -1);
|
|
1855
|
+
disabled = computed(() => this.inputs.disabled() || this.inputs.accordionGroup().inputs.disabled());
|
|
1856
|
+
hardDisabled = computed(() => this.disabled() && !this.inputs.accordionGroup().inputs.softDisabled());
|
|
1857
|
+
index = computed(() => this.inputs.accordionGroup().inputs.items().indexOf(this));
|
|
1858
|
+
constructor(inputs) {
|
|
1859
|
+
this.inputs = inputs;
|
|
1860
|
+
this.expanded = inputs.expanded;
|
|
1861
|
+
}
|
|
1862
|
+
open() {
|
|
1863
|
+
this.inputs.accordionGroup().expansionBehavior.open(this);
|
|
1864
|
+
}
|
|
1865
|
+
close() {
|
|
1866
|
+
this.inputs.accordionGroup().expansionBehavior.close(this);
|
|
1867
|
+
}
|
|
1868
|
+
toggle() {
|
|
1869
|
+
this.inputs.accordionGroup().expansionBehavior.toggle(this);
|
|
1864
1870
|
}
|
|
1865
1871
|
}
|
|
1866
1872
|
class AccordionPanelPattern {
|
|
1867
1873
|
inputs;
|
|
1874
|
+
id;
|
|
1875
|
+
accordionTrigger;
|
|
1868
1876
|
hidden;
|
|
1869
1877
|
constructor(inputs) {
|
|
1870
1878
|
this.inputs = inputs;
|
|
1871
1879
|
this.id = inputs.id;
|
|
1872
|
-
this.value = inputs.value;
|
|
1873
1880
|
this.accordionTrigger = inputs.accordionTrigger;
|
|
1874
1881
|
this.hidden = computed(() => inputs.accordionTrigger()?.expanded() === false);
|
|
1875
1882
|
}
|
|
@@ -1877,22 +1884,20 @@ class AccordionPanelPattern {
|
|
|
1877
1884
|
|
|
1878
1885
|
class TreeItemPattern {
|
|
1879
1886
|
inputs;
|
|
1880
|
-
id;
|
|
1881
|
-
value;
|
|
1882
|
-
element;
|
|
1883
|
-
disabled;
|
|
1884
|
-
searchTerm;
|
|
1885
|
-
tree;
|
|
1886
|
-
parent;
|
|
1887
|
-
children;
|
|
1887
|
+
id = () => this.inputs.id();
|
|
1888
|
+
value = () => this.inputs.value();
|
|
1889
|
+
element = () => this.inputs.element();
|
|
1890
|
+
disabled = () => this.inputs.disabled();
|
|
1891
|
+
searchTerm = () => this.inputs.searchTerm();
|
|
1892
|
+
tree = () => this.inputs.tree();
|
|
1893
|
+
parent = () => this.inputs.parent();
|
|
1894
|
+
children = () => this.inputs.children();
|
|
1888
1895
|
index = computed(() => this.tree().visibleItems().indexOf(this));
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
selectable;
|
|
1896
|
+
expansionBehavior;
|
|
1897
|
+
expandable = () => this.inputs.hasChildren();
|
|
1898
|
+
selectable = () => this.inputs.selectable();
|
|
1899
|
+
expanded;
|
|
1894
1900
|
level = computed(() => this.parent().level() + 1);
|
|
1895
|
-
expanded = computed(() => this.expansion.isExpanded());
|
|
1896
1901
|
visible = computed(() => this.parent().expanded() && this.parent().visible());
|
|
1897
1902
|
setsize = computed(() => this.parent().children().length);
|
|
1898
1903
|
posinset = computed(() => this.parent().children().indexOf(this) + 1);
|
|
@@ -1905,7 +1910,7 @@ class TreeItemPattern {
|
|
|
1905
1910
|
if (!this.selectable()) {
|
|
1906
1911
|
return undefined;
|
|
1907
1912
|
}
|
|
1908
|
-
return this.tree().
|
|
1913
|
+
return this.tree().values().includes(this.value());
|
|
1909
1914
|
});
|
|
1910
1915
|
current = computed(() => {
|
|
1911
1916
|
if (!this.tree().nav()) {
|
|
@@ -1914,31 +1919,14 @@ class TreeItemPattern {
|
|
|
1914
1919
|
if (!this.selectable()) {
|
|
1915
1920
|
return undefined;
|
|
1916
1921
|
}
|
|
1917
|
-
return this.tree().
|
|
1922
|
+
return this.tree().values().includes(this.value()) ? this.tree().currentType() : undefined;
|
|
1918
1923
|
});
|
|
1919
1924
|
constructor(inputs) {
|
|
1920
1925
|
this.inputs = inputs;
|
|
1921
|
-
this.
|
|
1922
|
-
this.
|
|
1923
|
-
this.element = inputs.element;
|
|
1924
|
-
this.disabled = inputs.disabled;
|
|
1925
|
-
this.searchTerm = inputs.searchTerm;
|
|
1926
|
-
this.expansionId = inputs.id;
|
|
1927
|
-
this.tree = inputs.tree;
|
|
1928
|
-
this.parent = inputs.parent;
|
|
1929
|
-
this.children = inputs.children;
|
|
1930
|
-
this.expandable = inputs.hasChildren;
|
|
1931
|
-
this.selectable = inputs.selectable;
|
|
1932
|
-
this.expansion = new ExpansionControl({
|
|
1933
|
-
...inputs,
|
|
1934
|
-
expandable: this.expandable,
|
|
1935
|
-
expansionId: this.expansionId,
|
|
1936
|
-
expansionManager: this.parent().expansionManager
|
|
1937
|
-
});
|
|
1938
|
-
this.expansionManager = new ListExpansion({
|
|
1926
|
+
this.expanded = inputs.expanded;
|
|
1927
|
+
this.expansionBehavior = new ListExpansion({
|
|
1939
1928
|
...inputs,
|
|
1940
1929
|
multiExpandable: () => true,
|
|
1941
|
-
expandedIds: signal([]),
|
|
1942
1930
|
items: this.children,
|
|
1943
1931
|
disabled: computed(() => this.tree()?.disabled() ?? false)
|
|
1944
1932
|
});
|
|
@@ -1947,7 +1935,7 @@ class TreeItemPattern {
|
|
|
1947
1935
|
class TreePattern {
|
|
1948
1936
|
inputs;
|
|
1949
1937
|
listBehavior;
|
|
1950
|
-
|
|
1938
|
+
expansionBehavior;
|
|
1951
1939
|
level = () => 0;
|
|
1952
1940
|
expanded = () => true;
|
|
1953
1941
|
visible = () => true;
|
|
@@ -1956,29 +1944,30 @@ class TreePattern {
|
|
|
1956
1944
|
children = computed(() => this.inputs.allItems().filter(item => item.level() === this.level() + 1));
|
|
1957
1945
|
visibleItems = computed(() => this.inputs.allItems().filter(item => item.visible()));
|
|
1958
1946
|
followFocus = computed(() => this.inputs.selectionMode() === 'follow');
|
|
1947
|
+
isRtl = computed(() => this.inputs.textDirection() === 'rtl');
|
|
1959
1948
|
prevKey = computed(() => {
|
|
1960
1949
|
if (this.inputs.orientation() === 'vertical') {
|
|
1961
1950
|
return 'ArrowUp';
|
|
1962
1951
|
}
|
|
1963
|
-
return this.
|
|
1952
|
+
return this.isRtl() ? 'ArrowRight' : 'ArrowLeft';
|
|
1964
1953
|
});
|
|
1965
1954
|
nextKey = computed(() => {
|
|
1966
1955
|
if (this.inputs.orientation() === 'vertical') {
|
|
1967
1956
|
return 'ArrowDown';
|
|
1968
1957
|
}
|
|
1969
|
-
return this.
|
|
1958
|
+
return this.isRtl() ? 'ArrowLeft' : 'ArrowRight';
|
|
1970
1959
|
});
|
|
1971
1960
|
collapseKey = computed(() => {
|
|
1972
1961
|
if (this.inputs.orientation() === 'horizontal') {
|
|
1973
1962
|
return 'ArrowUp';
|
|
1974
1963
|
}
|
|
1975
|
-
return this.
|
|
1964
|
+
return this.isRtl() ? 'ArrowRight' : 'ArrowLeft';
|
|
1976
1965
|
});
|
|
1977
1966
|
expandKey = computed(() => {
|
|
1978
1967
|
if (this.inputs.orientation() === 'horizontal') {
|
|
1979
1968
|
return 'ArrowDown';
|
|
1980
1969
|
}
|
|
1981
|
-
return this.
|
|
1970
|
+
return this.isRtl() ? 'ArrowLeft' : 'ArrowRight';
|
|
1982
1971
|
});
|
|
1983
1972
|
dynamicSpaceKey = computed(() => this.listBehavior.isTyping() ? '' : ' ');
|
|
1984
1973
|
typeaheadRegexp = /^.$/;
|
|
@@ -2064,45 +2053,33 @@ class TreePattern {
|
|
|
2064
2053
|
}
|
|
2065
2054
|
return manager;
|
|
2066
2055
|
});
|
|
2067
|
-
id;
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2056
|
+
id = () => this.inputs.id();
|
|
2057
|
+
element = () => this.inputs.element();
|
|
2058
|
+
nav = () => this.inputs.nav();
|
|
2059
|
+
currentType = () => this.inputs.currentType();
|
|
2060
|
+
allItems = () => this.inputs.allItems();
|
|
2061
|
+
focusMode = () => this.inputs.focusMode();
|
|
2062
|
+
disabled = () => this.inputs.disabled();
|
|
2063
|
+
activeItem;
|
|
2064
|
+
softDisabled = () => this.inputs.softDisabled();
|
|
2065
|
+
wrap = () => this.inputs.wrap();
|
|
2066
|
+
orientation = () => this.inputs.orientation();
|
|
2067
|
+
textDirection = () => this.textDirection();
|
|
2068
|
+
multi = computed(() => this.nav() ? false : this.inputs.multi());
|
|
2069
|
+
selectionMode = () => this.inputs.selectionMode();
|
|
2070
|
+
typeaheadDelay = () => this.inputs.typeaheadDelay();
|
|
2071
|
+
values;
|
|
2081
2072
|
constructor(inputs) {
|
|
2082
2073
|
this.inputs = inputs;
|
|
2083
|
-
this.id = inputs.id;
|
|
2084
|
-
this.nav = inputs.nav;
|
|
2085
|
-
this.currentType = inputs.currentType;
|
|
2086
|
-
this.allItems = inputs.allItems;
|
|
2087
|
-
this.focusMode = inputs.focusMode;
|
|
2088
|
-
this.disabled = inputs.disabled;
|
|
2089
2074
|
this.activeItem = inputs.activeItem;
|
|
2090
|
-
this.
|
|
2091
|
-
this.wrap = inputs.wrap;
|
|
2092
|
-
this.orientation = inputs.orientation;
|
|
2093
|
-
this.textDirection = inputs.textDirection;
|
|
2094
|
-
this.multi = computed(() => this.nav() ? false : this.inputs.multi());
|
|
2095
|
-
this.selectionMode = inputs.selectionMode;
|
|
2096
|
-
this.typeaheadDelay = inputs.typeaheadDelay;
|
|
2097
|
-
this.value = inputs.value;
|
|
2075
|
+
this.values = inputs.values;
|
|
2098
2076
|
this.listBehavior = new List({
|
|
2099
2077
|
...inputs,
|
|
2100
2078
|
items: this.visibleItems,
|
|
2101
2079
|
multi: this.multi
|
|
2102
2080
|
});
|
|
2103
|
-
this.
|
|
2081
|
+
this.expansionBehavior = new ListExpansion({
|
|
2104
2082
|
multiExpandable: () => true,
|
|
2105
|
-
expandedIds: signal([]),
|
|
2106
2083
|
items: this.children,
|
|
2107
2084
|
disabled: this.disabled
|
|
2108
2085
|
});
|
|
@@ -2147,14 +2124,14 @@ class TreePattern {
|
|
|
2147
2124
|
if (item.expanded()) {
|
|
2148
2125
|
this.collapse();
|
|
2149
2126
|
} else {
|
|
2150
|
-
|
|
2127
|
+
this.expansionBehavior.open(item);
|
|
2151
2128
|
}
|
|
2152
2129
|
}
|
|
2153
2130
|
expand(opts) {
|
|
2154
2131
|
const item = this.activeItem();
|
|
2155
2132
|
if (!item || !this.listBehavior.isFocusable(item)) return;
|
|
2156
2133
|
if (item.expandable() && !item.expanded()) {
|
|
2157
|
-
|
|
2134
|
+
this.expansionBehavior.open(item);
|
|
2158
2135
|
} else if (item.expanded() && item.children().some(item => this.listBehavior.isFocusable(item))) {
|
|
2159
2136
|
this.listBehavior.next(opts);
|
|
2160
2137
|
}
|
|
@@ -2162,13 +2139,13 @@ class TreePattern {
|
|
|
2162
2139
|
expandSiblings(item) {
|
|
2163
2140
|
item ??= this.activeItem();
|
|
2164
2141
|
const siblings = item?.parent()?.children();
|
|
2165
|
-
siblings?.forEach(item =>
|
|
2142
|
+
siblings?.forEach(item => this.expansionBehavior.open(item));
|
|
2166
2143
|
}
|
|
2167
2144
|
collapse(opts) {
|
|
2168
2145
|
const item = this.activeItem();
|
|
2169
2146
|
if (!item || !this.listBehavior.isFocusable(item)) return;
|
|
2170
2147
|
if (item.expandable() && item.expanded()) {
|
|
2171
|
-
|
|
2148
|
+
this.expansionBehavior.close(item);
|
|
2172
2149
|
} else if (item.parent() && item.parent() !== this) {
|
|
2173
2150
|
const parentItem = item.parent();
|
|
2174
2151
|
if (parentItem instanceof TreeItemPattern && this.listBehavior.isFocusable(parentItem)) {
|
|
@@ -2190,6 +2167,7 @@ class ComboboxTreePattern extends TreePattern {
|
|
|
2190
2167
|
isItemCollapsible = () => this.inputs.activeItem()?.parent() instanceof TreeItemPattern;
|
|
2191
2168
|
role = () => 'tree';
|
|
2192
2169
|
activeId = computed(() => this.listBehavior.activeDescendant());
|
|
2170
|
+
getActiveItem = () => this.inputs.activeItem();
|
|
2193
2171
|
items = computed(() => this.inputs.allItems());
|
|
2194
2172
|
tabIndex = () => -1;
|
|
2195
2173
|
constructor(inputs) {
|
|
@@ -2215,14 +2193,14 @@ class ComboboxTreePattern extends TreePattern {
|
|
|
2215
2193
|
clearSelection = () => this.listBehavior.deselectAll();
|
|
2216
2194
|
getItem = e => this._getItem(e);
|
|
2217
2195
|
getSelectedItems = () => this.inputs.allItems().filter(item => item.selected());
|
|
2218
|
-
setValue = value => this.inputs.
|
|
2196
|
+
setValue = value => this.inputs.values.set(value ? [value] : []);
|
|
2219
2197
|
expandItem = () => this.expand();
|
|
2220
2198
|
collapseItem = () => this.collapse();
|
|
2221
2199
|
isItemExpandable(item = this.inputs.activeItem()) {
|
|
2222
2200
|
return item ? item.expandable() : false;
|
|
2223
2201
|
}
|
|
2224
|
-
expandAll = () => this.items().forEach(item =>
|
|
2225
|
-
collapseAll = () => this.items().forEach(item => item.
|
|
2202
|
+
expandAll = () => this.items().forEach(item => this.expansionBehavior.open(item));
|
|
2203
|
+
collapseAll = () => this.items().forEach(item => item.expansionBehavior.close(item));
|
|
2226
2204
|
isItemSelectable = (item = this.inputs.activeItem()) => {
|
|
2227
2205
|
return item ? item.selectable() : false;
|
|
2228
2206
|
};
|
|
@@ -2334,5 +2312,5 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
2334
2312
|
ctorParameters: () => []
|
|
2335
2313
|
});
|
|
2336
2314
|
|
|
2337
|
-
export { AccordionGroupPattern, AccordionPanelPattern, AccordionTriggerPattern, ComboboxListboxPattern, ComboboxPattern, ComboboxTreePattern, DeferredContent, DeferredContentAware, ListboxPattern, MenuBarPattern, MenuItemPattern, MenuPattern, MenuTriggerPattern, OptionPattern, TabListPattern, TabPanelPattern, TabPattern, ToolbarPattern, ToolbarWidgetGroupPattern, ToolbarWidgetPattern, TreeItemPattern, TreePattern, convertGetterSetterToWritableSignalLike };
|
|
2315
|
+
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 };
|
|
2338
2316
|
//# sourceMappingURL=private.mjs.map
|