@angular/aria 21.0.0-rc.1 → 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 +439 -55
- package/_adev_assets/aria-combobox.json +343 -35
- package/_adev_assets/aria-grid.json +345 -77
- package/_adev_assets/aria-listbox.json +113 -33
- package/_adev_assets/aria-menu.json +366 -141
- package/_adev_assets/aria-tabs.json +261 -77
- package/_adev_assets/aria-toolbar.json +72 -33
- package/_adev_assets/aria-tree.json +169 -26
- package/fesm2022/_widget-chunk.mjs +388 -57
- package/fesm2022/_widget-chunk.mjs.map +1 -1
- package/fesm2022/accordion.mjs +121 -68
- package/fesm2022/accordion.mjs.map +1 -1
- package/fesm2022/aria.mjs +1 -1
- package/fesm2022/aria.mjs.map +1 -1
- package/fesm2022/combobox.mjs +132 -21
- package/fesm2022/combobox.mjs.map +1 -1
- package/fesm2022/grid.mjs +198 -61
- package/fesm2022/grid.mjs.map +1 -1
- package/fesm2022/listbox.mjs +42 -31
- package/fesm2022/listbox.mjs.map +1 -1
- package/fesm2022/menu.mjs +173 -67
- package/fesm2022/menu.mjs.map +1 -1
- package/fesm2022/private.mjs +415 -439
- package/fesm2022/private.mjs.map +1 -1
- package/fesm2022/tabs.mjs +86 -55
- package/fesm2022/tabs.mjs.map +1 -1
- package/fesm2022/toolbar.mjs +13 -25
- package/fesm2022/toolbar.mjs.map +1 -1
- package/fesm2022/tree.mjs +86 -44
- 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 +133 -34
- package/types/combobox.d.ts +145 -12
- package/types/grid.d.ts +149 -31
- package/types/listbox.d.ts +58 -26
- package/types/menu.d.ts +130 -46
- package/types/private.d.ts +210 -250
- package/types/tabs.d.ts +119 -39
- package/types/toolbar.d.ts +49 -29
- package/types/tree.d.ts +113 -41
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();
|
|
@@ -233,11 +298,15 @@ class ComboboxPattern {
|
|
|
233
298
|
}
|
|
234
299
|
this.close();
|
|
235
300
|
if (!this.readonly()) {
|
|
236
|
-
|
|
301
|
+
popupControls?.clearSelection();
|
|
237
302
|
}
|
|
238
303
|
}
|
|
239
304
|
open(nav) {
|
|
240
305
|
this.expanded.set(true);
|
|
306
|
+
const popupControls = this.inputs.popupControls();
|
|
307
|
+
if (popupControls instanceof ComboboxDialogPattern) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
241
310
|
const inputEl = this.inputs.inputEl();
|
|
242
311
|
if (inputEl && this.inputs.filterMode() === 'highlight') {
|
|
243
312
|
const isHighlighting = inputEl.selectionStart !== inputEl.value.length;
|
|
@@ -253,21 +322,21 @@ class ComboboxPattern {
|
|
|
253
322
|
this.last();
|
|
254
323
|
}
|
|
255
324
|
if (nav?.selected) {
|
|
256
|
-
const selectedItem =
|
|
257
|
-
selectedItem ?
|
|
325
|
+
const selectedItem = popupControls?.items().find(i => popupControls?.getSelectedItems().includes(i));
|
|
326
|
+
selectedItem ? popupControls?.focus(selectedItem) : this.first();
|
|
258
327
|
}
|
|
259
328
|
}
|
|
260
329
|
next() {
|
|
261
|
-
this._navigate(() => this.
|
|
330
|
+
this._navigate(() => this.listControls()?.next());
|
|
262
331
|
}
|
|
263
332
|
prev() {
|
|
264
|
-
this._navigate(() => this.
|
|
333
|
+
this._navigate(() => this.listControls()?.prev());
|
|
265
334
|
}
|
|
266
335
|
first() {
|
|
267
|
-
this._navigate(() => this.
|
|
336
|
+
this._navigate(() => this.listControls()?.first());
|
|
268
337
|
}
|
|
269
338
|
last() {
|
|
270
|
-
this._navigate(() => this.
|
|
339
|
+
this._navigate(() => this.listControls()?.last());
|
|
271
340
|
}
|
|
272
341
|
collapseItem() {
|
|
273
342
|
const controls = this.inputs.popupControls();
|
|
@@ -278,7 +347,7 @@ class ComboboxPattern {
|
|
|
278
347
|
this._navigate(() => controls?.expandItem());
|
|
279
348
|
}
|
|
280
349
|
select(opts = {}) {
|
|
281
|
-
const controls = this.
|
|
350
|
+
const controls = this.listControls();
|
|
282
351
|
if (opts.item) {
|
|
283
352
|
controls?.focus(opts.item, {
|
|
284
353
|
focusElement: false
|
|
@@ -294,7 +363,7 @@ class ComboboxPattern {
|
|
|
294
363
|
}
|
|
295
364
|
commit() {
|
|
296
365
|
const inputEl = this.inputs.inputEl();
|
|
297
|
-
const selectedItems = this.
|
|
366
|
+
const selectedItems = this.listControls()?.getSelectedItems();
|
|
298
367
|
if (!inputEl) {
|
|
299
368
|
return;
|
|
300
369
|
}
|
|
@@ -311,7 +380,7 @@ class ComboboxPattern {
|
|
|
311
380
|
this.select();
|
|
312
381
|
}
|
|
313
382
|
if (this.inputs.filterMode() === 'highlight') {
|
|
314
|
-
const selectedItem = this.
|
|
383
|
+
const selectedItem = this.listControls()?.getSelectedItems()[0];
|
|
315
384
|
if (!selectedItem) {
|
|
316
385
|
return;
|
|
317
386
|
}
|
|
@@ -324,116 +393,23 @@ class ComboboxPattern {
|
|
|
324
393
|
}
|
|
325
394
|
}
|
|
326
395
|
}
|
|
327
|
-
|
|
328
|
-
class ListFocus {
|
|
396
|
+
class ComboboxDialogPattern {
|
|
329
397
|
inputs;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
activeIndex = computed(() => {
|
|
335
|
-
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());
|
|
336
402
|
});
|
|
337
403
|
constructor(inputs) {
|
|
338
404
|
this.inputs = inputs;
|
|
339
405
|
}
|
|
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;
|
|
406
|
+
onKeydown(event) {
|
|
407
|
+
this.keydown().handle(event);
|
|
425
408
|
}
|
|
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
|
-
}
|
|
409
|
+
onClick(event) {
|
|
410
|
+
if (event.target === this.inputs.element()) {
|
|
411
|
+
this.inputs.combobox.close();
|
|
435
412
|
}
|
|
436
|
-
return;
|
|
437
413
|
}
|
|
438
414
|
}
|
|
439
415
|
|
|
@@ -441,7 +417,7 @@ class ListSelection {
|
|
|
441
417
|
inputs;
|
|
442
418
|
rangeStartIndex = signal(0);
|
|
443
419
|
rangeEndIndex = signal(0);
|
|
444
|
-
selectedItems = computed(() => this.inputs.items().filter(item => this.inputs.
|
|
420
|
+
selectedItems = computed(() => this.inputs.items().filter(item => this.inputs.values().includes(item.value())));
|
|
445
421
|
constructor(inputs) {
|
|
446
422
|
this.inputs = inputs;
|
|
447
423
|
}
|
|
@@ -449,7 +425,7 @@ class ListSelection {
|
|
|
449
425
|
anchor: true
|
|
450
426
|
}) {
|
|
451
427
|
item = item ?? this.inputs.focusManager.inputs.activeItem();
|
|
452
|
-
if (!item || item.disabled() || !item.selectable() || this.inputs.
|
|
428
|
+
if (!item || item.disabled() || !item.selectable() || this.inputs.values().includes(item.value())) {
|
|
453
429
|
return;
|
|
454
430
|
}
|
|
455
431
|
if (!this.inputs.multi()) {
|
|
@@ -459,24 +435,24 @@ class ListSelection {
|
|
|
459
435
|
if (opts.anchor) {
|
|
460
436
|
this.beginRangeSelection(index);
|
|
461
437
|
}
|
|
462
|
-
this.inputs.
|
|
438
|
+
this.inputs.values.update(values => values.concat(item.value()));
|
|
463
439
|
}
|
|
464
440
|
deselect(item) {
|
|
465
441
|
item = item ?? this.inputs.focusManager.inputs.activeItem();
|
|
466
442
|
if (item && !item.disabled() && item.selectable()) {
|
|
467
|
-
this.inputs.
|
|
443
|
+
this.inputs.values.update(values => values.filter(value => value !== item.value()));
|
|
468
444
|
}
|
|
469
445
|
}
|
|
470
446
|
toggle(item) {
|
|
471
447
|
item = item ?? this.inputs.focusManager.inputs.activeItem();
|
|
472
448
|
if (item) {
|
|
473
|
-
this.inputs.
|
|
449
|
+
this.inputs.values().includes(item.value()) ? this.deselect(item) : this.select(item);
|
|
474
450
|
}
|
|
475
451
|
}
|
|
476
452
|
toggleOne() {
|
|
477
453
|
const item = this.inputs.focusManager.inputs.activeItem();
|
|
478
454
|
if (item) {
|
|
479
|
-
this.inputs.
|
|
455
|
+
this.inputs.values().includes(item.value()) ? this.deselect() : this.selectOne();
|
|
480
456
|
}
|
|
481
457
|
}
|
|
482
458
|
selectAll() {
|
|
@@ -491,14 +467,14 @@ class ListSelection {
|
|
|
491
467
|
this.beginRangeSelection();
|
|
492
468
|
}
|
|
493
469
|
deselectAll() {
|
|
494
|
-
for (const value of this.inputs.
|
|
470
|
+
for (const value of this.inputs.values()) {
|
|
495
471
|
const item = this.inputs.items().find(i => i.value() === value);
|
|
496
|
-
item ? this.deselect(item) : this.inputs.
|
|
472
|
+
item ? this.deselect(item) : this.inputs.values.update(values => values.filter(v => v !== value));
|
|
497
473
|
}
|
|
498
474
|
}
|
|
499
475
|
toggleAll() {
|
|
500
476
|
const selectableValues = this.inputs.items().filter(i => !i.disabled() && i.selectable()).map(i => i.value());
|
|
501
|
-
selectableValues.every(i => this.inputs.
|
|
477
|
+
selectableValues.every(i => this.inputs.values().includes(i)) ? this.deselectAll() : this.selectAll();
|
|
502
478
|
}
|
|
503
479
|
selectOne() {
|
|
504
480
|
const item = this.inputs.focusManager.inputs.activeItem();
|
|
@@ -506,7 +482,7 @@ class ListSelection {
|
|
|
506
482
|
return;
|
|
507
483
|
}
|
|
508
484
|
this.deselectAll();
|
|
509
|
-
if (this.inputs.
|
|
485
|
+
if (this.inputs.values().length > 0 && !this.inputs.multi()) {
|
|
510
486
|
return;
|
|
511
487
|
}
|
|
512
488
|
this.select();
|
|
@@ -585,7 +561,7 @@ class ListTypeahead {
|
|
|
585
561
|
this.timeout = setTimeout(() => {
|
|
586
562
|
this._query.set('');
|
|
587
563
|
this._startIndex.set(undefined);
|
|
588
|
-
}, this.inputs.typeaheadDelay()
|
|
564
|
+
}, this.inputs.typeaheadDelay());
|
|
589
565
|
return true;
|
|
590
566
|
}
|
|
591
567
|
_getItem() {
|
|
@@ -843,8 +819,8 @@ class ListboxPattern {
|
|
|
843
819
|
}
|
|
844
820
|
validate() {
|
|
845
821
|
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.
|
|
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(', ')}`);
|
|
848
824
|
}
|
|
849
825
|
return violations;
|
|
850
826
|
}
|
|
@@ -889,7 +865,7 @@ class OptionPattern {
|
|
|
889
865
|
value;
|
|
890
866
|
index = computed(() => this.listbox()?.inputs.items().indexOf(this) ?? -1);
|
|
891
867
|
active = computed(() => this.listbox()?.inputs.activeItem() === this);
|
|
892
|
-
selected = computed(() => this.listbox()?.inputs.
|
|
868
|
+
selected = computed(() => this.listbox()?.inputs.values().includes(this.value()));
|
|
893
869
|
selectable = () => true;
|
|
894
870
|
disabled;
|
|
895
871
|
searchTerm;
|
|
@@ -930,6 +906,7 @@ class ComboboxListboxPattern extends ListboxPattern {
|
|
|
930
906
|
focus = (item, opts) => {
|
|
931
907
|
this.listBehavior.goto(item, opts);
|
|
932
908
|
};
|
|
909
|
+
getActiveItem = () => this.inputs.activeItem();
|
|
933
910
|
next = () => this.listBehavior.next();
|
|
934
911
|
prev = () => this.listBehavior.prev();
|
|
935
912
|
last = () => this.listBehavior.last();
|
|
@@ -941,7 +918,7 @@ class ComboboxListboxPattern extends ListboxPattern {
|
|
|
941
918
|
getItem = e => this._getItem(e);
|
|
942
919
|
getSelectedItems = () => {
|
|
943
920
|
const items = [];
|
|
944
|
-
for (const value of this.inputs.
|
|
921
|
+
for (const value of this.inputs.values()) {
|
|
945
922
|
const item = this.items().find(i => i.value() === value);
|
|
946
923
|
if (item) {
|
|
947
924
|
items.push(item);
|
|
@@ -949,17 +926,21 @@ class ComboboxListboxPattern extends ListboxPattern {
|
|
|
949
926
|
}
|
|
950
927
|
return items;
|
|
951
928
|
};
|
|
952
|
-
setValue = value => this.inputs.
|
|
929
|
+
setValue = value => this.inputs.values.set(value ? [value] : []);
|
|
953
930
|
}
|
|
954
931
|
|
|
955
932
|
class MenuPattern {
|
|
956
933
|
inputs;
|
|
957
934
|
id;
|
|
958
935
|
role = () => 'menu';
|
|
959
|
-
|
|
936
|
+
disabled = () => this.inputs.disabled();
|
|
937
|
+
visible = computed(() => this.inputs.parent() ? !!this.inputs.parent()?.expanded() : true);
|
|
960
938
|
listBehavior;
|
|
961
939
|
isFocused = signal(false);
|
|
962
940
|
hasBeenFocused = signal(false);
|
|
941
|
+
_openTimeout;
|
|
942
|
+
_closeTimeout;
|
|
943
|
+
tabIndex = () => this.listBehavior.tabIndex();
|
|
963
944
|
shouldFocus = computed(() => {
|
|
964
945
|
const root = this.root();
|
|
965
946
|
if (root instanceof MenuTriggerPattern) {
|
|
@@ -1000,40 +981,67 @@ class MenuPattern {
|
|
|
1000
981
|
this.id = inputs.id;
|
|
1001
982
|
this.listBehavior = new List({
|
|
1002
983
|
...inputs,
|
|
1003
|
-
|
|
1004
|
-
disabled: () => false
|
|
984
|
+
values: signal([])
|
|
1005
985
|
});
|
|
1006
986
|
}
|
|
1007
987
|
setDefaultState() {
|
|
1008
988
|
if (!this.inputs.parent()) {
|
|
1009
|
-
this.
|
|
989
|
+
this.listBehavior.goto(this.inputs.items()[0], {
|
|
990
|
+
focusElement: false
|
|
991
|
+
});
|
|
1010
992
|
}
|
|
1011
993
|
}
|
|
1012
994
|
onKeydown(event) {
|
|
1013
995
|
this.keydownManager().handle(event);
|
|
1014
996
|
}
|
|
1015
997
|
onMouseOver(event) {
|
|
1016
|
-
if (!this.
|
|
998
|
+
if (!this.visible()) {
|
|
1017
999
|
return;
|
|
1018
1000
|
}
|
|
1019
1001
|
const item = this.inputs.items().find(i => i.element()?.contains(event.target));
|
|
1020
1002
|
if (!item) {
|
|
1021
1003
|
return;
|
|
1022
1004
|
}
|
|
1005
|
+
const parent = this.inputs.parent();
|
|
1023
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
|
+
}
|
|
1024
1016
|
if (activeItem && activeItem !== item) {
|
|
1025
|
-
|
|
1017
|
+
this._closeItem(activeItem);
|
|
1026
1018
|
}
|
|
1027
|
-
if (item.expanded()
|
|
1028
|
-
|
|
1029
|
-
item.submenu()?.listBehavior.unfocus();
|
|
1019
|
+
if (item.expanded()) {
|
|
1020
|
+
this._clearCloseTimeout();
|
|
1030
1021
|
}
|
|
1031
|
-
|
|
1022
|
+
this._openItem(item);
|
|
1032
1023
|
this.listBehavior.goto(item, {
|
|
1033
1024
|
focusElement: this.shouldFocus()
|
|
1034
1025
|
});
|
|
1035
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
|
+
}
|
|
1036
1043
|
onMouseOut(event) {
|
|
1044
|
+
this._clearOpenTimeout();
|
|
1037
1045
|
if (this.isFocused()) {
|
|
1038
1046
|
return;
|
|
1039
1047
|
}
|
|
@@ -1082,7 +1090,7 @@ class MenuPattern {
|
|
|
1082
1090
|
return;
|
|
1083
1091
|
}
|
|
1084
1092
|
}
|
|
1085
|
-
if (this.
|
|
1093
|
+
if (this.visible() && !parentEl?.contains(relatedTarget) && !this.inputs.element()?.contains(relatedTarget)) {
|
|
1086
1094
|
this.isFocused.set(false);
|
|
1087
1095
|
this.inputs.parent()?.close();
|
|
1088
1096
|
}
|
|
@@ -1153,6 +1161,9 @@ class MenuPattern {
|
|
|
1153
1161
|
root.next();
|
|
1154
1162
|
}
|
|
1155
1163
|
}
|
|
1164
|
+
close() {
|
|
1165
|
+
this.inputs.parent()?.close();
|
|
1166
|
+
}
|
|
1156
1167
|
closeAll() {
|
|
1157
1168
|
const root = this.root();
|
|
1158
1169
|
if (root instanceof MenuTriggerPattern) {
|
|
@@ -1169,10 +1180,27 @@ class MenuPattern {
|
|
|
1169
1180
|
});
|
|
1170
1181
|
}
|
|
1171
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
|
+
}
|
|
1172
1199
|
}
|
|
1173
1200
|
class MenuBarPattern {
|
|
1174
1201
|
inputs;
|
|
1175
1202
|
listBehavior;
|
|
1203
|
+
tabIndex = () => this.listBehavior.tabIndex();
|
|
1176
1204
|
_nextKey = computed(() => {
|
|
1177
1205
|
return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
|
|
1178
1206
|
});
|
|
@@ -1183,6 +1211,7 @@ class MenuBarPattern {
|
|
|
1183
1211
|
typeaheadRegexp = /^.$/;
|
|
1184
1212
|
isFocused = signal(false);
|
|
1185
1213
|
hasBeenFocused = signal(false);
|
|
1214
|
+
disabled = () => this.inputs.disabled();
|
|
1186
1215
|
keydownManager = computed(() => {
|
|
1187
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({
|
|
1188
1217
|
first: true
|
|
@@ -1196,10 +1225,7 @@ class MenuBarPattern {
|
|
|
1196
1225
|
});
|
|
1197
1226
|
constructor(inputs) {
|
|
1198
1227
|
this.inputs = inputs;
|
|
1199
|
-
this.listBehavior = new List(
|
|
1200
|
-
...inputs,
|
|
1201
|
-
disabled: () => false
|
|
1202
|
-
});
|
|
1228
|
+
this.listBehavior = new List(inputs);
|
|
1203
1229
|
}
|
|
1204
1230
|
setDefaultState() {
|
|
1205
1231
|
this.inputs.activeItem.set(this.inputs.items()[0]);
|
|
@@ -1277,10 +1303,12 @@ class MenuBarPattern {
|
|
|
1277
1303
|
class MenuTriggerPattern {
|
|
1278
1304
|
inputs;
|
|
1279
1305
|
expanded = signal(false);
|
|
1306
|
+
hasBeenFocused = signal(false);
|
|
1280
1307
|
role = () => 'button';
|
|
1281
1308
|
hasPopup = () => true;
|
|
1282
1309
|
menu;
|
|
1283
1310
|
tabIndex = computed(() => this.expanded() && this.menu()?.inputs.activeItem() ? -1 : 0);
|
|
1311
|
+
disabled = () => this.inputs.disabled();
|
|
1284
1312
|
keydownManager = computed(() => {
|
|
1285
1313
|
return new KeyboardEventManager().on(' ', () => this.open({
|
|
1286
1314
|
first: true
|
|
@@ -1299,12 +1327,19 @@ class MenuTriggerPattern {
|
|
|
1299
1327
|
this.menu = this.inputs.menu;
|
|
1300
1328
|
}
|
|
1301
1329
|
onKeydown(event) {
|
|
1302
|
-
this.
|
|
1330
|
+
if (!this.inputs.disabled()) {
|
|
1331
|
+
this.keydownManager().handle(event);
|
|
1332
|
+
}
|
|
1303
1333
|
}
|
|
1304
1334
|
onClick() {
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
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);
|
|
1308
1343
|
}
|
|
1309
1344
|
onFocusOut(event) {
|
|
1310
1345
|
const element = this.inputs.element();
|
|
@@ -1340,10 +1375,11 @@ class MenuItemPattern {
|
|
|
1340
1375
|
inputs;
|
|
1341
1376
|
value;
|
|
1342
1377
|
id;
|
|
1343
|
-
disabled;
|
|
1378
|
+
disabled = () => this.inputs.parent()?.disabled() || this.inputs.disabled();
|
|
1344
1379
|
searchTerm;
|
|
1345
1380
|
element;
|
|
1346
|
-
|
|
1381
|
+
active = computed(() => this.inputs.parent()?.inputs.activeItem() === this);
|
|
1382
|
+
hasBeenFocused = signal(false);
|
|
1347
1383
|
tabIndex = computed(() => {
|
|
1348
1384
|
if (this.submenu() && this.submenu()?.inputs.activeItem()) {
|
|
1349
1385
|
return -1;
|
|
@@ -1363,12 +1399,14 @@ class MenuItemPattern {
|
|
|
1363
1399
|
this.id = inputs.id;
|
|
1364
1400
|
this.value = inputs.value;
|
|
1365
1401
|
this.element = inputs.element;
|
|
1366
|
-
this.disabled = inputs.disabled;
|
|
1367
1402
|
this.submenu = this.inputs.submenu;
|
|
1368
1403
|
this.searchTerm = inputs.searchTerm;
|
|
1369
1404
|
this.selectable = computed(() => !this.submenu());
|
|
1370
1405
|
}
|
|
1371
1406
|
open(opts) {
|
|
1407
|
+
if (this.disabled()) {
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1372
1410
|
this._expanded.set(true);
|
|
1373
1411
|
if (opts?.first) {
|
|
1374
1412
|
this.submenu()?.first();
|
|
@@ -1388,8 +1426,15 @@ class MenuItemPattern {
|
|
|
1388
1426
|
menuitem?._expanded.set(false);
|
|
1389
1427
|
menuitem?.inputs.parent()?.listBehavior.unfocus();
|
|
1390
1428
|
menuitems = menuitems.concat(menuitem?.submenu()?.inputs.items() ?? []);
|
|
1429
|
+
const parent = menuitem?.inputs.parent();
|
|
1430
|
+
if (parent instanceof MenuPattern) {
|
|
1431
|
+
parent._clearTimeouts();
|
|
1432
|
+
}
|
|
1391
1433
|
}
|
|
1392
1434
|
}
|
|
1435
|
+
onFocusIn() {
|
|
1436
|
+
this.hasBeenFocused.set(true);
|
|
1437
|
+
}
|
|
1393
1438
|
}
|
|
1394
1439
|
|
|
1395
1440
|
function convertGetterSetterToWritableSignalLike(getter, setter) {
|
|
@@ -1399,48 +1444,27 @@ function convertGetterSetterToWritableSignalLike(getter, setter) {
|
|
|
1399
1444
|
});
|
|
1400
1445
|
}
|
|
1401
1446
|
|
|
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
1447
|
class ListExpansion {
|
|
1423
1448
|
inputs;
|
|
1424
|
-
expandedIds;
|
|
1425
1449
|
constructor(inputs) {
|
|
1426
1450
|
this.inputs = inputs;
|
|
1427
|
-
this.expandedIds = inputs.expandedIds;
|
|
1428
1451
|
}
|
|
1429
1452
|
open(item) {
|
|
1430
|
-
if (!this.isExpandable(item)) return;
|
|
1431
|
-
if (
|
|
1453
|
+
if (!this.isExpandable(item)) return false;
|
|
1454
|
+
if (item.expanded()) return false;
|
|
1432
1455
|
if (!this.inputs.multiExpandable()) {
|
|
1433
1456
|
this.closeAll();
|
|
1434
1457
|
}
|
|
1435
|
-
|
|
1458
|
+
item.expanded.set(true);
|
|
1459
|
+
return true;
|
|
1436
1460
|
}
|
|
1437
1461
|
close(item) {
|
|
1438
|
-
if (this.isExpandable(item))
|
|
1439
|
-
|
|
1440
|
-
|
|
1462
|
+
if (!this.isExpandable(item)) return false;
|
|
1463
|
+
item.expanded.set(false);
|
|
1464
|
+
return true;
|
|
1441
1465
|
}
|
|
1442
1466
|
toggle(item) {
|
|
1443
|
-
|
|
1467
|
+
return item.expanded() ? this.close(item) : this.open(item);
|
|
1444
1468
|
}
|
|
1445
1469
|
openAll() {
|
|
1446
1470
|
if (this.inputs.multiExpandable()) {
|
|
@@ -1457,9 +1481,6 @@ class ListExpansion {
|
|
|
1457
1481
|
isExpandable(item) {
|
|
1458
1482
|
return !this.inputs.disabled() && !item.disabled() && item.expandable();
|
|
1459
1483
|
}
|
|
1460
|
-
isExpanded(item) {
|
|
1461
|
-
return this.expandedIds().includes(item.expansionId());
|
|
1462
|
-
}
|
|
1463
1484
|
}
|
|
1464
1485
|
|
|
1465
1486
|
class LabelControl {
|
|
@@ -1484,47 +1505,35 @@ class LabelControl {
|
|
|
1484
1505
|
|
|
1485
1506
|
class TabPattern {
|
|
1486
1507
|
inputs;
|
|
1487
|
-
|
|
1488
|
-
id;
|
|
1508
|
+
id = () => this.inputs.id();
|
|
1489
1509
|
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());
|
|
1510
|
+
value = () => this.inputs.value();
|
|
1511
|
+
disabled = () => this.inputs.disabled();
|
|
1512
|
+
element = () => this.inputs.element();
|
|
1513
|
+
expandable = () => true;
|
|
1514
|
+
expanded;
|
|
1498
1515
|
active = computed(() => this.inputs.tablist().inputs.activeItem() === this);
|
|
1499
|
-
selected = computed(() =>
|
|
1500
|
-
tabIndex = computed(() => this.inputs.tablist().
|
|
1516
|
+
selected = computed(() => this.inputs.tablist().selectedTab() === this);
|
|
1517
|
+
tabIndex = computed(() => this.inputs.tablist().focusBehavior.getItemTabIndex(this));
|
|
1501
1518
|
controls = computed(() => this.inputs.tabpanel()?.id());
|
|
1502
1519
|
constructor(inputs) {
|
|
1503
1520
|
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
|
-
});
|
|
1521
|
+
this.expanded = inputs.expanded;
|
|
1522
|
+
}
|
|
1523
|
+
open() {
|
|
1524
|
+
return this.inputs.tablist().open(this);
|
|
1514
1525
|
}
|
|
1515
1526
|
}
|
|
1516
1527
|
class TabPanelPattern {
|
|
1517
1528
|
inputs;
|
|
1518
|
-
id;
|
|
1519
|
-
value;
|
|
1529
|
+
id = () => this.inputs.id();
|
|
1530
|
+
value = () => this.inputs.value();
|
|
1520
1531
|
labelManager;
|
|
1521
1532
|
hidden = computed(() => this.inputs.tab()?.expanded() === false);
|
|
1522
1533
|
tabIndex = computed(() => this.hidden() ? -1 : 0);
|
|
1523
1534
|
labelledBy = computed(() => this.labelManager.labelledBy().length > 0 ? this.labelManager.labelledBy().join(' ') : undefined);
|
|
1524
1535
|
constructor(inputs) {
|
|
1525
1536
|
this.inputs = inputs;
|
|
1526
|
-
this.id = inputs.id;
|
|
1527
|
-
this.value = inputs.value;
|
|
1528
1537
|
this.labelManager = new LabelControl({
|
|
1529
1538
|
...inputs,
|
|
1530
1539
|
defaultLabelledBy: computed(() => this.inputs.tab() ? [this.inputs.tab().id()] : [])
|
|
@@ -1533,12 +1542,15 @@ class TabPanelPattern {
|
|
|
1533
1542
|
}
|
|
1534
1543
|
class TabListPattern {
|
|
1535
1544
|
inputs;
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
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());
|
|
1542
1554
|
followFocus = computed(() => this.inputs.selectionMode() === 'follow');
|
|
1543
1555
|
prevKey = computed(() => {
|
|
1544
1556
|
if (this.inputs.orientation() === 'vertical') {
|
|
@@ -1553,40 +1565,27 @@ class TabListPattern {
|
|
|
1553
1565
|
return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
|
|
1554
1566
|
});
|
|
1555
1567
|
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());
|
|
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());
|
|
1565
1569
|
});
|
|
1566
1570
|
pointerdown = computed(() => {
|
|
1567
|
-
return new PointerEventManager().on(e => this.
|
|
1568
|
-
select: true
|
|
1569
|
-
}));
|
|
1571
|
+
return new PointerEventManager().on(e => this._navigate(() => this.navigationBehavior.goto(this._getItem(e)), true));
|
|
1570
1572
|
});
|
|
1571
1573
|
constructor(inputs) {
|
|
1572
1574
|
this.inputs = inputs;
|
|
1573
|
-
this.
|
|
1574
|
-
this.
|
|
1575
|
-
this.listBehavior = new List({
|
|
1575
|
+
this.focusBehavior = new ListFocus(inputs);
|
|
1576
|
+
this.navigationBehavior = new ListNavigation({
|
|
1576
1577
|
...inputs,
|
|
1577
|
-
|
|
1578
|
-
typeaheadDelay: () => 0
|
|
1578
|
+
focusManager: this.focusBehavior
|
|
1579
1579
|
});
|
|
1580
|
-
this.
|
|
1580
|
+
this.expansionBehavior = new ListExpansion({
|
|
1581
1581
|
...inputs,
|
|
1582
|
-
multiExpandable: () => false
|
|
1583
|
-
expandedIds: this.inputs.value
|
|
1582
|
+
multiExpandable: () => false
|
|
1584
1583
|
});
|
|
1585
1584
|
}
|
|
1586
1585
|
setDefaultState() {
|
|
1587
1586
|
let firstItem;
|
|
1588
1587
|
for (const item of this.inputs.items()) {
|
|
1589
|
-
if (!this.
|
|
1588
|
+
if (!this.focusBehavior.isFocusable(item)) continue;
|
|
1590
1589
|
if (firstItem === undefined) {
|
|
1591
1590
|
firstItem = item;
|
|
1592
1591
|
}
|
|
@@ -1609,6 +1608,24 @@ class TabListPattern {
|
|
|
1609
1608
|
this.pointerdown().handle(event);
|
|
1610
1609
|
}
|
|
1611
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
|
+
}
|
|
1612
1629
|
_getItem(e) {
|
|
1613
1630
|
if (!(e.target instanceof HTMLElement)) {
|
|
1614
1631
|
return;
|
|
@@ -1702,7 +1719,7 @@ class ToolbarPattern {
|
|
|
1702
1719
|
multi: () => true,
|
|
1703
1720
|
focusMode: () => 'roving',
|
|
1704
1721
|
selectionMode: () => 'explicit',
|
|
1705
|
-
|
|
1722
|
+
values: signal([]),
|
|
1706
1723
|
typeaheadDelay: () => 0
|
|
1707
1724
|
});
|
|
1708
1725
|
}
|
|
@@ -1741,7 +1758,7 @@ class ToolbarWidgetPattern {
|
|
|
1741
1758
|
value = () => this.inputs.value();
|
|
1742
1759
|
selectable = () => true;
|
|
1743
1760
|
index = computed(() => this.toolbar().inputs.items().indexOf(this) ?? -1);
|
|
1744
|
-
selected = computed(() => this.toolbar().listBehavior.inputs.
|
|
1761
|
+
selected = computed(() => this.toolbar().listBehavior.inputs.values().includes(this.value()));
|
|
1745
1762
|
active = computed(() => this.toolbar().activeItem() === this);
|
|
1746
1763
|
constructor(inputs) {
|
|
1747
1764
|
this.inputs = inputs;
|
|
@@ -1765,82 +1782,45 @@ class ToolbarWidgetGroupPattern {
|
|
|
1765
1782
|
const focusMode = () => 'roving';
|
|
1766
1783
|
class AccordionGroupPattern {
|
|
1767
1784
|
inputs;
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1785
|
+
navigationBehavior;
|
|
1786
|
+
focusBehavior;
|
|
1787
|
+
expansionBehavior;
|
|
1771
1788
|
constructor(inputs) {
|
|
1772
1789
|
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({
|
|
1790
|
+
this.focusBehavior = new ListFocus({
|
|
1783
1791
|
...inputs,
|
|
1784
1792
|
focusMode
|
|
1785
1793
|
});
|
|
1786
|
-
this.
|
|
1794
|
+
this.navigationBehavior = new ListNavigation({
|
|
1787
1795
|
...inputs,
|
|
1788
1796
|
focusMode,
|
|
1789
|
-
focusManager: this.
|
|
1797
|
+
focusManager: this.focusBehavior
|
|
1790
1798
|
});
|
|
1791
|
-
this.
|
|
1799
|
+
this.expansionBehavior = new ListExpansion({
|
|
1792
1800
|
...inputs
|
|
1793
1801
|
});
|
|
1794
1802
|
}
|
|
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
1803
|
prevKey = computed(() => {
|
|
1823
|
-
if (this.inputs.
|
|
1804
|
+
if (this.inputs.orientation() === 'vertical') {
|
|
1824
1805
|
return 'ArrowUp';
|
|
1825
1806
|
}
|
|
1826
|
-
return this.inputs.
|
|
1807
|
+
return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
|
|
1827
1808
|
});
|
|
1828
1809
|
nextKey = computed(() => {
|
|
1829
|
-
if (this.inputs.
|
|
1810
|
+
if (this.inputs.orientation() === 'vertical') {
|
|
1830
1811
|
return 'ArrowDown';
|
|
1831
1812
|
}
|
|
1832
|
-
return this.inputs.
|
|
1813
|
+
return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
|
|
1833
1814
|
});
|
|
1834
1815
|
keydown = computed(() => {
|
|
1835
|
-
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());
|
|
1836
1817
|
});
|
|
1837
1818
|
pointerdown = computed(() => {
|
|
1838
1819
|
return new PointerEventManager().on(e => {
|
|
1839
|
-
const item = this.
|
|
1840
|
-
if (item)
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
}
|
|
1820
|
+
const item = this.inputs.getItem(e.target);
|
|
1821
|
+
if (!item) return;
|
|
1822
|
+
this.navigationBehavior.goto(item);
|
|
1823
|
+
this.expansionBehavior.toggle(item);
|
|
1844
1824
|
});
|
|
1845
1825
|
});
|
|
1846
1826
|
onKeydown(event) {
|
|
@@ -1850,26 +1830,51 @@ class AccordionTriggerPattern {
|
|
|
1850
1830
|
this.pointerdown().handle(event);
|
|
1851
1831
|
}
|
|
1852
1832
|
onFocus(event) {
|
|
1853
|
-
const item = this.
|
|
1854
|
-
if (item
|
|
1855
|
-
|
|
1856
|
-
|
|
1833
|
+
const item = this.inputs.getItem(event.target);
|
|
1834
|
+
if (!item) return;
|
|
1835
|
+
if (!this.focusBehavior.isFocusable(item)) return;
|
|
1836
|
+
this.focusBehavior.focus(item);
|
|
1857
1837
|
}
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
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);
|
|
1864
1868
|
}
|
|
1865
1869
|
}
|
|
1866
1870
|
class AccordionPanelPattern {
|
|
1867
1871
|
inputs;
|
|
1872
|
+
id;
|
|
1873
|
+
accordionTrigger;
|
|
1868
1874
|
hidden;
|
|
1869
1875
|
constructor(inputs) {
|
|
1870
1876
|
this.inputs = inputs;
|
|
1871
1877
|
this.id = inputs.id;
|
|
1872
|
-
this.value = inputs.value;
|
|
1873
1878
|
this.accordionTrigger = inputs.accordionTrigger;
|
|
1874
1879
|
this.hidden = computed(() => inputs.accordionTrigger()?.expanded() === false);
|
|
1875
1880
|
}
|
|
@@ -1877,22 +1882,20 @@ class AccordionPanelPattern {
|
|
|
1877
1882
|
|
|
1878
1883
|
class TreeItemPattern {
|
|
1879
1884
|
inputs;
|
|
1880
|
-
id;
|
|
1881
|
-
value;
|
|
1882
|
-
element;
|
|
1883
|
-
disabled;
|
|
1884
|
-
searchTerm;
|
|
1885
|
-
tree;
|
|
1886
|
-
parent;
|
|
1887
|
-
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();
|
|
1888
1893
|
index = computed(() => this.tree().visibleItems().indexOf(this));
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
selectable;
|
|
1894
|
+
expansionBehavior;
|
|
1895
|
+
expandable = () => this.inputs.hasChildren();
|
|
1896
|
+
selectable = () => this.inputs.selectable();
|
|
1897
|
+
expanded;
|
|
1894
1898
|
level = computed(() => this.parent().level() + 1);
|
|
1895
|
-
expanded = computed(() => this.expansion.isExpanded());
|
|
1896
1899
|
visible = computed(() => this.parent().expanded() && this.parent().visible());
|
|
1897
1900
|
setsize = computed(() => this.parent().children().length);
|
|
1898
1901
|
posinset = computed(() => this.parent().children().indexOf(this) + 1);
|
|
@@ -1905,7 +1908,7 @@ class TreeItemPattern {
|
|
|
1905
1908
|
if (!this.selectable()) {
|
|
1906
1909
|
return undefined;
|
|
1907
1910
|
}
|
|
1908
|
-
return this.tree().
|
|
1911
|
+
return this.tree().values().includes(this.value());
|
|
1909
1912
|
});
|
|
1910
1913
|
current = computed(() => {
|
|
1911
1914
|
if (!this.tree().nav()) {
|
|
@@ -1914,31 +1917,14 @@ class TreeItemPattern {
|
|
|
1914
1917
|
if (!this.selectable()) {
|
|
1915
1918
|
return undefined;
|
|
1916
1919
|
}
|
|
1917
|
-
return this.tree().
|
|
1920
|
+
return this.tree().values().includes(this.value()) ? this.tree().currentType() : undefined;
|
|
1918
1921
|
});
|
|
1919
1922
|
constructor(inputs) {
|
|
1920
1923
|
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({
|
|
1924
|
+
this.expanded = inputs.expanded;
|
|
1925
|
+
this.expansionBehavior = new ListExpansion({
|
|
1939
1926
|
...inputs,
|
|
1940
1927
|
multiExpandable: () => true,
|
|
1941
|
-
expandedIds: signal([]),
|
|
1942
1928
|
items: this.children,
|
|
1943
1929
|
disabled: computed(() => this.tree()?.disabled() ?? false)
|
|
1944
1930
|
});
|
|
@@ -1947,7 +1933,7 @@ class TreeItemPattern {
|
|
|
1947
1933
|
class TreePattern {
|
|
1948
1934
|
inputs;
|
|
1949
1935
|
listBehavior;
|
|
1950
|
-
|
|
1936
|
+
expansionBehavior;
|
|
1951
1937
|
level = () => 0;
|
|
1952
1938
|
expanded = () => true;
|
|
1953
1939
|
visible = () => true;
|
|
@@ -1956,29 +1942,30 @@ class TreePattern {
|
|
|
1956
1942
|
children = computed(() => this.inputs.allItems().filter(item => item.level() === this.level() + 1));
|
|
1957
1943
|
visibleItems = computed(() => this.inputs.allItems().filter(item => item.visible()));
|
|
1958
1944
|
followFocus = computed(() => this.inputs.selectionMode() === 'follow');
|
|
1945
|
+
isRtl = computed(() => this.inputs.textDirection() === 'rtl');
|
|
1959
1946
|
prevKey = computed(() => {
|
|
1960
1947
|
if (this.inputs.orientation() === 'vertical') {
|
|
1961
1948
|
return 'ArrowUp';
|
|
1962
1949
|
}
|
|
1963
|
-
return this.
|
|
1950
|
+
return this.isRtl() ? 'ArrowRight' : 'ArrowLeft';
|
|
1964
1951
|
});
|
|
1965
1952
|
nextKey = computed(() => {
|
|
1966
1953
|
if (this.inputs.orientation() === 'vertical') {
|
|
1967
1954
|
return 'ArrowDown';
|
|
1968
1955
|
}
|
|
1969
|
-
return this.
|
|
1956
|
+
return this.isRtl() ? 'ArrowLeft' : 'ArrowRight';
|
|
1970
1957
|
});
|
|
1971
1958
|
collapseKey = computed(() => {
|
|
1972
1959
|
if (this.inputs.orientation() === 'horizontal') {
|
|
1973
1960
|
return 'ArrowUp';
|
|
1974
1961
|
}
|
|
1975
|
-
return this.
|
|
1962
|
+
return this.isRtl() ? 'ArrowRight' : 'ArrowLeft';
|
|
1976
1963
|
});
|
|
1977
1964
|
expandKey = computed(() => {
|
|
1978
1965
|
if (this.inputs.orientation() === 'horizontal') {
|
|
1979
1966
|
return 'ArrowDown';
|
|
1980
1967
|
}
|
|
1981
|
-
return this.
|
|
1968
|
+
return this.isRtl() ? 'ArrowLeft' : 'ArrowRight';
|
|
1982
1969
|
});
|
|
1983
1970
|
dynamicSpaceKey = computed(() => this.listBehavior.isTyping() ? '' : ' ');
|
|
1984
1971
|
typeaheadRegexp = /^.$/;
|
|
@@ -2064,45 +2051,33 @@ class TreePattern {
|
|
|
2064
2051
|
}
|
|
2065
2052
|
return manager;
|
|
2066
2053
|
});
|
|
2067
|
-
id;
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
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;
|
|
2081
2070
|
constructor(inputs) {
|
|
2082
2071
|
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
2072
|
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;
|
|
2073
|
+
this.values = inputs.values;
|
|
2098
2074
|
this.listBehavior = new List({
|
|
2099
2075
|
...inputs,
|
|
2100
2076
|
items: this.visibleItems,
|
|
2101
2077
|
multi: this.multi
|
|
2102
2078
|
});
|
|
2103
|
-
this.
|
|
2079
|
+
this.expansionBehavior = new ListExpansion({
|
|
2104
2080
|
multiExpandable: () => true,
|
|
2105
|
-
expandedIds: signal([]),
|
|
2106
2081
|
items: this.children,
|
|
2107
2082
|
disabled: this.disabled
|
|
2108
2083
|
});
|
|
@@ -2147,14 +2122,14 @@ class TreePattern {
|
|
|
2147
2122
|
if (item.expanded()) {
|
|
2148
2123
|
this.collapse();
|
|
2149
2124
|
} else {
|
|
2150
|
-
|
|
2125
|
+
this.expansionBehavior.open(item);
|
|
2151
2126
|
}
|
|
2152
2127
|
}
|
|
2153
2128
|
expand(opts) {
|
|
2154
2129
|
const item = this.activeItem();
|
|
2155
2130
|
if (!item || !this.listBehavior.isFocusable(item)) return;
|
|
2156
2131
|
if (item.expandable() && !item.expanded()) {
|
|
2157
|
-
|
|
2132
|
+
this.expansionBehavior.open(item);
|
|
2158
2133
|
} else if (item.expanded() && item.children().some(item => this.listBehavior.isFocusable(item))) {
|
|
2159
2134
|
this.listBehavior.next(opts);
|
|
2160
2135
|
}
|
|
@@ -2162,13 +2137,13 @@ class TreePattern {
|
|
|
2162
2137
|
expandSiblings(item) {
|
|
2163
2138
|
item ??= this.activeItem();
|
|
2164
2139
|
const siblings = item?.parent()?.children();
|
|
2165
|
-
siblings?.forEach(item =>
|
|
2140
|
+
siblings?.forEach(item => this.expansionBehavior.open(item));
|
|
2166
2141
|
}
|
|
2167
2142
|
collapse(opts) {
|
|
2168
2143
|
const item = this.activeItem();
|
|
2169
2144
|
if (!item || !this.listBehavior.isFocusable(item)) return;
|
|
2170
2145
|
if (item.expandable() && item.expanded()) {
|
|
2171
|
-
|
|
2146
|
+
this.expansionBehavior.close(item);
|
|
2172
2147
|
} else if (item.parent() && item.parent() !== this) {
|
|
2173
2148
|
const parentItem = item.parent();
|
|
2174
2149
|
if (parentItem instanceof TreeItemPattern && this.listBehavior.isFocusable(parentItem)) {
|
|
@@ -2190,6 +2165,7 @@ class ComboboxTreePattern extends TreePattern {
|
|
|
2190
2165
|
isItemCollapsible = () => this.inputs.activeItem()?.parent() instanceof TreeItemPattern;
|
|
2191
2166
|
role = () => 'tree';
|
|
2192
2167
|
activeId = computed(() => this.listBehavior.activeDescendant());
|
|
2168
|
+
getActiveItem = () => this.inputs.activeItem();
|
|
2193
2169
|
items = computed(() => this.inputs.allItems());
|
|
2194
2170
|
tabIndex = () => -1;
|
|
2195
2171
|
constructor(inputs) {
|
|
@@ -2215,14 +2191,14 @@ class ComboboxTreePattern extends TreePattern {
|
|
|
2215
2191
|
clearSelection = () => this.listBehavior.deselectAll();
|
|
2216
2192
|
getItem = e => this._getItem(e);
|
|
2217
2193
|
getSelectedItems = () => this.inputs.allItems().filter(item => item.selected());
|
|
2218
|
-
setValue = value => this.inputs.
|
|
2194
|
+
setValue = value => this.inputs.values.set(value ? [value] : []);
|
|
2219
2195
|
expandItem = () => this.expand();
|
|
2220
2196
|
collapseItem = () => this.collapse();
|
|
2221
2197
|
isItemExpandable(item = this.inputs.activeItem()) {
|
|
2222
2198
|
return item ? item.expandable() : false;
|
|
2223
2199
|
}
|
|
2224
|
-
expandAll = () => this.items().forEach(item =>
|
|
2225
|
-
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));
|
|
2226
2202
|
isItemSelectable = (item = this.inputs.activeItem()) => {
|
|
2227
2203
|
return item ? item.selectable() : false;
|
|
2228
2204
|
};
|
|
@@ -2334,5 +2310,5 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
2334
2310
|
ctorParameters: () => []
|
|
2335
2311
|
});
|
|
2336
2312
|
|
|
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 };
|
|
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 };
|
|
2338
2314
|
//# sourceMappingURL=private.mjs.map
|