@masterteam/form-builder 0.0.2 → 0.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.
Files changed (33) hide show
  1. package/assets/form-builder.css +2 -4
  2. package/fesm2022/masterteam-form-builder.mjs +1908 -0
  3. package/fesm2022/masterteam-form-builder.mjs.map +1 -0
  4. package/package.json +16 -16
  5. package/types/masterteam-form-builder.d.ts +297 -0
  6. package/.angular/cache/21.0.2/ng-packagr/db70d8f07b5a2d2d1c3124ca92e8d56d14fb894dce4d4867ba7c0db29ba913a3 +0 -1
  7. package/.angular/cache/21.0.2/ng-packagr/tsbuildinfo/masterteam-form-builder.tsbuildinfo +0 -1
  8. package/BACKEND_API_SPEC.md +0 -338
  9. package/angular.json +0 -26
  10. package/ng-package.json +0 -13
  11. package/src/lib/fb-field-conditions/condition-constants.ts +0 -262
  12. package/src/lib/fb-field-conditions/fb-field-conditions.html +0 -35
  13. package/src/lib/fb-field-conditions/fb-field-conditions.ts +0 -123
  14. package/src/lib/fb-field-form/fb-field-form.html +0 -59
  15. package/src/lib/fb-field-form/fb-field-form.ts +0 -250
  16. package/src/lib/fb-preview-form/fb-preview-form.html +0 -31
  17. package/src/lib/fb-preview-form/fb-preview-form.ts +0 -147
  18. package/src/lib/fb-section/fb-section.html +0 -130
  19. package/src/lib/fb-section/fb-section.ts +0 -211
  20. package/src/lib/fb-section-form/fb-section-form.html +0 -38
  21. package/src/lib/fb-section-form/fb-section-form.ts +0 -128
  22. package/src/lib/form-builder.html +0 -166
  23. package/src/lib/form-builder.model.ts +0 -27
  24. package/src/lib/form-builder.scss +0 -20
  25. package/src/lib/form-builder.ts +0 -208
  26. package/src/public-api.ts +0 -6
  27. package/src/store/form-builder/api.model.ts +0 -13
  28. package/src/store/form-builder/form-builder.actions.ts +0 -113
  29. package/src/store/form-builder/form-builder.facade.ts +0 -207
  30. package/src/store/form-builder/form-builder.model.ts +0 -147
  31. package/src/store/form-builder/form-builder.state.ts +0 -668
  32. package/src/store/form-builder/index.ts +0 -5
  33. package/tsconfig.json +0 -31
@@ -1,27 +0,0 @@
1
- import type { FieldType } from '@masterteam/components';
2
- import type {
3
- FormField as BaseFormField,
4
- FormSection as BaseFormSection,
5
- FieldWidth,
6
- PropertyItem,
7
- } from '../store/form-builder/form-builder.model';
8
-
9
- export type { FieldType, FieldWidth, PropertyItem };
10
-
11
- // Re-export base types
12
- export type FormField = BaseFormField;
13
- export type FormSection = BaseFormSection;
14
-
15
- // Enriched field with UI properties (from PropertyItem)
16
- export interface EnrichedFormField extends BaseFormField {
17
- name: string;
18
- type: string;
19
- data?: any;
20
- _pending?: boolean; // Optimistic: field is being added
21
- _deleting?: boolean; // Optimistic: field is being deleted
22
- }
23
-
24
- // Enriched section for UI display
25
- export interface EnrichedFormSection extends Omit<BaseFormSection, 'fields'> {
26
- fields: EnrichedFormField[];
27
- }
@@ -1,20 +0,0 @@
1
- // Drag & Drop Cursor Styles
2
- .cdk-drag {
3
- cursor: grab;
4
-
5
- &:active {
6
- cursor: grabbing;
7
- }
8
- }
9
-
10
- .cdk-drag-preview {
11
- cursor: grabbing;
12
- }
13
-
14
- .cdk-drag-placeholder {
15
- opacity: 0.5;
16
- }
17
-
18
- .cdk-drop-list-dragging .cdk-drag {
19
- cursor: grabbing;
20
- }
@@ -1,208 +0,0 @@
1
- import { Component, computed, inject, signal, effect } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import { FormsModule } from '@angular/forms';
4
- import { TabsModule } from 'primeng/tabs';
5
- import { SkeletonModule } from 'primeng/skeleton';
6
- import { Button } from '@masterteam/components/button';
7
- import { Card } from '@masterteam/components/card';
8
- import { ModalService } from '@masterteam/components/modal';
9
- import { ConfirmationService } from '@masterteam/components/confirmation';
10
- import { TranslocoDirective, TranslocoService } from '@jsverse/transloco';
11
- import { FBSection } from './fb-section/fb-section';
12
- import type {
13
- EnrichedFormSection,
14
- EnrichedFormField,
15
- FieldWidth,
16
- PropertyItem,
17
- } from '../store/form-builder/form-builder.model';
18
- import { CdkDragDrop, DragDropModule } from '@angular/cdk/drag-drop';
19
- import { FBSectionForm } from './fb-section-form/fb-section-form';
20
- import { FBPreviewForm } from './fb-preview-form/fb-preview-form';
21
- import { FormBuilderFacade } from '../store/form-builder/form-builder.facade';
22
-
23
- @Component({
24
- selector: 'mt-form-builder',
25
- standalone: true,
26
- imports: [
27
- CommonModule,
28
- FormsModule,
29
- TabsModule,
30
- SkeletonModule,
31
- Button,
32
- Card,
33
- TranslocoDirective,
34
- FBSection,
35
- DragDropModule,
36
- ],
37
- templateUrl: './form-builder.html',
38
- styleUrl: './form-builder.scss',
39
- })
40
- export class FormBuilder {
41
- private readonly modalService = inject(ModalService);
42
- private readonly confirmationService = inject(ConfirmationService);
43
- private readonly translocoService = inject(TranslocoService);
44
- protected readonly facade = inject(FormBuilderFacade);
45
-
46
- private dialogRef: any;
47
-
48
- // Local UI state
49
- readonly activeTab = signal<string>('system');
50
-
51
- // State from facade
52
- readonly sections = this.facade.sections;
53
- readonly properties = this.facade.properties;
54
- readonly isLoading = this.facade.isLoadingFormConfiguration;
55
- readonly error = this.facade.formConfigurationError;
56
-
57
- // Properties map for enrichment
58
- private readonly propertiesMap = computed(() => {
59
- const map = new Map<number, PropertyItem>();
60
- for (const prop of this.properties()) {
61
- map.set(prop.id, prop);
62
- }
63
- return map;
64
- });
65
-
66
- // Enrich sections with property data for UI display
67
- readonly enrichedSections = computed<EnrichedFormSection[]>(() => {
68
- const sections = this.sections();
69
- const propsMap = this.propertiesMap();
70
- const lang = document.documentElement.lang as 'en' | 'ar';
71
-
72
- return sections.map((section) => ({
73
- ...section,
74
- fields: section.fields.map((field): EnrichedFormField => {
75
- const prop = propsMap.get(field.propertyId);
76
- const propName = prop?.name;
77
- const name =
78
- typeof propName === 'string'
79
- ? propName
80
- : (propName?.[lang] ??
81
- propName?.['en'] ??
82
- `Property ${field.propertyId}`);
83
-
84
- return {
85
- ...field,
86
- name,
87
- type: prop?.viewType || 'text',
88
- data: prop,
89
- };
90
- }),
91
- }));
92
- });
93
-
94
- // Available properties for toolbox tabs
95
- readonly availableTabs = computed(() => {
96
- const tabs: Array<{
97
- id: string;
98
- title: string;
99
- properties: PropertyItem[];
100
- }> = [];
101
- const usedPropertyIds = new Set(
102
- this.sections().flatMap((s) => s.fields.map((f) => f.propertyId)),
103
- );
104
-
105
- const availableProps = this.properties().filter(
106
- (p) => !usedPropertyIds.has(p.id),
107
- );
108
-
109
- const systemProps = availableProps.filter((p) => p['isSystem']);
110
- const customProps = availableProps.filter((p) => !p['isSystem']);
111
-
112
- if (systemProps.length > 0) {
113
- tabs.push({ id: 'system', title: 'System', properties: systemProps });
114
- }
115
- if (customProps.length > 0) {
116
- tabs.push({ id: 'custom', title: 'Custom', properties: customProps });
117
- }
118
-
119
- return tabs;
120
- });
121
-
122
- constructor() {
123
- // Update active tab when tabs change
124
- effect(() => {
125
- const tabs = this.availableTabs();
126
- const currentTab = this.activeTab();
127
- if (tabs.length > 0 && !tabs.some((t) => t.id === currentTab)) {
128
- this.activeTab.set(tabs[0].id);
129
- }
130
- });
131
- }
132
-
133
- drop(event: CdkDragDrop<EnrichedFormField[] | PropertyItem[]>): void {
134
- const targetSectionId = event.container.id;
135
-
136
- if (event.previousContainer === event.container) {
137
- // Reordering within the same section
138
- const fields = [...(event.container.data as EnrichedFormField[])];
139
- const [movedField] = fields.splice(event.previousIndex, 1);
140
- fields.splice(event.currentIndex, 0, movedField);
141
-
142
- // Build bulk reorder payload with new order values
143
- const reorderPayload = fields.map((field, index) => ({
144
- id: field.id,
145
- order: index,
146
- }));
147
-
148
- this.facade.reorderFields(targetSectionId, reorderPayload);
149
- } else if (event.previousContainer.id.startsWith('toolbox-')) {
150
- // Adding from toolbox
151
- const propertyItem = event.item.data as PropertyItem;
152
- this.facade.addField(targetSectionId, {
153
- propertyId: propertyItem.id,
154
- width: '100' as FieldWidth,
155
- order: event.currentIndex,
156
- hiddenInCreation: false,
157
- });
158
- } else {
159
- // Moving between sections
160
- const sourceSectionId = event.previousContainer.id;
161
- const field = event.item.data as EnrichedFormField;
162
- this.facade.moveField(sourceSectionId, field.id, {
163
- targetSectionId,
164
- order: event.currentIndex,
165
- });
166
- }
167
- }
168
-
169
- addSection(): void {
170
- this.dialogRef = this.modalService.openModal(FBSectionForm, 'drawer', {
171
- header: this.translocoService.translate('formBuilder.add-section'),
172
- height: '20vw',
173
- styleClass: '!w-100 !absolute ',
174
- position: 'end',
175
- appendTo: '#page-content',
176
- modal: true,
177
- dismissible: true,
178
- inputValues: {
179
- sectionsCount: this.sections().length,
180
- },
181
- });
182
- }
183
-
184
- openPreview(): void {
185
- this.dialogRef = this.modalService.openModal(FBPreviewForm, 'drawer', {
186
- header: this.translocoService.translate('formBuilder.preview'),
187
- styleClass: '!w-[80vw] ',
188
- position: 'end',
189
- modal: true,
190
- dismissible: true,
191
- inputValues: {
192
- sections: this.enrichedSections(),
193
- },
194
- });
195
- }
196
-
197
- resetFormConfiguration(): void {
198
- this.confirmationService.confirm({
199
- type: 'dialog',
200
- acceptButtonStyleClass: 'p-button-danger',
201
- accept: () => {
202
- this.facade.resetFormConfiguration();
203
- },
204
- });
205
- }
206
-
207
- noReturnPredicate = (): boolean => false;
208
- }
package/src/public-api.ts DELETED
@@ -1,6 +0,0 @@
1
- /*
2
- * Public API Surface of form-builder
3
- */
4
-
5
- export * from './lib/form-builder';
6
- export * from './store/form-builder';
@@ -1,13 +0,0 @@
1
- /**
2
- * Standard API Response wrapper
3
- */
4
- export interface Response<T> {
5
- endpoint: string;
6
- status: number;
7
- code: number;
8
- locale: string;
9
- message?: string | null;
10
- errors?: any | null;
11
- data: T;
12
- cacheSession?: string;
13
- }
@@ -1,113 +0,0 @@
1
- import type {
2
- AddFieldPayload,
3
- AddSectionPayload,
4
- MoveFieldPayload,
5
- PropertyItem,
6
- ReorderFieldPayload,
7
- UpdateFieldPayload,
8
- UpdateSectionPayload,
9
- } from './form-builder.model';
10
-
11
- // ============================================================================
12
- // Module Configuration Actions
13
- // ============================================================================
14
-
15
- export class SetModuleInfo {
16
- static readonly type = '[FormBuilder] Set Module Info';
17
- constructor(
18
- public moduleType: string,
19
- public moduleId: string | number,
20
- public parentModuleType?: string,
21
- public parentModuleId?: string | number,
22
- public parentPath?: string,
23
- ) {}
24
- }
25
-
26
- export class ResetFormBuilderState {
27
- static readonly type = '[FormBuilder] Reset State';
28
- }
29
-
30
- export class SetProperties {
31
- static readonly type = '[FormBuilder] Set Properties';
32
- constructor(public properties: PropertyItem[]) {}
33
- }
34
-
35
- // ============================================================================
36
- // Form Configuration Actions
37
- // ============================================================================
38
-
39
- export class GetFormConfiguration {
40
- static readonly type = '[FormBuilder] Get Form Configuration';
41
- }
42
-
43
- export class ResetFormConfiguration {
44
- static readonly type = '[FormBuilder] Reset Form Configuration';
45
- }
46
-
47
- // ============================================================================
48
- // Section Actions
49
- // ============================================================================
50
-
51
- export class AddSection {
52
- static readonly type = '[FormBuilder] Add Section';
53
- constructor(public payload: AddSectionPayload) {}
54
- }
55
-
56
- export class UpdateSection {
57
- static readonly type = '[FormBuilder] Update Section';
58
- constructor(
59
- public sectionId: string,
60
- public payload: UpdateSectionPayload,
61
- ) {}
62
- }
63
-
64
- export class DeleteSection {
65
- static readonly type = '[FormBuilder] Delete Section';
66
- constructor(public sectionId: string) {}
67
- }
68
-
69
- // ============================================================================
70
- // Field Actions
71
- // ============================================================================
72
-
73
- export class AddField {
74
- static readonly type = '[FormBuilder] Add Field';
75
- constructor(
76
- public sectionId: string,
77
- public payload: AddFieldPayload,
78
- ) {}
79
- }
80
-
81
- export class UpdateField {
82
- static readonly type = '[FormBuilder] Update Field';
83
- constructor(
84
- public sectionId: string,
85
- public fieldId: string,
86
- public payload: UpdateFieldPayload,
87
- ) {}
88
- }
89
-
90
- export class DeleteField {
91
- static readonly type = '[FormBuilder] Delete Field';
92
- constructor(
93
- public sectionId: string,
94
- public fieldId: string,
95
- ) {}
96
- }
97
-
98
- export class ReorderFields {
99
- static readonly type = '[FormBuilder] Reorder Fields';
100
- constructor(
101
- public sectionId: string,
102
- public payload: ReorderFieldPayload[],
103
- ) {}
104
- }
105
-
106
- export class MoveField {
107
- static readonly type = '[FormBuilder] Move Field';
108
- constructor(
109
- public sectionId: string,
110
- public fieldId: string,
111
- public payload: MoveFieldPayload,
112
- ) {}
113
- }
@@ -1,207 +0,0 @@
1
- import { computed, Injectable, inject } from '@angular/core';
2
- import { Store, select } from '@ngxs/store';
3
-
4
- import {
5
- AddFieldPayload,
6
- AddSectionPayload,
7
- FormBuilderActionKey,
8
- MoveFieldPayload,
9
- PropertyItem,
10
- ReorderFieldPayload,
11
- UpdateFieldPayload,
12
- UpdateSectionPayload,
13
- } from './form-builder.model';
14
- import {
15
- AddField,
16
- AddSection,
17
- DeleteField,
18
- DeleteSection,
19
- GetFormConfiguration,
20
- MoveField,
21
- ReorderFields,
22
- ResetFormBuilderState,
23
- ResetFormConfiguration,
24
- SetModuleInfo,
25
- SetProperties,
26
- UpdateField,
27
- UpdateSection,
28
- } from './form-builder.actions';
29
- import { FormBuilderState } from './form-builder.state';
30
-
31
- @Injectable({ providedIn: 'root' })
32
- export class FormBuilderFacade {
33
- private readonly store = inject(Store);
34
-
35
- // ============================================================================
36
- // State Selectors
37
- // ============================================================================
38
-
39
- private readonly stateSignal = select(FormBuilderState.getState);
40
-
41
- readonly formConfiguration = select(FormBuilderState.getFormConfiguration);
42
- readonly sections = select(FormBuilderState.getSections);
43
- readonly properties = select(FormBuilderState.getProperties);
44
- readonly moduleType = select(FormBuilderState.getModuleType);
45
- readonly moduleId = select(FormBuilderState.getModuleId);
46
-
47
- // ============================================================================
48
- // Loading Signals
49
- // ============================================================================
50
-
51
- readonly isLoadingFormConfiguration = computed(() =>
52
- this.stateSignal().loadingActive.includes(
53
- FormBuilderActionKey.GetFormConfiguration,
54
- ),
55
- );
56
-
57
- readonly isResettingFormConfiguration = computed(() =>
58
- this.stateSignal().loadingActive.includes(
59
- FormBuilderActionKey.ResetFormConfiguration,
60
- ),
61
- );
62
-
63
- readonly isAddingSection = computed(() =>
64
- this.stateSignal().loadingActive.includes(FormBuilderActionKey.AddSection),
65
- );
66
-
67
- readonly isUpdatingSection = computed(() =>
68
- this.stateSignal().loadingActive.includes(
69
- FormBuilderActionKey.UpdateSection,
70
- ),
71
- );
72
-
73
- readonly isDeletingSection = computed(() =>
74
- this.stateSignal().loadingActive.includes(
75
- FormBuilderActionKey.DeleteSection,
76
- ),
77
- );
78
-
79
- readonly isAddingField = computed(() =>
80
- this.stateSignal().loadingActive.includes(FormBuilderActionKey.AddField),
81
- );
82
-
83
- readonly isUpdatingField = computed(() =>
84
- this.stateSignal().loadingActive.includes(FormBuilderActionKey.UpdateField),
85
- );
86
-
87
- readonly isDeletingField = computed(() =>
88
- this.stateSignal().loadingActive.includes(FormBuilderActionKey.DeleteField),
89
- );
90
-
91
- readonly isMovingField = computed(() =>
92
- this.stateSignal().loadingActive.includes(FormBuilderActionKey.MoveField),
93
- );
94
-
95
- // ============================================================================
96
- // Error Signals
97
- // ============================================================================
98
-
99
- readonly formConfigurationError = computed(
100
- () =>
101
- this.stateSignal().errors[FormBuilderActionKey.GetFormConfiguration] ??
102
- null,
103
- );
104
-
105
- readonly sectionError = computed(() => {
106
- const errors = this.stateSignal().errors;
107
- return (
108
- errors[FormBuilderActionKey.AddSection] ??
109
- errors[FormBuilderActionKey.UpdateSection] ??
110
- errors[FormBuilderActionKey.DeleteSection] ??
111
- null
112
- );
113
- });
114
-
115
- readonly fieldError = computed(() => {
116
- const errors = this.stateSignal().errors;
117
- return (
118
- errors[FormBuilderActionKey.AddField] ??
119
- errors[FormBuilderActionKey.UpdateField] ??
120
- errors[FormBuilderActionKey.DeleteField] ??
121
- errors[FormBuilderActionKey.MoveField] ??
122
- null
123
- );
124
- });
125
-
126
- // ============================================================================
127
- // Module Configuration Dispatchers
128
- // ============================================================================
129
-
130
- setModuleInfo(
131
- moduleType: string,
132
- moduleId: string | number,
133
- parentModuleType?: string,
134
- parentModuleId?: string | number,
135
- parentPath?: string,
136
- ) {
137
- return this.store.dispatch(
138
- new SetModuleInfo(
139
- moduleType,
140
- moduleId,
141
- parentModuleType,
142
- parentModuleId,
143
- parentPath,
144
- ),
145
- );
146
- }
147
-
148
- resetState() {
149
- return this.store.dispatch(new ResetFormBuilderState());
150
- }
151
-
152
- setProperties(properties: PropertyItem[]) {
153
- return this.store.dispatch(new SetProperties(properties));
154
- }
155
-
156
- // ============================================================================
157
- // Form Configuration Dispatchers
158
- // ============================================================================
159
-
160
- getFormConfiguration() {
161
- return this.store.dispatch(new GetFormConfiguration());
162
- }
163
-
164
- resetFormConfiguration() {
165
- return this.store.dispatch(new ResetFormConfiguration());
166
- }
167
-
168
- // ============================================================================
169
- // Section Dispatchers
170
- // ============================================================================
171
-
172
- addSection(payload: AddSectionPayload) {
173
- return this.store.dispatch(new AddSection(payload));
174
- }
175
-
176
- updateSection(sectionId: string, payload: UpdateSectionPayload) {
177
- return this.store.dispatch(new UpdateSection(sectionId, payload));
178
- }
179
-
180
- deleteSection(sectionId: string) {
181
- return this.store.dispatch(new DeleteSection(sectionId));
182
- }
183
-
184
- // ============================================================================
185
- // Field Dispatchers
186
- // ============================================================================
187
-
188
- addField(sectionId: string, payload: AddFieldPayload) {
189
- return this.store.dispatch(new AddField(sectionId, payload));
190
- }
191
-
192
- updateField(sectionId: string, fieldId: string, payload: UpdateFieldPayload) {
193
- return this.store.dispatch(new UpdateField(sectionId, fieldId, payload));
194
- }
195
-
196
- deleteField(sectionId: string, fieldId: string) {
197
- return this.store.dispatch(new DeleteField(sectionId, fieldId));
198
- }
199
-
200
- reorderFields(sectionId: string, payload: ReorderFieldPayload[]) {
201
- return this.store.dispatch(new ReorderFields(sectionId, payload));
202
- }
203
-
204
- moveField(sectionId: string, fieldId: string, payload: MoveFieldPayload) {
205
- return this.store.dispatch(new MoveField(sectionId, fieldId, payload));
206
- }
207
- }