@memberjunction/ng-record-changes 5.27.1 → 5.28.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.
@@ -0,0 +1,748 @@
1
+ import { Component, ChangeDetectionStrategy, EventEmitter, Input, Output, ViewEncapsulation, } from '@angular/core';
2
+ import { EntityFieldTSType, Metadata, } from '@memberjunction/core';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@angular/forms";
5
+ import * as i2 from "@memberjunction/ng-versions";
6
+ const _forTrack0 = ($index, $item) => $item.FieldName;
7
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_12_Template(rf, ctx) { if (rf & 1) {
8
+ i0.ɵɵelementStart(0, "span")(1, "strong");
9
+ i0.ɵɵtext(2, "By:");
10
+ i0.ɵɵelementEnd();
11
+ i0.ɵɵtext(3);
12
+ i0.ɵɵelementEnd();
13
+ } if (rf & 2) {
14
+ const ctx_r1 = i0.ɵɵnextContext(2);
15
+ i0.ɵɵadvance(3);
16
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.VersionUser);
17
+ } }
18
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_13_Template(rf, ctx) { if (rf & 1) {
19
+ i0.ɵɵelementStart(0, "div", 8);
20
+ i0.ɵɵelement(1, "i", 20);
21
+ i0.ɵɵelementStart(2, "span");
22
+ i0.ɵɵtext(3);
23
+ i0.ɵɵelementEnd()();
24
+ } if (rf & 2) {
25
+ const ctx_r1 = i0.ɵɵnextContext(2);
26
+ i0.ɵɵadvance(3);
27
+ i0.ɵɵtextInterpolate2("", ctx_r1.DriftCount, " field", ctx_r1.DriftCount === 1 ? "" : "s", " from this snapshot no longer exist on the entity and will be skipped.");
28
+ } }
29
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_14_Template(rf, ctx) { if (rf & 1) {
30
+ i0.ɵɵelementStart(0, "div", 9);
31
+ i0.ɵɵelement(1, "i", 21);
32
+ i0.ɵɵelementStart(2, "p");
33
+ i0.ɵɵtext(3, "No fields could be parsed from this snapshot.");
34
+ i0.ɵɵelementEnd()();
35
+ } }
36
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_15_Template(rf, ctx) { if (rf & 1) {
37
+ const _r3 = i0.ɵɵgetCurrentView();
38
+ i0.ɵɵelementStart(0, "div", 10)(1, "span", 22);
39
+ i0.ɵɵtext(2);
40
+ i0.ɵɵelementEnd();
41
+ i0.ɵɵelementStart(3, "div", 23)(4, "button", 24);
42
+ i0.ɵɵlistener("click", function RestorePreviewPanelComponent_Conditional_1_Conditional_15_Template_button_click_4_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.SelectAll()); });
43
+ i0.ɵɵtext(5, "Select all changed");
44
+ i0.ɵɵelementEnd();
45
+ i0.ɵɵelementStart(6, "span", 25);
46
+ i0.ɵɵtext(7, "\u00B7");
47
+ i0.ɵɵelementEnd();
48
+ i0.ɵɵelementStart(8, "button", 24);
49
+ i0.ɵɵlistener("click", function RestorePreviewPanelComponent_Conditional_1_Conditional_15_Template_button_click_8_listener() { i0.ɵɵrestoreView(_r3); const ctx_r1 = i0.ɵɵnextContext(2); return i0.ɵɵresetView(ctx_r1.DeselectAll()); });
50
+ i0.ɵɵtext(9, "Deselect all");
51
+ i0.ɵɵelementEnd()()();
52
+ } if (rf & 2) {
53
+ const ctx_r1 = i0.ɵɵnextContext(2);
54
+ i0.ɵɵadvance(2);
55
+ i0.ɵɵtextInterpolate2("", ctx_r1.ChangedCount, " field", ctx_r1.ChangedCount === 1 ? "" : "s", " differ from current");
56
+ i0.ɵɵadvance(2);
57
+ i0.ɵɵproperty("disabled", ctx_r1.IsRestoring);
58
+ i0.ɵɵadvance(4);
59
+ i0.ɵɵproperty("disabled", ctx_r1.IsRestoring);
60
+ } }
61
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_Conditional_7_Template(rf, ctx) { if (rf & 1) {
62
+ i0.ɵɵelementStart(0, "th", 33);
63
+ i0.ɵɵtext(1, "Current Value");
64
+ i0.ɵɵelementEnd();
65
+ i0.ɵɵelementStart(2, "th", 34);
66
+ i0.ɵɵtext(3, "Restore To");
67
+ i0.ɵɵelementEnd();
68
+ } }
69
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_Conditional_8_Template(rf, ctx) { if (rf & 1) {
70
+ i0.ɵɵelementStart(0, "th", 30);
71
+ i0.ɵɵtext(1, "Will be created with");
72
+ i0.ɵɵelementEnd();
73
+ } }
74
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_3_Template(rf, ctx) { if (rf & 1) {
75
+ i0.ɵɵelement(0, "i", 37);
76
+ } }
77
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_9_Template(rf, ctx) { if (rf & 1) {
78
+ i0.ɵɵelementStart(0, "td", 33);
79
+ i0.ɵɵtext(1);
80
+ i0.ɵɵelementEnd();
81
+ i0.ɵɵelementStart(2, "td", 34);
82
+ i0.ɵɵtext(3);
83
+ i0.ɵɵelementEnd();
84
+ } if (rf & 2) {
85
+ const row_r5 = i0.ɵɵnextContext(2).$implicit;
86
+ i0.ɵɵclassProp("rpp-empty-cell", !row_r5.CurrentValue);
87
+ i0.ɵɵadvance();
88
+ i0.ɵɵtextInterpolate1(" ", row_r5.CurrentValue || "(empty)", " ");
89
+ i0.ɵɵadvance();
90
+ i0.ɵɵclassProp("rpp-empty-cell", !row_r5.RestoreValue);
91
+ i0.ɵɵadvance();
92
+ i0.ɵɵtextInterpolate1(" ", row_r5.RestoreValue || "(empty)", " ");
93
+ } }
94
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_10_Template(rf, ctx) { if (rf & 1) {
95
+ i0.ɵɵelementStart(0, "td", 30);
96
+ i0.ɵɵtext(1);
97
+ i0.ɵɵelementEnd();
98
+ } if (rf & 2) {
99
+ const row_r5 = i0.ɵɵnextContext(2).$implicit;
100
+ i0.ɵɵclassProp("rpp-empty-cell", !row_r5.RestoreValue);
101
+ i0.ɵɵadvance();
102
+ i0.ɵɵtextInterpolate1(" ", row_r5.RestoreValue || "(empty)", " ");
103
+ } }
104
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_12_Template(rf, ctx) { if (rf & 1) {
105
+ i0.ɵɵelement(0, "i", 41);
106
+ } }
107
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_13_Template(rf, ctx) { if (rf & 1) {
108
+ i0.ɵɵelement(0, "i", 42);
109
+ } }
110
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_14_Template(rf, ctx) { if (rf & 1) {
111
+ i0.ɵɵelement(0, "i", 43);
112
+ } }
113
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_15_Template(rf, ctx) { if (rf & 1) {
114
+ i0.ɵɵelement(0, "i", 44);
115
+ } }
116
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Template(rf, ctx) { if (rf & 1) {
117
+ const _r4 = i0.ɵɵgetCurrentView();
118
+ i0.ɵɵelementStart(0, "tr")(1, "td", 28)(2, "button", 36);
119
+ i0.ɵɵlistener("click", function RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Template_button_click_2_listener() { i0.ɵɵrestoreView(_r4); const row_r5 = i0.ɵɵnextContext().$implicit; const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ToggleRow(row_r5)); });
120
+ i0.ɵɵconditionalCreate(3, RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_3_Template, 1, 0, "i", 37);
121
+ i0.ɵɵelementEnd()();
122
+ i0.ɵɵelementStart(4, "td", 29)(5, "div", 38);
123
+ i0.ɵɵtext(6);
124
+ i0.ɵɵelementEnd();
125
+ i0.ɵɵelementStart(7, "div", 39);
126
+ i0.ɵɵtext(8);
127
+ i0.ɵɵelementEnd()();
128
+ i0.ɵɵconditionalCreate(9, RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_9_Template, 4, 6)(10, RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_10_Template, 2, 3, "td", 40);
129
+ i0.ɵɵelementStart(11, "td", 31);
130
+ i0.ɵɵconditionalCreate(12, RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_12_Template, 1, 0, "i", 41)(13, RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_13_Template, 1, 0, "i", 42)(14, RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_14_Template, 1, 0, "i", 43)(15, RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Conditional_15_Template, 1, 0, "i", 44);
131
+ i0.ɵɵelementEnd()();
132
+ } if (rf & 2) {
133
+ const row_r5 = i0.ɵɵnextContext().$implicit;
134
+ const ctx_r1 = i0.ɵɵnextContext(3);
135
+ i0.ɵɵclassProp("rpp-row-changed", row_r5.IsChanged)("rpp-row-unchanged", !row_r5.IsChanged)("rpp-row-immutable", row_r5.IsImmutable)("rpp-row-drift", row_r5.IsMissingInSchema);
136
+ i0.ɵɵadvance(2);
137
+ i0.ɵɵclassProp("checked", row_r5.Selected)("disabled", row_r5.IsImmutable || row_r5.IsMissingInSchema);
138
+ i0.ɵɵproperty("disabled", row_r5.IsImmutable || row_r5.IsMissingInSchema || ctx_r1.IsRestoring);
139
+ i0.ɵɵattribute("aria-label", "Toggle " + row_r5.DisplayName);
140
+ i0.ɵɵadvance();
141
+ i0.ɵɵconditional(row_r5.Selected ? 3 : -1);
142
+ i0.ɵɵadvance(3);
143
+ i0.ɵɵtextInterpolate(row_r5.DisplayName);
144
+ i0.ɵɵadvance(2);
145
+ i0.ɵɵtextInterpolate(row_r5.FieldName);
146
+ i0.ɵɵadvance();
147
+ i0.ɵɵconditional(ctx_r1.Mode === "live" ? 9 : 10);
148
+ i0.ɵɵadvance(3);
149
+ i0.ɵɵconditional(row_r5.IsMissingInSchema ? 12 : row_r5.IsImmutable ? 13 : row_r5.IsChanged ? 14 : 15);
150
+ } }
151
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Template(rf, ctx) { if (rf & 1) {
152
+ i0.ɵɵconditionalCreate(0, RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Conditional_0_Template, 16, 19, "tr", 35);
153
+ } if (rf & 2) {
154
+ const row_r5 = ctx.$implicit;
155
+ const ctx_r1 = i0.ɵɵnextContext(3);
156
+ i0.ɵɵconditional(row_r5.IsChanged || ctx_r1.ShowUnchanged ? 0 : -1);
157
+ } }
158
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_Conditional_13_Template(rf, ctx) { if (rf & 1) {
159
+ const _r6 = i0.ɵɵgetCurrentView();
160
+ i0.ɵɵelementStart(0, "button", 45);
161
+ i0.ɵɵlistener("click", function RestorePreviewPanelComponent_Conditional_1_Conditional_16_Conditional_13_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r1 = i0.ɵɵnextContext(3); return i0.ɵɵresetView(ctx_r1.ToggleUnchanged()); });
162
+ i0.ɵɵelement(1, "i", 46);
163
+ i0.ɵɵelementStart(2, "span");
164
+ i0.ɵɵtext(3);
165
+ i0.ɵɵelementEnd()();
166
+ } if (rf & 2) {
167
+ const ctx_r1 = i0.ɵɵnextContext(3);
168
+ i0.ɵɵadvance();
169
+ i0.ɵɵclassProp("fa-chevron-right", !ctx_r1.ShowUnchanged)("fa-chevron-down", ctx_r1.ShowUnchanged);
170
+ i0.ɵɵadvance(2);
171
+ i0.ɵɵtextInterpolate3("", ctx_r1.ShowUnchanged ? "Hide" : "Show", " ", ctx_r1.UnchangedCount, " unchanged field", ctx_r1.UnchangedCount === 1 ? "" : "s");
172
+ } }
173
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_16_Template(rf, ctx) { if (rf & 1) {
174
+ i0.ɵɵelementStart(0, "div", 26)(1, "table", 27)(2, "thead")(3, "tr");
175
+ i0.ɵɵelement(4, "th", 28);
176
+ i0.ɵɵelementStart(5, "th", 29);
177
+ i0.ɵɵtext(6, "Field");
178
+ i0.ɵɵelementEnd();
179
+ i0.ɵɵconditionalCreate(7, RestorePreviewPanelComponent_Conditional_1_Conditional_16_Conditional_7_Template, 4, 0)(8, RestorePreviewPanelComponent_Conditional_1_Conditional_16_Conditional_8_Template, 2, 0, "th", 30);
180
+ i0.ɵɵelement(9, "th", 31);
181
+ i0.ɵɵelementEnd()();
182
+ i0.ɵɵelementStart(10, "tbody");
183
+ i0.ɵɵrepeaterCreate(11, RestorePreviewPanelComponent_Conditional_1_Conditional_16_For_12_Template, 1, 1, null, null, _forTrack0);
184
+ i0.ɵɵelementEnd()()();
185
+ i0.ɵɵconditionalCreate(13, RestorePreviewPanelComponent_Conditional_1_Conditional_16_Conditional_13_Template, 4, 7, "button", 32);
186
+ } if (rf & 2) {
187
+ const ctx_r1 = i0.ɵɵnextContext(2);
188
+ i0.ɵɵadvance(7);
189
+ i0.ɵɵconditional(ctx_r1.Mode === "live" ? 7 : 8);
190
+ i0.ɵɵadvance(4);
191
+ i0.ɵɵrepeater(ctx_r1.Rows);
192
+ i0.ɵɵadvance(2);
193
+ i0.ɵɵconditional(ctx_r1.UnchangedCount > 0 && ctx_r1.Mode === "live" ? 13 : -1);
194
+ } }
195
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_17_Conditional_3_Template(rf, ctx) { if (rf & 1) {
196
+ i0.ɵɵelementStart(0, "span", 48);
197
+ i0.ɵɵtext(1, "*");
198
+ i0.ɵɵelementEnd();
199
+ } }
200
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_17_Conditional_4_Template(rf, ctx) { if (rf & 1) {
201
+ i0.ɵɵelementStart(0, "span", 49);
202
+ i0.ɵɵtext(1, "(optional)");
203
+ i0.ɵɵelementEnd();
204
+ } }
205
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_17_Template(rf, ctx) { if (rf & 1) {
206
+ const _r7 = i0.ɵɵgetCurrentView();
207
+ i0.ɵɵelementStart(0, "div", 11)(1, "label", 47);
208
+ i0.ɵɵtext(2, " Reason for restore ");
209
+ i0.ɵɵconditionalCreate(3, RestorePreviewPanelComponent_Conditional_1_Conditional_17_Conditional_3_Template, 2, 0, "span", 48)(4, RestorePreviewPanelComponent_Conditional_1_Conditional_17_Conditional_4_Template, 2, 0, "span", 49);
210
+ i0.ɵɵelementEnd();
211
+ i0.ɵɵelementStart(5, "textarea", 50);
212
+ i0.ɵɵtwoWayListener("ngModelChange", function RestorePreviewPanelComponent_Conditional_1_Conditional_17_Template_textarea_ngModelChange_5_listener($event) { i0.ɵɵrestoreView(_r7); const ctx_r1 = i0.ɵɵnextContext(2); i0.ɵɵtwoWayBindingSet(ctx_r1.Reason, $event) || (ctx_r1.Reason = $event); return i0.ɵɵresetView($event); });
213
+ i0.ɵɵelementEnd()();
214
+ } if (rf & 2) {
215
+ const ctx_r1 = i0.ɵɵnextContext(2);
216
+ i0.ɵɵadvance(3);
217
+ i0.ɵɵconditional(ctx_r1.RequireReason ? 3 : 4);
218
+ i0.ɵɵadvance(2);
219
+ i0.ɵɵtwoWayProperty("ngModel", ctx_r1.Reason);
220
+ i0.ɵɵproperty("disabled", ctx_r1.IsRestoring);
221
+ } }
222
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_21_Template(rf, ctx) { if (rf & 1) {
223
+ i0.ɵɵelementStart(0, "span");
224
+ i0.ɵɵtext(1, "A snapshot of the current state is saved automatically before the restore.");
225
+ i0.ɵɵelementEnd();
226
+ } }
227
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_22_Template(rf, ctx) { if (rf & 1) {
228
+ i0.ɵɵelementStart(0, "span");
229
+ i0.ɵɵtext(1, "A new \"Created\" entry will be added to this record's history, linked back to the original deletion.");
230
+ i0.ɵɵelementEnd();
231
+ } }
232
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_25_Template(rf, ctx) { if (rf & 1) {
233
+ i0.ɵɵelement(0, "i", 17);
234
+ } }
235
+ function RestorePreviewPanelComponent_Conditional_1_Conditional_26_Template(rf, ctx) { if (rf & 1) {
236
+ i0.ɵɵelement(0, "i", 18);
237
+ } }
238
+ function RestorePreviewPanelComponent_Conditional_1_Template(rf, ctx) { if (rf & 1) {
239
+ const _r1 = i0.ɵɵgetCurrentView();
240
+ i0.ɵɵelementStart(0, "div", 1)(1, "div", 2)(2, "div", 3);
241
+ i0.ɵɵelement(3, "i", 4);
242
+ i0.ɵɵelementEnd();
243
+ i0.ɵɵelementStart(4, "div", 5)(5, "div", 6);
244
+ i0.ɵɵtext(6);
245
+ i0.ɵɵelementEnd();
246
+ i0.ɵɵelementStart(7, "div", 7)(8, "span")(9, "strong");
247
+ i0.ɵɵtext(10, "Version:");
248
+ i0.ɵɵelementEnd();
249
+ i0.ɵɵtext(11);
250
+ i0.ɵɵelementEnd();
251
+ i0.ɵɵconditionalCreate(12, RestorePreviewPanelComponent_Conditional_1_Conditional_12_Template, 4, 1, "span");
252
+ i0.ɵɵelementEnd()()();
253
+ i0.ɵɵconditionalCreate(13, RestorePreviewPanelComponent_Conditional_1_Conditional_13_Template, 4, 2, "div", 8);
254
+ i0.ɵɵconditionalCreate(14, RestorePreviewPanelComponent_Conditional_1_Conditional_14_Template, 4, 0, "div", 9);
255
+ i0.ɵɵconditionalCreate(15, RestorePreviewPanelComponent_Conditional_1_Conditional_15_Template, 10, 4, "div", 10);
256
+ i0.ɵɵconditionalCreate(16, RestorePreviewPanelComponent_Conditional_1_Conditional_16_Template, 14, 2);
257
+ i0.ɵɵconditionalCreate(17, RestorePreviewPanelComponent_Conditional_1_Conditional_17_Template, 6, 3, "div", 11);
258
+ i0.ɵɵelementEnd();
259
+ i0.ɵɵelementStart(18, "div", 12)(19, "div", 13);
260
+ i0.ɵɵelement(20, "i", 14);
261
+ i0.ɵɵconditionalCreate(21, RestorePreviewPanelComponent_Conditional_1_Conditional_21_Template, 2, 0, "span")(22, RestorePreviewPanelComponent_Conditional_1_Conditional_22_Template, 2, 0, "span");
262
+ i0.ɵɵelementEnd();
263
+ i0.ɵɵelementStart(23, "div", 15)(24, "button", 16);
264
+ i0.ɵɵlistener("click", function RestorePreviewPanelComponent_Conditional_1_Template_button_click_24_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.ConfirmRestore()); });
265
+ i0.ɵɵconditionalCreate(25, RestorePreviewPanelComponent_Conditional_1_Conditional_25_Template, 1, 0, "i", 17)(26, RestorePreviewPanelComponent_Conditional_1_Conditional_26_Template, 1, 0, "i", 18);
266
+ i0.ɵɵtext(27);
267
+ i0.ɵɵelementEnd();
268
+ i0.ɵɵelementStart(28, "button", 19);
269
+ i0.ɵɵlistener("click", function RestorePreviewPanelComponent_Conditional_1_Template_button_click_28_listener() { i0.ɵɵrestoreView(_r1); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.Cancel()); });
270
+ i0.ɵɵtext(29, "Cancel");
271
+ i0.ɵɵelementEnd()()();
272
+ } if (rf & 2) {
273
+ const ctx_r1 = i0.ɵɵnextContext();
274
+ i0.ɵɵadvance(6);
275
+ i0.ɵɵtextInterpolate(ctx_r1.HeaderTitle);
276
+ i0.ɵɵadvance(5);
277
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.formatTimestamp(ctx_r1.VersionTimestamp));
278
+ i0.ɵɵadvance();
279
+ i0.ɵɵconditional(ctx_r1.VersionUser ? 12 : -1);
280
+ i0.ɵɵadvance();
281
+ i0.ɵɵconditional(ctx_r1.DriftCount > 0 ? 13 : -1);
282
+ i0.ɵɵadvance();
283
+ i0.ɵɵconditional(ctx_r1.Rows.length === 0 ? 14 : -1);
284
+ i0.ɵɵadvance();
285
+ i0.ɵɵconditional(ctx_r1.Rows.length > 0 && ctx_r1.Mode !== "undelete" ? 15 : -1);
286
+ i0.ɵɵadvance();
287
+ i0.ɵɵconditional(ctx_r1.Rows.length > 0 ? 16 : -1);
288
+ i0.ɵɵadvance();
289
+ i0.ɵɵconditional(!ctx_r1.HideReason && ctx_r1.Rows.length > 0 ? 17 : -1);
290
+ i0.ɵɵadvance(4);
291
+ i0.ɵɵconditional(ctx_r1.Mode === "live" ? 21 : 22);
292
+ i0.ɵɵadvance(3);
293
+ i0.ɵɵproperty("disabled", ctx_r1.IsRestoreDisabled);
294
+ i0.ɵɵadvance();
295
+ i0.ɵɵconditional(ctx_r1.IsRestoring ? 25 : 26);
296
+ i0.ɵɵadvance(2);
297
+ i0.ɵɵtextInterpolate1(" ", ctx_r1.RestoreButtonLabel, " ");
298
+ i0.ɵɵadvance();
299
+ i0.ɵɵproperty("disabled", ctx_r1.IsRestoring);
300
+ } }
301
+ /**
302
+ * Reusable slide-in panel that previews a restore operation against a
303
+ * historical {@link MJRecordChangeEntity} and lets the user confirm with
304
+ * field-level granularity.
305
+ *
306
+ * This component is rendered by both:
307
+ * - The Record Changes timeline (for restoring a live record from any past
308
+ * change row)
309
+ * - The Recycle Bin (for re-creating a hard-deleted record from its delete
310
+ * snapshot)
311
+ *
312
+ * It does NOT perform the save itself — the host component receives a
313
+ * {@link RestoreCommitEvent} with the selected field values and is
314
+ * responsible for applying them to a BaseEntity, setting the restore
315
+ * context, and calling Save(). This keeps the component purely
316
+ * presentational and reusable in any context.
317
+ *
318
+ * ### Semantic correctness
319
+ *
320
+ * The preview compares the **full snapshot** captured in the source
321
+ * change's `FullRecordJSON` to the current live record (or to nothing in
322
+ * un-delete mode). It does NOT roll back a single delta — restoring `v2`
323
+ * means "make the record look like it did at v2", not "undo v3's changes".
324
+ *
325
+ * @example Live restore from the timeline
326
+ * <mj-restore-preview-panel
327
+ * [Visible]="showPreview"
328
+ * [Mode]="'live'"
329
+ * [RecordChange]="selectedChange"
330
+ * [LiveRecord]="record"
331
+ * (RestoreConfirmed)="onRestoreConfirmed($event)"
332
+ * (RestoreCancelled)="showPreview = false">
333
+ * </mj-restore-preview-panel>
334
+ *
335
+ * @example Un-delete from the Recycle Bin
336
+ * <mj-restore-preview-panel
337
+ * [Visible]="showPreview"
338
+ * [Mode]="'undelete'"
339
+ * [RecordChange]="deletedChange"
340
+ * [EntityName]="'Customers'"
341
+ * (RestoreConfirmed)="onRecreate($event)"
342
+ * (RestoreCancelled)="showPreview = false">
343
+ * </mj-restore-preview-panel>
344
+ */
345
+ export class RestorePreviewPanelComponent {
346
+ cdr;
347
+ // ─── Inputs ─────────────────────────────────────────────────────
348
+ /**
349
+ * Controls panel visibility. Setting to true opens the slide-in;
350
+ * setting to false closes it.
351
+ */
352
+ Visible = false;
353
+ /**
354
+ * Operating mode — `'live'` for restoring an existing record from a
355
+ * snapshot, `'undelete'` for re-creating a hard-deleted record.
356
+ */
357
+ Mode = 'live';
358
+ /**
359
+ * The historical RecordChange row whose state will be restored. Required.
360
+ * The component reads `FullRecordJSON` from this entity to determine the
361
+ * target state. The change's `Type` does not matter — `Create`,
362
+ * `Update`, `Snapshot`, and `Delete` are all valid restore sources.
363
+ */
364
+ _recordChange = null;
365
+ set RecordChange(value) {
366
+ this._recordChange = value;
367
+ if (this.isInitialized)
368
+ this.rebuildRows();
369
+ }
370
+ get RecordChange() {
371
+ return this._recordChange;
372
+ }
373
+ /**
374
+ * The current live record to diff against. Required in `'live'` mode,
375
+ * ignored in `'undelete'` mode (since the live record no longer exists).
376
+ */
377
+ _liveRecord = null;
378
+ set LiveRecord(value) {
379
+ this._liveRecord = value;
380
+ if (this.isInitialized)
381
+ this.rebuildRows();
382
+ }
383
+ get LiveRecord() {
384
+ return this._liveRecord;
385
+ }
386
+ /**
387
+ * The entity name. Required in `'undelete'` mode (since there's no live
388
+ * record to read it from). In `'live'` mode it can be omitted and is
389
+ * inferred from the LiveRecord.
390
+ */
391
+ EntityName = null;
392
+ /**
393
+ * When true, the Restore button is disabled until the user enters a
394
+ * non-empty reason. Useful for regulated environments where every
395
+ * reversal needs justification. Default: false.
396
+ */
397
+ RequireReason = false;
398
+ /**
399
+ * When true, hides the optional reason text area entirely. Default: false.
400
+ */
401
+ HideReason = false;
402
+ // ─── Outputs ────────────────────────────────────────────────────
403
+ /**
404
+ * Cancelable event fired when the user clicks Restore but before
405
+ * {@link RestoreConfirmed} emits. Consumers can set `cancel = true` on
406
+ * the event arg to abort the operation — useful for custom approval
407
+ * workflows or for taking over the save themselves.
408
+ */
409
+ BeforeRestoreCommit = new EventEmitter();
410
+ /**
411
+ * Emitted after the user confirms the restore (and BeforeRestoreCommit
412
+ * was not cancelled). The host is responsible for applying the field
413
+ * values to a BaseEntity, calling SetRestoreContext, and invoking Save().
414
+ */
415
+ RestoreConfirmed = new EventEmitter();
416
+ /**
417
+ * Emitted when the user cancels the preview without restoring.
418
+ */
419
+ RestoreCancelled = new EventEmitter();
420
+ // ─── Public state (read by template) ────────────────────────────
421
+ Rows = [];
422
+ Reason = '';
423
+ IsRestoring = false;
424
+ ShowUnchanged = false;
425
+ /** Number of rows where the current value differs from the snapshot. */
426
+ ChangedCount = 0;
427
+ /** Number of rows that are checked (will be applied on restore). */
428
+ SelectedCount = 0;
429
+ /** Number of rows the schema has dropped or renamed since the snapshot. */
430
+ DriftCount = 0;
431
+ isInitialized = false;
432
+ resolvedEntityInfo = null;
433
+ constructor(cdr) {
434
+ this.cdr = cdr;
435
+ }
436
+ ngOnInit() {
437
+ this.isInitialized = true;
438
+ this.rebuildRows();
439
+ }
440
+ // ─── Public methods ─────────────────────────────────────────────
441
+ /**
442
+ * Toggles whether unchanged rows are visible in the table. When false
443
+ * (default), only rows where current ≠ snapshot are shown.
444
+ */
445
+ ToggleUnchanged() {
446
+ this.ShowUnchanged = !this.ShowUnchanged;
447
+ this.cdr.markForCheck();
448
+ }
449
+ /**
450
+ * Toggles whether a single row is selected for restore. Updates the
451
+ * SelectedCount in real time so the primary button label reflects it.
452
+ */
453
+ ToggleRow(row) {
454
+ if (row.IsImmutable || row.IsMissingInSchema)
455
+ return;
456
+ row.Selected = !row.Selected;
457
+ this.recountSelected();
458
+ this.cdr.markForCheck();
459
+ }
460
+ /**
461
+ * Selects every row that can be selected (skips immutable / drifted).
462
+ */
463
+ SelectAll() {
464
+ for (const row of this.Rows) {
465
+ if (!row.IsImmutable && !row.IsMissingInSchema)
466
+ row.Selected = true;
467
+ }
468
+ this.recountSelected();
469
+ this.cdr.markForCheck();
470
+ }
471
+ /**
472
+ * Deselects every row in the preview.
473
+ */
474
+ DeselectAll() {
475
+ for (const row of this.Rows)
476
+ row.Selected = false;
477
+ this.recountSelected();
478
+ this.cdr.markForCheck();
479
+ }
480
+ /**
481
+ * User clicked Restore — fire BeforeRestoreCommit (cancelable), then
482
+ * RestoreConfirmed if not cancelled.
483
+ */
484
+ ConfirmRestore() {
485
+ if (!this._recordChange)
486
+ return;
487
+ if (this.IsRestoreDisabled)
488
+ return;
489
+ const selected = this.Rows.filter(r => r.Selected && !r.IsMissingInSchema && !r.IsImmutable);
490
+ const reason = this.Reason.trim() ? this.Reason.trim() : null;
491
+ const beforeEvent = {
492
+ cancel: false,
493
+ SelectedFieldNames: selected.map(r => r.FieldName),
494
+ AllRows: this.Rows.slice(),
495
+ SourceChangeID: this._recordChange.ID,
496
+ Reason: reason,
497
+ Mode: this.Mode,
498
+ };
499
+ this.BeforeRestoreCommit.emit(beforeEvent);
500
+ if (beforeEvent.cancel)
501
+ return;
502
+ this.IsRestoring = true;
503
+ this.cdr.markForCheck();
504
+ const commitEvent = {
505
+ SourceChangeID: this._recordChange.ID,
506
+ Reason: reason,
507
+ FieldValues: selected.map(r => ({ FieldName: r.FieldName, Value: r.RawRestoreValue })),
508
+ AllRows: this.Rows.slice(),
509
+ Mode: this.Mode,
510
+ };
511
+ this.RestoreConfirmed.emit(commitEvent);
512
+ }
513
+ /**
514
+ * User cancelled the preview. Resets state and emits RestoreCancelled.
515
+ */
516
+ Cancel() {
517
+ this.RestoreCancelled.emit();
518
+ }
519
+ /**
520
+ * Resets internal state — useful after a save completes so the panel
521
+ * can be reopened cleanly. Called by the host component when needed.
522
+ */
523
+ Reset() {
524
+ this.Reason = '';
525
+ this.IsRestoring = false;
526
+ this.ShowUnchanged = false;
527
+ this.rebuildRows();
528
+ }
529
+ // ─── Computed getters (template) ────────────────────────────────
530
+ get IsRestoreDisabled() {
531
+ if (this.IsRestoring)
532
+ return true;
533
+ if (this.SelectedCount === 0)
534
+ return true;
535
+ if (this.RequireReason && this.Reason.trim().length === 0)
536
+ return true;
537
+ return false;
538
+ }
539
+ get RestoreButtonLabel() {
540
+ if (this.IsRestoring)
541
+ return 'Restoring…';
542
+ if (this.Mode === 'undelete') {
543
+ return this.SelectedCount > 0 ? `Re-create (${this.SelectedCount} field${this.SelectedCount === 1 ? '' : 's'})` : 'Re-create';
544
+ }
545
+ return this.SelectedCount > 0 ? `Restore (${this.SelectedCount} field${this.SelectedCount === 1 ? '' : 's'})` : 'Restore';
546
+ }
547
+ get HeaderTitle() {
548
+ return this.Mode === 'undelete' ? 'Re-create from snapshot' : 'Restore record to this version';
549
+ }
550
+ get VersionTimestamp() {
551
+ return this._recordChange?.ChangedAt ?? null;
552
+ }
553
+ get VersionUser() {
554
+ return this._recordChange?.User ?? '';
555
+ }
556
+ get UnchangedCount() {
557
+ return this.Rows.length - this.ChangedCount;
558
+ }
559
+ // ─── Internal: row building ─────────────────────────────────────
560
+ /**
561
+ * Rebuilds the Rows array from the current RecordChange + LiveRecord.
562
+ * Idempotent and cheap — safe to call from input setters.
563
+ */
564
+ rebuildRows() {
565
+ this.Rows = [];
566
+ this.ChangedCount = 0;
567
+ this.SelectedCount = 0;
568
+ this.DriftCount = 0;
569
+ if (!this._recordChange) {
570
+ this.cdr.markForCheck();
571
+ return;
572
+ }
573
+ const snapshot = this.parseSnapshot(this._recordChange.FullRecordJSON);
574
+ if (!snapshot) {
575
+ this.cdr.markForCheck();
576
+ return;
577
+ }
578
+ const entityInfo = this.resolveEntityInfo();
579
+ if (!entityInfo) {
580
+ this.cdr.markForCheck();
581
+ return;
582
+ }
583
+ // Build a row for every field in the snapshot. We iterate the snapshot
584
+ // (not EntityInfo.Fields) so fields that exist in the snapshot but no
585
+ // longer in the schema surface as drift warnings.
586
+ const seen = new Set();
587
+ for (const fieldName of Object.keys(snapshot)) {
588
+ seen.add(fieldName.toLowerCase());
589
+ const row = this.buildRowFromSnapshot(fieldName, snapshot[fieldName], entityInfo);
590
+ if (row)
591
+ this.Rows.push(row);
592
+ }
593
+ // Sort: changed rows first, then unchanged. Within each group, by display name.
594
+ this.Rows.sort((a, b) => {
595
+ if (a.IsChanged !== b.IsChanged)
596
+ return a.IsChanged ? -1 : 1;
597
+ return a.DisplayName.localeCompare(b.DisplayName);
598
+ });
599
+ this.ChangedCount = this.Rows.filter(r => r.IsChanged).length;
600
+ this.DriftCount = this.Rows.filter(r => r.IsMissingInSchema).length;
601
+ this.recountSelected();
602
+ this.cdr.markForCheck();
603
+ }
604
+ buildRowFromSnapshot(fieldName, snapshotValue, entityInfo) {
605
+ const field = entityInfo.Fields.find((f) => f.Name.trim().toLowerCase() === fieldName.trim().toLowerCase());
606
+ // Skip system / timestamp fields that the platform manages.
607
+ if (fieldName.startsWith('__mj_'))
608
+ return null;
609
+ const isImmutable = !!field && (field.ReadOnly || field.IsPrimaryKey);
610
+ const isMissingInSchema = !field;
611
+ const isDateField = field?.TSType === EntityFieldTSType.Date;
612
+ const formattedRestore = this.formatValue(snapshotValue, isDateField);
613
+ const formattedCurrent = this.Mode === 'undelete'
614
+ ? ''
615
+ : this.getCurrentFieldValue(fieldName, isDateField);
616
+ const isChanged = this.Mode === 'undelete'
617
+ ? snapshotValue != null && snapshotValue !== ''
618
+ : formattedCurrent !== formattedRestore;
619
+ // Default selection: pre-check changed rows that we can actually apply.
620
+ const selected = isChanged && !isImmutable && !isMissingInSchema;
621
+ return {
622
+ FieldName: fieldName,
623
+ DisplayName: field?.DisplayNameOrName ?? fieldName,
624
+ CurrentValue: formattedCurrent,
625
+ RestoreValue: formattedRestore,
626
+ RawRestoreValue: snapshotValue,
627
+ IsChanged: isChanged,
628
+ Selected: selected,
629
+ IsMissingInSchema: isMissingInSchema,
630
+ IsFKMissing: false, // Reserved for future FK-existence check
631
+ IsImmutable: isImmutable,
632
+ };
633
+ }
634
+ getCurrentFieldValue(fieldName, isDateField) {
635
+ if (!this._liveRecord)
636
+ return '';
637
+ const field = this._liveRecord.Fields.find(f => f.Name.trim().toLowerCase() === fieldName.trim().toLowerCase());
638
+ if (!field)
639
+ return '';
640
+ return this.formatValue(field.Value, isDateField);
641
+ }
642
+ parseSnapshot(json) {
643
+ if (!json)
644
+ return null;
645
+ try {
646
+ return JSON.parse(json);
647
+ }
648
+ catch {
649
+ return null;
650
+ }
651
+ }
652
+ /**
653
+ * Resolves the entity metadata. Prefers LiveRecord.EntityInfo (always
654
+ * accurate). Falls back to looking up by EntityName. Memoized.
655
+ */
656
+ resolveEntityInfo() {
657
+ if (this.resolvedEntityInfo)
658
+ return this.resolvedEntityInfo;
659
+ if (this._liveRecord?.EntityInfo) {
660
+ this.resolvedEntityInfo = this._liveRecord.EntityInfo;
661
+ return this.resolvedEntityInfo;
662
+ }
663
+ if (this.EntityName) {
664
+ const md = new Metadata();
665
+ const ei = md.Entities.find(e => e.Name.trim().toLowerCase() === this.EntityName.trim().toLowerCase());
666
+ this.resolvedEntityInfo = ei ?? null;
667
+ return this.resolvedEntityInfo;
668
+ }
669
+ return null;
670
+ }
671
+ formatValue(value, isDateField) {
672
+ if (value == null)
673
+ return '';
674
+ if (typeof value === 'object') {
675
+ const keys = Object.keys(value);
676
+ if (keys.length === 0)
677
+ return '';
678
+ return JSON.stringify(value);
679
+ }
680
+ if (isDateField && typeof value === 'string') {
681
+ const date = new Date(value);
682
+ if (!isNaN(date.getTime())) {
683
+ return new Intl.DateTimeFormat('en-US', {
684
+ month: 'short',
685
+ day: 'numeric',
686
+ year: 'numeric',
687
+ hour: 'numeric',
688
+ minute: '2-digit',
689
+ hour12: true,
690
+ }).format(date);
691
+ }
692
+ }
693
+ return String(value);
694
+ }
695
+ recountSelected() {
696
+ this.SelectedCount = this.Rows.filter(r => r.Selected).length;
697
+ }
698
+ // ─── Display helpers (template) ─────────────────────────────────
699
+ formatTimestamp(date) {
700
+ if (!date)
701
+ return '';
702
+ return new Intl.DateTimeFormat('en-US', {
703
+ year: 'numeric',
704
+ month: 'long',
705
+ day: 'numeric',
706
+ hour: 'numeric',
707
+ minute: '2-digit',
708
+ hour12: true,
709
+ }).format(new Date(date));
710
+ }
711
+ static ɵfac = function RestorePreviewPanelComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || RestorePreviewPanelComponent)(i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
712
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RestorePreviewPanelComponent, selectors: [["mj-restore-preview-panel"]], inputs: { Visible: "Visible", Mode: "Mode", RecordChange: "RecordChange", LiveRecord: "LiveRecord", EntityName: "EntityName", RequireReason: "RequireReason", HideReason: "HideReason" }, outputs: { BeforeRestoreCommit: "BeforeRestoreCommit", RestoreConfirmed: "RestoreConfirmed", RestoreCancelled: "RestoreCancelled" }, standalone: false, decls: 2, vars: 7, consts: [[3, "Closed", "Mode", "Title", "Visible", "Resizable", "MinWidthPx", "MaxWidthRatio"], [1, "rpp-container"], [1, "rpp-header"], [1, "rpp-header-icon"], ["aria-hidden", "true", 1, "fa-solid", "fa-clock-rotate-left"], [1, "rpp-header-text"], [1, "rpp-header-title"], [1, "rpp-header-meta"], [1, "rpp-banner", "rpp-banner-warning"], [1, "rpp-empty"], [1, "rpp-action-bar"], [1, "rpp-reason-section"], [1, "rpp-footer"], [1, "rpp-footer-info"], ["aria-hidden", "true", 1, "fa-solid", "fa-shield-halved"], [1, "rpp-footer-actions"], ["type", "button", 1, "rpp-btn", "rpp-btn-primary", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-spinner", "fa-spin"], ["aria-hidden", "true", 1, "fa-solid", "fa-rotate-left"], ["type", "button", 1, "rpp-btn", "rpp-btn-secondary", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-triangle-exclamation"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle-info"], [1, "rpp-action-bar-label"], [1, "rpp-action-bar-buttons"], ["type", "button", 1, "rpp-link-btn", 3, "click", "disabled"], [1, "rpp-action-bar-sep"], [1, "rpp-table-wrap"], [1, "rpp-table"], [1, "rpp-col-check"], [1, "rpp-col-field"], ["colspan", "2", 1, "rpp-col-restore"], [1, "rpp-col-flag"], ["type", "button", 1, "rpp-disclosure"], [1, "rpp-col-current"], [1, "rpp-col-restore"], [3, "rpp-row-changed", "rpp-row-unchanged", "rpp-row-immutable", "rpp-row-drift"], ["type", "button", 1, "rpp-checkbox", 3, "click", "disabled"], ["aria-hidden", "true", 1, "fa-solid", "fa-check"], [1, "rpp-field-display"], [1, "rpp-field-name"], ["colspan", "2", 1, "rpp-col-restore", 3, "rpp-empty-cell"], ["title", "This field no longer exists on the entity and will be skipped", "aria-hidden", "true", 1, "fa-solid", "fa-triangle-exclamation", "rpp-flag-drift"], ["title", "Read-only or system field \u2014 cannot be modified", "aria-hidden", "true", 1, "fa-solid", "fa-lock", "rpp-flag-immutable"], ["title", "Will be changed", "aria-hidden", "true", 1, "fa-solid", "fa-circle-exclamation", "rpp-flag-changed"], ["title", "Already matches", "aria-hidden", "true", 1, "fa-solid", "fa-check", "rpp-flag-ok"], ["type", "button", 1, "rpp-disclosure", 3, "click"], ["aria-hidden", "true", 1, "fa-solid"], ["for", "rpp-reason-input"], [1, "rpp-required"], [1, "rpp-optional"], ["id", "rpp-reason-input", "placeholder", "e.g., Reverting incorrect Q2 entries", "rows", "2", 1, "rpp-reason-textarea", 3, "ngModelChange", "ngModel", "disabled"]], template: function RestorePreviewPanelComponent_Template(rf, ctx) { if (rf & 1) {
713
+ i0.ɵɵelementStart(0, "mj-slide-panel", 0);
714
+ i0.ɵɵlistener("Closed", function RestorePreviewPanelComponent_Template_mj_slide_panel_Closed_0_listener() { return ctx.Cancel(); });
715
+ i0.ɵɵconditionalCreate(1, RestorePreviewPanelComponent_Conditional_1_Template, 30, 13);
716
+ i0.ɵɵelementEnd();
717
+ } if (rf & 2) {
718
+ i0.ɵɵproperty("Mode", "slide")("Title", ctx.HeaderTitle)("Visible", ctx.Visible)("Resizable", true)("MinWidthPx", 500)("MaxWidthRatio", 0.7);
719
+ i0.ɵɵadvance();
720
+ i0.ɵɵconditional(ctx.RecordChange ? 1 : -1);
721
+ } }, dependencies: [i1.DefaultValueAccessor, i1.NgControlStatus, i1.NgModel, i2.MjSlidePanelComponent], styles: ["/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 Preview Panel\n * Slide-in panel that previews a restore operation field-by-field.\n * All colors use --mj-* design tokens so it adapts to dark mode and\n * white-label themes.\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\u2500 */\n\n.rpp-container {\n padding: 18px 20px;\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n\n/* \u2500\u2500\u2500 Header summary \u2500\u2500\u2500 */\n\n.rpp-header {\n display: flex;\n align-items: flex-start;\n gap: 14px;\n padding-bottom: 14px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.rpp-header-icon {\n width: 38px;\n height: 38px;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n font-size: 16px;\n}\n\n.rpp-header-text {\n flex: 1;\n min-width: 0;\n}\n\n.rpp-header-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.rpp-header-meta {\n display: flex;\n flex-wrap: wrap;\n gap: 14px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.rpp-header-meta strong {\n color: var(--mj-text-secondary);\n font-weight: 500;\n margin-right: 4px;\n}\n\n/* \u2500\u2500\u2500 Banners \u2500\u2500\u2500 */\n\n.rpp-banner {\n display: flex;\n align-items: center;\n gap: 9px;\n padding: 10px 12px;\n border-radius: 8px;\n font-size: 12px;\n border: 1px solid;\n}\n\n.rpp-banner-warning {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border-color: var(--mj-status-warning-border);\n}\n\n/* \u2500\u2500\u2500 Empty state \u2500\u2500\u2500 */\n\n.rpp-empty {\n text-align: center;\n padding: 30px 20px;\n color: var(--mj-text-muted);\n}\n\n.rpp-empty i {\n font-size: 24px;\n margin-bottom: 8px;\n}\n\n.rpp-empty p {\n margin: 0;\n font-size: 13px;\n}\n\n/* \u2500\u2500\u2500 Action bar (select all / deselect all) \u2500\u2500\u2500 */\n\n.rpp-action-bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 7px;\n font-size: 12px;\n}\n\n.rpp-action-bar-label {\n color: var(--mj-text-secondary);\n font-weight: 500;\n}\n\n.rpp-action-bar-buttons {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.rpp-action-bar-sep {\n color: var(--mj-text-disabled);\n}\n\n.rpp-link-btn {\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: 2px 4px;\n border-radius: 4px;\n}\n\n.rpp-link-btn:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n\n.rpp-link-btn:disabled {\n color: var(--mj-text-disabled);\n cursor: not-allowed;\n}\n\n/* \u2500\u2500\u2500 Diff table \u2500\u2500\u2500 */\n\n.rpp-table-wrap {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.rpp-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n background: var(--mj-bg-surface);\n}\n\n.rpp-table thead th {\n text-align: left;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--mj-text-muted);\n font-weight: 600;\n}\n\n.rpp-table tbody td {\n padding: 10px 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n vertical-align: top;\n}\n\n.rpp-table tbody tr:last-child td {\n border-bottom: none;\n}\n\n.rpp-row-changed { background: var(--mj-bg-surface); }\n.rpp-row-unchanged {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n.rpp-row-immutable { opacity: 0.7; }\n.rpp-row-drift { background: color-mix(in srgb, var(--mj-status-warning) 5%, var(--mj-bg-surface)); }\n\n/* Column widths */\n.rpp-col-check { width: 36px; padding: 8px 4px 8px 12px; }\n.rpp-col-field { width: 28%; min-width: 140px; }\n.rpp-col-current,\n.rpp-col-restore { word-break: break-word; }\n.rpp-col-flag { width: 28px; text-align: right; padding-right: 12px; }\n\n/* \u2500\u2500\u2500 Field cell \u2500\u2500\u2500 */\n\n.rpp-field-display {\n font-weight: 500;\n color: var(--mj-text-primary);\n margin-bottom: 2px;\n}\n\n.rpp-field-name {\n color: var(--mj-text-disabled);\n font-size: 11px;\n font-family: ui-monospace, SFMono-Regular, Consolas, monospace;\n}\n\n.rpp-row-unchanged .rpp-field-display { color: var(--mj-text-muted); }\n\n/* \u2500\u2500\u2500 Value cells \u2500\u2500\u2500 */\n\n.rpp-col-current { color: var(--mj-text-secondary); }\n.rpp-col-restore {\n color: var(--mj-text-primary);\n font-weight: 500;\n background: linear-gradient(90deg,\n color-mix(in srgb, var(--mj-brand-primary) 6%, transparent),\n transparent 80%);\n}\n\n.rpp-empty-cell {\n color: var(--mj-text-disabled);\n font-style: italic;\n}\n\n/* \u2500\u2500\u2500 Checkbox \u2500\u2500\u2500 */\n\n.rpp-checkbox {\n width: 18px;\n height: 18px;\n border: 1.5px solid var(--mj-border-strong);\n border-radius: 4px;\n background: var(--mj-bg-surface);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n padding: 0;\n color: var(--mj-text-inverse, #fff);\n transition: background-color 0.1s, border-color 0.1s;\n}\n\n.rpp-checkbox:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n}\n\n.rpp-checkbox.checked {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.rpp-checkbox.checked i {\n font-size: 11px;\n}\n\n.rpp-checkbox.disabled,\n.rpp-checkbox:disabled {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-default);\n cursor: not-allowed;\n}\n\n/* \u2500\u2500\u2500 Flag icons \u2500\u2500\u2500 */\n\n.rpp-flag-changed { color: var(--mj-status-warning); }\n.rpp-flag-ok { color: var(--mj-text-disabled); }\n.rpp-flag-drift { color: var(--mj-status-warning); }\n.rpp-flag-immutable { color: var(--mj-text-disabled); }\n\n/* \u2500\u2500\u2500 Unchanged disclosure \u2500\u2500\u2500 */\n\n.rpp-disclosure {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n font-size: 12px;\n cursor: pointer;\n padding: 8px 4px;\n display: flex;\n align-items: center;\n gap: 8px;\n text-align: left;\n}\n\n.rpp-disclosure:hover {\n color: var(--mj-text-primary);\n}\n\n.rpp-disclosure i {\n font-size: 10px;\n width: 12px;\n}\n\n/* \u2500\u2500\u2500 Reason section \u2500\u2500\u2500 */\n\n.rpp-reason-section {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.rpp-reason-section label {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.rpp-required {\n color: var(--mj-status-error);\n margin-left: 4px;\n}\n\n.rpp-optional {\n color: var(--mj-text-disabled);\n font-weight: 400;\n margin-left: 4px;\n}\n\n.rpp-reason-textarea {\n width: 100%;\n border: 1px solid var(--mj-border-default);\n border-radius: 7px;\n padding: 8px 10px;\n font-family: inherit;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n resize: vertical;\n min-height: 50px;\n box-sizing: border-box;\n}\n\n.rpp-reason-textarea:focus {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: -1px;\n border-color: var(--mj-brand-primary);\n}\n\n.rpp-reason-textarea:disabled {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n/* \u2500\u2500\u2500 Footer \u2500\u2500\u2500 */\n\n.rpp-footer {\n position: sticky;\n bottom: 0;\n background: var(--mj-bg-surface);\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 20px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 14px;\n}\n\n.rpp-footer-info {\n display: flex;\n align-items: center;\n gap: 7px;\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.rpp-footer-info i {\n color: var(--mj-brand-primary);\n}\n\n.rpp-footer-actions {\n display: flex;\n gap: 10px;\n}\n\n.rpp-btn {\n padding: 8px 16px;\n border-radius: 7px;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n border: 1px solid transparent;\n display: inline-flex;\n align-items: center;\n gap: 7px;\n font-family: inherit;\n}\n\n.rpp-btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, #fff);\n border-color: var(--mj-brand-primary);\n}\n\n.rpp-btn-primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.rpp-btn-primary:disabled {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n border-color: var(--mj-border-default);\n cursor: not-allowed;\n}\n\n.rpp-btn-secondary {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border-color: var(--mj-border-default);\n font-weight: 500;\n}\n\n.rpp-btn-secondary:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.rpp-btn-secondary:disabled {\n color: var(--mj-text-disabled);\n cursor: not-allowed;\n}\n"], encapsulation: 2, changeDetection: 0 });
722
+ }
723
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RestorePreviewPanelComponent, [{
724
+ type: Component,
725
+ args: [{ standalone: false, selector: 'mj-restore-preview-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<mj-slide-panel\n [Mode]=\"'slide'\"\n [Title]=\"HeaderTitle\"\n [Visible]=\"Visible\"\n [Resizable]=\"true\"\n [MinWidthPx]=\"500\"\n [MaxWidthRatio]=\"0.7\"\n (Closed)=\"Cancel()\">\n\n @if (RecordChange) {\n <div class=\"rpp-container\">\n\n <!-- Header summary block -->\n <div class=\"rpp-header\">\n <div class=\"rpp-header-icon\">\n <i class=\"fa-solid fa-clock-rotate-left\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"rpp-header-text\">\n <div class=\"rpp-header-title\">{{ HeaderTitle }}</div>\n <div class=\"rpp-header-meta\">\n <span><strong>Version:</strong> {{ formatTimestamp(VersionTimestamp) }}</span>\n @if (VersionUser) {\n <span><strong>By:</strong> {{ VersionUser }}</span>\n }\n </div>\n </div>\n </div>\n\n <!-- Drift warning -->\n @if (DriftCount > 0) {\n <div class=\"rpp-banner rpp-banner-warning\">\n <i class=\"fa-solid fa-triangle-exclamation\" aria-hidden=\"true\"></i>\n <span>{{ DriftCount }} field{{ DriftCount === 1 ? '' : 's' }} from this snapshot no longer exist on the entity and will be skipped.</span>\n </div>\n }\n\n <!-- Empty state -->\n @if (Rows.length === 0) {\n <div class=\"rpp-empty\">\n <i class=\"fa-solid fa-circle-info\" aria-hidden=\"true\"></i>\n <p>No fields could be parsed from this snapshot.</p>\n </div>\n }\n\n <!-- Action bar (select all / deselect all) -->\n @if (Rows.length > 0 && Mode !== 'undelete') {\n <div class=\"rpp-action-bar\">\n <span class=\"rpp-action-bar-label\">{{ ChangedCount }} field{{ ChangedCount === 1 ? '' : 's' }} differ from current</span>\n <div class=\"rpp-action-bar-buttons\">\n <button class=\"rpp-link-btn\" type=\"button\" (click)=\"SelectAll()\" [disabled]=\"IsRestoring\">Select all changed</button>\n <span class=\"rpp-action-bar-sep\">\u00B7</span>\n <button class=\"rpp-link-btn\" type=\"button\" (click)=\"DeselectAll()\" [disabled]=\"IsRestoring\">Deselect all</button>\n </div>\n </div>\n }\n\n <!-- Diff table -->\n @if (Rows.length > 0) {\n <div class=\"rpp-table-wrap\">\n <table class=\"rpp-table\">\n <thead>\n <tr>\n <th class=\"rpp-col-check\"></th>\n <th class=\"rpp-col-field\">Field</th>\n @if (Mode === 'live') {\n <th class=\"rpp-col-current\">Current Value</th>\n <th class=\"rpp-col-restore\">Restore To</th>\n } @else {\n <th class=\"rpp-col-restore\" colspan=\"2\">Will be created with</th>\n }\n <th class=\"rpp-col-flag\"></th>\n </tr>\n </thead>\n <tbody>\n @for (row of Rows; track row.FieldName) {\n @if (row.IsChanged || ShowUnchanged) {\n <tr [class.rpp-row-changed]=\"row.IsChanged\"\n [class.rpp-row-unchanged]=\"!row.IsChanged\"\n [class.rpp-row-immutable]=\"row.IsImmutable\"\n [class.rpp-row-drift]=\"row.IsMissingInSchema\">\n <td class=\"rpp-col-check\">\n <button type=\"button\"\n class=\"rpp-checkbox\"\n [class.checked]=\"row.Selected\"\n [class.disabled]=\"row.IsImmutable || row.IsMissingInSchema\"\n [disabled]=\"row.IsImmutable || row.IsMissingInSchema || IsRestoring\"\n [attr.aria-label]=\"'Toggle ' + row.DisplayName\"\n (click)=\"ToggleRow(row)\">\n @if (row.Selected) {\n <i class=\"fa-solid fa-check\" aria-hidden=\"true\"></i>\n }\n </button>\n </td>\n <td class=\"rpp-col-field\">\n <div class=\"rpp-field-display\">{{ row.DisplayName }}</div>\n <div class=\"rpp-field-name\">{{ row.FieldName }}</div>\n </td>\n @if (Mode === 'live') {\n <td class=\"rpp-col-current\" [class.rpp-empty-cell]=\"!row.CurrentValue\">\n {{ row.CurrentValue || '(empty)' }}\n </td>\n <td class=\"rpp-col-restore\" [class.rpp-empty-cell]=\"!row.RestoreValue\">\n {{ row.RestoreValue || '(empty)' }}\n </td>\n } @else {\n <td class=\"rpp-col-restore\" colspan=\"2\" [class.rpp-empty-cell]=\"!row.RestoreValue\">\n {{ row.RestoreValue || '(empty)' }}\n </td>\n }\n <td class=\"rpp-col-flag\">\n @if (row.IsMissingInSchema) {\n <i class=\"fa-solid fa-triangle-exclamation rpp-flag-drift\"\n title=\"This field no longer exists on the entity and will be skipped\"\n aria-hidden=\"true\"></i>\n } @else if (row.IsImmutable) {\n <i class=\"fa-solid fa-lock rpp-flag-immutable\"\n title=\"Read-only or system field \u2014 cannot be modified\"\n aria-hidden=\"true\"></i>\n } @else if (row.IsChanged) {\n <i class=\"fa-solid fa-circle-exclamation rpp-flag-changed\"\n title=\"Will be changed\"\n aria-hidden=\"true\"></i>\n } @else {\n <i class=\"fa-solid fa-check rpp-flag-ok\"\n title=\"Already matches\"\n aria-hidden=\"true\"></i>\n }\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n\n <!-- Unchanged disclosure -->\n @if (UnchangedCount > 0 && Mode === 'live') {\n <button class=\"rpp-disclosure\" type=\"button\" (click)=\"ToggleUnchanged()\">\n <i class=\"fa-solid\"\n [class.fa-chevron-right]=\"!ShowUnchanged\"\n [class.fa-chevron-down]=\"ShowUnchanged\"\n aria-hidden=\"true\"></i>\n <span>{{ ShowUnchanged ? 'Hide' : 'Show' }} {{ UnchangedCount }} unchanged field{{ UnchangedCount === 1 ? '' : 's' }}</span>\n </button>\n }\n }\n\n <!-- Reason text area -->\n @if (!HideReason && Rows.length > 0) {\n <div class=\"rpp-reason-section\">\n <label for=\"rpp-reason-input\">\n Reason for restore\n @if (RequireReason) {\n <span class=\"rpp-required\">*</span>\n } @else {\n <span class=\"rpp-optional\">(optional)</span>\n }\n </label>\n <textarea id=\"rpp-reason-input\"\n [(ngModel)]=\"Reason\"\n [disabled]=\"IsRestoring\"\n placeholder=\"e.g., Reverting incorrect Q2 entries\"\n class=\"rpp-reason-textarea\"\n rows=\"2\"></textarea>\n </div>\n }\n </div>\n\n <!-- Footer actions -->\n <div class=\"rpp-footer\">\n <div class=\"rpp-footer-info\">\n <i class=\"fa-solid fa-shield-halved\" aria-hidden=\"true\"></i>\n @if (Mode === 'live') {\n <span>A snapshot of the current state is saved automatically before the restore.</span>\n } @else {\n <span>A new \"Created\" entry will be added to this record's history, linked back to the original deletion.</span>\n }\n </div>\n <div class=\"rpp-footer-actions\">\n <button type=\"button\"\n class=\"rpp-btn rpp-btn-primary\"\n [disabled]=\"IsRestoreDisabled\"\n (click)=\"ConfirmRestore()\">\n @if (IsRestoring) {\n <i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i>\n } @else {\n <i class=\"fa-solid fa-rotate-left\" aria-hidden=\"true\"></i>\n }\n {{ RestoreButtonLabel }}\n </button>\n <button type=\"button\"\n class=\"rpp-btn rpp-btn-secondary\"\n [disabled]=\"IsRestoring\"\n (click)=\"Cancel()\">Cancel</button>\n </div>\n </div>\n }\n</mj-slide-panel>\n", styles: ["/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 Preview Panel\n * Slide-in panel that previews a restore operation field-by-field.\n * All colors use --mj-* design tokens so it adapts to dark mode and\n * white-label themes.\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\u2500 */\n\n.rpp-container {\n padding: 18px 20px;\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n\n/* \u2500\u2500\u2500 Header summary \u2500\u2500\u2500 */\n\n.rpp-header {\n display: flex;\n align-items: flex-start;\n gap: 14px;\n padding-bottom: 14px;\n border-bottom: 1px solid var(--mj-border-subtle);\n}\n\n.rpp-header-icon {\n width: 38px;\n height: 38px;\n border-radius: 8px;\n background: color-mix(in srgb, var(--mj-brand-primary) 12%, var(--mj-bg-surface));\n color: var(--mj-brand-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n font-size: 16px;\n}\n\n.rpp-header-text {\n flex: 1;\n min-width: 0;\n}\n\n.rpp-header-title {\n font-size: 15px;\n font-weight: 600;\n color: var(--mj-text-primary);\n margin-bottom: 4px;\n}\n\n.rpp-header-meta {\n display: flex;\n flex-wrap: wrap;\n gap: 14px;\n font-size: 12px;\n color: var(--mj-text-muted);\n}\n\n.rpp-header-meta strong {\n color: var(--mj-text-secondary);\n font-weight: 500;\n margin-right: 4px;\n}\n\n/* \u2500\u2500\u2500 Banners \u2500\u2500\u2500 */\n\n.rpp-banner {\n display: flex;\n align-items: center;\n gap: 9px;\n padding: 10px 12px;\n border-radius: 8px;\n font-size: 12px;\n border: 1px solid;\n}\n\n.rpp-banner-warning {\n background: var(--mj-status-warning-bg);\n color: var(--mj-status-warning-text);\n border-color: var(--mj-status-warning-border);\n}\n\n/* \u2500\u2500\u2500 Empty state \u2500\u2500\u2500 */\n\n.rpp-empty {\n text-align: center;\n padding: 30px 20px;\n color: var(--mj-text-muted);\n}\n\n.rpp-empty i {\n font-size: 24px;\n margin-bottom: 8px;\n}\n\n.rpp-empty p {\n margin: 0;\n font-size: 13px;\n}\n\n/* \u2500\u2500\u2500 Action bar (select all / deselect all) \u2500\u2500\u2500 */\n\n.rpp-action-bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n padding: 8px 12px;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-subtle);\n border-radius: 7px;\n font-size: 12px;\n}\n\n.rpp-action-bar-label {\n color: var(--mj-text-secondary);\n font-weight: 500;\n}\n\n.rpp-action-bar-buttons {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.rpp-action-bar-sep {\n color: var(--mj-text-disabled);\n}\n\n.rpp-link-btn {\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: 2px 4px;\n border-radius: 4px;\n}\n\n.rpp-link-btn:hover:not(:disabled) {\n background: color-mix(in srgb, var(--mj-brand-primary) 8%, transparent);\n}\n\n.rpp-link-btn:disabled {\n color: var(--mj-text-disabled);\n cursor: not-allowed;\n}\n\n/* \u2500\u2500\u2500 Diff table \u2500\u2500\u2500 */\n\n.rpp-table-wrap {\n border: 1px solid var(--mj-border-default);\n border-radius: 8px;\n overflow: hidden;\n}\n\n.rpp-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n background: var(--mj-bg-surface);\n}\n\n.rpp-table thead th {\n text-align: left;\n padding: 10px 12px;\n background: var(--mj-bg-surface-card);\n border-bottom: 1px solid var(--mj-border-default);\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--mj-text-muted);\n font-weight: 600;\n}\n\n.rpp-table tbody td {\n padding: 10px 12px;\n border-bottom: 1px solid var(--mj-border-subtle);\n vertical-align: top;\n}\n\n.rpp-table tbody tr:last-child td {\n border-bottom: none;\n}\n\n.rpp-row-changed { background: var(--mj-bg-surface); }\n.rpp-row-unchanged {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n.rpp-row-immutable { opacity: 0.7; }\n.rpp-row-drift { background: color-mix(in srgb, var(--mj-status-warning) 5%, var(--mj-bg-surface)); }\n\n/* Column widths */\n.rpp-col-check { width: 36px; padding: 8px 4px 8px 12px; }\n.rpp-col-field { width: 28%; min-width: 140px; }\n.rpp-col-current,\n.rpp-col-restore { word-break: break-word; }\n.rpp-col-flag { width: 28px; text-align: right; padding-right: 12px; }\n\n/* \u2500\u2500\u2500 Field cell \u2500\u2500\u2500 */\n\n.rpp-field-display {\n font-weight: 500;\n color: var(--mj-text-primary);\n margin-bottom: 2px;\n}\n\n.rpp-field-name {\n color: var(--mj-text-disabled);\n font-size: 11px;\n font-family: ui-monospace, SFMono-Regular, Consolas, monospace;\n}\n\n.rpp-row-unchanged .rpp-field-display { color: var(--mj-text-muted); }\n\n/* \u2500\u2500\u2500 Value cells \u2500\u2500\u2500 */\n\n.rpp-col-current { color: var(--mj-text-secondary); }\n.rpp-col-restore {\n color: var(--mj-text-primary);\n font-weight: 500;\n background: linear-gradient(90deg,\n color-mix(in srgb, var(--mj-brand-primary) 6%, transparent),\n transparent 80%);\n}\n\n.rpp-empty-cell {\n color: var(--mj-text-disabled);\n font-style: italic;\n}\n\n/* \u2500\u2500\u2500 Checkbox \u2500\u2500\u2500 */\n\n.rpp-checkbox {\n width: 18px;\n height: 18px;\n border: 1.5px solid var(--mj-border-strong);\n border-radius: 4px;\n background: var(--mj-bg-surface);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n padding: 0;\n color: var(--mj-text-inverse, #fff);\n transition: background-color 0.1s, border-color 0.1s;\n}\n\n.rpp-checkbox:hover:not(:disabled) {\n border-color: var(--mj-brand-primary);\n}\n\n.rpp-checkbox.checked {\n background: var(--mj-brand-primary);\n border-color: var(--mj-brand-primary);\n}\n\n.rpp-checkbox.checked i {\n font-size: 11px;\n}\n\n.rpp-checkbox.disabled,\n.rpp-checkbox:disabled {\n background: var(--mj-bg-surface-sunken);\n border-color: var(--mj-border-default);\n cursor: not-allowed;\n}\n\n/* \u2500\u2500\u2500 Flag icons \u2500\u2500\u2500 */\n\n.rpp-flag-changed { color: var(--mj-status-warning); }\n.rpp-flag-ok { color: var(--mj-text-disabled); }\n.rpp-flag-drift { color: var(--mj-status-warning); }\n.rpp-flag-immutable { color: var(--mj-text-disabled); }\n\n/* \u2500\u2500\u2500 Unchanged disclosure \u2500\u2500\u2500 */\n\n.rpp-disclosure {\n background: none;\n border: none;\n color: var(--mj-text-muted);\n font-size: 12px;\n cursor: pointer;\n padding: 8px 4px;\n display: flex;\n align-items: center;\n gap: 8px;\n text-align: left;\n}\n\n.rpp-disclosure:hover {\n color: var(--mj-text-primary);\n}\n\n.rpp-disclosure i {\n font-size: 10px;\n width: 12px;\n}\n\n/* \u2500\u2500\u2500 Reason section \u2500\u2500\u2500 */\n\n.rpp-reason-section {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.rpp-reason-section label {\n font-size: 12px;\n font-weight: 500;\n color: var(--mj-text-secondary);\n}\n\n.rpp-required {\n color: var(--mj-status-error);\n margin-left: 4px;\n}\n\n.rpp-optional {\n color: var(--mj-text-disabled);\n font-weight: 400;\n margin-left: 4px;\n}\n\n.rpp-reason-textarea {\n width: 100%;\n border: 1px solid var(--mj-border-default);\n border-radius: 7px;\n padding: 8px 10px;\n font-family: inherit;\n font-size: 13px;\n color: var(--mj-text-primary);\n background: var(--mj-bg-surface);\n resize: vertical;\n min-height: 50px;\n box-sizing: border-box;\n}\n\n.rpp-reason-textarea:focus {\n outline: 2px solid var(--mj-brand-primary);\n outline-offset: -1px;\n border-color: var(--mj-brand-primary);\n}\n\n.rpp-reason-textarea:disabled {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n}\n\n/* \u2500\u2500\u2500 Footer \u2500\u2500\u2500 */\n\n.rpp-footer {\n position: sticky;\n bottom: 0;\n background: var(--mj-bg-surface);\n border-top: 1px solid var(--mj-border-default);\n padding: 12px 20px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 14px;\n}\n\n.rpp-footer-info {\n display: flex;\n align-items: center;\n gap: 7px;\n color: var(--mj-text-muted);\n font-size: 12px;\n}\n\n.rpp-footer-info i {\n color: var(--mj-brand-primary);\n}\n\n.rpp-footer-actions {\n display: flex;\n gap: 10px;\n}\n\n.rpp-btn {\n padding: 8px 16px;\n border-radius: 7px;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n border: 1px solid transparent;\n display: inline-flex;\n align-items: center;\n gap: 7px;\n font-family: inherit;\n}\n\n.rpp-btn-primary {\n background: var(--mj-brand-primary);\n color: var(--mj-text-inverse, #fff);\n border-color: var(--mj-brand-primary);\n}\n\n.rpp-btn-primary:hover:not(:disabled) {\n background: var(--mj-brand-primary-hover);\n}\n\n.rpp-btn-primary:disabled {\n background: var(--mj-bg-surface-sunken);\n color: var(--mj-text-disabled);\n border-color: var(--mj-border-default);\n cursor: not-allowed;\n}\n\n.rpp-btn-secondary {\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n border-color: var(--mj-border-default);\n font-weight: 500;\n}\n\n.rpp-btn-secondary:hover:not(:disabled) {\n background: var(--mj-bg-surface-hover);\n color: var(--mj-text-primary);\n}\n\n.rpp-btn-secondary:disabled {\n color: var(--mj-text-disabled);\n cursor: not-allowed;\n}\n"] }]
726
+ }], () => [{ type: i0.ChangeDetectorRef }], { Visible: [{
727
+ type: Input
728
+ }], Mode: [{
729
+ type: Input
730
+ }], RecordChange: [{
731
+ type: Input
732
+ }], LiveRecord: [{
733
+ type: Input
734
+ }], EntityName: [{
735
+ type: Input
736
+ }], RequireReason: [{
737
+ type: Input
738
+ }], HideReason: [{
739
+ type: Input
740
+ }], BeforeRestoreCommit: [{
741
+ type: Output
742
+ }], RestoreConfirmed: [{
743
+ type: Output
744
+ }], RestoreCancelled: [{
745
+ type: Output
746
+ }] }); })();
747
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassDebugInfo(RestorePreviewPanelComponent, { className: "RestorePreviewPanelComponent", filePath: "src/lib/restore-preview-panel/restore-preview-panel.component.ts", lineNumber: 159 }); })();
748
+ //# sourceMappingURL=restore-preview-panel.component.js.map