@memberjunction/ng-ui-components 5.38.0 → 5.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/applied-filters/applied-filters.component.d.ts +55 -0
- package/dist/lib/applied-filters/applied-filters.component.d.ts.map +1 -0
- package/dist/lib/applied-filters/applied-filters.component.js +128 -0
- package/dist/lib/applied-filters/applied-filters.component.js.map +1 -0
- package/dist/lib/filter-panel/filter-panel.component.d.ts +14 -0
- package/dist/lib/filter-panel/filter-panel.component.d.ts.map +1 -1
- package/dist/lib/filter-panel/filter-panel.component.js +30 -5
- package/dist/lib/filter-panel/filter-panel.component.js.map +1 -1
- package/dist/lib/filter-popover/filter-popover.component.d.ts +14 -2
- package/dist/lib/filter-popover/filter-popover.component.d.ts.map +1 -1
- package/dist/lib/filter-popover/filter-popover.component.js +153 -52
- package/dist/lib/filter-popover/filter-popover.component.js.map +1 -1
- package/dist/lib/left-nav/left-nav-content.component.d.ts.map +1 -1
- package/dist/lib/left-nav/left-nav-content.component.js +3 -3
- package/dist/lib/left-nav/left-nav-content.component.js.map +1 -1
- package/dist/lib/left-nav/left-nav.component.d.ts +36 -9
- package/dist/lib/left-nav/left-nav.component.d.ts.map +1 -1
- package/dist/lib/left-nav/left-nav.component.js +253 -117
- package/dist/lib/left-nav/left-nav.component.js.map +1 -1
- package/dist/lib/page-body/page-body.component.d.ts.map +1 -1
- package/dist/lib/page-body/page-body.component.js +3 -3
- package/dist/lib/page-body/page-body.component.js.map +1 -1
- package/dist/lib/page-header/page-header.component.js +2 -2
- package/dist/lib/page-header/page-header.scss +51 -4
- package/dist/lib/page-header-interior/page-header-interior.component.d.ts.map +1 -1
- package/dist/lib/page-header-interior/page-header-interior.component.js +3 -3
- package/dist/lib/page-header-interior/page-header-interior.component.js.map +1 -1
- package/dist/lib/refresh-button/refresh-button.component.d.ts.map +1 -1
- package/dist/lib/refresh-button/refresh-button.component.js +13 -10
- package/dist/lib/refresh-button/refresh-button.component.js.map +1 -1
- package/dist/lib/slide-panel/slide-panel.component.d.ts +64 -0
- package/dist/lib/slide-panel/slide-panel.component.d.ts.map +1 -0
- package/dist/lib/slide-panel/slide-panel.component.js +256 -0
- package/dist/lib/slide-panel/slide-panel.component.js.map +1 -0
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { EventEmitter } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* One applied filter, as surfaced in the `mj-applied-filters` chip row.
|
|
5
|
+
* `label` is the dimension (e.g. "Status"), `value` is the human-readable
|
|
6
|
+
* selection (e.g. "Active"), `key` uniquely identifies it for removal.
|
|
7
|
+
*/
|
|
8
|
+
export interface AppliedFilter {
|
|
9
|
+
/** Stable identifier emitted on removal — typically `<field>:<value>`. */
|
|
10
|
+
key: string;
|
|
11
|
+
/** Dimension label shown before the colon (e.g. "Status", "Sort"). */
|
|
12
|
+
label: string;
|
|
13
|
+
/** Human-readable applied value shown after the colon (e.g. "Active"). */
|
|
14
|
+
value: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* `mj-applied-filters` — the "Filtered by …" chip row that renders the *state*
|
|
18
|
+
* of filtering, separate from the *input* (a single `mj-filter-popover`
|
|
19
|
+
* "Filter" button). Each applied filter shows as a removable pill; a "Clear
|
|
20
|
+
* all" link clears the lot.
|
|
21
|
+
*
|
|
22
|
+
* Part of the concise-chrome model: one Filter entry point sets filters, this
|
|
23
|
+
* row shows what's on and removes them individually. Identical on desktop
|
|
24
|
+
* (chips wrap) and mobile (chips scroll horizontally) — nothing new to learn
|
|
25
|
+
* between breakpoints.
|
|
26
|
+
*
|
|
27
|
+
* Renders nothing when `Filters` is empty, so consumers can place it
|
|
28
|
+
* unconditionally above their content.
|
|
29
|
+
*
|
|
30
|
+
* ## Example
|
|
31
|
+
* ```html
|
|
32
|
+
* <mj-applied-filters
|
|
33
|
+
* [Filters]="appliedFilters"
|
|
34
|
+
* (Remove)="onRemoveFilter($event)"
|
|
35
|
+
* (ClearAll)="resetAllFilters()">
|
|
36
|
+
* </mj-applied-filters>
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare class MJAppliedFiltersComponent {
|
|
40
|
+
/** The currently-applied filters rendered as removable chips. */
|
|
41
|
+
Filters: AppliedFilter[];
|
|
42
|
+
/** Lead label shown before the chips. Defaults to "Filtered by". */
|
|
43
|
+
LeadLabel: string;
|
|
44
|
+
/** Label for the clear-all link. Defaults to "Clear all". */
|
|
45
|
+
ClearAllLabel: string;
|
|
46
|
+
/** Emitted when a single filter's ✕ is clicked. */
|
|
47
|
+
Remove: EventEmitter<AppliedFilter>;
|
|
48
|
+
/** Emitted when the "Clear all" link is clicked. */
|
|
49
|
+
ClearAll: EventEmitter<void>;
|
|
50
|
+
OnRemove(filter: AppliedFilter): void;
|
|
51
|
+
OnClearAll(): void;
|
|
52
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MJAppliedFiltersComponent, never>;
|
|
53
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MJAppliedFiltersComponent, "mj-applied-filters", never, { "Filters": { "alias": "Filters"; "required": false; }; "LeadLabel": { "alias": "LeadLabel"; "required": false; }; "ClearAllLabel": { "alias": "ClearAllLabel"; "required": false; }; }, { "Remove": "Remove"; "ClearAll": "ClearAll"; }, never, never, true, never>;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=applied-filters.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applied-filters.component.d.ts","sourceRoot":"","sources":["../../../src/lib/applied-filters/applied-filters.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;;AAEvE;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBA4Ha,yBAAyB;IACpC,iEAAiE;IACxD,OAAO,EAAE,aAAa,EAAE,CAAM;IAEvC,oEAAoE;IAC3D,SAAS,EAAE,MAAM,CAAiB;IAE3C,6DAA6D;IACpD,aAAa,EAAE,MAAM,CAAe;IAE7C,mDAAmD;IACzC,MAAM,8BAAqC;IAErD,oDAAoD;IAC1C,QAAQ,qBAA4B;IAE9C,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAIrC,UAAU,IAAI,IAAI;yCApBP,yBAAyB;2CAAzB,yBAAyB;CAuBrC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
const _forTrack0 = ($index, $item) => $item.key;
|
|
4
|
+
function MJAppliedFiltersComponent_Conditional_0_For_4_Template(rf, ctx) { if (rf & 1) {
|
|
5
|
+
const _r2 = i0.ɵɵgetCurrentView();
|
|
6
|
+
i0.ɵɵdomElementStart(0, "span", 2)(1, "span", 4);
|
|
7
|
+
i0.ɵɵtext(2);
|
|
8
|
+
i0.ɵɵdomElementEnd();
|
|
9
|
+
i0.ɵɵdomElementStart(3, "span", 5);
|
|
10
|
+
i0.ɵɵtext(4);
|
|
11
|
+
i0.ɵɵdomElementEnd();
|
|
12
|
+
i0.ɵɵdomElementStart(5, "button", 6);
|
|
13
|
+
i0.ɵɵdomListener("click", function MJAppliedFiltersComponent_Conditional_0_For_4_Template_button_click_5_listener() { const f_r3 = i0.ɵɵrestoreView(_r2).$implicit; const ctx_r3 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r3.OnRemove(f_r3)); });
|
|
14
|
+
i0.ɵɵdomElement(6, "i", 7);
|
|
15
|
+
i0.ɵɵdomElementEnd()();
|
|
16
|
+
} if (rf & 2) {
|
|
17
|
+
const f_r3 = ctx.$implicit;
|
|
18
|
+
i0.ɵɵadvance(2);
|
|
19
|
+
i0.ɵɵtextInterpolate1("", f_r3.label, ":");
|
|
20
|
+
i0.ɵɵadvance(2);
|
|
21
|
+
i0.ɵɵtextInterpolate(f_r3.value);
|
|
22
|
+
i0.ɵɵadvance();
|
|
23
|
+
i0.ɵɵattribute("aria-label", "Remove " + f_r3.label + " " + f_r3.value);
|
|
24
|
+
} }
|
|
25
|
+
function MJAppliedFiltersComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
26
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
27
|
+
i0.ɵɵdomElementStart(0, "div", 0)(1, "span", 1);
|
|
28
|
+
i0.ɵɵtext(2);
|
|
29
|
+
i0.ɵɵdomElementEnd();
|
|
30
|
+
i0.ɵɵrepeaterCreate(3, MJAppliedFiltersComponent_Conditional_0_For_4_Template, 7, 3, "span", 2, _forTrack0);
|
|
31
|
+
i0.ɵɵdomElementStart(5, "button", 3);
|
|
32
|
+
i0.ɵɵdomListener("click", function MJAppliedFiltersComponent_Conditional_0_Template_button_click_5_listener() { i0.ɵɵrestoreView(_r1); const ctx_r3 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r3.OnClearAll()); });
|
|
33
|
+
i0.ɵɵtext(6);
|
|
34
|
+
i0.ɵɵdomElementEnd()();
|
|
35
|
+
} if (rf & 2) {
|
|
36
|
+
const ctx_r3 = i0.ɵɵnextContext();
|
|
37
|
+
i0.ɵɵadvance(2);
|
|
38
|
+
i0.ɵɵtextInterpolate(ctx_r3.LeadLabel);
|
|
39
|
+
i0.ɵɵadvance();
|
|
40
|
+
i0.ɵɵrepeater(ctx_r3.Filters);
|
|
41
|
+
i0.ɵɵadvance(3);
|
|
42
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r3.ClearAllLabel, " ");
|
|
43
|
+
} }
|
|
44
|
+
/**
|
|
45
|
+
* `mj-applied-filters` — the "Filtered by …" chip row that renders the *state*
|
|
46
|
+
* of filtering, separate from the *input* (a single `mj-filter-popover`
|
|
47
|
+
* "Filter" button). Each applied filter shows as a removable pill; a "Clear
|
|
48
|
+
* all" link clears the lot.
|
|
49
|
+
*
|
|
50
|
+
* Part of the concise-chrome model: one Filter entry point sets filters, this
|
|
51
|
+
* row shows what's on and removes them individually. Identical on desktop
|
|
52
|
+
* (chips wrap) and mobile (chips scroll horizontally) — nothing new to learn
|
|
53
|
+
* between breakpoints.
|
|
54
|
+
*
|
|
55
|
+
* Renders nothing when `Filters` is empty, so consumers can place it
|
|
56
|
+
* unconditionally above their content.
|
|
57
|
+
*
|
|
58
|
+
* ## Example
|
|
59
|
+
* ```html
|
|
60
|
+
* <mj-applied-filters
|
|
61
|
+
* [Filters]="appliedFilters"
|
|
62
|
+
* (Remove)="onRemoveFilter($event)"
|
|
63
|
+
* (ClearAll)="resetAllFilters()">
|
|
64
|
+
* </mj-applied-filters>
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export class MJAppliedFiltersComponent {
|
|
68
|
+
/** The currently-applied filters rendered as removable chips. */
|
|
69
|
+
Filters = [];
|
|
70
|
+
/** Lead label shown before the chips. Defaults to "Filtered by". */
|
|
71
|
+
LeadLabel = 'Filtered by';
|
|
72
|
+
/** Label for the clear-all link. Defaults to "Clear all". */
|
|
73
|
+
ClearAllLabel = 'Clear all';
|
|
74
|
+
/** Emitted when a single filter's ✕ is clicked. */
|
|
75
|
+
Remove = new EventEmitter();
|
|
76
|
+
/** Emitted when the "Clear all" link is clicked. */
|
|
77
|
+
ClearAll = new EventEmitter();
|
|
78
|
+
OnRemove(filter) {
|
|
79
|
+
this.Remove.emit(filter);
|
|
80
|
+
}
|
|
81
|
+
OnClearAll() {
|
|
82
|
+
this.ClearAll.emit();
|
|
83
|
+
}
|
|
84
|
+
static ɵfac = function MJAppliedFiltersComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJAppliedFiltersComponent)(); };
|
|
85
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJAppliedFiltersComponent, selectors: [["mj-applied-filters"]], inputs: { Filters: "Filters", LeadLabel: "LeadLabel", ClearAllLabel: "ClearAllLabel" }, outputs: { Remove: "Remove", ClearAll: "ClearAll" }, decls: 1, vars: 1, consts: [[1, "mj-applied-filters"], [1, "mj-applied-filters__lead"], [1, "mj-applied-filters__token"], ["type", "button", 1, "mj-applied-filters__clear", 3, "click"], [1, "mj-applied-filters__k"], [1, "mj-applied-filters__v"], ["type", "button", 1, "mj-applied-filters__x", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-xmark"]], template: function MJAppliedFiltersComponent_Template(rf, ctx) { if (rf & 1) {
|
|
86
|
+
i0.ɵɵconditionalCreate(0, MJAppliedFiltersComponent_Conditional_0_Template, 7, 2, "div", 0);
|
|
87
|
+
} if (rf & 2) {
|
|
88
|
+
i0.ɵɵconditional(ctx.Filters.length > 0 ? 0 : -1);
|
|
89
|
+
} }, styles: ["[_nghost-%COMP%] {\n display: block;\n }\n\n .mj-applied-filters[_ngcontent-%COMP%] {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-3) var(--mj-space-5);\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .mj-applied-filters__lead[_ngcontent-%COMP%] {\n flex-shrink: 0;\n margin-right: 2px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--mj-text-muted);\n }\n\n .mj-applied-filters__token[_ngcontent-%COMP%] {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n gap: 7px;\n height: 30px;\n padding: 0 5px 0 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n background: var(--mj-bg-surface);\n font-size: 12.5px;\n }\n\n .mj-applied-filters__k[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n }\n\n .mj-applied-filters__v[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n font-weight: 600;\n }\n\n .mj-applied-filters__x[_ngcontent-%COMP%] {\n width: 19px;\n height: 19px;\n flex-shrink: 0;\n border: none;\n background: transparent;\n border-radius: 50%;\n display: grid;\n place-items: center;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 11px;\n font-family: inherit;\n }\n .mj-applied-filters__x[_ngcontent-%COMP%]:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n }\n\n .mj-applied-filters__clear[_ngcontent-%COMP%] {\n flex-shrink: 0;\n margin-left: 4px;\n border: none;\n background: transparent;\n cursor: pointer;\n font-family: inherit;\n font-size: 12.5px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n }\n .mj-applied-filters__clear[_ngcontent-%COMP%]:hover {\n text-decoration: underline;\n }\n\n \n\n\n @media (max-width: 700px) {\n .mj-applied-filters[_ngcontent-%COMP%] {\n overflow-x: auto;\n flex-wrap: nowrap;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n padding-left: var(--mj-space-4);\n padding-right: var(--mj-space-4);\n }\n .mj-applied-filters[_ngcontent-%COMP%]::-webkit-scrollbar {\n display: none;\n }\n }"] });
|
|
90
|
+
}
|
|
91
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJAppliedFiltersComponent, [{
|
|
92
|
+
type: Component,
|
|
93
|
+
args: [{ selector: 'mj-applied-filters', standalone: true, template: `
|
|
94
|
+
@if (Filters.length > 0) {
|
|
95
|
+
<div class="mj-applied-filters">
|
|
96
|
+
<span class="mj-applied-filters__lead">{{ LeadLabel }}</span>
|
|
97
|
+
@for (f of Filters; track f.key) {
|
|
98
|
+
<span class="mj-applied-filters__token">
|
|
99
|
+
<span class="mj-applied-filters__k">{{ f.label }}:</span>
|
|
100
|
+
<span class="mj-applied-filters__v">{{ f.value }}</span>
|
|
101
|
+
<button
|
|
102
|
+
type="button"
|
|
103
|
+
class="mj-applied-filters__x"
|
|
104
|
+
[attr.aria-label]="'Remove ' + f.label + ' ' + f.value"
|
|
105
|
+
(click)="OnRemove(f)">
|
|
106
|
+
<i class="fa-solid fa-xmark" aria-hidden="true"></i>
|
|
107
|
+
</button>
|
|
108
|
+
</span>
|
|
109
|
+
}
|
|
110
|
+
<button type="button" class="mj-applied-filters__clear" (click)="OnClearAll()">
|
|
111
|
+
{{ ClearAllLabel }}
|
|
112
|
+
</button>
|
|
113
|
+
</div>
|
|
114
|
+
}
|
|
115
|
+
`, styles: ["\n :host {\n display: block;\n }\n\n .mj-applied-filters {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-3) var(--mj-space-5);\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .mj-applied-filters__lead {\n flex-shrink: 0;\n margin-right: 2px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--mj-text-muted);\n }\n\n .mj-applied-filters__token {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n gap: 7px;\n height: 30px;\n padding: 0 5px 0 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n background: var(--mj-bg-surface);\n font-size: 12.5px;\n }\n\n .mj-applied-filters__k {\n color: var(--mj-text-muted);\n }\n\n .mj-applied-filters__v {\n color: var(--mj-text-primary);\n font-weight: 600;\n }\n\n .mj-applied-filters__x {\n width: 19px;\n height: 19px;\n flex-shrink: 0;\n border: none;\n background: transparent;\n border-radius: 50%;\n display: grid;\n place-items: center;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 11px;\n font-family: inherit;\n }\n .mj-applied-filters__x:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n }\n\n .mj-applied-filters__clear {\n flex-shrink: 0;\n margin-left: 4px;\n border: none;\n background: transparent;\n cursor: pointer;\n font-family: inherit;\n font-size: 12.5px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n }\n .mj-applied-filters__clear:hover {\n text-decoration: underline;\n }\n\n /* Mobile: the chip row scrolls horizontally rather than wrapping, so it\n stays a single compact line. */\n @media (max-width: 700px) {\n .mj-applied-filters {\n overflow-x: auto;\n flex-wrap: nowrap;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n padding-left: var(--mj-space-4);\n padding-right: var(--mj-space-4);\n }\n .mj-applied-filters::-webkit-scrollbar {\n display: none;\n }\n }\n "] }]
|
|
116
|
+
}], null, { Filters: [{
|
|
117
|
+
type: Input
|
|
118
|
+
}], LeadLabel: [{
|
|
119
|
+
type: Input
|
|
120
|
+
}], ClearAllLabel: [{
|
|
121
|
+
type: Input
|
|
122
|
+
}], Remove: [{
|
|
123
|
+
type: Output
|
|
124
|
+
}], ClearAll: [{
|
|
125
|
+
type: Output
|
|
126
|
+
}] }); })();
|
|
127
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJAppliedFiltersComponent, { className: "MJAppliedFiltersComponent", filePath: "lib/applied-filters/applied-filters.component.ts", lineNumber: 164 }); })();
|
|
128
|
+
//# sourceMappingURL=applied-filters.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"applied-filters.component.js","sourceRoot":"","sources":["../../../src/lib/applied-filters/applied-filters.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;;;;IAgD3D,AADF,kCAAwC,cACF;IAAA,YAAc;IAAA,oBAAO;IACzD,kCAAoC;IAAA,YAAa;IAAA,oBAAO;IACxD,oCAIwB;IAAtB,8NAAS,qBAAW,KAAC;IACrB,0BAAoD;IAExD,AADE,oBAAS,EACJ;;;IAT+B,eAAc;IAAd,0CAAc;IACd,eAAa;IAAb,gCAAa;IAI/C,cAAuD;;;;;IAR7D,AADF,iCAAgC,cACS;IAAA,YAAe;IAAA,oBAAO;IAC7D,2GAYC;IACD,oCAA+E;IAAvB,gMAAS,mBAAY,KAAC;IAC5E,YACF;IACF,AADE,oBAAS,EACL;;;IAjBmC,eAAe;IAAf,sCAAe;IACtD,cAYC;IAZD,6BAYC;IAEC,eACF;IADE,qDACF;;AA7CR;;;;;;;;;;;;;;;;;;;;;;GAsBG;AA6HH,MAAM,OAAO,yBAAyB;IACpC,iEAAiE;IACxD,OAAO,GAAoB,EAAE,CAAC;IAEvC,oEAAoE;IAC3D,SAAS,GAAW,aAAa,CAAC;IAE3C,6DAA6D;IACpD,aAAa,GAAW,WAAW,CAAC;IAE7C,mDAAmD;IACzC,MAAM,GAAG,IAAI,YAAY,EAAiB,CAAC;IAErD,oDAAoD;IAC1C,QAAQ,GAAG,IAAI,YAAY,EAAQ,CAAC;IAE9C,QAAQ,CAAC,MAAqB;QAC5B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED,UAAU;QACR,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;mHAtBU,yBAAyB;6DAAzB,yBAAyB;YAxHlC,2FAA0B;;YAA1B,iDAoBC;;;iFAoGQ,yBAAyB;cA5HrC,SAAS;2BACE,oBAAoB,cAClB,IAAI,YACN;;;;;;;;;;;;;;;;;;;;;;GAsBT;;kBAqGA,KAAK;;kBAGL,KAAK;;kBAGL,KAAK;;kBAGL,MAAM;;kBAGN,MAAM;;kFAdI,yBAAyB","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\n\n/**\n * One applied filter, as surfaced in the `mj-applied-filters` chip row.\n * `label` is the dimension (e.g. \"Status\"), `value` is the human-readable\n * selection (e.g. \"Active\"), `key` uniquely identifies it for removal.\n */\nexport interface AppliedFilter {\n /** Stable identifier emitted on removal — typically `<field>:<value>`. */\n key: string;\n /** Dimension label shown before the colon (e.g. \"Status\", \"Sort\"). */\n label: string;\n /** Human-readable applied value shown after the colon (e.g. \"Active\"). */\n value: string;\n}\n\n/**\n * `mj-applied-filters` — the \"Filtered by …\" chip row that renders the *state*\n * of filtering, separate from the *input* (a single `mj-filter-popover`\n * \"Filter\" button). Each applied filter shows as a removable pill; a \"Clear\n * all\" link clears the lot.\n *\n * Part of the concise-chrome model: one Filter entry point sets filters, this\n * row shows what's on and removes them individually. Identical on desktop\n * (chips wrap) and mobile (chips scroll horizontally) — nothing new to learn\n * between breakpoints.\n *\n * Renders nothing when `Filters` is empty, so consumers can place it\n * unconditionally above their content.\n *\n * ## Example\n * ```html\n * <mj-applied-filters\n * [Filters]=\"appliedFilters\"\n * (Remove)=\"onRemoveFilter($event)\"\n * (ClearAll)=\"resetAllFilters()\">\n * </mj-applied-filters>\n * ```\n */\n@Component({\n selector: 'mj-applied-filters',\n standalone: true,\n template: `\n @if (Filters.length > 0) {\n <div class=\"mj-applied-filters\">\n <span class=\"mj-applied-filters__lead\">{{ LeadLabel }}</span>\n @for (f of Filters; track f.key) {\n <span class=\"mj-applied-filters__token\">\n <span class=\"mj-applied-filters__k\">{{ f.label }}:</span>\n <span class=\"mj-applied-filters__v\">{{ f.value }}</span>\n <button\n type=\"button\"\n class=\"mj-applied-filters__x\"\n [attr.aria-label]=\"'Remove ' + f.label + ' ' + f.value\"\n (click)=\"OnRemove(f)\">\n <i class=\"fa-solid fa-xmark\" aria-hidden=\"true\"></i>\n </button>\n </span>\n }\n <button type=\"button\" class=\"mj-applied-filters__clear\" (click)=\"OnClearAll()\">\n {{ ClearAllLabel }}\n </button>\n </div>\n }\n `,\n styles: [`\n :host {\n display: block;\n }\n\n .mj-applied-filters {\n flex-shrink: 0;\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: var(--mj-space-3) var(--mj-space-5);\n background: var(--mj-bg-surface);\n border-bottom: 1px solid var(--mj-border-subtle);\n }\n\n .mj-applied-filters__lead {\n flex-shrink: 0;\n margin-right: 2px;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--mj-text-muted);\n }\n\n .mj-applied-filters__token {\n flex-shrink: 0;\n display: inline-flex;\n align-items: center;\n gap: 7px;\n height: 30px;\n padding: 0 5px 0 12px;\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n background: var(--mj-bg-surface);\n font-size: 12.5px;\n }\n\n .mj-applied-filters__k {\n color: var(--mj-text-muted);\n }\n\n .mj-applied-filters__v {\n color: var(--mj-text-primary);\n font-weight: 600;\n }\n\n .mj-applied-filters__x {\n width: 19px;\n height: 19px;\n flex-shrink: 0;\n border: none;\n background: transparent;\n border-radius: 50%;\n display: grid;\n place-items: center;\n cursor: pointer;\n color: var(--mj-text-muted);\n font-size: 11px;\n font-family: inherit;\n }\n .mj-applied-filters__x:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n }\n\n .mj-applied-filters__clear {\n flex-shrink: 0;\n margin-left: 4px;\n border: none;\n background: transparent;\n cursor: pointer;\n font-family: inherit;\n font-size: 12.5px;\n font-weight: 600;\n color: var(--mj-brand-primary);\n }\n .mj-applied-filters__clear:hover {\n text-decoration: underline;\n }\n\n /* Mobile: the chip row scrolls horizontally rather than wrapping, so it\n stays a single compact line. */\n @media (max-width: 700px) {\n .mj-applied-filters {\n overflow-x: auto;\n flex-wrap: nowrap;\n scrollbar-width: none;\n -webkit-overflow-scrolling: touch;\n padding-left: var(--mj-space-4);\n padding-right: var(--mj-space-4);\n }\n .mj-applied-filters::-webkit-scrollbar {\n display: none;\n }\n }\n `]\n})\nexport class MJAppliedFiltersComponent {\n /** The currently-applied filters rendered as removable chips. */\n @Input() Filters: AppliedFilter[] = [];\n\n /** Lead label shown before the chips. Defaults to \"Filtered by\". */\n @Input() LeadLabel: string = 'Filtered by';\n\n /** Label for the clear-all link. Defaults to \"Clear all\". */\n @Input() ClearAllLabel: string = 'Clear all';\n\n /** Emitted when a single filter's ✕ is clicked. */\n @Output() Remove = new EventEmitter<AppliedFilter>();\n\n /** Emitted when the \"Clear all\" link is clicked. */\n @Output() ClearAll = new EventEmitter<void>();\n\n OnRemove(filter: AppliedFilter): void {\n this.Remove.emit(filter);\n }\n\n OnClearAll(): void {\n this.ClearAll.emit();\n }\n}\n"]}
|
|
@@ -27,7 +27,16 @@ export interface FilterFieldConfig {
|
|
|
27
27
|
value: string | number | boolean | null;
|
|
28
28
|
icon?: string;
|
|
29
29
|
}[];
|
|
30
|
+
/**
|
|
31
|
+
* For `type === 'chips'` only. When `true`, the chip group is multi-select:
|
|
32
|
+
* the field's value is an **array** of selected option values and clicking a
|
|
33
|
+
* chip toggles it in/out. When absent/false (default), the group is
|
|
34
|
+
* single-select (value is the chosen option value, click replaces).
|
|
35
|
+
*/
|
|
36
|
+
multi?: boolean;
|
|
30
37
|
}
|
|
38
|
+
/** Option value type shared by dropdown + chip options. */
|
|
39
|
+
type FilterOptionValue = string | number | boolean | null;
|
|
31
40
|
/**
|
|
32
41
|
* mj-filter-panel — Single centralized filter panel for all dashboards.
|
|
33
42
|
*
|
|
@@ -63,7 +72,12 @@ export declare class MJFilterPanelComponent {
|
|
|
63
72
|
Reset: EventEmitter<void>;
|
|
64
73
|
getValue(key: string): unknown;
|
|
65
74
|
setValue(key: string, value: unknown): void;
|
|
75
|
+
/** Whether a chip option is currently active (handles single + multi). */
|
|
76
|
+
isChipActive(field: FilterFieldConfig, optValue: FilterOptionValue): boolean;
|
|
77
|
+
/** Chip click: replace (single-select) or toggle in/out of the array (multi). */
|
|
78
|
+
onChipClick(field: FilterFieldConfig, optValue: FilterOptionValue): void;
|
|
66
79
|
static ɵfac: i0.ɵɵFactoryDeclaration<MJFilterPanelComponent, never>;
|
|
67
80
|
static ɵcmp: i0.ɵɵComponentDeclaration<MJFilterPanelComponent, "mj-filter-panel", never, { "Fields": { "alias": "Fields"; "required": false; }; "Values": { "alias": "Values"; "required": false; }; "ShowReset": { "alias": "ShowReset"; "required": false; }; "ResetLabel": { "alias": "ResetLabel"; "required": false; }; }, { "ValuesChange": "ValuesChange"; "Reset": "Reset"; }, never, ["*"], true, never>;
|
|
68
81
|
}
|
|
82
|
+
export {};
|
|
69
83
|
//# sourceMappingURL=filter-panel.component.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/filter-panel/filter-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;;AAOvE,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AAE5D,wDAAwD;AACxD,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,IAAI,EAAE,eAAe,CAAC;IACtB,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IACtE,+DAA+D;IAC/D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"filter-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/filter-panel/filter-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;;AAOvE,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AAE5D,wDAAwD;AACxD,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,IAAI,EAAE,eAAe,CAAC;IACtB,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAA;KAAE,EAAE,CAAC;IACtE,+DAA+D;IAC/D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kDAAkD;IAClD,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACzF;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,2DAA2D;AAC3D,KAAK,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBA0Ia,sBAAsB;IACxB,MAAM,EAAE,iBAAiB,EAAE,CAAM;IACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM;IACrC,SAAS,EAAE,OAAO,CAAQ;IAC1B,UAAU,EAAE,MAAM,CAAmB;IAEpC,YAAY,wCAA+C;IAC3D,KAAK,qBAA4B;IAEpC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAI9B,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAKlD,0EAA0E;IACnE,YAAY,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,OAAO;IAQnF,iFAAiF;IAC1E,WAAW,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI;yCA5BpE,sBAAsB;2CAAtB,sBAAsB;CA2ClC"}
|
|
@@ -33,13 +33,13 @@ function MJFilterPanelComponent_For_3_Case_2_Template(rf, ctx) { if (rf & 1) {
|
|
|
33
33
|
function MJFilterPanelComponent_For_3_Case_3_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
34
34
|
const _r5 = i0.ɵɵgetCurrentView();
|
|
35
35
|
i0.ɵɵelementStart(0, "mj-filter-chip", 10);
|
|
36
|
-
i0.ɵɵlistener("Clicked", function MJFilterPanelComponent_For_3_Case_3_For_2_Template_mj_filter_chip_Clicked_0_listener() { const opt_r6 = i0.ɵɵrestoreView(_r5).$implicit; const field_r2 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.
|
|
36
|
+
i0.ɵɵlistener("Clicked", function MJFilterPanelComponent_For_3_Case_3_For_2_Template_mj_filter_chip_Clicked_0_listener() { const opt_r6 = i0.ɵɵrestoreView(_r5).$implicit; const field_r2 = i0.ɵɵnextContext(2).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.onChipClick(field_r2, opt_r6.value)); });
|
|
37
37
|
i0.ɵɵelementEnd();
|
|
38
38
|
} if (rf & 2) {
|
|
39
39
|
const opt_r6 = ctx.$implicit;
|
|
40
40
|
const field_r2 = i0.ɵɵnextContext(2).$implicit;
|
|
41
41
|
const ctx_r2 = i0.ɵɵnextContext();
|
|
42
|
-
i0.ɵɵproperty("Label", opt_r6.text)("Icon", opt_r6.icon ?? null)("Active", ctx_r2.
|
|
42
|
+
i0.ɵɵproperty("Label", opt_r6.text)("Icon", opt_r6.icon ?? null)("Active", ctx_r2.isChipActive(field_r2, opt_r6.value));
|
|
43
43
|
} }
|
|
44
44
|
function MJFilterPanelComponent_For_3_Case_3_Template(rf, ctx) { if (rf & 1) {
|
|
45
45
|
i0.ɵɵelementStart(0, "div", 6);
|
|
@@ -113,6 +113,31 @@ export class MJFilterPanelComponent {
|
|
|
113
113
|
this.Values = { ...this.Values, [key]: value };
|
|
114
114
|
this.ValuesChange.emit(this.Values);
|
|
115
115
|
}
|
|
116
|
+
/** Whether a chip option is currently active (handles single + multi). */
|
|
117
|
+
isChipActive(field, optValue) {
|
|
118
|
+
if (field.multi) {
|
|
119
|
+
const current = this.getValue(field.key);
|
|
120
|
+
return Array.isArray(current) && current.includes(optValue);
|
|
121
|
+
}
|
|
122
|
+
return this.getValue(field.key) === optValue;
|
|
123
|
+
}
|
|
124
|
+
/** Chip click: replace (single-select) or toggle in/out of the array (multi). */
|
|
125
|
+
onChipClick(field, optValue) {
|
|
126
|
+
if (!field.multi) {
|
|
127
|
+
this.setValue(field.key, optValue);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const current = this.getValue(field.key);
|
|
131
|
+
const next = Array.isArray(current) ? [...current] : [];
|
|
132
|
+
const idx = next.indexOf(optValue);
|
|
133
|
+
if (idx >= 0) {
|
|
134
|
+
next.splice(idx, 1);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
next.push(optValue);
|
|
138
|
+
}
|
|
139
|
+
this.setValue(field.key, next);
|
|
140
|
+
}
|
|
116
141
|
static ɵfac = function MJFilterPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJFilterPanelComponent)(); };
|
|
117
142
|
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJFilterPanelComponent, selectors: [["mj-filter-panel"]], inputs: { Fields: "Fields", Values: "Values", ShowReset: "ShowReset", ResetLabel: "ResetLabel" }, outputs: { ValuesChange: "ValuesChange", Reset: "Reset" }, ngContentSelectors: _c0, decls: 6, vars: 1, consts: [[1, "mj-filter-panel"], [1, "mj-filter-panel-body"], [3, "Label", "Icon"], [1, "mj-filter-panel-footer"], ["type", "text", 1, "mj-filter-panel-text-input", 3, "value", "placeholder"], ["TextField", "text", "ValueField", "value", 3, "Data", "ValuePrimitive", "Filterable", "Placeholder", "ngModel"], [1, "mj-filter-panel-chip-group"], ["type", "text", 1, "mj-filter-panel-text-input", 3, "input", "value", "placeholder"], ["TextField", "text", "ValueField", "value", 3, "ngModelChange", "Data", "ValuePrimitive", "Filterable", "Placeholder", "ngModel"], [3, "Label", "Icon", "Active"], [3, "Clicked", "Label", "Icon", "Active"], ["type", "button", 1, "mj-filter-panel-reset", 3, "click"], [1, "fa-solid", "fa-rotate-left"]], template: function MJFilterPanelComponent_Template(rf, ctx) { if (rf & 1) {
|
|
118
143
|
i0.ɵɵprojectionDef();
|
|
@@ -163,8 +188,8 @@ export class MJFilterPanelComponent {
|
|
|
163
188
|
<mj-filter-chip
|
|
164
189
|
[Label]="opt.text"
|
|
165
190
|
[Icon]="opt.icon ?? null"
|
|
166
|
-
[Active]="
|
|
167
|
-
(Clicked)="
|
|
191
|
+
[Active]="isChipActive(field, opt.value)"
|
|
192
|
+
(Clicked)="onChipClick(field, opt.value)">
|
|
168
193
|
</mj-filter-chip>
|
|
169
194
|
}
|
|
170
195
|
</div>
|
|
@@ -199,5 +224,5 @@ export class MJFilterPanelComponent {
|
|
|
199
224
|
}], Reset: [{
|
|
200
225
|
type: Output
|
|
201
226
|
}] }); })();
|
|
202
|
-
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJFilterPanelComponent, { className: "MJFilterPanelComponent", filePath: "lib/filter-panel/filter-panel.component.ts", lineNumber:
|
|
227
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJFilterPanelComponent, { className: "MJFilterPanelComponent", filePath: "lib/filter-panel/filter-panel.component.ts", lineNumber: 205 }); })();
|
|
203
228
|
//# sourceMappingURL=filter-panel.component.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-panel.component.js","sourceRoot":"","sources":["../../../src/lib/filter-panel/filter-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;;;;;;;;;IA8DhE,gCAK6D;IAA3D,6OAAS,kDAA8C,KAAC;IAL1D,iBAK6D;;;;IAD3D,AADA,2DAAmC,2CACI;;;;IAIzC,sCAQgD;IAA9C,mQAAiB,qCAA2B,KAAC;IAC/C,iBAAc;;;;IAFZ,AADA,AADA,AADA,AAHA,qEAA4B,wBAGL,qCACU,2CACM,0CACR;;;;IAO7B,0CAI6C;IAA3C,oRAAW,2CAA8B,KAAC;IAC5C,iBAAiB;;;;;IAFf,AADA,AADA,mCAAkB,6BACO,0DACmB;;;IALlD,8BAAwC;IACtC,iHAOC;IACH,iBAAM;;;IARJ,cAOC;IAPD,iEAOC;;;IA/BT,0CAAmE;IAsB/D,AAZA,AARA,yFAAgB,yEAQI,iEAYH;IAarB,iBAAkB;;;;IAnCqB,AAAtB,sCAAqB,+BAA4B;IAChE,cAiCC;IAjCD,gDAAA,MAAM,oBAAN,UAAU,oBAAV,OAAO,UAiCN;;;;IAUH,AADF,8BAAoC,iBACyC;IAAvB,0LAAS,mBAAY,KAAC;IACxE,wBAAuC;IAAC,YAC1C;IACF,AADE,iBAAS,EACL;;;IAFsC,eAC1C;IAD0C,kDAC1C;;AAhFV;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AA2IH,MAAM,OAAO,sBAAsB;IACxB,MAAM,GAAwB,EAAE,CAAC;IACjC,MAAM,GAA4B,EAAE,CAAC;IACrC,SAAS,GAAY,IAAI,CAAC;IAC1B,UAAU,GAAW,eAAe,CAAC;IAEpC,YAAY,GAAG,IAAI,YAAY,EAA2B,CAAC;IAC3D,KAAK,GAAG,IAAI,YAAY,EAAQ,CAAC;IAEpC,QAAQ,CAAC,GAAW;QACzB,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAEM,QAAQ,CAAC,GAAW,EAAE,KAAc;QACzC,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;QAC/C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;gHAhBU,sBAAsB;6DAAtB,sBAAsB;;YApI7B,AADF,8BAA6B,aACO;YAChC,qGAqCC;YAGD,kBAAyB;YAC3B,iBAAM;YAEN,wFAAiB;YAOnB,iBAAM;;YAlDF,eAqCC;YArCD,yBAqCC;YAMH,eAMC;YAND,wCAMC;4BArDK,YAAY,EAAE,WAAW,kCAAE,mBAAmB,EAAE,qBAAqB,EAAE,sBAAsB;;iFAuI5F,sBAAsB;cA1IlC,SAAS;2BACE,iBAAiB,cACf,IAAI,WACP,CAAC,YAAY,EAAE,WAAW,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,sBAAsB,CAAC,YAC9F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDT;;kBAiFA,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBAEL,MAAM;;kBACN,MAAM;;kFAPI,sBAAsB","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { MJDropdownComponent } from '../dropdown/dropdown.component';\nimport { MJFilterChipComponent } from '../filter-chip/filter-chip.component';\nimport { MJFilterFieldComponent } from '../filter-field/filter-field.component';\n\n/** Field types supported natively by <mj-filter-panel>. */\nexport type FilterFieldType = 'text' | 'dropdown' | 'chips';\n\n/** Per-field config understood by <mj-filter-panel>. */\nexport interface FilterFieldConfig {\n /** State key in the Values record. */\n key: string;\n /** Field type — drives which widget is rendered. */\n type: FilterFieldType;\n /** Display label. */\n label: string;\n /** Optional Font Awesome icon class (e.g. 'fa-solid fa-folder'). */\n icon?: string;\n /** Placeholder for text inputs / dropdowns. */\n placeholder?: string;\n /** Dropdown options (when type === 'dropdown'). Each option needs text + value. */\n options?: { text: string; value: string | number | boolean | null }[];\n /** Whether the dropdown should show an internal search box. */\n filterable?: boolean;\n /** Chip-group options (when type === 'chips'). */\n chipOptions?: { text: string; value: string | number | boolean | null; icon?: string }[];\n}\n\n/**\n * mj-filter-panel — Single centralized filter panel for all dashboards.\n *\n * Config-driven: pass an array of `FilterFieldConfig` plus a `Values` record;\n * the panel renders each field using the appropriate widget (text input,\n * `<mj-dropdown>`, or chip group), keeps everything visually consistent, and\n * emits state changes via `(ValuesChange)`.\n *\n * For widgets not covered by the config schema (tree-dropdown, date pickers,\n * etc.), project `<mj-filter-field>` elements as content — they render below\n * the config-driven fields with identical chrome.\n *\n * Example:\n * ```html\n * <mj-filter-panel\n * [Fields]=\"filterFields\"\n * [(Values)]=\"filterValues\"\n * (Reset)=\"onReset()\">\n *\n * <!-- escape hatch for custom widgets -->\n * <mj-filter-field Label=\"Category\" Icon=\"fa-solid fa-folder\">\n * <mj-tree-dropdown ...></mj-tree-dropdown>\n * </mj-filter-field>\n * </mj-filter-panel>\n * ```\n */\n@Component({\n selector: 'mj-filter-panel',\n standalone: true,\n imports: [CommonModule, FormsModule, MJDropdownComponent, MJFilterChipComponent, MJFilterFieldComponent],\n template: `\n <div class=\"mj-filter-panel\">\n <div class=\"mj-filter-panel-body\">\n @for (field of Fields; track field.key) {\n <mj-filter-field [Label]=\"field.label\" [Icon]=\"field.icon ?? null\">\n @switch (field.type) {\n @case ('text') {\n <input\n type=\"text\"\n class=\"mj-filter-panel-text-input\"\n [value]=\"getValue(field.key) ?? ''\"\n [placeholder]=\"field.placeholder ?? ''\"\n (input)=\"setValue(field.key, $any($event.target).value)\" />\n }\n @case ('dropdown') {\n <mj-dropdown\n [Data]=\"field.options ?? []\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [Filterable]=\"!!field.filterable\"\n [Placeholder]=\"field.placeholder ?? ''\"\n [ngModel]=\"getValue(field.key)\"\n (ngModelChange)=\"setValue(field.key, $event)\">\n </mj-dropdown>\n }\n @case ('chips') {\n <div class=\"mj-filter-panel-chip-group\">\n @for (opt of field.chipOptions ?? []; track opt.value) {\n <mj-filter-chip\n [Label]=\"opt.text\"\n [Icon]=\"opt.icon ?? null\"\n [Active]=\"getValue(field.key) === opt.value\"\n (Clicked)=\"setValue(field.key, opt.value)\">\n </mj-filter-chip>\n }\n </div>\n }\n }\n </mj-filter-field>\n }\n\n <!-- Escape hatch for custom field widgets (e.g. mj-tree-dropdown, date pickers) -->\n <ng-content></ng-content>\n </div>\n\n @if (ShowReset) {\n <div class=\"mj-filter-panel-footer\">\n <button type=\"button\" class=\"mj-filter-panel-reset\" (click)=\"Reset.emit()\">\n <i class=\"fa-solid fa-rotate-left\"></i> {{ ResetLabel }}\n </button>\n </div>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n }\n\n .mj-filter-panel {\n display: flex;\n flex-direction: column;\n gap: 14px;\n }\n\n .mj-filter-panel-body {\n display: flex;\n flex-direction: column;\n gap: 14px;\n }\n\n .mj-filter-panel-text-input {\n width: 100%;\n padding: 7px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n font: inherit;\n font-size: 13px;\n color: var(--mj-text-primary);\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n }\n\n .mj-filter-panel-text-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n\n .mj-filter-panel-text-input::placeholder {\n color: var(--mj-text-muted);\n }\n\n .mj-filter-panel-chip-group {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n\n .mj-filter-panel-footer {\n display: flex;\n justify-content: flex-end;\n padding-top: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n }\n\n .mj-filter-panel-reset {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-secondary);\n font: inherit;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n }\n\n .mj-filter-panel-reset:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n }\n\n .mj-filter-panel-reset i {\n font-size: 11px;\n }\n `]\n})\nexport class MJFilterPanelComponent {\n @Input() Fields: FilterFieldConfig[] = [];\n @Input() Values: Record<string, unknown> = {};\n @Input() ShowReset: boolean = true;\n @Input() ResetLabel: string = 'Reset filters';\n\n @Output() ValuesChange = new EventEmitter<Record<string, unknown>>();\n @Output() Reset = new EventEmitter<void>();\n\n public getValue(key: string): unknown {\n return this.Values?.[key];\n }\n\n public setValue(key: string, value: unknown): void {\n this.Values = { ...this.Values, [key]: value };\n this.ValuesChange.emit(this.Values);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"filter-panel.component.js","sourceRoot":"","sources":["../../../src/lib/filter-panel/filter-panel.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { MJDropdownComponent } from '../dropdown/dropdown.component';\nimport { MJFilterChipComponent } from '../filter-chip/filter-chip.component';\nimport { MJFilterFieldComponent } from '../filter-field/filter-field.component';\n\n/** Field types supported natively by <mj-filter-panel>. */\nexport type FilterFieldType = 'text' | 'dropdown' | 'chips';\n\n/** Per-field config understood by <mj-filter-panel>. */\nexport interface FilterFieldConfig {\n /** State key in the Values record. */\n key: string;\n /** Field type — drives which widget is rendered. */\n type: FilterFieldType;\n /** Display label. */\n label: string;\n /** Optional Font Awesome icon class (e.g. 'fa-solid fa-folder'). */\n icon?: string;\n /** Placeholder for text inputs / dropdowns. */\n placeholder?: string;\n /** Dropdown options (when type === 'dropdown'). Each option needs text + value. */\n options?: { text: string; value: string | number | boolean | null }[];\n /** Whether the dropdown should show an internal search box. */\n filterable?: boolean;\n /** Chip-group options (when type === 'chips'). */\n chipOptions?: { text: string; value: string | number | boolean | null; icon?: string }[];\n /**\n * For `type === 'chips'` only. When `true`, the chip group is multi-select:\n * the field's value is an **array** of selected option values and clicking a\n * chip toggles it in/out. When absent/false (default), the group is\n * single-select (value is the chosen option value, click replaces).\n */\n multi?: boolean;\n}\n\n/** Option value type shared by dropdown + chip options. */\ntype FilterOptionValue = string | number | boolean | null;\n\n/**\n * mj-filter-panel — Single centralized filter panel for all dashboards.\n *\n * Config-driven: pass an array of `FilterFieldConfig` plus a `Values` record;\n * the panel renders each field using the appropriate widget (text input,\n * `<mj-dropdown>`, or chip group), keeps everything visually consistent, and\n * emits state changes via `(ValuesChange)`.\n *\n * For widgets not covered by the config schema (tree-dropdown, date pickers,\n * etc.), project `<mj-filter-field>` elements as content — they render below\n * the config-driven fields with identical chrome.\n *\n * Example:\n * ```html\n * <mj-filter-panel\n * [Fields]=\"filterFields\"\n * [(Values)]=\"filterValues\"\n * (Reset)=\"onReset()\">\n *\n * <!-- escape hatch for custom widgets -->\n * <mj-filter-field Label=\"Category\" Icon=\"fa-solid fa-folder\">\n * <mj-tree-dropdown ...></mj-tree-dropdown>\n * </mj-filter-field>\n * </mj-filter-panel>\n * ```\n */\n@Component({\n selector: 'mj-filter-panel',\n standalone: true,\n imports: [CommonModule, FormsModule, MJDropdownComponent, MJFilterChipComponent, MJFilterFieldComponent],\n template: `\n <div class=\"mj-filter-panel\">\n <div class=\"mj-filter-panel-body\">\n @for (field of Fields; track field.key) {\n <mj-filter-field [Label]=\"field.label\" [Icon]=\"field.icon ?? null\">\n @switch (field.type) {\n @case ('text') {\n <input\n type=\"text\"\n class=\"mj-filter-panel-text-input\"\n [value]=\"getValue(field.key) ?? ''\"\n [placeholder]=\"field.placeholder ?? ''\"\n (input)=\"setValue(field.key, $any($event.target).value)\" />\n }\n @case ('dropdown') {\n <mj-dropdown\n [Data]=\"field.options ?? []\"\n TextField=\"text\"\n ValueField=\"value\"\n [ValuePrimitive]=\"true\"\n [Filterable]=\"!!field.filterable\"\n [Placeholder]=\"field.placeholder ?? ''\"\n [ngModel]=\"getValue(field.key)\"\n (ngModelChange)=\"setValue(field.key, $event)\">\n </mj-dropdown>\n }\n @case ('chips') {\n <div class=\"mj-filter-panel-chip-group\">\n @for (opt of field.chipOptions ?? []; track opt.value) {\n <mj-filter-chip\n [Label]=\"opt.text\"\n [Icon]=\"opt.icon ?? null\"\n [Active]=\"isChipActive(field, opt.value)\"\n (Clicked)=\"onChipClick(field, opt.value)\">\n </mj-filter-chip>\n }\n </div>\n }\n }\n </mj-filter-field>\n }\n\n <!-- Escape hatch for custom field widgets (e.g. mj-tree-dropdown, date pickers) -->\n <ng-content></ng-content>\n </div>\n\n @if (ShowReset) {\n <div class=\"mj-filter-panel-footer\">\n <button type=\"button\" class=\"mj-filter-panel-reset\" (click)=\"Reset.emit()\">\n <i class=\"fa-solid fa-rotate-left\"></i> {{ ResetLabel }}\n </button>\n </div>\n }\n </div>\n `,\n styles: [`\n :host {\n display: block;\n }\n\n .mj-filter-panel {\n display: flex;\n flex-direction: column;\n gap: 14px;\n }\n\n .mj-filter-panel-body {\n display: flex;\n flex-direction: column;\n gap: 14px;\n }\n\n .mj-filter-panel-text-input {\n width: 100%;\n padding: 7px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n font: inherit;\n font-size: 13px;\n color: var(--mj-text-primary);\n transition: border-color 0.15s ease, box-shadow 0.15s ease;\n }\n\n .mj-filter-panel-text-input:focus {\n outline: none;\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n }\n\n .mj-filter-panel-text-input::placeholder {\n color: var(--mj-text-muted);\n }\n\n .mj-filter-panel-chip-group {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n }\n\n .mj-filter-panel-footer {\n display: flex;\n justify-content: flex-end;\n padding-top: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n }\n\n .mj-filter-panel-reset {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 12px;\n background: transparent;\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-secondary);\n font: inherit;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;\n }\n\n .mj-filter-panel-reset:hover {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n }\n\n .mj-filter-panel-reset i {\n font-size: 11px;\n }\n `]\n})\nexport class MJFilterPanelComponent {\n @Input() Fields: FilterFieldConfig[] = [];\n @Input() Values: Record<string, unknown> = {};\n @Input() ShowReset: boolean = true;\n @Input() ResetLabel: string = 'Reset filters';\n\n @Output() ValuesChange = new EventEmitter<Record<string, unknown>>();\n @Output() Reset = new EventEmitter<void>();\n\n public getValue(key: string): unknown {\n return this.Values?.[key];\n }\n\n public setValue(key: string, value: unknown): void {\n this.Values = { ...this.Values, [key]: value };\n this.ValuesChange.emit(this.Values);\n }\n\n /** Whether a chip option is currently active (handles single + multi). */\n public isChipActive(field: FilterFieldConfig, optValue: FilterOptionValue): boolean {\n if (field.multi) {\n const current = this.getValue(field.key);\n return Array.isArray(current) && current.includes(optValue);\n }\n return this.getValue(field.key) === optValue;\n }\n\n /** Chip click: replace (single-select) or toggle in/out of the array (multi). */\n public onChipClick(field: FilterFieldConfig, optValue: FilterOptionValue): void {\n if (!field.multi) {\n this.setValue(field.key, optValue);\n return;\n }\n const current = this.getValue(field.key);\n const next: FilterOptionValue[] = Array.isArray(current) ? [...current] : [];\n const idx = next.indexOf(optValue);\n if (idx >= 0) {\n next.splice(idx, 1);\n } else {\n next.push(optValue);\n }\n this.setValue(field.key, next);\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventEmitter } from '@angular/core';
|
|
1
|
+
import { EventEmitter, OnDestroy } from '@angular/core';
|
|
2
2
|
import { ConnectedPosition } from '@angular/cdk/overlay';
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
4
|
/**
|
|
@@ -19,12 +19,24 @@ import * as i0 from "@angular/core";
|
|
|
19
19
|
* </mj-filter-popover>
|
|
20
20
|
* ```
|
|
21
21
|
*/
|
|
22
|
-
export declare class MJFilterPopoverComponent {
|
|
22
|
+
export declare class MJFilterPopoverComponent implements OnDestroy {
|
|
23
23
|
Label: string;
|
|
24
24
|
Icon: string;
|
|
25
25
|
ActiveCount: number;
|
|
26
26
|
ShowClearAll: boolean;
|
|
27
27
|
IsOpen: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* True when the viewport is narrow enough that the popover should dock as a
|
|
30
|
+
* bottom sheet instead of an anchored overlay. Driven by matchMedia so it
|
|
31
|
+
* tracks live resize without Angular change-detection plumbing.
|
|
32
|
+
*/
|
|
33
|
+
IsMobile: boolean;
|
|
34
|
+
private readonly zone;
|
|
35
|
+
private readonly cdr;
|
|
36
|
+
private readonly mediaQuery;
|
|
37
|
+
private readonly onMediaChange;
|
|
38
|
+
constructor();
|
|
39
|
+
ngOnDestroy(): void;
|
|
28
40
|
readonly Positions: ConnectedPosition[];
|
|
29
41
|
Toggle(): void;
|
|
30
42
|
Open(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-popover.component.d.ts","sourceRoot":"","sources":["../../../src/lib/filter-popover/filter-popover.component.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"filter-popover.component.d.ts","sourceRoot":"","sources":["../../../src/lib/filter-popover/filter-popover.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,YAAY,EAAiB,SAAS,EAAkB,MAAM,eAAe,CAAC;AAErH,OAAO,EAAiB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;;AAExE;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAoQa,wBAAyB,YAAW,SAAS;IAC/C,KAAK,EAAE,MAAM,CAAa;IAC1B,IAAI,EAAE,MAAM,CAAwB;IACpC,WAAW,EAAE,MAAM,CAAK;IACxB,YAAY,EAAE,OAAO,CAAS;IAEhC,MAAM,EAAE,OAAO,CAAS;IAE/B;;;;OAIG;IACI,QAAQ,EAAE,OAAO,CAAS;IAEjC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkB;IACvC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA6B;IAEjD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAGhB;IAOX,OAAO,CAAC,QAAQ,CAAC,aAAa,CAM5B;;IASF,WAAW,IAAI,IAAI;IAQnB,SAAgB,SAAS,EAAE,iBAAiB,EAAE,CAI5C;IAEK,MAAM,IAAI,IAAI;IACd,IAAI,IAAI,IAAI;IACZ,KAAK,IAAI,IAAI;IAEpB,mFAAmF;IAClE,iBAAiB,qBAA4B;IAEvD,QAAQ,IAAI,IAAI;yCAhEZ,wBAAwB;2CAAxB,wBAAwB;CAmEpC"}
|