@memberjunction/ng-record-changes 5.38.0 → 5.40.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/README.md CHANGED
@@ -198,7 +198,8 @@ import {
198
198
  | `@memberjunction/core` | Core framework (BaseEntity, Metadata, RunView) |
199
199
  | `@memberjunction/core-entities` | `MJRecordChangeEntity` definition |
200
200
  | `@memberjunction/ng-shared-generic` | Shared generic components (mj-loading) |
201
- | `@memberjunction/ng-versions` | Provides `mj-slide-panel` and version label create wizard |
201
+ | `@memberjunction/ng-ui-components` | Provides `mj-slide-panel` |
202
+ | `@memberjunction/ng-versions` | Version label create wizard |
202
203
  | `@memberjunction/ng-notifications` | Toast notifications |
203
204
  | `diff` | Word/character text diff for the timeline |
204
205
 
@@ -9,8 +9,9 @@ import * as i2 from "@angular/platform-browser";
9
9
  import * as i3 from "@angular/forms";
10
10
  import * as i4 from "@memberjunction/ng-shared-generic";
11
11
  import * as i5 from "@memberjunction/ng-versions";
12
- import * as i6 from "./restore-preview-panel/restore-preview-panel.component";
13
- import * as i7 from "@angular/common";
12
+ import * as i6 from "@memberjunction/ng-ui-components";
13
+ import * as i7 from "./restore-preview-panel/restore-preview-panel.component";
14
+ import * as i8 from "@angular/common";
14
15
  const _c0 = a0 => [a0];
15
16
  const _forTrack0 = ($index, $item) => $item.ID;
16
17
  const _forTrack1 = ($index, $item) => $item.Key;
@@ -1438,7 +1439,7 @@ export class RecordChangesComponent extends BaseAngularComponent {
1438
1439
  i0.ɵɵproperty("Visible", ctx.RestorePreviewVisible)("Mode", "live")("RecordChange", ctx.RestorePreviewChange)("LiveRecord", ctx.record);
1439
1440
  i0.ɵɵadvance();
1440
1441
  i0.ɵɵconditional(ctx.ShowCreateWizard ? 4 : -1);
1441
- } }, dependencies: [i3.DefaultValueAccessor, i3.NgControlStatus, i3.NgModel, i4.LoadingComponent, i5.MjSlidePanelComponent, i5.MjLabelCreateComponent, i6.RestorePreviewPanelComponent, i7.DatePipe], styles: ["/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Record Changes \u2014 Option A \"Clean Timeline\"\n Linear / Notion-inspired minimal timeline design\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* \u2500\u2500\u2500 Container \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\u2500\u2500\u2500 */\n.rc-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 20px 24px;\n background: var(--mj-bg-surface-card);\n}\n\n/* \u2500\u2500\u2500 Version Labels Section \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.rc-labels-section {\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 12px 16px;\n margin-bottom: 20px;\n border: 1px solid var(--mj-border-default);\n}\n\n.rc-labels-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.rc-labels-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.rc-labels-title i { color: var(--mj-brand-primary); }\n\n.rc-labels-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n border-radius: 10px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 700;\n}\n\n.rc-create-label-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: 1px solid var(--mj-brand-primary);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.rc-create-label-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.rc-labels-loading {\n font-size: 12px;\n color: var(--mj-text-muted);\n padding: 4px 0;\n}\n\n.rc-labels-loading i { margin-right: 4px; }\n\n.rc-labels-empty {\n font-size: 12px;\n color: var(--mj-text-disabled);\n font-style: italic;\n padding: 4px 0;\n}\n\n.rc-labels-list {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.rc-label-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 10px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n cursor: default;\n}\n\n.rc-label-chip:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.rc-label-chip-icon { color: var(--mj-brand-primary); font-size: 10px; }\n\n.rc-label-chip-name {\n font-weight: 600;\n max-width: 180px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-label-chip-meta {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.rc-label-chip-status {\n padding: 1px 5px;\n border-radius: 4px;\n font-weight: 600;\n text-transform: uppercase;\n font-size: 9px;\n letter-spacing: 0.03em;\n}\n\n.label-status-active { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.label-status-archived { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.label-status-restored { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n\n.rc-label-chip-items { white-space: nowrap; }\n\n/* \u2500\u2500\u2500 Empty State \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\u2500 */\n.rc-empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 64px 32px;\n text-align: center;\n min-height: 400px;\n}\n\n.rc-empty-state-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: var(--mj-bg-surface-sunken);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 24px;\n}\n\n.rc-empty-state-icon i { font-size: 32px; color: var(--mj-text-disabled); }\n\n.rc-empty-state-title {\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin: 0 0 12px 0;\n}\n\n.rc-empty-state-description {\n font-size: 14px;\n color: var(--mj-text-muted);\n line-height: 1.6;\n max-width: 320px;\n margin: 0 0 24px 0;\n}\n\n.rc-empty-state-hint {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 20px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.rc-empty-state-hint i { color: var(--mj-text-disabled); }\n\n/* \u2500\u2500\u2500 Page Header \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\u2500 */\n.rc-page-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n padding-bottom: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-page-title {\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.rc-page-subtitle {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-top: 4px;\n}\n\n.rc-header-meta { text-align: right; }\n\n.rc-entity-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-bg-surface));\n}\n\n.rc-change-count {\n font-size: 12px;\n color: var(--mj-text-disabled);\n margin-top: 6px;\n}\n\n/* \u2500\u2500\u2500 Filter Bar \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\u2500\u2500 */\n.rc-filter-bar {\n display: flex;\n gap: 8px;\n margin-bottom: 20px;\n flex-wrap: wrap;\n align-items: center;\n}\n\n.rc-search-wrap {\n position: relative;\n flex: 1;\n min-width: 180px;\n}\n\n.rc-search-wrap i {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-disabled);\n font-size: 13px;\n pointer-events: none;\n}\n\n.rc-search-box {\n width: 100%;\n padding: 8px 12px 8px 36px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n background: var(--mj-bg-surface);\n outline: none;\n color: var(--mj-text-primary);\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.rc-search-box:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-search-box::placeholder { color: var(--mj-text-disabled); }\n\n.rc-filter-pill {\n padding: 7px 14px;\n border-radius: 8px;\n font-size: 12px;\n font-weight: 500;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: all 0.15s;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n\n.rc-filter-pill:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.rc-filter-pill.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.rc-filter-results {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-bottom: 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.rc-clear-filters-link {\n background: none;\n border: none;\n color: var(--mj-brand-primary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n padding: 0;\n text-decoration: underline;\n}\n\n.rc-clear-filters-link:hover { color: var(--mj-brand-primary-hover); }\n\n/* \u2500\u2500\u2500 No Results \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\u2500\u2500 */\n.rc-no-results {\n text-align: center;\n padding: 48px 16px;\n color: var(--mj-text-muted);\n}\n\n.rc-no-results i {\n display: block;\n font-size: 32px;\n margin-bottom: 16px;\n color: var(--mj-text-disabled);\n}\n\n.rc-no-results p { font-size: 14px; margin: 0 0 16px 0; }\n\n.rc-clear-filters-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.rc-clear-filters-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n/* \u2500\u2500\u2500 Timeline \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\u2500\u2500\u2500\u2500 */\n.rc-timeline {\n position: relative;\n flex: 1;\n overflow-y: auto;\n}\n\n/* Vertical line running through the timeline */\n.rc-timeline::before {\n content: '';\n position: absolute;\n left: 15px;\n top: 24px;\n bottom: 0;\n width: 2px;\n background: var(--mj-border-default);\n}\n\n/* \u2500\u2500\u2500 Date Group \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\u2500\u2500 */\n.rc-date-group { margin-bottom: 8px; }\n\n.rc-date-label {\n position: relative;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n color: var(--mj-text-disabled);\n padding: 16px 0 12px 44px;\n}\n\n/* Date dot on the timeline line */\n.rc-date-label::before {\n content: '';\n position: absolute;\n left: 10px;\n top: 50%;\n transform: translateY(-50%);\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: var(--mj-border-default);\n border: 2px solid var(--mj-bg-surface-card);\n}\n\n/* \u2500\u2500\u2500 Change Card \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\u2500 */\n.rc-card {\n position: relative;\n margin-left: 44px;\n margin-bottom: 12px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n border: 1px solid var(--mj-border-default);\n transition: all 0.2s;\n overflow: hidden;\n}\n\n.rc-card:hover {\n border-color: var(--mj-border-strong);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.rc-card:focus {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Colored dot on the timeline line for each card */\n.rc-card::before {\n content: '';\n position: absolute;\n left: -23px;\n top: 20px;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n z-index: 1;\n}\n\n.rc-card.type-update::before {\n background: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-card.type-create::before {\n background: var(--mj-status-success);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-success) 15%, transparent);\n}\n\n.rc-card.type-delete::before {\n background: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 15%, transparent);\n}\n\n/* \u2500\u2500\u2500 Card Header \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\u2500 */\n.rc-card-header {\n padding: 14px 18px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n user-select: none;\n gap: 12px;\n}\n\n.rc-card-header-left {\n display: flex;\n align-items: center;\n gap: 10px;\n min-width: 0;\n flex: 1;\n /* Allow the lineage chip to wrap to a second line on narrow panel widths\n instead of squeezing the title text into a \"Name and Description c...\"\n truncation. The badge stays on the first line; chip wraps gracefully. */\n flex-wrap: wrap;\n row-gap: 6px;\n}\n\n.rc-card-type-badge {\n padding: 3px 10px;\n border-radius: 5px;\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.3px;\n text-transform: uppercase;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.type-update .rc-card-type-badge { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.type-create .rc-card-type-badge { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.type-delete .rc-card-type-badge { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n\n.rc-card-summary {\n font-size: 13px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-card-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n font-size: 12px;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n}\n\n.rc-card-user {\n display: flex;\n align-items: center;\n gap: 5px;\n white-space: nowrap;\n}\n\n.rc-avatar {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 8px;\n font-weight: 700;\n color: var(--mj-text-inverse);\n flex-shrink: 0;\n}\n\n.rc-card-time { white-space: nowrap; }\n\n.rc-card-source {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.source-internal { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.source-external { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n\n.rc-card-status {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n text-transform: uppercase;\n white-space: nowrap;\n}\n\n.status-complete { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.status-pending { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n.status-error { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n.status-unknown { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n.rc-card-chevron {\n color: var(--mj-text-disabled);\n transition: transform 0.2s;\n font-size: 12px;\n flex-shrink: 0;\n}\n\n.rc-card.expanded .rc-card-chevron { transform: rotate(180deg); }\n\n/* \u2500\u2500\u2500 Card Body \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\u2500\u2500\u2500 */\n.rc-card-body {\n border-top: 1px solid var(--mj-border-default);\n}\n\n/* \u2500\u2500\u2500 Field Row \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\u2500\u2500\u2500 */\n.rc-field-row {\n display: flex;\n align-items: stretch;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-field-row:last-child { border-bottom: none; }\n\n.rc-field-label {\n width: 140px;\n min-width: 140px;\n padding: 12px 16px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n display: flex;\n align-items: center;\n border-right: 1px solid var(--mj-border-default);\n}\n\n.rc-field-values {\n flex: 1;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n min-width: 0;\n}\n\n/* \u2500\u2500\u2500 Atomic Change (numbers, dates) \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.rc-atomic-change {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.rc-val-old {\n font-size: 13px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-disabled);\n text-decoration: line-through;\n font-weight: 400;\n}\n\n.rc-val-arrow {\n color: var(--mj-border-strong);\n font-size: 11px;\n flex-shrink: 0;\n}\n\n.rc-val-new {\n font-size: 13px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n/* \u2500\u2500\u2500 Boolean Change \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.rc-bool-change {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.rc-bool-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.rc-bool-dot.on { background: var(--mj-status-success); }\n.rc-bool-dot.off { background: var(--mj-border-strong); }\n\n.rc-bool-label {\n font-size: 13px;\n font-weight: 500;\n}\n\n.rc-bool-label.old {\n color: var(--mj-text-disabled);\n text-decoration: line-through;\n}\n\n.rc-bool-label.new.active { color: var(--mj-status-success); }\n.rc-bool-label.new.inactive { color: var(--mj-text-disabled); }\n\n/* \u2500\u2500\u2500 Text Diff (strings only) \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.rc-text-diff {\n font-size: 13px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n line-height: 1.6;\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n\n.rc-diff-added {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n padding: 1px 3px;\n border-radius: 3px;\n}\n\n.rc-diff-removed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n padding: 1px 3px;\n border-radius: 3px;\n text-decoration: line-through;\n}\n\n.rc-diff-unchanged {\n color: var(--mj-text-secondary);\n}\n\n/* \u2500\u2500\u2500 Deletion Note \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.rc-deletion-note {\n padding: 16px 18px;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-style: italic;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.rc-deletion-note i {\n color: var(--mj-status-error);\n font-size: 14px;\n}\n\n/* \u2500\u2500\u2500 Comments & Errors \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.rc-comments {\n padding: 12px 18px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-brand-primary);\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-comments i {\n color: var(--mj-brand-primary);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-errors {\n padding: 12px 18px;\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-status-error);\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-errors i {\n color: var(--mj-status-error);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-error-log {\n background: var(--mj-bg-surface);\n padding: 8px;\n border-radius: 4px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n font-size: 12px;\n color: var(--mj-status-error);\n margin: 0;\n white-space: pre-wrap;\n overflow-x: auto;\n flex: 1;\n}\n\n/* \u2500\u2500\u2500 Create Wizard Overlay \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.rc-wizard-overlay {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: rc-fadeIn 0.15s ease;\n}\n\n.rc-wizard-container {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\n width: 90%;\n max-width: 600px;\n max-height: 80vh;\n overflow-y: auto;\n padding: 24px;\n animation: rc-slideUp 0.2s ease;\n}\n\n@keyframes rc-fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes rc-slideUp {\n from { opacity: 0; transform: translateY(20px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* \u2500\u2500\u2500 Responsive \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\u2500\u2500 */\n@media (max-width: 768px) {\n .rc-card-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n\n .rc-card-meta {\n flex-wrap: wrap;\n gap: 8px;\n }\n\n .rc-field-row {\n flex-direction: column;\n }\n\n .rc-field-label {\n width: 100%;\n min-width: unset;\n border-right: none;\n border-bottom: 1px solid var(--mj-border-default);\n padding: 8px 16px;\n }\n\n .rc-field-values {\n padding: 8px 16px;\n }\n\n .rc-atomic-change {\n flex-wrap: wrap;\n }\n\n .rc-filter-bar {\n flex-direction: column;\n align-items: stretch;\n }\n\n .rc-search-wrap { min-width: unset; }\n\n .rc-filter-pill { justify-content: center; }\n\n .rc-page-header {\n flex-direction: column;\n gap: 12px;\n }\n\n .rc-header-meta { text-align: left; }\n}\n\n@media (max-width: 480px) {\n .rc-container { padding: 12px 16px; }\n\n .rc-card { margin-left: 36px; }\n\n .rc-date-label { padding-left: 36px; }\n\n .rc-card::before { left: -19px; }\n\n .rc-timeline::before { left: 12px; }\n\n .rc-date-label::before { left: 7px; }\n}\n\n/* \u2500\u2500\u2500 Restore Action \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.rc-restore-action {\n display: flex;\n justify-content: flex-end;\n padding-top: 10px;\n margin-top: 10px;\n /* Breathing room from the card's bottom and right edges so the button\n doesn't sit flush against the border. */\n padding-right: 10px;\n padding-bottom: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n.rc-restore-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n border-radius: 6px;\n cursor: pointer;\n transition: all 150ms ease;\n font-family: inherit;\n line-height: 1;\n}\n\n.rc-restore-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 6px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-restore-btn:active {\n transform: translateY(1px);\n box-shadow: none;\n}\n\n.rc-restore-btn i {\n font-size: 13px;\n}\n\n/* \u2500\u2500\u2500 Restore Preview Panel \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.rc-restore-preview-backdrop {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: rc-fadeIn 0.15s ease;\n}\n\n.rc-restore-preview-panel {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\n width: 90%;\n max-width: 700px;\n max-height: 80vh;\n overflow-y: auto;\n padding: 0;\n animation: rc-slideUp 0.2s ease;\n}\n\n.rc-restore-preview-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.rc-restore-preview-title i {\n color: var(--mj-brand-primary);\n}\n\n.rc-restore-preview-close {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 16px;\n transition: color 0.15s, background 0.15s;\n}\n\n.rc-restore-preview-close:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.rc-restore-preview-meta {\n display: flex;\n gap: 20px;\n padding: 12px 20px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-empty {\n padding: 24px 20px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 13px;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n\n.rc-restore-preview-empty i {\n color: var(--mj-text-disabled);\n}\n\n/* Restore Preview Table */\n.rc-restore-preview-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.rc-restore-preview-table th {\n text-align: left;\n padding: 10px 16px;\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-table td {\n padding: 10px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n vertical-align: top;\n}\n\n.rc-restore-preview-table tr:last-child td {\n border-bottom: none;\n}\n\n.rc-restore-preview-table tr.rc-diff-changed {\n background: color-mix(in srgb, var(--mj-status-warning) 5%, var(--mj-bg-surface));\n}\n\n.rc-restore-preview-table tr.rc-diff-unchanged {\n opacity: 0.6;\n}\n\n.rc-restore-field-name {\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n}\n\n.rc-restore-current {\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-secondary);\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-restore-version {\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-primary);\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-restore-indicator {\n text-align: center;\n width: 30px;\n}\n\n.rc-diff-changed .rc-restore-indicator i {\n color: var(--mj-status-warning);\n}\n\n.rc-diff-unchanged .rc-restore-indicator i {\n color: var(--mj-status-success);\n font-size: 12px;\n}\n\n/* Restore Preview Actions */\n.rc-restore-preview-actions {\n display: flex;\n gap: 10px;\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-confirm-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.15s, box-shadow 0.15s;\n font-family: inherit;\n}\n\n.rc-restore-confirm-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n.rc-restore-confirm-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.rc-restore-cancel-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n}\n\n.rc-restore-cancel-btn:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.rc-restore-cancel-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * Restore lineage + conditional filter chips + overflow popover\n * (added with the Restore Prior Version feature)\n * \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* \u2500\u2500\u2500 Filter pill enhancements \u2500\u2500\u2500 */\n\n.rc-filter-pill-count {\n margin-left: 4px;\n background: color-mix(in srgb, currentColor 12%, transparent);\n padding: 1px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 700;\n}\n\n.rc-filter-pill.active .rc-filter-pill-count {\n background: color-mix(in srgb, var(--mj-text-inverse, #fff) 22%, transparent);\n}\n\n/* Restore-variant pill: violet treatment to set it apart from type pills */\n.rc-filter-pill-restore {\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n color: color-mix(in srgb, var(--mj-status-info) 80%, var(--mj-text-secondary));\n border-color: color-mix(in srgb, var(--mj-status-info) 30%, var(--mj-border-default));\n}\n.rc-filter-pill-restore:hover {\n border-color: var(--mj-status-info);\n color: var(--mj-status-info);\n}\n.rc-filter-pill-restore.active {\n background: var(--mj-status-info);\n color: var(--mj-text-inverse, #fff);\n border-color: var(--mj-status-info);\n}\n\n/* \u2500\u2500\u2500 Overflow filter popover \u2500\u2500\u2500 */\n\n.rc-filter-overflow-wrap {\n position: relative;\n display: inline-block;\n}\n\n.rc-filter-pill-overflow {\n /* Overflow trigger inherits the standard filter pill look */\n}\n\n.rc-filter-overflow-caret {\n font-size: 9px;\n margin-left: 2px;\n}\n\n.rc-filter-overflow-backdrop {\n position: fixed;\n inset: 0;\n z-index: 10;\n}\n\n.rc-filter-overflow-popover {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n z-index: 11;\n min-width: 240px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n box-shadow: 0 14px 40px rgba(15, 23, 42, 0.18);\n padding: 8px;\n}\n\n.rc-filter-overflow-header {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--mj-text-muted);\n font-weight: 600;\n padding: 6px 8px 8px;\n}\n\n.rc-filter-overflow-row {\n display: flex;\n align-items: center;\n gap: 9px;\n padding: 7px 8px;\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n cursor: pointer;\n}\n\n.rc-filter-overflow-row:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.rc-filter-overflow-row input[type=\"checkbox\"] {\n margin: 0;\n accent-color: var(--mj-brand-primary);\n}\n\n.rc-filter-overflow-row i {\n color: var(--mj-text-muted);\n font-size: 12px;\n width: 14px;\n text-align: center;\n}\n\n.rc-filter-overflow-row-restore i {\n color: var(--mj-status-info);\n}\n\n.rc-filter-overflow-label {\n flex: 1;\n}\n\n.rc-filter-overflow-count {\n color: var(--mj-text-muted);\n font-size: 11px;\n font-weight: 500;\n}\n\n.rc-filter-overflow-actions {\n display: flex;\n justify-content: space-between;\n border-top: 1px solid var(--mj-border-subtle);\n padding-top: 8px;\n margin-top: 6px;\n}\n\n.rc-filter-overflow-clear,\n.rc-filter-overflow-done {\n background: none;\n border: none;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n padding: 4px 10px;\n border-radius: 5px;\n}\n\n.rc-filter-overflow-clear {\n color: var(--mj-text-muted);\n}\n.rc-filter-overflow-clear:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.rc-filter-overflow-done {\n color: var(--mj-brand-primary);\n}\n.rc-filter-overflow-done:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n\n/* \u2500\u2500\u2500 Snapshot type badge + card accent \u2500\u2500\u2500 */\n\n.type-snapshot .rc-card-type-badge {\n background: color-mix(in srgb, var(--mj-text-muted) 15%, var(--mj-bg-surface));\n color: var(--mj-text-secondary);\n}\n\n/* \u2500\u2500\u2500 Restore Source pill (in card meta) \u2500\u2500\u2500 */\n\n.source-restore {\n background: color-mix(in srgb, var(--mj-status-info) 12%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n/* \u2500\u2500\u2500 Restore card variant: violet left accent \u2500\u2500\u2500 */\n\n.rc-card.rc-card-restore {\n border-left: 3px solid var(--mj-status-info);\n}\n\n/* \u2500\u2500\u2500 Lineage chip \u2500\u2500\u2500 */\n\n/* Lineage chip \u2014 outline-only \"interactive link\" treatment so it reads as\n distinct from the filled RESTORE badge sitting next to it. The badge says\n \"this row IS a restore\" (filled, static); the chip says \"click here to\n see the source version\" (outline, hoverable). */\n.rc-restored-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n margin-left: 8px;\n padding: 2px 9px;\n border-radius: 11px;\n font-size: 11px;\n font-weight: 500;\n background: transparent;\n color: color-mix(in srgb, var(--mj-status-info) 90%, var(--mj-text-primary));\n border: 1px solid color-mix(in srgb, var(--mj-status-info) 40%, var(--mj-border-default));\n cursor: pointer;\n text-decoration: none;\n white-space: nowrap;\n transition: background-color 0.12s, border-color 0.12s, color 0.12s;\n}\n\n.rc-restored-chip:hover {\n background: color-mix(in srgb, var(--mj-status-info) 12%, transparent);\n border-color: var(--mj-status-info);\n color: var(--mj-status-info);\n}\n\n.rc-restored-chip i {\n font-size: 10px;\n}\n\n.rc-restored-chip-orphan {\n cursor: default;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-muted);\n border-color: var(--mj-border-default);\n}\n\n.rc-restored-chip-orphan:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-default);\n}\n\n/* \u2500\u2500\u2500 Card highlight (when jumped-to via lineage chip) \u2500\u2500\u2500 */\n\n.rc-card.rc-card-highlight {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n animation: rc-card-pulse 1.4s ease-in-out;\n}\n\n@keyframes rc-card-pulse {\n 0%, 100% { background: var(--mj-bg-surface); }\n 50% { background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface)); }\n}\n\n/* \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * Restore-row badge override + Restore Reason block\n * (mockup-aligned treatment for restore rows in the timeline)\n * \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* The base type-update badge styling would otherwise paint a restore row's\n badge blue with \"Update\" text. Override to violet + \"Restore\" text so it\n matches the source pill, lineage chip, and card border. */\n.rc-card-type-badge.rc-card-type-badge-restore {\n background: color-mix(in srgb, var(--mj-status-info) 14%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n/* Restore reason \u2014 minimal blockquote treatment.\n A thin violet left bar + italic text reads like a margin note rather than\n a heavy callout. Visually connected to the restore family (left bar uses\n the same violet as the badge / source pill / card border) without\n competing with the field-diff rows that follow. */\n.rc-restore-reason {\n /* Indented in from the card body edge so it visually nests one level\n deeper than the field-diff rows that follow, and given generous\n vertical breathing room so it doesn't crowd the lineage chip above\n or the first field row below. */\n margin: 14px 8px 18px 18px;\n padding: 0 0 0 12px;\n border-left: 2px solid color-mix(in srgb, var(--mj-status-info) 55%, var(--mj-border-default));\n display: flex;\n align-items: baseline;\n gap: 8px;\n font-size: 13px;\n line-height: 1.5;\n}\n\n.rc-restore-reason-label {\n flex-shrink: 0;\n font-size: 11px;\n font-weight: 600;\n color: color-mix(in srgb, var(--mj-status-info) 75%, var(--mj-text-muted));\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.rc-restore-reason-text {\n color: var(--mj-text-secondary);\n font-style: italic;\n}\n"], encapsulation: 2, changeDetection: 0 });
1442
+ } }, dependencies: [i3.DefaultValueAccessor, i3.NgControlStatus, i3.NgModel, i4.LoadingComponent, i5.MjLabelCreateComponent, i6.MjSlidePanelComponent, i7.RestorePreviewPanelComponent, i8.DatePipe], styles: ["/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n Record Changes \u2014 Option A \"Clean Timeline\"\n Linear / Notion-inspired minimal timeline design\n \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */\n\n/* \u2500\u2500\u2500 Container \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\u2500\u2500\u2500 */\n.rc-container {\n display: flex;\n flex-direction: column;\n height: 100%;\n padding: 20px 24px;\n background: var(--mj-bg-surface-card);\n}\n\n/* \u2500\u2500\u2500 Version Labels Section \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.rc-labels-section {\n background: var(--mj-bg-surface-card);\n border-radius: 8px;\n padding: 12px 16px;\n margin-bottom: 20px;\n border: 1px solid var(--mj-border-default);\n}\n\n.rc-labels-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 8px;\n}\n\n.rc-labels-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-weight: 600;\n font-size: 13px;\n color: var(--mj-text-secondary);\n}\n\n.rc-labels-title i { color: var(--mj-brand-primary); }\n\n.rc-labels-count {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 20px;\n height: 20px;\n padding: 0 6px;\n border-radius: 10px;\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n font-size: 10px;\n font-weight: 700;\n}\n\n.rc-create-label-btn {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 5px 12px;\n border: 1px solid var(--mj-brand-primary);\n border-radius: 6px;\n background: var(--mj-bg-surface);\n color: var(--mj-brand-primary);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.rc-create-label-btn:hover {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n}\n\n.rc-labels-loading {\n font-size: 12px;\n color: var(--mj-text-muted);\n padding: 4px 0;\n}\n\n.rc-labels-loading i { margin-right: 4px; }\n\n.rc-labels-empty {\n font-size: 12px;\n color: var(--mj-text-disabled);\n font-style: italic;\n padding: 4px 0;\n}\n\n.rc-labels-list {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n}\n\n.rc-label-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n padding: 4px 10px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 16px;\n font-size: 12px;\n color: var(--mj-text-secondary);\n transition: all 0.15s ease;\n cursor: default;\n}\n\n.rc-label-chip:hover {\n border-color: var(--mj-brand-primary);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.rc-label-chip-icon { color: var(--mj-brand-primary); font-size: 10px; }\n\n.rc-label-chip-name {\n font-weight: 600;\n max-width: 180px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-label-chip-meta {\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 10px;\n color: var(--mj-text-muted);\n}\n\n.rc-label-chip-status {\n padding: 1px 5px;\n border-radius: 4px;\n font-weight: 600;\n text-transform: uppercase;\n font-size: 9px;\n letter-spacing: 0.03em;\n}\n\n.label-status-active { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.label-status-archived { background: var(--mj-bg-surface-sunken); color: var(--mj-text-secondary); }\n.label-status-restored { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n\n.rc-label-chip-items { white-space: nowrap; }\n\n/* \u2500\u2500\u2500 Empty State \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\u2500 */\n.rc-empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 64px 32px;\n text-align: center;\n min-height: 400px;\n}\n\n.rc-empty-state-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n background: var(--mj-bg-surface-sunken);\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 24px;\n}\n\n.rc-empty-state-icon i { font-size: 32px; color: var(--mj-text-disabled); }\n\n.rc-empty-state-title {\n font-size: 20px;\n font-weight: 600;\n color: var(--mj-text-secondary);\n margin: 0 0 12px 0;\n}\n\n.rc-empty-state-description {\n font-size: 14px;\n color: var(--mj-text-muted);\n line-height: 1.6;\n max-width: 320px;\n margin: 0 0 24px 0;\n}\n\n.rc-empty-state-hint {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n padding: 8px 16px;\n background: var(--mj-bg-surface-sunken);\n border-radius: 20px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.rc-empty-state-hint i { color: var(--mj-text-disabled); }\n\n/* \u2500\u2500\u2500 Page Header \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\u2500 */\n.rc-page-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 24px;\n padding-bottom: 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-page-title {\n font-size: 20px;\n font-weight: 700;\n color: var(--mj-text-primary);\n margin: 0;\n}\n\n.rc-page-subtitle {\n font-size: 13px;\n color: var(--mj-text-muted);\n margin-top: 4px;\n}\n\n.rc-header-meta { text-align: right; }\n\n.rc-entity-badge {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 12px;\n border-radius: 6px;\n font-size: 12px;\n font-weight: 500;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, var(--mj-bg-surface));\n}\n\n.rc-change-count {\n font-size: 12px;\n color: var(--mj-text-disabled);\n margin-top: 6px;\n}\n\n/* \u2500\u2500\u2500 Filter Bar \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\u2500\u2500 */\n.rc-filter-bar {\n display: flex;\n gap: 8px;\n margin-bottom: 20px;\n flex-wrap: wrap;\n align-items: center;\n}\n\n.rc-search-wrap {\n position: relative;\n flex: 1;\n min-width: 180px;\n}\n\n.rc-search-wrap i {\n position: absolute;\n left: 12px;\n top: 50%;\n transform: translateY(-50%);\n color: var(--mj-text-disabled);\n font-size: 13px;\n pointer-events: none;\n}\n\n.rc-search-box {\n width: 100%;\n padding: 8px 12px 8px 36px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n font-size: 13px;\n background: var(--mj-bg-surface);\n outline: none;\n color: var(--mj-text-primary);\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n\n.rc-search-box:focus {\n border-color: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-search-box::placeholder { color: var(--mj-text-disabled); }\n\n.rc-filter-pill {\n padding: 7px 14px;\n border-radius: 8px;\n font-size: 12px;\n font-weight: 500;\n border: 1px solid var(--mj-border-default);\n background: var(--mj-bg-surface);\n cursor: pointer;\n color: var(--mj-text-secondary);\n transition: all 0.15s;\n display: flex;\n align-items: center;\n gap: 5px;\n}\n\n.rc-filter-pill:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n.rc-filter-pill.active {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse);\n border-color: var(--mj-brand-primary);\n}\n\n.rc-filter-results {\n font-size: 12px;\n color: var(--mj-text-muted);\n margin-bottom: 16px;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.rc-clear-filters-link {\n background: none;\n border: none;\n color: var(--mj-brand-primary);\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n padding: 0;\n text-decoration: underline;\n}\n\n.rc-clear-filters-link:hover { color: var(--mj-brand-primary-hover); }\n\n/* \u2500\u2500\u2500 No Results \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\u2500\u2500 */\n.rc-no-results {\n text-align: center;\n padding: 48px 16px;\n color: var(--mj-text-muted);\n}\n\n.rc-no-results i {\n display: block;\n font-size: 32px;\n margin-bottom: 16px;\n color: var(--mj-text-disabled);\n}\n\n.rc-no-results p { font-size: 14px; margin: 0 0 16px 0; }\n\n.rc-clear-filters-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 16px;\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: all 0.15s ease;\n}\n\n.rc-clear-filters-btn:hover {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n}\n\n/* \u2500\u2500\u2500 Timeline \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\u2500\u2500\u2500\u2500 */\n.rc-timeline {\n position: relative;\n flex: 1;\n overflow-y: auto;\n}\n\n/* Vertical line running through the timeline */\n.rc-timeline::before {\n content: '';\n position: absolute;\n left: 15px;\n top: 24px;\n bottom: 0;\n width: 2px;\n background: var(--mj-border-default);\n}\n\n/* \u2500\u2500\u2500 Date Group \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\u2500\u2500 */\n.rc-date-group { margin-bottom: 8px; }\n\n.rc-date-label {\n position: relative;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.8px;\n color: var(--mj-text-disabled);\n padding: 16px 0 12px 44px;\n}\n\n/* Date dot on the timeline line */\n.rc-date-label::before {\n content: '';\n position: absolute;\n left: 10px;\n top: 50%;\n transform: translateY(-50%);\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: var(--mj-border-default);\n border: 2px solid var(--mj-bg-surface-card);\n}\n\n/* \u2500\u2500\u2500 Change Card \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\u2500 */\n.rc-card {\n position: relative;\n margin-left: 44px;\n margin-bottom: 12px;\n background: var(--mj-bg-surface);\n border-radius: 12px;\n border: 1px solid var(--mj-border-default);\n transition: all 0.2s;\n overflow: hidden;\n}\n\n.rc-card:hover {\n border-color: var(--mj-border-strong);\n box-shadow: var(--mj-shadow-sm);\n}\n\n.rc-card:focus {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n}\n\n/* Colored dot on the timeline line for each card */\n.rc-card::before {\n content: '';\n position: absolute;\n left: -23px;\n top: 20px;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n z-index: 1;\n}\n\n.rc-card.type-update::before {\n background: var(--mj-brand-primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-card.type-create::before {\n background: var(--mj-status-success);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-success) 15%, transparent);\n}\n\n.rc-card.type-delete::before {\n background: var(--mj-status-error);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--mj-status-error) 15%, transparent);\n}\n\n/* \u2500\u2500\u2500 Card Header \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\u2500 */\n.rc-card-header {\n padding: 14px 18px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n cursor: pointer;\n user-select: none;\n gap: 12px;\n}\n\n.rc-card-header-left {\n display: flex;\n align-items: center;\n gap: 10px;\n min-width: 0;\n flex: 1;\n /* Allow the lineage chip to wrap to a second line on narrow panel widths\n instead of squeezing the title text into a \"Name and Description c...\"\n truncation. The badge stays on the first line; chip wraps gracefully. */\n flex-wrap: wrap;\n row-gap: 6px;\n}\n\n.rc-card-type-badge {\n padding: 3px 10px;\n border-radius: 5px;\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.3px;\n text-transform: uppercase;\n white-space: nowrap;\n flex-shrink: 0;\n}\n\n.type-update .rc-card-type-badge { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.type-create .rc-card-type-badge { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.type-delete .rc-card-type-badge { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n\n.rc-card-summary {\n font-size: 13px;\n color: var(--mj-text-secondary);\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-card-meta {\n display: flex;\n align-items: center;\n gap: 12px;\n font-size: 12px;\n color: var(--mj-text-disabled);\n flex-shrink: 0;\n}\n\n.rc-card-user {\n display: flex;\n align-items: center;\n gap: 5px;\n white-space: nowrap;\n}\n\n.rc-avatar {\n width: 20px;\n height: 20px;\n border-radius: 50%;\n background: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 8px;\n font-weight: 700;\n color: var(--mj-text-inverse);\n flex-shrink: 0;\n}\n\n.rc-card-time { white-space: nowrap; }\n\n.rc-card-source {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 500;\n white-space: nowrap;\n}\n\n.source-internal { background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface)); color: var(--mj-brand-primary); }\n.source-external { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n\n.rc-card-status {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 4px;\n font-weight: 600;\n text-transform: uppercase;\n white-space: nowrap;\n}\n\n.status-complete { background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface)); color: var(--mj-status-success); }\n.status-pending { background: color-mix(in srgb, var(--mj-status-warning) 15%, var(--mj-bg-surface)); color: var(--mj-status-warning); }\n.status-error { background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface)); color: var(--mj-status-error); }\n.status-unknown { background: var(--mj-bg-surface-sunken); color: var(--mj-text-muted); }\n\n.rc-card-chevron {\n color: var(--mj-text-disabled);\n transition: transform 0.2s;\n font-size: 12px;\n flex-shrink: 0;\n}\n\n.rc-card.expanded .rc-card-chevron { transform: rotate(180deg); }\n\n/* \u2500\u2500\u2500 Card Body \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\u2500\u2500\u2500 */\n.rc-card-body {\n border-top: 1px solid var(--mj-border-default);\n}\n\n/* \u2500\u2500\u2500 Field Row \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\u2500\u2500\u2500 */\n.rc-field-row {\n display: flex;\n align-items: stretch;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-field-row:last-child { border-bottom: none; }\n\n.rc-field-label {\n width: 140px;\n min-width: 140px;\n padding: 12px 16px;\n font-size: 12px;\n font-weight: 600;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-card);\n display: flex;\n align-items: center;\n border-right: 1px solid var(--mj-border-default);\n}\n\n.rc-field-values {\n flex: 1;\n padding: 12px 16px;\n display: flex;\n align-items: center;\n min-width: 0;\n}\n\n/* \u2500\u2500\u2500 Atomic Change (numbers, dates) \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.rc-atomic-change {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n}\n\n.rc-val-old {\n font-size: 13px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-disabled);\n text-decoration: line-through;\n font-weight: 400;\n}\n\n.rc-val-arrow {\n color: var(--mj-border-strong);\n font-size: 11px;\n flex-shrink: 0;\n}\n\n.rc-val-new {\n font-size: 13px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-primary);\n font-weight: 500;\n}\n\n/* \u2500\u2500\u2500 Boolean Change \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.rc-bool-change {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.rc-bool-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.rc-bool-dot.on { background: var(--mj-status-success); }\n.rc-bool-dot.off { background: var(--mj-border-strong); }\n\n.rc-bool-label {\n font-size: 13px;\n font-weight: 500;\n}\n\n.rc-bool-label.old {\n color: var(--mj-text-disabled);\n text-decoration: line-through;\n}\n\n.rc-bool-label.new.active { color: var(--mj-status-success); }\n.rc-bool-label.new.inactive { color: var(--mj-text-disabled); }\n\n/* \u2500\u2500\u2500 Text Diff (strings only) \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.rc-text-diff {\n font-size: 13px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n line-height: 1.6;\n word-wrap: break-word;\n white-space: pre-wrap;\n}\n\n.rc-diff-added {\n background: color-mix(in srgb, var(--mj-status-success) 15%, var(--mj-bg-surface));\n color: var(--mj-status-success);\n padding: 1px 3px;\n border-radius: 3px;\n}\n\n.rc-diff-removed {\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n color: var(--mj-status-error);\n padding: 1px 3px;\n border-radius: 3px;\n text-decoration: line-through;\n}\n\n.rc-diff-unchanged {\n color: var(--mj-text-secondary);\n}\n\n/* \u2500\u2500\u2500 Deletion Note \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.rc-deletion-note {\n padding: 16px 18px;\n color: var(--mj-text-muted);\n font-size: 13px;\n font-style: italic;\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.rc-deletion-note i {\n color: var(--mj-status-error);\n font-size: 14px;\n}\n\n/* \u2500\u2500\u2500 Comments & Errors \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.rc-comments {\n padding: 12px 18px;\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-brand-primary);\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-comments i {\n color: var(--mj-brand-primary);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-errors {\n padding: 12px 18px;\n background: color-mix(in srgb, var(--mj-status-error) 15%, var(--mj-bg-surface));\n font-size: 13px;\n color: var(--mj-status-error);\n display: flex;\n align-items: flex-start;\n gap: 8px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-errors i {\n color: var(--mj-status-error);\n margin-top: 2px;\n flex-shrink: 0;\n}\n\n.rc-error-log {\n background: var(--mj-bg-surface);\n padding: 8px;\n border-radius: 4px;\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n font-size: 12px;\n color: var(--mj-status-error);\n margin: 0;\n white-space: pre-wrap;\n overflow-x: auto;\n flex: 1;\n}\n\n/* \u2500\u2500\u2500 Create Wizard Overlay \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.rc-wizard-overlay {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: rc-fadeIn 0.15s ease;\n}\n\n.rc-wizard-container {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\n width: 90%;\n max-width: 600px;\n max-height: 80vh;\n overflow-y: auto;\n padding: 24px;\n animation: rc-slideUp 0.2s ease;\n}\n\n@keyframes rc-fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n@keyframes rc-slideUp {\n from { opacity: 0; transform: translateY(20px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* \u2500\u2500\u2500 Responsive \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\u2500\u2500 */\n@media (max-width: 768px) {\n .rc-card-header {\n flex-direction: column;\n align-items: flex-start;\n gap: 8px;\n }\n\n .rc-card-meta {\n flex-wrap: wrap;\n gap: 8px;\n }\n\n .rc-field-row {\n flex-direction: column;\n }\n\n .rc-field-label {\n width: 100%;\n min-width: unset;\n border-right: none;\n border-bottom: 1px solid var(--mj-border-default);\n padding: 8px 16px;\n }\n\n .rc-field-values {\n padding: 8px 16px;\n }\n\n .rc-atomic-change {\n flex-wrap: wrap;\n }\n\n .rc-filter-bar {\n flex-direction: column;\n align-items: stretch;\n }\n\n .rc-search-wrap { min-width: unset; }\n\n .rc-filter-pill { justify-content: center; }\n\n .rc-page-header {\n flex-direction: column;\n gap: 12px;\n }\n\n .rc-header-meta { text-align: left; }\n}\n\n@media (max-width: 480px) {\n .rc-container { padding: 12px 16px; }\n\n .rc-card { margin-left: 36px; }\n\n .rc-date-label { padding-left: 36px; }\n\n .rc-card::before { left: -19px; }\n\n .rc-timeline::before { left: 12px; }\n\n .rc-date-label::before { left: 7px; }\n}\n\n/* \u2500\u2500\u2500 Restore Action \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.rc-restore-action {\n display: flex;\n justify-content: flex-end;\n padding-top: 10px;\n margin-top: 10px;\n /* Breathing room from the card's bottom and right edges so the button\n doesn't sit flush against the border. */\n padding-right: 10px;\n padding-bottom: 10px;\n border-top: 1px solid var(--mj-border-subtle);\n}\n\n.rc-restore-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 6px 14px;\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-brand-primary);\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface));\n border: 1px solid color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n border-radius: 6px;\n cursor: pointer;\n transition: all 150ms ease;\n font-family: inherit;\n line-height: 1;\n}\n\n.rc-restore-btn:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 15%, var(--mj-bg-surface));\n border-color: var(--mj-brand-primary);\n box-shadow: 0 2px 6px color-mix(in srgb, var(--mj-brand-primary) 15%, transparent);\n}\n\n.rc-restore-btn:active {\n transform: translateY(1px);\n box-shadow: none;\n}\n\n.rc-restore-btn i {\n font-size: 13px;\n}\n\n/* \u2500\u2500\u2500 Restore Preview Panel \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.rc-restore-preview-backdrop {\n position: fixed;\n inset: 0;\n background: var(--mj-bg-overlay);\n z-index: 10000;\n display: flex;\n align-items: center;\n justify-content: center;\n animation: rc-fadeIn 0.15s ease;\n}\n\n.rc-restore-preview-panel {\n background: var(--mj-bg-surface);\n border-radius: 12px;\n box-shadow: var(--mj-shadow-lg);\n width: 90%;\n max-width: 700px;\n max-height: 80vh;\n overflow-y: auto;\n padding: 0;\n animation: rc-slideUp 0.2s ease;\n}\n\n.rc-restore-preview-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 16px 20px;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-title {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 16px;\n font-weight: 600;\n color: var(--mj-text-primary);\n}\n\n.rc-restore-preview-title i {\n color: var(--mj-brand-primary);\n}\n\n.rc-restore-preview-close {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n cursor: pointer;\n padding: 4px 8px;\n border-radius: 4px;\n font-size: 16px;\n transition: color 0.15s, background 0.15s;\n}\n\n.rc-restore-preview-close:hover {\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface-hover);\n}\n\n.rc-restore-preview-meta {\n display: flex;\n gap: 20px;\n padding: 12px 20px;\n font-size: 13px;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-empty {\n padding: 24px 20px;\n text-align: center;\n color: var(--mj-text-muted);\n font-size: 13px;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n}\n\n.rc-restore-preview-empty i {\n color: var(--mj-text-disabled);\n}\n\n/* Restore Preview Table */\n.rc-restore-preview-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n}\n\n.rc-restore-preview-table th {\n text-align: left;\n padding: 10px 16px;\n font-weight: 600;\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n color: var(--mj-text-muted);\n background: var(--mj-bg-surface-sunken);\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-preview-table td {\n padding: 10px 16px;\n border-bottom: 1px solid var(--mj-border-default);\n vertical-align: top;\n}\n\n.rc-restore-preview-table tr:last-child td {\n border-bottom: none;\n}\n\n.rc-restore-preview-table tr.rc-diff-changed {\n background: color-mix(in srgb, var(--mj-status-warning) 5%, var(--mj-bg-surface));\n}\n\n.rc-restore-preview-table tr.rc-diff-unchanged {\n opacity: 0.6;\n}\n\n.rc-restore-field-name {\n font-weight: 600;\n color: var(--mj-text-primary);\n white-space: nowrap;\n}\n\n.rc-restore-current {\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-secondary);\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-restore-version {\n font-family: 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;\n color: var(--mj-text-primary);\n font-weight: 500;\n max-width: 200px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.rc-restore-indicator {\n text-align: center;\n width: 30px;\n}\n\n.rc-diff-changed .rc-restore-indicator i {\n color: var(--mj-status-warning);\n}\n\n.rc-diff-unchanged .rc-restore-indicator i {\n color: var(--mj-status-success);\n font-size: 12px;\n}\n\n/* Restore Preview Actions */\n.rc-restore-preview-actions {\n display: flex;\n gap: 10px;\n padding: 16px 20px;\n border-top: 1px solid var(--mj-border-default);\n}\n\n.rc-restore-confirm-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 600;\n color: var(--mj-text-inverse);\n background: var(--mj-brand-primary);\n border: none;\n border-radius: 8px;\n cursor: pointer;\n transition: background 0.15s, box-shadow 0.15s;\n font-family: inherit;\n}\n\n.rc-restore-confirm-btn:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n box-shadow: 0 2px 8px color-mix(in srgb, var(--mj-brand-primary) 25%, transparent);\n}\n\n.rc-restore-confirm-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.rc-restore-cancel-btn {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 8px 18px;\n font-size: 13px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n cursor: pointer;\n transition: all 0.15s;\n font-family: inherit;\n}\n\n.rc-restore-cancel-btn:hover:not(:disabled) {\n border-color: var(--mj-border-strong);\n color: var(--mj-text-primary);\n}\n\n.rc-restore-cancel-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * Restore lineage + conditional filter chips + overflow popover\n * (added with the Restore Prior Version feature)\n * \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* \u2500\u2500\u2500 Filter pill enhancements \u2500\u2500\u2500 */\n\n.rc-filter-pill-count {\n margin-left: 4px;\n background: color-mix(in srgb, currentColor 12%, transparent);\n padding: 1px 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 700;\n}\n\n.rc-filter-pill.active .rc-filter-pill-count {\n background: color-mix(in srgb, var(--mj-text-inverse, #fff) 22%, transparent);\n}\n\n/* Restore-variant pill: violet treatment to set it apart from type pills */\n.rc-filter-pill-restore {\n background: color-mix(in srgb, var(--mj-status-info) 8%, var(--mj-bg-surface));\n color: color-mix(in srgb, var(--mj-status-info) 80%, var(--mj-text-secondary));\n border-color: color-mix(in srgb, var(--mj-status-info) 30%, var(--mj-border-default));\n}\n.rc-filter-pill-restore:hover {\n border-color: var(--mj-status-info);\n color: var(--mj-status-info);\n}\n.rc-filter-pill-restore.active {\n background: var(--mj-status-info);\n color: var(--mj-text-inverse, #fff);\n border-color: var(--mj-status-info);\n}\n\n/* \u2500\u2500\u2500 Overflow filter popover \u2500\u2500\u2500 */\n\n.rc-filter-overflow-wrap {\n position: relative;\n display: inline-block;\n}\n\n.rc-filter-pill-overflow {\n /* Overflow trigger inherits the standard filter pill look */\n}\n\n.rc-filter-overflow-caret {\n font-size: 9px;\n margin-left: 2px;\n}\n\n.rc-filter-overflow-backdrop {\n position: fixed;\n inset: 0;\n z-index: 10;\n}\n\n.rc-filter-overflow-popover {\n position: absolute;\n top: calc(100% + 6px);\n left: 0;\n z-index: 11;\n min-width: 240px;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 10px;\n box-shadow: 0 14px 40px rgba(15, 23, 42, 0.18);\n padding: 8px;\n}\n\n.rc-filter-overflow-header {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--mj-text-muted);\n font-weight: 600;\n padding: 6px 8px 8px;\n}\n\n.rc-filter-overflow-row {\n display: flex;\n align-items: center;\n gap: 9px;\n padding: 7px 8px;\n border-radius: 6px;\n font-size: 13px;\n color: var(--mj-text-primary);\n cursor: pointer;\n}\n\n.rc-filter-overflow-row:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.rc-filter-overflow-row input[type=\"checkbox\"] {\n margin: 0;\n accent-color: var(--mj-brand-primary);\n}\n\n.rc-filter-overflow-row i {\n color: var(--mj-text-muted);\n font-size: 12px;\n width: 14px;\n text-align: center;\n}\n\n.rc-filter-overflow-row-restore i {\n color: var(--mj-status-info);\n}\n\n.rc-filter-overflow-label {\n flex: 1;\n}\n\n.rc-filter-overflow-count {\n color: var(--mj-text-muted);\n font-size: 11px;\n font-weight: 500;\n}\n\n.rc-filter-overflow-actions {\n display: flex;\n justify-content: space-between;\n border-top: 1px solid var(--mj-border-subtle);\n padding-top: 8px;\n margin-top: 6px;\n}\n\n.rc-filter-overflow-clear,\n.rc-filter-overflow-done {\n background: none;\n border: none;\n font-size: 12px;\n font-weight: 500;\n cursor: pointer;\n padding: 4px 10px;\n border-radius: 5px;\n}\n\n.rc-filter-overflow-clear {\n color: var(--mj-text-muted);\n}\n.rc-filter-overflow-clear:hover {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.rc-filter-overflow-done {\n color: var(--mj-brand-primary);\n}\n.rc-filter-overflow-done:hover {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n\n/* \u2500\u2500\u2500 Snapshot type badge + card accent \u2500\u2500\u2500 */\n\n.type-snapshot .rc-card-type-badge {\n background: color-mix(in srgb, var(--mj-text-muted) 15%, var(--mj-bg-surface));\n color: var(--mj-text-secondary);\n}\n\n/* \u2500\u2500\u2500 Restore Source pill (in card meta) \u2500\u2500\u2500 */\n\n.source-restore {\n background: color-mix(in srgb, var(--mj-status-info) 12%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n/* \u2500\u2500\u2500 Restore card variant: violet left accent \u2500\u2500\u2500 */\n\n.rc-card.rc-card-restore {\n border-left: 3px solid var(--mj-status-info);\n}\n\n/* \u2500\u2500\u2500 Lineage chip \u2500\u2500\u2500 */\n\n/* Lineage chip \u2014 outline-only \"interactive link\" treatment so it reads as\n distinct from the filled RESTORE badge sitting next to it. The badge says\n \"this row IS a restore\" (filled, static); the chip says \"click here to\n see the source version\" (outline, hoverable). */\n.rc-restored-chip {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n margin-left: 8px;\n padding: 2px 9px;\n border-radius: 11px;\n font-size: 11px;\n font-weight: 500;\n background: transparent;\n color: color-mix(in srgb, var(--mj-status-info) 90%, var(--mj-text-primary));\n border: 1px solid color-mix(in srgb, var(--mj-status-info) 40%, var(--mj-border-default));\n cursor: pointer;\n text-decoration: none;\n white-space: nowrap;\n transition: background-color 0.12s, border-color 0.12s, color 0.12s;\n}\n\n.rc-restored-chip:hover {\n background: color-mix(in srgb, var(--mj-status-info) 12%, transparent);\n border-color: var(--mj-status-info);\n color: var(--mj-status-info);\n}\n\n.rc-restored-chip i {\n font-size: 10px;\n}\n\n.rc-restored-chip-orphan {\n cursor: default;\n background: var(--mj-bg-surface-card);\n color: var(--mj-text-muted);\n border-color: var(--mj-border-default);\n}\n\n.rc-restored-chip-orphan:hover {\n background: var(--mj-bg-surface-card);\n border-color: var(--mj-border-default);\n}\n\n/* \u2500\u2500\u2500 Card highlight (when jumped-to via lineage chip) \u2500\u2500\u2500 */\n\n.rc-card.rc-card-highlight {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: 2px;\n animation: rc-card-pulse 1.4s ease-in-out;\n}\n\n@keyframes rc-card-pulse {\n 0%, 100% { background: var(--mj-bg-surface); }\n 50% { background: color-mix(in srgb, var(--mj-brand-primary) 8%, var(--mj-bg-surface)); }\n}\n\n/* \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n * Restore-row badge override + Restore Reason block\n * (mockup-aligned treatment for restore rows in the timeline)\n * \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/* The base type-update badge styling would otherwise paint a restore row's\n badge blue with \"Update\" text. Override to violet + \"Restore\" text so it\n matches the source pill, lineage chip, and card border. */\n.rc-card-type-badge.rc-card-type-badge-restore {\n background: color-mix(in srgb, var(--mj-status-info) 14%, var(--mj-bg-surface));\n color: var(--mj-status-info);\n}\n\n/* Restore reason \u2014 minimal blockquote treatment.\n A thin violet left bar + italic text reads like a margin note rather than\n a heavy callout. Visually connected to the restore family (left bar uses\n the same violet as the badge / source pill / card border) without\n competing with the field-diff rows that follow. */\n.rc-restore-reason {\n /* Indented in from the card body edge so it visually nests one level\n deeper than the field-diff rows that follow, and given generous\n vertical breathing room so it doesn't crowd the lineage chip above\n or the first field row below. */\n margin: 14px 8px 18px 18px;\n padding: 0 0 0 12px;\n border-left: 2px solid color-mix(in srgb, var(--mj-status-info) 55%, var(--mj-border-default));\n display: flex;\n align-items: baseline;\n gap: 8px;\n font-size: 13px;\n line-height: 1.5;\n}\n\n.rc-restore-reason-label {\n flex-shrink: 0;\n font-size: 11px;\n font-weight: 600;\n color: color-mix(in srgb, var(--mj-status-info) 75%, var(--mj-text-muted));\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n\n.rc-restore-reason-text {\n color: var(--mj-text-secondary);\n font-style: italic;\n}\n"], encapsulation: 2, changeDetection: 0 });
1442
1443
  }
1443
1444
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RecordChangesComponent, [{
1444
1445
  type: Component,
@@ -1 +1 @@
1
- {"version":3,"file":"ng-record-changes.component.js","sourceRoot":"","sources":["../../src/lib/ng-record-changes.component.ts","../../src/lib/ng-record-changes.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n EventEmitter,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ChangeDetectorRef,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n NgZone,\n} from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { Subscription } from 'rxjs';\nimport {\n BaseEntity,\n BaseEntityEvent,\n CompositeKey,\n EntityFieldInfo,\n EntityFieldTSType,\n RunView,\n} from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { MJRecordChangeEntity } from '@memberjunction/core-entities';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { diffChars, diffWords, Change } from 'diff';\nimport { RestoreCommitEvent } from './restore-preview-panel/restore-preview-panel.component';\n\n/** Lightweight shape for displaying a version label associated with this record */\ninterface RecordLabel {\n ID: string;\n Name: string;\n Description: string | null;\n Scope: string;\n Status: string;\n CreatedAt: Date;\n ItemCount: number;\n}\n\n/**\n * Event payload emitted when the user confirms a restore.\n *\n * The host component (typically `record-form-container`) is responsible for:\n * 1. Reloading the live record (concurrency safety),\n * 2. Calling `record.SetRestoreContext(SourceChangeID, Reason)`,\n * 3. Calling `record.Set(FieldName, Value)` for each entry in `FieldValues`,\n * 4. Calling `record.Save()`,\n * 5. Calling `record.ClearRestoreContext()` after the save returns.\n *\n * The provider will write a new RecordChange row with `Source='Restore'`,\n * `RestoredFromID = SourceChangeID`, and `RestoreReason = Reason` —\n * producing the auditable lineage chain.\n */\nexport interface RestoreVersionEvent {\n /** ID of the historical RecordChange row whose state is being restored. */\n SourceChangeID: string;\n /** When the historical change was made. */\n ChangedAt: Date;\n /** Display name / email of who made the historical change. */\n ChangedByUser: string;\n /** Optional user-entered reason for the restore. */\n Reason: string | null;\n /** Selected field values, ready to pass to BaseEntity.Set(). */\n FieldValues: Array<{ FieldName: string; Value: unknown }>;\n}\n\n/** A single field change with type-aware rendering info (timeline display only). */\nexport interface FieldChangeInfo {\n field: string;\n displayName: string;\n oldValue: string;\n newValue: string;\n fieldType: 'boolean' | 'date' | 'number' | 'text';\n diffHtml?: SafeHtml;\n}\n\n/** A group of changes that share the same date. */\nexport interface DateGroup {\n label: string;\n changes: MJRecordChangeEntity[];\n}\n\n/** A conditional filter pill (one per type/source actually present in loaded data). */\nexport interface FilterPill {\n /** Unique key for selection state ('Update', 'Create', 'Delete', 'Snapshot', 'Restore'). */\n Key: string;\n /** User-facing label (pluralized: 'Updates', 'Restored', etc.). */\n Label: string;\n /** Font Awesome icon class. */\n Icon: string;\n /** Number of changes of this kind in the loaded data. */\n Count: number;\n /** Selection style — neutral type pill or violet restore pill. */\n Variant: 'type' | 'restore';\n}\n\n/**\n * Slide-out timeline of all changes to a single record. Hosts the reusable\n * {@link RestorePreviewPanelComponent} for the actual restore confirmation\n * flow, and exposes a `RestoreRequested` event the host can act on to\n * persist the restore.\n *\n * @example\n * <mj-record-changes\n * [record]=\"myEntity\"\n * [AllowRestore]=\"true\"\n * (dialogClosed)=\"showHistory = false\"\n * (RestoreRequested)=\"onRestoreRequested($event)\">\n * </mj-record-changes>\n */\n@Component({\n standalone: false,\n selector: 'mj-record-changes',\n templateUrl: './ng-record-changes.component.html',\n styleUrls: ['./ng-record-changes.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n})\nexport class RecordChangesComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n public IsLoading = false;\n public IsVisible = false;\n @Output() dialogClosed = new EventEmitter();\n @Input() record!: BaseEntity;\n\n /** Whether to show a \"Restore\" button on each historical version row. Default false. */\n @Input() AllowRestore = false;\n\n /**\n * Emitted when the user confirms a restore in the preview panel.\n * The host is responsible for applying the snapshot to the record and\n * saving with `record.SetRestoreContext()` set first.\n */\n @Output() RestoreRequested = new EventEmitter<RestoreVersionEvent>();\n\n viewData: MJRecordChangeEntity[] = [];\n filteredData: MJRecordChangeEntity[] = [];\n dateGroups: DateGroup[] = [];\n expandedItems: Set<string> = new Set();\n\n /** The change record currently selected for restore preview, or null. */\n RestorePreviewChange: MJRecordChangeEntity | null = null;\n /** Visibility of the embedded restore preview slide-in. */\n RestorePreviewVisible = false;\n /** Whether the restore commit is in progress (between confirmation and host response). */\n IsRestoring = false;\n\n // Version label state\n RecordLabels: RecordLabel[] = [];\n IsLoadingLabels = false;\n ShowCreateWizard = false;\n\n // Filter properties\n searchTerm = '';\n /** Single selected type filter (legacy, kept for backwards compat). */\n selectedType = '';\n selectedSource = '';\n /** Map of Key → selected, used by the conditional chip system. */\n ChipSelections: Record<string, boolean> = {};\n /** Whether the overflow popover is open. */\n ShowFilterOverflow = false;\n /** Highlighted change ID for the lineage-jump indicator (transient). */\n HighlightedChangeID: string | null = null;\n\n /**\n * Conditional filter pills derived from loaded data. Always includes 'All'\n * implicitly. Other pills only render when at least one matching change\n * exists. Overflows into a popover when the count exceeds 2.\n */\n ConditionalPills: FilterPill[] = [];\n\n /** Threshold above which conditional chips collapse into the overflow popover. */\n private readonly OVERFLOW_THRESHOLD = 2;\n\n /**\n * Subscription to the record's BaseEntity event stream. We listen for\n * 'save' events and auto-refresh the timeline so the user immediately\n * sees the new RecordChange row produced by either a normal save or a\n * restore. Cleaned up in ngOnDestroy.\n */\n private _entitySaveSub: Subscription | null = null;\n\n constructor(\n private cdr: ChangeDetectorRef,\n private ngZone: NgZone,\n private mjNotificationService: MJNotificationService,\n private sanitizer: DomSanitizer,\n ) { super(); }\n\n ngOnInit(): void {\n if (this.record) {\n this.IsLoading = true;\n this.IsVisible = true;\n this.cdr.markForCheck();\n this.LoadRecordChanges(this.record.PrimaryKey, '', this.record.EntityInfo.Name);\n this.LoadRecordLabels();\n this.subscribeToRecordSaves();\n }\n }\n\n ngOnDestroy(): void {\n this._entitySaveSub?.unsubscribe();\n this._entitySaveSub = null;\n }\n\n /**\n * Wires up an event handler on the live record so the timeline auto-\n * refreshes immediately after any save lands — including the one\n * produced by the restore flow. Without this the user sees their record\n * update in the form but the panel above still shows the pre-restore\n * change list, which is confusing.\n */\n private subscribeToRecordSaves(): void {\n if (!this.record) return;\n this._entitySaveSub?.unsubscribe();\n this._entitySaveSub = this.record.RegisterEventHandler((event: BaseEntityEvent) => {\n if (event?.type === 'save') {\n this.ngZone.run(() => this.Refresh());\n }\n });\n }\n\n /**\n * Reloads the record changes list from the database.\n * Called by the parent container after a save completes while the drawer is open.\n */\n public Refresh(): void {\n if (this.record) {\n this.IsLoading = true;\n this.cdr.markForCheck();\n this.LoadRecordChanges(this.record.PrimaryKey, '', this.record.EntityInfo.Name);\n }\n }\n\n public OnClose(): void {\n this.IsVisible = false;\n this.cdr.markForCheck();\n // Allow the slide-out animation to complete before emitting\n setTimeout(() => this.dialogClosed.emit(), 300);\n }\n\n public async LoadRecordChanges(pkey: CompositeKey, appName: string, entityName: string): Promise<void> {\n if (pkey && entityName) {\n const md = this.ProviderToUse;\n const entityInfo = md.EntityByName(entityName);\n let changes: MJRecordChangeEntity[] = [];\n if (entityInfo?.TrackRecordChanges) {\n const rvResult = await RunView.FromMetadataProvider(md).RunView<MJRecordChangeEntity>({\n EntityName: 'MJ: Record Changes',\n ExtraFilter: `Entity='${entityName}' AND RecordID='${pkey.ToConcatenatedString()}'`,\n OrderBy: 'ChangedAt DESC',\n ResultType: 'entity_object',\n });\n if (rvResult.Success) changes = rvResult.Results;\n }\n this.ngZone.run(() => {\n if (changes) {\n this.viewData = changes.sort(\n (a: MJRecordChangeEntity, b: MJRecordChangeEntity) => new Date(b.ChangedAt).getTime() - new Date(a.ChangedAt).getTime(),\n );\n this.rebuildConditionalPills();\n this.applyFilters();\n this.IsLoading = false;\n } else {\n this.mjNotificationService.CreateSimpleNotification(\n `Error loading record changes for ${entityName} with primary key ${pkey.ToString()}.`,\n 'error',\n );\n this.IsLoading = false;\n }\n this.cdr.markForCheck();\n });\n }\n }\n\n // ─── Filter & Search ────────────────────────────────────────────\n\n onSearchChange(): void {\n this.applyFilters();\n }\n\n onFilterChange(): void {\n this.applyFilters();\n }\n\n /**\n * Toggles the \"All\" pill — clears every conditional selection.\n */\n public SelectAllPill(): void {\n for (const k of Object.keys(this.ChipSelections)) this.ChipSelections[k] = false;\n this.applyFilters();\n }\n\n /**\n * Toggles a conditional pill on/off.\n */\n public TogglePill(key: string): void {\n this.ChipSelections[key] = !this.ChipSelections[key];\n this.applyFilters();\n }\n\n /**\n * Returns true when no conditional pills are selected (i.e. \"All\" mode).\n */\n public get IsAllSelected(): boolean {\n return !Object.values(this.ChipSelections).some(v => v);\n }\n\n /**\n * Whether any conditional pills are actually visible at all.\n */\n public get HasConditionalPills(): boolean {\n return this.ConditionalPills.length > 0;\n }\n\n /**\n * True when the conditional chips should collapse into an overflow popover\n * because there are more than the threshold.\n */\n public get UseOverflowPopover(): boolean {\n return this.ConditionalPills.length > this.OVERFLOW_THRESHOLD;\n }\n\n /** Number of currently selected conditional pills (for the popover trigger label). */\n public get SelectedConditionalCount(): number {\n return Object.values(this.ChipSelections).filter(v => v).length;\n }\n\n public ToggleFilterOverflow(): void {\n this.ShowFilterOverflow = !this.ShowFilterOverflow;\n this.cdr.markForCheck();\n }\n\n public CloseFilterOverflow(): void {\n this.ShowFilterOverflow = false;\n this.cdr.markForCheck();\n }\n\n public ClearFilters(): void {\n this.searchTerm = '';\n for (const k of Object.keys(this.ChipSelections)) this.ChipSelections[k] = false;\n this.applyFilters();\n }\n\n /**\n * Builds the list of conditional pills from currently loaded data —\n * a pill only appears for change types/sources that actually exist.\n */\n private rebuildConditionalPills(): void {\n const counts: Record<string, number> = {};\n let restoreCount = 0;\n\n for (const c of this.viewData) {\n const type = c.Type ?? 'Update';\n counts[type] = (counts[type] ?? 0) + 1;\n if (this.isRestoreChange(c)) restoreCount++;\n }\n\n const pills: FilterPill[] = [];\n if ((counts['Update'] ?? 0) > 0) {\n pills.push({ Key: 'Update', Label: 'Updates', Icon: 'fa-pen', Count: counts['Update'], Variant: 'type' });\n }\n if ((counts['Create'] ?? 0) > 0) {\n pills.push({ Key: 'Create', Label: 'Creates', Icon: 'fa-plus', Count: counts['Create'], Variant: 'type' });\n }\n if ((counts['Delete'] ?? 0) > 0) {\n pills.push({ Key: 'Delete', Label: 'Deletes', Icon: 'fa-trash', Count: counts['Delete'], Variant: 'type' });\n }\n if ((counts['Snapshot'] ?? 0) > 0) {\n pills.push({ Key: 'Snapshot', Label: 'Snapshots', Icon: 'fa-camera', Count: counts['Snapshot'], Variant: 'type' });\n }\n if (restoreCount > 0) {\n pills.push({ Key: 'Restore', Label: 'Restored', Icon: 'fa-clock-rotate-left', Count: restoreCount, Variant: 'restore' });\n }\n\n // Initialize/prune selection state\n const validKeys = new Set(pills.map(p => p.Key));\n for (const k of Object.keys(this.ChipSelections)) {\n if (!validKeys.has(k)) delete this.ChipSelections[k];\n }\n for (const p of pills) {\n if (this.ChipSelections[p.Key] === undefined) this.ChipSelections[p.Key] = false;\n }\n\n this.ConditionalPills = pills;\n }\n\n private isRestoreChange(c: MJRecordChangeEntity): boolean {\n return c.Source === 'Restore' || (c as any).RestoredFromID != null;\n }\n\n private applyFilters(): void {\n let filtered = [...this.viewData];\n\n if (this.searchTerm.trim()) {\n const search = this.searchTerm.toLowerCase();\n filtered = filtered.filter(\n change =>\n change.ChangesDescription?.toLowerCase().includes(search) ||\n change.User?.toLowerCase().includes(search) ||\n change.Comments?.toLowerCase().includes(search),\n );\n }\n\n // Apply conditional pill filters — if any are selected, only show changes matching ANY of them (OR semantics).\n const selectedKeys = Object.keys(this.ChipSelections).filter(k => this.ChipSelections[k]);\n if (selectedKeys.length > 0) {\n filtered = filtered.filter(change => {\n for (const key of selectedKeys) {\n if (key === 'Restore') {\n if (this.isRestoreChange(change)) return true;\n } else {\n if (change.Type === key) return true;\n }\n }\n return false;\n });\n }\n\n this.filteredData = filtered;\n this.dateGroups = this.buildDateGroups(this.filteredData);\n this.cdr.markForCheck();\n }\n\n // ─── Version Labels ─────────────────────────────────────────────\n\n public async LoadRecordLabels(): Promise<void> {\n if (!this.record) return;\n\n this.IsLoadingLabels = true;\n this.cdr.markForCheck();\n\n try {\n const entityId = this.record.EntityInfo.ID;\n const recordId = this.record.PrimaryKey.ToConcatenatedString();\n\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const itemsResult = await rv.RunView<{ VersionLabelID: string }>({\n EntityName: 'MJ: Version Label Items',\n Fields: ['VersionLabelID'],\n ExtraFilter: `EntityID='${entityId}' AND RecordID='${recordId}'`,\n ResultType: 'simple',\n });\n\n if (!itemsResult.Success || itemsResult.Results.length === 0) {\n this.ngZone.run(() => {\n this.RecordLabels = [];\n this.IsLoadingLabels = false;\n this.cdr.markForCheck();\n });\n return;\n }\n\n const labelIds = [...new Set(itemsResult.Results.map(i => i.VersionLabelID))];\n const labelIdFilter = labelIds.map(id => `'${id}'`).join(',');\n\n const labelsResult = await rv.RunView<{\n ID: string;\n Name: string;\n Description: string | null;\n Scope: string;\n Status: string;\n ItemCount: number;\n __mj_CreatedAt: Date;\n }>({\n EntityName: 'MJ: Version Labels',\n Fields: ['ID', 'Name', 'Description', 'Scope', 'Status', 'ItemCount', '__mj_CreatedAt'],\n ExtraFilter: `ID IN (${labelIdFilter})`,\n OrderBy: '__mj_CreatedAt DESC',\n ResultType: 'simple',\n });\n\n if (labelsResult.Success) {\n this.RecordLabels = labelsResult.Results.map(l => ({\n ID: l.ID,\n Name: l.Name,\n Description: l.Description,\n Scope: l.Scope,\n Status: l.Status,\n CreatedAt: l.__mj_CreatedAt,\n ItemCount: l.ItemCount,\n }));\n }\n } catch (error) {\n console.error('Error loading version labels for record:', error);\n this.RecordLabels = [];\n } finally {\n this.ngZone.run(() => {\n this.IsLoadingLabels = false;\n this.cdr.markForCheck();\n });\n }\n }\n\n public OpenCreateWizard(): void {\n this.ShowCreateWizard = true;\n this.cdr.markForCheck();\n }\n\n public OnLabelCreated(event: { LabelCount: number; ItemCount: number }): void {\n this.ShowCreateWizard = false;\n this.cdr.markForCheck();\n this.LoadRecordLabels();\n this.mjNotificationService.CreateSimpleNotification(\n `Version label created with ${event.ItemCount} snapshot${event.ItemCount !== 1 ? 's' : ''}`,\n 'info',\n 2000,\n );\n }\n\n public OnLabelCreateCancelled(): void {\n this.ShowCreateWizard = false;\n this.cdr.markForCheck();\n }\n\n public getLabelStatusClass(status: string): string {\n switch (status) {\n case 'Active': return 'label-status-active';\n case 'Archived': return 'label-status-archived';\n case 'Restored': return 'label-status-restored';\n default: return '';\n }\n }\n\n // ─── Timeline Interaction ───────────────────────────────────────\n\n toggleExpansion(changeId: string): void {\n if (this.expandedItems.has(changeId)) {\n this.expandedItems.delete(changeId);\n } else {\n this.expandedItems.add(changeId);\n }\n this.cdr.markForCheck();\n }\n\n onTimelineItemKeydown(event: KeyboardEvent, changeId: string): void {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.toggleExpansion(changeId);\n }\n }\n\n /**\n * Opens the embedded restore preview panel for a given change record.\n * The panel computes a full-record diff (current vs the change's\n * FullRecordJSON snapshot) — this is the semantic-correctness fix:\n * we restore TO the state at that point in time, not just undo the\n * one delta the user clicked.\n */\n OnRestoreVersion(change: MJRecordChangeEntity, event: MouseEvent): void {\n event.stopPropagation();\n this.RestorePreviewChange = change;\n this.RestorePreviewVisible = true;\n this.cdr.markForCheck();\n }\n\n /**\n * Called when the user confirms the restore in the embedded panel.\n * Translates the panel's RestoreCommitEvent into the broader-shape\n * RestoreVersionEvent the host is wired to handle.\n */\n OnRestorePanelConfirmed(commit: RestoreCommitEvent): void {\n if (!this.RestorePreviewChange) return;\n\n const change = this.RestorePreviewChange;\n this.IsRestoring = true;\n this.cdr.markForCheck();\n\n this.RestoreRequested.emit({\n SourceChangeID: commit.SourceChangeID,\n ChangedAt: change.ChangedAt,\n ChangedByUser: change.User || '',\n Reason: commit.Reason,\n FieldValues: commit.FieldValues,\n });\n\n // Close the panel after a brief delay so the host has a moment to react.\n setTimeout(() => {\n this.RestorePreviewVisible = false;\n this.RestorePreviewChange = null;\n this.IsRestoring = false;\n this.cdr.markForCheck();\n }, 500);\n }\n\n /**\n * Called when the user dismisses the restore preview without confirming.\n */\n OnRestorePanelCancelled(): void {\n this.RestorePreviewVisible = false;\n this.RestorePreviewChange = null;\n this.cdr.markForCheck();\n }\n\n // ─── Lineage chip ───────────────────────────────────────────────\n\n /**\n * Returns the source change for a given restored row, if found in the\n * currently loaded changes. Returns null when the source isn't loaded\n * (e.g., it's been pruned from history) or when this row isn't a restore.\n */\n public getRestoredFromSourceChange(change: MJRecordChangeEntity): MJRecordChangeEntity | null {\n const sourceId = (change as any).RestoredFromID;\n if (!sourceId) return null;\n return this.viewData.find(c => UUIDsEqual(c.ID, sourceId)) ?? null;\n }\n\n /**\n * True when the row was produced by a restore operation (either the\n * `Source` is `'Restore'` OR `RestoredFromID` is populated).\n */\n public isRestoreRow(change: MJRecordChangeEntity): boolean {\n return this.isRestoreChange(change);\n }\n\n /**\n * True when this change is the most recent in the loaded history.\n * `viewData` is sorted DESC by `ChangedAt`, so the most recent is index 0.\n * Restoring to the most recent version is a no-op, so the timeline hides\n * the Restore button on this row.\n */\n public isMostRecentChange(change: MJRecordChangeEntity): boolean {\n return this.viewData.length > 0 && this.viewData[0] === change;\n }\n\n /**\n * Click handler for the lineage chip — scrolls/highlights the source\n * change row in the timeline. Auto-clears after a few seconds.\n */\n public JumpToSourceChange(sourceChange: MJRecordChangeEntity, event: MouseEvent): void {\n event.stopPropagation();\n this.HighlightedChangeID = sourceChange.ID;\n this.expandedItems.add(sourceChange.ID);\n this.cdr.markForCheck();\n\n // Auto-clear the highlight after 3s\n setTimeout(() => {\n if (this.HighlightedChangeID && UUIDsEqual(this.HighlightedChangeID, sourceChange.ID)) {\n this.HighlightedChangeID = null;\n this.cdr.markForCheck();\n }\n }, 3000);\n\n // Scroll into view\n setTimeout(() => {\n const el = document.querySelector(`[data-change-id=\"${sourceChange.ID}\"]`);\n el?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }, 50);\n }\n\n // ─── Date Grouping ─────────────────────────────────────────────\n\n private buildDateGroups(changes: MJRecordChangeEntity[]): DateGroup[] {\n const groups = new Map<string, MJRecordChangeEntity[]>();\n\n for (const change of changes) {\n const label = this.formatDateGroupLabel(new Date(change.ChangedAt));\n if (!groups.has(label)) {\n groups.set(label, []);\n }\n groups.get(label)!.push(change);\n }\n\n return Array.from(groups.entries()).map(([label, items]) => ({ label, changes: items }));\n }\n\n private formatDateGroupLabel(date: Date): string {\n const now = new Date();\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const target = new Date(date.getFullYear(), date.getMonth(), date.getDate());\n const diffDays = Math.floor((today.getTime() - target.getTime()) / 86400000);\n\n const formatted = new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).format(date);\n\n if (diffDays === 0) return `Today \\u2014 ${formatted}`;\n if (diffDays === 1) return `Yesterday \\u2014 ${formatted}`;\n return formatted;\n }\n\n // ─── Display Helpers ────────────────────────────────────────────\n\n getChangeTypeCardClass(type: string): string {\n switch (type) {\n case 'Create': return 'type-create';\n case 'Update': return 'type-update';\n case 'Delete': return 'type-delete';\n case 'Snapshot': return 'type-snapshot';\n default: return 'type-update';\n }\n }\n\n getChangeTypeBadgeText(type: string): string {\n switch (type) {\n case 'Create': return 'Created';\n case 'Delete': return 'Deleted';\n case 'Snapshot': return 'Snapshot';\n default: return type;\n }\n }\n\n /**\n * Badge text for the row's primary type tag. For restore rows we override\n * the underlying `Type='Update'` and show \"Restore\" instead — matches the\n * mockup's intent of treating restore as a first-class operation in the\n * timeline rather than a flavor of update.\n */\n getEffectiveBadgeText(change: MJRecordChangeEntity): string {\n if (this.isRestoreRow(change)) return 'Restore';\n return this.getChangeTypeBadgeText(change.Type);\n }\n\n /**\n * Optional restore reason — pulled from the dynamic `RestoreReason`\n * column added by the lineage migration. Returns null when not present\n * or not a restore row.\n */\n getRestoreReason(change: MJRecordChangeEntity): string | null {\n if (!this.isRestoreRow(change)) return null;\n const reason = (change as unknown as { RestoreReason?: string | null }).RestoreReason;\n return reason && reason.trim().length > 0 ? reason : null;\n }\n\n getSourceClass(source: string): string {\n if (source === 'Restore') return 'source-restore';\n if (source === 'Internal') return 'source-internal';\n return 'source-external';\n }\n\n getStatusClass(status: string): string {\n switch (status) {\n case 'Complete': return 'status-complete';\n case 'Pending': return 'status-pending';\n case 'Error': return 'status-error';\n default: return 'status-unknown';\n }\n }\n\n getTimelineItemLabel(change: MJRecordChangeEntity): string {\n return `${change.Type} by ${change.User || 'Unknown User'} on ${this.formatFullDateTime(change.ChangedAt)}`;\n }\n\n getUserInitials(user: string | null): string {\n if (!user) return '?';\n if (user.includes('@')) {\n const local = user.split('@')[0];\n return local.substring(0, 2).toUpperCase();\n }\n const parts = user.trim().split(/\\s+/);\n if (parts.length >= 2) {\n return (parts[0][0] + parts[1][0]).toUpperCase();\n }\n return user.substring(0, 2).toUpperCase();\n }\n\n getUserDisplayName(user: string | null): string {\n if (!user) return 'Unknown';\n if (user.includes('@')) return user.split('@')[0];\n return user;\n }\n\n getUniqueContributorCount(): number {\n const users = new Set(this.viewData.map(c => c.User).filter(Boolean));\n return users.size;\n }\n\n formatTime(date: Date): string {\n return new Intl.DateTimeFormat('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n }).format(new Date(date));\n }\n\n formatRelativeTime(date: Date): string {\n const now = new Date();\n const diffMs = now.getTime() - new Date(date).getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMins / 60);\n const diffDays = Math.floor(diffHours / 24);\n\n if (diffMins < 1) return 'Just now';\n if (diffMins < 60) return `${diffMins} min${diffMins > 1 ? 's' : ''} ago`;\n if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`;\n if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`;\n\n return new Intl.DateTimeFormat('en-US', {\n month: 'short',\n day: 'numeric',\n year: diffDays > 365 ? 'numeric' : undefined,\n }).format(new Date(date));\n }\n\n formatFullDateTime(date: Date): string {\n return new Intl.DateTimeFormat('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n hour12: true,\n timeZoneName: 'short',\n }).format(new Date(date));\n }\n\n // ─── Change Summary ─────────────────────────────────────────────\n\n getChangeSummary(change: MJRecordChangeEntity): string {\n // Restore rows get a distinctive summary so the timeline reads like a\n // sentence — \"Restored to 5:56 PM version\" rather than yet another\n // \"Name and Description changed\". The lineage chip carries the full\n // source-version detail.\n if (this.isRestoreRow(change)) {\n const src = this.getRestoredFromSourceChange(change);\n if (src) return `Restored to ${this.formatTime(src.ChangedAt)} version`;\n return 'Restored from earlier version';\n }\n if (change.Type === 'Create') return 'Record created';\n if (change.Type === 'Delete') return 'Record deleted';\n if (change.Type === 'Snapshot') return change.ChangesDescription || 'Snapshot captured';\n\n try {\n const changesJson = JSON.parse(change.ChangesJSON || '{}');\n const fieldNames = this.extractFieldDisplayNames(changesJson);\n if (fieldNames.length === 0) return 'No field changes detected';\n\n return this.buildFieldListSummary(fieldNames);\n } catch {\n return change.ChangesDescription || 'Changes made';\n }\n }\n\n getCreatedFieldCount(change: MJRecordChangeEntity): number {\n try {\n if (!change.FullRecordJSON) return 0;\n const record = JSON.parse(change.FullRecordJSON);\n return this.record.EntityInfo.Fields.filter(\n (f: EntityFieldInfo) => record[f.Name] != null && record[f.Name] !== '',\n ).length;\n } catch {\n return 0;\n }\n }\n\n private extractFieldDisplayNames(changesJson: Record<string, { field?: string }>): string[] {\n return Object.keys(changesJson).map(fieldKey => {\n const changeInfo = changesJson[fieldKey];\n const field = this.record.EntityInfo.Fields.find(\n (f: EntityFieldInfo) => f.Name.trim().toLowerCase() === changeInfo.field?.trim().toLowerCase(),\n );\n return field?.DisplayNameOrName || changeInfo.field || fieldKey;\n });\n }\n\n private buildFieldListSummary(fieldNames: string[]): string {\n if (fieldNames.length === 1) return `${fieldNames[0]} changed`;\n if (fieldNames.length === 2) return `${fieldNames[0]} and ${fieldNames[1]} changed`;\n if (fieldNames.length <= 4) {\n const last = fieldNames[fieldNames.length - 1];\n return `${fieldNames.slice(0, -1).join(', ')}, and ${last} changed`;\n }\n const remaining = fieldNames.length - 3;\n return `${fieldNames.slice(0, 3).join(', ')}, and ${remaining} other field${remaining > 1 ? 's' : ''} changed`;\n }\n\n // ─── Field Changes (type-aware) ────────────────────────────────\n\n getFieldChanges(change: MJRecordChangeEntity): FieldChangeInfo[] {\n try {\n const changesJson = JSON.parse(change.ChangesJSON || '{}');\n return Object.keys(changesJson).map(fieldKey => this.buildFieldChangeInfo(changesJson[fieldKey]));\n } catch {\n return [];\n }\n }\n\n private buildFieldChangeInfo(changeInfo: { field?: string; oldValue?: unknown; newValue?: unknown }): FieldChangeInfo {\n const field = this.record.EntityInfo.Fields.find(\n (f: EntityFieldInfo) => f.Name.trim().toLowerCase() === changeInfo.field?.trim().toLowerCase(),\n );\n\n const fieldType = this.classifyFieldType(field);\n const isDateField = fieldType === 'date';\n const formattedOld = this.formatChangeValue(changeInfo.oldValue, isDateField);\n const formattedNew = this.formatChangeValue(changeInfo.newValue, isDateField);\n\n let diffHtml: SafeHtml | undefined;\n if (fieldType === 'text' && formattedOld !== formattedNew) {\n diffHtml = this.generateDiffHtml(formattedOld, formattedNew);\n }\n\n return {\n field: changeInfo.field || '',\n displayName: field?.DisplayNameOrName || changeInfo.field || '',\n oldValue: formattedOld,\n newValue: formattedNew,\n fieldType,\n diffHtml,\n };\n }\n\n private classifyFieldType(field: EntityFieldInfo | undefined): 'boolean' | 'date' | 'number' | 'text' {\n if (!field) return 'text';\n if (field.TSType === EntityFieldTSType.Boolean) return 'boolean';\n if (field.TSType === EntityFieldTSType.Date) return 'date';\n if (field.TSType === EntityFieldTSType.Number) return 'number';\n return 'text';\n }\n\n getCreatedFields(change: MJRecordChangeEntity): Array<{ name: string; displayName: string; value: string }> {\n try {\n if (!change.FullRecordJSON) return [];\n\n const record = JSON.parse(change.FullRecordJSON);\n const fields = this.record.EntityInfo.Fields;\n\n return fields\n .filter((field: EntityFieldInfo) => record[field.Name] != null && record[field.Name] !== '')\n .map((field: EntityFieldInfo) => ({\n name: field.Name,\n displayName: field.DisplayNameOrName,\n value: this.formatChangeValue(record[field.Name], field.TSType === EntityFieldTSType.Date),\n }));\n } catch {\n return [];\n }\n }\n\n // ─── Value Formatting ───────────────────────────────────────────\n\n private formatChangeValue(value: unknown, isDateField: boolean): string {\n if (value == null) return '';\n\n if (typeof value === 'object') {\n const keys = Object.keys(value as Record<string, unknown>);\n if (keys.length === 0) return '';\n return JSON.stringify(value);\n }\n\n if (isDateField && typeof value === 'string') {\n const date = new Date(value);\n if (!isNaN(date.getTime())) {\n return new Intl.DateTimeFormat('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n }).format(date);\n }\n }\n\n return String(value);\n }\n\n // ─── Diff Generation (text fields only) ─────────────────────────\n\n private generateDiffHtml(oldValue: string, newValue: string): SafeHtml {\n if (!oldValue && !newValue) {\n return this.sanitizer.bypassSecurityTrustHtml('<span class=\"rc-diff-unchanged\">(no change)</span>');\n }\n\n if (!oldValue) {\n return this.sanitizer.bypassSecurityTrustHtml(`<span class=\"rc-diff-added\">${this.escapeHtml(newValue)}</span>`);\n }\n\n if (!newValue) {\n return this.sanitizer.bypassSecurityTrustHtml(`<span class=\"rc-diff-removed\">${this.escapeHtml(oldValue)}</span>`);\n }\n\n const useWordDiff = this.shouldUseWordDiff(oldValue, newValue);\n const diffs = useWordDiff ? diffWords(oldValue, newValue) : diffChars(oldValue, newValue);\n\n const html = diffs\n .map((part: Change) => {\n const escaped = this.escapeHtml(part.value);\n if (part.added) return `<span class=\"rc-diff-added\">${escaped}</span>`;\n if (part.removed) return `<span class=\"rc-diff-removed\">${escaped}</span>`;\n return `<span class=\"rc-diff-unchanged\">${escaped}</span>`;\n })\n .join('');\n\n return this.sanitizer.bypassSecurityTrustHtml(html);\n }\n\n private shouldUseWordDiff(oldValue: string, newValue: string): boolean {\n const hasMultipleWords = (text: string) => text.includes(' ') && text.split(' ').length > 3;\n const isLongText = (text: string) => text.length > 50;\n\n return (hasMultipleWords(oldValue) || hasMultipleWords(newValue)) && (isLongText(oldValue) || isLongText(newValue));\n }\n\n private escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n}\n","<mj-slide-panel\n [Mode]=\"'slide'\"\n [Title]=\"'Record Changes History'\"\n [Visible]=\"IsVisible\"\n [Resizable]=\"true\"\n [MinWidthPx]=\"400\"\n [MaxWidthRatio]=\"0.6\"\n (Closed)=\"OnClose()\">\n\n @if (IsLoading) {\n <mj-loading text=\"Loading history...\" size=\"medium\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <div class=\"rc-container\">\n <!-- Version Labels Section -->\n <div class=\"rc-labels-section\">\n <div class=\"rc-labels-header\">\n <div class=\"rc-labels-title\">\n <i class=\"fa-solid fa-tags\" aria-hidden=\"true\"></i>\n <span>Version Labels</span>\n @if (RecordLabels.length > 0) {\n <span class=\"rc-labels-count\">{{ RecordLabels.length }}</span>\n }\n </div>\n <button class=\"rc-create-label-btn\" (click)=\"OpenCreateWizard()\" title=\"Create a version label for this record\">\n <i class=\"fa-solid fa-plus\"></i> Create Label\n </button>\n </div>\n @if (IsLoadingLabels) {\n <div class=\"rc-labels-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading labels...\n </div>\n } @else if (RecordLabels.length === 0) {\n <div class=\"rc-labels-empty\">\n No version labels for this record yet.\n </div>\n } @else {\n <div class=\"rc-labels-list\">\n @for (label of RecordLabels; track label.ID) {\n <div class=\"rc-label-chip\" [title]=\"label.Description || label.Name\">\n <i class=\"fa-solid fa-tag rc-label-chip-icon\"></i>\n <span class=\"rc-label-chip-name\">{{ label.Name }}</span>\n <span class=\"rc-label-chip-meta\">\n <span class=\"rc-label-chip-status\" [class]=\"getLabelStatusClass(label.Status)\">{{ label.Status }}</span>\n <span class=\"rc-label-chip-items\">{{ label.ItemCount }} item{{ label.ItemCount !== 1 ? 's' : '' }}</span>\n </span>\n </div>\n }\n </div>\n }\n </div>\n\n @if (viewData.length === 0) {\n <!-- Empty state -->\n <div class=\"rc-empty-state\">\n <div class=\"rc-empty-state-icon\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n </div>\n <h3 class=\"rc-empty-state-title\">No Change History</h3>\n <p class=\"rc-empty-state-description\">\n This record doesn't have any tracked changes yet.\n Changes will appear here automatically as edits are made.\n </p>\n <div class=\"rc-empty-state-hint\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Record change tracking is managed at the entity level</span>\n </div>\n </div>\n } @else {\n <!-- Page Header -->\n <div class=\"rc-page-header\">\n <div>\n <h2 class=\"rc-page-title\">Change History</h2>\n <div class=\"rc-page-subtitle\">{{ record.EntityInfo.Name }}</div>\n </div>\n <div class=\"rc-header-meta\">\n <div class=\"rc-entity-badge\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n {{ record.EntityInfo.Name }}\n </div>\n <div class=\"rc-change-count\">{{ viewData.length }} change{{ viewData.length !== 1 ? 's' : '' }} &middot; {{ getUniqueContributorCount() }} contributor{{ getUniqueContributorCount() !== 1 ? 's' : '' }}</div>\n </div>\n </div>\n\n <!-- Filter Bar — chips render only for change types/sources actually present in loaded data.\n When more than 2 conditional chips would render, they collapse into a \"More filters\" popover. -->\n <div class=\"rc-filter-bar\">\n <div class=\"rc-search-wrap\">\n <i class=\"fa-solid fa-search\" aria-hidden=\"true\"></i>\n <input\n class=\"rc-search-box\"\n type=\"text\"\n placeholder=\"Search changes...\"\n [(ngModel)]=\"searchTerm\"\n (input)=\"onSearchChange()\"\n aria-label=\"Search record changes\"\n />\n </div>\n\n <button class=\"rc-filter-pill\" [class.active]=\"IsAllSelected\" (click)=\"SelectAllPill()\" type=\"button\">\n <i class=\"fa-solid fa-layer-group\" aria-hidden=\"true\"></i> All\n </button>\n\n @if (HasConditionalPills) {\n @if (!UseOverflowPopover) {\n <!-- 1-2 conditional pills: render inline -->\n @for (pill of ConditionalPills; track pill.Key) {\n <button class=\"rc-filter-pill\"\n [class.active]=\"ChipSelections[pill.Key]\"\n [class.rc-filter-pill-restore]=\"pill.Variant === 'restore'\"\n (click)=\"TogglePill(pill.Key)\"\n type=\"button\">\n <i class=\"fa-solid {{ pill.Icon }}\" aria-hidden=\"true\"></i>\n {{ pill.Label }}\n <span class=\"rc-filter-pill-count\">{{ pill.Count }}</span>\n </button>\n }\n } @else {\n <!-- 3+ conditional pills: overflow popover -->\n <div class=\"rc-filter-overflow-wrap\">\n <button class=\"rc-filter-pill rc-filter-pill-overflow\"\n [class.active]=\"SelectedConditionalCount > 0\"\n (click)=\"ToggleFilterOverflow()\"\n type=\"button\">\n <i class=\"fa-solid fa-sliders\" aria-hidden=\"true\"></i>\n More filters\n @if (SelectedConditionalCount > 0) {\n <span class=\"rc-filter-pill-count\">{{ SelectedConditionalCount }}</span>\n }\n <i class=\"fa-solid fa-chevron-down rc-filter-overflow-caret\" aria-hidden=\"true\"></i>\n </button>\n\n @if (ShowFilterOverflow) {\n <!-- Backdrop: clicks close the popover -->\n <div class=\"rc-filter-overflow-backdrop\" (click)=\"CloseFilterOverflow()\"></div>\n <div class=\"rc-filter-overflow-popover\" role=\"menu\">\n <div class=\"rc-filter-overflow-header\">Filter by</div>\n @for (pill of ConditionalPills; track pill.Key) {\n <label class=\"rc-filter-overflow-row\" [class.rc-filter-overflow-row-restore]=\"pill.Variant === 'restore'\">\n <input type=\"checkbox\"\n [checked]=\"ChipSelections[pill.Key]\"\n (change)=\"TogglePill(pill.Key)\" />\n <i class=\"fa-solid {{ pill.Icon }}\" aria-hidden=\"true\"></i>\n <span class=\"rc-filter-overflow-label\">{{ pill.Label }}</span>\n <span class=\"rc-filter-overflow-count\">{{ pill.Count }}</span>\n </label>\n }\n <div class=\"rc-filter-overflow-actions\">\n <button class=\"rc-filter-overflow-clear\" (click)=\"SelectAllPill(); CloseFilterOverflow()\" type=\"button\">\n Clear all\n </button>\n <button class=\"rc-filter-overflow-done\" (click)=\"CloseFilterOverflow()\" type=\"button\">\n Done\n </button>\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n\n @if (filteredData.length !== viewData.length) {\n <div class=\"rc-filter-results\">\n Showing {{ filteredData.length }} of {{ viewData.length }} changes\n <button class=\"rc-clear-filters-link\" (click)=\"ClearFilters()\">Clear filters</button>\n </div>\n }\n\n <!-- Timeline -->\n <div class=\"rc-timeline\" [attr.aria-label]=\"'Timeline of changes for ' + record.EntityInfo.Name + ' record'\">\n @if (filteredData.length === 0) {\n <div class=\"rc-no-results\">\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n <p>No changes match your current filters.</p>\n <button class=\"rc-clear-filters-btn\" (click)=\"ClearFilters()\">\n <i class=\"fa-solid fa-xmark\"></i> Clear Filters\n </button>\n </div>\n } @else {\n @for (group of dateGroups; track group.label) {\n <div class=\"rc-date-group\">\n <div class=\"rc-date-label\">{{ group.label }}</div>\n\n @for (change of group.changes; track change.ID) {\n <div\n class=\"rc-card\"\n [attr.data-change-id]=\"change.ID\"\n [class]=\"getChangeTypeCardClass(change.Type)\"\n [class.expanded]=\"expandedItems.has(change.ID)\"\n [class.rc-card-restore]=\"isRestoreRow(change)\"\n [class.rc-card-highlight]=\"HighlightedChangeID === change.ID\"\n [attr.tabindex]=\"0\"\n [attr.aria-expanded]=\"expandedItems.has(change.ID)\"\n [attr.aria-label]=\"getTimelineItemLabel(change)\"\n (keydown)=\"onTimelineItemKeydown($event, change.ID)\"\n >\n <!-- Card Header -->\n <div class=\"rc-card-header\" (click)=\"toggleExpansion(change.ID)\">\n <div class=\"rc-card-header-left\">\n <span class=\"rc-card-type-badge\"\n [class.rc-card-type-badge-restore]=\"isRestoreRow(change)\">{{ getEffectiveBadgeText(change) }}</span>\n <span class=\"rc-card-summary\">{{ getChangeSummary(change) }}</span>\n\n <!-- Lineage chip — visible when this row was produced by a restore -->\n @if (isRestoreRow(change)) {\n @if (getRestoredFromSourceChange(change); as srcChange) {\n <a class=\"rc-restored-chip\"\n (click)=\"JumpToSourceChange(srcChange, $event)\"\n [title]=\"'Jump to source version (' + formatFullDateTime(srcChange.ChangedAt) + ')'\">\n <i class=\"fa-solid fa-link\" aria-hidden=\"true\"></i>\n Restored from {{ formatTime(srcChange.ChangedAt) }} {{ srcChange.ChangedAt ? 'on ' + (srcChange.ChangedAt | date:'mediumDate') : '' }}\n @if (srcChange.User) {\n by {{ getUserDisplayName(srcChange.User) }}\n }\n </a>\n } @else {\n <span class=\"rc-restored-chip rc-restored-chip-orphan\"\n title=\"Source version was not loaded into this view\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n Restored from earlier version\n </span>\n }\n }\n </div>\n <div class=\"rc-card-meta\">\n <div class=\"rc-card-user\">\n <div class=\"rc-avatar\">{{ getUserInitials(change.User) }}</div>\n {{ getUserDisplayName(change.User) }}\n </div>\n <span class=\"rc-card-time\" [title]=\"formatFullDateTime(change.ChangedAt)\">{{ formatTime(change.ChangedAt) }}</span>\n <span class=\"rc-card-source\" [class]=\"getSourceClass(change.Source)\">{{ change.Source }}</span>\n <span class=\"rc-card-status\" [class]=\"getStatusClass(change.Status)\">{{ change.Status }}</span>\n <i class=\"fa-solid fa-chevron-down rc-card-chevron\" aria-hidden=\"true\"></i>\n </div>\n </div>\n\n <!-- Card Body (expanded) -->\n @if (expandedItems.has(change.ID)) {\n <div class=\"rc-card-body\">\n <!-- Restore reason (when present) — Notion/Linear-style\n blockquote: a thin violet left bar + italic text,\n with a tiny \"Reason\" prefix. No box, no header,\n no large vertical footprint. Reads as a\n justification note rather than a callout. -->\n @if (getRestoreReason(change); as reason) {\n <blockquote class=\"rc-restore-reason\">\n <span class=\"rc-restore-reason-label\">Reason</span>\n <span class=\"rc-restore-reason-text\">{{ reason }}</span>\n </blockquote>\n }\n\n @if (change.Type === 'Create') {\n @if (change.FullRecordJSON) {\n @for (field of getCreatedFields(change); track field.name) {\n <div class=\"rc-field-row\">\n <div class=\"rc-field-label\">{{ field.displayName }}</div>\n <div class=\"rc-field-values\">\n <span class=\"rc-val-new\">{{ field.value }}</span>\n </div>\n </div>\n }\n }\n } @else if (change.Type === 'Delete') {\n <div class=\"rc-deletion-note\">\n <i class=\"fa-solid fa-trash\" aria-hidden=\"true\"></i>\n This record was permanently removed from the system.\n </div>\n } @else {\n <!-- Update / Snapshot / Restore: type-aware field changes -->\n @for (fc of getFieldChanges(change); track fc.field) {\n <div class=\"rc-field-row\">\n <div class=\"rc-field-label\">{{ fc.displayName }}</div>\n <div class=\"rc-field-values\">\n @if (fc.fieldType === 'boolean') {\n <div class=\"rc-bool-change\">\n <span class=\"rc-bool-dot\" [class.on]=\"fc.oldValue === 'true' || fc.oldValue === '1'\" [class.off]=\"fc.oldValue !== 'true' && fc.oldValue !== '1'\"></span>\n <span class=\"rc-bool-label old\">{{ fc.oldValue === 'true' || fc.oldValue === '1' ? 'Yes' : 'No' }}</span>\n <i class=\"fa-solid fa-arrow-right rc-val-arrow\" aria-hidden=\"true\"></i>\n <span class=\"rc-bool-dot\" [class.on]=\"fc.newValue === 'true' || fc.newValue === '1'\" [class.off]=\"fc.newValue !== 'true' && fc.newValue !== '1'\"></span>\n <span class=\"rc-bool-label new\" [class.active]=\"fc.newValue === 'true' || fc.newValue === '1'\" [class.inactive]=\"fc.newValue !== 'true' && fc.newValue !== '1'\">{{ fc.newValue === 'true' || fc.newValue === '1' ? 'Yes' : 'No' }}</span>\n </div>\n } @else if (fc.fieldType === 'date' || fc.fieldType === 'number') {\n <div class=\"rc-atomic-change\">\n <span class=\"rc-val-old\">{{ fc.oldValue || '(empty)' }}</span>\n <i class=\"fa-solid fa-arrow-right rc-val-arrow\" aria-hidden=\"true\"></i>\n <span class=\"rc-val-new\">{{ fc.newValue || '(empty)' }}</span>\n </div>\n } @else if (fc.diffHtml) {\n <div class=\"rc-text-diff\" [innerHTML]=\"fc.diffHtml\"></div>\n } @else {\n <div class=\"rc-atomic-change\">\n <span class=\"rc-val-old\">{{ fc.oldValue || '(empty)' }}</span>\n <i class=\"fa-solid fa-arrow-right rc-val-arrow\" aria-hidden=\"true\"></i>\n <span class=\"rc-val-new\">{{ fc.newValue || '(empty)' }}</span>\n </div>\n }\n </div>\n </div>\n }\n }\n\n @if (change.Comments) {\n <div class=\"rc-comments\">\n <i class=\"fa-solid fa-comment\" aria-hidden=\"true\"></i>\n {{ change.Comments }}\n </div>\n }\n\n @if (change.ErrorLog) {\n <div class=\"rc-errors\">\n <i class=\"fa-solid fa-exclamation-triangle\" aria-hidden=\"true\"></i>\n <pre class=\"rc-error-log\">{{ change.ErrorLog }}</pre>\n </div>\n }\n\n <!-- Restore action: shown for Update, Create, and Snapshot rows.\n Hidden on Delete rows (handled via the Recycle Bin path)\n and on the most recent change (restoring to current state is a no-op). -->\n @if (AllowRestore && change.Type !== 'Delete' && !isMostRecentChange(change)) {\n <div class=\"rc-restore-action\">\n <button class=\"rc-restore-btn\"\n (click)=\"OnRestoreVersion(change, $event)\"\n title=\"Restore the entire record to its state at this version\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n Restore record to this version\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n }\n\n <!-- Restore preview slide-in (reusable component) -->\n <mj-restore-preview-panel\n [Visible]=\"RestorePreviewVisible\"\n [Mode]=\"'live'\"\n [RecordChange]=\"RestorePreviewChange\"\n [LiveRecord]=\"record\"\n (RestoreConfirmed)=\"OnRestorePanelConfirmed($event)\"\n (RestoreCancelled)=\"OnRestorePanelCancelled()\">\n </mj-restore-preview-panel>\n\n @if (ShowCreateWizard) {\n <div class=\"rc-wizard-overlay\" (click)=\"OnLabelCreateCancelled()\">\n <div class=\"rc-wizard-container\" (click)=\"$event.stopPropagation()\">\n <mj-label-create\n [PreselectedEntity]=\"record.EntityInfo\"\n [PreselectedRecordIds]=\"[record.PrimaryKey.KeyValuePairs[0].Value]\"\n (Created)=\"OnLabelCreated($event)\"\n (Cancel)=\"OnLabelCreateCancelled()\">\n </mj-label-create>\n </div>\n </div>\n }\n</mj-slide-panel>\n"]}
1
+ {"version":3,"file":"ng-record-changes.component.js","sourceRoot":"","sources":["../../src/lib/ng-record-changes.component.ts","../../src/lib/ng-record-changes.component.html"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n EventEmitter,\n Input,\n OnDestroy,\n OnInit,\n Output,\n ChangeDetectorRef,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n NgZone,\n} from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { Subscription } from 'rxjs';\nimport {\n BaseEntity,\n BaseEntityEvent,\n CompositeKey,\n EntityFieldInfo,\n EntityFieldTSType,\n RunView,\n} from '@memberjunction/core';\nimport { UUIDsEqual } from '@memberjunction/global';\nimport { MJRecordChangeEntity } from '@memberjunction/core-entities';\nimport { MJNotificationService } from '@memberjunction/ng-notifications';\nimport { BaseAngularComponent } from '@memberjunction/ng-base-types';\nimport { diffChars, diffWords, Change } from 'diff';\nimport { RestoreCommitEvent } from './restore-preview-panel/restore-preview-panel.component';\n\n/** Lightweight shape for displaying a version label associated with this record */\ninterface RecordLabel {\n ID: string;\n Name: string;\n Description: string | null;\n Scope: string;\n Status: string;\n CreatedAt: Date;\n ItemCount: number;\n}\n\n/**\n * Event payload emitted when the user confirms a restore.\n *\n * The host component (typically `record-form-container`) is responsible for:\n * 1. Reloading the live record (concurrency safety),\n * 2. Calling `record.SetRestoreContext(SourceChangeID, Reason)`,\n * 3. Calling `record.Set(FieldName, Value)` for each entry in `FieldValues`,\n * 4. Calling `record.Save()`,\n * 5. Calling `record.ClearRestoreContext()` after the save returns.\n *\n * The provider will write a new RecordChange row with `Source='Restore'`,\n * `RestoredFromID = SourceChangeID`, and `RestoreReason = Reason` —\n * producing the auditable lineage chain.\n */\nexport interface RestoreVersionEvent {\n /** ID of the historical RecordChange row whose state is being restored. */\n SourceChangeID: string;\n /** When the historical change was made. */\n ChangedAt: Date;\n /** Display name / email of who made the historical change. */\n ChangedByUser: string;\n /** Optional user-entered reason for the restore. */\n Reason: string | null;\n /** Selected field values, ready to pass to BaseEntity.Set(). */\n FieldValues: Array<{ FieldName: string; Value: unknown }>;\n}\n\n/** A single field change with type-aware rendering info (timeline display only). */\nexport interface FieldChangeInfo {\n field: string;\n displayName: string;\n oldValue: string;\n newValue: string;\n fieldType: 'boolean' | 'date' | 'number' | 'text';\n diffHtml?: SafeHtml;\n}\n\n/** A group of changes that share the same date. */\nexport interface DateGroup {\n label: string;\n changes: MJRecordChangeEntity[];\n}\n\n/** A conditional filter pill (one per type/source actually present in loaded data). */\nexport interface FilterPill {\n /** Unique key for selection state ('Update', 'Create', 'Delete', 'Snapshot', 'Restore'). */\n Key: string;\n /** User-facing label (pluralized: 'Updates', 'Restored', etc.). */\n Label: string;\n /** Font Awesome icon class. */\n Icon: string;\n /** Number of changes of this kind in the loaded data. */\n Count: number;\n /** Selection style — neutral type pill or violet restore pill. */\n Variant: 'type' | 'restore';\n}\n\n/**\n * Slide-out timeline of all changes to a single record. Hosts the reusable\n * {@link RestorePreviewPanelComponent} for the actual restore confirmation\n * flow, and exposes a `RestoreRequested` event the host can act on to\n * persist the restore.\n *\n * @example\n * <mj-record-changes\n * [record]=\"myEntity\"\n * [AllowRestore]=\"true\"\n * (dialogClosed)=\"showHistory = false\"\n * (RestoreRequested)=\"onRestoreRequested($event)\">\n * </mj-record-changes>\n */\n@Component({\n standalone: false,\n selector: 'mj-record-changes',\n templateUrl: './ng-record-changes.component.html',\n styleUrls: ['./ng-record-changes.component.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n})\nexport class RecordChangesComponent extends BaseAngularComponent implements OnInit, OnDestroy {\n public IsLoading = false;\n public IsVisible = false;\n @Output() dialogClosed = new EventEmitter();\n @Input() record!: BaseEntity;\n\n /** Whether to show a \"Restore\" button on each historical version row. Default false. */\n @Input() AllowRestore = false;\n\n /**\n * Emitted when the user confirms a restore in the preview panel.\n * The host is responsible for applying the snapshot to the record and\n * saving with `record.SetRestoreContext()` set first.\n */\n @Output() RestoreRequested = new EventEmitter<RestoreVersionEvent>();\n\n viewData: MJRecordChangeEntity[] = [];\n filteredData: MJRecordChangeEntity[] = [];\n dateGroups: DateGroup[] = [];\n expandedItems: Set<string> = new Set();\n\n /** The change record currently selected for restore preview, or null. */\n RestorePreviewChange: MJRecordChangeEntity | null = null;\n /** Visibility of the embedded restore preview slide-in. */\n RestorePreviewVisible = false;\n /** Whether the restore commit is in progress (between confirmation and host response). */\n IsRestoring = false;\n\n // Version label state\n RecordLabels: RecordLabel[] = [];\n IsLoadingLabels = false;\n ShowCreateWizard = false;\n\n // Filter properties\n searchTerm = '';\n /** Single selected type filter (legacy, kept for backwards compat). */\n selectedType = '';\n selectedSource = '';\n /** Map of Key → selected, used by the conditional chip system. */\n ChipSelections: Record<string, boolean> = {};\n /** Whether the overflow popover is open. */\n ShowFilterOverflow = false;\n /** Highlighted change ID for the lineage-jump indicator (transient). */\n HighlightedChangeID: string | null = null;\n\n /**\n * Conditional filter pills derived from loaded data. Always includes 'All'\n * implicitly. Other pills only render when at least one matching change\n * exists. Overflows into a popover when the count exceeds 2.\n */\n ConditionalPills: FilterPill[] = [];\n\n /** Threshold above which conditional chips collapse into the overflow popover. */\n private readonly OVERFLOW_THRESHOLD = 2;\n\n /**\n * Subscription to the record's BaseEntity event stream. We listen for\n * 'save' events and auto-refresh the timeline so the user immediately\n * sees the new RecordChange row produced by either a normal save or a\n * restore. Cleaned up in ngOnDestroy.\n */\n private _entitySaveSub: Subscription | null = null;\n\n constructor(\n private cdr: ChangeDetectorRef,\n private ngZone: NgZone,\n private mjNotificationService: MJNotificationService,\n private sanitizer: DomSanitizer,\n ) { super(); }\n\n ngOnInit(): void {\n if (this.record) {\n this.IsLoading = true;\n this.IsVisible = true;\n this.cdr.markForCheck();\n this.LoadRecordChanges(this.record.PrimaryKey, '', this.record.EntityInfo.Name);\n this.LoadRecordLabels();\n this.subscribeToRecordSaves();\n }\n }\n\n ngOnDestroy(): void {\n this._entitySaveSub?.unsubscribe();\n this._entitySaveSub = null;\n }\n\n /**\n * Wires up an event handler on the live record so the timeline auto-\n * refreshes immediately after any save lands — including the one\n * produced by the restore flow. Without this the user sees their record\n * update in the form but the panel above still shows the pre-restore\n * change list, which is confusing.\n */\n private subscribeToRecordSaves(): void {\n if (!this.record) return;\n this._entitySaveSub?.unsubscribe();\n this._entitySaveSub = this.record.RegisterEventHandler((event: BaseEntityEvent) => {\n if (event?.type === 'save') {\n this.ngZone.run(() => this.Refresh());\n }\n });\n }\n\n /**\n * Reloads the record changes list from the database.\n * Called by the parent container after a save completes while the drawer is open.\n */\n public Refresh(): void {\n if (this.record) {\n this.IsLoading = true;\n this.cdr.markForCheck();\n this.LoadRecordChanges(this.record.PrimaryKey, '', this.record.EntityInfo.Name);\n }\n }\n\n public OnClose(): void {\n this.IsVisible = false;\n this.cdr.markForCheck();\n // Allow the slide-out animation to complete before emitting\n setTimeout(() => this.dialogClosed.emit(), 300);\n }\n\n public async LoadRecordChanges(pkey: CompositeKey, appName: string, entityName: string): Promise<void> {\n if (pkey && entityName) {\n const md = this.ProviderToUse;\n const entityInfo = md.EntityByName(entityName);\n let changes: MJRecordChangeEntity[] = [];\n if (entityInfo?.TrackRecordChanges) {\n const rvResult = await RunView.FromMetadataProvider(md).RunView<MJRecordChangeEntity>({\n EntityName: 'MJ: Record Changes',\n ExtraFilter: `Entity='${entityName}' AND RecordID='${pkey.ToConcatenatedString()}'`,\n OrderBy: 'ChangedAt DESC',\n ResultType: 'entity_object',\n });\n if (rvResult.Success) changes = rvResult.Results;\n }\n this.ngZone.run(() => {\n if (changes) {\n this.viewData = changes.sort(\n (a: MJRecordChangeEntity, b: MJRecordChangeEntity) => new Date(b.ChangedAt).getTime() - new Date(a.ChangedAt).getTime(),\n );\n this.rebuildConditionalPills();\n this.applyFilters();\n this.IsLoading = false;\n } else {\n this.mjNotificationService.CreateSimpleNotification(\n `Error loading record changes for ${entityName} with primary key ${pkey.ToString()}.`,\n 'error',\n );\n this.IsLoading = false;\n }\n this.cdr.markForCheck();\n });\n }\n }\n\n // ─── Filter & Search ────────────────────────────────────────────\n\n onSearchChange(): void {\n this.applyFilters();\n }\n\n onFilterChange(): void {\n this.applyFilters();\n }\n\n /**\n * Toggles the \"All\" pill — clears every conditional selection.\n */\n public SelectAllPill(): void {\n for (const k of Object.keys(this.ChipSelections)) this.ChipSelections[k] = false;\n this.applyFilters();\n }\n\n /**\n * Toggles a conditional pill on/off.\n */\n public TogglePill(key: string): void {\n this.ChipSelections[key] = !this.ChipSelections[key];\n this.applyFilters();\n }\n\n /**\n * Returns true when no conditional pills are selected (i.e. \"All\" mode).\n */\n public get IsAllSelected(): boolean {\n return !Object.values(this.ChipSelections).some(v => v);\n }\n\n /**\n * Whether any conditional pills are actually visible at all.\n */\n public get HasConditionalPills(): boolean {\n return this.ConditionalPills.length > 0;\n }\n\n /**\n * True when the conditional chips should collapse into an overflow popover\n * because there are more than the threshold.\n */\n public get UseOverflowPopover(): boolean {\n return this.ConditionalPills.length > this.OVERFLOW_THRESHOLD;\n }\n\n /** Number of currently selected conditional pills (for the popover trigger label). */\n public get SelectedConditionalCount(): number {\n return Object.values(this.ChipSelections).filter(v => v).length;\n }\n\n public ToggleFilterOverflow(): void {\n this.ShowFilterOverflow = !this.ShowFilterOverflow;\n this.cdr.markForCheck();\n }\n\n public CloseFilterOverflow(): void {\n this.ShowFilterOverflow = false;\n this.cdr.markForCheck();\n }\n\n public ClearFilters(): void {\n this.searchTerm = '';\n for (const k of Object.keys(this.ChipSelections)) this.ChipSelections[k] = false;\n this.applyFilters();\n }\n\n /**\n * Builds the list of conditional pills from currently loaded data —\n * a pill only appears for change types/sources that actually exist.\n */\n private rebuildConditionalPills(): void {\n const counts: Record<string, number> = {};\n let restoreCount = 0;\n\n for (const c of this.viewData) {\n const type = c.Type ?? 'Update';\n counts[type] = (counts[type] ?? 0) + 1;\n if (this.isRestoreChange(c)) restoreCount++;\n }\n\n const pills: FilterPill[] = [];\n if ((counts['Update'] ?? 0) > 0) {\n pills.push({ Key: 'Update', Label: 'Updates', Icon: 'fa-pen', Count: counts['Update'], Variant: 'type' });\n }\n if ((counts['Create'] ?? 0) > 0) {\n pills.push({ Key: 'Create', Label: 'Creates', Icon: 'fa-plus', Count: counts['Create'], Variant: 'type' });\n }\n if ((counts['Delete'] ?? 0) > 0) {\n pills.push({ Key: 'Delete', Label: 'Deletes', Icon: 'fa-trash', Count: counts['Delete'], Variant: 'type' });\n }\n if ((counts['Snapshot'] ?? 0) > 0) {\n pills.push({ Key: 'Snapshot', Label: 'Snapshots', Icon: 'fa-camera', Count: counts['Snapshot'], Variant: 'type' });\n }\n if (restoreCount > 0) {\n pills.push({ Key: 'Restore', Label: 'Restored', Icon: 'fa-clock-rotate-left', Count: restoreCount, Variant: 'restore' });\n }\n\n // Initialize/prune selection state\n const validKeys = new Set(pills.map(p => p.Key));\n for (const k of Object.keys(this.ChipSelections)) {\n if (!validKeys.has(k)) delete this.ChipSelections[k];\n }\n for (const p of pills) {\n if (this.ChipSelections[p.Key] === undefined) this.ChipSelections[p.Key] = false;\n }\n\n this.ConditionalPills = pills;\n }\n\n private isRestoreChange(c: MJRecordChangeEntity): boolean {\n return c.Source === 'Restore' || (c as any).RestoredFromID != null;\n }\n\n private applyFilters(): void {\n let filtered = [...this.viewData];\n\n if (this.searchTerm.trim()) {\n const search = this.searchTerm.toLowerCase();\n filtered = filtered.filter(\n change =>\n change.ChangesDescription?.toLowerCase().includes(search) ||\n change.User?.toLowerCase().includes(search) ||\n change.Comments?.toLowerCase().includes(search),\n );\n }\n\n // Apply conditional pill filters — if any are selected, only show changes matching ANY of them (OR semantics).\n const selectedKeys = Object.keys(this.ChipSelections).filter(k => this.ChipSelections[k]);\n if (selectedKeys.length > 0) {\n filtered = filtered.filter(change => {\n for (const key of selectedKeys) {\n if (key === 'Restore') {\n if (this.isRestoreChange(change)) return true;\n } else {\n if (change.Type === key) return true;\n }\n }\n return false;\n });\n }\n\n this.filteredData = filtered;\n this.dateGroups = this.buildDateGroups(this.filteredData);\n this.cdr.markForCheck();\n }\n\n // ─── Version Labels ─────────────────────────────────────────────\n\n public async LoadRecordLabels(): Promise<void> {\n if (!this.record) return;\n\n this.IsLoadingLabels = true;\n this.cdr.markForCheck();\n\n try {\n const entityId = this.record.EntityInfo.ID;\n const recordId = this.record.PrimaryKey.ToConcatenatedString();\n\n const rv = RunView.FromMetadataProvider(this.ProviderToUse);\n const itemsResult = await rv.RunView<{ VersionLabelID: string }>({\n EntityName: 'MJ: Version Label Items',\n Fields: ['VersionLabelID'],\n ExtraFilter: `EntityID='${entityId}' AND RecordID='${recordId}'`,\n ResultType: 'simple',\n });\n\n if (!itemsResult.Success || itemsResult.Results.length === 0) {\n this.ngZone.run(() => {\n this.RecordLabels = [];\n this.IsLoadingLabels = false;\n this.cdr.markForCheck();\n });\n return;\n }\n\n const labelIds = [...new Set(itemsResult.Results.map(i => i.VersionLabelID))];\n const labelIdFilter = labelIds.map(id => `'${id}'`).join(',');\n\n const labelsResult = await rv.RunView<{\n ID: string;\n Name: string;\n Description: string | null;\n Scope: string;\n Status: string;\n ItemCount: number;\n __mj_CreatedAt: Date;\n }>({\n EntityName: 'MJ: Version Labels',\n Fields: ['ID', 'Name', 'Description', 'Scope', 'Status', 'ItemCount', '__mj_CreatedAt'],\n ExtraFilter: `ID IN (${labelIdFilter})`,\n OrderBy: '__mj_CreatedAt DESC',\n ResultType: 'simple',\n });\n\n if (labelsResult.Success) {\n this.RecordLabels = labelsResult.Results.map(l => ({\n ID: l.ID,\n Name: l.Name,\n Description: l.Description,\n Scope: l.Scope,\n Status: l.Status,\n CreatedAt: l.__mj_CreatedAt,\n ItemCount: l.ItemCount,\n }));\n }\n } catch (error) {\n console.error('Error loading version labels for record:', error);\n this.RecordLabels = [];\n } finally {\n this.ngZone.run(() => {\n this.IsLoadingLabels = false;\n this.cdr.markForCheck();\n });\n }\n }\n\n public OpenCreateWizard(): void {\n this.ShowCreateWizard = true;\n this.cdr.markForCheck();\n }\n\n public OnLabelCreated(event: { LabelCount: number; ItemCount: number }): void {\n this.ShowCreateWizard = false;\n this.cdr.markForCheck();\n this.LoadRecordLabels();\n this.mjNotificationService.CreateSimpleNotification(\n `Version label created with ${event.ItemCount} snapshot${event.ItemCount !== 1 ? 's' : ''}`,\n 'info',\n 2000,\n );\n }\n\n public OnLabelCreateCancelled(): void {\n this.ShowCreateWizard = false;\n this.cdr.markForCheck();\n }\n\n public getLabelStatusClass(status: string): string {\n switch (status) {\n case 'Active': return 'label-status-active';\n case 'Archived': return 'label-status-archived';\n case 'Restored': return 'label-status-restored';\n default: return '';\n }\n }\n\n // ─── Timeline Interaction ───────────────────────────────────────\n\n toggleExpansion(changeId: string): void {\n if (this.expandedItems.has(changeId)) {\n this.expandedItems.delete(changeId);\n } else {\n this.expandedItems.add(changeId);\n }\n this.cdr.markForCheck();\n }\n\n onTimelineItemKeydown(event: KeyboardEvent, changeId: string): void {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.toggleExpansion(changeId);\n }\n }\n\n /**\n * Opens the embedded restore preview panel for a given change record.\n * The panel computes a full-record diff (current vs the change's\n * FullRecordJSON snapshot) — this is the semantic-correctness fix:\n * we restore TO the state at that point in time, not just undo the\n * one delta the user clicked.\n */\n OnRestoreVersion(change: MJRecordChangeEntity, event: MouseEvent): void {\n event.stopPropagation();\n this.RestorePreviewChange = change;\n this.RestorePreviewVisible = true;\n this.cdr.markForCheck();\n }\n\n /**\n * Called when the user confirms the restore in the embedded panel.\n * Translates the panel's RestoreCommitEvent into the broader-shape\n * RestoreVersionEvent the host is wired to handle.\n */\n OnRestorePanelConfirmed(commit: RestoreCommitEvent): void {\n if (!this.RestorePreviewChange) return;\n\n const change = this.RestorePreviewChange;\n this.IsRestoring = true;\n this.cdr.markForCheck();\n\n this.RestoreRequested.emit({\n SourceChangeID: commit.SourceChangeID,\n ChangedAt: change.ChangedAt,\n ChangedByUser: change.User || '',\n Reason: commit.Reason,\n FieldValues: commit.FieldValues,\n });\n\n // Close the panel after a brief delay so the host has a moment to react.\n setTimeout(() => {\n this.RestorePreviewVisible = false;\n this.RestorePreviewChange = null;\n this.IsRestoring = false;\n this.cdr.markForCheck();\n }, 500);\n }\n\n /**\n * Called when the user dismisses the restore preview without confirming.\n */\n OnRestorePanelCancelled(): void {\n this.RestorePreviewVisible = false;\n this.RestorePreviewChange = null;\n this.cdr.markForCheck();\n }\n\n // ─── Lineage chip ───────────────────────────────────────────────\n\n /**\n * Returns the source change for a given restored row, if found in the\n * currently loaded changes. Returns null when the source isn't loaded\n * (e.g., it's been pruned from history) or when this row isn't a restore.\n */\n public getRestoredFromSourceChange(change: MJRecordChangeEntity): MJRecordChangeEntity | null {\n const sourceId = (change as any).RestoredFromID;\n if (!sourceId) return null;\n return this.viewData.find(c => UUIDsEqual(c.ID, sourceId)) ?? null;\n }\n\n /**\n * True when the row was produced by a restore operation (either the\n * `Source` is `'Restore'` OR `RestoredFromID` is populated).\n */\n public isRestoreRow(change: MJRecordChangeEntity): boolean {\n return this.isRestoreChange(change);\n }\n\n /**\n * True when this change is the most recent in the loaded history.\n * `viewData` is sorted DESC by `ChangedAt`, so the most recent is index 0.\n * Restoring to the most recent version is a no-op, so the timeline hides\n * the Restore button on this row.\n */\n public isMostRecentChange(change: MJRecordChangeEntity): boolean {\n return this.viewData.length > 0 && this.viewData[0] === change;\n }\n\n /**\n * Click handler for the lineage chip — scrolls/highlights the source\n * change row in the timeline. Auto-clears after a few seconds.\n */\n public JumpToSourceChange(sourceChange: MJRecordChangeEntity, event: MouseEvent): void {\n event.stopPropagation();\n this.HighlightedChangeID = sourceChange.ID;\n this.expandedItems.add(sourceChange.ID);\n this.cdr.markForCheck();\n\n // Auto-clear the highlight after 3s\n setTimeout(() => {\n if (this.HighlightedChangeID && UUIDsEqual(this.HighlightedChangeID, sourceChange.ID)) {\n this.HighlightedChangeID = null;\n this.cdr.markForCheck();\n }\n }, 3000);\n\n // Scroll into view\n setTimeout(() => {\n const el = document.querySelector(`[data-change-id=\"${sourceChange.ID}\"]`);\n el?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }, 50);\n }\n\n // ─── Date Grouping ─────────────────────────────────────────────\n\n private buildDateGroups(changes: MJRecordChangeEntity[]): DateGroup[] {\n const groups = new Map<string, MJRecordChangeEntity[]>();\n\n for (const change of changes) {\n const label = this.formatDateGroupLabel(new Date(change.ChangedAt));\n if (!groups.has(label)) {\n groups.set(label, []);\n }\n groups.get(label)!.push(change);\n }\n\n return Array.from(groups.entries()).map(([label, items]) => ({ label, changes: items }));\n }\n\n private formatDateGroupLabel(date: Date): string {\n const now = new Date();\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());\n const target = new Date(date.getFullYear(), date.getMonth(), date.getDate());\n const diffDays = Math.floor((today.getTime() - target.getTime()) / 86400000);\n\n const formatted = new Intl.DateTimeFormat('en-US', { month: 'short', day: 'numeric', year: 'numeric' }).format(date);\n\n if (diffDays === 0) return `Today \\u2014 ${formatted}`;\n if (diffDays === 1) return `Yesterday \\u2014 ${formatted}`;\n return formatted;\n }\n\n // ─── Display Helpers ────────────────────────────────────────────\n\n getChangeTypeCardClass(type: string): string {\n switch (type) {\n case 'Create': return 'type-create';\n case 'Update': return 'type-update';\n case 'Delete': return 'type-delete';\n case 'Snapshot': return 'type-snapshot';\n default: return 'type-update';\n }\n }\n\n getChangeTypeBadgeText(type: string): string {\n switch (type) {\n case 'Create': return 'Created';\n case 'Delete': return 'Deleted';\n case 'Snapshot': return 'Snapshot';\n default: return type;\n }\n }\n\n /**\n * Badge text for the row's primary type tag. For restore rows we override\n * the underlying `Type='Update'` and show \"Restore\" instead — matches the\n * mockup's intent of treating restore as a first-class operation in the\n * timeline rather than a flavor of update.\n */\n getEffectiveBadgeText(change: MJRecordChangeEntity): string {\n if (this.isRestoreRow(change)) return 'Restore';\n return this.getChangeTypeBadgeText(change.Type);\n }\n\n /**\n * Optional restore reason — pulled from the dynamic `RestoreReason`\n * column added by the lineage migration. Returns null when not present\n * or not a restore row.\n */\n getRestoreReason(change: MJRecordChangeEntity): string | null {\n if (!this.isRestoreRow(change)) return null;\n const reason = (change as unknown as { RestoreReason?: string | null }).RestoreReason;\n return reason && reason.trim().length > 0 ? reason : null;\n }\n\n getSourceClass(source: string): string {\n if (source === 'Restore') return 'source-restore';\n if (source === 'Internal') return 'source-internal';\n return 'source-external';\n }\n\n getStatusClass(status: string): string {\n switch (status) {\n case 'Complete': return 'status-complete';\n case 'Pending': return 'status-pending';\n case 'Error': return 'status-error';\n default: return 'status-unknown';\n }\n }\n\n getTimelineItemLabel(change: MJRecordChangeEntity): string {\n return `${change.Type} by ${change.User || 'Unknown User'} on ${this.formatFullDateTime(change.ChangedAt)}`;\n }\n\n getUserInitials(user: string | null): string {\n if (!user) return '?';\n if (user.includes('@')) {\n const local = user.split('@')[0];\n return local.substring(0, 2).toUpperCase();\n }\n const parts = user.trim().split(/\\s+/);\n if (parts.length >= 2) {\n return (parts[0][0] + parts[1][0]).toUpperCase();\n }\n return user.substring(0, 2).toUpperCase();\n }\n\n getUserDisplayName(user: string | null): string {\n if (!user) return 'Unknown';\n if (user.includes('@')) return user.split('@')[0];\n return user;\n }\n\n getUniqueContributorCount(): number {\n const users = new Set(this.viewData.map(c => c.User).filter(Boolean));\n return users.size;\n }\n\n formatTime(date: Date): string {\n return new Intl.DateTimeFormat('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n }).format(new Date(date));\n }\n\n formatRelativeTime(date: Date): string {\n const now = new Date();\n const diffMs = now.getTime() - new Date(date).getTime();\n const diffMins = Math.floor(diffMs / 60000);\n const diffHours = Math.floor(diffMins / 60);\n const diffDays = Math.floor(diffHours / 24);\n\n if (diffMins < 1) return 'Just now';\n if (diffMins < 60) return `${diffMins} min${diffMins > 1 ? 's' : ''} ago`;\n if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`;\n if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`;\n\n return new Intl.DateTimeFormat('en-US', {\n month: 'short',\n day: 'numeric',\n year: diffDays > 365 ? 'numeric' : undefined,\n }).format(new Date(date));\n }\n\n formatFullDateTime(date: Date): string {\n return new Intl.DateTimeFormat('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n hour: 'numeric',\n minute: 'numeric',\n hour12: true,\n timeZoneName: 'short',\n }).format(new Date(date));\n }\n\n // ─── Change Summary ─────────────────────────────────────────────\n\n getChangeSummary(change: MJRecordChangeEntity): string {\n // Restore rows get a distinctive summary so the timeline reads like a\n // sentence — \"Restored to 5:56 PM version\" rather than yet another\n // \"Name and Description changed\". The lineage chip carries the full\n // source-version detail.\n if (this.isRestoreRow(change)) {\n const src = this.getRestoredFromSourceChange(change);\n if (src) return `Restored to ${this.formatTime(src.ChangedAt)} version`;\n return 'Restored from earlier version';\n }\n if (change.Type === 'Create') return 'Record created';\n if (change.Type === 'Delete') return 'Record deleted';\n if (change.Type === 'Snapshot') return change.ChangesDescription || 'Snapshot captured';\n\n try {\n const changesJson = JSON.parse(change.ChangesJSON || '{}');\n const fieldNames = this.extractFieldDisplayNames(changesJson);\n if (fieldNames.length === 0) return 'No field changes detected';\n\n return this.buildFieldListSummary(fieldNames);\n } catch {\n return change.ChangesDescription || 'Changes made';\n }\n }\n\n getCreatedFieldCount(change: MJRecordChangeEntity): number {\n try {\n if (!change.FullRecordJSON) return 0;\n const record = JSON.parse(change.FullRecordJSON);\n return this.record.EntityInfo.Fields.filter(\n (f: EntityFieldInfo) => record[f.Name] != null && record[f.Name] !== '',\n ).length;\n } catch {\n return 0;\n }\n }\n\n private extractFieldDisplayNames(changesJson: Record<string, { field?: string }>): string[] {\n return Object.keys(changesJson).map(fieldKey => {\n const changeInfo = changesJson[fieldKey];\n const field = this.record.EntityInfo.Fields.find(\n (f: EntityFieldInfo) => f.Name.trim().toLowerCase() === changeInfo.field?.trim().toLowerCase(),\n );\n return field?.DisplayNameOrName || changeInfo.field || fieldKey;\n });\n }\n\n private buildFieldListSummary(fieldNames: string[]): string {\n if (fieldNames.length === 1) return `${fieldNames[0]} changed`;\n if (fieldNames.length === 2) return `${fieldNames[0]} and ${fieldNames[1]} changed`;\n if (fieldNames.length <= 4) {\n const last = fieldNames[fieldNames.length - 1];\n return `${fieldNames.slice(0, -1).join(', ')}, and ${last} changed`;\n }\n const remaining = fieldNames.length - 3;\n return `${fieldNames.slice(0, 3).join(', ')}, and ${remaining} other field${remaining > 1 ? 's' : ''} changed`;\n }\n\n // ─── Field Changes (type-aware) ────────────────────────────────\n\n getFieldChanges(change: MJRecordChangeEntity): FieldChangeInfo[] {\n try {\n const changesJson = JSON.parse(change.ChangesJSON || '{}');\n return Object.keys(changesJson).map(fieldKey => this.buildFieldChangeInfo(changesJson[fieldKey]));\n } catch {\n return [];\n }\n }\n\n private buildFieldChangeInfo(changeInfo: { field?: string; oldValue?: unknown; newValue?: unknown }): FieldChangeInfo {\n const field = this.record.EntityInfo.Fields.find(\n (f: EntityFieldInfo) => f.Name.trim().toLowerCase() === changeInfo.field?.trim().toLowerCase(),\n );\n\n const fieldType = this.classifyFieldType(field);\n const isDateField = fieldType === 'date';\n const formattedOld = this.formatChangeValue(changeInfo.oldValue, isDateField);\n const formattedNew = this.formatChangeValue(changeInfo.newValue, isDateField);\n\n let diffHtml: SafeHtml | undefined;\n if (fieldType === 'text' && formattedOld !== formattedNew) {\n diffHtml = this.generateDiffHtml(formattedOld, formattedNew);\n }\n\n return {\n field: changeInfo.field || '',\n displayName: field?.DisplayNameOrName || changeInfo.field || '',\n oldValue: formattedOld,\n newValue: formattedNew,\n fieldType,\n diffHtml,\n };\n }\n\n private classifyFieldType(field: EntityFieldInfo | undefined): 'boolean' | 'date' | 'number' | 'text' {\n if (!field) return 'text';\n if (field.TSType === EntityFieldTSType.Boolean) return 'boolean';\n if (field.TSType === EntityFieldTSType.Date) return 'date';\n if (field.TSType === EntityFieldTSType.Number) return 'number';\n return 'text';\n }\n\n getCreatedFields(change: MJRecordChangeEntity): Array<{ name: string; displayName: string; value: string }> {\n try {\n if (!change.FullRecordJSON) return [];\n\n const record = JSON.parse(change.FullRecordJSON);\n const fields = this.record.EntityInfo.Fields;\n\n return fields\n .filter((field: EntityFieldInfo) => record[field.Name] != null && record[field.Name] !== '')\n .map((field: EntityFieldInfo) => ({\n name: field.Name,\n displayName: field.DisplayNameOrName,\n value: this.formatChangeValue(record[field.Name], field.TSType === EntityFieldTSType.Date),\n }));\n } catch {\n return [];\n }\n }\n\n // ─── Value Formatting ───────────────────────────────────────────\n\n private formatChangeValue(value: unknown, isDateField: boolean): string {\n if (value == null) return '';\n\n if (typeof value === 'object') {\n const keys = Object.keys(value as Record<string, unknown>);\n if (keys.length === 0) return '';\n return JSON.stringify(value);\n }\n\n if (isDateField && typeof value === 'string') {\n const date = new Date(value);\n if (!isNaN(date.getTime())) {\n return new Intl.DateTimeFormat('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n }).format(date);\n }\n }\n\n return String(value);\n }\n\n // ─── Diff Generation (text fields only) ─────────────────────────\n\n private generateDiffHtml(oldValue: string, newValue: string): SafeHtml {\n if (!oldValue && !newValue) {\n return this.sanitizer.bypassSecurityTrustHtml('<span class=\"rc-diff-unchanged\">(no change)</span>');\n }\n\n if (!oldValue) {\n return this.sanitizer.bypassSecurityTrustHtml(`<span class=\"rc-diff-added\">${this.escapeHtml(newValue)}</span>`);\n }\n\n if (!newValue) {\n return this.sanitizer.bypassSecurityTrustHtml(`<span class=\"rc-diff-removed\">${this.escapeHtml(oldValue)}</span>`);\n }\n\n const useWordDiff = this.shouldUseWordDiff(oldValue, newValue);\n const diffs = useWordDiff ? diffWords(oldValue, newValue) : diffChars(oldValue, newValue);\n\n const html = diffs\n .map((part: Change) => {\n const escaped = this.escapeHtml(part.value);\n if (part.added) return `<span class=\"rc-diff-added\">${escaped}</span>`;\n if (part.removed) return `<span class=\"rc-diff-removed\">${escaped}</span>`;\n return `<span class=\"rc-diff-unchanged\">${escaped}</span>`;\n })\n .join('');\n\n return this.sanitizer.bypassSecurityTrustHtml(html);\n }\n\n private shouldUseWordDiff(oldValue: string, newValue: string): boolean {\n const hasMultipleWords = (text: string) => text.includes(' ') && text.split(' ').length > 3;\n const isLongText = (text: string) => text.length > 50;\n\n return (hasMultipleWords(oldValue) || hasMultipleWords(newValue)) && (isLongText(oldValue) || isLongText(newValue));\n }\n\n private escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n}\n","<mj-slide-panel\n [Mode]=\"'slide'\"\n [Title]=\"'Record Changes History'\"\n [Visible]=\"IsVisible\"\n [Resizable]=\"true\"\n [MinWidthPx]=\"400\"\n [MaxWidthRatio]=\"0.6\"\n (Closed)=\"OnClose()\">\n\n @if (IsLoading) {\n <mj-loading text=\"Loading history...\" size=\"medium\"></mj-loading>\n }\n\n @if (!IsLoading) {\n <div class=\"rc-container\">\n <!-- Version Labels Section -->\n <div class=\"rc-labels-section\">\n <div class=\"rc-labels-header\">\n <div class=\"rc-labels-title\">\n <i class=\"fa-solid fa-tags\" aria-hidden=\"true\"></i>\n <span>Version Labels</span>\n @if (RecordLabels.length > 0) {\n <span class=\"rc-labels-count\">{{ RecordLabels.length }}</span>\n }\n </div>\n <button class=\"rc-create-label-btn\" (click)=\"OpenCreateWizard()\" title=\"Create a version label for this record\">\n <i class=\"fa-solid fa-plus\"></i> Create Label\n </button>\n </div>\n @if (IsLoadingLabels) {\n <div class=\"rc-labels-loading\">\n <i class=\"fa-solid fa-spinner fa-spin\"></i> Loading labels...\n </div>\n } @else if (RecordLabels.length === 0) {\n <div class=\"rc-labels-empty\">\n No version labels for this record yet.\n </div>\n } @else {\n <div class=\"rc-labels-list\">\n @for (label of RecordLabels; track label.ID) {\n <div class=\"rc-label-chip\" [title]=\"label.Description || label.Name\">\n <i class=\"fa-solid fa-tag rc-label-chip-icon\"></i>\n <span class=\"rc-label-chip-name\">{{ label.Name }}</span>\n <span class=\"rc-label-chip-meta\">\n <span class=\"rc-label-chip-status\" [class]=\"getLabelStatusClass(label.Status)\">{{ label.Status }}</span>\n <span class=\"rc-label-chip-items\">{{ label.ItemCount }} item{{ label.ItemCount !== 1 ? 's' : '' }}</span>\n </span>\n </div>\n }\n </div>\n }\n </div>\n\n @if (viewData.length === 0) {\n <!-- Empty state -->\n <div class=\"rc-empty-state\">\n <div class=\"rc-empty-state-icon\">\n <i class=\"fa-solid fa-clock-rotate-left\"></i>\n </div>\n <h3 class=\"rc-empty-state-title\">No Change History</h3>\n <p class=\"rc-empty-state-description\">\n This record doesn't have any tracked changes yet.\n Changes will appear here automatically as edits are made.\n </p>\n <div class=\"rc-empty-state-hint\">\n <i class=\"fa-solid fa-shield-halved\"></i>\n <span>Record change tracking is managed at the entity level</span>\n </div>\n </div>\n } @else {\n <!-- Page Header -->\n <div class=\"rc-page-header\">\n <div>\n <h2 class=\"rc-page-title\">Change History</h2>\n <div class=\"rc-page-subtitle\">{{ record.EntityInfo.Name }}</div>\n </div>\n <div class=\"rc-header-meta\">\n <div class=\"rc-entity-badge\">\n <i class=\"fa-solid fa-database\" aria-hidden=\"true\"></i>\n {{ record.EntityInfo.Name }}\n </div>\n <div class=\"rc-change-count\">{{ viewData.length }} change{{ viewData.length !== 1 ? 's' : '' }} &middot; {{ getUniqueContributorCount() }} contributor{{ getUniqueContributorCount() !== 1 ? 's' : '' }}</div>\n </div>\n </div>\n\n <!-- Filter Bar — chips render only for change types/sources actually present in loaded data.\n When more than 2 conditional chips would render, they collapse into a \"More filters\" popover. -->\n <div class=\"rc-filter-bar\">\n <div class=\"rc-search-wrap\">\n <i class=\"fa-solid fa-search\" aria-hidden=\"true\"></i>\n <input\n class=\"rc-search-box\"\n type=\"text\"\n placeholder=\"Search changes...\"\n [(ngModel)]=\"searchTerm\"\n (input)=\"onSearchChange()\"\n aria-label=\"Search record changes\"\n />\n </div>\n\n <button class=\"rc-filter-pill\" [class.active]=\"IsAllSelected\" (click)=\"SelectAllPill()\" type=\"button\">\n <i class=\"fa-solid fa-layer-group\" aria-hidden=\"true\"></i> All\n </button>\n\n @if (HasConditionalPills) {\n @if (!UseOverflowPopover) {\n <!-- 1-2 conditional pills: render inline -->\n @for (pill of ConditionalPills; track pill.Key) {\n <button class=\"rc-filter-pill\"\n [class.active]=\"ChipSelections[pill.Key]\"\n [class.rc-filter-pill-restore]=\"pill.Variant === 'restore'\"\n (click)=\"TogglePill(pill.Key)\"\n type=\"button\">\n <i class=\"fa-solid {{ pill.Icon }}\" aria-hidden=\"true\"></i>\n {{ pill.Label }}\n <span class=\"rc-filter-pill-count\">{{ pill.Count }}</span>\n </button>\n }\n } @else {\n <!-- 3+ conditional pills: overflow popover -->\n <div class=\"rc-filter-overflow-wrap\">\n <button class=\"rc-filter-pill rc-filter-pill-overflow\"\n [class.active]=\"SelectedConditionalCount > 0\"\n (click)=\"ToggleFilterOverflow()\"\n type=\"button\">\n <i class=\"fa-solid fa-sliders\" aria-hidden=\"true\"></i>\n More filters\n @if (SelectedConditionalCount > 0) {\n <span class=\"rc-filter-pill-count\">{{ SelectedConditionalCount }}</span>\n }\n <i class=\"fa-solid fa-chevron-down rc-filter-overflow-caret\" aria-hidden=\"true\"></i>\n </button>\n\n @if (ShowFilterOverflow) {\n <!-- Backdrop: clicks close the popover -->\n <div class=\"rc-filter-overflow-backdrop\" (click)=\"CloseFilterOverflow()\"></div>\n <div class=\"rc-filter-overflow-popover\" role=\"menu\">\n <div class=\"rc-filter-overflow-header\">Filter by</div>\n @for (pill of ConditionalPills; track pill.Key) {\n <label class=\"rc-filter-overflow-row\" [class.rc-filter-overflow-row-restore]=\"pill.Variant === 'restore'\">\n <input type=\"checkbox\"\n [checked]=\"ChipSelections[pill.Key]\"\n (change)=\"TogglePill(pill.Key)\" />\n <i class=\"fa-solid {{ pill.Icon }}\" aria-hidden=\"true\"></i>\n <span class=\"rc-filter-overflow-label\">{{ pill.Label }}</span>\n <span class=\"rc-filter-overflow-count\">{{ pill.Count }}</span>\n </label>\n }\n <div class=\"rc-filter-overflow-actions\">\n <button class=\"rc-filter-overflow-clear\" (click)=\"SelectAllPill(); CloseFilterOverflow()\" type=\"button\">\n Clear all\n </button>\n <button class=\"rc-filter-overflow-done\" (click)=\"CloseFilterOverflow()\" type=\"button\">\n Done\n </button>\n </div>\n </div>\n }\n </div>\n }\n }\n </div>\n\n @if (filteredData.length !== viewData.length) {\n <div class=\"rc-filter-results\">\n Showing {{ filteredData.length }} of {{ viewData.length }} changes\n <button class=\"rc-clear-filters-link\" (click)=\"ClearFilters()\">Clear filters</button>\n </div>\n }\n\n <!-- Timeline -->\n <div class=\"rc-timeline\" [attr.aria-label]=\"'Timeline of changes for ' + record.EntityInfo.Name + ' record'\">\n @if (filteredData.length === 0) {\n <div class=\"rc-no-results\">\n <i class=\"fa-solid fa-filter\" aria-hidden=\"true\"></i>\n <p>No changes match your current filters.</p>\n <button class=\"rc-clear-filters-btn\" (click)=\"ClearFilters()\">\n <i class=\"fa-solid fa-xmark\"></i> Clear Filters\n </button>\n </div>\n } @else {\n @for (group of dateGroups; track group.label) {\n <div class=\"rc-date-group\">\n <div class=\"rc-date-label\">{{ group.label }}</div>\n\n @for (change of group.changes; track change.ID) {\n <div\n class=\"rc-card\"\n [attr.data-change-id]=\"change.ID\"\n [class]=\"getChangeTypeCardClass(change.Type)\"\n [class.expanded]=\"expandedItems.has(change.ID)\"\n [class.rc-card-restore]=\"isRestoreRow(change)\"\n [class.rc-card-highlight]=\"HighlightedChangeID === change.ID\"\n [attr.tabindex]=\"0\"\n [attr.aria-expanded]=\"expandedItems.has(change.ID)\"\n [attr.aria-label]=\"getTimelineItemLabel(change)\"\n (keydown)=\"onTimelineItemKeydown($event, change.ID)\"\n >\n <!-- Card Header -->\n <div class=\"rc-card-header\" (click)=\"toggleExpansion(change.ID)\">\n <div class=\"rc-card-header-left\">\n <span class=\"rc-card-type-badge\"\n [class.rc-card-type-badge-restore]=\"isRestoreRow(change)\">{{ getEffectiveBadgeText(change) }}</span>\n <span class=\"rc-card-summary\">{{ getChangeSummary(change) }}</span>\n\n <!-- Lineage chip — visible when this row was produced by a restore -->\n @if (isRestoreRow(change)) {\n @if (getRestoredFromSourceChange(change); as srcChange) {\n <a class=\"rc-restored-chip\"\n (click)=\"JumpToSourceChange(srcChange, $event)\"\n [title]=\"'Jump to source version (' + formatFullDateTime(srcChange.ChangedAt) + ')'\">\n <i class=\"fa-solid fa-link\" aria-hidden=\"true\"></i>\n Restored from {{ formatTime(srcChange.ChangedAt) }} {{ srcChange.ChangedAt ? 'on ' + (srcChange.ChangedAt | date:'mediumDate') : '' }}\n @if (srcChange.User) {\n by {{ getUserDisplayName(srcChange.User) }}\n }\n </a>\n } @else {\n <span class=\"rc-restored-chip rc-restored-chip-orphan\"\n title=\"Source version was not loaded into this view\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n Restored from earlier version\n </span>\n }\n }\n </div>\n <div class=\"rc-card-meta\">\n <div class=\"rc-card-user\">\n <div class=\"rc-avatar\">{{ getUserInitials(change.User) }}</div>\n {{ getUserDisplayName(change.User) }}\n </div>\n <span class=\"rc-card-time\" [title]=\"formatFullDateTime(change.ChangedAt)\">{{ formatTime(change.ChangedAt) }}</span>\n <span class=\"rc-card-source\" [class]=\"getSourceClass(change.Source)\">{{ change.Source }}</span>\n <span class=\"rc-card-status\" [class]=\"getStatusClass(change.Status)\">{{ change.Status }}</span>\n <i class=\"fa-solid fa-chevron-down rc-card-chevron\" aria-hidden=\"true\"></i>\n </div>\n </div>\n\n <!-- Card Body (expanded) -->\n @if (expandedItems.has(change.ID)) {\n <div class=\"rc-card-body\">\n <!-- Restore reason (when present) — Notion/Linear-style\n blockquote: a thin violet left bar + italic text,\n with a tiny \"Reason\" prefix. No box, no header,\n no large vertical footprint. Reads as a\n justification note rather than a callout. -->\n @if (getRestoreReason(change); as reason) {\n <blockquote class=\"rc-restore-reason\">\n <span class=\"rc-restore-reason-label\">Reason</span>\n <span class=\"rc-restore-reason-text\">{{ reason }}</span>\n </blockquote>\n }\n\n @if (change.Type === 'Create') {\n @if (change.FullRecordJSON) {\n @for (field of getCreatedFields(change); track field.name) {\n <div class=\"rc-field-row\">\n <div class=\"rc-field-label\">{{ field.displayName }}</div>\n <div class=\"rc-field-values\">\n <span class=\"rc-val-new\">{{ field.value }}</span>\n </div>\n </div>\n }\n }\n } @else if (change.Type === 'Delete') {\n <div class=\"rc-deletion-note\">\n <i class=\"fa-solid fa-trash\" aria-hidden=\"true\"></i>\n This record was permanently removed from the system.\n </div>\n } @else {\n <!-- Update / Snapshot / Restore: type-aware field changes -->\n @for (fc of getFieldChanges(change); track fc.field) {\n <div class=\"rc-field-row\">\n <div class=\"rc-field-label\">{{ fc.displayName }}</div>\n <div class=\"rc-field-values\">\n @if (fc.fieldType === 'boolean') {\n <div class=\"rc-bool-change\">\n <span class=\"rc-bool-dot\" [class.on]=\"fc.oldValue === 'true' || fc.oldValue === '1'\" [class.off]=\"fc.oldValue !== 'true' && fc.oldValue !== '1'\"></span>\n <span class=\"rc-bool-label old\">{{ fc.oldValue === 'true' || fc.oldValue === '1' ? 'Yes' : 'No' }}</span>\n <i class=\"fa-solid fa-arrow-right rc-val-arrow\" aria-hidden=\"true\"></i>\n <span class=\"rc-bool-dot\" [class.on]=\"fc.newValue === 'true' || fc.newValue === '1'\" [class.off]=\"fc.newValue !== 'true' && fc.newValue !== '1'\"></span>\n <span class=\"rc-bool-label new\" [class.active]=\"fc.newValue === 'true' || fc.newValue === '1'\" [class.inactive]=\"fc.newValue !== 'true' && fc.newValue !== '1'\">{{ fc.newValue === 'true' || fc.newValue === '1' ? 'Yes' : 'No' }}</span>\n </div>\n } @else if (fc.fieldType === 'date' || fc.fieldType === 'number') {\n <div class=\"rc-atomic-change\">\n <span class=\"rc-val-old\">{{ fc.oldValue || '(empty)' }}</span>\n <i class=\"fa-solid fa-arrow-right rc-val-arrow\" aria-hidden=\"true\"></i>\n <span class=\"rc-val-new\">{{ fc.newValue || '(empty)' }}</span>\n </div>\n } @else if (fc.diffHtml) {\n <div class=\"rc-text-diff\" [innerHTML]=\"fc.diffHtml\"></div>\n } @else {\n <div class=\"rc-atomic-change\">\n <span class=\"rc-val-old\">{{ fc.oldValue || '(empty)' }}</span>\n <i class=\"fa-solid fa-arrow-right rc-val-arrow\" aria-hidden=\"true\"></i>\n <span class=\"rc-val-new\">{{ fc.newValue || '(empty)' }}</span>\n </div>\n }\n </div>\n </div>\n }\n }\n\n @if (change.Comments) {\n <div class=\"rc-comments\">\n <i class=\"fa-solid fa-comment\" aria-hidden=\"true\"></i>\n {{ change.Comments }}\n </div>\n }\n\n @if (change.ErrorLog) {\n <div class=\"rc-errors\">\n <i class=\"fa-solid fa-exclamation-triangle\" aria-hidden=\"true\"></i>\n <pre class=\"rc-error-log\">{{ change.ErrorLog }}</pre>\n </div>\n }\n\n <!-- Restore action: shown for Update, Create, and Snapshot rows.\n Hidden on Delete rows (handled via the Recycle Bin path)\n and on the most recent change (restoring to current state is a no-op). -->\n @if (AllowRestore && change.Type !== 'Delete' && !isMostRecentChange(change)) {\n <div class=\"rc-restore-action\">\n <button class=\"rc-restore-btn\"\n (click)=\"OnRestoreVersion(change, $event)\"\n title=\"Restore the entire record to its state at this version\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n Restore record to this version\n </button>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n }\n </div>\n }\n </div>\n }\n\n <!-- Restore preview slide-in (reusable component) -->\n <mj-restore-preview-panel\n [Visible]=\"RestorePreviewVisible\"\n [Mode]=\"'live'\"\n [RecordChange]=\"RestorePreviewChange\"\n [LiveRecord]=\"record\"\n (RestoreConfirmed)=\"OnRestorePanelConfirmed($event)\"\n (RestoreCancelled)=\"OnRestorePanelCancelled()\">\n </mj-restore-preview-panel>\n\n @if (ShowCreateWizard) {\n <div class=\"rc-wizard-overlay\" (click)=\"OnLabelCreateCancelled()\">\n <div class=\"rc-wizard-container\" (click)=\"$event.stopPropagation()\">\n <mj-label-create\n [PreselectedEntity]=\"record.EntityInfo\"\n [PreselectedRecordIds]=\"[record.PrimaryKey.KeyValuePairs[0].Value]\"\n (Created)=\"OnLabelCreated($event)\"\n (Cancel)=\"OnLabelCreateCancelled()\">\n </mj-label-create>\n </div>\n </div>\n }\n</mj-slide-panel>\n"]}
@@ -5,9 +5,10 @@ import * as i3 from "@angular/common";
5
5
  import * as i4 from "@angular/forms";
6
6
  import * as i5 from "@memberjunction/ng-shared-generic";
7
7
  import * as i6 from "@memberjunction/ng-versions";
8
+ import * as i7 from "@memberjunction/ng-ui-components";
8
9
  export declare class RecordChangesModule {
9
10
  static ɵfac: i0.ɵɵFactoryDeclaration<RecordChangesModule, never>;
10
- static ɵmod: i0.ɵɵNgModuleDeclaration<RecordChangesModule, [typeof i1.RecordChangesComponent, typeof i2.RestorePreviewPanelComponent], [typeof i3.CommonModule, typeof i4.FormsModule, typeof i5.SharedGenericModule, typeof i6.VersionsModule], [typeof i1.RecordChangesComponent, typeof i2.RestorePreviewPanelComponent]>;
11
+ static ɵmod: i0.ɵɵNgModuleDeclaration<RecordChangesModule, [typeof i1.RecordChangesComponent, typeof i2.RestorePreviewPanelComponent], [typeof i3.CommonModule, typeof i4.FormsModule, typeof i5.SharedGenericModule, typeof i6.VersionsModule, typeof i7.MjSlidePanelComponent], [typeof i1.RecordChangesComponent, typeof i2.RestorePreviewPanelComponent]>;
11
12
  static ɵinj: i0.ɵɵInjectorDeclaration<RecordChangesModule>;
12
13
  }
13
14
  //# sourceMappingURL=ng-record-changes.module.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-record-changes.module.d.ts","sourceRoot":"","sources":["../../src/lib/ng-record-changes.module.ts"],"names":[],"mappings":";;;;;;;AASA,qBAgBa,mBAAmB;yCAAnB,mBAAmB;0CAAnB,mBAAmB;0CAAnB,mBAAmB;CAAG"}
1
+ {"version":3,"file":"ng-record-changes.module.d.ts","sourceRoot":"","sources":["../../src/lib/ng-record-changes.module.ts"],"names":[],"mappings":";;;;;;;;AAUA,qBAiBa,mBAAmB;yCAAnB,mBAAmB;0CAAnB,mBAAmB;0CAAnB,mBAAmB;CAAG"}
@@ -5,6 +5,7 @@ import { RecordChangesComponent } from './ng-record-changes.component';
5
5
  import { RestorePreviewPanelComponent } from './restore-preview-panel/restore-preview-panel.component';
6
6
  import { SharedGenericModule } from '@memberjunction/ng-shared-generic';
7
7
  import { VersionsModule } from '@memberjunction/ng-versions';
8
+ import { MjSlidePanelComponent } from '@memberjunction/ng-ui-components';
8
9
  import * as i0 from "@angular/core";
9
10
  export class RecordChangesModule {
10
11
  static ɵfac = function RecordChangesModule_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RecordChangesModule)(); };
@@ -12,7 +13,8 @@ export class RecordChangesModule {
12
13
  static ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({ imports: [CommonModule,
13
14
  FormsModule,
14
15
  SharedGenericModule,
15
- VersionsModule] });
16
+ VersionsModule,
17
+ MjSlidePanelComponent] });
16
18
  }
17
19
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RecordChangesModule, [{
18
20
  type: NgModule,
@@ -25,7 +27,8 @@ export class RecordChangesModule {
25
27
  CommonModule,
26
28
  FormsModule,
27
29
  SharedGenericModule,
28
- VersionsModule
30
+ VersionsModule,
31
+ MjSlidePanelComponent
29
32
  ],
30
33
  exports: [
31
34
  RecordChangesComponent,
@@ -37,6 +40,7 @@ export class RecordChangesModule {
37
40
  RestorePreviewPanelComponent], imports: [CommonModule,
38
41
  FormsModule,
39
42
  SharedGenericModule,
40
- VersionsModule], exports: [RecordChangesComponent,
43
+ VersionsModule,
44
+ MjSlidePanelComponent], exports: [RecordChangesComponent,
41
45
  RestorePreviewPanelComponent] }); })();
42
46
  //# sourceMappingURL=ng-record-changes.module.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ng-record-changes.module.js","sourceRoot":"","sources":["../../src/lib/ng-record-changes.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yDAAyD,CAAC;AACvG,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;;AAkB7D,MAAM,OAAO,mBAAmB;6GAAnB,mBAAmB;4DAAnB,mBAAmB;gEAV5B,YAAY;YACZ,WAAW;YACX,mBAAmB;YACnB,cAAc;;iFAOL,mBAAmB;cAhB/B,QAAQ;eAAC;gBACR,YAAY,EAAE;oBACZ,sBAAsB;oBACtB,4BAA4B;iBAC7B;gBACD,OAAO,EAAE;oBACP,YAAY;oBACZ,WAAW;oBACX,mBAAmB;oBACnB,cAAc;iBACf;gBACD,OAAO,EAAE;oBACP,sBAAsB;oBACtB,4BAA4B;iBAC7B;aACF;;wFACY,mBAAmB,mBAd5B,sBAAsB;QACtB,4BAA4B,aAG5B,YAAY;QACZ,WAAW;QACX,mBAAmB;QACnB,cAAc,aAGd,sBAAsB;QACtB,4BAA4B","sourcesContent":["import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\n\nimport { RecordChangesComponent } from './ng-record-changes.component';\nimport { RestorePreviewPanelComponent } from './restore-preview-panel/restore-preview-panel.component';\nimport { SharedGenericModule } from '@memberjunction/ng-shared-generic';\nimport { VersionsModule } from '@memberjunction/ng-versions';\n\n@NgModule({\n declarations: [\n RecordChangesComponent,\n RestorePreviewPanelComponent\n ],\n imports: [\n CommonModule,\n FormsModule,\n SharedGenericModule,\n VersionsModule\n ],\n exports: [\n RecordChangesComponent,\n RestorePreviewPanelComponent\n ]\n})\nexport class RecordChangesModule {}\n"]}
1
+ {"version":3,"file":"ng-record-changes.module.js","sourceRoot":"","sources":["../../src/lib/ng-record-changes.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yDAAyD,CAAC;AACvG,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;;AAmBzE,MAAM,OAAO,mBAAmB;6GAAnB,mBAAmB;4DAAnB,mBAAmB;gEAX5B,YAAY;YACZ,WAAW;YACX,mBAAmB;YACnB,cAAc;YACd,qBAAqB;;iFAOZ,mBAAmB;cAjB/B,QAAQ;eAAC;gBACR,YAAY,EAAE;oBACZ,sBAAsB;oBACtB,4BAA4B;iBAC7B;gBACD,OAAO,EAAE;oBACP,YAAY;oBACZ,WAAW;oBACX,mBAAmB;oBACnB,cAAc;oBACd,qBAAqB;iBACtB;gBACD,OAAO,EAAE;oBACP,sBAAsB;oBACtB,4BAA4B;iBAC7B;aACF;;wFACY,mBAAmB,mBAf5B,sBAAsB;QACtB,4BAA4B,aAG5B,YAAY;QACZ,WAAW;QACX,mBAAmB;QACnB,cAAc;QACd,qBAAqB,aAGrB,sBAAsB;QACtB,4BAA4B","sourcesContent":["import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\n\nimport { RecordChangesComponent } from './ng-record-changes.component';\nimport { RestorePreviewPanelComponent } from './restore-preview-panel/restore-preview-panel.component';\nimport { SharedGenericModule } from '@memberjunction/ng-shared-generic';\nimport { VersionsModule } from '@memberjunction/ng-versions';\nimport { MjSlidePanelComponent } from '@memberjunction/ng-ui-components';\n\n@NgModule({\n declarations: [\n RecordChangesComponent,\n RestorePreviewPanelComponent\n ],\n imports: [\n CommonModule,\n FormsModule,\n SharedGenericModule,\n VersionsModule,\n MjSlidePanelComponent\n ],\n exports: [\n RecordChangesComponent,\n RestorePreviewPanelComponent\n ]\n})\nexport class RecordChangesModule {}\n"]}
@@ -3,7 +3,7 @@ import { EntityFieldTSType, } from '@memberjunction/core';
3
3
  import { BaseAngularComponent } from '@memberjunction/ng-base-types';
4
4
  import * as i0 from "@angular/core";
5
5
  import * as i1 from "@angular/forms";
6
- import * as i2 from "@memberjunction/ng-versions";
6
+ import * as i2 from "@memberjunction/ng-ui-components";
7
7
  const _forTrack0 = ($index, $item) => $item.FieldName;
8
8
  function RestorePreviewPanelComponent_Conditional_1_Conditional_12_Template(rf, ctx) { if (rf & 1) {
9
9
  i0.ɵɵelementStart(0, "span")(1, "strong");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/ng-record-changes",
3
- "version": "5.38.0",
3
+ "version": "5.40.0",
4
4
  "description": "MemberJunction: Angular dialog to show changes made to a specific individual record",
5
5
  "main": "./dist/public-api.js",
6
6
  "typings": "./dist/public-api.d.ts",
@@ -26,13 +26,14 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@angular/platform-browser": "21.1.3",
29
- "@memberjunction/core": "5.38.0",
30
- "@memberjunction/ng-base-types": "5.38.0",
31
- "@memberjunction/core-entities": "5.38.0",
32
- "@memberjunction/global": "5.38.0",
33
- "@memberjunction/ng-notifications": "5.38.0",
34
- "@memberjunction/ng-shared-generic": "5.38.0",
35
- "@memberjunction/ng-versions": "5.38.0",
29
+ "@memberjunction/core": "5.40.0",
30
+ "@memberjunction/core-entities": "5.40.0",
31
+ "@memberjunction/global": "5.40.0",
32
+ "@memberjunction/ng-base-types": "5.40.0",
33
+ "@memberjunction/ng-notifications": "5.40.0",
34
+ "@memberjunction/ng-shared-generic": "5.40.0",
35
+ "@memberjunction/ng-ui-components": "5.40.0",
36
+ "@memberjunction/ng-versions": "5.40.0",
36
37
  "diff": "8.0.3",
37
38
  "rxjs": "^7.8.2",
38
39
  "tslib": "^2.8.1"