@memberjunction/ng-ui-components 6.1.0-edge.4 → 6.1.0-edge.6
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 +9 -1
- package/dist/lib/alert/alert.component.d.ts.map +1 -1
- package/dist/lib/alert/alert.component.js +1 -1
- package/dist/lib/applied-filters/applied-filters.component.js +1 -1
- package/dist/lib/bottom-sheet/bottom-sheet.component.js +1 -1
- package/dist/lib/combobox/combobox.component.d.ts +32 -1
- package/dist/lib/combobox/combobox.component.d.ts.map +1 -1
- package/dist/lib/combobox/combobox.component.js +73 -28
- package/dist/lib/combobox/combobox.component.js.map +1 -1
- package/dist/lib/confirm-dialog/confirm-dialog.component.d.ts.map +1 -1
- package/dist/lib/datepicker/datepicker.component.d.ts +25 -1
- package/dist/lib/datepicker/datepicker.component.d.ts.map +1 -1
- package/dist/lib/datepicker/datepicker.component.js +59 -28
- package/dist/lib/datepicker/datepicker.component.js.map +1 -1
- package/dist/lib/dialog/dialog.component.js +1 -1
- package/dist/lib/dialog/dialog.component.js.map +1 -1
- package/dist/lib/dialog/dialog.service.js +15 -16
- package/dist/lib/dialog/dialog.service.js.map +1 -1
- package/dist/lib/dropdown/dropdown.component.d.ts +103 -3
- package/dist/lib/dropdown/dropdown.component.d.ts.map +1 -1
- package/dist/lib/dropdown/dropdown.component.js +208 -52
- package/dist/lib/dropdown/dropdown.component.js.map +1 -1
- package/dist/lib/dropdown/dropdown.scss +16 -0
- package/dist/lib/empty-state/empty-state.component.js +1 -1
- package/dist/lib/filter-popover/filter-popover.component.js +27 -28
- package/dist/lib/filter-popover/filter-popover.component.js.map +1 -1
- package/dist/lib/left-nav/left-nav-content.component.js +1 -1
- package/dist/lib/left-nav/left-nav.component.js +72 -73
- package/dist/lib/left-nav/left-nav.component.js.map +1 -1
- package/dist/lib/numeric-input/numeric-input.component.d.ts +22 -1
- package/dist/lib/numeric-input/numeric-input.component.d.ts.map +1 -1
- package/dist/lib/numeric-input/numeric-input.component.js +30 -3
- package/dist/lib/numeric-input/numeric-input.component.js.map +1 -1
- package/dist/lib/page-body/page-body.component.js +1 -1
- package/dist/lib/page-body-interior/page-body-interior.component.js +1 -1
- package/dist/lib/page-header/page-header.component.js +1 -1
- package/dist/lib/page-header-interior/page-header-interior.component.js +1 -1
- package/dist/lib/page-search/page-search.component.js +1 -1
- package/dist/lib/refresh-button/refresh-button.component.js +1 -1
- package/dist/lib/slide-panel/slide-panel.component.js +1 -1
- package/dist/lib/stat-badge/stat-badge.component.js +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 +30 -3
- package/dist/lib/switch/switch.component.js.map +1 -1
- package/dist/lib/tab-nav/tab-nav.component.js +1 -1
- package/dist/lib/view-toggle/view-toggle.component.js +1 -1
- package/dist/lib/window/window.component.js +1 -1
- package/dist/lib/window/window.component.js.map +1 -1
- package/dist/lib/workspace-tabs/workspace-card.component.js +1 -1
- package/dist/lib/workspace-tabs/workspace-tab-strip.component.js +1 -1
- package/package.json +8 -8
|
@@ -7,9 +7,27 @@ import * as i0 from "@angular/core";
|
|
|
7
7
|
*
|
|
8
8
|
* Replaces `<kendo-dropdownlist>`.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
10
|
+
* Every dropdown needs an ACCESSIBLE NAME, or it announces as "combobox, collapsed" with no hint of
|
|
11
|
+
* what it selects (WCAG 2.1 4.1.2). Use {@link AriaLabelledBy} when a visible label already exists —
|
|
12
|
+
* `<label for>` cannot name a `div[role=combobox]` — and {@link AriaLabel} when none does.
|
|
13
|
+
*
|
|
14
|
+
* @example With a visible label (preferred)
|
|
15
|
+
* ```html
|
|
16
|
+
* <span id="persona-label">Interview persona</span>
|
|
17
|
+
* <mj-dropdown
|
|
18
|
+
* AriaLabelledBy="persona-label"
|
|
19
|
+
* [Data]="items"
|
|
20
|
+
* TextField="name"
|
|
21
|
+
* ValueField="id"
|
|
22
|
+
* [(ngModel)]="selectedId"
|
|
23
|
+
* [ValuePrimitive]="true">
|
|
24
|
+
* </mj-dropdown>
|
|
25
|
+
* ```
|
|
26
|
+
*
|
|
27
|
+
* @example With no visible label
|
|
11
28
|
* ```html
|
|
12
29
|
* <mj-dropdown
|
|
30
|
+
* AriaLabel="Interview persona"
|
|
13
31
|
* [Data]="items"
|
|
14
32
|
* TextField="name"
|
|
15
33
|
* ValueField="id"
|
|
@@ -21,12 +39,43 @@ import * as i0 from "@angular/core";
|
|
|
21
39
|
* ```
|
|
22
40
|
*/
|
|
23
41
|
export declare class MJDropdownComponent implements ControlValueAccessor, OnDestroy {
|
|
42
|
+
/**
|
|
43
|
+
* Accessible name for the combobox (#3860). Without one — and with no visible label wired via
|
|
44
|
+
* {@link AriaLabelledBy} — the control announces as an UNNAMED combobox, which fails WCAG 2.1
|
|
45
|
+
* 4.1.2 (Name, Role, Value): "combobox, collapsed" with no hint of what it selects. Applied as
|
|
46
|
+
* `aria-label` on the trigger AND on the popup listbox, so both halves announce the same name.
|
|
47
|
+
*/
|
|
48
|
+
AriaLabel: string;
|
|
49
|
+
/**
|
|
50
|
+
* The id of a VISIBLE label element that names this control — the preferred wiring when a label
|
|
51
|
+
* already exists on screen (an `aria-label` would duplicate its text and drift on rename). This,
|
|
52
|
+
* not `<label for>`, is the visible-label path: the trigger is a `div[role=combobox]`, and the
|
|
53
|
+
* label-for association only names labelable form elements. `aria-labelledby` beats `AriaLabel`
|
|
54
|
+
* in the accessible-name computation where both are present. Applied to trigger AND listbox.
|
|
55
|
+
*/
|
|
56
|
+
AriaLabelledBy: string;
|
|
57
|
+
/**
|
|
58
|
+
* `id` for the combobox trigger, so other markup can REFERENCE it — `aria-controls`, hint text,
|
|
59
|
+
* test hooks. It is deliberately not documented as a `<label for>` target: the trigger is a div,
|
|
60
|
+
* which `label[for]` neither names nor focuses. To name the control from a visible label, put an
|
|
61
|
+
* id on the LABEL and pass it as {@link AriaLabelledBy}.
|
|
62
|
+
*/
|
|
63
|
+
InputId: string;
|
|
64
|
+
/** `aria-describedby` passthrough for hint/error text — same shape of gap as the name. */
|
|
65
|
+
AriaDescribedBy: string;
|
|
24
66
|
Data: Record<string, unknown>[] | string[] | readonly unknown[] | null;
|
|
25
67
|
TextField: string;
|
|
26
68
|
ValueField: string;
|
|
27
69
|
Filterable: boolean;
|
|
28
70
|
ValuePrimitive: boolean;
|
|
29
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Host-driven disable. Composed with Angular Forms' `setDisabledState()` into `IsDisabled`
|
|
73
|
+
* (the actual gate) — see `syncDisabled`. A setter, not a bare field, because this input is
|
|
74
|
+
* routinely bound to an expression that changes over the control's lifetime
|
|
75
|
+
* (`[Disabled]="!draft.CompanyID"`), and the gate has to follow it every time.
|
|
76
|
+
*/
|
|
77
|
+
set Disabled(value: boolean);
|
|
78
|
+
get Disabled(): boolean;
|
|
30
79
|
Placeholder: string;
|
|
31
80
|
DefaultItem: Record<string, unknown> | string | null;
|
|
32
81
|
FilterChange: EventEmitter<string>;
|
|
@@ -40,7 +89,35 @@ export declare class MJDropdownComponent implements ControlValueAccessor, OnDest
|
|
|
40
89
|
private cdr;
|
|
41
90
|
private static nextId;
|
|
42
91
|
DropdownId: number;
|
|
92
|
+
/**
|
|
93
|
+
* Id of the popup listbox, so the trigger can point `aria-controls` at it while open — the half of
|
|
94
|
+
* the combobox pattern that makes "collapsed/expanded" refer to something a screen reader can
|
|
95
|
+
* find. Generated per instance from the same `static nextId` counter `dialog`, `window` and
|
|
96
|
+
* `accordion` use in this package.
|
|
97
|
+
*/
|
|
98
|
+
get ListboxId(): string;
|
|
99
|
+
/** Id of the hidden "Filter" word, composed into the filter box's name via an id list. */
|
|
100
|
+
get FilterWordId(): string;
|
|
101
|
+
/**
|
|
102
|
+
* `aria-labelledby` for the filter box when the dropdown is named by a VISIBLE label: "Filter"
|
|
103
|
+
* plus that label's own text, composed by the accessibility tree. Empty when there is no such
|
|
104
|
+
* label, in which case {@link FilterLabel} supplies a string instead.
|
|
105
|
+
*/
|
|
106
|
+
get FilterLabelledBy(): string;
|
|
107
|
+
/**
|
|
108
|
+
* `aria-label` for the filter box in the no-visible-label case.
|
|
109
|
+
*
|
|
110
|
+
* The "filter" guard is not cosmetic: this repo's house habit is `AriaLabel="Filter roles"`, and
|
|
111
|
+
* an unconditional prefix announces that box as "Filter Filter roles". A name that already begins
|
|
112
|
+
* with the word is used as-is.
|
|
113
|
+
*/
|
|
114
|
+
get FilterLabel(): string;
|
|
43
115
|
IsOpen: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* The single gate on `Toggle()` / `Open()` — true when EITHER the `Disabled` input or Angular
|
|
118
|
+
* Forms says so. Never assign it directly; go through `syncDisabled()` so both sources are
|
|
119
|
+
* always composed and a lock closes an open panel.
|
|
120
|
+
*/
|
|
44
121
|
IsDisabled: boolean;
|
|
45
122
|
HighlightedIndex: number;
|
|
46
123
|
SelectedValue: unknown;
|
|
@@ -49,12 +126,35 @@ export declare class MJDropdownComponent implements ControlValueAccessor, OnDest
|
|
|
49
126
|
Positions: ConnectedPosition[];
|
|
50
127
|
private onChange;
|
|
51
128
|
private onTouched;
|
|
129
|
+
/** Backing field for the `Disabled` input. */
|
|
130
|
+
private disabledInput;
|
|
131
|
+
/** The forms-driven disabled state, kept SEPARATE so neither source can stomp the other. */
|
|
132
|
+
private formDisabled;
|
|
133
|
+
/**
|
|
134
|
+
* Recompute the gate from both of its sources. Called whenever either changes.
|
|
135
|
+
*
|
|
136
|
+
* `IsDisabled` is derived state, and the only thing that assigned it was `setDisabledState()`.
|
|
137
|
+
* The forms-driven half was in fact fine — `setUpControl` also wires `registerOnDisabledChange`,
|
|
138
|
+
* so that hook fires on every `control.disable()`/`enable()`, not just at registration. What had
|
|
139
|
+
* no recompute path at all was the `Disabled` @Input: a plain field, so the gate froze at
|
|
140
|
+
* whatever the first compose produced and every later change to the input was dropped.
|
|
141
|
+
*
|
|
142
|
+
* That is how a `[Disabled]="!draft.CompanyID"` picker stayed dead for the life of the
|
|
143
|
+
* component after the company was finally chosen.
|
|
144
|
+
*/
|
|
145
|
+
private syncDisabled;
|
|
52
146
|
get FilteredItems(): unknown[];
|
|
53
147
|
get HasValue(): boolean;
|
|
54
148
|
get DisplayText(): string;
|
|
55
149
|
Toggle(): void;
|
|
56
150
|
Open(): void;
|
|
57
151
|
Close(): void;
|
|
152
|
+
/**
|
|
153
|
+
* Panel state only — no change detection. Split out of `Close()` because `syncDisabled()` can
|
|
154
|
+
* run from an @Input setter, i.e. DURING the parent's change-detection pass, where a nested
|
|
155
|
+
* `detectChanges()` re-enters CD and trips NG0100 on the parent's own bindings.
|
|
156
|
+
*/
|
|
157
|
+
private resetPanelState;
|
|
58
158
|
SelectItem(item: unknown | null, event?: Event): void;
|
|
59
159
|
IsItemSelected(item: unknown): boolean;
|
|
60
160
|
OnFilterInput(event: Event): void;
|
|
@@ -70,6 +170,6 @@ export declare class MJDropdownComponent implements ControlValueAccessor, OnDest
|
|
|
70
170
|
ngOnDestroy(): void;
|
|
71
171
|
private getSelectedIndex;
|
|
72
172
|
static ɵfac: i0.ɵɵFactoryDeclaration<MJDropdownComponent, never>;
|
|
73
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<MJDropdownComponent, "mj-dropdown", never, { "Data": { "alias": "Data"; "required": false; }; "TextField": { "alias": "TextField"; "required": false; }; "ValueField": { "alias": "ValueField"; "required": false; }; "Filterable": { "alias": "Filterable"; "required": false; }; "ValuePrimitive": { "alias": "ValuePrimitive"; "required": false; }; "Disabled": { "alias": "Disabled"; "required": false; }; "Placeholder": { "alias": "Placeholder"; "required": false; }; "DefaultItem": { "alias": "DefaultItem"; "required": false; }; }, { "FilterChange": "FilterChange"; "ValueChange": "ValueChange"; }, ["itemTemplate"], never, true, never>;
|
|
173
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MJDropdownComponent, "mj-dropdown", never, { "AriaLabel": { "alias": "AriaLabel"; "required": false; }; "AriaLabelledBy": { "alias": "AriaLabelledBy"; "required": false; }; "InputId": { "alias": "InputId"; "required": false; }; "AriaDescribedBy": { "alias": "AriaDescribedBy"; "required": false; }; "Data": { "alias": "Data"; "required": false; }; "TextField": { "alias": "TextField"; "required": false; }; "ValueField": { "alias": "ValueField"; "required": false; }; "Filterable": { "alias": "Filterable"; "required": false; }; "ValuePrimitive": { "alias": "ValuePrimitive"; "required": false; }; "Disabled": { "alias": "Disabled"; "required": false; }; "Placeholder": { "alias": "Placeholder"; "required": false; }; "DefaultItem": { "alias": "DefaultItem"; "required": false; }; }, { "FilterChange": "FilterChange"; "ValueChange": "ValueChange"; }, ["itemTemplate"], never, true, never>;
|
|
74
174
|
}
|
|
75
175
|
//# sourceMappingURL=dropdown.component.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropdown.component.d.ts","sourceRoot":"","sources":["../../../src/lib/dropdown/dropdown.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,YAAY,EAMZ,WAAW,EACX,SAAS,EAGV,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAqB,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAiB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;;AAExE
|
|
1
|
+
{"version":3,"file":"dropdown.component.d.ts","sourceRoot":"","sources":["../../../src/lib/dropdown/dropdown.component.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,59 +9,65 @@ const _c1 = ["trigger"];
|
|
|
9
9
|
const _c2 = ["filterInput"];
|
|
10
10
|
const _c3 = a0 => ({ $implicit: a0 });
|
|
11
11
|
function MJDropdownComponent_ng_template_6_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
12
|
-
const
|
|
13
|
-
i0.ɵɵelementStart(0, "div", 7)(1, "
|
|
14
|
-
i0.ɵɵ
|
|
12
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
13
|
+
i0.ɵɵelementStart(0, "div", 7)(1, "span", 11);
|
|
14
|
+
i0.ɵɵtext(2, "Filter");
|
|
15
|
+
i0.ɵɵelementEnd();
|
|
16
|
+
i0.ɵɵelementStart(3, "input", 12, 1);
|
|
17
|
+
i0.ɵɵlistener("input", function MJDropdownComponent_ng_template_6_Conditional_1_Template_input_input_3_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnFilterInput($event)); })("keydown", function MJDropdownComponent_ng_template_6_Conditional_1_Template_input_keydown_3_listener($event) { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.OnKeyDown($event)); });
|
|
15
18
|
i0.ɵɵelementEnd()();
|
|
16
19
|
} if (rf & 2) {
|
|
17
|
-
const
|
|
20
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
18
21
|
i0.ɵɵadvance();
|
|
19
|
-
i0.ɵɵ
|
|
22
|
+
i0.ɵɵattribute("id", ctx_r1.FilterWordId);
|
|
23
|
+
i0.ɵɵadvance(2);
|
|
24
|
+
i0.ɵɵproperty("value", ctx_r1.filterText);
|
|
25
|
+
i0.ɵɵattribute("aria-labelledby", ctx_r1.FilterLabelledBy)("aria-label", ctx_r1.FilterLabelledBy ? null : ctx_r1.FilterLabel);
|
|
20
26
|
} }
|
|
21
27
|
function MJDropdownComponent_ng_template_6_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
22
|
-
const
|
|
23
|
-
i0.ɵɵelementStart(0, "div",
|
|
24
|
-
i0.ɵɵlistener("click", function MJDropdownComponent_ng_template_6_Conditional_2_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(
|
|
28
|
+
const _r3 = i0.ɵɵgetCurrentView();
|
|
29
|
+
i0.ɵɵelementStart(0, "div", 13);
|
|
30
|
+
i0.ɵɵlistener("click", function MJDropdownComponent_ng_template_6_Conditional_2_Template_div_click_0_listener($event) { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SelectItem(null, $event)); });
|
|
25
31
|
i0.ɵɵtext(1);
|
|
26
32
|
i0.ɵɵelementEnd();
|
|
27
33
|
} if (rf & 2) {
|
|
28
|
-
const
|
|
29
|
-
i0.ɵɵclassProp("mj-dropdown-option--selected",
|
|
30
|
-
i0.ɵɵattribute("aria-selected",
|
|
34
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
35
|
+
i0.ɵɵclassProp("mj-dropdown-option--selected", ctx_r1.SelectedValue == null)("mj-dropdown-option--highlighted", ctx_r1.HighlightedIndex === -1);
|
|
36
|
+
i0.ɵɵattribute("aria-selected", ctx_r1.SelectedValue == null);
|
|
31
37
|
i0.ɵɵadvance();
|
|
32
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
38
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.GetItemText(ctx_r1.DefaultItem), " ");
|
|
33
39
|
} }
|
|
34
40
|
function MJDropdownComponent_ng_template_6_For_4_Conditional_1_ng_container_0_Template(rf, ctx) { if (rf & 1) {
|
|
35
41
|
i0.ɵɵelementContainer(0);
|
|
36
42
|
} }
|
|
37
43
|
function MJDropdownComponent_ng_template_6_For_4_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
38
|
-
i0.ɵɵtemplate(0, MJDropdownComponent_ng_template_6_For_4_Conditional_1_ng_container_0_Template, 1, 0, "ng-container",
|
|
44
|
+
i0.ɵɵtemplate(0, MJDropdownComponent_ng_template_6_For_4_Conditional_1_ng_container_0_Template, 1, 0, "ng-container", 15);
|
|
39
45
|
} if (rf & 2) {
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
i0.ɵɵproperty("ngTemplateOutlet",
|
|
46
|
+
const item_r5 = i0.ɵɵnextContext().$implicit;
|
|
47
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
48
|
+
i0.ɵɵproperty("ngTemplateOutlet", ctx_r1.itemTemplate)("ngTemplateOutletContext", i0.ɵɵpureFunction1(2, _c3, item_r5));
|
|
43
49
|
} }
|
|
44
50
|
function MJDropdownComponent_ng_template_6_For_4_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
45
51
|
i0.ɵɵtext(0);
|
|
46
52
|
} if (rf & 2) {
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
i0.ɵɵtextInterpolate1(" ",
|
|
53
|
+
const item_r5 = i0.ɵɵnextContext().$implicit;
|
|
54
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
55
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.GetItemText(item_r5), " ");
|
|
50
56
|
} }
|
|
51
57
|
function MJDropdownComponent_ng_template_6_For_4_Template(rf, ctx) { if (rf & 1) {
|
|
52
|
-
const
|
|
53
|
-
i0.ɵɵelementStart(0, "div",
|
|
54
|
-
i0.ɵɵlistener("click", function MJDropdownComponent_ng_template_6_For_4_Template_div_click_0_listener($event) { const
|
|
58
|
+
const _r4 = i0.ɵɵgetCurrentView();
|
|
59
|
+
i0.ɵɵelementStart(0, "div", 14);
|
|
60
|
+
i0.ɵɵlistener("click", function MJDropdownComponent_ng_template_6_For_4_Template_div_click_0_listener($event) { const item_r5 = i0.ɵɵrestoreView(_r4).$implicit; const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SelectItem(item_r5, $event)); });
|
|
55
61
|
i0.ɵɵconditionalCreate(1, MJDropdownComponent_ng_template_6_For_4_Conditional_1_Template, 1, 4, "ng-container")(2, MJDropdownComponent_ng_template_6_For_4_Conditional_2_Template, 1, 1);
|
|
56
62
|
i0.ɵɵelementEnd();
|
|
57
63
|
} if (rf & 2) {
|
|
58
|
-
const
|
|
59
|
-
const $
|
|
60
|
-
const
|
|
61
|
-
i0.ɵɵclassProp("mj-dropdown-option--selected",
|
|
62
|
-
i0.ɵɵattribute("aria-selected",
|
|
64
|
+
const item_r5 = ctx.$implicit;
|
|
65
|
+
const $index_r6 = ctx.$index;
|
|
66
|
+
const ctx_r1 = i0.ɵɵnextContext(2);
|
|
67
|
+
i0.ɵɵclassProp("mj-dropdown-option--selected", ctx_r1.IsItemSelected(item_r5))("mj-dropdown-option--highlighted", ctx_r1.HighlightedIndex === $index_r6);
|
|
68
|
+
i0.ɵɵattribute("aria-selected", ctx_r1.IsItemSelected(item_r5));
|
|
63
69
|
i0.ɵɵadvance();
|
|
64
|
-
i0.ɵɵconditional(
|
|
70
|
+
i0.ɵɵconditional(ctx_r1.itemTemplate ? 1 : 2);
|
|
65
71
|
} }
|
|
66
72
|
function MJDropdownComponent_ng_template_6_Conditional_5_Template(rf, ctx) { if (rf & 1) {
|
|
67
73
|
i0.ɵɵelementStart(0, "div", 10);
|
|
@@ -70,30 +76,49 @@ function MJDropdownComponent_ng_template_6_Conditional_5_Template(rf, ctx) { if
|
|
|
70
76
|
} }
|
|
71
77
|
function MJDropdownComponent_ng_template_6_Template(rf, ctx) { if (rf & 1) {
|
|
72
78
|
i0.ɵɵelementStart(0, "div", 6);
|
|
73
|
-
i0.ɵɵconditionalCreate(1, MJDropdownComponent_ng_template_6_Conditional_1_Template,
|
|
79
|
+
i0.ɵɵconditionalCreate(1, MJDropdownComponent_ng_template_6_Conditional_1_Template, 5, 4, "div", 7);
|
|
74
80
|
i0.ɵɵconditionalCreate(2, MJDropdownComponent_ng_template_6_Conditional_2_Template, 2, 6, "div", 8);
|
|
75
81
|
i0.ɵɵrepeaterCreate(3, MJDropdownComponent_ng_template_6_For_4_Template, 3, 6, "div", 9, i0.ɵɵcomponentInstance().TrackByIndex, true);
|
|
76
82
|
i0.ɵɵconditionalCreate(5, MJDropdownComponent_ng_template_6_Conditional_5_Template, 2, 0, "div", 10);
|
|
77
83
|
i0.ɵɵelementEnd();
|
|
78
84
|
} if (rf & 2) {
|
|
79
|
-
const
|
|
85
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
86
|
+
i0.ɵɵattribute("id", ctx_r1.ListboxId)("aria-label", ctx_r1.AriaLabel || null)("aria-labelledby", ctx_r1.AriaLabelledBy || null);
|
|
80
87
|
i0.ɵɵadvance();
|
|
81
|
-
i0.ɵɵconditional(
|
|
88
|
+
i0.ɵɵconditional(ctx_r1.Filterable ? 1 : -1);
|
|
82
89
|
i0.ɵɵadvance();
|
|
83
|
-
i0.ɵɵconditional(
|
|
90
|
+
i0.ɵɵconditional(ctx_r1.DefaultItem != null ? 2 : -1);
|
|
84
91
|
i0.ɵɵadvance();
|
|
85
|
-
i0.ɵɵrepeater(
|
|
92
|
+
i0.ɵɵrepeater(ctx_r1.FilteredItems);
|
|
86
93
|
i0.ɵɵadvance(2);
|
|
87
|
-
i0.ɵɵconditional(
|
|
94
|
+
i0.ɵɵconditional(ctx_r1.FilteredItems.length === 0 ? 5 : -1);
|
|
88
95
|
} }
|
|
89
96
|
/**
|
|
90
97
|
* mj-dropdown — Dropdown select component using CDK Overlay.
|
|
91
98
|
*
|
|
92
99
|
* Replaces `<kendo-dropdownlist>`.
|
|
93
100
|
*
|
|
94
|
-
*
|
|
101
|
+
* Every dropdown needs an ACCESSIBLE NAME, or it announces as "combobox, collapsed" with no hint of
|
|
102
|
+
* what it selects (WCAG 2.1 4.1.2). Use {@link AriaLabelledBy} when a visible label already exists —
|
|
103
|
+
* `<label for>` cannot name a `div[role=combobox]` — and {@link AriaLabel} when none does.
|
|
104
|
+
*
|
|
105
|
+
* @example With a visible label (preferred)
|
|
106
|
+
* ```html
|
|
107
|
+
* <span id="persona-label">Interview persona</span>
|
|
108
|
+
* <mj-dropdown
|
|
109
|
+
* AriaLabelledBy="persona-label"
|
|
110
|
+
* [Data]="items"
|
|
111
|
+
* TextField="name"
|
|
112
|
+
* ValueField="id"
|
|
113
|
+
* [(ngModel)]="selectedId"
|
|
114
|
+
* [ValuePrimitive]="true">
|
|
115
|
+
* </mj-dropdown>
|
|
116
|
+
* ```
|
|
117
|
+
*
|
|
118
|
+
* @example With no visible label
|
|
95
119
|
* ```html
|
|
96
120
|
* <mj-dropdown
|
|
121
|
+
* AriaLabel="Interview persona"
|
|
97
122
|
* [Data]="items"
|
|
98
123
|
* TextField="name"
|
|
99
124
|
* ValueField="id"
|
|
@@ -105,12 +130,48 @@ function MJDropdownComponent_ng_template_6_Template(rf, ctx) { if (rf & 1) {
|
|
|
105
130
|
* ```
|
|
106
131
|
*/
|
|
107
132
|
export class MJDropdownComponent {
|
|
133
|
+
/**
|
|
134
|
+
* Accessible name for the combobox (#3860). Without one — and with no visible label wired via
|
|
135
|
+
* {@link AriaLabelledBy} — the control announces as an UNNAMED combobox, which fails WCAG 2.1
|
|
136
|
+
* 4.1.2 (Name, Role, Value): "combobox, collapsed" with no hint of what it selects. Applied as
|
|
137
|
+
* `aria-label` on the trigger AND on the popup listbox, so both halves announce the same name.
|
|
138
|
+
*/
|
|
139
|
+
AriaLabel = '';
|
|
140
|
+
/**
|
|
141
|
+
* The id of a VISIBLE label element that names this control — the preferred wiring when a label
|
|
142
|
+
* already exists on screen (an `aria-label` would duplicate its text and drift on rename). This,
|
|
143
|
+
* not `<label for>`, is the visible-label path: the trigger is a `div[role=combobox]`, and the
|
|
144
|
+
* label-for association only names labelable form elements. `aria-labelledby` beats `AriaLabel`
|
|
145
|
+
* in the accessible-name computation where both are present. Applied to trigger AND listbox.
|
|
146
|
+
*/
|
|
147
|
+
AriaLabelledBy = '';
|
|
148
|
+
/**
|
|
149
|
+
* `id` for the combobox trigger, so other markup can REFERENCE it — `aria-controls`, hint text,
|
|
150
|
+
* test hooks. It is deliberately not documented as a `<label for>` target: the trigger is a div,
|
|
151
|
+
* which `label[for]` neither names nor focuses. To name the control from a visible label, put an
|
|
152
|
+
* id on the LABEL and pass it as {@link AriaLabelledBy}.
|
|
153
|
+
*/
|
|
154
|
+
InputId = '';
|
|
155
|
+
/** `aria-describedby` passthrough for hint/error text — same shape of gap as the name. */
|
|
156
|
+
AriaDescribedBy = '';
|
|
108
157
|
Data = [];
|
|
109
158
|
TextField = '';
|
|
110
159
|
ValueField = '';
|
|
111
160
|
Filterable = false;
|
|
112
161
|
ValuePrimitive = false;
|
|
113
|
-
|
|
162
|
+
/**
|
|
163
|
+
* Host-driven disable. Composed with Angular Forms' `setDisabledState()` into `IsDisabled`
|
|
164
|
+
* (the actual gate) — see `syncDisabled`. A setter, not a bare field, because this input is
|
|
165
|
+
* routinely bound to an expression that changes over the control's lifetime
|
|
166
|
+
* (`[Disabled]="!draft.CompanyID"`), and the gate has to follow it every time.
|
|
167
|
+
*/
|
|
168
|
+
set Disabled(value) {
|
|
169
|
+
this.disabledInput = value;
|
|
170
|
+
this.syncDisabled();
|
|
171
|
+
}
|
|
172
|
+
get Disabled() {
|
|
173
|
+
return this.disabledInput;
|
|
174
|
+
}
|
|
114
175
|
Placeholder = 'Select...';
|
|
115
176
|
DefaultItem = null;
|
|
116
177
|
FilterChange = new EventEmitter();
|
|
@@ -122,7 +183,40 @@ export class MJDropdownComponent {
|
|
|
122
183
|
cdr = inject(ChangeDetectorRef);
|
|
123
184
|
static nextId = 0;
|
|
124
185
|
DropdownId = MJDropdownComponent.nextId++;
|
|
186
|
+
/**
|
|
187
|
+
* Id of the popup listbox, so the trigger can point `aria-controls` at it while open — the half of
|
|
188
|
+
* the combobox pattern that makes "collapsed/expanded" refer to something a screen reader can
|
|
189
|
+
* find. Generated per instance from the same `static nextId` counter `dialog`, `window` and
|
|
190
|
+
* `accordion` use in this package.
|
|
191
|
+
*/
|
|
192
|
+
get ListboxId() { return `mj-dropdown-listbox-${this.DropdownId}`; }
|
|
193
|
+
/** Id of the hidden "Filter" word, composed into the filter box's name via an id list. */
|
|
194
|
+
get FilterWordId() { return `mj-dropdown-filter-word-${this.DropdownId}`; }
|
|
195
|
+
/**
|
|
196
|
+
* `aria-labelledby` for the filter box when the dropdown is named by a VISIBLE label: "Filter"
|
|
197
|
+
* plus that label's own text, composed by the accessibility tree. Empty when there is no such
|
|
198
|
+
* label, in which case {@link FilterLabel} supplies a string instead.
|
|
199
|
+
*/
|
|
200
|
+
get FilterLabelledBy() { return this.AriaLabelledBy ? `${this.FilterWordId} ${this.AriaLabelledBy}` : ''; }
|
|
201
|
+
/**
|
|
202
|
+
* `aria-label` for the filter box in the no-visible-label case.
|
|
203
|
+
*
|
|
204
|
+
* The "filter" guard is not cosmetic: this repo's house habit is `AriaLabel="Filter roles"`, and
|
|
205
|
+
* an unconditional prefix announces that box as "Filter Filter roles". A name that already begins
|
|
206
|
+
* with the word is used as-is.
|
|
207
|
+
*/
|
|
208
|
+
get FilterLabel() {
|
|
209
|
+
const name = this.AriaLabel.trim();
|
|
210
|
+
if (!name)
|
|
211
|
+
return 'Filter options';
|
|
212
|
+
return /^filter\b/i.test(name) ? name : `Filter ${name}`;
|
|
213
|
+
}
|
|
125
214
|
IsOpen = false;
|
|
215
|
+
/**
|
|
216
|
+
* The single gate on `Toggle()` / `Open()` — true when EITHER the `Disabled` input or Angular
|
|
217
|
+
* Forms says so. Never assign it directly; go through `syncDisabled()` so both sources are
|
|
218
|
+
* always composed and a lock closes an open panel.
|
|
219
|
+
*/
|
|
126
220
|
IsDisabled = false;
|
|
127
221
|
HighlightedIndex = -1;
|
|
128
222
|
SelectedValue = null;
|
|
@@ -134,6 +228,33 @@ export class MJDropdownComponent {
|
|
|
134
228
|
];
|
|
135
229
|
onChange = () => { };
|
|
136
230
|
onTouched = () => { };
|
|
231
|
+
/** Backing field for the `Disabled` input. */
|
|
232
|
+
disabledInput = false;
|
|
233
|
+
/** The forms-driven disabled state, kept SEPARATE so neither source can stomp the other. */
|
|
234
|
+
formDisabled = false;
|
|
235
|
+
/**
|
|
236
|
+
* Recompute the gate from both of its sources. Called whenever either changes.
|
|
237
|
+
*
|
|
238
|
+
* `IsDisabled` is derived state, and the only thing that assigned it was `setDisabledState()`.
|
|
239
|
+
* The forms-driven half was in fact fine — `setUpControl` also wires `registerOnDisabledChange`,
|
|
240
|
+
* so that hook fires on every `control.disable()`/`enable()`, not just at registration. What had
|
|
241
|
+
* no recompute path at all was the `Disabled` @Input: a plain field, so the gate froze at
|
|
242
|
+
* whatever the first compose produced and every later change to the input was dropped.
|
|
243
|
+
*
|
|
244
|
+
* That is how a `[Disabled]="!draft.CompanyID"` picker stayed dead for the life of the
|
|
245
|
+
* component after the company was finally chosen.
|
|
246
|
+
*/
|
|
247
|
+
syncDisabled() {
|
|
248
|
+
const disabled = this.disabledInput || this.formDisabled;
|
|
249
|
+
if (disabled === this.IsDisabled)
|
|
250
|
+
return;
|
|
251
|
+
this.IsDisabled = disabled;
|
|
252
|
+
// Becoming disabled while the panel is open would otherwise leave an interactive list
|
|
253
|
+
// hanging off a control the user can no longer operate.
|
|
254
|
+
if (disabled)
|
|
255
|
+
this.resetPanelState();
|
|
256
|
+
this.cdr.markForCheck();
|
|
257
|
+
}
|
|
137
258
|
get FilteredItems() {
|
|
138
259
|
const data = (this.Data ?? []);
|
|
139
260
|
if (!this.Filterable || !this.filterText)
|
|
@@ -172,10 +293,18 @@ export class MJDropdownComponent {
|
|
|
172
293
|
Close() {
|
|
173
294
|
if (!this.IsOpen)
|
|
174
295
|
return;
|
|
296
|
+
this.resetPanelState();
|
|
297
|
+
this.cdr.detectChanges();
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Panel state only — no change detection. Split out of `Close()` because `syncDisabled()` can
|
|
301
|
+
* run from an @Input setter, i.e. DURING the parent's change-detection pass, where a nested
|
|
302
|
+
* `detectChanges()` re-enters CD and trips NG0100 on the parent's own bindings.
|
|
303
|
+
*/
|
|
304
|
+
resetPanelState() {
|
|
175
305
|
this.IsOpen = false;
|
|
176
306
|
this.filterText = '';
|
|
177
307
|
this.HighlightedIndex = -1;
|
|
178
|
-
this.cdr.detectChanges();
|
|
179
308
|
}
|
|
180
309
|
SelectItem(item, event) {
|
|
181
310
|
event?.stopPropagation();
|
|
@@ -272,7 +401,7 @@ export class MJDropdownComponent {
|
|
|
272
401
|
writeValue(value) { this.SelectedValue = value; }
|
|
273
402
|
registerOnChange(fn) { this.onChange = fn; }
|
|
274
403
|
registerOnTouched(fn) { this.onTouched = fn; }
|
|
275
|
-
setDisabledState(isDisabled) { this.
|
|
404
|
+
setDisabledState(isDisabled) { this.formDisabled = isDisabled; this.syncDisabled(); }
|
|
276
405
|
ngOnDestroy() { this.Close(); }
|
|
277
406
|
getSelectedIndex() {
|
|
278
407
|
if (this.SelectedValue == null)
|
|
@@ -293,31 +422,30 @@ export class MJDropdownComponent {
|
|
|
293
422
|
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.filterInputEl = _t.first);
|
|
294
423
|
} }, hostVars: 2, hostBindings: function MJDropdownComponent_HostBindings(rf, ctx) { if (rf & 2) {
|
|
295
424
|
i0.ɵɵclassProp("mj-dropdown-host", ctx.hostClass);
|
|
296
|
-
} }, inputs: { Data: "Data", TextField: "TextField", ValueField: "ValueField", Filterable: "Filterable", ValuePrimitive: "ValuePrimitive", Disabled: "Disabled", Placeholder: "Placeholder", DefaultItem: "DefaultItem" }, outputs: { FilterChange: "FilterChange", ValueChange: "ValueChange" }, features: [i0.ɵɵProvidersFeature([{
|
|
425
|
+
} }, inputs: { AriaLabel: "AriaLabel", AriaLabelledBy: "AriaLabelledBy", InputId: "InputId", AriaDescribedBy: "AriaDescribedBy", Data: "Data", TextField: "TextField", ValueField: "ValueField", Filterable: "Filterable", ValuePrimitive: "ValuePrimitive", Disabled: "Disabled", Placeholder: "Placeholder", DefaultItem: "DefaultItem" }, outputs: { FilterChange: "FilterChange", ValueChange: "ValueChange" }, features: [i0.ɵɵProvidersFeature([{
|
|
297
426
|
provide: NG_VALUE_ACCESSOR,
|
|
298
427
|
useExisting: forwardRef(() => MJDropdownComponent),
|
|
299
428
|
multi: true
|
|
300
|
-
}])], decls: 7, vars:
|
|
301
|
-
const _r1 = i0.ɵɵgetCurrentView();
|
|
429
|
+
}])], decls: 7, vars: 20, consts: [["trigger", "", "overlayOrigin", "cdkOverlayOrigin"], ["filterInput", ""], ["cdkOverlayOrigin", "", "role", "combobox", "aria-haspopup", "listbox", 1, "mj-dropdown", 3, "click", "keydown", "blur"], [1, "mj-dropdown-value"], [1, "fa-solid", "fa-chevron-down", "mj-dropdown-arrow"], ["cdkConnectedOverlay", "", "cdkConnectedOverlayBackdropClass", "mj-dropdown-backdrop", 3, "backdropClick", "detach", "cdkConnectedOverlayOrigin", "cdkConnectedOverlayOpen", "cdkConnectedOverlayPositions", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHasBackdrop"], ["role", "listbox", 1, "mj-dropdown-panel"], [1, "mj-dropdown-filter-wrap"], ["role", "option", 1, "mj-dropdown-option", "mj-dropdown-option--default", 3, "mj-dropdown-option--selected", "mj-dropdown-option--highlighted"], ["role", "option", 1, "mj-dropdown-option", 3, "mj-dropdown-option--selected", "mj-dropdown-option--highlighted"], [1, "mj-dropdown-no-data"], [1, "mj-dropdown-sr-only"], ["type", "text", "placeholder", "Filter...", 1, "mj-input", "mj-dropdown-filter", 3, "input", "keydown", "value"], ["role", "option", 1, "mj-dropdown-option", "mj-dropdown-option--default", 3, "click"], ["role", "option", 1, "mj-dropdown-option", 3, "click"], [4, "ngTemplateOutlet", "ngTemplateOutletContext"]], template: function MJDropdownComponent_Template(rf, ctx) { if (rf & 1) {
|
|
302
430
|
i0.ɵɵelementStart(0, "div", 2, 0);
|
|
303
|
-
i0.ɵɵlistener("click", function MJDropdownComponent_Template_div_click_0_listener() {
|
|
431
|
+
i0.ɵɵlistener("click", function MJDropdownComponent_Template_div_click_0_listener() { return ctx.Toggle(); })("keydown", function MJDropdownComponent_Template_div_keydown_0_listener($event) { return ctx.OnKeyDown($event); })("blur", function MJDropdownComponent_Template_div_blur_0_listener() { return ctx.OnBlur(); });
|
|
304
432
|
i0.ɵɵelementStart(3, "span", 3);
|
|
305
433
|
i0.ɵɵtext(4);
|
|
306
434
|
i0.ɵɵelementEnd();
|
|
307
435
|
i0.ɵɵelement(5, "i", 4);
|
|
308
436
|
i0.ɵɵelementEnd();
|
|
309
|
-
i0.ɵɵtemplate(6, MJDropdownComponent_ng_template_6_Template, 6,
|
|
310
|
-
i0.ɵɵlistener("backdropClick", function MJDropdownComponent_Template_ng_template_backdropClick_6_listener() {
|
|
437
|
+
i0.ɵɵtemplate(6, MJDropdownComponent_ng_template_6_Template, 6, 6, "ng-template", 5);
|
|
438
|
+
i0.ɵɵlistener("backdropClick", function MJDropdownComponent_Template_ng_template_backdropClick_6_listener() { return ctx.Close(); })("detach", function MJDropdownComponent_Template_ng_template_detach_6_listener() { return ctx.Close(); });
|
|
311
439
|
} if (rf & 2) {
|
|
312
|
-
const
|
|
440
|
+
const overlayOrigin_r7 = i0.ɵɵreference(2);
|
|
313
441
|
i0.ɵɵclassProp("mj-dropdown--open", ctx.IsOpen)("mj-dropdown--disabled", ctx.IsDisabled);
|
|
314
|
-
i0.ɵɵattribute("aria-expanded", ctx.IsOpen);
|
|
442
|
+
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-controls", ctx.IsOpen ? ctx.ListboxId : null)("aria-disabled", ctx.IsDisabled ? "true" : null)("tabindex", ctx.IsDisabled ? -1 : 0);
|
|
315
443
|
i0.ɵɵadvance(3);
|
|
316
444
|
i0.ɵɵclassProp("mj-dropdown-placeholder", !ctx.HasValue);
|
|
317
445
|
i0.ɵɵadvance();
|
|
318
446
|
i0.ɵɵtextInterpolate1(" ", ctx.DisplayText, " ");
|
|
319
447
|
i0.ɵɵadvance(2);
|
|
320
|
-
i0.ɵɵproperty("cdkConnectedOverlayOrigin",
|
|
448
|
+
i0.ɵɵproperty("cdkConnectedOverlayOrigin", overlayOrigin_r7)("cdkConnectedOverlayOpen", ctx.IsOpen)("cdkConnectedOverlayPositions", ctx.Positions)("cdkConnectedOverlayWidth", ctx.TriggerWidth)("cdkConnectedOverlayHasBackdrop", true);
|
|
321
449
|
} }, dependencies: [NgTemplateOutlet, OverlayModule, i1.CdkConnectedOverlay, i1.CdkOverlayOrigin], encapsulation: 2 });
|
|
322
450
|
}
|
|
323
451
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJDropdownComponent, [{
|
|
@@ -335,9 +463,15 @@ export class MJDropdownComponent {
|
|
|
335
463
|
[class.mj-dropdown--open]="IsOpen"
|
|
336
464
|
[class.mj-dropdown--disabled]="IsDisabled"
|
|
337
465
|
role="combobox"
|
|
466
|
+
[attr.id]="InputId || null"
|
|
467
|
+
[attr.aria-label]="AriaLabel || null"
|
|
468
|
+
[attr.aria-labelledby]="AriaLabelledBy || null"
|
|
469
|
+
[attr.aria-describedby]="AriaDescribedBy || null"
|
|
338
470
|
[attr.aria-expanded]="IsOpen"
|
|
339
471
|
aria-haspopup="listbox"
|
|
340
|
-
|
|
472
|
+
[attr.aria-controls]="IsOpen ? ListboxId : null"
|
|
473
|
+
[attr.aria-disabled]="IsDisabled ? 'true' : null"
|
|
474
|
+
[attr.tabindex]="IsDisabled ? -1 : 0"
|
|
341
475
|
(click)="Toggle()"
|
|
342
476
|
(keydown)="OnKeyDown($event)"
|
|
343
477
|
(blur)="OnBlur()">
|
|
@@ -357,14 +491,28 @@ export class MJDropdownComponent {
|
|
|
357
491
|
cdkConnectedOverlayBackdropClass="mj-dropdown-backdrop"
|
|
358
492
|
(backdropClick)="Close()"
|
|
359
493
|
(detach)="Close()">
|
|
360
|
-
<div class="mj-dropdown-panel" role="listbox"
|
|
494
|
+
<div class="mj-dropdown-panel" role="listbox"
|
|
495
|
+
[attr.id]="ListboxId"
|
|
496
|
+
[attr.aria-label]="AriaLabel || null"
|
|
497
|
+
[attr.aria-labelledby]="AriaLabelledBy || null">
|
|
361
498
|
@if (Filterable) {
|
|
362
499
|
<div class="mj-dropdown-filter-wrap">
|
|
500
|
+
<!--
|
|
501
|
+
The word "Filter" lives in a hidden span rather than in a concatenated string so the
|
|
502
|
+
AriaLabelledBy path can NAME this box from the same visible label that names the
|
|
503
|
+
dropdown: aria-labelledby takes an ID LIST, so "Filter" plus the label's own text is
|
|
504
|
+
composed by the accessibility tree without this component ever seeing that text.
|
|
505
|
+
Without it, every filterable dropdown on a form named this way announces as an
|
|
506
|
+
identical "Filter options".
|
|
507
|
+
-->
|
|
508
|
+
<span class="mj-dropdown-sr-only" [attr.id]="FilterWordId">Filter</span>
|
|
363
509
|
<input
|
|
364
510
|
#filterInput
|
|
365
511
|
class="mj-input mj-dropdown-filter"
|
|
366
512
|
type="text"
|
|
367
|
-
placeholder="
|
|
513
|
+
placeholder="Filter..."
|
|
514
|
+
[attr.aria-labelledby]="FilterLabelledBy"
|
|
515
|
+
[attr.aria-label]="FilterLabelledBy ? null : FilterLabel"
|
|
368
516
|
[value]="filterText"
|
|
369
517
|
(input)="OnFilterInput($event)"
|
|
370
518
|
(keydown)="OnKeyDown($event)" />
|
|
@@ -408,7 +556,15 @@ export class MJDropdownComponent {
|
|
|
408
556
|
multi: true
|
|
409
557
|
}]
|
|
410
558
|
}]
|
|
411
|
-
}], null, {
|
|
559
|
+
}], null, { AriaLabel: [{
|
|
560
|
+
type: Input
|
|
561
|
+
}], AriaLabelledBy: [{
|
|
562
|
+
type: Input
|
|
563
|
+
}], InputId: [{
|
|
564
|
+
type: Input
|
|
565
|
+
}], AriaDescribedBy: [{
|
|
566
|
+
type: Input
|
|
567
|
+
}], Data: [{
|
|
412
568
|
type: Input
|
|
413
569
|
}], TextField: [{
|
|
414
570
|
type: Input
|
|
@@ -441,5 +597,5 @@ export class MJDropdownComponent {
|
|
|
441
597
|
type: HostBinding,
|
|
442
598
|
args: ['class.mj-dropdown-host']
|
|
443
599
|
}] }); })();
|
|
444
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJDropdownComponent, { className: "MJDropdownComponent", filePath: "lib/dropdown/dropdown.component.ts", lineNumber:
|
|
600
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJDropdownComponent, { className: "MJDropdownComponent", filePath: "lib/dropdown/dropdown.component.ts", lineNumber: 162 }); })();
|
|
445
601
|
//# sourceMappingURL=dropdown.component.js.map
|