@bcweed/dynamic-form-lib 0.0.1

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.
Files changed (63) hide show
  1. package/.editorconfig +17 -0
  2. package/.postcssrc.json +5 -0
  3. package/.vscode/extensions.json +4 -0
  4. package/.vscode/launch.json +20 -0
  5. package/.vscode/tasks.json +42 -0
  6. package/AngularDynamicFormLibrary.esproj +13 -0
  7. package/CHANGELOG.md +16 -0
  8. package/README.md +59 -0
  9. package/angular.json +169 -0
  10. package/aspnetcore-https.js +37 -0
  11. package/karma.conf.js +44 -0
  12. package/obj/Debug/AngularDynamicFormLibrary.esproj.CoreCompileInputs.cache +0 -0
  13. package/obj/Debug/AngularDynamicFormLibrary.esproj.FileListAbsolute.txt +1 -0
  14. package/obj/Debug/package.g.props +56 -0
  15. package/package.json +65 -0
  16. package/postcss.config.js +6 -0
  17. package/projects/dynamic-form-lib/.postcssrc.json +5 -0
  18. package/projects/dynamic-form-lib/README.md +63 -0
  19. package/projects/dynamic-form-lib/ng-package.json +10 -0
  20. package/projects/dynamic-form-lib/package.json +27 -0
  21. package/projects/dynamic-form-lib/src/lib/README.md +424 -0
  22. package/projects/dynamic-form-lib/src/lib/SUMMARY.md +159 -0
  23. package/projects/dynamic-form-lib/src/lib/directives/dynamic-ref-directive.ts +13 -0
  24. package/projects/dynamic-form-lib/src/lib/dynamic-form-demo/dynamic-form-demo.component.html +75 -0
  25. package/projects/dynamic-form-lib/src/lib/dynamic-form-demo/dynamic-form-demo.component.scss +127 -0
  26. package/projects/dynamic-form-lib/src/lib/dynamic-form-demo/dynamic-form-demo.component.ts +50 -0
  27. package/projects/dynamic-form-lib/src/lib/dynamic-form-field/dynamic-form-field.component.html +234 -0
  28. package/projects/dynamic-form-lib/src/lib/dynamic-form-field/dynamic-form-field.component.scss +315 -0
  29. package/projects/dynamic-form-lib/src/lib/dynamic-form-field/dynamic-form-field.component.ts +219 -0
  30. package/projects/dynamic-form-lib/src/lib/dynamic-form.component.html +137 -0
  31. package/projects/dynamic-form-lib/src/lib/dynamic-form.component.scss +141 -0
  32. package/projects/dynamic-form-lib/src/lib/dynamic-form.component.ts +366 -0
  33. package/projects/dynamic-form-lib/src/lib/helpers/component-helper.ts +54 -0
  34. package/projects/dynamic-form-lib/src/lib/index.ts +10 -0
  35. package/projects/dynamic-form-lib/src/lib/models/dynamic-form-interfaces.ts +117 -0
  36. package/projects/dynamic-form-lib/src/lib/services/dynamic-form.service.spec.ts +302 -0
  37. package/projects/dynamic-form-lib/src/lib/services/dynamic-form.service.ts +325 -0
  38. package/projects/dynamic-form-lib/src/lib/style.css +4 -0
  39. package/projects/dynamic-form-lib/src/lib/style.scss +3 -0
  40. package/projects/dynamic-form-lib/src/lib/tailwind-output.css +0 -0
  41. package/projects/dynamic-form-lib/src/lib/validators/compare-validator.ts +26 -0
  42. package/projects/dynamic-form-lib/src/public-api.css +1 -0
  43. package/projects/dynamic-form-lib/src/public-api.ts +10 -0
  44. package/projects/dynamic-form-lib/tailwind.config.js +10 -0
  45. package/projects/dynamic-form-lib/tsconfig.lib.json +15 -0
  46. package/projects/dynamic-form-lib/tsconfig.lib.prod.json +11 -0
  47. package/projects/dynamic-form-lib/tsconfig.spec.json +15 -0
  48. package/public/favicon.ico +0 -0
  49. package/src/app/app-routing.module.ts +10 -0
  50. package/src/app/app.component.css +0 -0
  51. package/src/app/app.component.html +18 -0
  52. package/src/app/app.component.spec.ts +35 -0
  53. package/src/app/app.component.ts +1038 -0
  54. package/src/app/app.config.ts +45 -0
  55. package/src/app/app.module.ts +46 -0
  56. package/src/app/app.routes.ts +8 -0
  57. package/src/index.html +13 -0
  58. package/src/main.ts +16 -0
  59. package/src/styles.css +2 -0
  60. package/tailwind.config.js +10 -0
  61. package/tsconfig.app.json +15 -0
  62. package/tsconfig.json +32 -0
  63. package/tsconfig.spec.json +15 -0
@@ -0,0 +1,127 @@
1
+ .demo-container {
2
+ padding: 2rem 0;
3
+
4
+ .info-panel,
5
+ .help-panel {
6
+ margin-bottom: 1rem;
7
+ padding: 1.5rem;
8
+
9
+ h5, h6 {
10
+ margin-top: 0;
11
+ color: #333;
12
+ }
13
+
14
+ hr {
15
+ margin: 1rem 0;
16
+ }
17
+ }
18
+
19
+ .info-panel {
20
+ background-color: #f8f9fa;
21
+
22
+ .status-item {
23
+ display: flex;
24
+ justify-content: space-between;
25
+ padding: 0.5rem 0;
26
+ border-bottom: 1px solid #dee2e6;
27
+
28
+ &:last-child {
29
+ border-bottom: none;
30
+ }
31
+
32
+ label {
33
+ font-weight: 500;
34
+ color: #666;
35
+ }
36
+
37
+ .status-success {
38
+ color: #28a745;
39
+ font-weight: 600;
40
+ }
41
+
42
+ .status-error {
43
+ color: #dc3545;
44
+ font-weight: 600;
45
+ }
46
+
47
+ .status-info {
48
+ color: #17a2b8;
49
+ font-weight: 600;
50
+ }
51
+ }
52
+
53
+ .errors-section {
54
+ margin-top: 1rem;
55
+ padding-top: 1rem;
56
+ border-top: 2px solid #dee2e6;
57
+
58
+ h6 {
59
+ color: #dc3545;
60
+ margin-bottom: 0.5rem;
61
+ }
62
+
63
+ ul {
64
+ list-style: none;
65
+ padding: 0;
66
+ margin: 0;
67
+
68
+ .error-item {
69
+ padding: 0.25rem 0;
70
+ font-size: 0.9rem;
71
+ color: #666;
72
+
73
+ strong {
74
+ color: #dc3545;
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ .submitted-data {
81
+ margin-top: 1rem;
82
+ padding-top: 1rem;
83
+ border-top: 2px solid #dee2e6;
84
+
85
+ h6 {
86
+ color: #28a745;
87
+ margin-bottom: 0.5rem;
88
+ }
89
+
90
+ pre {
91
+ background-color: #fff;
92
+ border: 1px solid #dee2e6;
93
+ border-radius: 4px;
94
+ padding: 1rem;
95
+ font-size: 0.85rem;
96
+ max-height: 300px;
97
+ overflow-y: auto;
98
+ }
99
+ }
100
+ }
101
+
102
+ .help-panel {
103
+ background-color: #e7f3ff;
104
+ border-left: 4px solid #007bff;
105
+
106
+ ul {
107
+ margin: 0;
108
+ padding-left: 1.5rem;
109
+
110
+ li {
111
+ margin-bottom: 0.5rem;
112
+ color: #333;
113
+ }
114
+ }
115
+ }
116
+ }
117
+
118
+ @media (max-width: 768px) {
119
+ .demo-container {
120
+ padding: 1rem 0;
121
+
122
+ .col-md-8,
123
+ .col-md-4 {
124
+ margin-bottom: 1rem;
125
+ }
126
+ }
127
+ }
@@ -0,0 +1,50 @@
1
+ import { Component, OnInit } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { DynamicFormComponent } from '../dynamic-form.component';
4
+ import { DynamicFormConfig, DynamicFormValue, DynamicFormState } from '../models/dynamic-form-interfaces';
5
+ import { DynamicFormService } from '../services/dynamic-form.service';
6
+
7
+ @Component({
8
+ selector: 'app-dynamic-form-demo',
9
+ standalone: true,
10
+ imports: [CommonModule, DynamicFormComponent],
11
+ templateUrl: './dynamic-form-demo.component.html',
12
+ styleUrls: ['./dynamic-form-demo.component.scss']
13
+ })
14
+ export class DynamicFormDemoComponent implements OnInit {
15
+ formConfig!: DynamicFormConfig;
16
+ formValues: DynamicFormValue = {};
17
+ formState: DynamicFormState | null = null;
18
+ submittedData: any = null;
19
+
20
+ constructor(private dynamicFormService: DynamicFormService) {}
21
+
22
+ ngOnInit(): void {
23
+ }
24
+
25
+ onFormSubmit(values: DynamicFormValue): void {
26
+ console.log('Form submitted:', values);
27
+ this.submittedData = values;
28
+ alert('Form submitted successfully! Check console for values.');
29
+ }
30
+
31
+ onFormCancel(): void {
32
+ console.log('Form cancelled');
33
+ this.submittedData = null;
34
+ alert('Form cancelled');
35
+ }
36
+
37
+ onFormStateChange(state: DynamicFormState): void {
38
+ this.formState = state;
39
+ console.log('Form state changed:', state);
40
+ }
41
+
42
+
43
+ get formIsValid(): boolean {
44
+ return this.formState?.isValid ?? false;
45
+ }
46
+
47
+ get formErrorCount(): number {
48
+ return this.formState?.errors.length ?? 0;
49
+ }
50
+ }
@@ -0,0 +1,234 @@
1
+
2
+ <div [ngClass]="fieldClasses" [formGroup]="form">
3
+ <div [ngStyle]="{ width: fieldWidthStyle(), position: 'relative' }">
4
+ <!-- Label -->
5
+ <div *ngIf="field.leftPreInput" class="left-pre-input">
6
+ <span [innerHTML]="field.leftPreInput" class="left-pre-input-text">
7
+ </span>
8
+
9
+ </div>
10
+ <div #field_container class="input-container">
11
+ <div class="label-row" [ngStyle]="{ width: labelWidthStyle() }">
12
+ <label [attr.for]="field.id" class="control-label">
13
+ {{ field.label }}
14
+ <span *ngIf="field.required" class="required-indicator">*</span>
15
+ </label>
16
+ <div class="help-icons">
17
+ <i (click)="helpSideBarVisible = true" class="pi pi-question-circle" *ngIf="allowHelpSideBar && field.popInfo"></i>
18
+ <i (click)="popover.toggle($event)" class="pi pi-question-circle" *ngIf="allowHelpOverlay && field.popInfo"></i>
19
+ </div>
20
+ </div>
21
+ <!-- Text Input -->
22
+ <input *ngIf="field.type === 'text'"
23
+ [attr.data-dynamic-id]="field.id"
24
+ [refKey]="field.id" dynamicRef
25
+ [id]="field.id"
26
+ [formControlName]="controlName"
27
+ [placeholder]="field.placeholder || ''"
28
+ class="form-control"
29
+ type="text"
30
+ pInputText
31
+ [ngStyle]="{ width: inputWidthStyle() }"
32
+ tooltipPosition="bottom"
33
+ pTooltip="{{field.toolTip}}"
34
+ (blur)="onBlur()"
35
+ (onClick)="onClick($event)" />
36
+ <!-- Email Input -->
37
+ <input *ngIf="field.type === 'email'"
38
+ [attr.data-dynamic-id]="field.id"
39
+ [refKey]="field.id" dynamicRef
40
+ [id]="field.id"
41
+ [formControlName]="controlName"
42
+ [placeholder]="field.placeholder || ''"
43
+ class="form-control"
44
+ type="email"
45
+ pInputText
46
+ pTooltip="{{field.toolTip}}"
47
+ [ngStyle]="{ width: inputWidthStyle() }"
48
+ tooltipPosition="bottom"
49
+ (blur)="onBlur()"
50
+ (onClick)="onClick($event)" />
51
+ <!-- Number Input -->
52
+ <p-inputNumber *ngIf="field.type === 'number'"
53
+ [attr.data-dynamic-id]="field.id"
54
+ [refKey]="field.id" dynamicRef
55
+ [id]="field.id"
56
+ [inputId]="field.id"
57
+ [useGrouping]="false"
58
+ [minFractionDigits]="getDecimalPlace"
59
+ [min]="getMinValue"
60
+ [max]="getMaxValue"
61
+ [formControlName]="controlName"
62
+ [placeholder]="field.placeholder || ''"
63
+ styleClass="form-control"
64
+ pTooltip="{{field.toolTip}}"
65
+ [ngStyle]="{ width: inputWidthStyle() }"
66
+ tooltipPosition="bottom"
67
+ (onBlur)="onBlur()"
68
+ (onClick)="onClick($event)"></p-inputNumber>
69
+
70
+
71
+ <!-- phone -->
72
+
73
+ <p-inputMask *ngIf="field.type === 'phone'"
74
+ [attr.data-dynamic-id]="field.id"
75
+ [refKey]="field.id" dynamicRef
76
+ [id]="field.id"
77
+ [formControlName]="controlName"
78
+ [placeholder]="field.placeholder || ''"
79
+ mask="(999) 999-9999"
80
+ unmask="true"
81
+ styleClass="form-control-phone"
82
+ [ngStyle]="{ width: inputWidthStyle() }"
83
+ tooltipPosition="bottom"
84
+ pTooltip="{{field.toolTip}}"
85
+ (blur)="onBlur()"
86
+ (onClick)="onClick($event)"></p-inputMask>
87
+ <!-- Textarea -->
88
+ <textarea *ngIf="field.type === 'textarea'"
89
+ [attr.data-dynamic-id]="field.id"
90
+ [refKey]="field.id" dynamicRef
91
+ [id]="field.id"
92
+ [formControlName]="controlName"
93
+ [placeholder]="field.placeholder || ''"
94
+ [rows]="5"
95
+ class="form-control"
96
+ pInputTextarea
97
+ [ngStyle]="{ width: inputWidthStyle() }"
98
+ tooltipPosition="bottom"
99
+ pTooltip="{{field.toolTip}}"
100
+ (blur)="onBlur()"
101
+ (onClick)="onClick($event)"></textarea>
102
+
103
+ <!-- Date Picker -->
104
+ <p-datepicker *ngIf="field.type === 'date'"
105
+ [attr.data-dynamic-id]="field.id"
106
+ [refKey]="field.id" dynamicRef
107
+ [inputId]="field.id"
108
+ [id]="field.id"
109
+ [formControlName]="controlName"
110
+ [placeholder]="field.placeholder || ''"
111
+ styleClass="form-control-datepicker"
112
+ dateFormat="DD MM yy"
113
+ [showIcon]="true"
114
+ [style]="{ width: inputWidthStyle() }"
115
+ [ngStyle]="{ width: inputWidthStyle() }"
116
+ tooltipPosition="bottom"
117
+ pTooltip="{{field.toolTip}}"
118
+ (onBlur)="onBlur()"
119
+ (onClick)="onClick($event)"></p-datepicker>
120
+
121
+ <!-- Select Dropdown -->
122
+ <p-select *ngIf="field.type === 'select'"
123
+ [attr.data-dynamic-id]="field.id"
124
+ [refKey]="field.id" dynamicRef
125
+ [inputId]="field.id"
126
+ [formControlName]="controlName"
127
+ [id]="field.id"
128
+ appendTo="body"
129
+ [options]="field.options || []"
130
+ [placeholder]="field.placeholder || 'Select an option'"
131
+ optionLabel="label"
132
+ optionValue="value"
133
+ styleClass="form-control-select"
134
+ [showClear]="!field.required"
135
+ [ngStyle]="{ width: inputWidthStyle() }"
136
+ tooltipPosition="bottom"
137
+ pTooltip="{{field.toolTip}}"
138
+ (onBlur)="onBlur()"
139
+ (onClick)="onClick($event)"></p-select>
140
+
141
+ <!-- Checkbox -->
142
+ <div *ngIf="field.type === 'checkbox'" class="checkbox-wrapper">
143
+ <p-checkbox [attr.data-dynamic-id]="field.id"
144
+ [refKey]="field.id" dynamicRef
145
+ [id]="field.id"
146
+ [inputId]="field.id"
147
+ [formControlName]="controlName"
148
+ [style]="{ width: inputWidthStyle() }"
149
+ [ngStyle]="{ width: inputWidthStyle() }"
150
+ [binary]="true"
151
+ tooltipPosition="right"
152
+ pTooltip="{{field.toolTip}}"
153
+ (onBlur)="onBlur()"
154
+ (onClick)="onClick($event)"></p-checkbox>
155
+ </div>
156
+
157
+ <!-- Radio Buttons -->
158
+ <div *ngIf="field.type === 'radio'" class="radio-group">
159
+ <div *ngFor="let option of field.options; trackBy: trackByFn; let first = first"
160
+ class="radio-option" tooltipPosition="right" pTooltip="{{option.toolTip}}">
161
+
162
+ <p-radioButton *ngIf="first"
163
+ [attr.data-dynamic-id]="field.id"
164
+ [inputId]="field.id + '_' + option.value"
165
+ [id]="field.id + '_' + option.value"
166
+ [name]="field.id"
167
+ [value]="option.value"
168
+ [formControlName]="controlName"
169
+ (onBlur)="onBlur()"
170
+ (onClick)="onClick($event.originalEvent)"></p-radioButton>
171
+ <p-radioButton *ngIf="!first"
172
+ [inputId]="field.id + '_' + option.value"
173
+ [id]="field.id + '_' + option.value"
174
+ [name]="field.id"
175
+ [value]="option.value"
176
+ [formControlName]="controlName"
177
+ (onBlur)="onBlur()"
178
+ (onClick)="onClick($event.originalEvent)"></p-radioButton>
179
+ <label [for]="field.id + '_' + option.value" class="radio-label">
180
+ {{ option.label }}
181
+ </label>
182
+ <div *ngIf="option.helpInfo" class="radio-message-container">
183
+ <p-message styleClass="light-font" severity="info">
184
+ <div [innerHTML]="option.helpInfo"></div>
185
+ </p-message>
186
+ </div>
187
+ <div *ngIf="option.errorInfo && displayRadioError(option)" class="radio-message-container">
188
+ <p-message severity="error">
189
+ <div [innerHTML]="option.errorInfo"></div>
190
+ </p-message>
191
+ </div>
192
+ <small class="radion-hint" *ngIf="option.hint" id="field.id + '_' + option.value + '-help'">{{option.hint}}</small>
193
+
194
+
195
+ </div>
196
+ </div>
197
+ <small class="field-hint" *ngIf="field.hint" id="field.id + '-help'">{{field.hint}}</small>
198
+ </div>
199
+ <!-- Error Messages -->
200
+ <div *ngIf="showError" class="error-messages">
201
+ <p-message *ngFor="let error of errors"
202
+ severity="error"
203
+ [text]="error"></p-message>
204
+ </div>
205
+
206
+ <div *ngIf="field.postInfo" class="message-container">
207
+ <p-message styleClass="light-font" severity="info">
208
+ <div [innerHTML]="field.postInfo"></div>
209
+ </p-message>
210
+ </div>
211
+ <div *ngIf="field.postWarning" class="message-container">
212
+ <p-message styleClass="light-font" severity="warn">
213
+ <div [innerHTML]="field.postWarning"></div>
214
+ </p-message>
215
+ </div>
216
+
217
+ <!-- Valid Indicator (optional) -->
218
+ <div *ngIf="isValid && isTouched && field.required" [ngClass]="successIndicatorClass">
219
+ <i class="pi pi-check-circle"></i>
220
+ </div>
221
+ </div>
222
+ </div>
223
+
224
+ <p-popover appendTo="body" styleClass="form-pop-info" #popover>
225
+ <h4>{{field.label}}</h4>
226
+ <div [innerHTML]="field.popInfo"></div>
227
+ </p-popover>
228
+ @if (allowHelpSideBar && field.popInfo) {
229
+ <p-drawer header="{{field.label}}" autoZIndex="false" baseZIndex="10000" [ngStyle]="{'z-index': '10000', 'top': '65px'}" position="right" styleClass="form-pop-info" appendTo="body" [(visible)]="helpSideBarVisible">
230
+ <p-scrollPanel [ngStyle]="{height: '100%'}">
231
+ <div [innerHTML]="field.popInfo"></div>
232
+ </p-scrollPanel>
233
+ </p-drawer>
234
+ }