ngx-form-draft 1.0.2 → 1.0.3

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,409 @@
1
+ import * as i0 from '@angular/core';
2
+ import { EventEmitter, Component, ChangeDetectionStrategy, Input, Output, Injectable, Directive, Optional, NgModule } from '@angular/core';
3
+ import * as i1$1 from '@angular/forms';
4
+ import { FormGroup, FormArray, FormControl } from '@angular/forms';
5
+ import { Subject } from 'rxjs';
6
+ import { debounceTime, takeUntil } from 'rxjs/operators';
7
+ import { trigger, transition, style, animate } from '@angular/animations';
8
+ import * as i1 from '@angular/common';
9
+ import { CommonModule } from '@angular/common';
10
+
11
+ class FormDraftBannerComponent {
12
+ constructor() {
13
+ this.visible = false;
14
+ this.timeLabel = '';
15
+ this.isRestored = false;
16
+ this.restoredText = 'Draft restored';
17
+ this.savedText = 'Draft saved';
18
+ this.savedLabel = 'saved';
19
+ this.discardText = 'Discard';
20
+ this.discard = new EventEmitter();
21
+ }
22
+ }
23
+ FormDraftBannerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FormDraftBannerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
24
+ FormDraftBannerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: FormDraftBannerComponent, selector: "ngx-form-draft-banner", inputs: { visible: "visible", timeLabel: "timeLabel", isRestored: "isRestored", restoredText: "restoredText", savedText: "savedText", savedLabel: "savedLabel", discardText: "discardText" }, outputs: { discard: "discard" }, ngImport: i0, template: `
25
+ <div class="form-draft-banner" *ngIf="visible" [@slideDown]>
26
+ <div class="form-draft-banner__icon">
27
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
28
+ <path d="M12 8V12L14.5 14.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
29
+ <circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2"/>
30
+ </svg>
31
+ </div>
32
+ <div class="form-draft-banner__content">
33
+ <span class="form-draft-banner__text">
34
+ <span *ngIf="isRestored">{{ restoredText }}</span>
35
+ <span *ngIf="!isRestored">{{ savedText }}</span>
36
+ <span class="form-draft-banner__time" *ngIf="timeLabel && isRestored">
37
+ &middot; {{ savedLabel }} {{ timeLabel }}
38
+ </span>
39
+ </span>
40
+ </div>
41
+ <div class="form-draft-banner__actions">
42
+ <button class="form-draft-banner__btn form-draft-banner__btn--discard" (click)="discard.emit()" type="button">
43
+ ✕ {{ discardText }}
44
+ </button>
45
+ </div>
46
+ </div>
47
+ `, isInline: true, styles: [":host{display:block;width:100%}.form-draft-banner{display:flex;align-items:center;gap:10px;padding:10px 14px;margin-bottom:12px;border-radius:8px;background:linear-gradient(135deg,#eef6ff 0%,#f0f4ff 100%);border:1px solid #c5ddf8;box-shadow:0 2px 8px #128ad614}.form-draft-banner__icon{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:6px;background:linear-gradient(135deg,#128ad6,#22b9ff);color:#fff;flex-shrink:0}.form-draft-banner__content{flex:1;min-width:0}.form-draft-banner__text{font-size:13px;font-weight:600;color:#1a3a5c}.form-draft-banner__time{font-weight:400;color:#6b8aaa;font-size:12px}.form-draft-banner__actions{flex-shrink:0}.form-draft-banner__btn{border:none;padding:5px 12px;border-radius:6px;font-size:12px;font-weight:600;cursor:pointer;transition:all .2s ease}.form-draft-banner__btn--discard{background:transparent;color:#8899a6;border:1px solid #d0dce6}.form-draft-banner__btn--discard:hover{background:#fef2f2;color:#e62e43;border-color:#e62e43}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], animations: [
48
+ trigger('slideDown', [
49
+ transition(':enter', [
50
+ style({ opacity: 0, transform: 'translateY(-8px)' }),
51
+ animate('250ms cubic-bezier(0.4, 0, 0.2, 1)', style({ opacity: 1, transform: 'translateY(0)' }))
52
+ ]),
53
+ transition(':leave', [
54
+ animate('200ms cubic-bezier(0.4, 0, 0.2, 1)', style({ opacity: 0, transform: 'translateY(-8px)' }))
55
+ ])
56
+ ])
57
+ ], changeDetection: i0.ChangeDetectionStrategy.OnPush });
58
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FormDraftBannerComponent, decorators: [{
59
+ type: Component,
60
+ args: [{ selector: 'ngx-form-draft-banner', template: `
61
+ <div class="form-draft-banner" *ngIf="visible" [@slideDown]>
62
+ <div class="form-draft-banner__icon">
63
+ <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
64
+ <path d="M12 8V12L14.5 14.5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
65
+ <circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2"/>
66
+ </svg>
67
+ </div>
68
+ <div class="form-draft-banner__content">
69
+ <span class="form-draft-banner__text">
70
+ <span *ngIf="isRestored">{{ restoredText }}</span>
71
+ <span *ngIf="!isRestored">{{ savedText }}</span>
72
+ <span class="form-draft-banner__time" *ngIf="timeLabel && isRestored">
73
+ &middot; {{ savedLabel }} {{ timeLabel }}
74
+ </span>
75
+ </span>
76
+ </div>
77
+ <div class="form-draft-banner__actions">
78
+ <button class="form-draft-banner__btn form-draft-banner__btn--discard" (click)="discard.emit()" type="button">
79
+ ✕ {{ discardText }}
80
+ </button>
81
+ </div>
82
+ </div>
83
+ `, animations: [
84
+ trigger('slideDown', [
85
+ transition(':enter', [
86
+ style({ opacity: 0, transform: 'translateY(-8px)' }),
87
+ animate('250ms cubic-bezier(0.4, 0, 0.2, 1)', style({ opacity: 1, transform: 'translateY(0)' }))
88
+ ]),
89
+ transition(':leave', [
90
+ animate('200ms cubic-bezier(0.4, 0, 0.2, 1)', style({ opacity: 0, transform: 'translateY(-8px)' }))
91
+ ])
92
+ ])
93
+ ], changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;width:100%}.form-draft-banner{display:flex;align-items:center;gap:10px;padding:10px 14px;margin-bottom:12px;border-radius:8px;background:linear-gradient(135deg,#eef6ff 0%,#f0f4ff 100%);border:1px solid #c5ddf8;box-shadow:0 2px 8px #128ad614}.form-draft-banner__icon{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:6px;background:linear-gradient(135deg,#128ad6,#22b9ff);color:#fff;flex-shrink:0}.form-draft-banner__content{flex:1;min-width:0}.form-draft-banner__text{font-size:13px;font-weight:600;color:#1a3a5c}.form-draft-banner__time{font-weight:400;color:#6b8aaa;font-size:12px}.form-draft-banner__actions{flex-shrink:0}.form-draft-banner__btn{border:none;padding:5px 12px;border-radius:6px;font-size:12px;font-weight:600;cursor:pointer;transition:all .2s ease}.form-draft-banner__btn--discard{background:transparent;color:#8899a6;border:1px solid #d0dce6}.form-draft-banner__btn--discard:hover{background:#fef2f2;color:#e62e43;border-color:#e62e43}\n"] }]
94
+ }], propDecorators: { visible: [{
95
+ type: Input
96
+ }], timeLabel: [{
97
+ type: Input
98
+ }], isRestored: [{
99
+ type: Input
100
+ }], restoredText: [{
101
+ type: Input
102
+ }], savedText: [{
103
+ type: Input
104
+ }], savedLabel: [{
105
+ type: Input
106
+ }], discardText: [{
107
+ type: Input
108
+ }], discard: [{
109
+ type: Output
110
+ }] } });
111
+
112
+ class FormDraftService {
113
+ constructor() {
114
+ this.STORAGE_PREFIX = 'form_draft_';
115
+ this.MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
116
+ }
117
+ buildKey(formId) {
118
+ return `${this.STORAGE_PREFIX}${formId}`;
119
+ }
120
+ save(formId, values) {
121
+ try {
122
+ const draft = { values, savedAt: Date.now(), formId };
123
+ localStorage.setItem(this.buildKey(formId), JSON.stringify(draft));
124
+ }
125
+ catch (e) {
126
+ console.warn('[FormDraft] Could not save draft:', e);
127
+ }
128
+ }
129
+ load(formId) {
130
+ try {
131
+ const raw = localStorage.getItem(this.buildKey(formId));
132
+ if (!raw)
133
+ return null;
134
+ const draft = JSON.parse(raw);
135
+ if (Date.now() - draft.savedAt > this.MAX_AGE_MS) {
136
+ this.clear(formId);
137
+ return null;
138
+ }
139
+ return draft;
140
+ }
141
+ catch (e) {
142
+ console.warn('[FormDraft] Could not load draft:', e);
143
+ return null;
144
+ }
145
+ }
146
+ clear(formId) {
147
+ try {
148
+ localStorage.removeItem(this.buildKey(formId));
149
+ }
150
+ catch (e) {
151
+ console.warn('[FormDraft] Could not clear draft:', e);
152
+ }
153
+ }
154
+ formatTimestamp(timestamp) {
155
+ const seconds = Math.floor((Date.now() - timestamp) / 1000);
156
+ if (seconds < 60)
157
+ return 'just now';
158
+ const minutes = Math.floor(seconds / 60);
159
+ if (minutes < 60)
160
+ return `${minutes}m ago`;
161
+ const hours = Math.floor(minutes / 60);
162
+ if (hours < 24)
163
+ return `${hours}h ago`;
164
+ const days = Math.floor(hours / 24);
165
+ return `${days}d ago`;
166
+ }
167
+ }
168
+ FormDraftService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FormDraftService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
169
+ FormDraftService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FormDraftService, providedIn: 'root' });
170
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FormDraftService, decorators: [{
171
+ type: Injectable,
172
+ args: [{
173
+ providedIn: 'root'
174
+ }]
175
+ }] });
176
+
177
+ /**
178
+ * Auto-saves and restores form drafts
179
+ *
180
+ * @example
181
+ * <form [formGroup]="myForm" ngxFormDraft="myFormId">
182
+ *
183
+ * @example
184
+ * <form [formGroup]="myForm" [ngxFormDraft]="'edit_' + entityId" [draftExcludeFields]="['password']">
185
+ */
186
+ class FormDraftDirective {
187
+ constructor(formGroupDir, ngForm, draftService, viewContainerRef, cdRef, elRef, renderer) {
188
+ this.formGroupDir = formGroupDir;
189
+ this.ngForm = ngForm;
190
+ this.draftService = draftService;
191
+ this.viewContainerRef = viewContainerRef;
192
+ this.cdRef = cdRef;
193
+ this.elRef = elRef;
194
+ this.renderer = renderer;
195
+ this.draftDebounce = 800;
196
+ this.draftExcludeFields = [];
197
+ this.draftShowOnChange = false;
198
+ this.draftRestoredText = 'Draft restored';
199
+ this.draftSavedText = 'Draft saved';
200
+ this.draftSavedLabel = 'saved';
201
+ this.draftDiscardText = 'Discard';
202
+ this.destroy$ = new Subject();
203
+ this.bannerRef = null;
204
+ this.formControl = null;
205
+ this.initialValues = {};
206
+ this.isRestoring = false;
207
+ }
208
+ ngOnInit() {
209
+ this.formControl = this.formGroupDir?.form || this.ngForm?.form || null;
210
+ if (!this.formControl || !this.formId)
211
+ return;
212
+ this.initialValues = JSON.parse(JSON.stringify(this.formControl.value));
213
+ const draft = this.draftService.load(this.formId);
214
+ if (draft) {
215
+ this.restoreDraft(draft.values);
216
+ this.showBanner(draft.savedAt, true);
217
+ }
218
+ this.formControl.valueChanges
219
+ .pipe(debounceTime(this.draftDebounce), takeUntil(this.destroy$))
220
+ .subscribe((values) => {
221
+ if (this.isRestoring)
222
+ return;
223
+ this.saveDraft(values);
224
+ });
225
+ }
226
+ ngOnDestroy() {
227
+ this.destroy$.next();
228
+ this.destroy$.complete();
229
+ this.destroyBanner();
230
+ }
231
+ saveDraft(values) {
232
+ const filtered = this.filterFields(values);
233
+ if (this.isAllEmpty(filtered) || this.matchesInitialValues(filtered)) {
234
+ return;
235
+ }
236
+ this.draftService.save(this.formId, filtered);
237
+ if (this.draftShowOnChange && !this.bannerRef) {
238
+ this.showBanner(Date.now(), false);
239
+ }
240
+ }
241
+ filterFields(values) {
242
+ if (!this.draftExcludeFields.length)
243
+ return values;
244
+ const result = { ...values };
245
+ this.draftExcludeFields.forEach(field => delete result[field]);
246
+ return result;
247
+ }
248
+ isAllEmpty(values) {
249
+ return Object.values(values).every(v => v === null || v === undefined || v === '' || (Array.isArray(v) && v.length === 0));
250
+ }
251
+ matchesInitialValues(values) {
252
+ return JSON.stringify(values) === JSON.stringify(this.initialValues);
253
+ }
254
+ restoreDraft(values) {
255
+ if (!this.formControl)
256
+ return;
257
+ this.isRestoring = true;
258
+ const form = this.formGroupDir?.form || this.ngForm?.form;
259
+ if (form) {
260
+ this.prepareFormArrays(form, values);
261
+ form.patchValue(values);
262
+ }
263
+ setTimeout(() => this.isRestoring = false, 100);
264
+ }
265
+ prepareFormArrays(control, value) {
266
+ if (!control || value == null)
267
+ return;
268
+ if (control instanceof FormGroup && value && typeof value === 'object' && !Array.isArray(value)) {
269
+ Object.keys(value).forEach(key => {
270
+ const childControl = control.get(key);
271
+ if (childControl)
272
+ this.prepareFormArrays(childControl, value[key]);
273
+ });
274
+ return;
275
+ }
276
+ if (control instanceof FormArray && Array.isArray(value)) {
277
+ const formArray = control;
278
+ while (formArray.length < value.length) {
279
+ const template = formArray.at(0);
280
+ if (template instanceof FormGroup) {
281
+ const newGroup = new FormGroup({});
282
+ Object.keys(template.controls).forEach(ctrlName => {
283
+ const existing = template.get(ctrlName);
284
+ if (existing instanceof FormArray) {
285
+ newGroup.addControl(ctrlName, new FormArray([]));
286
+ }
287
+ else if (existing instanceof FormGroup) {
288
+ newGroup.addControl(ctrlName, new FormGroup({}));
289
+ }
290
+ else {
291
+ newGroup.addControl(ctrlName, new FormControl(null));
292
+ }
293
+ });
294
+ formArray.push(newGroup);
295
+ }
296
+ else if (template) {
297
+ formArray.push(new FormControl(null));
298
+ }
299
+ else {
300
+ const firstValue = value[0];
301
+ if (firstValue && typeof firstValue === 'object' && !Array.isArray(firstValue)) {
302
+ const group = new FormGroup({});
303
+ Object.keys(firstValue).forEach(key => group.addControl(key, new FormControl(null)));
304
+ formArray.push(group);
305
+ }
306
+ else {
307
+ formArray.push(new FormControl(null));
308
+ }
309
+ }
310
+ }
311
+ while (formArray.length > value.length) {
312
+ formArray.removeAt(formArray.length - 1);
313
+ }
314
+ value.forEach((childValue, index) => {
315
+ this.prepareFormArrays(formArray.at(index), childValue);
316
+ });
317
+ }
318
+ }
319
+ discardDraft() {
320
+ this.draftService.clear(this.formId);
321
+ if (this.formControl) {
322
+ this.isRestoring = true;
323
+ const form = this.formGroupDir?.form || this.ngForm?.form;
324
+ if (form) {
325
+ this.prepareFormArrays(form, this.initialValues);
326
+ form.reset(this.initialValues);
327
+ }
328
+ setTimeout(() => {
329
+ this.isRestoring = false;
330
+ }, this.draftDebounce + 200);
331
+ }
332
+ this.destroyBanner();
333
+ }
334
+ showBanner(savedAt, isRestored = false) {
335
+ this.bannerRef = this.viewContainerRef.createComponent(FormDraftBannerComponent);
336
+ this.bannerRef.setInput('visible', true);
337
+ this.bannerRef.setInput('isRestored', isRestored);
338
+ this.bannerRef.setInput('timeLabel', isRestored ? this.draftService.formatTimestamp(savedAt) : '');
339
+ this.bannerRef.setInput('restoredText', this.draftRestoredText);
340
+ this.bannerRef.setInput('savedText', this.draftSavedText);
341
+ this.bannerRef.setInput('savedLabel', this.draftSavedLabel);
342
+ this.bannerRef.setInput('discardText', this.draftDiscardText);
343
+ this.bannerRef.instance.discard.subscribe(() => this.discardDraft());
344
+ const bannerEl = this.bannerRef.location.nativeElement;
345
+ const formEl = this.elRef.nativeElement;
346
+ this.renderer.insertBefore(formEl, bannerEl, formEl.firstChild);
347
+ this.cdRef.detectChanges();
348
+ }
349
+ destroyBanner() {
350
+ if (this.bannerRef) {
351
+ this.bannerRef.destroy();
352
+ this.bannerRef = null;
353
+ }
354
+ }
355
+ clearDraft() {
356
+ this.draftService.clear(this.formId);
357
+ this.destroyBanner();
358
+ }
359
+ }
360
+ FormDraftDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FormDraftDirective, deps: [{ token: i1$1.FormGroupDirective, optional: true }, { token: i1$1.NgForm, optional: true }, { token: FormDraftService }, { token: i0.ViewContainerRef }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Directive });
361
+ FormDraftDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.3.0", type: FormDraftDirective, selector: "[ngxFormDraft]", inputs: { formId: ["ngxFormDraft", "formId"], draftDebounce: "draftDebounce", draftExcludeFields: "draftExcludeFields", draftShowOnChange: "draftShowOnChange", draftRestoredText: "draftRestoredText", draftSavedText: "draftSavedText", draftSavedLabel: "draftSavedLabel", draftDiscardText: "draftDiscardText" }, ngImport: i0 });
362
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FormDraftDirective, decorators: [{
363
+ type: Directive,
364
+ args: [{
365
+ selector: '[ngxFormDraft]',
366
+ }]
367
+ }], ctorParameters: function () { return [{ type: i1$1.FormGroupDirective, decorators: [{
368
+ type: Optional
369
+ }] }, { type: i1$1.NgForm, decorators: [{
370
+ type: Optional
371
+ }] }, { type: FormDraftService }, { type: i0.ViewContainerRef }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i0.Renderer2 }]; }, propDecorators: { formId: [{
372
+ type: Input,
373
+ args: ['ngxFormDraft']
374
+ }], draftDebounce: [{
375
+ type: Input
376
+ }], draftExcludeFields: [{
377
+ type: Input
378
+ }], draftShowOnChange: [{
379
+ type: Input
380
+ }], draftRestoredText: [{
381
+ type: Input
382
+ }], draftSavedText: [{
383
+ type: Input
384
+ }], draftSavedLabel: [{
385
+ type: Input
386
+ }], draftDiscardText: [{
387
+ type: Input
388
+ }] } });
389
+
390
+ class NgxFormDraftModule {
391
+ }
392
+ NgxFormDraftModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgxFormDraftModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
393
+ NgxFormDraftModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: NgxFormDraftModule, declarations: [FormDraftDirective, FormDraftBannerComponent], imports: [CommonModule], exports: [FormDraftDirective, FormDraftBannerComponent] });
394
+ NgxFormDraftModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgxFormDraftModule, imports: [CommonModule] });
395
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NgxFormDraftModule, decorators: [{
396
+ type: NgModule,
397
+ args: [{
398
+ declarations: [FormDraftDirective, FormDraftBannerComponent],
399
+ imports: [CommonModule],
400
+ exports: [FormDraftDirective, FormDraftBannerComponent],
401
+ }]
402
+ }] });
403
+
404
+ /**
405
+ * Generated bundle index. Do not edit.
406
+ */
407
+
408
+ export { FormDraftBannerComponent, FormDraftDirective, FormDraftService, NgxFormDraftModule };
409
+ //# sourceMappingURL=ngx-form-draft.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-form-draft.mjs","sources":["../../src/form-draft-banner.component.ts","../../src/form-draft.service.ts","../../src/form-draft.directive.ts","../../src/ngx-form-draft.module.ts","../../src/ngx-form-draft.ts"],"sourcesContent":["import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';\nimport { trigger, transition, style, animate } from '@angular/animations';\n\n@Component({\n selector: 'ngx-form-draft-banner',\n template: `\n <div class=\"form-draft-banner\" *ngIf=\"visible\" [@slideDown]>\n <div class=\"form-draft-banner__icon\">\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M12 8V12L14.5 14.5\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <circle cx=\"12\" cy=\"12\" r=\"9\" stroke=\"currentColor\" stroke-width=\"2\"/>\n </svg>\n </div>\n <div class=\"form-draft-banner__content\">\n <span class=\"form-draft-banner__text\">\n <span *ngIf=\"isRestored\">{{ restoredText }}</span>\n <span *ngIf=\"!isRestored\">{{ savedText }}</span>\n <span class=\"form-draft-banner__time\" *ngIf=\"timeLabel && isRestored\">\n &middot; {{ savedLabel }} {{ timeLabel }}\n </span>\n </span>\n </div>\n <div class=\"form-draft-banner__actions\">\n <button class=\"form-draft-banner__btn form-draft-banner__btn--discard\" (click)=\"discard.emit()\" type=\"button\">\n ✕ {{ discardText }}\n </button>\n </div>\n </div>\n `,\n styles: [`\n :host { display: block; width: 100%; }\n .form-draft-banner {\n display: flex; align-items: center; gap: 10px; padding: 10px 14px; margin-bottom: 12px;\n border-radius: 8px; background: linear-gradient(135deg, #eef6ff 0%, #f0f4ff 100%);\n border: 1px solid #c5ddf8; box-shadow: 0 2px 8px rgba(18, 138, 214, 0.08);\n }\n .form-draft-banner__icon {\n display: flex; align-items: center; justify-content: center; width: 32px; height: 32px;\n border-radius: 6px; background: linear-gradient(135deg, #128ad6, #22b9ff); color: #fff; flex-shrink: 0;\n }\n .form-draft-banner__content { flex: 1; min-width: 0; }\n .form-draft-banner__text { font-size: 13px; font-weight: 600; color: #1a3a5c; }\n .form-draft-banner__time { font-weight: 400; color: #6b8aaa; font-size: 12px; }\n .form-draft-banner__actions { flex-shrink: 0; }\n .form-draft-banner__btn {\n border: none; padding: 5px 12px; border-radius: 6px; font-size: 12px;\n font-weight: 600; cursor: pointer; transition: all 0.2s ease;\n }\n .form-draft-banner__btn--discard { background: transparent; color: #8899a6; border: 1px solid #d0dce6; }\n .form-draft-banner__btn--discard:hover { background: #fef2f2; color: #e62e43; border-color: #e62e43; }\n `],\n animations: [\n trigger('slideDown', [\n transition(':enter', [\n style({ opacity: 0, transform: 'translateY(-8px)' }),\n animate('250ms cubic-bezier(0.4, 0, 0.2, 1)', style({ opacity: 1, transform: 'translateY(0)' }))\n ]),\n transition(':leave', [\n animate('200ms cubic-bezier(0.4, 0, 0.2, 1)', style({ opacity: 0, transform: 'translateY(-8px)' }))\n ])\n ])\n ],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class FormDraftBannerComponent {\n @Input() visible = false;\n @Input() timeLabel = '';\n @Input() isRestored = false;\n @Input() restoredText = 'Draft restored';\n @Input() savedText = 'Draft saved';\n @Input() savedLabel = 'saved';\n @Input() discardText = 'Discard';\n @Output() discard = new EventEmitter<void>();\n}\n","import { Injectable } from '@angular/core';\n\nexport interface FormDraftData {\n values: Record<string, any>;\n savedAt: number;\n formId: string;\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class FormDraftService {\n private readonly STORAGE_PREFIX = 'form_draft_';\n private readonly MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;\n\n private buildKey(formId: string): string {\n return `${this.STORAGE_PREFIX}${formId}`;\n }\n\n save(formId: string, values: Record<string, any>): void {\n try {\n const draft: FormDraftData = { values, savedAt: Date.now(), formId };\n localStorage.setItem(this.buildKey(formId), JSON.stringify(draft));\n } catch (e) {\n console.warn('[FormDraft] Could not save draft:', e);\n }\n }\n\n load(formId: string): FormDraftData | null {\n try {\n const raw = localStorage.getItem(this.buildKey(formId));\n if (!raw) return null;\n\n const draft: FormDraftData = JSON.parse(raw);\n if (Date.now() - draft.savedAt > this.MAX_AGE_MS) {\n this.clear(formId);\n return null;\n }\n return draft;\n } catch (e) {\n console.warn('[FormDraft] Could not load draft:', e);\n return null;\n }\n }\n\n clear(formId: string): void {\n try {\n localStorage.removeItem(this.buildKey(formId));\n } catch (e) {\n console.warn('[FormDraft] Could not clear draft:', e);\n }\n }\n\n formatTimestamp(timestamp: number): string {\n const seconds = Math.floor((Date.now() - timestamp) / 1000);\n if (seconds < 60) return 'just now';\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return `${days}d ago`;\n }\n}\n","import {\n Directive, Input, OnInit, OnDestroy, Optional, ComponentRef,\n ViewContainerRef, ChangeDetectorRef, ElementRef, Renderer2,\n} from '@angular/core';\nimport { NgForm, FormGroupDirective, AbstractControl, FormArray, FormGroup, FormControl } from '@angular/forms';\nimport { Subject } from 'rxjs';\nimport { debounceTime, takeUntil } from 'rxjs/operators';\nimport { FormDraftService } from './form-draft.service';\nimport { FormDraftBannerComponent } from './form-draft-banner.component';\n\n/**\n * Auto-saves and restores form drafts\n * \n * @example\n * <form [formGroup]=\"myForm\" ngxFormDraft=\"myFormId\">\n * \n * @example\n * <form [formGroup]=\"myForm\" [ngxFormDraft]=\"'edit_' + entityId\" [draftExcludeFields]=\"['password']\">\n */\n@Directive({\n selector: '[ngxFormDraft]',\n})\nexport class FormDraftDirective implements OnInit, OnDestroy {\n @Input('ngxFormDraft') formId!: string;\n @Input() draftDebounce = 800;\n @Input() draftExcludeFields: string[] = [];\n @Input() draftShowOnChange = false;\n @Input() draftRestoredText = 'Draft restored';\n @Input() draftSavedText = 'Draft saved';\n @Input() draftSavedLabel = 'saved';\n @Input() draftDiscardText = 'Discard';\n\n private destroy$ = new Subject<void>();\n private bannerRef: ComponentRef<FormDraftBannerComponent> | null = null;\n private formControl: AbstractControl | null = null;\n private initialValues: Record<string, any> = {};\n private isRestoring = false;\n\n constructor(\n @Optional() private formGroupDir: FormGroupDirective,\n @Optional() private ngForm: NgForm,\n private draftService: FormDraftService,\n private viewContainerRef: ViewContainerRef,\n private cdRef: ChangeDetectorRef,\n private elRef: ElementRef,\n private renderer: Renderer2,\n ) {}\n\n ngOnInit(): void {\n this.formControl = this.formGroupDir?.form || this.ngForm?.form || null;\n if (!this.formControl || !this.formId) return;\n\n this.initialValues = JSON.parse(JSON.stringify(this.formControl.value));\n\n const draft = this.draftService.load(this.formId);\n if (draft) {\n this.restoreDraft(draft.values);\n this.showBanner(draft.savedAt, true);\n }\n\n this.formControl.valueChanges\n .pipe(debounceTime(this.draftDebounce), takeUntil(this.destroy$))\n .subscribe((values) => {\n if (this.isRestoring) return;\n this.saveDraft(values);\n });\n }\n\n ngOnDestroy(): void {\n this.destroy$.next();\n this.destroy$.complete();\n this.destroyBanner();\n }\n\n private saveDraft(values: Record<string, any>): void {\n const filtered = this.filterFields(values);\n \n if (this.isAllEmpty(filtered) || this.matchesInitialValues(filtered)) {\n return;\n }\n\n this.draftService.save(this.formId, filtered);\n if (this.draftShowOnChange && !this.bannerRef) {\n this.showBanner(Date.now(), false);\n }\n }\n\n private filterFields(values: Record<string, any>): Record<string, any> {\n if (!this.draftExcludeFields.length) return values;\n const result = { ...values };\n this.draftExcludeFields.forEach(field => delete result[field]);\n return result;\n }\n\n private isAllEmpty(values: Record<string, any>): boolean {\n return Object.values(values).every(\n v => v === null || v === undefined || v === '' || (Array.isArray(v) && v.length === 0)\n );\n }\n\n private matchesInitialValues(values: Record<string, any>): boolean {\n return JSON.stringify(values) === JSON.stringify(this.initialValues);\n }\n\n private restoreDraft(values: Record<string, any>): void {\n if (!this.formControl) return;\n this.isRestoring = true;\n\n const form = this.formGroupDir?.form || this.ngForm?.form;\n if (form) {\n this.prepareFormArrays(form, values);\n form.patchValue(values);\n }\n\n setTimeout(() => this.isRestoring = false, 100);\n }\n\n private prepareFormArrays(control: AbstractControl, value: any): void {\n if (!control || value == null) return;\n\n if (control instanceof FormGroup && value && typeof value === 'object' && !Array.isArray(value)) {\n Object.keys(value).forEach(key => {\n const childControl = control.get(key);\n if (childControl) this.prepareFormArrays(childControl, value[key]);\n });\n return;\n }\n\n if (control instanceof FormArray && Array.isArray(value)) {\n const formArray = control as FormArray;\n\n while (formArray.length < value.length) {\n const template = formArray.at(0);\n if (template instanceof FormGroup) {\n const newGroup = new FormGroup({});\n Object.keys(template.controls).forEach(ctrlName => {\n const existing = template.get(ctrlName) as AbstractControl;\n if (existing instanceof FormArray) {\n newGroup.addControl(ctrlName, new FormArray([]));\n } else if (existing instanceof FormGroup) {\n newGroup.addControl(ctrlName, new FormGroup({}));\n } else {\n newGroup.addControl(ctrlName, new FormControl(null));\n }\n });\n formArray.push(newGroup);\n } else if (template) {\n formArray.push(new FormControl(null));\n } else {\n const firstValue = value[0];\n if (firstValue && typeof firstValue === 'object' && !Array.isArray(firstValue)) {\n const group = new FormGroup({});\n Object.keys(firstValue).forEach(key => group.addControl(key, new FormControl(null)));\n formArray.push(group);\n } else {\n formArray.push(new FormControl(null));\n }\n }\n }\n\n while (formArray.length > value.length) {\n formArray.removeAt(formArray.length - 1);\n }\n\n value.forEach((childValue, index) => {\n this.prepareFormArrays(formArray.at(index), childValue);\n });\n }\n }\n\n private discardDraft(): void {\n this.draftService.clear(this.formId);\n\n if (this.formControl) {\n this.isRestoring = true;\n const form = this.formGroupDir?.form || this.ngForm?.form;\n if (form) {\n this.prepareFormArrays(form, this.initialValues);\n form.reset(this.initialValues);\n }\n setTimeout(() => {\n this.isRestoring = false;\n }, this.draftDebounce + 200);\n }\n\n this.destroyBanner();\n }\n\n private showBanner(savedAt: number, isRestored = false): void {\n this.bannerRef = this.viewContainerRef.createComponent(FormDraftBannerComponent);\n this.bannerRef.setInput('visible', true);\n this.bannerRef.setInput('isRestored', isRestored);\n this.bannerRef.setInput('timeLabel', isRestored ? this.draftService.formatTimestamp(savedAt) : '');\n this.bannerRef.setInput('restoredText', this.draftRestoredText);\n this.bannerRef.setInput('savedText', this.draftSavedText);\n this.bannerRef.setInput('savedLabel', this.draftSavedLabel);\n this.bannerRef.setInput('discardText', this.draftDiscardText);\n\n this.bannerRef.instance.discard.subscribe(() => this.discardDraft());\n\n const bannerEl = this.bannerRef.location.nativeElement;\n const formEl = this.elRef.nativeElement;\n this.renderer.insertBefore(formEl, bannerEl, formEl.firstChild);\n\n this.cdRef.detectChanges();\n }\n\n private destroyBanner(): void {\n if (this.bannerRef) {\n this.bannerRef.destroy();\n this.bannerRef = null;\n }\n }\n\n public clearDraft(): void {\n this.draftService.clear(this.formId);\n this.destroyBanner();\n }\n}\n","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormDraftDirective } from './form-draft.directive';\nimport { FormDraftBannerComponent } from './form-draft-banner.component';\n\n@NgModule({\n declarations: [FormDraftDirective, FormDraftBannerComponent],\n imports: [CommonModule],\n exports: [FormDraftDirective, FormDraftBannerComponent],\n})\nexport class NgxFormDraftModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1","i2.FormDraftService"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { EventEmitter } from '@angular/core';
2
+ import * as i0 from "@angular/core";
2
3
  export declare class FormDraftBannerComponent {
3
4
  visible: boolean;
4
5
  timeLabel: string;
@@ -8,4 +9,6 @@ export declare class FormDraftBannerComponent {
8
9
  savedLabel: string;
9
10
  discardText: string;
10
11
  discard: EventEmitter<void>;
12
+ static ɵfac: i0.ɵɵFactoryDeclaration<FormDraftBannerComponent, never>;
13
+ static ɵcmp: i0.ɵɵComponentDeclaration<FormDraftBannerComponent, "ngx-form-draft-banner", never, { "visible": "visible"; "timeLabel": "timeLabel"; "isRestored": "isRestored"; "restoredText": "restoredText"; "savedText": "savedText"; "savedLabel": "savedLabel"; "discardText": "discardText"; }, { "discard": "discard"; }, never, never, false>;
11
14
  }
@@ -1,6 +1,7 @@
1
1
  import { OnInit, OnDestroy, ViewContainerRef, ChangeDetectorRef, ElementRef, Renderer2 } from '@angular/core';
2
2
  import { NgForm, FormGroupDirective } from '@angular/forms';
3
3
  import { FormDraftService } from './form-draft.service';
4
+ import * as i0 from "@angular/core";
4
5
  /**
5
6
  * Auto-saves and restores form drafts
6
7
  *
@@ -44,4 +45,6 @@ export declare class FormDraftDirective implements OnInit, OnDestroy {
44
45
  private showBanner;
45
46
  private destroyBanner;
46
47
  clearDraft(): void;
48
+ static ɵfac: i0.ɵɵFactoryDeclaration<FormDraftDirective, [{ optional: true; }, { optional: true; }, null, null, null, null, null]>;
49
+ static ɵdir: i0.ɵɵDirectiveDeclaration<FormDraftDirective, "[ngxFormDraft]", never, { "formId": "ngxFormDraft"; "draftDebounce": "draftDebounce"; "draftExcludeFields": "draftExcludeFields"; "draftShowOnChange": "draftShowOnChange"; "draftRestoredText": "draftRestoredText"; "draftSavedText": "draftSavedText"; "draftSavedLabel": "draftSavedLabel"; "draftDiscardText": "draftDiscardText"; }, {}, never, never, false>;
47
50
  }
@@ -1,3 +1,4 @@
1
+ import * as i0 from "@angular/core";
1
2
  export interface FormDraftData {
2
3
  values: Record<string, any>;
3
4
  savedAt: number;
@@ -11,4 +12,6 @@ export declare class FormDraftService {
11
12
  load(formId: string): FormDraftData | null;
12
13
  clear(formId: string): void;
13
14
  formatTimestamp(timestamp: number): string;
15
+ static ɵfac: i0.ɵɵFactoryDeclaration<FormDraftService, never>;
16
+ static ɵprov: i0.ɵɵInjectableDeclaration<FormDraftService>;
14
17
  }
@@ -1,2 +1,9 @@
1
+ import * as i0 from "@angular/core";
2
+ import * as i1 from "./form-draft.directive";
3
+ import * as i2 from "./form-draft-banner.component";
4
+ import * as i3 from "@angular/common";
1
5
  export declare class NgxFormDraftModule {
6
+ static ɵfac: i0.ɵɵFactoryDeclaration<NgxFormDraftModule, never>;
7
+ static ɵmod: i0.ɵɵNgModuleDeclaration<NgxFormDraftModule, [typeof i1.FormDraftDirective, typeof i2.FormDraftBannerComponent], [typeof i3.CommonModule], [typeof i1.FormDraftDirective, typeof i2.FormDraftBannerComponent]>;
8
+ static ɵinj: i0.ɵɵInjectorDeclaration<NgxFormDraftModule>;
2
9
  }
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "ngx-form-draft",
3
+ "version": "1.0.3",
4
+ "description": "Auto-save and restore Angular form drafts with zero dependencies",
5
+ "main": "dist/bundles/ngx-form-draft.umd.js",
6
+ "module": "fesm2015/ngx-form-draft.mjs",
7
+ "es2015": "dist/fesm2015/ngx-form-draft.js",
8
+ "esm2015": "dist/esm2015/index.js",
9
+ "fesm2015": "fesm2015/ngx-form-draft.mjs",
10
+ "typings": "index.d.ts",
11
+ "author": "Karam",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/neokyuubi/ngx-form-draft.git"
15
+ },
16
+ "bugs": {
17
+ "url": "https://github.com/neokyuubi/ngx-form-draft/issues"
18
+ },
19
+ "homepage": "https://github.com/neokyuubi/ngx-form-draft#readme",
20
+ "peerDependencies": {
21
+ "@angular/core": ">=12.0.0",
22
+ "@angular/common": ">=12.0.0",
23
+ "@angular/forms": ">=12.0.0",
24
+ "@angular/animations": ">=12.0.0",
25
+ "rxjs": ">=6.0.0"
26
+ },
27
+ "keywords": [
28
+ "angular",
29
+ "forms",
30
+ "draft",
31
+ "autosave",
32
+ "reactive-forms",
33
+ "template-driven-forms",
34
+ "form-array",
35
+ "localstorage",
36
+ "angular-directive"
37
+ ],
38
+ "license": "MIT",
39
+ "files": [
40
+ "dist",
41
+ "README.md",
42
+ "LICENSE"
43
+ ],
44
+ "es2020": "fesm2020/ngx-form-draft.mjs",
45
+ "esm2020": "esm2020/ngx-form-draft.mjs",
46
+ "fesm2020": "fesm2020/ngx-form-draft.mjs",
47
+ "exports": {
48
+ "./package.json": {
49
+ "default": "./package.json"
50
+ },
51
+ ".": {
52
+ "types": "./index.d.ts",
53
+ "esm2020": "./esm2020/ngx-form-draft.mjs",
54
+ "es2020": "./fesm2020/ngx-form-draft.mjs",
55
+ "es2015": "./fesm2015/ngx-form-draft.mjs",
56
+ "node": "./fesm2015/ngx-form-draft.mjs",
57
+ "default": "./fesm2020/ngx-form-draft.mjs"
58
+ }
59
+ },
60
+ "sideEffects": false,
61
+ "dependencies": {
62
+ "tslib": "^2.0.0"
63
+ }
64
+ }
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "ngx-form-draft",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Auto-save and restore Angular form drafts with zero dependencies",
5
- "main": "dist/index.js",
6
- "module": "dist/index.js",
7
- "types": "dist/index.d.ts",
5
+ "main": "dist/bundles/ngx-form-draft.umd.js",
6
+ "module": "dist/fesm2015/ngx-form-draft.js",
7
+ "es2015": "dist/fesm2015/ngx-form-draft.js",
8
+ "esm2015": "dist/esm2015/index.js",
9
+ "fesm2015": "dist/fesm2015/ngx-form-draft.js",
10
+ "typings": "dist/index.d.ts",
8
11
  "author": "Karam",
9
12
  "repository": {
10
13
  "type": "git",
@@ -23,10 +26,22 @@
23
26
  "tslib": "^2.0.0"
24
27
  },
25
28
  "devDependencies": {
26
- "typescript": "^4.7.0"
29
+ "@angular/animations": "^14.0.0",
30
+ "@angular/common": "^14.0.0",
31
+ "@angular/compiler": "^14.0.0",
32
+ "@angular/compiler-cli": "^14.0.0",
33
+ "@angular/core": "^14.0.0",
34
+ "@angular/forms": "^14.0.0",
35
+ "@angular/platform-browser": "^14.0.0",
36
+ "@angular/platform-browser-dynamic": "^14.0.0",
37
+ "ng-packagr": "^14.0.0",
38
+ "rxjs": "^7.5.0",
39
+ "tslib": "^2.3.0",
40
+ "typescript": "~4.7.0",
41
+ "zone.js": "~0.11.4"
27
42
  },
28
43
  "scripts": {
29
- "build": "tsc",
44
+ "build": "ng-packagr -p ng-package.json",
30
45
  "prepublishOnly": "npm run build"
31
46
  },
32
47
  "keywords": [