@memberjunction/ng-ui-components 6.2.0-edge.0 → 6.2.0-edge.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -9
- package/dist/lib/a11y/named-control.base.d.ts +91 -0
- package/dist/lib/a11y/named-control.base.d.ts.map +1 -0
- package/dist/lib/a11y/named-control.base.js +121 -0
- package/dist/lib/a11y/named-control.base.js.map +1 -0
- package/dist/lib/a11y/unnamed-control-guard.d.ts +52 -0
- package/dist/lib/a11y/unnamed-control-guard.d.ts.map +1 -0
- package/dist/lib/a11y/unnamed-control-guard.js +94 -0
- package/dist/lib/a11y/unnamed-control-guard.js.map +1 -0
- package/dist/lib/accordion/accordion.component.d.ts +16 -4
- package/dist/lib/accordion/accordion.component.d.ts.map +1 -1
- package/dist/lib/accordion/accordion.component.js +36 -12
- package/dist/lib/accordion/accordion.component.js.map +1 -1
- package/dist/lib/applied-filters/applied-filters.component.js.map +1 -1
- package/dist/lib/button/button.directive.d.ts +34 -6
- package/dist/lib/button/button.directive.d.ts.map +1 -1
- package/dist/lib/button/button.directive.js +85 -25
- package/dist/lib/button/button.directive.js.map +1 -1
- package/dist/lib/card-grid/card-grid.component.d.ts +3 -1
- package/dist/lib/card-grid/card-grid.component.d.ts.map +1 -1
- package/dist/lib/card-grid/card-grid.component.js +13 -9
- package/dist/lib/card-grid/card-grid.component.js.map +1 -1
- package/dist/lib/clickable/clickable.directive.d.ts +11 -3
- package/dist/lib/clickable/clickable.directive.d.ts.map +1 -1
- package/dist/lib/clickable/clickable.directive.js +25 -5
- package/dist/lib/clickable/clickable.directive.js.map +1 -1
- package/dist/lib/combobox/combobox.component.d.ts +44 -3
- package/dist/lib/combobox/combobox.component.d.ts.map +1 -1
- package/dist/lib/combobox/combobox.component.js +135 -51
- package/dist/lib/combobox/combobox.component.js.map +1 -1
- package/dist/lib/confirm-dialog/confirm-dialog.component.d.ts +6 -0
- package/dist/lib/confirm-dialog/confirm-dialog.component.d.ts.map +1 -1
- package/dist/lib/confirm-dialog/confirm-dialog.component.js +16 -4
- package/dist/lib/confirm-dialog/confirm-dialog.component.js.map +1 -1
- package/dist/lib/datepicker/datepicker.component.d.ts +25 -2
- package/dist/lib/datepicker/datepicker.component.d.ts.map +1 -1
- package/dist/lib/datepicker/datepicker.component.js +98 -42
- package/dist/lib/datepicker/datepicker.component.js.map +1 -1
- package/dist/lib/dialog/dialog.component.d.ts +4 -0
- package/dist/lib/dialog/dialog.component.d.ts.map +1 -1
- package/dist/lib/dialog/dialog.component.js +12 -4
- package/dist/lib/dialog/dialog.component.js.map +1 -1
- package/dist/lib/dialog/dialog.service.js.map +1 -1
- package/dist/lib/dropdown/dropdown.component.d.ts +19 -44
- package/dist/lib/dropdown/dropdown.component.d.ts.map +1 -1
- package/dist/lib/dropdown/dropdown.component.js +37 -76
- package/dist/lib/dropdown/dropdown.component.js.map +1 -1
- package/dist/lib/dropdown/dropdown.scss +0 -16
- package/dist/lib/filter-panel/filter-panel.component.d.ts +8 -0
- package/dist/lib/filter-panel/filter-panel.component.d.ts.map +1 -1
- package/dist/lib/filter-panel/filter-panel.component.js +25 -9
- package/dist/lib/filter-panel/filter-panel.component.js.map +1 -1
- package/dist/lib/numeric-input/numeric-input.component.d.ts +15 -1
- package/dist/lib/numeric-input/numeric-input.component.d.ts.map +1 -1
- package/dist/lib/numeric-input/numeric-input.component.js +36 -9
- package/dist/lib/numeric-input/numeric-input.component.js.map +1 -1
- package/dist/lib/page-search/page-search.component.d.ts +32 -3
- package/dist/lib/page-search/page-search.component.d.ts.map +1 -1
- package/dist/lib/page-search/page-search.component.js +68 -12
- package/dist/lib/page-search/page-search.component.js.map +1 -1
- package/dist/lib/switch/switch.component.d.ts +22 -1
- package/dist/lib/switch/switch.component.d.ts.map +1 -1
- package/dist/lib/switch/switch.component.js +50 -16
- package/dist/lib/switch/switch.component.js.map +1 -1
- package/dist/lib/tabs/tab-chrome-guard.d.ts +2 -0
- package/dist/lib/tabs/tab-chrome-guard.d.ts.map +1 -1
- package/dist/lib/tabs/tab-chrome-guard.js +5 -1
- package/dist/lib/tabs/tab-chrome-guard.js.map +1 -1
- package/dist/lib/window/window.component.d.ts +10 -0
- package/dist/lib/window/window.component.d.ts.map +1 -1
- package/dist/lib/window/window.component.js +27 -7
- package/dist/lib/window/window.component.js.map +1 -1
- package/dist/lib/workspace-tabs/workspace-tab-strip.component.d.ts +10 -0
- package/dist/lib/workspace-tabs/workspace-tab-strip.component.d.ts.map +1 -1
- package/dist/lib/workspace-tabs/workspace-tab-strip.component.js +27 -7
- package/dist/lib/workspace-tabs/workspace-tab-strip.component.js.map +1 -1
- package/dist/public-api.d.ts +2 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +2 -2
|
@@ -2,63 +2,69 @@ import { Component, Input, Output, EventEmitter, forwardRef, HostBinding, ViewCh
|
|
|
2
2
|
import { NgTemplateOutlet } from '@angular/common';
|
|
3
3
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
4
|
import { OverlayModule } from '@angular/cdk/overlay';
|
|
5
|
+
import { MJNamedControlBase } from '../a11y/named-control.base';
|
|
6
|
+
import { WarnIfUnnamed } from '../a11y/unnamed-control-guard';
|
|
5
7
|
import * as i0 from "@angular/core";
|
|
6
8
|
import * as i1 from "@angular/cdk/overlay";
|
|
7
9
|
const _c0 = ["mjComboboxItem"];
|
|
8
10
|
const _c1 = ["trigger"];
|
|
9
11
|
const _c2 = ["comboInput"];
|
|
10
12
|
const _c3 = a0 => ({ $implicit: a0 });
|
|
11
|
-
function
|
|
13
|
+
function MJComboboxComponent_Conditional_9_Template(rf, ctx) { if (rf & 1) {
|
|
12
14
|
const _r1 = i0.ɵɵgetCurrentView();
|
|
13
|
-
i0.ɵɵelementStart(0, "button",
|
|
14
|
-
i0.ɵɵlistener("mousedown", function
|
|
15
|
-
i0.ɵɵelement(1, "i",
|
|
15
|
+
i0.ɵɵelementStart(0, "button", 9);
|
|
16
|
+
i0.ɵɵlistener("mousedown", function MJComboboxComponent_Conditional_9_Template_button_mousedown_0_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.OnClear($event)); });
|
|
17
|
+
i0.ɵɵelement(1, "i", 10);
|
|
16
18
|
i0.ɵɵelementEnd();
|
|
19
|
+
} if (rf & 2) {
|
|
20
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
21
|
+
i0.ɵɵattribute("aria-labelledby", ctx_r1.ClearLabelledBy || null)("aria-label", ctx_r1.ClearLabelledBy ? null : ctx_r1.ClearLabel);
|
|
17
22
|
} }
|
|
18
|
-
function
|
|
23
|
+
function MJComboboxComponent_ng_template_12_For_2_Conditional_1_ng_container_0_Template(rf, ctx) { if (rf & 1) {
|
|
19
24
|
i0.ɵɵelementContainer(0);
|
|
20
25
|
} }
|
|
21
|
-
function
|
|
22
|
-
i0.ɵɵtemplate(0,
|
|
26
|
+
function MJComboboxComponent_ng_template_12_For_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
27
|
+
i0.ɵɵtemplate(0, MJComboboxComponent_ng_template_12_For_2_Conditional_1_ng_container_0_Template, 1, 0, "ng-container", 15);
|
|
23
28
|
} if (rf & 2) {
|
|
24
29
|
const item_r4 = i0.ɵɵnextContext().$implicit;
|
|
25
30
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
26
31
|
i0.ɵɵproperty("ngTemplateOutlet", ctx_r1.ItemTemplate)("ngTemplateOutletContext", i0.ɵɵpureFunction1(2, _c3, item_r4));
|
|
27
32
|
} }
|
|
28
|
-
function
|
|
33
|
+
function MJComboboxComponent_ng_template_12_For_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
29
34
|
i0.ɵɵtext(0);
|
|
30
35
|
} if (rf & 2) {
|
|
31
36
|
const item_r4 = i0.ɵɵnextContext().$implicit;
|
|
32
37
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
33
38
|
i0.ɵɵtextInterpolate1(" ", ctx_r1.GetItemText(item_r4), " ");
|
|
34
39
|
} }
|
|
35
|
-
function
|
|
40
|
+
function MJComboboxComponent_ng_template_12_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
36
41
|
const _r3 = i0.ɵɵgetCurrentView();
|
|
37
|
-
i0.ɵɵelementStart(0, "div",
|
|
38
|
-
i0.ɵɵlistener("mousedown", function
|
|
39
|
-
i0.ɵɵconditionalCreate(1,
|
|
42
|
+
i0.ɵɵelementStart(0, "div", 14);
|
|
43
|
+
i0.ɵɵlistener("mousedown", function MJComboboxComponent_ng_template_12_For_2_Template_div_mousedown_0_listener($event) { const item_r4 = i0.ɵɵrestoreView(_r3).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SelectItem(item_r4, $event)); });
|
|
44
|
+
i0.ɵɵconditionalCreate(1, MJComboboxComponent_ng_template_12_For_2_Conditional_1_Template, 1, 4, "ng-container")(2, MJComboboxComponent_ng_template_12_For_2_Conditional_2_Template, 1, 1);
|
|
40
45
|
i0.ɵɵelementEnd();
|
|
41
46
|
} if (rf & 2) {
|
|
42
47
|
const item_r4 = ctx.$implicit;
|
|
43
48
|
const $index_r5 = ctx.$index;
|
|
44
49
|
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
45
50
|
i0.ɵɵclassProp("mj-dropdown-option--selected", ctx_r1.IsItemSelected(item_r4))("mj-dropdown-option--highlighted", ctx_r1.HighlightedIndex === $index_r5);
|
|
46
|
-
i0.ɵɵattribute("aria-selected", ctx_r1.IsItemSelected(item_r4));
|
|
51
|
+
i0.ɵɵattribute("id", ctx_r1.OptionId($index_r5))("aria-selected", ctx_r1.IsItemSelected(item_r4));
|
|
47
52
|
i0.ɵɵadvance();
|
|
48
53
|
i0.ɵɵconditional(ctx_r1.ItemTemplate ? 1 : 2);
|
|
49
54
|
} }
|
|
50
|
-
function
|
|
51
|
-
i0.ɵɵelementStart(0, "div",
|
|
55
|
+
function MJComboboxComponent_ng_template_12_Conditional_3_Template(rf, ctx) { if (rf & 1) {
|
|
56
|
+
i0.ɵɵelementStart(0, "div", 13);
|
|
52
57
|
i0.ɵɵtext(1, "No data found");
|
|
53
58
|
i0.ɵɵelementEnd();
|
|
54
59
|
} }
|
|
55
|
-
function
|
|
56
|
-
i0.ɵɵelementStart(0, "div",
|
|
57
|
-
i0.ɵɵrepeaterCreate(1,
|
|
58
|
-
i0.ɵɵconditionalCreate(3,
|
|
60
|
+
function MJComboboxComponent_ng_template_12_Template(rf, ctx) { if (rf & 1) {
|
|
61
|
+
i0.ɵɵelementStart(0, "div", 11);
|
|
62
|
+
i0.ɵɵrepeaterCreate(1, MJComboboxComponent_ng_template_12_For_2_Template, 3, 7, "div", 12, i0.ɵɵcomponentInstance().TrackByIndex, true);
|
|
63
|
+
i0.ɵɵconditionalCreate(3, MJComboboxComponent_ng_template_12_Conditional_3_Template, 2, 0, "div", 13);
|
|
59
64
|
i0.ɵɵelementEnd();
|
|
60
65
|
} if (rf & 2) {
|
|
61
66
|
const ctx_r1 = i0.ɵɵnextContext();
|
|
67
|
+
i0.ɵɵattribute("id", ctx_r1.ListboxId)("aria-label", ctx_r1.AriaLabel || null)("aria-labelledby", ctx_r1.AriaLabelledBy || null);
|
|
62
68
|
i0.ɵɵadvance();
|
|
63
69
|
i0.ɵɵrepeater(ctx_r1.FilteredItems);
|
|
64
70
|
i0.ɵɵadvance(2);
|
|
@@ -71,6 +77,20 @@ function MJComboboxComponent_ng_template_8_Template(rf, ctx) { if (rf & 1) {
|
|
|
71
77
|
* that filters the list as you type. When AllowCustom is true, typed text that
|
|
72
78
|
* doesn't match any item is emitted as the value.
|
|
73
79
|
*
|
|
80
|
+
* Every combobox needs an ACCESSIBLE NAME, or it announces as "combobox, collapsed" with no hint of
|
|
81
|
+
* what it selects (WCAG 2.1 4.1.2). Use {@link MJNamedControlBase.AriaLabelledBy} when a visible
|
|
82
|
+
* label already exists and {@link MJNamedControlBase.AriaLabel} when none does. Here the trigger is
|
|
83
|
+
* a real `<input>`, so {@link MJNamedControlBase.InputId} IS a valid `<label for>` target — unlike
|
|
84
|
+
* `mj-dropdown`, whose trigger is a div.
|
|
85
|
+
*
|
|
86
|
+
* @example With a visible label (preferred)
|
|
87
|
+
* ```html
|
|
88
|
+
* <span id="category-label">Category</span>
|
|
89
|
+
* <mj-combobox AriaLabelledBy="category-label" [Data]="categories" TextField="text"
|
|
90
|
+
* ValueField="value" [(ngModel)]="selectedCategory" [ValuePrimitive]="true">
|
|
91
|
+
* </mj-combobox>
|
|
92
|
+
* ```
|
|
93
|
+
*
|
|
74
94
|
* @example
|
|
75
95
|
* ```html
|
|
76
96
|
* <mj-combobox
|
|
@@ -85,7 +105,7 @@ function MJComboboxComponent_ng_template_8_Template(rf, ctx) { if (rf & 1) {
|
|
|
85
105
|
* </mj-combobox>
|
|
86
106
|
* ```
|
|
87
107
|
*/
|
|
88
|
-
export class MJComboboxComponent {
|
|
108
|
+
export class MJComboboxComponent extends MJNamedControlBase {
|
|
89
109
|
set Data(value) {
|
|
90
110
|
this._data = value;
|
|
91
111
|
// Re-resolve display text when data arrives after writeValue
|
|
@@ -135,6 +155,34 @@ export class MJComboboxComponent {
|
|
|
135
155
|
{ originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },
|
|
136
156
|
{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' }
|
|
137
157
|
];
|
|
158
|
+
/**
|
|
159
|
+
* Id of the popup listbox, so the input can point `aria-controls` at it while open — the half of
|
|
160
|
+
* the combobox pattern that makes "collapsed/expanded" refer to something a screen reader can
|
|
161
|
+
* find.
|
|
162
|
+
*/
|
|
163
|
+
get ListboxId() { return `mj-combobox-listbox-${this.NamedControlId}`; }
|
|
164
|
+
/** Id of one rendered option, referenced by {@link ActiveDescendantId}. */
|
|
165
|
+
OptionId(index) { return `mj-combobox-option-${this.NamedControlId}-${index}`; }
|
|
166
|
+
/**
|
|
167
|
+
* `aria-activedescendant` for the input: the option the arrow keys have moved to. Focus stays in
|
|
168
|
+
* the input the whole time, so without this the highlight is a CSS class and nothing else — a
|
|
169
|
+
* screen-reader user arrowing through the list hears no change at all.
|
|
170
|
+
*/
|
|
171
|
+
get ActiveDescendantId() {
|
|
172
|
+
const active = this.IsOpen && this.HighlightedIndex >= 0 && this.HighlightedIndex < this.FilteredItems.length;
|
|
173
|
+
return active ? this.OptionId(this.HighlightedIndex) : null;
|
|
174
|
+
}
|
|
175
|
+
/** `aria-labelledby` id list for the clear button when a VISIBLE label names the combobox. */
|
|
176
|
+
get ClearLabelledBy() { return this.SecondaryLabelledBy('clear-word'); }
|
|
177
|
+
/** `aria-label` for the clear button in the no-visible-label case. */
|
|
178
|
+
get ClearLabel() { return this.SecondaryLabel('Clear', 'Clear'); }
|
|
179
|
+
/** `aria-labelledby` id list for the toggle button when a VISIBLE label names the combobox. */
|
|
180
|
+
get ToggleLabelledBy() { return this.SecondaryLabelledBy('toggle-word'); }
|
|
181
|
+
/**
|
|
182
|
+
* `aria-label` for the toggle button in the no-visible-label case. It had no name at all before
|
|
183
|
+
* #4116 — an unnamed button next to a named input, which announces as "button".
|
|
184
|
+
*/
|
|
185
|
+
get ToggleLabel() { return this.SecondaryLabel('Show options for', 'Show options'); }
|
|
138
186
|
onChange = () => { };
|
|
139
187
|
onTouched = () => { };
|
|
140
188
|
isBlurring = false;
|
|
@@ -178,7 +226,7 @@ export class MJComboboxComponent {
|
|
|
178
226
|
if (!this.isBlurring)
|
|
179
227
|
return;
|
|
180
228
|
this.isBlurring = false;
|
|
181
|
-
this.
|
|
229
|
+
this.commitValue();
|
|
182
230
|
this.Close();
|
|
183
231
|
this.onTouched();
|
|
184
232
|
}, 150);
|
|
@@ -246,7 +294,7 @@ export class MJComboboxComponent {
|
|
|
246
294
|
this.cdr.detectChanges();
|
|
247
295
|
}
|
|
248
296
|
/** Commit the current input text as a value (for AllowCustom or matching item) */
|
|
249
|
-
|
|
297
|
+
commitValue() {
|
|
250
298
|
if (!this.InputText.trim()) {
|
|
251
299
|
// Empty input — clear the value
|
|
252
300
|
if (this.SelectedValue != null) {
|
|
@@ -309,7 +357,7 @@ export class MJComboboxComponent {
|
|
|
309
357
|
this.SelectItem(items[this.HighlightedIndex]);
|
|
310
358
|
}
|
|
311
359
|
else {
|
|
312
|
-
this.
|
|
360
|
+
this.commitValue();
|
|
313
361
|
this.Close();
|
|
314
362
|
}
|
|
315
363
|
break;
|
|
@@ -344,6 +392,7 @@ export class MJComboboxComponent {
|
|
|
344
392
|
registerOnChange(fn) { this.onChange = fn; }
|
|
345
393
|
registerOnTouched(fn) { this.onTouched = fn; }
|
|
346
394
|
setDisabledState(isDisabled) { this.formDisabled = isDisabled; this.syncDisabled(); }
|
|
395
|
+
ngAfterViewInit() { WarnIfUnnamed(this.ComboInput?.nativeElement, 'mj-combobox'); }
|
|
347
396
|
ngOnDestroy() { this.Close(); }
|
|
348
397
|
getDisplayText() {
|
|
349
398
|
if (this.SelectedValue == null)
|
|
@@ -361,7 +410,7 @@ export class MJComboboxComponent {
|
|
|
361
410
|
return -1;
|
|
362
411
|
return this.FilteredItems.findIndex(item => this.IsItemSelected(item));
|
|
363
412
|
}
|
|
364
|
-
static ɵfac = function MJComboboxComponent_Factory(__ngFactoryType__) { return
|
|
413
|
+
static ɵfac = /*@__PURE__*/ (() => { let ɵMJComboboxComponent_BaseFactory; return function MJComboboxComponent_Factory(__ngFactoryType__) { return (ɵMJComboboxComponent_BaseFactory || (ɵMJComboboxComponent_BaseFactory = i0.ɵɵgetInheritedFactory(MJComboboxComponent)))(__ngFactoryType__ || MJComboboxComponent); }; })();
|
|
365
414
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJComboboxComponent, selectors: [["mj-combobox"]], contentQueries: function MJComboboxComponent_ContentQueries(rf, ctx, dirIndex) { if (rf & 1) {
|
|
366
415
|
i0.ɵɵcontentQuery(dirIndex, _c0, 5);
|
|
367
416
|
} if (rf & 2) {
|
|
@@ -379,52 +428,71 @@ export class MJComboboxComponent {
|
|
|
379
428
|
provide: NG_VALUE_ACCESSOR,
|
|
380
429
|
useExisting: forwardRef(() => MJComboboxComponent),
|
|
381
430
|
multi: true
|
|
382
|
-
}])], decls:
|
|
431
|
+
}]), i0.ɵɵInheritDefinitionFeature], decls: 13, vars: 26, consts: [["trigger", "", "overlayOrigin", "cdkOverlayOrigin"], ["comboInput", ""], ["cdkOverlayOrigin", "", 1, "mj-combobox"], ["type", "text", "role", "combobox", "aria-haspopup", "listbox", "autocomplete", "off", 1, "mj-input", "mj-combobox-input", 3, "input", "focus", "keydown", "blur", "placeholder", "value", "disabled"], ["aria-hidden", "true", 1, "mj-combobox-sr-only"], ["type", "button", "tabindex", "-1", 1, "mj-combobox-clear"], ["type", "button", "tabindex", "-1", 1, "mj-combobox-toggle", 3, "mousedown", "disabled"], [1, "fa-solid", "fa-chevron-down"], ["cdkConnectedOverlay", "", "cdkConnectedOverlayBackdropClass", "mj-dropdown-backdrop", 3, "backdropClick", "detach", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayPositions", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHasBackdrop"], ["type", "button", "tabindex", "-1", 1, "mj-combobox-clear", 3, "mousedown"], [1, "fa-solid", "fa-times"], ["role", "listbox", 1, "mj-dropdown-panel"], ["role", "option", 1, "mj-dropdown-option", 3, "mj-dropdown-option--selected", "mj-dropdown-option--highlighted"], [1, "mj-dropdown-no-data"], ["role", "option", 1, "mj-dropdown-option", 3, "mousedown"], [4, "ngTemplateOutlet", "ngTemplateOutletContext"]], template: function MJComboboxComponent_Template(rf, ctx) { if (rf & 1) {
|
|
383
432
|
i0.ɵɵelementStart(0, "div", 2, 0)(3, "input", 3, 1);
|
|
384
433
|
i0.ɵɵlistener("input", function MJComboboxComponent_Template_input_input_3_listener($event) { return ctx.OnInput($event); })("focus", function MJComboboxComponent_Template_input_focus_3_listener() { return ctx.OnFocus(); })("keydown", function MJComboboxComponent_Template_input_keydown_3_listener($event) { return ctx.OnKeyDown($event); })("blur", function MJComboboxComponent_Template_input_blur_3_listener() { return ctx.OnInputBlur(); });
|
|
385
434
|
i0.ɵɵelementEnd();
|
|
386
|
-
i0.ɵɵ
|
|
387
|
-
i0.ɵɵ
|
|
388
|
-
i0.ɵɵ
|
|
389
|
-
i0.ɵɵ
|
|
435
|
+
i0.ɵɵelementStart(5, "span", 4);
|
|
436
|
+
i0.ɵɵtext(6, "Clear");
|
|
437
|
+
i0.ɵɵelementEnd();
|
|
438
|
+
i0.ɵɵelementStart(7, "span", 4);
|
|
439
|
+
i0.ɵɵtext(8, "Show options for");
|
|
440
|
+
i0.ɵɵelementEnd();
|
|
441
|
+
i0.ɵɵconditionalCreate(9, MJComboboxComponent_Conditional_9_Template, 2, 2, "button", 5);
|
|
442
|
+
i0.ɵɵelementStart(10, "button", 6);
|
|
443
|
+
i0.ɵɵlistener("mousedown", function MJComboboxComponent_Template_button_mousedown_10_listener($event) { return ctx.OnToggleMouseDown($event); });
|
|
444
|
+
i0.ɵɵelement(11, "i", 7);
|
|
390
445
|
i0.ɵɵelementEnd()();
|
|
391
|
-
i0.ɵɵtemplate(
|
|
392
|
-
i0.ɵɵlistener("backdropClick", function
|
|
446
|
+
i0.ɵɵtemplate(12, MJComboboxComponent_ng_template_12_Template, 4, 4, "ng-template", 8);
|
|
447
|
+
i0.ɵɵlistener("backdropClick", function MJComboboxComponent_Template_ng_template_backdropClick_12_listener() { return ctx.Close(); })("detach", function MJComboboxComponent_Template_ng_template_detach_12_listener() { return ctx.Close(); });
|
|
393
448
|
} if (rf & 2) {
|
|
394
449
|
const overlayOrigin_r6 = i0.ɵɵreference(2);
|
|
395
450
|
i0.ɵɵclassProp("mj-combobox--open", ctx.IsOpen)("mj-combobox--disabled", ctx.IsDisabled);
|
|
396
|
-
i0.ɵɵattribute("aria-expanded", ctx.IsOpen);
|
|
397
451
|
i0.ɵɵadvance(3);
|
|
398
452
|
i0.ɵɵproperty("placeholder", ctx.Placeholder)("value", ctx.InputText)("disabled", ctx.IsDisabled);
|
|
453
|
+
i0.ɵɵattribute("id", ctx.InputId || null)("aria-label", ctx.AriaLabel || null)("aria-labelledby", ctx.AriaLabelledBy || null)("aria-describedby", ctx.AriaDescribedBy || null)("aria-expanded", ctx.IsOpen)("aria-autocomplete", ctx.Filterable ? "list" : "none")("aria-controls", ctx.IsOpen ? ctx.ListboxId : null)("aria-activedescendant", ctx.ActiveDescendantId);
|
|
454
|
+
i0.ɵɵadvance(2);
|
|
455
|
+
i0.ɵɵattribute("id", ctx.SecondaryWordId("clear-word"));
|
|
456
|
+
i0.ɵɵadvance(2);
|
|
457
|
+
i0.ɵɵattribute("id", ctx.SecondaryWordId("toggle-word"));
|
|
399
458
|
i0.ɵɵadvance(2);
|
|
400
|
-
i0.ɵɵconditional(ctx.InputText && !ctx.IsDisabled ?
|
|
459
|
+
i0.ɵɵconditional(ctx.InputText && !ctx.IsDisabled ? 9 : -1);
|
|
401
460
|
i0.ɵɵadvance();
|
|
402
461
|
i0.ɵɵproperty("disabled", ctx.IsDisabled);
|
|
462
|
+
i0.ɵɵattribute("aria-labelledby", ctx.ToggleLabelledBy || null)("aria-label", ctx.ToggleLabelledBy ? null : ctx.ToggleLabel);
|
|
403
463
|
i0.ɵɵadvance(2);
|
|
404
464
|
i0.ɵɵproperty("cdkConnectedOverlayOrigin", overlayOrigin_r6)("cdkConnectedOverlayOpen", ctx.IsOpen)("cdkConnectedOverlayPositions", ctx.Positions)("cdkConnectedOverlayWidth", ctx.TriggerWidth)("cdkConnectedOverlayHasBackdrop", true);
|
|
405
|
-
} }, dependencies: [NgTemplateOutlet, OverlayModule, i1.CdkConnectedOverlay, i1.CdkOverlayOrigin],
|
|
465
|
+
} }, dependencies: [NgTemplateOutlet, OverlayModule, i1.CdkConnectedOverlay, i1.CdkOverlayOrigin], styles: ["\n\n\n\n\n\n\n\n\n .mj-combobox-sr-only[_ngcontent-%COMP%] {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }"] });
|
|
406
466
|
}
|
|
407
467
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJComboboxComponent, [{
|
|
408
468
|
type: Component,
|
|
409
|
-
args: [{
|
|
410
|
-
selector: 'mj-combobox',
|
|
411
|
-
standalone: true,
|
|
412
|
-
imports: [NgTemplateOutlet, OverlayModule],
|
|
413
|
-
template: `
|
|
469
|
+
args: [{ selector: 'mj-combobox', standalone: true, imports: [NgTemplateOutlet, OverlayModule], template: `
|
|
414
470
|
<div
|
|
415
471
|
class="mj-combobox"
|
|
416
472
|
#trigger
|
|
417
473
|
cdkOverlayOrigin
|
|
418
474
|
#overlayOrigin="cdkOverlayOrigin"
|
|
419
475
|
[class.mj-combobox--open]="IsOpen"
|
|
420
|
-
[class.mj-combobox--disabled]="IsDisabled"
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
476
|
+
[class.mj-combobox--disabled]="IsDisabled">
|
|
477
|
+
<!--
|
|
478
|
+
role="combobox" belongs on the INPUT, not on this wrapper. The wrapper is not focusable, so
|
|
479
|
+
a screen reader never lands on it: its role, its name and its expanded state all went
|
|
480
|
+
unannounced while the element the user actually focused announced as a plain textbox.
|
|
481
|
+
-->
|
|
424
482
|
<input
|
|
425
483
|
#comboInput
|
|
426
484
|
class="mj-input mj-combobox-input"
|
|
427
485
|
type="text"
|
|
486
|
+
role="combobox"
|
|
487
|
+
[attr.id]="InputId || null"
|
|
488
|
+
[attr.aria-label]="AriaLabel || null"
|
|
489
|
+
[attr.aria-labelledby]="AriaLabelledBy || null"
|
|
490
|
+
[attr.aria-describedby]="AriaDescribedBy || null"
|
|
491
|
+
[attr.aria-expanded]="IsOpen"
|
|
492
|
+
aria-haspopup="listbox"
|
|
493
|
+
[attr.aria-autocomplete]="Filterable ? 'list' : 'none'"
|
|
494
|
+
[attr.aria-controls]="IsOpen ? ListboxId : null"
|
|
495
|
+
[attr.aria-activedescendant]="ActiveDescendantId"
|
|
428
496
|
[placeholder]="Placeholder"
|
|
429
497
|
[value]="InputText"
|
|
430
498
|
[disabled]="IsDisabled"
|
|
@@ -433,13 +501,25 @@ export class MJComboboxComponent {
|
|
|
433
501
|
(keydown)="OnKeyDown($event)"
|
|
434
502
|
(blur)="OnInputBlur()"
|
|
435
503
|
autocomplete="off" />
|
|
504
|
+
<!--
|
|
505
|
+
The fixed words live in hidden spans rather than in concatenated strings so the
|
|
506
|
+
AriaLabelledBy path can name these two buttons from the same visible label that names the
|
|
507
|
+
combobox: aria-labelledby takes an ID LIST, so the word plus the label's own text is
|
|
508
|
+
composed by the accessibility tree without this component ever seeing that text.
|
|
509
|
+
A hidden node that is DIRECTLY referenced by aria-labelledby is still included in the name
|
|
510
|
+
(accname §4.1), so aria-hidden keeps the word out of the reading order without costing the
|
|
511
|
+
composed name.
|
|
512
|
+
-->
|
|
513
|
+
<span class="mj-combobox-sr-only" aria-hidden="true" [attr.id]="SecondaryWordId('clear-word')">Clear</span>
|
|
514
|
+
<span class="mj-combobox-sr-only" aria-hidden="true" [attr.id]="SecondaryWordId('toggle-word')">Show options for</span>
|
|
436
515
|
@if (InputText && !IsDisabled) {
|
|
437
516
|
<button
|
|
438
517
|
class="mj-combobox-clear"
|
|
439
518
|
type="button"
|
|
440
519
|
tabindex="-1"
|
|
441
520
|
(mousedown)="OnClear($event)"
|
|
442
|
-
aria-
|
|
521
|
+
[attr.aria-labelledby]="ClearLabelledBy || null"
|
|
522
|
+
[attr.aria-label]="ClearLabelledBy ? null : ClearLabel">
|
|
443
523
|
<i class="fa-solid fa-times"></i>
|
|
444
524
|
</button>
|
|
445
525
|
}
|
|
@@ -448,7 +528,9 @@ export class MJComboboxComponent {
|
|
|
448
528
|
type="button"
|
|
449
529
|
tabindex="-1"
|
|
450
530
|
[disabled]="IsDisabled"
|
|
451
|
-
(mousedown)="OnToggleMouseDown($event)"
|
|
531
|
+
(mousedown)="OnToggleMouseDown($event)"
|
|
532
|
+
[attr.aria-labelledby]="ToggleLabelledBy || null"
|
|
533
|
+
[attr.aria-label]="ToggleLabelledBy ? null : ToggleLabel">
|
|
452
534
|
<i class="fa-solid fa-chevron-down"></i>
|
|
453
535
|
</button>
|
|
454
536
|
</div>
|
|
@@ -463,13 +545,17 @@ export class MJComboboxComponent {
|
|
|
463
545
|
cdkConnectedOverlayBackdropClass="mj-dropdown-backdrop"
|
|
464
546
|
(backdropClick)="Close()"
|
|
465
547
|
(detach)="Close()">
|
|
466
|
-
<div class="mj-dropdown-panel" role="listbox"
|
|
548
|
+
<div class="mj-dropdown-panel" role="listbox"
|
|
549
|
+
[attr.id]="ListboxId"
|
|
550
|
+
[attr.aria-label]="AriaLabel || null"
|
|
551
|
+
[attr.aria-labelledby]="AriaLabelledBy || null">
|
|
467
552
|
@for (item of FilteredItems; track TrackByIndex($index)) {
|
|
468
553
|
<div
|
|
469
554
|
class="mj-dropdown-option"
|
|
470
555
|
[class.mj-dropdown-option--selected]="IsItemSelected(item)"
|
|
471
556
|
[class.mj-dropdown-option--highlighted]="HighlightedIndex === $index"
|
|
472
557
|
role="option"
|
|
558
|
+
[attr.id]="OptionId($index)"
|
|
473
559
|
[attr.aria-selected]="IsItemSelected(item)"
|
|
474
560
|
(mousedown)="SelectItem(item, $event)">
|
|
475
561
|
@if (ItemTemplate) {
|
|
@@ -484,13 +570,11 @@ export class MJComboboxComponent {
|
|
|
484
570
|
}
|
|
485
571
|
</div>
|
|
486
572
|
</ng-template>
|
|
487
|
-
`,
|
|
488
|
-
providers: [{
|
|
573
|
+
`, providers: [{
|
|
489
574
|
provide: NG_VALUE_ACCESSOR,
|
|
490
575
|
useExisting: forwardRef(() => MJComboboxComponent),
|
|
491
576
|
multi: true
|
|
492
|
-
}]
|
|
493
|
-
}]
|
|
577
|
+
}], styles: ["\n /*\n * Component-scoped ON PURPOSE, unlike the rest of this control's styling, which ships as a global\n * stylesheet the host application imports. A host that skips that import gets unstyled chrome \u2014\n * survivable \u2014 but a hidden-word span that is not hidden renders its word as literal text in the\n * middle of the field. The rule that hides it therefore has to travel with the component.\n *\n * Not display:none or visibility:hidden \u2014 both remove the element from the accessibility tree,\n * which is the one thing this element exists to be in.\n */\n .mj-combobox-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n "] }]
|
|
494
578
|
}], null, { Data: [{
|
|
495
579
|
type: Input
|
|
496
580
|
}], TextField: [{
|
|
@@ -524,5 +608,5 @@ export class MJComboboxComponent {
|
|
|
524
608
|
type: HostBinding,
|
|
525
609
|
args: ['class.mj-combobox-host']
|
|
526
610
|
}] }); })();
|
|
527
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJComboboxComponent, { className: "MJComboboxComponent", filePath: "lib/combobox/combobox.component.ts", lineNumber:
|
|
611
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJComboboxComponent, { className: "MJComboboxComponent", filePath: "lib/combobox/combobox.component.ts", lineNumber: 195 }); })();
|
|
528
612
|
//# sourceMappingURL=combobox.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combobox.component.js","sourceRoot":"","sources":["../../../src/lib/combobox/combobox.component.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n Input,\n Output,\n EventEmitter,\n forwardRef,\n HostBinding,\n ElementRef,\n ViewChild,\n ContentChild,\n TemplateRef,\n OnDestroy,\n inject,\n ChangeDetectorRef\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';\nimport { OverlayModule, ConnectedPosition } from '@angular/cdk/overlay';\n\n/**\n * mj-combobox — Editable dropdown with filtering and optional custom values.\n *\n * Replaces `<kendo-combobox>`. Unlike mj-dropdown, the trigger is a text input\n * that filters the list as you type. When AllowCustom is true, typed text that\n * doesn't match any item is emitted as the value.\n *\n * @example\n * ```html\n * <mj-combobox\n * [Data]=\"categories\"\n * TextField=\"text\"\n * ValueField=\"value\"\n * [(ngModel)]=\"selectedCategory\"\n * [ValuePrimitive]=\"true\"\n * [AllowCustom]=\"true\"\n * [Filterable]=\"true\"\n * Placeholder=\"Select or enter new...\">\n * </mj-combobox>\n * ```\n */\n@Component({\n selector: 'mj-combobox',\n standalone: true,\n imports: [NgTemplateOutlet, OverlayModule],\n template: `\n <div\n class=\"mj-combobox\"\n #trigger\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n [class.mj-combobox--open]=\"IsOpen\"\n [class.mj-combobox--disabled]=\"IsDisabled\"\n role=\"combobox\"\n [attr.aria-expanded]=\"IsOpen\"\n aria-haspopup=\"listbox\">\n <input\n #comboInput\n class=\"mj-input mj-combobox-input\"\n type=\"text\"\n [placeholder]=\"Placeholder\"\n [value]=\"InputText\"\n [disabled]=\"IsDisabled\"\n (input)=\"OnInput($event)\"\n (focus)=\"OnFocus()\"\n (keydown)=\"OnKeyDown($event)\"\n (blur)=\"OnInputBlur()\"\n autocomplete=\"off\" />\n @if (InputText && !IsDisabled) {\n <button\n class=\"mj-combobox-clear\"\n type=\"button\"\n tabindex=\"-1\"\n (mousedown)=\"OnClear($event)\"\n aria-label=\"Clear\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n <button\n class=\"mj-combobox-toggle\"\n type=\"button\"\n tabindex=\"-1\"\n [disabled]=\"IsDisabled\"\n (mousedown)=\"OnToggleMouseDown($event)\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n </div>\n\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"IsOpen\"\n [cdkConnectedOverlayPositions]=\"Positions\"\n [cdkConnectedOverlayWidth]=\"TriggerWidth\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"mj-dropdown-backdrop\"\n (backdropClick)=\"Close()\"\n (detach)=\"Close()\">\n <div class=\"mj-dropdown-panel\" role=\"listbox\">\n @for (item of FilteredItems; track TrackByIndex($index)) {\n <div\n class=\"mj-dropdown-option\"\n [class.mj-dropdown-option--selected]=\"IsItemSelected(item)\"\n [class.mj-dropdown-option--highlighted]=\"HighlightedIndex === $index\"\n role=\"option\"\n [attr.aria-selected]=\"IsItemSelected(item)\"\n (mousedown)=\"SelectItem(item, $event)\">\n @if (ItemTemplate) {\n <ng-container *ngTemplateOutlet=\"ItemTemplate; context: { $implicit: item }\"></ng-container>\n } @else {\n {{ GetItemText(item) }}\n }\n </div>\n }\n @if (FilteredItems.length === 0) {\n <div class=\"mj-dropdown-no-data\">No data found</div>\n }\n </div>\n </ng-template>\n `,\n providers: [{\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => MJComboboxComponent),\n multi: true\n }]\n})\nexport class MJComboboxComponent implements ControlValueAccessor, OnDestroy {\n @Input()\n set Data(value: Record<string, unknown>[] | string[] | readonly unknown[] | null) {\n this._data = value;\n // Re-resolve display text when data arrives after writeValue\n if (this.SelectedValue != null && !this.InputText) {\n this.InputText = this.getDisplayText();\n }\n }\n get Data(): Record<string, unknown>[] | string[] | readonly unknown[] | null { return this._data; }\n private _data: Record<string, unknown>[] | string[] | readonly unknown[] | null = [];\n @Input() TextField = '';\n @Input() ValueField = '';\n @Input() Filterable = true;\n @Input() ValuePrimitive = false;\n /**\n * Host-driven disable. Composed with Angular Forms' `setDisabledState()` into `IsDisabled`\n * (the actual gate) — see `syncDisabled`. A setter, not a bare field, because this input is\n * routinely bound to an expression that changes over the control's lifetime, and the gate has\n * to follow it every time.\n */\n @Input()\n set Disabled(value: boolean) {\n this.disabledInput = value;\n this.syncDisabled();\n }\n get Disabled(): boolean {\n return this.disabledInput;\n }\n @Input() Placeholder = '';\n @Input() AllowCustom = false;\n\n @Output() ValueChange = new EventEmitter<unknown>();\n @Output() FilterChange = new EventEmitter<string>();\n\n @ContentChild('mjComboboxItem') ItemTemplate: TemplateRef<{ $implicit: unknown }> | null = null;\n\n @ViewChild('trigger') private triggerEl!: ElementRef<HTMLElement>;\n @ViewChild('comboInput') ComboInput!: ElementRef<HTMLInputElement>;\n\n @HostBinding('class.mj-combobox-host') readonly hostClass = true;\n\n private cdr = inject(ChangeDetectorRef);\n\n IsOpen = false;\n /**\n * The single gate on `Toggle()` / `Open()` — true when EITHER the `Disabled` input or Angular\n * Forms says so. Never assign it directly; go through `syncDisabled()`.\n */\n IsDisabled = false;\n HighlightedIndex = -1;\n SelectedValue: unknown = null;\n TriggerWidth = 0;\n InputText = '';\n\n Positions: ConnectedPosition[] = [\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' }\n ];\n\n private onChange: (value: unknown) => void = () => {};\n private onTouched: () => void = () => {};\n private isBlurring = false;\n\n get FilteredItems(): unknown[] {\n const data = (this.Data ?? []) as unknown[];\n if (!this.Filterable || !this.InputText) return data;\n const search = this.InputText.toLowerCase();\n return data.filter(item => this.GetItemText(item).toLowerCase().includes(search));\n }\n\n OnInput(event: Event): void {\n this.InputText = (event.target as HTMLInputElement).value;\n this.HighlightedIndex = 0;\n this.FilterChange.emit(this.InputText);\n if (!this.IsOpen) this.Open();\n this.cdr.detectChanges();\n }\n\n OnFocus(): void {\n if (!this.IsOpen) this.Open();\n }\n\n OnToggleMouseDown(event: Event): void {\n event.preventDefault(); // Prevent blur on the input\n this.Toggle();\n }\n\n OnClear(event: Event): void {\n event.preventDefault();\n event.stopPropagation();\n this.isBlurring = false;\n this.InputText = '';\n this.SelectedValue = null;\n this.onChange(null);\n this.ValueChange.emit(null);\n this.Close();\n this.cdr.detectChanges();\n }\n\n OnInputBlur(): void {\n this.isBlurring = true;\n setTimeout(() => {\n if (!this.isBlurring) return;\n this.isBlurring = false;\n this.CommitValue();\n this.Close();\n this.onTouched();\n }, 150);\n }\n\n Toggle(): void {\n if (this.IsDisabled) return;\n this.IsOpen ? this.Close() : this.Open();\n }\n\n Open(): void {\n if (this.IsDisabled || this.IsOpen) return;\n this.TriggerWidth = this.triggerEl?.nativeElement.offsetWidth ?? 200;\n this.IsOpen = true;\n this.HighlightedIndex = this.getSelectedIndex();\n this.cdr.detectChanges();\n }\n\n Close(): void {\n if (!this.IsOpen) return;\n this.resetPanelState();\n this.cdr.detectChanges();\n }\n\n /**\n * Panel state only — no change detection. Split out of `Close()` because `syncDisabled()` can\n * run from an @Input setter, i.e. DURING the parent's change-detection pass, where a nested\n * `detectChanges()` re-enters CD and trips NG0100 on the parent's own bindings.\n */\n private resetPanelState(): void {\n this.IsOpen = false;\n this.HighlightedIndex = -1;\n }\n\n /** Backing field for the `Disabled` input. */\n private disabledInput = false;\n /** The forms-driven disabled state, kept SEPARATE so neither source can stomp the other. */\n private formDisabled = false;\n\n /**\n * Recompute the gate from both of its sources. Called whenever either changes.\n *\n * `IsDisabled` is derived state, and the only thing that assigned it was `setDisabledState()`.\n * The forms-driven half was in fact fine — `setUpControl` also wires `registerOnDisabledChange`,\n * so that hook fires on every `control.disable()`/`enable()`, not just at registration. What had\n * no recompute path at all was the `Disabled` @Input: a plain field, so the gate froze at\n * whatever the first compose produced and every later change to the input was dropped.\n */\n private syncDisabled(): void {\n const disabled = this.disabledInput || this.formDisabled;\n if (disabled === this.IsDisabled) return;\n this.IsDisabled = disabled;\n if (disabled) this.resetPanelState();\n this.cdr.markForCheck();\n }\n\n SelectItem(item: unknown, event?: Event): void {\n event?.preventDefault();\n event?.stopPropagation();\n this.isBlurring = false;\n\n const value = this.ValuePrimitive && this.ValueField ? this.GetItemValue(item) : item;\n this.SelectedValue = value;\n this.InputText = this.GetItemText(item);\n this.onChange(value);\n this.ValueChange.emit(value);\n this.Close();\n this.cdr.detectChanges();\n }\n\n /** Commit the current input text as a value (for AllowCustom or matching item) */\n private CommitValue(): void {\n if (!this.InputText.trim()) {\n // Empty input — clear the value\n if (this.SelectedValue != null) {\n this.SelectedValue = null;\n this.onChange(null);\n this.ValueChange.emit(null);\n }\n return;\n }\n\n // Try to find a matching item\n const data = (this.Data ?? []) as unknown[];\n const match = data.find(item => this.GetItemText(item).toLowerCase() === this.InputText.toLowerCase());\n if (match) {\n const value = this.ValuePrimitive && this.ValueField ? this.GetItemValue(match) : match;\n if (value !== this.SelectedValue) {\n this.SelectedValue = value;\n this.InputText = this.GetItemText(match);\n this.onChange(value);\n this.ValueChange.emit(value);\n }\n } else if (this.AllowCustom) {\n // No match but custom values allowed — emit the typed text\n this.SelectedValue = this.InputText;\n this.onChange(this.InputText);\n this.ValueChange.emit(this.InputText);\n } else {\n // No match and no custom — revert to previous display\n this.InputText = this.getDisplayText();\n }\n }\n\n IsItemSelected(item: unknown): boolean {\n if (this.SelectedValue == null) return false;\n if (this.ValuePrimitive && this.ValueField) return this.GetItemValue(item) === this.SelectedValue;\n if (this.ValueField && typeof item === 'object' && typeof this.SelectedValue === 'object')\n return this.GetItemValue(item) === this.GetItemValue(this.SelectedValue);\n return item === this.SelectedValue;\n }\n\n OnKeyDown(event: KeyboardEvent): void {\n const items = this.FilteredItems;\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n if (!this.IsOpen) this.Open();\n else this.HighlightedIndex = Math.min(this.HighlightedIndex + 1, items.length - 1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n if (this.IsOpen) this.HighlightedIndex = Math.max(this.HighlightedIndex - 1, 0);\n break;\n case 'Enter':\n event.preventDefault();\n if (this.IsOpen && this.HighlightedIndex >= 0 && this.HighlightedIndex < items.length) {\n this.SelectItem(items[this.HighlightedIndex]);\n } else {\n this.CommitValue();\n this.Close();\n }\n break;\n case 'Escape':\n event.preventDefault();\n this.InputText = this.getDisplayText();\n this.Close();\n break;\n }\n }\n\n GetItemText(item: unknown): string {\n if (item == null) return '';\n if (typeof item === 'string') return item;\n if (this.TextField && typeof item === 'object') return String((item as Record<string, unknown>)[this.TextField] ?? '');\n return String(item);\n }\n\n GetItemValue(item: unknown): unknown {\n if (typeof item === 'string') return item;\n if (this.ValueField && typeof item === 'object' && item != null) return (item as Record<string, unknown>)[this.ValueField];\n return item;\n }\n\n TrackByIndex(index: number): number { return index; }\n\n writeValue(value: unknown): void {\n this.SelectedValue = value;\n this.InputText = this.getDisplayText();\n }\n\n registerOnChange(fn: (value: unknown) => void): void { this.onChange = fn; }\n registerOnTouched(fn: () => void): void { this.onTouched = fn; }\n setDisabledState(isDisabled: boolean): void { this.formDisabled = isDisabled; this.syncDisabled(); }\n ngOnDestroy(): void { this.Close(); }\n\n private getDisplayText(): string {\n if (this.SelectedValue == null) return '';\n if (this.ValuePrimitive && this.ValueField) {\n const found = ((this.Data ?? []) as unknown[]).find(item => this.GetItemValue(item) === this.SelectedValue);\n return found ? this.GetItemText(found) : String(this.SelectedValue);\n }\n if (typeof this.SelectedValue === 'string') return this.SelectedValue;\n return this.GetItemText(this.SelectedValue as Record<string, unknown>);\n }\n\n private getSelectedIndex(): number {\n if (this.SelectedValue == null) return -1;\n return this.FilteredItems.findIndex(item => this.IsItemSelected(item));\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"combobox.component.js","sourceRoot":"","sources":["../../../src/lib/combobox/combobox.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EACT,KAAK,EACL,MAAM,EACN,YAAY,EACZ,UAAU,EACV,WAAW,EAEX,SAAS,EACT,YAAY,EAGZ,MAAM,EACN,iBAAiB,EAClB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAwB,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,aAAa,EAAqB,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;;;;;;;;;IAwFtD,iCAM0D;IAFxD,qMAAa,sBAAe,KAAC;IAG7B,wBAAiC;IACnC,iBAAS;;;;;;IAsCH,wBAA4F;;;IAA5F,0HAA6E;;;;IAA9B,AAAhC,sDAAgC,gEAA4B;;;IAE3E,YACF;;;;IADE,4DACF;;;;IAZF,+BAOyC;IAAvC,oOAAa,kCAAwB,KAAC;IAGpC,AAFF,gHAAoB,0EAEX;IAGX,iBAAM;;;;;IAVJ,AADA,8EAA2D,0EACU;;IAKrE,cAIC;IAJD,6CAIC;;;IAIH,+BAAiC;IAAA,6BAAa;IAAA,iBAAM;;;IArBxD,+BAGkD;IAChD,uIAeC;IACD,qGAAkC;IAGpC,iBAAM;;;;IAnBJ,cAeC;IAfD,mCAeC;IACD,eAEC;IAFD,4DAEC;;AA5IT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AA0IH,MAAM,OAAO,mBAAoB,SAAQ,kBAAkB;IACzD,IACI,IAAI,CAAC,KAAuE;QAC9E,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,6DAA6D;QAC7D,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YAClD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;IACD,IAAI,IAAI,KAAuE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3F,KAAK,GAAqE,EAAE,CAAC;IAC5E,SAAS,GAAG,EAAE,CAAC;IACf,UAAU,GAAG,EAAE,CAAC;IAChB,UAAU,GAAG,IAAI,CAAC;IAClB,cAAc,GAAG,KAAK,CAAC;IAChC;;;;;OAKG;IACH,IACI,QAAQ,CAAC,KAAc;QACzB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IACD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IACQ,WAAW,GAAG,EAAE,CAAC;IACjB,WAAW,GAAG,KAAK,CAAC;IAEnB,WAAW,GAAG,IAAI,YAAY,EAAW,CAAC;IAC1C,YAAY,GAAG,IAAI,YAAY,EAAU,CAAC;IAEpB,YAAY,GAA+C,IAAI,CAAC;IAElE,SAAS,CAA2B;IACzC,UAAU,CAAgC;IAEnB,SAAS,GAAG,IAAI,CAAC;IAEzD,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAExC,MAAM,GAAG,KAAK,CAAC;IACf;;;OAGG;IACH,UAAU,GAAG,KAAK,CAAC;IACnB,gBAAgB,GAAG,CAAC,CAAC,CAAC;IACtB,aAAa,GAAY,IAAI,CAAC;IAC9B,YAAY,GAAG,CAAC,CAAC;IACjB,SAAS,GAAG,EAAE,CAAC;IAEf,SAAS,GAAwB;QAC/B,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE;QAC3E,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE;KAC5E,CAAC;IAEF;;;;OAIG;IACH,IAAI,SAAS,KAAa,OAAO,uBAAuB,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;IAEhF,2EAA2E;IAC3E,QAAQ,CAAC,KAAa,IAAY,OAAO,sBAAsB,IAAI,CAAC,cAAc,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;IAEhG;;;;OAIG;IACH,IAAI,kBAAkB;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;QAC9G,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,CAAC;IAED,8FAA8F;IAC9F,IAAI,eAAe,KAAa,OAAO,IAAI,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAEhF,sEAAsE;IACtE,IAAI,UAAU,KAAa,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAE1E,+FAA+F;IAC/F,IAAI,gBAAgB,KAAa,OAAO,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAElF;;;OAGG;IACH,IAAI,WAAW,KAAa,OAAO,IAAI,CAAC,cAAc,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IAErF,QAAQ,GAA6B,GAAG,EAAE,GAAE,CAAC,CAAC;IAC9C,SAAS,GAAe,GAAG,EAAE,GAAE,CAAC,CAAC;IACjC,UAAU,GAAG,KAAK,CAAC;IAE3B,IAAI,aAAa;QACf,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAc,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QACrD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACpF,CAAC;IAED,OAAO,CAAC,KAAY;QAClB,IAAI,CAAC,SAAS,GAAI,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;QAC1D,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC;IAED,iBAAiB,CAAC,KAAY;QAC5B,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,4BAA4B;QACpD,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,OAAO,CAAC,KAAY;QAClB,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED,WAAW;QACT,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,IAAI,CAAC,UAAU;gBAAE,OAAO;YAC7B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC,WAAW,EAAE,CAAC;YACnB,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC;IAED,MAAM;QACJ,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO;QAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC3C,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QAC3C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,WAAW,IAAI,GAAG,CAAC;QACrE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAChD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QACzB,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACK,eAAe;QACrB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,8CAA8C;IACtC,aAAa,GAAG,KAAK,CAAC;IAC9B,4FAA4F;IACpF,YAAY,GAAG,KAAK,CAAC;IAE7B;;;;;;;;OAQG;IACK,YAAY;QAClB,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,YAAY,CAAC;QACzD,IAAI,QAAQ,KAAK,IAAI,CAAC,UAAU;YAAE,OAAO;QACzC,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC;QAC3B,IAAI,QAAQ;YAAE,IAAI,CAAC,eAAe,EAAE,CAAC;QACrC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,CAAC;IAC1B,CAAC;IAED,UAAU,CAAC,IAAa,EAAE,KAAa;QACrC,KAAK,EAAE,cAAc,EAAE,CAAC;QACxB,KAAK,EAAE,eAAe,EAAE,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QAExB,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACtF,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACrB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC3B,CAAC;IAED,kFAAkF;IAC1E,WAAW;QACjB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3B,gCAAgC;YAChC,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,EAAE,CAAC;gBAC/B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;gBAC1B,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACpB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9B,CAAC;YACD,OAAO;QACT,CAAC;QAED,8BAA8B;QAC9B,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAc,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;QACvG,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YACxF,IAAI,KAAK,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;gBACjC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;gBAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBACzC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBACrB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC5B,2DAA2D;YAC3D,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC;YACpC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9B,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,sDAAsD;YACtD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;IAED,cAAc,CAAC,IAAa;QAC1B,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI;YAAE,OAAO,KAAK,CAAC;QAC7C,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC;QAClG,IAAI,IAAI,CAAC,UAAU,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ;YACvF,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC3E,OAAO,IAAI,KAAK,IAAI,CAAC,aAAa,CAAC;IACrC,CAAC;IAED,SAAS,CAAC,KAAoB;QAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC;QACjC,QAAQ,KAAK,CAAC,GAAG,EAAE,CAAC;YAClB,KAAK,WAAW;gBACd,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,CAAC,IAAI,CAAC,MAAM;oBAAE,IAAI,CAAC,IAAI,EAAE,CAAC;;oBACzB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,GAAG,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBACnF,MAAM;YACR,KAAK,SAAS;gBACZ,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,IAAI,CAAC,MAAM;oBAAE,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;gBAChF,MAAM;YACR,KAAK,OAAO;gBACV,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;oBACtF,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;gBAChD,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,WAAW,EAAE,CAAC;oBACnB,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,CAAC;gBACD,MAAM;YACR,KAAK,QAAQ;gBACX,KAAK,CAAC,cAAc,EAAE,CAAC;gBACvB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;gBACvC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACb,MAAM;QACV,CAAC;IACH,CAAC;IAED,WAAW,CAAC,IAAa;QACvB,IAAI,IAAI,IAAI,IAAI;YAAE,OAAO,EAAE,CAAC;QAC5B,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,IAAI,IAAI,CAAC,SAAS,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAE,IAAgC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QACvH,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAED,YAAY,CAAC,IAAa;QACxB,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC;QAC1C,IAAI,IAAI,CAAC,UAAU,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,IAAI,IAAI;YAAE,OAAQ,IAAgC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3H,OAAO,IAAI,CAAC;IACd,CAAC;IAED,YAAY,CAAC,KAAa,IAAY,OAAO,KAAK,CAAC,CAAC,CAAC;IAErD,UAAU,CAAC,KAAc;QACvB,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;IACzC,CAAC;IAED,gBAAgB,CAAC,EAA4B,IAAU,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC;IAC5E,iBAAiB,CAAC,EAAc,IAAU,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC;IAChE,gBAAgB,CAAC,UAAmB,IAAU,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;IACpG,eAAe,KAAW,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IACzF,WAAW,KAAW,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAE7B,cAAc;QACpB,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI;YAAE,OAAO,EAAE,CAAC;QAC1C,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAC3C,MAAM,KAAK,GAAI,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAe,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC,CAAC;YAC5G,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACtE,CAAC;QACD,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,aAAa,CAAC;QACtE,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,aAAwC,CAAC,CAAC;IACzE,CAAC;IAEO,gBAAgB;QACtB,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI;YAAE,OAAO,CAAC,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IACzE,CAAC;yPAjUU,mBAAmB,yBAAnB,mBAAmB;6DAAnB,mBAAmB;;;;;;;;;;;;YAAnB,iDAAmB;2UANnB,CAAC;oBACV,OAAO,EAAE,iBAAiB;oBAC1B,WAAW,EAAE,UAAU,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC;oBAClD,KAAK,EAAE,IAAI;iBACZ,CAAC;YAtHE,AAZF,iCAM6C,kBA2BpB;YADrB,AADA,AADA,AADA,qGAAS,mBAAe,IAAC,kFAChB,aAAS,IAAC,4FACR,qBAAiB,IAAC,gFACrB,iBAAa,IAAC;YApBxB,iBAqBuB;YAUvB,+BAA+F;YAAA,qBAAK;YAAA,iBAAO;YAC3G,+BAAgG;YAAA,gCAAgB;YAAA,iBAAO;YACvH,wFAAgC;YAWhC,kCAO4D;YAF1D,+GAAa,6BAAyB,IAAC;YAGvC,wBAAwC;YAE5C,AADE,iBAAS,EACL;YAEN,sFASqB;YAAnB,AADA,sHAAiB,WAAO,IAAC,2FACf,WAAO,IAAC;;;YAvElB,AADA,+CAAkC,yCACQ;YAoBxC,eAA2B;YAE3B,AADA,AADA,6CAA2B,wBACR,4BACI;;YAe4B,eAAyC;;YACzC,eAA0C;;YAC/F,eAUC;YAVD,2DAUC;YAKC,cAAuB;YAAvB,yCAAuB;;YAUzB,eAA2C;YAI3C,AADA,AADA,AADA,AADA,4DAA2C,uCACT,+CACQ,8CACD,wCACF;4BA5EjC,gBAAgB,EAAE,aAAa;;iFAsI9B,mBAAmB;cAzI/B,SAAS;2BACE,aAAa,cACX,IAAI,WACP,CAAC,gBAAgB,EAAE,aAAa,CAAC,YAChC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwGT,aAuBU,CAAC;wBACV,OAAO,EAAE,iBAAiB;wBAC1B,WAAW,EAAE,UAAU,CAAC,GAAG,EAAE,oBAAoB,CAAC;wBAClD,KAAK,EAAE,IAAI;qBACZ,CAAC;;kBAGD,KAAK;;kBAUL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBAOL,KAAK;;kBAQL,KAAK;;kBACL,KAAK;;kBAEL,MAAM;;kBACN,MAAM;;kBAEN,YAAY;mBAAC,gBAAgB;;kBAE7B,SAAS;mBAAC,SAAS;;kBACnB,SAAS;mBAAC,YAAY;;kBAEtB,WAAW;mBAAC,wBAAwB;;kFAxC1B,mBAAmB","sourcesContent":["import {\n AfterViewInit,\n Component,\n Input,\n Output,\n EventEmitter,\n forwardRef,\n HostBinding,\n ElementRef,\n ViewChild,\n ContentChild,\n TemplateRef,\n OnDestroy,\n inject,\n ChangeDetectorRef\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';\nimport { OverlayModule, ConnectedPosition } from '@angular/cdk/overlay';\nimport { MJNamedControlBase } from '../a11y/named-control.base';\nimport { WarnIfUnnamed } from '../a11y/unnamed-control-guard';\n\n/**\n * mj-combobox — Editable dropdown with filtering and optional custom values.\n *\n * Replaces `<kendo-combobox>`. Unlike mj-dropdown, the trigger is a text input\n * that filters the list as you type. When AllowCustom is true, typed text that\n * doesn't match any item is emitted as the value.\n *\n * Every combobox needs an ACCESSIBLE NAME, or it announces as \"combobox, collapsed\" with no hint of\n * what it selects (WCAG 2.1 4.1.2). Use {@link MJNamedControlBase.AriaLabelledBy} when a visible\n * label already exists and {@link MJNamedControlBase.AriaLabel} when none does. Here the trigger is\n * a real `<input>`, so {@link MJNamedControlBase.InputId} IS a valid `<label for>` target — unlike\n * `mj-dropdown`, whose trigger is a div.\n *\n * @example With a visible label (preferred)\n * ```html\n * <span id=\"category-label\">Category</span>\n * <mj-combobox AriaLabelledBy=\"category-label\" [Data]=\"categories\" TextField=\"text\"\n * ValueField=\"value\" [(ngModel)]=\"selectedCategory\" [ValuePrimitive]=\"true\">\n * </mj-combobox>\n * ```\n *\n * @example\n * ```html\n * <mj-combobox\n * [Data]=\"categories\"\n * TextField=\"text\"\n * ValueField=\"value\"\n * [(ngModel)]=\"selectedCategory\"\n * [ValuePrimitive]=\"true\"\n * [AllowCustom]=\"true\"\n * [Filterable]=\"true\"\n * Placeholder=\"Select or enter new...\">\n * </mj-combobox>\n * ```\n */\n@Component({\n selector: 'mj-combobox',\n standalone: true,\n imports: [NgTemplateOutlet, OverlayModule],\n template: `\n <div\n class=\"mj-combobox\"\n #trigger\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n [class.mj-combobox--open]=\"IsOpen\"\n [class.mj-combobox--disabled]=\"IsDisabled\">\n <!--\n role=\"combobox\" belongs on the INPUT, not on this wrapper. The wrapper is not focusable, so\n a screen reader never lands on it: its role, its name and its expanded state all went\n unannounced while the element the user actually focused announced as a plain textbox.\n -->\n <input\n #comboInput\n class=\"mj-input mj-combobox-input\"\n type=\"text\"\n role=\"combobox\"\n [attr.id]=\"InputId || null\"\n [attr.aria-label]=\"AriaLabel || null\"\n [attr.aria-labelledby]=\"AriaLabelledBy || null\"\n [attr.aria-describedby]=\"AriaDescribedBy || null\"\n [attr.aria-expanded]=\"IsOpen\"\n aria-haspopup=\"listbox\"\n [attr.aria-autocomplete]=\"Filterable ? 'list' : 'none'\"\n [attr.aria-controls]=\"IsOpen ? ListboxId : null\"\n [attr.aria-activedescendant]=\"ActiveDescendantId\"\n [placeholder]=\"Placeholder\"\n [value]=\"InputText\"\n [disabled]=\"IsDisabled\"\n (input)=\"OnInput($event)\"\n (focus)=\"OnFocus()\"\n (keydown)=\"OnKeyDown($event)\"\n (blur)=\"OnInputBlur()\"\n autocomplete=\"off\" />\n <!--\n The fixed words live in hidden spans rather than in concatenated strings so the\n AriaLabelledBy path can name these two buttons from the same visible label that names the\n combobox: aria-labelledby takes an ID LIST, so the word plus the label's own text is\n composed by the accessibility tree without this component ever seeing that text.\n A hidden node that is DIRECTLY referenced by aria-labelledby is still included in the name\n (accname §4.1), so aria-hidden keeps the word out of the reading order without costing the\n composed name.\n -->\n <span class=\"mj-combobox-sr-only\" aria-hidden=\"true\" [attr.id]=\"SecondaryWordId('clear-word')\">Clear</span>\n <span class=\"mj-combobox-sr-only\" aria-hidden=\"true\" [attr.id]=\"SecondaryWordId('toggle-word')\">Show options for</span>\n @if (InputText && !IsDisabled) {\n <button\n class=\"mj-combobox-clear\"\n type=\"button\"\n tabindex=\"-1\"\n (mousedown)=\"OnClear($event)\"\n [attr.aria-labelledby]=\"ClearLabelledBy || null\"\n [attr.aria-label]=\"ClearLabelledBy ? null : ClearLabel\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n }\n <button\n class=\"mj-combobox-toggle\"\n type=\"button\"\n tabindex=\"-1\"\n [disabled]=\"IsDisabled\"\n (mousedown)=\"OnToggleMouseDown($event)\"\n [attr.aria-labelledby]=\"ToggleLabelledBy || null\"\n [attr.aria-label]=\"ToggleLabelledBy ? null : ToggleLabel\">\n <i class=\"fa-solid fa-chevron-down\"></i>\n </button>\n </div>\n\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"IsOpen\"\n [cdkConnectedOverlayPositions]=\"Positions\"\n [cdkConnectedOverlayWidth]=\"TriggerWidth\"\n [cdkConnectedOverlayHasBackdrop]=\"true\"\n cdkConnectedOverlayBackdropClass=\"mj-dropdown-backdrop\"\n (backdropClick)=\"Close()\"\n (detach)=\"Close()\">\n <div class=\"mj-dropdown-panel\" role=\"listbox\"\n [attr.id]=\"ListboxId\"\n [attr.aria-label]=\"AriaLabel || null\"\n [attr.aria-labelledby]=\"AriaLabelledBy || null\">\n @for (item of FilteredItems; track TrackByIndex($index)) {\n <div\n class=\"mj-dropdown-option\"\n [class.mj-dropdown-option--selected]=\"IsItemSelected(item)\"\n [class.mj-dropdown-option--highlighted]=\"HighlightedIndex === $index\"\n role=\"option\"\n [attr.id]=\"OptionId($index)\"\n [attr.aria-selected]=\"IsItemSelected(item)\"\n (mousedown)=\"SelectItem(item, $event)\">\n @if (ItemTemplate) {\n <ng-container *ngTemplateOutlet=\"ItemTemplate; context: { $implicit: item }\"></ng-container>\n } @else {\n {{ GetItemText(item) }}\n }\n </div>\n }\n @if (FilteredItems.length === 0) {\n <div class=\"mj-dropdown-no-data\">No data found</div>\n }\n </div>\n </ng-template>\n `,\n styles: [`\n /*\n * Component-scoped ON PURPOSE, unlike the rest of this control's styling, which ships as a global\n * stylesheet the host application imports. A host that skips that import gets unstyled chrome —\n * survivable — but a hidden-word span that is not hidden renders its word as literal text in the\n * middle of the field. The rule that hides it therefore has to travel with the component.\n *\n * Not display:none or visibility:hidden — both remove the element from the accessibility tree,\n * which is the one thing this element exists to be in.\n */\n .mj-combobox-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n `],\n providers: [{\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => MJComboboxComponent),\n multi: true\n }]\n})\nexport class MJComboboxComponent extends MJNamedControlBase implements ControlValueAccessor, AfterViewInit, OnDestroy {\n @Input()\n set Data(value: Record<string, unknown>[] | string[] | readonly unknown[] | null) {\n this._data = value;\n // Re-resolve display text when data arrives after writeValue\n if (this.SelectedValue != null && !this.InputText) {\n this.InputText = this.getDisplayText();\n }\n }\n get Data(): Record<string, unknown>[] | string[] | readonly unknown[] | null { return this._data; }\n private _data: Record<string, unknown>[] | string[] | readonly unknown[] | null = [];\n @Input() TextField = '';\n @Input() ValueField = '';\n @Input() Filterable = true;\n @Input() ValuePrimitive = false;\n /**\n * Host-driven disable. Composed with Angular Forms' `setDisabledState()` into `IsDisabled`\n * (the actual gate) — see `syncDisabled`. A setter, not a bare field, because this input is\n * routinely bound to an expression that changes over the control's lifetime, and the gate has\n * to follow it every time.\n */\n @Input()\n set Disabled(value: boolean) {\n this.disabledInput = value;\n this.syncDisabled();\n }\n get Disabled(): boolean {\n return this.disabledInput;\n }\n @Input() Placeholder = '';\n @Input() AllowCustom = false;\n\n @Output() ValueChange = new EventEmitter<unknown>();\n @Output() FilterChange = new EventEmitter<string>();\n\n @ContentChild('mjComboboxItem') ItemTemplate: TemplateRef<{ $implicit: unknown }> | null = null;\n\n @ViewChild('trigger') private triggerEl!: ElementRef<HTMLElement>;\n @ViewChild('comboInput') ComboInput!: ElementRef<HTMLInputElement>;\n\n @HostBinding('class.mj-combobox-host') readonly hostClass = true;\n\n private cdr = inject(ChangeDetectorRef);\n\n IsOpen = false;\n /**\n * The single gate on `Toggle()` / `Open()` — true when EITHER the `Disabled` input or Angular\n * Forms says so. Never assign it directly; go through `syncDisabled()`.\n */\n IsDisabled = false;\n HighlightedIndex = -1;\n SelectedValue: unknown = null;\n TriggerWidth = 0;\n InputText = '';\n\n Positions: ConnectedPosition[] = [\n { originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top' },\n { originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' }\n ];\n\n /**\n * Id of the popup listbox, so the input can point `aria-controls` at it while open — the half of\n * the combobox pattern that makes \"collapsed/expanded\" refer to something a screen reader can\n * find.\n */\n get ListboxId(): string { return `mj-combobox-listbox-${this.NamedControlId}`; }\n\n /** Id of one rendered option, referenced by {@link ActiveDescendantId}. */\n OptionId(index: number): string { return `mj-combobox-option-${this.NamedControlId}-${index}`; }\n\n /**\n * `aria-activedescendant` for the input: the option the arrow keys have moved to. Focus stays in\n * the input the whole time, so without this the highlight is a CSS class and nothing else — a\n * screen-reader user arrowing through the list hears no change at all.\n */\n get ActiveDescendantId(): string | null {\n const active = this.IsOpen && this.HighlightedIndex >= 0 && this.HighlightedIndex < this.FilteredItems.length;\n return active ? this.OptionId(this.HighlightedIndex) : null;\n }\n\n /** `aria-labelledby` id list for the clear button when a VISIBLE label names the combobox. */\n get ClearLabelledBy(): string { return this.SecondaryLabelledBy('clear-word'); }\n\n /** `aria-label` for the clear button in the no-visible-label case. */\n get ClearLabel(): string { return this.SecondaryLabel('Clear', 'Clear'); }\n\n /** `aria-labelledby` id list for the toggle button when a VISIBLE label names the combobox. */\n get ToggleLabelledBy(): string { return this.SecondaryLabelledBy('toggle-word'); }\n\n /**\n * `aria-label` for the toggle button in the no-visible-label case. It had no name at all before\n * #4116 — an unnamed button next to a named input, which announces as \"button\".\n */\n get ToggleLabel(): string { return this.SecondaryLabel('Show options for', 'Show options'); }\n\n private onChange: (value: unknown) => void = () => {};\n private onTouched: () => void = () => {};\n private isBlurring = false;\n\n get FilteredItems(): unknown[] {\n const data = (this.Data ?? []) as unknown[];\n if (!this.Filterable || !this.InputText) return data;\n const search = this.InputText.toLowerCase();\n return data.filter(item => this.GetItemText(item).toLowerCase().includes(search));\n }\n\n OnInput(event: Event): void {\n this.InputText = (event.target as HTMLInputElement).value;\n this.HighlightedIndex = 0;\n this.FilterChange.emit(this.InputText);\n if (!this.IsOpen) this.Open();\n this.cdr.detectChanges();\n }\n\n OnFocus(): void {\n if (!this.IsOpen) this.Open();\n }\n\n OnToggleMouseDown(event: Event): void {\n event.preventDefault(); // Prevent blur on the input\n this.Toggle();\n }\n\n OnClear(event: Event): void {\n event.preventDefault();\n event.stopPropagation();\n this.isBlurring = false;\n this.InputText = '';\n this.SelectedValue = null;\n this.onChange(null);\n this.ValueChange.emit(null);\n this.Close();\n this.cdr.detectChanges();\n }\n\n OnInputBlur(): void {\n this.isBlurring = true;\n setTimeout(() => {\n if (!this.isBlurring) return;\n this.isBlurring = false;\n this.commitValue();\n this.Close();\n this.onTouched();\n }, 150);\n }\n\n Toggle(): void {\n if (this.IsDisabled) return;\n this.IsOpen ? this.Close() : this.Open();\n }\n\n Open(): void {\n if (this.IsDisabled || this.IsOpen) return;\n this.TriggerWidth = this.triggerEl?.nativeElement.offsetWidth ?? 200;\n this.IsOpen = true;\n this.HighlightedIndex = this.getSelectedIndex();\n this.cdr.detectChanges();\n }\n\n Close(): void {\n if (!this.IsOpen) return;\n this.resetPanelState();\n this.cdr.detectChanges();\n }\n\n /**\n * Panel state only — no change detection. Split out of `Close()` because `syncDisabled()` can\n * run from an @Input setter, i.e. DURING the parent's change-detection pass, where a nested\n * `detectChanges()` re-enters CD and trips NG0100 on the parent's own bindings.\n */\n private resetPanelState(): void {\n this.IsOpen = false;\n this.HighlightedIndex = -1;\n }\n\n /** Backing field for the `Disabled` input. */\n private disabledInput = false;\n /** The forms-driven disabled state, kept SEPARATE so neither source can stomp the other. */\n private formDisabled = false;\n\n /**\n * Recompute the gate from both of its sources. Called whenever either changes.\n *\n * `IsDisabled` is derived state, and the only thing that assigned it was `setDisabledState()`.\n * The forms-driven half was in fact fine — `setUpControl` also wires `registerOnDisabledChange`,\n * so that hook fires on every `control.disable()`/`enable()`, not just at registration. What had\n * no recompute path at all was the `Disabled` @Input: a plain field, so the gate froze at\n * whatever the first compose produced and every later change to the input was dropped.\n */\n private syncDisabled(): void {\n const disabled = this.disabledInput || this.formDisabled;\n if (disabled === this.IsDisabled) return;\n this.IsDisabled = disabled;\n if (disabled) this.resetPanelState();\n this.cdr.markForCheck();\n }\n\n SelectItem(item: unknown, event?: Event): void {\n event?.preventDefault();\n event?.stopPropagation();\n this.isBlurring = false;\n\n const value = this.ValuePrimitive && this.ValueField ? this.GetItemValue(item) : item;\n this.SelectedValue = value;\n this.InputText = this.GetItemText(item);\n this.onChange(value);\n this.ValueChange.emit(value);\n this.Close();\n this.cdr.detectChanges();\n }\n\n /** Commit the current input text as a value (for AllowCustom or matching item) */\n private commitValue(): void {\n if (!this.InputText.trim()) {\n // Empty input — clear the value\n if (this.SelectedValue != null) {\n this.SelectedValue = null;\n this.onChange(null);\n this.ValueChange.emit(null);\n }\n return;\n }\n\n // Try to find a matching item\n const data = (this.Data ?? []) as unknown[];\n const match = data.find(item => this.GetItemText(item).toLowerCase() === this.InputText.toLowerCase());\n if (match) {\n const value = this.ValuePrimitive && this.ValueField ? this.GetItemValue(match) : match;\n if (value !== this.SelectedValue) {\n this.SelectedValue = value;\n this.InputText = this.GetItemText(match);\n this.onChange(value);\n this.ValueChange.emit(value);\n }\n } else if (this.AllowCustom) {\n // No match but custom values allowed — emit the typed text\n this.SelectedValue = this.InputText;\n this.onChange(this.InputText);\n this.ValueChange.emit(this.InputText);\n } else {\n // No match and no custom — revert to previous display\n this.InputText = this.getDisplayText();\n }\n }\n\n IsItemSelected(item: unknown): boolean {\n if (this.SelectedValue == null) return false;\n if (this.ValuePrimitive && this.ValueField) return this.GetItemValue(item) === this.SelectedValue;\n if (this.ValueField && typeof item === 'object' && typeof this.SelectedValue === 'object')\n return this.GetItemValue(item) === this.GetItemValue(this.SelectedValue);\n return item === this.SelectedValue;\n }\n\n OnKeyDown(event: KeyboardEvent): void {\n const items = this.FilteredItems;\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n if (!this.IsOpen) this.Open();\n else this.HighlightedIndex = Math.min(this.HighlightedIndex + 1, items.length - 1);\n break;\n case 'ArrowUp':\n event.preventDefault();\n if (this.IsOpen) this.HighlightedIndex = Math.max(this.HighlightedIndex - 1, 0);\n break;\n case 'Enter':\n event.preventDefault();\n if (this.IsOpen && this.HighlightedIndex >= 0 && this.HighlightedIndex < items.length) {\n this.SelectItem(items[this.HighlightedIndex]);\n } else {\n this.commitValue();\n this.Close();\n }\n break;\n case 'Escape':\n event.preventDefault();\n this.InputText = this.getDisplayText();\n this.Close();\n break;\n }\n }\n\n GetItemText(item: unknown): string {\n if (item == null) return '';\n if (typeof item === 'string') return item;\n if (this.TextField && typeof item === 'object') return String((item as Record<string, unknown>)[this.TextField] ?? '');\n return String(item);\n }\n\n GetItemValue(item: unknown): unknown {\n if (typeof item === 'string') return item;\n if (this.ValueField && typeof item === 'object' && item != null) return (item as Record<string, unknown>)[this.ValueField];\n return item;\n }\n\n TrackByIndex(index: number): number { return index; }\n\n writeValue(value: unknown): void {\n this.SelectedValue = value;\n this.InputText = this.getDisplayText();\n }\n\n registerOnChange(fn: (value: unknown) => void): void { this.onChange = fn; }\n registerOnTouched(fn: () => void): void { this.onTouched = fn; }\n setDisabledState(isDisabled: boolean): void { this.formDisabled = isDisabled; this.syncDisabled(); }\n ngAfterViewInit(): void { WarnIfUnnamed(this.ComboInput?.nativeElement, 'mj-combobox'); }\n ngOnDestroy(): void { this.Close(); }\n\n private getDisplayText(): string {\n if (this.SelectedValue == null) return '';\n if (this.ValuePrimitive && this.ValueField) {\n const found = ((this.Data ?? []) as unknown[]).find(item => this.GetItemValue(item) === this.SelectedValue);\n return found ? this.GetItemText(found) : String(this.SelectedValue);\n }\n if (typeof this.SelectedValue === 'string') return this.SelectedValue;\n return this.GetItemText(this.SelectedValue as Record<string, unknown>);\n }\n\n private getSelectedIndex(): number {\n if (this.SelectedValue == null) return -1;\n return this.FilteredItems.findIndex(item => this.IsItemSelected(item));\n }\n}\n"]}
|
|
@@ -90,9 +90,15 @@ export declare class MJConfirmDialogComponent {
|
|
|
90
90
|
* to suppress it), otherwise the per-type default.
|
|
91
91
|
*/
|
|
92
92
|
get ResolvedIcon(): string;
|
|
93
|
+
OnConfirm(): void;
|
|
94
|
+
/** @deprecated Use {@link OnConfirm}. */
|
|
93
95
|
onConfirm(): void;
|
|
96
|
+
OnCancel(): void;
|
|
97
|
+
/** @deprecated Use {@link OnCancel}. */
|
|
94
98
|
onCancel(): void;
|
|
95
99
|
/** Backdrop / Esc / ✕ from the underlying dialog — ignored while Processing. */
|
|
100
|
+
OnDismiss(): void;
|
|
101
|
+
/** @deprecated Use {@link OnDismiss}. */
|
|
96
102
|
onDismiss(): void;
|
|
97
103
|
private close;
|
|
98
104
|
static ɵfac: i0.ɵɵFactoryDeclaration<MJConfirmDialogComponent, never>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"confirm-dialog.component.d.ts","sourceRoot":"","sources":["../../../src/lib/confirm-dialog/confirm-dialog.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAmC,MAAM,eAAe,CAAC;;AAIzF;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAS5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBA+Ea,wBAAwB;IACnC,oEAAoE;IAC3D,OAAO,UAAS;IACzB,sFAAsF;IAC5E,aAAa,wBAA+B;IAEtD,6CAA6C;IACpC,KAAK,SAAa;IAE3B,qFAAqF;IAC5E,OAAO,SAAmB;IAEnC,2EAA2E;IAClE,aAAa,SAAM;IAE5B,4FAA4F;IACnF,IAAI,EAAE,mBAAmB,CAAa;IAE/C,gCAAgC;IACvB,WAAW,SAAa;IAEjC,4BAA4B;IACnB,UAAU,SAAY;IAE/B;;;OAGG;IACM,IAAI,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEpC;;;;OAIG;IACqC,UAAU,UAAS;IAE3D,gFAAgF;IACtE,SAAS,qBAA4B;IAE/C,yFAAyF;IAC/E,SAAS,qBAA4B;IAE/C,kFAAkF;IAClF,IAAI,cAAc,IAAI,SAAS,GAAG,QAAQ,CAEzC;IAED;;;OAGG;IACH,IAAI,YAAY,IAAI,MAAM,CAKzB;IAED,SAAS,IAAI,IAAI;IAIjB,QAAQ,IAAI,IAAI;IAKhB,gFAAgF;IAChF,SAAS,IAAI,IAAI;IAOjB,OAAO,CAAC,KAAK;
|
|
1
|
+
{"version":3,"file":"confirm-dialog.component.d.ts","sourceRoot":"","sources":["../../../src/lib/confirm-dialog/confirm-dialog.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAmC,MAAM,eAAe,CAAC;;AAIzF;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAS5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBA+Ea,wBAAwB;IACnC,oEAAoE;IAC3D,OAAO,UAAS;IACzB,sFAAsF;IAC5E,aAAa,wBAA+B;IAEtD,6CAA6C;IACpC,KAAK,SAAa;IAE3B,qFAAqF;IAC5E,OAAO,SAAmB;IAEnC,2EAA2E;IAClE,aAAa,SAAM;IAE5B,4FAA4F;IACnF,IAAI,EAAE,mBAAmB,CAAa;IAE/C,gCAAgC;IACvB,WAAW,SAAa;IAEjC,4BAA4B;IACnB,UAAU,SAAY;IAE/B;;;OAGG;IACM,IAAI,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEpC;;;;OAIG;IACqC,UAAU,UAAS;IAE3D,gFAAgF;IACtE,SAAS,qBAA4B;IAE/C,yFAAyF;IAC/E,SAAS,qBAA4B;IAE/C,kFAAkF;IAClF,IAAI,cAAc,IAAI,SAAS,GAAG,QAAQ,CAEzC;IAED;;;OAGG;IACH,IAAI,YAAY,IAAI,MAAM,CAKzB;IAED,SAAS,IAAI,IAAI;IAIjB,yCAAyC;IACzC,SAAS,IAAI,IAAI;IAIjB,QAAQ,IAAI,IAAI;IAKhB,wCAAwC;IACxC,QAAQ,IAAI,IAAI;IAIhB,gFAAgF;IAChF,SAAS,IAAI,IAAI;IAOjB,yCAAyC;IACzC,SAAS,IAAI,IAAI;IAIjB,OAAO,CAAC,KAAK;yCA3FF,wBAAwB;2CAAxB,wBAAwB;yCAgG8z9L,OAAQ;CAD129L"}
|
|
@@ -123,19 +123,31 @@ export class MJConfirmDialogComponent {
|
|
|
123
123
|
}
|
|
124
124
|
return DEFAULT_ICONS[this.Type] ?? DEFAULT_ICONS.default;
|
|
125
125
|
}
|
|
126
|
-
|
|
126
|
+
OnConfirm() {
|
|
127
127
|
this.Confirmed.emit();
|
|
128
128
|
}
|
|
129
|
-
|
|
129
|
+
/** @deprecated Use {@link OnConfirm}. */
|
|
130
|
+
onConfirm() {
|
|
131
|
+
return this.OnConfirm();
|
|
132
|
+
}
|
|
133
|
+
OnCancel() {
|
|
130
134
|
this.close();
|
|
131
135
|
this.Cancelled.emit();
|
|
132
136
|
}
|
|
137
|
+
/** @deprecated Use {@link OnCancel}. */
|
|
138
|
+
onCancel() {
|
|
139
|
+
return this.OnCancel();
|
|
140
|
+
}
|
|
133
141
|
/** Backdrop / Esc / ✕ from the underlying dialog — ignored while Processing. */
|
|
134
|
-
|
|
142
|
+
OnDismiss() {
|
|
135
143
|
if (this.Processing) {
|
|
136
144
|
return;
|
|
137
145
|
}
|
|
138
|
-
this.
|
|
146
|
+
this.OnCancel();
|
|
147
|
+
}
|
|
148
|
+
/** @deprecated Use {@link OnDismiss}. */
|
|
149
|
+
onDismiss() {
|
|
150
|
+
return this.OnDismiss();
|
|
139
151
|
}
|
|
140
152
|
close() {
|
|
141
153
|
this.Visible = false;
|