@agorapulse/ui-components 21.1.9 → 21.1.11
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/agorapulse-ui-components-21.1.11.tgz +0 -0
- package/fesm2022/agorapulse-ui-components-dropdown-base.mjs +3 -0
- package/fesm2022/agorapulse-ui-components-dropdown-base.mjs.map +1 -1
- package/fesm2022/agorapulse-ui-components-filter-dropdown.mjs +247 -189
- package/fesm2022/agorapulse-ui-components-filter-dropdown.mjs.map +1 -1
- package/fesm2022/agorapulse-ui-components-tooltip.mjs +1 -3
- package/fesm2022/agorapulse-ui-components-tooltip.mjs.map +1 -1
- package/package.json +1 -1
- package/types/agorapulse-ui-components-filter-dropdown.d.ts +117 -49
- package/agorapulse-ui-components-21.1.9.tgz +0 -0
|
@@ -19,188 +19,191 @@ import { FormFieldComponent } from '@agorapulse/ui-components/form-field';
|
|
|
19
19
|
import { ActionDropdownComponent } from '@agorapulse/ui-components/action-dropdown';
|
|
20
20
|
import { CounterComponent } from '@agorapulse/ui-components/counter';
|
|
21
21
|
|
|
22
|
+
/** Whether a filter value represents an active selection. */
|
|
23
|
+
function hasSelection(value) {
|
|
24
|
+
switch (value.filterType) {
|
|
25
|
+
case 'checkbox':
|
|
26
|
+
return value.selected.length > 0;
|
|
27
|
+
case 'radio':
|
|
28
|
+
return Boolean(value.selected);
|
|
29
|
+
case 'toggle':
|
|
30
|
+
return value.checked;
|
|
31
|
+
case 'select':
|
|
32
|
+
return value.selectionType === 'single' ? Boolean(value.selected) : value.selected.length > 0;
|
|
33
|
+
case 'date-range':
|
|
34
|
+
return Boolean(value.selectedPeriod);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Whether a value's discriminator matches a group's type (so it may seed that group). */
|
|
38
|
+
function isCompatible(value, group) {
|
|
39
|
+
if (value.filterType !== group.filterType)
|
|
40
|
+
return false;
|
|
41
|
+
if (value.filterType === 'select' && group.filterType === 'select') {
|
|
42
|
+
return value.selectionType === group.selectionType;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
function buildEmptyValue(group) {
|
|
47
|
+
switch (group.filterType) {
|
|
48
|
+
case 'checkbox':
|
|
49
|
+
return { filterType: 'checkbox', selected: [] };
|
|
50
|
+
case 'radio':
|
|
51
|
+
return { filterType: 'radio', selected: null };
|
|
52
|
+
case 'toggle':
|
|
53
|
+
return { filterType: 'toggle', checked: false };
|
|
54
|
+
case 'select':
|
|
55
|
+
if (group.selectionType === 'single') {
|
|
56
|
+
return { filterType: 'select', selectionType: 'single', selected: undefined };
|
|
57
|
+
}
|
|
58
|
+
return { filterType: 'select', selectionType: 'multiple', selected: [] };
|
|
59
|
+
case 'date-range':
|
|
60
|
+
return { filterType: 'date-range', selectedPeriod: undefined };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Working state for a single filter-dropdown instance. Component-scoped (provided on
|
|
65
|
+
* `FilterDropdownComponent`), never `providedIn: 'root'`.
|
|
66
|
+
*
|
|
67
|
+
* This is a PURE state container: every method here only reads or writes signals — none of them
|
|
68
|
+
* emit anything. The apply→value→apply loop is impossible because the ONLY code that emits
|
|
69
|
+
* `applyFilters` lives inside the component's user-gesture handlers (see FilterDropdownComponent),
|
|
70
|
+
* and seeding an input never runs a gesture handler. Re-seeding `value`/`savedValue` therefore
|
|
71
|
+
* updates the draft and stops there — there is no emit path to loop through.
|
|
72
|
+
*
|
|
73
|
+
* The internal `_baseline` is the dirty-tracking reference: seeded from the `savedValue` input
|
|
74
|
+
* (falling back to `value`), and moved locally by `commit()` on Apply/Save/Update.
|
|
75
|
+
*/
|
|
22
76
|
class FilterState {
|
|
23
77
|
_groups = signal([], ...(ngDevMode ? [{ debugName: "_groups" }] : /* istanbul ignore next */ []));
|
|
24
|
-
// Deep-equal so that re-seeding with equivalent values
|
|
78
|
+
// Deep-equal so that re-seeding with equivalent values keeps the same reference (fewer recomputes downstream).
|
|
25
79
|
_draft = signal({}, { ...(ngDevMode ? { debugName: "_draft" } : /* istanbul ignore next */ {}), equal: isEqual });
|
|
26
80
|
_baseline = signal({}, { ...(ngDevMode ? { debugName: "_baseline" } : /* istanbul ignore next */ {}), equal: isEqual });
|
|
81
|
+
// Live expand/collapse state, keyed by group key. Owned here, never written back to the `groups` config.
|
|
82
|
+
_expanded = signal({}, ...(ngDevMode ? [{ debugName: "_expanded" }] : /* istanbul ignore next */ []));
|
|
83
|
+
groups = this._groups.asReadonly();
|
|
84
|
+
draft = this._draft.asReadonly();
|
|
85
|
+
expanded = this._expanded.asReadonly();
|
|
27
86
|
activeFilterCount = computed(() => {
|
|
87
|
+
const draft = this._draft();
|
|
28
88
|
let count = 0;
|
|
29
|
-
for (const key in
|
|
30
|
-
const value =
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
switch (value.filterType) {
|
|
34
|
-
case 'checkbox':
|
|
35
|
-
if (value.selected.length > 0) {
|
|
36
|
-
count += 1;
|
|
37
|
-
}
|
|
38
|
-
break;
|
|
39
|
-
case 'radio':
|
|
40
|
-
if (value.selected)
|
|
41
|
-
count += 1;
|
|
42
|
-
break;
|
|
43
|
-
case 'toggle':
|
|
44
|
-
if (value.checked)
|
|
45
|
-
count += 1;
|
|
46
|
-
break;
|
|
47
|
-
case 'select':
|
|
48
|
-
if (value.selectionType === 'single' && value.selected) {
|
|
49
|
-
count += 1;
|
|
50
|
-
}
|
|
51
|
-
else if (value.selectionType === 'multiple') {
|
|
52
|
-
count += value.selected.length > 0 ? 1 : 0;
|
|
53
|
-
}
|
|
54
|
-
break;
|
|
55
|
-
case 'date-range':
|
|
56
|
-
if (value.selectedPeriod)
|
|
57
|
-
count += 1;
|
|
58
|
-
break;
|
|
59
|
-
}
|
|
89
|
+
for (const key in draft) {
|
|
90
|
+
const value = draft[key];
|
|
91
|
+
if (value && hasSelection(value))
|
|
92
|
+
count += 1;
|
|
60
93
|
}
|
|
61
94
|
return count;
|
|
62
95
|
}, ...(ngDevMode ? [{ debugName: "activeFilterCount" }] : /* istanbul ignore next */ []));
|
|
63
|
-
groups = this._groups.asReadonly();
|
|
64
|
-
draft = this._draft.asReadonly();
|
|
65
96
|
isFilterCountActive = computed(() => this.activeFilterCount() > 0, ...(ngDevMode ? [{ debugName: "isFilterCountActive" }] : /* istanbul ignore next */ []));
|
|
66
97
|
hasChanges = computed(() => !isEqual(this._draft(), this._baseline()), ...(ngDevMode ? [{ debugName: "hasChanges" }] : /* istanbul ignore next */ []));
|
|
98
|
+
/** Save / Update / Reset / Apply are gated on dirty state. */
|
|
67
99
|
buttonsDisabled = computed(() => !this.hasChanges(), ...(ngDevMode ? [{ debugName: "buttonsDisabled" }] : /* istanbul ignore next */ []));
|
|
68
|
-
/**
|
|
69
|
-
|
|
100
|
+
/** Clear is gated on "is there anything to clear", not on dirty state. */
|
|
101
|
+
clearDisabled = computed(() => this.activeFilterCount() === 0, ...(ngDevMode ? [{ debugName: "clearDisabled" }] : /* istanbul ignore next */ []));
|
|
102
|
+
// --- Seeding (pure signal writes; nothing here emits) ---
|
|
103
|
+
/** Refresh the structural schema and reconcile the value keyspace (add empty / drop removed). */
|
|
104
|
+
setSchema(groups) {
|
|
70
105
|
this._groups.set(groups);
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.
|
|
106
|
+
this.seedExpanded(groups);
|
|
107
|
+
this._draft.update(draft => this.reconcileKeyspace(draft, groups));
|
|
108
|
+
this._baseline.update(baseline => this.reconcileKeyspace(baseline, groups));
|
|
109
|
+
}
|
|
110
|
+
/** Seed the draft from an external value, projected onto the current keyspace. Echo-gated, silent. */
|
|
111
|
+
seedDraft(value) {
|
|
112
|
+
this._draft.set(this.projectValues(value));
|
|
113
|
+
}
|
|
114
|
+
/** Seed the baseline (the saved reference for dirty tracking / reset) from an external value. Silent. */
|
|
115
|
+
seedBaseline(value) {
|
|
116
|
+
this._baseline.set(this.projectValues(value));
|
|
78
117
|
}
|
|
79
|
-
|
|
118
|
+
// --- Commit / user actions ---
|
|
119
|
+
/** Adopt the current draft as the baseline (Apply / Save / Update). */
|
|
80
120
|
commit() {
|
|
81
121
|
this._baseline.set({ ...this._draft() });
|
|
82
122
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
values[group.key] = this.buildInitialValue(group);
|
|
87
|
-
}
|
|
88
|
-
return values;
|
|
123
|
+
/** Revert the draft to the committed baseline (user action). */
|
|
124
|
+
reset() {
|
|
125
|
+
this._draft.set({ ...this._baseline() });
|
|
89
126
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
127
|
+
/** Clear all draft values to their empty states (user action). */
|
|
128
|
+
clear() {
|
|
129
|
+
const cleared = {};
|
|
130
|
+
for (const group of this._groups()) {
|
|
131
|
+
cleared[group.key] = buildEmptyValue(group);
|
|
95
132
|
}
|
|
133
|
+
this._draft.set(cleared);
|
|
96
134
|
}
|
|
97
|
-
|
|
135
|
+
// --- Value selectors / mutators ---
|
|
136
|
+
/** Get the draft value for a specific filter key. */
|
|
98
137
|
getValue(key) {
|
|
99
138
|
return this._draft()[key];
|
|
100
139
|
}
|
|
101
|
-
/**
|
|
140
|
+
/** Return the current draft snapshot (used on Apply / Save). */
|
|
141
|
+
getSnapshot() {
|
|
142
|
+
return { ...this._draft() };
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Apply a single filter's fully-formed draft value (user action). The value is built by the
|
|
146
|
+
* leaf that owns the widget; this state only stores it, keeping the type-specific shaping at
|
|
147
|
+
* the edge where the DOM event happens.
|
|
148
|
+
*/
|
|
102
149
|
updateValue(key, value) {
|
|
103
150
|
this._draft.update(draft => ({ ...draft, [key]: value }));
|
|
104
151
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return;
|
|
110
|
-
const selected = checked ? [...current.selected, name] : current.selected.filter(n => n !== name);
|
|
111
|
-
this.updateValue(key, { filterType: 'checkbox', selected });
|
|
112
|
-
}
|
|
113
|
-
/** Set the selected radio value */
|
|
114
|
-
setRadioValue(key, value) {
|
|
115
|
-
this.updateValue(key, { filterType: 'radio', selected: value });
|
|
116
|
-
}
|
|
117
|
-
/** Set the toggle checked state */
|
|
118
|
-
setToggleValue(key, checked) {
|
|
119
|
-
this.updateValue(key, { filterType: 'toggle', checked });
|
|
152
|
+
// --- Expand / collapse ---
|
|
153
|
+
/** Whether a group is currently expanded. Defaults to collapsed for unknown keys. */
|
|
154
|
+
isExpanded(key) {
|
|
155
|
+
return this._expanded()[key] ?? false;
|
|
120
156
|
}
|
|
121
|
-
/**
|
|
122
|
-
|
|
123
|
-
this.
|
|
124
|
-
}
|
|
125
|
-
setMultipleSelectValue(key, selected) {
|
|
126
|
-
this.updateValue(key, { filterType: 'select', selectionType: 'multiple', selected });
|
|
127
|
-
}
|
|
128
|
-
/** Set the selected period for a date range filter */
|
|
129
|
-
setDateRangeValue(key, selectedPeriod) {
|
|
130
|
-
this.updateValue(key, { filterType: 'date-range', selectedPeriod });
|
|
131
|
-
}
|
|
132
|
-
/** Return the current draft snapshot (used on Apply) */
|
|
133
|
-
getSnapshot() {
|
|
134
|
-
return { ...this._draft() };
|
|
157
|
+
/** Toggle a group's expand/collapse state. Updates internal state only — the config is never mutated. */
|
|
158
|
+
collapseHeader(key) {
|
|
159
|
+
this._expanded.update(expanded => ({ ...expanded, [key]: !(expanded[key] ?? false) }));
|
|
135
160
|
}
|
|
136
|
-
/**
|
|
137
|
-
|
|
138
|
-
|
|
161
|
+
/**
|
|
162
|
+
* On open, optionally re-derive each group's expanded state from a policy. `'collapse-empty'` expands
|
|
163
|
+
* groups that currently have a selection; a custom predicate is evaluated against the current draft.
|
|
164
|
+
* When no policy is given the state is left untouched, so it persists across opens.
|
|
165
|
+
*/
|
|
166
|
+
applyExpandOnOpen(policy) {
|
|
167
|
+
if (!policy)
|
|
168
|
+
return;
|
|
169
|
+
const predicate = policy === 'collapse-empty' ? (_group, value) => hasSelection(value) : policy;
|
|
170
|
+
const draft = this._draft();
|
|
171
|
+
this._expanded.update(expanded => {
|
|
172
|
+
const next = {};
|
|
173
|
+
for (const group of this._groups()) {
|
|
174
|
+
const value = draft[group.key];
|
|
175
|
+
next[group.key] = value ? predicate(group, value) : (expanded[group.key] ?? false);
|
|
176
|
+
}
|
|
177
|
+
return next;
|
|
178
|
+
});
|
|
139
179
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
180
|
+
// --- Internals ---
|
|
181
|
+
/** Seed the live expanded state from config, preserving any key that already has a live value. */
|
|
182
|
+
seedExpanded(groups) {
|
|
183
|
+
this._expanded.update(current => {
|
|
184
|
+
const next = {};
|
|
185
|
+
for (const group of groups) {
|
|
186
|
+
next[group.key] = current[group.key] ?? group.expanded ?? false;
|
|
187
|
+
}
|
|
188
|
+
return next;
|
|
189
|
+
});
|
|
147
190
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
selected: group.defaultSelected ?? [],
|
|
154
|
-
};
|
|
155
|
-
case 'radio':
|
|
156
|
-
const firstItem = group.items[0].value;
|
|
157
|
-
return {
|
|
158
|
-
filterType: 'radio',
|
|
159
|
-
selected: group.defaultSelected ?? firstItem,
|
|
160
|
-
};
|
|
161
|
-
case 'toggle':
|
|
162
|
-
return {
|
|
163
|
-
filterType: 'toggle',
|
|
164
|
-
checked: group.defaultSelected ?? false,
|
|
165
|
-
};
|
|
166
|
-
case 'select':
|
|
167
|
-
if (group.selectionType === 'single') {
|
|
168
|
-
return {
|
|
169
|
-
filterType: 'select',
|
|
170
|
-
selectionType: 'single',
|
|
171
|
-
selected: group.defaultSelected ? group.defaultSelected : undefined,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
return {
|
|
176
|
-
filterType: 'select',
|
|
177
|
-
selectionType: 'multiple',
|
|
178
|
-
selected: group.defaultSelected ?? [],
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
case 'date-range':
|
|
182
|
-
return {
|
|
183
|
-
filterType: 'date-range',
|
|
184
|
-
selectedPeriod: group.selectedPeriod,
|
|
185
|
-
};
|
|
191
|
+
/** Keep only keys present in `groups`; fill missing keys with their empty value, preserve existing ones. */
|
|
192
|
+
reconcileKeyspace(values, groups) {
|
|
193
|
+
const next = {};
|
|
194
|
+
for (const group of groups) {
|
|
195
|
+
next[group.key] = values[group.key] ?? buildEmptyValue(group);
|
|
186
196
|
}
|
|
197
|
+
return next;
|
|
187
198
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
case 'toggle':
|
|
195
|
-
return { filterType: 'toggle', checked: false };
|
|
196
|
-
case 'select':
|
|
197
|
-
if (group.selectionType === 'single') {
|
|
198
|
-
return { filterType: 'select', selectionType: 'single', selected: undefined };
|
|
199
|
-
}
|
|
200
|
-
return { filterType: 'select', selectionType: 'multiple', selected: [] };
|
|
201
|
-
case 'date-range':
|
|
202
|
-
return { filterType: 'date-range', selectedPeriod: undefined };
|
|
199
|
+
/** Project an external value onto the current keyspace: matching entries kept, others empty, extras dropped. */
|
|
200
|
+
projectValues(value) {
|
|
201
|
+
const next = {};
|
|
202
|
+
for (const group of this._groups()) {
|
|
203
|
+
const candidate = value[group.key];
|
|
204
|
+
next[group.key] = candidate && isCompatible(candidate, group) ? candidate : buildEmptyValue(group);
|
|
203
205
|
}
|
|
206
|
+
return next;
|
|
204
207
|
}
|
|
205
208
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FilterState, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
206
209
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FilterState });
|
|
@@ -213,12 +216,20 @@ const MULTIPLE_DISPLAY_TYPES = new Set(['tag', 'label']);
|
|
|
213
216
|
class FilterLeafSelectComponent {
|
|
214
217
|
filterState = inject(FilterState);
|
|
215
218
|
item = input.required(...(ngDevMode ? [{ debugName: "item" }] : /* istanbul ignore next */ []));
|
|
219
|
+
/** Reports a user edit up (forwarded by the leaf to the dropdown). */
|
|
220
|
+
valueChange = output();
|
|
216
221
|
/** Event emitted when a select item feature locked is clicked */
|
|
217
222
|
lockedFeatureClicked = output();
|
|
218
223
|
multipleDisplayType = computed(() => {
|
|
219
224
|
const dt = this.item().displayType;
|
|
220
225
|
return MULTIPLE_DISPLAY_TYPES.has(dt) ? dt : 'label';
|
|
221
226
|
}, ...(ngDevMode ? [{ debugName: "multipleDisplayType" }] : /* istanbul ignore next */ []));
|
|
227
|
+
onSingleSelectChange(selected) {
|
|
228
|
+
this.valueChange.emit({ key: this.item().key, value: { filterType: 'select', selectionType: 'single', selected } });
|
|
229
|
+
}
|
|
230
|
+
onMultipleSelectChange(selected) {
|
|
231
|
+
this.valueChange.emit({ key: this.item().key, value: { filterType: 'select', selectionType: 'multiple', selected } });
|
|
232
|
+
}
|
|
222
233
|
singleSelectValue = computed(() => {
|
|
223
234
|
const value = this.filterState.getValue(this.item().key);
|
|
224
235
|
return value?.filterType === 'select' && value.selectionType === 'single' ? value.selected : undefined;
|
|
@@ -228,7 +239,7 @@ class FilterLeafSelectComponent {
|
|
|
228
239
|
return value?.filterType === 'select' && value?.selectionType === 'multiple' ? value.selected : [];
|
|
229
240
|
}, ...(ngDevMode ? [{ debugName: "multipleSelectValue" }] : /* istanbul ignore next */ []));
|
|
230
241
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FilterLeafSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
231
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FilterLeafSelectComponent, isStandalone: true, selector: "ap-filter-leaf-select", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { lockedFeatureClicked: "lockedFeatureClicked" }, ngImport: i0, template: "@let selectItem = item();\n<div class=\"ap-filter-leaf__option\">\n <ap-form-field>\n @if (selectItem.label) {\n <label for=\"select-{{ selectItem.key }}\">\n {{ selectItem.label }}\n </label>\n }\n @if (selectItem.selectionType === 'single') {\n <ng-select\n id=\"select-{{ selectItem.key }}\"\n apSelectSingle\n bindLabel=\"label\"\n bindValue=\"value\"\n [disabled]=\"!!selectItem.featureLocked\"\n [items]=\"selectItem.items\"\n [placeholder]=\"selectItem.placeholder ?? 'Select an option'\"\n [inlineLabel]=\"selectItem.inlineLabel\"\n [ngModel]=\"singleSelectValue()\"\n (ngModelChange)=\"
|
|
242
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FilterLeafSelectComponent, isStandalone: true, selector: "ap-filter-leaf-select", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { valueChange: "valueChange", lockedFeatureClicked: "lockedFeatureClicked" }, ngImport: i0, template: "@let selectItem = item();\n<div class=\"ap-filter-leaf__option\">\n <ap-form-field>\n @if (selectItem.label) {\n <label for=\"select-{{ selectItem.key }}\">\n {{ selectItem.label }}\n </label>\n }\n @if (selectItem.selectionType === 'single') {\n <ng-select\n id=\"select-{{ selectItem.key }}\"\n apSelectSingle\n bindLabel=\"label\"\n bindValue=\"value\"\n [disabled]=\"!!selectItem.featureLocked\"\n [items]=\"selectItem.items\"\n [placeholder]=\"selectItem.placeholder ?? 'Select an option'\"\n [inlineLabel]=\"selectItem.inlineLabel\"\n [ngModel]=\"singleSelectValue()\"\n (ngModelChange)=\"onSingleSelectChange($event)\"\n >\n <ng-template\n let-item=\"item\"\n ng-label-tmp>\n <ap-select-label-single\n [displayType]=\"selectItem.displayType\"\n [avatarUrl]=\"item.avatarUrl\"\n [network]=\"item.network\"\n [label]=\"item.label\" />\n </ng-template>\n\n <ng-template\n let-item=\"item\"\n let-item$=\"item$\"\n ng-option-tmp>\n @if (item.caption) {\n <ap-dropdown-item-single-two-lines\n [caption]=\"item$.caption\"\n [selected]=\"item$.selected\"\n [text]=\"item$.label\"\n [avatarUrl]=\"item$.avatarUrl\"\n [network]=\"item$.network\"\n [symbolId]=\"item$.symbolId\"\n [isFeatureLocked]=\"item.featureLocked\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit(item)\"\n />\n } @else {\n <ap-dropdown-item-single-one-line\n [selected]=\"item$.selected\"\n [text]=\"item.label\"\n [avatarUrl]=\"item.avatarUrl\"\n [network]=\"item.network\"\n [symbolId]=\"item.symbolId\"\n [isFeatureLocked]=\"item.featureLocked\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit(item)\"\n />\n }\n\n </ng-template>\n\n </ng-select>\n } @else {\n <ng-select\n id=\"select-{{ selectItem.key }}\"\n apSelectMultiple\n bindLabel=\"label\"\n bindValue=\"value\"\n [items]=\"selectItem.items\"\n [placeholder]=\"selectItem.placeholder ?? 'Select an option'\"\n [inlineLabel]=\"selectItem.inlineLabel\"\n [ngModel]=\"multipleSelectValue()\"\n (ngModelChange)=\"onMultipleSelectChange($event)\">\n <ng-template\n let-items=\"items\"\n let-clear=\"clear\"\n ng-multi-label-tmp>\n <ap-select-label-multiple\n bindValue=\"value\"\n bindLabel=\"label\"\n [displayType]=\"multipleDisplayType()\"\n [selectedItems]=\"items\"\n (removeItem)=\"clear($event)\"\n />\n </ng-template>\n\n <ng-template\n let-item=\"item\"\n let-item$=\"item$\"\n ng-option-tmp>\n @if (item.caption) {\n <ap-dropdown-item-multiple-two-lines\n [selected]=\"item$.selected\"\n [onlyText]=\"selectItem.onlyText ?? 'Only'\"\n [caption]=\"item.caption\"\n [text]=\"item.label\"\n [htmlId]=\"item$.htmlId\"\n [avatarUrl]=\"item.avatarUrl\"\n [network]=\"item.network\"\n [symbolId]=\"item.symbolId\"\n [isFeatureLocked]=\"item.featureLocked\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit(item)\"\n />\n } @else {\n <ap-dropdown-item-multiple-one-line\n [onlyText]=\"selectItem.onlyText ?? 'Only'\"\n [selected]=\"item$.selected\"\n [htmlId]=\"item$.htmlId\"\n [text]=\"item.label\"\n [avatarUrl]=\"item.avatarUrl\"\n [network]=\"item.network\"\n [symbolId]=\"item.symbolId\"\n [isFeatureLocked]=\"item.featureLocked\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit(item)\"\n />\n }\n </ng-template>\n </ng-select>\n }\n </ap-form-field>\n</div>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: NgSelectComponent, selector: "ng-select", inputs: ["ariaLabelDropdown", "ariaLabel", "markFirst", "placeholder", "fixedPlaceholder", "notFoundText", "typeToSearchText", "preventToggleOnRightClick", "addTagText", "loadingText", "clearAllText", "dropdownPosition", "appendTo", "outsideClickEvent", "loading", "closeOnSelect", "hideSelected", "selectOnTab", "openOnEnter", "maxSelectedItems", "groupBy", "groupValue", "bufferAmount", "virtualScroll", "selectableGroup", "tabFocusOnClearButton", "selectableGroupAsModel", "searchFn", "trackByFn", "clearOnBackspace", "labelForId", "inputAttrs", "tabIndex", "readonly", "searchWhileComposing", "minTermLength", "editableSearchTerm", "ngClass", "typeahead", "multiple", "addTag", "searchable", "clearable", "clearKeepsDisabledOptions", "deselectOnClick", "clearSearchOnAdd", "compareWith", "keyDownFn", "popover", "bindLabel", "bindValue", "appearance", "isOpen", "items"], outputs: ["bindLabelChange", "bindValueChange", "appearanceChange", "isOpenChange", "itemsChange", "blur", "focus", "change", "open", "close", "search", "clear", "add", "remove", "scroll", "scrollToEnd"], exportAs: ["ngSelect"] }, { kind: "directive", type: SelectMultipleDirective, selector: "ng-select[apSelectMultiple]", inputs: ["maxItemsTooltip", "pinnedItemsEnabled"] }, { kind: "directive", type: SelectSingleDirective, selector: "ng-select[apSelectSingle]" }, { kind: "component", type: SelectLabelSingleComponent, selector: "ap-select-label-single", inputs: ["displayType", "label", "avatarUrl", "network", "showAvatarInitials", "roundedAvatar"] }, { kind: "component", type: SelectLabelMultipleComponent, selector: "ap-select-label-multiple", inputs: ["displayType", "tagColor", "selectedItems", "bindLabel", "bindValue", "bindAvatarUrl", "bindSymbolId", "roundedAvatar", "bindNetwork"], outputs: ["removeItem"] }, { kind: "directive", type: NgOptionTemplateDirective, selector: "[ng-option-tmp]" }, { kind: "component", type: DropdownItemMultipleTwoLinesComponent, selector: "ap-dropdown-item-multiple-two-lines", inputs: ["text", "caption", "selected", "htmlId", "disabled", "avatarUrl", "symbolId", "disabledTooltip", "badgeText", "dividerEnabled", "onlyEnabled", "onlyText", "isFeatureLocked", "roundedAvatar", "network", "symbolColor", "symbolTooltipText"], outputs: ["selectOnly", "lockedFeatureClicked"] }, { kind: "component", type: DropdownItemMultipleOneLineComponent, selector: "ap-dropdown-item-multiple-one-line", inputs: ["text", "selected", "indeterminate", "htmlId", "disabled", "avatarUrl", "symbolId", "disabledTooltip", "badgeText", "dividerEnabled", "onlyEnabled", "onlyText", "isFeatureLocked", "roundedAvatar", "network", "symbolColor", "symbolTooltipText"], outputs: ["selectOnly", "selectionChange", "lockedFeatureClicked"] }, { kind: "component", type: DropdownItemSingleOneLineComponent, selector: "ap-dropdown-item-single-one-line", inputs: ["text", "selected", "disabled", "avatarUrl", "showAvatarInitials", "symbolId", "disabledTooltip", "badgeText", "dividerEnabled", "network", "roundedAvatar", "isFeatureLocked"], outputs: ["lockedFeatureClicked"] }, { kind: "component", type: DropdownItemSingleTwoLinesComponent, selector: "ap-dropdown-item-single-two-lines", inputs: ["text", "caption", "selected", "disabled", "avatarUrl", "symbolId", "disabledTooltip", "badgeText", "dividerEnabled", "network", "roundedAvatar", "isFeatureLocked"], outputs: ["lockedFeatureClicked"] }, { kind: "directive", type: NgLabelTemplateDirective, selector: "[ng-label-tmp]" }, { kind: "directive", type: NgMultiLabelTemplateDirective, selector: "[ng-multi-label-tmp]" }, { kind: "component", type: FormFieldComponent, selector: "ap-form-field" }] });
|
|
232
243
|
}
|
|
233
244
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FilterLeafSelectComponent, decorators: [{
|
|
234
245
|
type: Component,
|
|
@@ -247,8 +258,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
247
258
|
NgLabelTemplateDirective,
|
|
248
259
|
NgMultiLabelTemplateDirective,
|
|
249
260
|
FormFieldComponent,
|
|
250
|
-
], template: "@let selectItem = item();\n<div class=\"ap-filter-leaf__option\">\n <ap-form-field>\n @if (selectItem.label) {\n <label for=\"select-{{ selectItem.key }}\">\n {{ selectItem.label }}\n </label>\n }\n @if (selectItem.selectionType === 'single') {\n <ng-select\n id=\"select-{{ selectItem.key }}\"\n apSelectSingle\n bindLabel=\"label\"\n bindValue=\"value\"\n [disabled]=\"!!selectItem.featureLocked\"\n [items]=\"selectItem.items\"\n [placeholder]=\"selectItem.placeholder ?? 'Select an option'\"\n [inlineLabel]=\"selectItem.inlineLabel\"\n [ngModel]=\"singleSelectValue()\"\n (ngModelChange)=\"
|
|
251
|
-
}], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], lockedFeatureClicked: [{ type: i0.Output, args: ["lockedFeatureClicked"] }] } });
|
|
261
|
+
], template: "@let selectItem = item();\n<div class=\"ap-filter-leaf__option\">\n <ap-form-field>\n @if (selectItem.label) {\n <label for=\"select-{{ selectItem.key }}\">\n {{ selectItem.label }}\n </label>\n }\n @if (selectItem.selectionType === 'single') {\n <ng-select\n id=\"select-{{ selectItem.key }}\"\n apSelectSingle\n bindLabel=\"label\"\n bindValue=\"value\"\n [disabled]=\"!!selectItem.featureLocked\"\n [items]=\"selectItem.items\"\n [placeholder]=\"selectItem.placeholder ?? 'Select an option'\"\n [inlineLabel]=\"selectItem.inlineLabel\"\n [ngModel]=\"singleSelectValue()\"\n (ngModelChange)=\"onSingleSelectChange($event)\"\n >\n <ng-template\n let-item=\"item\"\n ng-label-tmp>\n <ap-select-label-single\n [displayType]=\"selectItem.displayType\"\n [avatarUrl]=\"item.avatarUrl\"\n [network]=\"item.network\"\n [label]=\"item.label\" />\n </ng-template>\n\n <ng-template\n let-item=\"item\"\n let-item$=\"item$\"\n ng-option-tmp>\n @if (item.caption) {\n <ap-dropdown-item-single-two-lines\n [caption]=\"item$.caption\"\n [selected]=\"item$.selected\"\n [text]=\"item$.label\"\n [avatarUrl]=\"item$.avatarUrl\"\n [network]=\"item$.network\"\n [symbolId]=\"item$.symbolId\"\n [isFeatureLocked]=\"item.featureLocked\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit(item)\"\n />\n } @else {\n <ap-dropdown-item-single-one-line\n [selected]=\"item$.selected\"\n [text]=\"item.label\"\n [avatarUrl]=\"item.avatarUrl\"\n [network]=\"item.network\"\n [symbolId]=\"item.symbolId\"\n [isFeatureLocked]=\"item.featureLocked\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit(item)\"\n />\n }\n\n </ng-template>\n\n </ng-select>\n } @else {\n <ng-select\n id=\"select-{{ selectItem.key }}\"\n apSelectMultiple\n bindLabel=\"label\"\n bindValue=\"value\"\n [items]=\"selectItem.items\"\n [placeholder]=\"selectItem.placeholder ?? 'Select an option'\"\n [inlineLabel]=\"selectItem.inlineLabel\"\n [ngModel]=\"multipleSelectValue()\"\n (ngModelChange)=\"onMultipleSelectChange($event)\">\n <ng-template\n let-items=\"items\"\n let-clear=\"clear\"\n ng-multi-label-tmp>\n <ap-select-label-multiple\n bindValue=\"value\"\n bindLabel=\"label\"\n [displayType]=\"multipleDisplayType()\"\n [selectedItems]=\"items\"\n (removeItem)=\"clear($event)\"\n />\n </ng-template>\n\n <ng-template\n let-item=\"item\"\n let-item$=\"item$\"\n ng-option-tmp>\n @if (item.caption) {\n <ap-dropdown-item-multiple-two-lines\n [selected]=\"item$.selected\"\n [onlyText]=\"selectItem.onlyText ?? 'Only'\"\n [caption]=\"item.caption\"\n [text]=\"item.label\"\n [htmlId]=\"item$.htmlId\"\n [avatarUrl]=\"item.avatarUrl\"\n [network]=\"item.network\"\n [symbolId]=\"item.symbolId\"\n [isFeatureLocked]=\"item.featureLocked\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit(item)\"\n />\n } @else {\n <ap-dropdown-item-multiple-one-line\n [onlyText]=\"selectItem.onlyText ?? 'Only'\"\n [selected]=\"item$.selected\"\n [htmlId]=\"item$.htmlId\"\n [text]=\"item.label\"\n [avatarUrl]=\"item.avatarUrl\"\n [network]=\"item.network\"\n [symbolId]=\"item.symbolId\"\n [isFeatureLocked]=\"item.featureLocked\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit(item)\"\n />\n }\n </ng-template>\n </ng-select>\n }\n </ap-form-field>\n</div>\n" }]
|
|
262
|
+
}], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], lockedFeatureClicked: [{ type: i0.Output, args: ["lockedFeatureClicked"] }] } });
|
|
252
263
|
|
|
253
264
|
class FilterLeafComponent {
|
|
254
265
|
DatepickerMode = DatepickerMode;
|
|
@@ -258,10 +269,14 @@ class FilterLeafComponent {
|
|
|
258
269
|
/** whether the leaf is closable */
|
|
259
270
|
closable = input(true, ...(ngDevMode ? [{ debugName: "closable" }] : /* istanbul ignore next */ []));
|
|
260
271
|
isLastLeaf = input(false, ...(ngDevMode ? [{ debugName: "isLastLeaf" }] : /* istanbul ignore next */ []));
|
|
272
|
+
/** Reports a user edit up to the dropdown, which owns the apply/emit decision. */
|
|
273
|
+
valueChange = output();
|
|
261
274
|
/** Event emitted when a select item feature locked is clicked */
|
|
262
275
|
lockedFeatureClicked = output();
|
|
263
276
|
/** Event emitted when a group with locked feature is clicked */
|
|
264
277
|
filterDropdownGroupLockedClicked = output();
|
|
278
|
+
/** Live expand/collapse state for this leaf, owned by FilterState (not read from the `item` config). */
|
|
279
|
+
expanded = computed(() => this.filterState.isExpanded(this.item().key), ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
265
280
|
displayLabelInLeaf = computed(() => {
|
|
266
281
|
const item = this.item();
|
|
267
282
|
return item.filterType === 'checkbox' || item.filterType === 'radio' || item.filterType === 'toggle';
|
|
@@ -317,19 +332,27 @@ class FilterLeafComponent {
|
|
|
317
332
|
}
|
|
318
333
|
}
|
|
319
334
|
onCheckboxChange(name, checked) {
|
|
320
|
-
|
|
335
|
+
// ap-checkbox re-emits its inner <input>'s native `change` (a DOM Event) that Angular's
|
|
336
|
+
// `(change)` binding catches alongside the component's boolean @Output; ignore the
|
|
337
|
+
// non-boolean echo, otherwise a check→uncheck round-trip never nets back to empty.
|
|
338
|
+
if (typeof checked !== 'boolean')
|
|
339
|
+
return;
|
|
340
|
+
const current = this.filterState.getValue(this.item().key);
|
|
341
|
+
const selected = current?.filterType === 'checkbox' ? current.selected : [];
|
|
342
|
+
const next = checked ? [...selected, name] : selected.filter(n => n !== name);
|
|
343
|
+
this.valueChange.emit({ key: this.item().key, value: { filterType: 'checkbox', selected: next } });
|
|
321
344
|
}
|
|
322
345
|
onRadioClick(value) {
|
|
323
|
-
this.
|
|
346
|
+
this.valueChange.emit({ key: this.item().key, value: { filterType: 'radio', selected: value } });
|
|
324
347
|
}
|
|
325
348
|
onToggleChange(checked) {
|
|
326
|
-
this.
|
|
349
|
+
this.valueChange.emit({ key: this.item().key, value: { filterType: 'toggle', checked } });
|
|
327
350
|
}
|
|
328
|
-
onDateRangeChange(
|
|
329
|
-
this.
|
|
351
|
+
onDateRangeChange(selectedPeriod) {
|
|
352
|
+
this.valueChange.emit({ key: this.item().key, value: { filterType: 'date-range', selectedPeriod } });
|
|
330
353
|
}
|
|
331
354
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FilterLeafComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
332
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FilterLeafComponent, isStandalone: true, selector: "ap-filter-leaf", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, isLastLeaf: { classPropertyName: "isLastLeaf", publicName: "isLastLeaf", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { lockedFeatureClicked: "lockedFeatureClicked", filterDropdownGroupLockedClicked: "filterDropdownGroupLockedClicked" }, providers: [provideUiComponentsSymbols(apChevronDown, apInfo, apFeatureLock)], ngImport: i0, template: "<div [class.with-border-bottom]=\"!isLastLeaf()\" class=\"ap-filter-leaf\">\n\n <div\n (click)=\"onHeaderClick()\"\n (keyup.enter)=\"onHeaderClick()\"\n [class.ap-filter-leaf__closable]=\"closable() || item().featureLocked\"\n [class.ap-filter-leaf__expanded]=\"(!closable() || item().expanded) && (!item().featureLocked || !closable())\"\n class=\"ap-filter-leaf__header\" tabindex=\"0\">\n <div class=\"ap-filter-leaf__title\">\n <span>{{ item().title }}</span>\n @if (item().tooltipText) {\n <ap-symbol color=\"light-grey\" symbolId=\"info\" size=\"sm\" [apTooltip]=\"item().tooltipText\" />\n }\n </div>\n @if (item().featureLocked) {\n <div class=\"ap-filter-leaf__actions\">\n <ap-symbol color=\"purple\" symbolId=\"feature-lock\" size=\"sm\"\n [apTooltip]=\"item().featureLockTooltipText\" />\n </div>\n } @else if (closable()) {\n <div class=\"ap-filter-leaf__actions\" [class.ap-filter-leaf__chevron--rotated]=\"!item().expanded\">\n <ap-symbol symbolId=\"chevron-up\" size=\"sm\" />\n </div>\n }\n </div>\n\n @if ((!closable() || item().expanded) && (!item().featureLocked || !closable())) {\n <div class=\"ap-filter-leaf__content\">\n @if (item().label && displayLabelInLeaf()) {\n <span class=\"ap-filter-leaf__label\">{{ item().label }}</span>\n }\n @switch (item().filterType) {\n @case ('checkbox') {\n @if (checkboxItem(); as vCheckboxItem) {\n @for (option of vCheckboxItem.items; track option.name) {\n <div class=\"ap-filter-leaf__option\">\n <ap-checkbox\n [name]=\"'checkbox-' + option.name\"\n [checked]=\"checkboxValue()[option.name]\"\n [disabled]=\"!!option.disabled || item().featureLocked\"\n (change)=\"onCheckboxChange(option.name, $event)\"\n >\n <span>{{ option.label }}</span>\n </ap-checkbox>\n </div>\n }\n }\n }\n @case ('radio') {\n @if (radioItem(); as vRadioItem) {\n @for (option of vRadioItem.items; track option.radioId) {\n <div class=\"ap-filter-leaf__option\">\n <ap-radio\n [radioId]=\"option.radioId\"\n [value]=\"option.value\"\n [disabled]=\"!!option.disabled || !!item().featureLocked\"\n [name]=\"item().key\"\n [ngModel]=\"radioValue()\"\n (ngModelChange)=\"onRadioClick($event)\"\n >\n <span>{{ option.label }}</span>\n </ap-radio>\n </div>\n }\n }\n }\n @case ('toggle') {\n @if (toggleItem(); as vToggleItem) {\n <div class=\"ap-filter-leaf__option\">\n <ap-toggle\n [name]=\"'toggle-' + vToggleItem.item.name\"\n [checked]=\"toggleValue()\"\n [disabled]=\"vToggleItem.item.disabled || item().featureLocked\"\n (change)=\"onToggleChange($event)\"\n />\n <span class=\"toggle\"\n [class.disabled]=\"vToggleItem.item.disabled || item().featureLocked\">{{ vToggleItem.item.label }}</span>\n </div>\n }\n }\n @case ('select') {\n @if (selectItem(); as vSelectItem) {\n <ap-filter-leaf-select [item]=\"vSelectItem\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit($event)\" />\n }\n }\n @case ('date-range') {\n @if (dateRangeItem(); as vDateRangeItem) {\n <ap-input-datepicker\n [disabled]=\"!!item().featureLocked\"\n [label]=\"vDateRangeItem.label\"\n [mode]=\"DatepickerMode.Range\"\n [placeholder]=\"vDateRangeItem.placeholder ?? 'Select date range'\"\n [minDate]=\"vDateRangeItem.minDate\"\n [maxDate]=\"vDateRangeItem.maxDate\"\n [dateFormat]=\"vDateRangeItem.dateFormat ?? 'MMMM DD, YYYY'\"\n [selectedPeriod]=\"dateRangeValue()\"\n (periodChanged)=\"onDateRangeChange($event)\"\n />\n }\n }\n }\n </div>\n }\n\n</div>\n", styles: [".ap-filter-leaf{display:flex;flex-direction:column}.ap-filter-leaf.with-border-bottom{border-bottom:1px solid var(--ref-color-grey-10)}.ap-filter-leaf__header{display:flex;align-items:center;justify-content:space-between;padding:var(--ref-spacing-sm)}.ap-filter-leaf__header.ap-filter-leaf__expanded{padding-bottom:var(--ref-spacing-xs)}.ap-filter-leaf__closable{cursor:pointer}.ap-filter-leaf__title{display:flex;align-items:center;gap:var(--ref-spacing-xxxs);flex:1 0 0;color:var(--ref-color-grey-100);font-family:Averta;font-size:var(--ref-font-size-sm);font-style:normal;font-weight:var(--ref-font-weight-bold);line-height:var(--ref-font-line-height-sm)}.ap-filter-leaf__label{color:var(--ref-color-grey-100);font-family:Averta;font-size:var(--ref-font-size-sm);font-style:normal;font-weight:var(--ref-font-weight-regular);line-height:var(--ref-font-line-height-sm)}.ap-filter-leaf__chevron--rotated{transform:rotate(180deg)}.ap-filter-leaf__content{display:flex;flex-direction:column;gap:var(--ref-spacing-xs);padding:0 var(--ref-spacing-sm) var(--ref-spacing-sm)}.ap-filter-leaf__option{display:flex;gap:var(--ref-spacing-xxs);align-items:center;justify-content:flex-start}.ap-filter-leaf__option .toggle{font-family:var(--sys-text-style-body-font-family);font-size:var(--sys-text-style-body-size);font-weight:var(--sys-text-style-body-weight);line-height:var(--sys-text-style-body-line-height);color:var(--ref-color-grey-100)}.ap-filter-leaf__option span.disabled{color:var(--ref-color-grey-60)}\n"], dependencies: [{ kind: "directive", type: TooltipDirective, selector: "[apTooltip]", inputs: ["apTooltip", "apTooltipPosition", "apTooltipShowDelay", "apTooltipHideDelay", "apTooltipDuration", "apTooltipDisabled", "apTooltipTruncatedTextOnly", "apTooltipTemplateContext", "apTooltipVirtualScrollElement", "apTooltipTrigger", "apTooltipType", "apTooltipPresentationContext", "apTooltipListItems", "apTooltipShowAvatarCaption"], exportAs: ["apTooltip"] }, { kind: "component", type: SymbolComponent, selector: "ap-symbol", inputs: ["symbolId", "color", "size"], outputs: ["sizeChange"] }, { kind: "component", type: CheckboxComponent, selector: "ap-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "disabled", "indeterminate", "checked", "required", "name"], outputs: ["change"] }, { kind: "component", type: RadioComponent, selector: "ap-radio", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "disabled", "labelPosition", "radioId", "formControlName", "value", "required", "name"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ToggleComponent, selector: "ap-toggle", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "labelPosition", "disabled", "checked", "required", "confirm", "confirmMessage", "confirmOk", "confirmCancel", "confirmTitle", "name"], outputs: ["change"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: FilterLeafSelectComponent, selector: "ap-filter-leaf-select", inputs: ["item"], outputs: ["lockedFeatureClicked"] }, { kind: "component", type: InputDatepickerComponent, selector: "ap-input-datepicker", inputs: ["mode", "label", "placeholder", "firstDayOfWeek", "locale", "dateFormat", "disabled", "minDate", "maxDate", "selectedDate", "selectedDates", "selectedPeriod", "i18n", "showRanges", "showCustomRangeLabel", "rangesConfig", "showBackdrop", "defaultPosition"], outputs: ["periodChanged", "dateSelected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
355
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FilterLeafComponent, isStandalone: true, selector: "ap-filter-leaf", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, isLastLeaf: { classPropertyName: "isLastLeaf", publicName: "isLastLeaf", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", lockedFeatureClicked: "lockedFeatureClicked", filterDropdownGroupLockedClicked: "filterDropdownGroupLockedClicked" }, providers: [provideUiComponentsSymbols(apChevronDown, apInfo, apFeatureLock)], ngImport: i0, template: "<div [class.with-border-bottom]=\"!isLastLeaf()\" class=\"ap-filter-leaf\">\n\n <div\n (click)=\"onHeaderClick()\"\n (keyup.enter)=\"onHeaderClick()\"\n [class.ap-filter-leaf__closable]=\"closable() || item().featureLocked\"\n [class.ap-filter-leaf__expanded]=\"(!closable() || expanded()) && (!item().featureLocked || !closable())\"\n class=\"ap-filter-leaf__header\" tabindex=\"0\">\n <div class=\"ap-filter-leaf__title\">\n <span>{{ item().title }}</span>\n @if (item().tooltipText) {\n <ap-symbol color=\"light-grey\" symbolId=\"info\" size=\"sm\" [apTooltip]=\"item().tooltipText\" />\n }\n </div>\n @if (item().featureLocked) {\n <div class=\"ap-filter-leaf__actions\">\n <ap-symbol color=\"purple\" symbolId=\"feature-lock\" size=\"sm\"\n [apTooltip]=\"item().featureLockTooltipText\" />\n </div>\n } @else if (closable()) {\n <div class=\"ap-filter-leaf__actions\" [class.ap-filter-leaf__chevron--rotated]=\"!expanded()\">\n <ap-symbol symbolId=\"chevron-up\" size=\"sm\" />\n </div>\n }\n </div>\n\n @if ((!closable() || expanded()) && (!item().featureLocked || !closable())) {\n <div class=\"ap-filter-leaf__content\">\n @if (item().label && displayLabelInLeaf()) {\n <span class=\"ap-filter-leaf__label\">{{ item().label }}</span>\n }\n @switch (item().filterType) {\n @case ('checkbox') {\n @if (checkboxItem(); as vCheckboxItem) {\n @for (option of vCheckboxItem.items; track option.name) {\n <div class=\"ap-filter-leaf__option\">\n <ap-checkbox\n [name]=\"'checkbox-' + item().key + '-' + option.name\"\n [checked]=\"checkboxValue()[option.name]\"\n [disabled]=\"!!option.disabled || item().featureLocked\"\n (change)=\"onCheckboxChange(option.name, $event)\"\n >\n <span>{{ option.label }}</span>\n </ap-checkbox>\n </div>\n }\n }\n }\n @case ('radio') {\n @if (radioItem(); as vRadioItem) {\n @for (option of vRadioItem.items; track option.radioId) {\n <div class=\"ap-filter-leaf__option\">\n <ap-radio\n [radioId]=\"option.radioId\"\n [value]=\"option.value\"\n [disabled]=\"!!option.disabled || !!item().featureLocked\"\n [name]=\"item().key\"\n [ngModel]=\"radioValue()\"\n (ngModelChange)=\"onRadioClick($event)\"\n >\n <span>{{ option.label }}</span>\n </ap-radio>\n </div>\n }\n }\n }\n @case ('toggle') {\n @if (toggleItem(); as vToggleItem) {\n <div class=\"ap-filter-leaf__option\">\n <ap-toggle\n [name]=\"'toggle-' + vToggleItem.item.name\"\n [checked]=\"toggleValue()\"\n [disabled]=\"vToggleItem.item.disabled || item().featureLocked\"\n (change)=\"onToggleChange($event)\"\n />\n <span class=\"toggle\"\n [class.disabled]=\"vToggleItem.item.disabled || item().featureLocked\">{{ vToggleItem.item.label }}</span>\n </div>\n }\n }\n @case ('select') {\n @if (selectItem(); as vSelectItem) {\n <ap-filter-leaf-select [item]=\"vSelectItem\"\n (valueChange)=\"valueChange.emit($event)\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit($event)\" />\n }\n }\n @case ('date-range') {\n @if (dateRangeItem(); as vDateRangeItem) {\n <ap-input-datepicker\n [disabled]=\"!!item().featureLocked\"\n [label]=\"vDateRangeItem.label\"\n [mode]=\"DatepickerMode.Range\"\n [placeholder]=\"vDateRangeItem.placeholder ?? 'Select date range'\"\n [minDate]=\"vDateRangeItem.minDate\"\n [maxDate]=\"vDateRangeItem.maxDate\"\n [dateFormat]=\"vDateRangeItem.dateFormat ?? 'MMMM DD, YYYY'\"\n [selectedPeriod]=\"dateRangeValue()\"\n (periodChanged)=\"onDateRangeChange($event)\"\n />\n }\n }\n }\n </div>\n }\n\n</div>\n", styles: [".ap-filter-leaf{display:flex;flex-direction:column}.ap-filter-leaf.with-border-bottom{border-bottom:1px solid var(--ref-color-grey-10)}.ap-filter-leaf__header{display:flex;align-items:center;justify-content:space-between;padding:var(--ref-spacing-sm)}.ap-filter-leaf__header.ap-filter-leaf__expanded{padding-bottom:var(--ref-spacing-xs)}.ap-filter-leaf__closable{cursor:pointer}.ap-filter-leaf__title{display:flex;align-items:center;gap:var(--ref-spacing-xxxs);flex:1 0 0;color:var(--ref-color-grey-100);font-family:Averta;font-size:var(--ref-font-size-sm);font-style:normal;font-weight:var(--ref-font-weight-bold);line-height:var(--ref-font-line-height-sm)}.ap-filter-leaf__label{color:var(--ref-color-grey-100);font-family:Averta;font-size:var(--ref-font-size-sm);font-style:normal;font-weight:var(--ref-font-weight-regular);line-height:var(--ref-font-line-height-sm)}.ap-filter-leaf__chevron--rotated{transform:rotate(180deg)}.ap-filter-leaf__content{display:flex;flex-direction:column;gap:var(--ref-spacing-xs);padding:0 var(--ref-spacing-sm) var(--ref-spacing-sm)}.ap-filter-leaf__option{display:flex;gap:var(--ref-spacing-xxs);align-items:center;justify-content:flex-start}.ap-filter-leaf__option .toggle{font-family:var(--sys-text-style-body-font-family);font-size:var(--sys-text-style-body-size);font-weight:var(--sys-text-style-body-weight);line-height:var(--sys-text-style-body-line-height);color:var(--ref-color-grey-100)}.ap-filter-leaf__option span.disabled{color:var(--ref-color-grey-60)}\n"], dependencies: [{ kind: "directive", type: TooltipDirective, selector: "[apTooltip]", inputs: ["apTooltip", "apTooltipPosition", "apTooltipShowDelay", "apTooltipHideDelay", "apTooltipDuration", "apTooltipDisabled", "apTooltipTruncatedTextOnly", "apTooltipTemplateContext", "apTooltipVirtualScrollElement", "apTooltipTrigger", "apTooltipType", "apTooltipPresentationContext", "apTooltipListItems", "apTooltipShowAvatarCaption"], exportAs: ["apTooltip"] }, { kind: "component", type: SymbolComponent, selector: "ap-symbol", inputs: ["symbolId", "color", "size"], outputs: ["sizeChange"] }, { kind: "component", type: CheckboxComponent, selector: "ap-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "disabled", "indeterminate", "checked", "required", "name"], outputs: ["change"] }, { kind: "component", type: RadioComponent, selector: "ap-radio", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "disabled", "labelPosition", "radioId", "formControlName", "value", "required", "name"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ToggleComponent, selector: "ap-toggle", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "labelPosition", "disabled", "checked", "required", "confirm", "confirmMessage", "confirmOk", "confirmCancel", "confirmTitle", "name"], outputs: ["change"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: FilterLeafSelectComponent, selector: "ap-filter-leaf-select", inputs: ["item"], outputs: ["valueChange", "lockedFeatureClicked"] }, { kind: "component", type: InputDatepickerComponent, selector: "ap-input-datepicker", inputs: ["mode", "label", "placeholder", "firstDayOfWeek", "locale", "dateFormat", "disabled", "minDate", "maxDate", "selectedDate", "selectedDates", "selectedPeriod", "i18n", "showRanges", "showCustomRangeLabel", "rangesConfig", "showBackdrop", "defaultPosition"], outputs: ["periodChanged", "dateSelected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
333
356
|
}
|
|
334
357
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FilterLeafComponent, decorators: [{
|
|
335
358
|
type: Component,
|
|
@@ -344,39 +367,52 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImpo
|
|
|
344
367
|
InputDatepickerComponent,
|
|
345
368
|
SymbolComponent,
|
|
346
369
|
SymbolComponent,
|
|
347
|
-
], providers: [provideUiComponentsSymbols(apChevronDown, apInfo, apFeatureLock)], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class.with-border-bottom]=\"!isLastLeaf()\" class=\"ap-filter-leaf\">\n\n <div\n (click)=\"onHeaderClick()\"\n (keyup.enter)=\"onHeaderClick()\"\n [class.ap-filter-leaf__closable]=\"closable() || item().featureLocked\"\n [class.ap-filter-leaf__expanded]=\"(!closable() ||
|
|
348
|
-
}], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], isLastLeaf: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLastLeaf", required: false }] }], lockedFeatureClicked: [{ type: i0.Output, args: ["lockedFeatureClicked"] }], filterDropdownGroupLockedClicked: [{ type: i0.Output, args: ["filterDropdownGroupLockedClicked"] }] } });
|
|
370
|
+
], providers: [provideUiComponentsSymbols(apChevronDown, apInfo, apFeatureLock)], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class.with-border-bottom]=\"!isLastLeaf()\" class=\"ap-filter-leaf\">\n\n <div\n (click)=\"onHeaderClick()\"\n (keyup.enter)=\"onHeaderClick()\"\n [class.ap-filter-leaf__closable]=\"closable() || item().featureLocked\"\n [class.ap-filter-leaf__expanded]=\"(!closable() || expanded()) && (!item().featureLocked || !closable())\"\n class=\"ap-filter-leaf__header\" tabindex=\"0\">\n <div class=\"ap-filter-leaf__title\">\n <span>{{ item().title }}</span>\n @if (item().tooltipText) {\n <ap-symbol color=\"light-grey\" symbolId=\"info\" size=\"sm\" [apTooltip]=\"item().tooltipText\" />\n }\n </div>\n @if (item().featureLocked) {\n <div class=\"ap-filter-leaf__actions\">\n <ap-symbol color=\"purple\" symbolId=\"feature-lock\" size=\"sm\"\n [apTooltip]=\"item().featureLockTooltipText\" />\n </div>\n } @else if (closable()) {\n <div class=\"ap-filter-leaf__actions\" [class.ap-filter-leaf__chevron--rotated]=\"!expanded()\">\n <ap-symbol symbolId=\"chevron-up\" size=\"sm\" />\n </div>\n }\n </div>\n\n @if ((!closable() || expanded()) && (!item().featureLocked || !closable())) {\n <div class=\"ap-filter-leaf__content\">\n @if (item().label && displayLabelInLeaf()) {\n <span class=\"ap-filter-leaf__label\">{{ item().label }}</span>\n }\n @switch (item().filterType) {\n @case ('checkbox') {\n @if (checkboxItem(); as vCheckboxItem) {\n @for (option of vCheckboxItem.items; track option.name) {\n <div class=\"ap-filter-leaf__option\">\n <ap-checkbox\n [name]=\"'checkbox-' + item().key + '-' + option.name\"\n [checked]=\"checkboxValue()[option.name]\"\n [disabled]=\"!!option.disabled || item().featureLocked\"\n (change)=\"onCheckboxChange(option.name, $event)\"\n >\n <span>{{ option.label }}</span>\n </ap-checkbox>\n </div>\n }\n }\n }\n @case ('radio') {\n @if (radioItem(); as vRadioItem) {\n @for (option of vRadioItem.items; track option.radioId) {\n <div class=\"ap-filter-leaf__option\">\n <ap-radio\n [radioId]=\"option.radioId\"\n [value]=\"option.value\"\n [disabled]=\"!!option.disabled || !!item().featureLocked\"\n [name]=\"item().key\"\n [ngModel]=\"radioValue()\"\n (ngModelChange)=\"onRadioClick($event)\"\n >\n <span>{{ option.label }}</span>\n </ap-radio>\n </div>\n }\n }\n }\n @case ('toggle') {\n @if (toggleItem(); as vToggleItem) {\n <div class=\"ap-filter-leaf__option\">\n <ap-toggle\n [name]=\"'toggle-' + vToggleItem.item.name\"\n [checked]=\"toggleValue()\"\n [disabled]=\"vToggleItem.item.disabled || item().featureLocked\"\n (change)=\"onToggleChange($event)\"\n />\n <span class=\"toggle\"\n [class.disabled]=\"vToggleItem.item.disabled || item().featureLocked\">{{ vToggleItem.item.label }}</span>\n </div>\n }\n }\n @case ('select') {\n @if (selectItem(); as vSelectItem) {\n <ap-filter-leaf-select [item]=\"vSelectItem\"\n (valueChange)=\"valueChange.emit($event)\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit($event)\" />\n }\n }\n @case ('date-range') {\n @if (dateRangeItem(); as vDateRangeItem) {\n <ap-input-datepicker\n [disabled]=\"!!item().featureLocked\"\n [label]=\"vDateRangeItem.label\"\n [mode]=\"DatepickerMode.Range\"\n [placeholder]=\"vDateRangeItem.placeholder ?? 'Select date range'\"\n [minDate]=\"vDateRangeItem.minDate\"\n [maxDate]=\"vDateRangeItem.maxDate\"\n [dateFormat]=\"vDateRangeItem.dateFormat ?? 'MMMM DD, YYYY'\"\n [selectedPeriod]=\"dateRangeValue()\"\n (periodChanged)=\"onDateRangeChange($event)\"\n />\n }\n }\n }\n </div>\n }\n\n</div>\n", styles: [".ap-filter-leaf{display:flex;flex-direction:column}.ap-filter-leaf.with-border-bottom{border-bottom:1px solid var(--ref-color-grey-10)}.ap-filter-leaf__header{display:flex;align-items:center;justify-content:space-between;padding:var(--ref-spacing-sm)}.ap-filter-leaf__header.ap-filter-leaf__expanded{padding-bottom:var(--ref-spacing-xs)}.ap-filter-leaf__closable{cursor:pointer}.ap-filter-leaf__title{display:flex;align-items:center;gap:var(--ref-spacing-xxxs);flex:1 0 0;color:var(--ref-color-grey-100);font-family:Averta;font-size:var(--ref-font-size-sm);font-style:normal;font-weight:var(--ref-font-weight-bold);line-height:var(--ref-font-line-height-sm)}.ap-filter-leaf__label{color:var(--ref-color-grey-100);font-family:Averta;font-size:var(--ref-font-size-sm);font-style:normal;font-weight:var(--ref-font-weight-regular);line-height:var(--ref-font-line-height-sm)}.ap-filter-leaf__chevron--rotated{transform:rotate(180deg)}.ap-filter-leaf__content{display:flex;flex-direction:column;gap:var(--ref-spacing-xs);padding:0 var(--ref-spacing-sm) var(--ref-spacing-sm)}.ap-filter-leaf__option{display:flex;gap:var(--ref-spacing-xxs);align-items:center;justify-content:flex-start}.ap-filter-leaf__option .toggle{font-family:var(--sys-text-style-body-font-family);font-size:var(--sys-text-style-body-size);font-weight:var(--sys-text-style-body-weight);line-height:var(--sys-text-style-body-line-height);color:var(--ref-color-grey-100)}.ap-filter-leaf__option span.disabled{color:var(--ref-color-grey-60)}\n"] }]
|
|
371
|
+
}], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], isLastLeaf: [{ type: i0.Input, args: [{ isSignal: true, alias: "isLastLeaf", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], lockedFeatureClicked: [{ type: i0.Output, args: ["lockedFeatureClicked"] }], filterDropdownGroupLockedClicked: [{ type: i0.Output, args: ["filterDropdownGroupLockedClicked"] }] } });
|
|
349
372
|
|
|
350
373
|
class FilterDropdownComponent {
|
|
351
374
|
overlay = createDropdownOverlay();
|
|
352
375
|
filterState = inject(FilterState);
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
this.
|
|
363
|
-
const needApply = this.needApplyButton();
|
|
376
|
+
/**
|
|
377
|
+
* Seed the component state from its inputs. This is the ONLY reactive path and it is silent:
|
|
378
|
+
* it just copies inputs into `FilterState`. It never emits — emitting lives exclusively in the
|
|
379
|
+
* user-gesture handlers below — so feeding an applied `value` back here cannot start a loop.
|
|
380
|
+
* `savedValue` falls back to `value` when omitted (non-preset consumers).
|
|
381
|
+
*/
|
|
382
|
+
syncFromInputs = effect(() => {
|
|
383
|
+
const groups = this.groups();
|
|
384
|
+
const value = this.value();
|
|
385
|
+
const savedValue = this.savedValue();
|
|
364
386
|
untracked(() => {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
387
|
+
this.filterState.setSchema(groups);
|
|
388
|
+
this.filterState.seedDraft(value);
|
|
389
|
+
this.filterState.seedBaseline(savedValue ?? value);
|
|
368
390
|
});
|
|
369
|
-
}, ...(ngDevMode ? [{ debugName: "
|
|
391
|
+
}, ...(ngDevMode ? [{ debugName: "syncFromInputs" }] : /* istanbul ignore next */ []));
|
|
370
392
|
filterGroupTemplate = viewChild('filterGroupTemplate', ...(ngDevMode ? [{ debugName: "filterGroupTemplate" }] : /* istanbul ignore next */ []));
|
|
371
393
|
/**
|
|
372
|
-
* The filter groups to display
|
|
373
|
-
*
|
|
394
|
+
* The filter groups to display: STRUCTURE only (keys, titles, options, locks, display type, and the
|
|
395
|
+
* optional initial `expanded` seed). Not a value binding — selection lives in `value`, never here.
|
|
396
|
+
*/
|
|
397
|
+
groups = input([], ...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
|
|
398
|
+
/** The current / applied selection. Seeds the editable draft; re-seeding is silent (never emits). */
|
|
399
|
+
value = input({}, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
400
|
+
/**
|
|
401
|
+
* The consumer's saved value (e.g. the active preset's filter) that the dirty state and Reset compare
|
|
402
|
+
* against. Falls back to `value` when omitted. Kept distinct from `value` so an auto-applied edit stays
|
|
403
|
+
* dirty vs the preset.
|
|
374
404
|
*/
|
|
375
|
-
|
|
405
|
+
savedValue = input(undefined, ...(ngDevMode ? [{ debugName: "savedValue" }] : /* istanbul ignore next */ []));
|
|
376
406
|
/** Whether the filter needs the apply button to be clicked for applyFilters to emit */
|
|
377
407
|
needApplyButton = input(true, ...(ngDevMode ? [{ debugName: "needApplyButton" }] : /* istanbul ignore next */ []));
|
|
378
408
|
/** Whether the filter group can be closed (collapsed) by the user. If false, the group will always be expanded and the user won't see a toggle button. */
|
|
379
409
|
closable = input(true, ...(ngDevMode ? [{ debugName: "closable" }] : /* istanbul ignore next */ []));
|
|
410
|
+
/**
|
|
411
|
+
* Policy deciding which groups start expanded each time the dropdown opens. `'collapse-empty'` expands
|
|
412
|
+
* groups that currently have a selection; a predicate is evaluated per group against its draft value.
|
|
413
|
+
* Omitted → the expand/collapse state persists across opens.
|
|
414
|
+
*/
|
|
415
|
+
expandOnOpen = input(...(ngDevMode ? [undefined, { debugName: "expandOnOpen" }] : /* istanbul ignore next */ []));
|
|
380
416
|
/** whether the feature to save presets is locked for the org */
|
|
381
417
|
presetsFeatureLocked = input(false, ...(ngDevMode ? [{ debugName: "presetsFeatureLocked" }] : /* istanbul ignore next */ []));
|
|
382
418
|
/** whether the mode is in preset mode */
|
|
@@ -438,6 +474,7 @@ class FilterDropdownComponent {
|
|
|
438
474
|
const template = this.filterGroupTemplate();
|
|
439
475
|
if (this.isOpen() || !template)
|
|
440
476
|
return;
|
|
477
|
+
this.filterState.applyExpandOnOpen(this.expandOnOpen());
|
|
441
478
|
this.overlay.open(template, triggerElement, {
|
|
442
479
|
showBackdrop: this.showBackdrop(),
|
|
443
480
|
defaultPosition: this.defaultPosition(),
|
|
@@ -461,18 +498,36 @@ class FilterDropdownComponent {
|
|
|
461
498
|
this.open(triggerElement);
|
|
462
499
|
}
|
|
463
500
|
}
|
|
501
|
+
/**
|
|
502
|
+
* A leaf reported a user edit. Store it, then — in auto-apply mode — emit the new snapshot
|
|
503
|
+
* immediately. This is the whole auto-apply mechanism: an edit is a gesture, so it emits here;
|
|
504
|
+
* seeding an input never runs this handler, so an echoed value can never loop.
|
|
505
|
+
*/
|
|
506
|
+
onLeafEdit(edit) {
|
|
507
|
+
this.filterState.updateValue(edit.key, edit.value);
|
|
508
|
+
this.emitIfAuto();
|
|
509
|
+
}
|
|
510
|
+
/** Manual-apply commit (Apply button; only rendered when `needApplyButton`). */
|
|
464
511
|
onApplyFilters() {
|
|
465
512
|
this.applyFilters.emit(this.filterState.getSnapshot());
|
|
466
513
|
this.filterState.commit();
|
|
467
514
|
}
|
|
468
515
|
onClearFilters() {
|
|
469
516
|
this.filterState.clear();
|
|
517
|
+
this.emitIfAuto();
|
|
470
518
|
this.clearFilters.emit();
|
|
471
519
|
}
|
|
472
520
|
onResetFilters() {
|
|
473
521
|
this.filterState.reset();
|
|
522
|
+
this.emitIfAuto();
|
|
474
523
|
this.resetFilters.emit();
|
|
475
524
|
}
|
|
525
|
+
/** In auto-apply mode, push the current draft to the consumer. The single place clear/reset/leaf-edit funnel through. */
|
|
526
|
+
emitIfAuto() {
|
|
527
|
+
if (!this.needApplyButton()) {
|
|
528
|
+
this.applyFilters.emit(this.filterState.getSnapshot());
|
|
529
|
+
}
|
|
530
|
+
}
|
|
476
531
|
onSavePresets() {
|
|
477
532
|
if (this.presetsFeatureLocked()) {
|
|
478
533
|
this.presetsLockedClicked.emit();
|
|
@@ -496,12 +551,12 @@ class FilterDropdownComponent {
|
|
|
496
551
|
}
|
|
497
552
|
}
|
|
498
553
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FilterDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
499
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FilterDropdownComponent, isStandalone: true, selector: "ap-filter-dropdown", inputs: {
|
|
554
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FilterDropdownComponent, isStandalone: true, selector: "ap-filter-dropdown", inputs: { groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, savedValue: { classPropertyName: "savedValue", publicName: "savedValue", isSignal: true, isRequired: false, transformFunction: null }, needApplyButton: { classPropertyName: "needApplyButton", publicName: "needApplyButton", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, expandOnOpen: { classPropertyName: "expandOnOpen", publicName: "expandOnOpen", isSignal: true, isRequired: false, transformFunction: null }, presetsFeatureLocked: { classPropertyName: "presetsFeatureLocked", publicName: "presetsFeatureLocked", isSignal: true, isRequired: false, transformFunction: null }, savePresetsMode: { classPropertyName: "savePresetsMode", publicName: "savePresetsMode", isSignal: true, isRequired: false, transformFunction: null }, editingPresetsMode: { classPropertyName: "editingPresetsMode", publicName: "editingPresetsMode", isSignal: true, isRequired: false, transformFunction: null }, showBackdrop: { classPropertyName: "showBackdrop", publicName: "showBackdrop", isSignal: true, isRequired: false, transformFunction: null }, defaultPosition: { classPropertyName: "defaultPosition", publicName: "defaultPosition", isSignal: true, isRequired: false, transformFunction: null }, saveNewPresetsText: { classPropertyName: "saveNewPresetsText", publicName: "saveNewPresetsText", isSignal: true, isRequired: false, transformFunction: null }, saveAsNewPresetText: { classPropertyName: "saveAsNewPresetText", publicName: "saveAsNewPresetText", isSignal: true, isRequired: false, transformFunction: null }, savePresetText: { classPropertyName: "savePresetText", publicName: "savePresetText", isSignal: true, isRequired: false, transformFunction: null }, updateExistingPresetText: { classPropertyName: "updateExistingPresetText", publicName: "updateExistingPresetText", isSignal: true, isRequired: false, transformFunction: null }, resetFilterText: { classPropertyName: "resetFilterText", publicName: "resetFilterText", isSignal: true, isRequired: false, transformFunction: null }, applyFiltersText: { classPropertyName: "applyFiltersText", publicName: "applyFiltersText", isSignal: true, isRequired: false, transformFunction: null }, clearFilterText: { classPropertyName: "clearFilterText", publicName: "clearFilterText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed", presetsLockedClicked: "presetsLockedClicked", saveNewPresets: "saveNewPresets", updatePresets: "updatePresets", applyFilters: "applyFilters", clearFilters: "clearFilters", resetFilters: "resetFilters", lockedFeatureClicked: "lockedFeatureClicked", filterDropdownGroupLockedClicked: "filterDropdownGroupLockedClicked" }, providers: [FilterState, provideUiComponentsSymbols(apReset, apChevronDown$1, apPlus, apRefresh, apFeatureLock)], viewQueries: [{ propertyName: "filterGroupTemplate", first: true, predicate: ["filterGroupTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #filterGroupTemplate>\n <div\n class=\"ap-filter-dropdown\"\n role=\"menu\"\n tabindex=\"-1\"\n aria-label=\"Filter dropdown\">\n\n <div class=\"ap-filter-dropdown__content\">\n @for (item of filterState.groups(); let last = $last; track item.key) {\n <ap-filter-leaf\n [item]=\"item\"\n [closable]=\"closable()\"\n [isLastLeaf]=\"last\"\n (valueChange)=\"onLeafEdit($event)\"\n (filterDropdownGroupLockedClicked)=\"filterDropdownGroupLockedClicked.emit($event)\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit($event)\" />\n }\n </div>\n\n <div class=\"ap-filter-dropdown__footer\">\n @if (savePresetsMode()) {\n <div class=\"ap-filter-dropdown__footer--presets\">\n @if (!editingPresetsMode() || presetsFeatureLocked()) {\n <ap-button\n name=\"filter-dropdown-save-preset\"\n [config]=\"{ color: 'blue', style: 'stroked-transparent' }\"\n [disabled]=\"filterState.buttonsDisabled() && !presetsFeatureLocked()\"\n [locked]=\"presetsFeatureLocked()\"\n (click)=\"onSavePresets()\">\n {{ saveNewPresetsText() }}\n </ap-button>\n } @else {\n <ap-button\n name=\"filter-dropdown-edit-presets\"\n symbolId=\"chevron-down\"\n symbolPosition=\"right\"\n [apDropdownTrigger]=\"updatePresetsDropdown\"\n [config]=\"{ color: 'blue', style: 'stroked-transparent' }\"\n [disabled]=\"filterState.buttonsDisabled()\"\n >\n {{ savePresetText() }}\n </ap-button>\n }\n\n <ap-button\n name=\"filter-dropdown-reset-filters\"\n [symbolId]=\"'reset'\"\n [symbolPosition]=\"'left'\"\n [config]=\"{ color: 'blue', style: 'ghost' }\"\n [disabled]=\"filterState.buttonsDisabled()\"\n (click)=\"onResetFilters()\">\n {{ resetFilterText() }}\n </ap-button>\n </div>\n } @else {\n <div class=\"ap-filter-dropdown__footer--apply\">\n <ap-button\n name=\"filter-dropdown-clear-filters\"\n [config]=\"{ color: 'blue', style: 'ghost' }\"\n [disabled]=\"filterState.clearDisabled()\"\n (click)=\"onClearFilters()\">\n {{ clearFilterText() }}\n </ap-button>\n\n @if (needApplyButton()) {\n <ap-button\n name=\"filter-dropdown-apply-filters\"\n [config]=\"{ color: 'blue', style: 'primary' }\"\n [disabled]=\"filterState.buttonsDisabled()\"\n (click)=\"onApplyFilters()\">\n {{ applyFiltersText() }}\n </ap-button>\n }\n </div>\n }\n </div>\n </div>\n\n</ng-template>\n\n<ap-action-dropdown\n #updatePresetsDropdown\n [items]=\"savePresetsDropdownItems()\"\n (itemClick)=\"onActionDropdownItemClick($event)\"\n/>\n", styles: [":host{display:none}.ap-filter-dropdown{display:flex;flex-direction:column;width:420px;background-color:var(--comp-action-dropdown-background-color);border-radius:var(--comp-action-dropdown-border-radius);box-shadow:var(--comp-action-dropdown-box-shadow);outline:none;max-height:min(90vh,750px)}.ap-filter-dropdown__footer{padding:var(--ref-spacing-xxs) var(--ref-spacing-sm)}.ap-filter-dropdown__content{overflow-x:hidden;overflow-y:auto}.ap-filter-dropdown__footer{border-top:1px solid var(--comp-action-dropdown-divider-color)}.ap-filter-dropdown__footer--presets{display:flex;justify-content:space-between}.ap-filter-dropdown__footer--apply{display:flex;justify-content:flex-end;gap:var(--ref-spacing-sm)}\n"], dependencies: [{ kind: "component", type: ButtonComponent, selector: "ap-button", inputs: ["ariaLabel", "disabled", "name", "form", "config", "loading", "locked", "menuTrigger", "symbolPosition", "symbolId"], outputs: ["menuOpened", "menuClosed", "click", "focus", "blur"] }, { kind: "component", type: FilterLeafComponent, selector: "ap-filter-leaf", inputs: ["item", "closable", "isLastLeaf"], outputs: ["valueChange", "lockedFeatureClicked", "filterDropdownGroupLockedClicked"] }, { kind: "directive", type: DropdownTriggerDirective, selector: "[apDropdownTrigger]", inputs: ["apDropdownTrigger"] }, { kind: "component", type: ActionDropdownComponent, selector: "ap-action-dropdown", inputs: ["items", "largeModeEnabled", "customWidth", "showBackdrop", "disabled", "defaultPosition"], outputs: ["opened", "closed", "itemClick"] }] });
|
|
500
555
|
}
|
|
501
556
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FilterDropdownComponent, decorators: [{
|
|
502
557
|
type: Component,
|
|
503
|
-
args: [{ selector: 'ap-filter-dropdown', imports: [ButtonComponent, FilterLeafComponent, DropdownTriggerDirective, ActionDropdownComponent], providers: [FilterState, provideUiComponentsSymbols(apReset, apChevronDown$1, apPlus, apRefresh, apFeatureLock)], template: "<ng-template #filterGroupTemplate>\n <div\n class=\"ap-filter-dropdown\"\n role=\"menu\"\n tabindex=\"-1\"\n aria-label=\"Filter dropdown\">\n\n <div class=\"ap-filter-dropdown__content\">\n @for (item of filterState.groups(); let last = $last; track item.key) {\n <ap-filter-leaf\n [item]=\"item\"\n [closable]=\"closable()\"\n [isLastLeaf]=\"last\"\n (filterDropdownGroupLockedClicked)=\"filterDropdownGroupLockedClicked.emit($event)\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit($event)\" />\n }\n </div>\n\n <div class=\"ap-filter-dropdown__footer\">\n @if (savePresetsMode()) {\n <div class=\"ap-filter-dropdown__footer--presets\">\n @if (!editingPresetsMode() || presetsFeatureLocked()) {\n <ap-button\n name=\"filter-dropdown-save-preset\"\n [config]=\"{ color: 'blue', style: 'stroked-transparent' }\"\n [disabled]=\"filterState.buttonsDisabled() && !presetsFeatureLocked()\"\n [locked]=\"presetsFeatureLocked()\"\n (click)=\"onSavePresets()\">\n {{ saveNewPresetsText() }}\n </ap-button>\n } @else {\n <ap-button\n name=\"filter-dropdown-edit-presets\"\n symbolId=\"chevron-down\"\n symbolPosition=\"right\"\n [apDropdownTrigger]=\"updatePresetsDropdown\"\n [config]=\"{ color: 'blue', style: 'stroked-transparent' }\"\n [disabled]=\"filterState.buttonsDisabled()\"\n >\n {{ savePresetText() }}\n </ap-button>\n }\n\n <ap-button\n name=\"filter-dropdown-reset-filters\"\n [symbolId]=\"'reset'\"\n [symbolPosition]=\"'left'\"\n [config]=\"{ color: 'blue', style: 'ghost' }\"\n [disabled]=\"filterState.buttonsDisabled()\"\n (click)=\"onResetFilters()\">\n {{ resetFilterText() }}\n </ap-button>\n </div>\n } @else {\n <div class=\"ap-filter-dropdown__footer--apply\">\n <ap-button\n name=\"filter-dropdown-clear-filters\"\n [config]=\"{ color: 'blue', style: 'ghost' }\"\n [disabled]=\"filterState.
|
|
504
|
-
}], propDecorators: { filterGroupTemplate: [{ type: i0.ViewChild, args: ['filterGroupTemplate', { isSignal: true }] }],
|
|
558
|
+
args: [{ selector: 'ap-filter-dropdown', imports: [ButtonComponent, FilterLeafComponent, DropdownTriggerDirective, ActionDropdownComponent], providers: [FilterState, provideUiComponentsSymbols(apReset, apChevronDown$1, apPlus, apRefresh, apFeatureLock)], template: "<ng-template #filterGroupTemplate>\n <div\n class=\"ap-filter-dropdown\"\n role=\"menu\"\n tabindex=\"-1\"\n aria-label=\"Filter dropdown\">\n\n <div class=\"ap-filter-dropdown__content\">\n @for (item of filterState.groups(); let last = $last; track item.key) {\n <ap-filter-leaf\n [item]=\"item\"\n [closable]=\"closable()\"\n [isLastLeaf]=\"last\"\n (valueChange)=\"onLeafEdit($event)\"\n (filterDropdownGroupLockedClicked)=\"filterDropdownGroupLockedClicked.emit($event)\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit($event)\" />\n }\n </div>\n\n <div class=\"ap-filter-dropdown__footer\">\n @if (savePresetsMode()) {\n <div class=\"ap-filter-dropdown__footer--presets\">\n @if (!editingPresetsMode() || presetsFeatureLocked()) {\n <ap-button\n name=\"filter-dropdown-save-preset\"\n [config]=\"{ color: 'blue', style: 'stroked-transparent' }\"\n [disabled]=\"filterState.buttonsDisabled() && !presetsFeatureLocked()\"\n [locked]=\"presetsFeatureLocked()\"\n (click)=\"onSavePresets()\">\n {{ saveNewPresetsText() }}\n </ap-button>\n } @else {\n <ap-button\n name=\"filter-dropdown-edit-presets\"\n symbolId=\"chevron-down\"\n symbolPosition=\"right\"\n [apDropdownTrigger]=\"updatePresetsDropdown\"\n [config]=\"{ color: 'blue', style: 'stroked-transparent' }\"\n [disabled]=\"filterState.buttonsDisabled()\"\n >\n {{ savePresetText() }}\n </ap-button>\n }\n\n <ap-button\n name=\"filter-dropdown-reset-filters\"\n [symbolId]=\"'reset'\"\n [symbolPosition]=\"'left'\"\n [config]=\"{ color: 'blue', style: 'ghost' }\"\n [disabled]=\"filterState.buttonsDisabled()\"\n (click)=\"onResetFilters()\">\n {{ resetFilterText() }}\n </ap-button>\n </div>\n } @else {\n <div class=\"ap-filter-dropdown__footer--apply\">\n <ap-button\n name=\"filter-dropdown-clear-filters\"\n [config]=\"{ color: 'blue', style: 'ghost' }\"\n [disabled]=\"filterState.clearDisabled()\"\n (click)=\"onClearFilters()\">\n {{ clearFilterText() }}\n </ap-button>\n\n @if (needApplyButton()) {\n <ap-button\n name=\"filter-dropdown-apply-filters\"\n [config]=\"{ color: 'blue', style: 'primary' }\"\n [disabled]=\"filterState.buttonsDisabled()\"\n (click)=\"onApplyFilters()\">\n {{ applyFiltersText() }}\n </ap-button>\n }\n </div>\n }\n </div>\n </div>\n\n</ng-template>\n\n<ap-action-dropdown\n #updatePresetsDropdown\n [items]=\"savePresetsDropdownItems()\"\n (itemClick)=\"onActionDropdownItemClick($event)\"\n/>\n", styles: [":host{display:none}.ap-filter-dropdown{display:flex;flex-direction:column;width:420px;background-color:var(--comp-action-dropdown-background-color);border-radius:var(--comp-action-dropdown-border-radius);box-shadow:var(--comp-action-dropdown-box-shadow);outline:none;max-height:min(90vh,750px)}.ap-filter-dropdown__footer{padding:var(--ref-spacing-xxs) var(--ref-spacing-sm)}.ap-filter-dropdown__content{overflow-x:hidden;overflow-y:auto}.ap-filter-dropdown__footer{border-top:1px solid var(--comp-action-dropdown-divider-color)}.ap-filter-dropdown__footer--presets{display:flex;justify-content:space-between}.ap-filter-dropdown__footer--apply{display:flex;justify-content:flex-end;gap:var(--ref-spacing-sm)}\n"] }]
|
|
559
|
+
}], propDecorators: { filterGroupTemplate: [{ type: i0.ViewChild, args: ['filterGroupTemplate', { isSignal: true }] }], groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], savedValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "savedValue", required: false }] }], needApplyButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "needApplyButton", required: false }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], expandOnOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandOnOpen", required: false }] }], presetsFeatureLocked: [{ type: i0.Input, args: [{ isSignal: true, alias: "presetsFeatureLocked", required: false }] }], savePresetsMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "savePresetsMode", required: false }] }], editingPresetsMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "editingPresetsMode", required: false }] }], showBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBackdrop", required: false }] }], defaultPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultPosition", required: false }] }], saveNewPresetsText: [{ type: i0.Input, args: [{ isSignal: true, alias: "saveNewPresetsText", required: false }] }], saveAsNewPresetText: [{ type: i0.Input, args: [{ isSignal: true, alias: "saveAsNewPresetText", required: false }] }], savePresetText: [{ type: i0.Input, args: [{ isSignal: true, alias: "savePresetText", required: false }] }], updateExistingPresetText: [{ type: i0.Input, args: [{ isSignal: true, alias: "updateExistingPresetText", required: false }] }], resetFilterText: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetFilterText", required: false }] }], applyFiltersText: [{ type: i0.Input, args: [{ isSignal: true, alias: "applyFiltersText", required: false }] }], clearFilterText: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearFilterText", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], presetsLockedClicked: [{ type: i0.Output, args: ["presetsLockedClicked"] }], saveNewPresets: [{ type: i0.Output, args: ["saveNewPresets"] }], updatePresets: [{ type: i0.Output, args: ["updatePresets"] }], applyFilters: [{ type: i0.Output, args: ["applyFilters"] }], clearFilters: [{ type: i0.Output, args: ["clearFilters"] }], resetFilters: [{ type: i0.Output, args: ["resetFilters"] }], lockedFeatureClicked: [{ type: i0.Output, args: ["lockedFeatureClicked"] }], filterDropdownGroupLockedClicked: [{ type: i0.Output, args: ["filterDropdownGroupLockedClicked"] }] } });
|
|
505
560
|
|
|
506
561
|
class FilterDropdownButtonComponent {
|
|
507
562
|
// FilterState is provided by the inner FilterDropdownComponent, so read the counter through it.
|
|
@@ -511,15 +566,18 @@ class FilterDropdownButtonComponent {
|
|
|
511
566
|
/** text of the button, input specific to the button */
|
|
512
567
|
buttonFilterText = input('Filters', ...(ngDevMode ? [{ debugName: "buttonFilterText" }] : /* istanbul ignore next */ []));
|
|
513
568
|
/** input specific to the filter-dropdown */
|
|
514
|
-
/**
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
569
|
+
/** The filter groups to display: STRUCTURE only (keys, titles, options, locks, display type, expand seed). */
|
|
570
|
+
groups = input([], ...(ngDevMode ? [{ debugName: "groups" }] : /* istanbul ignore next */ []));
|
|
571
|
+
/** The current / applied selection. Seeds the editable draft; re-seeding is silent (never emits). */
|
|
572
|
+
value = input({}, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
573
|
+
/** The consumer's saved value (e.g. the active preset's filter) that dirty state / Reset compare against. Falls back to `value`. */
|
|
574
|
+
savedValue = input(undefined, ...(ngDevMode ? [{ debugName: "savedValue" }] : /* istanbul ignore next */ []));
|
|
519
575
|
/** Whether the filter needs the apply button to be clicked for applyFilters to emit */
|
|
520
576
|
needApplyButton = input(true, ...(ngDevMode ? [{ debugName: "needApplyButton" }] : /* istanbul ignore next */ []));
|
|
521
577
|
/** Whether the filter group can be closed (collapsed) by the user. If false, the group will always be expanded and the user won't see a toggle button. */
|
|
522
578
|
closable = input(true, ...(ngDevMode ? [{ debugName: "closable" }] : /* istanbul ignore next */ []));
|
|
579
|
+
/** Policy deciding which groups start expanded on each open ('collapse-empty' | predicate). Omitted → persist. */
|
|
580
|
+
expandOnOpen = input(...(ngDevMode ? [undefined, { debugName: "expandOnOpen" }] : /* istanbul ignore next */ []));
|
|
523
581
|
/** whether the feature to save presets is locked for the org */
|
|
524
582
|
presetsFeatureLocked = input(false, ...(ngDevMode ? [{ debugName: "presetsFeatureLocked" }] : /* istanbul ignore next */ []));
|
|
525
583
|
/** whether the mode is in preset mode */
|
|
@@ -560,12 +618,12 @@ class FilterDropdownButtonComponent {
|
|
|
560
618
|
/** Event emitted when a group with locked feature is clicked */
|
|
561
619
|
filterDropdownGroupLockedClicked = output();
|
|
562
620
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FilterDropdownButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
563
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FilterDropdownButtonComponent, isStandalone: true, selector: "ap-filter-dropdown-button", inputs: { buttonFilterText: { classPropertyName: "buttonFilterText", publicName: "buttonFilterText", isSignal: true, isRequired: false, transformFunction: null },
|
|
621
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.16", type: FilterDropdownButtonComponent, isStandalone: true, selector: "ap-filter-dropdown-button", inputs: { buttonFilterText: { classPropertyName: "buttonFilterText", publicName: "buttonFilterText", isSignal: true, isRequired: false, transformFunction: null }, groups: { classPropertyName: "groups", publicName: "groups", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, savedValue: { classPropertyName: "savedValue", publicName: "savedValue", isSignal: true, isRequired: false, transformFunction: null }, needApplyButton: { classPropertyName: "needApplyButton", publicName: "needApplyButton", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, expandOnOpen: { classPropertyName: "expandOnOpen", publicName: "expandOnOpen", isSignal: true, isRequired: false, transformFunction: null }, presetsFeatureLocked: { classPropertyName: "presetsFeatureLocked", publicName: "presetsFeatureLocked", isSignal: true, isRequired: false, transformFunction: null }, savePresetsMode: { classPropertyName: "savePresetsMode", publicName: "savePresetsMode", isSignal: true, isRequired: false, transformFunction: null }, editingPresetsMode: { classPropertyName: "editingPresetsMode", publicName: "editingPresetsMode", isSignal: true, isRequired: false, transformFunction: null }, showBackdrop: { classPropertyName: "showBackdrop", publicName: "showBackdrop", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, defaultPosition: { classPropertyName: "defaultPosition", publicName: "defaultPosition", isSignal: true, isRequired: false, transformFunction: null }, saveNewPresetsText: { classPropertyName: "saveNewPresetsText", publicName: "saveNewPresetsText", isSignal: true, isRequired: false, transformFunction: null }, saveAsNewPresetText: { classPropertyName: "saveAsNewPresetText", publicName: "saveAsNewPresetText", isSignal: true, isRequired: false, transformFunction: null }, savePresetText: { classPropertyName: "savePresetText", publicName: "savePresetText", isSignal: true, isRequired: false, transformFunction: null }, updateExistingPresetText: { classPropertyName: "updateExistingPresetText", publicName: "updateExistingPresetText", isSignal: true, isRequired: false, transformFunction: null }, resetFilterText: { classPropertyName: "resetFilterText", publicName: "resetFilterText", isSignal: true, isRequired: false, transformFunction: null }, applyFiltersText: { classPropertyName: "applyFiltersText", publicName: "applyFiltersText", isSignal: true, isRequired: false, transformFunction: null }, clearFilterText: { classPropertyName: "clearFilterText", publicName: "clearFilterText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { opened: "opened", closed: "closed", presetsLockedClicked: "presetsLockedClicked", saveNewPresets: "saveNewPresets", updatePresets: "updatePresets", applyFilters: "applyFilters", clearFilters: "clearFilters", resetFilters: "resetFilters", lockedFeatureClicked: "lockedFeatureClicked", filterDropdownGroupLockedClicked: "filterDropdownGroupLockedClicked" }, providers: [withSymbols(apFilter, apFilterFill)], viewQueries: [{ propertyName: "filterDropdown", first: true, predicate: FilterDropdownComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<ap-button\n [apDropdownTrigger]=\"filterDropdown\"\n [config]=\"{ style: 'stroked', color: isFilterCountActive() ? 'blue' : 'grey' }\"\n ariaLabel=\"Button toggling filters\"\n name=\"toggle-filter\"\n symbolPosition=\"left\">\n <ap-symbol [symbolId]=\"isFilterCountActive() ? 'filter_fill' : 'filter'\" />\n @if (isFilterCountActive()) {\n <ap-counter\n size=\"big\"\n color=\"blue\"\n [background]=\"true\">\n {{ activeFilterCount() }}\n </ap-counter>\n }\n {{ buttonFilterText() }}\n</ap-button>\n\n<ap-filter-dropdown\n #filterDropdown\n [presetsFeatureLocked]=\"presetsFeatureLocked()\"\n [applyFiltersText]=\"applyFiltersText()\"\n [clearFilterText]=\"clearFilterText()\"\n [closable]=\"closable()\"\n [defaultPosition]=\"defaultPosition()\"\n [editingPresetsMode]=\"editingPresetsMode()\"\n [groups]=\"groups()\"\n [value]=\"value()\"\n [savedValue]=\"savedValue()\"\n [expandOnOpen]=\"expandOnOpen()\"\n [needApplyButton]=\"needApplyButton()\"\n [resetFilterText]=\"resetFilterText()\"\n [saveAsNewPresetText]=\"saveAsNewPresetText()\"\n [saveNewPresetsText]=\"saveNewPresetsText()\"\n [savePresetText]=\"savePresetText()\"\n [savePresetsMode]=\"savePresetsMode()\"\n [showBackdrop]=\"showBackdrop()\"\n (applyFilters)=\"applyFilters.emit($event)\"\n (clearFilters)=\"clearFilters.emit()\"\n (closed)=\"closed.emit()\"\n (filterDropdownGroupLockedClicked)=\"filterDropdownGroupLockedClicked.emit($event)\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit($event)\"\n (opened)=\"opened.emit()\"\n (presetsLockedClicked)=\"presetsLockedClicked.emit()\"\n (resetFilters)=\"resetFilters.emit()\"\n (saveNewPresets)=\"saveNewPresets.emit($event)\"\n (updatePresets)=\"updatePresets.emit($event)\"\n [updateExistingPresetText]=\"updateExistingPresetText()\" />\n", dependencies: [{ kind: "component", type: ButtonComponent, selector: "ap-button", inputs: ["ariaLabel", "disabled", "name", "form", "config", "loading", "locked", "menuTrigger", "symbolPosition", "symbolId"], outputs: ["menuOpened", "menuClosed", "click", "focus", "blur"] }, { kind: "directive", type: DropdownTriggerDirective, selector: "[apDropdownTrigger]", inputs: ["apDropdownTrigger"] }, { kind: "component", type: SymbolComponent, selector: "ap-symbol", inputs: ["symbolId", "color", "size"], outputs: ["sizeChange"] }, { kind: "component", type: FilterDropdownComponent, selector: "ap-filter-dropdown", inputs: ["groups", "value", "savedValue", "needApplyButton", "closable", "expandOnOpen", "presetsFeatureLocked", "savePresetsMode", "editingPresetsMode", "showBackdrop", "defaultPosition", "saveNewPresetsText", "saveAsNewPresetText", "savePresetText", "updateExistingPresetText", "resetFilterText", "applyFiltersText", "clearFilterText"], outputs: ["opened", "closed", "presetsLockedClicked", "saveNewPresets", "updatePresets", "applyFilters", "clearFilters", "resetFilters", "lockedFeatureClicked", "filterDropdownGroupLockedClicked"] }, { kind: "component", type: CounterComponent, selector: "ap-counter", inputs: ["color", "size", "notif", "background", "role"] }] });
|
|
564
622
|
}
|
|
565
623
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.16", ngImport: i0, type: FilterDropdownButtonComponent, decorators: [{
|
|
566
624
|
type: Component,
|
|
567
|
-
args: [{ selector: 'ap-filter-dropdown-button', imports: [ButtonComponent, DropdownTriggerDirective, SymbolComponent, FilterDropdownComponent, CounterComponent], providers: [withSymbols(apFilter, apFilterFill)], template: "<ap-button\n [apDropdownTrigger]=\"filterDropdown\"\n [config]=\"{ style: 'stroked', color: isFilterCountActive() ? 'blue' : 'grey' }\"\n ariaLabel=\"Button toggling filters\"\n name=\"toggle-filter\"\n symbolPosition=\"left\">\n <ap-symbol [symbolId]=\"isFilterCountActive() ? 'filter_fill' : 'filter'\" />\n @if (isFilterCountActive()) {\n <ap-counter\n size=\"big\"\n color=\"blue\"\n [background]=\"true\">\n {{ activeFilterCount() }}\n </ap-counter>\n }\n {{ buttonFilterText() }}\n</ap-button>\n\n<ap-filter-dropdown\n #filterDropdown\n [presetsFeatureLocked]=\"presetsFeatureLocked()\"\n [applyFiltersText]=\"applyFiltersText()\"\n [clearFilterText]=\"clearFilterText()\"\n [closable]=\"closable()\"\n [defaultPosition]=\"defaultPosition()\"\n [editingPresetsMode]=\"editingPresetsMode()\"\n [
|
|
568
|
-
}], propDecorators: { filterDropdown: [{ type: i0.ViewChild, args: [i0.forwardRef(() => FilterDropdownComponent), { isSignal: true }] }], buttonFilterText: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonFilterText", required: false }] }],
|
|
625
|
+
args: [{ selector: 'ap-filter-dropdown-button', imports: [ButtonComponent, DropdownTriggerDirective, SymbolComponent, FilterDropdownComponent, CounterComponent], providers: [withSymbols(apFilter, apFilterFill)], template: "<ap-button\n [apDropdownTrigger]=\"filterDropdown\"\n [config]=\"{ style: 'stroked', color: isFilterCountActive() ? 'blue' : 'grey' }\"\n ariaLabel=\"Button toggling filters\"\n name=\"toggle-filter\"\n symbolPosition=\"left\">\n <ap-symbol [symbolId]=\"isFilterCountActive() ? 'filter_fill' : 'filter'\" />\n @if (isFilterCountActive()) {\n <ap-counter\n size=\"big\"\n color=\"blue\"\n [background]=\"true\">\n {{ activeFilterCount() }}\n </ap-counter>\n }\n {{ buttonFilterText() }}\n</ap-button>\n\n<ap-filter-dropdown\n #filterDropdown\n [presetsFeatureLocked]=\"presetsFeatureLocked()\"\n [applyFiltersText]=\"applyFiltersText()\"\n [clearFilterText]=\"clearFilterText()\"\n [closable]=\"closable()\"\n [defaultPosition]=\"defaultPosition()\"\n [editingPresetsMode]=\"editingPresetsMode()\"\n [groups]=\"groups()\"\n [value]=\"value()\"\n [savedValue]=\"savedValue()\"\n [expandOnOpen]=\"expandOnOpen()\"\n [needApplyButton]=\"needApplyButton()\"\n [resetFilterText]=\"resetFilterText()\"\n [saveAsNewPresetText]=\"saveAsNewPresetText()\"\n [saveNewPresetsText]=\"saveNewPresetsText()\"\n [savePresetText]=\"savePresetText()\"\n [savePresetsMode]=\"savePresetsMode()\"\n [showBackdrop]=\"showBackdrop()\"\n (applyFilters)=\"applyFilters.emit($event)\"\n (clearFilters)=\"clearFilters.emit()\"\n (closed)=\"closed.emit()\"\n (filterDropdownGroupLockedClicked)=\"filterDropdownGroupLockedClicked.emit($event)\"\n (lockedFeatureClicked)=\"lockedFeatureClicked.emit($event)\"\n (opened)=\"opened.emit()\"\n (presetsLockedClicked)=\"presetsLockedClicked.emit()\"\n (resetFilters)=\"resetFilters.emit()\"\n (saveNewPresets)=\"saveNewPresets.emit($event)\"\n (updatePresets)=\"updatePresets.emit($event)\"\n [updateExistingPresetText]=\"updateExistingPresetText()\" />\n" }]
|
|
626
|
+
}], propDecorators: { filterDropdown: [{ type: i0.ViewChild, args: [i0.forwardRef(() => FilterDropdownComponent), { isSignal: true }] }], buttonFilterText: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttonFilterText", required: false }] }], groups: [{ type: i0.Input, args: [{ isSignal: true, alias: "groups", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], savedValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "savedValue", required: false }] }], needApplyButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "needApplyButton", required: false }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], expandOnOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandOnOpen", required: false }] }], presetsFeatureLocked: [{ type: i0.Input, args: [{ isSignal: true, alias: "presetsFeatureLocked", required: false }] }], savePresetsMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "savePresetsMode", required: false }] }], editingPresetsMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "editingPresetsMode", required: false }] }], showBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBackdrop", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], defaultPosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultPosition", required: false }] }], saveNewPresetsText: [{ type: i0.Input, args: [{ isSignal: true, alias: "saveNewPresetsText", required: false }] }], saveAsNewPresetText: [{ type: i0.Input, args: [{ isSignal: true, alias: "saveAsNewPresetText", required: false }] }], savePresetText: [{ type: i0.Input, args: [{ isSignal: true, alias: "savePresetText", required: false }] }], updateExistingPresetText: [{ type: i0.Input, args: [{ isSignal: true, alias: "updateExistingPresetText", required: false }] }], resetFilterText: [{ type: i0.Input, args: [{ isSignal: true, alias: "resetFilterText", required: false }] }], applyFiltersText: [{ type: i0.Input, args: [{ isSignal: true, alias: "applyFiltersText", required: false }] }], clearFilterText: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearFilterText", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], presetsLockedClicked: [{ type: i0.Output, args: ["presetsLockedClicked"] }], saveNewPresets: [{ type: i0.Output, args: ["saveNewPresets"] }], updatePresets: [{ type: i0.Output, args: ["updatePresets"] }], applyFilters: [{ type: i0.Output, args: ["applyFilters"] }], clearFilters: [{ type: i0.Output, args: ["clearFilters"] }], resetFilters: [{ type: i0.Output, args: ["resetFilters"] }], lockedFeatureClicked: [{ type: i0.Output, args: ["lockedFeatureClicked"] }], filterDropdownGroupLockedClicked: [{ type: i0.Output, args: ["filterDropdownGroupLockedClicked"] }] } });
|
|
569
627
|
|
|
570
628
|
/**
|
|
571
629
|
* Generated bundle index. Do not edit.
|