@masterteam/forms 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.
- package/README.md +24 -0
- package/dynamic-field/index.d.ts +16 -0
- package/dynamic-form/index.d.ts +28 -0
- package/fesm2022/masterteam-forms-dynamic-field.mjs +85 -0
- package/fesm2022/masterteam-forms-dynamic-field.mjs.map +1 -0
- package/fesm2022/masterteam-forms-dynamic-form.mjs +174 -0
- package/fesm2022/masterteam-forms-dynamic-form.mjs.map +1 -0
- package/fesm2022/masterteam-forms-pipes.mjs +57 -0
- package/fesm2022/masterteam-forms-pipes.mjs.map +1 -0
- package/fesm2022/masterteam-forms.mjs +6 -0
- package/fesm2022/masterteam-forms.mjs.map +1 -0
- package/index.d.ts +2 -0
- package/package.json +49 -0
- package/pipes/index.d.ts +11 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @masterteam/forms
|
|
2
|
+
|
|
3
|
+
Angular Form Components Library
|
|
4
|
+
|
|
5
|
+
## Components
|
|
6
|
+
|
|
7
|
+
- **DynamicFieldComponent**: A dynamic field component that renders different input types based on configuration
|
|
8
|
+
- **DynamicFormComponent**: A dynamic form component that creates forms based on configuration objects
|
|
9
|
+
|
|
10
|
+
## Pipes
|
|
11
|
+
|
|
12
|
+
- **SortPipe**: A pipe for sorting arrays by specified keys and directions
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @masterteam/forms
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { DynamicFieldComponent, DynamicFormComponent, SortPipe } from '@masterteam/forms';
|
|
24
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { Signal } from '@angular/core';
|
|
3
|
+
import { DynamicFieldConfig } from '@masterteam/components';
|
|
4
|
+
|
|
5
|
+
declare class DynamicField {
|
|
6
|
+
readonly fieldConfig: _angular_core.InputSignal<DynamicFieldConfig>;
|
|
7
|
+
readonly transformedFieldConfig: Signal<DynamicFieldConfig>;
|
|
8
|
+
private controlContainer;
|
|
9
|
+
readonly fieldName: _angular_core.InputSignal<string>;
|
|
10
|
+
constructor();
|
|
11
|
+
private transformToFieldConfig;
|
|
12
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DynamicField, never>;
|
|
13
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DynamicField, "mt-dynamic-field", never, { "fieldConfig": { "alias": "fieldConfig"; "required": true; "isSignal": true; }; "fieldName": { "alias": "fieldName"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export { DynamicField };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { OnDestroy } from '@angular/core';
|
|
3
|
+
import { ControlValueAccessor, Validator, FormGroup, AbstractControl, ValidationErrors } from '@angular/forms';
|
|
4
|
+
import { DynamicFormConfig } from '@masterteam/components';
|
|
5
|
+
|
|
6
|
+
declare class DynamicForm implements OnDestroy, ControlValueAccessor, Validator {
|
|
7
|
+
private fb;
|
|
8
|
+
readonly formConfig: i0.InputSignal<DynamicFormConfig>;
|
|
9
|
+
form: FormGroup<{}>;
|
|
10
|
+
private onChange;
|
|
11
|
+
private onTouched;
|
|
12
|
+
private onValidatorChange;
|
|
13
|
+
private formSubscription?;
|
|
14
|
+
private statusSubscription?;
|
|
15
|
+
constructor();
|
|
16
|
+
registerOnValidatorChange(fn: () => void): void;
|
|
17
|
+
registerOnChange(fn: (value: any) => void): void;
|
|
18
|
+
registerOnTouched(fn: () => void): void;
|
|
19
|
+
private buildForm;
|
|
20
|
+
writeValue(value: any): void;
|
|
21
|
+
validate(_control: AbstractControl): ValidationErrors | null;
|
|
22
|
+
private buildValidators;
|
|
23
|
+
ngOnDestroy(): void;
|
|
24
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<DynamicForm, never>;
|
|
25
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<DynamicForm, "mt-dynamic-form", never, { "formConfig": { "alias": "formConfig"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { DynamicForm };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, computed, inject, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/forms';
|
|
4
|
+
import { ControlContainer, FormGroupDirective, ReactiveFormsModule } from '@angular/forms';
|
|
5
|
+
import { TextField } from '@masterteam/components/text-field';
|
|
6
|
+
import { TextareaField } from '@masterteam/components/textarea-field';
|
|
7
|
+
import { SelectField } from '@masterteam/components/select-field';
|
|
8
|
+
import { DateField } from '@masterteam/components/date-field';
|
|
9
|
+
import { NumberField } from '@masterteam/components/number-field';
|
|
10
|
+
import { SliderField } from '@masterteam/components/slider-field';
|
|
11
|
+
import { MultiSelectField } from '@masterteam/components/multi-select-field';
|
|
12
|
+
import { CheckboxField } from '@masterteam/components/checkbox-field';
|
|
13
|
+
import { TextFieldConfig, TextareaFieldConfig, SelectFieldConfig, DateFieldConfig, NumberFieldConfig, SliderFieldConfig, MultiSelectFieldConfig, CheckboxFieldConfig } from '@masterteam/components';
|
|
14
|
+
|
|
15
|
+
class DynamicField {
|
|
16
|
+
// Input signal with transform to handle class for text type
|
|
17
|
+
fieldConfig = input.required(...(ngDevMode ? [{ debugName: "fieldConfig" }] : []));
|
|
18
|
+
// Computed property for transformed field config
|
|
19
|
+
transformedFieldConfig = computed(() => this.transformToFieldConfig(this.fieldConfig()), ...(ngDevMode ? [{ debugName: "transformedFieldConfig" }] : []));
|
|
20
|
+
// Inject ControlContainer to connect directly with parent form
|
|
21
|
+
controlContainer = inject(ControlContainer);
|
|
22
|
+
// Input for the form control name
|
|
23
|
+
fieldName = input.required(...(ngDevMode ? [{ debugName: "fieldName" }] : []));
|
|
24
|
+
constructor() { }
|
|
25
|
+
transformToFieldConfig(value) {
|
|
26
|
+
// If it's a plain object, transform it to appropriate field config
|
|
27
|
+
if (typeof value === 'object') {
|
|
28
|
+
if (value.type === 'text') {
|
|
29
|
+
return new TextFieldConfig(value);
|
|
30
|
+
}
|
|
31
|
+
if (value.type === 'textarea') {
|
|
32
|
+
return new TextareaFieldConfig(value);
|
|
33
|
+
}
|
|
34
|
+
if (value.type === 'select') {
|
|
35
|
+
return new SelectFieldConfig(value);
|
|
36
|
+
}
|
|
37
|
+
if (value.type === 'date') {
|
|
38
|
+
return new DateFieldConfig(value);
|
|
39
|
+
}
|
|
40
|
+
if (value.type === 'number') {
|
|
41
|
+
return new NumberFieldConfig(value);
|
|
42
|
+
}
|
|
43
|
+
if (value.type === 'slider') {
|
|
44
|
+
return new SliderFieldConfig(value);
|
|
45
|
+
}
|
|
46
|
+
if (value.type === 'multi-select') {
|
|
47
|
+
return new MultiSelectFieldConfig(value);
|
|
48
|
+
}
|
|
49
|
+
if (value.type === 'checkbox') {
|
|
50
|
+
return new CheckboxFieldConfig(value);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Default fallback to TextFieldConfig
|
|
54
|
+
return new TextFieldConfig({
|
|
55
|
+
...value,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: DynamicField, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
59
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.0", type: DynamicField, isStandalone: true, selector: "mt-dynamic-field", inputs: { fieldConfig: { classPropertyName: "fieldConfig", publicName: "fieldConfig", isSignal: true, isRequired: true, transformFunction: null }, fieldName: { classPropertyName: "fieldName", publicName: "fieldName", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@switch (transformedFieldConfig().type) {\n @case (\"text\") {\n <mt-text-field\n [label]=\"transformedFieldConfig().label\"\n [placeholder]=\"transformedFieldConfig().placeholder\"\n [type]=\"transformedFieldConfig().inputType || 'text'\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"textarea\") {\n <mt-textarea-field\n [label]=\"transformedFieldConfig().label\"\n [placeholder]=\"transformedFieldConfig().placeholder\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"select\") {\n <mt-select-field\n [label]=\"transformedFieldConfig().label || ''\"\n [placeholder]=\"transformedFieldConfig().placeholder || ''\"\n [options]=\"transformedFieldConfig().options || []\"\n [optionLabel]=\"transformedFieldConfig().optionLabel || 'label'\"\n [optionValue]=\"transformedFieldConfig().optionValue || 'value'\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"date\") {\n <mt-date-field\n [label]=\"transformedFieldConfig().label\"\n [placeholder]=\"transformedFieldConfig().placeholder\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"number\") {\n <mt-number-field\n [label]=\"transformedFieldConfig().label\"\n [placeholder]=\"transformedFieldConfig().placeholder\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"slider\") {\n <mt-slider-field\n [label]=\"transformedFieldConfig().label\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"multi-select\") {\n <mt-multi-select-field\n [label]=\"transformedFieldConfig().label || ''\"\n [placeholder]=\"transformedFieldConfig().placeholder || ''\"\n [options]=\"transformedFieldConfig().options || []\"\n [optionLabel]=\"transformedFieldConfig().optionLabel || 'label'\"\n [optionValue]=\"transformedFieldConfig().optionValue || 'value'\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"checkbox\") {\n <mt-checkbox-field\n [label]=\"transformedFieldConfig().label\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n}\n", styles: [":host{display:block;width:100%}\n"], dependencies: [{ kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "pKeyFilter"] }, { kind: "component", type: TextareaField, selector: "mt-textarea-field", inputs: ["field", "label", "placeholder", "class", "readonly", "noErrorStyle", "pInputs", "rows"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect"], outputs: ["onChange"] }, { kind: "component", type: DateField, selector: "mt-date-field", inputs: ["field", "label", "placeholder", "class", "readonly", "showIcon", "showClear", "showTime", "pInputs"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "format", "maxFractionDigits", "min", "max"] }, { kind: "component", type: SliderField, selector: "mt-slider-field", inputs: ["field", "label", "animate", "class", "min", "max", "step", "hideNumber", "unit", "readonly", "pInputs"], outputs: ["onChange", "onSlideEnd"] }, { kind: "component", type: MultiSelectField, selector: "mt-multi-select-field", inputs: ["field", "label", "placeholder", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "display"], outputs: ["onChange"] }, { kind: "component", type: CheckboxField, selector: "mt-checkbox-field", inputs: ["label", "placeholder", "class", "readonly", "pInputs"], outputs: ["onChange"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }], viewProviders: [
|
|
60
|
+
{ provide: ControlContainer, useExisting: FormGroupDirective },
|
|
61
|
+
], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
62
|
+
}
|
|
63
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: DynamicField, decorators: [{
|
|
64
|
+
type: Component,
|
|
65
|
+
args: [{ selector: 'mt-dynamic-field', standalone: true, imports: [
|
|
66
|
+
TextField,
|
|
67
|
+
TextareaField,
|
|
68
|
+
SelectField,
|
|
69
|
+
DateField,
|
|
70
|
+
NumberField,
|
|
71
|
+
SliderField,
|
|
72
|
+
MultiSelectField,
|
|
73
|
+
CheckboxField,
|
|
74
|
+
ReactiveFormsModule,
|
|
75
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, viewProviders: [
|
|
76
|
+
{ provide: ControlContainer, useExisting: FormGroupDirective },
|
|
77
|
+
], template: "@switch (transformedFieldConfig().type) {\n @case (\"text\") {\n <mt-text-field\n [label]=\"transformedFieldConfig().label\"\n [placeholder]=\"transformedFieldConfig().placeholder\"\n [type]=\"transformedFieldConfig().inputType || 'text'\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"textarea\") {\n <mt-textarea-field\n [label]=\"transformedFieldConfig().label\"\n [placeholder]=\"transformedFieldConfig().placeholder\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"select\") {\n <mt-select-field\n [label]=\"transformedFieldConfig().label || ''\"\n [placeholder]=\"transformedFieldConfig().placeholder || ''\"\n [options]=\"transformedFieldConfig().options || []\"\n [optionLabel]=\"transformedFieldConfig().optionLabel || 'label'\"\n [optionValue]=\"transformedFieldConfig().optionValue || 'value'\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"date\") {\n <mt-date-field\n [label]=\"transformedFieldConfig().label\"\n [placeholder]=\"transformedFieldConfig().placeholder\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"number\") {\n <mt-number-field\n [label]=\"transformedFieldConfig().label\"\n [placeholder]=\"transformedFieldConfig().placeholder\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"slider\") {\n <mt-slider-field\n [label]=\"transformedFieldConfig().label\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"multi-select\") {\n <mt-multi-select-field\n [label]=\"transformedFieldConfig().label || ''\"\n [placeholder]=\"transformedFieldConfig().placeholder || ''\"\n [options]=\"transformedFieldConfig().options || []\"\n [optionLabel]=\"transformedFieldConfig().optionLabel || 'label'\"\n [optionValue]=\"transformedFieldConfig().optionValue || 'value'\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"checkbox\") {\n <mt-checkbox-field\n [label]=\"transformedFieldConfig().label\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n}\n", styles: [":host{display:block;width:100%}\n"] }]
|
|
78
|
+
}], ctorParameters: () => [] });
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Generated bundle index. Do not edit.
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
export { DynamicField };
|
|
85
|
+
//# sourceMappingURL=masterteam-forms-dynamic-field.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"masterteam-forms-dynamic-field.mjs","sources":["../../../../packages/masterteam/forms/dynamic-field/dynamic-field.ts","../../../../packages/masterteam/forms/dynamic-field/dynamic-field.html","../../../../packages/masterteam/forms/dynamic-field/masterteam-forms-dynamic-field.ts"],"sourcesContent":["import {\n Component,\n input,\n computed,\n ChangeDetectionStrategy,\n Signal,\n inject,\n} from '@angular/core';\nimport {\n ReactiveFormsModule,\n ControlContainer,\n FormGroupDirective,\n} from '@angular/forms';\nimport { TextField } from '@masterteam/components/text-field';\nimport { TextareaField } from '@masterteam/components/textarea-field';\nimport { SelectField } from '@masterteam/components/select-field';\nimport { DateField } from '@masterteam/components/date-field';\nimport { NumberField } from '@masterteam/components/number-field';\nimport { SliderField } from '@masterteam/components/slider-field';\nimport { MultiSelectField } from '@masterteam/components/multi-select-field';\nimport { CheckboxField } from '@masterteam/components/checkbox-field';\nimport {\n TextFieldConfig,\n TextareaFieldConfig,\n SelectFieldConfig,\n DateFieldConfig,\n NumberFieldConfig,\n SliderFieldConfig,\n MultiSelectFieldConfig,\n CheckboxFieldConfig,\n DynamicFieldConfig,\n} from '@masterteam/components';\n\n@Component({\n selector: 'mt-dynamic-field',\n standalone: true,\n imports: [\n TextField,\n TextareaField,\n SelectField,\n DateField,\n NumberField,\n SliderField,\n MultiSelectField,\n CheckboxField,\n ReactiveFormsModule,\n ],\n templateUrl: './dynamic-field.html',\n styleUrls: ['./dynamic-field.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n viewProviders: [\n { provide: ControlContainer, useExisting: FormGroupDirective },\n ],\n})\nexport class DynamicField {\n // Input signal with transform to handle class for text type\n readonly fieldConfig = input.required<DynamicFieldConfig>();\n\n // Computed property for transformed field config\n readonly transformedFieldConfig: Signal<DynamicFieldConfig> = computed(() =>\n this.transformToFieldConfig(this.fieldConfig()),\n );\n\n // Inject ControlContainer to connect directly with parent form\n private controlContainer = inject(ControlContainer);\n\n // Input for the form control name\n readonly fieldName = input.required<string>();\n constructor() {}\n\n private transformToFieldConfig(value: any): DynamicFieldConfig {\n // If it's a plain object, transform it to appropriate field config\n if (typeof value === 'object') {\n if (value.type === 'text') {\n return new TextFieldConfig(value);\n }\n if (value.type === 'textarea') {\n return new TextareaFieldConfig(value);\n }\n if (value.type === 'select') {\n return new SelectFieldConfig(value);\n }\n if (value.type === 'date') {\n return new DateFieldConfig(value);\n }\n if (value.type === 'number') {\n return new NumberFieldConfig(value);\n }\n if (value.type === 'slider') {\n return new SliderFieldConfig(value);\n }\n if (value.type === 'multi-select') {\n return new MultiSelectFieldConfig(value);\n }\n if (value.type === 'checkbox') {\n return new CheckboxFieldConfig(value);\n }\n }\n\n // Default fallback to TextFieldConfig\n return new TextFieldConfig({\n ...value,\n });\n }\n}\n","@switch (transformedFieldConfig().type) {\n @case (\"text\") {\n <mt-text-field\n [label]=\"transformedFieldConfig().label\"\n [placeholder]=\"transformedFieldConfig().placeholder\"\n [type]=\"transformedFieldConfig().inputType || 'text'\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"textarea\") {\n <mt-textarea-field\n [label]=\"transformedFieldConfig().label\"\n [placeholder]=\"transformedFieldConfig().placeholder\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"select\") {\n <mt-select-field\n [label]=\"transformedFieldConfig().label || ''\"\n [placeholder]=\"transformedFieldConfig().placeholder || ''\"\n [options]=\"transformedFieldConfig().options || []\"\n [optionLabel]=\"transformedFieldConfig().optionLabel || 'label'\"\n [optionValue]=\"transformedFieldConfig().optionValue || 'value'\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"date\") {\n <mt-date-field\n [label]=\"transformedFieldConfig().label\"\n [placeholder]=\"transformedFieldConfig().placeholder\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"number\") {\n <mt-number-field\n [label]=\"transformedFieldConfig().label\"\n [placeholder]=\"transformedFieldConfig().placeholder\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"slider\") {\n <mt-slider-field\n [label]=\"transformedFieldConfig().label\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"multi-select\") {\n <mt-multi-select-field\n [label]=\"transformedFieldConfig().label || ''\"\n [placeholder]=\"transformedFieldConfig().placeholder || ''\"\n [options]=\"transformedFieldConfig().options || []\"\n [optionLabel]=\"transformedFieldConfig().optionLabel || 'label'\"\n [optionValue]=\"transformedFieldConfig().optionValue || 'value'\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n @case (\"checkbox\") {\n <mt-checkbox-field\n [label]=\"transformedFieldConfig().label\"\n [readonly]=\"transformedFieldConfig().readonly!\"\n [formControlName]=\"fieldName()\"\n />\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, input, effect, forwardRef, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/forms';
|
|
4
|
+
import { FormBuilder, FormGroup, Validators, ReactiveFormsModule, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
|
|
5
|
+
import { CommonModule } from '@angular/common';
|
|
6
|
+
import { DynamicField } from '@masterteam/forms/dynamic-field';
|
|
7
|
+
import { SortPipe } from '@masterteam/forms/pipes';
|
|
8
|
+
import { createCustomValidator, wrapValidatorWithMessage } from '@masterteam/components';
|
|
9
|
+
|
|
10
|
+
class DynamicForm {
|
|
11
|
+
fb = inject(FormBuilder);
|
|
12
|
+
formConfig = input.required(...(ngDevMode ? [{ debugName: "formConfig" }] : []));
|
|
13
|
+
form = new FormGroup({});
|
|
14
|
+
// ControlValueAccessor implementation
|
|
15
|
+
onChange = (_value) => { };
|
|
16
|
+
onTouched = () => { };
|
|
17
|
+
onValidatorChange = () => { };
|
|
18
|
+
// private disabled = false;
|
|
19
|
+
formSubscription;
|
|
20
|
+
statusSubscription;
|
|
21
|
+
constructor() {
|
|
22
|
+
// Effect to rebuild form when config changes
|
|
23
|
+
effect(() => {
|
|
24
|
+
this.buildForm();
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
registerOnValidatorChange(fn) {
|
|
28
|
+
this.onValidatorChange = fn;
|
|
29
|
+
}
|
|
30
|
+
registerOnChange(fn) {
|
|
31
|
+
this.onChange = fn;
|
|
32
|
+
}
|
|
33
|
+
registerOnTouched(fn) {
|
|
34
|
+
this.onTouched = fn;
|
|
35
|
+
}
|
|
36
|
+
buildForm() {
|
|
37
|
+
// Clean up previous subscriptions
|
|
38
|
+
if (this.formSubscription) {
|
|
39
|
+
this.formSubscription.unsubscribe();
|
|
40
|
+
}
|
|
41
|
+
if (this.statusSubscription) {
|
|
42
|
+
this.statusSubscription.unsubscribe();
|
|
43
|
+
}
|
|
44
|
+
const formControls = {};
|
|
45
|
+
this.formConfig().sections.forEach((section) => {
|
|
46
|
+
section.fields.forEach((field) => {
|
|
47
|
+
if (field.key) {
|
|
48
|
+
const validators = this.buildValidators(field.validators || []);
|
|
49
|
+
const control = this.fb.control({
|
|
50
|
+
value: field.defaultValue || '',
|
|
51
|
+
disabled: field.disabled || false,
|
|
52
|
+
}, validators);
|
|
53
|
+
formControls[field.key] = control;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
this.form = this.fb.group(formControls);
|
|
58
|
+
// Subscribe to form value changes
|
|
59
|
+
this.formSubscription = this.form.valueChanges.subscribe((value) => {
|
|
60
|
+
this.onChange(value);
|
|
61
|
+
});
|
|
62
|
+
// Trigger initial validation state
|
|
63
|
+
this.onValidatorChange();
|
|
64
|
+
}
|
|
65
|
+
// ControlValueAccessor implementation
|
|
66
|
+
writeValue(value) {
|
|
67
|
+
if (value && this.form) {
|
|
68
|
+
this.form.patchValue(value, { emitEvent: false });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
validate(_control) {
|
|
72
|
+
if (!this.form) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
// Return the form's errors if invalid, null if valid
|
|
76
|
+
return this.form.valid ? null : { invalidForm: true };
|
|
77
|
+
}
|
|
78
|
+
buildValidators(validatorConfigs) {
|
|
79
|
+
const validators = [];
|
|
80
|
+
validatorConfigs.forEach((config) => {
|
|
81
|
+
let validator = null;
|
|
82
|
+
switch (config.type) {
|
|
83
|
+
case 'required':
|
|
84
|
+
validator = Validators.required;
|
|
85
|
+
break;
|
|
86
|
+
case 'email':
|
|
87
|
+
validator = Validators.email;
|
|
88
|
+
break;
|
|
89
|
+
case 'minLength':
|
|
90
|
+
if (config.value) {
|
|
91
|
+
validator = Validators.minLength(config.value);
|
|
92
|
+
}
|
|
93
|
+
break;
|
|
94
|
+
case 'maxLength':
|
|
95
|
+
if (config.value) {
|
|
96
|
+
validator = Validators.maxLength(config.value);
|
|
97
|
+
}
|
|
98
|
+
break;
|
|
99
|
+
case 'min':
|
|
100
|
+
if (config.value !== undefined) {
|
|
101
|
+
validator = Validators.min(config.value);
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
case 'max':
|
|
105
|
+
if (config.value !== undefined) {
|
|
106
|
+
validator = Validators.max(config.value);
|
|
107
|
+
}
|
|
108
|
+
break;
|
|
109
|
+
case 'pattern':
|
|
110
|
+
if (config.value) {
|
|
111
|
+
validator = Validators.pattern(config.value);
|
|
112
|
+
}
|
|
113
|
+
break;
|
|
114
|
+
case 'custom':
|
|
115
|
+
if (config.customValidator) {
|
|
116
|
+
validators.push(createCustomValidator(config.customValidator, config.message));
|
|
117
|
+
}
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
// If we have a validator and a custom message, wrap it
|
|
121
|
+
if (validator && config.message) {
|
|
122
|
+
validators.push(wrapValidatorWithMessage(validator, config.type, config.message));
|
|
123
|
+
}
|
|
124
|
+
else if (validator) {
|
|
125
|
+
validators.push(validator);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return validators;
|
|
129
|
+
}
|
|
130
|
+
ngOnDestroy() {
|
|
131
|
+
// Clean up subscriptions
|
|
132
|
+
if (this.formSubscription) {
|
|
133
|
+
this.formSubscription.unsubscribe();
|
|
134
|
+
}
|
|
135
|
+
if (this.statusSubscription) {
|
|
136
|
+
this.statusSubscription.unsubscribe();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: DynamicForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
140
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.0", type: DynamicForm, isStandalone: true, selector: "mt-dynamic-form", inputs: { formConfig: { classPropertyName: "formConfig", publicName: "formConfig", isSignal: true, isRequired: true, transformFunction: null } }, providers: [
|
|
141
|
+
{
|
|
142
|
+
provide: NG_VALUE_ACCESSOR,
|
|
143
|
+
useExisting: forwardRef(() => DynamicForm),
|
|
144
|
+
multi: true,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
provide: NG_VALIDATORS,
|
|
148
|
+
useExisting: forwardRef(() => DynamicForm),
|
|
149
|
+
multi: true,
|
|
150
|
+
},
|
|
151
|
+
], ngImport: i0, template: "<form [formGroup]=\"form\">\n <div\n class=\"flex flex-col gap-6 max-w-4xl mx-auto p-4\"\n [class]=\"formConfig().layout?.containerClass\"\n >\n @for (\n section of formConfig().sections | sort: \"order\";\n track section.key || $index\n ) {\n <div\n [class]=\"\n section.cssClass ||\n formConfig().layout?.sectionClass ||\n 'flex flex-col gap-4'\n \"\n >\n @if (section.type === \"header\" && section.label) {\n <h3\n [class]=\"\n section?.headerClass ||\n 'text-xl font-semibold text-gray-800 border-b-2 border-gray-200 pb-2 mb-4'\n \"\n >\n {{ section.label }}\n </h3>\n }\n\n <div\n [class]=\"\n section?.bodyClass ||\n 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 items-start'\n \"\n >\n @for (field of section.fields | sort: \"order\"; track field.key) {\n <div\n [class]=\"\n field.cssClass ||\n formConfig().layout?.fieldClass ||\n 'flex flex-col gap-1'\n \"\n [hidden]=\"field.hidden\"\n >\n <mt-dynamic-field\n [fieldConfig]=\"field\"\n [fieldName]=\"field.key!\"\n />\n </div>\n }\n </div>\n </div>\n }\n </div>\n</form>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: DynamicField, selector: "mt-dynamic-field", inputs: ["fieldConfig", "fieldName"] }, { kind: "pipe", type: SortPipe, name: "sort" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
152
|
+
}
|
|
153
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: DynamicForm, decorators: [{
|
|
154
|
+
type: Component,
|
|
155
|
+
args: [{ selector: 'mt-dynamic-form', standalone: true, imports: [CommonModule, ReactiveFormsModule, DynamicField, SortPipe], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
156
|
+
{
|
|
157
|
+
provide: NG_VALUE_ACCESSOR,
|
|
158
|
+
useExisting: forwardRef(() => DynamicForm),
|
|
159
|
+
multi: true,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
provide: NG_VALIDATORS,
|
|
163
|
+
useExisting: forwardRef(() => DynamicForm),
|
|
164
|
+
multi: true,
|
|
165
|
+
},
|
|
166
|
+
], template: "<form [formGroup]=\"form\">\n <div\n class=\"flex flex-col gap-6 max-w-4xl mx-auto p-4\"\n [class]=\"formConfig().layout?.containerClass\"\n >\n @for (\n section of formConfig().sections | sort: \"order\";\n track section.key || $index\n ) {\n <div\n [class]=\"\n section.cssClass ||\n formConfig().layout?.sectionClass ||\n 'flex flex-col gap-4'\n \"\n >\n @if (section.type === \"header\" && section.label) {\n <h3\n [class]=\"\n section?.headerClass ||\n 'text-xl font-semibold text-gray-800 border-b-2 border-gray-200 pb-2 mb-4'\n \"\n >\n {{ section.label }}\n </h3>\n }\n\n <div\n [class]=\"\n section?.bodyClass ||\n 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 items-start'\n \"\n >\n @for (field of section.fields | sort: \"order\"; track field.key) {\n <div\n [class]=\"\n field.cssClass ||\n formConfig().layout?.fieldClass ||\n 'flex flex-col gap-1'\n \"\n [hidden]=\"field.hidden\"\n >\n <mt-dynamic-field\n [fieldConfig]=\"field\"\n [fieldName]=\"field.key!\"\n />\n </div>\n }\n </div>\n </div>\n }\n </div>\n</form>\n" }]
|
|
167
|
+
}], ctorParameters: () => [] });
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Generated bundle index. Do not edit.
|
|
171
|
+
*/
|
|
172
|
+
|
|
173
|
+
export { DynamicForm };
|
|
174
|
+
//# sourceMappingURL=masterteam-forms-dynamic-form.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"masterteam-forms-dynamic-form.mjs","sources":["../../../../packages/masterteam/forms/dynamic-form/dynamic-form.ts","../../../../packages/masterteam/forms/dynamic-form/dynamic-form.html","../../../../packages/masterteam/forms/dynamic-form/masterteam-forms-dynamic-form.ts"],"sourcesContent":["import {\n Component,\n input,\n effect,\n ChangeDetectionStrategy,\n OnDestroy,\n forwardRef,\n inject,\n} from '@angular/core';\nimport {\n FormBuilder,\n FormGroup,\n ReactiveFormsModule,\n Validators,\n AbstractControl,\n ValidatorFn,\n ControlValueAccessor,\n NG_VALUE_ACCESSOR,\n Validator,\n ValidationErrors,\n NG_VALIDATORS,\n} from '@angular/forms';\nimport { CommonModule } from '@angular/common';\nimport { DynamicField } from '@masterteam/forms/dynamic-field';\nimport { SortPipe } from '@masterteam/forms/pipes';\n// import { SortPipe } from '../pipes/sort.pipe';\nimport {\n DynamicFormConfig,\n ValidatorConfig,\n createCustomValidator,\n wrapValidatorWithMessage,\n} from '@masterteam/components';\nimport { Subscription } from 'rxjs';\n\n@Component({\n selector: 'mt-dynamic-form',\n standalone: true,\n imports: [CommonModule, ReactiveFormsModule, DynamicField, SortPipe],\n templateUrl: './dynamic-form.html',\n styleUrls: ['./dynamic-form.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => DynamicForm),\n multi: true,\n },\n {\n provide: NG_VALIDATORS,\n useExisting: forwardRef(() => DynamicForm),\n multi: true,\n },\n ],\n})\nexport class DynamicForm implements OnDestroy, ControlValueAccessor, Validator {\n private fb = inject(FormBuilder);\n\n readonly formConfig = input.required<DynamicFormConfig>();\n\n form = new FormGroup({});\n\n // ControlValueAccessor implementation\n private onChange = (_value: any) => {};\n private onTouched = () => {};\n private onValidatorChange = () => {};\n // private disabled = false;\n private formSubscription?: Subscription;\n private statusSubscription?: Subscription;\n\n constructor() {\n // Effect to rebuild form when config changes\n effect(() => {\n this.buildForm();\n });\n }\n\n registerOnValidatorChange(fn: () => void): void {\n this.onValidatorChange = fn;\n }\n registerOnChange(fn: (value: any) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n private buildForm() {\n // Clean up previous subscriptions\n if (this.formSubscription) {\n this.formSubscription.unsubscribe();\n }\n if (this.statusSubscription) {\n this.statusSubscription.unsubscribe();\n }\n\n const formControls: { [key: string]: AbstractControl } = {};\n\n this.formConfig().sections.forEach((section) => {\n section.fields.forEach((field) => {\n if (field.key) {\n const validators = this.buildValidators(field.validators || []);\n const control = this.fb.control(\n {\n value: field.defaultValue || '',\n disabled: field.disabled || false,\n },\n validators,\n );\n formControls[field.key] = control;\n }\n });\n });\n\n this.form = this.fb.group(formControls);\n\n // Subscribe to form value changes\n this.formSubscription = this.form.valueChanges.subscribe((value) => {\n this.onChange(value);\n });\n\n // Trigger initial validation state\n this.onValidatorChange();\n }\n\n // ControlValueAccessor implementation\n writeValue(value: any): void {\n if (value && this.form) {\n this.form.patchValue(value, { emitEvent: false });\n }\n }\n\n validate(_control: AbstractControl): ValidationErrors | null {\n if (!this.form) {\n return null;\n }\n // Return the form's errors if invalid, null if valid\n return this.form.valid ? null : { invalidForm: true };\n }\n\n private buildValidators(validatorConfigs: ValidatorConfig[]): ValidatorFn[] {\n const validators: ValidatorFn[] = [];\n\n validatorConfigs.forEach((config) => {\n let validator: ValidatorFn | null = null;\n\n switch (config.type) {\n case 'required':\n validator = Validators.required;\n break;\n case 'email':\n validator = Validators.email;\n break;\n case 'minLength':\n if (config.value) {\n validator = Validators.minLength(config.value);\n }\n break;\n case 'maxLength':\n if (config.value) {\n validator = Validators.maxLength(config.value);\n }\n break;\n case 'min':\n if (config.value !== undefined) {\n validator = Validators.min(config.value);\n }\n break;\n case 'max':\n if (config.value !== undefined) {\n validator = Validators.max(config.value);\n }\n break;\n case 'pattern':\n if (config.value) {\n validator = Validators.pattern(config.value);\n }\n break;\n case 'custom':\n if (config.customValidator) {\n validators.push(\n createCustomValidator(config.customValidator, config.message),\n );\n }\n break;\n }\n\n // If we have a validator and a custom message, wrap it\n if (validator && config.message) {\n validators.push(\n wrapValidatorWithMessage(validator, config.type, config.message),\n );\n } else if (validator) {\n validators.push(validator);\n }\n });\n\n return validators;\n }\n\n ngOnDestroy(): void {\n // Clean up subscriptions\n if (this.formSubscription) {\n this.formSubscription.unsubscribe();\n }\n if (this.statusSubscription) {\n this.statusSubscription.unsubscribe();\n }\n }\n}\n","<form [formGroup]=\"form\">\n <div\n class=\"flex flex-col gap-6 max-w-4xl mx-auto p-4\"\n [class]=\"formConfig().layout?.containerClass\"\n >\n @for (\n section of formConfig().sections | sort: \"order\";\n track section.key || $index\n ) {\n <div\n [class]=\"\n section.cssClass ||\n formConfig().layout?.sectionClass ||\n 'flex flex-col gap-4'\n \"\n >\n @if (section.type === \"header\" && section.label) {\n <h3\n [class]=\"\n section?.headerClass ||\n 'text-xl font-semibold text-gray-800 border-b-2 border-gray-200 pb-2 mb-4'\n \"\n >\n {{ section.label }}\n </h3>\n }\n\n <div\n [class]=\"\n section?.bodyClass ||\n 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 items-start'\n \"\n >\n @for (field of section.fields | sort: \"order\"; track field.key) {\n <div\n [class]=\"\n field.cssClass ||\n formConfig().layout?.fieldClass ||\n 'flex flex-col gap-1'\n \"\n [hidden]=\"field.hidden\"\n >\n <mt-dynamic-field\n [fieldConfig]=\"field\"\n [fieldName]=\"field.key!\"\n />\n </div>\n }\n </div>\n </div>\n }\n </div>\n</form>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Pipe } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
class SortPipe {
|
|
5
|
+
transform(array, keySort = 'order', direction = 'asc') {
|
|
6
|
+
if (!array || !Array.isArray(array)) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
return [...array].sort((a, b) => {
|
|
10
|
+
const aValue = this.getNestedValue(a, keySort);
|
|
11
|
+
const bValue = this.getNestedValue(b, keySort);
|
|
12
|
+
// Handle null/undefined values - they should go to the end
|
|
13
|
+
if (aValue == null && bValue == null)
|
|
14
|
+
return 0;
|
|
15
|
+
if (aValue == null)
|
|
16
|
+
return 1;
|
|
17
|
+
if (bValue == null)
|
|
18
|
+
return -1;
|
|
19
|
+
let comparison = 0;
|
|
20
|
+
if (typeof aValue === 'string' && typeof bValue === 'string') {
|
|
21
|
+
comparison = aValue.localeCompare(bValue);
|
|
22
|
+
}
|
|
23
|
+
else if (typeof aValue === 'number' && typeof bValue === 'number') {
|
|
24
|
+
comparison = aValue - bValue;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
// Convert to string for comparison
|
|
28
|
+
const aStr = String(aValue);
|
|
29
|
+
const bStr = String(bValue);
|
|
30
|
+
comparison = aStr.localeCompare(bStr);
|
|
31
|
+
}
|
|
32
|
+
return direction === 'desc' ? -comparison : comparison;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
getNestedValue(obj, path) {
|
|
36
|
+
return path.split('.').reduce((current, key) => {
|
|
37
|
+
return current && current[key] !== undefined ? current[key] : 0;
|
|
38
|
+
}, obj);
|
|
39
|
+
}
|
|
40
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: SortPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
41
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.1.0", ngImport: i0, type: SortPipe, isStandalone: true, name: "sort" });
|
|
42
|
+
}
|
|
43
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0", ngImport: i0, type: SortPipe, decorators: [{
|
|
44
|
+
type: Pipe,
|
|
45
|
+
args: [{
|
|
46
|
+
name: 'sort',
|
|
47
|
+
standalone: true,
|
|
48
|
+
pure: true,
|
|
49
|
+
}]
|
|
50
|
+
}] });
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Generated bundle index. Do not edit.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
export { SortPipe };
|
|
57
|
+
//# sourceMappingURL=masterteam-forms-pipes.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"masterteam-forms-pipes.mjs","sources":["../../../../packages/masterteam/forms/pipes/sort.pipe.ts","../../../../packages/masterteam/forms/pipes/masterteam-forms-pipes.ts"],"sourcesContent":["import { Pipe, PipeTransform } from '@angular/core';\n\n@Pipe({\n name: 'sort',\n standalone: true,\n pure: true,\n})\nexport class SortPipe implements PipeTransform {\n transform<T>(\n array: T[] | null | undefined,\n keySort: string = 'order',\n direction: 'asc' | 'desc' = 'asc',\n ): T[] {\n if (!array || !Array.isArray(array)) {\n return [];\n }\n\n return [...array].sort((a, b) => {\n const aValue = this.getNestedValue(a, keySort);\n const bValue = this.getNestedValue(b, keySort);\n\n // Handle null/undefined values - they should go to the end\n if (aValue == null && bValue == null) return 0;\n if (aValue == null) return 1;\n if (bValue == null) return -1;\n\n let comparison = 0;\n\n if (typeof aValue === 'string' && typeof bValue === 'string') {\n comparison = aValue.localeCompare(bValue);\n } else if (typeof aValue === 'number' && typeof bValue === 'number') {\n comparison = aValue - bValue;\n } else {\n // Convert to string for comparison\n const aStr = String(aValue);\n const bStr = String(bValue);\n comparison = aStr.localeCompare(bStr);\n }\n\n return direction === 'desc' ? -comparison : comparison;\n });\n }\n\n private getNestedValue(obj: any, path: string): any {\n return path.split('.').reduce((current, key) => {\n return current && current[key] !== undefined ? current[key] : 0;\n }, obj);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;MAOa,QAAQ,CAAA;AACnB,IAAA,SAAS,CACP,KAA6B,EAC7B,UAAkB,OAAO,EACzB,YAA4B,KAAK,EAAA;QAEjC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACnC,YAAA,OAAO,EAAE;QACX;AAEA,QAAA,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,KAAI;YAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC;YAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,OAAO,CAAC;;AAG9C,YAAA,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI;AAAE,gBAAA,OAAO,CAAC;YAC9C,IAAI,MAAM,IAAI,IAAI;AAAE,gBAAA,OAAO,CAAC;YAC5B,IAAI,MAAM,IAAI,IAAI;gBAAE,OAAO,CAAC,CAAC;YAE7B,IAAI,UAAU,GAAG,CAAC;YAElB,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AAC5D,gBAAA,UAAU,GAAG,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC;YAC3C;iBAAO,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;AACnE,gBAAA,UAAU,GAAG,MAAM,GAAG,MAAM;YAC9B;iBAAO;;AAEL,gBAAA,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC;AAC3B,gBAAA,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC;AAC3B,gBAAA,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YACvC;AAEA,YAAA,OAAO,SAAS,KAAK,MAAM,GAAG,CAAC,UAAU,GAAG,UAAU;AACxD,QAAA,CAAC,CAAC;IACJ;IAEQ,cAAc,CAAC,GAAQ,EAAE,IAAY,EAAA;AAC3C,QAAA,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,GAAG,KAAI;AAC7C,YAAA,OAAO,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;QACjE,CAAC,EAAE,GAAG,CAAC;IACT;uGAxCW,QAAQ,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,IAAA,EAAA,CAAA;qGAAR,QAAQ,EAAA,YAAA,EAAA,IAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA;;2FAAR,QAAQ,EAAA,UAAA,EAAA,CAAA;kBALpB,IAAI;AAAC,YAAA,IAAA,EAAA,CAAA;AACJ,oBAAA,IAAI,EAAE,MAAM;AACZ,oBAAA,UAAU,EAAE,IAAI;AAChB,oBAAA,IAAI,EAAE,IAAI;AACX,iBAAA;;;ACND;;AAEG;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"masterteam-forms.mjs","sources":["../../../../packages/masterteam/forms/src/public-api.ts","../../../../packages/masterteam/forms/src/masterteam-forms.ts"],"sourcesContent":["export default {};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"AAAA,gBAAe,EAAE;;ACAjB;;AAEG"}
|
package/index.d.ts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@masterteam/forms",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"directory": ".",
|
|
6
|
+
"linkDirectory": false,
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"peerDependencies": {
|
|
10
|
+
"@angular/common": "^20.1.0",
|
|
11
|
+
"@angular/core": "^20.1.0",
|
|
12
|
+
"@angular/forms": "^20.1.0",
|
|
13
|
+
"postcss": "^8.5.6",
|
|
14
|
+
"@tailwindcss/postcss": "^4.1.11",
|
|
15
|
+
"tailwindcss": "^4.1.11",
|
|
16
|
+
"tailwindcss-primeui": "^0.6.1",
|
|
17
|
+
"primeng": "20.0.0-rc.3",
|
|
18
|
+
"@primeuix/themes": "^1.2.1",
|
|
19
|
+
"rxjs": "^7.8.2"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@masterteam/components": "x",
|
|
23
|
+
"tslib": "^2.3.0"
|
|
24
|
+
},
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"module": "fesm2022/masterteam-forms.mjs",
|
|
27
|
+
"typings": "index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
"./package.json": {
|
|
30
|
+
"default": "./package.json"
|
|
31
|
+
},
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./index.d.ts",
|
|
34
|
+
"default": "./fesm2022/masterteam-forms.mjs"
|
|
35
|
+
},
|
|
36
|
+
"./dynamic-field": {
|
|
37
|
+
"types": "./dynamic-field/index.d.ts",
|
|
38
|
+
"default": "./fesm2022/masterteam-forms-dynamic-field.mjs"
|
|
39
|
+
},
|
|
40
|
+
"./dynamic-form": {
|
|
41
|
+
"types": "./dynamic-form/index.d.ts",
|
|
42
|
+
"default": "./fesm2022/masterteam-forms-dynamic-form.mjs"
|
|
43
|
+
},
|
|
44
|
+
"./pipes": {
|
|
45
|
+
"types": "./pipes/index.d.ts",
|
|
46
|
+
"default": "./fesm2022/masterteam-forms-pipes.mjs"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
package/pipes/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { PipeTransform } from '@angular/core';
|
|
3
|
+
|
|
4
|
+
declare class SortPipe implements PipeTransform {
|
|
5
|
+
transform<T>(array: T[] | null | undefined, keySort?: string, direction?: 'asc' | 'desc'): T[];
|
|
6
|
+
private getNestedValue;
|
|
7
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SortPipe, never>;
|
|
8
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<SortPipe, "sort", true>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { SortPipe };
|