@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.
- package/README.md +220 -0
- package/dist/__tests__/restore-version.test.js +102 -152
- package/dist/__tests__/restore-version.test.js.map +1 -1
- package/dist/lib/__tests__/record-changes.test.js +21 -12
- package/dist/lib/__tests__/record-changes.test.js.map +1 -1
- package/dist/lib/ng-record-changes.component.d.ts +171 -49
- package/dist/lib/ng-record-changes.component.d.ts.map +1 -1
- package/dist/lib/ng-record-changes.component.js +645 -416
- package/dist/lib/ng-record-changes.component.js.map +1 -1
- package/dist/lib/ng-record-changes.module.d.ts +6 -5
- package/dist/lib/ng-record-changes.module.d.ts.map +1 -1
- package/dist/lib/ng-record-changes.module.js +9 -4
- package/dist/lib/ng-record-changes.module.js.map +1 -1
- package/dist/lib/restore-preview-panel/restore-preview-panel.component.d.ts +267 -0
- package/dist/lib/restore-preview-panel/restore-preview-panel.component.d.ts.map +1 -0
- package/dist/lib/restore-preview-panel/restore-preview-panel.component.js +748 -0
- package/dist/lib/restore-preview-panel/restore-preview-panel.component.js.map +1 -0
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +2 -1
- package/dist/public-api.js.map +1 -1
- package/package.json +8 -7
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { ChangeDetectorRef, EventEmitter, OnInit } from '@angular/core';
|
|
2
|
+
import { BaseEntity } from '@memberjunction/core';
|
|
3
|
+
import { MJRecordChangeEntity } from '@memberjunction/core-entities';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* Mode controls how the preview is rendered and how the restore is interpreted.
|
|
7
|
+
*
|
|
8
|
+
* - `'live'`: target record exists; the preview shows a current-vs-restore
|
|
9
|
+
* diff per field. Confirming applies the snapshot to the live record and
|
|
10
|
+
* triggers an UPDATE.
|
|
11
|
+
* - `'undelete'`: target record was hard-deleted. The preview shows the
|
|
12
|
+
* snapshot fields that will be inserted; confirming triggers an INSERT.
|
|
13
|
+
*/
|
|
14
|
+
export type RestorePreviewMode = 'live' | 'undelete';
|
|
15
|
+
/**
|
|
16
|
+
* One row in the restore preview table.
|
|
17
|
+
*
|
|
18
|
+
* Renders as a checkbox + field name + (current / restore) values. The
|
|
19
|
+
* `IsChanged` flag drives the default-checked state and the row's visual
|
|
20
|
+
* treatment. `IsMissingInSchema` and `IsFKMissing` surface drift warnings.
|
|
21
|
+
*/
|
|
22
|
+
export interface RestoreFieldRow {
|
|
23
|
+
/** Raw field name (matches EntityField.Name). */
|
|
24
|
+
FieldName: string;
|
|
25
|
+
/** Friendly label (EntityField.DisplayNameOrName). */
|
|
26
|
+
DisplayName: string;
|
|
27
|
+
/** Formatted current value of the live record (empty in undelete mode). */
|
|
28
|
+
CurrentValue: string;
|
|
29
|
+
/** Formatted snapshot value that would be applied. */
|
|
30
|
+
RestoreValue: string;
|
|
31
|
+
/** Raw snapshot value (the value passed to BaseEntity.Set). */
|
|
32
|
+
RawRestoreValue: unknown;
|
|
33
|
+
/** True when CurrentValue and RestoreValue differ. Drives default checked. */
|
|
34
|
+
IsChanged: boolean;
|
|
35
|
+
/** User's selection — when true, this field will be applied on restore. */
|
|
36
|
+
Selected: boolean;
|
|
37
|
+
/** True when the snapshot references a field that no longer exists on the entity. */
|
|
38
|
+
IsMissingInSchema: boolean;
|
|
39
|
+
/** True when the field is a FK whose target row no longer exists (best-effort). */
|
|
40
|
+
IsFKMissing: boolean;
|
|
41
|
+
/** True when the field is read-only / system / PK and cannot be restored. */
|
|
42
|
+
IsImmutable: boolean;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Cancelable event fired immediately after the user clicks Restore but
|
|
46
|
+
* before {@link RestorePreviewPanelComponent.RestoreConfirmed} emits.
|
|
47
|
+
*
|
|
48
|
+
* Consumers can set `cancel = true` (and optionally `cancelReason`) to abort
|
|
49
|
+
* the restore — useful for custom approval workflows, audit logging hooks,
|
|
50
|
+
* or for a consumer that wants to take over the actual save itself.
|
|
51
|
+
*/
|
|
52
|
+
export interface BeforeRestoreCommitEvent {
|
|
53
|
+
/** Set to true to abort. RestoreConfirmed will not fire. */
|
|
54
|
+
cancel: boolean;
|
|
55
|
+
/** Optional explanation surfaced by the consumer. */
|
|
56
|
+
cancelReason?: string;
|
|
57
|
+
/** Selected field names (only fields the user kept checked). */
|
|
58
|
+
SelectedFieldNames: string[];
|
|
59
|
+
/** The full set of rows in the preview, including unselected. */
|
|
60
|
+
AllRows: RestoreFieldRow[];
|
|
61
|
+
/** ID of the source RecordChange row whose state is being restored. */
|
|
62
|
+
SourceChangeID: string;
|
|
63
|
+
/** Optional reason text the user entered. */
|
|
64
|
+
Reason: string | null;
|
|
65
|
+
/** The mode — 'live' (UPDATE) or 'undelete' (INSERT). */
|
|
66
|
+
Mode: RestorePreviewMode;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Event payload emitted after the user has confirmed a restore.
|
|
70
|
+
*
|
|
71
|
+
* The host component is responsible for applying the snapshot to a
|
|
72
|
+
* BaseEntity instance, calling {@link BaseEntity.SetRestoreContext}, and
|
|
73
|
+
* invoking Save(). This component never touches the database directly so
|
|
74
|
+
* it remains usable in any consumer context.
|
|
75
|
+
*/
|
|
76
|
+
export interface RestoreCommitEvent {
|
|
77
|
+
/** ID of the source RecordChange row whose state is being restored. */
|
|
78
|
+
SourceChangeID: string;
|
|
79
|
+
/** Optional user-entered reason; persisted to RecordChange.RestoreReason. */
|
|
80
|
+
Reason: string | null;
|
|
81
|
+
/** Selected fields with their snapshot values, ready for BaseEntity.Set. */
|
|
82
|
+
FieldValues: Array<{
|
|
83
|
+
FieldName: string;
|
|
84
|
+
Value: unknown;
|
|
85
|
+
}>;
|
|
86
|
+
/** The full preview rows (including unselected) for audit/logging. */
|
|
87
|
+
AllRows: RestoreFieldRow[];
|
|
88
|
+
/** Mode indicates UPDATE (live) vs INSERT (undelete). */
|
|
89
|
+
Mode: RestorePreviewMode;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Reusable slide-in panel that previews a restore operation against a
|
|
93
|
+
* historical {@link MJRecordChangeEntity} and lets the user confirm with
|
|
94
|
+
* field-level granularity.
|
|
95
|
+
*
|
|
96
|
+
* This component is rendered by both:
|
|
97
|
+
* - The Record Changes timeline (for restoring a live record from any past
|
|
98
|
+
* change row)
|
|
99
|
+
* - The Recycle Bin (for re-creating a hard-deleted record from its delete
|
|
100
|
+
* snapshot)
|
|
101
|
+
*
|
|
102
|
+
* It does NOT perform the save itself — the host component receives a
|
|
103
|
+
* {@link RestoreCommitEvent} with the selected field values and is
|
|
104
|
+
* responsible for applying them to a BaseEntity, setting the restore
|
|
105
|
+
* context, and calling Save(). This keeps the component purely
|
|
106
|
+
* presentational and reusable in any context.
|
|
107
|
+
*
|
|
108
|
+
* ### Semantic correctness
|
|
109
|
+
*
|
|
110
|
+
* The preview compares the **full snapshot** captured in the source
|
|
111
|
+
* change's `FullRecordJSON` to the current live record (or to nothing in
|
|
112
|
+
* un-delete mode). It does NOT roll back a single delta — restoring `v2`
|
|
113
|
+
* means "make the record look like it did at v2", not "undo v3's changes".
|
|
114
|
+
*
|
|
115
|
+
* @example Live restore from the timeline
|
|
116
|
+
* <mj-restore-preview-panel
|
|
117
|
+
* [Visible]="showPreview"
|
|
118
|
+
* [Mode]="'live'"
|
|
119
|
+
* [RecordChange]="selectedChange"
|
|
120
|
+
* [LiveRecord]="record"
|
|
121
|
+
* (RestoreConfirmed)="onRestoreConfirmed($event)"
|
|
122
|
+
* (RestoreCancelled)="showPreview = false">
|
|
123
|
+
* </mj-restore-preview-panel>
|
|
124
|
+
*
|
|
125
|
+
* @example Un-delete from the Recycle Bin
|
|
126
|
+
* <mj-restore-preview-panel
|
|
127
|
+
* [Visible]="showPreview"
|
|
128
|
+
* [Mode]="'undelete'"
|
|
129
|
+
* [RecordChange]="deletedChange"
|
|
130
|
+
* [EntityName]="'Customers'"
|
|
131
|
+
* (RestoreConfirmed)="onRecreate($event)"
|
|
132
|
+
* (RestoreCancelled)="showPreview = false">
|
|
133
|
+
* </mj-restore-preview-panel>
|
|
134
|
+
*/
|
|
135
|
+
export declare class RestorePreviewPanelComponent implements OnInit {
|
|
136
|
+
private cdr;
|
|
137
|
+
/**
|
|
138
|
+
* Controls panel visibility. Setting to true opens the slide-in;
|
|
139
|
+
* setting to false closes it.
|
|
140
|
+
*/
|
|
141
|
+
Visible: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Operating mode — `'live'` for restoring an existing record from a
|
|
144
|
+
* snapshot, `'undelete'` for re-creating a hard-deleted record.
|
|
145
|
+
*/
|
|
146
|
+
Mode: RestorePreviewMode;
|
|
147
|
+
/**
|
|
148
|
+
* The historical RecordChange row whose state will be restored. Required.
|
|
149
|
+
* The component reads `FullRecordJSON` from this entity to determine the
|
|
150
|
+
* target state. The change's `Type` does not matter — `Create`,
|
|
151
|
+
* `Update`, `Snapshot`, and `Delete` are all valid restore sources.
|
|
152
|
+
*/
|
|
153
|
+
private _recordChange;
|
|
154
|
+
set RecordChange(value: MJRecordChangeEntity | null);
|
|
155
|
+
get RecordChange(): MJRecordChangeEntity | null;
|
|
156
|
+
/**
|
|
157
|
+
* The current live record to diff against. Required in `'live'` mode,
|
|
158
|
+
* ignored in `'undelete'` mode (since the live record no longer exists).
|
|
159
|
+
*/
|
|
160
|
+
private _liveRecord;
|
|
161
|
+
set LiveRecord(value: BaseEntity | null);
|
|
162
|
+
get LiveRecord(): BaseEntity | null;
|
|
163
|
+
/**
|
|
164
|
+
* The entity name. Required in `'undelete'` mode (since there's no live
|
|
165
|
+
* record to read it from). In `'live'` mode it can be omitted and is
|
|
166
|
+
* inferred from the LiveRecord.
|
|
167
|
+
*/
|
|
168
|
+
EntityName: string | null;
|
|
169
|
+
/**
|
|
170
|
+
* When true, the Restore button is disabled until the user enters a
|
|
171
|
+
* non-empty reason. Useful for regulated environments where every
|
|
172
|
+
* reversal needs justification. Default: false.
|
|
173
|
+
*/
|
|
174
|
+
RequireReason: boolean;
|
|
175
|
+
/**
|
|
176
|
+
* When true, hides the optional reason text area entirely. Default: false.
|
|
177
|
+
*/
|
|
178
|
+
HideReason: boolean;
|
|
179
|
+
/**
|
|
180
|
+
* Cancelable event fired when the user clicks Restore but before
|
|
181
|
+
* {@link RestoreConfirmed} emits. Consumers can set `cancel = true` on
|
|
182
|
+
* the event arg to abort the operation — useful for custom approval
|
|
183
|
+
* workflows or for taking over the save themselves.
|
|
184
|
+
*/
|
|
185
|
+
BeforeRestoreCommit: EventEmitter<BeforeRestoreCommitEvent>;
|
|
186
|
+
/**
|
|
187
|
+
* Emitted after the user confirms the restore (and BeforeRestoreCommit
|
|
188
|
+
* was not cancelled). The host is responsible for applying the field
|
|
189
|
+
* values to a BaseEntity, calling SetRestoreContext, and invoking Save().
|
|
190
|
+
*/
|
|
191
|
+
RestoreConfirmed: EventEmitter<RestoreCommitEvent>;
|
|
192
|
+
/**
|
|
193
|
+
* Emitted when the user cancels the preview without restoring.
|
|
194
|
+
*/
|
|
195
|
+
RestoreCancelled: EventEmitter<void>;
|
|
196
|
+
Rows: RestoreFieldRow[];
|
|
197
|
+
Reason: string;
|
|
198
|
+
IsRestoring: boolean;
|
|
199
|
+
ShowUnchanged: boolean;
|
|
200
|
+
/** Number of rows where the current value differs from the snapshot. */
|
|
201
|
+
ChangedCount: number;
|
|
202
|
+
/** Number of rows that are checked (will be applied on restore). */
|
|
203
|
+
SelectedCount: number;
|
|
204
|
+
/** Number of rows the schema has dropped or renamed since the snapshot. */
|
|
205
|
+
DriftCount: number;
|
|
206
|
+
private isInitialized;
|
|
207
|
+
private resolvedEntityInfo;
|
|
208
|
+
constructor(cdr: ChangeDetectorRef);
|
|
209
|
+
ngOnInit(): void;
|
|
210
|
+
/**
|
|
211
|
+
* Toggles whether unchanged rows are visible in the table. When false
|
|
212
|
+
* (default), only rows where current ≠ snapshot are shown.
|
|
213
|
+
*/
|
|
214
|
+
ToggleUnchanged(): void;
|
|
215
|
+
/**
|
|
216
|
+
* Toggles whether a single row is selected for restore. Updates the
|
|
217
|
+
* SelectedCount in real time so the primary button label reflects it.
|
|
218
|
+
*/
|
|
219
|
+
ToggleRow(row: RestoreFieldRow): void;
|
|
220
|
+
/**
|
|
221
|
+
* Selects every row that can be selected (skips immutable / drifted).
|
|
222
|
+
*/
|
|
223
|
+
SelectAll(): void;
|
|
224
|
+
/**
|
|
225
|
+
* Deselects every row in the preview.
|
|
226
|
+
*/
|
|
227
|
+
DeselectAll(): void;
|
|
228
|
+
/**
|
|
229
|
+
* User clicked Restore — fire BeforeRestoreCommit (cancelable), then
|
|
230
|
+
* RestoreConfirmed if not cancelled.
|
|
231
|
+
*/
|
|
232
|
+
ConfirmRestore(): void;
|
|
233
|
+
/**
|
|
234
|
+
* User cancelled the preview. Resets state and emits RestoreCancelled.
|
|
235
|
+
*/
|
|
236
|
+
Cancel(): void;
|
|
237
|
+
/**
|
|
238
|
+
* Resets internal state — useful after a save completes so the panel
|
|
239
|
+
* can be reopened cleanly. Called by the host component when needed.
|
|
240
|
+
*/
|
|
241
|
+
Reset(): void;
|
|
242
|
+
get IsRestoreDisabled(): boolean;
|
|
243
|
+
get RestoreButtonLabel(): string;
|
|
244
|
+
get HeaderTitle(): string;
|
|
245
|
+
get VersionTimestamp(): Date | null;
|
|
246
|
+
get VersionUser(): string;
|
|
247
|
+
get UnchangedCount(): number;
|
|
248
|
+
/**
|
|
249
|
+
* Rebuilds the Rows array from the current RecordChange + LiveRecord.
|
|
250
|
+
* Idempotent and cheap — safe to call from input setters.
|
|
251
|
+
*/
|
|
252
|
+
private rebuildRows;
|
|
253
|
+
private buildRowFromSnapshot;
|
|
254
|
+
private getCurrentFieldValue;
|
|
255
|
+
private parseSnapshot;
|
|
256
|
+
/**
|
|
257
|
+
* Resolves the entity metadata. Prefers LiveRecord.EntityInfo (always
|
|
258
|
+
* accurate). Falls back to looking up by EntityName. Memoized.
|
|
259
|
+
*/
|
|
260
|
+
private resolveEntityInfo;
|
|
261
|
+
private formatValue;
|
|
262
|
+
private recountSelected;
|
|
263
|
+
formatTimestamp(date: Date | null): string;
|
|
264
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<RestorePreviewPanelComponent, never>;
|
|
265
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<RestorePreviewPanelComponent, "mj-restore-preview-panel", never, { "Visible": { "alias": "Visible"; "required": false; }; "Mode": { "alias": "Mode"; "required": false; }; "RecordChange": { "alias": "RecordChange"; "required": false; }; "LiveRecord": { "alias": "LiveRecord"; "required": false; }; "EntityName": { "alias": "EntityName"; "required": false; }; "RequireReason": { "alias": "RequireReason"; "required": false; }; "HideReason": { "alias": "HideReason"; "required": false; }; }, { "BeforeRestoreCommit": "BeforeRestoreCommit"; "RestoreConfirmed": "RestoreConfirmed"; "RestoreCancelled": "RestoreCancelled"; }, never, never, false, never>;
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=restore-preview-panel.component.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"restore-preview-panel.component.d.ts","sourceRoot":"","sources":["../../../src/lib/restore-preview-panel/restore-preview-panel.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,iBAAiB,EACjB,YAAY,EAGZ,MAAM,EAEP,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,UAAU,EAKX,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;;AAErE;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,UAAU,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,WAAW,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,YAAY,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,eAAe,EAAE,OAAO,CAAC;IACzB,8EAA8E;IAC9E,SAAS,EAAE,OAAO,CAAC;IACnB,2EAA2E;IAC3E,QAAQ,EAAE,OAAO,CAAC;IAClB,qFAAqF;IACrF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,mFAAmF;IACnF,WAAW,EAAE,OAAO,CAAC;IACrB,6EAA6E;IAC7E,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,wBAAwB;IACvC,4DAA4D;IAC5D,MAAM,EAAE,OAAO,CAAC;IAChB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,iEAAiE;IACjE,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,uEAAuE;IACvE,cAAc,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,yDAAyD;IACzD,IAAI,EAAE,kBAAkB,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,cAAc,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,4EAA4E;IAC5E,WAAW,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1D,sEAAsE;IACtE,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,yDAAyD;IACzD,IAAI,EAAE,kBAAkB,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,qBAQa,4BAA6B,YAAW,MAAM;IAuG7C,OAAO,CAAC,GAAG;IApGvB;;;OAGG;IACM,OAAO,UAAS;IAEzB;;;OAGG;IACM,IAAI,EAAE,kBAAkB,CAAU;IAE3C;;;;;OAKG;IACH,OAAO,CAAC,aAAa,CAAqC;IAC1D,IACI,YAAY,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,EAGlD;IACD,IAAI,YAAY,IAAI,oBAAoB,GAAG,IAAI,CAE9C;IAED;;;OAGG;IACH,OAAO,CAAC,WAAW,CAA2B;IAC9C,IACI,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,EAGtC;IACD,IAAI,UAAU,IAAI,UAAU,GAAG,IAAI,CAElC;IAED;;;;OAIG;IACM,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE1C;;;;OAIG;IACM,aAAa,UAAS;IAE/B;;OAEG;IACM,UAAU,UAAS;IAI5B;;;;;OAKG;IACO,mBAAmB,yCAAgD;IAE7E;;;;OAIG;IACO,gBAAgB,mCAA0C;IAEpE;;OAEG;IACO,gBAAgB,qBAA4B;IAI/C,IAAI,EAAE,eAAe,EAAE,CAAM;IAC7B,MAAM,SAAM;IACZ,WAAW,UAAS;IACpB,aAAa,UAAS;IAE7B,wEAAwE;IACjE,YAAY,SAAK;IACxB,oEAAoE;IAC7D,aAAa,SAAK;IACzB,2EAA2E;IACpE,UAAU,SAAK;IAEtB,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,kBAAkB,CAA2B;gBAEjC,GAAG,EAAE,iBAAiB;IAE1C,QAAQ,IAAI,IAAI;IAOhB;;;OAGG;IACI,eAAe,IAAI,IAAI;IAK9B;;;OAGG;IACI,SAAS,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAO5C;;OAEG;IACI,SAAS,IAAI,IAAI;IAQxB;;OAEG;IACI,WAAW,IAAI,IAAI;IAM1B;;;OAGG;IACI,cAAc,IAAI,IAAI;IA+B7B;;OAEG;IACI,MAAM,IAAI,IAAI;IAIrB;;;OAGG;IACI,KAAK,IAAI,IAAI;IASpB,IAAW,iBAAiB,IAAI,OAAO,CAKtC;IAED,IAAW,kBAAkB,IAAI,MAAM,CAMtC;IAED,IAAW,WAAW,IAAI,MAAM,CAE/B;IAED,IAAW,gBAAgB,IAAI,IAAI,GAAG,IAAI,CAEzC;IAED,IAAW,WAAW,IAAI,MAAM,CAE/B;IAED,IAAW,cAAc,IAAI,MAAM,CAElC;IAID;;;OAGG;IACH,OAAO,CAAC,WAAW;IA6CnB,OAAO,CAAC,oBAAoB;IA0C5B,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,aAAa;IASrB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAiBzB,OAAO,CAAC,WAAW;IAuBnB,OAAO,CAAC,eAAe;IAMhB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,MAAM;yCA/YtC,4BAA4B;2CAA5B,4BAA4B;CA0ZxC"}
|