@masterteam/forms 0.0.5 → 0.0.6
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.
|
@@ -64,7 +64,7 @@ class DynamicForm {
|
|
|
64
64
|
else {
|
|
65
65
|
// Regular field without nesting
|
|
66
66
|
const control = this.fb.control({
|
|
67
|
-
value: field.defaultValue
|
|
67
|
+
value: field.defaultValue,
|
|
68
68
|
disabled: field.disabled || false,
|
|
69
69
|
}, validators);
|
|
70
70
|
formControls[field.key] = control;
|
|
@@ -1 +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\n // Check if field key contains dot notation (e.g., \"name.ar\", \"name.en\")\n if (field.key.includes('.')) {\n const [parentKey, childKey] = field.key.split('.');\n\n // Create or get the parent FormGroup\n if (!formControls[parentKey]) {\n formControls[parentKey] = this.fb.group({});\n }\n\n const parentGroup = formControls[parentKey] as FormGroup;\n\n // Add the child control to the parent group\n const control = this.fb.control(\n {\n value: field.defaultValue,\n disabled: field.disabled || false,\n },\n validators,\n );\n\n parentGroup.addControl(childKey, control);\n } else {\n // Regular field without nesting\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\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 @if (field.key!.includes(\".\")) {\n <!-- Handle nested fields (e.g., name.ar, name.en) -->\n @let parentKey = field.key!.split(\".\")[0];\n @let childKey = field.key!.split(\".\")[1];\n <form [formGroup]=\"form.get(parentKey)\">\n <mt-dynamic-field\n [fieldConfig]=\"field\"\n [fieldName]=\"childKey\"\n />\n </form>\n } @else {\n <!-- Handle regular fields -->\n <mt-dynamic-field\n [fieldConfig]=\"field\"\n [fieldName]=\"field.key!\"\n />\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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"}
|
|
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\n // Check if field key contains dot notation (e.g., \"name.ar\", \"name.en\")\n if (field.key.includes('.')) {\n const [parentKey, childKey] = field.key.split('.');\n\n // Create or get the parent FormGroup\n if (!formControls[parentKey]) {\n formControls[parentKey] = this.fb.group({});\n }\n\n const parentGroup = formControls[parentKey] as FormGroup;\n\n // Add the child control to the parent group\n const control = this.fb.control(\n {\n value: field.defaultValue,\n disabled: field.disabled || false,\n },\n validators,\n );\n\n parentGroup.addControl(childKey, control);\n } else {\n // Regular field without nesting\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\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 @if (field.key!.includes(\".\")) {\n <!-- Handle nested fields (e.g., name.ar, name.en) -->\n @let parentKey = field.key!.split(\".\")[0];\n @let childKey = field.key!.split(\".\")[1];\n <form [formGroup]=\"form.get(parentKey)\">\n <mt-dynamic-field\n [fieldConfig]=\"field\"\n [fieldName]=\"childKey\"\n />\n </form>\n } @else {\n <!-- Handle regular fields -->\n <mt-dynamic-field\n [fieldConfig]=\"field\"\n [fieldName]=\"field.key!\"\n />\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":";;;;;;;;;MAsDa,WAAW,CAAA;AACd,IAAA,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC;AAEvB,IAAA,UAAU,GAAG,KAAK,CAAC,QAAQ,qDAAqB;AAEzD,IAAA,IAAI,GAAG,IAAI,SAAS,CAAC,EAAE,CAAC;;AAGhB,IAAA,QAAQ,GAAG,CAAC,MAAW,KAAI,EAAE,CAAC;AAC9B,IAAA,SAAS,GAAG,MAAK,EAAE,CAAC;AACpB,IAAA,iBAAiB,GAAG,MAAK,EAAE,CAAC;;AAE5B,IAAA,gBAAgB;AAChB,IAAA,kBAAkB;AAE1B,IAAA,WAAA,GAAA;;QAEE,MAAM,CAAC,MAAK;YACV,IAAI,CAAC,SAAS,EAAE;AAClB,QAAA,CAAC,CAAC;IACJ;AAEA,IAAA,yBAAyB,CAAC,EAAc,EAAA;AACtC,QAAA,IAAI,CAAC,iBAAiB,GAAG,EAAE;IAC7B;AACA,IAAA,gBAAgB,CAAC,EAAwB,EAAA;AACvC,QAAA,IAAI,CAAC,QAAQ,GAAG,EAAE;IACpB;AAEA,IAAA,iBAAiB,CAAC,EAAc,EAAA;AAC9B,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;IACrB;IAEQ,SAAS,GAAA;;AAEf,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;AACzB,YAAA,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE;QACrC;AACA,QAAA,IAAI,IAAI,CAAC,kBAAkB,EAAE;AAC3B,YAAA,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE;QACvC;QAEA,MAAM,YAAY,GAAuC,EAAE;QAE3D,IAAI,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,OAAO,KAAI;YAC7C,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,KAAI;AAC/B,gBAAA,IAAI,KAAK,CAAC,GAAG,EAAE;AACb,oBAAA,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC;;oBAG/D,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;AAC3B,wBAAA,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;;AAGlD,wBAAA,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE;AAC5B,4BAAA,YAAY,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;wBAC7C;AAEA,wBAAA,MAAM,WAAW,GAAG,YAAY,CAAC,SAAS,CAAc;;AAGxD,wBAAA,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC7B;4BACE,KAAK,EAAE,KAAK,CAAC,YAAY;AACzB,4BAAA,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK;yBAClC,EACD,UAAU,CACX;AAED,wBAAA,WAAW,CAAC,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC;oBAC3C;yBAAO;;AAEL,wBAAA,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC7B;4BACE,KAAK,EAAE,KAAK,CAAC,YAAY;AACzB,4BAAA,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,KAAK;yBAClC,EACD,UAAU,CACX;AACD,wBAAA,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO;oBACnC;gBACF;AACF,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;QAEF,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC;;AAGvC,QAAA,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,KAAK,KAAI;AACjE,YAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;AACtB,QAAA,CAAC,CAAC;;QAGF,IAAI,CAAC,iBAAiB,EAAE;IAC1B;;AAGA,IAAA,UAAU,CAAC,KAAU,EAAA;AACnB,QAAA,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,EAAE;AACtB,YAAA,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACnD;IACF;AAEA,IAAA,QAAQ,CAAC,QAAyB,EAAA;AAChC,QAAA,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;AACd,YAAA,OAAO,IAAI;QACb;;AAEA,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,WAAW,EAAE,IAAI,EAAE;IACvD;AAEQ,IAAA,eAAe,CAAC,gBAAmC,EAAA;QACzD,MAAM,UAAU,GAAkB,EAAE;AAEpC,QAAA,gBAAgB,CAAC,OAAO,CAAC,CAAC,MAAM,KAAI;YAClC,IAAI,SAAS,GAAuB,IAAI;AAExC,YAAA,QAAQ,MAAM,CAAC,IAAI;AACjB,gBAAA,KAAK,UAAU;AACb,oBAAA,SAAS,GAAG,UAAU,CAAC,QAAQ;oBAC/B;AACF,gBAAA,KAAK,OAAO;AACV,oBAAA,SAAS,GAAG,UAAU,CAAC,KAAK;oBAC5B;AACF,gBAAA,KAAK,WAAW;AACd,oBAAA,IAAI,MAAM,CAAC,KAAK,EAAE;wBAChB,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC;oBAChD;oBACA;AACF,gBAAA,KAAK,WAAW;AACd,oBAAA,IAAI,MAAM,CAAC,KAAK,EAAE;wBAChB,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC;oBAChD;oBACA;AACF,gBAAA,KAAK,KAAK;AACR,oBAAA,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE;wBAC9B,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;oBAC1C;oBACA;AACF,gBAAA,KAAK,KAAK;AACR,oBAAA,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE;wBAC9B,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;oBAC1C;oBACA;AACF,gBAAA,KAAK,SAAS;AACZ,oBAAA,IAAI,MAAM,CAAC,KAAK,EAAE;wBAChB,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;oBAC9C;oBACA;AACF,gBAAA,KAAK,QAAQ;AACX,oBAAA,IAAI,MAAM,CAAC,eAAe,EAAE;AAC1B,wBAAA,UAAU,CAAC,IAAI,CACb,qBAAqB,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,OAAO,CAAC,CAC9D;oBACH;oBACA;;;AAIJ,YAAA,IAAI,SAAS,IAAI,MAAM,CAAC,OAAO,EAAE;AAC/B,gBAAA,UAAU,CAAC,IAAI,CACb,wBAAwB,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CACjE;YACH;iBAAO,IAAI,SAAS,EAAE;AACpB,gBAAA,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;YAC5B;AACF,QAAA,CAAC,CAAC;AAEF,QAAA,OAAO,UAAU;IACnB;IAEA,WAAW,GAAA;;AAET,QAAA,IAAI,IAAI,CAAC,gBAAgB,EAAE;AACzB,YAAA,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE;QACrC;AACA,QAAA,IAAI,IAAI,CAAC,kBAAkB,EAAE;AAC3B,YAAA,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE;QACvC;IACF;uGAnLW,WAAW,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAX,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,WAAW,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EAbX;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,iBAAiB;AAC1B,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,WAAW,CAAC;AAC1C,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;AACD,YAAA;AACE,gBAAA,OAAO,EAAE,aAAa;AACtB,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,WAAW,CAAC;AAC1C,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;SACF,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECpDH,0gEAkEA,yDD7BY,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,aAAA,EAAA,QAAA,EAAA,8CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,0FAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,kBAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,YAAY,8FAAE,QAAQ,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAiBxD,WAAW,EAAA,UAAA,EAAA,CAAA;kBApBvB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iBAAiB,cACf,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAA,eAAA,EAGnD,uBAAuB,CAAC,MAAM,EAAA,SAAA,EACpC;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,iBAAiB;AAC1B,4BAAA,WAAW,EAAE,UAAU,CAAC,iBAAiB,CAAC;AAC1C,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACD,wBAAA;AACE,4BAAA,OAAO,EAAE,aAAa;AACtB,4BAAA,WAAW,EAAE,UAAU,CAAC,iBAAiB,CAAC;AAC1C,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA,EAAA,QAAA,EAAA,0gEAAA,EAAA;;;AEpDH;;AAEG;;;;"}
|