ng-primitives 0.120.4 → 0.121.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/example-theme/index.css +9 -0
- package/fesm2022/ng-primitives-a11y.mjs +5 -5
- package/fesm2022/ng-primitives-a11y.mjs.map +1 -1
- package/fesm2022/ng-primitives-accordion.mjs +34 -51
- package/fesm2022/ng-primitives-accordion.mjs.map +1 -1
- package/fesm2022/ng-primitives-ai.mjs +39 -52
- package/fesm2022/ng-primitives-ai.mjs.map +1 -1
- package/fesm2022/ng-primitives-autofill.mjs +4 -4
- package/fesm2022/ng-primitives-autofill.mjs.map +1 -1
- package/fesm2022/ng-primitives-avatar.mjs +14 -17
- package/fesm2022/ng-primitives-avatar.mjs.map +1 -1
- package/fesm2022/ng-primitives-breadcrumbs.mjs +21 -21
- package/fesm2022/ng-primitives-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ng-primitives-button.mjs +7 -9
- package/fesm2022/ng-primitives-button.mjs.map +1 -1
- package/fesm2022/ng-primitives-checkbox.mjs +15 -30
- package/fesm2022/ng-primitives-checkbox.mjs.map +1 -1
- package/fesm2022/ng-primitives-combobox.mjs +60 -92
- package/fesm2022/ng-primitives-combobox.mjs.map +1 -1
- package/fesm2022/ng-primitives-common.mjs +4 -4
- package/fesm2022/ng-primitives-common.mjs.map +1 -1
- package/fesm2022/ng-primitives-context-menu.mjs +68 -121
- package/fesm2022/ng-primitives-context-menu.mjs.map +1 -1
- package/fesm2022/ng-primitives-date-picker.mjs +91 -115
- package/fesm2022/ng-primitives-date-picker.mjs.map +1 -1
- package/fesm2022/ng-primitives-dialog.mjs +35 -51
- package/fesm2022/ng-primitives-dialog.mjs.map +1 -1
- package/fesm2022/ng-primitives-file-upload.mjs +26 -53
- package/fesm2022/ng-primitives-file-upload.mjs.map +1 -1
- package/fesm2022/ng-primitives-focus-trap.mjs +5 -8
- package/fesm2022/ng-primitives-focus-trap.mjs.map +1 -1
- package/fesm2022/ng-primitives-form-field.mjs +39 -44
- package/fesm2022/ng-primitives-form-field.mjs.map +1 -1
- package/fesm2022/ng-primitives-input-otp.mjs +30 -43
- package/fesm2022/ng-primitives-input-otp.mjs.map +1 -1
- package/fesm2022/ng-primitives-input.mjs +6 -8
- package/fesm2022/ng-primitives-input.mjs.map +1 -1
- package/fesm2022/ng-primitives-interactions.mjs +31 -48
- package/fesm2022/ng-primitives-interactions.mjs.map +1 -1
- package/fesm2022/ng-primitives-internal.mjs +39 -35
- package/fesm2022/ng-primitives-internal.mjs.map +1 -1
- package/fesm2022/ng-primitives-listbox.mjs +34 -48
- package/fesm2022/ng-primitives-listbox.mjs.map +1 -1
- package/fesm2022/ng-primitives-menu.mjs +85 -151
- package/fesm2022/ng-primitives-menu.mjs.map +1 -1
- package/fesm2022/ng-primitives-meter.mjs +25 -36
- package/fesm2022/ng-primitives-meter.mjs.map +1 -1
- package/fesm2022/ng-primitives-navigation-menu.mjs +60 -108
- package/fesm2022/ng-primitives-navigation-menu.mjs.map +1 -1
- package/fesm2022/ng-primitives-number-field.mjs +35 -59
- package/fesm2022/ng-primitives-number-field.mjs.map +1 -1
- package/fesm2022/ng-primitives-pagination.mjs +270 -297
- package/fesm2022/ng-primitives-pagination.mjs.map +1 -1
- package/fesm2022/ng-primitives-popover.mjs +209 -223
- package/fesm2022/ng-primitives-popover.mjs.map +1 -1
- package/fesm2022/ng-primitives-portal.mjs +88 -59
- package/fesm2022/ng-primitives-portal.mjs.map +1 -1
- package/fesm2022/ng-primitives-progress.mjs +30 -41
- package/fesm2022/ng-primitives-progress.mjs.map +1 -1
- package/fesm2022/ng-primitives-radio.mjs +20 -30
- package/fesm2022/ng-primitives-radio.mjs.map +1 -1
- package/fesm2022/ng-primitives-resize.mjs +3 -3
- package/fesm2022/ng-primitives-resize.mjs.map +1 -1
- package/fesm2022/ng-primitives-roving-focus.mjs +20 -34
- package/fesm2022/ng-primitives-roving-focus.mjs.map +1 -1
- package/fesm2022/ng-primitives-search.mjs +9 -9
- package/fesm2022/ng-primitives-search.mjs.map +1 -1
- package/fesm2022/ng-primitives-select.mjs +720 -620
- package/fesm2022/ng-primitives-select.mjs.map +1 -1
- package/fesm2022/ng-primitives-separator.mjs +4 -6
- package/fesm2022/ng-primitives-separator.mjs.map +1 -1
- package/fesm2022/ng-primitives-slider.mjs +63 -100
- package/fesm2022/ng-primitives-slider.mjs.map +1 -1
- package/fesm2022/ng-primitives-state.mjs +3 -3
- package/fesm2022/ng-primitives-state.mjs.map +1 -1
- package/fesm2022/ng-primitives-switch.mjs +15 -21
- package/fesm2022/ng-primitives-switch.mjs.map +1 -1
- package/fesm2022/ng-primitives-tabs.mjs +31 -41
- package/fesm2022/ng-primitives-tabs.mjs.map +1 -1
- package/fesm2022/ng-primitives-textarea.mjs +5 -7
- package/fesm2022/ng-primitives-textarea.mjs.map +1 -1
- package/fesm2022/ng-primitives-toast.mjs +30 -23
- package/fesm2022/ng-primitives-toast.mjs.map +1 -1
- package/fesm2022/ng-primitives-toggle-group.mjs +20 -36
- package/fesm2022/ng-primitives-toggle-group.mjs.map +1 -1
- package/fesm2022/ng-primitives-toggle.mjs +10 -19
- package/fesm2022/ng-primitives-toggle.mjs.map +1 -1
- package/fesm2022/ng-primitives-toolbar.mjs +4 -6
- package/fesm2022/ng-primitives-toolbar.mjs.map +1 -1
- package/fesm2022/ng-primitives-tooltip.mjs +401 -402
- package/fesm2022/ng-primitives-tooltip.mjs.map +1 -1
- package/fesm2022/ng-primitives-utils.mjs +5 -4
- package/fesm2022/ng-primitives-utils.mjs.map +1 -1
- package/package.json +56 -55
- package/schematics/ng-generate/templates/select/select.__fileSuffix@dasherize__.ts.template +48 -48
- package/{a11y/index.d.ts → types/ng-primitives-a11y.d.ts} +18 -24
- package/{accordion/index.d.ts → types/ng-primitives-accordion.d.ts} +85 -98
- package/{autofill/index.d.ts → types/ng-primitives-autofill.d.ts} +3 -10
- package/{avatar/index.d.ts → types/ng-primitives-avatar.d.ts} +7 -30
- package/{breadcrumbs/index.d.ts → types/ng-primitives-breadcrumbs.d.ts} +15 -70
- package/{button/index.d.ts → types/ng-primitives-button.d.ts} +23 -29
- package/{checkbox/index.d.ts → types/ng-primitives-checkbox.d.ts} +68 -74
- package/{combobox/index.d.ts → types/ng-primitives-combobox.d.ts} +35 -35
- package/{context-menu/index.d.ts → types/ng-primitives-context-menu.d.ts} +2 -1
- package/{date-picker/index.d.ts → types/ng-primitives-date-picker.d.ts} +2 -2
- package/{dialog/index.d.ts → types/ng-primitives-dialog.d.ts} +7 -2
- package/{file-upload/index.d.ts → types/ng-primitives-file-upload.d.ts} +5 -20
- package/{focus-trap/index.d.ts → types/ng-primitives-focus-trap.d.ts} +3 -10
- package/{form-field/index.d.ts → types/ng-primitives-form-field.d.ts} +9 -40
- package/{input/index.d.ts → types/ng-primitives-input.d.ts} +3 -10
- package/{menu/index.d.ts → types/ng-primitives-menu.d.ts} +17 -63
- package/{navigation-menu/index.d.ts → types/ng-primitives-navigation-menu.d.ts} +15 -70
- package/{number-field/index.d.ts → types/ng-primitives-number-field.d.ts} +80 -110
- package/types/ng-primitives-pagination.d.ts +502 -0
- package/{popover/index.d.ts → types/ng-primitives-popover.d.ts} +244 -57
- package/{portal/index.d.ts → types/ng-primitives-portal.d.ts} +22 -13
- package/{progress/index.d.ts → types/ng-primitives-progress.d.ts} +3 -10
- package/{roving-focus/index.d.ts → types/ng-primitives-roving-focus.d.ts} +65 -79
- package/types/ng-primitives-select.d.ts +687 -0
- package/{separator/index.d.ts → types/ng-primitives-separator.d.ts} +3 -10
- package/{slider/index.d.ts → types/ng-primitives-slider.d.ts} +76 -138
- package/{state/index.d.ts → types/ng-primitives-state.d.ts} +26 -21
- package/{switch/index.d.ts → types/ng-primitives-switch.d.ts} +50 -64
- package/{tabs/index.d.ts → types/ng-primitives-tabs.d.ts} +9 -40
- package/{textarea/index.d.ts → types/ng-primitives-textarea.d.ts} +3 -10
- package/{toast/index.d.ts → types/ng-primitives-toast.d.ts} +13 -1
- package/{toggle-group/index.d.ts → types/ng-primitives-toggle-group.d.ts} +75 -89
- package/{toggle/index.d.ts → types/ng-primitives-toggle.d.ts} +50 -56
- package/{toolbar/index.d.ts → types/ng-primitives-toolbar.d.ts} +3 -10
- package/types/ng-primitives-tooltip.d.ts +691 -0
- package/pagination/index.d.ts +0 -211
- package/select/index.d.ts +0 -396
- package/tooltip/index.d.ts +0 -384
- /package/{ai/index.d.ts → types/ng-primitives-ai.d.ts} +0 -0
- /package/{common/index.d.ts → types/ng-primitives-common.d.ts} +0 -0
- /package/{date-time-luxon/index.d.ts → types/ng-primitives-date-time-luxon.d.ts} +0 -0
- /package/{date-time/index.d.ts → types/ng-primitives-date-time.d.ts} +0 -0
- /package/{input-otp/index.d.ts → types/ng-primitives-input-otp.d.ts} +0 -0
- /package/{interactions/index.d.ts → types/ng-primitives-interactions.d.ts} +0 -0
- /package/{internal/index.d.ts → types/ng-primitives-internal.d.ts} +0 -0
- /package/{listbox/index.d.ts → types/ng-primitives-listbox.d.ts} +0 -0
- /package/{meter/index.d.ts → types/ng-primitives-meter.d.ts} +0 -0
- /package/{radio/index.d.ts → types/ng-primitives-radio.d.ts} +0 -0
- /package/{resize/index.d.ts → types/ng-primitives-resize.d.ts} +0 -0
- /package/{search/index.d.ts → types/ng-primitives-search.d.ts} +0 -0
- /package/{utils/index.d.ts → types/ng-primitives-utils.d.ts} +0 -0
- /package/{index.d.ts → types/ng-primitives.d.ts} +0 -0
|
@@ -1,29 +1,34 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, booleanAttribute, Directive,
|
|
2
|
+
import { signal, input, booleanAttribute, Directive, computed, output, inject, TemplateRef, ViewContainerRef, Injector, InjectionToken } from '@angular/core';
|
|
3
|
+
import { uniqueId } from 'ng-primitives/utils';
|
|
3
4
|
import { ngpFormControl } from 'ng-primitives/form-field';
|
|
4
5
|
import { ngpInteractions } from 'ng-primitives/interactions';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { createOverlay, coerceFlip, coerceOffset } from 'ng-primitives/portal';
|
|
6
|
+
import { injectElementRef, domSort, observeResize, scrollIntoViewIfNeeded } from 'ng-primitives/internal';
|
|
7
|
+
import { createPrimitive, controlled, attrBinding, deprecatedSetter, emitter, dataBinding, listener, styleBinding, onDestroy } from 'ng-primitives/state';
|
|
8
|
+
import { provideControlContainerIsolation, createOverlay, coerceFlip, coerceOffset } from 'ng-primitives/portal';
|
|
9
9
|
import { activeDescendantManager } from 'ng-primitives/a11y';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
const [NgpNativeSelectStateToken, ngpNativeSelect, injectNativeSelectState, provideNativeSelectState,] = createPrimitive('NgpNativeSelect', ({ disabled: _disabled = signal(false), id = signal(uniqueId('ngp-native-select')), }) => {
|
|
12
|
+
const element = injectElementRef();
|
|
13
|
+
const disabled = controlled(_disabled);
|
|
14
|
+
// Setup interactions
|
|
15
|
+
ngpInteractions({
|
|
16
|
+
hover: true,
|
|
17
|
+
press: true,
|
|
18
|
+
focus: true,
|
|
19
|
+
focusVisible: true,
|
|
20
|
+
disabled: disabled,
|
|
21
|
+
});
|
|
22
|
+
ngpFormControl({ id: id, disabled: disabled });
|
|
23
|
+
attrBinding(element, 'disabled', disabled);
|
|
24
|
+
function setDisabled(value) {
|
|
25
|
+
disabled.set(value);
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
disabled: deprecatedSetter(disabled, 'setDisabled'),
|
|
29
|
+
setDisabled,
|
|
30
|
+
};
|
|
31
|
+
});
|
|
27
32
|
|
|
28
33
|
/**
|
|
29
34
|
* Apply the `ngpNativeSelect` directive to a select element that you want to enhance.
|
|
@@ -33,543 +38,149 @@ class NgpNativeSelect {
|
|
|
33
38
|
/**
|
|
34
39
|
* The id of the select. If not provided, a unique id will be generated.
|
|
35
40
|
*/
|
|
36
|
-
this.id = input(uniqueId('ngp-native-select'), ...(ngDevMode ? [{ debugName: "id" }] : []));
|
|
41
|
+
this.id = input(uniqueId('ngp-native-select'), ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
37
42
|
/**
|
|
38
43
|
* Whether the select is disabled.
|
|
39
44
|
*/
|
|
40
|
-
this.disabled = input(false, ...(ngDevMode ?
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* The select state.
|
|
47
|
-
*/
|
|
48
|
-
this.state = selectNativeSelectState(this);
|
|
49
|
-
ngpInteractions({
|
|
50
|
-
hover: true,
|
|
51
|
-
press: true,
|
|
52
|
-
focus: true,
|
|
53
|
-
focusVisible: true,
|
|
54
|
-
disabled: this.state.disabled,
|
|
45
|
+
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), alias: 'ngpNativeSelectDisabled',
|
|
46
|
+
transform: booleanAttribute });
|
|
47
|
+
ngpNativeSelect({
|
|
48
|
+
id: this.id,
|
|
49
|
+
disabled: this.disabled,
|
|
55
50
|
});
|
|
56
|
-
ngpFormControl({ id: this.state.id, disabled: this.state.disabled });
|
|
57
51
|
}
|
|
58
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
59
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "
|
|
52
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NgpNativeSelect, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
53
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.14", type: NgpNativeSelect, isStandalone: true, selector: "select[ngpNativeSelect]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpNativeSelectDisabled", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideNativeSelectState()], exportAs: ["ngpNativeSelect"], ngImport: i0 }); }
|
|
60
54
|
}
|
|
61
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
55
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NgpNativeSelect, decorators: [{
|
|
62
56
|
type: Directive,
|
|
63
57
|
args: [{
|
|
64
58
|
selector: 'select[ngpNativeSelect]',
|
|
65
59
|
exportAs: 'ngpNativeSelect',
|
|
66
60
|
providers: [provideNativeSelectState()],
|
|
67
|
-
host: {
|
|
68
|
-
'[attr.disabled]': 'state.disabled() || null',
|
|
69
|
-
},
|
|
70
61
|
}]
|
|
71
62
|
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpNativeSelectDisabled", required: false }] }] } });
|
|
72
63
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
host: {
|
|
114
|
-
role: 'listbox',
|
|
115
|
-
'[id]': 'id()',
|
|
116
|
-
'[style.left.px]': 'state().overlay()?.position()?.x',
|
|
117
|
-
'[style.top.px]': 'state().overlay()?.position()?.y',
|
|
118
|
-
'[style.--ngp-select-transform-origin]': 'state().overlay()?.transformOrigin()',
|
|
119
|
-
'[style.--ngp-select-available-width.px]': 'state().overlay()?.availableWidth()',
|
|
120
|
-
'[style.--ngp-select-available-height.px]': 'state().overlay()?.availableHeight()',
|
|
121
|
-
'[style.--ngp-select-width.px]': 'selectDimensions().width',
|
|
122
|
-
},
|
|
123
|
-
}]
|
|
124
|
-
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
|
|
125
|
-
|
|
126
|
-
class NgpSelectOption {
|
|
127
|
-
constructor() {
|
|
128
|
-
/** Access the select state. */
|
|
129
|
-
this.state = injectSelectState();
|
|
130
|
-
/**
|
|
131
|
-
* The element reference of the option.
|
|
132
|
-
* @internal
|
|
133
|
-
*/
|
|
134
|
-
this.elementRef = injectElementRef();
|
|
135
|
-
/** The id of the option. */
|
|
136
|
-
this.id = input(uniqueId('ngp-select-option'), ...(ngDevMode ? [{ debugName: "id" }] : []));
|
|
137
|
-
/** @required The value of the option. */
|
|
138
|
-
this.value = input(undefined, ...(ngDevMode ? [{ debugName: "value", alias: 'ngpSelectOptionValue' }] : [{
|
|
139
|
-
alias: 'ngpSelectOptionValue',
|
|
140
|
-
}]));
|
|
141
|
-
/** The disabled state of the option. */
|
|
142
|
-
this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", alias: 'ngpSelectOptionDisabled',
|
|
143
|
-
transform: booleanAttribute }] : [{
|
|
144
|
-
alias: 'ngpSelectOptionDisabled',
|
|
145
|
-
transform: booleanAttribute,
|
|
146
|
-
}]));
|
|
147
|
-
/** The index of the option in the list. */
|
|
148
|
-
this.index = input(undefined, ...(ngDevMode ? [{ debugName: "index", alias: 'ngpSelectOptionIndex' }] : [{
|
|
149
|
-
alias: 'ngpSelectOptionIndex',
|
|
150
|
-
}]));
|
|
151
|
-
/**
|
|
152
|
-
* Event emitted when the option is activated via click or keyboard.
|
|
153
|
-
* This is useful for options without values that need custom behavior.
|
|
154
|
-
*/
|
|
155
|
-
this.activated = output({
|
|
156
|
-
alias: 'ngpSelectOptionActivated',
|
|
157
|
-
});
|
|
158
|
-
/**
|
|
159
|
-
* Whether this option is the active descendant.
|
|
160
|
-
* @internal
|
|
161
|
-
*/
|
|
162
|
-
this.active = computed(() => {
|
|
163
|
-
// if the option has an index, use that to determine if it's active because this
|
|
164
|
-
// is required for virtual scrolling scenarios
|
|
165
|
-
const index = this.index();
|
|
166
|
-
if (index !== undefined) {
|
|
167
|
-
return this.state().activeDescendantManager.index() === index;
|
|
168
|
-
}
|
|
169
|
-
return this.state().activeDescendantManager.id() === this.id();
|
|
170
|
-
}, ...(ngDevMode ? [{ debugName: "active" }] : []));
|
|
171
|
-
/** Whether this option is selected. */
|
|
172
|
-
this.selected = computed(() => {
|
|
173
|
-
const value = this.value();
|
|
174
|
-
const stateValue = this.state().value();
|
|
175
|
-
// Only treat `undefined` as "no value" (allow '', 0, false).
|
|
176
|
-
if (value === undefined) {
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
if (this.state().multiple()) {
|
|
180
|
-
return (Array.isArray(stateValue) && stateValue.some(v => this.state().compareWith()(value, v)));
|
|
181
|
-
}
|
|
182
|
-
// Only treat `undefined` as "no selection" (allow '', 0, false).
|
|
183
|
-
if (stateValue === undefined) {
|
|
184
|
-
return false;
|
|
64
|
+
const [NgpSelectStateToken, ngpSelect, _injectSelectState, provideSelectState] = createPrimitive('NgpSelect', ({ id = signal(uniqueId('ngp-select')), value: _value = signal(undefined), multiple = signal(false), disabled: _disabled = signal(false), compareWith = signal(Object.is), placement = signal('bottom'), container = signal('body'), flip = signal(true), offset = signal(0), scrollToOption = signal(undefined), allOptions = signal(undefined), onValueChange, onOpenChange, }) => {
|
|
65
|
+
const elementRef = injectElementRef();
|
|
66
|
+
const value = controlled(_value);
|
|
67
|
+
const disabled = controlled(_disabled, false);
|
|
68
|
+
const valueChangeEmitter = emitter();
|
|
69
|
+
function setValue(newValue, options) {
|
|
70
|
+
value.set(newValue);
|
|
71
|
+
if (options?.emit !== false) {
|
|
72
|
+
onValueChange?.(newValue);
|
|
73
|
+
valueChangeEmitter.emit(newValue);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function setDisabled(isDisabled) {
|
|
77
|
+
disabled.set(isDisabled);
|
|
78
|
+
}
|
|
79
|
+
ngpInteractions({
|
|
80
|
+
focus: true,
|
|
81
|
+
focusWithin: true,
|
|
82
|
+
hover: true,
|
|
83
|
+
press: true,
|
|
84
|
+
disabled,
|
|
85
|
+
});
|
|
86
|
+
ngpFormControl({ id, disabled });
|
|
87
|
+
const portal = signal(undefined, ...(ngDevMode ? [{ debugName: "portal" }] : /* istanbul ignore next */ []));
|
|
88
|
+
const dropdown = signal(undefined, ...(ngDevMode ? [{ debugName: "dropdown" }] : /* istanbul ignore next */ []));
|
|
89
|
+
const options = signal([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
90
|
+
const overlay = computed(() => portal()?.overlay(), ...(ngDevMode ? [{ debugName: "overlay" }] : /* istanbul ignore next */ []));
|
|
91
|
+
const open = computed(() => overlay()?.isOpen() ?? false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
92
|
+
const sortedOptions = computed(() => domSort(options(), option => option.elementRef.nativeElement, option => option.index?.()), ...(ngDevMode ? [{ debugName: "sortedOptions" }] : /* istanbul ignore next */ []));
|
|
93
|
+
const activeDescendantManagerInstance = activeDescendantManager({
|
|
94
|
+
// we must wrap the signal in a computed to ensure it is not used before it is defined
|
|
95
|
+
disabled: computed(() => disabled()),
|
|
96
|
+
wrap: signal(true),
|
|
97
|
+
count: computed(() => allOptions()?.length ?? options().length),
|
|
98
|
+
getItemId: index => getOptionAtIndex(index)?.id(),
|
|
99
|
+
isItemDisabled: index => getOptionAtIndex(index)?.disabled() ?? false,
|
|
100
|
+
scrollIntoView: index => {
|
|
101
|
+
const isPositioned = portal()?.overlay()?.isPositioned() ?? false;
|
|
102
|
+
if (!isPositioned || index === -1) {
|
|
103
|
+
return;
|
|
185
104
|
}
|
|
186
|
-
|
|
187
|
-
}, ...(ngDevMode ? [{ debugName: "selected" }] : []));
|
|
188
|
-
this.state().registerOption(this);
|
|
189
|
-
ngpInteractions({
|
|
190
|
-
hover: true,
|
|
191
|
-
press: true,
|
|
192
|
-
disabled: this.disabled,
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
ngOnDestroy() {
|
|
196
|
-
this.state().unregisterOption(this);
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Select the option.
|
|
200
|
-
* @internal
|
|
201
|
-
*/
|
|
202
|
-
select() {
|
|
203
|
-
if (this.disabled()) {
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
this.activated.emit();
|
|
207
|
-
this.state().toggleOption(this.id());
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Scroll the option into view.
|
|
211
|
-
* @internal
|
|
212
|
-
*/
|
|
213
|
-
scrollIntoView() {
|
|
214
|
-
scrollIntoViewIfNeeded(this.elementRef.nativeElement);
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Whenever the pointer enters the option, activate it.
|
|
218
|
-
* @internal
|
|
219
|
-
*/
|
|
220
|
-
onPointerEnter() {
|
|
221
|
-
// if we have a known index, use that to activate the option because this
|
|
222
|
-
// is required for virtual scrolling scenarios
|
|
223
|
-
const index = this.index();
|
|
224
|
-
if (index !== undefined) {
|
|
225
|
-
this.state().activeDescendantManager.activateByIndex(index, {
|
|
226
|
-
scroll: false,
|
|
227
|
-
origin: 'pointer',
|
|
228
|
-
});
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
// otherwise, activate by id
|
|
232
|
-
this.state().activeDescendantManager.activateById(this.id(), {
|
|
233
|
-
scroll: false,
|
|
234
|
-
origin: 'pointer',
|
|
235
|
-
});
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Whenever the pointer leaves the option, deactivate it.
|
|
239
|
-
* @internal
|
|
240
|
-
*/
|
|
241
|
-
onPointerLeave() {
|
|
242
|
-
if (this.state().activeDescendantManager.id() === this.id()) {
|
|
243
|
-
this.state().activeDescendantManager.reset({ origin: 'pointer' });
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpSelectOption, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
247
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.3.9", type: NgpSelectOption, isStandalone: true, selector: "[ngpSelectOption]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "ngpSelectOptionValue", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpSelectOptionDisabled", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "ngpSelectOptionIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activated: "ngpSelectOptionActivated" }, 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: ["ngpSelectOption"], ngImport: i0 }); }
|
|
248
|
-
}
|
|
249
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpSelectOption, decorators: [{
|
|
250
|
-
type: Directive,
|
|
251
|
-
args: [{
|
|
252
|
-
selector: '[ngpSelectOption]',
|
|
253
|
-
exportAs: 'ngpSelectOption',
|
|
254
|
-
host: {
|
|
255
|
-
role: 'option',
|
|
256
|
-
'[id]': 'id()',
|
|
257
|
-
'[attr.tabindex]': '-1',
|
|
258
|
-
'[attr.aria-selected]': 'selected() ? "true" : undefined',
|
|
259
|
-
'[attr.data-selected]': 'selected() ? "" : undefined',
|
|
260
|
-
'[attr.data-active]': 'active() ? "" : undefined',
|
|
261
|
-
'[attr.data-disabled]': 'disabled() ? "" : undefined',
|
|
262
|
-
'(click)': 'select()',
|
|
263
|
-
},
|
|
264
|
-
}]
|
|
265
|
-
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectOptionValue", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectOptionDisabled", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectOptionIndex", required: false }] }], activated: [{ type: i0.Output, args: ["ngpSelectOptionActivated"] }], onPointerEnter: [{
|
|
266
|
-
type: HostListener,
|
|
267
|
-
args: ['pointerenter']
|
|
268
|
-
}], onPointerLeave: [{
|
|
269
|
-
type: HostListener,
|
|
270
|
-
args: ['pointerleave']
|
|
271
|
-
}] } });
|
|
272
|
-
|
|
273
|
-
class NgpSelectPortal {
|
|
274
|
-
constructor() {
|
|
275
|
-
/** Access the select state. */
|
|
276
|
-
this.state = injectSelectState();
|
|
277
|
-
/** Access the view container reference. */
|
|
278
|
-
this.viewContainerRef = inject(ViewContainerRef);
|
|
279
|
-
/** Access the template reference. */
|
|
280
|
-
this.templateRef = inject(TemplateRef);
|
|
281
|
-
/** Access the injector. */
|
|
282
|
-
this.injector = inject(Injector);
|
|
283
|
-
/**
|
|
284
|
-
* The overlay that manages the popover
|
|
285
|
-
* @internal
|
|
286
|
-
*/
|
|
287
|
-
this.overlay = signal(null, ...(ngDevMode ? [{ debugName: "overlay" }] : []));
|
|
288
|
-
this.state().registerPortal(this);
|
|
289
|
-
}
|
|
290
|
-
/** Cleanup the portal. */
|
|
291
|
-
ngOnDestroy() {
|
|
292
|
-
this.overlay()?.destroy();
|
|
293
|
-
}
|
|
294
|
-
/**
|
|
295
|
-
* Attach the portal.
|
|
296
|
-
* @internal
|
|
297
|
-
*/
|
|
298
|
-
show() {
|
|
299
|
-
// Create the overlay if it doesn't exist yet
|
|
300
|
-
if (!this.overlay()) {
|
|
301
|
-
this.createOverlay();
|
|
302
|
-
}
|
|
303
|
-
// Show the overlay
|
|
304
|
-
return this.overlay().show();
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Detach the portal.
|
|
308
|
-
* @internal
|
|
309
|
-
*/
|
|
310
|
-
async detach() {
|
|
311
|
-
this.overlay()?.hide();
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Create the overlay that will contain the dropdown
|
|
315
|
-
*/
|
|
316
|
-
createOverlay() {
|
|
317
|
-
// Create config for the overlay
|
|
318
|
-
const config = {
|
|
319
|
-
content: this.templateRef,
|
|
320
|
-
viewContainerRef: this.viewContainerRef,
|
|
321
|
-
triggerElement: this.state().elementRef.nativeElement,
|
|
322
|
-
injector: this.injector,
|
|
323
|
-
placement: this.state().placement,
|
|
324
|
-
offset: this.state().offset(),
|
|
325
|
-
flip: this.state().flip(),
|
|
326
|
-
closeOnOutsideClick: true,
|
|
327
|
-
closeOnEscape: true,
|
|
328
|
-
restoreFocus: false,
|
|
329
|
-
scrollBehaviour: 'reposition',
|
|
330
|
-
container: this.state().container(),
|
|
331
|
-
onClose: () => this.state().onOverlayClosed(),
|
|
332
|
-
};
|
|
333
|
-
this.overlay.set(createOverlay(config));
|
|
334
|
-
}
|
|
335
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpSelectPortal, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
336
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.9", type: NgpSelectPortal, isStandalone: true, selector: "[ngpSelectPortal]", exportAs: ["ngpSelectPortal"], ngImport: i0 }); }
|
|
337
|
-
}
|
|
338
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgpSelectPortal, decorators: [{
|
|
339
|
-
type: Directive,
|
|
340
|
-
args: [{
|
|
341
|
-
selector: '[ngpSelectPortal]',
|
|
342
|
-
exportAs: 'ngpSelectPortal',
|
|
343
|
-
}]
|
|
344
|
-
}], ctorParameters: () => [] });
|
|
345
|
-
|
|
346
|
-
const defaultSelectConfig = {
|
|
347
|
-
placement: 'bottom',
|
|
348
|
-
container: 'body',
|
|
349
|
-
flip: true,
|
|
350
|
-
offset: 0,
|
|
351
|
-
};
|
|
352
|
-
const NgpSelectConfigToken = new InjectionToken('NgpSelectConfigToken');
|
|
353
|
-
/**
|
|
354
|
-
* Provide the default Select configuration
|
|
355
|
-
* @param config The Select configuration
|
|
356
|
-
* @returns The provider
|
|
357
|
-
*/
|
|
358
|
-
function provideSelectConfig(config) {
|
|
359
|
-
return [
|
|
360
|
-
{
|
|
361
|
-
provide: NgpSelectConfigToken,
|
|
362
|
-
useValue: { ...defaultSelectConfig, ...config },
|
|
105
|
+
scrollTo(index);
|
|
363
106
|
},
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
this.elementRef = injectElementRef();
|
|
380
|
-
/** Access the injector. */
|
|
381
|
-
this.injector = inject(Injector);
|
|
382
|
-
/** The unique id of the select. */
|
|
383
|
-
this.id = input(uniqueId('ngp-select'), ...(ngDevMode ? [{ debugName: "id" }] : []));
|
|
384
|
-
/** The value of the select. */
|
|
385
|
-
this.value = input(undefined, ...(ngDevMode ? [{ debugName: "value", alias: 'ngpSelectValue' }] : [{
|
|
386
|
-
alias: 'ngpSelectValue',
|
|
387
|
-
}]));
|
|
388
|
-
/** Event emitted when the value changes. */
|
|
389
|
-
this.valueChange = output({
|
|
390
|
-
alias: 'ngpSelectValueChange',
|
|
391
|
-
});
|
|
392
|
-
/** Whether the select is multiple selection. */
|
|
393
|
-
this.multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple", alias: 'ngpSelectMultiple',
|
|
394
|
-
transform: booleanAttribute }] : [{
|
|
395
|
-
alias: 'ngpSelectMultiple',
|
|
396
|
-
transform: booleanAttribute,
|
|
397
|
-
}]));
|
|
398
|
-
/** Whether the select is disabled. */
|
|
399
|
-
this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", alias: 'ngpSelectDisabled',
|
|
400
|
-
transform: booleanAttribute }] : [{
|
|
401
|
-
alias: 'ngpSelectDisabled',
|
|
402
|
-
transform: booleanAttribute,
|
|
403
|
-
}]));
|
|
404
|
-
/** Emit when the dropdown open state changes. */
|
|
405
|
-
this.openChange = output({
|
|
406
|
-
alias: 'ngpSelectOpenChange',
|
|
407
|
-
});
|
|
408
|
-
/** The comparator function used to compare options. */
|
|
409
|
-
this.compareWith = input(Object.is, ...(ngDevMode ? [{ debugName: "compareWith", alias: 'ngpSelectCompareWith' }] : [{
|
|
410
|
-
alias: 'ngpSelectCompareWith',
|
|
411
|
-
}]));
|
|
412
|
-
/** The position of the dropdown. */
|
|
413
|
-
this.placement = input(this.config.placement, ...(ngDevMode ? [{ debugName: "placement", alias: 'ngpSelectDropdownPlacement' }] : [{
|
|
414
|
-
alias: 'ngpSelectDropdownPlacement',
|
|
415
|
-
}]));
|
|
416
|
-
/** The container for the dropdown. */
|
|
417
|
-
this.container = input(this.config.container, ...(ngDevMode ? [{ debugName: "container", alias: 'ngpSelectDropdownContainer' }] : [{
|
|
418
|
-
alias: 'ngpSelectDropdownContainer',
|
|
419
|
-
}]));
|
|
420
|
-
/** Whether the dropdown should flip when there is not enough space. Can be a boolean to enable/disable, or an object with padding and fallbackPlacements options. */
|
|
421
|
-
this.flip = input(this.config.flip, ...(ngDevMode ? [{ debugName: "flip", alias: 'ngpSelectDropdownFlip',
|
|
422
|
-
transform: coerceFlip }] : [{
|
|
423
|
-
alias: 'ngpSelectDropdownFlip',
|
|
424
|
-
transform: coerceFlip,
|
|
425
|
-
}]));
|
|
426
|
-
/**
|
|
427
|
-
* Define the offset of the select dropdown relative to the trigger.
|
|
428
|
-
* Can be a number (applies to mainAxis) or an object with mainAxis, crossAxis, and alignmentAxis.
|
|
429
|
-
* @default 0
|
|
430
|
-
*/
|
|
431
|
-
this.offset = input(this.config.offset, ...(ngDevMode ? [{ debugName: "offset", alias: 'ngpSelectDropdownOffset',
|
|
432
|
-
transform: coerceOffset }] : [{
|
|
433
|
-
alias: 'ngpSelectDropdownOffset',
|
|
434
|
-
transform: coerceOffset,
|
|
435
|
-
}]));
|
|
436
|
-
/**
|
|
437
|
-
* A function that will scroll the active option into view. This can be overridden
|
|
438
|
-
* for cases such as virtual scrolling where we cannot scroll the option directly because
|
|
439
|
-
* it may not be rendered.
|
|
440
|
-
*/
|
|
441
|
-
this.scrollToOption = input(undefined, ...(ngDevMode ? [{ debugName: "scrollToOption", alias: 'ngpSelectScrollToOption' }] : [{
|
|
442
|
-
alias: 'ngpSelectScrollToOption',
|
|
443
|
-
}]));
|
|
444
|
-
/**
|
|
445
|
-
* Provide all the option values to the select. This is useful for virtual scrolling scenarios
|
|
446
|
-
* where not all options are rendered in the DOM. This is not an alternative to adding the options
|
|
447
|
-
* in the DOM, it is only to provide the select with the full list of options. This list should match
|
|
448
|
-
* the order of the options as they would appear in the DOM.
|
|
449
|
-
*/
|
|
450
|
-
this.allOptions = input(undefined, ...(ngDevMode ? [{ debugName: "allOptions", alias: 'ngpSelectOptions' }] : [{ alias: 'ngpSelectOptions' }]));
|
|
451
|
-
/**
|
|
452
|
-
* Store the select portal.
|
|
453
|
-
* @internal
|
|
454
|
-
*/
|
|
455
|
-
this.portal = signal(undefined, ...(ngDevMode ? [{ debugName: "portal" }] : []));
|
|
456
|
-
/**
|
|
457
|
-
* Store the select dropdown.
|
|
458
|
-
* @internal
|
|
459
|
-
*/
|
|
460
|
-
this.dropdown = signal(undefined, ...(ngDevMode ? [{ debugName: "dropdown" }] : []));
|
|
461
|
-
/**
|
|
462
|
-
* Store the select options.
|
|
463
|
-
* @internal
|
|
464
|
-
*/
|
|
465
|
-
this.options = signal([], ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
466
|
-
/**
|
|
467
|
-
* Access the overlay
|
|
468
|
-
* @internal
|
|
469
|
-
*/
|
|
470
|
-
this.overlay = computed(() => this.portal()?.overlay(), ...(ngDevMode ? [{ debugName: "overlay" }] : []));
|
|
471
|
-
/**
|
|
472
|
-
* The open state of the select.
|
|
473
|
-
* @internal
|
|
474
|
-
*/
|
|
475
|
-
this.open = computed(() => this.overlay()?.isOpen() ?? false, ...(ngDevMode ? [{ debugName: "open" }] : []));
|
|
476
|
-
/**
|
|
477
|
-
* The options sorted by their index or DOM position.
|
|
478
|
-
* @internal
|
|
479
|
-
*/
|
|
480
|
-
this.sortedOptions = computed(() => domSort(this.options(), option => option.elementRef.nativeElement, option => option.index?.()), ...(ngDevMode ? [{ debugName: "sortedOptions" }] : []));
|
|
481
|
-
/**
|
|
482
|
-
* The active key descendant manager.
|
|
483
|
-
* @internal
|
|
484
|
-
*/
|
|
485
|
-
this.activeDescendantManager = activeDescendantManager({
|
|
486
|
-
// we must wrap the signal in a computed to ensure it is not used before it is defined
|
|
487
|
-
disabled: computed(() => this.state.disabled()),
|
|
488
|
-
wrap: signal(true),
|
|
489
|
-
count: computed(() => this.allOptions()?.length ?? this.options().length),
|
|
490
|
-
getItemId: index => this.getOptionAtIndex(index)?.id(),
|
|
491
|
-
isItemDisabled: index => this.getOptionAtIndex(index)?.disabled() ?? false,
|
|
492
|
-
scrollIntoView: index => {
|
|
493
|
-
const isPositioned = this.portal()?.overlay()?.isPositioned() ?? false;
|
|
494
|
-
if (!isPositioned || index === -1) {
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
this.scrollTo(index);
|
|
498
|
-
},
|
|
499
|
-
});
|
|
500
|
-
/** The state of the select. */
|
|
501
|
-
this.state = selectState(this);
|
|
502
|
-
ngpInteractions({
|
|
503
|
-
focus: true,
|
|
504
|
-
focusWithin: true,
|
|
505
|
-
hover: true,
|
|
506
|
-
press: true,
|
|
507
|
-
disabled: this.state.disabled,
|
|
508
|
-
});
|
|
509
|
-
ngpFormControl({ id: this.state.id, disabled: this.state.disabled });
|
|
510
|
-
}
|
|
107
|
+
});
|
|
108
|
+
// Host bindings
|
|
109
|
+
attrBinding(elementRef, 'role', 'combobox');
|
|
110
|
+
attrBinding(elementRef, 'id', id);
|
|
111
|
+
attrBinding(elementRef, 'aria-expanded', open);
|
|
112
|
+
attrBinding(elementRef, 'aria-controls', () => (open() ? dropdown()?.id() : undefined));
|
|
113
|
+
attrBinding(elementRef, 'aria-activedescendant', () => open() ? activeDescendantManagerInstance.id() : undefined);
|
|
114
|
+
attrBinding(elementRef, 'tabindex', () => (disabled() ? -1 : 0));
|
|
115
|
+
dataBinding(elementRef, 'data-open', () => (open() ? '' : null));
|
|
116
|
+
dataBinding(elementRef, 'data-disabled', () => (disabled() ? '' : null));
|
|
117
|
+
dataBinding(elementRef, 'data-multiple', () => (multiple() ? '' : null));
|
|
118
|
+
// Event listeners
|
|
119
|
+
listener(elementRef, 'click', () => void toggleDropdown());
|
|
120
|
+
listener(elementRef, 'keydown', handleKeydown);
|
|
121
|
+
listener(elementRef, 'blur', onBlur);
|
|
511
122
|
/**
|
|
512
123
|
* Open the dropdown.
|
|
513
124
|
* @internal
|
|
514
125
|
*/
|
|
515
|
-
async openDropdown() {
|
|
516
|
-
if (
|
|
126
|
+
async function openDropdown() {
|
|
127
|
+
if (disabled() || open()) {
|
|
517
128
|
return;
|
|
518
129
|
}
|
|
519
|
-
|
|
520
|
-
await
|
|
130
|
+
onOpenChange?.(true);
|
|
131
|
+
await portal()?.show();
|
|
521
132
|
let selectedOptionIdx = -1;
|
|
522
133
|
// if we have been provided with allOptions, we need to find the selected option(s) from that list
|
|
523
|
-
if (
|
|
524
|
-
selectedOptionIdx =
|
|
525
|
-
.allOptions()
|
|
526
|
-
.findIndex(option => this.isOptionSelected(option));
|
|
134
|
+
if (allOptions()) {
|
|
135
|
+
selectedOptionIdx = allOptions().findIndex(option => isOptionSelected(option));
|
|
527
136
|
}
|
|
528
137
|
// if we don't have allOptions, find the selected option(s) from the registered options
|
|
529
138
|
if (selectedOptionIdx === -1) {
|
|
530
139
|
// if there is a selected option(s), set the active descendant to the first selected option
|
|
531
|
-
selectedOptionIdx =
|
|
140
|
+
selectedOptionIdx = sortedOptions().findIndex(option => isOptionSelected(option.value()));
|
|
532
141
|
}
|
|
533
142
|
// if after checking there is a selected option, set the active descendant to the first option
|
|
534
143
|
if (selectedOptionIdx !== -1) {
|
|
535
144
|
// scroll to and activate the selected option
|
|
536
|
-
|
|
537
|
-
|
|
145
|
+
scrollTo(selectedOptionIdx);
|
|
146
|
+
activeDescendantManagerInstance.activateByIndex(selectedOptionIdx);
|
|
538
147
|
return;
|
|
539
148
|
}
|
|
540
149
|
// activate the selected option or the first option
|
|
541
|
-
|
|
150
|
+
activeDescendantManagerInstance.first();
|
|
542
151
|
}
|
|
543
152
|
/**
|
|
544
153
|
* Close the dropdown.
|
|
545
154
|
* @internal
|
|
546
155
|
*/
|
|
547
|
-
closeDropdown() {
|
|
548
|
-
if (!
|
|
156
|
+
function closeDropdown() {
|
|
157
|
+
if (!open()) {
|
|
549
158
|
return;
|
|
550
159
|
}
|
|
551
|
-
|
|
160
|
+
portal()?.hide();
|
|
552
161
|
}
|
|
553
162
|
/**
|
|
554
|
-
*
|
|
555
|
-
* Emits
|
|
163
|
+
* Handle the overlay being closed (whether via imperative closeDropdown(),
|
|
164
|
+
* outside click, or Escape). Emits openChange(false) and resets the active
|
|
165
|
+
* descendant. Wired in from select-portal-state.ts via the overlay onClose
|
|
166
|
+
* config — this is the single source of truth for the close-side emit so
|
|
167
|
+
* external close paths (outside click, Escape) also fire openChange.
|
|
556
168
|
* @internal
|
|
557
169
|
*/
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
this.activeDescendantManager.reset();
|
|
170
|
+
function onOverlayClose() {
|
|
171
|
+
onOpenChange?.(false);
|
|
172
|
+
activeDescendantManagerInstance.reset();
|
|
562
173
|
}
|
|
563
174
|
/**
|
|
564
175
|
* Toggle the dropdown.
|
|
565
176
|
* @internal
|
|
566
177
|
*/
|
|
567
|
-
async toggleDropdown() {
|
|
568
|
-
if (
|
|
569
|
-
|
|
178
|
+
async function toggleDropdown() {
|
|
179
|
+
if (open()) {
|
|
180
|
+
closeDropdown();
|
|
570
181
|
}
|
|
571
182
|
else {
|
|
572
|
-
await
|
|
183
|
+
await openDropdown();
|
|
573
184
|
}
|
|
574
185
|
}
|
|
575
186
|
/**
|
|
@@ -577,14 +188,14 @@ class NgpSelect {
|
|
|
577
188
|
* @param index The index of the option to select.
|
|
578
189
|
* @internal
|
|
579
190
|
*/
|
|
580
|
-
selectOption(id) {
|
|
581
|
-
if (
|
|
191
|
+
function selectOption(id) {
|
|
192
|
+
if (disabled()) {
|
|
582
193
|
return;
|
|
583
194
|
}
|
|
584
|
-
const option =
|
|
195
|
+
const option = sortedOptions().find(opt => opt.id() === id);
|
|
585
196
|
if (!option) {
|
|
586
|
-
|
|
587
|
-
|
|
197
|
+
setValue(undefined, { emit: false });
|
|
198
|
+
closeDropdown();
|
|
588
199
|
return;
|
|
589
200
|
}
|
|
590
201
|
const optionValue = option.value();
|
|
@@ -592,21 +203,19 @@ class NgpSelect {
|
|
|
592
203
|
if (optionValue === undefined) {
|
|
593
204
|
return;
|
|
594
205
|
}
|
|
595
|
-
if (
|
|
206
|
+
if (multiple()) {
|
|
596
207
|
// if the option is already selected, do nothing
|
|
597
|
-
if (
|
|
208
|
+
if (isOptionSelected(optionValue)) {
|
|
598
209
|
return;
|
|
599
210
|
}
|
|
600
|
-
const
|
|
211
|
+
const newValue = [...(value() ?? []), optionValue];
|
|
601
212
|
// add the option to the value
|
|
602
|
-
|
|
603
|
-
this.valueChange.emit(value);
|
|
213
|
+
setValue(newValue);
|
|
604
214
|
}
|
|
605
215
|
else {
|
|
606
|
-
|
|
607
|
-
this.valueChange.emit(optionValue);
|
|
216
|
+
setValue(optionValue);
|
|
608
217
|
// close the dropdown on single selection
|
|
609
|
-
|
|
218
|
+
closeDropdown();
|
|
610
219
|
}
|
|
611
220
|
}
|
|
612
221
|
/**
|
|
@@ -614,7 +223,7 @@ class NgpSelect {
|
|
|
614
223
|
* @param option The option to deselect.
|
|
615
224
|
* @internal
|
|
616
225
|
*/
|
|
617
|
-
deselectOption(option) {
|
|
226
|
+
function deselectOption(option) {
|
|
618
227
|
const optionValue = option.value();
|
|
619
228
|
// Options without values cannot be deselected (and should never be selected).
|
|
620
229
|
if (optionValue === undefined) {
|
|
@@ -622,25 +231,24 @@ class NgpSelect {
|
|
|
622
231
|
}
|
|
623
232
|
// if the select is disabled or the option is not selected, do nothing
|
|
624
233
|
// if the select is single selection, we don't allow deselecting
|
|
625
|
-
if (
|
|
234
|
+
if (disabled() || !isOptionSelected(optionValue) || !multiple()) {
|
|
626
235
|
return;
|
|
627
236
|
}
|
|
628
|
-
const values =
|
|
629
|
-
const newValue = values.filter(v => !
|
|
237
|
+
const values = value() ?? [];
|
|
238
|
+
const newValue = values.filter(v => !compareWith()(v, optionValue));
|
|
630
239
|
// remove the option from the value
|
|
631
|
-
|
|
632
|
-
this.valueChange.emit(newValue);
|
|
240
|
+
setValue(newValue);
|
|
633
241
|
}
|
|
634
242
|
/**
|
|
635
243
|
* Toggle the selection of an option.
|
|
636
244
|
* @param id The id of the option to toggle.
|
|
637
245
|
* @internal
|
|
638
246
|
*/
|
|
639
|
-
toggleOption(id) {
|
|
640
|
-
if (
|
|
247
|
+
function toggleOption(id) {
|
|
248
|
+
if (disabled()) {
|
|
641
249
|
return;
|
|
642
250
|
}
|
|
643
|
-
const option =
|
|
251
|
+
const option = sortedOptions().find(opt => opt.id() === id);
|
|
644
252
|
if (!option) {
|
|
645
253
|
return;
|
|
646
254
|
}
|
|
@@ -650,17 +258,17 @@ class NgpSelect {
|
|
|
650
258
|
return;
|
|
651
259
|
}
|
|
652
260
|
// if the state is single selection, we don't allow toggling
|
|
653
|
-
if (!
|
|
261
|
+
if (!multiple()) {
|
|
654
262
|
// always select the option in single selection mode even if it is already selected so that we update the input
|
|
655
|
-
|
|
263
|
+
selectOption(id);
|
|
656
264
|
return;
|
|
657
265
|
}
|
|
658
266
|
// otherwise toggle the option
|
|
659
|
-
if (
|
|
660
|
-
|
|
267
|
+
if (isOptionSelected(optionValue)) {
|
|
268
|
+
deselectOption(option);
|
|
661
269
|
}
|
|
662
270
|
else {
|
|
663
|
-
|
|
271
|
+
selectOption(id);
|
|
664
272
|
}
|
|
665
273
|
}
|
|
666
274
|
/**
|
|
@@ -668,224 +276,716 @@ class NgpSelect {
|
|
|
668
276
|
* @param option The option to check.
|
|
669
277
|
* @internal
|
|
670
278
|
*/
|
|
671
|
-
isOptionSelected(option) {
|
|
672
|
-
if (
|
|
279
|
+
function isOptionSelected(option) {
|
|
280
|
+
if (disabled()) {
|
|
673
281
|
return false;
|
|
674
282
|
}
|
|
675
|
-
const
|
|
283
|
+
const currentValue = value();
|
|
676
284
|
// Only treat `undefined` as "no selection" (allow '', 0, false).
|
|
677
|
-
if (
|
|
285
|
+
if (currentValue === undefined) {
|
|
678
286
|
return false;
|
|
679
287
|
}
|
|
680
|
-
if (
|
|
681
|
-
return Array.isArray(
|
|
288
|
+
if (multiple()) {
|
|
289
|
+
return Array.isArray(currentValue) && currentValue.some(v => compareWith()(option, v));
|
|
682
290
|
}
|
|
683
|
-
return
|
|
291
|
+
return compareWith()(option, currentValue);
|
|
684
292
|
}
|
|
685
293
|
/**
|
|
686
294
|
* Activate the next option in the list if there is one.
|
|
687
295
|
* If there is no option currently active, activate the selected option or the first option.
|
|
688
296
|
* @internal
|
|
689
297
|
*/
|
|
690
|
-
activateNextOption() {
|
|
691
|
-
if (
|
|
298
|
+
function activateNextOption() {
|
|
299
|
+
if (disabled()) {
|
|
692
300
|
return;
|
|
693
301
|
}
|
|
694
|
-
const
|
|
302
|
+
const currentOptions = sortedOptions();
|
|
695
303
|
// if there are no options, do nothing
|
|
696
|
-
if (
|
|
304
|
+
if (currentOptions.length === 0) {
|
|
697
305
|
return;
|
|
698
306
|
}
|
|
699
307
|
// if there is no active option, activate the first option
|
|
700
|
-
if (
|
|
701
|
-
const selectedOption =
|
|
308
|
+
if (activeDescendantManagerInstance.index() === -1) {
|
|
309
|
+
const selectedOption = currentOptions.findIndex(option => isOptionSelected(option.value()));
|
|
702
310
|
// if there is a selected option(s), set the active descendant to the first selected option
|
|
703
311
|
const targetOption = selectedOption !== -1 ? selectedOption : 0;
|
|
704
|
-
|
|
312
|
+
activeDescendantManagerInstance.activateByIndex(targetOption, { origin: 'keyboard' });
|
|
705
313
|
return;
|
|
706
314
|
}
|
|
707
315
|
// otherwise activate the next option
|
|
708
|
-
|
|
316
|
+
activeDescendantManagerInstance.next({ origin: 'keyboard' });
|
|
709
317
|
}
|
|
710
318
|
/**
|
|
711
319
|
* Activate the previous option in the list if there is one.
|
|
712
320
|
* @internal
|
|
713
321
|
*/
|
|
714
|
-
activatePreviousOption() {
|
|
715
|
-
if (
|
|
322
|
+
function activatePreviousOption() {
|
|
323
|
+
if (disabled()) {
|
|
716
324
|
return;
|
|
717
325
|
}
|
|
718
|
-
const
|
|
326
|
+
const currentOptions = sortedOptions();
|
|
719
327
|
// if there are no options, do nothing
|
|
720
|
-
if (
|
|
328
|
+
if (currentOptions.length === 0) {
|
|
721
329
|
return;
|
|
722
330
|
}
|
|
723
331
|
// if there is no active option, activate the last option
|
|
724
|
-
if (
|
|
725
|
-
const selectedOption =
|
|
332
|
+
if (activeDescendantManagerInstance.index() === -1) {
|
|
333
|
+
const selectedOption = currentOptions.findIndex(option => isOptionSelected(option.value()));
|
|
726
334
|
// if there is a selected option(s), set the active descendant to the first selected option
|
|
727
|
-
const targetOption = selectedOption !== -1 ? selectedOption :
|
|
728
|
-
|
|
335
|
+
const targetOption = selectedOption !== -1 ? selectedOption : currentOptions.length - 1;
|
|
336
|
+
activeDescendantManagerInstance.activateByIndex(targetOption, { origin: 'keyboard' });
|
|
729
337
|
return;
|
|
730
338
|
}
|
|
731
339
|
// otherwise activate the previous option
|
|
732
|
-
|
|
340
|
+
activeDescendantManagerInstance.previous({ origin: 'keyboard' });
|
|
733
341
|
}
|
|
734
342
|
/**
|
|
735
343
|
* Register the dropdown portal with the select.
|
|
736
344
|
* @param portal The dropdown portal.
|
|
737
345
|
* @internal
|
|
738
346
|
*/
|
|
739
|
-
registerPortal(
|
|
740
|
-
|
|
347
|
+
function registerPortal(portalInstance) {
|
|
348
|
+
portal.set(portalInstance);
|
|
741
349
|
}
|
|
742
350
|
/**
|
|
743
351
|
* Register the dropdown with the select.
|
|
744
352
|
* @param dropdown The dropdown to register.
|
|
745
353
|
* @internal
|
|
746
354
|
*/
|
|
747
|
-
registerDropdown(
|
|
748
|
-
|
|
355
|
+
function registerDropdown(dropdownInstance) {
|
|
356
|
+
dropdown.set(dropdownInstance);
|
|
749
357
|
}
|
|
750
358
|
/**
|
|
751
359
|
* Register an option with the select.
|
|
752
360
|
* @param option The option to register.
|
|
753
361
|
* @internal
|
|
754
362
|
*/
|
|
755
|
-
registerOption(option) {
|
|
756
|
-
|
|
363
|
+
function registerOption(option) {
|
|
364
|
+
options.update(current => [...current, option]);
|
|
757
365
|
}
|
|
758
366
|
/**
|
|
759
367
|
* Unregister an option from the select.
|
|
760
368
|
* @param option The option to unregister.
|
|
761
369
|
* @internal
|
|
762
370
|
*/
|
|
763
|
-
unregisterOption(option) {
|
|
764
|
-
|
|
371
|
+
function unregisterOption(option) {
|
|
372
|
+
options.update(current => current.filter(o => o !== option));
|
|
765
373
|
}
|
|
766
374
|
/**
|
|
767
375
|
* Focus the select.
|
|
768
376
|
* @internal
|
|
769
377
|
*/
|
|
770
|
-
focus() {
|
|
771
|
-
|
|
378
|
+
function focus() {
|
|
379
|
+
elementRef.nativeElement.focus();
|
|
772
380
|
}
|
|
773
381
|
/** Handle keydown events for accessibility. */
|
|
774
|
-
handleKeydown(event) {
|
|
382
|
+
function handleKeydown(event) {
|
|
775
383
|
switch (event.key) {
|
|
776
384
|
case 'ArrowDown':
|
|
777
|
-
if (
|
|
778
|
-
|
|
385
|
+
if (open()) {
|
|
386
|
+
activateNextOption();
|
|
779
387
|
}
|
|
780
388
|
else {
|
|
781
|
-
|
|
389
|
+
void openDropdown();
|
|
782
390
|
}
|
|
783
391
|
event.preventDefault();
|
|
784
392
|
break;
|
|
785
393
|
case 'ArrowUp':
|
|
786
|
-
if (
|
|
787
|
-
|
|
394
|
+
if (open()) {
|
|
395
|
+
activatePreviousOption();
|
|
788
396
|
}
|
|
789
397
|
else {
|
|
790
|
-
|
|
791
|
-
|
|
398
|
+
void openDropdown();
|
|
399
|
+
activeDescendantManagerInstance.last();
|
|
792
400
|
}
|
|
793
401
|
event.preventDefault();
|
|
794
402
|
break;
|
|
795
403
|
case 'Home':
|
|
796
|
-
if (
|
|
797
|
-
|
|
404
|
+
if (open()) {
|
|
405
|
+
activeDescendantManagerInstance.first({ origin: 'keyboard' });
|
|
798
406
|
}
|
|
799
407
|
event.preventDefault();
|
|
800
408
|
break;
|
|
801
409
|
case 'End':
|
|
802
|
-
if (
|
|
803
|
-
|
|
410
|
+
if (open()) {
|
|
411
|
+
activeDescendantManagerInstance.last({ origin: 'keyboard' });
|
|
804
412
|
}
|
|
805
413
|
event.preventDefault();
|
|
806
414
|
break;
|
|
807
415
|
case 'Enter':
|
|
808
|
-
if (
|
|
809
|
-
const activeId =
|
|
416
|
+
if (open()) {
|
|
417
|
+
const activeId = activeDescendantManagerInstance.id();
|
|
810
418
|
if (activeId) {
|
|
811
|
-
const option =
|
|
419
|
+
const option = sortedOptions().find(opt => opt.id() === activeId);
|
|
812
420
|
option?.select();
|
|
813
421
|
}
|
|
814
422
|
}
|
|
815
423
|
else {
|
|
816
|
-
|
|
424
|
+
void openDropdown();
|
|
817
425
|
}
|
|
818
426
|
event.preventDefault();
|
|
819
427
|
break;
|
|
820
428
|
case ' ':
|
|
821
|
-
|
|
429
|
+
void toggleDropdown();
|
|
822
430
|
event.preventDefault();
|
|
823
431
|
break;
|
|
824
432
|
}
|
|
825
433
|
}
|
|
826
|
-
onBlur(event) {
|
|
434
|
+
function onBlur(event) {
|
|
827
435
|
const relatedTarget = event.relatedTarget;
|
|
828
436
|
// if the blur was caused by focus moving to the dropdown, don't close
|
|
829
|
-
if (relatedTarget &&
|
|
437
|
+
if (relatedTarget && dropdown()?.elementRef.nativeElement.contains(relatedTarget)) {
|
|
830
438
|
return;
|
|
831
439
|
}
|
|
832
|
-
|
|
440
|
+
closeDropdown();
|
|
833
441
|
event.preventDefault();
|
|
834
442
|
}
|
|
835
|
-
scrollTo(index) {
|
|
836
|
-
const
|
|
837
|
-
if (
|
|
838
|
-
|
|
443
|
+
function scrollTo(index) {
|
|
444
|
+
const customScrollToOption = scrollToOption();
|
|
445
|
+
if (customScrollToOption) {
|
|
446
|
+
customScrollToOption(index);
|
|
839
447
|
return;
|
|
840
448
|
}
|
|
841
|
-
const option =
|
|
449
|
+
const option = getOptionAtIndex(index);
|
|
842
450
|
if (option) {
|
|
843
451
|
option.scrollIntoView();
|
|
844
452
|
}
|
|
845
453
|
}
|
|
846
|
-
getOptionAtIndex(index) {
|
|
454
|
+
function getOptionAtIndex(index) {
|
|
847
455
|
// if the option has an index, use that to get the option because this is required for virtual scrolling scenarios
|
|
848
|
-
const optionIndex =
|
|
456
|
+
const optionIndex = options().findIndex(opt => opt.index?.() === index);
|
|
849
457
|
if (optionIndex !== -1) {
|
|
850
|
-
return
|
|
458
|
+
return options()[optionIndex];
|
|
459
|
+
}
|
|
460
|
+
return sortedOptions()[index];
|
|
461
|
+
}
|
|
462
|
+
return {
|
|
463
|
+
elementRef,
|
|
464
|
+
id,
|
|
465
|
+
value: deprecatedSetter(value, 'setValue', v => setValue(v)),
|
|
466
|
+
multiple,
|
|
467
|
+
disabled: deprecatedSetter(disabled, 'setDisabled', setDisabled),
|
|
468
|
+
compareWith,
|
|
469
|
+
placement,
|
|
470
|
+
container,
|
|
471
|
+
flip,
|
|
472
|
+
offset,
|
|
473
|
+
scrollToOption,
|
|
474
|
+
allOptions,
|
|
475
|
+
portal,
|
|
476
|
+
dropdown,
|
|
477
|
+
options,
|
|
478
|
+
overlay,
|
|
479
|
+
open,
|
|
480
|
+
sortedOptions,
|
|
481
|
+
activeDescendantManager: activeDescendantManagerInstance,
|
|
482
|
+
openDropdown,
|
|
483
|
+
closeDropdown,
|
|
484
|
+
onOverlayClose,
|
|
485
|
+
toggleDropdown,
|
|
486
|
+
selectOption,
|
|
487
|
+
deselectOption,
|
|
488
|
+
toggleOption,
|
|
489
|
+
isOptionSelected,
|
|
490
|
+
activateNextOption,
|
|
491
|
+
activatePreviousOption,
|
|
492
|
+
setValue,
|
|
493
|
+
setDisabled,
|
|
494
|
+
valueChange: valueChangeEmitter.asObservable(),
|
|
495
|
+
registerPortal,
|
|
496
|
+
registerDropdown,
|
|
497
|
+
registerOption,
|
|
498
|
+
unregisterOption,
|
|
499
|
+
focus,
|
|
500
|
+
};
|
|
501
|
+
});
|
|
502
|
+
function injectSelectState(options) {
|
|
503
|
+
return _injectSelectState(options);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
const [NgpSelectDropdownStateToken, ngpSelectDropdown, _injectSelectDropdownState, provideSelectDropdownState,] = createPrimitive('NgpSelectDropdown', ({ id: _id = signal(uniqueId('ngp-select-dropdown')) }) => {
|
|
507
|
+
const elementRef = injectElementRef();
|
|
508
|
+
const selectState = injectSelectState();
|
|
509
|
+
const selectDimensions = observeResize(() => selectState().elementRef.nativeElement);
|
|
510
|
+
// Host bindings
|
|
511
|
+
attrBinding(elementRef, 'role', 'listbox');
|
|
512
|
+
attrBinding(elementRef, 'id', _id);
|
|
513
|
+
styleBinding(elementRef, 'left.px', () => selectState().overlay()?.position()?.x ?? null);
|
|
514
|
+
styleBinding(elementRef, 'top.px', () => selectState().overlay()?.position()?.y ?? null);
|
|
515
|
+
styleBinding(elementRef, '--ngp-select-transform-origin', () => selectState().overlay()?.transformOrigin() ?? null);
|
|
516
|
+
styleBinding(elementRef, '--ngp-select-available-width.px', () => selectState().overlay()?.availableWidth() ?? null);
|
|
517
|
+
styleBinding(elementRef, '--ngp-select-available-height.px', () => selectState().overlay()?.availableHeight() ?? null);
|
|
518
|
+
styleBinding(elementRef, '--ngp-select-width.px', () => selectDimensions().width ?? null);
|
|
519
|
+
const state = {
|
|
520
|
+
elementRef,
|
|
521
|
+
id: _id,
|
|
522
|
+
};
|
|
523
|
+
selectState().registerDropdown(state);
|
|
524
|
+
return state;
|
|
525
|
+
});
|
|
526
|
+
function injectSelectDropdownState(options) {
|
|
527
|
+
return _injectSelectDropdownState(options);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
class NgpSelectDropdown {
|
|
531
|
+
constructor() {
|
|
532
|
+
/** The id of the dropdown. */
|
|
533
|
+
this.id = input(uniqueId('ngp-select-dropdown'), ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
534
|
+
ngpSelectDropdown({
|
|
535
|
+
id: this.id,
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NgpSelectDropdown, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
539
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.14", type: NgpSelectDropdown, isStandalone: true, selector: "[ngpSelectDropdown]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideControlContainerIsolation()], exportAs: ["ngpSelectDropdown"], ngImport: i0 }); }
|
|
540
|
+
}
|
|
541
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NgpSelectDropdown, decorators: [{
|
|
542
|
+
type: Directive,
|
|
543
|
+
args: [{
|
|
544
|
+
selector: '[ngpSelectDropdown]',
|
|
545
|
+
exportAs: 'ngpSelectDropdown',
|
|
546
|
+
providers: [provideControlContainerIsolation()],
|
|
547
|
+
}]
|
|
548
|
+
}], ctorParameters: () => [], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }] } });
|
|
549
|
+
|
|
550
|
+
const [NgpSelectOptionStateToken, ngpSelectOption, _injectSelectOptionState, provideSelectOptionState,] = createPrimitive('NgpSelectOption', ({ id = signal(uniqueId('ngp-select-option')), value = signal(undefined), disabled = signal(false), index = signal(undefined), onActivated, }) => {
|
|
551
|
+
const elementRef = injectElementRef();
|
|
552
|
+
const selectState = injectSelectState();
|
|
553
|
+
ngpInteractions({
|
|
554
|
+
hover: true,
|
|
555
|
+
press: true,
|
|
556
|
+
disabled: disabled,
|
|
557
|
+
});
|
|
558
|
+
// Computed states
|
|
559
|
+
const active = computed(() => {
|
|
560
|
+
const idx = index();
|
|
561
|
+
if (idx !== undefined) {
|
|
562
|
+
return selectState().activeDescendantManager.index() === idx;
|
|
563
|
+
}
|
|
564
|
+
return selectState().activeDescendantManager.id() === id();
|
|
565
|
+
}, ...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
|
|
566
|
+
const selected = computed(() => {
|
|
567
|
+
const val = value();
|
|
568
|
+
const stateValue = selectState().value();
|
|
569
|
+
if (val === undefined) {
|
|
570
|
+
return false;
|
|
571
|
+
}
|
|
572
|
+
if (selectState().multiple()) {
|
|
573
|
+
return (Array.isArray(stateValue) && stateValue.some(v => selectState().compareWith()(val, v)));
|
|
574
|
+
}
|
|
575
|
+
if (stateValue === undefined) {
|
|
576
|
+
return false;
|
|
851
577
|
}
|
|
852
|
-
return
|
|
578
|
+
return selectState().compareWith()(val, stateValue);
|
|
579
|
+
}, ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
|
|
580
|
+
// Host bindings
|
|
581
|
+
attrBinding(elementRef, 'role', 'option');
|
|
582
|
+
attrBinding(elementRef, 'tabindex', -1);
|
|
583
|
+
attrBinding(elementRef, 'id', id);
|
|
584
|
+
attrBinding(elementRef, 'aria-selected', () => (selected() ? 'true' : undefined));
|
|
585
|
+
dataBinding(elementRef, 'data-selected', () => (selected() ? '' : null));
|
|
586
|
+
dataBinding(elementRef, 'data-active', () => (active() ? '' : null));
|
|
587
|
+
dataBinding(elementRef, 'data-disabled', () => (disabled() ? '' : null));
|
|
588
|
+
// Event listeners
|
|
589
|
+
listener(elementRef, 'click', () => select());
|
|
590
|
+
listener(elementRef, 'pointerenter', () => activateOnPointerEnter());
|
|
591
|
+
listener(elementRef, 'pointerleave', () => deactivateOnPointerLeave());
|
|
592
|
+
// Methods
|
|
593
|
+
function select() {
|
|
594
|
+
if (disabled()) {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
onActivated?.();
|
|
598
|
+
selectState().toggleOption(id());
|
|
599
|
+
}
|
|
600
|
+
function scrollIntoView() {
|
|
601
|
+
scrollIntoViewIfNeeded(elementRef.nativeElement);
|
|
602
|
+
}
|
|
603
|
+
function activateOnPointerEnter() {
|
|
604
|
+
const idx = index();
|
|
605
|
+
if (idx !== undefined) {
|
|
606
|
+
selectState().activeDescendantManager.activateByIndex(idx, {
|
|
607
|
+
scroll: false,
|
|
608
|
+
origin: 'pointer',
|
|
609
|
+
});
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
selectState().activeDescendantManager.activateById(id(), {
|
|
613
|
+
scroll: false,
|
|
614
|
+
origin: 'pointer',
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
function deactivateOnPointerLeave() {
|
|
618
|
+
if (selectState().activeDescendantManager.id() === id()) {
|
|
619
|
+
selectState().activeDescendantManager.reset({ origin: 'pointer' });
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
const state = {
|
|
623
|
+
elementRef,
|
|
624
|
+
id,
|
|
625
|
+
value,
|
|
626
|
+
disabled,
|
|
627
|
+
index,
|
|
628
|
+
active,
|
|
629
|
+
selected,
|
|
630
|
+
select,
|
|
631
|
+
scrollIntoView,
|
|
632
|
+
activateOnPointerEnter,
|
|
633
|
+
deactivateOnPointerLeave,
|
|
634
|
+
emitActivated: () => onActivated?.(),
|
|
635
|
+
};
|
|
636
|
+
selectState().registerOption(state);
|
|
637
|
+
onDestroy(() => {
|
|
638
|
+
selectState().unregisterOption(state);
|
|
639
|
+
});
|
|
640
|
+
return state;
|
|
641
|
+
});
|
|
642
|
+
function injectSelectOptionState(options) {
|
|
643
|
+
return _injectSelectOptionState(options);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
class NgpSelectOption {
|
|
647
|
+
constructor() {
|
|
648
|
+
/** Access the select state. */
|
|
649
|
+
this.selectState = injectSelectState();
|
|
650
|
+
/** The id of the option. */
|
|
651
|
+
this.id = input(uniqueId('ngp-select-option'), ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
652
|
+
/** @required The value of the option. */
|
|
653
|
+
this.value = input(undefined, { ...(ngDevMode ? { debugName: "value" } : /* istanbul ignore next */ {}), alias: 'ngpSelectOptionValue' });
|
|
654
|
+
/** The disabled state of the option. */
|
|
655
|
+
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), alias: 'ngpSelectOptionDisabled',
|
|
656
|
+
transform: booleanAttribute });
|
|
657
|
+
/** The index of the option in the list. */
|
|
658
|
+
this.index = input(undefined, { ...(ngDevMode ? { debugName: "index" } : /* istanbul ignore next */ {}), alias: 'ngpSelectOptionIndex' });
|
|
659
|
+
/**
|
|
660
|
+
* Event emitted when the option is activated via click or keyboard.
|
|
661
|
+
* This is useful for options without values that need custom behavior.
|
|
662
|
+
*/
|
|
663
|
+
this.activated = output({
|
|
664
|
+
alias: 'ngpSelectOptionActivated',
|
|
665
|
+
});
|
|
666
|
+
/** Access the select option state */
|
|
667
|
+
this.state = ngpSelectOption({
|
|
668
|
+
id: this.id,
|
|
669
|
+
value: this.value,
|
|
670
|
+
disabled: this.disabled,
|
|
671
|
+
index: this.index,
|
|
672
|
+
onActivated: () => this.activated.emit(),
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Select the option.
|
|
677
|
+
* @internal
|
|
678
|
+
*/
|
|
679
|
+
select() {
|
|
680
|
+
this.state.select();
|
|
681
|
+
}
|
|
682
|
+
/**
|
|
683
|
+
* Scroll the option into view.
|
|
684
|
+
* @internal
|
|
685
|
+
*/
|
|
686
|
+
scrollIntoView() {
|
|
687
|
+
this.state.scrollIntoView();
|
|
688
|
+
}
|
|
689
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NgpSelectOption, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
690
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.14", type: NgpSelectOption, isStandalone: true, selector: "[ngpSelectOption]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "ngpSelectOptionValue", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpSelectOptionDisabled", isSignal: true, isRequired: false, transformFunction: null }, index: { classPropertyName: "index", publicName: "ngpSelectOptionIndex", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activated: "ngpSelectOptionActivated" }, exportAs: ["ngpSelectOption"], ngImport: i0 }); }
|
|
691
|
+
}
|
|
692
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NgpSelectOption, decorators: [{
|
|
693
|
+
type: Directive,
|
|
694
|
+
args: [{
|
|
695
|
+
selector: '[ngpSelectOption]',
|
|
696
|
+
exportAs: 'ngpSelectOption',
|
|
697
|
+
}]
|
|
698
|
+
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectOptionValue", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectOptionDisabled", required: false }] }], index: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectOptionIndex", required: false }] }], activated: [{ type: i0.Output, args: ["ngpSelectOptionActivated"] }] } });
|
|
699
|
+
|
|
700
|
+
const [NgpSelectPortalStateToken, ngpSelectPortal, _injectSelectPortalState, provideSelectPortalState,] = createPrimitive('NgpSelectPortal', ({}) => {
|
|
701
|
+
const templateRef = inject(TemplateRef);
|
|
702
|
+
const viewContainerRef = inject(ViewContainerRef);
|
|
703
|
+
const injector = inject(Injector);
|
|
704
|
+
const selectState = injectSelectState();
|
|
705
|
+
const overlay = signal(null, ...(ngDevMode ? [{ debugName: "overlay" }] : /* istanbul ignore next */ []));
|
|
706
|
+
// Methods
|
|
707
|
+
async function show() {
|
|
708
|
+
if (!overlay()) {
|
|
709
|
+
createOverlayInstance();
|
|
710
|
+
}
|
|
711
|
+
return overlay()?.show();
|
|
712
|
+
}
|
|
713
|
+
function hide() {
|
|
714
|
+
overlay()?.hide();
|
|
715
|
+
}
|
|
716
|
+
function destroy() {
|
|
717
|
+
overlay()?.destroy();
|
|
718
|
+
}
|
|
719
|
+
function createOverlayInstance() {
|
|
720
|
+
const overlayConfig = {
|
|
721
|
+
content: templateRef,
|
|
722
|
+
viewContainerRef,
|
|
723
|
+
triggerElement: selectState().elementRef.nativeElement,
|
|
724
|
+
injector,
|
|
725
|
+
placement: selectState().placement,
|
|
726
|
+
offset: selectState().offset(),
|
|
727
|
+
flip: selectState().flip(),
|
|
728
|
+
container: selectState().container(),
|
|
729
|
+
closeOnOutsideClick: true,
|
|
730
|
+
closeOnEscape: true,
|
|
731
|
+
restoreFocus: false,
|
|
732
|
+
scrollBehaviour: 'reposition',
|
|
733
|
+
onClose: () => selectState().onOverlayClose(),
|
|
734
|
+
};
|
|
735
|
+
overlay.set(createOverlay(overlayConfig));
|
|
736
|
+
}
|
|
737
|
+
const state = {
|
|
738
|
+
overlay,
|
|
739
|
+
show,
|
|
740
|
+
hide,
|
|
741
|
+
destroy,
|
|
742
|
+
};
|
|
743
|
+
selectState().registerPortal(state);
|
|
744
|
+
return state;
|
|
745
|
+
});
|
|
746
|
+
function injectSelectPortalState(options) {
|
|
747
|
+
return _injectSelectPortalState(options);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
class NgpSelectPortal {
|
|
751
|
+
constructor() {
|
|
752
|
+
this.state = ngpSelectPortal({});
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Attach the portal.
|
|
756
|
+
* @internal
|
|
757
|
+
*/
|
|
758
|
+
show() {
|
|
759
|
+
return this.state.show();
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Detach the portal.
|
|
763
|
+
* @internal
|
|
764
|
+
*/
|
|
765
|
+
detach() {
|
|
766
|
+
this.state.hide();
|
|
767
|
+
}
|
|
768
|
+
ngOnDestroy() {
|
|
769
|
+
this.state.destroy();
|
|
770
|
+
}
|
|
771
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NgpSelectPortal, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
772
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.14", type: NgpSelectPortal, isStandalone: true, selector: "[ngpSelectPortal]", exportAs: ["ngpSelectPortal"], ngImport: i0 }); }
|
|
773
|
+
}
|
|
774
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NgpSelectPortal, decorators: [{
|
|
775
|
+
type: Directive,
|
|
776
|
+
args: [{
|
|
777
|
+
selector: '[ngpSelectPortal]',
|
|
778
|
+
exportAs: 'ngpSelectPortal',
|
|
779
|
+
}]
|
|
780
|
+
}] });
|
|
781
|
+
|
|
782
|
+
const defaultSelectConfig = {
|
|
783
|
+
placement: 'bottom',
|
|
784
|
+
container: 'body',
|
|
785
|
+
flip: true,
|
|
786
|
+
offset: 0,
|
|
787
|
+
};
|
|
788
|
+
const NgpSelectConfigToken = new InjectionToken('NgpSelectConfigToken');
|
|
789
|
+
/**
|
|
790
|
+
* Provide the default Select configuration
|
|
791
|
+
* @param config The Select configuration
|
|
792
|
+
* @returns The provider
|
|
793
|
+
*/
|
|
794
|
+
function provideSelectConfig(config) {
|
|
795
|
+
return [
|
|
796
|
+
{
|
|
797
|
+
provide: NgpSelectConfigToken,
|
|
798
|
+
useValue: { ...defaultSelectConfig, ...config },
|
|
799
|
+
},
|
|
800
|
+
];
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Inject the Select configuration
|
|
804
|
+
* @returns The global Select configuration
|
|
805
|
+
*/
|
|
806
|
+
function injectSelectConfig() {
|
|
807
|
+
return inject(NgpSelectConfigToken, { optional: true }) ?? defaultSelectConfig;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
class NgpSelect {
|
|
811
|
+
constructor() {
|
|
812
|
+
/** Access the select configuration. */
|
|
813
|
+
this.config = injectSelectConfig();
|
|
814
|
+
/** The unique id of the select. */
|
|
815
|
+
this.id = input(uniqueId('ngp-select'), ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
816
|
+
/** The value of the select. */
|
|
817
|
+
this.value = input(undefined, { ...(ngDevMode ? { debugName: "value" } : /* istanbul ignore next */ {}), alias: 'ngpSelectValue' });
|
|
818
|
+
/** Event emitted when the value changes. */
|
|
819
|
+
this.valueChange = output({
|
|
820
|
+
alias: 'ngpSelectValueChange',
|
|
821
|
+
});
|
|
822
|
+
/** Whether the select is multiple selection. */
|
|
823
|
+
this.multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), alias: 'ngpSelectMultiple',
|
|
824
|
+
transform: booleanAttribute });
|
|
825
|
+
/** Whether the select is disabled. */
|
|
826
|
+
this.disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), alias: 'ngpSelectDisabled',
|
|
827
|
+
transform: booleanAttribute });
|
|
828
|
+
/** Emit when the dropdown open state changes. */
|
|
829
|
+
this.openChange = output({
|
|
830
|
+
alias: 'ngpSelectOpenChange',
|
|
831
|
+
});
|
|
832
|
+
/** The comparator function used to compare options. */
|
|
833
|
+
this.compareWith = input(Object.is, { ...(ngDevMode ? { debugName: "compareWith" } : /* istanbul ignore next */ {}), alias: 'ngpSelectCompareWith' });
|
|
834
|
+
/** The position of the dropdown. */
|
|
835
|
+
this.placement = input(this.config.placement, { ...(ngDevMode ? { debugName: "placement" } : /* istanbul ignore next */ {}), alias: 'ngpSelectDropdownPlacement' });
|
|
836
|
+
/** The container for the dropdown. */
|
|
837
|
+
this.container = input(this.config.container, { ...(ngDevMode ? { debugName: "container" } : /* istanbul ignore next */ {}), alias: 'ngpSelectDropdownContainer' });
|
|
838
|
+
/** Whether the dropdown should flip when there is not enough space. Can be a boolean to enable/disable, or an object with padding and fallbackPlacements options. */
|
|
839
|
+
this.flip = input(this.config.flip, { ...(ngDevMode ? { debugName: "flip" } : /* istanbul ignore next */ {}), alias: 'ngpSelectDropdownFlip',
|
|
840
|
+
transform: coerceFlip });
|
|
841
|
+
/**
|
|
842
|
+
* Define the offset of the select dropdown relative to the trigger.
|
|
843
|
+
* Can be a number (applies to mainAxis) or an object with mainAxis, crossAxis, and alignmentAxis.
|
|
844
|
+
* @default 0
|
|
845
|
+
*/
|
|
846
|
+
this.offset = input(this.config.offset, { ...(ngDevMode ? { debugName: "offset" } : /* istanbul ignore next */ {}), alias: 'ngpSelectDropdownOffset',
|
|
847
|
+
transform: coerceOffset });
|
|
848
|
+
/**
|
|
849
|
+
* A function that will scroll the active option into view. This can be overridden
|
|
850
|
+
* for cases such as virtual scrolling where we cannot scroll the option directly because
|
|
851
|
+
* it may not be rendered.
|
|
852
|
+
*/
|
|
853
|
+
this.scrollToOption = input(undefined, { ...(ngDevMode ? { debugName: "scrollToOption" } : /* istanbul ignore next */ {}), alias: 'ngpSelectScrollToOption' });
|
|
854
|
+
/**
|
|
855
|
+
* Provide all the option values to the select. This is useful for virtual scrolling scenarios
|
|
856
|
+
* where not all options are rendered in the DOM. This is not an alternative to adding the options
|
|
857
|
+
* in the DOM, it is only to provide the select with the full list of options. This list should match
|
|
858
|
+
* the order of the options as they would appear in the DOM.
|
|
859
|
+
*/
|
|
860
|
+
this.allOptions = input(undefined, { ...(ngDevMode ? { debugName: "allOptions" } : /* istanbul ignore next */ {}), alias: 'ngpSelectOptions' });
|
|
861
|
+
/** The state of the select. */
|
|
862
|
+
this.state = ngpSelect({
|
|
863
|
+
id: this.id,
|
|
864
|
+
value: this.value,
|
|
865
|
+
multiple: this.multiple,
|
|
866
|
+
disabled: this.disabled,
|
|
867
|
+
compareWith: this.compareWith,
|
|
868
|
+
placement: this.placement,
|
|
869
|
+
container: this.container,
|
|
870
|
+
flip: this.flip,
|
|
871
|
+
offset: this.offset,
|
|
872
|
+
scrollToOption: this.scrollToOption,
|
|
873
|
+
allOptions: this.allOptions,
|
|
874
|
+
onValueChange: value => this.valueChange.emit(value),
|
|
875
|
+
onOpenChange: open => this.openChange.emit(open),
|
|
876
|
+
});
|
|
877
|
+
/** @internal Access the select element. */
|
|
878
|
+
this.elementRef = this.state.elementRef;
|
|
879
|
+
/**
|
|
880
|
+
* Store the select portal.
|
|
881
|
+
* @internal
|
|
882
|
+
*/
|
|
883
|
+
this.portal = this.state.portal;
|
|
884
|
+
/**
|
|
885
|
+
* Store the select dropdown.
|
|
886
|
+
* @internal
|
|
887
|
+
*/
|
|
888
|
+
this.dropdown = this.state.dropdown;
|
|
889
|
+
/**
|
|
890
|
+
* Store the select options.
|
|
891
|
+
* @internal
|
|
892
|
+
*/
|
|
893
|
+
this.options = this.state.options;
|
|
894
|
+
/**
|
|
895
|
+
* Access the overlay
|
|
896
|
+
* @internal
|
|
897
|
+
*/
|
|
898
|
+
this.overlay = this.state.overlay;
|
|
899
|
+
/**
|
|
900
|
+
* The open state of the select.
|
|
901
|
+
* @internal
|
|
902
|
+
*/
|
|
903
|
+
this.open = this.state.open;
|
|
904
|
+
/**
|
|
905
|
+
* The options sorted by their index or DOM position.
|
|
906
|
+
* @internal
|
|
907
|
+
*/
|
|
908
|
+
this.sortedOptions = this.state.sortedOptions;
|
|
909
|
+
/**
|
|
910
|
+
* The active key descendant manager.
|
|
911
|
+
* @internal
|
|
912
|
+
*/
|
|
913
|
+
this.activeDescendantManager = this.state.activeDescendantManager;
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Open the dropdown.
|
|
917
|
+
* @internal
|
|
918
|
+
*/
|
|
919
|
+
openDropdown() {
|
|
920
|
+
return this.state.openDropdown();
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Close the dropdown.
|
|
924
|
+
* @internal
|
|
925
|
+
*/
|
|
926
|
+
closeDropdown() {
|
|
927
|
+
return this.state.closeDropdown();
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* Toggle the dropdown.
|
|
931
|
+
* @internal
|
|
932
|
+
*/
|
|
933
|
+
toggleDropdown() {
|
|
934
|
+
return this.state.toggleDropdown();
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Select an option.
|
|
938
|
+
* @param id The id of the option to select.
|
|
939
|
+
* @internal
|
|
940
|
+
*/
|
|
941
|
+
selectOption(id) {
|
|
942
|
+
this.state.selectOption(id);
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* Determine if an option is selected.
|
|
946
|
+
* @param option The option to check.
|
|
947
|
+
* @internal
|
|
948
|
+
*/
|
|
949
|
+
isOptionSelected(option) {
|
|
950
|
+
return this.state.isOptionSelected(option);
|
|
951
|
+
}
|
|
952
|
+
/**
|
|
953
|
+
* Activate the next option in the list if there is one.
|
|
954
|
+
* If there is no option currently active, activate the selected option or the first option.
|
|
955
|
+
* @internal
|
|
956
|
+
*/
|
|
957
|
+
activateNextOption() {
|
|
958
|
+
this.state.activateNextOption();
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Activate the previous option in the list if there is one.
|
|
962
|
+
* @internal
|
|
963
|
+
*/
|
|
964
|
+
activatePreviousOption() {
|
|
965
|
+
this.state.activatePreviousOption();
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Focus the select.
|
|
969
|
+
* @internal
|
|
970
|
+
*/
|
|
971
|
+
focus() {
|
|
972
|
+
this.state.focus();
|
|
853
973
|
}
|
|
854
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
855
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "
|
|
974
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NgpSelect, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
975
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.14", type: NgpSelect, isStandalone: true, selector: "[ngpSelect]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "ngpSelectValue", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "ngpSelectMultiple", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "ngpSelectDisabled", isSignal: true, isRequired: false, transformFunction: null }, compareWith: { classPropertyName: "compareWith", publicName: "ngpSelectCompareWith", isSignal: true, isRequired: false, transformFunction: null }, placement: { classPropertyName: "placement", publicName: "ngpSelectDropdownPlacement", isSignal: true, isRequired: false, transformFunction: null }, container: { classPropertyName: "container", publicName: "ngpSelectDropdownContainer", isSignal: true, isRequired: false, transformFunction: null }, flip: { classPropertyName: "flip", publicName: "ngpSelectDropdownFlip", isSignal: true, isRequired: false, transformFunction: null }, offset: { classPropertyName: "offset", publicName: "ngpSelectDropdownOffset", isSignal: true, isRequired: false, transformFunction: null }, scrollToOption: { classPropertyName: "scrollToOption", publicName: "ngpSelectScrollToOption", isSignal: true, isRequired: false, transformFunction: null }, allOptions: { classPropertyName: "allOptions", publicName: "ngpSelectOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "ngpSelectValueChange", openChange: "ngpSelectOpenChange" }, providers: [provideSelectState()], exportAs: ["ngpSelect"], ngImport: i0 }); }
|
|
856
976
|
}
|
|
857
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
977
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: NgpSelect, decorators: [{
|
|
858
978
|
type: Directive,
|
|
859
979
|
args: [{
|
|
860
980
|
selector: '[ngpSelect]',
|
|
861
981
|
exportAs: 'ngpSelect',
|
|
862
982
|
providers: [provideSelectState()],
|
|
863
|
-
host: {
|
|
864
|
-
role: 'combobox',
|
|
865
|
-
'[id]': 'state.id()',
|
|
866
|
-
'[attr.aria-expanded]': 'open()',
|
|
867
|
-
'[attr.aria-controls]': 'open() ? dropdown()?.id() : undefined',
|
|
868
|
-
'[attr.aria-activedescendant]': 'open() ? activeDescendantManager.id() : undefined',
|
|
869
|
-
'[attr.tabindex]': 'state.disabled() ? -1 : 0',
|
|
870
|
-
'[attr.data-open]': 'open() ? "" : undefined',
|
|
871
|
-
'[attr.data-disabled]': 'state.disabled() ? "" : undefined',
|
|
872
|
-
'[attr.data-multiple]': 'state.multiple() ? "" : undefined',
|
|
873
|
-
},
|
|
874
983
|
}]
|
|
875
|
-
}],
|
|
876
|
-
type: HostListener,
|
|
877
|
-
args: ['click']
|
|
878
|
-
}], handleKeydown: [{
|
|
879
|
-
type: HostListener,
|
|
880
|
-
args: ['keydown', ['$event']]
|
|
881
|
-
}], onBlur: [{
|
|
882
|
-
type: HostListener,
|
|
883
|
-
args: ['blur', ['$event']]
|
|
884
|
-
}] } });
|
|
984
|
+
}], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectValue", required: false }] }], valueChange: [{ type: i0.Output, args: ["ngpSelectValueChange"] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectMultiple", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectDisabled", required: false }] }], openChange: [{ type: i0.Output, args: ["ngpSelectOpenChange"] }], compareWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectCompareWith", required: false }] }], placement: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectDropdownPlacement", required: false }] }], container: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectDropdownContainer", required: false }] }], flip: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectDropdownFlip", required: false }] }], offset: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectDropdownOffset", required: false }] }], scrollToOption: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectScrollToOption", required: false }] }], allOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngpSelectOptions", required: false }] }] } });
|
|
885
985
|
|
|
886
986
|
/**
|
|
887
987
|
* Generated bundle index. Do not edit.
|
|
888
988
|
*/
|
|
889
989
|
|
|
890
|
-
export { NgpNativeSelect, NgpSelect, NgpSelectDropdown, NgpSelectOption, NgpSelectPortal, injectNativeSelectState, injectSelectConfig, injectSelectState, provideNativeSelectState, provideSelectConfig, provideSelectState };
|
|
990
|
+
export { NgpNativeSelect, NgpSelect, NgpSelectDropdown, NgpSelectDropdownStateToken, NgpSelectOption, NgpSelectOptionStateToken, NgpSelectPortal, NgpSelectPortalStateToken, NgpSelectStateToken, injectNativeSelectState, injectSelectConfig, injectSelectDropdownState, injectSelectOptionState, injectSelectPortalState, injectSelectState, ngpSelect, ngpSelectDropdown, ngpSelectOption, ngpSelectPortal, provideNativeSelectState, provideSelectConfig, provideSelectDropdownState, provideSelectOptionState, provideSelectPortalState, provideSelectState };
|
|
891
991
|
//# sourceMappingURL=ng-primitives-select.mjs.map
|