@memberjunction/ng-ui-components 5.34.1 → 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,162 @@
|
|
|
1
|
+
import { Component, HostBinding, Input } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
const _c0 = ["*"];
|
|
4
|
+
function MJStatBadgeComponent_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
5
|
+
i0.ɵɵdomElement(0, "i", 2);
|
|
6
|
+
} if (rf & 2) {
|
|
7
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
8
|
+
i0.ɵɵclassMap(ctx_r0.Icon);
|
|
9
|
+
} }
|
|
10
|
+
function MJStatBadgeComponent_Conditional_1_Conditional_0_Template(rf, ctx) { if (rf & 1) {
|
|
11
|
+
i0.ɵɵdomElementStart(0, "strong");
|
|
12
|
+
i0.ɵɵtext(1);
|
|
13
|
+
i0.ɵɵdomElementEnd();
|
|
14
|
+
i0.ɵɵdomElementStart(2, "span", 3);
|
|
15
|
+
i0.ɵɵtext(3, "of");
|
|
16
|
+
i0.ɵɵdomElementEnd();
|
|
17
|
+
i0.ɵɵdomElementStart(4, "strong");
|
|
18
|
+
i0.ɵɵtext(5);
|
|
19
|
+
i0.ɵɵdomElementEnd();
|
|
20
|
+
} if (rf & 2) {
|
|
21
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
22
|
+
i0.ɵɵadvance();
|
|
23
|
+
i0.ɵɵtextInterpolate(ctx_r0.Count);
|
|
24
|
+
i0.ɵɵadvance(4);
|
|
25
|
+
i0.ɵɵtextInterpolate(ctx_r0.Total);
|
|
26
|
+
} }
|
|
27
|
+
function MJStatBadgeComponent_Conditional_1_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
28
|
+
i0.ɵɵdomElementStart(0, "strong");
|
|
29
|
+
i0.ɵɵtext(1);
|
|
30
|
+
i0.ɵɵdomElementEnd();
|
|
31
|
+
} if (rf & 2) {
|
|
32
|
+
const ctx_r0 = i0.ɵɵnextContext(2);
|
|
33
|
+
i0.ɵɵadvance();
|
|
34
|
+
i0.ɵɵtextInterpolate(ctx_r0.Count);
|
|
35
|
+
} }
|
|
36
|
+
function MJStatBadgeComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
37
|
+
i0.ɵɵconditionalCreate(0, MJStatBadgeComponent_Conditional_1_Conditional_0_Template, 6, 2)(1, MJStatBadgeComponent_Conditional_1_Conditional_1_Template, 2, 1, "strong");
|
|
38
|
+
} if (rf & 2) {
|
|
39
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
40
|
+
i0.ɵɵconditional(ctx_r0.Total != null ? 0 : 1);
|
|
41
|
+
} }
|
|
42
|
+
function MJStatBadgeComponent_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
43
|
+
i0.ɵɵdomElementStart(0, "span", 1);
|
|
44
|
+
i0.ɵɵtext(1);
|
|
45
|
+
i0.ɵɵdomElementEnd();
|
|
46
|
+
} if (rf & 2) {
|
|
47
|
+
const ctx_r0 = i0.ɵɵnextContext();
|
|
48
|
+
i0.ɵɵadvance();
|
|
49
|
+
i0.ɵɵtextInterpolate(ctx_r0.Label);
|
|
50
|
+
} }
|
|
51
|
+
/**
|
|
52
|
+
* mj-stat-badge — Small read-only pill for the `[meta]` slot of
|
|
53
|
+
* `<mj-page-header>`. Used to surface counts, status pills, and other
|
|
54
|
+
* informational chips next to the page title.
|
|
55
|
+
*
|
|
56
|
+
* Replaces the per-section `.{section}-stat-badge` / `.X-header-meta-badge`
|
|
57
|
+
* CSS that pages were duplicating after the chrome migration.
|
|
58
|
+
*
|
|
59
|
+
* Examples:
|
|
60
|
+
* ```html
|
|
61
|
+
* <mj-stat-badge [Count]="42" Label="integrations" />
|
|
62
|
+
*
|
|
63
|
+
* <mj-stat-badge [Count]="failedRuns" Label="failed" Variant="error" />
|
|
64
|
+
*
|
|
65
|
+
* <mj-stat-badge Icon="fa-solid fa-spinner fa-spin" Label="running" Variant="running" />
|
|
66
|
+
*
|
|
67
|
+
* <!-- Result-count style: render "X of Y label" when Total is set -->
|
|
68
|
+
* <mj-stat-badge [Count]="filteredCount" [Total]="totalCount" Label="agents" />
|
|
69
|
+
*
|
|
70
|
+
* <mj-stat-badge Variant="success">All clear</mj-stat-badge> <!-- arbitrary projected content -->
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* Note: this component absorbed the former `mj-result-count` (deleted in the
|
|
74
|
+
* organizational refactor). When `Total` is set, the badge renders the
|
|
75
|
+
* "X of Y label" pattern; otherwise it renders "X label" — same shape, same
|
|
76
|
+
* styling, one component.
|
|
77
|
+
*/
|
|
78
|
+
export class MJStatBadgeComponent {
|
|
79
|
+
/** Numeric or text value rendered as `<strong>`. Omit if using `Label` only. */
|
|
80
|
+
Count = null;
|
|
81
|
+
/**
|
|
82
|
+
* Optional total when the badge represents a filtered subset (e.g. "12 of 50 prompts").
|
|
83
|
+
* When set together with `Count`, the badge renders "{Count} of {Total} {Label}".
|
|
84
|
+
* Replaces the old `mj-result-count` component.
|
|
85
|
+
*/
|
|
86
|
+
Total = null;
|
|
87
|
+
/** Descriptive text after the count (e.g. "integrations", "failed"). */
|
|
88
|
+
Label = '';
|
|
89
|
+
/** Optional Font Awesome icon prefixed before the count/label. */
|
|
90
|
+
Icon = '';
|
|
91
|
+
/** Color treatment. Defaults to neutral surface-card. */
|
|
92
|
+
Variant = 'default';
|
|
93
|
+
get IsSuccess() { return this.Variant === 'success'; }
|
|
94
|
+
get IsError() { return this.Variant === 'error'; }
|
|
95
|
+
get IsWarning() { return this.Variant === 'warning'; }
|
|
96
|
+
get IsRunning() { return this.Variant === 'running'; }
|
|
97
|
+
get IsInfo() { return this.Variant === 'info'; }
|
|
98
|
+
static ɵfac = function MJStatBadgeComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJStatBadgeComponent)(); };
|
|
99
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJStatBadgeComponent, selectors: [["mj-stat-badge"]], hostVars: 10, hostBindings: function MJStatBadgeComponent_HostBindings(rf, ctx) { if (rf & 2) {
|
|
100
|
+
i0.ɵɵclassProp("mj-stat-badge--success", ctx.IsSuccess)("mj-stat-badge--error", ctx.IsError)("mj-stat-badge--warning", ctx.IsWarning)("mj-stat-badge--running", ctx.IsRunning)("mj-stat-badge--info", ctx.IsInfo);
|
|
101
|
+
} }, inputs: { Count: "Count", Total: "Total", Label: "Label", Icon: "Icon", Variant: "Variant" }, ngContentSelectors: _c0, decls: 4, vars: 3, consts: [["aria-hidden", "true", 3, "class"], [1, "mj-stat-badge-label"], ["aria-hidden", "true"], [1, "mj-stat-badge-of"]], template: function MJStatBadgeComponent_Template(rf, ctx) { if (rf & 1) {
|
|
102
|
+
i0.ɵɵprojectionDef();
|
|
103
|
+
i0.ɵɵconditionalCreate(0, MJStatBadgeComponent_Conditional_0_Template, 1, 2, "i", 0);
|
|
104
|
+
i0.ɵɵconditionalCreate(1, MJStatBadgeComponent_Conditional_1_Template, 2, 1);
|
|
105
|
+
i0.ɵɵconditionalCreate(2, MJStatBadgeComponent_Conditional_2_Template, 2, 1, "span", 1);
|
|
106
|
+
i0.ɵɵprojection(3);
|
|
107
|
+
} if (rf & 2) {
|
|
108
|
+
i0.ɵɵconditional(ctx.Icon ? 0 : -1);
|
|
109
|
+
i0.ɵɵadvance();
|
|
110
|
+
i0.ɵɵconditional(ctx.Count != null ? 1 : -1);
|
|
111
|
+
i0.ɵɵadvance();
|
|
112
|
+
i0.ɵɵconditional(ctx.Label ? 2 : -1);
|
|
113
|
+
} }, styles: ["[_nghost-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-1-5);\n padding: var(--mj-space-1) var(--mj-space-2-5);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n line-height: 1.4;\n }\n\n [_nghost-%COMP%] strong[_ngcontent-%COMP%] {\n color: var(--mj-text-primary);\n font-weight: 600;\n }\n\n \n\n\n\n .mj-stat-badge-of[_ngcontent-%COMP%] {\n color: var(--mj-text-muted);\n font-weight: 400;\n }\n\n \n\n\n .mj-stat-badge--success[_nghost-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-border-default));\n color: var(--mj-status-success);\n }\n .mj-stat-badge--success[_nghost-%COMP%] strong[_ngcontent-%COMP%] { color: inherit; }\n\n .mj-stat-badge--error[_nghost-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-border-default));\n color: var(--mj-status-error);\n }\n .mj-stat-badge--error[_nghost-%COMP%] strong[_ngcontent-%COMP%] { color: inherit; }\n\n .mj-stat-badge--warning[_nghost-%COMP%], \n .mj-stat-badge--running[_nghost-%COMP%] {\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, var(--mj-border-default));\n color: var(--mj-status-warning);\n }\n .mj-stat-badge--warning[_nghost-%COMP%] strong[_ngcontent-%COMP%], \n .mj-stat-badge--running[_nghost-%COMP%] strong[_ngcontent-%COMP%] { color: inherit; }\n\n .mj-stat-badge--info[_nghost-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-border-default));\n color: var(--mj-brand-primary);\n }\n .mj-stat-badge--info[_nghost-%COMP%] strong[_ngcontent-%COMP%] { color: inherit; }"] });
|
|
114
|
+
}
|
|
115
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJStatBadgeComponent, [{
|
|
116
|
+
type: Component,
|
|
117
|
+
args: [{ selector: 'mj-stat-badge', standalone: true, template: `
|
|
118
|
+
@if (Icon) {
|
|
119
|
+
<i [class]="Icon" aria-hidden="true"></i>
|
|
120
|
+
}
|
|
121
|
+
@if (Count != null) {
|
|
122
|
+
@if (Total != null) {
|
|
123
|
+
<strong>{{ Count }}</strong>
|
|
124
|
+
<span class="mj-stat-badge-of">of</span>
|
|
125
|
+
<strong>{{ Total }}</strong>
|
|
126
|
+
} @else {
|
|
127
|
+
<strong>{{ Count }}</strong>
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
@if (Label) {
|
|
131
|
+
<span class="mj-stat-badge-label">{{ Label }}</span>
|
|
132
|
+
}
|
|
133
|
+
<ng-content></ng-content>
|
|
134
|
+
`, styles: ["\n :host {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-1-5);\n padding: var(--mj-space-1) var(--mj-space-2-5);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n line-height: 1.4;\n }\n\n :host strong {\n color: var(--mj-text-primary);\n font-weight: 600;\n }\n\n /* Small \"of\" separator used when Total is set (X of Y label). Sits\n between the two <strong> counts and stays in the muted/secondary tone\n so the numbers carry the visual weight. */\n .mj-stat-badge-of {\n color: var(--mj-text-muted);\n font-weight: 400;\n }\n\n /* \u2500\u2500 Variants \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n :host(.mj-stat-badge--success) {\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-border-default));\n color: var(--mj-status-success);\n }\n :host(.mj-stat-badge--success) strong { color: inherit; }\n\n :host(.mj-stat-badge--error) {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-border-default));\n color: var(--mj-status-error);\n }\n :host(.mj-stat-badge--error) strong { color: inherit; }\n\n :host(.mj-stat-badge--warning),\n :host(.mj-stat-badge--running) {\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, var(--mj-border-default));\n color: var(--mj-status-warning);\n }\n :host(.mj-stat-badge--warning) strong,\n :host(.mj-stat-badge--running) strong { color: inherit; }\n\n :host(.mj-stat-badge--info) {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-border-default));\n color: var(--mj-brand-primary);\n }\n :host(.mj-stat-badge--info) strong { color: inherit; }\n "] }]
|
|
135
|
+
}], null, { Count: [{
|
|
136
|
+
type: Input
|
|
137
|
+
}], Total: [{
|
|
138
|
+
type: Input
|
|
139
|
+
}], Label: [{
|
|
140
|
+
type: Input
|
|
141
|
+
}], Icon: [{
|
|
142
|
+
type: Input
|
|
143
|
+
}], Variant: [{
|
|
144
|
+
type: Input
|
|
145
|
+
}], IsSuccess: [{
|
|
146
|
+
type: HostBinding,
|
|
147
|
+
args: ['class.mj-stat-badge--success']
|
|
148
|
+
}], IsError: [{
|
|
149
|
+
type: HostBinding,
|
|
150
|
+
args: ['class.mj-stat-badge--error']
|
|
151
|
+
}], IsWarning: [{
|
|
152
|
+
type: HostBinding,
|
|
153
|
+
args: ['class.mj-stat-badge--warning']
|
|
154
|
+
}], IsRunning: [{
|
|
155
|
+
type: HostBinding,
|
|
156
|
+
args: ['class.mj-stat-badge--running']
|
|
157
|
+
}], IsInfo: [{
|
|
158
|
+
type: HostBinding,
|
|
159
|
+
args: ['class.mj-stat-badge--info']
|
|
160
|
+
}] }); })();
|
|
161
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJStatBadgeComponent, { className: "MJStatBadgeComponent", filePath: "lib/stat-badge/stat-badge.component.ts", lineNumber: 121 }); })();
|
|
162
|
+
//# sourceMappingURL=stat-badge.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stat-badge.component.js","sourceRoot":"","sources":["../../../src/lib/stat-badge/stat-badge.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;;;;IA2CxD,0BAAyC;;;IAAtC,0BAAc;;;IAIf,iCAAQ;IAAA,YAAW;IAAA,oBAAS;IAC5B,kCAA+B;IAAA,kBAAE;IAAA,oBAAO;IACxC,iCAAQ;IAAA,YAAW;IAAA,oBAAS;;;IAFpB,cAAW;IAAX,kCAAW;IAEX,eAAW;IAAX,kCAAW;;;IAEnB,iCAAQ;IAAA,YAAW;IAAA,oBAAS;;;IAApB,cAAW;IAAX,kCAAW;;;IADnB,AAJF,0FAAqB,8EAIZ;;;IAJT,8CAMC;;;IAGD,kCAAkC;IAAA,YAAW;IAAA,oBAAO;;;IAAlB,cAAW;IAAX,kCAAW;;AA5CnD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAmFH,MAAM,OAAO,oBAAoB;IAC/B,gFAAgF;IACvE,KAAK,GAA2B,IAAI,CAAC;IAE9C;;;;OAIG;IACM,KAAK,GAA2B,IAAI,CAAC;IAE9C,wEAAwE;IAC/D,KAAK,GAAW,EAAE,CAAC;IAE5B,kEAAkE;IACzD,IAAI,GAAW,EAAE,CAAC;IAE3B,yDAAyD;IAChD,OAAO,GAAuB,SAAS,CAAC;IAEjD,IACI,SAAS,KAAc,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC;IAE/D,IACI,OAAO,KAAc,OAAO,IAAI,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC;IAE3D,IACI,SAAS,KAAc,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC;IAE/D,IACI,SAAS,KAAc,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC;IAE/D,IACI,MAAM,KAAc,OAAO,IAAI,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC;8GAjC9C,oBAAoB;6DAApB,oBAAoB;YAApB,uDAAoB,qCAAA,yCAAA,yCAAA,mCAAA;;;YA9E7B,oFAAY;YAGZ,4EAAqB;YASrB,uFAAa;YAGb,kBAAyB;;YAfzB,mCAEC;YACD,cAQC;YARD,4CAQC;YACD,cAEC;YAFD,oCAEC;;;iFAgEQ,oBAAoB;cAlFhC,SAAS;2BACE,eAAe,cACb,IAAI,YACN;;;;;;;;;;;;;;;;;GAiBT;;kBAgEA,KAAK;;kBAOL,KAAK;;kBAGL,KAAK;;kBAGL,KAAK;;kBAGL,KAAK;;kBAEL,WAAW;mBAAC,8BAA8B;;kBAG1C,WAAW;mBAAC,4BAA4B;;kBAGxC,WAAW;mBAAC,8BAA8B;;kBAG1C,WAAW;mBAAC,8BAA8B;;kBAG1C,WAAW;mBAAC,2BAA2B;;kFAhC7B,oBAAoB","sourcesContent":["import { Component, HostBinding, Input } from '@angular/core';\n\n/** Visual variant for `<mj-stat-badge>`. */\nexport type MJStatBadgeVariant =\n | 'default' // neutral surface-card pill\n | 'success' // green-tinted (e.g. \"12 succeeded\")\n | 'error' // red-tinted (e.g. \"3 failed\")\n | 'warning' // amber-tinted (e.g. \"5 expiring\")\n | 'running' // amber-tinted with spinner-friendly affordance\n | 'info'; // brand-tinted\n\n/**\n * mj-stat-badge — Small read-only pill for the `[meta]` slot of\n * `<mj-page-header>`. Used to surface counts, status pills, and other\n * informational chips next to the page title.\n *\n * Replaces the per-section `.{section}-stat-badge` / `.X-header-meta-badge`\n * CSS that pages were duplicating after the chrome migration.\n *\n * Examples:\n * ```html\n * <mj-stat-badge [Count]=\"42\" Label=\"integrations\" />\n *\n * <mj-stat-badge [Count]=\"failedRuns\" Label=\"failed\" Variant=\"error\" />\n *\n * <mj-stat-badge Icon=\"fa-solid fa-spinner fa-spin\" Label=\"running\" Variant=\"running\" />\n *\n * <!-- Result-count style: render \"X of Y label\" when Total is set -->\n * <mj-stat-badge [Count]=\"filteredCount\" [Total]=\"totalCount\" Label=\"agents\" />\n *\n * <mj-stat-badge Variant=\"success\">All clear</mj-stat-badge> <!-- arbitrary projected content -->\n * ```\n *\n * Note: this component absorbed the former `mj-result-count` (deleted in the\n * organizational refactor). When `Total` is set, the badge renders the\n * \"X of Y label\" pattern; otherwise it renders \"X label\" — same shape, same\n * styling, one component.\n */\n@Component({\n selector: 'mj-stat-badge',\n standalone: true,\n template: `\n @if (Icon) {\n <i [class]=\"Icon\" aria-hidden=\"true\"></i>\n }\n @if (Count != null) {\n @if (Total != null) {\n <strong>{{ Count }}</strong>\n <span class=\"mj-stat-badge-of\">of</span>\n <strong>{{ Total }}</strong>\n } @else {\n <strong>{{ Count }}</strong>\n }\n }\n @if (Label) {\n <span class=\"mj-stat-badge-label\">{{ Label }}</span>\n }\n <ng-content></ng-content>\n `,\n styles: [`\n :host {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-1-5);\n padding: var(--mj-space-1) var(--mj-space-2-5);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-full);\n font-size: var(--mj-text-xs);\n color: var(--mj-text-secondary);\n white-space: nowrap;\n line-height: 1.4;\n }\n\n :host strong {\n color: var(--mj-text-primary);\n font-weight: 600;\n }\n\n /* Small \"of\" separator used when Total is set (X of Y label). Sits\n between the two <strong> counts and stays in the muted/secondary tone\n so the numbers carry the visual weight. */\n .mj-stat-badge-of {\n color: var(--mj-text-muted);\n font-weight: 400;\n }\n\n /* ── Variants ─────────────────────────────────────────────── */\n\n :host(.mj-stat-badge--success) {\n background: color-mix(in srgb, var(--mj-status-success) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-success) 30%, var(--mj-border-default));\n color: var(--mj-status-success);\n }\n :host(.mj-stat-badge--success) strong { color: inherit; }\n\n :host(.mj-stat-badge--error) {\n background: color-mix(in srgb, var(--mj-status-error) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-error) 30%, var(--mj-border-default));\n color: var(--mj-status-error);\n }\n :host(.mj-stat-badge--error) strong { color: inherit; }\n\n :host(.mj-stat-badge--warning),\n :host(.mj-stat-badge--running) {\n background: color-mix(in srgb, var(--mj-status-warning) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-status-warning) 30%, var(--mj-border-default));\n color: var(--mj-status-warning);\n }\n :host(.mj-stat-badge--warning) strong,\n :host(.mj-stat-badge--running) strong { color: inherit; }\n\n :host(.mj-stat-badge--info) {\n background: color-mix(in srgb, var(--mj-brand-primary) 10%, var(--mj-bg-surface));\n border-color: color-mix(in srgb, var(--mj-brand-primary) 30%, var(--mj-border-default));\n color: var(--mj-brand-primary);\n }\n :host(.mj-stat-badge--info) strong { color: inherit; }\n `]\n})\nexport class MJStatBadgeComponent {\n /** Numeric or text value rendered as `<strong>`. Omit if using `Label` only. */\n @Input() Count: number | string | null = null;\n\n /**\n * Optional total when the badge represents a filtered subset (e.g. \"12 of 50 prompts\").\n * When set together with `Count`, the badge renders \"{Count} of {Total} {Label}\".\n * Replaces the old `mj-result-count` component.\n */\n @Input() Total: number | string | null = null;\n\n /** Descriptive text after the count (e.g. \"integrations\", \"failed\"). */\n @Input() Label: string = '';\n\n /** Optional Font Awesome icon prefixed before the count/label. */\n @Input() Icon: string = '';\n\n /** Color treatment. Defaults to neutral surface-card. */\n @Input() Variant: MJStatBadgeVariant = 'default';\n\n @HostBinding('class.mj-stat-badge--success')\n get IsSuccess(): boolean { return this.Variant === 'success'; }\n\n @HostBinding('class.mj-stat-badge--error')\n get IsError(): boolean { return this.Variant === 'error'; }\n\n @HostBinding('class.mj-stat-badge--warning')\n get IsWarning(): boolean { return this.Variant === 'warning'; }\n\n @HostBinding('class.mj-stat-badge--running')\n get IsRunning(): boolean { return this.Variant === 'running'; }\n\n @HostBinding('class.mj-stat-badge--info')\n get IsInfo(): boolean { return this.Variant === 'info'; }\n}\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { EventEmitter } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/** Per-tab config understood by <mj-tab-nav>. */
|
|
4
|
+
export interface TabConfig {
|
|
5
|
+
/** Unique key — emitted via (TabChange) when this tab is clicked. */
|
|
6
|
+
key: string;
|
|
7
|
+
/** Visible label. */
|
|
8
|
+
label: string;
|
|
9
|
+
/** Optional Font Awesome icon class (e.g. 'fa-solid fa-server'). */
|
|
10
|
+
icon?: string;
|
|
11
|
+
/** Optional count or short string shown in a small badge after the label. */
|
|
12
|
+
badge?: number | string | null;
|
|
13
|
+
/** Semantic variant for the badge (drives color). Defaults to 'default'. */
|
|
14
|
+
badgeVariant?: 'default' | 'error' | 'warning' | 'success';
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* mj-tab-nav — Canonical horizontal sub-navigation for pages that have
|
|
18
|
+
* multiple top-level views (e.g. MCP: Servers / Connections / Tools / Logs;
|
|
19
|
+
* Admin: Identity & Access / Data & Schema / Monitoring / Developer Tools).
|
|
20
|
+
*
|
|
21
|
+
* Visually distinct from `<mj-filter-chip>` (filters) — tabs are bigger,
|
|
22
|
+
* have a grouped container, and a more committed active state. Both share
|
|
23
|
+
* the brand-primary active color for design-language consistency.
|
|
24
|
+
*
|
|
25
|
+
* Example:
|
|
26
|
+
* ```html
|
|
27
|
+
* <mj-tab-nav
|
|
28
|
+
* [Tabs]="mcpTabs"
|
|
29
|
+
* [ActiveKey]="ActiveTab"
|
|
30
|
+
* (TabChange)="setActiveTab($event)">
|
|
31
|
+
* </mj-tab-nav>
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare class MJTabNavComponent {
|
|
35
|
+
Tabs: TabConfig[];
|
|
36
|
+
ActiveKey: string;
|
|
37
|
+
TabChange: EventEmitter<string>;
|
|
38
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MJTabNavComponent, never>;
|
|
39
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MJTabNavComponent, "mj-tab-nav", never, { "Tabs": { "alias": "Tabs"; "required": false; }; "ActiveKey": { "alias": "ActiveKey"; "required": false; }; }, { "TabChange": "TabChange"; }, never, never, true, never>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=tab-nav.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tab-nav.component.d.ts","sourceRoot":"","sources":["../../../src/lib/tab-nav/tab-nav.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;;AAEvE,iDAAiD;AACjD,MAAM,WAAW,SAAS;IACxB,qEAAqE;IACrE,GAAG,EAAE,MAAM,CAAC;IACZ,qBAAqB;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC/B,4EAA4E;IAC5E,YAAY,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,CAAC;CAC5D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAkHa,iBAAiB;IACnB,IAAI,EAAE,SAAS,EAAE,CAAM;IACvB,SAAS,EAAE,MAAM,CAAM;IACtB,SAAS,uBAA8B;yCAHtC,iBAAiB;2CAAjB,iBAAiB;CAI7B"}
|
|
@@ -0,0 +1,111 @@
|
|
|
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 MJTabNavComponent_For_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
5
|
+
i0.ɵɵdomElement(0, "i", 6);
|
|
6
|
+
} if (rf & 2) {
|
|
7
|
+
const tab_r2 = i0.ɵɵnextContext().$implicit;
|
|
8
|
+
i0.ɵɵclassMap(tab_r2.icon);
|
|
9
|
+
} }
|
|
10
|
+
function MJTabNavComponent_For_2_Conditional_4_Template(rf, ctx) { if (rf & 1) {
|
|
11
|
+
i0.ɵɵdomElementStart(0, "span", 7);
|
|
12
|
+
i0.ɵɵtext(1);
|
|
13
|
+
i0.ɵɵdomElementEnd();
|
|
14
|
+
} if (rf & 2) {
|
|
15
|
+
const tab_r2 = i0.ɵɵnextContext().$implicit;
|
|
16
|
+
i0.ɵɵclassProp("mj-tab-nav-badge--error", tab_r2.badgeVariant === "error")("mj-tab-nav-badge--warning", tab_r2.badgeVariant === "warning")("mj-tab-nav-badge--success", tab_r2.badgeVariant === "success");
|
|
17
|
+
i0.ɵɵadvance();
|
|
18
|
+
i0.ɵɵtextInterpolate1(" ", tab_r2.badge, " ");
|
|
19
|
+
} }
|
|
20
|
+
function MJTabNavComponent_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
21
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
22
|
+
i0.ɵɵdomElementStart(0, "button", 2);
|
|
23
|
+
i0.ɵɵdomListener("click", function MJTabNavComponent_For_2_Template_button_click_0_listener() { const tab_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.TabChange.emit(tab_r2.key)); });
|
|
24
|
+
i0.ɵɵconditionalCreate(1, MJTabNavComponent_For_2_Conditional_1_Template, 1, 2, "i", 3);
|
|
25
|
+
i0.ɵɵdomElementStart(2, "span", 4);
|
|
26
|
+
i0.ɵɵtext(3);
|
|
27
|
+
i0.ɵɵdomElementEnd();
|
|
28
|
+
i0.ɵɵconditionalCreate(4, MJTabNavComponent_For_2_Conditional_4_Template, 2, 7, "span", 5);
|
|
29
|
+
i0.ɵɵdomElementEnd();
|
|
30
|
+
} if (rf & 2) {
|
|
31
|
+
const tab_r2 = ctx.$implicit;
|
|
32
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
33
|
+
i0.ɵɵclassProp("mj-tab-nav-btn--active", tab_r2.key === ctx_r2.ActiveKey);
|
|
34
|
+
i0.ɵɵattribute("aria-selected", tab_r2.key === ctx_r2.ActiveKey);
|
|
35
|
+
i0.ɵɵadvance();
|
|
36
|
+
i0.ɵɵconditional(tab_r2.icon ? 1 : -1);
|
|
37
|
+
i0.ɵɵadvance(2);
|
|
38
|
+
i0.ɵɵtextInterpolate(tab_r2.label);
|
|
39
|
+
i0.ɵɵadvance();
|
|
40
|
+
i0.ɵɵconditional(tab_r2.badge != null && tab_r2.badge !== "" ? 4 : -1);
|
|
41
|
+
} }
|
|
42
|
+
/**
|
|
43
|
+
* mj-tab-nav — Canonical horizontal sub-navigation for pages that have
|
|
44
|
+
* multiple top-level views (e.g. MCP: Servers / Connections / Tools / Logs;
|
|
45
|
+
* Admin: Identity & Access / Data & Schema / Monitoring / Developer Tools).
|
|
46
|
+
*
|
|
47
|
+
* Visually distinct from `<mj-filter-chip>` (filters) — tabs are bigger,
|
|
48
|
+
* have a grouped container, and a more committed active state. Both share
|
|
49
|
+
* the brand-primary active color for design-language consistency.
|
|
50
|
+
*
|
|
51
|
+
* Example:
|
|
52
|
+
* ```html
|
|
53
|
+
* <mj-tab-nav
|
|
54
|
+
* [Tabs]="mcpTabs"
|
|
55
|
+
* [ActiveKey]="ActiveTab"
|
|
56
|
+
* (TabChange)="setActiveTab($event)">
|
|
57
|
+
* </mj-tab-nav>
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export class MJTabNavComponent {
|
|
61
|
+
Tabs = [];
|
|
62
|
+
ActiveKey = '';
|
|
63
|
+
TabChange = new EventEmitter();
|
|
64
|
+
static ɵfac = function MJTabNavComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJTabNavComponent)(); };
|
|
65
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJTabNavComponent, selectors: [["mj-tab-nav"]], inputs: { Tabs: "Tabs", ActiveKey: "ActiveKey" }, outputs: { TabChange: "TabChange" }, decls: 3, vars: 0, consts: [["role", "tablist", 1, "mj-tab-nav"], ["type", "button", "role", "tab", 1, "mj-tab-nav-btn", 3, "mj-tab-nav-btn--active"], ["type", "button", "role", "tab", 1, "mj-tab-nav-btn", 3, "click"], ["aria-hidden", "true", 3, "class"], [1, "mj-tab-nav-label"], [1, "mj-tab-nav-badge", 3, "mj-tab-nav-badge--error", "mj-tab-nav-badge--warning", "mj-tab-nav-badge--success"], ["aria-hidden", "true"], [1, "mj-tab-nav-badge"]], template: function MJTabNavComponent_Template(rf, ctx) { if (rf & 1) {
|
|
66
|
+
i0.ɵɵdomElementStart(0, "div", 0);
|
|
67
|
+
i0.ɵɵrepeaterCreate(1, MJTabNavComponent_For_2_Template, 5, 6, "button", 1, _forTrack0);
|
|
68
|
+
i0.ɵɵdomElementEnd();
|
|
69
|
+
} if (rf & 2) {
|
|
70
|
+
i0.ɵɵadvance();
|
|
71
|
+
i0.ɵɵrepeater(ctx.Tabs);
|
|
72
|
+
} }, styles: ["[_nghost-%COMP%] { display: inline-flex; }\n\n .mj-tab-nav[_ngcontent-%COMP%] {\n display: inline-flex;\n gap: var(--mj-space-1);\n padding: var(--mj-space-1);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n }\n\n .mj-tab-nav-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: 7px var(--mj-space-3-5);\n background: transparent;\n border: none;\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-secondary);\n font-family: inherit;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.2;\n cursor: pointer;\n transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;\n white-space: nowrap;\n }\n\n .mj-tab-nav-btn[_ngcontent-%COMP%]:hover:not(.mj-tab-nav-btn--active) {\n background: color-mix(in srgb, var(--mj-bg-surface) 70%, transparent);\n color: var(--mj-text-primary);\n }\n\n .mj-tab-nav-btn--active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 3px color-mix(in srgb, var(--mj-text-primary) 12%, transparent);\n }\n\n .mj-tab-nav-btn[_ngcontent-%COMP%] i[_ngcontent-%COMP%] {\n font-size: 13px;\n }\n\n .mj-tab-nav-label[_ngcontent-%COMP%] {\n font-weight: 500;\n }\n\n \n\n .mj-tab-nav-badge[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 18px;\n padding: 0 var(--mj-space-1-5);\n border-radius: 9px;\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n }\n\n .mj-tab-nav-btn--active[_ngcontent-%COMP%] .mj-tab-nav-badge[_ngcontent-%COMP%] {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n }\n\n .mj-tab-nav-badge--error[_ngcontent-%COMP%] {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n }\n .mj-tab-nav-badge--warning[_ngcontent-%COMP%] {\n background: var(--mj-status-warning);\n color: var(--mj-text-inverse);\n }\n .mj-tab-nav-badge--success[_ngcontent-%COMP%] {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n }"] });
|
|
73
|
+
}
|
|
74
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJTabNavComponent, [{
|
|
75
|
+
type: Component,
|
|
76
|
+
args: [{ selector: 'mj-tab-nav', standalone: true, template: `
|
|
77
|
+
<div class="mj-tab-nav" role="tablist">
|
|
78
|
+
@for (tab of Tabs; track tab.key) {
|
|
79
|
+
<button
|
|
80
|
+
type="button"
|
|
81
|
+
class="mj-tab-nav-btn"
|
|
82
|
+
[class.mj-tab-nav-btn--active]="tab.key === ActiveKey"
|
|
83
|
+
role="tab"
|
|
84
|
+
[attr.aria-selected]="tab.key === ActiveKey"
|
|
85
|
+
(click)="TabChange.emit(tab.key)">
|
|
86
|
+
@if (tab.icon) {
|
|
87
|
+
<i [class]="tab.icon" aria-hidden="true"></i>
|
|
88
|
+
}
|
|
89
|
+
<span class="mj-tab-nav-label">{{ tab.label }}</span>
|
|
90
|
+
@if (tab.badge != null && tab.badge !== '') {
|
|
91
|
+
<span
|
|
92
|
+
class="mj-tab-nav-badge"
|
|
93
|
+
[class.mj-tab-nav-badge--error]="tab.badgeVariant === 'error'"
|
|
94
|
+
[class.mj-tab-nav-badge--warning]="tab.badgeVariant === 'warning'"
|
|
95
|
+
[class.mj-tab-nav-badge--success]="tab.badgeVariant === 'success'">
|
|
96
|
+
{{ tab.badge }}
|
|
97
|
+
</span>
|
|
98
|
+
}
|
|
99
|
+
</button>
|
|
100
|
+
}
|
|
101
|
+
</div>
|
|
102
|
+
`, styles: ["\n :host { display: inline-flex; }\n\n .mj-tab-nav {\n display: inline-flex;\n gap: var(--mj-space-1);\n padding: var(--mj-space-1);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n }\n\n .mj-tab-nav-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: 7px var(--mj-space-3-5);\n background: transparent;\n border: none;\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-secondary);\n font-family: inherit;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.2;\n cursor: pointer;\n transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;\n white-space: nowrap;\n }\n\n .mj-tab-nav-btn:hover:not(.mj-tab-nav-btn--active) {\n background: color-mix(in srgb, var(--mj-bg-surface) 70%, transparent);\n color: var(--mj-text-primary);\n }\n\n .mj-tab-nav-btn--active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 3px color-mix(in srgb, var(--mj-text-primary) 12%, transparent);\n }\n\n .mj-tab-nav-btn i {\n font-size: 13px;\n }\n\n .mj-tab-nav-label {\n font-weight: 500;\n }\n\n /* Badge */\n .mj-tab-nav-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 18px;\n padding: 0 var(--mj-space-1-5);\n border-radius: 9px;\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n }\n\n .mj-tab-nav-btn--active .mj-tab-nav-badge {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n }\n\n .mj-tab-nav-badge--error {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n }\n .mj-tab-nav-badge--warning {\n background: var(--mj-status-warning);\n color: var(--mj-text-inverse);\n }\n .mj-tab-nav-badge--success {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n }\n "] }]
|
|
103
|
+
}], null, { Tabs: [{
|
|
104
|
+
type: Input
|
|
105
|
+
}], ActiveKey: [{
|
|
106
|
+
type: Input
|
|
107
|
+
}], TabChange: [{
|
|
108
|
+
type: Output
|
|
109
|
+
}] }); })();
|
|
110
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJTabNavComponent, { className: "MJTabNavComponent", filePath: "lib/tab-nav/tab-nav.component.ts", lineNumber: 149 }); })();
|
|
111
|
+
//# sourceMappingURL=tab-nav.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tab-nav.component.js","sourceRoot":"","sources":["../../../src/lib/tab-nav/tab-nav.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;;;IAgD3D,0BAA6C;;;IAA1C,0BAAkB;;;IAIrB,kCAIqE;IACnE,YACF;IAAA,oBAAO;;;IAFL,AADA,AADA,0EAA8D,gEACI,gEACA;IAClE,cACF;IADE,6CACF;;;;IAlBJ,oCAMoC;IAAlC,yMAAS,iCAAuB,KAAC;IACjC,uFAAgB;IAGhB,kCAA+B;IAAA,YAAe;IAAA,oBAAO;IACrD,0FAA6C;IAS/C,oBAAS;;;;IAjBP,yEAAsD;;IAItD,cAEC;IAFD,sCAEC;IAC8B,eAAe;IAAf,kCAAe;IAC9C,cAQC;IARD,sEAQC;;AA3CX;;;;;;;;;;;;;;;;;GAiBG;AAmHH,MAAM,OAAO,iBAAiB;IACnB,IAAI,GAAgB,EAAE,CAAC;IACvB,SAAS,GAAW,EAAE,CAAC;IACtB,SAAS,GAAG,IAAI,YAAY,EAAU,CAAC;2GAHtC,iBAAiB;6DAAjB,iBAAiB;YA9G1B,iCAAuC;YACrC,uFAsBC;YACH,oBAAM;;YAvBJ,cAsBC;YAtBD,uBAsBC;;;iFAuFM,iBAAiB;cAlH7B,SAAS;2BACE,YAAY,cACV,IAAI,YACN;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BT;;kBAsFA,KAAK;;kBACL,KAAK;;kBACL,MAAM;;kFAHI,iBAAiB","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\n\n/** Per-tab config understood by <mj-tab-nav>. */\nexport interface TabConfig {\n /** Unique key — emitted via (TabChange) when this tab is clicked. */\n key: string;\n /** Visible label. */\n label: string;\n /** Optional Font Awesome icon class (e.g. 'fa-solid fa-server'). */\n icon?: string;\n /** Optional count or short string shown in a small badge after the label. */\n badge?: number | string | null;\n /** Semantic variant for the badge (drives color). Defaults to 'default'. */\n badgeVariant?: 'default' | 'error' | 'warning' | 'success';\n}\n\n/**\n * mj-tab-nav — Canonical horizontal sub-navigation for pages that have\n * multiple top-level views (e.g. MCP: Servers / Connections / Tools / Logs;\n * Admin: Identity & Access / Data & Schema / Monitoring / Developer Tools).\n *\n * Visually distinct from `<mj-filter-chip>` (filters) — tabs are bigger,\n * have a grouped container, and a more committed active state. Both share\n * the brand-primary active color for design-language consistency.\n *\n * Example:\n * ```html\n * <mj-tab-nav\n * [Tabs]=\"mcpTabs\"\n * [ActiveKey]=\"ActiveTab\"\n * (TabChange)=\"setActiveTab($event)\">\n * </mj-tab-nav>\n * ```\n */\n@Component({\n selector: 'mj-tab-nav',\n standalone: true,\n template: `\n <div class=\"mj-tab-nav\" role=\"tablist\">\n @for (tab of Tabs; track tab.key) {\n <button\n type=\"button\"\n class=\"mj-tab-nav-btn\"\n [class.mj-tab-nav-btn--active]=\"tab.key === ActiveKey\"\n role=\"tab\"\n [attr.aria-selected]=\"tab.key === ActiveKey\"\n (click)=\"TabChange.emit(tab.key)\">\n @if (tab.icon) {\n <i [class]=\"tab.icon\" aria-hidden=\"true\"></i>\n }\n <span class=\"mj-tab-nav-label\">{{ tab.label }}</span>\n @if (tab.badge != null && tab.badge !== '') {\n <span\n class=\"mj-tab-nav-badge\"\n [class.mj-tab-nav-badge--error]=\"tab.badgeVariant === 'error'\"\n [class.mj-tab-nav-badge--warning]=\"tab.badgeVariant === 'warning'\"\n [class.mj-tab-nav-badge--success]=\"tab.badgeVariant === 'success'\">\n {{ tab.badge }}\n </span>\n }\n </button>\n }\n </div>\n `,\n styles: [`\n :host { display: inline-flex; }\n\n .mj-tab-nav {\n display: inline-flex;\n gap: var(--mj-space-1);\n padding: var(--mj-space-1);\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-lg);\n }\n\n .mj-tab-nav-btn {\n display: inline-flex;\n align-items: center;\n gap: var(--mj-space-2);\n padding: 7px var(--mj-space-3-5);\n background: transparent;\n border: none;\n border-radius: var(--mj-radius-md);\n color: var(--mj-text-secondary);\n font-family: inherit;\n font-size: 13px;\n font-weight: 500;\n line-height: 1.2;\n cursor: pointer;\n transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;\n white-space: nowrap;\n }\n\n .mj-tab-nav-btn:hover:not(.mj-tab-nav-btn--active) {\n background: color-mix(in srgb, var(--mj-bg-surface) 70%, transparent);\n color: var(--mj-text-primary);\n }\n\n .mj-tab-nav-btn--active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 3px color-mix(in srgb, var(--mj-text-primary) 12%, transparent);\n }\n\n .mj-tab-nav-btn i {\n font-size: 13px;\n }\n\n .mj-tab-nav-label {\n font-weight: 500;\n }\n\n /* Badge */\n .mj-tab-nav-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 22px;\n height: 18px;\n padding: 0 var(--mj-space-1-5);\n border-radius: 9px;\n background: var(--mj-border-default);\n color: var(--mj-text-muted);\n font-size: 11px;\n font-weight: 600;\n line-height: 1;\n }\n\n .mj-tab-nav-btn--active .mj-tab-nav-badge {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n color: var(--mj-brand-primary);\n }\n\n .mj-tab-nav-badge--error {\n background: var(--mj-status-error);\n color: var(--mj-text-inverse);\n }\n .mj-tab-nav-badge--warning {\n background: var(--mj-status-warning);\n color: var(--mj-text-inverse);\n }\n .mj-tab-nav-badge--success {\n background: var(--mj-status-success);\n color: var(--mj-text-inverse);\n }\n `]\n})\nexport class MJTabNavComponent {\n @Input() Tabs: TabConfig[] = [];\n @Input() ActiveKey: string = '';\n @Output() TabChange = new EventEmitter<string>();\n}\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { EventEmitter } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/** Per-option config understood by <mj-view-toggle>. */
|
|
4
|
+
export interface ViewToggleOption {
|
|
5
|
+
/** Unique key — emitted via (KeyChange) when clicked. */
|
|
6
|
+
key: string;
|
|
7
|
+
/** Font Awesome icon class (e.g. 'fa-solid fa-grip'). Optional when `label` is provided. */
|
|
8
|
+
icon?: string;
|
|
9
|
+
/** Visible text label. Optional — when omitted the option is icon-only. */
|
|
10
|
+
label?: string;
|
|
11
|
+
/** Tooltip / aria-label. Required when `label` is omitted (icon-only mode). */
|
|
12
|
+
title?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* mj-view-toggle — Compact icon-only segmented control for view-mode selection
|
|
16
|
+
* (grid / list / tree / card etc.). Visually smaller than `<mj-tab-nav>` to signal
|
|
17
|
+
* "this is a view setting, not page navigation".
|
|
18
|
+
*
|
|
19
|
+
* Example:
|
|
20
|
+
* ```html
|
|
21
|
+
* <mj-view-toggle
|
|
22
|
+
* [Options]="viewOptions"
|
|
23
|
+
* [ActiveKey]="viewMode"
|
|
24
|
+
* (KeyChange)="setViewMode($event)">
|
|
25
|
+
* </mj-view-toggle>
|
|
26
|
+
*
|
|
27
|
+
* // In the component:
|
|
28
|
+
* viewOptions = [
|
|
29
|
+
* { key: 'grid', icon: 'fa-solid fa-grip', title: 'Grid View' },
|
|
30
|
+
* { key: 'list', icon: 'fa-solid fa-list', title: 'List View' },
|
|
31
|
+
* { key: 'tree', icon: 'fa-solid fa-folder-tree', title: 'Category Tree View' },
|
|
32
|
+
* ];
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare class MJViewToggleComponent {
|
|
36
|
+
Options: ViewToggleOption[];
|
|
37
|
+
ActiveKey: string;
|
|
38
|
+
KeyChange: EventEmitter<string>;
|
|
39
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MJViewToggleComponent, never>;
|
|
40
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MJViewToggleComponent, "mj-view-toggle", never, { "Options": { "alias": "Options"; "required": false; }; "ActiveKey": { "alias": "ActiveKey"; "required": false; }; }, { "KeyChange": "KeyChange"; }, never, never, true, never>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=view-toggle.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-toggle.component.d.ts","sourceRoot":"","sources":["../../../src/lib/view-toggle/view-toggle.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAiB,MAAM,eAAe,CAAC;;AAEvE,wDAAwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ,4FAA4F;IAC5F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBA+Ea,qBAAqB;IACvB,OAAO,EAAE,gBAAgB,EAAE,CAAM;IACjC,SAAS,EAAE,MAAM,CAAM;IACtB,SAAS,uBAA8B;yCAHtC,qBAAqB;2CAArB,qBAAqB;CAIjC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
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 MJViewToggleComponent_For_2_Conditional_1_Template(rf, ctx) { if (rf & 1) {
|
|
5
|
+
i0.ɵɵdomElement(0, "i", 5);
|
|
6
|
+
} if (rf & 2) {
|
|
7
|
+
const opt_r2 = i0.ɵɵnextContext().$implicit;
|
|
8
|
+
i0.ɵɵclassMap(opt_r2.icon);
|
|
9
|
+
} }
|
|
10
|
+
function MJViewToggleComponent_For_2_Conditional_2_Template(rf, ctx) { if (rf & 1) {
|
|
11
|
+
i0.ɵɵdomElementStart(0, "span", 4);
|
|
12
|
+
i0.ɵɵtext(1);
|
|
13
|
+
i0.ɵɵdomElementEnd();
|
|
14
|
+
} if (rf & 2) {
|
|
15
|
+
const opt_r2 = i0.ɵɵnextContext().$implicit;
|
|
16
|
+
i0.ɵɵadvance();
|
|
17
|
+
i0.ɵɵtextInterpolate(opt_r2.label);
|
|
18
|
+
} }
|
|
19
|
+
function MJViewToggleComponent_For_2_Template(rf, ctx) { if (rf & 1) {
|
|
20
|
+
const _r1 = i0.ɵɵgetCurrentView();
|
|
21
|
+
i0.ɵɵdomElementStart(0, "button", 2);
|
|
22
|
+
i0.ɵɵdomListener("click", function MJViewToggleComponent_For_2_Template_button_click_0_listener() { const opt_r2 = i0.ɵɵrestoreView(_r1).$implicit; const ctx_r2 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r2.KeyChange.emit(opt_r2.key)); });
|
|
23
|
+
i0.ɵɵconditionalCreate(1, MJViewToggleComponent_For_2_Conditional_1_Template, 1, 2, "i", 3);
|
|
24
|
+
i0.ɵɵconditionalCreate(2, MJViewToggleComponent_For_2_Conditional_2_Template, 2, 1, "span", 4);
|
|
25
|
+
i0.ɵɵdomElementEnd();
|
|
26
|
+
} if (rf & 2) {
|
|
27
|
+
const opt_r2 = ctx.$implicit;
|
|
28
|
+
const ctx_r2 = i0.ɵɵnextContext();
|
|
29
|
+
i0.ɵɵclassProp("mj-view-toggle-btn--active", opt_r2.key === ctx_r2.ActiveKey)("mj-view-toggle-btn--text", !!opt_r2.label);
|
|
30
|
+
i0.ɵɵdomProperty("title", opt_r2.title ?? opt_r2.label);
|
|
31
|
+
i0.ɵɵattribute("aria-pressed", opt_r2.key === ctx_r2.ActiveKey)("aria-label", opt_r2.title ?? opt_r2.label);
|
|
32
|
+
i0.ɵɵadvance();
|
|
33
|
+
i0.ɵɵconditional(opt_r2.icon ? 1 : -1);
|
|
34
|
+
i0.ɵɵadvance();
|
|
35
|
+
i0.ɵɵconditional(opt_r2.label ? 2 : -1);
|
|
36
|
+
} }
|
|
37
|
+
/**
|
|
38
|
+
* mj-view-toggle — Compact icon-only segmented control for view-mode selection
|
|
39
|
+
* (grid / list / tree / card etc.). Visually smaller than `<mj-tab-nav>` to signal
|
|
40
|
+
* "this is a view setting, not page navigation".
|
|
41
|
+
*
|
|
42
|
+
* Example:
|
|
43
|
+
* ```html
|
|
44
|
+
* <mj-view-toggle
|
|
45
|
+
* [Options]="viewOptions"
|
|
46
|
+
* [ActiveKey]="viewMode"
|
|
47
|
+
* (KeyChange)="setViewMode($event)">
|
|
48
|
+
* </mj-view-toggle>
|
|
49
|
+
*
|
|
50
|
+
* // In the component:
|
|
51
|
+
* viewOptions = [
|
|
52
|
+
* { key: 'grid', icon: 'fa-solid fa-grip', title: 'Grid View' },
|
|
53
|
+
* { key: 'list', icon: 'fa-solid fa-list', title: 'List View' },
|
|
54
|
+
* { key: 'tree', icon: 'fa-solid fa-folder-tree', title: 'Category Tree View' },
|
|
55
|
+
* ];
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export class MJViewToggleComponent {
|
|
59
|
+
Options = [];
|
|
60
|
+
ActiveKey = '';
|
|
61
|
+
KeyChange = new EventEmitter();
|
|
62
|
+
static ɵfac = function MJViewToggleComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MJViewToggleComponent)(); };
|
|
63
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MJViewToggleComponent, selectors: [["mj-view-toggle"]], inputs: { Options: "Options", ActiveKey: "ActiveKey" }, outputs: { KeyChange: "KeyChange" }, decls: 3, vars: 0, consts: [["role", "group", 1, "mj-view-toggle"], ["type", "button", 1, "mj-view-toggle-btn", 3, "mj-view-toggle-btn--active", "mj-view-toggle-btn--text", "title"], ["type", "button", 1, "mj-view-toggle-btn", 3, "click", "title"], ["aria-hidden", "true", 3, "class"], [1, "mj-view-toggle-label"], ["aria-hidden", "true"]], template: function MJViewToggleComponent_Template(rf, ctx) { if (rf & 1) {
|
|
64
|
+
i0.ɵɵdomElementStart(0, "div", 0);
|
|
65
|
+
i0.ɵɵrepeaterCreate(1, MJViewToggleComponent_For_2_Template, 3, 9, "button", 1, _forTrack0);
|
|
66
|
+
i0.ɵɵdomElementEnd();
|
|
67
|
+
} if (rf & 2) {
|
|
68
|
+
i0.ɵɵadvance();
|
|
69
|
+
i0.ɵɵrepeater(ctx.Options);
|
|
70
|
+
} }, styles: ["[_nghost-%COMP%] { display: inline-flex; }\n\n .mj-view-toggle[_ngcontent-%COMP%] {\n display: inline-flex;\n gap: var(--mj-space-0-5);\n padding: 3px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n }\n\n .mj-view-toggle-btn[_ngcontent-%COMP%] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--mj-space-1-5);\n width: 28px;\n height: 28px;\n background: transparent;\n border: none;\n border-radius: var(--mj-radius-sm);\n color: var(--mj-text-muted);\n font-size: 13px;\n line-height: 1;\n cursor: pointer;\n transition: background-color 0.15s ease, color 0.15s ease;\n }\n\n \n\n .mj-view-toggle-btn--text[_ngcontent-%COMP%] {\n width: auto;\n padding: 0 var(--mj-space-3);\n font-weight: 600;\n }\n\n .mj-view-toggle-label[_ngcontent-%COMP%] {\n font-size: var(--mj-text-xs);\n line-height: 1;\n white-space: nowrap;\n }\n\n .mj-view-toggle-btn[_ngcontent-%COMP%]:hover:not(.mj-view-toggle-btn--active) {\n background: color-mix(in srgb, var(--mj-bg-surface) 70%, transparent);\n color: var(--mj-text-primary);\n }\n\n .mj-view-toggle-btn--active[_ngcontent-%COMP%] {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px color-mix(in srgb, var(--mj-text-primary) 12%, transparent);\n }"] });
|
|
71
|
+
}
|
|
72
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MJViewToggleComponent, [{
|
|
73
|
+
type: Component,
|
|
74
|
+
args: [{ selector: 'mj-view-toggle', standalone: true, template: `
|
|
75
|
+
<div class="mj-view-toggle" role="group">
|
|
76
|
+
@for (opt of Options; track opt.key) {
|
|
77
|
+
<button
|
|
78
|
+
type="button"
|
|
79
|
+
class="mj-view-toggle-btn"
|
|
80
|
+
[class.mj-view-toggle-btn--active]="opt.key === ActiveKey"
|
|
81
|
+
[class.mj-view-toggle-btn--text]="!!opt.label"
|
|
82
|
+
[attr.aria-pressed]="opt.key === ActiveKey"
|
|
83
|
+
[attr.aria-label]="opt.title ?? opt.label"
|
|
84
|
+
[title]="opt.title ?? opt.label"
|
|
85
|
+
(click)="KeyChange.emit(opt.key)">
|
|
86
|
+
@if (opt.icon) {
|
|
87
|
+
<i [class]="opt.icon" aria-hidden="true"></i>
|
|
88
|
+
}
|
|
89
|
+
@if (opt.label) {
|
|
90
|
+
<span class="mj-view-toggle-label">{{ opt.label }}</span>
|
|
91
|
+
}
|
|
92
|
+
</button>
|
|
93
|
+
}
|
|
94
|
+
</div>
|
|
95
|
+
`, styles: ["\n :host { display: inline-flex; }\n\n .mj-view-toggle {\n display: inline-flex;\n gap: var(--mj-space-0-5);\n padding: 3px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n }\n\n .mj-view-toggle-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--mj-space-1-5);\n width: 28px;\n height: 28px;\n background: transparent;\n border: none;\n border-radius: var(--mj-radius-sm);\n color: var(--mj-text-muted);\n font-size: 13px;\n line-height: 1;\n cursor: pointer;\n transition: background-color 0.15s ease, color 0.15s ease;\n }\n\n /* Text-label mode: wider button with padding for the label. */\n .mj-view-toggle-btn--text {\n width: auto;\n padding: 0 var(--mj-space-3);\n font-weight: 600;\n }\n\n .mj-view-toggle-label {\n font-size: var(--mj-text-xs);\n line-height: 1;\n white-space: nowrap;\n }\n\n .mj-view-toggle-btn:hover:not(.mj-view-toggle-btn--active) {\n background: color-mix(in srgb, var(--mj-bg-surface) 70%, transparent);\n color: var(--mj-text-primary);\n }\n\n .mj-view-toggle-btn--active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px color-mix(in srgb, var(--mj-text-primary) 12%, transparent);\n }\n "] }]
|
|
96
|
+
}], null, { Options: [{
|
|
97
|
+
type: Input
|
|
98
|
+
}], ActiveKey: [{
|
|
99
|
+
type: Input
|
|
100
|
+
}], KeyChange: [{
|
|
101
|
+
type: Output
|
|
102
|
+
}] }); })();
|
|
103
|
+
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MJViewToggleComponent, { className: "MJViewToggleComponent", filePath: "lib/view-toggle/view-toggle.component.ts", lineNumber: 115 }); })();
|
|
104
|
+
//# sourceMappingURL=view-toggle.component.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-toggle.component.js","sourceRoot":"","sources":["../../../src/lib/view-toggle/view-toggle.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;;;IAmD3D,0BAA6C;;;IAA1C,0BAAkB;;;IAGrB,kCAAmC;IAAA,YAAe;IAAA,oBAAO;;;IAAtB,cAAe;IAAf,kCAAe;;;;IAbtD,oCAQoC;IAAlC,6MAAS,iCAAuB,KAAC;IACjC,2FAAgB;IAGhB,8FAAiB;IAGnB,oBAAS;;;;IAXP,AADA,6EAA0D,4CACZ;IAG9C,uDAAgC;;IAEhC,cAEC;IAFD,sCAEC;IACD,cAEC;IAFD,uCAEC;;AAzCX;;;;;;;;;;;;;;;;;;;;GAoBG;AAgFH,MAAM,OAAO,qBAAqB;IACvB,OAAO,GAAuB,EAAE,CAAC;IACjC,SAAS,GAAW,EAAE,CAAC;IACtB,SAAS,GAAG,IAAI,YAAY,EAAU,CAAC;+GAHtC,qBAAqB;6DAArB,qBAAqB;YA3E9B,iCAAyC;YACvC,2FAiBC;YACH,oBAAM;;YAlBJ,cAiBC;YAjBD,0BAiBC;;;iFAyDM,qBAAqB;cA/EjC,SAAS;2BACE,gBAAgB,cACd,IAAI,YACN;;;;;;;;;;;;;;;;;;;;;GAqBT;;kBAwDA,KAAK;;kBACL,KAAK;;kBACL,MAAM;;kFAHI,qBAAqB","sourcesContent":["import { Component, EventEmitter, Input, Output } from '@angular/core';\n\n/** Per-option config understood by <mj-view-toggle>. */\nexport interface ViewToggleOption {\n /** Unique key — emitted via (KeyChange) when clicked. */\n key: string;\n /** Font Awesome icon class (e.g. 'fa-solid fa-grip'). Optional when `label` is provided. */\n icon?: string;\n /** Visible text label. Optional — when omitted the option is icon-only. */\n label?: string;\n /** Tooltip / aria-label. Required when `label` is omitted (icon-only mode). */\n title?: string;\n}\n\n/**\n * mj-view-toggle — Compact icon-only segmented control for view-mode selection\n * (grid / list / tree / card etc.). Visually smaller than `<mj-tab-nav>` to signal\n * \"this is a view setting, not page navigation\".\n *\n * Example:\n * ```html\n * <mj-view-toggle\n * [Options]=\"viewOptions\"\n * [ActiveKey]=\"viewMode\"\n * (KeyChange)=\"setViewMode($event)\">\n * </mj-view-toggle>\n *\n * // In the component:\n * viewOptions = [\n * { key: 'grid', icon: 'fa-solid fa-grip', title: 'Grid View' },\n * { key: 'list', icon: 'fa-solid fa-list', title: 'List View' },\n * { key: 'tree', icon: 'fa-solid fa-folder-tree', title: 'Category Tree View' },\n * ];\n * ```\n */\n@Component({\n selector: 'mj-view-toggle',\n standalone: true,\n template: `\n <div class=\"mj-view-toggle\" role=\"group\">\n @for (opt of Options; track opt.key) {\n <button\n type=\"button\"\n class=\"mj-view-toggle-btn\"\n [class.mj-view-toggle-btn--active]=\"opt.key === ActiveKey\"\n [class.mj-view-toggle-btn--text]=\"!!opt.label\"\n [attr.aria-pressed]=\"opt.key === ActiveKey\"\n [attr.aria-label]=\"opt.title ?? opt.label\"\n [title]=\"opt.title ?? opt.label\"\n (click)=\"KeyChange.emit(opt.key)\">\n @if (opt.icon) {\n <i [class]=\"opt.icon\" aria-hidden=\"true\"></i>\n }\n @if (opt.label) {\n <span class=\"mj-view-toggle-label\">{{ opt.label }}</span>\n }\n </button>\n }\n </div>\n `,\n styles: [`\n :host { display: inline-flex; }\n\n .mj-view-toggle {\n display: inline-flex;\n gap: var(--mj-space-0-5);\n padding: 3px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: var(--mj-radius-md);\n }\n\n .mj-view-toggle-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--mj-space-1-5);\n width: 28px;\n height: 28px;\n background: transparent;\n border: none;\n border-radius: var(--mj-radius-sm);\n color: var(--mj-text-muted);\n font-size: 13px;\n line-height: 1;\n cursor: pointer;\n transition: background-color 0.15s ease, color 0.15s ease;\n }\n\n /* Text-label mode: wider button with padding for the label. */\n .mj-view-toggle-btn--text {\n width: auto;\n padding: 0 var(--mj-space-3);\n font-weight: 600;\n }\n\n .mj-view-toggle-label {\n font-size: var(--mj-text-xs);\n line-height: 1;\n white-space: nowrap;\n }\n\n .mj-view-toggle-btn:hover:not(.mj-view-toggle-btn--active) {\n background: color-mix(in srgb, var(--mj-bg-surface) 70%, transparent);\n color: var(--mj-text-primary);\n }\n\n .mj-view-toggle-btn--active {\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n box-shadow: 0 1px 2px color-mix(in srgb, var(--mj-text-primary) 12%, transparent);\n }\n `]\n})\nexport class MJViewToggleComponent {\n @Input() Options: ViewToggleOption[] = [];\n @Input() ActiveKey: string = '';\n @Output() KeyChange = new EventEmitter<string>();\n}\n"]}
|
package/dist/public-api.d.ts
CHANGED
|
@@ -11,4 +11,16 @@ export * from './lib/splitter/splitter.component';
|
|
|
11
11
|
export * from './lib/accordion/accordion.component';
|
|
12
12
|
export * from './lib/window/window.component';
|
|
13
13
|
export * from './lib/combobox/combobox.component';
|
|
14
|
+
export * from './lib/page-header/page-header.component';
|
|
15
|
+
export * from './lib/page-layout/page-layout.component';
|
|
16
|
+
export * from './lib/page-body/page-body.component';
|
|
17
|
+
export * from './lib/stat-badge/stat-badge.component';
|
|
18
|
+
export * from './lib/refresh-button/refresh-button.component';
|
|
19
|
+
export * from './lib/filter-popover/filter-popover.component';
|
|
20
|
+
export * from './lib/page-search/page-search.component';
|
|
21
|
+
export * from './lib/filter-chip/filter-chip.component';
|
|
22
|
+
export * from './lib/filter-field/filter-field.component';
|
|
23
|
+
export * from './lib/filter-panel/filter-panel.component';
|
|
24
|
+
export * from './lib/tab-nav/tab-nav.component';
|
|
25
|
+
export * from './lib/view-toggle/view-toggle.component';
|
|
14
26
|
//# sourceMappingURL=public-api.d.ts.map
|
package/dist/public-api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAGA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC"}
|
|
1
|
+
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAGA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC"}
|
package/dist/public-api.js
CHANGED
|
@@ -13,4 +13,16 @@ export * from './lib/splitter/splitter.component';
|
|
|
13
13
|
export * from './lib/accordion/accordion.component';
|
|
14
14
|
export * from './lib/window/window.component';
|
|
15
15
|
export * from './lib/combobox/combobox.component';
|
|
16
|
+
export * from './lib/page-header/page-header.component';
|
|
17
|
+
export * from './lib/page-layout/page-layout.component';
|
|
18
|
+
export * from './lib/page-body/page-body.component';
|
|
19
|
+
export * from './lib/stat-badge/stat-badge.component';
|
|
20
|
+
export * from './lib/refresh-button/refresh-button.component';
|
|
21
|
+
export * from './lib/filter-popover/filter-popover.component';
|
|
22
|
+
export * from './lib/page-search/page-search.component';
|
|
23
|
+
export * from './lib/filter-chip/filter-chip.component';
|
|
24
|
+
export * from './lib/filter-field/filter-field.component';
|
|
25
|
+
export * from './lib/filter-panel/filter-panel.component';
|
|
26
|
+
export * from './lib/tab-nav/tab-nav.component';
|
|
27
|
+
export * from './lib/view-toggle/view-toggle.component';
|
|
16
28
|
//# sourceMappingURL=public-api.js.map
|
package/dist/public-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,+DAA+D;AAE/D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC","sourcesContent":["// @memberjunction/ng-ui-components\n// Reusable standalone Angular UI components for MemberJunction\n\nexport * from './lib/button/button.directive';\nexport * from './lib/dialog/dialog.component';\nexport * from './lib/dialog/dialog.service';\nexport * from './lib/dropdown/dropdown.component';\nexport * from './lib/switch/switch.component';\nexport * from './lib/numeric-input/numeric-input.component';\nexport * from './lib/progress-bar/progress-bar.component';\nexport * from './lib/calendar/calendar-utils';\nexport * from './lib/datepicker/datepicker.component';\nexport * from './lib/splitter/splitter.component';\nexport * from './lib/accordion/accordion.component';\nexport * from './lib/window/window.component';\nexport * from './lib/combobox/combobox.component';\n"]}
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,+DAA+D;AAE/D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6CAA6C,CAAC;AAC5D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uCAAuC,CAAC;AACtD,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,qCAAqC,CAAC;AACpD,cAAc,uCAAuC,CAAC;AACtD,cAAc,+CAA+C,CAAC;AAC9D,cAAc,+CAA+C,CAAC;AAC9D,cAAc,yCAAyC,CAAC;AACxD,cAAc,yCAAyC,CAAC;AACxD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,2CAA2C,CAAC;AAC1D,cAAc,iCAAiC,CAAC;AAChD,cAAc,yCAAyC,CAAC","sourcesContent":["// @memberjunction/ng-ui-components\n// Reusable standalone Angular UI components for MemberJunction\n\nexport * from './lib/button/button.directive';\nexport * from './lib/dialog/dialog.component';\nexport * from './lib/dialog/dialog.service';\nexport * from './lib/dropdown/dropdown.component';\nexport * from './lib/switch/switch.component';\nexport * from './lib/numeric-input/numeric-input.component';\nexport * from './lib/progress-bar/progress-bar.component';\nexport * from './lib/calendar/calendar-utils';\nexport * from './lib/datepicker/datepicker.component';\nexport * from './lib/splitter/splitter.component';\nexport * from './lib/accordion/accordion.component';\nexport * from './lib/window/window.component';\nexport * from './lib/combobox/combobox.component';\nexport * from './lib/page-header/page-header.component';\nexport * from './lib/page-layout/page-layout.component';\nexport * from './lib/page-body/page-body.component';\nexport * from './lib/stat-badge/stat-badge.component';\nexport * from './lib/refresh-button/refresh-button.component';\nexport * from './lib/filter-popover/filter-popover.component';\nexport * from './lib/page-search/page-search.component';\nexport * from './lib/filter-chip/filter-chip.component';\nexport * from './lib/filter-field/filter-field.component';\nexport * from './lib/filter-panel/filter-panel.component';\nexport * from './lib/tab-nav/tab-nav.component';\nexport * from './lib/view-toggle/view-toggle.component';\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-ui-components",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.35.0",
|
|
4
4
|
"description": "MemberJunction: Angular UI Components - reusable standalone components replacing Kendo UI dependencies.",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"test": "vitest run",
|
|
12
12
|
"build": "npm run clean && ngc && npm run copy-assets",
|
|
13
|
-
"copy-assets": "cpy src/lib/button/button.scss dist/lib/button --flat && cpy src/lib/dialog/dialog.scss dist/lib/dialog --flat && cpy src/lib/dropdown/dropdown.scss dist/lib/dropdown --flat && cpy src/lib/combobox/combobox.scss dist/lib/combobox --flat && cpy src/lib/input/input.scss dist/lib/input --flat && cpy src/lib/input/input-switch-progress.scss dist/lib/input --flat && cpy src/lib/datepicker/datepicker.scss dist/lib/datepicker --flat && cpy src/lib/splitter/splitter.scss dist/lib/splitter --flat && cpy src/lib/accordion/accordion.scss dist/lib/accordion --flat && cpy src/lib/window/window.scss dist/lib/window --flat && cpy src/lib/input/chip.scss dist/lib/input --flat",
|
|
13
|
+
"copy-assets": "cpy src/lib/button/button.scss dist/lib/button --flat && cpy src/lib/dialog/dialog.scss dist/lib/dialog --flat && cpy src/lib/dropdown/dropdown.scss dist/lib/dropdown --flat && cpy src/lib/combobox/combobox.scss dist/lib/combobox --flat && cpy src/lib/input/input.scss dist/lib/input --flat && cpy src/lib/input/input-switch-progress.scss dist/lib/input --flat && cpy src/lib/datepicker/datepicker.scss dist/lib/datepicker --flat && cpy src/lib/splitter/splitter.scss dist/lib/splitter --flat && cpy src/lib/accordion/accordion.scss dist/lib/accordion --flat && cpy src/lib/window/window.scss dist/lib/window --flat && cpy src/lib/input/chip.scss dist/lib/input --flat && cpy src/lib/page-header/page-header.scss dist/lib/page-header --flat",
|
|
14
14
|
"clean": "rimraf dist",
|
|
15
15
|
"test:watch": "vitest"
|
|
16
16
|
},
|