@memberjunction/ng-ui-components 5.34.0 → 5.35.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/filter-chip/filter-chip.component.d.ts +31 -0
- package/dist/lib/filter-chip/filter-chip.component.d.ts.map +1 -0
- package/dist/lib/filter-chip/filter-chip.component.js +94 -0
- package/dist/lib/filter-chip/filter-chip.component.js.map +1 -0
- package/dist/lib/filter-field/filter-field.component.d.ts +22 -0
- package/dist/lib/filter-field/filter-field.component.d.ts.map +1 -0
- package/dist/lib/filter-field/filter-field.component.js +60 -0
- package/dist/lib/filter-field/filter-field.component.js.map +1 -0
- package/dist/lib/filter-panel/filter-panel.component.d.ts +69 -0
- package/dist/lib/filter-panel/filter-panel.component.d.ts.map +1 -0
- package/dist/lib/filter-panel/filter-panel.component.js +203 -0
- package/dist/lib/filter-panel/filter-panel.component.js.map +1 -0
- package/dist/lib/filter-popover/filter-popover.component.d.ts +38 -0
- package/dist/lib/filter-popover/filter-popover.component.d.ts.map +1 -0
- package/dist/lib/filter-popover/filter-popover.component.js +170 -0
- package/dist/lib/filter-popover/filter-popover.component.js.map +1 -0
- package/dist/lib/page-body/page-body.component.d.ts +46 -0
- package/dist/lib/page-body/page-body.component.d.ts.map +1 -0
- package/dist/lib/page-body/page-body.component.js +72 -0
- package/dist/lib/page-body/page-body.component.js.map +1 -0
- package/dist/lib/page-header/page-header.component.d.ts +35 -0
- package/dist/lib/page-header/page-header.component.d.ts.map +1 -0
- package/dist/lib/page-header/page-header.component.js +121 -0
- package/dist/lib/page-header/page-header.component.js.map +1 -0
- package/dist/lib/page-header/page-header.scss +139 -0
- package/dist/lib/page-layout/page-layout.component.d.ts +20 -0
- package/dist/lib/page-layout/page-layout.component.d.ts.map +1 -0
- package/dist/lib/page-layout/page-layout.component.js +30 -0
- package/dist/lib/page-layout/page-layout.component.js.map +1 -0
- package/dist/lib/page-search/page-search.component.d.ts +29 -0
- package/dist/lib/page-search/page-search.component.d.ts.map +1 -0
- package/dist/lib/page-search/page-search.component.js +69 -0
- package/dist/lib/page-search/page-search.component.js.map +1 -0
- package/dist/lib/refresh-button/refresh-button.component.d.ts +46 -0
- package/dist/lib/refresh-button/refresh-button.component.d.ts.map +1 -0
- package/dist/lib/refresh-button/refresh-button.component.js +106 -0
- package/dist/lib/refresh-button/refresh-button.component.js.map +1 -0
- package/dist/lib/stat-badge/stat-badge.component.d.ts +54 -0
- package/dist/lib/stat-badge/stat-badge.component.d.ts.map +1 -0
- package/dist/lib/stat-badge/stat-badge.component.js +162 -0
- package/dist/lib/stat-badge/stat-badge.component.js.map +1 -0
- package/dist/lib/tab-nav/tab-nav.component.d.ts +41 -0
- package/dist/lib/tab-nav/tab-nav.component.d.ts.map +1 -0
- package/dist/lib/tab-nav/tab-nav.component.js +111 -0
- package/dist/lib/tab-nav/tab-nav.component.js.map +1 -0
- package/dist/lib/view-toggle/view-toggle.component.d.ts +42 -0
- package/dist/lib/view-toggle/view-toggle.component.d.ts.map +1 -0
- package/dist/lib/view-toggle/view-toggle.component.js +104 -0
- package/dist/lib/view-toggle/view-toggle.component.js.map +1 -0
- package/dist/public-api.d.ts +12 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +12 -0
- package/dist/public-api.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: block;
|
|
3
|
+
/* External consumers using <mj-page-header> outside <mj-page-layout> get a
|
|
4
|
+
24px bottom margin so the header has breathing room from whatever follows.
|
|
5
|
+
This preserves backward compatibility with the published v5.x contract. */
|
|
6
|
+
margin-bottom: var(--mj-space-6);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* When nested inside <mj-page-layout>, the spacing between header and body is
|
|
10
|
+
owned by <mj-page-body>'s padding-top — so the header sits flush against the
|
|
11
|
+
body. This lets pages using <mj-page-body [Padding]="false"> (e.g. AI
|
|
12
|
+
Analytics flush sidebar) render truly flush against the header. */
|
|
13
|
+
:host-context(mj-page-layout) {
|
|
14
|
+
margin-bottom: 0;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Slot-wrapper passthrough — any element a consumer projects with the `meta`,
|
|
18
|
+
`actions`, or `toolbar` attribute (regardless of class name) becomes a
|
|
19
|
+
transparent container so its children become direct flex children of the
|
|
20
|
+
page-header row and inherit the row's gap. Eliminates the per-page
|
|
21
|
+
`.{section}-header-meta { display: contents }` rules that pages had to
|
|
22
|
+
declare in their own CSS files. */
|
|
23
|
+
:host ::ng-deep [meta],
|
|
24
|
+
:host ::ng-deep [actions],
|
|
25
|
+
:host ::ng-deep [toolbar] {
|
|
26
|
+
display: contents;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.mj-page-header {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
background: var(--mj-bg-surface);
|
|
33
|
+
box-shadow: var(--mj-shadow-sm);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.mj-page-header-row {
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
gap: var(--mj-space-3);
|
|
40
|
+
padding: 0 var(--mj-space-6);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.mj-page-header-row--primary {
|
|
44
|
+
justify-content: space-between;
|
|
45
|
+
gap: var(--mj-space-4);
|
|
46
|
+
padding-top: var(--mj-space-4);
|
|
47
|
+
padding-bottom: var(--mj-space-4);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.mj-page-header-row--toolbar {
|
|
51
|
+
flex-wrap: wrap;
|
|
52
|
+
padding-top: 0;
|
|
53
|
+
padding-bottom: var(--mj-space-4);
|
|
54
|
+
border-top: 1px solid var(--mj-border-subtle);
|
|
55
|
+
margin-top: 0;
|
|
56
|
+
padding-top: var(--mj-space-3);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.mj-page-header-row--toolbar:empty {
|
|
60
|
+
display: none;
|
|
61
|
+
border-top: 0;
|
|
62
|
+
padding: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.mj-page-header-titlebar {
|
|
66
|
+
display: flex;
|
|
67
|
+
align-items: center;
|
|
68
|
+
gap: var(--mj-space-3);
|
|
69
|
+
flex: 1 1 auto;
|
|
70
|
+
min-width: 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.mj-page-header-icon {
|
|
74
|
+
flex-shrink: 0;
|
|
75
|
+
width: 40px;
|
|
76
|
+
height: 40px;
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
justify-content: center;
|
|
80
|
+
background: color-mix(in srgb, var(--mj-brand-primary) 12%, transparent);
|
|
81
|
+
color: var(--mj-brand-primary);
|
|
82
|
+
border-radius: var(--mj-radius-md);
|
|
83
|
+
font-size: var(--mj-text-lg);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.mj-page-header-text {
|
|
87
|
+
min-width: 0;
|
|
88
|
+
flex: 1 1 auto;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.mj-page-header-title-row {
|
|
92
|
+
display: flex;
|
|
93
|
+
align-items: center;
|
|
94
|
+
gap: var(--mj-space-3);
|
|
95
|
+
flex-wrap: wrap;
|
|
96
|
+
min-width: 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.mj-page-header-title {
|
|
100
|
+
margin: 0;
|
|
101
|
+
font-size: var(--mj-text-xl);
|
|
102
|
+
font-weight: var(--mj-font-semibold);
|
|
103
|
+
color: var(--mj-text-primary);
|
|
104
|
+
line-height: 1.25;
|
|
105
|
+
white-space: nowrap;
|
|
106
|
+
overflow: hidden;
|
|
107
|
+
text-overflow: ellipsis;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.mj-page-header-subtitle {
|
|
111
|
+
margin: var(--mj-space-1) 0 0;
|
|
112
|
+
font-size: var(--mj-text-sm);
|
|
113
|
+
color: var(--mj-text-secondary);
|
|
114
|
+
line-height: 1.4;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.mj-page-header-meta,
|
|
118
|
+
.mj-page-header-actions {
|
|
119
|
+
display: flex;
|
|
120
|
+
align-items: center;
|
|
121
|
+
gap: var(--mj-space-3);
|
|
122
|
+
flex-shrink: 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.mj-page-header-meta:empty,
|
|
126
|
+
.mj-page-header-actions:empty {
|
|
127
|
+
display: none;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@media (max-width: 768px) {
|
|
131
|
+
.mj-page-header-row--primary {
|
|
132
|
+
flex-direction: column;
|
|
133
|
+
align-items: stretch;
|
|
134
|
+
gap: var(--mj-space-3);
|
|
135
|
+
}
|
|
136
|
+
.mj-page-header-actions {
|
|
137
|
+
justify-content: flex-end;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
/**
|
|
3
|
+
* mj-page-layout — Canonical outer shell for MJ Explorer dashboards/resource pages.
|
|
4
|
+
*
|
|
5
|
+
* Provides the standard flex-column / full-height / page-background container.
|
|
6
|
+
* Place a `<mj-page-header>` and the page body inside.
|
|
7
|
+
*
|
|
8
|
+
* Example:
|
|
9
|
+
* ```html
|
|
10
|
+
* <mj-page-layout>
|
|
11
|
+
* <mj-page-header Title="Agents" Icon="fa-solid fa-robot">...</mj-page-header>
|
|
12
|
+
* <!-- page content -->
|
|
13
|
+
* </mj-page-layout>
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare class MJPageLayoutComponent {
|
|
17
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MJPageLayoutComponent, never>;
|
|
18
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MJPageLayoutComponent, "mj-page-layout", never, {}, {}, never, ["*"], true, never>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=page-layout.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-layout.component.d.ts","sourceRoot":"","sources":["../../../src/lib/page-layout/page-layout.component.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;GAaG;AACH,qBAca,qBAAqB;yCAArB,qBAAqB;2CAArB,qBAAqB;CAAG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Component } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
const _c0 = ["*"];
|
|
4
|
+
/**
|
|
5
|
+
* mj-page-layout — Canonical outer shell for MJ Explorer dashboards/resource pages.
|
|
6
|
+
*
|
|
7
|
+
* Provides the standard flex-column / full-height / page-background container.
|
|
8
|
+
* Place a `<mj-page-header>` and the page body inside.
|
|
9
|
+
*
|
|
10
|
+
* Example:
|
|
11
|
+
* ```html
|
|
12
|
+
* <mj-page-layout>
|
|
13
|
+
* <mj-page-header Title="Agents" Icon="fa-solid fa-robot">...</mj-page-header>
|
|
14
|
+
* <!-- page content -->
|
|
15
|
+
* </mj-page-layout>
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export class MJPageLayoutComponent {
|
|
19
|
+
static ɵfac = function MJPageLayoutComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJPageLayoutComponent)(); };
|
|
20
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJPageLayoutComponent, selectors: [["mj-page-layout"]], ngContentSelectors: _c0, decls: 1, vars: 0, template: function MJPageLayoutComponent_Template(rf, ctx) { if (rf & 1) {
|
|
21
|
+
i0.ɵɵprojectionDef();
|
|
22
|
+
i0.ɵɵprojection(0);
|
|
23
|
+
} }, styles: ["[_nghost-%COMP%] {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-page);\n overflow: hidden;\n }"] });
|
|
24
|
+
}
|
|
25
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJPageLayoutComponent, [{
|
|
26
|
+
type: Component,
|
|
27
|
+
args: [{ selector: 'mj-page-layout', standalone: true, template: `<ng-content></ng-content>`, styles: ["\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-page);\n overflow: hidden;\n }\n "] }]
|
|
28
|
+
}], null, null); })();
|
|
29
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJPageLayoutComponent, { className: "MJPageLayoutComponent", filePath: "lib/page-layout/page-layout.component.ts", lineNumber: 31 }); })();
|
|
30
|
+
//# sourceMappingURL=page-layout.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-layout.component.js","sourceRoot":"","sources":["../../../src/lib/page-layout/page-layout.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;;;AAE1C;;;;;;;;;;;;;GAaG;AAeH,MAAM,OAAO,qBAAqB;+GAArB,qBAAqB;6DAArB,qBAAqB;;YAXrB,kBAAyB;;;iFAWzB,qBAAqB;cAdjC,SAAS;2BACE,gBAAgB,cACd,IAAI,YACN,2BAA2B;;kFAW1B,qBAAqB","sourcesContent":["import { Component } from '@angular/core';\n\n/**\n * mj-page-layout — Canonical outer shell for MJ Explorer dashboards/resource pages.\n *\n * Provides the standard flex-column / full-height / page-background container.\n * Place a `<mj-page-header>` and the page body inside.\n *\n * Example:\n * ```html\n * <mj-page-layout>\n * <mj-page-header Title=\"Agents\" Icon=\"fa-solid fa-robot\">...</mj-page-header>\n * <!-- page content -->\n * </mj-page-layout>\n * ```\n */\n@Component({\n selector: 'mj-page-layout',\n standalone: true,\n template: `<ng-content></ng-content>`,\n styles: [`\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--mj-bg-page);\n overflow: hidden;\n }\n `]\n})\nexport class MJPageLayoutComponent {}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { EventEmitter } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* mj-page-search — Canonical in-page search input for dashboard headers and toolbars.
|
|
5
|
+
* Replaces per-page `.search-input-wrapper` rules so styling can't drift.
|
|
6
|
+
*
|
|
7
|
+
* Distinct from `mj-search-input` (the navbar/global search in `@memberjunction/ng-search`)
|
|
8
|
+
* — this one is a simple text input used for filtering page content.
|
|
9
|
+
*
|
|
10
|
+
* Example:
|
|
11
|
+
* ```html
|
|
12
|
+
* <mj-page-search
|
|
13
|
+
* Placeholder="Search templates..."
|
|
14
|
+
* [Value]="searchTerm"
|
|
15
|
+
* (ValueChange)="onSearch($event)">
|
|
16
|
+
* </mj-page-search>
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare class MJPageSearchComponent {
|
|
20
|
+
Placeholder: string;
|
|
21
|
+
Value: string;
|
|
22
|
+
Icon: string;
|
|
23
|
+
ValueChange: EventEmitter<string>;
|
|
24
|
+
focused: boolean;
|
|
25
|
+
onInput(event: Event): void;
|
|
26
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MJPageSearchComponent, never>;
|
|
27
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MJPageSearchComponent, "mj-page-search", never, { "Placeholder": { "alias": "Placeholder"; "required": false; }; "Value": { "alias": "Value"; "required": false; }; "Icon": { "alias": "Icon"; "required": false; }; }, { "ValueChange": "ValueChange"; }, never, never, true, never>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=page-search.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-search.component.d.ts","sourceRoot":"","sources":["../../../src/lib/page-search/page-search.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;;AAEvE;;;;;;;;;;;;;;;GAeG;AACH,qBA0Ea,qBAAqB;IACvB,WAAW,EAAE,MAAM,CAAe;IAClC,KAAK,EAAE,MAAM,CAAM;IACnB,IAAI,EAAE,MAAM,CAAwB;IACnC,WAAW,uBAA8B;IAE5C,OAAO,EAAE,OAAO,CAAS;IAEzB,OAAO,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;yCARvB,qBAAqB;2CAArB,qBAAqB;CAajC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* mj-page-search — Canonical in-page search input for dashboard headers and toolbars.
|
|
5
|
+
* Replaces per-page `.search-input-wrapper` rules so styling can't drift.
|
|
6
|
+
*
|
|
7
|
+
* Distinct from `mj-search-input` (the navbar/global search in `@memberjunction/ng-search`)
|
|
8
|
+
* — this one is a simple text input used for filtering page content.
|
|
9
|
+
*
|
|
10
|
+
* Example:
|
|
11
|
+
* ```html
|
|
12
|
+
* <mj-page-search
|
|
13
|
+
* Placeholder="Search templates..."
|
|
14
|
+
* [Value]="searchTerm"
|
|
15
|
+
* (ValueChange)="onSearch($event)">
|
|
16
|
+
* </mj-page-search>
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export class MJPageSearchComponent {
|
|
20
|
+
Placeholder = 'Search...';
|
|
21
|
+
Value = '';
|
|
22
|
+
Icon = 'fa-solid fa-search';
|
|
23
|
+
ValueChange = new EventEmitter();
|
|
24
|
+
focused = false;
|
|
25
|
+
onInput(event) {
|
|
26
|
+
const v = event.target.value;
|
|
27
|
+
this.Value = v;
|
|
28
|
+
this.ValueChange.emit(v);
|
|
29
|
+
}
|
|
30
|
+
static ɵfac = function MJPageSearchComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJPageSearchComponent)(); };
|
|
31
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJPageSearchComponent, selectors: [["mj-page-search"]], inputs: { Placeholder: "Placeholder", Value: "Value", Icon: "Icon" }, outputs: { ValueChange: "ValueChange" }, decls: 3, vars: 6, consts: [[1, "mj-page-search"], ["type", "text", 3, "input", "focus", "blur", "placeholder", "value"]], template: function MJPageSearchComponent_Template(rf, ctx) { if (rf & 1) {
|
|
32
|
+
i0.ɵɵdomElementStart(0, "div", 0);
|
|
33
|
+
i0.ɵɵdomElement(1, "i");
|
|
34
|
+
i0.ɵɵdomElementStart(2, "input", 1);
|
|
35
|
+
i0.ɵɵdomListener("input", function MJPageSearchComponent_Template_input_input_2_listener($event) { return ctx.onInput($event); })("focus", function MJPageSearchComponent_Template_input_focus_2_listener() { return ctx.focused = true; })("blur", function MJPageSearchComponent_Template_input_blur_2_listener() { return ctx.focused = false; });
|
|
36
|
+
i0.ɵɵdomElementEnd()();
|
|
37
|
+
} if (rf & 2) {
|
|
38
|
+
i0.ɵɵclassProp("mj-page-search--focused", ctx.focused);
|
|
39
|
+
i0.ɵɵadvance();
|
|
40
|
+
i0.ɵɵclassMap(ctx.Icon);
|
|
41
|
+
i0.ɵɵadvance();
|
|
42
|
+
i0.ɵɵdomProperty("placeholder", ctx.Placeholder)("value", ctx.Value);
|
|
43
|
+
} }, styles: ["[_nghost-%COMP%] {\n display: inline-flex;\n min-width: 220px;\n }\n\n \n\n\n\n\n\n .mj-page-search[_ngcontent-%COMP%] {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n width: 100%;\n padding: var(--mj-space-1) var(--mj-space-3);\n font-family: var(--mj-font-family);\n font-size: var(--mj-text-sm);\n line-height: 1.5;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n transition: var(--mj-transition-colors), box-shadow var(--mj-transition-base);\n min-height: 32px;\n box-sizing: border-box;\n }\n\n .mj-page-search[_ngcontent-%COMP%]:hover {\n border-color: var(--mj-border-strong);\n }\n\n .mj-page-search--focused[_ngcontent-%COMP%] {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-focus-ring);\n }\n\n .mj-page-search[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-size: 13px;\n flex-shrink: 0;\n }\n\n .mj-page-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%] {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n font: inherit;\n color: var(--mj-text-primary);\n min-width: 0;\n }\n\n .mj-page-search[_ngcontent-%COMP%] input[_ngcontent-%COMP%]::placeholder {\n color: var(--mj-text-disabled);\n }"] });
|
|
44
|
+
}
|
|
45
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJPageSearchComponent, [{
|
|
46
|
+
type: Component,
|
|
47
|
+
args: [{ selector: 'mj-page-search', standalone: true, template: `
|
|
48
|
+
<div class="mj-page-search" [class.mj-page-search--focused]="focused">
|
|
49
|
+
<i [class]="Icon"></i>
|
|
50
|
+
<input
|
|
51
|
+
type="text"
|
|
52
|
+
[placeholder]="Placeholder"
|
|
53
|
+
[value]="Value"
|
|
54
|
+
(input)="onInput($event)"
|
|
55
|
+
(focus)="focused = true"
|
|
56
|
+
(blur)="focused = false" />
|
|
57
|
+
</div>
|
|
58
|
+
`, styles: ["\n :host {\n display: inline-flex;\n min-width: 220px;\n }\n\n /* Compact toolbar density (32px) to match mjButton size=\"sm\" and other\n header widgets. White background + border-default for visual differentiation\n on both the page-header (white) and body (sunken) surfaces.\n Note: this is intentionally tighter than .mj-input (38px) because\n mj-page-search is a toolbar widget, not a form field. */\n .mj-page-search {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n width: 100%;\n padding: var(--mj-space-1) var(--mj-space-3);\n font-family: var(--mj-font-family);\n font-size: var(--mj-text-sm);\n line-height: 1.5;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n transition: var(--mj-transition-colors), box-shadow var(--mj-transition-base);\n min-height: 32px;\n box-sizing: border-box;\n }\n\n .mj-page-search:hover {\n border-color: var(--mj-border-strong);\n }\n\n .mj-page-search--focused {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-focus-ring);\n }\n\n .mj-page-search i {\n color: var(--mj-text-muted);\n font-size: 13px;\n flex-shrink: 0;\n }\n\n .mj-page-search input {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n font: inherit;\n color: var(--mj-text-primary);\n min-width: 0;\n }\n\n .mj-page-search input::placeholder {\n color: var(--mj-text-disabled);\n }\n "] }]
|
|
59
|
+
}], null, { Placeholder: [{
|
|
60
|
+
type: Input
|
|
61
|
+
}], Value: [{
|
|
62
|
+
type: Input
|
|
63
|
+
}], Icon: [{
|
|
64
|
+
type: Input
|
|
65
|
+
}], ValueChange: [{
|
|
66
|
+
type: Output
|
|
67
|
+
}] }); })();
|
|
68
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJPageSearchComponent, { className: "MJPageSearchComponent", filePath: "lib/page-search/page-search.component.ts", lineNumber: 93 }); })();
|
|
69
|
+
//# sourceMappingURL=page-search.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-search.component.js","sourceRoot":"","sources":["../../../src/lib/page-search/page-search.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;AAEvE;;;;;;;;;;;;;;;GAeG;AA2EH,MAAM,OAAO,qBAAqB;IACvB,WAAW,GAAW,WAAW,CAAC;IAClC,KAAK,GAAW,EAAE,CAAC;IACnB,IAAI,GAAW,oBAAoB,CAAC;IACnC,WAAW,GAAG,IAAI,YAAY,EAAU,CAAC;IAE5C,OAAO,GAAY,KAAK,CAAC;IAEzB,OAAO,CAAC,KAAY;QACzB,MAAM,CAAC,GAAI,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;QACnD,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACf,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;+GAZU,qBAAqB;6DAArB,qBAAqB;YAtE9B,iCAAsE;YACpE,uBAAsB;YACtB,mCAM6B;YAA3B,AADA,AADA,0GAAS,mBAAe,IAAC,kGACN,IAAI,IAAC,gGACN,KAAK,IAAC;YAC5B,AAPE,oBAM6B,EACzB;;YATsB,sDAAyC;YAChE,cAAc;YAAd,uBAAc;YAGf,cAA2B;YAC3B,AADA,gDAA2B,oBACZ;;;iFAiEV,qBAAqB;cA1EjC,SAAS;2BACE,gBAAgB,cACd,IAAI,YACN;;;;;;;;;;;GAWT;;kBA6DA,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,MAAM;;kFAJI,qBAAqB","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\n\n/**\n * mj-page-search — Canonical in-page search input for dashboard headers and toolbars.\n * Replaces per-page `.search-input-wrapper` rules so styling can't drift.\n *\n * Distinct from `mj-search-input` (the navbar/global search in `@memberjunction/ng-search`)\n * — this one is a simple text input used for filtering page content.\n *\n * Example:\n * ```html\n * <mj-page-search\n * Placeholder=\"Search templates...\"\n * [Value]=\"searchTerm\"\n * (ValueChange)=\"onSearch($event)\">\n * </mj-page-search>\n * ```\n */\n@Component({\n selector: 'mj-page-search',\n standalone: true,\n template: `\n <div class=\"mj-page-search\" [class.mj-page-search--focused]=\"focused\">\n <i [class]=\"Icon\"></i>\n <input\n type=\"text\"\n [placeholder]=\"Placeholder\"\n [value]=\"Value\"\n (input)=\"onInput($event)\"\n (focus)=\"focused = true\"\n (blur)=\"focused = false\" />\n </div>\n `,\n styles: [`\n :host {\n display: inline-flex;\n min-width: 220px;\n }\n\n /* Compact toolbar density (32px) to match mjButton size=\"sm\" and other\n header widgets. White background + border-default for visual differentiation\n on both the page-header (white) and body (sunken) surfaces.\n Note: this is intentionally tighter than .mj-input (38px) because\n mj-page-search is a toolbar widget, not a form field. */\n .mj-page-search {\n display: flex;\n align-items: center;\n gap: var(--mj-space-2);\n width: 100%;\n padding: var(--mj-space-1) var(--mj-space-3);\n font-family: var(--mj-font-family);\n font-size: var(--mj-text-sm);\n line-height: 1.5;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-sm);\n transition: var(--mj-transition-colors), box-shadow var(--mj-transition-base);\n min-height: 32px;\n box-sizing: border-box;\n }\n\n .mj-page-search:hover {\n border-color: var(--mj-border-strong);\n }\n\n .mj-page-search--focused {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-focus-ring);\n }\n\n .mj-page-search i {\n color: var(--mj-text-muted);\n font-size: 13px;\n flex-shrink: 0;\n }\n\n .mj-page-search input {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n font: inherit;\n color: var(--mj-text-primary);\n min-width: 0;\n }\n\n .mj-page-search input::placeholder {\n color: var(--mj-text-disabled);\n }\n `]\n})\nexport class MJPageSearchComponent {\n @Input() Placeholder: string = 'Search...';\n @Input() Value: string = '';\n @Input() Icon: string = 'fa-solid fa-search';\n @Output() ValueChange = new EventEmitter<string>();\n\n public focused: boolean = false;\n\n public onInput(event: Event): void {\n const v = (event.target as HTMLInputElement).value;\n this.Value = v;\n this.ValueChange.emit(v);\n }\n}\n"]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { EventEmitter } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* mj-refresh-button — Canonical Refresh button for the `[actions]` slot of
|
|
5
|
+
* `<mj-page-header>`. Encapsulates the icon + spin-on-loading behavior so
|
|
6
|
+
* pages don't reinvent it every time.
|
|
7
|
+
*
|
|
8
|
+
* Replaces the repeated:
|
|
9
|
+
* ```html
|
|
10
|
+
* <button mjButton variant="secondary" size="sm" (click)="LoadData()" [disabled]="IsLoading" title="Refresh">
|
|
11
|
+
* <i class="fa-solid fa-arrows-rotate" [class.fa-spin]="IsLoading"></i> Refresh
|
|
12
|
+
* </button>
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* ```html
|
|
17
|
+
* <mj-refresh-button [Loading]="IsLoading" (Clicked)="LoadData()" />
|
|
18
|
+
*
|
|
19
|
+
* <mj-refresh-button [Loading]="IsLoading" (Clicked)="Refresh()" [ShowLabel]="false" /> <!-- icon-only -->
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* The `Loading` input drives both the spinner AND the disabled state — pass
|
|
23
|
+
* the page's `IsLoading` flag and you're done.
|
|
24
|
+
*/
|
|
25
|
+
export declare class MJRefreshButtonComponent {
|
|
26
|
+
/** When true, the icon spins and the button is disabled. Pass `IsLoading` from the page. */
|
|
27
|
+
Loading: boolean;
|
|
28
|
+
/** Force-disable independently of `Loading`. */
|
|
29
|
+
Disabled: boolean;
|
|
30
|
+
/** Visible button text. Defaults to "Refresh". Use `[ShowLabel]="false"` for icon-only. */
|
|
31
|
+
Label: string;
|
|
32
|
+
/** Hover/aria tooltip. Defaults to "Refresh". */
|
|
33
|
+
Title: string;
|
|
34
|
+
/** Show the text label next to the icon. Defaults to true. */
|
|
35
|
+
ShowLabel: boolean;
|
|
36
|
+
/** Button variant passed to mjButton. Defaults to 'secondary'. */
|
|
37
|
+
Variant: 'primary' | 'secondary' | 'outline' | 'flat' | 'icon';
|
|
38
|
+
/** Button size passed to mjButton. Defaults to 'sm' to match page-header density. */
|
|
39
|
+
Size: 'sm' | 'md' | 'lg';
|
|
40
|
+
/** Emitted when the button is clicked AND the button isn't disabled/loading. */
|
|
41
|
+
Clicked: EventEmitter<MouseEvent>;
|
|
42
|
+
OnClick(event: MouseEvent): void;
|
|
43
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MJRefreshButtonComponent, never>;
|
|
44
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MJRefreshButtonComponent, "mj-refresh-button", never, { "Loading": { "alias": "Loading"; "required": false; }; "Disabled": { "alias": "Disabled"; "required": false; }; "Label": { "alias": "Label"; "required": false; }; "Title": { "alias": "Title"; "required": false; }; "ShowLabel": { "alias": "ShowLabel"; "required": false; }; "Variant": { "alias": "Variant"; "required": false; }; "Size": { "alias": "Size"; "required": false; }; }, { "Clicked": "Clicked"; }, never, never, true, never>;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=refresh-button.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-button.component.d.ts","sourceRoot":"","sources":["../../../src/lib/refresh-button/refresh-button.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;;AAGvE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAwBa,wBAAwB;IACnC,4FAA4F;IACnF,OAAO,EAAE,OAAO,CAAS;IAElC,gDAAgD;IACvC,QAAQ,EAAE,OAAO,CAAS;IAEnC,2FAA2F;IAClF,KAAK,EAAE,MAAM,CAAa;IAEnC,iDAAiD;IACxC,KAAK,EAAE,MAAM,CAAa;IAEnC,8DAA8D;IACrD,SAAS,EAAE,OAAO,CAAQ;IAEnC,kEAAkE;IACzD,OAAO,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,CAAe;IAEtF,qFAAqF;IAC5E,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAQ;IAEzC,gFAAgF;IACtE,OAAO,2BAAkC;IAEnD,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;yCAzBrB,wBAAwB;2CAAxB,wBAAwB;CA6BpC"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
|
2
|
+
import { MJButtonDirective } from '../button/button.directive';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
function MJRefreshButtonComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
5
|
+
i0.ɵɵtext(0);
|
|
6
|
+
} if (rf & 2) {
|
|
7
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
8
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r0.Label, " ");
|
|
9
|
+
} }
|
|
10
|
+
/**
|
|
11
|
+
* mj-refresh-button — Canonical Refresh button for the `[actions]` slot of
|
|
12
|
+
* `<mj-page-header>`. Encapsulates the icon + spin-on-loading behavior so
|
|
13
|
+
* pages don't reinvent it every time.
|
|
14
|
+
*
|
|
15
|
+
* Replaces the repeated:
|
|
16
|
+
* ```html
|
|
17
|
+
* <button mjButton variant="secondary" size="sm" (click)="LoadData()" [disabled]="IsLoading" title="Refresh">
|
|
18
|
+
* <i class="fa-solid fa-arrows-rotate" [class.fa-spin]="IsLoading"></i> Refresh
|
|
19
|
+
* </button>
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* ```html
|
|
24
|
+
* <mj-refresh-button [Loading]="IsLoading" (Clicked)="LoadData()" />
|
|
25
|
+
*
|
|
26
|
+
* <mj-refresh-button [Loading]="IsLoading" (Clicked)="Refresh()" [ShowLabel]="false" /> <!-- icon-only -->
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* The `Loading` input drives both the spinner AND the disabled state — pass
|
|
30
|
+
* the page's `IsLoading` flag and you're done.
|
|
31
|
+
*/
|
|
32
|
+
export class MJRefreshButtonComponent {
|
|
33
|
+
/** When true, the icon spins and the button is disabled. Pass `IsLoading` from the page. */
|
|
34
|
+
Loading = false;
|
|
35
|
+
/** Force-disable independently of `Loading`. */
|
|
36
|
+
Disabled = false;
|
|
37
|
+
/** Visible button text. Defaults to "Refresh". Use `[ShowLabel]="false"` for icon-only. */
|
|
38
|
+
Label = 'Refresh';
|
|
39
|
+
/** Hover/aria tooltip. Defaults to "Refresh". */
|
|
40
|
+
Title = 'Refresh';
|
|
41
|
+
/** Show the text label next to the icon. Defaults to true. */
|
|
42
|
+
ShowLabel = true;
|
|
43
|
+
/** Button variant passed to mjButton. Defaults to 'secondary'. */
|
|
44
|
+
Variant = 'secondary';
|
|
45
|
+
/** Button size passed to mjButton. Defaults to 'sm' to match page-header density. */
|
|
46
|
+
Size = 'sm';
|
|
47
|
+
/** Emitted when the button is clicked AND the button isn't disabled/loading. */
|
|
48
|
+
Clicked = new EventEmitter();
|
|
49
|
+
OnClick(event) {
|
|
50
|
+
if (this.Disabled || this.Loading)
|
|
51
|
+
return;
|
|
52
|
+
this.Clicked.emit(event);
|
|
53
|
+
}
|
|
54
|
+
static ɵfac = function MJRefreshButtonComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJRefreshButtonComponent)(); };
|
|
55
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJRefreshButtonComponent, selectors: [["mj-refresh-button"]], inputs: { Loading: "Loading", Disabled: "Disabled", Label: "Label", Title: "Title", ShowLabel: "ShowLabel", Variant: "Variant", Size: "Size" }, outputs: { Clicked: "Clicked" }, decls: 3, vars: 8, consts: [["type", "button", "mjButton", "", 3, "click", "variant", "size", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-arrows-rotate"]], template: function MJRefreshButtonComponent_Template(rf, ctx) { if (rf & 1) {
|
|
56
|
+
i0.ɵɵelementStart(0, "button", 0);
|
|
57
|
+
i0.ɵɵlistener("click", function MJRefreshButtonComponent_Template_button_click_0_listener($event) { return ctx.OnClick($event); });
|
|
58
|
+
i0.ɵɵelement(1, "i", 1);
|
|
59
|
+
i0.ɵɵconditionalCreate(2, MJRefreshButtonComponent_Conditional_2_Template, 1, 1);
|
|
60
|
+
i0.ɵɵelementEnd();
|
|
61
|
+
} if (rf & 2) {
|
|
62
|
+
i0.ɵɵproperty("variant", ctx.Variant)("size", ctx.Size)("disabled", ctx.Disabled || ctx.Loading);
|
|
63
|
+
i0.ɵɵattribute("title", ctx.Title)("aria-label", !ctx.ShowLabel ? ctx.Title : null);
|
|
64
|
+
i0.ɵɵadvance();
|
|
65
|
+
i0.ɵɵclassProp("fa-spin", ctx.Loading);
|
|
66
|
+
i0.ɵɵadvance();
|
|
67
|
+
i0.ɵɵconditional(ctx.ShowLabel ? 2 : -1);
|
|
68
|
+
} }, dependencies: [MJButtonDirective], styles: ["[_nghost-%COMP%] { display: inline-flex; }"] });
|
|
69
|
+
}
|
|
70
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJRefreshButtonComponent, [{
|
|
71
|
+
type: Component,
|
|
72
|
+
args: [{ selector: 'mj-refresh-button', standalone: true, imports: [MJButtonDirective], template: `
|
|
73
|
+
<button
|
|
74
|
+
type="button"
|
|
75
|
+
mjButton
|
|
76
|
+
[variant]="Variant"
|
|
77
|
+
[size]="Size"
|
|
78
|
+
[disabled]="Disabled || Loading"
|
|
79
|
+
[attr.title]="Title"
|
|
80
|
+
[attr.aria-label]="!ShowLabel ? Title : null"
|
|
81
|
+
(click)="OnClick($event)">
|
|
82
|
+
<i class="fa-solid fa-arrows-rotate" [class.fa-spin]="Loading" aria-hidden="true"></i>
|
|
83
|
+
@if (ShowLabel) {
|
|
84
|
+
{{ Label }}
|
|
85
|
+
}
|
|
86
|
+
</button>
|
|
87
|
+
`, styles: ["\n :host { display: inline-flex; }\n "] }]
|
|
88
|
+
}], null, { Loading: [{
|
|
89
|
+
type: Input
|
|
90
|
+
}], Disabled: [{
|
|
91
|
+
type: Input
|
|
92
|
+
}], Label: [{
|
|
93
|
+
type: Input
|
|
94
|
+
}], Title: [{
|
|
95
|
+
type: Input
|
|
96
|
+
}], ShowLabel: [{
|
|
97
|
+
type: Input
|
|
98
|
+
}], Variant: [{
|
|
99
|
+
type: Input
|
|
100
|
+
}], Size: [{
|
|
101
|
+
type: Input
|
|
102
|
+
}], Clicked: [{
|
|
103
|
+
type: Output
|
|
104
|
+
}] }); })();
|
|
105
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJRefreshButtonComponent, { className: "MJRefreshButtonComponent", filePath: "lib/refresh-button/refresh-button.component.ts", lineNumber: 50 }); })();
|
|
106
|
+
//# sourceMappingURL=refresh-button.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refresh-button.component.js","sourceRoot":"","sources":["../../../src/lib/refresh-button/refresh-button.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;;;IAwCvD,YACF;;;IADE,6CACF;;AAvCN;;;;;;;;;;;;;;;;;;;;;GAqBG;AAyBH,MAAM,OAAO,wBAAwB;IACnC,4FAA4F;IACnF,OAAO,GAAY,KAAK,CAAC;IAElC,gDAAgD;IACvC,QAAQ,GAAY,KAAK,CAAC;IAEnC,2FAA2F;IAClF,KAAK,GAAW,SAAS,CAAC;IAEnC,iDAAiD;IACxC,KAAK,GAAW,SAAS,CAAC;IAEnC,8DAA8D;IACrD,SAAS,GAAY,IAAI,CAAC;IAEnC,kEAAkE;IACzD,OAAO,GAA0D,WAAW,CAAC;IAEtF,qFAAqF;IAC5E,IAAI,GAAuB,IAAI,CAAC;IAEzC,gFAAgF;IACtE,OAAO,GAAG,IAAI,YAAY,EAAc,CAAC;IAEnD,OAAO,CAAC,KAAiB;QACvB,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;kHA5BU,wBAAwB;6DAAxB,wBAAwB;YAnBjC,iCAQ4B;YAA1B,2GAAS,mBAAe,IAAC;YACzB,uBAAsF;YACtF,gFAAiB;YAGnB,iBAAS;;YARP,AADA,AADA,qCAAmB,kBACN,yCACmB;;YAIK,cAAyB;YAAzB,sCAAyB;YAC9D,cAEC;YAFD,wCAEC;4BAdK,iBAAiB;;iFAqBhB,wBAAwB;cAxBpC,SAAS;2BACE,mBAAmB,cACjB,IAAI,WACP,CAAC,iBAAiB,CAAC,YAClB;;;;;;;;;;;;;;;GAeT;;kBAOA,KAAK;;kBAGL,KAAK;;kBAGL,KAAK;;kBAGL,KAAK;;kBAGL,KAAK;;kBAGL,KAAK;;kBAGL,KAAK;;kBAGL,MAAM;;kFAvBI,wBAAwB","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { MJButtonDirective } from '../button/button.directive';\n\n/**\n * mj-refresh-button — Canonical Refresh button for the `[actions]` slot of\n * `<mj-page-header>`. Encapsulates the icon + spin-on-loading behavior so\n * pages don't reinvent it every time.\n *\n * Replaces the repeated:\n * ```html\n * <button mjButton variant=\"secondary\" size=\"sm\" (click)=\"LoadData()\" [disabled]=\"IsLoading\" title=\"Refresh\">\n * <i class=\"fa-solid fa-arrows-rotate\" [class.fa-spin]=\"IsLoading\"></i> Refresh\n * </button>\n * ```\n *\n * Usage:\n * ```html\n * <mj-refresh-button [Loading]=\"IsLoading\" (Clicked)=\"LoadData()\" />\n *\n * <mj-refresh-button [Loading]=\"IsLoading\" (Clicked)=\"Refresh()\" [ShowLabel]=\"false\" /> <!-- icon-only -->\n * ```\n *\n * The `Loading` input drives both the spinner AND the disabled state — pass\n * the page's `IsLoading` flag and you're done.\n */\n@Component({\n selector: 'mj-refresh-button',\n standalone: true,\n imports: [MJButtonDirective],\n template: `\n <button\n type=\"button\"\n mjButton\n [variant]=\"Variant\"\n [size]=\"Size\"\n [disabled]=\"Disabled || Loading\"\n [attr.title]=\"Title\"\n [attr.aria-label]=\"!ShowLabel ? Title : null\"\n (click)=\"OnClick($event)\">\n <i class=\"fa-solid fa-arrows-rotate\" [class.fa-spin]=\"Loading\" aria-hidden=\"true\"></i>\n @if (ShowLabel) {\n {{ Label }}\n }\n </button>\n `,\n styles: [`\n :host { display: inline-flex; }\n `]\n})\nexport class MJRefreshButtonComponent {\n /** When true, the icon spins and the button is disabled. Pass `IsLoading` from the page. */\n @Input() Loading: boolean = false;\n\n /** Force-disable independently of `Loading`. */\n @Input() Disabled: boolean = false;\n\n /** Visible button text. Defaults to \"Refresh\". Use `[ShowLabel]=\"false\"` for icon-only. */\n @Input() Label: string = 'Refresh';\n\n /** Hover/aria tooltip. Defaults to \"Refresh\". */\n @Input() Title: string = 'Refresh';\n\n /** Show the text label next to the icon. Defaults to true. */\n @Input() ShowLabel: boolean = true;\n\n /** Button variant passed to mjButton. Defaults to 'secondary'. */\n @Input() Variant: 'primary' | 'secondary' | 'outline' | 'flat' | 'icon' = 'secondary';\n\n /** Button size passed to mjButton. Defaults to 'sm' to match page-header density. */\n @Input() Size: 'sm' | 'md' | 'lg' = 'sm';\n\n /** Emitted when the button is clicked AND the button isn't disabled/loading. */\n @Output() Clicked = new EventEmitter<MouseEvent>();\n\n OnClick(event: MouseEvent): void {\n if (this.Disabled || this.Loading) return;\n this.Clicked.emit(event);\n }\n}\n"]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
/** Visual variant for `<mj-stat-badge>`. */
|
|
3
|
+
export type MJStatBadgeVariant = 'default' | 'success' | 'error' | 'warning' | 'running' | 'info';
|
|
4
|
+
/**
|
|
5
|
+
* mj-stat-badge — Small read-only pill for the `[meta]` slot of
|
|
6
|
+
* `<mj-page-header>`. Used to surface counts, status pills, and other
|
|
7
|
+
* informational chips next to the page title.
|
|
8
|
+
*
|
|
9
|
+
* Replaces the per-section `.{section}-stat-badge` / `.X-header-meta-badge`
|
|
10
|
+
* CSS that pages were duplicating after the chrome migration.
|
|
11
|
+
*
|
|
12
|
+
* Examples:
|
|
13
|
+
* ```html
|
|
14
|
+
* <mj-stat-badge [Count]="42" Label="integrations" />
|
|
15
|
+
*
|
|
16
|
+
* <mj-stat-badge [Count]="failedRuns" Label="failed" Variant="error" />
|
|
17
|
+
*
|
|
18
|
+
* <mj-stat-badge Icon="fa-solid fa-spinner fa-spin" Label="running" Variant="running" />
|
|
19
|
+
*
|
|
20
|
+
* <!-- Result-count style: render "X of Y label" when Total is set -->
|
|
21
|
+
* <mj-stat-badge [Count]="filteredCount" [Total]="totalCount" Label="agents" />
|
|
22
|
+
*
|
|
23
|
+
* <mj-stat-badge Variant="success">All clear</mj-stat-badge> <!-- arbitrary projected content -->
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Note: this component absorbed the former `mj-result-count` (deleted in the
|
|
27
|
+
* organizational refactor). When `Total` is set, the badge renders the
|
|
28
|
+
* "X of Y label" pattern; otherwise it renders "X label" — same shape, same
|
|
29
|
+
* styling, one component.
|
|
30
|
+
*/
|
|
31
|
+
export declare class MJStatBadgeComponent {
|
|
32
|
+
/** Numeric or text value rendered as `<strong>`. Omit if using `Label` only. */
|
|
33
|
+
Count: number | string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Optional total when the badge represents a filtered subset (e.g. "12 of 50 prompts").
|
|
36
|
+
* When set together with `Count`, the badge renders "{Count} of {Total} {Label}".
|
|
37
|
+
* Replaces the old `mj-result-count` component.
|
|
38
|
+
*/
|
|
39
|
+
Total: number | string | null;
|
|
40
|
+
/** Descriptive text after the count (e.g. "integrations", "failed"). */
|
|
41
|
+
Label: string;
|
|
42
|
+
/** Optional Font Awesome icon prefixed before the count/label. */
|
|
43
|
+
Icon: string;
|
|
44
|
+
/** Color treatment. Defaults to neutral surface-card. */
|
|
45
|
+
Variant: MJStatBadgeVariant;
|
|
46
|
+
get IsSuccess(): boolean;
|
|
47
|
+
get IsError(): boolean;
|
|
48
|
+
get IsWarning(): boolean;
|
|
49
|
+
get IsRunning(): boolean;
|
|
50
|
+
get IsInfo(): boolean;
|
|
51
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MJStatBadgeComponent, never>;
|
|
52
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MJStatBadgeComponent, "mj-stat-badge", never, { "Count": { "alias": "Count"; "required": false; }; "Total": { "alias": "Total"; "required": false; }; "Label": { "alias": "Label"; "required": false; }; "Icon": { "alias": "Icon"; "required": false; }; "Variant": { "alias": "Variant"; "required": false; }; }, {}, never, ["*"], true, never>;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=stat-badge.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stat-badge.component.d.ts","sourceRoot":"","sources":["../../../src/lib/stat-badge/stat-badge.component.ts"],"names":[],"mappings":";AAEA,4CAA4C;AAC5C,MAAM,MAAM,kBAAkB,GAC1B,SAAS,GACT,SAAS,GACT,OAAO,GACP,SAAS,GACT,SAAS,GACT,MAAM,CAAC;AAEX;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAkFa,oBAAoB;IAC/B,gFAAgF;IACvE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAQ;IAE9C;;;;OAIG;IACM,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAQ;IAE9C,wEAAwE;IAC/D,KAAK,EAAE,MAAM,CAAM;IAE5B,kEAAkE;IACzD,IAAI,EAAE,MAAM,CAAM;IAE3B,yDAAyD;IAChD,OAAO,EAAE,kBAAkB,CAAa;IAEjD,IACI,SAAS,IAAI,OAAO,CAAuC;IAE/D,IACI,OAAO,IAAI,OAAO,CAAqC;IAE3D,IACI,SAAS,IAAI,OAAO,CAAuC;IAE/D,IACI,SAAS,IAAI,OAAO,CAAuC;IAE/D,IACI,MAAM,IAAI,OAAO,CAAoC;yCAjC9C,oBAAoB;2CAApB,oBAAoB;CAkChC"}
|