@angular/aria 21.1.0-next.0 → 21.1.0-next.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.
Files changed (56) hide show
  1. package/fesm2022/_combobox-chunk.mjs +425 -0
  2. package/fesm2022/_combobox-chunk.mjs.map +1 -0
  3. package/fesm2022/_combobox-listbox-chunk.mjs +522 -0
  4. package/fesm2022/_combobox-listbox-chunk.mjs.map +1 -0
  5. package/fesm2022/_combobox-popup-chunk.mjs +46 -0
  6. package/fesm2022/_combobox-popup-chunk.mjs.map +1 -0
  7. package/fesm2022/_list-navigation-chunk.mjs +116 -0
  8. package/fesm2022/_list-navigation-chunk.mjs.map +1 -0
  9. package/fesm2022/_pointer-event-manager-chunk.mjs +134 -0
  10. package/fesm2022/_pointer-event-manager-chunk.mjs.map +1 -0
  11. package/fesm2022/_widget-chunk.mjs +4 -246
  12. package/fesm2022/_widget-chunk.mjs.map +1 -1
  13. package/fesm2022/accordion.mjs +64 -51
  14. package/fesm2022/accordion.mjs.map +1 -1
  15. package/fesm2022/aria.mjs +1 -1
  16. package/fesm2022/aria.mjs.map +1 -1
  17. package/fesm2022/combobox.mjs +120 -144
  18. package/fesm2022/combobox.mjs.map +1 -1
  19. package/fesm2022/grid.mjs +285 -261
  20. package/fesm2022/grid.mjs.map +1 -1
  21. package/fesm2022/listbox.mjs +205 -193
  22. package/fesm2022/listbox.mjs.map +1 -1
  23. package/fesm2022/menu.mjs +301 -283
  24. package/fesm2022/menu.mjs.map +1 -1
  25. package/fesm2022/private.mjs +15 -938
  26. package/fesm2022/private.mjs.map +1 -1
  27. package/fesm2022/tabs.mjs +209 -195
  28. package/fesm2022/tabs.mjs.map +1 -1
  29. package/fesm2022/toolbar.mjs +59 -47
  30. package/fesm2022/toolbar.mjs.map +1 -1
  31. package/fesm2022/tree.mjs +43 -41
  32. package/fesm2022/tree.mjs.map +1 -1
  33. package/package.json +2 -2
  34. package/types/_combobox-chunk.d.ts +98 -0
  35. package/types/_combobox-chunk.d2.ts +193 -0
  36. package/types/_grid-chunk.d.ts +3 -210
  37. package/types/_list-chunk.d.ts +212 -0
  38. package/types/_list-navigation-chunk.d.ts +212 -0
  39. package/types/_listbox-chunk.d.ts +106 -0
  40. package/types/accordion.d.ts +52 -49
  41. package/types/combobox.d.ts +25 -111
  42. package/types/grid.d.ts +37 -32
  43. package/types/listbox.d.ts +8 -5
  44. package/types/menu.d.ts +113 -113
  45. package/types/private.d.ts +12 -498
  46. package/types/tabs.d.ts +89 -84
  47. package/types/toolbar.d.ts +69 -66
  48. package/types/tree.d.ts +106 -103
  49. package/_adev_assets/aria-accordion.json +0 -743
  50. package/_adev_assets/aria-combobox.json +0 -607
  51. package/_adev_assets/aria-grid.json +0 -901
  52. package/_adev_assets/aria-listbox.json +0 -544
  53. package/_adev_assets/aria-menu.json +0 -1049
  54. package/_adev_assets/aria-tabs.json +0 -880
  55. package/_adev_assets/aria-toolbar.json +0 -545
  56. package/_adev_assets/aria-tree.json +0 -861
@@ -1,937 +1,12 @@
1
+ export { ComboboxDialogPattern, ComboboxPattern } from './_combobox-chunk.mjs';
2
+ import { List } from './_combobox-listbox-chunk.mjs';
3
+ export { ComboboxListboxPattern, ListboxPattern, OptionPattern } from './_combobox-listbox-chunk.mjs';
1
4
  import * as i0 from '@angular/core';
2
- import { signal, computed, model, Directive, inject, TemplateRef, ViewContainerRef, afterRenderEffect } from '@angular/core';
3
- import { PointerEventManager, KeyboardEventManager, ListFocus, ListNavigation, Modifier } from './_widget-chunk.mjs';
5
+ import { computed, signal, model, Directive, inject, TemplateRef, ViewContainerRef, afterRenderEffect } from '@angular/core';
6
+ import { KeyboardEventManager, PointerEventManager, Modifier } from './_pointer-event-manager-chunk.mjs';
7
+ import { ListFocus, ListNavigation } from './_list-navigation-chunk.mjs';
4
8
  export { GridCellPattern, GridCellWidgetPattern, GridPattern, GridRowPattern } from './_widget-chunk.mjs';
5
9
 
6
- class ComboboxPattern {
7
- inputs;
8
- expanded = signal(false);
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
- });
17
- highlightedItem = signal(undefined);
18
- isDeleting = false;
19
- isFocused = signal(false);
20
- hasBeenFocused = signal(false);
21
- expandKey = computed(() => this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight');
22
- collapseKey = computed(() => this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft');
23
- popupId = computed(() => this.inputs.popupControls()?.id() || null);
24
- autocomplete = computed(() => this.inputs.filterMode() === 'highlight' ? 'both' : 'list');
25
- hasPopup = computed(() => this.inputs.popupControls()?.role() || 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
- };
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
- }
61
- if (!this.expanded()) {
62
- manager.on('ArrowDown', () => this.open({
63
- first: true
64
- })).on('ArrowUp', () => this.open({
65
- last: true
66
- }));
67
- if (this.readonly()) {
68
- manager.on('Enter', () => this.open({
69
- selected: true
70
- })).on(' ', () => this.open({
71
- selected: true
72
- }));
73
- }
74
- return manager;
75
- }
76
- manager.on('ArrowDown', () => this.next()).on('ArrowUp', () => this.prev()).on('Home', () => this.first()).on('End', () => this.last());
77
- if (this.readonly()) {
78
- manager.on(' ', () => this.select({
79
- commit: true,
80
- close: !popupControls.multi()
81
- }));
82
- }
83
- if (popupControls.role() === 'listbox') {
84
- manager.on('Enter', () => {
85
- this.select({
86
- commit: true,
87
- close: !popupControls.multi()
88
- });
89
- });
90
- }
91
- const treeControls = this.treeControls();
92
- if (treeControls?.isItemSelectable()) {
93
- manager.on('Enter', () => this.select({
94
- commit: true,
95
- close: true
96
- }));
97
- }
98
- if (treeControls?.isItemExpandable()) {
99
- manager.on(this.expandKey(), () => this.expandItem()).on(this.collapseKey(), () => this.collapseItem());
100
- if (!treeControls.isItemSelectable()) {
101
- manager.on('Enter', () => this.expandItem());
102
- }
103
- }
104
- if (treeControls?.isItemCollapsible()) {
105
- manager.on(this.collapseKey(), () => this.collapseItem());
106
- }
107
- return manager;
108
- });
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);
122
- if (item) {
123
- if (controls?.role() === 'tree') {
124
- const treeControls = controls;
125
- if (treeControls.isItemExpandable(item) && !treeControls.isItemSelectable(item)) {
126
- treeControls.toggleExpansion(item);
127
- this.inputs.inputEl()?.focus();
128
- return;
129
- }
130
- }
131
- this.select({
132
- item,
133
- commit: true,
134
- close: !controls?.multi()
135
- });
136
- this.inputs.inputEl()?.focus();
137
- }
138
- }));
139
- constructor(inputs) {
140
- this.inputs = inputs;
141
- }
142
- onKeydown(event) {
143
- if (!this.inputs.disabled()) {
144
- this.keydown().handle(event);
145
- }
146
- }
147
- onClick(event) {
148
- if (!this.inputs.disabled()) {
149
- this.click().handle(event);
150
- }
151
- }
152
- onInput(event) {
153
- if (this.inputs.disabled() || this.inputs.readonly()) {
154
- return;
155
- }
156
- const inputEl = this.inputs.inputEl();
157
- if (!inputEl) {
158
- return;
159
- }
160
- const popupControls = this.inputs.popupControls();
161
- if (popupControls instanceof ComboboxDialogPattern) {
162
- return;
163
- }
164
- this.open();
165
- this.inputs.inputValue?.set(inputEl.value);
166
- this.isDeleting = event instanceof InputEvent && !!event.inputType.match(/^delete/);
167
- if (this.inputs.filterMode() === 'highlight' && !this.isDeleting) {
168
- this.highlight();
169
- }
170
- }
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
- }
176
- this.isFocused.set(true);
177
- this.hasBeenFocused.set(true);
178
- }
179
- onFocusOut(event) {
180
- if (this.inputs.disabled()) {
181
- return;
182
- }
183
- const popupControls = this.inputs.popupControls();
184
- if (popupControls instanceof ComboboxDialogPattern) {
185
- return;
186
- }
187
- if (!(event.relatedTarget instanceof HTMLElement) || !this.inputs.containerEl()?.contains(event.relatedTarget)) {
188
- this.isFocused.set(false);
189
- if (this.readonly()) {
190
- this.close();
191
- return;
192
- }
193
- if (this.inputs.filterMode() !== 'manual') {
194
- this.commit();
195
- } else {
196
- const item = popupControls?.items().find(i => i.searchTerm() === this.inputs.inputEl()?.value);
197
- if (item) {
198
- this.select({
199
- item
200
- });
201
- }
202
- }
203
- this.close();
204
- }
205
- }
206
- firstMatch = computed(() => {
207
- if (this.listControls()?.role() === 'listbox') {
208
- return this.listControls()?.items()[0];
209
- }
210
- return this.listControls()?.items().find(i => i.value() === this.inputs.firstMatch());
211
- });
212
- onFilter() {
213
- if (this.readonly()) {
214
- return;
215
- }
216
- const popupControls = this.inputs.popupControls();
217
- if (popupControls instanceof ComboboxDialogPattern) {
218
- return;
219
- }
220
- const isInitialRender = !this.inputs.inputValue?.().length && !this.isDeleting;
221
- if (isInitialRender) {
222
- return;
223
- }
224
- if (!this.isFocused()) {
225
- return;
226
- }
227
- if (this.inputs.popupControls()?.role() === 'tree') {
228
- const treeControls = this.inputs.popupControls();
229
- this.inputs.inputValue?.().length ? treeControls.expandAll() : treeControls.collapseAll();
230
- }
231
- const item = this.firstMatch();
232
- if (!item) {
233
- popupControls?.clearSelection();
234
- popupControls?.unfocus();
235
- return;
236
- }
237
- popupControls?.focus(item);
238
- if (this.inputs.filterMode() !== 'manual') {
239
- this.select({
240
- item
241
- });
242
- }
243
- if (this.inputs.filterMode() === 'highlight' && !this.isDeleting) {
244
- this.highlight();
245
- }
246
- }
247
- highlight() {
248
- const inputEl = this.inputs.inputEl();
249
- const selectedItems = this.listControls()?.getSelectedItems();
250
- const item = selectedItems?.[0];
251
- if (!inputEl || !item) {
252
- return;
253
- }
254
- const isHighlightable = item.searchTerm().toLowerCase().startsWith(this.inputs.inputValue().toLowerCase());
255
- if (isHighlightable) {
256
- inputEl.value = this.inputs.inputValue() + item.searchTerm().slice(this.inputs.inputValue().length);
257
- inputEl.setSelectionRange(this.inputs.inputValue().length, item.searchTerm().length);
258
- this.highlightedItem.set(item);
259
- }
260
- }
261
- close(opts) {
262
- const popupControls = this.inputs.popupControls();
263
- if (this.inputs.alwaysExpanded()) {
264
- return;
265
- }
266
- if (popupControls instanceof ComboboxDialogPattern) {
267
- this.expanded.set(false);
268
- return;
269
- }
270
- if (this.readonly()) {
271
- this.expanded.set(false);
272
- popupControls?.unfocus();
273
- return;
274
- }
275
- if (!opts?.reset) {
276
- if (this.inputs.filterMode() === 'manual') {
277
- if (!this.listControls()?.items().some(i => i.searchTerm() === this.inputs.inputEl()?.value)) {
278
- this.listControls()?.clearSelection();
279
- }
280
- }
281
- this.expanded.set(false);
282
- popupControls?.unfocus();
283
- return;
284
- }
285
- if (!this.expanded()) {
286
- this.inputs.inputValue?.set('');
287
- popupControls?.clearSelection();
288
- const inputEl = this.inputs.inputEl();
289
- if (inputEl) {
290
- inputEl.value = '';
291
- }
292
- } else if (this.expanded()) {
293
- this.expanded.set(false);
294
- const selectedItem = popupControls?.getSelectedItems()?.[0];
295
- if (selectedItem?.searchTerm() !== this.inputs.inputValue()) {
296
- popupControls?.clearSelection();
297
- }
298
- return;
299
- }
300
- this.close();
301
- if (!this.readonly()) {
302
- popupControls?.clearSelection();
303
- }
304
- }
305
- open(nav) {
306
- this.expanded.set(true);
307
- const popupControls = this.inputs.popupControls();
308
- if (popupControls instanceof ComboboxDialogPattern) {
309
- return;
310
- }
311
- const inputEl = this.inputs.inputEl();
312
- if (inputEl && this.inputs.filterMode() === 'highlight') {
313
- const isHighlighting = inputEl.selectionStart !== inputEl.value.length;
314
- this.inputs.inputValue?.set(inputEl.value.slice(0, inputEl.selectionStart || 0));
315
- if (!isHighlighting) {
316
- this.highlightedItem.set(undefined);
317
- }
318
- }
319
- if (nav?.first) {
320
- this.first();
321
- }
322
- if (nav?.last) {
323
- this.last();
324
- }
325
- if (nav?.selected) {
326
- const selectedItem = popupControls?.items().find(i => popupControls?.getSelectedItems().includes(i));
327
- if (selectedItem) {
328
- popupControls?.focus(selectedItem);
329
- }
330
- }
331
- }
332
- next() {
333
- this._navigate(() => this.listControls()?.next());
334
- }
335
- prev() {
336
- this._navigate(() => this.listControls()?.prev());
337
- }
338
- first() {
339
- this._navigate(() => this.listControls()?.first());
340
- }
341
- last() {
342
- this._navigate(() => this.listControls()?.last());
343
- }
344
- collapseItem() {
345
- const controls = this.inputs.popupControls();
346
- this._navigate(() => controls?.collapseItem());
347
- }
348
- expandItem() {
349
- const controls = this.inputs.popupControls();
350
- this._navigate(() => controls?.expandItem());
351
- }
352
- select(opts = {}) {
353
- const controls = this.listControls();
354
- if (opts.item) {
355
- controls?.focus(opts.item, {
356
- focusElement: false
357
- });
358
- }
359
- controls?.multi() ? controls.toggle(opts.item) : controls?.select(opts.item);
360
- if (opts.commit) {
361
- this.commit();
362
- }
363
- if (opts.close) {
364
- this.close();
365
- }
366
- }
367
- commit() {
368
- const inputEl = this.inputs.inputEl();
369
- const selectedItems = this.listControls()?.getSelectedItems();
370
- if (!inputEl) {
371
- return;
372
- }
373
- inputEl.value = selectedItems?.map(i => i.searchTerm()).join(', ') || '';
374
- this.inputs.inputValue?.set(inputEl.value);
375
- if (this.inputs.filterMode() === 'highlight' && !this.readonly()) {
376
- const length = inputEl.value.length;
377
- inputEl.setSelectionRange(length, length);
378
- }
379
- }
380
- _navigate(operation) {
381
- operation();
382
- if (this.inputs.filterMode() !== 'manual') {
383
- this.select();
384
- }
385
- if (this.inputs.filterMode() === 'highlight') {
386
- const selectedItem = this.listControls()?.getSelectedItems()[0];
387
- if (!selectedItem) {
388
- return;
389
- }
390
- if (selectedItem === this.highlightedItem()) {
391
- this.highlight();
392
- } else {
393
- const inputEl = this.inputs.inputEl();
394
- inputEl.value = selectedItem?.searchTerm();
395
- }
396
- }
397
- }
398
- }
399
- class ComboboxDialogPattern {
400
- inputs;
401
- id = () => this.inputs.id();
402
- role = () => 'dialog';
403
- keydown = computed(() => {
404
- return new KeyboardEventManager().on('Escape', () => this.inputs.combobox.close());
405
- });
406
- constructor(inputs) {
407
- this.inputs = inputs;
408
- }
409
- onKeydown(event) {
410
- this.keydown().handle(event);
411
- }
412
- onClick(event) {
413
- if (event.target === this.inputs.element()) {
414
- this.inputs.combobox.close();
415
- }
416
- }
417
- }
418
-
419
- class ListSelection {
420
- inputs;
421
- rangeStartIndex = signal(0);
422
- rangeEndIndex = signal(0);
423
- selectedItems = computed(() => this.inputs.items().filter(item => this.inputs.values().includes(item.value())));
424
- constructor(inputs) {
425
- this.inputs = inputs;
426
- }
427
- select(item, opts = {
428
- anchor: true
429
- }) {
430
- item = item ?? this.inputs.focusManager.inputs.activeItem();
431
- if (!item || item.disabled() || !item.selectable() || this.inputs.values().includes(item.value())) {
432
- return;
433
- }
434
- if (!this.inputs.multi()) {
435
- this.deselectAll();
436
- }
437
- const index = this.inputs.items().findIndex(i => i === item);
438
- if (opts.anchor) {
439
- this.beginRangeSelection(index);
440
- }
441
- this.inputs.values.update(values => values.concat(item.value()));
442
- }
443
- deselect(item) {
444
- item = item ?? this.inputs.focusManager.inputs.activeItem();
445
- if (item && !item.disabled() && item.selectable()) {
446
- this.inputs.values.update(values => values.filter(value => value !== item.value()));
447
- }
448
- }
449
- toggle(item) {
450
- item = item ?? this.inputs.focusManager.inputs.activeItem();
451
- if (item) {
452
- this.inputs.values().includes(item.value()) ? this.deselect(item) : this.select(item);
453
- }
454
- }
455
- toggleOne() {
456
- const item = this.inputs.focusManager.inputs.activeItem();
457
- if (item) {
458
- this.inputs.values().includes(item.value()) ? this.deselect() : this.selectOne();
459
- }
460
- }
461
- selectAll() {
462
- if (!this.inputs.multi()) {
463
- return;
464
- }
465
- for (const item of this.inputs.items()) {
466
- this.select(item, {
467
- anchor: false
468
- });
469
- }
470
- this.beginRangeSelection();
471
- }
472
- deselectAll() {
473
- for (const value of this.inputs.values()) {
474
- const item = this.inputs.items().find(i => i.value() === value);
475
- item ? this.deselect(item) : this.inputs.values.update(values => values.filter(v => v !== value));
476
- }
477
- }
478
- toggleAll() {
479
- const selectableValues = this.inputs.items().filter(i => !i.disabled() && i.selectable()).map(i => i.value());
480
- selectableValues.every(i => this.inputs.values().includes(i)) ? this.deselectAll() : this.selectAll();
481
- }
482
- selectOne() {
483
- const item = this.inputs.focusManager.inputs.activeItem();
484
- if (item && (item.disabled() || !item.selectable())) {
485
- return;
486
- }
487
- this.deselectAll();
488
- if (this.inputs.values().length > 0 && !this.inputs.multi()) {
489
- return;
490
- }
491
- this.select();
492
- }
493
- selectRange(opts = {
494
- anchor: true
495
- }) {
496
- const isStartOfRange = this.inputs.focusManager.prevActiveIndex() === this.rangeStartIndex();
497
- if (isStartOfRange && opts.anchor) {
498
- this.beginRangeSelection(this.inputs.focusManager.prevActiveIndex());
499
- }
500
- const itemsInRange = this._getItemsFromIndex(this.rangeStartIndex());
501
- const itemsOutOfRange = this._getItemsFromIndex(this.rangeEndIndex()).filter(i => !itemsInRange.includes(i));
502
- for (const item of itemsOutOfRange) {
503
- this.deselect(item);
504
- }
505
- for (const item of itemsInRange) {
506
- this.select(item, {
507
- anchor: false
508
- });
509
- }
510
- if (itemsInRange.length) {
511
- const item = itemsInRange.pop();
512
- const index = this.inputs.items().findIndex(i => i === item);
513
- this.rangeEndIndex.set(index);
514
- }
515
- }
516
- beginRangeSelection(index = this.inputs.focusManager.activeIndex()) {
517
- this.rangeStartIndex.set(index);
518
- this.rangeEndIndex.set(index);
519
- }
520
- _getItemsFromIndex(index) {
521
- if (index === -1) {
522
- return [];
523
- }
524
- const upper = Math.max(this.inputs.focusManager.activeIndex(), index);
525
- const lower = Math.min(this.inputs.focusManager.activeIndex(), index);
526
- const items = [];
527
- for (let i = lower; i <= upper; i++) {
528
- items.push(this.inputs.items()[i]);
529
- }
530
- if (this.inputs.focusManager.activeIndex() < index) {
531
- return items.reverse();
532
- }
533
- return items;
534
- }
535
- }
536
-
537
- class ListTypeahead {
538
- inputs;
539
- timeout;
540
- focusManager;
541
- isTyping = computed(() => this._query().length > 0);
542
- _query = signal('');
543
- _startIndex = signal(undefined);
544
- constructor(inputs) {
545
- this.inputs = inputs;
546
- this.focusManager = inputs.focusManager;
547
- }
548
- search(char) {
549
- if (char.length !== 1) {
550
- return false;
551
- }
552
- if (!this.isTyping() && char === ' ') {
553
- return false;
554
- }
555
- if (this._startIndex() === undefined) {
556
- this._startIndex.set(this.focusManager.activeIndex());
557
- }
558
- clearTimeout(this.timeout);
559
- this._query.update(q => q + char.toLowerCase());
560
- const item = this._getItem();
561
- if (item) {
562
- this.focusManager.focus(item);
563
- }
564
- this.timeout = setTimeout(() => {
565
- this._query.set('');
566
- this._startIndex.set(undefined);
567
- }, this.inputs.typeaheadDelay());
568
- return true;
569
- }
570
- _getItem() {
571
- let items = this.focusManager.inputs.items();
572
- const after = items.slice(this._startIndex() + 1);
573
- const before = items.slice(0, this._startIndex());
574
- items = after.concat(before);
575
- items.push(this.inputs.items()[this._startIndex()]);
576
- const focusableItems = [];
577
- for (const item of items) {
578
- if (this.focusManager.isFocusable(item)) {
579
- focusableItems.push(item);
580
- }
581
- }
582
- return focusableItems.find(i => i.searchTerm().toLowerCase().startsWith(this._query()));
583
- }
584
- }
585
-
586
- class List {
587
- inputs;
588
- navigationBehavior;
589
- selectionBehavior;
590
- typeaheadBehavior;
591
- focusBehavior;
592
- disabled = computed(() => this.focusBehavior.isListDisabled());
593
- activeDescendant = computed(() => this.focusBehavior.getActiveDescendant());
594
- tabIndex = computed(() => this.focusBehavior.getListTabIndex());
595
- activeIndex = computed(() => this.focusBehavior.activeIndex());
596
- _anchorIndex = signal(0);
597
- _wrap = signal(true);
598
- constructor(inputs) {
599
- this.inputs = inputs;
600
- this.focusBehavior = new ListFocus(inputs);
601
- this.selectionBehavior = new ListSelection({
602
- ...inputs,
603
- focusManager: this.focusBehavior
604
- });
605
- this.typeaheadBehavior = new ListTypeahead({
606
- ...inputs,
607
- focusManager: this.focusBehavior
608
- });
609
- this.navigationBehavior = new ListNavigation({
610
- ...inputs,
611
- focusManager: this.focusBehavior,
612
- wrap: computed(() => this._wrap() && this.inputs.wrap())
613
- });
614
- }
615
- getItemTabindex(item) {
616
- return this.focusBehavior.getItemTabIndex(item);
617
- }
618
- first(opts) {
619
- this._navigate(opts, () => this.navigationBehavior.first(opts));
620
- }
621
- last(opts) {
622
- this._navigate(opts, () => this.navigationBehavior.last(opts));
623
- }
624
- next(opts) {
625
- this._navigate(opts, () => this.navigationBehavior.next(opts));
626
- }
627
- prev(opts) {
628
- this._navigate(opts, () => this.navigationBehavior.prev(opts));
629
- }
630
- goto(item, opts) {
631
- this._navigate(opts, () => this.navigationBehavior.goto(item, opts));
632
- }
633
- unfocus() {
634
- this.inputs.activeItem.set(undefined);
635
- }
636
- anchor(index) {
637
- this._anchorIndex.set(index);
638
- }
639
- search(char, opts) {
640
- this._navigate(opts, () => this.typeaheadBehavior.search(char));
641
- }
642
- isTyping() {
643
- return this.typeaheadBehavior.isTyping();
644
- }
645
- select(item) {
646
- this.selectionBehavior.select(item);
647
- }
648
- selectOne() {
649
- this.selectionBehavior.selectOne();
650
- }
651
- deselect(item) {
652
- this.selectionBehavior.deselect(item);
653
- }
654
- deselectAll() {
655
- this.selectionBehavior.deselectAll();
656
- }
657
- toggle(item) {
658
- this.selectionBehavior.toggle(item);
659
- }
660
- toggleOne() {
661
- this.selectionBehavior.toggleOne();
662
- }
663
- toggleAll() {
664
- this.selectionBehavior.toggleAll();
665
- }
666
- isFocusable(item) {
667
- return this.focusBehavior.isFocusable(item);
668
- }
669
- updateSelection(opts = {
670
- anchor: true
671
- }) {
672
- if (opts.toggle) {
673
- this.selectionBehavior.toggle();
674
- }
675
- if (opts.select) {
676
- this.selectionBehavior.select();
677
- }
678
- if (opts.selectOne) {
679
- this.selectionBehavior.selectOne();
680
- }
681
- if (opts.selectRange) {
682
- this.selectionBehavior.selectRange();
683
- }
684
- if (!opts.anchor) {
685
- this.anchor(this.selectionBehavior.rangeStartIndex());
686
- }
687
- }
688
- _navigate(opts = {}, operation) {
689
- if (opts?.selectRange) {
690
- this._wrap.set(false);
691
- this.selectionBehavior.rangeStartIndex.set(this._anchorIndex());
692
- }
693
- const moved = operation();
694
- if (moved) {
695
- this.updateSelection(opts);
696
- }
697
- this._wrap.set(true);
698
- }
699
- }
700
-
701
- class ListboxPattern {
702
- inputs;
703
- listBehavior;
704
- orientation;
705
- disabled = computed(() => this.listBehavior.disabled());
706
- readonly;
707
- tabIndex = computed(() => this.listBehavior.tabIndex());
708
- activeDescendant = computed(() => this.listBehavior.activeDescendant());
709
- multi;
710
- setsize = computed(() => this.inputs.items().length);
711
- followFocus = computed(() => this.inputs.selectionMode() === 'follow');
712
- wrap = signal(true);
713
- prevKey = computed(() => {
714
- if (this.inputs.orientation() === 'vertical') {
715
- return 'ArrowUp';
716
- }
717
- return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
718
- });
719
- nextKey = computed(() => {
720
- if (this.inputs.orientation() === 'vertical') {
721
- return 'ArrowDown';
722
- }
723
- return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
724
- });
725
- dynamicSpaceKey = computed(() => this.listBehavior.isTyping() ? '' : ' ');
726
- typeaheadRegexp = /^.$/;
727
- keydown = computed(() => {
728
- const manager = new KeyboardEventManager();
729
- if (this.readonly()) {
730
- return manager.on(this.prevKey, () => this.listBehavior.prev()).on(this.nextKey, () => this.listBehavior.next()).on('Home', () => this.listBehavior.first()).on('End', () => this.listBehavior.last()).on(this.typeaheadRegexp, e => this.listBehavior.search(e.key));
731
- }
732
- if (!this.followFocus()) {
733
- manager.on(this.prevKey, () => this.listBehavior.prev()).on(this.nextKey, () => this.listBehavior.next()).on('Home', () => this.listBehavior.first()).on('End', () => this.listBehavior.last()).on(this.typeaheadRegexp, e => this.listBehavior.search(e.key));
734
- }
735
- if (this.followFocus()) {
736
- manager.on(this.prevKey, () => this.listBehavior.prev({
737
- selectOne: true
738
- })).on(this.nextKey, () => this.listBehavior.next({
739
- selectOne: true
740
- })).on('Home', () => this.listBehavior.first({
741
- selectOne: true
742
- })).on('End', () => this.listBehavior.last({
743
- selectOne: true
744
- })).on(this.typeaheadRegexp, e => this.listBehavior.search(e.key, {
745
- selectOne: true
746
- }));
747
- }
748
- if (this.inputs.multi()) {
749
- manager.on(Modifier.Any, 'Shift', () => this.listBehavior.anchor(this.listBehavior.activeIndex())).on(Modifier.Shift, this.prevKey, () => this.listBehavior.prev({
750
- selectRange: true
751
- })).on(Modifier.Shift, this.nextKey, () => this.listBehavior.next({
752
- selectRange: true
753
- })).on([Modifier.Ctrl | Modifier.Shift, Modifier.Meta | Modifier.Shift], 'Home', () => this.listBehavior.first({
754
- selectRange: true,
755
- anchor: false
756
- })).on([Modifier.Ctrl | Modifier.Shift, Modifier.Meta | Modifier.Shift], 'End', () => this.listBehavior.last({
757
- selectRange: true,
758
- anchor: false
759
- })).on(Modifier.Shift, 'Enter', () => this.listBehavior.updateSelection({
760
- selectRange: true,
761
- anchor: false
762
- })).on(Modifier.Shift, this.dynamicSpaceKey, () => this.listBehavior.updateSelection({
763
- selectRange: true,
764
- anchor: false
765
- }));
766
- }
767
- if (!this.followFocus() && this.inputs.multi()) {
768
- manager.on(this.dynamicSpaceKey, () => this.listBehavior.toggle()).on('Enter', () => this.listBehavior.toggle()).on([Modifier.Ctrl, Modifier.Meta], 'A', () => this.listBehavior.toggleAll());
769
- }
770
- if (!this.followFocus() && !this.inputs.multi()) {
771
- manager.on(this.dynamicSpaceKey, () => this.listBehavior.toggleOne());
772
- manager.on('Enter', () => this.listBehavior.toggleOne());
773
- }
774
- if (this.inputs.multi() && this.followFocus()) {
775
- manager.on([Modifier.Ctrl, Modifier.Meta], this.prevKey, () => this.listBehavior.prev()).on([Modifier.Ctrl, Modifier.Meta], this.nextKey, () => this.listBehavior.next()).on([Modifier.Ctrl, Modifier.Meta], ' ', () => this.listBehavior.toggle()).on([Modifier.Ctrl, Modifier.Meta], 'Enter', () => this.listBehavior.toggle()).on([Modifier.Ctrl, Modifier.Meta], 'Home', () => this.listBehavior.first()).on([Modifier.Ctrl, Modifier.Meta], 'End', () => this.listBehavior.last()).on([Modifier.Ctrl, Modifier.Meta], 'A', () => {
776
- this.listBehavior.toggleAll();
777
- this.listBehavior.select();
778
- });
779
- }
780
- return manager;
781
- });
782
- pointerdown = computed(() => {
783
- const manager = new PointerEventManager();
784
- if (this.readonly()) {
785
- return manager.on(e => this.listBehavior.goto(this._getItem(e)));
786
- }
787
- if (this.multi()) {
788
- manager.on(Modifier.Shift, e => this.listBehavior.goto(this._getItem(e), {
789
- selectRange: true
790
- }));
791
- }
792
- if (!this.multi() && this.followFocus()) {
793
- return manager.on(e => this.listBehavior.goto(this._getItem(e), {
794
- selectOne: true
795
- }));
796
- }
797
- if (!this.multi() && !this.followFocus()) {
798
- return manager.on(e => this.listBehavior.goto(this._getItem(e), {
799
- toggle: true
800
- }));
801
- }
802
- if (this.multi() && this.followFocus()) {
803
- return manager.on(e => this.listBehavior.goto(this._getItem(e), {
804
- selectOne: true
805
- })).on(Modifier.Ctrl, e => this.listBehavior.goto(this._getItem(e), {
806
- toggle: true
807
- }));
808
- }
809
- if (this.multi() && !this.followFocus()) {
810
- return manager.on(e => this.listBehavior.goto(this._getItem(e), {
811
- toggle: true
812
- }));
813
- }
814
- return manager;
815
- });
816
- constructor(inputs) {
817
- this.inputs = inputs;
818
- this.readonly = inputs.readonly;
819
- this.orientation = inputs.orientation;
820
- this.multi = inputs.multi;
821
- this.listBehavior = new List(inputs);
822
- }
823
- validate() {
824
- const violations = [];
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(', ')}`);
827
- }
828
- return violations;
829
- }
830
- onKeydown(event) {
831
- if (!this.disabled()) {
832
- this.keydown().handle(event);
833
- }
834
- }
835
- onPointerdown(event) {
836
- if (!this.disabled()) {
837
- this.pointerdown().handle(event);
838
- }
839
- }
840
- setDefaultState() {
841
- let firstItem = null;
842
- for (const item of this.inputs.items()) {
843
- if (this.listBehavior.isFocusable(item)) {
844
- if (!firstItem) {
845
- firstItem = item;
846
- }
847
- if (item.selected()) {
848
- this.inputs.activeItem.set(item);
849
- return;
850
- }
851
- }
852
- }
853
- if (firstItem) {
854
- this.inputs.activeItem.set(firstItem);
855
- }
856
- }
857
- _getItem(e) {
858
- if (!(e.target instanceof HTMLElement)) {
859
- return;
860
- }
861
- const element = e.target.closest('[role="option"]');
862
- return this.inputs.items().find(i => i.element() === element);
863
- }
864
- }
865
-
866
- class OptionPattern {
867
- id;
868
- value;
869
- index = computed(() => this.listbox()?.inputs.items().indexOf(this) ?? -1);
870
- active = computed(() => this.listbox()?.inputs.activeItem() === this);
871
- selected = computed(() => this.listbox()?.inputs.values().includes(this.value()));
872
- selectable = () => true;
873
- disabled;
874
- searchTerm;
875
- listbox;
876
- tabIndex = computed(() => this.listbox()?.listBehavior.getItemTabindex(this));
877
- element;
878
- constructor(args) {
879
- this.id = args.id;
880
- this.value = args.value;
881
- this.listbox = args.listbox;
882
- this.element = args.element;
883
- this.disabled = args.disabled;
884
- this.searchTerm = args.searchTerm;
885
- }
886
- }
887
-
888
- class ComboboxListboxPattern extends ListboxPattern {
889
- inputs;
890
- id = computed(() => this.inputs.id());
891
- role = computed(() => 'listbox');
892
- activeId = computed(() => this.listBehavior.activeDescendant());
893
- items = computed(() => this.inputs.items());
894
- tabIndex = () => -1;
895
- multi = computed(() => {
896
- return this.inputs.combobox()?.readonly() ? this.inputs.multi() : false;
897
- });
898
- constructor(inputs) {
899
- if (inputs.combobox()) {
900
- inputs.focusMode = () => 'activedescendant';
901
- inputs.element = inputs.combobox().inputs.inputEl;
902
- }
903
- super(inputs);
904
- this.inputs = inputs;
905
- }
906
- onKeydown(_) {}
907
- onPointerdown(_) {}
908
- setDefaultState() {}
909
- focus = (item, opts) => {
910
- this.listBehavior.goto(item, opts);
911
- };
912
- getActiveItem = () => this.inputs.activeItem();
913
- next = () => this.listBehavior.next();
914
- prev = () => this.listBehavior.prev();
915
- last = () => this.listBehavior.last();
916
- first = () => this.listBehavior.first();
917
- unfocus = () => this.listBehavior.unfocus();
918
- select = item => this.listBehavior.select(item);
919
- toggle = item => this.listBehavior.toggle(item);
920
- clearSelection = () => this.listBehavior.deselectAll();
921
- getItem = e => this._getItem(e);
922
- getSelectedItems = () => {
923
- const items = [];
924
- for (const value of this.inputs.values()) {
925
- const item = this.items().find(i => i.value() === value);
926
- if (item) {
927
- items.push(item);
928
- }
929
- }
930
- return items;
931
- };
932
- setValue = value => this.inputs.values.set(value ? [value] : []);
933
- }
934
-
935
10
  class MenuPattern {
936
11
  inputs;
937
12
  id;
@@ -941,6 +16,7 @@ class MenuPattern {
941
16
  listBehavior;
942
17
  isFocused = signal(false);
943
18
  hasBeenFocused = signal(false);
19
+ hasBeenHovered = signal(false);
944
20
  _openTimeout;
945
21
  _closeTimeout;
946
22
  tabIndex = () => this.listBehavior.tabIndex();
@@ -1001,6 +77,7 @@ class MenuPattern {
1001
77
  if (!this.visible()) {
1002
78
  return;
1003
79
  }
80
+ this.hasBeenHovered.set(true);
1004
81
  const item = this.inputs.items().find(i => i.element()?.contains(event.target));
1005
82
  if (!item) {
1006
83
  return;
@@ -2215,7 +1292,7 @@ class DeferredContentAware {
2215
1292
  }] : []));
2216
1293
  static ɵfac = i0.ɵɵngDeclareFactory({
2217
1294
  minVersion: "12.0.0",
2218
- version: "21.0.0",
1295
+ version: "21.0.3",
2219
1296
  ngImport: i0,
2220
1297
  type: DeferredContentAware,
2221
1298
  deps: [],
@@ -2223,7 +1300,7 @@ class DeferredContentAware {
2223
1300
  });
2224
1301
  static ɵdir = i0.ɵɵngDeclareDirective({
2225
1302
  minVersion: "17.1.0",
2226
- version: "21.0.0",
1303
+ version: "21.0.3",
2227
1304
  type: DeferredContentAware,
2228
1305
  isStandalone: true,
2229
1306
  inputs: {
@@ -2243,7 +1320,7 @@ class DeferredContentAware {
2243
1320
  }
2244
1321
  i0.ɵɵngDeclareClassMetadata({
2245
1322
  minVersion: "12.0.0",
2246
- version: "21.0.0",
1323
+ version: "21.0.3",
2247
1324
  ngImport: i0,
2248
1325
  type: DeferredContentAware,
2249
1326
  decorators: [{
@@ -2300,7 +1377,7 @@ class DeferredContent {
2300
1377
  }
2301
1378
  static ɵfac = i0.ɵɵngDeclareFactory({
2302
1379
  minVersion: "12.0.0",
2303
- version: "21.0.0",
1380
+ version: "21.0.3",
2304
1381
  ngImport: i0,
2305
1382
  type: DeferredContent,
2306
1383
  deps: [],
@@ -2308,7 +1385,7 @@ class DeferredContent {
2308
1385
  });
2309
1386
  static ɵdir = i0.ɵɵngDeclareDirective({
2310
1387
  minVersion: "14.0.0",
2311
- version: "21.0.0",
1388
+ version: "21.0.3",
2312
1389
  type: DeferredContent,
2313
1390
  isStandalone: true,
2314
1391
  ngImport: i0
@@ -2316,7 +1393,7 @@ class DeferredContent {
2316
1393
  }
2317
1394
  i0.ɵɵngDeclareClassMetadata({
2318
1395
  minVersion: "12.0.0",
2319
- version: "21.0.0",
1396
+ version: "21.0.3",
2320
1397
  ngImport: i0,
2321
1398
  type: DeferredContent,
2322
1399
  decorators: [{
@@ -2325,5 +1402,5 @@ i0.ɵɵngDeclareClassMetadata({
2325
1402
  ctorParameters: () => []
2326
1403
  });
2327
1404
 
2328
- 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 };
1405
+ export { AccordionGroupPattern, AccordionPanelPattern, AccordionTriggerPattern, ComboboxTreePattern, DeferredContent, DeferredContentAware, MenuBarPattern, MenuItemPattern, MenuPattern, MenuTriggerPattern, TabListPattern, TabPanelPattern, TabPattern, ToolbarPattern, ToolbarWidgetGroupPattern, ToolbarWidgetPattern, TreeItemPattern, TreePattern, convertGetterSetterToWritableSignalLike };
2329
1406
  //# sourceMappingURL=private.mjs.map