ng-primitives 0.43.1 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/a11y/active-descendant/active-descendant.d.ts +38 -0
- package/a11y/index.d.ts +2 -1
- package/combobox/README.md +3 -0
- package/combobox/combobox/combobox-state.d.ts +59 -0
- package/combobox/combobox/combobox.d.ts +176 -0
- package/combobox/combobox-button/combobox-button.d.ts +60 -0
- package/combobox/combobox-dropdown/combobox-dropdown.d.ts +15 -0
- package/combobox/combobox-input/combobox-input.d.ts +78 -0
- package/combobox/combobox-option/combobox-option.d.ts +93 -0
- package/combobox/combobox-portal/combobox-portal.d.ts +48 -0
- package/combobox/index.d.ts +7 -0
- package/dialog/config/dialog-config.d.ts +2 -0
- package/dialog/dialog/dialog-ref.d.ts +2 -0
- package/dialog/dialog-trigger/dialog-trigger.d.ts +8 -1
- package/fesm2022/ng-primitives-a11y.mjs +100 -1
- package/fesm2022/ng-primitives-a11y.mjs.map +1 -1
- package/fesm2022/ng-primitives-combobox.mjs +807 -0
- package/fesm2022/ng-primitives-combobox.mjs.map +1 -0
- package/fesm2022/ng-primitives-dialog.mjs +19 -3
- package/fesm2022/ng-primitives-dialog.mjs.map +1 -1
- package/fesm2022/ng-primitives-resize.mjs +21 -2
- package/fesm2022/ng-primitives-resize.mjs.map +1 -1
- package/package.json +17 -13
- package/resize/index.d.ts +1 -1
- package/resize/utils/resize.d.ts +5 -0
- package/schematics/ng-generate/schema.d.ts +2 -1
- package/schematics/ng-generate/schema.json +1 -0
- package/schematics/ng-generate/templates/combobox/combobox.__fileSuffix@dasherize__.ts.template +233 -0
- package/schematics/ng-generate/templates/listbox/listbox.__fileSuffix@dasherize__.ts.template +2 -0
|
@@ -0,0 +1,807 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, Directive, computed, HostListener, booleanAttribute, inject, TemplateRef, ViewContainerRef, Injector, signal, effect, output, afterNextRender } from '@angular/core';
|
|
3
|
+
import { injectElementRef, setupInteractions, explicitEffect } from 'ng-primitives/internal';
|
|
4
|
+
import { uniqueId } from 'ng-primitives/utils';
|
|
5
|
+
import { createStateToken, createStateProvider, createStateInjector, createState } from 'ng-primitives/state';
|
|
6
|
+
import { DOCUMENT } from '@angular/common';
|
|
7
|
+
import { flip, autoUpdate, computePosition } from '@floating-ui/dom';
|
|
8
|
+
import { createPortal } from 'ng-primitives/portal';
|
|
9
|
+
import { observeResize } from 'ng-primitives/resize';
|
|
10
|
+
import { activeDescendantManager } from 'ng-primitives/a11y';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The state token for the Combobox primitive.
|
|
14
|
+
*/
|
|
15
|
+
const NgpComboboxStateToken = createStateToken('Combobox');
|
|
16
|
+
/**
|
|
17
|
+
* Provides the Combobox state.
|
|
18
|
+
*/
|
|
19
|
+
const provideComboboxState = createStateProvider(NgpComboboxStateToken);
|
|
20
|
+
/**
|
|
21
|
+
* Injects the Combobox state.
|
|
22
|
+
*/
|
|
23
|
+
const injectComboboxState = createStateInjector(NgpComboboxStateToken);
|
|
24
|
+
/**
|
|
25
|
+
* The Combobox state registration function.
|
|
26
|
+
*/
|
|
27
|
+
const comboboxState = createState(NgpComboboxStateToken);
|
|
28
|
+
|
|
29
|
+
class NgpComboboxDropdown {
|
|
30
|
+
constructor() {
|
|
31
|
+
/** Access the combobox state. */
|
|
32
|
+
this.state = injectComboboxState();
|
|
33
|
+
/**
|
|
34
|
+
* Access the element reference.
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
this.elementRef = injectElementRef();
|
|
38
|
+
/** The id of the dropdown. */
|
|
39
|
+
this.id = input(uniqueId('ngp-combobox-dropdown'));
|
|
40
|
+
this.state().registerDropdown(this);
|
|
41
|
+
}
|
|
42
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpComboboxDropdown, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
43
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.11", type: NgpComboboxDropdown, isStandalone: true, selector: "[ngpComboboxDropdown]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "listbox" }, properties: { "id": "id()" } }, exportAs: ["ngpComboboxDropdown"], ngImport: i0 }); }
|
|
44
|
+
}
|
|
45
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpComboboxDropdown, decorators: [{
|
|
46
|
+
type: Directive,
|
|
47
|
+
args: [{
|
|
48
|
+
selector: '[ngpComboboxDropdown]',
|
|
49
|
+
exportAs: 'ngpComboboxDropdown',
|
|
50
|
+
host: {
|
|
51
|
+
role: 'listbox',
|
|
52
|
+
'[id]': 'id()',
|
|
53
|
+
},
|
|
54
|
+
}]
|
|
55
|
+
}], ctorParameters: () => [] });
|
|
56
|
+
|
|
57
|
+
class NgpComboboxInput {
|
|
58
|
+
constructor() {
|
|
59
|
+
/** Access the combobox state. */
|
|
60
|
+
this.state = injectComboboxState();
|
|
61
|
+
/**
|
|
62
|
+
* Access the element reference.
|
|
63
|
+
* @internal
|
|
64
|
+
*/
|
|
65
|
+
this.elementRef = injectElementRef();
|
|
66
|
+
/** The id of the input. */
|
|
67
|
+
this.id = input(uniqueId('ngp-combobox-input'));
|
|
68
|
+
/**
|
|
69
|
+
* Extract the string representation of the value.
|
|
70
|
+
*/
|
|
71
|
+
this.displayWith = input((value) => {
|
|
72
|
+
if (typeof value === 'string') {
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
throw new Error('You must provide a displayWith function for non-string values');
|
|
76
|
+
});
|
|
77
|
+
/** The id of the dropdown. */
|
|
78
|
+
this.dropdownId = computed(() => this.state().dropdown()?.id());
|
|
79
|
+
/** The id of the active descendant. */
|
|
80
|
+
this.activeDescendant = computed(() => this.state().activeDescendantManager.activeDescendant());
|
|
81
|
+
/** Determine if the pointer was used to focus the input. */
|
|
82
|
+
this.pointerFocused = false;
|
|
83
|
+
setupInteractions({
|
|
84
|
+
focus: true,
|
|
85
|
+
hover: true,
|
|
86
|
+
press: true,
|
|
87
|
+
disabled: this.state().disabled,
|
|
88
|
+
});
|
|
89
|
+
this.state().registerInput(this);
|
|
90
|
+
}
|
|
91
|
+
/** Handle keydown events for accessibility. */
|
|
92
|
+
handleKeydown(event) {
|
|
93
|
+
switch (event.key) {
|
|
94
|
+
case 'ArrowDown':
|
|
95
|
+
if (this.state().open()) {
|
|
96
|
+
this.state().activateNextOption();
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
this.state().openDropdown();
|
|
100
|
+
}
|
|
101
|
+
event.preventDefault();
|
|
102
|
+
break;
|
|
103
|
+
case 'ArrowUp':
|
|
104
|
+
if (this.state().open()) {
|
|
105
|
+
this.state().activatePreviousOption();
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
this.state().openDropdown();
|
|
109
|
+
this.state().activeDescendantManager.last();
|
|
110
|
+
}
|
|
111
|
+
event.preventDefault();
|
|
112
|
+
break;
|
|
113
|
+
case 'Home':
|
|
114
|
+
if (this.state().open()) {
|
|
115
|
+
this.state().activeDescendantManager.first();
|
|
116
|
+
}
|
|
117
|
+
event.preventDefault();
|
|
118
|
+
break;
|
|
119
|
+
case 'End':
|
|
120
|
+
if (this.state().open()) {
|
|
121
|
+
this.state().activeDescendantManager.last();
|
|
122
|
+
}
|
|
123
|
+
event.preventDefault();
|
|
124
|
+
break;
|
|
125
|
+
case 'Enter':
|
|
126
|
+
if (this.state().open()) {
|
|
127
|
+
this.state().selectOption(this.state().activeDescendantManager.activeItem());
|
|
128
|
+
}
|
|
129
|
+
event.preventDefault();
|
|
130
|
+
break;
|
|
131
|
+
case 'Escape':
|
|
132
|
+
this.state().closeDropdown();
|
|
133
|
+
event.preventDefault();
|
|
134
|
+
break;
|
|
135
|
+
default:
|
|
136
|
+
// Ignore keys with length > 1 (e.g., 'Shift', 'ArrowLeft', 'Enter', etc.)
|
|
137
|
+
// Filter out control/meta key combos (e.g., Ctrl+C)
|
|
138
|
+
if (event.key.length > 1 || event.ctrlKey || event.metaKey || event.altKey) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// if this was a character key, we want to open the dropdown
|
|
142
|
+
this.state().openDropdown();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
closeDropdown(event) {
|
|
146
|
+
const relatedTarget = event.relatedTarget;
|
|
147
|
+
// if the blur was caused by focus moving to the dropdown, don't close
|
|
148
|
+
if (relatedTarget &&
|
|
149
|
+
this.state().dropdown()?.elementRef.nativeElement.contains(relatedTarget)) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// if the blur was caused by focus moving to the button, don't close
|
|
153
|
+
if (relatedTarget && this.state().button()?.elementRef.nativeElement.contains(relatedTarget)) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
this.state().closeDropdown();
|
|
157
|
+
event.preventDefault();
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Focus the input field
|
|
161
|
+
* @internal
|
|
162
|
+
*/
|
|
163
|
+
focus() {
|
|
164
|
+
this.elementRef.nativeElement.focus();
|
|
165
|
+
}
|
|
166
|
+
highlightText() {
|
|
167
|
+
if (this.pointerFocused) {
|
|
168
|
+
this.pointerFocused = false;
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
// highlight the text in the input
|
|
172
|
+
this.elementRef.nativeElement.setSelectionRange(0, this.elementRef.nativeElement.value.length);
|
|
173
|
+
}
|
|
174
|
+
handlePointerDown() {
|
|
175
|
+
this.pointerFocused = true;
|
|
176
|
+
}
|
|
177
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpComboboxInput, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
178
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.11", type: NgpComboboxInput, isStandalone: true, selector: "input[ngpComboboxInput]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, displayWith: { classPropertyName: "displayWith", publicName: "displayWith", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "combobox", "type": "text", "autocomplete": "off", "autocorrect": "off", "spellcheck": "false", "aria-haspopup": "listbox", "aria-autocomplete": "list" }, listeners: { "keydown": "handleKeydown($event)", "blur": "closeDropdown($event)", "focus": "highlightText($event)", "pointerdown": "handlePointerDown($event)" }, properties: { "id": "id()", "attr.aria-controls": "state().open() ? dropdownId() : undefined", "attr.aria-expanded": "state().open()", "attr.data-open": "state().open() ? \"\" : undefined", "attr.data-disabled": "state().disabled() ? \"\" : undefined", "attr.data-multiple": "state().multiple() ? \"\" : undefined", "attr.aria-activedescendant": "activeDescendant()", "disabled": "state().disabled()" } }, exportAs: ["ngpComboboxInput"], ngImport: i0 }); }
|
|
179
|
+
}
|
|
180
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpComboboxInput, decorators: [{
|
|
181
|
+
type: Directive,
|
|
182
|
+
args: [{
|
|
183
|
+
selector: 'input[ngpComboboxInput]',
|
|
184
|
+
exportAs: 'ngpComboboxInput',
|
|
185
|
+
host: {
|
|
186
|
+
role: 'combobox',
|
|
187
|
+
type: 'text',
|
|
188
|
+
autocomplete: 'off',
|
|
189
|
+
autocorrect: 'off',
|
|
190
|
+
spellcheck: 'false',
|
|
191
|
+
'aria-haspopup': 'listbox',
|
|
192
|
+
'aria-autocomplete': 'list',
|
|
193
|
+
'[id]': 'id()',
|
|
194
|
+
'[attr.aria-controls]': 'state().open() ? dropdownId() : undefined',
|
|
195
|
+
'[attr.aria-expanded]': 'state().open()',
|
|
196
|
+
'[attr.data-open]': 'state().open() ? "" : undefined',
|
|
197
|
+
'[attr.data-disabled]': 'state().disabled() ? "" : undefined',
|
|
198
|
+
'[attr.data-multiple]': 'state().multiple() ? "" : undefined',
|
|
199
|
+
'[attr.aria-activedescendant]': 'activeDescendant()',
|
|
200
|
+
'[disabled]': 'state().disabled()',
|
|
201
|
+
},
|
|
202
|
+
}]
|
|
203
|
+
}], ctorParameters: () => [], propDecorators: { handleKeydown: [{
|
|
204
|
+
type: HostListener,
|
|
205
|
+
args: ['keydown', ['$event']]
|
|
206
|
+
}], closeDropdown: [{
|
|
207
|
+
type: HostListener,
|
|
208
|
+
args: ['blur', ['$event']]
|
|
209
|
+
}], highlightText: [{
|
|
210
|
+
type: HostListener,
|
|
211
|
+
args: ['focus', ['$event']]
|
|
212
|
+
}], handlePointerDown: [{
|
|
213
|
+
type: HostListener,
|
|
214
|
+
args: ['pointerdown', ['$event']]
|
|
215
|
+
}] } });
|
|
216
|
+
|
|
217
|
+
class NgpComboboxOption {
|
|
218
|
+
constructor() {
|
|
219
|
+
/** Access the combobox state. */
|
|
220
|
+
this.state = injectComboboxState();
|
|
221
|
+
/**
|
|
222
|
+
* The element reference of the option.
|
|
223
|
+
* @internal
|
|
224
|
+
*/
|
|
225
|
+
this.elementRef = injectElementRef();
|
|
226
|
+
/** The id of the option. */
|
|
227
|
+
this.id = input(uniqueId('ngp-combobox-option'));
|
|
228
|
+
/** The value of the option. */
|
|
229
|
+
this.value = input(undefined, {
|
|
230
|
+
alias: 'ngpComboboxOptionValue',
|
|
231
|
+
});
|
|
232
|
+
/** The disabled state of the option. */
|
|
233
|
+
this.disabled = input(false, {
|
|
234
|
+
alias: 'ngpComboboxOptionDisabled',
|
|
235
|
+
transform: booleanAttribute,
|
|
236
|
+
});
|
|
237
|
+
/**
|
|
238
|
+
* Whether this option is the active descendant.
|
|
239
|
+
* @internal
|
|
240
|
+
*/
|
|
241
|
+
this.active = computed(() => this.state().activeDescendantManager.activeDescendant() === this.id());
|
|
242
|
+
/** Whether this option is selected. */
|
|
243
|
+
this.selected = computed(() => {
|
|
244
|
+
const value = this.value();
|
|
245
|
+
if (!value) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
if (this.state().multiple()) {
|
|
249
|
+
return (Array.isArray(value) && value.some(v => this.state().compareWith()(v, this.state().value())));
|
|
250
|
+
}
|
|
251
|
+
return this.state().compareWith()(value, this.state().value());
|
|
252
|
+
});
|
|
253
|
+
this.state().registerOption(this);
|
|
254
|
+
setupInteractions({
|
|
255
|
+
hover: true,
|
|
256
|
+
press: true,
|
|
257
|
+
disabled: this.disabled,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
ngOnInit() {
|
|
261
|
+
if (this.value() === undefined) {
|
|
262
|
+
throw new Error('ngpComboboxOption: The value input is required. Please provide a value for the option.');
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
ngOnDestroy() {
|
|
266
|
+
this.state().unregisterOption(this);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Select the option.
|
|
270
|
+
* @internal
|
|
271
|
+
*/
|
|
272
|
+
select() {
|
|
273
|
+
if (this.disabled()) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
this.state().toggleOption(this);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Scroll the option into view.
|
|
280
|
+
* @internal
|
|
281
|
+
*/
|
|
282
|
+
scrollIntoView() {
|
|
283
|
+
this.elementRef.nativeElement.scrollIntoView({ block: 'nearest' });
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Whenever the pointer enters the option, activate it.
|
|
287
|
+
* @internal
|
|
288
|
+
*/
|
|
289
|
+
onPointerEnter() {
|
|
290
|
+
this.state().activeDescendantManager.activate(this);
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Whenever the pointer leaves the option, deactivate it.
|
|
294
|
+
* @internal
|
|
295
|
+
*/
|
|
296
|
+
onPointerLeave() {
|
|
297
|
+
this.state().activeDescendantManager.activate(undefined);
|
|
298
|
+
}
|
|
299
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpComboboxOption, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
300
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.11", type: NgpComboboxOption, isStandalone: true, selector: "[ngpComboboxOption]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "ngpComboboxOptionValue", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpComboboxOptionDisabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "option" }, listeners: { "click": "select()", "pointerenter": "onPointerEnter()", "pointerleave": "onPointerLeave()" }, properties: { "id": "id()", "attr.tabindex": "-1", "attr.aria-selected": "selected() ? \"true\" : undefined", "attr.data-selected": "selected() ? \"\" : undefined", "attr.data-active": "active() ? \"\" : undefined", "attr.data-disabled": "disabled() ? \"\" : undefined" } }, exportAs: ["ngpComboboxOption"], ngImport: i0 }); }
|
|
301
|
+
}
|
|
302
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpComboboxOption, decorators: [{
|
|
303
|
+
type: Directive,
|
|
304
|
+
args: [{
|
|
305
|
+
selector: '[ngpComboboxOption]',
|
|
306
|
+
exportAs: 'ngpComboboxOption',
|
|
307
|
+
host: {
|
|
308
|
+
role: 'option',
|
|
309
|
+
'[id]': 'id()',
|
|
310
|
+
'[attr.tabindex]': '-1',
|
|
311
|
+
'[attr.aria-selected]': 'selected() ? "true" : undefined',
|
|
312
|
+
'[attr.data-selected]': 'selected() ? "" : undefined',
|
|
313
|
+
'[attr.data-active]': 'active() ? "" : undefined',
|
|
314
|
+
'[attr.data-disabled]': 'disabled() ? "" : undefined',
|
|
315
|
+
'(click)': 'select()',
|
|
316
|
+
},
|
|
317
|
+
}]
|
|
318
|
+
}], ctorParameters: () => [], propDecorators: { onPointerEnter: [{
|
|
319
|
+
type: HostListener,
|
|
320
|
+
args: ['pointerenter']
|
|
321
|
+
}], onPointerLeave: [{
|
|
322
|
+
type: HostListener,
|
|
323
|
+
args: ['pointerleave']
|
|
324
|
+
}] } });
|
|
325
|
+
|
|
326
|
+
class NgpComboboxPortal {
|
|
327
|
+
constructor() {
|
|
328
|
+
/** Access the combobox state. */
|
|
329
|
+
this.state = injectComboboxState();
|
|
330
|
+
/** Access the template reference. */
|
|
331
|
+
this.templateRef = inject(TemplateRef);
|
|
332
|
+
/** Access the view container reference. */
|
|
333
|
+
this.viewContainerRef = inject(ViewContainerRef);
|
|
334
|
+
/** Access the injector. */
|
|
335
|
+
this.injector = inject(Injector);
|
|
336
|
+
/** Access the document. */
|
|
337
|
+
this.document = inject(DOCUMENT);
|
|
338
|
+
/**
|
|
339
|
+
* Store the embedded view reference.
|
|
340
|
+
* @internal
|
|
341
|
+
*/
|
|
342
|
+
this.viewRef = signal(null);
|
|
343
|
+
/** Store the dispose function. */
|
|
344
|
+
this.dispose = null;
|
|
345
|
+
/** The position of the dropdown. */
|
|
346
|
+
this.position = signal({ x: 0, y: 0 });
|
|
347
|
+
/** The dimensions of the combobox. */
|
|
348
|
+
this.comboboxDimensions = observeResize(() => this.state().elementRef.nativeElement);
|
|
349
|
+
/** The dimensions of the combobox. */
|
|
350
|
+
this.inputDimensions = observeResize(() => this.state().input()?.elementRef.nativeElement);
|
|
351
|
+
/** Store the combobox button dimensions. */
|
|
352
|
+
this.buttonDimensions = observeResize(() => this.state().button()?.elementRef.nativeElement);
|
|
353
|
+
this.state().registerPortal(this);
|
|
354
|
+
effect(() => {
|
|
355
|
+
const dropdownElement = this.viewRef()?.getElements()[0];
|
|
356
|
+
if (!dropdownElement) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const position = this.position();
|
|
360
|
+
const comboboxWidth = this.comboboxDimensions().width;
|
|
361
|
+
const inputWidth = this.inputDimensions().width;
|
|
362
|
+
const buttonWidth = this.buttonDimensions().width;
|
|
363
|
+
if (!dropdownElement) {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
const styles = {
|
|
367
|
+
position: 'absolute',
|
|
368
|
+
left: `${position.x}px`,
|
|
369
|
+
top: `${position.y}px`,
|
|
370
|
+
'--ngp-combobox-width': `${comboboxWidth}px`,
|
|
371
|
+
'--ngp-combobox-input-width': `${inputWidth}px`,
|
|
372
|
+
'--ngp-combobox-button-width': `${buttonWidth}px`,
|
|
373
|
+
};
|
|
374
|
+
for (const [key, value] of Object.entries(styles)) {
|
|
375
|
+
dropdownElement.style.setProperty(key, value);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
/** Cleanup the portal. */
|
|
380
|
+
ngOnDestroy() {
|
|
381
|
+
this.detach();
|
|
382
|
+
this.dispose?.();
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Attach the portal.
|
|
386
|
+
* @internal
|
|
387
|
+
*/
|
|
388
|
+
attach() {
|
|
389
|
+
const viewRef = createPortal(this.templateRef, this.viewContainerRef, this.injector);
|
|
390
|
+
viewRef.attach(this.document.body);
|
|
391
|
+
viewRef.detectChanges();
|
|
392
|
+
this.viewRef.set(viewRef);
|
|
393
|
+
const dropdownElement = this.viewRef()?.getElements()[0];
|
|
394
|
+
if (!dropdownElement) {
|
|
395
|
+
throw new Error('Dropdown element not found');
|
|
396
|
+
}
|
|
397
|
+
let placement;
|
|
398
|
+
const middleware = [];
|
|
399
|
+
switch (this.state().dropdownPosition()) {
|
|
400
|
+
case 'top':
|
|
401
|
+
placement = 'top-start';
|
|
402
|
+
break;
|
|
403
|
+
case 'bottom':
|
|
404
|
+
placement = 'bottom-start';
|
|
405
|
+
break;
|
|
406
|
+
case 'auto':
|
|
407
|
+
placement = 'bottom-start';
|
|
408
|
+
middleware.push(flip({ fallbackPlacements: ['top-start'] }));
|
|
409
|
+
break;
|
|
410
|
+
}
|
|
411
|
+
this.dispose = autoUpdate(this.state().elementRef.nativeElement, dropdownElement, async () => {
|
|
412
|
+
const position = await computePosition(this.state().elementRef.nativeElement, dropdownElement, { placement, middleware, strategy: 'absolute' });
|
|
413
|
+
this.position.set({ x: position.x, y: position.y });
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Detach the portal.
|
|
418
|
+
* @internal
|
|
419
|
+
*/
|
|
420
|
+
async detach() {
|
|
421
|
+
await this.viewRef()?.detach();
|
|
422
|
+
this.viewRef.set(null);
|
|
423
|
+
this.dispose?.();
|
|
424
|
+
this.dispose = null;
|
|
425
|
+
}
|
|
426
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpComboboxPortal, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
427
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.11", type: NgpComboboxPortal, isStandalone: true, selector: "[ngpComboboxPortal]", exportAs: ["ngpComboboxPortal"], ngImport: i0 }); }
|
|
428
|
+
}
|
|
429
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpComboboxPortal, decorators: [{
|
|
430
|
+
type: Directive,
|
|
431
|
+
args: [{
|
|
432
|
+
selector: '[ngpComboboxPortal]',
|
|
433
|
+
exportAs: 'ngpComboboxPortal',
|
|
434
|
+
}]
|
|
435
|
+
}], ctorParameters: () => [] });
|
|
436
|
+
|
|
437
|
+
class NgpCombobox {
|
|
438
|
+
constructor() {
|
|
439
|
+
/** @internal Access the combobox element. */
|
|
440
|
+
this.elementRef = injectElementRef();
|
|
441
|
+
/** Access the injector. */
|
|
442
|
+
this.injector = inject(Injector);
|
|
443
|
+
/** The value of the combobox. */
|
|
444
|
+
this.value = input(undefined, {
|
|
445
|
+
alias: 'ngpComboboxValue',
|
|
446
|
+
});
|
|
447
|
+
/** Event emitted when the value changes. */
|
|
448
|
+
this.valueChange = output({
|
|
449
|
+
alias: 'ngpComboboxValueChange',
|
|
450
|
+
});
|
|
451
|
+
/** Whether the combobox is multiple selection. */
|
|
452
|
+
this.multiple = input(false, {
|
|
453
|
+
alias: 'ngpComboboxMultiple',
|
|
454
|
+
transform: booleanAttribute,
|
|
455
|
+
});
|
|
456
|
+
/** Whether the combobox is disabled. */
|
|
457
|
+
this.disabled = input(false, {
|
|
458
|
+
alias: 'ngpComboboxDisabled',
|
|
459
|
+
transform: booleanAttribute,
|
|
460
|
+
});
|
|
461
|
+
/** Emit when the dropdown open state changes. */
|
|
462
|
+
this.openChange = output({
|
|
463
|
+
alias: 'ngpComboboxOpenChange',
|
|
464
|
+
});
|
|
465
|
+
/** The comparator function used to compare options. */
|
|
466
|
+
this.compareWith = input(Object.is, {
|
|
467
|
+
alias: 'ngpComboboxCompareWith',
|
|
468
|
+
});
|
|
469
|
+
/** The position of the dropdown. */
|
|
470
|
+
this.dropdownPosition = input('bottom', {
|
|
471
|
+
alias: 'ngpComboboxDropdownPosition',
|
|
472
|
+
});
|
|
473
|
+
/**
|
|
474
|
+
* Store the combobox input
|
|
475
|
+
* @internal
|
|
476
|
+
*/
|
|
477
|
+
this.input = signal(undefined);
|
|
478
|
+
/**
|
|
479
|
+
* Store the combobox button.
|
|
480
|
+
* @internal
|
|
481
|
+
*/
|
|
482
|
+
this.button = signal(undefined);
|
|
483
|
+
/**
|
|
484
|
+
* Store the combobox portal.
|
|
485
|
+
* @internal
|
|
486
|
+
*/
|
|
487
|
+
this.portal = signal(undefined);
|
|
488
|
+
/**
|
|
489
|
+
* Store the combobox dropdown.
|
|
490
|
+
* @internal
|
|
491
|
+
*/
|
|
492
|
+
this.dropdown = signal(undefined);
|
|
493
|
+
/**
|
|
494
|
+
* Store the combobox options.
|
|
495
|
+
* @internal
|
|
496
|
+
*/
|
|
497
|
+
this.options = signal([]);
|
|
498
|
+
/**
|
|
499
|
+
* The open state of the combobox.
|
|
500
|
+
* @internal
|
|
501
|
+
*/
|
|
502
|
+
this.open = computed(() => this.portal()?.viewRef() !== null);
|
|
503
|
+
/**
|
|
504
|
+
* The active key descendant manager.
|
|
505
|
+
* @internal
|
|
506
|
+
*/
|
|
507
|
+
this.activeDescendantManager = activeDescendantManager({
|
|
508
|
+
// we must wrap the signal in a computed to ensure it is not used before it is defined
|
|
509
|
+
disabled: computed(() => this.state.disabled()),
|
|
510
|
+
items: this.options,
|
|
511
|
+
});
|
|
512
|
+
/** The state of the combobox. */
|
|
513
|
+
this.state = comboboxState(this);
|
|
514
|
+
// any time the active descendant changes, ensure we scroll it into view
|
|
515
|
+
explicitEffect([this.activeDescendantManager.activeItem], ([option]) =>
|
|
516
|
+
// perform after next render to ensure the DOM is updated
|
|
517
|
+
// e.g. the dropdown is open before the option is scrolled into view
|
|
518
|
+
afterNextRender({ write: () => option?.scrollIntoView?.() }, { injector: this.injector }));
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Open the dropdown.
|
|
522
|
+
* @internal
|
|
523
|
+
*/
|
|
524
|
+
openDropdown() {
|
|
525
|
+
if (this.state.disabled() || this.open()) {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
this.portal()?.attach();
|
|
529
|
+
// if there is a selected option(s), set the active descendant to the first selected option
|
|
530
|
+
const selectedOption = this.options().find(option => this.isOptionSelected(option));
|
|
531
|
+
// if there is no selected option, set the active descendant to the first option
|
|
532
|
+
const targetOption = selectedOption ?? this.options()[0];
|
|
533
|
+
// if there is no target option, do nothing
|
|
534
|
+
if (!targetOption) {
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
// activate the selected option or the first option
|
|
538
|
+
this.activeDescendantManager.activate(targetOption);
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Close the dropdown.
|
|
542
|
+
* @internal
|
|
543
|
+
*/
|
|
544
|
+
closeDropdown() {
|
|
545
|
+
if (!this.open()) {
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
548
|
+
this.openChange.emit(false);
|
|
549
|
+
this.portal()?.detach();
|
|
550
|
+
// clear the active descendant
|
|
551
|
+
this.activeDescendantManager.reset();
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Toggle the dropdown.
|
|
555
|
+
* @internal
|
|
556
|
+
*/
|
|
557
|
+
toggleDropdown() {
|
|
558
|
+
if (this.open()) {
|
|
559
|
+
this.closeDropdown();
|
|
560
|
+
}
|
|
561
|
+
else {
|
|
562
|
+
this.openDropdown();
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Select an option.
|
|
567
|
+
* @param option The option to select.
|
|
568
|
+
* @internal
|
|
569
|
+
*/
|
|
570
|
+
selectOption(option) {
|
|
571
|
+
if (this.state.disabled() || this.isOptionSelected(option)) {
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
if (this.state.multiple()) {
|
|
575
|
+
const value = [...this.state.value(), option.value()];
|
|
576
|
+
// add the option to the value
|
|
577
|
+
this.state.value.set(value);
|
|
578
|
+
this.valueChange.emit(value);
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
this.state.value.set(option.value());
|
|
582
|
+
this.valueChange.emit(option.value());
|
|
583
|
+
// close the dropdown on single selection
|
|
584
|
+
this.closeDropdown();
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Deselect an option.
|
|
589
|
+
* @param option The option to deselect.
|
|
590
|
+
* @internal
|
|
591
|
+
*/
|
|
592
|
+
deselectOption(option) {
|
|
593
|
+
// if the combobox is disabled or the option is not selected, do nothing
|
|
594
|
+
// if the combobox is single selection, we don't allow deselecting
|
|
595
|
+
if (this.state.disabled() || !this.isOptionSelected(option) || !this.state.multiple()) {
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
const values = this.state.value() ?? [];
|
|
599
|
+
const newValue = values.filter(v => !this.state.compareWith()(v, option.value()));
|
|
600
|
+
// remove the option from the value
|
|
601
|
+
this.state.value.set(newValue);
|
|
602
|
+
this.valueChange.emit(newValue);
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Toggle the selection of an option.
|
|
606
|
+
* @param option The option to toggle.
|
|
607
|
+
* @internal
|
|
608
|
+
*/
|
|
609
|
+
toggleOption(option) {
|
|
610
|
+
if (this.state.disabled()) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
if (this.isOptionSelected(option)) {
|
|
614
|
+
this.deselectOption(option);
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
this.selectOption(option);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Determine if an option is selected.
|
|
622
|
+
* @param option The option to check.
|
|
623
|
+
* @internal
|
|
624
|
+
*/
|
|
625
|
+
isOptionSelected(option) {
|
|
626
|
+
if (this.state.disabled()) {
|
|
627
|
+
return false;
|
|
628
|
+
}
|
|
629
|
+
const value = this.state.value();
|
|
630
|
+
if (!value) {
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
if (this.state.multiple()) {
|
|
634
|
+
return value && value.some(v => this.state.compareWith()(option.value(), v));
|
|
635
|
+
}
|
|
636
|
+
return this.state.compareWith()(option.value(), value);
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Activate the next option in the list if there is one.
|
|
640
|
+
* If there is no option currently active, activate the selected option or the first option.
|
|
641
|
+
* @internal
|
|
642
|
+
*/
|
|
643
|
+
activateNextOption() {
|
|
644
|
+
if (this.state.disabled()) {
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
const options = this.options();
|
|
648
|
+
// if there are no options, do nothing
|
|
649
|
+
if (options.length === 0) {
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
652
|
+
// if there is no active option, activate the first option
|
|
653
|
+
if (!this.activeDescendantManager.activeItem()) {
|
|
654
|
+
const selectedOption = options.find(option => this.isOptionSelected(option));
|
|
655
|
+
// if there is a selected option(s), set the active descendant to the first selected option
|
|
656
|
+
const targetOption = selectedOption ?? options[0];
|
|
657
|
+
this.activeDescendantManager.activate(targetOption);
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
// otherwise activate the next option
|
|
661
|
+
this.activeDescendantManager.next();
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Activate the previous option in the list if there is one.
|
|
665
|
+
* @internal
|
|
666
|
+
*/
|
|
667
|
+
activatePreviousOption() {
|
|
668
|
+
if (this.state.disabled()) {
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
const options = this.options();
|
|
672
|
+
// if there are no options, do nothing
|
|
673
|
+
if (options.length === 0) {
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
// if there is no active option, activate the last option
|
|
677
|
+
if (!this.activeDescendantManager.activeItem()) {
|
|
678
|
+
const selectedOption = options.find(option => this.isOptionSelected(option));
|
|
679
|
+
// if there is a selected option(s), set the active descendant to the first selected option
|
|
680
|
+
const targetOption = selectedOption ?? options[options.length - 1];
|
|
681
|
+
this.activeDescendantManager.activate(targetOption);
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
// otherwise activate the previous option
|
|
685
|
+
this.activeDescendantManager.previous();
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Register the dropdown portal with the combobox.
|
|
689
|
+
* @param portal The dropdown portal.
|
|
690
|
+
* @internal
|
|
691
|
+
*/
|
|
692
|
+
registerPortal(portal) {
|
|
693
|
+
this.portal.set(portal);
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Register the combobox input with the combobox.
|
|
697
|
+
* @param input The combobox input.
|
|
698
|
+
* @internal
|
|
699
|
+
*/
|
|
700
|
+
registerInput(input) {
|
|
701
|
+
this.input.set(input);
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Register the combobox button with the combobox.
|
|
705
|
+
* @param button The combobox button.
|
|
706
|
+
* @internal
|
|
707
|
+
*/
|
|
708
|
+
registerButton(button) {
|
|
709
|
+
this.button.set(button);
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Register the dropdown with the combobox.
|
|
713
|
+
* @param dropdown The dropdown to register.
|
|
714
|
+
* @internal
|
|
715
|
+
*/
|
|
716
|
+
registerDropdown(dropdown) {
|
|
717
|
+
this.dropdown.set(dropdown);
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Register an option with the combobox.
|
|
721
|
+
* @param option The option to register.
|
|
722
|
+
* @internal
|
|
723
|
+
*/
|
|
724
|
+
registerOption(option) {
|
|
725
|
+
this.options.update(options => [...options, option]);
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Unregister an option from the combobox.
|
|
729
|
+
* @param option The option to unregister.
|
|
730
|
+
* @internal
|
|
731
|
+
*/
|
|
732
|
+
unregisterOption(option) {
|
|
733
|
+
this.options.update(options => options.filter(o => o !== option));
|
|
734
|
+
}
|
|
735
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpCombobox, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
736
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.11", type: NgpCombobox, isStandalone: true, selector: "[ngpCombobox]", inputs: { value: { classPropertyName: "value", publicName: "ngpComboboxValue", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "ngpComboboxMultiple", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpComboboxDisabled", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "ngpComboboxCompareWith", isSignal: true, isRequired: false, transformFunction: null }, dropdownPosition: { classPropertyName: "dropdownPosition", publicName: "ngpComboboxDropdownPosition", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "ngpComboboxValueChange", openChange: "ngpComboboxOpenChange" }, host: { properties: { "attr.data-open": "state.open() ? \"\" : undefined", "attr.data-disabled": "state.disabled() ? \"\" : undefined", "attr.data-multiple": "state.multiple() ? \"\" : undefined" } }, providers: [provideComboboxState()], exportAs: ["ngpCombobox"], ngImport: i0 }); }
|
|
737
|
+
}
|
|
738
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpCombobox, decorators: [{
|
|
739
|
+
type: Directive,
|
|
740
|
+
args: [{
|
|
741
|
+
selector: '[ngpCombobox]',
|
|
742
|
+
exportAs: 'ngpCombobox',
|
|
743
|
+
providers: [provideComboboxState()],
|
|
744
|
+
host: {
|
|
745
|
+
'[attr.data-open]': 'state.open() ? "" : undefined',
|
|
746
|
+
'[attr.data-disabled]': 'state.disabled() ? "" : undefined',
|
|
747
|
+
'[attr.data-multiple]': 'state.multiple() ? "" : undefined',
|
|
748
|
+
},
|
|
749
|
+
}]
|
|
750
|
+
}], ctorParameters: () => [] });
|
|
751
|
+
|
|
752
|
+
class NgpComboboxButton {
|
|
753
|
+
constructor() {
|
|
754
|
+
/** Access the combobox state. */
|
|
755
|
+
this.state = injectComboboxState();
|
|
756
|
+
/**
|
|
757
|
+
* Access the element reference.
|
|
758
|
+
* @internal
|
|
759
|
+
*/
|
|
760
|
+
this.elementRef = injectElementRef();
|
|
761
|
+
/** The id of the button. */
|
|
762
|
+
this.id = input(uniqueId('ngp-combobox-button'));
|
|
763
|
+
/** The id of the dropdown. */
|
|
764
|
+
this.dropdownId = computed(() => this.state().dropdown()?.id());
|
|
765
|
+
setupInteractions({
|
|
766
|
+
hover: true,
|
|
767
|
+
press: true,
|
|
768
|
+
disabled: this.state().disabled,
|
|
769
|
+
});
|
|
770
|
+
this.state().registerButton(this);
|
|
771
|
+
}
|
|
772
|
+
toggleDropdown() {
|
|
773
|
+
this.state().toggleDropdown();
|
|
774
|
+
this.state().input()?.focus();
|
|
775
|
+
}
|
|
776
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpComboboxButton, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
777
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.11", type: NgpComboboxButton, isStandalone: true, selector: "[ngpComboboxButton]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "button", "tabindex": "-1", "aria-haspopup": "listbox" }, listeners: { "click": "toggleDropdown()" }, properties: { "id": "id()", "attr.aria-controls": "dropdownId()", "attr.aria-expanded": "state().open()", "attr.data-open": "state().open() ? \"\" : undefined", "attr.data-disabled": "state().disabled() ? \"\" : undefined", "attr.data-multiple": "state().multiple() ? \"\" : undefined", "disabled": "state().disabled()" } }, exportAs: ["ngpComboboxButton"], ngImport: i0 }); }
|
|
778
|
+
}
|
|
779
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.11", ngImport: i0, type: NgpComboboxButton, decorators: [{
|
|
780
|
+
type: Directive,
|
|
781
|
+
args: [{
|
|
782
|
+
selector: '[ngpComboboxButton]',
|
|
783
|
+
exportAs: 'ngpComboboxButton',
|
|
784
|
+
host: {
|
|
785
|
+
type: 'button',
|
|
786
|
+
tabindex: '-1',
|
|
787
|
+
'aria-haspopup': 'listbox',
|
|
788
|
+
'[id]': 'id()',
|
|
789
|
+
'[attr.aria-controls]': 'dropdownId()',
|
|
790
|
+
'[attr.aria-expanded]': 'state().open()',
|
|
791
|
+
'[attr.data-open]': 'state().open() ? "" : undefined',
|
|
792
|
+
'[attr.data-disabled]': 'state().disabled() ? "" : undefined',
|
|
793
|
+
'[attr.data-multiple]': 'state().multiple() ? "" : undefined',
|
|
794
|
+
'[disabled]': 'state().disabled()',
|
|
795
|
+
},
|
|
796
|
+
}]
|
|
797
|
+
}], ctorParameters: () => [], propDecorators: { toggleDropdown: [{
|
|
798
|
+
type: HostListener,
|
|
799
|
+
args: ['click']
|
|
800
|
+
}] } });
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Generated bundle index. Do not edit.
|
|
804
|
+
*/
|
|
805
|
+
|
|
806
|
+
export { NgpCombobox, NgpComboboxButton, NgpComboboxDropdown, NgpComboboxInput, NgpComboboxOption, NgpComboboxPortal, injectComboboxState, provideComboboxState };
|
|
807
|
+
//# sourceMappingURL=ng-primitives-combobox.mjs.map
|