@memberjunction/ng-versions 5.30.0 → 5.31.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.
@@ -19,6 +19,12 @@ export declare class MjSlidePanelComponent implements OnInit, OnDestroy {
19
19
  get WidthPx(): number;
20
20
  Closed: EventEmitter<void>;
21
21
  WidthChanged: EventEmitter<number>;
22
+ /**
23
+ * Optional guard called before any close gesture (X button, backdrop click, Escape).
24
+ * Return `false` to cancel the close — e.g., when an in-progress operation is running.
25
+ * The panel itself never shows a dialog; the consumer is responsible for any confirmation UI.
26
+ */
27
+ CanClose: (() => boolean) | null;
22
28
  IsVisible: boolean;
23
29
  private _widthPx;
24
30
  private isResizing;
@@ -34,6 +40,6 @@ export declare class MjSlidePanelComponent implements OnInit, OnDestroy {
34
40
  private onResizeMove;
35
41
  private onResizeEnd;
36
42
  static ɵfac: i0.ɵɵFactoryDeclaration<MjSlidePanelComponent, never>;
37
- static ɵcmp: i0.ɵɵComponentDeclaration<MjSlidePanelComponent, "mj-slide-panel", never, { "Mode": { "alias": "Mode"; "required": false; }; "Title": { "alias": "Title"; "required": false; }; "Visible": { "alias": "Visible"; "required": false; }; "Resizable": { "alias": "Resizable"; "required": false; }; "MinWidthPx": { "alias": "MinWidthPx"; "required": false; }; "MaxWidthRatio": { "alias": "MaxWidthRatio"; "required": false; }; "WidthPx": { "alias": "WidthPx"; "required": false; }; }, { "Closed": "Closed"; "WidthChanged": "WidthChanged"; }, never, ["*", "[dialog-content]"], false, never>;
43
+ static ɵcmp: i0.ɵɵComponentDeclaration<MjSlidePanelComponent, "mj-slide-panel", never, { "Mode": { "alias": "Mode"; "required": false; }; "Title": { "alias": "Title"; "required": false; }; "Visible": { "alias": "Visible"; "required": false; }; "Resizable": { "alias": "Resizable"; "required": false; }; "MinWidthPx": { "alias": "MinWidthPx"; "required": false; }; "MaxWidthRatio": { "alias": "MaxWidthRatio"; "required": false; }; "WidthPx": { "alias": "WidthPx"; "required": false; }; "CanClose": { "alias": "CanClose"; "required": false; }; }, { "Closed": "Closed"; "WidthChanged": "WidthChanged"; }, never, ["*", "[dialog-content]"], false, never>;
38
44
  }
39
45
  //# sourceMappingURL=slide-panel.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"slide-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/panel/slide-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAyC,UAAU,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACxK,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;;AAE1C,qBAOa,qBAAsB,YAAW,MAAM,EAAE,SAAS;IAkDvD,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,KAAK;IAnDR,IAAI,EAAE,cAAc,CAAW;IAC/B,KAAK,SAAM;IACpB,IACI,OAAO,CAAC,KAAK,EAAE,OAAO,EAezB;IACD,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,WAAW,CAAS;IAEnB,SAAS,UAAQ;IACjB,UAAU,SAAO;IACjB,aAAa,SAAQ;IAE9B,wFAAwF;IACxF,IACI,OAAO,CAAC,KAAK,EAAE,MAAM,EAExB;IACD,IAAI,OAAO,IAAI,MAAM,CAEpB;IAES,MAAM,qBAA4B;IAClC,YAAY,uBAA8B;IAE7C,SAAS,UAAS;IACzB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,iBAAiB,CAAgC;IACzD,OAAO,CAAC,gBAAgB,CAA+B;gBAG3C,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,UAAU;IAG7B,QAAQ,IAAI,IAAI;IAkBhB,WAAW,IAAI,IAAI;IAMZ,WAAW,IAAI,IAAI;IAInB,OAAO,IAAI,IAAI;IAQf,eAAe,IAAI,IAAI;IAQvB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAa7C,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,WAAW;yCAxHV,qBAAqB;2CAArB,qBAAqB;CAiIjC"}
1
+ {"version":3,"file":"slide-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/panel/slide-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAyC,UAAU,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACxK,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;;AAE1C,qBAOa,qBAAsB,YAAW,MAAM,EAAE,SAAS;IAyDvD,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,KAAK;IA1DR,IAAI,EAAE,cAAc,CAAW;IAC/B,KAAK,SAAM;IACpB,IACI,OAAO,CAAC,KAAK,EAAE,OAAO,EAezB;IACD,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,WAAW,CAAS;IAEnB,SAAS,UAAQ;IACjB,UAAU,SAAO;IACjB,aAAa,SAAQ;IAE9B,wFAAwF;IACxF,IACI,OAAO,CAAC,KAAK,EAAE,MAAM,EAExB;IACD,IAAI,OAAO,IAAI,MAAM,CAEpB;IAES,MAAM,qBAA4B;IAClC,YAAY,uBAA8B;IAEpD;;;;OAIG;IACM,QAAQ,EAAE,CAAC,MAAM,OAAO,CAAC,GAAG,IAAI,CAAQ;IAE1C,SAAS,UAAS;IACzB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,iBAAiB,CAAgC;IACzD,OAAO,CAAC,gBAAgB,CAA+B;gBAG3C,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,UAAU;IAG7B,QAAQ,IAAI,IAAI;IAkBhB,WAAW,IAAI,IAAI;IAMZ,WAAW,IAAI,IAAI;IAInB,OAAO,IAAI,IAAI;IASf,eAAe,IAAI,IAAI;IAQvB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAa7C,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,WAAW;yCAhIV,qBAAqB;2CAArB,qBAAqB;CAyIjC"}
@@ -32,7 +32,7 @@ function MjSlidePanelComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
32
32
  i0.ɵɵelementEnd()();
33
33
  } if (rf & 2) {
34
34
  const ctx_r1 = i0.ɵɵnextContext();
35
- i0.ɵɵstyleProp("width", ctx_r1.WidthPx, "px");
35
+ i0.ɵɵstyleProp("width", ctx_r1.WidthPx, "px")("max-width", ctx_r1.MaxWidthRatio * 100 + "vw");
36
36
  i0.ɵɵclassProp("visible", ctx_r1.IsVisible);
37
37
  i0.ɵɵadvance();
38
38
  i0.ɵɵconditional(ctx_r1.Resizable ? 1 : -1);
@@ -106,6 +106,12 @@ export class MjSlidePanelComponent {
106
106
  }
107
107
  Closed = new EventEmitter();
108
108
  WidthChanged = new EventEmitter();
109
+ /**
110
+ * Optional guard called before any close gesture (X button, backdrop click, Escape).
111
+ * Return `false` to cancel the close — e.g., when an in-progress operation is running.
112
+ * The panel itself never shows a dialog; the consumer is responsible for any confirmation UI.
113
+ */
114
+ CanClose = null;
109
115
  IsVisible = false;
110
116
  _widthPx = 0;
111
117
  isResizing = false;
@@ -139,6 +145,8 @@ export class MjSlidePanelComponent {
139
145
  this.OnClose();
140
146
  }
141
147
  OnClose() {
148
+ if (this.CanClose && !this.CanClose())
149
+ return;
142
150
  this.IsVisible = false;
143
151
  this._visible = false;
144
152
  this.cdr.markForCheck();
@@ -184,12 +192,12 @@ export class MjSlidePanelComponent {
184
192
  static ɵfac = function MjSlidePanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MjSlidePanelComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.NgZone), i0.ɵɵdirectiveInject(i0.ElementRef)); };
185
193
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MjSlidePanelComponent, selectors: [["mj-slide-panel"]], hostBindings: function MjSlidePanelComponent_HostBindings(rf, ctx) { if (rf & 1) {
186
194
  i0.ɵɵlistener("keydown.escape", function MjSlidePanelComponent_keydown_escape_HostBindingHandler() { return ctx.OnEscapeKey(); }, i0.ɵɵresolveDocument);
187
- } }, inputs: { Mode: "Mode", Title: "Title", Visible: "Visible", Resizable: "Resizable", MinWidthPx: "MinWidthPx", MaxWidthRatio: "MaxWidthRatio", WidthPx: "WidthPx" }, outputs: { Closed: "Closed", WidthChanged: "WidthChanged" }, standalone: false, ngContentSelectors: _c1, decls: 3, vars: 6, consts: [[1, "sp-backdrop", 3, "click"], [1, "sp-panel", 3, "visible", "width"], [1, "sp-dialog", 3, "visible", "width"], [1, "sp-panel"], [1, "sp-resize-handle"], [1, "sp-header"], [1, "sp-body"], [1, "sp-resize-handle", 3, "mousedown"], [1, "sp-resize-grip"], [1, "sp-title"], [1, "sp-close-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "sp-dialog"], [1, "sp-body", "sp-dialog-body"]], template: function MjSlidePanelComponent_Template(rf, ctx) { if (rf & 1) {
195
+ } }, inputs: { Mode: "Mode", Title: "Title", Visible: "Visible", Resizable: "Resizable", MinWidthPx: "MinWidthPx", MaxWidthRatio: "MaxWidthRatio", WidthPx: "WidthPx", CanClose: "CanClose" }, outputs: { Closed: "Closed", WidthChanged: "WidthChanged" }, standalone: false, ngContentSelectors: _c1, decls: 3, vars: 6, consts: [[1, "sp-backdrop", 3, "click"], [1, "sp-panel", 3, "visible", "width", "max-width"], [1, "sp-dialog", 3, "visible", "width"], [1, "sp-panel"], [1, "sp-resize-handle"], [1, "sp-header"], [1, "sp-body"], [1, "sp-resize-handle", 3, "mousedown"], [1, "sp-resize-grip"], [1, "sp-title"], [1, "sp-close-btn", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "sp-dialog"], [1, "sp-body", "sp-dialog-body"]], template: function MjSlidePanelComponent_Template(rf, ctx) { if (rf & 1) {
188
196
  i0.ɵɵprojectionDef(_c0);
189
197
  i0.ɵɵelementStart(0, "div", 0);
190
198
  i0.ɵɵlistener("click", function MjSlidePanelComponent_Template_div_click_0_listener() { return ctx.OnBackdropClick(); });
191
199
  i0.ɵɵelementEnd();
192
- i0.ɵɵconditionalCreate(1, MjSlidePanelComponent_Conditional_1_Template, 5, 6, "div", 1);
200
+ i0.ɵɵconditionalCreate(1, MjSlidePanelComponent_Conditional_1_Template, 5, 8, "div", 1);
193
201
  i0.ɵɵconditionalCreate(2, MjSlidePanelComponent_Conditional_2_Template, 4, 5, "div", 2);
194
202
  } if (rf & 2) {
195
203
  i0.ɵɵclassProp("visible", ctx.IsVisible)("sp-dialog-backdrop", ctx.Mode === "dialog");
@@ -201,7 +209,7 @@ export class MjSlidePanelComponent {
201
209
  }
202
210
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MjSlidePanelComponent, [{
203
211
  type: Component,
204
- args: [{ standalone: false, selector: 'mj-slide-panel', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Backdrop overlay -->\n<div class=\"sp-backdrop\"\n [class.visible]=\"IsVisible\"\n [class.sp-dialog-backdrop]=\"Mode === 'dialog'\"\n (click)=\"OnBackdropClick()\">\n</div>\n\n<!-- Panel (slide-in from right) -->\n@if (Mode === 'slide') {\n <div\n class=\"sp-panel\"\n [class.visible]=\"IsVisible\"\n [style.width.px]=\"WidthPx\">\n <!-- Resize handle -->\n @if (Resizable) {\n <div class=\"sp-resize-handle\" (mousedown)=\"OnResizeStart($event)\">\n <div class=\"sp-resize-grip\"></div>\n </div>\n }\n <!-- Header (if Title provided) -->\n @if (Title) {\n <div class=\"sp-header\">\n <h2 class=\"sp-title\">{{Title}}</h2>\n <button class=\"sp-close-btn\" (click)=\"OnClose()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n <!-- Content projection -->\n <div class=\"sp-body\">\n <ng-content></ng-content>\n </div>\n </div>\n}\n\n<!-- Dialog (centered modal) -->\n@if (Mode === 'dialog') {\n <div\n class=\"sp-dialog\"\n [class.visible]=\"IsVisible\"\n [style.width.px]=\"WidthPx\">\n <!-- Header (if Title provided) -->\n @if (Title) {\n <div class=\"sp-header\">\n <h2 class=\"sp-title\">{{Title}}</h2>\n <button class=\"sp-close-btn\" (click)=\"OnClose()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n <!-- Content projection -->\n <div class=\"sp-body sp-dialog-body\">\n <ng-content select=\"[dialog-content]\"></ng-content>\n </div>\n </div>\n}\n", styles: ["/* ================================================================= */\n/* BACKDROP */\n/* ================================================================= */\n\n.sp-backdrop {\n position: fixed;\n inset: 0;\n background: transparent;\n z-index: 1000;\n transition: background 0.3s ease;\n pointer-events: none;\n}\n\n.sp-backdrop.visible {\n background: var(--mj-bg-overlay);\n pointer-events: auto;\n}\n\n.sp-dialog-backdrop.visible {\n background: var(--mj-bg-overlay);\n}\n\n/* ================================================================= */\n/* SLIDE PANEL */\n/* ================================================================= */\n\n.sp-panel {\n position: fixed;\n top: 0;\n right: 0;\n height: 100vh;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-lg);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n min-width: 400px;\n max-width: 92vw;\n}\n\n.sp-panel.visible {\n transform: translateX(0);\n}\n\n/* ================================================================= */\n/* DIALOG (centered modal) */\n/* ================================================================= */\n\n.sp-dialog {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%) scale(0.95);\n max-height: 85vh;\n background: var(--mj-bg-surface);\n border-radius: 16px;\n box-shadow: var(--mj-shadow-lg);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n opacity: 0;\n transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n min-width: 360px;\n max-width: 95vw;\n}\n\n.sp-dialog.visible {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n}\n\n/* ================================================================= */\n/* RESIZE HANDLE */\n/* ================================================================= */\n\n.sp-resize-handle {\n position: absolute;\n left: -4px;\n top: 0;\n width: 8px;\n height: 100%;\n cursor: col-resize;\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.sp-resize-handle:hover .sp-resize-grip,\n.sp-resize-handle:active .sp-resize-grip {\n opacity: 1;\n background: var(--mj-brand-primary);\n}\n\n.sp-resize-grip {\n width: 3px;\n height: 40px;\n background: var(--mj-border-strong);\n border-radius: 3px;\n opacity: 0;\n transition: opacity 0.2s ease, background 0.2s ease;\n}\n\n.sp-resize-handle:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 4%, transparent);\n}\n\n/* ================================================================= */\n/* HEADER */\n/* ================================================================= */\n\n.sp-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.sp-title {\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n}\n\n.sp-close-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: none;\n border: none;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s ease;\n font-size: 16px;\n flex-shrink: 0;\n}\n\n.sp-close-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n/* ================================================================= */\n/* BODY */\n/* ================================================================= */\n\n.sp-body {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n.sp-dialog-body {\n padding: 0;\n}\n\n/* ================================================================= */\n/* RESPONSIVE */\n/* ================================================================= */\n\n@media (max-width: 768px) {\n .sp-panel {\n width: 100% !important;\n min-width: unset;\n }\n\n .sp-resize-handle {\n display: none;\n }\n\n .sp-dialog {\n width: 95vw !important;\n max-height: 90vh;\n }\n}\n"] }]
212
+ args: [{ standalone: false, selector: 'mj-slide-panel', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Backdrop overlay -->\n<div class=\"sp-backdrop\"\n [class.visible]=\"IsVisible\"\n [class.sp-dialog-backdrop]=\"Mode === 'dialog'\"\n (click)=\"OnBackdropClick()\">\n</div>\n\n<!-- Panel (slide-in from right) -->\n@if (Mode === 'slide') {\n <div\n class=\"sp-panel\"\n [class.visible]=\"IsVisible\"\n [style.width.px]=\"WidthPx\"\n [style.max-width]=\"(MaxWidthRatio * 100) + 'vw'\">\n <!-- Resize handle -->\n @if (Resizable) {\n <div class=\"sp-resize-handle\" (mousedown)=\"OnResizeStart($event)\">\n <div class=\"sp-resize-grip\"></div>\n </div>\n }\n <!-- Header (if Title provided) -->\n @if (Title) {\n <div class=\"sp-header\">\n <h2 class=\"sp-title\">{{Title}}</h2>\n <button class=\"sp-close-btn\" (click)=\"OnClose()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n <!-- Content projection -->\n <div class=\"sp-body\">\n <ng-content></ng-content>\n </div>\n </div>\n}\n\n<!-- Dialog (centered modal) -->\n@if (Mode === 'dialog') {\n <div\n class=\"sp-dialog\"\n [class.visible]=\"IsVisible\"\n [style.width.px]=\"WidthPx\">\n <!-- Header (if Title provided) -->\n @if (Title) {\n <div class=\"sp-header\">\n <h2 class=\"sp-title\">{{Title}}</h2>\n <button class=\"sp-close-btn\" (click)=\"OnClose()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n <!-- Content projection -->\n <div class=\"sp-body sp-dialog-body\">\n <ng-content select=\"[dialog-content]\"></ng-content>\n </div>\n </div>\n}\n", styles: ["/* ================================================================= */\n/* BACKDROP */\n/* ================================================================= */\n\n.sp-backdrop {\n position: fixed;\n inset: 0;\n background: transparent;\n z-index: 1000;\n transition: background 0.3s ease;\n pointer-events: none;\n}\n\n.sp-backdrop.visible {\n background: var(--mj-bg-overlay);\n pointer-events: auto;\n}\n\n.sp-dialog-backdrop.visible {\n background: var(--mj-bg-overlay);\n}\n\n/* ================================================================= */\n/* SLIDE PANEL */\n/* ================================================================= */\n\n.sp-panel {\n position: fixed;\n top: 0;\n right: 0;\n height: 100vh;\n background: var(--mj-bg-surface);\n box-shadow: var(--mj-shadow-lg);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n transform: translateX(100%);\n transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);\n min-width: 400px;\n max-width: 92vw;\n}\n\n.sp-panel.visible {\n transform: translateX(0);\n}\n\n/* ================================================================= */\n/* DIALOG (centered modal) */\n/* ================================================================= */\n\n.sp-dialog {\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%) scale(0.95);\n max-height: 85vh;\n background: var(--mj-bg-surface);\n border-radius: 16px;\n box-shadow: var(--mj-shadow-lg);\n z-index: 1001;\n display: flex;\n flex-direction: column;\n opacity: 0;\n transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);\n min-width: 360px;\n max-width: 95vw;\n}\n\n.sp-dialog.visible {\n opacity: 1;\n transform: translate(-50%, -50%) scale(1);\n}\n\n/* ================================================================= */\n/* RESIZE HANDLE */\n/* ================================================================= */\n\n.sp-resize-handle {\n position: absolute;\n left: -4px;\n top: 0;\n width: 8px;\n height: 100%;\n cursor: col-resize;\n z-index: 10;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.sp-resize-handle:hover .sp-resize-grip,\n.sp-resize-handle:active .sp-resize-grip {\n opacity: 1;\n background: var(--mj-brand-primary);\n}\n\n.sp-resize-grip {\n width: 3px;\n height: 40px;\n background: var(--mj-border-strong);\n border-radius: 3px;\n opacity: 0;\n transition: opacity 0.2s ease, background 0.2s ease;\n}\n\n.sp-resize-handle:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 4%, transparent);\n}\n\n/* ================================================================= */\n/* HEADER */\n/* ================================================================= */\n\n.sp-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 24px;\n border-bottom: 1px solid var(--mj-border-default);\n flex-shrink: 0;\n}\n\n.sp-title {\n font-size: 18px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n}\n\n.sp-close-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: none;\n border: none;\n border-radius: 8px;\n color: var(--mj-text-secondary);\n cursor: pointer;\n transition: all 0.15s ease;\n font-size: 16px;\n flex-shrink: 0;\n}\n\n.sp-close-btn:hover {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-primary);\n}\n\n/* ================================================================= */\n/* BODY */\n/* ================================================================= */\n\n.sp-body {\n flex: 1;\n overflow-y: auto;\n overflow-x: hidden;\n}\n\n.sp-dialog-body {\n padding: 0;\n}\n\n/* ================================================================= */\n/* RESPONSIVE */\n/* ================================================================= */\n\n@media (max-width: 768px) {\n .sp-panel {\n width: 100% !important;\n min-width: unset;\n }\n\n .sp-resize-handle {\n display: none;\n }\n\n .sp-dialog {\n width: 95vw !important;\n max-height: 90vh;\n }\n}\n"] }]
205
213
  }], () => [{ type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: i0.ElementRef }], { Mode: [{
206
214
  type: Input
207
215
  }], Title: [{
@@ -220,6 +228,8 @@ export class MjSlidePanelComponent {
220
228
  type: Output
221
229
  }], WidthChanged: [{
222
230
  type: Output
231
+ }], CanClose: [{
232
+ type: Input
223
233
  }], OnEscapeKey: [{
224
234
  type: HostListener,
225
235
  args: ['document:keydown.escape']
@@ -1 +1 @@
1
- {"version":3,"file":"slide-panel.component.js","sourceRoot":"","sources":["../../../src/lib/panel/slide-panel.component.ts","../../../src/lib/panel/slide-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy, HostListener, ElementRef, NgZone } from '@angular/core';\nimport { SlidePanelMode } from '../types';\n\n@Component({\n standalone: false,\n selector: 'mj-slide-panel',\n templateUrl: './slide-panel.component.html',\n styleUrls: ['./slide-panel.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class MjSlidePanelComponent implements OnInit, OnDestroy {\n @Input() Mode: SlidePanelMode = 'slide';\n @Input() Title = '';\n @Input()\n set Visible(value: boolean) {\n const changed = this._visible !== value;\n this._visible = value;\n if (changed && this.initialized) {\n if (value) {\n // Opening: animate in on next microtask\n Promise.resolve().then(() => {\n this.IsVisible = true;\n this.cdr.markForCheck();\n });\n } else {\n this.IsVisible = false;\n this.cdr.markForCheck();\n }\n }\n }\n get Visible(): boolean {\n return this._visible;\n }\n private _visible = true;\n private initialized = false;\n\n @Input() Resizable = true;\n @Input() MinWidthPx = 400;\n @Input() MaxWidthRatio = 0.92;\n\n /** Initial width in pixels. Defaults to 65% of viewport for slide, 800px for dialog. */\n @Input()\n set WidthPx(value: number) {\n this._widthPx = value;\n }\n get WidthPx(): number {\n return this._widthPx;\n }\n\n @Output() Closed = new EventEmitter<void>();\n @Output() WidthChanged = new EventEmitter<number>();\n\n public IsVisible = false;\n private _widthPx = 0;\n private isResizing = false;\n\n private boundOnResizeMove = this.onResizeMove.bind(this);\n private boundOnResizeEnd = this.onResizeEnd.bind(this);\n\n constructor(\n private cdr: ChangeDetectorRef,\n private ngZone: NgZone,\n private elRef: ElementRef\n ) {}\n\n ngOnInit(): void {\n if (this._widthPx === 0) {\n this._widthPx = this.Mode === 'dialog'\n ? 800\n : Math.max(this.MinWidthPx, Math.min(window.innerWidth * 0.65, 1000));\n }\n\n this.initialized = true;\n\n // Animate in on next microtask if initially visible\n if (this._visible) {\n Promise.resolve().then(() => {\n this.IsVisible = true;\n this.cdr.markForCheck();\n });\n }\n }\n\n ngOnDestroy(): void {\n document.removeEventListener('mousemove', this.boundOnResizeMove);\n document.removeEventListener('mouseup', this.boundOnResizeEnd);\n }\n\n @HostListener('document:keydown.escape')\n public OnEscapeKey(): void {\n this.OnClose();\n }\n\n public OnClose(): void {\n this.IsVisible = false;\n this._visible = false;\n this.cdr.markForCheck();\n // Wait for CSS transition to complete\n setTimeout(() => this.Closed.emit(), 300);\n }\n\n public OnBackdropClick(): void {\n this.OnClose();\n }\n\n // =========================================================================\n // Resize\n // =========================================================================\n\n public OnResizeStart(event: MouseEvent): void {\n if (!this.Resizable || this.Mode === 'dialog') return;\n event.preventDefault();\n this.isResizing = true;\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n\n this.ngZone.runOutsideAngular(() => {\n document.addEventListener('mousemove', this.boundOnResizeMove);\n document.addEventListener('mouseup', this.boundOnResizeEnd);\n });\n }\n\n private onResizeMove(event: MouseEvent): void {\n if (!this.isResizing) return;\n const viewportWidth = window.innerWidth;\n const maxWidth = viewportWidth * this.MaxWidthRatio;\n this._widthPx = Math.max(this.MinWidthPx, Math.min(maxWidth, viewportWidth - event.clientX));\n this.ngZone.run(() => this.cdr.markForCheck());\n }\n\n private onResizeEnd(): void {\n if (!this.isResizing) return;\n this.isResizing = false;\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n document.removeEventListener('mousemove', this.boundOnResizeMove);\n document.removeEventListener('mouseup', this.boundOnResizeEnd);\n this.WidthChanged.emit(this._widthPx);\n }\n}\n","<!-- Backdrop overlay -->\n<div class=\"sp-backdrop\"\n [class.visible]=\"IsVisible\"\n [class.sp-dialog-backdrop]=\"Mode === 'dialog'\"\n (click)=\"OnBackdropClick()\">\n</div>\n\n<!-- Panel (slide-in from right) -->\n@if (Mode === 'slide') {\n <div\n class=\"sp-panel\"\n [class.visible]=\"IsVisible\"\n [style.width.px]=\"WidthPx\">\n <!-- Resize handle -->\n @if (Resizable) {\n <div class=\"sp-resize-handle\" (mousedown)=\"OnResizeStart($event)\">\n <div class=\"sp-resize-grip\"></div>\n </div>\n }\n <!-- Header (if Title provided) -->\n @if (Title) {\n <div class=\"sp-header\">\n <h2 class=\"sp-title\">{{Title}}</h2>\n <button class=\"sp-close-btn\" (click)=\"OnClose()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n <!-- Content projection -->\n <div class=\"sp-body\">\n <ng-content></ng-content>\n </div>\n </div>\n}\n\n<!-- Dialog (centered modal) -->\n@if (Mode === 'dialog') {\n <div\n class=\"sp-dialog\"\n [class.visible]=\"IsVisible\"\n [style.width.px]=\"WidthPx\">\n <!-- Header (if Title provided) -->\n @if (Title) {\n <div class=\"sp-header\">\n <h2 class=\"sp-title\">{{Title}}</h2>\n <button class=\"sp-close-btn\" (click)=\"OnClose()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n <!-- Content projection -->\n <div class=\"sp-body sp-dialog-body\">\n <ng-content select=\"[dialog-content]\"></ng-content>\n </div>\n </div>\n}\n"]}
1
+ {"version":3,"file":"slide-panel.component.js","sourceRoot":"","sources":["../../../src/lib/panel/slide-panel.component.ts","../../../src/lib/panel/slide-panel.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, OnDestroy, ChangeDetectorRef, ChangeDetectionStrategy, HostListener, ElementRef, NgZone } from '@angular/core';\nimport { SlidePanelMode } from '../types';\n\n@Component({\n standalone: false,\n selector: 'mj-slide-panel',\n templateUrl: './slide-panel.component.html',\n styleUrls: ['./slide-panel.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class MjSlidePanelComponent implements OnInit, OnDestroy {\n @Input() Mode: SlidePanelMode = 'slide';\n @Input() Title = '';\n @Input()\n set Visible(value: boolean) {\n const changed = this._visible !== value;\n this._visible = value;\n if (changed && this.initialized) {\n if (value) {\n // Opening: animate in on next microtask\n Promise.resolve().then(() => {\n this.IsVisible = true;\n this.cdr.markForCheck();\n });\n } else {\n this.IsVisible = false;\n this.cdr.markForCheck();\n }\n }\n }\n get Visible(): boolean {\n return this._visible;\n }\n private _visible = true;\n private initialized = false;\n\n @Input() Resizable = true;\n @Input() MinWidthPx = 400;\n @Input() MaxWidthRatio = 0.92;\n\n /** Initial width in pixels. Defaults to 65% of viewport for slide, 800px for dialog. */\n @Input()\n set WidthPx(value: number) {\n this._widthPx = value;\n }\n get WidthPx(): number {\n return this._widthPx;\n }\n\n @Output() Closed = new EventEmitter<void>();\n @Output() WidthChanged = new EventEmitter<number>();\n\n /**\n * Optional guard called before any close gesture (X button, backdrop click, Escape).\n * Return `false` to cancel the close — e.g., when an in-progress operation is running.\n * The panel itself never shows a dialog; the consumer is responsible for any confirmation UI.\n */\n @Input() CanClose: (() => boolean) | null = null;\n\n public IsVisible = false;\n private _widthPx = 0;\n private isResizing = false;\n\n private boundOnResizeMove = this.onResizeMove.bind(this);\n private boundOnResizeEnd = this.onResizeEnd.bind(this);\n\n constructor(\n private cdr: ChangeDetectorRef,\n private ngZone: NgZone,\n private elRef: ElementRef\n ) {}\n\n ngOnInit(): void {\n if (this._widthPx === 0) {\n this._widthPx = this.Mode === 'dialog'\n ? 800\n : Math.max(this.MinWidthPx, Math.min(window.innerWidth * 0.65, 1000));\n }\n\n this.initialized = true;\n\n // Animate in on next microtask if initially visible\n if (this._visible) {\n Promise.resolve().then(() => {\n this.IsVisible = true;\n this.cdr.markForCheck();\n });\n }\n }\n\n ngOnDestroy(): void {\n document.removeEventListener('mousemove', this.boundOnResizeMove);\n document.removeEventListener('mouseup', this.boundOnResizeEnd);\n }\n\n @HostListener('document:keydown.escape')\n public OnEscapeKey(): void {\n this.OnClose();\n }\n\n public OnClose(): void {\n if (this.CanClose && !this.CanClose()) return;\n this.IsVisible = false;\n this._visible = false;\n this.cdr.markForCheck();\n // Wait for CSS transition to complete\n setTimeout(() => this.Closed.emit(), 300);\n }\n\n public OnBackdropClick(): void {\n this.OnClose();\n }\n\n // =========================================================================\n // Resize\n // =========================================================================\n\n public OnResizeStart(event: MouseEvent): void {\n if (!this.Resizable || this.Mode === 'dialog') return;\n event.preventDefault();\n this.isResizing = true;\n document.body.style.cursor = 'col-resize';\n document.body.style.userSelect = 'none';\n\n this.ngZone.runOutsideAngular(() => {\n document.addEventListener('mousemove', this.boundOnResizeMove);\n document.addEventListener('mouseup', this.boundOnResizeEnd);\n });\n }\n\n private onResizeMove(event: MouseEvent): void {\n if (!this.isResizing) return;\n const viewportWidth = window.innerWidth;\n const maxWidth = viewportWidth * this.MaxWidthRatio;\n this._widthPx = Math.max(this.MinWidthPx, Math.min(maxWidth, viewportWidth - event.clientX));\n this.ngZone.run(() => this.cdr.markForCheck());\n }\n\n private onResizeEnd(): void {\n if (!this.isResizing) return;\n this.isResizing = false;\n document.body.style.cursor = '';\n document.body.style.userSelect = '';\n document.removeEventListener('mousemove', this.boundOnResizeMove);\n document.removeEventListener('mouseup', this.boundOnResizeEnd);\n this.WidthChanged.emit(this._widthPx);\n }\n}\n","<!-- Backdrop overlay -->\n<div class=\"sp-backdrop\"\n [class.visible]=\"IsVisible\"\n [class.sp-dialog-backdrop]=\"Mode === 'dialog'\"\n (click)=\"OnBackdropClick()\">\n</div>\n\n<!-- Panel (slide-in from right) -->\n@if (Mode === 'slide') {\n <div\n class=\"sp-panel\"\n [class.visible]=\"IsVisible\"\n [style.width.px]=\"WidthPx\"\n [style.max-width]=\"(MaxWidthRatio * 100) + 'vw'\">\n <!-- Resize handle -->\n @if (Resizable) {\n <div class=\"sp-resize-handle\" (mousedown)=\"OnResizeStart($event)\">\n <div class=\"sp-resize-grip\"></div>\n </div>\n }\n <!-- Header (if Title provided) -->\n @if (Title) {\n <div class=\"sp-header\">\n <h2 class=\"sp-title\">{{Title}}</h2>\n <button class=\"sp-close-btn\" (click)=\"OnClose()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n <!-- Content projection -->\n <div class=\"sp-body\">\n <ng-content></ng-content>\n </div>\n </div>\n}\n\n<!-- Dialog (centered modal) -->\n@if (Mode === 'dialog') {\n <div\n class=\"sp-dialog\"\n [class.visible]=\"IsVisible\"\n [style.width.px]=\"WidthPx\">\n <!-- Header (if Title provided) -->\n @if (Title) {\n <div class=\"sp-header\">\n <h2 class=\"sp-title\">{{Title}}</h2>\n <button class=\"sp-close-btn\" (click)=\"OnClose()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n }\n <!-- Content projection -->\n <div class=\"sp-body sp-dialog-body\">\n <ng-content select=\"[dialog-content]\"></ng-content>\n </div>\n </div>\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { EventEmitter, OnInit, ChangeDetectorRef } from '@angular/core';
2
2
  import { CompositeKey } from '@memberjunction/core';
3
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
3
4
  import { MicroViewData } from '../types';
4
5
  import * as i0 from "@angular/core";
5
6
  interface FieldDisplay {
@@ -28,7 +29,7 @@ export interface EntityLinkClickEvent {
28
29
  RecordID: string;
29
30
  CompositeKey: CompositeKey;
30
31
  }
31
- export declare class MjRecordMicroViewComponent implements OnInit {
32
+ export declare class MjRecordMicroViewComponent extends BaseAngularComponent implements OnInit {
32
33
  private cdr;
33
34
  Data: MicroViewData;
34
35
  Inline: boolean;
@@ -46,7 +47,7 @@ export declare class MjRecordMicroViewComponent implements OnInit {
46
47
  RecordDisplayName: string;
47
48
  /** Icon CSS class from EntityInfo.Icon, falls back to 'fa-solid fa-table' */
48
49
  EntityIcon: string;
49
- private metadata;
50
+ private get metadata();
50
51
  constructor(cdr: ChangeDetectorRef);
51
52
  ngOnInit(): void;
52
53
  OnEscapeKey(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"record-micro-view.component.d.ts","sourceRoot":"","sources":["../../../src/lib/record-micro-view/record-micro-view.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,YAAY,EAAE,MAAM,EAAE,iBAAiB,EAAyC,MAAM,eAAe,CAAC;AACzI,OAAO,EAAiC,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEnF,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;;AAEzC,UAAU,YAAY;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,kGAAkG;IAClG,sBAAsB,EAAE,MAAM,CAAC;IAC/B,kEAAkE;IAClE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,+CAA+C;IAC/C,kBAAkB,EAAE,MAAM,CAAC;CAC9B;AAMD,uEAAuE;AACvE,MAAM,WAAW,oBAAoB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,YAAY,CAAC;CAC9B;AAED,qBAOa,0BAA2B,YAAW,MAAM;IAwBzC,OAAO,CAAC,GAAG;IAvBd,IAAI,EAAG,aAAa,CAAC;IACrB,MAAM,UAAS;IACd,KAAK,qBAA4B;IACjC,eAAe,qCAA4C;IAC3D,UAAU,qCAA4C;IAEzD,SAAS,UAAQ;IACjB,SAAS,UAAS;IAClB,MAAM,EAAE,YAAY,EAAE,CAAM;IAC5B,YAAY,SAAM;IAClB,cAAc,UAAS;IAE9B,oFAAoF;IAC7E,eAAe,SAAM;IAE5B,6DAA6D;IACtD,iBAAiB,SAAM;IAE9B,6EAA6E;IACtE,UAAU,SAAuB;IAExC,OAAO,CAAC,QAAQ,CAAkB;gBAEd,GAAG,EAAE,iBAAiB;IAE1C,QAAQ,IAAI,IAAI;IAcT,WAAW,IAAI,IAAI;IAMnB,OAAO,IAAI,IAAI;IAUf,eAAe,IAAI,IAAI;IAIvB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IA0BxC,IAAW,QAAQ,IAAI,OAAO,CAE7B;IAED,IAAW,aAAa,IAAI,YAAY,EAAE,CAKzC;IAED,IAAW,eAAe,IAAI,MAAM,CAEnC;IAEM,eAAe,IAAI,IAAI;IAKvB,mBAAmB,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI;IAYjE,YAAY,IAAI,IAAI;YAgBb,cAAc;YA2Bd,oBAAoB;IAsBlC,OAAO,CAAC,cAAc;IAwCtB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAS7B,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,YAAY;IAUpB;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IA8B1B;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IA8C1B,0FAA0F;IAC1F,OAAO,CAAC,aAAa;IAIrB;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAiB5B;;;OAGG;IACH,OAAO,CAAC,cAAc;IAYtB;;OAEG;IACH,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,cAAc;IAKtB,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,WAAW;IAqBnB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,UAAU;IAYlB,OAAO,CAAC,SAAS;yCA7dR,0BAA0B;2CAA1B,0BAA0B;CAwetC"}
1
+ {"version":3,"file":"record-micro-view.component.d.ts","sourceRoot":"","sources":["../../../src/lib/record-micro-view/record-micro-view.component.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, HostListener } from '@angular/core';
2
- import { RunView, Metadata, CompositeKey } from '@memberjunction/core';
2
+ import { RunView, CompositeKey } from '@memberjunction/core';
3
3
  import { UUIDsEqual } from '@memberjunction/global';
4
+ import { BaseAngularComponent } from '@memberjunction/ng-base-types';
4
5
  import * as i0 from "@angular/core";
5
6
  import * as i1 from "@angular/common";
6
7
  import * as i2 from "@memberjunction/ng-shared-generic";
@@ -336,7 +337,7 @@ function MjRecordMicroViewComponent_ng_template_2_Template(rf, ctx) { if (rf & 1
336
337
  i0.ɵɵadvance();
337
338
  i0.ɵɵconditional(!ctx_r1.IsLoading && !ctx_r1.ErrorMessage && ctx_r1.Fields.length === 0 ? 6 : -1);
338
339
  } }
339
- export class MjRecordMicroViewComponent {
340
+ export class MjRecordMicroViewComponent extends BaseAngularComponent {
340
341
  cdr;
341
342
  Data;
342
343
  Inline = false;
@@ -354,8 +355,9 @@ export class MjRecordMicroViewComponent {
354
355
  RecordDisplayName = '';
355
356
  /** Icon CSS class from EntityInfo.Icon, falls back to 'fa-solid fa-table' */
356
357
  EntityIcon = 'fa-solid fa-table';
357
- metadata = new Metadata();
358
+ get metadata() { return this.ProviderToUse; }
358
359
  constructor(cdr) {
360
+ super();
359
361
  this.cdr = cdr;
360
362
  }
361
363
  ngOnInit() {
@@ -482,7 +484,7 @@ export class MjRecordMicroViewComponent {
482
484
  }
483
485
  }
484
486
  async loadRecordChangeJson(changeId) {
485
- const rv = new RunView();
487
+ const rv = RunView.FromMetadataProvider(this.ProviderToUse);
486
488
  const result = await rv.RunView({
487
489
  EntityName: 'MJ: Record Changes',
488
490
  ExtraFilter: `ID = '${changeId}'`,
@@ -794,7 +796,7 @@ export class MjRecordMicroViewComponent {
794
796
  static ɵfac = function MjRecordMicroViewComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || MjRecordMicroViewComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
795
797
  static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: MjRecordMicroViewComponent, selectors: [["mj-record-micro-view"]], hostBindings: function MjRecordMicroViewComponent_HostBindings(rf, ctx) { if (rf & 1) {
796
798
  i0.ɵɵlistener("keydown.escape", function MjRecordMicroViewComponent_keydown_escape_HostBindingHandler() { return ctx.OnEscapeKey(); }, i0.ɵɵresolveDocument);
797
- } }, inputs: { Data: "Data", Inline: "Inline" }, outputs: { Close: "Close", EntityLinkClick: "EntityLinkClick", OpenRecord: "OpenRecord" }, standalone: false, decls: 4, vars: 2, consts: [["microContent", ""], [1, "micro-inline"], [1, "micro-backdrop", 3, "click"], [1, "micro-panel"], [4, "ngTemplateOutlet"], [1, "micro-header"], [1, "micro-inline-header"], [1, "micro-content"], ["text", "Loading record data..."], [1, "micro-error"], [1, "micro-fields"], [1, "micro-empty"], [1, "micro-header-info"], [1, "micro-entity"], [1, "micro-entity-icon"], [1, "micro-record-name"], [1, "micro-record-id"], [1, "fa-solid", "fa-fingerprint"], [1, "micro-header-actions"], ["title", "Open this record", 1, "micro-open-btn", 3, "click"], [1, "fa-solid", "fa-arrow-up-right-from-square"], [1, "micro-close", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "micro-header-left"], [1, "fa-solid", "fa-circle-exclamation"], [1, "micro-toolbar"], [1, "micro-field-header"], [1, "mf-col-name"], [1, "mf-col-value"], [1, "micro-field-row", 3, "odd", "ngClass"], [1, "null-toggle"], ["type", "checkbox", 3, "change", "checked"], [1, "null-toggle-label"], [1, "mf-col-old"], [1, "mf-col-new"], [1, "micro-field-row", 3, "ngClass"], [1, "mf-col-name", 3, "title"], [1, "mf-type-icon"], [1, "mf-field-name"], [1, "mf-col-value", 3, "title"], [1, "mf-fk-link", 3, "title"], [1, "mf-json-value"], [1, "mf-bool-icon"], [1, "mf-bool-label"], [1, "mf-fk-link", 3, "click", "title"], [1, "mf-fk-id"], [1, "fa-solid", "fa-arrow-up-right-from-square", "mf-fk-icon"], [1, "mf-col-old", 3, "title"], [1, "mf-col-new", 3, "title"]], template: function MjRecordMicroViewComponent_Template(rf, ctx) { if (rf & 1) {
799
+ } }, inputs: { Data: "Data", Inline: "Inline" }, outputs: { Close: "Close", EntityLinkClick: "EntityLinkClick", OpenRecord: "OpenRecord" }, standalone: false, features: [i0.ɵɵInheritDefinitionFeature], decls: 4, vars: 2, consts: [["microContent", ""], [1, "micro-inline"], [1, "micro-backdrop", 3, "click"], [1, "micro-panel"], [4, "ngTemplateOutlet"], [1, "micro-header"], [1, "micro-inline-header"], [1, "micro-content"], ["text", "Loading record data..."], [1, "micro-error"], [1, "micro-fields"], [1, "micro-empty"], [1, "micro-header-info"], [1, "micro-entity"], [1, "micro-entity-icon"], [1, "micro-record-name"], [1, "micro-record-id"], [1, "fa-solid", "fa-fingerprint"], [1, "micro-header-actions"], ["title", "Open this record", 1, "micro-open-btn", 3, "click"], [1, "fa-solid", "fa-arrow-up-right-from-square"], [1, "micro-close", 3, "click"], [1, "fa-solid", "fa-xmark"], [1, "micro-header-left"], [1, "fa-solid", "fa-circle-exclamation"], [1, "micro-toolbar"], [1, "micro-field-header"], [1, "mf-col-name"], [1, "mf-col-value"], [1, "micro-field-row", 3, "odd", "ngClass"], [1, "null-toggle"], ["type", "checkbox", 3, "change", "checked"], [1, "null-toggle-label"], [1, "mf-col-old"], [1, "mf-col-new"], [1, "micro-field-row", 3, "ngClass"], [1, "mf-col-name", 3, "title"], [1, "mf-type-icon"], [1, "mf-field-name"], [1, "mf-col-value", 3, "title"], [1, "mf-fk-link", 3, "title"], [1, "mf-json-value"], [1, "mf-bool-icon"], [1, "mf-bool-label"], [1, "mf-fk-link", 3, "click", "title"], [1, "mf-fk-id"], [1, "fa-solid", "fa-arrow-up-right-from-square", "mf-fk-icon"], [1, "mf-col-old", 3, "title"], [1, "mf-col-new", 3, "title"]], template: function MjRecordMicroViewComponent_Template(rf, ctx) { if (rf & 1) {
798
800
  i0.ɵɵconditionalCreate(0, MjRecordMicroViewComponent_Conditional_0_Template, 3, 5);
799
801
  i0.ɵɵconditionalCreate(1, MjRecordMicroViewComponent_Conditional_1_Template, 2, 1, "div", 1);
800
802
  i0.ɵɵtemplate(2, MjRecordMicroViewComponent_ng_template_2_Template, 7, 8, "ng-template", null, 0, i0.ɵɵtemplateRefExtractor);
@@ -821,5 +823,5 @@ export class MjRecordMicroViewComponent {
821
823
  type: HostListener,
822
824
  args: ['document:keydown.escape']
823
825
  }] }); })();
824
- (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MjRecordMicroViewComponent, { className: "MjRecordMicroViewComponent", filePath: "src/lib/record-micro-view/record-micro-view.component.ts", lineNumber: 45 }); })();
826
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(MjRecordMicroViewComponent, { className: "MjRecordMicroViewComponent", filePath: "src/lib/record-micro-view/record-micro-view.component.ts", lineNumber: 46 }); })();
825
827
  //# sourceMappingURL=record-micro-view.component.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"record-micro-view.component.js","sourceRoot":"","sources":["../../../src/lib/record-micro-view/record-micro-view.component.ts","../../../src/lib/record-micro-view/record-micro-view.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, ChangeDetectorRef, ChangeDetectionStrategy, HostListener } from '@angular/core';\nimport { RunView, Metadata, EntityInfo, CompositeKey } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { MicroViewData } from '../types';\n\ninterface FieldDisplay {\n Name: string;\n DisplayName: string;\n Value: string;\n Type: string;\n Description: string;\n DiffClass: string;\n OldValue: string;\n IsNull: boolean;\n IsBoolean: boolean;\n BooleanValue: boolean;\n IsJson: boolean;\n Sequence: number;\n /** When set, the field is a FK and this holds the display value from the related virtual field */\n ForeignKeyDisplayValue: string;\n /** When set, user can click to navigate to this related record */\n ForeignKeyEntityName: string;\n /** The raw FK value (a GUID) for navigation */\n ForeignKeyRecordId: string;\n}\n\ninterface RecordChangeSimple {\n FullRecordJSON: string;\n}\n\n/** Event emitted when user wants to navigate to a related FK record */\nexport interface EntityLinkClickEvent {\n EntityName: string;\n RecordID: string;\n CompositeKey: CompositeKey;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-record-micro-view',\n templateUrl: './record-micro-view.component.html',\n styleUrls: ['./record-micro-view.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class MjRecordMicroViewComponent implements OnInit {\n @Input() Data!: MicroViewData;\n @Input() Inline = false;\n @Output() Close = new EventEmitter<void>();\n @Output() EntityLinkClick = new EventEmitter<EntityLinkClickEvent>();\n @Output() OpenRecord = new EventEmitter<EntityLinkClickEvent>();\n\n public IsLoading = true;\n public IsVisible = false;\n public Fields: FieldDisplay[] = [];\n public ErrorMessage = '';\n public ShowNullValues = false;\n\n /** Formatted display of the record primary key (simplified for single-value PKs) */\n public DisplayRecordID = '';\n\n /** The value of the IsNameField for display in the header */\n public RecordDisplayName = '';\n\n /** Icon CSS class from EntityInfo.Icon, falls back to 'fa-solid fa-table' */\n public EntityIcon = 'fa-solid fa-table';\n\n private metadata = new Metadata();\n\n constructor(private cdr: ChangeDetectorRef) {}\n\n ngOnInit(): void {\n if (this.Inline) {\n this.IsVisible = true;\n } else {\n Promise.resolve().then(() => {\n this.IsVisible = true;\n this.cdr.markForCheck();\n });\n }\n this.DisplayRecordID = this.formatRecordId(this.Data.RecordID);\n this.loadRecordData();\n }\n\n @HostListener('document:keydown.escape')\n public OnEscapeKey(): void {\n if (!this.Inline) {\n this.OnClose();\n }\n }\n\n public OnClose(): void {\n if (this.Inline) {\n this.Close.emit();\n } else {\n this.IsVisible = false;\n this.cdr.markForCheck();\n setTimeout(() => this.Close.emit(), 250);\n }\n }\n\n public OnBackdropClick(): void {\n this.OnClose();\n }\n\n public GetTypeIcon(type: string): string {\n const icons: Record<string, string> = {\n 'uniqueidentifier': 'fa-solid fa-fingerprint',\n 'datetime': 'fa-solid fa-calendar',\n 'datetimeoffset': 'fa-solid fa-calendar',\n 'date': 'fa-solid fa-calendar-day',\n 'time': 'fa-solid fa-clock',\n 'bit': 'fa-solid fa-toggle-on',\n 'boolean': 'fa-solid fa-toggle-on',\n 'int': 'fa-solid fa-hashtag',\n 'bigint': 'fa-solid fa-hashtag',\n 'float': 'fa-solid fa-hashtag',\n 'decimal': 'fa-solid fa-hashtag',\n 'money': 'fa-solid fa-hashtag',\n 'number': 'fa-solid fa-hashtag',\n 'nvarchar': 'fa-solid fa-font',\n 'varchar': 'fa-solid fa-font',\n 'ntext': 'fa-solid fa-align-left',\n 'text': 'fa-solid fa-align-left',\n 'string': 'fa-solid fa-font',\n 'object': 'fa-solid fa-code',\n 'null': 'fa-solid fa-circle-xmark'\n };\n return icons[type.toLowerCase()] ?? 'fa-solid fa-font';\n }\n\n public get HasDiffs(): boolean {\n return this.Data.FieldDiffs != null && this.Data.FieldDiffs.length > 0;\n }\n\n public get VisibleFields(): FieldDisplay[] {\n if (this.ShowNullValues) {\n return this.Fields;\n }\n return this.Fields.filter(f => !f.IsNull);\n }\n\n public get HiddenNullCount(): number {\n return this.Fields.filter(f => f.IsNull).length;\n }\n\n public ToggleShowNulls(): void {\n this.ShowNullValues = !this.ShowNullValues;\n this.cdr.markForCheck();\n }\n\n public OnEntityLinkClicked(event: MouseEvent, field: FieldDisplay): void {\n event.stopPropagation();\n if (field.ForeignKeyEntityName && field.ForeignKeyRecordId) {\n const pkey = new CompositeKey([{ FieldName: 'ID', Value: field.ForeignKeyRecordId }]);\n this.EntityLinkClick.emit({\n EntityName: field.ForeignKeyEntityName,\n RecordID: field.ForeignKeyRecordId,\n CompositeKey: pkey\n });\n }\n }\n\n public OnOpenRecord(): void {\n if (this.Data.EntityName && this.Data.RecordID) {\n const rawId = this.extractRawId(this.Data.RecordID);\n const pkey = new CompositeKey([{ FieldName: 'ID', Value: rawId }]);\n this.OpenRecord.emit({\n EntityName: this.Data.EntityName,\n RecordID: rawId,\n CompositeKey: pkey\n });\n }\n }\n\n // =========================================================================\n // Data loading\n // =========================================================================\n\n private async loadRecordData(): Promise<void> {\n this.IsLoading = true;\n this.cdr.markForCheck();\n\n try {\n let recordData = this.Data.FullRecordJSON;\n\n if (!recordData && this.Data.RecordChangeID) {\n recordData = await this.loadRecordChangeJson(this.Data.RecordChangeID);\n }\n\n if (recordData) {\n const entityInfo = this.findEntityInfo();\n this.EntityIcon = entityInfo?.Icon || 'fa-solid fa-table';\n this.RecordDisplayName = this.extractNameFieldValue(entityInfo, recordData);\n this.Fields = this.buildFieldList(recordData, entityInfo);\n } else {\n this.ErrorMessage = 'Unable to load record data.';\n }\n } catch (e) {\n this.ErrorMessage = e instanceof Error ? e.message : 'Failed to load record data.';\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n private async loadRecordChangeJson(changeId: string): Promise<Record<string, unknown> | null> {\n const rv = new RunView();\n const result = await rv.RunView<RecordChangeSimple>({\n EntityName: 'MJ: Record Changes',\n ExtraFilter: `ID = '${changeId}'`,\n Fields: ['FullRecordJSON'],\n ResultType: 'simple'\n });\n\n if (result.Success && result.Results.length > 0) {\n const json = result.Results[0].FullRecordJSON;\n if (json) {\n return JSON.parse(json) as Record<string, unknown>;\n }\n }\n return null;\n }\n\n // =========================================================================\n // Field building\n // =========================================================================\n\n private buildFieldList(data: Record<string, unknown>, entityInfo: EntityInfo | undefined): FieldDisplay[] {\n const diffMap = this.buildDiffMap();\n const fkMap = this.buildForeignKeyMap(entityInfo, data);\n const virtualFieldNames = this.getVirtualFieldNames(entityInfo);\n const fields: FieldDisplay[] = [];\n\n for (const [key, value] of Object.entries(data)) {\n if (key.startsWith('__mj_')) continue;\n // Skip virtual fields that we've merged into their FK counterpart\n if (virtualFieldNames.has(key)) continue;\n\n const fieldMeta = entityInfo?.Fields.find(f => f.Name === key);\n const diff = diffMap.get(key);\n const fkInfo = fkMap.get(key);\n const fieldType = fieldMeta?.Type ?? this.inferType(value);\n const isBooleanField = this.isBooleanType(fieldType, value);\n const isJsonField = this.isJsonValue(value);\n\n fields.push({\n Name: key,\n DisplayName: fieldMeta?.DisplayNameOrName ?? key,\n Value: this.formatValue(value, isJsonField),\n Type: fieldType,\n Description: fieldMeta?.Description ?? '',\n DiffClass: diff?.ChangeType ? `diff-${diff.ChangeType.toLowerCase()}` : '',\n OldValue: diff?.OldValue ?? '',\n IsNull: value == null,\n IsBoolean: isBooleanField,\n BooleanValue: this.toBooleanValue(value),\n IsJson: isJsonField,\n Sequence: fieldMeta?.Sequence ?? 9999,\n ForeignKeyDisplayValue: fkInfo?.DisplayValue ?? '',\n ForeignKeyEntityName: fkInfo?.EntityName ?? '',\n ForeignKeyRecordId: fkInfo?.RecordId ?? ''\n });\n }\n\n return fields.sort((a, b) => a.Sequence - b.Sequence);\n }\n\n /**\n * Find the entity's NameField (uses EntityInfo.NameField getter which checks\n * IsNameField first, then falls back to a field called \"Name\").\n */\n private extractNameFieldValue(entityInfo: EntityInfo | undefined, data: Record<string, unknown>): string {\n if (!entityInfo) return '';\n const nameField = entityInfo.NameField;\n if (nameField && data[nameField.Name] != null) {\n return String(data[nameField.Name]);\n }\n return '';\n }\n\n private findEntityInfo(): EntityInfo | undefined {\n if (this.Data.EntityName && this.Data.EntityName !== 'Unknown') {\n return this.metadata.Entities.find(e => e.Name === this.Data.EntityName);\n }\n if (this.Data.EntityID) {\n return this.metadata.Entities.find(e => UUIDsEqual(e.ID, this.Data.EntityID));\n }\n return undefined;\n }\n\n private buildDiffMap(): Map<string, { ChangeType: string; OldValue: string }> {\n const map = new Map<string, { ChangeType: string; OldValue: string }>();\n if (this.Data.FieldDiffs) {\n for (const diff of this.Data.FieldDiffs) {\n map.set(diff.FieldName, { ChangeType: diff.ChangeType, OldValue: diff.OldValue });\n }\n }\n return map;\n }\n\n /**\n * Build a map of FK field name -> { DisplayValue, EntityName, RecordId }\n * by matching FK fields to their associated virtual (display) fields.\n */\n private buildForeignKeyMap(\n entityInfo: EntityInfo | undefined,\n data: Record<string, unknown>\n ): Map<string, { DisplayValue: string; EntityName: string; RecordId: string }> {\n const map = new Map<string, { DisplayValue: string; EntityName: string; RecordId: string }>();\n if (!entityInfo) return map;\n\n for (const field of entityInfo.Fields) {\n if (!field.RelatedEntityID || field.Name === 'ID') continue;\n\n // Find the related entity name\n const relatedEntity = this.metadata.Entities.find(e => UUIDsEqual(e.ID, field.RelatedEntityID));\n if (!relatedEntity) continue;\n\n const fkValue = data[field.Name];\n if (fkValue == null) continue;\n\n // Find display value from the associated virtual field\n const displayValue = this.findFkDisplayValue(entityInfo, field.Name, data);\n\n map.set(field.Name, {\n DisplayValue: displayValue,\n EntityName: relatedEntity.Name,\n RecordId: String(fkValue)\n });\n }\n\n return map;\n }\n\n /**\n * Find the display value for a FK field by checking multiple strategies:\n * 1. Look for a virtual field with RelatedEntityNameFieldMap pointing to this FK\n * 2. Look for any virtual field whose name is derived from the FK name\n * 3. Scan data keys for common naming patterns (e.g., \"TypeID\" -> \"Type\")\n */\n private findFkDisplayValue(entityInfo: EntityInfo, fkFieldName: string, data: Record<string, unknown>): string {\n // Strategy 1: Metadata-linked virtual field via RelatedEntityNameFieldMap\n const linkedVirtual = entityInfo.Fields.find(f =>\n f.RelatedEntityNameFieldMap === fkFieldName && f.IsVirtual\n );\n if (linkedVirtual && data[linkedVirtual.Name] != null) {\n return String(data[linkedVirtual.Name]);\n }\n\n // Strategy 2: Find any virtual field that looks like a display field for this FK\n // by checking all virtual fields and matching via naming patterns\n const virtualFields = entityInfo.Fields.filter(f => f.IsVirtual);\n for (const vf of virtualFields) {\n // Check if this virtual field's RelatedEntityNameFieldMap matches (case-insensitive)\n if (vf.RelatedEntityNameFieldMap &&\n vf.RelatedEntityNameFieldMap.toLowerCase() === fkFieldName.toLowerCase() &&\n data[vf.Name] != null) {\n return String(data[vf.Name]);\n }\n }\n\n // Strategy 3: Try common naming conventions in the data itself\n // e.g., \"TypeID\" -> look for \"Type\" key in data\n // \"OwnerUserID\" -> look for \"Owner User\" or \"OwnerUser\"\n // Strip trailing \"ID\" from the FK name and try variations\n if (fkFieldName.endsWith('ID') && fkFieldName.length > 2) {\n const baseName = fkFieldName.slice(0, -2);\n\n // Direct match in data (e.g., \"CategoryID\" -> \"Category\")\n if (data[baseName] != null && typeof data[baseName] === 'string' &&\n !this.looksLikeGuid(data[baseName] as string)) {\n return String(data[baseName]);\n }\n\n // Try with space before capitals (e.g., \"OwnerUserID\" -> \"Owner User\")\n const spacedName = baseName.replace(/([a-z])([A-Z])/g, '$1 $2');\n if (spacedName !== baseName && data[spacedName] != null &&\n typeof data[spacedName] === 'string' &&\n !this.looksLikeGuid(data[spacedName] as string)) {\n return String(data[spacedName]);\n }\n }\n\n return '';\n }\n\n /** Quick check if a string looks like a GUID (to avoid using GUIDs as display values). */\n private looksLikeGuid(value: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n }\n\n /**\n * Get the set of virtual field names so we can skip them in the main field list.\n * Virtual fields are display-only fields whose values are merged into FK rows.\n * We skip ALL virtual fields — not just ones with RelatedEntityNameFieldMap —\n * because they are derived/computed and don't represent stored data.\n */\n private getVirtualFieldNames(entityInfo: EntityInfo | undefined): Set<string> {\n const names = new Set<string>();\n if (!entityInfo) return names;\n\n for (const field of entityInfo.Fields) {\n if (field.IsVirtual) {\n names.add(field.Name);\n }\n }\n\n return names;\n }\n\n // =========================================================================\n // Record ID formatting\n // =========================================================================\n\n /**\n * For single-value PKs like \"ID|<uuid>\", extract just the uuid.\n * For composite keys, show the full concatenated string.\n */\n private formatRecordId(recordId: string): string {\n if (!recordId) return '';\n const parts = recordId.split('||');\n if (parts.length === 1) {\n const singleParts = recordId.split('|');\n if (singleParts.length === 2) {\n return singleParts[1];\n }\n }\n return recordId;\n }\n\n /**\n * Extract the raw ID value from a potentially formatted record ID string.\n */\n private extractRawId(recordId: string): string {\n if (!recordId) return '';\n const parts = recordId.split('||');\n if (parts.length === 1) {\n const singleParts = recordId.split('|');\n if (singleParts.length === 2) {\n return singleParts[1];\n }\n }\n return recordId;\n }\n\n // =========================================================================\n // Type helpers\n // =========================================================================\n\n private isBooleanType(type: string, value: unknown): boolean {\n const t = type.toLowerCase();\n if (t === 'bit' || t === 'boolean') return true;\n if (value === true || value === false) return true;\n return false;\n }\n\n private toBooleanValue(value: unknown): boolean {\n if (value === true || value === 1 || value === '1' || value === 'true') return true;\n return false;\n }\n\n private isJsonValue(value: unknown): boolean {\n if (typeof value === 'object' && value != null) return true;\n if (typeof value === 'string') {\n const trimmed = value.trim();\n return (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'));\n }\n return false;\n }\n\n // =========================================================================\n // Formatting helpers\n // =========================================================================\n\n private formatValue(value: unknown, isJson: boolean): string {\n if (value == null) return 'null';\n if (typeof value === 'boolean') return value ? 'true' : 'false';\n if (typeof value === 'number') return String(value);\n if (typeof value === 'string') {\n if (this.isDateString(value)) return this.formatDate(value);\n // Try to pretty-print JSON strings\n if (isJson) return this.formatJsonString(value);\n if (value.length > 300) return value.substring(0, 300) + '...';\n return value;\n }\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n }\n return String(value);\n }\n\n private formatJsonString(value: string): string {\n try {\n const parsed = JSON.parse(value);\n return JSON.stringify(parsed, null, 2);\n } catch {\n return value;\n }\n }\n\n private isDateString(value: string): boolean {\n return /^\\d{4}-\\d{2}-\\d{2}T/.test(value);\n }\n\n private formatDate(value: string): string {\n try {\n const d = new Date(value);\n return d.toLocaleDateString('en-US', {\n month: 'short', day: 'numeric', year: 'numeric',\n hour: '2-digit', minute: '2-digit'\n });\n } catch {\n return value;\n }\n }\n\n private inferType(value: unknown): string {\n if (value == null) return 'null';\n if (typeof value === 'boolean') return 'bit';\n if (typeof value === 'number') return 'int';\n if (typeof value === 'string') {\n if (this.isDateString(value)) return 'datetime';\n if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)) return 'uniqueidentifier';\n return 'nvarchar';\n }\n return 'object';\n }\n}\n","<!-- Overlay mode -->\n@if (!Inline) {\n <div class=\"micro-backdrop\" [class.visible]=\"IsVisible\" (click)=\"OnBackdropClick()\"></div>\n <div class=\"micro-panel\" [class.visible]=\"IsVisible\">\n <ng-container *ngTemplateOutlet=\"microContent\"></ng-container>\n </div>\n}\n\n<!-- Inline mode (embedded in parent panel) -->\n@if (Inline) {\n <div class=\"micro-inline\">\n <ng-container *ngTemplateOutlet=\"microContent\"></ng-container>\n </div>\n}\n\n<!-- Shared content template -->\n<ng-template #microContent>\n <!-- Header (overlay mode only) -->\n @if (!Inline) {\n <div class=\"micro-header\">\n <div class=\"micro-header-info\">\n <div class=\"micro-entity\">\n <i [class]=\"EntityIcon\" class=\"micro-entity-icon\"></i>\n <span>{{Data.EntityName}}</span>\n @if (RecordDisplayName) {\n <span class=\"micro-record-name\">{{RecordDisplayName}}</span>\n }\n </div>\n <div class=\"micro-record-id\">\n <i class=\"fa-solid fa-fingerprint\"></i>\n <span>{{DisplayRecordID}}</span>\n </div>\n </div>\n <div class=\"micro-header-actions\">\n <button class=\"micro-open-btn\" (click)=\"OnOpenRecord()\" title=\"Open this record\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i> Open\n </button>\n <button class=\"micro-close\" (click)=\"OnClose()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n </div>\n }\n\n <!-- Inline header -->\n @if (Inline) {\n <div class=\"micro-inline-header\">\n <div class=\"micro-header-left\">\n <div class=\"micro-entity\">\n <i [class]=\"EntityIcon\" class=\"micro-entity-icon\"></i>\n <span>{{Data.EntityName}}</span>\n @if (RecordDisplayName) {\n <span class=\"micro-record-name\">{{RecordDisplayName}}</span>\n }\n </div>\n <div class=\"micro-record-id\">\n <i class=\"fa-solid fa-fingerprint\"></i>\n <span>{{DisplayRecordID}}</span>\n </div>\n </div>\n <button class=\"micro-open-btn\" (click)=\"OnOpenRecord()\" title=\"Open this record\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i> Open\n </button>\n </div>\n }\n\n <!-- Content -->\n <div class=\"micro-content\" [class.micro-content-inline]=\"Inline\">\n @if (IsLoading) {\n <mj-loading text=\"Loading record data...\"></mj-loading>\n }\n\n <!-- Error -->\n @if (!IsLoading && ErrorMessage) {\n <div class=\"micro-error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n <span>{{ErrorMessage}}</span>\n </div>\n }\n\n <!-- Field table -->\n @if (!IsLoading && !ErrorMessage && Fields.length > 0) {\n <div class=\"micro-fields\">\n <!-- Null toggle toolbar -->\n @if (HiddenNullCount > 0) {\n <div class=\"micro-toolbar\">\n <label class=\"null-toggle\">\n <input type=\"checkbox\" [checked]=\"ShowNullValues\" (change)=\"ToggleShowNulls()\" />\n <span class=\"null-toggle-label\">Show null values ({{HiddenNullCount}})</span>\n </label>\n </div>\n }\n <div class=\"micro-field-header\">\n <span class=\"mf-col-name\">Field</span>\n @if (!HasDiffs) {\n <span class=\"mf-col-value\">Value</span>\n }\n @if (HasDiffs) {\n <span class=\"mf-col-old\">Old</span>\n <span class=\"mf-col-new\">New</span>\n }\n </div>\n @for (field of VisibleFields; track field; let odd = $odd) {\n <div class=\"micro-field-row\"\n [class.odd]=\"odd\" [ngClass]=\"field.DiffClass\">\n <span class=\"mf-col-name\" [title]=\"field.Description\">\n <i [class]=\"GetTypeIcon(field.Type)\" class=\"mf-type-icon\"></i>\n <span class=\"mf-field-name\">{{field.DisplayName}}</span>\n </span>\n @if (!HasDiffs) {\n <span class=\"mf-col-value\" [title]=\"field.Value\">\n <!-- Boolean field -->\n @if (field.IsBoolean && !field.IsNull) {\n <i [class]=\"field.BooleanValue ? 'fa-solid fa-square-check mf-bool-true' : 'fa-regular fa-square mf-bool-false'\"\n class=\"mf-bool-icon\"></i>\n <span class=\"mf-bool-label\">{{field.BooleanValue ? 'Yes' : 'No'}}</span>\n }\n <!-- FK field with display value — show display name (ID) with open icon -->\n @if (!field.IsBoolean && field.ForeignKeyEntityName && field.ForeignKeyDisplayValue) {\n <a class=\"mf-fk-link\" (click)=\"OnEntityLinkClicked($event, field)\"\n [title]=\"field.ForeignKeyEntityName + ': ' + field.ForeignKeyRecordId\">\n {{field.ForeignKeyDisplayValue}}\n <span class=\"mf-fk-id\">({{field.ForeignKeyRecordId | slice:0:8}}...)</span>\n <i class=\"fa-solid fa-arrow-up-right-from-square mf-fk-icon\"></i>\n </a>\n }\n <!-- FK field without display value — show raw ID with open icon -->\n @if (!field.IsBoolean && field.ForeignKeyEntityName && !field.ForeignKeyDisplayValue) {\n <a class=\"mf-fk-link\" (click)=\"OnEntityLinkClicked($event, field)\"\n [title]=\"'Open ' + field.ForeignKeyEntityName\">\n {{field.Value}}\n <i class=\"fa-solid fa-arrow-up-right-from-square mf-fk-icon\"></i>\n </a>\n }\n <!-- JSON field — formatted -->\n @if (!field.IsBoolean && !field.ForeignKeyEntityName && field.IsJson) {\n <pre class=\"mf-json-value\">{{field.Value}}</pre>\n }\n <!-- Regular value -->\n @if (!field.IsBoolean && !field.ForeignKeyEntityName && !field.IsJson) {\n {{field.Value}}\n }\n </span>\n }\n @if (HasDiffs) {\n <span class=\"mf-col-old\" [title]=\"field.OldValue\">\n {{field.OldValue || field.Value}}\n </span>\n <span class=\"mf-col-new\" [title]=\"field.Value\">\n {{field.Value}}\n </span>\n }\n </div>\n }\n </div>\n }\n\n <!-- Empty -->\n @if (!IsLoading && !ErrorMessage && Fields.length === 0) {\n <div class=\"micro-empty\">\n <p>No field data available.</p>\n </div>\n }\n </div>\n</ng-template>\n"]}
1
+ {"version":3,"file":"record-micro-view.component.js","sourceRoot":"","sources":["../../../src/lib/record-micro-view/record-micro-view.component.ts","../../../src/lib/record-micro-view/record-micro-view.component.html"],"names":[],"mappings":"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","sourcesContent":["import { Component, Input, Output, EventEmitter, OnInit, ChangeDetectorRef, ChangeDetectionStrategy, HostListener } from '@angular/core';\nimport { RunView, EntityInfo, CompositeKey } from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { MicroViewData } from '../types';\n\ninterface FieldDisplay {\n Name: string;\n DisplayName: string;\n Value: string;\n Type: string;\n Description: string;\n DiffClass: string;\n OldValue: string;\n IsNull: boolean;\n IsBoolean: boolean;\n BooleanValue: boolean;\n IsJson: boolean;\n Sequence: number;\n /** When set, the field is a FK and this holds the display value from the related virtual field */\n ForeignKeyDisplayValue: string;\n /** When set, user can click to navigate to this related record */\n ForeignKeyEntityName: string;\n /** The raw FK value (a GUID) for navigation */\n ForeignKeyRecordId: string;\n}\n\ninterface RecordChangeSimple {\n FullRecordJSON: string;\n}\n\n/** Event emitted when user wants to navigate to a related FK record */\nexport interface EntityLinkClickEvent {\n EntityName: string;\n RecordID: string;\n CompositeKey: CompositeKey;\n}\n\n@Component({\n standalone: false,\n selector: 'mj-record-micro-view',\n templateUrl: './record-micro-view.component.html',\n styleUrls: ['./record-micro-view.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class MjRecordMicroViewComponent extends BaseAngularComponent implements OnInit {\n @Input() Data!: MicroViewData;\n @Input() Inline = false;\n @Output() Close = new EventEmitter<void>();\n @Output() EntityLinkClick = new EventEmitter<EntityLinkClickEvent>();\n @Output() OpenRecord = new EventEmitter<EntityLinkClickEvent>();\n\n public IsLoading = true;\n public IsVisible = false;\n public Fields: FieldDisplay[] = [];\n public ErrorMessage = '';\n public ShowNullValues = false;\n\n /** Formatted display of the record primary key (simplified for single-value PKs) */\n public DisplayRecordID = '';\n\n /** The value of the IsNameField for display in the header */\n public RecordDisplayName = '';\n\n /** Icon CSS class from EntityInfo.Icon, falls back to 'fa-solid fa-table' */\n public EntityIcon = 'fa-solid fa-table';\n\n private get metadata() { return this.ProviderToUse; }\n\n constructor(private cdr: ChangeDetectorRef) { super(); }\n\n ngOnInit(): void {\n if (this.Inline) {\n this.IsVisible = true;\n } else {\n Promise.resolve().then(() => {\n this.IsVisible = true;\n this.cdr.markForCheck();\n });\n }\n this.DisplayRecordID = this.formatRecordId(this.Data.RecordID);\n this.loadRecordData();\n }\n\n @HostListener('document:keydown.escape')\n public OnEscapeKey(): void {\n if (!this.Inline) {\n this.OnClose();\n }\n }\n\n public OnClose(): void {\n if (this.Inline) {\n this.Close.emit();\n } else {\n this.IsVisible = false;\n this.cdr.markForCheck();\n setTimeout(() => this.Close.emit(), 250);\n }\n }\n\n public OnBackdropClick(): void {\n this.OnClose();\n }\n\n public GetTypeIcon(type: string): string {\n const icons: Record<string, string> = {\n 'uniqueidentifier': 'fa-solid fa-fingerprint',\n 'datetime': 'fa-solid fa-calendar',\n 'datetimeoffset': 'fa-solid fa-calendar',\n 'date': 'fa-solid fa-calendar-day',\n 'time': 'fa-solid fa-clock',\n 'bit': 'fa-solid fa-toggle-on',\n 'boolean': 'fa-solid fa-toggle-on',\n 'int': 'fa-solid fa-hashtag',\n 'bigint': 'fa-solid fa-hashtag',\n 'float': 'fa-solid fa-hashtag',\n 'decimal': 'fa-solid fa-hashtag',\n 'money': 'fa-solid fa-hashtag',\n 'number': 'fa-solid fa-hashtag',\n 'nvarchar': 'fa-solid fa-font',\n 'varchar': 'fa-solid fa-font',\n 'ntext': 'fa-solid fa-align-left',\n 'text': 'fa-solid fa-align-left',\n 'string': 'fa-solid fa-font',\n 'object': 'fa-solid fa-code',\n 'null': 'fa-solid fa-circle-xmark'\n };\n return icons[type.toLowerCase()] ?? 'fa-solid fa-font';\n }\n\n public get HasDiffs(): boolean {\n return this.Data.FieldDiffs != null && this.Data.FieldDiffs.length > 0;\n }\n\n public get VisibleFields(): FieldDisplay[] {\n if (this.ShowNullValues) {\n return this.Fields;\n }\n return this.Fields.filter(f => !f.IsNull);\n }\n\n public get HiddenNullCount(): number {\n return this.Fields.filter(f => f.IsNull).length;\n }\n\n public ToggleShowNulls(): void {\n this.ShowNullValues = !this.ShowNullValues;\n this.cdr.markForCheck();\n }\n\n public OnEntityLinkClicked(event: MouseEvent, field: FieldDisplay): void {\n event.stopPropagation();\n if (field.ForeignKeyEntityName && field.ForeignKeyRecordId) {\n const pkey = new CompositeKey([{ FieldName: 'ID', Value: field.ForeignKeyRecordId }]);\n this.EntityLinkClick.emit({\n EntityName: field.ForeignKeyEntityName,\n RecordID: field.ForeignKeyRecordId,\n CompositeKey: pkey\n });\n }\n }\n\n public OnOpenRecord(): void {\n if (this.Data.EntityName && this.Data.RecordID) {\n const rawId = this.extractRawId(this.Data.RecordID);\n const pkey = new CompositeKey([{ FieldName: 'ID', Value: rawId }]);\n this.OpenRecord.emit({\n EntityName: this.Data.EntityName,\n RecordID: rawId,\n CompositeKey: pkey\n });\n }\n }\n\n // =========================================================================\n // Data loading\n // =========================================================================\n\n private async loadRecordData(): Promise<void> {\n this.IsLoading = true;\n this.cdr.markForCheck();\n\n try {\n let recordData = this.Data.FullRecordJSON;\n\n if (!recordData && this.Data.RecordChangeID) {\n recordData = await this.loadRecordChangeJson(this.Data.RecordChangeID);\n }\n\n if (recordData) {\n const entityInfo = this.findEntityInfo();\n this.EntityIcon = entityInfo?.Icon || 'fa-solid fa-table';\n this.RecordDisplayName = this.extractNameFieldValue(entityInfo, recordData);\n this.Fields = this.buildFieldList(recordData, entityInfo);\n } else {\n this.ErrorMessage = 'Unable to load record data.';\n }\n } catch (e) {\n this.ErrorMessage = e instanceof Error ? e.message : 'Failed to load record data.';\n } finally {\n this.IsLoading = false;\n this.cdr.markForCheck();\n }\n }\n\n private async loadRecordChangeJson(changeId: string): Promise<Record<string, unknown> | null> {\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const result = await rv.RunView<RecordChangeSimple>({\n EntityName: 'MJ: Record Changes',\n ExtraFilter: `ID = '${changeId}'`,\n Fields: ['FullRecordJSON'],\n ResultType: 'simple'\n });\n\n if (result.Success && result.Results.length > 0) {\n const json = result.Results[0].FullRecordJSON;\n if (json) {\n return JSON.parse(json) as Record<string, unknown>;\n }\n }\n return null;\n }\n\n // =========================================================================\n // Field building\n // =========================================================================\n\n private buildFieldList(data: Record<string, unknown>, entityInfo: EntityInfo | undefined): FieldDisplay[] {\n const diffMap = this.buildDiffMap();\n const fkMap = this.buildForeignKeyMap(entityInfo, data);\n const virtualFieldNames = this.getVirtualFieldNames(entityInfo);\n const fields: FieldDisplay[] = [];\n\n for (const [key, value] of Object.entries(data)) {\n if (key.startsWith('__mj_')) continue;\n // Skip virtual fields that we've merged into their FK counterpart\n if (virtualFieldNames.has(key)) continue;\n\n const fieldMeta = entityInfo?.Fields.find(f => f.Name === key);\n const diff = diffMap.get(key);\n const fkInfo = fkMap.get(key);\n const fieldType = fieldMeta?.Type ?? this.inferType(value);\n const isBooleanField = this.isBooleanType(fieldType, value);\n const isJsonField = this.isJsonValue(value);\n\n fields.push({\n Name: key,\n DisplayName: fieldMeta?.DisplayNameOrName ?? key,\n Value: this.formatValue(value, isJsonField),\n Type: fieldType,\n Description: fieldMeta?.Description ?? '',\n DiffClass: diff?.ChangeType ? `diff-${diff.ChangeType.toLowerCase()}` : '',\n OldValue: diff?.OldValue ?? '',\n IsNull: value == null,\n IsBoolean: isBooleanField,\n BooleanValue: this.toBooleanValue(value),\n IsJson: isJsonField,\n Sequence: fieldMeta?.Sequence ?? 9999,\n ForeignKeyDisplayValue: fkInfo?.DisplayValue ?? '',\n ForeignKeyEntityName: fkInfo?.EntityName ?? '',\n ForeignKeyRecordId: fkInfo?.RecordId ?? ''\n });\n }\n\n return fields.sort((a, b) => a.Sequence - b.Sequence);\n }\n\n /**\n * Find the entity's NameField (uses EntityInfo.NameField getter which checks\n * IsNameField first, then falls back to a field called \"Name\").\n */\n private extractNameFieldValue(entityInfo: EntityInfo | undefined, data: Record<string, unknown>): string {\n if (!entityInfo) return '';\n const nameField = entityInfo.NameField;\n if (nameField && data[nameField.Name] != null) {\n return String(data[nameField.Name]);\n }\n return '';\n }\n\n private findEntityInfo(): EntityInfo | undefined {\n if (this.Data.EntityName && this.Data.EntityName !== 'Unknown') {\n return this.metadata.Entities.find(e => e.Name === this.Data.EntityName);\n }\n if (this.Data.EntityID) {\n return this.metadata.Entities.find(e => UUIDsEqual(e.ID, this.Data.EntityID));\n }\n return undefined;\n }\n\n private buildDiffMap(): Map<string, { ChangeType: string; OldValue: string }> {\n const map = new Map<string, { ChangeType: string; OldValue: string }>();\n if (this.Data.FieldDiffs) {\n for (const diff of this.Data.FieldDiffs) {\n map.set(diff.FieldName, { ChangeType: diff.ChangeType, OldValue: diff.OldValue });\n }\n }\n return map;\n }\n\n /**\n * Build a map of FK field name -> { DisplayValue, EntityName, RecordId }\n * by matching FK fields to their associated virtual (display) fields.\n */\n private buildForeignKeyMap(\n entityInfo: EntityInfo | undefined,\n data: Record<string, unknown>\n ): Map<string, { DisplayValue: string; EntityName: string; RecordId: string }> {\n const map = new Map<string, { DisplayValue: string; EntityName: string; RecordId: string }>();\n if (!entityInfo) return map;\n\n for (const field of entityInfo.Fields) {\n if (!field.RelatedEntityID || field.Name === 'ID') continue;\n\n // Find the related entity name\n const relatedEntity = this.metadata.Entities.find(e => UUIDsEqual(e.ID, field.RelatedEntityID));\n if (!relatedEntity) continue;\n\n const fkValue = data[field.Name];\n if (fkValue == null) continue;\n\n // Find display value from the associated virtual field\n const displayValue = this.findFkDisplayValue(entityInfo, field.Name, data);\n\n map.set(field.Name, {\n DisplayValue: displayValue,\n EntityName: relatedEntity.Name,\n RecordId: String(fkValue)\n });\n }\n\n return map;\n }\n\n /**\n * Find the display value for a FK field by checking multiple strategies:\n * 1. Look for a virtual field with RelatedEntityNameFieldMap pointing to this FK\n * 2. Look for any virtual field whose name is derived from the FK name\n * 3. Scan data keys for common naming patterns (e.g., \"TypeID\" -> \"Type\")\n */\n private findFkDisplayValue(entityInfo: EntityInfo, fkFieldName: string, data: Record<string, unknown>): string {\n // Strategy 1: Metadata-linked virtual field via RelatedEntityNameFieldMap\n const linkedVirtual = entityInfo.Fields.find(f =>\n f.RelatedEntityNameFieldMap === fkFieldName && f.IsVirtual\n );\n if (linkedVirtual && data[linkedVirtual.Name] != null) {\n return String(data[linkedVirtual.Name]);\n }\n\n // Strategy 2: Find any virtual field that looks like a display field for this FK\n // by checking all virtual fields and matching via naming patterns\n const virtualFields = entityInfo.Fields.filter(f => f.IsVirtual);\n for (const vf of virtualFields) {\n // Check if this virtual field's RelatedEntityNameFieldMap matches (case-insensitive)\n if (vf.RelatedEntityNameFieldMap &&\n vf.RelatedEntityNameFieldMap.toLowerCase() === fkFieldName.toLowerCase() &&\n data[vf.Name] != null) {\n return String(data[vf.Name]);\n }\n }\n\n // Strategy 3: Try common naming conventions in the data itself\n // e.g., \"TypeID\" -> look for \"Type\" key in data\n // \"OwnerUserID\" -> look for \"Owner User\" or \"OwnerUser\"\n // Strip trailing \"ID\" from the FK name and try variations\n if (fkFieldName.endsWith('ID') && fkFieldName.length > 2) {\n const baseName = fkFieldName.slice(0, -2);\n\n // Direct match in data (e.g., \"CategoryID\" -> \"Category\")\n if (data[baseName] != null && typeof data[baseName] === 'string' &&\n !this.looksLikeGuid(data[baseName] as string)) {\n return String(data[baseName]);\n }\n\n // Try with space before capitals (e.g., \"OwnerUserID\" -> \"Owner User\")\n const spacedName = baseName.replace(/([a-z])([A-Z])/g, '$1 $2');\n if (spacedName !== baseName && data[spacedName] != null &&\n typeof data[spacedName] === 'string' &&\n !this.looksLikeGuid(data[spacedName] as string)) {\n return String(data[spacedName]);\n }\n }\n\n return '';\n }\n\n /** Quick check if a string looks like a GUID (to avoid using GUIDs as display values). */\n private looksLikeGuid(value: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n }\n\n /**\n * Get the set of virtual field names so we can skip them in the main field list.\n * Virtual fields are display-only fields whose values are merged into FK rows.\n * We skip ALL virtual fields — not just ones with RelatedEntityNameFieldMap —\n * because they are derived/computed and don't represent stored data.\n */\n private getVirtualFieldNames(entityInfo: EntityInfo | undefined): Set<string> {\n const names = new Set<string>();\n if (!entityInfo) return names;\n\n for (const field of entityInfo.Fields) {\n if (field.IsVirtual) {\n names.add(field.Name);\n }\n }\n\n return names;\n }\n\n // =========================================================================\n // Record ID formatting\n // =========================================================================\n\n /**\n * For single-value PKs like \"ID|<uuid>\", extract just the uuid.\n * For composite keys, show the full concatenated string.\n */\n private formatRecordId(recordId: string): string {\n if (!recordId) return '';\n const parts = recordId.split('||');\n if (parts.length === 1) {\n const singleParts = recordId.split('|');\n if (singleParts.length === 2) {\n return singleParts[1];\n }\n }\n return recordId;\n }\n\n /**\n * Extract the raw ID value from a potentially formatted record ID string.\n */\n private extractRawId(recordId: string): string {\n if (!recordId) return '';\n const parts = recordId.split('||');\n if (parts.length === 1) {\n const singleParts = recordId.split('|');\n if (singleParts.length === 2) {\n return singleParts[1];\n }\n }\n return recordId;\n }\n\n // =========================================================================\n // Type helpers\n // =========================================================================\n\n private isBooleanType(type: string, value: unknown): boolean {\n const t = type.toLowerCase();\n if (t === 'bit' || t === 'boolean') return true;\n if (value === true || value === false) return true;\n return false;\n }\n\n private toBooleanValue(value: unknown): boolean {\n if (value === true || value === 1 || value === '1' || value === 'true') return true;\n return false;\n }\n\n private isJsonValue(value: unknown): boolean {\n if (typeof value === 'object' && value != null) return true;\n if (typeof value === 'string') {\n const trimmed = value.trim();\n return (trimmed.startsWith('{') && trimmed.endsWith('}')) ||\n (trimmed.startsWith('[') && trimmed.endsWith(']'));\n }\n return false;\n }\n\n // =========================================================================\n // Formatting helpers\n // =========================================================================\n\n private formatValue(value: unknown, isJson: boolean): string {\n if (value == null) return 'null';\n if (typeof value === 'boolean') return value ? 'true' : 'false';\n if (typeof value === 'number') return String(value);\n if (typeof value === 'string') {\n if (this.isDateString(value)) return this.formatDate(value);\n // Try to pretty-print JSON strings\n if (isJson) return this.formatJsonString(value);\n if (value.length > 300) return value.substring(0, 300) + '...';\n return value;\n }\n if (typeof value === 'object') {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n }\n return String(value);\n }\n\n private formatJsonString(value: string): string {\n try {\n const parsed = JSON.parse(value);\n return JSON.stringify(parsed, null, 2);\n } catch {\n return value;\n }\n }\n\n private isDateString(value: string): boolean {\n return /^\\d{4}-\\d{2}-\\d{2}T/.test(value);\n }\n\n private formatDate(value: string): string {\n try {\n const d = new Date(value);\n return d.toLocaleDateString('en-US', {\n month: 'short', day: 'numeric', year: 'numeric',\n hour: '2-digit', minute: '2-digit'\n });\n } catch {\n return value;\n }\n }\n\n private inferType(value: unknown): string {\n if (value == null) return 'null';\n if (typeof value === 'boolean') return 'bit';\n if (typeof value === 'number') return 'int';\n if (typeof value === 'string') {\n if (this.isDateString(value)) return 'datetime';\n if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value)) return 'uniqueidentifier';\n return 'nvarchar';\n }\n return 'object';\n }\n}\n","<!-- Overlay mode -->\n@if (!Inline) {\n <div class=\"micro-backdrop\" [class.visible]=\"IsVisible\" (click)=\"OnBackdropClick()\"></div>\n <div class=\"micro-panel\" [class.visible]=\"IsVisible\">\n <ng-container *ngTemplateOutlet=\"microContent\"></ng-container>\n </div>\n}\n\n<!-- Inline mode (embedded in parent panel) -->\n@if (Inline) {\n <div class=\"micro-inline\">\n <ng-container *ngTemplateOutlet=\"microContent\"></ng-container>\n </div>\n}\n\n<!-- Shared content template -->\n<ng-template #microContent>\n <!-- Header (overlay mode only) -->\n @if (!Inline) {\n <div class=\"micro-header\">\n <div class=\"micro-header-info\">\n <div class=\"micro-entity\">\n <i [class]=\"EntityIcon\" class=\"micro-entity-icon\"></i>\n <span>{{Data.EntityName}}</span>\n @if (RecordDisplayName) {\n <span class=\"micro-record-name\">{{RecordDisplayName}}</span>\n }\n </div>\n <div class=\"micro-record-id\">\n <i class=\"fa-solid fa-fingerprint\"></i>\n <span>{{DisplayRecordID}}</span>\n </div>\n </div>\n <div class=\"micro-header-actions\">\n <button class=\"micro-open-btn\" (click)=\"OnOpenRecord()\" title=\"Open this record\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i> Open\n </button>\n <button class=\"micro-close\" (click)=\"OnClose()\">\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n </div>\n }\n\n <!-- Inline header -->\n @if (Inline) {\n <div class=\"micro-inline-header\">\n <div class=\"micro-header-left\">\n <div class=\"micro-entity\">\n <i [class]=\"EntityIcon\" class=\"micro-entity-icon\"></i>\n <span>{{Data.EntityName}}</span>\n @if (RecordDisplayName) {\n <span class=\"micro-record-name\">{{RecordDisplayName}}</span>\n }\n </div>\n <div class=\"micro-record-id\">\n <i class=\"fa-solid fa-fingerprint\"></i>\n <span>{{DisplayRecordID}}</span>\n </div>\n </div>\n <button class=\"micro-open-btn\" (click)=\"OnOpenRecord()\" title=\"Open this record\">\n <i class=\"fa-solid fa-arrow-up-right-from-square\"></i> Open\n </button>\n </div>\n }\n\n <!-- Content -->\n <div class=\"micro-content\" [class.micro-content-inline]=\"Inline\">\n @if (IsLoading) {\n <mj-loading text=\"Loading record data...\"></mj-loading>\n }\n\n <!-- Error -->\n @if (!IsLoading && ErrorMessage) {\n <div class=\"micro-error\">\n <i class=\"fa-solid fa-circle-exclamation\"></i>\n <span>{{ErrorMessage}}</span>\n </div>\n }\n\n <!-- Field table -->\n @if (!IsLoading && !ErrorMessage && Fields.length > 0) {\n <div class=\"micro-fields\">\n <!-- Null toggle toolbar -->\n @if (HiddenNullCount > 0) {\n <div class=\"micro-toolbar\">\n <label class=\"null-toggle\">\n <input type=\"checkbox\" [checked]=\"ShowNullValues\" (change)=\"ToggleShowNulls()\" />\n <span class=\"null-toggle-label\">Show null values ({{HiddenNullCount}})</span>\n </label>\n </div>\n }\n <div class=\"micro-field-header\">\n <span class=\"mf-col-name\">Field</span>\n @if (!HasDiffs) {\n <span class=\"mf-col-value\">Value</span>\n }\n @if (HasDiffs) {\n <span class=\"mf-col-old\">Old</span>\n <span class=\"mf-col-new\">New</span>\n }\n </div>\n @for (field of VisibleFields; track field; let odd = $odd) {\n <div class=\"micro-field-row\"\n [class.odd]=\"odd\" [ngClass]=\"field.DiffClass\">\n <span class=\"mf-col-name\" [title]=\"field.Description\">\n <i [class]=\"GetTypeIcon(field.Type)\" class=\"mf-type-icon\"></i>\n <span class=\"mf-field-name\">{{field.DisplayName}}</span>\n </span>\n @if (!HasDiffs) {\n <span class=\"mf-col-value\" [title]=\"field.Value\">\n <!-- Boolean field -->\n @if (field.IsBoolean && !field.IsNull) {\n <i [class]=\"field.BooleanValue ? 'fa-solid fa-square-check mf-bool-true' : 'fa-regular fa-square mf-bool-false'\"\n class=\"mf-bool-icon\"></i>\n <span class=\"mf-bool-label\">{{field.BooleanValue ? 'Yes' : 'No'}}</span>\n }\n <!-- FK field with display value — show display name (ID) with open icon -->\n @if (!field.IsBoolean && field.ForeignKeyEntityName && field.ForeignKeyDisplayValue) {\n <a class=\"mf-fk-link\" (click)=\"OnEntityLinkClicked($event, field)\"\n [title]=\"field.ForeignKeyEntityName + ': ' + field.ForeignKeyRecordId\">\n {{field.ForeignKeyDisplayValue}}\n <span class=\"mf-fk-id\">({{field.ForeignKeyRecordId | slice:0:8}}...)</span>\n <i class=\"fa-solid fa-arrow-up-right-from-square mf-fk-icon\"></i>\n </a>\n }\n <!-- FK field without display value — show raw ID with open icon -->\n @if (!field.IsBoolean && field.ForeignKeyEntityName && !field.ForeignKeyDisplayValue) {\n <a class=\"mf-fk-link\" (click)=\"OnEntityLinkClicked($event, field)\"\n [title]=\"'Open ' + field.ForeignKeyEntityName\">\n {{field.Value}}\n <i class=\"fa-solid fa-arrow-up-right-from-square mf-fk-icon\"></i>\n </a>\n }\n <!-- JSON field — formatted -->\n @if (!field.IsBoolean && !field.ForeignKeyEntityName && field.IsJson) {\n <pre class=\"mf-json-value\">{{field.Value}}</pre>\n }\n <!-- Regular value -->\n @if (!field.IsBoolean && !field.ForeignKeyEntityName && !field.IsJson) {\n {{field.Value}}\n }\n </span>\n }\n @if (HasDiffs) {\n <span class=\"mf-col-old\" [title]=\"field.OldValue\">\n {{field.OldValue || field.Value}}\n </span>\n <span class=\"mf-col-new\" [title]=\"field.Value\">\n {{field.Value}}\n </span>\n }\n </div>\n }\n </div>\n }\n\n <!-- Empty -->\n @if (!IsLoading && !ErrorMessage && Fields.length === 0) {\n <div class=\"micro-empty\">\n <p>No field data available.</p>\n </div>\n }\n </div>\n</ng-template>\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-versions",
3
- "version": "5.30.0",
3
+ "version": "5.31.0",
4
4
  "description": "MemberJunction: Angular Version History Components - Label creation, detail viewing, and slide panel",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -26,11 +26,12 @@
26
26
  "@angular/forms": "21.1.3"
27
27
  },
28
28
  "dependencies": {
29
- "@memberjunction/core": "5.30.0",
30
- "@memberjunction/core-entities": "5.30.0",
31
- "@memberjunction/global": "5.30.0",
32
- "@memberjunction/graphql-dataprovider": "5.30.0",
33
- "@memberjunction/ng-shared-generic": "5.30.0",
29
+ "@memberjunction/core": "5.31.0",
30
+ "@memberjunction/ng-base-types": "5.31.0",
31
+ "@memberjunction/core-entities": "5.31.0",
32
+ "@memberjunction/global": "5.31.0",
33
+ "@memberjunction/graphql-dataprovider": "5.31.0",
34
+ "@memberjunction/ng-shared-generic": "5.31.0",
34
35
  "rxjs": "^7.8.2",
35
36
  "tslib": "^2.8.1"
36
37
  },