@angular/aria 22.0.0-next.6 → 22.0.0-next.8

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 (105) hide show
  1. package/fesm2022/_accordion-chunk.mjs +1 -1
  2. package/fesm2022/_accordion-chunk.mjs.map +1 -1
  3. package/fesm2022/_click-event-manager-chunk.mjs +1 -1
  4. package/fesm2022/_click-event-manager-chunk.mjs.map +1 -1
  5. package/fesm2022/{_signal-like-chunk.mjs → _collection-chunk.mjs} +51 -3
  6. package/fesm2022/_collection-chunk.mjs.map +1 -0
  7. package/fesm2022/_deferred-content-chunk.mjs +16 -14
  8. package/fesm2022/_deferred-content-chunk.mjs.map +1 -1
  9. package/fesm2022/_expansion-chunk.mjs.map +1 -1
  10. package/fesm2022/_list-chunk.mjs +4 -1
  11. package/fesm2022/_list-chunk.mjs.map +1 -1
  12. package/fesm2022/_list-navigation-chunk.mjs +4 -2
  13. package/fesm2022/_list-navigation-chunk.mjs.map +1 -1
  14. package/fesm2022/_list-typeahead-chunk.mjs +1 -1
  15. package/fesm2022/_list-typeahead-chunk.mjs.map +1 -1
  16. package/fesm2022/_menu-chunk.mjs +1 -1
  17. package/fesm2022/_menu-chunk.mjs.map +1 -1
  18. package/fesm2022/{_combobox-listbox-chunk.mjs → _option-chunk.mjs} +6 -50
  19. package/fesm2022/_option-chunk.mjs.map +1 -0
  20. package/fesm2022/_tabs-chunk.mjs +22 -47
  21. package/fesm2022/_tabs-chunk.mjs.map +1 -1
  22. package/fesm2022/_toolbar-widget-group-chunk.mjs +1 -1
  23. package/fesm2022/_toolbar-widget-group-chunk.mjs.map +1 -1
  24. package/fesm2022/_transforms-chunk.mjs +8 -0
  25. package/fesm2022/_transforms-chunk.mjs.map +1 -0
  26. package/fesm2022/{_combobox-tree-chunk.mjs → _tree-chunk.mjs} +3 -48
  27. package/fesm2022/_tree-chunk.mjs.map +1 -0
  28. package/fesm2022/_widget-chunk.mjs +84 -21
  29. package/fesm2022/_widget-chunk.mjs.map +1 -1
  30. package/fesm2022/accordion-testing.mjs.map +1 -1
  31. package/fesm2022/accordion.mjs +32 -57
  32. package/fesm2022/accordion.mjs.map +1 -1
  33. package/fesm2022/aria.mjs +1 -1
  34. package/fesm2022/aria.mjs.map +1 -1
  35. package/fesm2022/combobox-testing.mjs +79 -0
  36. package/fesm2022/combobox-testing.mjs.map +1 -0
  37. package/fesm2022/combobox.mjs +287 -296
  38. package/fesm2022/combobox.mjs.map +1 -1
  39. package/fesm2022/grid-testing.mjs +80 -0
  40. package/fesm2022/grid-testing.mjs.map +1 -0
  41. package/fesm2022/grid.mjs +113 -86
  42. package/fesm2022/grid.mjs.map +1 -1
  43. package/fesm2022/listbox-testing.mjs +4 -0
  44. package/fesm2022/listbox-testing.mjs.map +1 -1
  45. package/fesm2022/listbox.mjs +231 -225
  46. package/fesm2022/listbox.mjs.map +1 -1
  47. package/fesm2022/menu-testing.mjs +11 -0
  48. package/fesm2022/menu-testing.mjs.map +1 -1
  49. package/fesm2022/menu.mjs +66 -84
  50. package/fesm2022/menu.mjs.map +1 -1
  51. package/fesm2022/private.mjs +166 -9
  52. package/fesm2022/private.mjs.map +1 -1
  53. package/fesm2022/tabs-testing.mjs.map +1 -1
  54. package/fesm2022/tabs.mjs +241 -222
  55. package/fesm2022/tabs.mjs.map +1 -1
  56. package/fesm2022/toolbar-testing.mjs +5 -1
  57. package/fesm2022/toolbar-testing.mjs.map +1 -1
  58. package/fesm2022/toolbar.mjs +23 -33
  59. package/fesm2022/toolbar.mjs.map +1 -1
  60. package/fesm2022/tree-testing.mjs +12 -0
  61. package/fesm2022/tree-testing.mjs.map +1 -1
  62. package/fesm2022/tree.mjs +160 -156
  63. package/fesm2022/tree.mjs.map +1 -1
  64. package/package.json +10 -2
  65. package/types/_accordion-chunk.d.ts +2 -2
  66. package/types/_collection-chunk.d.ts +42 -0
  67. package/types/_expansion-chunk.d.ts +1 -1
  68. package/types/_grid-chunk.d.ts +23 -9
  69. package/types/_keyboard-event-manager-chunk.d.ts +1 -1
  70. package/types/_list-chunk.d.ts +1 -1
  71. package/types/_list-navigation-chunk.d.ts +1 -1
  72. package/types/_listbox-chunk.d.ts +1 -1
  73. package/types/_menu-chunk.d.ts +1 -1
  74. package/types/_tabs-chunk.d.ts +8 -43
  75. package/types/_toolbar-chunk.d.ts +1 -1
  76. package/types/_tree-chunk.d.ts +1 -1
  77. package/types/accordion.d.ts +7 -13
  78. package/types/combobox-testing.d.ts +63 -0
  79. package/types/combobox.d.ts +96 -192
  80. package/types/grid-testing.d.ts +83 -0
  81. package/types/grid.d.ts +102 -90
  82. package/types/listbox-testing.d.ts +25 -0
  83. package/types/listbox.d.ts +60 -63
  84. package/types/menu-testing.d.ts +6 -0
  85. package/types/menu.d.ts +24 -17
  86. package/types/private.d.ts +115 -133
  87. package/types/tabs.d.ts +26 -24
  88. package/types/toolbar-testing.d.ts +4 -0
  89. package/types/toolbar.d.ts +5 -6
  90. package/types/tree-testing.d.ts +8 -0
  91. package/types/tree.d.ts +11 -15
  92. package/fesm2022/_combobox-chunk.mjs +0 -429
  93. package/fesm2022/_combobox-chunk.mjs.map +0 -1
  94. package/fesm2022/_combobox-listbox-chunk.mjs.map +0 -1
  95. package/fesm2022/_combobox-tree-chunk.mjs.map +0 -1
  96. package/fesm2022/_element-chunk.mjs +0 -6
  97. package/fesm2022/_element-chunk.mjs.map +0 -1
  98. package/fesm2022/_pointer-event-manager-chunk.mjs +0 -54
  99. package/fesm2022/_pointer-event-manager-chunk.mjs.map +0 -1
  100. package/fesm2022/_signal-like-chunk.mjs.map +0 -1
  101. package/resources/code-examples.db +0 -0
  102. package/types/_combobox-chunk.d.ts +0 -194
  103. package/types/_element-chunk.d.ts +0 -10
  104. package/types/_pointer-event-manager-chunk.d.ts +0 -34
  105. package/types/_signal-like-chunk.d.ts +0 -14
package/types/tabs.d.ts CHANGED
@@ -1,11 +1,10 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { OnInit, OnDestroy } from '@angular/core';
2
+ import { OnInit, OnDestroy, WritableSignal } from '@angular/core';
3
3
  import * as _angular_cdk_bidi from '@angular/cdk/bidi';
4
4
  import { TabPattern, TabListPattern, TabPanelPattern } from './_tabs-chunk.js';
5
- import { HasElement } from './_element-chunk.js';
5
+ import { HasElement, SortedCollection } from './_collection-chunk.js';
6
6
  import { DeferredContentAware, DeferredContent } from './_deferred-content-chunk.js';
7
7
  import './_keyboard-event-manager-chunk.js';
8
- import './_signal-like-chunk.js';
9
8
  import './_click-event-manager-chunk.js';
10
9
  import './_expansion-chunk.js';
11
10
  import './_list-navigation-chunk.js';
@@ -31,14 +30,10 @@ declare class Tab implements HasElement, OnInit, OnDestroy {
31
30
  private readonly _elementRef;
32
31
  /** A reference to the host element. */
33
32
  readonly element: HTMLElement;
34
- /** The parent Tabs. */
35
- private readonly _tabs;
36
33
  /** The parent TabList. */
37
34
  private readonly _tabList;
38
35
  /** A unique identifier for the widget. */
39
36
  readonly id: _angular_core.InputSignal<string>;
40
- /** The parent TabList UIPattern. */
41
- private readonly _tablistPattern;
42
37
  /** The TabPanel UIPattern associated with the tab */
43
38
  private readonly _tabpanelPattern;
44
39
  /** Whether a tab is disabled. */
@@ -82,16 +77,16 @@ declare class TabList implements OnInit, OnDestroy {
82
77
  private readonly _elementRef;
83
78
  /** A reference to the host element. */
84
79
  readonly element: HTMLElement;
85
- /** The parent Tabs. */
86
- private readonly _tabs;
87
- /** The Tabs nested inside of the TabList. */
88
- private readonly _unorderedTabs;
89
- /** Text direction. */
90
- readonly textDirection: _angular_core.WritableSignal<_angular_cdk_bidi.Direction>;
80
+ /** The parent Tabs container. */
81
+ readonly _tabsParent: Tabs;
82
+ /** The collection of Tabs. */
83
+ readonly _collection: SortedCollection<Tab>;
91
84
  /** The Tab UIPatterns of the child Tabs. */
92
85
  readonly _tabPatterns: _angular_core.Signal<TabPattern[]>;
93
86
  /** Whether the tablist is vertically or horizontally oriented. */
94
87
  readonly orientation: _angular_core.InputSignal<"vertical" | "horizontal">;
88
+ /** Text direction. */
89
+ readonly textDirection: WritableSignal<_angular_cdk_bidi.Direction>;
95
90
  /** Whether focus should wrap when navigating. */
96
91
  readonly wrap: _angular_core.InputSignalWithTransform<boolean, unknown>;
97
92
  /**
@@ -111,8 +106,10 @@ declare class TabList implements OnInit, OnDestroy {
111
106
  * - `explicit`: Tabs are selected explicitly by the user (e.g., via click or spacebar).
112
107
  */
113
108
  readonly selectionMode: _angular_core.InputSignal<"follow" | "explicit">;
114
- /** The current selected tab. */
109
+ /** The current selected tab as a model input. */
115
110
  readonly selectedTab: _angular_core.ModelSignal<string | undefined>;
111
+ /** The current selected Tab pattern, passed to the List pattern. */
112
+ private readonly _selectedTabPattern;
116
113
  /** Whether the tablist is disabled. */
117
114
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
118
115
  /** The TabList UIPattern. */
@@ -120,10 +117,9 @@ declare class TabList implements OnInit, OnDestroy {
120
117
  constructor();
121
118
  ngOnInit(): void;
122
119
  ngOnDestroy(): void;
123
- _register(child: Tab): void;
124
- _unregister(child: Tab): void;
125
120
  /** Opens the tab panel with the specified value. */
126
121
  open(value: string): boolean;
122
+ findTab(value?: string): Tab | undefined;
127
123
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TabList, never>;
128
124
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<TabList, "[ngTabList]", ["ngTabList"], { "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "wrap": { "alias": "wrap"; "required": false; "isSignal": true; }; "softDisabled": { "alias": "softDisabled"; "required": false; "isSignal": true; }; "focusMode": { "alias": "focusMode"; "required": false; "isSignal": true; }; "selectionMode": { "alias": "selectionMode"; "required": false; "isSignal": true; }; "selectedTab": { "alias": "selectedTab"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "selectedTab": "selectedTabChange"; }, never, never, true, never>;
129
125
  }
@@ -204,21 +200,27 @@ declare class TabPanel implements OnInit, OnDestroy {
204
200
  *
205
201
  * @see [Tabs](guide/aria/tabs)
206
202
  */
207
- declare class Tabs {
203
+ declare class Tabs implements OnDestroy {
208
204
  /** A reference to the host element. */
209
205
  private readonly _elementRef;
210
206
  /** A reference to the host element. */
211
207
  readonly element: HTMLElement;
212
- /** The TabList nested inside of the container. */
213
- private readonly _tablist;
214
- /** The TabPanels nested inside of the container. */
215
- private readonly _unorderedPanels;
208
+ /** The TabList registered for this container. */
209
+ readonly _tabList: _angular_core.WritableSignal<TabList | undefined>;
210
+ /** The collection of TabPanels. */
211
+ readonly _collection: SortedCollection<TabPanel>;
216
212
  /** The Tab UIPattern of the child Tabs. */
217
213
  readonly _tabPatterns: _angular_core.Signal<TabPattern[] | undefined>;
218
214
  /** The TabPanel UIPattern of the child TabPanels. */
219
- readonly _unorderedTabpanelPatterns: _angular_core.Signal<TabPanelPattern[]>;
220
- _register(child: TabList | TabPanel): void;
221
- _unregister(child: TabList | TabPanel): void;
215
+ readonly _tabPanelPatterns: _angular_core.Signal<TabPanelPattern[]>;
216
+ /** A reactive map of tab values to their TabPanelPattern. */
217
+ readonly _panelMap: _angular_core.Signal<Map<string, TabPanelPattern>>;
218
+ /** A reactive map of tab values to their TabPattern. */
219
+ readonly _tabMap: _angular_core.Signal<Map<string, TabPattern>>;
220
+ constructor();
221
+ ngOnDestroy(): void;
222
+ _register(child: TabList): void;
223
+ _unregister(): void;
222
224
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Tabs, never>;
223
225
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<Tabs, "[ngTabs]", ["ngTabs"], {}, {}, never, never, true, never>;
224
226
  }
@@ -12,6 +12,8 @@ interface ToolbarWidgetHarnessFilters extends BaseHarnessFilters {
12
12
  text?: string | RegExp;
13
13
  /** Active state that the widget should match. */
14
14
  active?: boolean;
15
+ /** Selected state that the widget should match. */
16
+ selected?: boolean;
15
17
  }
16
18
 
17
19
  /** Harness for interacting with an Aria toolbar widget in tests. */
@@ -32,6 +34,8 @@ declare class ToolbarWidgetHarness extends ContentContainerComponentHarness<stri
32
34
  isActive(): Promise<boolean>;
33
35
  /** Gets whether the widget is disabled. */
34
36
  isDisabled(): Promise<boolean>;
37
+ /** Gets whether the widget is selected. */
38
+ isSelected(): Promise<boolean>;
35
39
  }
36
40
 
37
41
  /** Harness for interacting with an Aria toolbar widget group in tests. */
@@ -2,7 +2,7 @@ import * as _angular_core from '@angular/core';
2
2
  import { OnInit, OnDestroy } from '@angular/core';
3
3
  import * as _angular_cdk_bidi from '@angular/cdk/bidi';
4
4
  import { ToolbarWidgetGroupPattern, ToolbarWidgetPattern, ToolbarPattern } from './_toolbar-chunk.js';
5
- import './_signal-like-chunk.js';
5
+ import { SortedCollection } from './_collection-chunk.js';
6
6
  import './_list-chunk.js';
7
7
  import './_list-navigation-chunk.js';
8
8
 
@@ -108,13 +108,13 @@ declare class ToolbarWidget<V> implements OnInit, OnDestroy {
108
108
  *
109
109
  * @see [Toolbar](guide/aria/toolbar)
110
110
  */
111
- declare class Toolbar<V> {
111
+ declare class Toolbar<V> implements OnDestroy {
112
112
  /** A reference to the host element. */
113
113
  private readonly _elementRef;
114
114
  /** A reference to the host element. */
115
115
  readonly element: HTMLElement;
116
- /** The TabList nested inside of the container. */
117
- private readonly _widgets;
116
+ /** The collection of widgets in the toolbar. */
117
+ readonly _collection: SortedCollection<ToolbarWidget<V>>;
118
118
  /** Text direction. */
119
119
  readonly textDirection: _angular_core.WritableSignal<_angular_cdk_bidi.Direction>;
120
120
  /** Sorted UIPatterns of the child widgets */
@@ -135,8 +135,7 @@ declare class Toolbar<V> {
135
135
  /** The toolbar UIPattern. */
136
136
  readonly _pattern: ToolbarPattern<V>;
137
137
  constructor();
138
- _register(widget: ToolbarWidget<V>): void;
139
- _unregister(widget: ToolbarWidget<V>): void;
138
+ ngOnDestroy(): void;
140
139
  /** Finds the toolbar item associated with a given element. */
141
140
  private _getItem;
142
141
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Toolbar<any>, never>;
@@ -38,6 +38,14 @@ declare class TreeItemHarness extends ContentContainerComponentHarness<string> {
38
38
  getText(): Promise<string>;
39
39
  /** Clicks the tree item. */
40
40
  click(): Promise<void>;
41
+ /** Focuses the tree item. */
42
+ focus(): Promise<void>;
43
+ /** Blurs the tree item. */
44
+ blur(): Promise<void>;
45
+ /** Whether the tree item is active. */
46
+ isActive(): Promise<boolean>;
47
+ /** Whether the tree item has focus. */
48
+ isFocused(): Promise<boolean>;
41
49
  private _getHostAttribute;
42
50
  }
43
51
 
package/types/tree.d.ts CHANGED
@@ -2,18 +2,13 @@ import * as _angular_cdk_bidi from '@angular/cdk/bidi';
2
2
  import * as _angular_core from '@angular/core';
3
3
  import { OnInit, OnDestroy, Signal } from '@angular/core';
4
4
  import { TreeItemPattern, TreePattern } from './_tree-chunk.js';
5
+ import { HasElement, SortedCollection } from './_collection-chunk.js';
5
6
  import { DeferredContent, DeferredContentAware } from './_deferred-content-chunk.js';
6
- import { HasElement } from './_element-chunk.js';
7
- import { ComboboxPopup } from './combobox.js';
8
- export { Combobox as ɵɵCombobox, ComboboxDialog as ɵɵComboboxDialog, ComboboxInput as ɵɵComboboxInput, ComboboxPopupContainer as ɵɵComboboxPopupContainer } from './combobox.js';
9
- import './_signal-like-chunk.js';
10
7
  import './_expansion-chunk.js';
11
8
  import './_list-navigation-chunk.js';
12
9
  import './_list-chunk.js';
13
10
  import './_keyboard-event-manager-chunk.js';
14
11
  import './_click-event-manager-chunk.js';
15
- import './_combobox-chunk.js';
16
- import './_pointer-event-manager-chunk.js';
17
12
 
18
13
  /**
19
14
  * Group that contains children tree items.
@@ -155,15 +150,13 @@ declare class TreeItem<V> extends DeferredContentAware implements OnInit, OnDest
155
150
  *
156
151
  * @see [Tree](guide/aria/tree)
157
152
  */
158
- declare class Tree<V> {
153
+ declare class Tree<V> implements OnDestroy {
159
154
  /** A reference to the host element. */
160
155
  private readonly _elementRef;
161
156
  /** A reference to the host element. */
162
157
  readonly element: HTMLElement;
163
- /** A reference to the parent combobox popup, if one exists. */
164
- private readonly _popup;
165
- /** All TreeItem instances within this tree. */
166
- private readonly _unorderedItems;
158
+ /** The collection of tree items. */
159
+ readonly _collection: SortedCollection<TreeItem<V>>;
167
160
  /** A unique identifier for the tree. */
168
161
  readonly id: _angular_core.InputSignal<string>;
169
162
  /** Orientation of the tree. */
@@ -193,6 +186,8 @@ declare class Tree<V> {
193
186
  readonly softDisabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
194
187
  /** The delay in seconds before the typeahead search is reset. */
195
188
  readonly typeaheadDelay: _angular_core.InputSignal<number>;
189
+ /** The tabindex of the tree. */
190
+ readonly tabIndex: _angular_core.InputSignalWithTransform<number | undefined, string | number | undefined>;
196
191
  /** The values of the currently selected items. */
197
192
  readonly value: _angular_core.ModelSignal<V[]>;
198
193
  /** Text direction. */
@@ -206,12 +201,13 @@ declare class Tree<V> {
206
201
  readonly currentType: _angular_core.InputSignal<"page" | "step" | "location" | "date" | "time" | "true" | "false">;
207
202
  /** The UI pattern for the tree. */
208
203
  readonly _pattern: TreePattern<V>;
204
+ /** The ID of the active descendant in the tree. */
205
+ readonly activeDescendant: Signal<string | undefined>;
209
206
  constructor();
210
- _register(child: TreeItem<V>): void;
211
- _unregister(child: TreeItem<V>): void;
207
+ ngOnDestroy(): void;
212
208
  scrollActiveItemIntoView(options?: ScrollIntoViewOptions): void;
213
209
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<Tree<any>, never>;
214
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<Tree<any>, "[ngTree]", ["ngTree"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "multi": { "alias": "multi"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "selectionMode": { "alias": "selectionMode"; "required": false; "isSignal": true; }; "focusMode": { "alias": "focusMode"; "required": false; "isSignal": true; }; "wrap": { "alias": "wrap"; "required": false; "isSignal": true; }; "softDisabled": { "alias": "softDisabled"; "required": false; "isSignal": true; }; "typeaheadDelay": { "alias": "typeaheadDelay"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "nav": { "alias": "nav"; "required": false; "isSignal": true; }; "currentType": { "alias": "currentType"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, [{ directive: typeof ComboboxPopup; inputs: {}; outputs: {}; }]>;
210
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<Tree<any>, "[ngTree]", ["ngTree"], { "id": { "alias": "id"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "multi": { "alias": "multi"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "selectionMode": { "alias": "selectionMode"; "required": false; "isSignal": true; }; "focusMode": { "alias": "focusMode"; "required": false; "isSignal": true; }; "wrap": { "alias": "wrap"; "required": false; "isSignal": true; }; "softDisabled": { "alias": "softDisabled"; "required": false; "isSignal": true; }; "typeaheadDelay": { "alias": "typeaheadDelay"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabindex"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; "isSignal": true; }; "nav": { "alias": "nav"; "required": false; "isSignal": true; }; "currentType": { "alias": "currentType"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; }, never, never, true, never>;
215
211
  }
216
212
 
217
- export { Tree, TreeItem, TreeItemGroup, ComboboxPopup as ɵɵComboboxPopup, DeferredContent as ɵɵDeferredContent };
213
+ export { Tree, TreeItem, TreeItemGroup, DeferredContent as ɵɵDeferredContent };
@@ -1,429 +0,0 @@
1
- import { computed, signal, KeyboardEventManager } from './_signal-like-chunk.mjs';
2
- import { PointerEventManager } from './_pointer-event-manager-chunk.mjs';
3
-
4
- class ComboboxPattern {
5
- inputs;
6
- expanded = signal(false);
7
- disabled = () => this.inputs.disabled();
8
- activeDescendant = computed(() => {
9
- const popupControls = this.inputs.popupControls();
10
- if (popupControls instanceof ComboboxDialogPattern) {
11
- return null;
12
- }
13
- return popupControls?.activeId() ?? null;
14
- });
15
- highlightedItem = signal(undefined);
16
- _isDeleting = false;
17
- isFocused = signal(false);
18
- hasBeenInteracted = signal(false);
19
- expandKey = computed(() => this.inputs.textDirection() === 'rtl' ? 'ArrowLeft' : 'ArrowRight');
20
- collapseKey = computed(() => this.inputs.textDirection() === 'rtl' ? 'ArrowRight' : 'ArrowLeft');
21
- popupId = computed(() => this.inputs.popupControls()?.id() || null);
22
- autocomplete = computed(() => this.inputs.filterMode() === 'highlight' ? 'both' : 'list');
23
- hasPopup = computed(() => this.inputs.popupControls()?.role() || null);
24
- readonly = computed(() => this.inputs.readonly() || this.inputs.disabled() || null);
25
- listControls = () => {
26
- const popupControls = this.inputs.popupControls();
27
- if (popupControls instanceof ComboboxDialogPattern) {
28
- return null;
29
- }
30
- return popupControls;
31
- };
32
- treeControls = () => {
33
- const popupControls = this.inputs.popupControls();
34
- if (popupControls?.role() === 'tree') {
35
- return popupControls;
36
- }
37
- return null;
38
- };
39
- keydown = computed(() => {
40
- const manager = new KeyboardEventManager();
41
- const popupControls = this.inputs.popupControls();
42
- if (!popupControls) {
43
- return manager;
44
- }
45
- if (popupControls instanceof ComboboxDialogPattern) {
46
- if (!this.expanded()) {
47
- manager.on('ArrowUp', () => this.open()).on('ArrowDown', () => this.open());
48
- if (this.readonly()) {
49
- manager.on('Enter', () => this.open()).on(' ', () => this.open());
50
- }
51
- }
52
- return manager;
53
- }
54
- if (!this.inputs.alwaysExpanded()) {
55
- manager.on('Escape', () => this.close({
56
- reset: !this.readonly()
57
- }));
58
- }
59
- if (!this.expanded()) {
60
- manager.on('ArrowDown', () => this.open({
61
- first: true
62
- })).on('ArrowUp', () => this.open({
63
- last: true
64
- }));
65
- if (this.readonly()) {
66
- manager.on('Enter', () => this.open({
67
- selected: true
68
- })).on(' ', () => this.open({
69
- selected: true
70
- }));
71
- }
72
- return manager;
73
- }
74
- manager.on('ArrowDown', () => this.next(), {
75
- ignoreRepeat: false
76
- }).on('ArrowUp', () => this.prev(), {
77
- ignoreRepeat: false
78
- }).on('Home', () => this.first()).on('End', () => this.last());
79
- if (this.readonly()) {
80
- manager.on(' ', () => this.select({
81
- commit: true,
82
- close: !popupControls.multi()
83
- }));
84
- }
85
- if (popupControls.role() === 'listbox') {
86
- manager.on('Enter', () => {
87
- this.select({
88
- commit: true,
89
- close: !popupControls.multi()
90
- });
91
- });
92
- }
93
- const treeControls = this.treeControls();
94
- if (treeControls?.isItemSelectable()) {
95
- manager.on('Enter', () => this.select({
96
- commit: true,
97
- close: true
98
- }));
99
- }
100
- if (treeControls?.isItemExpandable()) {
101
- manager.on(this.expandKey(), () => this.expandItem()).on(this.collapseKey(), () => this.collapseItem());
102
- if (!treeControls.isItemSelectable()) {
103
- manager.on('Enter', () => this.expandItem());
104
- }
105
- }
106
- if (treeControls?.isItemCollapsible()) {
107
- manager.on(this.collapseKey(), () => this.collapseItem());
108
- }
109
- return manager;
110
- });
111
- click = computed(() => new PointerEventManager().on(e => {
112
- if (e.target === this.inputs.inputEl()) {
113
- if (this.readonly()) {
114
- this.expanded() ? this.close() : this.open({
115
- selected: true
116
- });
117
- }
118
- }
119
- const controls = this.inputs.popupControls();
120
- if (controls instanceof ComboboxDialogPattern) {
121
- return;
122
- }
123
- const item = controls?.getItem(e);
124
- if (item) {
125
- if (controls?.role() === 'tree') {
126
- const treeControls = controls;
127
- if (treeControls.isItemExpandable(item) && !treeControls.isItemSelectable(item)) {
128
- treeControls.toggleExpansion(item);
129
- this.inputs.inputEl()?.focus();
130
- return;
131
- }
132
- }
133
- this.select({
134
- item,
135
- commit: true,
136
- close: !controls?.multi()
137
- });
138
- this.inputs.inputEl()?.focus();
139
- }
140
- }));
141
- constructor(inputs) {
142
- this.inputs = inputs;
143
- }
144
- onKeydown(event) {
145
- if (!this.inputs.disabled()) {
146
- this.keydown().handle(event);
147
- }
148
- }
149
- onClick(event) {
150
- if (!this.inputs.disabled()) {
151
- this.click().handle(event);
152
- }
153
- }
154
- onInput(event) {
155
- if (this.inputs.disabled() || this.inputs.readonly()) {
156
- return;
157
- }
158
- const inputEl = this.inputs.inputEl();
159
- if (!inputEl) {
160
- return;
161
- }
162
- const popupControls = this.inputs.popupControls();
163
- if (popupControls instanceof ComboboxDialogPattern) {
164
- return;
165
- }
166
- this.open();
167
- this.inputs.inputValue?.set(inputEl.value);
168
- this._isDeleting = event instanceof InputEvent && !!event.inputType.match(/^delete/);
169
- if (this.inputs.filterMode() === 'highlight' && !this._isDeleting) {
170
- this.highlight();
171
- }
172
- }
173
- onFocusIn() {
174
- if (this.inputs.alwaysExpanded() && !this.hasBeenInteracted()) {
175
- const firstSelectedItem = this.listControls()?.getSelectedItems()[0];
176
- firstSelectedItem ? this.listControls()?.focus(firstSelectedItem) : this.first();
177
- }
178
- this.isFocused.set(true);
179
- this.hasBeenInteracted.set(true);
180
- }
181
- onFocusOut(event) {
182
- if (this.inputs.disabled()) {
183
- return;
184
- }
185
- const popupControls = this.inputs.popupControls();
186
- if (popupControls instanceof ComboboxDialogPattern) {
187
- return;
188
- }
189
- if (!(event.relatedTarget instanceof HTMLElement) || !this.inputs.containerEl()?.contains(event.relatedTarget)) {
190
- this.isFocused.set(false);
191
- if (!this.expanded()) {
192
- return;
193
- }
194
- if (this.readonly()) {
195
- this.close();
196
- return;
197
- }
198
- if (this.inputs.filterMode() !== 'manual') {
199
- this.commit();
200
- } else {
201
- const item = popupControls?.items().find(i => i.searchTerm() === this.inputs.inputEl()?.value);
202
- if (item) {
203
- this.select({
204
- item
205
- });
206
- }
207
- }
208
- this.close();
209
- }
210
- }
211
- firstMatch = computed(() => {
212
- if (this.listControls()?.role() === 'listbox') {
213
- return this.listControls()?.items()[0];
214
- }
215
- return this.listControls()?.items().find(i => i.value() === this.inputs.firstMatch());
216
- });
217
- onFilter() {
218
- if (this.readonly()) {
219
- return;
220
- }
221
- const popupControls = this.inputs.popupControls();
222
- if (popupControls instanceof ComboboxDialogPattern) {
223
- return;
224
- }
225
- const isInitialRender = !this.inputs.inputValue?.().length && !this._isDeleting;
226
- if (isInitialRender) {
227
- return;
228
- }
229
- if (!this.isFocused()) {
230
- return;
231
- }
232
- if (this.inputs.popupControls()?.role() === 'tree') {
233
- const treeControls = this.inputs.popupControls();
234
- this.inputs.inputValue?.().length ? treeControls.expandAll() : treeControls.collapseAll();
235
- }
236
- const item = this.firstMatch();
237
- if (!item) {
238
- popupControls?.clearSelection();
239
- popupControls?.unfocus();
240
- return;
241
- }
242
- popupControls?.focus(item);
243
- if (this.inputs.filterMode() !== 'manual') {
244
- this.select({
245
- item
246
- });
247
- }
248
- if (this.inputs.filterMode() === 'highlight' && !this._isDeleting) {
249
- this.highlight();
250
- }
251
- }
252
- highlight() {
253
- const inputEl = this.inputs.inputEl();
254
- const selectedItems = this.listControls()?.getSelectedItems();
255
- const item = selectedItems?.[0];
256
- if (!inputEl || !item) {
257
- return;
258
- }
259
- const isHighlightable = item.searchTerm().toLowerCase().startsWith(this.inputs.inputValue().toLowerCase());
260
- if (isHighlightable) {
261
- inputEl.value = this.inputs.inputValue() + item.searchTerm().slice(this.inputs.inputValue().length);
262
- inputEl.setSelectionRange(this.inputs.inputValue().length, item.searchTerm().length);
263
- this.highlightedItem.set(item);
264
- }
265
- }
266
- close(opts) {
267
- const popupControls = this.inputs.popupControls();
268
- if (this.inputs.alwaysExpanded()) {
269
- return;
270
- }
271
- if (popupControls instanceof ComboboxDialogPattern) {
272
- this.expanded.set(false);
273
- return;
274
- }
275
- if (this.readonly()) {
276
- this.expanded.set(false);
277
- popupControls?.unfocus();
278
- return;
279
- }
280
- if (!opts?.reset) {
281
- if (this.inputs.filterMode() === 'manual') {
282
- if (!this.listControls()?.items().some(i => i.searchTerm() === this.inputs.inputEl()?.value)) {
283
- this.listControls()?.clearSelection();
284
- }
285
- }
286
- this.expanded.set(false);
287
- popupControls?.unfocus();
288
- return;
289
- }
290
- if (!this.expanded()) {
291
- this.inputs.inputValue?.set('');
292
- popupControls?.clearSelection();
293
- const inputEl = this.inputs.inputEl();
294
- if (inputEl) {
295
- inputEl.value = '';
296
- }
297
- } else if (this.expanded()) {
298
- this.expanded.set(false);
299
- const selectedItem = popupControls?.getSelectedItems()?.[0];
300
- if (selectedItem?.searchTerm() !== this.inputs.inputValue()) {
301
- popupControls?.clearSelection();
302
- }
303
- return;
304
- }
305
- this.close();
306
- if (!this.readonly()) {
307
- popupControls?.clearSelection();
308
- }
309
- }
310
- open(nav) {
311
- this.expanded.set(true);
312
- const popupControls = this.inputs.popupControls();
313
- if (popupControls instanceof ComboboxDialogPattern) {
314
- return;
315
- }
316
- const inputEl = this.inputs.inputEl();
317
- if (inputEl && this.inputs.filterMode() === 'highlight') {
318
- const isHighlighting = inputEl.selectionStart !== inputEl.value.length;
319
- this.inputs.inputValue?.set(inputEl.value.slice(0, inputEl.selectionStart || 0));
320
- if (!isHighlighting) {
321
- this.highlightedItem.set(undefined);
322
- }
323
- }
324
- if (nav?.first) {
325
- this.first();
326
- }
327
- if (nav?.last) {
328
- this.last();
329
- }
330
- if (nav?.selected) {
331
- const selectedItem = popupControls?.items().find(i => popupControls?.getSelectedItems().includes(i));
332
- if (selectedItem) {
333
- popupControls?.focus(selectedItem);
334
- }
335
- }
336
- }
337
- next() {
338
- this._navigate(() => this.listControls()?.next());
339
- }
340
- prev() {
341
- this._navigate(() => this.listControls()?.prev());
342
- }
343
- first() {
344
- this._navigate(() => this.listControls()?.first());
345
- }
346
- last() {
347
- this._navigate(() => this.listControls()?.last());
348
- }
349
- collapseItem() {
350
- const controls = this.inputs.popupControls();
351
- this._navigate(() => controls?.collapseItem());
352
- }
353
- expandItem() {
354
- const controls = this.inputs.popupControls();
355
- this._navigate(() => controls?.expandItem());
356
- }
357
- select(opts = {}) {
358
- const controls = this.listControls();
359
- const item = opts.item ?? controls?.getActiveItem();
360
- if (item?.disabled()) {
361
- return;
362
- }
363
- if (opts.item) {
364
- controls?.focus(opts.item, {
365
- focusElement: false
366
- });
367
- }
368
- controls?.multi() ? controls.toggle(opts.item) : controls?.select(opts.item);
369
- if (opts.commit) {
370
- this.commit();
371
- }
372
- if (opts.close) {
373
- this.close();
374
- }
375
- }
376
- commit() {
377
- const inputEl = this.inputs.inputEl();
378
- const selectedItems = this.listControls()?.getSelectedItems();
379
- if (!inputEl) {
380
- return;
381
- }
382
- inputEl.value = selectedItems?.map(i => i.searchTerm()).join(', ') || '';
383
- this.inputs.inputValue?.set(inputEl.value);
384
- if (this.inputs.filterMode() === 'highlight' && !this.readonly()) {
385
- const length = inputEl.value.length;
386
- inputEl.setSelectionRange(length, length);
387
- }
388
- }
389
- _navigate(operation) {
390
- operation();
391
- if (this.inputs.filterMode() !== 'manual') {
392
- this.select();
393
- }
394
- if (this.inputs.filterMode() === 'highlight') {
395
- const selectedItem = this.listControls()?.getSelectedItems()[0];
396
- if (!selectedItem) {
397
- return;
398
- }
399
- if (selectedItem === this.highlightedItem()) {
400
- this.highlight();
401
- } else {
402
- const inputEl = this.inputs.inputEl();
403
- inputEl.value = selectedItem?.searchTerm();
404
- }
405
- }
406
- }
407
- }
408
- class ComboboxDialogPattern {
409
- inputs;
410
- id = () => this.inputs.id();
411
- role = () => 'dialog';
412
- keydown = computed(() => {
413
- return new KeyboardEventManager().on('Escape', () => this.inputs.combobox.close());
414
- });
415
- constructor(inputs) {
416
- this.inputs = inputs;
417
- }
418
- onKeydown(event) {
419
- this.keydown().handle(event);
420
- }
421
- onClick(event) {
422
- if (event.target === this.inputs.element()) {
423
- this.inputs.combobox.close();
424
- }
425
- }
426
- }
427
-
428
- export { ComboboxDialogPattern, ComboboxPattern };
429
- //# sourceMappingURL=_combobox-chunk.mjs.map