@angular/aria 21.0.0-next.9 → 21.0.0-rc.1

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 (49) hide show
  1. package/_adev_assets/aria-accordion.json +373 -0
  2. package/_adev_assets/aria-combobox.json +383 -0
  3. package/_adev_assets/aria-grid.json +647 -0
  4. package/_adev_assets/aria-listbox.json +511 -0
  5. package/_adev_assets/aria-menu.json +852 -0
  6. package/_adev_assets/aria-tabs.json +987 -0
  7. package/_adev_assets/aria-toolbar.json +696 -0
  8. package/_adev_assets/aria-tree.json +1071 -0
  9. package/fesm2022/_widget-chunk.mjs +949 -0
  10. package/fesm2022/_widget-chunk.mjs.map +1 -0
  11. package/fesm2022/accordion.mjs +372 -174
  12. package/fesm2022/accordion.mjs.map +1 -1
  13. package/fesm2022/aria.mjs +1 -2
  14. package/fesm2022/aria.mjs.map +1 -1
  15. package/fesm2022/combobox.mjs +308 -116
  16. package/fesm2022/combobox.mjs.map +1 -1
  17. package/fesm2022/grid.mjs +566 -0
  18. package/fesm2022/grid.mjs.map +1 -0
  19. package/fesm2022/listbox.mjs +384 -184
  20. package/fesm2022/listbox.mjs.map +1 -1
  21. package/fesm2022/menu.mjs +591 -0
  22. package/fesm2022/menu.mjs.map +1 -0
  23. package/fesm2022/private.mjs +2338 -0
  24. package/fesm2022/private.mjs.map +1 -0
  25. package/fesm2022/tabs.mjs +484 -276
  26. package/fesm2022/tabs.mjs.map +1 -1
  27. package/fesm2022/toolbar.mjs +366 -200
  28. package/fesm2022/toolbar.mjs.map +1 -1
  29. package/fesm2022/tree.mjs +515 -267
  30. package/fesm2022/tree.mjs.map +1 -1
  31. package/package.json +12 -12
  32. package/types/_grid-chunk.d.ts +608 -0
  33. package/types/accordion.d.ts +8 -8
  34. package/types/combobox.d.ts +20 -7
  35. package/types/grid.d.ts +120 -0
  36. package/types/listbox.d.ts +9 -7
  37. package/types/menu.d.ts +170 -0
  38. package/types/{ui-patterns.d.ts → private.d.ts} +555 -433
  39. package/types/tabs.d.ts +8 -8
  40. package/types/toolbar.d.ts +31 -28
  41. package/types/tree.d.ts +11 -9
  42. package/fesm2022/deferred-content.mjs +0 -60
  43. package/fesm2022/deferred-content.mjs.map +0 -1
  44. package/fesm2022/radio-group.mjs +0 -197
  45. package/fesm2022/radio-group.mjs.map +0 -1
  46. package/fesm2022/ui-patterns.mjs +0 -2504
  47. package/fesm2022/ui-patterns.mjs.map +0 -1
  48. package/types/deferred-content.d.ts +0 -38
  49. package/types/radio-group.d.ts +0 -82
@@ -0,0 +1,2338 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, computed, model, Directive, inject, TemplateRef, ViewContainerRef, afterRenderEffect } from '@angular/core';
3
+ import { KeyboardEventManager, PointerEventManager, Modifier } from './_widget-chunk.mjs';
4
+ export { GridCellPattern, GridCellWidgetPattern, GridPattern, GridRowPattern } from './_widget-chunk.mjs';
5
+
6
+ class ComboboxPattern {
7
+ inputs;
8
+ expanded = signal(false);
9
+ activeDescendant = computed(() => this.inputs.popupControls()?.activeId() ?? null);
10
+ highlightedItem = signal(undefined);
11
+ isDeleting = false;
12
+ isFocused = signal(false);
13
+ expandKey = computed(() => this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight');
14
+ collapseKey = computed(() => this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft');
15
+ popupId = computed(() => this.inputs.popupControls()?.id() || null);
16
+ autocomplete = computed(() => this.inputs.filterMode() === 'highlight' ? 'both' : 'list');
17
+ hasPopup = computed(() => this.inputs.popupControls()?.role() || null);
18
+ readonly = computed(() => this.inputs.readonly() || null);
19
+ keydown = computed(() => {
20
+ if (!this.expanded()) {
21
+ const manager = new KeyboardEventManager().on('ArrowDown', () => this.open({
22
+ first: true
23
+ })).on('ArrowUp', () => this.open({
24
+ last: true
25
+ })).on('Escape', () => this.close({
26
+ reset: !this.readonly()
27
+ }));
28
+ if (this.readonly()) {
29
+ manager.on('Enter', () => this.open({
30
+ selected: true
31
+ })).on(' ', () => this.open({
32
+ selected: true
33
+ }));
34
+ }
35
+ return manager;
36
+ }
37
+ const popupControls = this.inputs.popupControls();
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
+ }));
44
+ if (this.readonly()) {
45
+ manager.on(' ', () => this.select({
46
+ commit: true,
47
+ close: !popupControls.multi()
48
+ }));
49
+ }
50
+ if (popupControls.role() === 'listbox') {
51
+ manager.on('Enter', () => this.select({
52
+ commit: true,
53
+ close: !popupControls.multi()
54
+ }));
55
+ }
56
+ if (popupControls.role() === 'tree') {
57
+ const treeControls = popupControls;
58
+ if (treeControls.isItemSelectable()) {
59
+ manager.on('Enter', () => this.select({
60
+ commit: true,
61
+ close: true
62
+ }));
63
+ } else if (treeControls.isItemExpandable()) {
64
+ manager.on('Enter', () => this.expandItem());
65
+ }
66
+ if (treeControls.isItemExpandable() || treeControls.isItemCollapsible()) {
67
+ manager.on(this.collapseKey(), () => this.collapseItem());
68
+ }
69
+ if (treeControls.isItemExpandable()) {
70
+ manager.on(this.expandKey(), () => this.expandItem());
71
+ }
72
+ }
73
+ return manager;
74
+ });
75
+ pointerup = computed(() => new PointerEventManager().on(e => {
76
+ const item = this.inputs.popupControls()?.getItem(e);
77
+ if (item) {
78
+ if (this.inputs.popupControls()?.role() === 'tree') {
79
+ const treeControls = this.inputs.popupControls();
80
+ if (treeControls.isItemExpandable(item) && !treeControls.isItemSelectable(item)) {
81
+ treeControls.toggleExpansion(item);
82
+ this.inputs.inputEl()?.focus();
83
+ return;
84
+ }
85
+ }
86
+ this.select({
87
+ item,
88
+ commit: true,
89
+ close: !this.inputs.popupControls()?.multi()
90
+ });
91
+ this.inputs.inputEl()?.focus();
92
+ }
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
+ }));
101
+ constructor(inputs) {
102
+ this.inputs = inputs;
103
+ }
104
+ onKeydown(event) {
105
+ if (!this.inputs.disabled()) {
106
+ this.keydown().handle(event);
107
+ }
108
+ }
109
+ onPointerup(event) {
110
+ if (!this.inputs.disabled()) {
111
+ this.pointerup().handle(event);
112
+ }
113
+ }
114
+ onInput(event) {
115
+ if (this.inputs.disabled() || this.inputs.readonly()) {
116
+ return;
117
+ }
118
+ const inputEl = this.inputs.inputEl();
119
+ if (!inputEl) {
120
+ return;
121
+ }
122
+ this.open();
123
+ this.inputs.inputValue?.set(inputEl.value);
124
+ 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
+ if (this.inputs.filterMode() === 'highlight' && !this.isDeleting) {
133
+ this.highlight();
134
+ }
135
+ }
136
+ onFocusIn() {
137
+ this.isFocused.set(true);
138
+ }
139
+ onFocusOut(event) {
140
+ if (this.inputs.disabled()) {
141
+ return;
142
+ }
143
+ if (!(event.relatedTarget instanceof HTMLElement) || !this.inputs.containerEl()?.contains(event.relatedTarget)) {
144
+ this.isFocused.set(false);
145
+ if (this.readonly()) {
146
+ this.close();
147
+ return;
148
+ }
149
+ if (this.inputs.filterMode() !== 'manual') {
150
+ this.commit();
151
+ } else {
152
+ const item = this.inputs.popupControls()?.items().find(i => i.searchTerm() === this.inputs.inputEl()?.value);
153
+ if (item) {
154
+ this.select({
155
+ item
156
+ });
157
+ }
158
+ }
159
+ this.close();
160
+ }
161
+ }
162
+ firstMatch = computed(() => {
163
+ if (this.inputs.popupControls()?.role() === 'listbox') {
164
+ return this.inputs.popupControls()?.items()[0];
165
+ }
166
+ return this.inputs.popupControls()?.items().find(i => i.value() === this.inputs.firstMatch());
167
+ });
168
+ onFilter() {
169
+ if (this.readonly()) {
170
+ return;
171
+ }
172
+ const isInitialRender = !this.inputs.inputValue?.().length && !this.isDeleting;
173
+ if (isInitialRender) {
174
+ return;
175
+ }
176
+ if (!this.isFocused()) {
177
+ return;
178
+ }
179
+ if (this.inputs.popupControls()?.role() === 'tree') {
180
+ const treeControls = this.inputs.popupControls();
181
+ this.inputs.inputValue?.().length ? treeControls.expandAll() : treeControls.collapseAll();
182
+ }
183
+ const item = this.firstMatch();
184
+ if (!item) {
185
+ this.inputs.popupControls()?.clearSelection();
186
+ this.inputs.popupControls()?.unfocus();
187
+ return;
188
+ }
189
+ this.inputs.popupControls()?.focus(item);
190
+ if (this.inputs.filterMode() !== 'manual') {
191
+ this.select({
192
+ item
193
+ });
194
+ }
195
+ if (this.inputs.filterMode() === 'highlight' && !this.isDeleting) {
196
+ this.highlight();
197
+ }
198
+ }
199
+ highlight() {
200
+ const inputEl = this.inputs.inputEl();
201
+ const selectedItems = this.inputs.popupControls()?.getSelectedItems();
202
+ const item = selectedItems?.[0];
203
+ if (!inputEl || !item) {
204
+ return;
205
+ }
206
+ const isHighlightable = item.searchTerm().toLowerCase().startsWith(this.inputs.inputValue().toLowerCase());
207
+ if (isHighlightable) {
208
+ inputEl.value = this.inputs.inputValue() + item.searchTerm().slice(this.inputs.inputValue().length);
209
+ inputEl.setSelectionRange(this.inputs.inputValue().length, item.searchTerm().length);
210
+ this.highlightedItem.set(item);
211
+ }
212
+ }
213
+ close(opts) {
214
+ if (!opts?.reset) {
215
+ this.expanded.set(false);
216
+ this.inputs.popupControls()?.unfocus();
217
+ return;
218
+ }
219
+ const popupControls = this.inputs.popupControls();
220
+ if (!this.expanded()) {
221
+ this.inputs.inputValue?.set('');
222
+ popupControls?.clearSelection();
223
+ const inputEl = this.inputs.inputEl();
224
+ if (inputEl) {
225
+ inputEl.value = '';
226
+ }
227
+ } else if (this.expanded()) {
228
+ this.close();
229
+ const selectedItem = popupControls?.getSelectedItems()?.[0];
230
+ if (selectedItem?.searchTerm() !== this.inputs.inputValue()) {
231
+ popupControls?.clearSelection();
232
+ }
233
+ }
234
+ this.close();
235
+ if (!this.readonly()) {
236
+ this.inputs.popupControls()?.clearSelection();
237
+ }
238
+ }
239
+ open(nav) {
240
+ this.expanded.set(true);
241
+ const inputEl = this.inputs.inputEl();
242
+ if (inputEl && this.inputs.filterMode() === 'highlight') {
243
+ const isHighlighting = inputEl.selectionStart !== inputEl.value.length;
244
+ this.inputs.inputValue?.set(inputEl.value.slice(0, inputEl.selectionStart || 0));
245
+ if (!isHighlighting) {
246
+ this.highlightedItem.set(undefined);
247
+ }
248
+ }
249
+ if (nav?.first) {
250
+ this.first();
251
+ }
252
+ if (nav?.last) {
253
+ this.last();
254
+ }
255
+ if (nav?.selected) {
256
+ const selectedItem = this.inputs.popupControls()?.items().find(i => this.inputs.popupControls()?.getSelectedItems().includes(i));
257
+ selectedItem ? this.inputs.popupControls()?.focus(selectedItem) : this.first();
258
+ }
259
+ }
260
+ next() {
261
+ this._navigate(() => this.inputs.popupControls()?.next());
262
+ }
263
+ prev() {
264
+ this._navigate(() => this.inputs.popupControls()?.prev());
265
+ }
266
+ first() {
267
+ this._navigate(() => this.inputs.popupControls()?.first());
268
+ }
269
+ last() {
270
+ this._navigate(() => this.inputs.popupControls()?.last());
271
+ }
272
+ collapseItem() {
273
+ const controls = this.inputs.popupControls();
274
+ this._navigate(() => controls?.collapseItem());
275
+ }
276
+ expandItem() {
277
+ const controls = this.inputs.popupControls();
278
+ this._navigate(() => controls?.expandItem());
279
+ }
280
+ select(opts = {}) {
281
+ const controls = this.inputs.popupControls();
282
+ if (opts.item) {
283
+ controls?.focus(opts.item, {
284
+ focusElement: false
285
+ });
286
+ }
287
+ controls?.multi() ? controls.toggle(opts.item) : controls?.select(opts.item);
288
+ if (opts.commit) {
289
+ this.commit();
290
+ }
291
+ if (opts.close) {
292
+ this.close();
293
+ }
294
+ }
295
+ commit() {
296
+ const inputEl = this.inputs.inputEl();
297
+ const selectedItems = this.inputs.popupControls()?.getSelectedItems();
298
+ if (!inputEl) {
299
+ return;
300
+ }
301
+ inputEl.value = selectedItems?.map(i => i.searchTerm()).join(', ') || '';
302
+ this.inputs.inputValue?.set(inputEl.value);
303
+ if (this.inputs.filterMode() === 'highlight' && !this.readonly()) {
304
+ const length = inputEl.value.length;
305
+ inputEl.setSelectionRange(length, length);
306
+ }
307
+ }
308
+ _navigate(operation) {
309
+ operation();
310
+ if (this.inputs.filterMode() !== 'manual') {
311
+ this.select();
312
+ }
313
+ if (this.inputs.filterMode() === 'highlight') {
314
+ const selectedItem = this.inputs.popupControls()?.getSelectedItems()[0];
315
+ if (!selectedItem) {
316
+ return;
317
+ }
318
+ if (selectedItem === this.highlightedItem()) {
319
+ this.highlight();
320
+ } else {
321
+ const inputEl = this.inputs.inputEl();
322
+ inputEl.value = selectedItem?.searchTerm();
323
+ }
324
+ }
325
+ }
326
+ }
327
+
328
+ class ListFocus {
329
+ inputs;
330
+ prevActiveItem = signal(undefined);
331
+ prevActiveIndex = computed(() => {
332
+ return this.prevActiveItem() ? this.inputs.items().indexOf(this.prevActiveItem()) : -1;
333
+ });
334
+ activeIndex = computed(() => {
335
+ return this.inputs.activeItem() ? this.inputs.items().indexOf(this.inputs.activeItem()) : -1;
336
+ });
337
+ constructor(inputs) {
338
+ this.inputs = inputs;
339
+ }
340
+ isListDisabled() {
341
+ return this.inputs.disabled() || this.inputs.items().every(i => i.disabled());
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;
425
+ }
426
+ _peek(delta) {
427
+ const items = this.inputs.items();
428
+ const itemCount = items.length;
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
+ }
435
+ }
436
+ return;
437
+ }
438
+ }
439
+
440
+ class ListSelection {
441
+ inputs;
442
+ rangeStartIndex = signal(0);
443
+ rangeEndIndex = signal(0);
444
+ selectedItems = computed(() => this.inputs.items().filter(item => this.inputs.value().includes(item.value())));
445
+ constructor(inputs) {
446
+ this.inputs = inputs;
447
+ }
448
+ select(item, opts = {
449
+ anchor: true
450
+ }) {
451
+ item = item ?? this.inputs.focusManager.inputs.activeItem();
452
+ if (!item || item.disabled() || !item.selectable() || this.inputs.value().includes(item.value())) {
453
+ return;
454
+ }
455
+ if (!this.inputs.multi()) {
456
+ this.deselectAll();
457
+ }
458
+ const index = this.inputs.items().findIndex(i => i === item);
459
+ if (opts.anchor) {
460
+ this.beginRangeSelection(index);
461
+ }
462
+ this.inputs.value.update(values => values.concat(item.value()));
463
+ }
464
+ deselect(item) {
465
+ item = item ?? this.inputs.focusManager.inputs.activeItem();
466
+ if (item && !item.disabled() && item.selectable()) {
467
+ this.inputs.value.update(values => values.filter(value => value !== item.value()));
468
+ }
469
+ }
470
+ toggle(item) {
471
+ item = item ?? this.inputs.focusManager.inputs.activeItem();
472
+ if (item) {
473
+ this.inputs.value().includes(item.value()) ? this.deselect(item) : this.select(item);
474
+ }
475
+ }
476
+ toggleOne() {
477
+ const item = this.inputs.focusManager.inputs.activeItem();
478
+ if (item) {
479
+ this.inputs.value().includes(item.value()) ? this.deselect() : this.selectOne();
480
+ }
481
+ }
482
+ selectAll() {
483
+ if (!this.inputs.multi()) {
484
+ return;
485
+ }
486
+ for (const item of this.inputs.items()) {
487
+ this.select(item, {
488
+ anchor: false
489
+ });
490
+ }
491
+ this.beginRangeSelection();
492
+ }
493
+ deselectAll() {
494
+ for (const value of this.inputs.value()) {
495
+ const item = this.inputs.items().find(i => i.value() === value);
496
+ item ? this.deselect(item) : this.inputs.value.update(values => values.filter(v => v !== value));
497
+ }
498
+ }
499
+ toggleAll() {
500
+ const selectableValues = this.inputs.items().filter(i => !i.disabled() && i.selectable()).map(i => i.value());
501
+ selectableValues.every(i => this.inputs.value().includes(i)) ? this.deselectAll() : this.selectAll();
502
+ }
503
+ selectOne() {
504
+ const item = this.inputs.focusManager.inputs.activeItem();
505
+ if (item && (item.disabled() || !item.selectable())) {
506
+ return;
507
+ }
508
+ this.deselectAll();
509
+ if (this.inputs.value().length > 0 && !this.inputs.multi()) {
510
+ return;
511
+ }
512
+ this.select();
513
+ }
514
+ selectRange(opts = {
515
+ anchor: true
516
+ }) {
517
+ const isStartOfRange = this.inputs.focusManager.prevActiveIndex() === this.rangeStartIndex();
518
+ if (isStartOfRange && opts.anchor) {
519
+ this.beginRangeSelection(this.inputs.focusManager.prevActiveIndex());
520
+ }
521
+ const itemsInRange = this._getItemsFromIndex(this.rangeStartIndex());
522
+ const itemsOutOfRange = this._getItemsFromIndex(this.rangeEndIndex()).filter(i => !itemsInRange.includes(i));
523
+ for (const item of itemsOutOfRange) {
524
+ this.deselect(item);
525
+ }
526
+ for (const item of itemsInRange) {
527
+ this.select(item, {
528
+ anchor: false
529
+ });
530
+ }
531
+ if (itemsInRange.length) {
532
+ const item = itemsInRange.pop();
533
+ const index = this.inputs.items().findIndex(i => i === item);
534
+ this.rangeEndIndex.set(index);
535
+ }
536
+ }
537
+ beginRangeSelection(index = this.inputs.focusManager.activeIndex()) {
538
+ this.rangeStartIndex.set(index);
539
+ this.rangeEndIndex.set(index);
540
+ }
541
+ _getItemsFromIndex(index) {
542
+ if (index === -1) {
543
+ return [];
544
+ }
545
+ const upper = Math.max(this.inputs.focusManager.activeIndex(), index);
546
+ const lower = Math.min(this.inputs.focusManager.activeIndex(), index);
547
+ const items = [];
548
+ for (let i = lower; i <= upper; i++) {
549
+ items.push(this.inputs.items()[i]);
550
+ }
551
+ if (this.inputs.focusManager.activeIndex() < index) {
552
+ return items.reverse();
553
+ }
554
+ return items;
555
+ }
556
+ }
557
+
558
+ class ListTypeahead {
559
+ inputs;
560
+ timeout;
561
+ focusManager;
562
+ isTyping = computed(() => this._query().length > 0);
563
+ _query = signal('');
564
+ _startIndex = signal(undefined);
565
+ constructor(inputs) {
566
+ this.inputs = inputs;
567
+ this.focusManager = inputs.focusManager;
568
+ }
569
+ search(char) {
570
+ if (char.length !== 1) {
571
+ return false;
572
+ }
573
+ if (!this.isTyping() && char === ' ') {
574
+ return false;
575
+ }
576
+ if (this._startIndex() === undefined) {
577
+ this._startIndex.set(this.focusManager.activeIndex());
578
+ }
579
+ clearTimeout(this.timeout);
580
+ this._query.update(q => q + char.toLowerCase());
581
+ const item = this._getItem();
582
+ if (item) {
583
+ this.focusManager.focus(item);
584
+ }
585
+ this.timeout = setTimeout(() => {
586
+ this._query.set('');
587
+ this._startIndex.set(undefined);
588
+ }, this.inputs.typeaheadDelay() * 1000);
589
+ return true;
590
+ }
591
+ _getItem() {
592
+ let items = this.focusManager.inputs.items();
593
+ const after = items.slice(this._startIndex() + 1);
594
+ const before = items.slice(0, this._startIndex());
595
+ items = after.concat(before);
596
+ items.push(this.inputs.items()[this._startIndex()]);
597
+ const focusableItems = [];
598
+ for (const item of items) {
599
+ if (this.focusManager.isFocusable(item)) {
600
+ focusableItems.push(item);
601
+ }
602
+ }
603
+ return focusableItems.find(i => i.searchTerm().toLowerCase().startsWith(this._query()));
604
+ }
605
+ }
606
+
607
+ class List {
608
+ inputs;
609
+ navigationBehavior;
610
+ selectionBehavior;
611
+ typeaheadBehavior;
612
+ focusBehavior;
613
+ disabled = computed(() => this.focusBehavior.isListDisabled());
614
+ activeDescendant = computed(() => this.focusBehavior.getActiveDescendant());
615
+ tabIndex = computed(() => this.focusBehavior.getListTabIndex());
616
+ activeIndex = computed(() => this.focusBehavior.activeIndex());
617
+ _anchorIndex = signal(0);
618
+ _wrap = signal(true);
619
+ constructor(inputs) {
620
+ this.inputs = inputs;
621
+ this.focusBehavior = new ListFocus(inputs);
622
+ this.selectionBehavior = new ListSelection({
623
+ ...inputs,
624
+ focusManager: this.focusBehavior
625
+ });
626
+ this.typeaheadBehavior = new ListTypeahead({
627
+ ...inputs,
628
+ focusManager: this.focusBehavior
629
+ });
630
+ this.navigationBehavior = new ListNavigation({
631
+ ...inputs,
632
+ focusManager: this.focusBehavior,
633
+ wrap: computed(() => this._wrap() && this.inputs.wrap())
634
+ });
635
+ }
636
+ getItemTabindex(item) {
637
+ return this.focusBehavior.getItemTabIndex(item);
638
+ }
639
+ first(opts) {
640
+ this._navigate(opts, () => this.navigationBehavior.first(opts));
641
+ }
642
+ last(opts) {
643
+ this._navigate(opts, () => this.navigationBehavior.last(opts));
644
+ }
645
+ next(opts) {
646
+ this._navigate(opts, () => this.navigationBehavior.next(opts));
647
+ }
648
+ prev(opts) {
649
+ this._navigate(opts, () => this.navigationBehavior.prev(opts));
650
+ }
651
+ goto(item, opts) {
652
+ this._navigate(opts, () => this.navigationBehavior.goto(item, opts));
653
+ }
654
+ unfocus() {
655
+ this.inputs.activeItem.set(undefined);
656
+ }
657
+ anchor(index) {
658
+ this._anchorIndex.set(index);
659
+ }
660
+ search(char, opts) {
661
+ this._navigate(opts, () => this.typeaheadBehavior.search(char));
662
+ }
663
+ isTyping() {
664
+ return this.typeaheadBehavior.isTyping();
665
+ }
666
+ select(item) {
667
+ this.selectionBehavior.select(item);
668
+ }
669
+ selectOne() {
670
+ this.selectionBehavior.selectOne();
671
+ }
672
+ deselect(item) {
673
+ this.selectionBehavior.deselect(item);
674
+ }
675
+ deselectAll() {
676
+ this.selectionBehavior.deselectAll();
677
+ }
678
+ toggle(item) {
679
+ this.selectionBehavior.toggle(item);
680
+ }
681
+ toggleOne() {
682
+ this.selectionBehavior.toggleOne();
683
+ }
684
+ toggleAll() {
685
+ this.selectionBehavior.toggleAll();
686
+ }
687
+ isFocusable(item) {
688
+ return this.focusBehavior.isFocusable(item);
689
+ }
690
+ updateSelection(opts = {
691
+ anchor: true
692
+ }) {
693
+ if (opts.toggle) {
694
+ this.selectionBehavior.toggle();
695
+ }
696
+ if (opts.select) {
697
+ this.selectionBehavior.select();
698
+ }
699
+ if (opts.selectOne) {
700
+ this.selectionBehavior.selectOne();
701
+ }
702
+ if (opts.selectRange) {
703
+ this.selectionBehavior.selectRange();
704
+ }
705
+ if (!opts.anchor) {
706
+ this.anchor(this.selectionBehavior.rangeStartIndex());
707
+ }
708
+ }
709
+ _navigate(opts = {}, operation) {
710
+ if (opts?.selectRange) {
711
+ this._wrap.set(false);
712
+ this.selectionBehavior.rangeStartIndex.set(this._anchorIndex());
713
+ }
714
+ const moved = operation();
715
+ if (moved) {
716
+ this.updateSelection(opts);
717
+ }
718
+ this._wrap.set(true);
719
+ }
720
+ }
721
+
722
+ class ListboxPattern {
723
+ inputs;
724
+ listBehavior;
725
+ orientation;
726
+ disabled = computed(() => this.listBehavior.disabled());
727
+ readonly;
728
+ tabIndex = computed(() => this.listBehavior.tabIndex());
729
+ activeDescendant = computed(() => this.listBehavior.activeDescendant());
730
+ multi;
731
+ setsize = computed(() => this.inputs.items().length);
732
+ followFocus = computed(() => this.inputs.selectionMode() === 'follow');
733
+ wrap = signal(true);
734
+ prevKey = computed(() => {
735
+ if (this.inputs.orientation() === 'vertical') {
736
+ return 'ArrowUp';
737
+ }
738
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
739
+ });
740
+ nextKey = computed(() => {
741
+ if (this.inputs.orientation() === 'vertical') {
742
+ return 'ArrowDown';
743
+ }
744
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
745
+ });
746
+ dynamicSpaceKey = computed(() => this.listBehavior.isTyping() ? '' : ' ');
747
+ typeaheadRegexp = /^.$/;
748
+ keydown = computed(() => {
749
+ const manager = new KeyboardEventManager();
750
+ if (this.readonly()) {
751
+ 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));
752
+ }
753
+ if (!this.followFocus()) {
754
+ 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));
755
+ }
756
+ if (this.followFocus()) {
757
+ manager.on(this.prevKey, () => this.listBehavior.prev({
758
+ selectOne: true
759
+ })).on(this.nextKey, () => this.listBehavior.next({
760
+ selectOne: true
761
+ })).on('Home', () => this.listBehavior.first({
762
+ selectOne: true
763
+ })).on('End', () => this.listBehavior.last({
764
+ selectOne: true
765
+ })).on(this.typeaheadRegexp, e => this.listBehavior.search(e.key, {
766
+ selectOne: true
767
+ }));
768
+ }
769
+ if (this.inputs.multi()) {
770
+ manager.on(Modifier.Any, 'Shift', () => this.listBehavior.anchor(this.listBehavior.activeIndex())).on(Modifier.Shift, this.prevKey, () => this.listBehavior.prev({
771
+ selectRange: true
772
+ })).on(Modifier.Shift, this.nextKey, () => this.listBehavior.next({
773
+ selectRange: true
774
+ })).on([Modifier.Ctrl | Modifier.Shift, Modifier.Meta | Modifier.Shift], 'Home', () => this.listBehavior.first({
775
+ selectRange: true,
776
+ anchor: false
777
+ })).on([Modifier.Ctrl | Modifier.Shift, Modifier.Meta | Modifier.Shift], 'End', () => this.listBehavior.last({
778
+ selectRange: true,
779
+ anchor: false
780
+ })).on(Modifier.Shift, 'Enter', () => this.listBehavior.updateSelection({
781
+ selectRange: true,
782
+ anchor: false
783
+ })).on(Modifier.Shift, this.dynamicSpaceKey, () => this.listBehavior.updateSelection({
784
+ selectRange: true,
785
+ anchor: false
786
+ }));
787
+ }
788
+ if (!this.followFocus() && this.inputs.multi()) {
789
+ manager.on(this.dynamicSpaceKey, () => this.listBehavior.toggle()).on('Enter', () => this.listBehavior.toggle()).on([Modifier.Ctrl, Modifier.Meta], 'A', () => this.listBehavior.toggleAll());
790
+ }
791
+ if (!this.followFocus() && !this.inputs.multi()) {
792
+ manager.on(this.dynamicSpaceKey, () => this.listBehavior.toggleOne());
793
+ manager.on('Enter', () => this.listBehavior.toggleOne());
794
+ }
795
+ if (this.inputs.multi() && this.followFocus()) {
796
+ 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', () => {
797
+ this.listBehavior.toggleAll();
798
+ this.listBehavior.select();
799
+ });
800
+ }
801
+ return manager;
802
+ });
803
+ pointerdown = computed(() => {
804
+ const manager = new PointerEventManager();
805
+ if (this.readonly()) {
806
+ return manager.on(e => this.listBehavior.goto(this._getItem(e)));
807
+ }
808
+ if (this.multi()) {
809
+ manager.on(Modifier.Shift, e => this.listBehavior.goto(this._getItem(e), {
810
+ selectRange: true
811
+ }));
812
+ }
813
+ if (!this.multi() && this.followFocus()) {
814
+ return manager.on(e => this.listBehavior.goto(this._getItem(e), {
815
+ selectOne: true
816
+ }));
817
+ }
818
+ if (!this.multi() && !this.followFocus()) {
819
+ return manager.on(e => this.listBehavior.goto(this._getItem(e), {
820
+ toggle: true
821
+ }));
822
+ }
823
+ if (this.multi() && this.followFocus()) {
824
+ return manager.on(e => this.listBehavior.goto(this._getItem(e), {
825
+ selectOne: true
826
+ })).on(Modifier.Ctrl, e => this.listBehavior.goto(this._getItem(e), {
827
+ toggle: true
828
+ }));
829
+ }
830
+ if (this.multi() && !this.followFocus()) {
831
+ return manager.on(e => this.listBehavior.goto(this._getItem(e), {
832
+ toggle: true
833
+ }));
834
+ }
835
+ return manager;
836
+ });
837
+ constructor(inputs) {
838
+ this.inputs = inputs;
839
+ this.readonly = inputs.readonly;
840
+ this.orientation = inputs.orientation;
841
+ this.multi = inputs.multi;
842
+ this.listBehavior = new List(inputs);
843
+ }
844
+ validate() {
845
+ const violations = [];
846
+ if (!this.inputs.multi() && this.inputs.value().length > 1) {
847
+ violations.push(`A single-select listbox should not have multiple selected options. Selected options: ${this.inputs.value().join(', ')}`);
848
+ }
849
+ return violations;
850
+ }
851
+ onKeydown(event) {
852
+ if (!this.disabled()) {
853
+ this.keydown().handle(event);
854
+ }
855
+ }
856
+ onPointerdown(event) {
857
+ if (!this.disabled()) {
858
+ this.pointerdown().handle(event);
859
+ }
860
+ }
861
+ setDefaultState() {
862
+ let firstItem = null;
863
+ for (const item of this.inputs.items()) {
864
+ if (this.listBehavior.isFocusable(item)) {
865
+ if (!firstItem) {
866
+ firstItem = item;
867
+ }
868
+ if (item.selected()) {
869
+ this.inputs.activeItem.set(item);
870
+ return;
871
+ }
872
+ }
873
+ }
874
+ if (firstItem) {
875
+ this.inputs.activeItem.set(firstItem);
876
+ }
877
+ }
878
+ _getItem(e) {
879
+ if (!(e.target instanceof HTMLElement)) {
880
+ return;
881
+ }
882
+ const element = e.target.closest('[role="option"]');
883
+ return this.inputs.items().find(i => i.element() === element);
884
+ }
885
+ }
886
+
887
+ class OptionPattern {
888
+ id;
889
+ value;
890
+ index = computed(() => this.listbox()?.inputs.items().indexOf(this) ?? -1);
891
+ active = computed(() => this.listbox()?.inputs.activeItem() === this);
892
+ selected = computed(() => this.listbox()?.inputs.value().includes(this.value()));
893
+ selectable = () => true;
894
+ disabled;
895
+ searchTerm;
896
+ listbox;
897
+ tabIndex = computed(() => this.listbox()?.listBehavior.getItemTabindex(this));
898
+ element;
899
+ constructor(args) {
900
+ this.id = args.id;
901
+ this.value = args.value;
902
+ this.listbox = args.listbox;
903
+ this.element = args.element;
904
+ this.disabled = args.disabled;
905
+ this.searchTerm = args.searchTerm;
906
+ }
907
+ }
908
+
909
+ class ComboboxListboxPattern extends ListboxPattern {
910
+ inputs;
911
+ id = computed(() => this.inputs.id());
912
+ role = computed(() => 'listbox');
913
+ activeId = computed(() => this.listBehavior.activeDescendant());
914
+ items = computed(() => this.inputs.items());
915
+ tabIndex = () => -1;
916
+ multi = computed(() => {
917
+ return this.inputs.combobox()?.readonly() ? this.inputs.multi() : false;
918
+ });
919
+ constructor(inputs) {
920
+ if (inputs.combobox()) {
921
+ inputs.focusMode = () => 'activedescendant';
922
+ inputs.element = inputs.combobox().inputs.inputEl;
923
+ }
924
+ super(inputs);
925
+ this.inputs = inputs;
926
+ }
927
+ onKeydown(_) {}
928
+ onPointerdown(_) {}
929
+ setDefaultState() {}
930
+ focus = (item, opts) => {
931
+ this.listBehavior.goto(item, opts);
932
+ };
933
+ next = () => this.listBehavior.next();
934
+ prev = () => this.listBehavior.prev();
935
+ last = () => this.listBehavior.last();
936
+ first = () => this.listBehavior.first();
937
+ unfocus = () => this.listBehavior.unfocus();
938
+ select = item => this.listBehavior.select(item);
939
+ toggle = item => this.listBehavior.toggle(item);
940
+ clearSelection = () => this.listBehavior.deselectAll();
941
+ getItem = e => this._getItem(e);
942
+ getSelectedItems = () => {
943
+ const items = [];
944
+ for (const value of this.inputs.value()) {
945
+ const item = this.items().find(i => i.value() === value);
946
+ if (item) {
947
+ items.push(item);
948
+ }
949
+ }
950
+ return items;
951
+ };
952
+ setValue = value => this.inputs.value.set(value ? [value] : []);
953
+ }
954
+
955
+ class MenuPattern {
956
+ inputs;
957
+ id;
958
+ role = () => 'menu';
959
+ isVisible = computed(() => this.inputs.parent() ? !!this.inputs.parent()?.expanded() : true);
960
+ listBehavior;
961
+ isFocused = signal(false);
962
+ hasBeenFocused = signal(false);
963
+ shouldFocus = computed(() => {
964
+ const root = this.root();
965
+ if (root instanceof MenuTriggerPattern) {
966
+ return true;
967
+ }
968
+ if (root instanceof MenuBarPattern || root instanceof MenuPattern) {
969
+ return root.isFocused();
970
+ }
971
+ return false;
972
+ });
973
+ _expandKey = computed(() => {
974
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
975
+ });
976
+ _collapseKey = computed(() => {
977
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
978
+ });
979
+ dynamicSpaceKey = computed(() => this.listBehavior.isTyping() ? '' : ' ');
980
+ typeaheadRegexp = /^.$/;
981
+ root = computed(() => {
982
+ const parent = this.inputs.parent();
983
+ if (!parent) {
984
+ return this;
985
+ }
986
+ if (parent instanceof MenuTriggerPattern) {
987
+ return parent;
988
+ }
989
+ const grandparent = parent.inputs.parent();
990
+ if (grandparent instanceof MenuBarPattern) {
991
+ return grandparent;
992
+ }
993
+ return grandparent?.root();
994
+ });
995
+ keydownManager = computed(() => {
996
+ return new KeyboardEventManager().on('ArrowDown', () => this.next()).on('ArrowUp', () => this.prev()).on('Home', () => this.first()).on('End', () => this.last()).on('Enter', () => this.trigger()).on('Escape', () => this.closeAll()).on(this._expandKey, () => this.expand()).on(this._collapseKey, () => this.collapse()).on(this.dynamicSpaceKey, () => this.trigger()).on(this.typeaheadRegexp, e => this.listBehavior.search(e.key));
997
+ });
998
+ constructor(inputs) {
999
+ this.inputs = inputs;
1000
+ this.id = inputs.id;
1001
+ this.listBehavior = new List({
1002
+ ...inputs,
1003
+ value: signal([]),
1004
+ disabled: () => false
1005
+ });
1006
+ }
1007
+ setDefaultState() {
1008
+ if (!this.inputs.parent()) {
1009
+ this.inputs.activeItem.set(this.inputs.items()[0]);
1010
+ }
1011
+ }
1012
+ onKeydown(event) {
1013
+ this.keydownManager().handle(event);
1014
+ }
1015
+ onMouseOver(event) {
1016
+ if (!this.isVisible()) {
1017
+ return;
1018
+ }
1019
+ const item = this.inputs.items().find(i => i.element()?.contains(event.target));
1020
+ if (!item) {
1021
+ return;
1022
+ }
1023
+ const activeItem = this?.inputs.activeItem();
1024
+ if (activeItem && activeItem !== item) {
1025
+ activeItem.close();
1026
+ }
1027
+ if (item.expanded() && item.submenu()?.inputs.activeItem()) {
1028
+ item.submenu()?.inputs.activeItem()?.close();
1029
+ item.submenu()?.listBehavior.unfocus();
1030
+ }
1031
+ item.open();
1032
+ this.listBehavior.goto(item, {
1033
+ focusElement: this.shouldFocus()
1034
+ });
1035
+ }
1036
+ onMouseOut(event) {
1037
+ if (this.isFocused()) {
1038
+ return;
1039
+ }
1040
+ const root = this.root();
1041
+ const parent = this.inputs.parent();
1042
+ const relatedTarget = event.relatedTarget;
1043
+ if (!root || !parent || parent instanceof MenuTriggerPattern) {
1044
+ return;
1045
+ }
1046
+ const grandparent = parent.inputs.parent();
1047
+ if (!grandparent || grandparent instanceof MenuBarPattern) {
1048
+ return;
1049
+ }
1050
+ if (!grandparent.inputs.element()?.contains(relatedTarget)) {
1051
+ parent.close();
1052
+ }
1053
+ }
1054
+ onClick(event) {
1055
+ const relatedTarget = event.target;
1056
+ const item = this.inputs.items().find(i => i.element()?.contains(relatedTarget));
1057
+ if (item) {
1058
+ item.open();
1059
+ this.listBehavior.goto(item);
1060
+ this.submit(item);
1061
+ }
1062
+ }
1063
+ onFocusIn() {
1064
+ this.isFocused.set(true);
1065
+ this.hasBeenFocused.set(true);
1066
+ }
1067
+ onFocusOut(event) {
1068
+ const parent = this.inputs.parent();
1069
+ const parentEl = parent?.inputs.element();
1070
+ const relatedTarget = event.relatedTarget;
1071
+ if (!relatedTarget) {
1072
+ this.isFocused.set(false);
1073
+ this.inputs.parent()?.close({
1074
+ refocus: true
1075
+ });
1076
+ }
1077
+ if (parent instanceof MenuItemPattern) {
1078
+ const grandparent = parent.inputs.parent();
1079
+ const siblings = grandparent?.inputs.items().filter(i => i !== parent);
1080
+ const item = siblings?.find(i => i.element()?.contains(relatedTarget));
1081
+ if (item) {
1082
+ return;
1083
+ }
1084
+ }
1085
+ if (this.isVisible() && !parentEl?.contains(relatedTarget) && !this.inputs.element()?.contains(relatedTarget)) {
1086
+ this.isFocused.set(false);
1087
+ this.inputs.parent()?.close();
1088
+ }
1089
+ }
1090
+ prev() {
1091
+ this.inputs.activeItem()?.close();
1092
+ this.listBehavior.prev();
1093
+ }
1094
+ next() {
1095
+ this.inputs.activeItem()?.close();
1096
+ this.listBehavior.next();
1097
+ }
1098
+ first() {
1099
+ this.inputs.activeItem()?.close();
1100
+ this.listBehavior.first();
1101
+ }
1102
+ last() {
1103
+ this.inputs.activeItem()?.close();
1104
+ this.listBehavior.last();
1105
+ }
1106
+ trigger() {
1107
+ this.inputs.activeItem()?.hasPopup() ? this.inputs.activeItem()?.open({
1108
+ first: true
1109
+ }) : this.submit();
1110
+ }
1111
+ submit(item = this.inputs.activeItem()) {
1112
+ const root = this.root();
1113
+ if (item && !item.disabled()) {
1114
+ const isMenu = root instanceof MenuPattern;
1115
+ const isMenuBar = root instanceof MenuBarPattern;
1116
+ const isMenuTrigger = root instanceof MenuTriggerPattern;
1117
+ if (!item.submenu() && isMenuTrigger) {
1118
+ root.close({
1119
+ refocus: true
1120
+ });
1121
+ }
1122
+ if (!item.submenu() && isMenuBar) {
1123
+ root.close();
1124
+ root?.inputs.onSelect?.(item.value());
1125
+ }
1126
+ if (!item.submenu() && isMenu) {
1127
+ root.inputs.activeItem()?.close({
1128
+ refocus: true
1129
+ });
1130
+ root?.inputs.onSelect?.(item.value());
1131
+ }
1132
+ }
1133
+ }
1134
+ collapse() {
1135
+ const root = this.root();
1136
+ const parent = this.inputs.parent();
1137
+ if (parent instanceof MenuItemPattern && !(parent.inputs.parent() instanceof MenuBarPattern)) {
1138
+ parent.close({
1139
+ refocus: true
1140
+ });
1141
+ } else if (root instanceof MenuBarPattern) {
1142
+ root.prev();
1143
+ }
1144
+ }
1145
+ expand() {
1146
+ const root = this.root();
1147
+ const activeItem = this.inputs.activeItem();
1148
+ if (activeItem?.submenu()) {
1149
+ activeItem.open({
1150
+ first: true
1151
+ });
1152
+ } else if (root instanceof MenuBarPattern) {
1153
+ root.next();
1154
+ }
1155
+ }
1156
+ closeAll() {
1157
+ const root = this.root();
1158
+ if (root instanceof MenuTriggerPattern) {
1159
+ root.close({
1160
+ refocus: true
1161
+ });
1162
+ }
1163
+ if (root instanceof MenuBarPattern) {
1164
+ root.close();
1165
+ }
1166
+ if (root instanceof MenuPattern) {
1167
+ root.inputs.activeItem()?.close({
1168
+ refocus: true
1169
+ });
1170
+ }
1171
+ }
1172
+ }
1173
+ class MenuBarPattern {
1174
+ inputs;
1175
+ listBehavior;
1176
+ _nextKey = computed(() => {
1177
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
1178
+ });
1179
+ _previousKey = computed(() => {
1180
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
1181
+ });
1182
+ dynamicSpaceKey = computed(() => this.listBehavior.isTyping() ? '' : ' ');
1183
+ typeaheadRegexp = /^.$/;
1184
+ isFocused = signal(false);
1185
+ hasBeenFocused = signal(false);
1186
+ keydownManager = computed(() => {
1187
+ 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
+ first: true
1189
+ })).on('ArrowUp', () => this.inputs.activeItem()?.open({
1190
+ last: true
1191
+ })).on('ArrowDown', () => this.inputs.activeItem()?.open({
1192
+ first: true
1193
+ })).on(this.dynamicSpaceKey, () => this.inputs.activeItem()?.open({
1194
+ first: true
1195
+ })).on(this.typeaheadRegexp, e => this.listBehavior.search(e.key));
1196
+ });
1197
+ constructor(inputs) {
1198
+ this.inputs = inputs;
1199
+ this.listBehavior = new List({
1200
+ ...inputs,
1201
+ disabled: () => false
1202
+ });
1203
+ }
1204
+ setDefaultState() {
1205
+ this.inputs.activeItem.set(this.inputs.items()[0]);
1206
+ }
1207
+ onKeydown(event) {
1208
+ this.keydownManager().handle(event);
1209
+ }
1210
+ onClick(event) {
1211
+ const item = this.inputs.items().find(i => i.element()?.contains(event.target));
1212
+ if (!item) {
1213
+ return;
1214
+ }
1215
+ this.goto(item);
1216
+ item.expanded() ? item.close() : item.open();
1217
+ }
1218
+ onMouseOver(event) {
1219
+ const item = this.inputs.items().find(i => i.element()?.contains(event.target));
1220
+ if (item) {
1221
+ this.goto(item, {
1222
+ focusElement: this.isFocused()
1223
+ });
1224
+ }
1225
+ }
1226
+ onFocusIn() {
1227
+ this.isFocused.set(true);
1228
+ this.hasBeenFocused.set(true);
1229
+ }
1230
+ onFocusOut(event) {
1231
+ const relatedTarget = event.relatedTarget;
1232
+ if (!this.inputs.element()?.contains(relatedTarget)) {
1233
+ this.isFocused.set(false);
1234
+ this.close();
1235
+ }
1236
+ }
1237
+ goto(item, opts) {
1238
+ const prevItem = this.inputs.activeItem();
1239
+ this.listBehavior.goto(item, opts);
1240
+ if (prevItem?.expanded()) {
1241
+ prevItem?.close();
1242
+ this.inputs.activeItem()?.open();
1243
+ }
1244
+ if (item === prevItem) {
1245
+ if (item.expanded() && item.submenu()?.inputs.activeItem()) {
1246
+ item.submenu()?.inputs.activeItem()?.close();
1247
+ item.submenu()?.listBehavior.unfocus();
1248
+ }
1249
+ }
1250
+ }
1251
+ next() {
1252
+ const prevItem = this.inputs.activeItem();
1253
+ this.listBehavior.next();
1254
+ if (prevItem?.expanded()) {
1255
+ prevItem?.close();
1256
+ this.inputs.activeItem()?.open({
1257
+ first: true
1258
+ });
1259
+ }
1260
+ }
1261
+ prev() {
1262
+ const prevItem = this.inputs.activeItem();
1263
+ this.listBehavior.prev();
1264
+ if (prevItem?.expanded()) {
1265
+ prevItem?.close();
1266
+ this.inputs.activeItem()?.open({
1267
+ first: true
1268
+ });
1269
+ }
1270
+ }
1271
+ close() {
1272
+ this.inputs.activeItem()?.close({
1273
+ refocus: this.isFocused()
1274
+ });
1275
+ }
1276
+ }
1277
+ class MenuTriggerPattern {
1278
+ inputs;
1279
+ expanded = signal(false);
1280
+ role = () => 'button';
1281
+ hasPopup = () => true;
1282
+ menu;
1283
+ tabIndex = computed(() => this.expanded() && this.menu()?.inputs.activeItem() ? -1 : 0);
1284
+ keydownManager = computed(() => {
1285
+ return new KeyboardEventManager().on(' ', () => this.open({
1286
+ first: true
1287
+ })).on('Enter', () => this.open({
1288
+ first: true
1289
+ })).on('ArrowDown', () => this.open({
1290
+ first: true
1291
+ })).on('ArrowUp', () => this.open({
1292
+ last: true
1293
+ })).on('Escape', () => this.close({
1294
+ refocus: true
1295
+ }));
1296
+ });
1297
+ constructor(inputs) {
1298
+ this.inputs = inputs;
1299
+ this.menu = this.inputs.menu;
1300
+ }
1301
+ onKeydown(event) {
1302
+ this.keydownManager().handle(event);
1303
+ }
1304
+ onClick() {
1305
+ this.expanded() ? this.close() : this.open({
1306
+ first: true
1307
+ });
1308
+ }
1309
+ onFocusOut(event) {
1310
+ const element = this.inputs.element();
1311
+ const relatedTarget = event.relatedTarget;
1312
+ if (this.expanded() && !element?.contains(relatedTarget) && !this.inputs.menu()?.inputs.element()?.contains(relatedTarget)) {
1313
+ this.close();
1314
+ }
1315
+ }
1316
+ open(opts) {
1317
+ this.expanded.set(true);
1318
+ if (opts?.first) {
1319
+ this.inputs.menu()?.first();
1320
+ } else if (opts?.last) {
1321
+ this.inputs.menu()?.last();
1322
+ }
1323
+ }
1324
+ close(opts = {}) {
1325
+ this.expanded.set(false);
1326
+ this.menu()?.listBehavior.unfocus();
1327
+ if (opts.refocus) {
1328
+ this.inputs.element()?.focus();
1329
+ }
1330
+ let menuitems = this.inputs.menu()?.inputs.items() ?? [];
1331
+ while (menuitems.length) {
1332
+ const menuitem = menuitems.pop();
1333
+ menuitem?._expanded.set(false);
1334
+ menuitem?.inputs.parent()?.listBehavior.unfocus();
1335
+ menuitems = menuitems.concat(menuitem?.submenu()?.inputs.items() ?? []);
1336
+ }
1337
+ }
1338
+ }
1339
+ class MenuItemPattern {
1340
+ inputs;
1341
+ value;
1342
+ id;
1343
+ disabled;
1344
+ searchTerm;
1345
+ element;
1346
+ isActive = computed(() => this.inputs.parent()?.inputs.activeItem() === this);
1347
+ tabIndex = computed(() => {
1348
+ if (this.submenu() && this.submenu()?.inputs.activeItem()) {
1349
+ return -1;
1350
+ }
1351
+ return this.inputs.parent()?.listBehavior.getItemTabindex(this) ?? -1;
1352
+ });
1353
+ index = computed(() => this.inputs.parent()?.inputs.items().indexOf(this) ?? -1);
1354
+ expanded = computed(() => this.submenu() ? this._expanded() : null);
1355
+ _expanded = signal(false);
1356
+ controls = signal(undefined);
1357
+ role = () => 'menuitem';
1358
+ hasPopup = computed(() => !!this.submenu());
1359
+ submenu;
1360
+ selectable;
1361
+ constructor(inputs) {
1362
+ this.inputs = inputs;
1363
+ this.id = inputs.id;
1364
+ this.value = inputs.value;
1365
+ this.element = inputs.element;
1366
+ this.disabled = inputs.disabled;
1367
+ this.submenu = this.inputs.submenu;
1368
+ this.searchTerm = inputs.searchTerm;
1369
+ this.selectable = computed(() => !this.submenu());
1370
+ }
1371
+ open(opts) {
1372
+ this._expanded.set(true);
1373
+ if (opts?.first) {
1374
+ this.submenu()?.first();
1375
+ }
1376
+ if (opts?.last) {
1377
+ this.submenu()?.last();
1378
+ }
1379
+ }
1380
+ close(opts = {}) {
1381
+ this._expanded.set(false);
1382
+ if (opts.refocus) {
1383
+ this.inputs.parent()?.listBehavior.goto(this);
1384
+ }
1385
+ let menuitems = this.inputs.submenu()?.inputs.items() ?? [];
1386
+ while (menuitems.length) {
1387
+ const menuitem = menuitems.pop();
1388
+ menuitem?._expanded.set(false);
1389
+ menuitem?.inputs.parent()?.listBehavior.unfocus();
1390
+ menuitems = menuitems.concat(menuitem?.submenu()?.inputs.items() ?? []);
1391
+ }
1392
+ }
1393
+ }
1394
+
1395
+ function convertGetterSetterToWritableSignalLike(getter, setter) {
1396
+ return Object.assign(getter, {
1397
+ set: setter,
1398
+ update: updateCallback => setter(updateCallback(getter()))
1399
+ });
1400
+ }
1401
+
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
+ class ListExpansion {
1423
+ inputs;
1424
+ expandedIds;
1425
+ constructor(inputs) {
1426
+ this.inputs = inputs;
1427
+ this.expandedIds = inputs.expandedIds;
1428
+ }
1429
+ open(item) {
1430
+ if (!this.isExpandable(item)) return;
1431
+ if (this.isExpanded(item)) return;
1432
+ if (!this.inputs.multiExpandable()) {
1433
+ this.closeAll();
1434
+ }
1435
+ this.expandedIds.update(ids => ids.concat(item.expansionId()));
1436
+ }
1437
+ close(item) {
1438
+ if (this.isExpandable(item)) {
1439
+ this.expandedIds.update(ids => ids.filter(id => id !== item.expansionId()));
1440
+ }
1441
+ }
1442
+ toggle(item) {
1443
+ this.expandedIds().includes(item.expansionId()) ? this.close(item) : this.open(item);
1444
+ }
1445
+ openAll() {
1446
+ if (this.inputs.multiExpandable()) {
1447
+ for (const item of this.inputs.items()) {
1448
+ this.open(item);
1449
+ }
1450
+ }
1451
+ }
1452
+ closeAll() {
1453
+ for (const item of this.inputs.items()) {
1454
+ this.close(item);
1455
+ }
1456
+ }
1457
+ isExpandable(item) {
1458
+ return !this.inputs.disabled() && !item.disabled() && item.expandable();
1459
+ }
1460
+ isExpanded(item) {
1461
+ return this.expandedIds().includes(item.expansionId());
1462
+ }
1463
+ }
1464
+
1465
+ class LabelControl {
1466
+ inputs;
1467
+ label = computed(() => this.inputs.label?.());
1468
+ labelledBy = computed(() => {
1469
+ const label = this.label();
1470
+ const labelledBy = this.inputs.labelledBy?.();
1471
+ const defaultLabelledBy = this.inputs.defaultLabelledBy();
1472
+ if (labelledBy && labelledBy.length > 0) {
1473
+ return labelledBy;
1474
+ }
1475
+ if (label) {
1476
+ return [];
1477
+ }
1478
+ return defaultLabelledBy;
1479
+ });
1480
+ constructor(inputs) {
1481
+ this.inputs = inputs;
1482
+ }
1483
+ }
1484
+
1485
+ class TabPattern {
1486
+ inputs;
1487
+ expansion;
1488
+ id;
1489
+ index = computed(() => this.inputs.tablist().inputs.items().indexOf(this));
1490
+ value;
1491
+ disabled;
1492
+ element;
1493
+ selectable = () => true;
1494
+ searchTerm = () => '';
1495
+ expandable = computed(() => this.expansion.expandable());
1496
+ expansionId = computed(() => this.expansion.expansionId());
1497
+ expanded = computed(() => this.expansion.isExpanded());
1498
+ active = computed(() => this.inputs.tablist().inputs.activeItem() === this);
1499
+ selected = computed(() => !!this.inputs.tablist().inputs.value().includes(this.value()));
1500
+ tabIndex = computed(() => this.inputs.tablist().listBehavior.getItemTabindex(this));
1501
+ controls = computed(() => this.inputs.tabpanel()?.id());
1502
+ constructor(inputs) {
1503
+ this.inputs = inputs;
1504
+ this.id = inputs.id;
1505
+ this.value = inputs.value;
1506
+ this.disabled = inputs.disabled;
1507
+ this.element = inputs.element;
1508
+ this.expansion = new ExpansionControl({
1509
+ ...inputs,
1510
+ expansionId: inputs.value,
1511
+ expandable: () => true,
1512
+ expansionManager: inputs.tablist().expansionManager
1513
+ });
1514
+ }
1515
+ }
1516
+ class TabPanelPattern {
1517
+ inputs;
1518
+ id;
1519
+ value;
1520
+ labelManager;
1521
+ hidden = computed(() => this.inputs.tab()?.expanded() === false);
1522
+ tabIndex = computed(() => this.hidden() ? -1 : 0);
1523
+ labelledBy = computed(() => this.labelManager.labelledBy().length > 0 ? this.labelManager.labelledBy().join(' ') : undefined);
1524
+ constructor(inputs) {
1525
+ this.inputs = inputs;
1526
+ this.id = inputs.id;
1527
+ this.value = inputs.value;
1528
+ this.labelManager = new LabelControl({
1529
+ ...inputs,
1530
+ defaultLabelledBy: computed(() => this.inputs.tab() ? [this.inputs.tab().id()] : [])
1531
+ });
1532
+ }
1533
+ }
1534
+ class TabListPattern {
1535
+ inputs;
1536
+ listBehavior;
1537
+ expansionManager;
1538
+ orientation;
1539
+ disabled;
1540
+ tabIndex = computed(() => this.listBehavior.tabIndex());
1541
+ activeDescendant = computed(() => this.listBehavior.activeDescendant());
1542
+ followFocus = computed(() => this.inputs.selectionMode() === 'follow');
1543
+ prevKey = computed(() => {
1544
+ if (this.inputs.orientation() === 'vertical') {
1545
+ return 'ArrowUp';
1546
+ }
1547
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
1548
+ });
1549
+ nextKey = computed(() => {
1550
+ if (this.inputs.orientation() === 'vertical') {
1551
+ return 'ArrowDown';
1552
+ }
1553
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
1554
+ });
1555
+ keydown = computed(() => {
1556
+ return new KeyboardEventManager().on(this.prevKey, () => this.listBehavior.prev({
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());
1565
+ });
1566
+ pointerdown = computed(() => {
1567
+ return new PointerEventManager().on(e => this.listBehavior.goto(this._getItem(e), {
1568
+ select: true
1569
+ }));
1570
+ });
1571
+ constructor(inputs) {
1572
+ this.inputs = inputs;
1573
+ this.disabled = inputs.disabled;
1574
+ this.orientation = inputs.orientation;
1575
+ this.listBehavior = new List({
1576
+ ...inputs,
1577
+ multi: () => false,
1578
+ typeaheadDelay: () => 0
1579
+ });
1580
+ this.expansionManager = new ListExpansion({
1581
+ ...inputs,
1582
+ multiExpandable: () => false,
1583
+ expandedIds: this.inputs.value
1584
+ });
1585
+ }
1586
+ setDefaultState() {
1587
+ let firstItem;
1588
+ for (const item of this.inputs.items()) {
1589
+ if (!this.listBehavior.isFocusable(item)) continue;
1590
+ if (firstItem === undefined) {
1591
+ firstItem = item;
1592
+ }
1593
+ if (item.selected()) {
1594
+ this.inputs.activeItem.set(item);
1595
+ return;
1596
+ }
1597
+ }
1598
+ if (firstItem !== undefined) {
1599
+ this.inputs.activeItem.set(firstItem);
1600
+ }
1601
+ }
1602
+ onKeydown(event) {
1603
+ if (!this.disabled()) {
1604
+ this.keydown().handle(event);
1605
+ }
1606
+ }
1607
+ onPointerdown(event) {
1608
+ if (!this.disabled()) {
1609
+ this.pointerdown().handle(event);
1610
+ }
1611
+ }
1612
+ _getItem(e) {
1613
+ if (!(e.target instanceof HTMLElement)) {
1614
+ return;
1615
+ }
1616
+ const element = e.target.closest('[role="tab"]');
1617
+ return this.inputs.items().find(i => i.element() === element);
1618
+ }
1619
+ }
1620
+
1621
+ class ToolbarPattern {
1622
+ inputs;
1623
+ listBehavior;
1624
+ orientation;
1625
+ softDisabled;
1626
+ disabled = computed(() => this.listBehavior.disabled());
1627
+ tabIndex = computed(() => this.listBehavior.tabIndex());
1628
+ activeDescendant = computed(() => this.listBehavior.activeDescendant());
1629
+ activeItem = () => this.listBehavior.inputs.activeItem();
1630
+ _prevKey = computed(() => {
1631
+ if (this.inputs.orientation() === 'vertical') {
1632
+ return 'ArrowUp';
1633
+ }
1634
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
1635
+ });
1636
+ _nextKey = computed(() => {
1637
+ if (this.inputs.orientation() === 'vertical') {
1638
+ return 'ArrowDown';
1639
+ }
1640
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
1641
+ });
1642
+ _altPrevKey = computed(() => {
1643
+ if (this.inputs.orientation() === 'vertical') {
1644
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
1645
+ }
1646
+ return 'ArrowUp';
1647
+ });
1648
+ _altNextKey = computed(() => {
1649
+ if (this.inputs.orientation() === 'vertical') {
1650
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
1651
+ }
1652
+ return 'ArrowDown';
1653
+ });
1654
+ _keydown = computed(() => {
1655
+ const manager = new KeyboardEventManager();
1656
+ return manager.on(this._nextKey, () => this.listBehavior.next()).on(this._prevKey, () => this.listBehavior.prev()).on(this._altNextKey, () => this._groupNext()).on(this._altPrevKey, () => this._groupPrev()).on(' ', () => this.select()).on('Enter', () => this.select()).on('Home', () => this.listBehavior.first()).on('End', () => this.listBehavior.last());
1657
+ });
1658
+ _groupNext() {
1659
+ const currGroup = this.inputs.activeItem()?.group();
1660
+ const nextGroup = this.listBehavior.navigationBehavior.peekNext()?.group();
1661
+ if (!currGroup) {
1662
+ return;
1663
+ }
1664
+ if (currGroup !== nextGroup) {
1665
+ this.listBehavior.goto(this.listBehavior.navigationBehavior.peekFirst(currGroup.inputs.items()));
1666
+ return;
1667
+ }
1668
+ this.listBehavior.next();
1669
+ }
1670
+ _groupPrev() {
1671
+ const currGroup = this.inputs.activeItem()?.group();
1672
+ const nextGroup = this.listBehavior.navigationBehavior.peekPrev()?.group();
1673
+ if (!currGroup) {
1674
+ return;
1675
+ }
1676
+ if (currGroup !== nextGroup) {
1677
+ this.listBehavior.goto(this.listBehavior.navigationBehavior.peekLast(currGroup.inputs.items()));
1678
+ return;
1679
+ }
1680
+ this.listBehavior.prev();
1681
+ }
1682
+ _goto(e) {
1683
+ const item = this.inputs.getItem(e.target);
1684
+ if (item) {
1685
+ this.listBehavior.goto(item);
1686
+ this.select();
1687
+ }
1688
+ }
1689
+ select() {
1690
+ const group = this.inputs.activeItem()?.group();
1691
+ if (!group?.multi()) {
1692
+ group?.inputs.items().forEach(i => this.listBehavior.deselect(i));
1693
+ }
1694
+ this.listBehavior.toggle();
1695
+ }
1696
+ constructor(inputs) {
1697
+ this.inputs = inputs;
1698
+ this.orientation = inputs.orientation;
1699
+ this.softDisabled = inputs.softDisabled;
1700
+ this.listBehavior = new List({
1701
+ ...inputs,
1702
+ multi: () => true,
1703
+ focusMode: () => 'roving',
1704
+ selectionMode: () => 'explicit',
1705
+ value: signal([]),
1706
+ typeaheadDelay: () => 0
1707
+ });
1708
+ }
1709
+ onKeydown(event) {
1710
+ if (this.disabled()) return;
1711
+ this._keydown().handle(event);
1712
+ }
1713
+ onPointerdown(event) {
1714
+ event.preventDefault();
1715
+ }
1716
+ onClick(event) {
1717
+ if (this.disabled()) return;
1718
+ this._goto(event);
1719
+ }
1720
+ setDefaultState() {
1721
+ const firstItem = this.listBehavior.navigationBehavior.peekFirst(this.inputs.items());
1722
+ if (firstItem) {
1723
+ this.inputs.activeItem.set(firstItem);
1724
+ }
1725
+ }
1726
+ validate() {
1727
+ const violations = [];
1728
+ return violations;
1729
+ }
1730
+ }
1731
+
1732
+ class ToolbarWidgetPattern {
1733
+ inputs;
1734
+ id = () => this.inputs.id();
1735
+ element = () => this.inputs.element();
1736
+ disabled = () => this.inputs.disabled() || this.group()?.disabled() || false;
1737
+ group = () => this.inputs.group();
1738
+ toolbar = () => this.inputs.toolbar();
1739
+ tabIndex = computed(() => this.toolbar().listBehavior.getItemTabindex(this));
1740
+ searchTerm = () => '';
1741
+ value = () => this.inputs.value();
1742
+ selectable = () => true;
1743
+ index = computed(() => this.toolbar().inputs.items().indexOf(this) ?? -1);
1744
+ selected = computed(() => this.toolbar().listBehavior.inputs.value().includes(this.value()));
1745
+ active = computed(() => this.toolbar().activeItem() === this);
1746
+ constructor(inputs) {
1747
+ this.inputs = inputs;
1748
+ }
1749
+ }
1750
+
1751
+ class ToolbarWidgetGroupPattern {
1752
+ inputs;
1753
+ disabled = () => this.inputs.disabled();
1754
+ toolbar = () => this.inputs.toolbar();
1755
+ multi = () => this.inputs.multi();
1756
+ searchTerm = () => '';
1757
+ value = () => '';
1758
+ selectable = () => true;
1759
+ element = () => undefined;
1760
+ constructor(inputs) {
1761
+ this.inputs = inputs;
1762
+ }
1763
+ }
1764
+
1765
+ const focusMode = () => 'roving';
1766
+ class AccordionGroupPattern {
1767
+ inputs;
1768
+ navigation;
1769
+ focusManager;
1770
+ expansionManager;
1771
+ constructor(inputs) {
1772
+ this.inputs = inputs;
1773
+ this.wrap = inputs.wrap;
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({
1783
+ ...inputs,
1784
+ focusMode
1785
+ });
1786
+ this.navigation = new ListNavigation({
1787
+ ...inputs,
1788
+ focusMode,
1789
+ focusManager: this.focusManager
1790
+ });
1791
+ this.expansionManager = new ListExpansion({
1792
+ ...inputs
1793
+ });
1794
+ }
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
+ prevKey = computed(() => {
1823
+ if (this.inputs.accordionGroup().orientation() === 'vertical') {
1824
+ return 'ArrowUp';
1825
+ }
1826
+ return this.inputs.accordionGroup().textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
1827
+ });
1828
+ nextKey = computed(() => {
1829
+ if (this.inputs.accordionGroup().orientation() === 'vertical') {
1830
+ return 'ArrowDown';
1831
+ }
1832
+ return this.inputs.accordionGroup().textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
1833
+ });
1834
+ keydown = computed(() => {
1835
+ return new KeyboardEventManager().on(this.prevKey, () => this.inputs.accordionGroup().navigation.prev()).on(this.nextKey, () => this.inputs.accordionGroup().navigation.next()).on('Home', () => this.inputs.accordionGroup().navigation.first()).on('End', () => this.inputs.accordionGroup().navigation.last()).on(' ', () => this.expansionControl.toggle()).on('Enter', () => this.expansionControl.toggle());
1836
+ });
1837
+ pointerdown = computed(() => {
1838
+ return new PointerEventManager().on(e => {
1839
+ const item = this._getItem(e);
1840
+ if (item) {
1841
+ this.inputs.accordionGroup().navigation.goto(item);
1842
+ this.expansionControl.toggle();
1843
+ }
1844
+ });
1845
+ });
1846
+ onKeydown(event) {
1847
+ this.keydown().handle(event);
1848
+ }
1849
+ onPointerdown(event) {
1850
+ this.pointerdown().handle(event);
1851
+ }
1852
+ onFocus(event) {
1853
+ const item = this._getItem(event);
1854
+ if (item && this.inputs.accordionGroup().focusManager.isFocusable(item)) {
1855
+ this.inputs.accordionGroup().focusManager.focus(item);
1856
+ }
1857
+ }
1858
+ _getItem(e) {
1859
+ if (!(e.target instanceof HTMLElement)) {
1860
+ return;
1861
+ }
1862
+ const element = e.target.closest('[role="button"]');
1863
+ return this.inputs.accordionGroup().items().find(i => i.element() === element);
1864
+ }
1865
+ }
1866
+ class AccordionPanelPattern {
1867
+ inputs;
1868
+ hidden;
1869
+ constructor(inputs) {
1870
+ this.inputs = inputs;
1871
+ this.id = inputs.id;
1872
+ this.value = inputs.value;
1873
+ this.accordionTrigger = inputs.accordionTrigger;
1874
+ this.hidden = computed(() => inputs.accordionTrigger()?.expanded() === false);
1875
+ }
1876
+ }
1877
+
1878
+ class TreeItemPattern {
1879
+ inputs;
1880
+ id;
1881
+ value;
1882
+ element;
1883
+ disabled;
1884
+ searchTerm;
1885
+ tree;
1886
+ parent;
1887
+ children;
1888
+ index = computed(() => this.tree().visibleItems().indexOf(this));
1889
+ expansionId;
1890
+ expansionManager;
1891
+ expansion;
1892
+ expandable;
1893
+ selectable;
1894
+ level = computed(() => this.parent().level() + 1);
1895
+ expanded = computed(() => this.expansion.isExpanded());
1896
+ visible = computed(() => this.parent().expanded() && this.parent().visible());
1897
+ setsize = computed(() => this.parent().children().length);
1898
+ posinset = computed(() => this.parent().children().indexOf(this) + 1);
1899
+ active = computed(() => this.tree().activeItem() === this);
1900
+ tabIndex = computed(() => this.tree().listBehavior.getItemTabindex(this));
1901
+ selected = computed(() => {
1902
+ if (this.tree().nav()) {
1903
+ return undefined;
1904
+ }
1905
+ if (!this.selectable()) {
1906
+ return undefined;
1907
+ }
1908
+ return this.tree().value().includes(this.value());
1909
+ });
1910
+ current = computed(() => {
1911
+ if (!this.tree().nav()) {
1912
+ return undefined;
1913
+ }
1914
+ if (!this.selectable()) {
1915
+ return undefined;
1916
+ }
1917
+ return this.tree().value().includes(this.value()) ? this.tree().currentType() : undefined;
1918
+ });
1919
+ constructor(inputs) {
1920
+ this.inputs = inputs;
1921
+ this.id = inputs.id;
1922
+ this.value = inputs.value;
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({
1939
+ ...inputs,
1940
+ multiExpandable: () => true,
1941
+ expandedIds: signal([]),
1942
+ items: this.children,
1943
+ disabled: computed(() => this.tree()?.disabled() ?? false)
1944
+ });
1945
+ }
1946
+ }
1947
+ class TreePattern {
1948
+ inputs;
1949
+ listBehavior;
1950
+ expansionManager;
1951
+ level = () => 0;
1952
+ expanded = () => true;
1953
+ visible = () => true;
1954
+ tabIndex = computed(() => this.listBehavior.tabIndex());
1955
+ activeDescendant = computed(() => this.listBehavior.activeDescendant());
1956
+ children = computed(() => this.inputs.allItems().filter(item => item.level() === this.level() + 1));
1957
+ visibleItems = computed(() => this.inputs.allItems().filter(item => item.visible()));
1958
+ followFocus = computed(() => this.inputs.selectionMode() === 'follow');
1959
+ prevKey = computed(() => {
1960
+ if (this.inputs.orientation() === 'vertical') {
1961
+ return 'ArrowUp';
1962
+ }
1963
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
1964
+ });
1965
+ nextKey = computed(() => {
1966
+ if (this.inputs.orientation() === 'vertical') {
1967
+ return 'ArrowDown';
1968
+ }
1969
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
1970
+ });
1971
+ collapseKey = computed(() => {
1972
+ if (this.inputs.orientation() === 'horizontal') {
1973
+ return 'ArrowUp';
1974
+ }
1975
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft';
1976
+ });
1977
+ expandKey = computed(() => {
1978
+ if (this.inputs.orientation() === 'horizontal') {
1979
+ return 'ArrowDown';
1980
+ }
1981
+ return this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight';
1982
+ });
1983
+ dynamicSpaceKey = computed(() => this.listBehavior.isTyping() ? '' : ' ');
1984
+ typeaheadRegexp = /^.$/;
1985
+ keydown = computed(() => {
1986
+ const manager = new KeyboardEventManager();
1987
+ const list = this.listBehavior;
1988
+ manager.on(this.prevKey, () => list.prev({
1989
+ selectOne: this.followFocus()
1990
+ })).on(this.nextKey, () => list.next({
1991
+ selectOne: this.followFocus()
1992
+ })).on('Home', () => list.first({
1993
+ selectOne: this.followFocus()
1994
+ })).on('End', () => list.last({
1995
+ selectOne: this.followFocus()
1996
+ })).on(this.typeaheadRegexp, e => list.search(e.key, {
1997
+ selectOne: this.followFocus()
1998
+ })).on(this.expandKey, () => this.expand({
1999
+ selectOne: this.followFocus()
2000
+ })).on(this.collapseKey, () => this.collapse({
2001
+ selectOne: this.followFocus()
2002
+ })).on(Modifier.Shift, '*', () => this.expandSiblings());
2003
+ if (this.inputs.multi()) {
2004
+ manager.on(Modifier.Any, 'Shift', () => list.anchor(this.listBehavior.activeIndex())).on(Modifier.Shift, this.prevKey, () => list.prev({
2005
+ selectRange: true
2006
+ })).on(Modifier.Shift, this.nextKey, () => list.next({
2007
+ selectRange: true
2008
+ })).on([Modifier.Ctrl | Modifier.Shift, Modifier.Meta | Modifier.Shift], 'Home', () => list.first({
2009
+ selectRange: true,
2010
+ anchor: false
2011
+ })).on([Modifier.Ctrl | Modifier.Shift, Modifier.Meta | Modifier.Shift], 'End', () => list.last({
2012
+ selectRange: true,
2013
+ anchor: false
2014
+ })).on(Modifier.Shift, 'Enter', () => list.updateSelection({
2015
+ selectRange: true,
2016
+ anchor: false
2017
+ })).on(Modifier.Shift, this.dynamicSpaceKey, () => list.updateSelection({
2018
+ selectRange: true,
2019
+ anchor: false
2020
+ }));
2021
+ }
2022
+ if (!this.followFocus() && this.inputs.multi()) {
2023
+ manager.on(this.dynamicSpaceKey, () => list.toggle()).on('Enter', () => list.toggle(), {
2024
+ preventDefault: !this.nav()
2025
+ }).on([Modifier.Ctrl, Modifier.Meta], 'A', () => list.toggleAll());
2026
+ }
2027
+ if (!this.followFocus() && !this.inputs.multi()) {
2028
+ manager.on(this.dynamicSpaceKey, () => list.selectOne());
2029
+ manager.on('Enter', () => list.selectOne(), {
2030
+ preventDefault: !this.nav()
2031
+ });
2032
+ }
2033
+ if (this.inputs.multi() && this.followFocus()) {
2034
+ manager.on([Modifier.Ctrl, Modifier.Meta], this.prevKey, () => list.prev()).on([Modifier.Ctrl, Modifier.Meta], this.nextKey, () => list.next()).on([Modifier.Ctrl, Modifier.Meta], this.expandKey, () => this.expand()).on([Modifier.Ctrl, Modifier.Meta], this.collapseKey, () => this.collapse()).on([Modifier.Ctrl, Modifier.Meta], ' ', () => list.toggle()).on([Modifier.Ctrl, Modifier.Meta], 'Enter', () => list.toggle()).on([Modifier.Ctrl, Modifier.Meta], 'Home', () => list.first()).on([Modifier.Ctrl, Modifier.Meta], 'End', () => list.last()).on([Modifier.Ctrl, Modifier.Meta], 'A', () => {
2035
+ list.toggleAll();
2036
+ list.select();
2037
+ });
2038
+ }
2039
+ return manager;
2040
+ });
2041
+ pointerdown = computed(() => {
2042
+ const manager = new PointerEventManager();
2043
+ if (this.multi()) {
2044
+ manager.on(Modifier.Shift, e => this.goto(e, {
2045
+ selectRange: true
2046
+ }));
2047
+ }
2048
+ if (!this.multi()) {
2049
+ return manager.on(e => this.goto(e, {
2050
+ selectOne: true
2051
+ }));
2052
+ }
2053
+ if (this.multi() && this.followFocus()) {
2054
+ return manager.on(e => this.goto(e, {
2055
+ selectOne: true
2056
+ })).on(Modifier.Ctrl, e => this.goto(e, {
2057
+ toggle: true
2058
+ }));
2059
+ }
2060
+ if (this.multi() && !this.followFocus()) {
2061
+ return manager.on(e => this.goto(e, {
2062
+ toggle: true
2063
+ }));
2064
+ }
2065
+ return manager;
2066
+ });
2067
+ id;
2068
+ nav;
2069
+ currentType;
2070
+ allItems;
2071
+ disabled;
2072
+ activeItem = signal(undefined);
2073
+ softDisabled;
2074
+ wrap;
2075
+ orientation;
2076
+ textDirection;
2077
+ multi;
2078
+ selectionMode;
2079
+ typeaheadDelay;
2080
+ value;
2081
+ constructor(inputs) {
2082
+ 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
+ this.activeItem = inputs.activeItem;
2090
+ this.softDisabled = inputs.softDisabled;
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;
2098
+ this.listBehavior = new List({
2099
+ ...inputs,
2100
+ items: this.visibleItems,
2101
+ multi: this.multi
2102
+ });
2103
+ this.expansionManager = new ListExpansion({
2104
+ multiExpandable: () => true,
2105
+ expandedIds: signal([]),
2106
+ items: this.children,
2107
+ disabled: this.disabled
2108
+ });
2109
+ }
2110
+ setDefaultState() {
2111
+ let firstItem;
2112
+ for (const item of this.allItems()) {
2113
+ if (!item.visible()) continue;
2114
+ if (!this.listBehavior.isFocusable(item)) continue;
2115
+ if (firstItem === undefined) {
2116
+ firstItem = item;
2117
+ }
2118
+ if (item.selected()) {
2119
+ this.activeItem.set(item);
2120
+ return;
2121
+ }
2122
+ }
2123
+ if (firstItem !== undefined) {
2124
+ this.activeItem.set(firstItem);
2125
+ }
2126
+ }
2127
+ onKeydown(event) {
2128
+ if (!this.disabled()) {
2129
+ this.keydown().handle(event);
2130
+ }
2131
+ }
2132
+ onPointerdown(event) {
2133
+ if (!this.disabled()) {
2134
+ this.pointerdown().handle(event);
2135
+ }
2136
+ }
2137
+ goto(e, opts) {
2138
+ const item = this._getItem(e);
2139
+ if (!item) return;
2140
+ this.listBehavior.goto(item, opts);
2141
+ this.toggleExpansion(item);
2142
+ }
2143
+ toggleExpansion(item) {
2144
+ item ??= this.activeItem();
2145
+ if (!item || !this.listBehavior.isFocusable(item)) return;
2146
+ if (!item.expandable()) return;
2147
+ if (item.expanded()) {
2148
+ this.collapse();
2149
+ } else {
2150
+ item.expansion.open();
2151
+ }
2152
+ }
2153
+ expand(opts) {
2154
+ const item = this.activeItem();
2155
+ if (!item || !this.listBehavior.isFocusable(item)) return;
2156
+ if (item.expandable() && !item.expanded()) {
2157
+ item.expansion.open();
2158
+ } else if (item.expanded() && item.children().some(item => this.listBehavior.isFocusable(item))) {
2159
+ this.listBehavior.next(opts);
2160
+ }
2161
+ }
2162
+ expandSiblings(item) {
2163
+ item ??= this.activeItem();
2164
+ const siblings = item?.parent()?.children();
2165
+ siblings?.forEach(item => item.expansion.open());
2166
+ }
2167
+ collapse(opts) {
2168
+ const item = this.activeItem();
2169
+ if (!item || !this.listBehavior.isFocusable(item)) return;
2170
+ if (item.expandable() && item.expanded()) {
2171
+ item.expansion.close();
2172
+ } else if (item.parent() && item.parent() !== this) {
2173
+ const parentItem = item.parent();
2174
+ if (parentItem instanceof TreeItemPattern && this.listBehavior.isFocusable(parentItem)) {
2175
+ this.listBehavior.goto(parentItem, opts);
2176
+ }
2177
+ }
2178
+ }
2179
+ _getItem(event) {
2180
+ if (!(event.target instanceof HTMLElement)) {
2181
+ return;
2182
+ }
2183
+ const element = event.target.closest('[role="treeitem"]');
2184
+ return this.inputs.allItems().find(i => i.element() === element);
2185
+ }
2186
+ }
2187
+
2188
+ class ComboboxTreePattern extends TreePattern {
2189
+ inputs;
2190
+ isItemCollapsible = () => this.inputs.activeItem()?.parent() instanceof TreeItemPattern;
2191
+ role = () => 'tree';
2192
+ activeId = computed(() => this.listBehavior.activeDescendant());
2193
+ items = computed(() => this.inputs.allItems());
2194
+ tabIndex = () => -1;
2195
+ constructor(inputs) {
2196
+ if (inputs.combobox()) {
2197
+ inputs.multi = () => false;
2198
+ inputs.focusMode = () => 'activedescendant';
2199
+ inputs.element = inputs.combobox().inputs.inputEl;
2200
+ }
2201
+ super(inputs);
2202
+ this.inputs = inputs;
2203
+ }
2204
+ onKeydown(_) {}
2205
+ onPointerdown(_) {}
2206
+ setDefaultState() {}
2207
+ focus = item => this.listBehavior.goto(item);
2208
+ next = () => this.listBehavior.next();
2209
+ prev = () => this.listBehavior.prev();
2210
+ last = () => this.listBehavior.last();
2211
+ first = () => this.listBehavior.first();
2212
+ unfocus = () => this.listBehavior.unfocus();
2213
+ select = item => this.listBehavior.select(item);
2214
+ toggle = item => this.listBehavior.toggle(item);
2215
+ clearSelection = () => this.listBehavior.deselectAll();
2216
+ getItem = e => this._getItem(e);
2217
+ getSelectedItems = () => this.inputs.allItems().filter(item => item.selected());
2218
+ setValue = value => this.inputs.value.set(value ? [value] : []);
2219
+ expandItem = () => this.expand();
2220
+ collapseItem = () => this.collapse();
2221
+ isItemExpandable(item = this.inputs.activeItem()) {
2222
+ return item ? item.expandable() : false;
2223
+ }
2224
+ expandAll = () => this.items().forEach(item => item.expansion.open());
2225
+ collapseAll = () => this.items().forEach(item => item.expansion.close());
2226
+ isItemSelectable = (item = this.inputs.activeItem()) => {
2227
+ return item ? item.selectable() : false;
2228
+ };
2229
+ }
2230
+
2231
+ class DeferredContentAware {
2232
+ contentVisible = signal(false, ...(ngDevMode ? [{
2233
+ debugName: "contentVisible"
2234
+ }] : []));
2235
+ preserveContent = model(false, ...(ngDevMode ? [{
2236
+ debugName: "preserveContent"
2237
+ }] : []));
2238
+ static ɵfac = i0.ɵɵngDeclareFactory({
2239
+ minVersion: "12.0.0",
2240
+ version: "20.2.0-next.2",
2241
+ ngImport: i0,
2242
+ type: DeferredContentAware,
2243
+ deps: [],
2244
+ target: i0.ɵɵFactoryTarget.Directive
2245
+ });
2246
+ static ɵdir = i0.ɵɵngDeclareDirective({
2247
+ minVersion: "17.1.0",
2248
+ version: "20.2.0-next.2",
2249
+ type: DeferredContentAware,
2250
+ isStandalone: true,
2251
+ inputs: {
2252
+ preserveContent: {
2253
+ classPropertyName: "preserveContent",
2254
+ publicName: "preserveContent",
2255
+ isSignal: true,
2256
+ isRequired: false,
2257
+ transformFunction: null
2258
+ }
2259
+ },
2260
+ outputs: {
2261
+ preserveContent: "preserveContentChange"
2262
+ },
2263
+ ngImport: i0
2264
+ });
2265
+ }
2266
+ i0.ɵɵngDeclareClassMetadata({
2267
+ minVersion: "12.0.0",
2268
+ version: "20.2.0-next.2",
2269
+ ngImport: i0,
2270
+ type: DeferredContentAware,
2271
+ decorators: [{
2272
+ type: Directive
2273
+ }]
2274
+ });
2275
+ class DeferredContent {
2276
+ _deferredContentAware = inject(DeferredContentAware, {
2277
+ optional: true
2278
+ });
2279
+ _templateRef = inject(TemplateRef);
2280
+ _viewContainerRef = inject(ViewContainerRef);
2281
+ _currentViewRef = null;
2282
+ _isRendered = false;
2283
+ deferredContentAware = signal(this._deferredContentAware, ...(ngDevMode ? [{
2284
+ debugName: "deferredContentAware"
2285
+ }] : []));
2286
+ constructor() {
2287
+ afterRenderEffect(() => {
2288
+ if (this.deferredContentAware()?.contentVisible()) {
2289
+ if (!this._isRendered) {
2290
+ this._destroyContent();
2291
+ this._currentViewRef = this._viewContainerRef.createEmbeddedView(this._templateRef);
2292
+ this._isRendered = true;
2293
+ }
2294
+ } else if (!this.deferredContentAware()?.preserveContent()) {
2295
+ this._destroyContent();
2296
+ this._isRendered = false;
2297
+ }
2298
+ });
2299
+ }
2300
+ ngOnDestroy() {
2301
+ this._destroyContent();
2302
+ }
2303
+ _destroyContent() {
2304
+ const ref = this._currentViewRef;
2305
+ if (ref && !ref.destroyed) {
2306
+ ref.destroy();
2307
+ this._currentViewRef = null;
2308
+ }
2309
+ }
2310
+ static ɵfac = i0.ɵɵngDeclareFactory({
2311
+ minVersion: "12.0.0",
2312
+ version: "20.2.0-next.2",
2313
+ ngImport: i0,
2314
+ type: DeferredContent,
2315
+ deps: [],
2316
+ target: i0.ɵɵFactoryTarget.Directive
2317
+ });
2318
+ static ɵdir = i0.ɵɵngDeclareDirective({
2319
+ minVersion: "14.0.0",
2320
+ version: "20.2.0-next.2",
2321
+ type: DeferredContent,
2322
+ isStandalone: true,
2323
+ ngImport: i0
2324
+ });
2325
+ }
2326
+ i0.ɵɵngDeclareClassMetadata({
2327
+ minVersion: "12.0.0",
2328
+ version: "20.2.0-next.2",
2329
+ ngImport: i0,
2330
+ type: DeferredContent,
2331
+ decorators: [{
2332
+ type: Directive
2333
+ }],
2334
+ ctorParameters: () => []
2335
+ });
2336
+
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 };
2338
+ //# sourceMappingURL=private.mjs.map