ngx-histaff-alpha 5.9.1 → 5.9.2

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 (38) hide show
  1. package/fesm2022/{ngx-histaff-alpha-ai-hint-for-table.component-ClNRMk6B.mjs → ngx-histaff-alpha-ai-hint-for-table.component-BO_Ci77l.mjs} +3 -3
  2. package/fesm2022/{ngx-histaff-alpha-ai-hint-for-table.component-ClNRMk6B.mjs.map → ngx-histaff-alpha-ai-hint-for-table.component-BO_Ci77l.mjs.map} +1 -1
  3. package/fesm2022/{ngx-histaff-alpha-core-form-design.component-KQsI4L2g.mjs → ngx-histaff-alpha-core-form-design.component-CGf-jOqR.mjs} +996 -154
  4. package/fesm2022/ngx-histaff-alpha-core-form-design.component-CGf-jOqR.mjs.map +1 -0
  5. package/fesm2022/{ngx-histaff-alpha-core-sticker-collection.component-ZJ29hnW7.mjs → ngx-histaff-alpha-core-sticker-collection.component-zkrmzfmx.mjs} +3 -3
  6. package/fesm2022/{ngx-histaff-alpha-core-sticker-collection.component-ZJ29hnW7.mjs.map → ngx-histaff-alpha-core-sticker-collection.component-zkrmzfmx.mjs.map} +1 -1
  7. package/fesm2022/{ngx-histaff-alpha-core-toast-loading.component-D4lPsJ_K.mjs → ngx-histaff-alpha-core-toast-loading.component-BLGPX2ov.mjs} +2 -2
  8. package/fesm2022/{ngx-histaff-alpha-core-toast-loading.component-D4lPsJ_K.mjs.map → ngx-histaff-alpha-core-toast-loading.component-BLGPX2ov.mjs.map} +1 -1
  9. package/fesm2022/{ngx-histaff-alpha-core-workflow-consume.component-Dxy4PssU.mjs → ngx-histaff-alpha-core-workflow-consume.component-DKYtFwki.mjs} +2 -2
  10. package/fesm2022/{ngx-histaff-alpha-core-workflow-consume.component-Dxy4PssU.mjs.map → ngx-histaff-alpha-core-workflow-consume.component-DKYtFwki.mjs.map} +1 -1
  11. package/fesm2022/{ngx-histaff-alpha-db-settings.component-ovw3ShzY.mjs → ngx-histaff-alpha-db-settings.component-CBB_Ahf3.mjs} +5 -5
  12. package/fesm2022/{ngx-histaff-alpha-db-settings.component-ovw3ShzY.mjs.map → ngx-histaff-alpha-db-settings.component-CBB_Ahf3.mjs.map} +1 -1
  13. package/fesm2022/{ngx-histaff-alpha-design-wrapper.component-Dd5UoJX1.mjs → ngx-histaff-alpha-design-wrapper.component-DaSrXARH.mjs} +5 -5
  14. package/fesm2022/{ngx-histaff-alpha-design-wrapper.component-Dd5UoJX1.mjs.map → ngx-histaff-alpha-design-wrapper.component-DaSrXARH.mjs.map} +1 -1
  15. package/fesm2022/{ngx-histaff-alpha-design-wrapper.route-DLdFwwhp.mjs → ngx-histaff-alpha-design-wrapper.route-RgR94c12.mjs} +5 -5
  16. package/fesm2022/{ngx-histaff-alpha-design-wrapper.route-DLdFwwhp.mjs.map → ngx-histaff-alpha-design-wrapper.route-RgR94c12.mjs.map} +1 -1
  17. package/fesm2022/{ngx-histaff-alpha-form-array-props.component-DkAM9Uk9.mjs → ngx-histaff-alpha-form-array-props.component-CCccglL5.mjs} +3 -3
  18. package/fesm2022/{ngx-histaff-alpha-form-array-props.component-DkAM9Uk9.mjs.map → ngx-histaff-alpha-form-array-props.component-CCccglL5.mjs.map} +1 -1
  19. package/fesm2022/{ngx-histaff-alpha-live-form.component-BMCAth2_.mjs → ngx-histaff-alpha-live-form.component-Df56ufkx.mjs} +2 -2
  20. package/fesm2022/{ngx-histaff-alpha-live-form.component-BMCAth2_.mjs.map → ngx-histaff-alpha-live-form.component-Df56ufkx.mjs.map} +1 -1
  21. package/fesm2022/{ngx-histaff-alpha-ngx-histaff-alpha-CkvGEG39.mjs → ngx-histaff-alpha-ngx-histaff-alpha-CYQ3j6IP.mjs} +31 -12
  22. package/fesm2022/{ngx-histaff-alpha-ngx-histaff-alpha-CkvGEG39.mjs.map → ngx-histaff-alpha-ngx-histaff-alpha-CYQ3j6IP.mjs.map} +1 -1
  23. package/fesm2022/{ngx-histaff-alpha-tracker-studio.component-CeB-VuEP.mjs → ngx-histaff-alpha-tracker-studio.component-h4r8nXvw.mjs} +2 -2
  24. package/fesm2022/{ngx-histaff-alpha-tracker-studio.component-CeB-VuEP.mjs.map → ngx-histaff-alpha-tracker-studio.component-h4r8nXvw.mjs.map} +1 -1
  25. package/fesm2022/{ngx-histaff-alpha-wf-form-assign.component-CO09ZkTB.mjs → ngx-histaff-alpha-wf-form-assign.component-Dcwd8mdT.mjs} +2 -2
  26. package/fesm2022/{ngx-histaff-alpha-wf-form-assign.component-CO09ZkTB.mjs.map → ngx-histaff-alpha-wf-form-assign.component-Dcwd8mdT.mjs.map} +1 -1
  27. package/fesm2022/{ngx-histaff-alpha-wf-instance-status.component-DQfVNySE.mjs → ngx-histaff-alpha-wf-instance-status.component-BEucf9x7.mjs} +4 -4
  28. package/fesm2022/{ngx-histaff-alpha-wf-instance-status.component-DQfVNySE.mjs.map → ngx-histaff-alpha-wf-instance-status.component-BEucf9x7.mjs.map} +1 -1
  29. package/fesm2022/{ngx-histaff-alpha-wf-instance-step-react.component-DRUYdQY3.mjs → ngx-histaff-alpha-wf-instance-step-react.component-CR-UUVFi.mjs} +3 -3
  30. package/fesm2022/{ngx-histaff-alpha-wf-instance-step-react.component-DRUYdQY3.mjs.map → ngx-histaff-alpha-wf-instance-step-react.component-CR-UUVFi.mjs.map} +1 -1
  31. package/fesm2022/ngx-histaff-alpha.mjs +1 -1
  32. package/lib/app/libraries/core-form-design/core-form-array-layout-editor/core-form-array-layout-editor.component.d.ts +1 -8
  33. package/lib/app/libraries/core-form-design/core-form-design.component.d.ts +1 -2
  34. package/lib/app/libraries/core-form-design/core-form-design.service.d.ts +12 -2
  35. package/lib/app/libraries/core-form-design/core-form-group-editor.component.d.ts +104 -0
  36. package/lib/app/libraries/core-form-design/field-setting/field-setting.component.d.ts +2 -1
  37. package/package.json +1 -1
  38. package/fesm2022/ngx-histaff-alpha-core-form-design.component-KQsI4L2g.mjs.map +0 -1
@@ -1,16 +1,16 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ChangeDetectorRef, Component, signal, effect, HostListener, ChangeDetectionStrategy, Injectable, computed, viewChild, ViewContainerRef, Input, EventEmitter, Output, Renderer2, input, isDevMode } from '@angular/core';
2
+ import { inject, ChangeDetectorRef, Component, signal, effect, HostListener, ChangeDetectionStrategy, Injectable, computed, viewChild, ViewContainerRef, Input, EventEmitter, Output, input, Renderer2, isDevMode } from '@angular/core';
3
3
  import { trigger, state, transition, style, animate } from '@angular/animations';
4
- import { n as CoreFormDesignService, b as CoreWorkflowService, B as BaseEditComponent, i as AlertService, L as AppConfigService, O as EnumCorePageEditMode, P as EnumCoreButtonVNSCode, R as READONLY_WORKFLOW_FIELDS, Q as noneAutoClosedAlertOptions, p as DialogService, M as MultiLanguageService, C as CorePageHeaderComponent, U as CoreFormComponent, V as CoreButtonGroupVnsComponent, T as TranslatePipe, E as EnumFormBaseContolType, e as BaseComponent, W as EnumCoreTablePipeType, J as CoreCheckboxComponent, r as CoreDropdownComponent, g as TooltipDirective, G as GptService, l as alertOptions, y as CoreRadioGroupComponent, X as HtmlTooltipDirective, c as EnumCoreFormControlSeekerSourceType, Y as CoreControlNoFormArrayComponent, Z as EnumFormDesignMode, q as DomService, K as JsonService, z as ApplicationHelpService, H as HotKeysDirective, _ as CoreControlComponent, j as TableCellPipe, s as CoreChecklistComponent, u as CoreFormControlSeekerComponent, $ as CoreAttachmentComponent, t as CoreDatePickerComponent, a0 as CoreMonthSelectorComponent, v as CoreCurrencyInputComponent } from './ngx-histaff-alpha-ngx-histaff-alpha-CkvGEG39.mjs';
4
+ import { n as CoreFormDesignService, b as CoreWorkflowService, B as BaseEditComponent, i as AlertService, L as AppConfigService, O as EnumCorePageEditMode, P as EnumCoreButtonVNSCode, R as READONLY_WORKFLOW_FIELDS, Q as noneAutoClosedAlertOptions, p as DialogService, M as MultiLanguageService, C as CorePageHeaderComponent, U as CoreFormComponent, V as CoreButtonGroupVnsComponent, T as TranslatePipe, E as EnumFormBaseContolType, e as BaseComponent, W as EnumCoreTablePipeType, J as CoreCheckboxComponent, r as CoreDropdownComponent, g as TooltipDirective, G as GptService, l as alertOptions, y as CoreRadioGroupComponent, X as HtmlTooltipDirective, c as EnumCoreFormControlSeekerSourceType, Y as CoreControlNoFormArrayComponent, Z as EnumFormDesignMode, q as DomService, K as JsonService, z as ApplicationHelpService, _ as CoreControlComponent, j as TableCellPipe, H as HotKeysDirective, s as CoreChecklistComponent, u as CoreFormControlSeekerComponent, $ as CoreAttachmentComponent, t as CoreDatePickerComponent, a0 as CoreMonthSelectorComponent, v as CoreCurrencyInputComponent } from './ngx-histaff-alpha-ngx-histaff-alpha-CYQ3j6IP.mjs';
5
5
  import * as i1 from '@angular/forms';
6
6
  import { FormsModule, FormGroup, FormControl, FormArray, Validators, ReactiveFormsModule } from '@angular/forms';
7
- import { NgStyle, JsonPipe, UpperCasePipe, AsyncPipe, NgTemplateOutlet } from '@angular/common';
7
+ import { NgStyle, JsonPipe, AsyncPipe, NgTemplateOutlet } from '@angular/common';
8
8
  import { BehaviorSubject, catchError, of, filter, distinctUntilChanged, tap, switchMap } from 'rxjs';
9
9
  import { Router, ActivatedRoute } from '@angular/router';
10
- import { CoreStickerCollectionComponent } from './ngx-histaff-alpha-core-sticker-collection.component-ZJ29hnW7.mjs';
11
- import { D as DbService, C as CoreToastLoadingComponent } from './ngx-histaff-alpha-core-toast-loading.component-D4lPsJ_K.mjs';
10
+ import { CoreStickerCollectionComponent } from './ngx-histaff-alpha-core-sticker-collection.component-zkrmzfmx.mjs';
11
+ import { D as DbService, C as CoreToastLoadingComponent } from './ngx-histaff-alpha-core-toast-loading.component-BLGPX2ov.mjs';
12
12
  import { EnumTranslateKey } from 'alpha-global-constants';
13
- import { L as LiveFormComponent } from './ngx-histaff-alpha-live-form.component-BMCAth2_.mjs';
13
+ import { L as LiveFormComponent } from './ngx-histaff-alpha-live-form.component-Df56ufkx.mjs';
14
14
 
15
15
  const slideFromTopFadeIn = trigger('slideFromTopFadeIn', [
16
16
  state('in', style({ opacity: 1, transform: 'translateY(0)' })),
@@ -1081,6 +1081,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImpor
1081
1081
  class FieldSettingComponent extends BaseComponent {
1082
1082
  constructor() {
1083
1083
  super(...arguments);
1084
+ this.$isNested = input(false);
1084
1085
  this.coreFormDesignService = inject(CoreFormDesignService);
1085
1086
  this.enumControlType = EnumFormBaseContolType;
1086
1087
  this.renderer = inject(Renderer2);
@@ -1098,7 +1099,7 @@ class FieldSettingComponent extends BaseComponent {
1098
1099
  'number-props': () => Promise.resolve().then(function () { return numberProps_component; }).then(m => m.NumberPropsComponent),
1099
1100
  'email-props': () => import('./ngx-histaff-alpha-email-props.component-Cf35Pexq.mjs').then(m => m.EmailPropsComponent),
1100
1101
  'dropdown-props': () => Promise.resolve().then(function () { return dropdownProps_component; }).then(m => m.DropdownPropsComponent),
1101
- 'form-array-props': () => import('./ngx-histaff-alpha-form-array-props.component-DkAM9Uk9.mjs').then(m => m.FormArrayPropsComponent),
1102
+ 'form-array-props': () => import('./ngx-histaff-alpha-form-array-props.component-CCccglL5.mjs').then(m => m.FormArrayPropsComponent),
1102
1103
  // etc...
1103
1104
  };
1104
1105
  }
@@ -1147,7 +1148,7 @@ class FieldSettingComponent extends BaseComponent {
1147
1148
  this.listenerFn();
1148
1149
  }
1149
1150
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: FieldSettingComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1150
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.5", type: FieldSettingComponent, isStandalone: true, selector: "field-setting", usesInheritance: true, ngImport: i0, template: "<div class=\"field-setting-container\">\r\n\r\n @if (!!$control()) {\r\n <div class=\"panel-caption-header\">\r\n <div class=\"panel-caption\">\r\n Editing: {{ $control().type !== 'calculated' ? $control()?.controlType + ' - ' : '' }}{{ $control()?.field ||\r\n 'Unnamed' }}\r\n </div>\r\n <div class=\"close-wrapper pointer\" (click)=\"closeFieldSettingPanel()\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n </div>\r\n\r\n\r\n <div class=\"field-setting-content\">\r\n\r\n\r\n @if ($control().type === 'calculated') {\r\n\r\n <div class=\"group-title mandatory\">\r\n <div class=\"icon-wrapper\">\r\n <i class=\"feather-lock\"></i>\r\n </div>\r\n <div class=\"group-name\">Mandatory</div>\r\n </div>\r\n <mandatory-props></mandatory-props>\r\n\r\n <div class=\"group-title calculated\">\r\n <div class=\"icon-wrapper\">\r\n <i class=\"feather-lock\"></i>\r\n </div>\r\n <div class=\"group-name\">Calculated Rule<i class=\"feather-help-circle\" [htmlTooltip]=\"aboutCalculatedField\"\r\n [maxWidthUnset]=\"true\"></i></div>\r\n </div>\r\n <calculated-props></calculated-props>\r\n\r\n\r\n } @else {\r\n\r\n <div class=\"group-title mandatory\">\r\n <div class=\"icon-wrapper\">\r\n <i class=\"feather-lock\"></i>\r\n </div>\r\n <div class=\"group-name\">Mandatory</div>\r\n </div>\r\n <mandatory-props></mandatory-props>\r\n\r\n <!-- <div class=\"setting-divider\"></div> -->\r\n\r\n @if ($control().controlType !== 'FORM_ARRAY') {\r\n <div class=\"group-title optional\">\r\n <div class=\"icon-wrapper\">\r\n <i class=\"feather-sliders\"></i>\r\n </div>\r\n <div class=\"group-name\">Optional</div>\r\n </div>\r\n <optional-props></optional-props>\r\n\r\n <!-- <div class=\"setting-divider\"></div> -->\r\n\r\n <div class=\"group-title validators\">\r\n <div class=\"icon-wrapper\">\r\n <i class=\"feather-check-square\"></i>\r\n </div>\r\n <div class=\"group-name\">Validators</div>\r\n </div>\r\n <validator-editor></validator-editor>\r\n }\r\n\r\n @if (!($control().controlType === 'TEXTBOX' && ['string', 'text', 'email'].includes(($control().type ||\r\n '').toLowerCase()))) {\r\n\r\n <div class=\"group-title\">\r\n <div class=\"icon-wrapper\">\r\n <i class=\"feather-check-square\"></i>\r\n </div>\r\n <div class=\"group-name\">{{ getFriendlyControlLabel($control()) }} Settings</div>\r\n </div>\r\n\r\n <props-host [loadComponent]=\"componentLoaderMap[coreFormDesignService.$currentPropsComponent()]\"\r\n [props]=\"{ control: $control(), controlChange: onControlParamsChange.bind(this) }\">\r\n </props-host>\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n\r\n\r\n</div>\r\n\r\n<ng-template #aboutCalculatedField>\r\n\r\n <div class=\"calculated-field-rule\" style=\"padding: 1rem; border-radius: 8px; background: #000; width: 800px;\">\r\n <h4 style=\"margin-top: 0; color: #fff;\">Calculated Field Rule</h4>\r\n <p><strong>Calculated fields</strong> are invisible boolean fields evaluated based on form inputs and logic. They\r\n help drive dynamic workflow behavior, such as conditional routing or validation triggers.</p>\r\n\r\n <h5 style=\"margin-bottom: 0.5rem; color: #fff;\">Key Properties</h5>\r\n <ul style=\"margin-top: 0;\">\r\n <li><strong>script:</strong> Expression to evaluate (e.g.,\r\n <code>leaveDays &gt; 3 &amp;&amp; status == 'Approved'</code>)</li>\r\n <li><strong>evaluationMode:</strong> <code>\"in-memory\"</code> or <code>\"sql-query\"</code></li>\r\n <li><strong>dependsOn[]:</strong> List of field names the script depends on</li>\r\n <li><strong>filterMode:</strong> <code>\"HardBlock\"</code> or <code>\"SoftWarn\"</code></li>\r\n </ul>\r\n\r\n <h5 style=\"margin-bottom: 0.5rem; color: #fff;\">Evaluation Modes</h5>\r\n <ul style=\"margin-top: 0;\">\r\n <li>\r\n <strong>in-memory:</strong> Uses <code>DynamicExpresso</code> to evaluate C#-like logic at runtime<br />\r\n <small>Example: <code>leaveType == \"ANNUAL\" &amp;&amp; leaveDays &lt; 5</code></small>\r\n </li>\r\n <li>\r\n <strong>sql-query:</strong> Runs backend SQL to evaluate conditions via\r\n <code>SELECT CASE WHEN ... THEN 1 ELSE 0 END</code><br />\r\n <small>Example:\r\n <code>SELECT CASE WHEN QUOTA &gt; 0 THEN 1 ELSE 0 END FROM LEAVE_QUOTA WHERE EMPLOYEE_ID = {{ '@' }}employeeId</code></small>\r\n </li>\r\n </ul>\r\n\r\n <h5 style=\"margin-bottom: 0.5rem; color: #fff;\">Use Cases</h5>\r\n <ul style=\"margin-top: 0;\">\r\n <li>Validate complex logic without showing the field</li>\r\n <li>Route to a different workflow branch based on hidden logic</li>\r\n <li>Trigger warning or block submission based on business rules</li>\r\n </ul>\r\n\r\n <h5 style=\"margin-bottom: 0.5rem; color: #fff;\">Example</h5>\r\n <pre style=\"color: #eee; padding: 0.5rem 1rem; border-radius: 4px; overflow-x: auto;\">\r\n {{ '{' }}\r\n \"script\": \"leaveDays > 3 && status == 'APPROVED'\",\r\n \"evaluationMode\": \"in-memory\",\r\n \"dependsOn\": [\"leaveDays\", \"status\"],\r\n \"filterMode\": \"HardBlock\"\r\n {{ '}' }}\r\n </pre>\r\n </div>\r\n\r\n\r\n</ng-template>", styles: [".field-setting-container{max-height:100%;overflow-x:hidden;overflow-y:auto}.field-setting-container .field-setting-content{padding:15px}.field-setting-container .panel-caption-header{display:flex;align-items:center;justify-content:space-between;padding:15px;height:60px;background-color:#f8fafc;border-bottom:1px solid #e2e8f0;color:#1f2937}.field-setting-container .panel-caption-header .panel-caption{flex-grow:1}.field-setting-container .panel-caption-header .close-wrapper{display:flex;align-items:center;justify-content:center;background-color:#f1f5f9;width:32px;height:32px;border-radius:50%;cursor:pointer;transition:background-color .2s}.field-setting-container .panel-caption-header .close-wrapper:hover{background-color:#e2e8f0}.field-setting-container .setting-divider{margin:1.5rem 0 .75rem;color:#555;border-top:1px dashed #ccc;padding-top:.5rem}.field-setting-container .group-title{display:flex;height:35px;align-items:center;gap:8px;background-color:#87ceeb;padding:6px 12px;font-weight:600;color:#1f2937;font-size:13px;margin:12px 0 4px;box-shadow:0 1px 2px #0000000d}.field-setting-container .group-title .icon-wrapper{display:flex;align-items:center;justify-content:center;width:18px;height:18px;color:#1f2937}.field-setting-container .group-title .icon-wrapper i{width:16px;height:16px;stroke-width:2}.field-setting-container .group-title.mandatory{background-color:#ffecb3}.field-setting-container .group-title.optional{background-color:#d0f0fd}.field-setting-container .group-title.validators{background-color:#e8f5e9}.field-setting-container .group-title .group-name{flex:1}.field-setting-container .group-title .group-name .feather-help-circle{display:inline-block;margin-left:8px}.field-setting-container .calculated-field-rule{font-family:system-ui,sans-serif;border:1px solid #ccc;padding:1rem;border-radius:8px}.field-setting-container .calculated-field-rule h2{margin-top:0;color:#2b3e50}.field-setting-container .calculated-field-rule pre{background:#eee;padding:.5rem 1rem;border-radius:4px;overflow-x:auto}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: MandatoryPropsComponent, selector: "mandatory-props" }, { kind: "component", type: OptionalPropsComponent, selector: "optional-props" }, { kind: "component", type: ValidatorEditorComponent, selector: "validator-editor" }, { kind: "component", type: PropsHostComponent, selector: "props-host", inputs: ["loadComponent", "props"] }, { kind: "component", type: CalculatedPropsComponent, selector: "calculated-props" }, { kind: "directive", type: HtmlTooltipDirective, selector: "[htmlTooltip]", inputs: ["htmlTooltip", "tooltipContext", "maxWidthUnset", "backgroundColor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1151
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.5", type: FieldSettingComponent, isStandalone: true, selector: "field-setting", inputs: { $isNested: { classPropertyName: "$isNested", publicName: "$isNested", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: "<div class=\"field-setting-container\">\r\n\r\n @if (!!$control()) {\r\n <div class=\"panel-caption-header\">\r\n <div class=\"panel-caption\">\r\n Editing: {{ $control().type !== 'calculated' ? $control()?.controlType + ' - ' : '' }}{{ $control()?.field ||\r\n 'Unnamed' }}\r\n </div>\r\n <div class=\"close-wrapper pointer\" (click)=\"closeFieldSettingPanel()\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n </div>\r\n\r\n\r\n <div class=\"field-setting-content\">\r\n\r\n\r\n @if ($control().type === 'calculated') {\r\n\r\n <div class=\"group-title mandatory\">\r\n <div class=\"icon-wrapper\">\r\n <i class=\"feather-lock\"></i>\r\n </div>\r\n <div class=\"group-name\">Mandatory</div>\r\n </div>\r\n <mandatory-props></mandatory-props>\r\n\r\n <div class=\"group-title calculated\">\r\n <div class=\"icon-wrapper\">\r\n <i class=\"feather-lock\"></i>\r\n </div>\r\n <div class=\"group-name\">Calculated Rule<i class=\"feather-help-circle\" [htmlTooltip]=\"aboutCalculatedField\"\r\n [maxWidthUnset]=\"true\"></i></div>\r\n </div>\r\n <calculated-props></calculated-props>\r\n\r\n\r\n } @else {\r\n\r\n <div class=\"group-title mandatory\">\r\n <div class=\"icon-wrapper\">\r\n <i class=\"feather-lock\"></i>\r\n </div>\r\n <div class=\"group-name\">Mandatory</div>\r\n </div>\r\n <mandatory-props></mandatory-props>\r\n\r\n <!-- <div class=\"setting-divider\"></div> -->\r\n\r\n @if ($control().controlType !== 'FORM_ARRAY') {\r\n <div class=\"group-title optional\">\r\n <div class=\"icon-wrapper\">\r\n <i class=\"feather-sliders\"></i>\r\n </div>\r\n <div class=\"group-name\">Optional</div>\r\n </div>\r\n <optional-props></optional-props>\r\n\r\n <!-- <div class=\"setting-divider\"></div> -->\r\n\r\n <div class=\"group-title validators\">\r\n <div class=\"icon-wrapper\">\r\n <i class=\"feather-check-square\"></i>\r\n </div>\r\n <div class=\"group-name\">Validators</div>\r\n </div>\r\n <validator-editor></validator-editor>\r\n }\r\n\r\n @if (!($control().controlType === 'TEXTBOX' && ['string', 'text', 'email'].includes(($control().type ||\r\n '').toLowerCase()))) {\r\n\r\n <div class=\"group-title\">\r\n <div class=\"icon-wrapper\">\r\n <i class=\"feather-check-square\"></i>\r\n </div>\r\n <div class=\"group-name\">{{ getFriendlyControlLabel($control()) }} Settings</div>\r\n </div>\r\n\r\n <props-host [loadComponent]=\"componentLoaderMap[coreFormDesignService.$currentPropsComponent()]\"\r\n [props]=\"{ control: $control(), controlChange: onControlParamsChange.bind(this) }\">\r\n </props-host>\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n\r\n\r\n</div>\r\n\r\n<ng-template #aboutCalculatedField>\r\n\r\n <div class=\"calculated-field-rule\" style=\"padding: 1rem; border-radius: 8px; background: #000; width: 800px;\">\r\n <h4 style=\"margin-top: 0; color: #fff;\">Calculated Field Rule</h4>\r\n <p><strong>Calculated fields</strong> are invisible boolean fields evaluated based on form inputs and logic. They\r\n help drive dynamic workflow behavior, such as conditional routing or validation triggers.</p>\r\n\r\n <h5 style=\"margin-bottom: 0.5rem; color: #fff;\">Key Properties</h5>\r\n <ul style=\"margin-top: 0;\">\r\n <li><strong>script:</strong> Expression to evaluate (e.g.,\r\n <code>leaveDays &gt; 3 &amp;&amp; status == 'Approved'</code>)</li>\r\n <li><strong>evaluationMode:</strong> <code>\"in-memory\"</code> or <code>\"sql-query\"</code></li>\r\n <li><strong>dependsOn[]:</strong> List of field names the script depends on</li>\r\n <li><strong>filterMode:</strong> <code>\"HardBlock\"</code> or <code>\"SoftWarn\"</code></li>\r\n </ul>\r\n\r\n <h5 style=\"margin-bottom: 0.5rem; color: #fff;\">Evaluation Modes</h5>\r\n <ul style=\"margin-top: 0;\">\r\n <li>\r\n <strong>in-memory:</strong> Uses <code>DynamicExpresso</code> to evaluate C#-like logic at runtime<br />\r\n <small>Example: <code>leaveType == \"ANNUAL\" &amp;&amp; leaveDays &lt; 5</code></small>\r\n </li>\r\n <li>\r\n <strong>sql-query:</strong> Runs backend SQL to evaluate conditions via\r\n <code>SELECT CASE WHEN ... THEN 1 ELSE 0 END</code><br />\r\n <small>Example:\r\n <code>SELECT CASE WHEN QUOTA &gt; 0 THEN 1 ELSE 0 END FROM LEAVE_QUOTA WHERE EMPLOYEE_ID = {{ '@' }}employeeId</code></small>\r\n </li>\r\n </ul>\r\n\r\n <h5 style=\"margin-bottom: 0.5rem; color: #fff;\">Use Cases</h5>\r\n <ul style=\"margin-top: 0;\">\r\n <li>Validate complex logic without showing the field</li>\r\n <li>Route to a different workflow branch based on hidden logic</li>\r\n <li>Trigger warning or block submission based on business rules</li>\r\n </ul>\r\n\r\n <h5 style=\"margin-bottom: 0.5rem; color: #fff;\">Example</h5>\r\n <pre style=\"color: #eee; padding: 0.5rem 1rem; border-radius: 4px; overflow-x: auto;\">\r\n {{ '{' }}\r\n \"script\": \"leaveDays > 3 && status == 'APPROVED'\",\r\n \"evaluationMode\": \"in-memory\",\r\n \"dependsOn\": [\"leaveDays\", \"status\"],\r\n \"filterMode\": \"HardBlock\"\r\n {{ '}' }}\r\n </pre>\r\n </div>\r\n\r\n\r\n</ng-template>", styles: [".field-setting-container{max-height:100%;overflow-x:hidden;overflow-y:auto}.field-setting-container .field-setting-content{padding:15px}.field-setting-container .panel-caption-header{display:flex;align-items:center;justify-content:space-between;padding:15px;height:60px;background-color:#f8fafc;border-bottom:1px solid #e2e8f0;color:#1f2937}.field-setting-container .panel-caption-header .panel-caption{flex-grow:1}.field-setting-container .panel-caption-header .close-wrapper{display:flex;align-items:center;justify-content:center;background-color:#f1f5f9;width:32px;height:32px;border-radius:50%;cursor:pointer;transition:background-color .2s}.field-setting-container .panel-caption-header .close-wrapper:hover{background-color:#e2e8f0}.field-setting-container .setting-divider{margin:1.5rem 0 .75rem;color:#555;border-top:1px dashed #ccc;padding-top:.5rem}.field-setting-container .group-title{display:flex;height:35px;align-items:center;gap:8px;background-color:#87ceeb;padding:6px 12px;font-weight:600;color:#1f2937;font-size:13px;margin:12px 0 4px;box-shadow:0 1px 2px #0000000d}.field-setting-container .group-title .icon-wrapper{display:flex;align-items:center;justify-content:center;width:18px;height:18px;color:#1f2937}.field-setting-container .group-title .icon-wrapper i{width:16px;height:16px;stroke-width:2}.field-setting-container .group-title.mandatory{background-color:#ffecb3}.field-setting-container .group-title.optional{background-color:#d0f0fd}.field-setting-container .group-title.validators{background-color:#e8f5e9}.field-setting-container .group-title .group-name{flex:1}.field-setting-container .group-title .group-name .feather-help-circle{display:inline-block;margin-left:8px}.field-setting-container .calculated-field-rule{font-family:system-ui,sans-serif;border:1px solid #ccc;padding:1rem;border-radius:8px}.field-setting-container .calculated-field-rule h2{margin-top:0;color:#2b3e50}.field-setting-container .calculated-field-rule pre{background:#eee;padding:.5rem 1rem;border-radius:4px;overflow-x:auto}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "component", type: MandatoryPropsComponent, selector: "mandatory-props" }, { kind: "component", type: OptionalPropsComponent, selector: "optional-props" }, { kind: "component", type: ValidatorEditorComponent, selector: "validator-editor" }, { kind: "component", type: PropsHostComponent, selector: "props-host", inputs: ["loadComponent", "props"] }, { kind: "component", type: CalculatedPropsComponent, selector: "calculated-props" }, { kind: "directive", type: HtmlTooltipDirective, selector: "[htmlTooltip]", inputs: ["htmlTooltip", "tooltipContext", "maxWidthUnset", "backgroundColor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1151
1152
  }
1152
1153
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: FieldSettingComponent, decorators: [{
1153
1154
  type: Component,
@@ -1192,7 +1193,7 @@ class CoreFormArrayControlPaletteComponent {
1192
1193
  field: 'stringBox',
1193
1194
  label: '',
1194
1195
  value: '',
1195
- readonly: true,
1196
+ //readonly: true,
1196
1197
  placeholder: 'String box',
1197
1198
  headless: true,
1198
1199
  },
@@ -1203,7 +1204,7 @@ class CoreFormArrayControlPaletteComponent {
1203
1204
  field: 'email',
1204
1205
  label: '',
1205
1206
  value: '',
1206
- readonly: true,
1207
+ //readonly: true,
1207
1208
  placeholder: 'Email',
1208
1209
  headless: true,
1209
1210
  },
@@ -1214,7 +1215,7 @@ class CoreFormArrayControlPaletteComponent {
1214
1215
  field: 'textarea',
1215
1216
  label: '',
1216
1217
  value: '',
1217
- readonly: true,
1218
+ //readonly: true,
1218
1219
  textareaRows: 2,
1219
1220
  placeholder: 'Text area',
1220
1221
  headless: true,
@@ -1226,7 +1227,7 @@ class CoreFormArrayControlPaletteComponent {
1226
1227
  field: 'number',
1227
1228
  label: '',
1228
1229
  value: 100,
1229
- readonly: true,
1230
+ //readonly: true,
1230
1231
  placeholder: 'Number',
1231
1232
  headless: true,
1232
1233
  },
@@ -1237,7 +1238,7 @@ class CoreFormArrayControlPaletteComponent {
1237
1238
  field: 'currency',
1238
1239
  label: '',
1239
1240
  value: '',
1240
- readonly: true,
1241
+ //readonly: true,
1241
1242
  placeholder: 'Currency',
1242
1243
  headless: true,
1243
1244
  },
@@ -1248,7 +1249,7 @@ class CoreFormArrayControlPaletteComponent {
1248
1249
  field: 'dropdown',
1249
1250
  label: '',
1250
1251
  value: '',
1251
- readonly: true,
1252
+ //readonly: true,
1252
1253
  dropdownOptions$: new BehaviorSubject([]),
1253
1254
  shownFrom: 'name',
1254
1255
  getByIdObject$: new BehaviorSubject({}),
@@ -1263,7 +1264,7 @@ class CoreFormArrayControlPaletteComponent {
1263
1264
  field: 'employeeSeeker',
1264
1265
  label: '',
1265
1266
  value: ['Nguyễn A'],
1266
- readonly: true,
1267
+ //readonly: true,
1267
1268
  boundFrom: 'id',
1268
1269
  shownFrom: 'fullname',
1269
1270
  getByIdObject$: new BehaviorSubject({}),
@@ -1277,7 +1278,7 @@ class CoreFormArrayControlPaletteComponent {
1277
1278
  field: 'checklist',
1278
1279
  label: '',
1279
1280
  value: [],
1280
- readonly: true,
1281
+ //readonly: true,
1281
1282
  checklistOptions$: new BehaviorSubject([]),
1282
1283
  shownFrom: 'name',
1283
1284
  getByIdObject$: new BehaviorSubject({}),
@@ -1293,7 +1294,7 @@ class CoreFormArrayControlPaletteComponent {
1293
1294
  field: 'employeeSeekerMultiple',
1294
1295
  label: '',
1295
1296
  value: [],
1296
- readonly: true,
1297
+ //readonly: true,
1297
1298
  objectList$: new BehaviorSubject([]),
1298
1299
  boundFrom: 'id',
1299
1300
  shownFrom: 'fullname',
@@ -1309,7 +1310,7 @@ class CoreFormArrayControlPaletteComponent {
1309
1310
  field: 'datePicker',
1310
1311
  label: '',
1311
1312
  value: '',
1312
- readonly: true,
1313
+ //readonly: true,
1313
1314
  placeholder: 'Date picker',
1314
1315
  showPlaceholder: true,
1315
1316
  headless: true,
@@ -1321,7 +1322,7 @@ class CoreFormArrayControlPaletteComponent {
1321
1322
  field: 'timeBox',
1322
1323
  label: '',
1323
1324
  value: null,
1324
- readonly: true,
1325
+ //readonly: true,
1325
1326
  placeholder: 'Time box',
1326
1327
  headless: true,
1327
1328
  },
@@ -1332,7 +1333,7 @@ class CoreFormArrayControlPaletteComponent {
1332
1333
  field: 'monthSelector',
1333
1334
  label: '',
1334
1335
  value: '',
1335
- readonly: true,
1336
+ //readonly: true,
1336
1337
  placeholder: 'Month selector',
1337
1338
  headless: true,
1338
1339
  },
@@ -1343,7 +1344,7 @@ class CoreFormArrayControlPaletteComponent {
1343
1344
  field: 'attachment',
1344
1345
  label: '',
1345
1346
  value: '',
1346
- readonly: true,
1347
+ //readonly: true,
1347
1348
  assignTo: 'unknown',
1348
1349
  placeholder: 'Attachment',
1349
1350
  headless: true,
@@ -1355,7 +1356,7 @@ class CoreFormArrayControlPaletteComponent {
1355
1356
  field: 'checkbox',
1356
1357
  label: '',
1357
1358
  value: '',
1358
- readonly: true,
1359
+ //readonly: true,
1359
1360
  placeholder: 'Checkbox',
1360
1361
  headless: true,
1361
1362
  }
@@ -1380,90 +1381,24 @@ class CoreFormArrayControlPaletteComponent {
1380
1381
  this.checkError$ = new BehaviorSubject(false);
1381
1382
  }
1382
1383
  onDragStart(event, control) {
1383
- event.dataTransfer?.setData('application/json', JSON.stringify(control));
1384
+ this.coreFormDesignService.beginDragTemplate(control);
1384
1385
  }
1385
1386
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CoreFormArrayControlPaletteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1386
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.5", type: CoreFormArrayControlPaletteComponent, isStandalone: true, selector: "core-form-array-control-palette", ngImport: i0, template: "<ul>\r\n <!-- <div class=\"palette-debug\">\r\n <div>controlOptions length: {{ controlOptions.length }}</div>\r\n <pre>{{ controlOptions | json }}</pre>\r\n </div> -->\r\n @for (control of controlOptions; track $index) {\r\n <li class=\"palette-item\" draggable=\"true\" (dragstart)=\"onDragStart($event, control)\">\r\n <core-control-no-form-array [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\" />\r\n </li>\r\n }\r\n</ul>", styles: [".palette-debug{font-size:12px;background:#f9f9f9;border:1px solid #ddd;padding:8px;border-radius:4px;color:#333;margin-bottom:8px;white-space:pre-wrap}ul{padding:0}ul li{margin:8px}\n"], dependencies: [{ kind: "component", type: CoreControlNoFormArrayComponent, selector: "core-control-no-form-array", inputs: ["control", "form", "checkError$", "rangeLimit"] }] }); }
1387
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.5", type: CoreFormArrayControlPaletteComponent, isStandalone: true, selector: "core-form-array-control-palette", ngImport: i0, template: "<ul>\r\n <!-- <div class=\"palette-debug\">\r\n <div>controlOptions length: {{ controlOptions.length }}</div>\r\n <pre>{{ controlOptions | json }}</pre>\r\n </div> -->\r\n @for (control of controlOptions; track $index) {\r\n <li class=\"palette-item\" draggable=\"true\" (dragstart)=\"onDragStart($event, control)\">\r\n <core-control-no-form-array [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\" />\r\n </li>\r\n }\r\n</ul>", styles: [".palette-debug{font-size:12px;background:#f9f9f9;border:1px solid #ddd;padding:8px;border-radius:4px;color:#333;margin-bottom:8px;white-space:pre-wrap}ul{padding:0}ul li{margin-top:8px;margin-bottom:8px;margin-right:15px}\n"], dependencies: [{ kind: "component", type: CoreControlNoFormArrayComponent, selector: "core-control-no-form-array", inputs: ["control", "form", "checkError$", "rangeLimit"] }] }); }
1387
1388
  }
1388
1389
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CoreFormArrayControlPaletteComponent, decorators: [{
1389
1390
  type: Component,
1390
1391
  args: [{ selector: 'core-form-array-control-palette', imports: [
1391
1392
  JsonPipe,
1392
1393
  CoreControlNoFormArrayComponent
1393
- ], template: "<ul>\r\n <!-- <div class=\"palette-debug\">\r\n <div>controlOptions length: {{ controlOptions.length }}</div>\r\n <pre>{{ controlOptions | json }}</pre>\r\n </div> -->\r\n @for (control of controlOptions; track $index) {\r\n <li class=\"palette-item\" draggable=\"true\" (dragstart)=\"onDragStart($event, control)\">\r\n <core-control-no-form-array [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\" />\r\n </li>\r\n }\r\n</ul>", styles: [".palette-debug{font-size:12px;background:#f9f9f9;border:1px solid #ddd;padding:8px;border-radius:4px;color:#333;margin-bottom:8px;white-space:pre-wrap}ul{padding:0}ul li{margin:8px}\n"] }]
1394
- }] });
1395
-
1396
- const PLACEHOLDER_CONTROL = {
1397
- controlType: EnumFormBaseContolType.PLACEHOLDER,
1398
- field: '',
1399
- label: '',
1400
- flexSize: 12,
1401
- value: ''
1402
- };
1403
- class CoreFormArrayLayoutEditorComponent {
1404
- constructor() {
1405
- this.checkError$ = new BehaviorSubject(false);
1406
- this.coreFormDesignService = inject(CoreFormDesignService);
1407
- this.$sections = this.coreFormDesignService.$nestedDesignSections;
1408
- this.form = this.coreFormDesignService.formDesign;
1409
- this.showDebug = false;
1410
- this.dropIndex = 0;
1411
- }
1412
- onClose() {
1413
- this.coreFormDesignService.$showFormArrayDesign.set(false);
1414
- }
1415
- onMiniDrop(event, sectionIndex, rowIndex, colIndex) {
1416
- const rawData = event?.dataTransfer?.getData('application/json');
1417
- if (!rawData)
1418
- return;
1419
- const control = JSON.parse(rawData);
1420
- const newControl = structuredClone(control);
1421
- newControl.field = `control_${++this.dropIndex}`;
1422
- const current = this.$sections();
1423
- if (!current)
1424
- return;
1425
- current[sectionIndex].rows[rowIndex][colIndex] = newControl;
1426
- this.$sections.set([...current]);
1427
- }
1428
- addSection() {
1429
- const current = this.$sections() || [];
1430
- current.push({ caption: '', rows: [[PLACEHOLDER_CONTROL]] });
1431
- this.$sections.set([...current]);
1432
- }
1433
- addRow(sectionIndex) {
1434
- const current = this.$sections();
1435
- if (!current?.[sectionIndex])
1436
- return;
1437
- current[sectionIndex].rows.push([PLACEHOLDER_CONTROL]);
1438
- this.$sections.set([...current]);
1439
- }
1440
- removeControl(sectionIndex, rowIndex, colIndex) {
1441
- const current = this.$sections();
1442
- // Guard: Make sure the section and row exist
1443
- if (!current?.[sectionIndex]?.rows[rowIndex])
1444
- return;
1445
- // Replace the control at given slot with a type-safe placeholder
1446
- current[sectionIndex].rows[rowIndex][colIndex] = PLACEHOLDER_CONTROL;
1447
- // Update the signal to trigger re-render
1448
- this.$sections.set([...current]);
1449
- }
1450
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CoreFormArrayLayoutEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1451
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.5", type: CoreFormArrayLayoutEditorComponent, isStandalone: true, selector: "core-form-array-layout-editor", ngImport: i0, template: "<div class=\"core-form-array-layout-editor-container\">\r\n <div class=\"modal-container\">\r\n <div class=\"modal-content-root\">\r\n\r\n <div class=\"layout-header\">\r\n {{ 'Design Form Array Layout' | uppercase }}\r\n <button class=\"close-button\" (click)=\"onClose()\">\u00D7</button>\r\n </div>\r\n\r\n <div class=\"layout-main-content\">\r\n <!-- Left: Palette -->\r\n <div class=\"layout-left\">\r\n <core-form-array-control-palette />\r\n </div>\r\n\r\n <!-- Right: Grid Layout -->\r\n <div class=\"layout-right\">\r\n <div class=\"layout-toolbar\">\r\n <button class=\"btn btn-sm btn-primary\" (click)=\"addSection()\">+ Section</button>\r\n <button class=\"btn btn-sm btn-secondary\" (click)=\"addRow(0)\">+ Row to First Section</button>\r\n <button class=\"btn btn-sm btn-outline-dark\" (click)=\"showDebug = !showDebug\">\r\n {{ showDebug ? 'Hide' : 'Show' }} Debug\r\n </button>\r\n </div>\r\n\r\n @if (showDebug) {\r\n <pre>{{ $sections() | json }}</pre>\r\n }\r\n\r\n <div class=\"layout-body\">\r\n @for (section of $sections(); track $index; let sectionIndex = $index) {\r\n <div class=\"section-card\">\r\n <div class=\"section-caption\">\r\n {{ section.caption || 'Untitled Section' }}\r\n </div>\r\n\r\n @for (row of section.rows; track $index; let rowIndex = $index) {\r\n <div class=\"row\">\r\n @for (control of row; track $index; let colIndex = $index) {\r\n <div class=\"form-cell mini-drop-target\" miniDropTarget\r\n (miniDropped)=\"onMiniDrop($event, sectionIndex, rowIndex, colIndex)\">\r\n @if (control) {\r\n <div class=\"form-cell-inner\">\r\n <core-control-no-form-array [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\" />\r\n <button class=\"btn btn-sm btn-link text-danger remove-btn\"\r\n (click)=\"removeControl(sectionIndex, rowIndex, colIndex)\">\r\n \u00D7\r\n </button>\r\n </div>\r\n } @else {\r\n <div class=\"placeholder-slot\">Drop Here</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".layout-header{position:relative;padding:15px;font-size:20px;border-bottom:1px solid #e0e0e0;display:flex;align-items:center;transform:translate(-15px,-15px);width:calc(100% + 30px)}.close-button{position:absolute;top:12px;right:12px;background:none;border:none;font-size:22px;cursor:pointer;color:#666;line-height:1;padding:0;z-index:1}.close-button:hover{color:#000}.layout-main-content{display:flex;gap:24px}.layout-left{width:200px;flex:0 0 240px;border-right:1px solid #eee;padding-right:16px;overflow:auto}.layout-right{flex:1;padding-left:16px;overflow-x:auto}.layout-toolbar{display:flex;gap:12px;margin-bottom:12px}.layout-body{display:flex;flex-direction:column;gap:24px}.section-card{background-color:#fdfdfd;border:1px solid #ddd;border-radius:8px;padding:12px}.section-caption{font-weight:600;margin-bottom:12px}.row{display:flex;gap:12px;margin-bottom:12px}.form-cell{flex:1;min-width:120px;padding:6px;border:1px dashed #ccc;border-radius:4px;background-color:#fff;position:relative}.form-cell-inner{position:relative}.remove-btn{position:absolute;top:0;right:0;font-size:14px;padding:0 4px;border:none}.placeholder-slot{text-align:center;color:#aaa;padding:16px;background:#fafafa;border:1px dashed #bbb;border-radius:4px}\n"], dependencies: [{ kind: "pipe", type: JsonPipe, name: "json" }, { kind: "pipe", type: UpperCasePipe, name: "uppercase" }, { kind: "component", type: CoreControlNoFormArrayComponent, selector: "core-control-no-form-array", inputs: ["control", "form", "checkError$", "rangeLimit"] }, { kind: "component", type: CoreFormArrayControlPaletteComponent, selector: "core-form-array-control-palette" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1452
- }
1453
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CoreFormArrayLayoutEditorComponent, decorators: [{
1454
- type: Component,
1455
- args: [{ selector: 'core-form-array-layout-editor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1456
- JsonPipe,
1457
- UpperCasePipe,
1458
- CoreControlNoFormArrayComponent,
1459
- CoreFormArrayControlPaletteComponent
1460
- ], template: "<div class=\"core-form-array-layout-editor-container\">\r\n <div class=\"modal-container\">\r\n <div class=\"modal-content-root\">\r\n\r\n <div class=\"layout-header\">\r\n {{ 'Design Form Array Layout' | uppercase }}\r\n <button class=\"close-button\" (click)=\"onClose()\">\u00D7</button>\r\n </div>\r\n\r\n <div class=\"layout-main-content\">\r\n <!-- Left: Palette -->\r\n <div class=\"layout-left\">\r\n <core-form-array-control-palette />\r\n </div>\r\n\r\n <!-- Right: Grid Layout -->\r\n <div class=\"layout-right\">\r\n <div class=\"layout-toolbar\">\r\n <button class=\"btn btn-sm btn-primary\" (click)=\"addSection()\">+ Section</button>\r\n <button class=\"btn btn-sm btn-secondary\" (click)=\"addRow(0)\">+ Row to First Section</button>\r\n <button class=\"btn btn-sm btn-outline-dark\" (click)=\"showDebug = !showDebug\">\r\n {{ showDebug ? 'Hide' : 'Show' }} Debug\r\n </button>\r\n </div>\r\n\r\n @if (showDebug) {\r\n <pre>{{ $sections() | json }}</pre>\r\n }\r\n\r\n <div class=\"layout-body\">\r\n @for (section of $sections(); track $index; let sectionIndex = $index) {\r\n <div class=\"section-card\">\r\n <div class=\"section-caption\">\r\n {{ section.caption || 'Untitled Section' }}\r\n </div>\r\n\r\n @for (row of section.rows; track $index; let rowIndex = $index) {\r\n <div class=\"row\">\r\n @for (control of row; track $index; let colIndex = $index) {\r\n <div class=\"form-cell mini-drop-target\" miniDropTarget\r\n (miniDropped)=\"onMiniDrop($event, sectionIndex, rowIndex, colIndex)\">\r\n @if (control) {\r\n <div class=\"form-cell-inner\">\r\n <core-control-no-form-array [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\" />\r\n <button class=\"btn btn-sm btn-link text-danger remove-btn\"\r\n (click)=\"removeControl(sectionIndex, rowIndex, colIndex)\">\r\n \u00D7\r\n </button>\r\n </div>\r\n } @else {\r\n <div class=\"placeholder-slot\">Drop Here</div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".layout-header{position:relative;padding:15px;font-size:20px;border-bottom:1px solid #e0e0e0;display:flex;align-items:center;transform:translate(-15px,-15px);width:calc(100% + 30px)}.close-button{position:absolute;top:12px;right:12px;background:none;border:none;font-size:22px;cursor:pointer;color:#666;line-height:1;padding:0;z-index:1}.close-button:hover{color:#000}.layout-main-content{display:flex;gap:24px}.layout-left{width:200px;flex:0 0 240px;border-right:1px solid #eee;padding-right:16px;overflow:auto}.layout-right{flex:1;padding-left:16px;overflow-x:auto}.layout-toolbar{display:flex;gap:12px;margin-bottom:12px}.layout-body{display:flex;flex-direction:column;gap:24px}.section-card{background-color:#fdfdfd;border:1px solid #ddd;border-radius:8px;padding:12px}.section-caption{font-weight:600;margin-bottom:12px}.row{display:flex;gap:12px;margin-bottom:12px}.form-cell{flex:1;min-width:120px;padding:6px;border:1px dashed #ccc;border-radius:4px;background-color:#fff;position:relative}.form-cell-inner{position:relative}.remove-btn{position:absolute;top:0;right:0;font-size:14px;padding:0 4px;border:none}.placeholder-slot{text-align:center;color:#aaa;padding:16px;background:#fafafa;border:1px dashed #bbb;border-radius:4px}\n"] }]
1394
+ ], template: "<ul>\r\n <!-- <div class=\"palette-debug\">\r\n <div>controlOptions length: {{ controlOptions.length }}</div>\r\n <pre>{{ controlOptions | json }}</pre>\r\n </div> -->\r\n @for (control of controlOptions; track $index) {\r\n <li class=\"palette-item\" draggable=\"true\" (dragstart)=\"onDragStart($event, control)\">\r\n <core-control-no-form-array [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\" />\r\n </li>\r\n }\r\n</ul>", styles: [".palette-debug{font-size:12px;background:#f9f9f9;border:1px solid #ddd;padding:8px;border-radius:4px;color:#333;margin-bottom:8px;white-space:pre-wrap}ul{padding:0}ul li{margin-top:8px;margin-bottom:8px;margin-right:15px}\n"] }]
1461
1395
  }] });
1462
1396
 
1463
- class CoreFormDesignComponent extends BaseComponent {
1397
+ class CoreFormGroupEditorComponent extends BaseComponent {
1464
1398
  constructor(mls) {
1465
1399
  super(mls);
1466
1400
  this.mls = mls;
1401
+ this.$isNested = input(false);
1467
1402
  this.$idAsInput = input();
1468
1403
  this.$id = input();
1469
1404
  this.$settingPanel = viewChild('settingPanel');
@@ -1851,6 +1786,7 @@ class CoreFormDesignComponent extends BaseComponent {
1851
1786
  this.generateLabelNameFor = this.coreFormDesignService.generateLabelNameFor.bind(this.coreFormDesignService);
1852
1787
  this.getAllControlsFromSections = this.coreFormDesignService.getAllControlsFromSections.bind(this.coreFormDesignService);
1853
1788
  this.getControl = this.coreFormDesignService.getControl.bind(this.coreFormDesignService);
1789
+ this.filteredCells = this.coreFormDesignService.filteredCells;
1854
1790
  this.coreFormDesignService.resetFormDesignState();
1855
1791
  effect(() => {
1856
1792
  const _ = this.coreFormDesignService.$placeholderSections();
@@ -2192,60 +2128,6 @@ class CoreFormDesignComponent extends BaseComponent {
2192
2128
  this.coreFormDesignService.$selectedCell.set({ ...cell });
2193
2129
  this.coreFormDesignService.$fieldSettingPanelOpen.set(true);
2194
2130
  }
2195
- /*
2196
- deleteField(row: IFormDesignRow | undefined, colIndex: number): void {
2197
- if (!row || !row.cells[colIndex]) return;
2198
- const cellToDelete = row.cells[colIndex];
2199
- if (!cellToDelete.control) return;
2200
-
2201
- if (confirm('Are you sure to remove the field?')) {
2202
-
2203
- // 🧠 Check if it's selected
2204
- const selectedCell = this.coreFormDesignService.$selectedCell();
2205
- const shouldClearSelection = selectedCell === cellToDelete;
2206
- let deletedControl: IFormBaseControl | null = null;
2207
-
2208
- // ✅ Update the reactive state
2209
- this.coreFormDesignService.$placeholderSections.update(sections => {
2210
- for (const section of sections) {
2211
- for (const r of section.rows) {
2212
- if (r === row) {
2213
- const control = r.cells[colIndex].control;
2214
- if (control && control.field && control.flexSize !== undefined) {
2215
- deletedControl = control as IFormBaseControl; // ✅ Save before removing
2216
- }
2217
- r.cells[colIndex].control = { flexSize: r.cells[colIndex].control?.flexSize }; // ❌ Clear after
2218
- break;
2219
- }
2220
- }
2221
- }
2222
- return sections;
2223
- });
2224
-
2225
- if (deletedControl) {
2226
- this.coreFormDesignService.$placeholderSections.update(sections => {
2227
- for (const section of sections) {
2228
- for (const row of section.rows) {
2229
- if (!!row) {
2230
- row.cells = row.cells.filter(cell => cell.control?.field !== deletedControl?.assignTo);
2231
- }
2232
- }
2233
- }
2234
- return sections;
2235
- });
2236
- }
2237
-
2238
- // ❌ Clear selection if needed
2239
- if (shouldClearSelection) {
2240
- this.coreFormDesignService.$selectedCell.set(null);
2241
- }
2242
-
2243
- console.log("this.coreFormDesignService.$placeholderSections before triggerUpdateSections", this.coreFormDesignService.$placeholderSections())
2244
- this.triggerUpdateSections();
2245
- }
2246
- }
2247
- */
2248
- // Anti AI version
2249
2131
  deleteField(row, sectionIndex, rowIndex, colIndex) {
2250
2132
  if (!row)
2251
2133
  return;
@@ -2378,10 +2260,969 @@ class CoreFormDesignComponent extends BaseComponent {
2378
2260
  return false;
2379
2261
  return control.validators.some((v) => v.name === 'required' || v.name === 'requiredTrue');
2380
2262
  }
2381
- filteredCells(row) {
2382
- if (!row)
2383
- return [];
2384
- return row.cells.filter(cell => (cell?.flexSize ?? 0) > 0);
2263
+ onFormDesignCreated(e) {
2264
+ console.log("onFormDesignCreated", e);
2265
+ }
2266
+ onLiveFormCreated(e) {
2267
+ console.log("onLiveFormCreated", e);
2268
+ }
2269
+ showMetadata() {
2270
+ this.coreFormDesignService.$showFormMetadata.set(true);
2271
+ }
2272
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CoreFormGroupEditorComponent, deps: [{ token: MultiLanguageService }], target: i0.ɵɵFactoryTarget.Component }); }
2273
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.5", type: CoreFormGroupEditorComponent, isStandalone: true, selector: "core-form-group-editor", inputs: { $isNested: { classPropertyName: "$isNested", publicName: "$isNested", isSignal: true, isRequired: false, transformFunction: null }, $idAsInput: { classPropertyName: "$idAsInput", publicName: "$idAsInput", isSignal: true, isRequired: false, transformFunction: null }, $id: { classPropertyName: "$id", publicName: "$id", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "$settingPanel", first: true, predicate: ["settingPanel"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"core-form-group-editor-container\">\r\n\r\n <div class=\"form-design-right\">\r\n\r\n @if (coreFormDesignService.$mode() === enumType.Default) {\r\n <div class=\"form-wrapper\">\r\n\r\n @if (!$isNested() && !!coreFormDesignService.$isInWorkflowDesign()) {\r\n <form-metadata></form-metadata>\r\n }\r\n\r\n <form [formGroup]=\"formDesign\" autocomplete=\"off\">\r\n <div class=\"form-cells\"> \r\n\r\n <div class=\"form-tool-bar\">\r\n @if (!$isNested() && !$hasCalculatedSection()) {\r\n <button class=\"core-button-vns-container\" (click)=\"addCalculatedSection()\">+ Calculated fields</button>\r\n }\r\n <button class=\"core-button-vns-container\" (click)=\"addSection()\">+ Add Section</button>\r\n </div>\r\n \r\n @for (section of coreFormDesignService.$placeholderSections(); track $index; let sectionIndex = $index) {\r\n <div class=\"form-section-placeholder\">\r\n\r\n <div class=\"section-header\">\r\n\r\n <div class=\"section-img-wrapper\">\r\n <div class=\"section-img\" [class.calculated]=\"section.forCalculatedFields\"></div>\r\n </div>\r\n\r\n <label [attr.contenteditable]=\"!section.forCalculatedFields\"\r\n [htmlTooltip]=\"!!section.forCalculatedFields ? calculatedFieldsTooltip : null\"\r\n (blur)=\"onCaptionEditEnd(sectionIndex, $event)\"\r\n (keydown.enter)=\"onCaptionEditEnd(sectionIndex, $event); $event.preventDefault()\"\r\n >{{ section.caption }}</label>\r\n\r\n <div class=\"section-tool pointer\" (click)=\"deleteSection(sectionIndex)\" [appTooltip]=\"'Delete section'\" [showAnyway]=\"true\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n \r\n </div>\r\n \r\n @for (row of section.rows; track $index; let rowIndex = $index) {\r\n\r\n <div class=\"form-row-wrapper\">\r\n <div class=\"form-row\">\r\n @for (cell of filteredCells(row); track $index; let colIndex = $index) {\r\n <div class=\"form-cell drop-target\" \r\n [ngStyle]=\"{ flex: (cell.flexSize ?? 0) + ' 1 0%' }\"\r\n [attr.data-flex]=\"cell.flexSize ?? 0\"\r\n (drop)=\"onDropIntoCell($event, sectionIndex, rowIndex, colIndex)\"\r\n (dragover)=\"onDragOver($event, section, cell.control!)\"\r\n (dragenter)=\"onDragEnter(sectionIndex + '_' + rowIndex + '_' + colIndex)\"\r\n (dragleave)=\"onDragLeave(sectionIndex + '_' + rowIndex + '_' + colIndex)\"\r\n [class.selected]=\"cell?.selected\"\r\n [class.dragging-over]=\"isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex]\"\r\n [class.has-control]=\"!!cell && !!cell.control && !!getControl(cell)\"\r\n (click)=\"onCellClicked(sectionIndex, rowIndex, colIndex)\"\r\n >\r\n\r\n\r\n @if (!isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex]) {\r\n\r\n @if (!!cell && !!cell.control && !!getControl(cell)) {\r\n <label contenteditable=\"true\"\r\n (blur)=\"onFieldCaptionEditEnd(cell, $event)\"\r\n (keydown.enter)=\"onFieldCaptionEditEnd(cell, $event); $event.preventDefault()\"\r\n [class.d-none]=\"!!getControl(cell)?.hidden\"\r\n [class.required]=\"!!cell && !!cell.control && !!getControl(cell) && isRequired(getControl(cell))\"\r\n >{{ cell.control.label || 'label' }}</label>\r\n\r\n @if (cell.control.controlType==='CALCULATED') {\r\n <div class=\"control-wrapper\" (click)=\"openSettingsForCell(cell, sectionIndex, rowIndex, colIndex)\">\r\n <core-control \r\n [control]=\"getControl(cell)!\" \r\n [form]=\"formDesign\"\r\n [checkError$]=\"checkError$\" />\r\n </div>\r\n } @else {\r\n <core-control \r\n [control]=\"getControl(cell)!\" \r\n [form]=\"formDesign\"\r\n [checkError$]=\"checkError$\" />\r\n }\r\n \r\n <div class=\"field-toolbar\">\r\n <ul>\r\n <li>\r\n <div class=\"field-tool pointer\" (click)=\"openSettingsForCell(cell, sectionIndex, rowIndex, colIndex)\" [appTooltip]=\"'Show settings'\">\r\n <i class=\"feather-settings\"></i>\r\n </div>\r\n </li>\r\n <li>\r\n <div class=\"field-tool pointer\" (click)=\"deleteField(row, sectionIndex, rowIndex, colIndex)\" [appTooltip]=\"'Remove field from cell'\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n \r\n } @else {\r\n <div class=\"calculated-placeholder\" [class.calculated]=\"!!section.forCalculatedFields\">\r\n {{ !!section.forCalculatedFields ? 'Drop calculated field here' : 'Drop here'}}\r\n </div>\r\n }\r\n\r\n @if (cell?.selected && canMergeCells(sectionIndex, rowIndex)) {\r\n <div class=\"merge-toolbar\">\r\n <button (click)=\"mergeCells(sectionIndex, rowIndex)\">\uD83D\uDD17 Merge</button>\r\n </div>\r\n }\r\n \r\n }\r\n\r\n </div>\r\n }\r\n </div>\r\n <div class=\"row-tool-bar\">\r\n <div class=\"icon-wrapper\" (click)=\"deleteRow(sectionIndex, rowIndex)\" [appTooltip]=\"'Delete row'\" [showAnyway]=\"true\"><i class=\"feather-x\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"addRow(sectionIndex)\" [appTooltip]=\"'Add row'\" [showAnyway]=\"true\"><i class=\"feather-arrow-down\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"insertRow(sectionIndex, rowIndex)\" [appTooltip]=\"'Insert row'\" [showAnyway]=\"true\"><i class=\"feather-corner-right-down\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"addColumn(row)\" [appTooltip]=\"'Add column'\" [showAnyway]=\"true\"><i class=\"feather-arrow-right\"></i></div>\r\n </div>\r\n </div>\r\n\r\n }\r\n </div>\r\n }\r\n \r\n \r\n </div>\r\n </form>\r\n </div>\r\n } @else if (!!$sections()) {\r\n\r\n @if(!!(injectedFields$ | async) && !!(injectedFields$ | async)!.length) {\r\n\r\n @if (!!coreFormDesignService.$afInstance().normalMode) {\r\n <live-form [$designMode]=\"true\" [$forKickOff]=\"true\" />\r\n } @else {\r\n <live-form [$designMode]=\"true\" [$forKickOff]=\"true\" ($onClose)=\"closePreview()\" />\r\n }\r\n\r\n } @else {\r\n <h2>COULD NOT UPDATE injectedFields$</h2>\r\n }\r\n\r\n } @else {\r\n <h2>$sections() empty / null / undefined</h2>\r\n }\r\n </div>\r\n</div>\r\n\r\n<ng-template #calculatedFieldsTooltip>\r\n <div style=\"max-width: 280px;\">\r\n <strong>Calculated Fields</strong><br />\r\n <p></p>\r\n These fields are hidden from the form and cannot be edited directly.<br /><br />\r\n - They are computed automatically during workflow execution.<br />\r\n - Each field depends on one or more standard input fields.<br />\r\n - The calculation is evaluated using either an SQL query engine (like <strong>Dapper</strong>) or an in-memory expression engine (like <strong>Dynamic Expresso</strong>).<br /><br />\r\n These results can be used to influence workflow logic, rule trees, or approval paths.\r\n </div>\r\n</ng-template>\r\n\r\n\r\n ", styles: ["@charset \"UTF-8\";.core-form-group-editor-container{position:relative;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));width:100%;overflow:hidden;background-color:#eff0f1;font-size:13px}.core-form-group-editor-container .core-button-vns-container{margin-right:8px!important}.core-form-group-editor-container .core-button-vns-container:last-child{background-color:#000;color:#fff;margin-right:0}.core-form-group-editor-container .af-metadata-overlay{position:fixed;top:60px;left:66px;background:#fff;box-shadow:.4rem 0 2rem #0000002e;z-index:1000;width:1214px;height:calc(100vh - 75px);overflow-y:auto;pointer-events:none}.core-form-group-editor-container .af-metadata-overlay.shown{pointer-events:auto}.core-form-group-editor-container *{border-radius:0}.core-form-group-editor-container ul,.core-form-group-editor-container li{padding:0}.core-form-group-editor-container li{max-width:200px}.core-form-group-editor-container ul div.space{display:block;height:15px}.core-form-group-editor-container li.full-width{max-width:100%}.core-form-group-editor-container .field-setting-panel{display:block;position:fixed;width:360px;height:100vh;top:0;right:-360px;background-color:#fff;box-shadow:.4rem 0 2rem #0000002e;transition:right .5s ease-out}.core-form-group-editor-container .field-setting-panel .close-wrapper{width:32px;height:32px;position:absolute;top:15px;right:15px;display:flex;background-color:#848484;border-radius:50%}.core-form-group-editor-container .field-setting-panel .close-wrapper i{width:16px;height:16px;font-size:18px;color:#848484}.core-form-group-editor-container .field-setting-panel .panel-caption{margin-bottom:1rem;padding-bottom:.5rem;border-bottom:1px solid #ddd;width:100%;overflow:hidden;text-wrap:nowrap;text-overflow:ellipsis}.core-form-group-editor-container .field-setting-panel.calculated-type{width:500px;right:-500px}.core-form-group-editor-container .field-setting-panel.calculated-type textarea{border-radius:8px;height:150px}.core-form-group-editor-container .field-setting-panel.open{right:0}.core-form-group-editor-container .form-design-left{position:absolute;top:var(--size-core-page-header-height);bottom:0;left:0;z-index:1;width:360px;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));padding:15px;padding-right:calc(15px + var(--size-scrollbar-width));background-color:#87ceeb;overflow-y:hidden}.core-form-group-editor-container .form-design-left .category-name{color:#fff}.core-form-group-editor-container .form-design-left .grid-buffer-wrapper{background-color:#fff;padding:15px}.core-form-group-editor-container .form-design-left ul:last-child{padding-bottom:400px}.core-form-group-editor-container .form-design-left .category-name{margin-bottom:15px}.core-form-group-editor-container .form-design-left .json-preview{background-color:#fff;color:#333;padding:1rem 1.5rem;box-shadow:0 2px 6px #00000014;font-family:Fira Code,monospace;font-size:.85rem;word-break:keep-all;overflow-x:auto;line-height:1.5;width:330px;height:calc(100vh - 205px)}.core-form-group-editor-container .form-design-left button{height:35px;border-radius:0;margin-bottom:15px;color:#fff;border:none;font-size:13px;background-color:transparent}.core-form-group-editor-container .form-design-left:hover{overflow-y:auto;padding-right:15px}.core-form-group-editor-container .form-design-right{width:100%;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));overflow-y:auto}.core-form-group-editor-container .form-design-right .form-wrapper{width:100%;overflow-y:visible;background-color:#fff}.core-form-group-editor-container .form-design-right .form-wrapper button{margin-left:12px;padding:4px 10px;border:1px solid #ccc;cursor:pointer;transition:all .2s;width:110px}.core-form-group-editor-container .form-design-right .form-wrapper button:hover{background-color:#e4f0ff;border-color:#007bff;color:#007bff}.core-form-group-editor-container .form-design-right .form-wrapper .form-tool-bar{display:flex;align-items:center;justify-content:flex-end}.core-form-group-editor-container .form-design-right .form-wrapper .form-tool-bar>button{width:150px;margin:0}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells{display:flex;flex-direction:column;gap:32px;padding:20px 15px 15px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder{padding:12px 15px;border:1px dashed #ccc;background-color:#fff;box-shadow:0 2px 6px #0000000a}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header{display:flex;position:relative;align-items:center;justify-content:flex-start;font-weight:600;margin-bottom:12px;color:#333}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-img{width:34px;height:34px;border-radius:50%;background-color:#d3d3d3;float:left;background-image:url(/assets/images/info.svg);background-repeat:no-repeat;background-position:center;margin-right:8px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-img.calculated{background-image:url(/assets/images/sql-icon.svg);background-color:transparent;border-radius:0}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-tool{position:absolute;right:5px;top:6px;display:none;z-index:2;color:gray}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-tool i{font-size:24px;color:#848484}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header:hover .section-tool{display:block}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .row-tool-bar{display:flex;align-items:center;justify-content:flex-end;margin-bottom:8px;height:24px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-row{display:flex;gap:15px;margin-bottom:15px;min-height:50px;background-color:#d3d3d3;padding:8px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell{flex:1;min-height:90px;background-color:#fcfcfc;border:1px dashed #ccc;position:relative;padding:20px 10px 10px;transition:border .2s ease-in-out}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell:before{content:attr(data-flex);position:absolute;top:2px;left:4px;font-size:10px;color:#999}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell label.required:after{content:\" *\";color:#ff040b}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar{position:absolute;right:7px;top:6px;display:none;z-index:2;color:gray}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul{display:flex}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul li div{display:flex;width:24px;height:24px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul li div i{font-size:18px;width:18px;height:18px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell.has-control:hover .field-toolbar{display:flex}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell.active-drop{border-color:#007bff;background-color:#eef6ff;transition:.2s}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .calculated-placeholder{display:flex;align-items:center;justify-content:center;background-color:#fff;color:#007bff;padding:15px 0;width:100%;cursor:default}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .calculated-placeholder.calculated{color:#ff4500}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .icon-wrapper{width:24px;height:24px;border-radius:50%;padding:0;cursor:pointer;display:none;color:gray;border:1px solid gray;margin-left:8px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .icon-wrapper i{font-size:18px;width:18px;height:18px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper:hover .icon-wrapper{display:flex}.core-form-group-editor-container .form-design-right .form-wrapper .form-cell.selected{background-color:#dff6dd}.core-form-group-editor-container .form-design-right .form-wrapper .merge-toolbar{text-align:center;margin-top:4px}.core-form-group-editor-container .form-design-right .form-wrapper.live-form{padding-bottom:15px}.core-form-group-editor-container .form-design-right .form-wrapper.live-form .live-form-header{padding:0 15px}.core-form-group-editor-container .form-design-right .form-wrapper.live-form .live-form-header .preview-close-icon{position:absolute;right:7px;top:6px;z-index:2;color:gray;cursor:pointer}.core-form-group-editor-container .form-design-right .form-wrapper.live-form .live-form-header .preview-close-icon i{font-size:18px}.core-form-group-editor-container .drop-target{min-height:50px;min-width:50px;border:2px dashed transparent;transition:border .2s ease}.core-form-group-editor-container .drop-target.active-drop{border-color:#007bff;background-color:#eaf4ff}.core-form-group-editor-container .no-padding{padding:0!important}.core-form-group-editor-container .modal-content-root{overflow:visible}\n", ".core-form-container{overflow-x:visible}.core-form-container>form .section{margin-top:var(--size-layout-block-cell-spacing)}.core-form-container>form .section:not(:first-child){margin-top:calc(var(--size-layout-block-cell-spacing) * 2)}.core-form-container>form .section .section-header-label{display:block;height:34px;line-height:34px;margin-bottom:15px;margin-left:12px}.core-form-container>form .section .section-header-label .section-img-wrapper{position:relative}.core-form-container>form .section .section-header-label .section-img-wrapper .section-img{position:absolute;width:34px;height:34px;border-radius:50%;background-color:#d3d3d3;float:left;background-image:url(/assets/images/info.svg);background-repeat:no-repeat;background-position:center}.core-form-container>form .section .section-header-label .section-img-wrapper .section-img.calculated{background-image:url(/assets/images/sql-icon.svg);border-radius:0;background-color:transparent}.core-form-container>form .section .section-header-label .section-calc-wrapper{width:34px;height:34px;display:flex;align-items:center;justify-content:center;background-color:#d3d3d3;border-radius:50%}.core-form-container>form .section .section-header-label .section-calc-wrapper i{width:24px;height:24px;font-size:24px;color:#1b4332}.core-form-container>form .section .section-header-label .section-caption{padding-left:40px;font-weight:700;color:#696969}.core-form-container .row{margin-left:var(--size-layout-block-cell-spacing) 0px;margin-right:var(--size-layout-block-cell-spacing) 0px}.core-form-container .row .grid-buffer{border:dotted 2px darkgray}.core-form-container .row .button-control{display:flex;align-items:flex-end}.core-form-container .form-row{margin:var(--size-layout-block-cell-spacing) 0px;display:flex;align-items:center;justify-content:center}.core-form-container .form-row>button{cursor:pointer;border-radius:0}.core-form-container .form-row>button:not(:first-child){margin-left:var(--size-layout-block-cell-spacing)}.core-form-container .dev-button{cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:13px;padding:8px;width:120px;border-radius:18px;box-shadow:.4rem 0 2rem #0000002e}.core-form-container .dev-button:not(:last-child){margin-right:15px}.core-form-container .dev-button:first-child{background-color:#dff6dd;border:1px #9fdc9d solid}.core-form-container .dev-button:last-child{background-color:#fff4ce;border:1px #ffda6a solid}.core-form-container .payload-preview{display:block;width:calc(100% - 48px);height:200px;white-space:pre-wrap;overflow-x:hidden;overflow-y:auto;background-color:#dff6dd;padding:24px;margin:24px;text-indent:-58px;color:#333!important;font-family:Fira Code,monospace;font-size:.85rem;word-break:keep-all;line-height:1.5}.core-form-container .payload-preview.validator-preview{background-color:#fff4ce}.core-form-container .bottom-template-wrapper{padding-left:12px;padding-right:12px}.core-form-container .w-100{width:100%}.core-form-container .pr18{padding-right:18px}\n", ".core-button-vns-container{height:30px;display:flex;align-items:center;justify-content:center;min-width:30px}.core-button-vns-container .action-wrapper{height:30px!important;width:30px!important;display:flex;align-items:center;justify-content:center}.core-button-vns-container .action-wrapper:has(i:hover){background-color:#e7e7e7;border-radius:50%}.core-button-vns-container .btn-for-form{border:none;border-radius:0;background-color:transparent;color:#000;min-width:120px}.core-button-vns-container button.last-child{background-color:#000;color:#fff}.core-button-vns-container .action-wrapper.last-child{background-color:var(--color-basic-orange);color:#fff;border-radius:50%}.core-button-vns-container .action-wrapper.last-child:hover{background-color:var(--color-basic-orange);box-shadow:0 1rem 3rem #0000002e}.core-button-vns-container .temporary-unavailable{user-select:none;-moz-user-select:none;-webkit-user-select:none;cursor:not-allowed!important;opacity:.5}.core-button-vns-container .temporary-unavailable:hover{background-color:transparent!important}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "component", type: FormMetadataComponent, selector: "form-metadata" }, { 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: "directive", type: TooltipDirective, selector: "[appTooltip]", inputs: ["color", "backgroundColor", "appTooltip", "showAnyway", "position"] }, { kind: "component", type: CoreControlComponent, selector: "core-control", inputs: ["control", "form", "checkError$", "rangeLimit"] }, { kind: "component", type: LiveFormComponent, selector: "live-form", inputs: ["$designMode", "$forKickOff", "$workflowReactContext"], outputs: ["$onClose"] }, { kind: "directive", type: HtmlTooltipDirective, selector: "[htmlTooltip]", inputs: ["htmlTooltip", "tooltipContext", "maxWidthUnset", "backgroundColor"] }], animations: [slideFromTopFadeIn], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2274
+ }
2275
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CoreFormGroupEditorComponent, decorators: [{
2276
+ type: Component,
2277
+ args: [{ selector: 'core-form-group-editor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2278
+ NgStyle,
2279
+ AsyncPipe,
2280
+ NgTemplateOutlet,
2281
+ CoreFormArrayLayoutEditorComponent,
2282
+ CoreToastLoadingComponent,
2283
+ CorePageHeaderComponent,
2284
+ FormMetadataComponent,
2285
+ ReactiveFormsModule,
2286
+ TranslatePipe,
2287
+ TableCellPipe,
2288
+ TooltipDirective,
2289
+ HotKeysDirective,
2290
+ CoreFormComponent,
2291
+ CoreControlComponent,
2292
+ CoreDropdownComponent,
2293
+ CoreChecklistComponent,
2294
+ CoreFormControlSeekerComponent,
2295
+ CoreCheckboxComponent,
2296
+ CoreAttachmentComponent,
2297
+ CoreDatePickerComponent,
2298
+ CoreRadioGroupComponent,
2299
+ CoreMonthSelectorComponent,
2300
+ TooltipDirective,
2301
+ CoreCurrencyInputComponent,
2302
+ FieldSettingComponent,
2303
+ LiveFormComponent,
2304
+ HtmlTooltipDirective,
2305
+ ], animations: [slideFromTopFadeIn], template: "<div class=\"core-form-group-editor-container\">\r\n\r\n <div class=\"form-design-right\">\r\n\r\n @if (coreFormDesignService.$mode() === enumType.Default) {\r\n <div class=\"form-wrapper\">\r\n\r\n @if (!$isNested() && !!coreFormDesignService.$isInWorkflowDesign()) {\r\n <form-metadata></form-metadata>\r\n }\r\n\r\n <form [formGroup]=\"formDesign\" autocomplete=\"off\">\r\n <div class=\"form-cells\"> \r\n\r\n <div class=\"form-tool-bar\">\r\n @if (!$isNested() && !$hasCalculatedSection()) {\r\n <button class=\"core-button-vns-container\" (click)=\"addCalculatedSection()\">+ Calculated fields</button>\r\n }\r\n <button class=\"core-button-vns-container\" (click)=\"addSection()\">+ Add Section</button>\r\n </div>\r\n \r\n @for (section of coreFormDesignService.$placeholderSections(); track $index; let sectionIndex = $index) {\r\n <div class=\"form-section-placeholder\">\r\n\r\n <div class=\"section-header\">\r\n\r\n <div class=\"section-img-wrapper\">\r\n <div class=\"section-img\" [class.calculated]=\"section.forCalculatedFields\"></div>\r\n </div>\r\n\r\n <label [attr.contenteditable]=\"!section.forCalculatedFields\"\r\n [htmlTooltip]=\"!!section.forCalculatedFields ? calculatedFieldsTooltip : null\"\r\n (blur)=\"onCaptionEditEnd(sectionIndex, $event)\"\r\n (keydown.enter)=\"onCaptionEditEnd(sectionIndex, $event); $event.preventDefault()\"\r\n >{{ section.caption }}</label>\r\n\r\n <div class=\"section-tool pointer\" (click)=\"deleteSection(sectionIndex)\" [appTooltip]=\"'Delete section'\" [showAnyway]=\"true\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n \r\n </div>\r\n \r\n @for (row of section.rows; track $index; let rowIndex = $index) {\r\n\r\n <div class=\"form-row-wrapper\">\r\n <div class=\"form-row\">\r\n @for (cell of filteredCells(row); track $index; let colIndex = $index) {\r\n <div class=\"form-cell drop-target\" \r\n [ngStyle]=\"{ flex: (cell.flexSize ?? 0) + ' 1 0%' }\"\r\n [attr.data-flex]=\"cell.flexSize ?? 0\"\r\n (drop)=\"onDropIntoCell($event, sectionIndex, rowIndex, colIndex)\"\r\n (dragover)=\"onDragOver($event, section, cell.control!)\"\r\n (dragenter)=\"onDragEnter(sectionIndex + '_' + rowIndex + '_' + colIndex)\"\r\n (dragleave)=\"onDragLeave(sectionIndex + '_' + rowIndex + '_' + colIndex)\"\r\n [class.selected]=\"cell?.selected\"\r\n [class.dragging-over]=\"isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex]\"\r\n [class.has-control]=\"!!cell && !!cell.control && !!getControl(cell)\"\r\n (click)=\"onCellClicked(sectionIndex, rowIndex, colIndex)\"\r\n >\r\n\r\n\r\n @if (!isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex]) {\r\n\r\n @if (!!cell && !!cell.control && !!getControl(cell)) {\r\n <label contenteditable=\"true\"\r\n (blur)=\"onFieldCaptionEditEnd(cell, $event)\"\r\n (keydown.enter)=\"onFieldCaptionEditEnd(cell, $event); $event.preventDefault()\"\r\n [class.d-none]=\"!!getControl(cell)?.hidden\"\r\n [class.required]=\"!!cell && !!cell.control && !!getControl(cell) && isRequired(getControl(cell))\"\r\n >{{ cell.control.label || 'label' }}</label>\r\n\r\n @if (cell.control.controlType==='CALCULATED') {\r\n <div class=\"control-wrapper\" (click)=\"openSettingsForCell(cell, sectionIndex, rowIndex, colIndex)\">\r\n <core-control \r\n [control]=\"getControl(cell)!\" \r\n [form]=\"formDesign\"\r\n [checkError$]=\"checkError$\" />\r\n </div>\r\n } @else {\r\n <core-control \r\n [control]=\"getControl(cell)!\" \r\n [form]=\"formDesign\"\r\n [checkError$]=\"checkError$\" />\r\n }\r\n \r\n <div class=\"field-toolbar\">\r\n <ul>\r\n <li>\r\n <div class=\"field-tool pointer\" (click)=\"openSettingsForCell(cell, sectionIndex, rowIndex, colIndex)\" [appTooltip]=\"'Show settings'\">\r\n <i class=\"feather-settings\"></i>\r\n </div>\r\n </li>\r\n <li>\r\n <div class=\"field-tool pointer\" (click)=\"deleteField(row, sectionIndex, rowIndex, colIndex)\" [appTooltip]=\"'Remove field from cell'\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n \r\n } @else {\r\n <div class=\"calculated-placeholder\" [class.calculated]=\"!!section.forCalculatedFields\">\r\n {{ !!section.forCalculatedFields ? 'Drop calculated field here' : 'Drop here'}}\r\n </div>\r\n }\r\n\r\n @if (cell?.selected && canMergeCells(sectionIndex, rowIndex)) {\r\n <div class=\"merge-toolbar\">\r\n <button (click)=\"mergeCells(sectionIndex, rowIndex)\">\uD83D\uDD17 Merge</button>\r\n </div>\r\n }\r\n \r\n }\r\n\r\n </div>\r\n }\r\n </div>\r\n <div class=\"row-tool-bar\">\r\n <div class=\"icon-wrapper\" (click)=\"deleteRow(sectionIndex, rowIndex)\" [appTooltip]=\"'Delete row'\" [showAnyway]=\"true\"><i class=\"feather-x\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"addRow(sectionIndex)\" [appTooltip]=\"'Add row'\" [showAnyway]=\"true\"><i class=\"feather-arrow-down\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"insertRow(sectionIndex, rowIndex)\" [appTooltip]=\"'Insert row'\" [showAnyway]=\"true\"><i class=\"feather-corner-right-down\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"addColumn(row)\" [appTooltip]=\"'Add column'\" [showAnyway]=\"true\"><i class=\"feather-arrow-right\"></i></div>\r\n </div>\r\n </div>\r\n\r\n }\r\n </div>\r\n }\r\n \r\n \r\n </div>\r\n </form>\r\n </div>\r\n } @else if (!!$sections()) {\r\n\r\n @if(!!(injectedFields$ | async) && !!(injectedFields$ | async)!.length) {\r\n\r\n @if (!!coreFormDesignService.$afInstance().normalMode) {\r\n <live-form [$designMode]=\"true\" [$forKickOff]=\"true\" />\r\n } @else {\r\n <live-form [$designMode]=\"true\" [$forKickOff]=\"true\" ($onClose)=\"closePreview()\" />\r\n }\r\n\r\n } @else {\r\n <h2>COULD NOT UPDATE injectedFields$</h2>\r\n }\r\n\r\n } @else {\r\n <h2>$sections() empty / null / undefined</h2>\r\n }\r\n </div>\r\n</div>\r\n\r\n<ng-template #calculatedFieldsTooltip>\r\n <div style=\"max-width: 280px;\">\r\n <strong>Calculated Fields</strong><br />\r\n <p></p>\r\n These fields are hidden from the form and cannot be edited directly.<br /><br />\r\n - They are computed automatically during workflow execution.<br />\r\n - Each field depends on one or more standard input fields.<br />\r\n - The calculation is evaluated using either an SQL query engine (like <strong>Dapper</strong>) or an in-memory expression engine (like <strong>Dynamic Expresso</strong>).<br /><br />\r\n These results can be used to influence workflow logic, rule trees, or approval paths.\r\n </div>\r\n</ng-template>\r\n\r\n\r\n ", styles: ["@charset \"UTF-8\";.core-form-group-editor-container{position:relative;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));width:100%;overflow:hidden;background-color:#eff0f1;font-size:13px}.core-form-group-editor-container .core-button-vns-container{margin-right:8px!important}.core-form-group-editor-container .core-button-vns-container:last-child{background-color:#000;color:#fff;margin-right:0}.core-form-group-editor-container .af-metadata-overlay{position:fixed;top:60px;left:66px;background:#fff;box-shadow:.4rem 0 2rem #0000002e;z-index:1000;width:1214px;height:calc(100vh - 75px);overflow-y:auto;pointer-events:none}.core-form-group-editor-container .af-metadata-overlay.shown{pointer-events:auto}.core-form-group-editor-container *{border-radius:0}.core-form-group-editor-container ul,.core-form-group-editor-container li{padding:0}.core-form-group-editor-container li{max-width:200px}.core-form-group-editor-container ul div.space{display:block;height:15px}.core-form-group-editor-container li.full-width{max-width:100%}.core-form-group-editor-container .field-setting-panel{display:block;position:fixed;width:360px;height:100vh;top:0;right:-360px;background-color:#fff;box-shadow:.4rem 0 2rem #0000002e;transition:right .5s ease-out}.core-form-group-editor-container .field-setting-panel .close-wrapper{width:32px;height:32px;position:absolute;top:15px;right:15px;display:flex;background-color:#848484;border-radius:50%}.core-form-group-editor-container .field-setting-panel .close-wrapper i{width:16px;height:16px;font-size:18px;color:#848484}.core-form-group-editor-container .field-setting-panel .panel-caption{margin-bottom:1rem;padding-bottom:.5rem;border-bottom:1px solid #ddd;width:100%;overflow:hidden;text-wrap:nowrap;text-overflow:ellipsis}.core-form-group-editor-container .field-setting-panel.calculated-type{width:500px;right:-500px}.core-form-group-editor-container .field-setting-panel.calculated-type textarea{border-radius:8px;height:150px}.core-form-group-editor-container .field-setting-panel.open{right:0}.core-form-group-editor-container .form-design-left{position:absolute;top:var(--size-core-page-header-height);bottom:0;left:0;z-index:1;width:360px;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));padding:15px;padding-right:calc(15px + var(--size-scrollbar-width));background-color:#87ceeb;overflow-y:hidden}.core-form-group-editor-container .form-design-left .category-name{color:#fff}.core-form-group-editor-container .form-design-left .grid-buffer-wrapper{background-color:#fff;padding:15px}.core-form-group-editor-container .form-design-left ul:last-child{padding-bottom:400px}.core-form-group-editor-container .form-design-left .category-name{margin-bottom:15px}.core-form-group-editor-container .form-design-left .json-preview{background-color:#fff;color:#333;padding:1rem 1.5rem;box-shadow:0 2px 6px #00000014;font-family:Fira Code,monospace;font-size:.85rem;word-break:keep-all;overflow-x:auto;line-height:1.5;width:330px;height:calc(100vh - 205px)}.core-form-group-editor-container .form-design-left button{height:35px;border-radius:0;margin-bottom:15px;color:#fff;border:none;font-size:13px;background-color:transparent}.core-form-group-editor-container .form-design-left:hover{overflow-y:auto;padding-right:15px}.core-form-group-editor-container .form-design-right{width:100%;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));overflow-y:auto}.core-form-group-editor-container .form-design-right .form-wrapper{width:100%;overflow-y:visible;background-color:#fff}.core-form-group-editor-container .form-design-right .form-wrapper button{margin-left:12px;padding:4px 10px;border:1px solid #ccc;cursor:pointer;transition:all .2s;width:110px}.core-form-group-editor-container .form-design-right .form-wrapper button:hover{background-color:#e4f0ff;border-color:#007bff;color:#007bff}.core-form-group-editor-container .form-design-right .form-wrapper .form-tool-bar{display:flex;align-items:center;justify-content:flex-end}.core-form-group-editor-container .form-design-right .form-wrapper .form-tool-bar>button{width:150px;margin:0}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells{display:flex;flex-direction:column;gap:32px;padding:20px 15px 15px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder{padding:12px 15px;border:1px dashed #ccc;background-color:#fff;box-shadow:0 2px 6px #0000000a}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header{display:flex;position:relative;align-items:center;justify-content:flex-start;font-weight:600;margin-bottom:12px;color:#333}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-img{width:34px;height:34px;border-radius:50%;background-color:#d3d3d3;float:left;background-image:url(/assets/images/info.svg);background-repeat:no-repeat;background-position:center;margin-right:8px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-img.calculated{background-image:url(/assets/images/sql-icon.svg);background-color:transparent;border-radius:0}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-tool{position:absolute;right:5px;top:6px;display:none;z-index:2;color:gray}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-tool i{font-size:24px;color:#848484}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header:hover .section-tool{display:block}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .row-tool-bar{display:flex;align-items:center;justify-content:flex-end;margin-bottom:8px;height:24px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-row{display:flex;gap:15px;margin-bottom:15px;min-height:50px;background-color:#d3d3d3;padding:8px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell{flex:1;min-height:90px;background-color:#fcfcfc;border:1px dashed #ccc;position:relative;padding:20px 10px 10px;transition:border .2s ease-in-out}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell:before{content:attr(data-flex);position:absolute;top:2px;left:4px;font-size:10px;color:#999}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell label.required:after{content:\" *\";color:#ff040b}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar{position:absolute;right:7px;top:6px;display:none;z-index:2;color:gray}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul{display:flex}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul li div{display:flex;width:24px;height:24px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul li div i{font-size:18px;width:18px;height:18px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell.has-control:hover .field-toolbar{display:flex}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell.active-drop{border-color:#007bff;background-color:#eef6ff;transition:.2s}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .calculated-placeholder{display:flex;align-items:center;justify-content:center;background-color:#fff;color:#007bff;padding:15px 0;width:100%;cursor:default}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .calculated-placeholder.calculated{color:#ff4500}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .icon-wrapper{width:24px;height:24px;border-radius:50%;padding:0;cursor:pointer;display:none;color:gray;border:1px solid gray;margin-left:8px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .icon-wrapper i{font-size:18px;width:18px;height:18px}.core-form-group-editor-container .form-design-right .form-wrapper .form-cells .form-row-wrapper:hover .icon-wrapper{display:flex}.core-form-group-editor-container .form-design-right .form-wrapper .form-cell.selected{background-color:#dff6dd}.core-form-group-editor-container .form-design-right .form-wrapper .merge-toolbar{text-align:center;margin-top:4px}.core-form-group-editor-container .form-design-right .form-wrapper.live-form{padding-bottom:15px}.core-form-group-editor-container .form-design-right .form-wrapper.live-form .live-form-header{padding:0 15px}.core-form-group-editor-container .form-design-right .form-wrapper.live-form .live-form-header .preview-close-icon{position:absolute;right:7px;top:6px;z-index:2;color:gray;cursor:pointer}.core-form-group-editor-container .form-design-right .form-wrapper.live-form .live-form-header .preview-close-icon i{font-size:18px}.core-form-group-editor-container .drop-target{min-height:50px;min-width:50px;border:2px dashed transparent;transition:border .2s ease}.core-form-group-editor-container .drop-target.active-drop{border-color:#007bff;background-color:#eaf4ff}.core-form-group-editor-container .no-padding{padding:0!important}.core-form-group-editor-container .modal-content-root{overflow:visible}\n", ".core-form-container{overflow-x:visible}.core-form-container>form .section{margin-top:var(--size-layout-block-cell-spacing)}.core-form-container>form .section:not(:first-child){margin-top:calc(var(--size-layout-block-cell-spacing) * 2)}.core-form-container>form .section .section-header-label{display:block;height:34px;line-height:34px;margin-bottom:15px;margin-left:12px}.core-form-container>form .section .section-header-label .section-img-wrapper{position:relative}.core-form-container>form .section .section-header-label .section-img-wrapper .section-img{position:absolute;width:34px;height:34px;border-radius:50%;background-color:#d3d3d3;float:left;background-image:url(/assets/images/info.svg);background-repeat:no-repeat;background-position:center}.core-form-container>form .section .section-header-label .section-img-wrapper .section-img.calculated{background-image:url(/assets/images/sql-icon.svg);border-radius:0;background-color:transparent}.core-form-container>form .section .section-header-label .section-calc-wrapper{width:34px;height:34px;display:flex;align-items:center;justify-content:center;background-color:#d3d3d3;border-radius:50%}.core-form-container>form .section .section-header-label .section-calc-wrapper i{width:24px;height:24px;font-size:24px;color:#1b4332}.core-form-container>form .section .section-header-label .section-caption{padding-left:40px;font-weight:700;color:#696969}.core-form-container .row{margin-left:var(--size-layout-block-cell-spacing) 0px;margin-right:var(--size-layout-block-cell-spacing) 0px}.core-form-container .row .grid-buffer{border:dotted 2px darkgray}.core-form-container .row .button-control{display:flex;align-items:flex-end}.core-form-container .form-row{margin:var(--size-layout-block-cell-spacing) 0px;display:flex;align-items:center;justify-content:center}.core-form-container .form-row>button{cursor:pointer;border-radius:0}.core-form-container .form-row>button:not(:first-child){margin-left:var(--size-layout-block-cell-spacing)}.core-form-container .dev-button{cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:13px;padding:8px;width:120px;border-radius:18px;box-shadow:.4rem 0 2rem #0000002e}.core-form-container .dev-button:not(:last-child){margin-right:15px}.core-form-container .dev-button:first-child{background-color:#dff6dd;border:1px #9fdc9d solid}.core-form-container .dev-button:last-child{background-color:#fff4ce;border:1px #ffda6a solid}.core-form-container .payload-preview{display:block;width:calc(100% - 48px);height:200px;white-space:pre-wrap;overflow-x:hidden;overflow-y:auto;background-color:#dff6dd;padding:24px;margin:24px;text-indent:-58px;color:#333!important;font-family:Fira Code,monospace;font-size:.85rem;word-break:keep-all;line-height:1.5}.core-form-container .payload-preview.validator-preview{background-color:#fff4ce}.core-form-container .bottom-template-wrapper{padding-left:12px;padding-right:12px}.core-form-container .w-100{width:100%}.core-form-container .pr18{padding-right:18px}\n", ".core-button-vns-container{height:30px;display:flex;align-items:center;justify-content:center;min-width:30px}.core-button-vns-container .action-wrapper{height:30px!important;width:30px!important;display:flex;align-items:center;justify-content:center}.core-button-vns-container .action-wrapper:has(i:hover){background-color:#e7e7e7;border-radius:50%}.core-button-vns-container .btn-for-form{border:none;border-radius:0;background-color:transparent;color:#000;min-width:120px}.core-button-vns-container button.last-child{background-color:#000;color:#fff}.core-button-vns-container .action-wrapper.last-child{background-color:var(--color-basic-orange);color:#fff;border-radius:50%}.core-button-vns-container .action-wrapper.last-child:hover{background-color:var(--color-basic-orange);box-shadow:0 1rem 3rem #0000002e}.core-button-vns-container .temporary-unavailable{user-select:none;-moz-user-select:none;-webkit-user-select:none;cursor:not-allowed!important;opacity:.5}.core-button-vns-container .temporary-unavailable:hover{background-color:transparent!important}\n"] }]
2306
+ }], ctorParameters: () => [{ type: MultiLanguageService }] });
2307
+
2308
+ class CoreFormArrayLayoutEditorComponent {
2309
+ constructor() {
2310
+ this.checkError$ = new BehaviorSubject(false);
2311
+ this.coreFormDesignService = inject(CoreFormDesignService);
2312
+ this.$sections = this.coreFormDesignService.$nestedDesignSections;
2313
+ this.form = this.coreFormDesignService.formDesign;
2314
+ }
2315
+ onClose() {
2316
+ this.coreFormDesignService.$showFormArrayDesign.set(false);
2317
+ }
2318
+ onMiniDrop(event, sectionIndex, rowIndex, colIndex) {
2319
+ const rawData = event?.dataTransfer?.getData('application/json');
2320
+ if (rawData) {
2321
+ const control = JSON.parse(rawData);
2322
+ // clone control để tránh mutate template gốc
2323
+ const newControl = structuredClone(control);
2324
+ // insert vào đúng chỗ
2325
+ const current = this.$sections();
2326
+ if (!current)
2327
+ return;
2328
+ current[sectionIndex].rows[rowIndex][colIndex] = newControl;
2329
+ // trigger signal cập nhật
2330
+ this.$sections.set([...current]);
2331
+ }
2332
+ }
2333
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CoreFormArrayLayoutEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2334
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.5", type: CoreFormArrayLayoutEditorComponent, isStandalone: true, selector: "core-form-array-layout-editor", ngImport: i0, template: "<div class=\"core-form-array-layout-editor-container\">\r\n\r\n\r\n <div class=\"modal-container\">\r\n <div class=\"modal-content-root\">\r\n\r\n <div class=\"layout-header\">\r\n DESIGN FORM ARRAY LAYOUT\r\n <button class=\"btn btn-sm btn-outline-secondary\" (click)=\"onClose()\">\u2716</button>\r\n </div>\r\n\r\n <div class=\"layout-body\">\r\n <div class=\"json-holder\">\r\n <pre>{{ coreFormDesignService.$currentControlJson() }}</pre>\r\n </div>\r\n <div class=\"palete\">\r\n <core-form-array-control-palette />\r\n </div>\r\n <div class=\"sections-holder\">\r\n <core-form-group-editor [$idAsInput]=\"true\" [$isNested]=\"true\"/>\r\n </div>\r\n <div class=\"field-setting-holder\">\r\n <field-setting [$isNested]=\"true\"></field-setting>\r\n </div>\r\n \r\n <!-- @for (section of $sections(); track $index; let sectionIndex = $index) {\r\n <div class=\"section-card\">\r\n <div class=\"section-caption\">{{ section.caption || 'Untitled Section' }}</div>\r\n\r\n @for (row of section.rows; track $index; let rowIndex = $index) {\r\n <div class=\"row\">\r\n @for (control of row; track $index; let colIndex = $index) {\r\n <div\r\n class=\"form-cell mini-drop-target\"\r\n [attr.data-index]=\"$index\"\r\n miniDropTarget\r\n (miniDropped)=\"onMiniDrop($event, sectionIndex, rowIndex, colIndex)\"\r\n >\r\n <core-control-no-form-array\r\n [control]=\"control\"\r\n [form]=\"form\"\r\n [checkError$]=\"checkError$\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n } -->\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n\r\n</div>", styles: [".core-form-array-layout-editor-container{height:100%;width:100vw;display:flex;flex-direction:column}.layout-header{display:flex;justify-content:space-between;align-items:center;padding:15px;height:50px;background:#f7f7f7;border-bottom:1px solid #ddd;transform:translate(-15px,-15px);width:calc(100% + 30px);font-size:20px}.layout-body{display:flex;vertical-align:top}.layout-body .json-holder,.layout-body .palete{width:240px;display:inline-block}.layout-body .sections-holder{width:480px;display:inline-block}.layout-body .field-setting-holder{width:360px;display:inline-block}.layout-footer{padding:1rem;border-top:1px solid #ddd;text-align:right}\n"], dependencies: [{ kind: "component", type: CoreFormArrayControlPaletteComponent, selector: "core-form-array-control-palette" }, { kind: "component", type: CoreFormGroupEditorComponent, selector: "core-form-group-editor", inputs: ["$isNested", "$idAsInput", "$id"] }, { kind: "component", type: FieldSettingComponent, selector: "field-setting", inputs: ["$isNested"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2335
+ }
2336
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CoreFormArrayLayoutEditorComponent, decorators: [{
2337
+ type: Component,
2338
+ args: [{ selector: 'core-form-array-layout-editor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
2339
+ CoreControlNoFormArrayComponent,
2340
+ CoreFormArrayControlPaletteComponent,
2341
+ CoreFormGroupEditorComponent,
2342
+ FieldSettingComponent
2343
+ ], template: "<div class=\"core-form-array-layout-editor-container\">\r\n\r\n\r\n <div class=\"modal-container\">\r\n <div class=\"modal-content-root\">\r\n\r\n <div class=\"layout-header\">\r\n DESIGN FORM ARRAY LAYOUT\r\n <button class=\"btn btn-sm btn-outline-secondary\" (click)=\"onClose()\">\u2716</button>\r\n </div>\r\n\r\n <div class=\"layout-body\">\r\n <div class=\"json-holder\">\r\n <pre>{{ coreFormDesignService.$currentControlJson() }}</pre>\r\n </div>\r\n <div class=\"palete\">\r\n <core-form-array-control-palette />\r\n </div>\r\n <div class=\"sections-holder\">\r\n <core-form-group-editor [$idAsInput]=\"true\" [$isNested]=\"true\"/>\r\n </div>\r\n <div class=\"field-setting-holder\">\r\n <field-setting [$isNested]=\"true\"></field-setting>\r\n </div>\r\n \r\n <!-- @for (section of $sections(); track $index; let sectionIndex = $index) {\r\n <div class=\"section-card\">\r\n <div class=\"section-caption\">{{ section.caption || 'Untitled Section' }}</div>\r\n\r\n @for (row of section.rows; track $index; let rowIndex = $index) {\r\n <div class=\"row\">\r\n @for (control of row; track $index; let colIndex = $index) {\r\n <div\r\n class=\"form-cell mini-drop-target\"\r\n [attr.data-index]=\"$index\"\r\n miniDropTarget\r\n (miniDropped)=\"onMiniDrop($event, sectionIndex, rowIndex, colIndex)\"\r\n >\r\n <core-control-no-form-array\r\n [control]=\"control\"\r\n [form]=\"form\"\r\n [checkError$]=\"checkError$\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n } -->\r\n </div>\r\n\r\n </div>\r\n </div>\r\n\r\n\r\n</div>", styles: [".core-form-array-layout-editor-container{height:100%;width:100vw;display:flex;flex-direction:column}.layout-header{display:flex;justify-content:space-between;align-items:center;padding:15px;height:50px;background:#f7f7f7;border-bottom:1px solid #ddd;transform:translate(-15px,-15px);width:calc(100% + 30px);font-size:20px}.layout-body{display:flex;vertical-align:top}.layout-body .json-holder,.layout-body .palete{width:240px;display:inline-block}.layout-body .sections-holder{width:480px;display:inline-block}.layout-body .field-setting-holder{width:360px;display:inline-block}.layout-footer{padding:1rem;border-top:1px solid #ddd;text-align:right}\n"] }]
2344
+ }] });
2345
+
2346
+ class CoreFormDesignComponent extends BaseComponent {
2347
+ constructor(mls) {
2348
+ super(mls);
2349
+ this.mls = mls;
2350
+ this.$idAsInput = input();
2351
+ this.$id = input();
2352
+ this.$settingPanel = viewChild('settingPanel');
2353
+ this.$jsonMode = signal('selectedField');
2354
+ this.injectedFields$ = new BehaviorSubject([]);
2355
+ this.enumType = EnumFormDesignMode;
2356
+ this.enumLeftPanelMode = EnumLeftPanelMode;
2357
+ this.$leftPanelMode = computed(() => {
2358
+ if (this.coreFormDesignService.$fieldSettingPanelOpen()) {
2359
+ return this.enumLeftPanelMode.Json;
2360
+ }
2361
+ else {
2362
+ return this.enumLeftPanelMode.FieldCollection;
2363
+ }
2364
+ });
2365
+ this.ds = inject(DomService);
2366
+ this.js = inject(JsonService);
2367
+ this.$zIndex = computed(() => {
2368
+ if (this.coreFormDesignService.$fieldSettingPanelOpen()) {
2369
+ return this.ds.getMaxZIndex() + 1;
2370
+ }
2371
+ else {
2372
+ return 0;
2373
+ }
2374
+ });
2375
+ this.previewMode$ = new BehaviorSubject(EnumCorePageEditMode.CREATE);
2376
+ this.$loading = signal(false);
2377
+ this.coreFormDesignService = inject(CoreFormDesignService);
2378
+ this.renderer = inject(Renderer2);
2379
+ this.cdr = inject(ChangeDetectorRef);
2380
+ this.router = inject(Router);
2381
+ this.route = inject(ActivatedRoute);
2382
+ this.alertService = inject(AlertService);
2383
+ this.applicationHelpService = inject(ApplicationHelpService);
2384
+ this.wfs = inject(CoreWorkflowService);
2385
+ this.dbs = inject(DbService);
2386
+ this.appConfigService = inject(AppConfigService);
2387
+ this.$hasCalculatedSection = computed(() => {
2388
+ return this.coreFormDesignService.$placeholderSections().some(s => !!s.forCalculatedFields);
2389
+ });
2390
+ this.formDesign = this.coreFormDesignService.formDesign;
2391
+ this.setControlProp = this.coreFormDesignService.setControlProp.bind(this.coreFormDesignService);
2392
+ this.isDragOverMap = {};
2393
+ this.idStream$ = new BehaviorSubject(undefined);
2394
+ this.getByIdStream$ = this.idStream$.pipe(filter(id => !!id && id !== '0'), distinctUntilChanged(), tap(() => {
2395
+ this.$loading.set(true);
2396
+ this.coreFormDesignService.editMode$.next(EnumCorePageEditMode.UPDATE);
2397
+ this.coreFormDesignService.$submitText.set(EnumTranslateKey.UI_EDIT_FORM_BUTTON_SAVE);
2398
+ }), switchMap(id => {
2399
+ return this.coreFormDesignService.getById(id)
2400
+ .pipe(catchError(err => {
2401
+ this.$loading.set(false);
2402
+ return of(err);
2403
+ }));
2404
+ }));
2405
+ this.form = new FormGroup({
2406
+ stringBox: new FormControl(),
2407
+ timeBox: new FormControl(),
2408
+ email: new FormControl(),
2409
+ textarea: new FormControl(),
2410
+ number: new FormControl(),
2411
+ currency: new FormControl(),
2412
+ dropdown: new FormControl(),
2413
+ employeeSeeker: new FormControl(),
2414
+ checklist: new FormControl(),
2415
+ employeeSeekerMultiple: new FormControl(),
2416
+ datePicker: new FormControl(),
2417
+ monthSelector: new FormControl(),
2418
+ attachment: new FormControl(),
2419
+ attachmentBuffer: new FormControl(),
2420
+ checkbox: new FormControl(),
2421
+ calculated: new FormControl(),
2422
+ formArray: new FormArray([
2423
+ new FormControl('')
2424
+ ])
2425
+ });
2426
+ this.$sections = computed(() => {
2427
+ const hydrated = this.coreFormDesignService.rehydrateSections(this.coreFormDesignService.$placeholderSections());
2428
+ let sections = this.coreFormDesignService.toCoreFormSections(hydrated);
2429
+ // ✅ Inject hidden "id" field into the first cell row of the first section
2430
+ sections = this.coreFormDesignService.injectSystemControls(sections, this.coreFormDesignService.$afInstance().hasIdOfStringType ?? false);
2431
+ return sections;
2432
+ });
2433
+ this.checkError$ = new BehaviorSubject(false);
2434
+ this.controlCategories = [
2435
+ {
2436
+ name: 'Calculated fields',
2437
+ controls: [
2438
+ {
2439
+ flexSize: 12,
2440
+ controlType: EnumFormBaseContolType.CALCULATED,
2441
+ type: 'calculated',
2442
+ field: 'calculated',
2443
+ label: '',
2444
+ value: '',
2445
+ placeholder: 'Calculated',
2446
+ headless: true,
2447
+ }
2448
+ ]
2449
+ },
2450
+ {
2451
+ name: 'Text',
2452
+ controls: [
2453
+ {
2454
+ flexSize: 12,
2455
+ controlType: EnumFormBaseContolType.TEXTBOX,
2456
+ type: 'string',
2457
+ field: 'stringBox',
2458
+ label: '',
2459
+ value: '',
2460
+ placeholder: 'String box',
2461
+ headless: true,
2462
+ },
2463
+ {
2464
+ flexSize: 12,
2465
+ controlType: EnumFormBaseContolType.TEXTBOX,
2466
+ type: 'email',
2467
+ field: 'email',
2468
+ label: '',
2469
+ value: '',
2470
+ placeholder: 'Email',
2471
+ headless: true,
2472
+ },
2473
+ {
2474
+ flexSize: 12,
2475
+ controlType: EnumFormBaseContolType.TEXTAREA,
2476
+ type: 'string',
2477
+ field: 'textarea',
2478
+ label: '',
2479
+ value: '',
2480
+ textareaRows: 2,
2481
+ placeholder: 'Text area',
2482
+ headless: true,
2483
+ }
2484
+ ]
2485
+ },
2486
+ {
2487
+ name: 'Numerical',
2488
+ controls: [
2489
+ {
2490
+ flexSize: 12,
2491
+ controlType: EnumFormBaseContolType.TEXTBOX,
2492
+ type: 'number',
2493
+ field: 'number',
2494
+ label: '',
2495
+ value: 100,
2496
+ placeholder: 'Number',
2497
+ headless: true,
2498
+ },
2499
+ {
2500
+ flexSize: 12,
2501
+ controlType: EnumFormBaseContolType.CURRENCY,
2502
+ type: 'number',
2503
+ field: 'currency',
2504
+ label: '',
2505
+ value: '',
2506
+ placeholder: 'Currency',
2507
+ headless: true,
2508
+ },
2509
+ ]
2510
+ },
2511
+ {
2512
+ name: 'Single selection',
2513
+ controls: [
2514
+ {
2515
+ flexSize: 12,
2516
+ controlType: EnumFormBaseContolType.DROPDOWN,
2517
+ type: 'any',
2518
+ field: 'dropdown',
2519
+ label: '',
2520
+ value: '',
2521
+ dropdownOptions$: new BehaviorSubject([]),
2522
+ shownFrom: 'name',
2523
+ getByIdObject$: new BehaviorSubject({}),
2524
+ placeholder: 'Dropdown',
2525
+ headless: true,
2526
+ },
2527
+ {
2528
+ flexSize: 12,
2529
+ controlType: EnumFormBaseContolType.SEEKER,
2530
+ seekerSourceType: EnumCoreFormControlSeekerSourceType.EMPLOYEE_SEEK,
2531
+ type: 'any[]',
2532
+ field: 'employeeSeeker',
2533
+ label: '',
2534
+ value: ['Nguyễn A'],
2535
+ boundFrom: 'id',
2536
+ shownFrom: 'fullname',
2537
+ getByIdObject$: new BehaviorSubject({}),
2538
+ placeholder: 'Employee seeker',
2539
+ headless: true,
2540
+ }
2541
+ ]
2542
+ },
2543
+ {
2544
+ name: 'Multiple Selection',
2545
+ controls: [
2546
+ // {
2547
+ // flexSize: 12,
2548
+ // controlType: EnumFormBaseContolType.GRIDBUFFER,
2549
+ // type: 'children',
2550
+ // field: 'gridbuffer',
2551
+ // label: '',
2552
+ // value: [],
2553
+ // placeholder: 'Grid buffer',
2554
+ // gridBufferFormSections: [
2555
+ // {
2556
+ // rows: [
2557
+ // [
2558
+ // {
2559
+ // flexSize: 6,
2560
+ // field: 'field1',
2561
+ // type: 'date',
2562
+ // value: '',
2563
+ // controlType: EnumFormBaseContolType.DATEPICKER,
2564
+ // label: 'field 1'
2565
+ // },
2566
+ // {
2567
+ // flexSize: 6,
2568
+ // field: 'field2',
2569
+ // type: 'number',
2570
+ // value: null,
2571
+ // controlType: EnumFormBaseContolType.TEXTBOX,
2572
+ // label: 'field 2'
2573
+ // },
2574
+ // ]
2575
+ // ]
2576
+ // }
2577
+ // ],
2578
+ // gridBufferTableColumns: [
2579
+ // {
2580
+ // caption: 'id',
2581
+ // field: 'id',
2582
+ // hidden: true,
2583
+ // type: 'string',
2584
+ // align: 'left',
2585
+ // width: 0,
2586
+ // },
2587
+ // {
2588
+ // field: 'field1',
2589
+ // width: 200,
2590
+ // caption: 'field 1',
2591
+ // type: 'date',
2592
+ // pipe: EnumCoreTablePipeType.DATE,
2593
+ // align: 'center'
2594
+ // },
2595
+ // {
2596
+ // field: 'field2',
2597
+ // width: 100,
2598
+ // caption: 'field 2',
2599
+ // type: 'number',
2600
+ // align: 'right'
2601
+ // },
2602
+ // ],
2603
+ // headless: true,
2604
+ // tableHeight: 100,
2605
+ // liteMode: true,
2606
+ // },
2607
+ {
2608
+ flexSize: 12,
2609
+ controlType: EnumFormBaseContolType.CHECKLIST,
2610
+ type: 'any[]',
2611
+ field: 'checklist',
2612
+ label: '',
2613
+ value: [],
2614
+ checklistOptions$: new BehaviorSubject([]),
2615
+ shownFrom: 'name',
2616
+ getByIdObject$: new BehaviorSubject({}),
2617
+ placeholder: 'Check list',
2618
+ headless: true,
2619
+ },
2620
+ {
2621
+ flexSize: 12,
2622
+ controlType: EnumFormBaseContolType.SEEKER,
2623
+ seekerSourceType: EnumCoreFormControlSeekerSourceType.EMPLOYEE_SEEK,
2624
+ multiMode: true,
2625
+ type: 'any[]',
2626
+ field: 'employeeSeekerMultiple',
2627
+ label: '',
2628
+ value: [],
2629
+ objectList$: new BehaviorSubject([]),
2630
+ boundFrom: 'id',
2631
+ shownFrom: 'fullname',
2632
+ getByIdObject$: new BehaviorSubject({}),
2633
+ multiModeTableHeight: 100,
2634
+ placeholder: 'Employee seeker (multi mode)',
2635
+ headless: true,
2636
+ }
2637
+ ]
2638
+ },
2639
+ {
2640
+ name: 'Date',
2641
+ controls: [
2642
+ {
2643
+ flexSize: 12,
2644
+ controlType: EnumFormBaseContolType.DATEPICKER,
2645
+ type: 'date',
2646
+ field: 'datePicker',
2647
+ label: '',
2648
+ value: '',
2649
+ placeholder: 'Date picker',
2650
+ showPlaceholder: true,
2651
+ headless: true,
2652
+ },
2653
+ {
2654
+ flexSize: 12,
2655
+ controlType: EnumFormBaseContolType.TEXTBOX,
2656
+ type: 'time',
2657
+ field: 'timeBox',
2658
+ label: '',
2659
+ value: null,
2660
+ placeholder: 'Time box',
2661
+ headless: true,
2662
+ },
2663
+ {
2664
+ flexSize: 12,
2665
+ controlType: EnumFormBaseContolType.MONTHSELECTOR,
2666
+ type: 'string',
2667
+ field: 'monthSelector',
2668
+ label: '',
2669
+ value: '',
2670
+ placeholder: 'Month selector',
2671
+ headless: true,
2672
+ },
2673
+ ]
2674
+ },
2675
+ {
2676
+ name: 'Other',
2677
+ controls: [
2678
+ {
2679
+ flexSize: 12,
2680
+ controlType: EnumFormBaseContolType.ATTACHMENT,
2681
+ type: 'string',
2682
+ field: 'attachment',
2683
+ label: '',
2684
+ value: '',
2685
+ assignTo: 'unknown',
2686
+ placeholder: 'Attachment',
2687
+ headless: true,
2688
+ },
2689
+ {
2690
+ flexSize: 12,
2691
+ controlType: EnumFormBaseContolType.CHECKBOX,
2692
+ type: 'boolean',
2693
+ field: 'checkbox',
2694
+ label: '',
2695
+ value: '',
2696
+ placeholder: 'Checkbox',
2697
+ headless: true,
2698
+ },
2699
+ ]
2700
+ },
2701
+ {
2702
+ name: 'Form Array',
2703
+ controls: [
2704
+ {
2705
+ flexSize: 12,
2706
+ controlType: EnumFormBaseContolType.FORM_ARRAY,
2707
+ type: 'children',
2708
+ field: 'formArray',
2709
+ label: '',
2710
+ value: '',
2711
+ placeholder: 'FormArray',
2712
+ headless: true,
2713
+ childrenSections: [
2714
+ {
2715
+ rows: [
2716
+ [
2717
+ {
2718
+ field: 'textBox',
2719
+ flexSize: 12,
2720
+ controlType: EnumFormBaseContolType.TEXTBOX,
2721
+ type: 'text',
2722
+ value: '',
2723
+ label: ''
2724
+ }
2725
+ ]
2726
+ ]
2727
+ }
2728
+ ]
2729
+ },
2730
+ ]
2731
+ },
2732
+ ];
2733
+ /*
2734
+ onDropIntoCell(event: DragEvent, sectionIndex: number, rowIndex: number, colIndex: number): void {
2735
+ event.preventDefault();
2736
+ const template = this.coreFormDesignService.$currentControlTemplate();
2737
+ if (!template) return;
2738
+
2739
+ const section = this.coreFormDesignService.$placeholderSections()[sectionIndex];
2740
+ if (!section.forCalculatedFields && template.type === 'calculated') return;
2741
+ if (!!section.forCalculatedFields && template.type !== 'calculated') return;
2742
+
2743
+ const normalized = this.coreFormDesignService.normalize({
2744
+ ...template,
2745
+ field: this.generateFieldNameFor(template),
2746
+ label: this.generateLabelNameFor(template),
2747
+ value: null
2748
+ });
2749
+
2750
+ if (normalized.controlType === EnumFormBaseContolType.CALCULATED) {
2751
+ normalized.returnType = 'number'
2752
+ }
2753
+
2754
+ this.coreFormDesignService.$placeholderSections.update(sections => {
2755
+ const section = sections[sectionIndex];
2756
+ const row = section?.rows[rowIndex];
2757
+ if (!row || row.cells.length <= colIndex) return sections;
2758
+
2759
+ const usedFlex = row.cells.reduce((sum, cell) => sum + (cell?.control?.flexSize ?? 0), 0);
2760
+ const remainingFlex = 12 - usedFlex;
2761
+ const flexSize = Math.max(1, remainingFlex);
2762
+ normalized.flexSize = flexSize;
2763
+
2764
+ const previous = row.cells[colIndex]?.control;
2765
+
2766
+ if (previous && previous.flexSize !== undefined) {
2767
+
2768
+ // AttachmentFieldHelperService.handleAttachmentOverwrite(
2769
+ // previous as IFormBaseControl,
2770
+ // this.coreFormDesignService.getAllControlsFromSections()
2771
+ // );
2772
+
2773
+ }
2774
+
2775
+ const previousField = row.cells[colIndex]?.control?.field ?? null;
2776
+ this.coreFormDesignService.replaceControl(previousField, normalized);
2777
+
2778
+ // 🔹 INSERT FIRST
2779
+ row.cells[colIndex] = { ...row.cells[colIndex], control: normalized };
2780
+ this.coreFormDesignService.$selectedCell.set(row.cells[colIndex]);
2781
+
2782
+ // 🔹 THEN CALL setup
2783
+ if (AttachmentFieldHelperService.isAttachment(normalized)) {
2784
+ const assignToField = AttachmentFieldHelperService.buildHiddenAssignToField(normalized.field);
2785
+ normalized.field = `${normalized.field}Buffer`
2786
+ normalized.assignTo = assignToField.field;
2787
+ AttachmentFieldHelperService.injectAssignToFieldIntoRow(row, assignToField);
2788
+ }
2789
+
2790
+
2791
+ setTimeout(() => {
2792
+ this.coreFormDesignService.setControlPropDirectly(
2793
+ 'validators',
2794
+ normalized.validators ?? [],
2795
+ normalized
2796
+ );
2797
+ });
2798
+
2799
+ return sections;
2800
+ });
2801
+
2802
+ this.triggerUpdateSections();
2803
+ this.isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex] = false;
2804
+ this.coreFormDesignService.endDrag();
2805
+ this.openSettingsForCell(this.coreFormDesignService.$selectedCell()!, sectionIndex, rowIndex, colIndex)
2806
+ }
2807
+ */
2808
+ this.generateFieldNameFor = this.coreFormDesignService.generateFieldNameFor.bind(this.coreFormDesignService);
2809
+ this.generateLabelNameFor = this.coreFormDesignService.generateLabelNameFor.bind(this.coreFormDesignService);
2810
+ this.getAllControlsFromSections = this.coreFormDesignService.getAllControlsFromSections.bind(this.coreFormDesignService);
2811
+ this.getControl = this.coreFormDesignService.getControl.bind(this.coreFormDesignService);
2812
+ this.filteredCells = this.coreFormDesignService.filteredCells;
2813
+ this.coreFormDesignService.resetFormDesignState();
2814
+ effect(() => {
2815
+ const _ = this.coreFormDesignService.$placeholderSections();
2816
+ this.syncFormDesignWithSections();
2817
+ });
2818
+ effect(() => {
2819
+ this.idStream$.next(this.$id());
2820
+ });
2821
+ this.applicationHelpService.activeKey$.pipe(distinctUntilChanged()).subscribe(x => {
2822
+ switch (x) {
2823
+ case 'F3':
2824
+ this.coreFormDesignService.$fieldSettingPanelOpen.set(true);
2825
+ break;
2826
+ case 'F6':
2827
+ this.coreFormDesignService.$mode.set(EnumFormDesignMode.Preview);
2828
+ break;
2829
+ case 'Escape':
2830
+ this.coreFormDesignService.$fieldSettingPanelOpen.set(false);
2831
+ this.coreFormDesignService.$mode.set(EnumFormDesignMode.Default);
2832
+ break;
2833
+ }
2834
+ });
2835
+ }
2836
+ ngOnInit() {
2837
+ this.subscriptions.push(this.mls.lang$.subscribe(x => this.lang = x));
2838
+ if (this.appConfigService.WORKFLOW_ENABLE_DEBUG_MODE) {
2839
+ this.injectedFields$.next([
2840
+ {
2841
+ field: '___submitterEmployeeId',
2842
+ flexSize: 12,
2843
+ type: 'number',
2844
+ controlType: EnumFormBaseContolType.SEEKER,
2845
+ seekerSourceType: EnumCoreFormControlSeekerSourceType.EMPLOYEE_SEEK,
2846
+ getByIdApi: '',
2847
+ getByIdObject$: new BehaviorSubject({}),
2848
+ label: 'Simulated Requester',
2849
+ boundFrom: 'id',
2850
+ shownFrom: 'fullname',
2851
+ value: null,
2852
+ },
2853
+ {
2854
+ field: "___reason",
2855
+ type: "text",
2856
+ value: '',
2857
+ label: "UI_FORM_CONTROL_LABEL.REASON",
2858
+ flexSize: 12,
2859
+ controlType: EnumFormBaseContolType.TEXTAREA,
2860
+ textareaRows: 5,
2861
+ validators: [
2862
+ {
2863
+ name: 'required',
2864
+ validator: Validators.required,
2865
+ errorMessage: EnumTranslateKey.UI_FORM_CONTROL_ERROR_REQUIRED
2866
+ }
2867
+ ],
2868
+ }
2869
+ ]);
2870
+ }
2871
+ else {
2872
+ this.injectedFields$.next([
2873
+ {
2874
+ field: "___reason",
2875
+ type: "text",
2876
+ value: '',
2877
+ label: "UI_FORM_CONTROL_LABEL.REASON",
2878
+ flexSize: 12,
2879
+ controlType: EnumFormBaseContolType.TEXTAREA,
2880
+ textareaRows: 5,
2881
+ validators: [
2882
+ {
2883
+ name: 'required',
2884
+ validator: Validators.required,
2885
+ errorMessage: EnumTranslateKey.UI_FORM_CONTROL_ERROR_REQUIRED
2886
+ }
2887
+ ],
2888
+ }
2889
+ ]);
2890
+ }
2891
+ }
2892
+ switchJson() {
2893
+ if (this.$jsonMode() === 'full') {
2894
+ this.$jsonMode.set('selectedField');
2895
+ }
2896
+ else {
2897
+ this.$jsonMode.set('full');
2898
+ }
2899
+ }
2900
+ onDragStart(event, control) {
2901
+ this.coreFormDesignService.beginDragTemplate(control);
2902
+ }
2903
+ onDragOver(event, section, control) {
2904
+ event.preventDefault(); // necessary to allow drop
2905
+ if ((!!section.forCalculatedFields && this.coreFormDesignService.$draggingControl()?.type === 'calculated') ||
2906
+ (!section.forCalculatedFields && this.coreFormDesignService.$draggingControl()?.type !== 'calculated')) {
2907
+ event.dataTransfer.dropEffect = 'copy';
2908
+ }
2909
+ else {
2910
+ event.dataTransfer.dropEffect = 'none';
2911
+ }
2912
+ }
2913
+ onDragEnter(placeholderId) {
2914
+ this.isDragOverMap[placeholderId] = true;
2915
+ }
2916
+ onDragLeave(placeholderId) {
2917
+ this.isDragOverMap[placeholderId] = false;
2918
+ }
2919
+ addCalculatedSection() {
2920
+ this.coreFormDesignService.$placeholderSections.update(sections => [
2921
+ {
2922
+ caption: `Calculated Section`,
2923
+ forCalculatedFields: true,
2924
+ hidden: true,
2925
+ rows: [{ cells: [{ flexSize: 12 }] }]
2926
+ },
2927
+ ...sections,
2928
+ ]);
2929
+ }
2930
+ addSection() {
2931
+ this.coreFormDesignService.$placeholderSections.update(sections => [
2932
+ ...sections,
2933
+ {
2934
+ caption: `Section ${sections.length + 1}`,
2935
+ rows: [{ cells: [{ flexSize: 12 }] }]
2936
+ }
2937
+ ]);
2938
+ }
2939
+ deleteSection(sectionIndex) {
2940
+ const sections = this.coreFormDesignService.$placeholderSections();
2941
+ const section = sections[sectionIndex];
2942
+ const hasControls = section?.rows?.some(row => row?.cells?.some(cell => !!cell?.control));
2943
+ if (hasControls) {
2944
+ const confirmed = confirm('This section contains controls. Are you sure you want to delete it?');
2945
+ if (!confirmed)
2946
+ return;
2947
+ }
2948
+ this.coreFormDesignService.$placeholderSections.update(prev => prev.filter((_, idx) => idx !== sectionIndex));
2949
+ }
2950
+ deleteRow(sectionIndex, rowIndex) {
2951
+ const sections = this.coreFormDesignService.$placeholderSections();
2952
+ const section = sections[sectionIndex];
2953
+ const row = section?.rows?.[rowIndex];
2954
+ if (!row)
2955
+ return; // safety check
2956
+ const hasControls = row.cells?.some(cell => !!cell?.control);
2957
+ if (hasControls) {
2958
+ const confirmed = confirm('This row contains controls. Are you sure you want to delete it?');
2959
+ if (!confirmed)
2960
+ return; // user canceled
2961
+ }
2962
+ this.coreFormDesignService.$placeholderSections.update(sections => {
2963
+ return sections.map((section, sIdx) => {
2964
+ if (sIdx !== sectionIndex)
2965
+ return section;
2966
+ return {
2967
+ ...section,
2968
+ rows: (section.rows ?? []).filter((_, rIdx) => rIdx !== rowIndex)
2969
+ };
2970
+ });
2971
+ });
2972
+ }
2973
+ addRow(sectionIndex) {
2974
+ this.coreFormDesignService.$placeholderSections.update(sections => {
2975
+ const section = sections[sectionIndex];
2976
+ if (section) {
2977
+ section.rows.push({ cells: [{ flexSize: 12 }] });
2978
+ }
2979
+ return sections;
2980
+ });
2981
+ }
2982
+ addColumn(row) {
2983
+ if (!row || row.cells.length >= 4)
2984
+ return;
2985
+ const usedFlex = row.cells.reduce((sum, c) => sum + (c.flexSize ?? 0), 0);
2986
+ // ✅ Case 1: Normal case – still space available
2987
+ if (usedFlex < 12) {
2988
+ const remaining = 12 - usedFlex;
2989
+ row.cells.push({ flexSize: Math.min(3, remaining) });
2990
+ return;
2991
+ }
2992
+ // 💥 Case 2: Full row — try to rebalance
2993
+ if (usedFlex === 12) {
2994
+ const count = row.cells.length;
2995
+ if (count === 1) {
2996
+ // 12 → 6 + 6
2997
+ row.cells[0].flexSize = 6;
2998
+ row.cells.push({ flexSize: 6 });
2999
+ return;
3000
+ }
3001
+ if (count === 2) {
3002
+ // 6 + 6 → 4 + 4 + 4
3003
+ row.cells.forEach(c => (c.flexSize = 4));
3004
+ row.cells.push({ flexSize: 4 });
3005
+ return;
3006
+ }
3007
+ if (count === 3) {
3008
+ // 4 + 4 + 4 → 3 + 3 + 3 + 3
3009
+ row.cells.forEach(c => (c.flexSize = 3));
3010
+ row.cells.push({ flexSize: 3 });
3011
+ return;
3012
+ }
3013
+ // ❌ Already 4 cells, each 3 — can’t split further
3014
+ return;
3015
+ }
3016
+ // 🔧 Optional fallback logic for unknown edge cases
3017
+ const maxIndex = row.cells.reduce((maxI, c, i, arr) => (c.flexSize ?? 0) > (arr[maxI]?.flexSize ?? 0) ? i : maxI, 0);
3018
+ const maxCell = row.cells[maxIndex];
3019
+ if ((maxCell?.flexSize ?? 0) <= 3)
3020
+ return; // nothing to shrink
3021
+ maxCell.flexSize -= 3;
3022
+ row.cells.push({ flexSize: 3 });
3023
+ }
3024
+ onCorePageHeaderButtonClicked(e) {
3025
+ if (e.code === EnumCoreButtonVNSCode.HEADER_SWITCH_VIEW) {
3026
+ if (this.coreFormDesignService.$mode() === EnumFormDesignMode.Default) {
3027
+ const sections = this.coreFormDesignService.toCoreFormSections(this.coreFormDesignService.$placeholderSections());
3028
+ this.coreFormDesignService.$liveFormSections.set(sections);
3029
+ }
3030
+ setTimeout(() => this.coreFormDesignService.$mode.set(this.coreFormDesignService.$mode() === EnumFormDesignMode.Preview ? EnumFormDesignMode.Default : EnumFormDesignMode.Preview));
3031
+ }
3032
+ else if (e.code === EnumCoreButtonVNSCode.HEADER_SAVE) {
3033
+ }
3034
+ }
3035
+ closePreview() {
3036
+ this.coreFormDesignService.$mode.set(EnumFormDesignMode.Default);
3037
+ }
3038
+ onPreviewSubmit(e) {
3039
+ alert(JSON.stringify(e, null, 2));
3040
+ }
3041
+ onCellClicked(sectionIndex, rowIndex, colIndex) {
3042
+ const row = this.coreFormDesignService.$placeholderSections()[sectionIndex].rows[rowIndex];
3043
+ if (!!row) {
3044
+ // Toggle selection
3045
+ if (!!row.cells && row.cells.length > colIndex) {
3046
+ row.cells[colIndex].selected = !row.cells[colIndex].selected;
3047
+ }
3048
+ // Only allow max 2 selections
3049
+ const selected = row.cells.filter(c => c?.selected);
3050
+ if (selected.length > 2) {
3051
+ row.cells.forEach(c => c && (c.selected = false));
3052
+ row[colIndex].selected = true;
3053
+ }
3054
+ }
3055
+ }
3056
+ canMergeCells(sectionIndex, rowIndex) {
3057
+ const row = this.coreFormDesignService.$placeholderSections()[sectionIndex].rows[rowIndex];
3058
+ const selected = row?.cells.map((c, i) => ({ c, i })).filter(x => x.c?.selected);
3059
+ if (selected?.length !== 2)
3060
+ return false;
3061
+ const [a, b] = selected;
3062
+ if (a.c.control || b.c.control)
3063
+ return false;
3064
+ return Math.abs(a.i - b.i) === 1; // Must be neighbors
3065
+ }
3066
+ mergeCells(sectionIndex, rowIndex) {
3067
+ const row = this.coreFormDesignService.$placeholderSections()[sectionIndex].rows[rowIndex];
3068
+ if (!row)
3069
+ return;
3070
+ this.coreFormDesignService.$placeholderSections.update(sections => {
3071
+ const selected = row.cells
3072
+ .map((c, i) => ({ c, i }))
3073
+ .filter(x => x.c?.selected);
3074
+ if (selected.length !== 2)
3075
+ return sections;
3076
+ const [a, b] = selected.sort((a, b) => a.i - b.i);
3077
+ const mergedFlex = (typeof a.c.flexSize === 'number' ? a.c.flexSize : 3) +
3078
+ (typeof b.c.flexSize === 'number' ? b.c.flexSize : 3);
3079
+ const mergedCell = {
3080
+ //control: { ...a.c.control, flexSize: mergedFlex }, // keep control data
3081
+ flexSize: mergedFlex,
3082
+ selected: false
3083
+ };
3084
+ row.cells.splice(a.i, 2, mergedCell); // replace both cells with one
3085
+ return sections;
3086
+ });
3087
+ }
3088
+ openSettingsForCell(cell, sectionIndex, rowIndex, colIndex) {
3089
+ this.coreFormDesignService.$sectionIndex.set(sectionIndex);
3090
+ this.coreFormDesignService.$rowIndex.set(rowIndex);
3091
+ this.coreFormDesignService.$colIndex.set(colIndex);
3092
+ this.coreFormDesignService.$selectedCell.set({ ...cell });
3093
+ this.coreFormDesignService.$fieldSettingPanelOpen.set(true);
3094
+ }
3095
+ deleteField(row, sectionIndex, rowIndex, colIndex) {
3096
+ if (!row)
3097
+ return;
3098
+ const dCell = row.cells[colIndex];
3099
+ const currentControl = dCell.control;
3100
+ if (!currentControl)
3101
+ return;
3102
+ const currentPlaceholderSections = this.coreFormDesignService.$placeholderSections();
3103
+ if (!currentPlaceholderSections[sectionIndex].rows[rowIndex])
3104
+ return;
3105
+ currentPlaceholderSections[sectionIndex].rows[rowIndex].cells[colIndex].control = undefined;
3106
+ this.coreFormDesignService.$selectedCell.set(null);
3107
+ this.coreFormDesignService.$placeholderSections.set([...currentPlaceholderSections]);
3108
+ }
3109
+ onCaptionEditEnd(index, event) {
3110
+ const newCaption = event.target.innerText.trim();
3111
+ this.coreFormDesignService.$placeholderSections.update(sections => {
3112
+ sections[index].caption = newCaption;
3113
+ return sections;
3114
+ });
3115
+ }
3116
+ onFieldCaptionEditEnd(cell, event) {
3117
+ const element = event.target;
3118
+ const newLabel = element.innerText.trim();
3119
+ // Fallback if empty
3120
+ cell.control.label = newLabel || 'Unnamed Field';
3121
+ this.triggerUpdateSections();
3122
+ }
3123
+ insertSection() {
3124
+ }
3125
+ insertRow(sectionIndex, rowIndex) {
3126
+ const sections = this.coreFormDesignService.$placeholderSections();
3127
+ const section = sections[sectionIndex];
3128
+ if (!section)
3129
+ return;
3130
+ const newRow = {
3131
+ cells: [
3132
+ { flexSize: 12 },
3133
+ ]
3134
+ };
3135
+ section.rows.splice(rowIndex + 1, 0, newRow);
3136
+ this.coreFormDesignService.$placeholderSections.set([...sections]);
3137
+ }
3138
+ closeFieldSettingPanel() {
3139
+ this.coreFormDesignService.$fieldSettingPanelOpen.set(false);
3140
+ this.coreFormDesignService.$selectedCell.set(null);
3141
+ this.coreFormDesignService.$currentControlTemplate.set(null);
3142
+ this.coreFormDesignService.$currentControl.set(null);
3143
+ }
3144
+ ngAfterViewInit() {
3145
+ setTimeout(() => {
3146
+ this.subscriptions.push(this.getByIdStream$.subscribe(x => {
3147
+ this.$loading.set(false);
3148
+ if (x.ok && x.status === 200 && x.body?.statusCode === 200) {
3149
+ this.coreFormDesignService.$afInstance.set(this.coreFormDesignService.mapFromAfInstanceDTO(x.body.innerBody));
3150
+ this.coreFormDesignService.syncPlaceholderSectionsFromInstance();
3151
+ this.coreFormDesignService.$shouldPatchMetadataForm.set(true);
3152
+ const saveLiveJson = this.coreFormDesignService.$saveLiveJson();
3153
+ setTimeout(() => this.wfs.$initialFormDesignJson.set(saveLiveJson));
3154
+ }
3155
+ }));
3156
+ if (!this.$idAsInput()) {
3157
+ this.subscriptions.push(this.route.params.subscribe(x => {
3158
+ let id = '0';
3159
+ try {
3160
+ id = atob(x['id']);
3161
+ this.coreFormDesignService.$afInstance.update(instance => ({
3162
+ ...instance,
3163
+ id
3164
+ }));
3165
+ }
3166
+ catch (err) {
3167
+ if (isDevMode()) {
3168
+ this.alertService.error(err.toString(), noneAutoClosedAlertOptions);
3169
+ }
3170
+ return;
3171
+ }
3172
+ this.idStream$.next(id);
3173
+ }));
3174
+ }
3175
+ console.warn('InitialFormDesignJson on load', this.wfs.$initialFormDesignJson());
3176
+ });
3177
+ }
3178
+ onControlParamsChange(updated) {
3179
+ this.coreFormDesignService.$placeholderSections.update(sections => {
3180
+ const cell = this.coreFormDesignService.$selectedCell();
3181
+ if (!cell)
3182
+ return sections;
3183
+ // Patch the selected cell
3184
+ Object.assign(cell.control, updated);
3185
+ return sections;
3186
+ });
3187
+ }
3188
+ get normalizedSelectedControl() {
3189
+ const cell = this.coreFormDesignService.$selectedCell();
3190
+ if (!cell?.control) {
3191
+ throw new Error('No control is currently selected.');
3192
+ }
3193
+ return this.coreFormDesignService.normalize(cell.control);
3194
+ }
3195
+ triggerUpdateSections() {
3196
+ const newValue = this.coreFormDesignService.$placeholderSections();
3197
+ this.coreFormDesignService.$placeholderSections.set([...newValue]);
3198
+ }
3199
+ syncFormDesignWithSections() {
3200
+ const existingControls = Object.keys(this.formDesign.controls);
3201
+ const expectedControls = [];
3202
+ for (const section of this.coreFormDesignService.$placeholderSections()) {
3203
+ for (const row of section.rows) {
3204
+ for (const cell of row?.cells || []) {
3205
+ const control = cell?.control;
3206
+ if (control?.field) {
3207
+ expectedControls.push(control.field);
3208
+ if (!this.formDesign.contains(control.field)) {
3209
+ this.formDesign.addControl(control.field, new FormControl(control.value ?? null));
3210
+ }
3211
+ }
3212
+ }
3213
+ }
3214
+ }
3215
+ // 🧹 Remove controls that no longer exist
3216
+ for (const field of existingControls) {
3217
+ if (!expectedControls.includes(field)) {
3218
+ this.formDesign.removeControl(field);
3219
+ }
3220
+ }
3221
+ }
3222
+ isRequired(control) {
3223
+ if (!control || !control.validators)
3224
+ return false;
3225
+ return control.validators.some((v) => v.name === 'required' || v.name === 'requiredTrue');
2385
3226
  }
2386
3227
  onFormDesignCreated(e) {
2387
3228
  console.log("onFormDesignCreated", e);
@@ -2393,7 +3234,7 @@ class CoreFormDesignComponent extends BaseComponent {
2393
3234
  this.coreFormDesignService.$showFormMetadata.set(true);
2394
3235
  }
2395
3236
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CoreFormDesignComponent, deps: [{ token: MultiLanguageService }], target: i0.ɵɵFactoryTarget.Component }); }
2396
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.5", type: CoreFormDesignComponent, isStandalone: true, selector: "core-form-design", inputs: { $idAsInput: { classPropertyName: "$idAsInput", publicName: "$idAsInput", isSignal: true, isRequired: false, transformFunction: null }, $id: { classPropertyName: "$id", publicName: "$id", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "$settingPanel", first: true, predicate: ["settingPanel"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"core-form-design-container fs-13\" [hotKeys]=\"['F3', 'F6', 'Escape']\">\r\n\r\n <core-page-header title=\"UI.COMPONENT_TITLE.WORKFLOW_FORM_DESIGN\" (buttonClick)=\"onCorePageHeaderButtonClicked($event)\"></core-page-header>\r\n\r\n <ng-template #formMetadata>\r\n <form-metadata></form-metadata>\r\n </ng-template>\r\n\r\n @if (coreFormDesignService.$showFormArrayDesign()) {\r\n <core-form-array-layout-editor />\r\n }\r\n\r\n @if (!coreFormDesignService.$isInWorkflowDesign()) {\r\n <aside class=\"af-metadata-overlay\" [@slideFromTopFadeIn]=\"coreFormDesignService.$showFormMetadata() ? 'in' : 'out'\"\r\n [class.shown]=\"coreFormDesignService.$showFormMetadata()\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"formMetadata\"></ng-container>\r\n </aside>\r\n }\r\n\r\n <div \r\n class=\"field-setting-panel\" \r\n [class.open]=\"coreFormDesignService.$fieldSettingPanelOpen()\" \r\n [class.calculated-type]=\"coreFormDesignService.$selectedCell()?.control?.type==='calculated'\"\r\n [ngStyle]=\"{ zIndex: $zIndex() }\"\r\n #settingPanel\r\n >\r\n @if (!!(this.coreFormDesignService.$selectedCell())) {\r\n <field-setting></field-setting>\r\n }\r\n </div>\r\n\r\n <div class=\"form-design-left\">\r\n\r\n @switch ($leftPanelMode()) {\r\n @case (enumLeftPanelMode.FieldCollection) {\r\n @for (category of controlCategories; track $index) {\r\n <div class=\"category-name\">\r\n {{ category.name }}\r\n </div>\r\n <ul>\r\n @for (control of category.controls; track $index) {\r\n <li draggable=\"true\" (dragstart)=\"onDragStart($event, control)\" [class.full-width]=\"control.controlType === 'SEEKER' || control.controlType === 'ATTACHMENT' || control.controlType === 'GRIDBUFFER'\">\r\n @if (control.controlType === 'GRIDBUFFER') {\r\n <div class=\"grid-buffer-wrapper\">\r\n <core-control [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\"></core-control>\r\n </div>\r\n } @else {\r\n <core-control [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\"></core-control>\r\n }\r\n </li>\r\n <div class=\"space\"></div>\r\n }\r\n </ul>\r\n }\r\n }\r\n @case (enumLeftPanelMode.Json) {\r\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"switchJson()\">{{ $jsonMode() }}</button>\r\n @if ($jsonMode()==='selectedField') {\r\n <pre class=\"json-preview\">{{ coreFormDesignService.$currentControlJson() }}</pre>\r\n } @else {\r\n <pre class=\"json-preview\">{{ coreFormDesignService.$saveLiveJson() }}</pre>\r\n }\r\n \r\n }\r\n }\r\n\r\n </div>\r\n\r\n <div class=\"form-design-right\">\r\n <!-- <pre>{{ $injectedFieldsJson() }}</pre> -->\r\n\r\n @if (coreFormDesignService.$mode() === enumType.Default) {\r\n <div class=\"form-wrapper\">\r\n\r\n @if (!!coreFormDesignService.$isInWorkflowDesign()) {\r\n <form-metadata></form-metadata>\r\n }\r\n\r\n <form [formGroup]=\"formDesign\" autocomplete=\"off\">\r\n <div class=\"form-cells\">\r\n\r\n <div class=\"form-tool-bar\">\r\n @if (!$hasCalculatedSection()) {\r\n <button class=\"core-button-vns-container\" (click)=\"addCalculatedSection()\">+ Calculated fields</button>\r\n }\r\n <button class=\"core-button-vns-container\" (click)=\"addSection()\">+ Add Section</button>\r\n </div>\r\n \r\n @for (section of coreFormDesignService.$placeholderSections(); track $index; let sectionIndex = $index) {\r\n <div class=\"form-section-placeholder\">\r\n\r\n <div class=\"section-header\">\r\n\r\n <div class=\"section-img-wrapper\">\r\n <div class=\"section-img\" [class.calculated]=\"section.forCalculatedFields\"></div>\r\n </div>\r\n\r\n <label [attr.contenteditable]=\"!section.forCalculatedFields\"\r\n [htmlTooltip]=\"!!section.forCalculatedFields ? calculatedFieldsTooltip : null\"\r\n (blur)=\"onCaptionEditEnd(sectionIndex, $event)\"\r\n (keydown.enter)=\"onCaptionEditEnd(sectionIndex, $event); $event.preventDefault()\"\r\n >{{ section.caption }}</label>\r\n\r\n <div class=\"section-tool pointer\" (click)=\"deleteSection(sectionIndex)\" [appTooltip]=\"'Delete section'\" [showAnyway]=\"true\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n \r\n </div>\r\n \r\n @for (row of section.rows; track $index; let rowIndex = $index) {\r\n\r\n <div class=\"form-row-wrapper\">\r\n <div class=\"form-row\">\r\n @for (cell of filteredCells(row); track $index; let colIndex = $index) {\r\n <div class=\"form-cell drop-target\" \r\n [ngStyle]=\"{ flex: (cell.flexSize ?? 0) + ' 1 0%' }\"\r\n [attr.data-flex]=\"cell.flexSize ?? 0\"\r\n (drop)=\"onDropIntoCell($event, sectionIndex, rowIndex, colIndex)\"\r\n (dragover)=\"onDragOver($event, section, cell.control!)\"\r\n (dragenter)=\"onDragEnter(sectionIndex + '_' + rowIndex + '_' + colIndex)\"\r\n (dragleave)=\"onDragLeave(sectionIndex + '_' + rowIndex + '_' + colIndex)\"\r\n [class.selected]=\"cell?.selected\"\r\n [class.dragging-over]=\"isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex]\"\r\n [class.has-control]=\"!!cell && !!cell.control && !!getControl(cell)\"\r\n (click)=\"onCellClicked(sectionIndex, rowIndex, colIndex)\"\r\n >\r\n\r\n\r\n @if (!isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex]) {\r\n\r\n @if (!!cell && !!cell.control && !!getControl(cell)) {\r\n <label contenteditable=\"true\"\r\n (blur)=\"onFieldCaptionEditEnd(cell, $event)\"\r\n (keydown.enter)=\"onFieldCaptionEditEnd(cell, $event); $event.preventDefault()\"\r\n [class.d-none]=\"!!getControl(cell)?.hidden\"\r\n [class.required]=\"!!cell && !!cell.control && !!getControl(cell) && isRequired(getControl(cell))\"\r\n >{{ cell.control.label || 'label' }}</label>\r\n\r\n @if (cell.control.controlType==='CALCULATED') {\r\n <div class=\"control-wrapper\" (click)=\"openSettingsForCell(cell, sectionIndex, rowIndex, colIndex)\">\r\n <core-control \r\n [control]=\"getControl(cell)!\" \r\n [form]=\"formDesign\"\r\n [checkError$]=\"checkError$\" />\r\n </div>\r\n } @else {\r\n <core-control \r\n [control]=\"getControl(cell)!\" \r\n [form]=\"formDesign\"\r\n [checkError$]=\"checkError$\" />\r\n }\r\n \r\n <div class=\"field-toolbar\">\r\n <ul>\r\n <li>\r\n <div class=\"field-tool pointer\" (click)=\"openSettingsForCell(cell, sectionIndex, rowIndex, colIndex)\" [appTooltip]=\"'Show settings'\">\r\n <i class=\"feather-settings\"></i>\r\n </div>\r\n </li>\r\n <li>\r\n <div class=\"field-tool pointer\" (click)=\"deleteField(row, sectionIndex, rowIndex, colIndex)\" [appTooltip]=\"'Remove field from cell'\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n \r\n } @else {\r\n <div class=\"placeholder\" [class.calculated]=\"!!section.forCalculatedFields\">\r\n {{ !!section.forCalculatedFields ? 'Drop calculated field here' : 'Drop here'}}\r\n </div>\r\n }\r\n\r\n @if (cell?.selected && canMergeCells(sectionIndex, rowIndex)) {\r\n <div class=\"merge-toolbar\">\r\n <button (click)=\"mergeCells(sectionIndex, rowIndex)\">\uD83D\uDD17 Merge</button>\r\n </div>\r\n }\r\n \r\n }\r\n\r\n </div>\r\n }\r\n </div>\r\n <div class=\"row-tool-bar\">\r\n <div class=\"icon-wrapper\" (click)=\"deleteRow(sectionIndex, rowIndex)\" [appTooltip]=\"'Delete row'\" [showAnyway]=\"true\"><i class=\"feather-x\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"addRow(sectionIndex)\" [appTooltip]=\"'Add row'\" [showAnyway]=\"true\"><i class=\"feather-arrow-down\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"insertRow(sectionIndex, rowIndex)\" [appTooltip]=\"'Insert row'\" [showAnyway]=\"true\"><i class=\"feather-corner-right-down\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"addColumn(row)\" [appTooltip]=\"'Add column'\" [showAnyway]=\"true\"><i class=\"feather-arrow-right\"></i></div>\r\n </div>\r\n </div>\r\n\r\n }\r\n </div>\r\n }\r\n \r\n \r\n </div>\r\n </form>\r\n </div>\r\n } @else if (!!$sections()) {\r\n\r\n @if(!!(injectedFields$ | async) && !!(injectedFields$ | async)!.length) {\r\n\r\n @if (!!coreFormDesignService.$afInstance().normalMode) {\r\n <live-form [$designMode]=\"true\" [$forKickOff]=\"true\" />\r\n } @else {\r\n <live-form [$designMode]=\"true\" [$forKickOff]=\"true\" ($onClose)=\"closePreview()\" />\r\n }\r\n\r\n } @else {\r\n <h2>COULD NOT UPDATE injectedFields$</h2>\r\n }\r\n\r\n } @else {\r\n <h2>$sections() empty / null / undefined</h2>\r\n }\r\n\r\n\r\n \r\n </div>\r\n @if ($loading()) {\r\n <core-toast-loading></core-toast-loading>\r\n }\r\n\r\n <ng-template #calculatedFieldsTooltip>\r\n <div style=\"max-width: 280px;\">\r\n <strong>Calculated Fields</strong><br />\r\n <p></p>\r\n These fields are hidden from the form and cannot be edited directly.<br /><br />\r\n - They are computed automatically during workflow execution.<br />\r\n - Each field depends on one or more standard input fields.<br />\r\n - The calculation is evaluated using either an SQL query engine (like <strong>Dapper</strong>) or an in-memory expression engine (like <strong>Dynamic Expresso</strong>).<br /><br />\r\n In both cases, the result is a <code>0</code> or <code>1</code>, representing <strong>false</strong> or <strong>true</strong>.<br /><br />\r\n These results can be used to influence workflow logic, rule trees, or approval paths.\r\n </div>\r\n </ng-template>\r\n \r\n</div>", styles: ["@charset \"UTF-8\";.core-form-design-container{position:relative;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));width:100%;overflow:hidden;background-color:#eff0f1;font-size:13px}.core-form-design-container .core-button-vns-container{margin-right:8px!important}.core-form-design-container .core-button-vns-container:last-child{background-color:#000;color:#fff;margin-right:0}.core-form-design-container .af-metadata-overlay{position:fixed;top:60px;left:66px;background:#fff;box-shadow:.4rem 0 2rem #0000002e;z-index:1000;width:1214px;height:calc(100vh - 75px);overflow-y:auto;pointer-events:none}.core-form-design-container .af-metadata-overlay.shown{pointer-events:auto}.core-form-design-container *{border-radius:0}.core-form-design-container ul,.core-form-design-container li{padding:0}.core-form-design-container li{max-width:200px}.core-form-design-container ul div.space{display:block;height:15px}.core-form-design-container li.full-width{max-width:100%}.core-form-design-container .field-setting-panel{display:block;position:fixed;width:360px;height:100vh;top:0;right:-360px;background-color:#fff;box-shadow:.4rem 0 2rem #0000002e;transition:right .5s ease-out}.core-form-design-container .field-setting-panel .close-wrapper{width:32px;height:32px;position:absolute;top:15px;right:15px;display:flex;background-color:#848484;border-radius:50%}.core-form-design-container .field-setting-panel .close-wrapper i{width:16px;height:16px;font-size:18px;color:#848484}.core-form-design-container .field-setting-panel .panel-caption{margin-bottom:1rem;padding-bottom:.5rem;border-bottom:1px solid #ddd;width:100%;overflow:hidden;text-wrap:nowrap;text-overflow:ellipsis}.core-form-design-container .field-setting-panel.calculated-type{width:500px;right:-500px}.core-form-design-container .field-setting-panel.calculated-type textarea{border-radius:8px;height:150px}.core-form-design-container .field-setting-panel.open{right:0}.core-form-design-container .form-design-left{position:absolute;top:var(--size-core-page-header-height);bottom:0;left:0;z-index:1;width:360px;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));padding:15px;padding-right:calc(15px + var(--size-scrollbar-width));background-color:#87ceeb;overflow-y:hidden}.core-form-design-container .form-design-left .category-name{color:#fff}.core-form-design-container .form-design-left .grid-buffer-wrapper{background-color:#fff;padding:15px}.core-form-design-container .form-design-left ul:last-child{padding-bottom:400px}.core-form-design-container .form-design-left .category-name{margin-bottom:15px}.core-form-design-container .form-design-left .json-preview{background-color:#fff;color:#333;padding:1rem 1.5rem;box-shadow:0 2px 6px #00000014;font-family:Fira Code,monospace;font-size:.85rem;word-break:keep-all;overflow-x:auto;line-height:1.5;width:330px;height:calc(100vh - 205px)}.core-form-design-container .form-design-left button{height:35px;border-radius:0;margin-bottom:15px;color:#fff;border:none;font-size:13px;background-color:transparent}.core-form-design-container .form-design-left:hover{overflow-y:auto;padding-right:15px}.core-form-design-container .form-design-right{width:100%;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));padding:15px 15px 15px 375px;overflow-y:auto}.core-form-design-container .form-design-right .form-wrapper{width:100%;overflow-y:visible;background-color:#fff}.core-form-design-container .form-design-right .form-wrapper button{margin-left:12px;padding:4px 10px;border:1px solid #ccc;cursor:pointer;transition:all .2s;width:110px}.core-form-design-container .form-design-right .form-wrapper button:hover{background-color:#e4f0ff;border-color:#007bff;color:#007bff}.core-form-design-container .form-design-right .form-wrapper .form-tool-bar{display:flex;align-items:center;justify-content:flex-end}.core-form-design-container .form-design-right .form-wrapper .form-tool-bar>button{width:150px;margin:0}.core-form-design-container .form-design-right .form-wrapper .form-cells{display:flex;flex-direction:column;gap:32px;padding:20px 15px 15px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder{padding:12px 15px;border:1px dashed #ccc;background-color:#fff;box-shadow:0 2px 6px #0000000a}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header{display:flex;position:relative;align-items:center;justify-content:flex-start;font-weight:600;margin-bottom:12px;color:#333}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-img{width:34px;height:34px;border-radius:50%;background-color:#d3d3d3;float:left;background-image:url(/assets/images/info.svg);background-repeat:no-repeat;background-position:center;margin-right:8px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-img.calculated{background-image:url(/assets/images/sql-icon.svg);background-color:transparent;border-radius:0}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-tool{position:absolute;right:5px;top:6px;display:none;z-index:2;color:gray}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-tool i{font-size:24px;color:#848484}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header:hover .section-tool{display:block}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .row-tool-bar{display:flex;align-items:center;justify-content:flex-end;margin-bottom:8px;height:24px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-row{display:flex;gap:15px;margin-bottom:15px;min-height:50px;background-color:#d3d3d3;padding:8px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell{flex:1;min-height:90px;background-color:#fcfcfc;border:1px dashed #ccc;position:relative;padding:20px 10px 10px;transition:border .2s ease-in-out}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell:before{content:attr(data-flex);position:absolute;top:2px;left:4px;font-size:10px;color:#999}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell label.required:after{content:\" *\";color:#ff040b}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar{position:absolute;right:7px;top:6px;display:none;z-index:2;color:gray}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul{display:flex}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul li div{display:flex;width:24px;height:24px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul li div i{font-size:18px;width:18px;height:18px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell.has-control:hover .field-toolbar{display:flex}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell.active-drop{border-color:#007bff;background-color:#eef6ff;transition:.2s}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .placeholder{display:flex;align-items:center;justify-content:center;background-color:#fff;color:#007bff;padding:15px 0;width:100%;cursor:default}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .placeholder.calculated{color:#ff4500}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .icon-wrapper{width:24px;height:24px;border-radius:50%;padding:0;cursor:pointer;display:none;color:gray;border:1px solid gray;margin-left:8px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .icon-wrapper i{font-size:18px;width:18px;height:18px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper:hover .icon-wrapper{display:flex}.core-form-design-container .form-design-right .form-wrapper .form-cell.selected{background-color:#dff6dd}.core-form-design-container .form-design-right .form-wrapper .merge-toolbar{text-align:center;margin-top:4px}.core-form-design-container .form-design-right .form-wrapper.live-form{padding-bottom:15px}.core-form-design-container .form-design-right .form-wrapper.live-form .live-form-header{padding:0 15px}.core-form-design-container .form-design-right .form-wrapper.live-form .live-form-header .preview-close-icon{position:absolute;right:7px;top:6px;z-index:2;color:gray;cursor:pointer}.core-form-design-container .form-design-right .form-wrapper.live-form .live-form-header .preview-close-icon i{font-size:18px}.core-form-design-container .drop-target{min-height:50px;min-width:50px;border:2px dashed transparent;transition:border .2s ease}.core-form-design-container .drop-target.active-drop{border-color:#007bff;background-color:#eaf4ff}.core-form-design-container .no-padding{padding:0!important}.core-form-design-container .modal-content-root{overflow:visible}\n", ".core-form-container{overflow-x:visible}.core-form-container>form .section{margin-top:var(--size-layout-block-cell-spacing)}.core-form-container>form .section:not(:first-child){margin-top:calc(var(--size-layout-block-cell-spacing) * 2)}.core-form-container>form .section .section-header-label{display:block;height:34px;line-height:34px;margin-bottom:15px;margin-left:12px}.core-form-container>form .section .section-header-label .section-img-wrapper{position:relative}.core-form-container>form .section .section-header-label .section-img-wrapper .section-img{position:absolute;width:34px;height:34px;border-radius:50%;background-color:#d3d3d3;float:left;background-image:url(/assets/images/info.svg);background-repeat:no-repeat;background-position:center}.core-form-container>form .section .section-header-label .section-img-wrapper .section-img.calculated{background-image:url(/assets/images/sql-icon.svg);border-radius:0;background-color:transparent}.core-form-container>form .section .section-header-label .section-calc-wrapper{width:34px;height:34px;display:flex;align-items:center;justify-content:center;background-color:#d3d3d3;border-radius:50%}.core-form-container>form .section .section-header-label .section-calc-wrapper i{width:24px;height:24px;font-size:24px;color:#1b4332}.core-form-container>form .section .section-header-label .section-caption{padding-left:40px;font-weight:700;color:#696969}.core-form-container .row{margin-left:var(--size-layout-block-cell-spacing) 0px;margin-right:var(--size-layout-block-cell-spacing) 0px}.core-form-container .row .grid-buffer{border:dotted 2px darkgray}.core-form-container .row .button-control{display:flex;align-items:flex-end}.core-form-container .form-row{margin:var(--size-layout-block-cell-spacing) 0px;display:flex;align-items:center;justify-content:center}.core-form-container .form-row>button{cursor:pointer;border-radius:0}.core-form-container .form-row>button:not(:first-child){margin-left:var(--size-layout-block-cell-spacing)}.core-form-container .dev-button{cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:13px;padding:8px;width:120px;border-radius:18px;box-shadow:.4rem 0 2rem #0000002e}.core-form-container .dev-button:not(:last-child){margin-right:15px}.core-form-container .dev-button:first-child{background-color:#dff6dd;border:1px #9fdc9d solid}.core-form-container .dev-button:last-child{background-color:#fff4ce;border:1px #ffda6a solid}.core-form-container .payload-preview{display:block;width:calc(100% - 48px);height:200px;white-space:pre-wrap;overflow-x:hidden;overflow-y:auto;background-color:#dff6dd;padding:24px;margin:24px;text-indent:-58px;color:#333!important;font-family:Fira Code,monospace;font-size:.85rem;word-break:keep-all;line-height:1.5}.core-form-container .payload-preview.validator-preview{background-color:#fff4ce}.core-form-container .bottom-template-wrapper{padding-left:12px;padding-right:12px}.core-form-container .w-100{width:100%}.core-form-container .pr18{padding-right:18px}\n", ".core-button-vns-container{height:30px;display:flex;align-items:center;justify-content:center;min-width:30px}.core-button-vns-container .action-wrapper{height:30px!important;width:30px!important;display:flex;align-items:center;justify-content:center}.core-button-vns-container .action-wrapper:has(i:hover){background-color:#e7e7e7;border-radius:50%}.core-button-vns-container .btn-for-form{border:none;border-radius:0;background-color:transparent;color:#000;min-width:120px}.core-button-vns-container button.last-child{background-color:#000;color:#fff}.core-button-vns-container .action-wrapper.last-child{background-color:var(--color-basic-orange);color:#fff;border-radius:50%}.core-button-vns-container .action-wrapper.last-child:hover{background-color:var(--color-basic-orange);box-shadow:0 1rem 3rem #0000002e}.core-button-vns-container .temporary-unavailable{user-select:none;-moz-user-select:none;-webkit-user-select:none;cursor:not-allowed!important;opacity:.5}.core-button-vns-container .temporary-unavailable:hover{background-color:transparent!important}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CoreFormArrayLayoutEditorComponent, selector: "core-form-array-layout-editor" }, { kind: "component", type: CoreToastLoadingComponent, selector: "core-toast-loading" }, { kind: "component", type: CorePageHeaderComponent, selector: "core-page-header", inputs: ["instanceNumber", "shownItems", "title", "hideButtonGroup", "htmlTooltipRef"], outputs: ["buttonClick"] }, { kind: "component", type: FormMetadataComponent, selector: "form-metadata" }, { 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: "directive", type: TooltipDirective, selector: "[appTooltip]", inputs: ["color", "backgroundColor", "appTooltip", "showAnyway", "position"] }, { kind: "directive", type: HotKeysDirective, selector: "[hotKeys]", inputs: ["hotKeys"] }, { kind: "component", type: CoreControlComponent, selector: "core-control", inputs: ["control", "form", "checkError$", "rangeLimit"] }, { kind: "component", type: FieldSettingComponent, selector: "field-setting" }, { kind: "component", type: LiveFormComponent, selector: "live-form", inputs: ["$designMode", "$forKickOff", "$workflowReactContext"], outputs: ["$onClose"] }, { kind: "directive", type: HtmlTooltipDirective, selector: "[htmlTooltip]", inputs: ["htmlTooltip", "tooltipContext", "maxWidthUnset", "backgroundColor"] }], animations: [slideFromTopFadeIn], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3237
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.5", type: CoreFormDesignComponent, isStandalone: true, selector: "core-form-design", inputs: { $idAsInput: { classPropertyName: "$idAsInput", publicName: "$idAsInput", isSignal: true, isRequired: false, transformFunction: null }, $id: { classPropertyName: "$id", publicName: "$id", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "$settingPanel", first: true, predicate: ["settingPanel"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"core-form-design-container fs-13\" [hotKeys]=\"['F3', 'F6', 'Escape']\">\r\n\r\n <core-page-header title=\"UI.COMPONENT_TITLE.WORKFLOW_FORM_DESIGN\" (buttonClick)=\"onCorePageHeaderButtonClicked($event)\"></core-page-header>\r\n\r\n <ng-template #formMetadata>\r\n <form-metadata></form-metadata>\r\n </ng-template>\r\n\r\n @if (coreFormDesignService.$showFormArrayDesign()) {\r\n <core-form-array-layout-editor />\r\n }\r\n\r\n @if (!coreFormDesignService.$isInWorkflowDesign()) {\r\n <aside class=\"af-metadata-overlay\" [@slideFromTopFadeIn]=\"coreFormDesignService.$showFormMetadata() ? 'in' : 'out'\"\r\n [class.shown]=\"coreFormDesignService.$showFormMetadata()\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"formMetadata\"></ng-container>\r\n </aside>\r\n }\r\n\r\n <div \r\n class=\"field-setting-panel\" \r\n [class.open]=\"coreFormDesignService.$fieldSettingPanelOpen()\" \r\n [class.calculated-type]=\"coreFormDesignService.$selectedCell()?.control?.type==='calculated'\"\r\n [ngStyle]=\"{ zIndex: $zIndex() }\"\r\n #settingPanel\r\n >\r\n @if (!!(this.coreFormDesignService.$selectedCell())) {\r\n <field-setting></field-setting>\r\n }\r\n </div>\r\n\r\n <div class=\"form-design-left\">\r\n\r\n @switch ($leftPanelMode()) {\r\n @case (enumLeftPanelMode.FieldCollection) {\r\n @for (category of controlCategories; track $index) {\r\n <div class=\"category-name\">\r\n {{ category.name }}\r\n </div>\r\n <ul>\r\n @for (control of category.controls; track $index) {\r\n <li draggable=\"true\" (dragstart)=\"onDragStart($event, control)\" [class.full-width]=\"control.controlType === 'SEEKER' || control.controlType === 'ATTACHMENT' || control.controlType === 'GRIDBUFFER'\">\r\n @if (control.controlType === 'GRIDBUFFER') {\r\n <div class=\"grid-buffer-wrapper\">\r\n <core-control [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\"></core-control>\r\n </div>\r\n } @else {\r\n <core-control [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\"></core-control>\r\n }\r\n </li>\r\n <div class=\"space\"></div>\r\n }\r\n </ul>\r\n }\r\n }\r\n @case (enumLeftPanelMode.Json) {\r\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"switchJson()\">{{ $jsonMode() }}</button>\r\n @if ($jsonMode()==='selectedField') {\r\n <pre class=\"json-preview\">{{ coreFormDesignService.$currentControlJson() }}</pre>\r\n } @else {\r\n <pre class=\"json-preview\">{{ coreFormDesignService.$saveLiveJson() }}</pre>\r\n }\r\n \r\n }\r\n }\r\n\r\n </div>\r\n\r\n <div class=\"form-design-right\">\r\n\r\n <core-form-group-editor [$idAsInput]=\"true\" />\r\n <!-- <pre>{{ $injectedFieldsJson() }}</pre> -->\r\n\r\n \r\n <!-- @if (coreFormDesignService.$mode() === enumType.Default) {\r\n <div class=\"form-wrapper\">\r\n\r\n @if (!!coreFormDesignService.$isInWorkflowDesign()) {\r\n <form-metadata></form-metadata>\r\n }\r\n\r\n <form [formGroup]=\"formDesign\" autocomplete=\"off\">\r\n <div class=\"form-cells\">\r\n\r\n <div class=\"form-tool-bar\">\r\n @if (!$hasCalculatedSection()) {\r\n <button class=\"core-button-vns-container\" (click)=\"addCalculatedSection()\">+ Calculated fields</button>\r\n }\r\n <button class=\"core-button-vns-container\" (click)=\"addSection()\">+ Add Section</button>\r\n </div>\r\n \r\n @for (section of coreFormDesignService.$placeholderSections(); track $index; let sectionIndex = $index) {\r\n <div class=\"form-section-placeholder\">\r\n\r\n <div class=\"section-header\">\r\n\r\n <div class=\"section-img-wrapper\">\r\n <div class=\"section-img\" [class.calculated]=\"section.forCalculatedFields\"></div>\r\n </div>\r\n\r\n <label [attr.contenteditable]=\"!section.forCalculatedFields\"\r\n [htmlTooltip]=\"!!section.forCalculatedFields ? calculatedFieldsTooltip : null\"\r\n (blur)=\"onCaptionEditEnd(sectionIndex, $event)\"\r\n (keydown.enter)=\"onCaptionEditEnd(sectionIndex, $event); $event.preventDefault()\"\r\n >{{ section.caption }}</label>\r\n\r\n <div class=\"section-tool pointer\" (click)=\"deleteSection(sectionIndex)\" [appTooltip]=\"'Delete section'\" [showAnyway]=\"true\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n \r\n </div>\r\n \r\n @for (row of section.rows; track $index; let rowIndex = $index) {\r\n\r\n <div class=\"form-row-wrapper\">\r\n <div class=\"form-row\">\r\n @for (cell of filteredCells(row); track $index; let colIndex = $index) {\r\n <div class=\"form-cell drop-target\" \r\n [ngStyle]=\"{ flex: (cell.flexSize ?? 0) + ' 1 0%' }\"\r\n [attr.data-flex]=\"cell.flexSize ?? 0\"\r\n (drop)=\"onDropIntoCell($event, sectionIndex, rowIndex, colIndex)\"\r\n (dragover)=\"onDragOver($event, section, cell.control!)\"\r\n (dragenter)=\"onDragEnter(sectionIndex + '_' + rowIndex + '_' + colIndex)\"\r\n (dragleave)=\"onDragLeave(sectionIndex + '_' + rowIndex + '_' + colIndex)\"\r\n [class.selected]=\"cell?.selected\"\r\n [class.dragging-over]=\"isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex]\"\r\n [class.has-control]=\"!!cell && !!cell.control && !!getControl(cell)\"\r\n (click)=\"onCellClicked(sectionIndex, rowIndex, colIndex)\"\r\n >\r\n\r\n\r\n @if (!isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex]) {\r\n\r\n @if (!!cell && !!cell.control && !!getControl(cell)) {\r\n <label contenteditable=\"true\"\r\n (blur)=\"onFieldCaptionEditEnd(cell, $event)\"\r\n (keydown.enter)=\"onFieldCaptionEditEnd(cell, $event); $event.preventDefault()\"\r\n [class.d-none]=\"!!getControl(cell)?.hidden\"\r\n [class.required]=\"!!cell && !!cell.control && !!getControl(cell) && isRequired(getControl(cell))\"\r\n >{{ cell.control.label || 'label' }}</label>\r\n\r\n @if (cell.control.controlType==='CALCULATED') {\r\n <div class=\"control-wrapper\" (click)=\"openSettingsForCell(cell, sectionIndex, rowIndex, colIndex)\">\r\n <core-control \r\n [control]=\"getControl(cell)!\" \r\n [form]=\"formDesign\"\r\n [checkError$]=\"checkError$\" />\r\n </div>\r\n } @else {\r\n <core-control \r\n [control]=\"getControl(cell)!\" \r\n [form]=\"formDesign\"\r\n [checkError$]=\"checkError$\" />\r\n }\r\n \r\n <div class=\"field-toolbar\">\r\n <ul>\r\n <li>\r\n <div class=\"field-tool pointer\" (click)=\"openSettingsForCell(cell, sectionIndex, rowIndex, colIndex)\" [appTooltip]=\"'Show settings'\">\r\n <i class=\"feather-settings\"></i>\r\n </div>\r\n </li>\r\n <li>\r\n <div class=\"field-tool pointer\" (click)=\"deleteField(row, sectionIndex, rowIndex, colIndex)\" [appTooltip]=\"'Remove field from cell'\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n \r\n } @else {\r\n <div class=\"placeholder\" [class.calculated]=\"!!section.forCalculatedFields\">\r\n {{ !!section.forCalculatedFields ? 'Drop calculated field here' : 'Drop here'}}\r\n </div>\r\n }\r\n\r\n @if (cell?.selected && canMergeCells(sectionIndex, rowIndex)) {\r\n <div class=\"merge-toolbar\">\r\n <button (click)=\"mergeCells(sectionIndex, rowIndex)\">\uD83D\uDD17 Merge</button>\r\n </div>\r\n }\r\n \r\n }\r\n\r\n </div>\r\n }\r\n </div>\r\n <div class=\"row-tool-bar\">\r\n <div class=\"icon-wrapper\" (click)=\"deleteRow(sectionIndex, rowIndex)\" [appTooltip]=\"'Delete row'\" [showAnyway]=\"true\"><i class=\"feather-x\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"addRow(sectionIndex)\" [appTooltip]=\"'Add row'\" [showAnyway]=\"true\"><i class=\"feather-arrow-down\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"insertRow(sectionIndex, rowIndex)\" [appTooltip]=\"'Insert row'\" [showAnyway]=\"true\"><i class=\"feather-corner-right-down\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"addColumn(row)\" [appTooltip]=\"'Add column'\" [showAnyway]=\"true\"><i class=\"feather-arrow-right\"></i></div>\r\n </div>\r\n </div>\r\n\r\n }\r\n </div>\r\n }\r\n \r\n \r\n </div>\r\n </form>\r\n </div>\r\n } @else if (!!$sections()) {\r\n\r\n @if(!!(injectedFields$ | async) && !!(injectedFields$ | async)!.length) {\r\n\r\n @if (!!coreFormDesignService.$afInstance().normalMode) {\r\n <live-form [$designMode]=\"true\" [$forKickOff]=\"true\" />\r\n } @else {\r\n <live-form [$designMode]=\"true\" [$forKickOff]=\"true\" ($onClose)=\"closePreview()\" />\r\n }\r\n\r\n } @else {\r\n <h2>COULD NOT UPDATE injectedFields$</h2>\r\n }\r\n\r\n } @else {\r\n <h2>$sections() empty / null / undefined</h2>\r\n } -->\r\n\r\n\r\n \r\n </div>\r\n @if ($loading()) {\r\n <core-toast-loading></core-toast-loading>\r\n }\r\n\r\n <ng-template #calculatedFieldsTooltip>\r\n <div style=\"max-width: 280px;\">\r\n <strong>Calculated Fields</strong><br />\r\n <p></p>\r\n These fields are hidden from the form and cannot be edited directly.<br /><br />\r\n - They are computed automatically during workflow execution.<br />\r\n - Each field depends on one or more standard input fields.<br />\r\n - The calculation is evaluated using either an SQL query engine (like <strong>Dapper</strong>) or an in-memory expression engine (like <strong>Dynamic Expresso</strong>).<br /><br />\r\n In both cases, the result is a <code>0</code> or <code>1</code>, representing <strong>false</strong> or <strong>true</strong>.<br /><br />\r\n These results can be used to influence workflow logic, rule trees, or approval paths.\r\n </div>\r\n </ng-template>\r\n \r\n</div>", styles: ["@charset \"UTF-8\";.core-form-design-container{position:relative;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));width:100%;overflow:hidden;background-color:#eff0f1;font-size:13px}.core-form-design-container .core-button-vns-container{margin-right:8px!important}.core-form-design-container .core-button-vns-container:last-child{background-color:#000;color:#fff;margin-right:0}.core-form-design-container .af-metadata-overlay{position:fixed;top:60px;left:66px;background:#fff;box-shadow:.4rem 0 2rem #0000002e;z-index:1000;width:1214px;height:calc(100vh - 75px);overflow-y:auto;pointer-events:none}.core-form-design-container .af-metadata-overlay.shown{pointer-events:auto}.core-form-design-container *{border-radius:0}.core-form-design-container ul,.core-form-design-container li{padding:0}.core-form-design-container li{max-width:200px}.core-form-design-container ul div.space{display:block;height:15px}.core-form-design-container li.full-width{max-width:100%}.core-form-design-container .field-setting-panel{display:block;position:fixed;width:360px;height:100vh;top:0;right:-360px;background-color:#fff;box-shadow:.4rem 0 2rem #0000002e;transition:right .5s ease-out}.core-form-design-container .field-setting-panel .close-wrapper{width:32px;height:32px;position:absolute;top:15px;right:15px;display:flex;background-color:#848484;border-radius:50%}.core-form-design-container .field-setting-panel .close-wrapper i{width:16px;height:16px;font-size:18px;color:#848484}.core-form-design-container .field-setting-panel .panel-caption{margin-bottom:1rem;padding-bottom:.5rem;border-bottom:1px solid #ddd;width:100%;overflow:hidden;text-wrap:nowrap;text-overflow:ellipsis}.core-form-design-container .field-setting-panel.calculated-type{width:500px;right:-500px}.core-form-design-container .field-setting-panel.calculated-type textarea{border-radius:8px;height:150px}.core-form-design-container .field-setting-panel.open{right:0}.core-form-design-container .form-design-left{position:absolute;top:var(--size-core-page-header-height);bottom:0;left:0;z-index:1;width:360px;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));padding:15px;padding-right:calc(15px + var(--size-scrollbar-width));background-color:#87ceeb;overflow-y:hidden}.core-form-design-container .form-design-left .category-name{color:#fff}.core-form-design-container .form-design-left .grid-buffer-wrapper{background-color:#fff;padding:15px}.core-form-design-container .form-design-left ul:last-child{padding-bottom:400px}.core-form-design-container .form-design-left .category-name{margin-bottom:15px}.core-form-design-container .form-design-left .json-preview{background-color:#fff;color:#333;padding:1rem 1.5rem;box-shadow:0 2px 6px #00000014;font-family:Fira Code,monospace;font-size:.85rem;word-break:keep-all;overflow-x:auto;line-height:1.5;width:330px;height:calc(100vh - 205px)}.core-form-design-container .form-design-left button{height:35px;border-radius:0;margin-bottom:15px;color:#fff;border:none;font-size:13px;background-color:transparent}.core-form-design-container .form-design-left:hover{overflow-y:auto;padding-right:15px}.core-form-design-container .form-design-right{width:100%;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));padding:15px 15px 15px 375px;overflow-y:auto}.core-form-design-container .form-design-right .form-wrapper{width:100%;overflow-y:visible;background-color:#fff}.core-form-design-container .form-design-right .form-wrapper button{margin-left:12px;padding:4px 10px;border:1px solid #ccc;cursor:pointer;transition:all .2s;width:110px}.core-form-design-container .form-design-right .form-wrapper button:hover{background-color:#e4f0ff;border-color:#007bff;color:#007bff}.core-form-design-container .form-design-right .form-wrapper .form-tool-bar{display:flex;align-items:center;justify-content:flex-end}.core-form-design-container .form-design-right .form-wrapper .form-tool-bar>button{width:150px;margin:0}.core-form-design-container .form-design-right .form-wrapper .form-cells{display:flex;flex-direction:column;gap:32px;padding:20px 15px 15px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder{padding:12px 15px;border:1px dashed #ccc;background-color:#fff;box-shadow:0 2px 6px #0000000a}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header{display:flex;position:relative;align-items:center;justify-content:flex-start;font-weight:600;margin-bottom:12px;color:#333}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-img{width:34px;height:34px;border-radius:50%;background-color:#d3d3d3;float:left;background-image:url(/assets/images/info.svg);background-repeat:no-repeat;background-position:center;margin-right:8px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-img.calculated{background-image:url(/assets/images/sql-icon.svg);background-color:transparent;border-radius:0}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-tool{position:absolute;right:5px;top:6px;display:none;z-index:2;color:gray}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-tool i{font-size:24px;color:#848484}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header:hover .section-tool{display:block}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .row-tool-bar{display:flex;align-items:center;justify-content:flex-end;margin-bottom:8px;height:24px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-row{display:flex;gap:15px;margin-bottom:15px;min-height:50px;background-color:#d3d3d3;padding:8px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell{flex:1;min-height:90px;background-color:#fcfcfc;border:1px dashed #ccc;position:relative;padding:20px 10px 10px;transition:border .2s ease-in-out}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell:before{content:attr(data-flex);position:absolute;top:2px;left:4px;font-size:10px;color:#999}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell label.required:after{content:\" *\";color:#ff040b}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar{position:absolute;right:7px;top:6px;display:none;z-index:2;color:gray}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul{display:flex}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul li div{display:flex;width:24px;height:24px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul li div i{font-size:18px;width:18px;height:18px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell.has-control:hover .field-toolbar{display:flex}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell.active-drop{border-color:#007bff;background-color:#eef6ff;transition:.2s}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .placeholder{display:flex;align-items:center;justify-content:center;background-color:#fff;color:#007bff;padding:15px 0;width:100%;cursor:default}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .placeholder.calculated{color:#ff4500}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .icon-wrapper{width:24px;height:24px;border-radius:50%;padding:0;cursor:pointer;display:none;color:gray;border:1px solid gray;margin-left:8px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .icon-wrapper i{font-size:18px;width:18px;height:18px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper:hover .icon-wrapper{display:flex}.core-form-design-container .form-design-right .form-wrapper .form-cell.selected{background-color:#dff6dd}.core-form-design-container .form-design-right .form-wrapper .merge-toolbar{text-align:center;margin-top:4px}.core-form-design-container .form-design-right .form-wrapper.live-form{padding-bottom:15px}.core-form-design-container .form-design-right .form-wrapper.live-form .live-form-header{padding:0 15px}.core-form-design-container .form-design-right .form-wrapper.live-form .live-form-header .preview-close-icon{position:absolute;right:7px;top:6px;z-index:2;color:gray;cursor:pointer}.core-form-design-container .form-design-right .form-wrapper.live-form .live-form-header .preview-close-icon i{font-size:18px}.core-form-design-container .drop-target{min-height:50px;min-width:50px;border:2px dashed transparent;transition:border .2s ease}.core-form-design-container .drop-target.active-drop{border-color:#007bff;background-color:#eaf4ff}.core-form-design-container .no-padding{padding:0!important}.core-form-design-container .modal-content-root{overflow:visible}\n", ".core-form-container{overflow-x:visible}.core-form-container>form .section{margin-top:var(--size-layout-block-cell-spacing)}.core-form-container>form .section:not(:first-child){margin-top:calc(var(--size-layout-block-cell-spacing) * 2)}.core-form-container>form .section .section-header-label{display:block;height:34px;line-height:34px;margin-bottom:15px;margin-left:12px}.core-form-container>form .section .section-header-label .section-img-wrapper{position:relative}.core-form-container>form .section .section-header-label .section-img-wrapper .section-img{position:absolute;width:34px;height:34px;border-radius:50%;background-color:#d3d3d3;float:left;background-image:url(/assets/images/info.svg);background-repeat:no-repeat;background-position:center}.core-form-container>form .section .section-header-label .section-img-wrapper .section-img.calculated{background-image:url(/assets/images/sql-icon.svg);border-radius:0;background-color:transparent}.core-form-container>form .section .section-header-label .section-calc-wrapper{width:34px;height:34px;display:flex;align-items:center;justify-content:center;background-color:#d3d3d3;border-radius:50%}.core-form-container>form .section .section-header-label .section-calc-wrapper i{width:24px;height:24px;font-size:24px;color:#1b4332}.core-form-container>form .section .section-header-label .section-caption{padding-left:40px;font-weight:700;color:#696969}.core-form-container .row{margin-left:var(--size-layout-block-cell-spacing) 0px;margin-right:var(--size-layout-block-cell-spacing) 0px}.core-form-container .row .grid-buffer{border:dotted 2px darkgray}.core-form-container .row .button-control{display:flex;align-items:flex-end}.core-form-container .form-row{margin:var(--size-layout-block-cell-spacing) 0px;display:flex;align-items:center;justify-content:center}.core-form-container .form-row>button{cursor:pointer;border-radius:0}.core-form-container .form-row>button:not(:first-child){margin-left:var(--size-layout-block-cell-spacing)}.core-form-container .dev-button{cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:13px;padding:8px;width:120px;border-radius:18px;box-shadow:.4rem 0 2rem #0000002e}.core-form-container .dev-button:not(:last-child){margin-right:15px}.core-form-container .dev-button:first-child{background-color:#dff6dd;border:1px #9fdc9d solid}.core-form-container .dev-button:last-child{background-color:#fff4ce;border:1px #ffda6a solid}.core-form-container .payload-preview{display:block;width:calc(100% - 48px);height:200px;white-space:pre-wrap;overflow-x:hidden;overflow-y:auto;background-color:#dff6dd;padding:24px;margin:24px;text-indent:-58px;color:#333!important;font-family:Fira Code,monospace;font-size:.85rem;word-break:keep-all;line-height:1.5}.core-form-container .payload-preview.validator-preview{background-color:#fff4ce}.core-form-container .bottom-template-wrapper{padding-left:12px;padding-right:12px}.core-form-container .w-100{width:100%}.core-form-container .pr18{padding-right:18px}\n", ".core-button-vns-container{height:30px;display:flex;align-items:center;justify-content:center;min-width:30px}.core-button-vns-container .action-wrapper{height:30px!important;width:30px!important;display:flex;align-items:center;justify-content:center}.core-button-vns-container .action-wrapper:has(i:hover){background-color:#e7e7e7;border-radius:50%}.core-button-vns-container .btn-for-form{border:none;border-radius:0;background-color:transparent;color:#000;min-width:120px}.core-button-vns-container button.last-child{background-color:#000;color:#fff}.core-button-vns-container .action-wrapper.last-child{background-color:var(--color-basic-orange);color:#fff;border-radius:50%}.core-button-vns-container .action-wrapper.last-child:hover{background-color:var(--color-basic-orange);box-shadow:0 1rem 3rem #0000002e}.core-button-vns-container .temporary-unavailable{user-select:none;-moz-user-select:none;-webkit-user-select:none;cursor:not-allowed!important;opacity:.5}.core-button-vns-container .temporary-unavailable:hover{background-color:transparent!important}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: CoreFormGroupEditorComponent, selector: "core-form-group-editor", inputs: ["$isNested", "$idAsInput", "$id"] }, { kind: "component", type: CoreFormArrayLayoutEditorComponent, selector: "core-form-array-layout-editor" }, { kind: "component", type: CoreToastLoadingComponent, selector: "core-toast-loading" }, { kind: "component", type: CorePageHeaderComponent, selector: "core-page-header", inputs: ["instanceNumber", "shownItems", "title", "hideButtonGroup", "htmlTooltipRef"], outputs: ["buttonClick"] }, { kind: "component", type: FormMetadataComponent, selector: "form-metadata" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: HotKeysDirective, selector: "[hotKeys]", inputs: ["hotKeys"] }, { kind: "component", type: CoreControlComponent, selector: "core-control", inputs: ["control", "form", "checkError$", "rangeLimit"] }, { kind: "component", type: FieldSettingComponent, selector: "field-setting", inputs: ["$isNested"] }], animations: [slideFromTopFadeIn], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2397
3238
  }
2398
3239
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: CoreFormDesignComponent, decorators: [{
2399
3240
  type: Component,
@@ -2401,6 +3242,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImpor
2401
3242
  NgStyle,
2402
3243
  AsyncPipe,
2403
3244
  NgTemplateOutlet,
3245
+ CoreFormGroupEditorComponent,
2404
3246
  CoreFormArrayLayoutEditorComponent,
2405
3247
  CoreToastLoadingComponent,
2406
3248
  CorePageHeaderComponent,
@@ -2425,7 +3267,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImpor
2425
3267
  FieldSettingComponent,
2426
3268
  LiveFormComponent,
2427
3269
  HtmlTooltipDirective,
2428
- ], animations: [slideFromTopFadeIn], template: "<div class=\"core-form-design-container fs-13\" [hotKeys]=\"['F3', 'F6', 'Escape']\">\r\n\r\n <core-page-header title=\"UI.COMPONENT_TITLE.WORKFLOW_FORM_DESIGN\" (buttonClick)=\"onCorePageHeaderButtonClicked($event)\"></core-page-header>\r\n\r\n <ng-template #formMetadata>\r\n <form-metadata></form-metadata>\r\n </ng-template>\r\n\r\n @if (coreFormDesignService.$showFormArrayDesign()) {\r\n <core-form-array-layout-editor />\r\n }\r\n\r\n @if (!coreFormDesignService.$isInWorkflowDesign()) {\r\n <aside class=\"af-metadata-overlay\" [@slideFromTopFadeIn]=\"coreFormDesignService.$showFormMetadata() ? 'in' : 'out'\"\r\n [class.shown]=\"coreFormDesignService.$showFormMetadata()\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"formMetadata\"></ng-container>\r\n </aside>\r\n }\r\n\r\n <div \r\n class=\"field-setting-panel\" \r\n [class.open]=\"coreFormDesignService.$fieldSettingPanelOpen()\" \r\n [class.calculated-type]=\"coreFormDesignService.$selectedCell()?.control?.type==='calculated'\"\r\n [ngStyle]=\"{ zIndex: $zIndex() }\"\r\n #settingPanel\r\n >\r\n @if (!!(this.coreFormDesignService.$selectedCell())) {\r\n <field-setting></field-setting>\r\n }\r\n </div>\r\n\r\n <div class=\"form-design-left\">\r\n\r\n @switch ($leftPanelMode()) {\r\n @case (enumLeftPanelMode.FieldCollection) {\r\n @for (category of controlCategories; track $index) {\r\n <div class=\"category-name\">\r\n {{ category.name }}\r\n </div>\r\n <ul>\r\n @for (control of category.controls; track $index) {\r\n <li draggable=\"true\" (dragstart)=\"onDragStart($event, control)\" [class.full-width]=\"control.controlType === 'SEEKER' || control.controlType === 'ATTACHMENT' || control.controlType === 'GRIDBUFFER'\">\r\n @if (control.controlType === 'GRIDBUFFER') {\r\n <div class=\"grid-buffer-wrapper\">\r\n <core-control [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\"></core-control>\r\n </div>\r\n } @else {\r\n <core-control [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\"></core-control>\r\n }\r\n </li>\r\n <div class=\"space\"></div>\r\n }\r\n </ul>\r\n }\r\n }\r\n @case (enumLeftPanelMode.Json) {\r\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"switchJson()\">{{ $jsonMode() }}</button>\r\n @if ($jsonMode()==='selectedField') {\r\n <pre class=\"json-preview\">{{ coreFormDesignService.$currentControlJson() }}</pre>\r\n } @else {\r\n <pre class=\"json-preview\">{{ coreFormDesignService.$saveLiveJson() }}</pre>\r\n }\r\n \r\n }\r\n }\r\n\r\n </div>\r\n\r\n <div class=\"form-design-right\">\r\n <!-- <pre>{{ $injectedFieldsJson() }}</pre> -->\r\n\r\n @if (coreFormDesignService.$mode() === enumType.Default) {\r\n <div class=\"form-wrapper\">\r\n\r\n @if (!!coreFormDesignService.$isInWorkflowDesign()) {\r\n <form-metadata></form-metadata>\r\n }\r\n\r\n <form [formGroup]=\"formDesign\" autocomplete=\"off\">\r\n <div class=\"form-cells\">\r\n\r\n <div class=\"form-tool-bar\">\r\n @if (!$hasCalculatedSection()) {\r\n <button class=\"core-button-vns-container\" (click)=\"addCalculatedSection()\">+ Calculated fields</button>\r\n }\r\n <button class=\"core-button-vns-container\" (click)=\"addSection()\">+ Add Section</button>\r\n </div>\r\n \r\n @for (section of coreFormDesignService.$placeholderSections(); track $index; let sectionIndex = $index) {\r\n <div class=\"form-section-placeholder\">\r\n\r\n <div class=\"section-header\">\r\n\r\n <div class=\"section-img-wrapper\">\r\n <div class=\"section-img\" [class.calculated]=\"section.forCalculatedFields\"></div>\r\n </div>\r\n\r\n <label [attr.contenteditable]=\"!section.forCalculatedFields\"\r\n [htmlTooltip]=\"!!section.forCalculatedFields ? calculatedFieldsTooltip : null\"\r\n (blur)=\"onCaptionEditEnd(sectionIndex, $event)\"\r\n (keydown.enter)=\"onCaptionEditEnd(sectionIndex, $event); $event.preventDefault()\"\r\n >{{ section.caption }}</label>\r\n\r\n <div class=\"section-tool pointer\" (click)=\"deleteSection(sectionIndex)\" [appTooltip]=\"'Delete section'\" [showAnyway]=\"true\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n \r\n </div>\r\n \r\n @for (row of section.rows; track $index; let rowIndex = $index) {\r\n\r\n <div class=\"form-row-wrapper\">\r\n <div class=\"form-row\">\r\n @for (cell of filteredCells(row); track $index; let colIndex = $index) {\r\n <div class=\"form-cell drop-target\" \r\n [ngStyle]=\"{ flex: (cell.flexSize ?? 0) + ' 1 0%' }\"\r\n [attr.data-flex]=\"cell.flexSize ?? 0\"\r\n (drop)=\"onDropIntoCell($event, sectionIndex, rowIndex, colIndex)\"\r\n (dragover)=\"onDragOver($event, section, cell.control!)\"\r\n (dragenter)=\"onDragEnter(sectionIndex + '_' + rowIndex + '_' + colIndex)\"\r\n (dragleave)=\"onDragLeave(sectionIndex + '_' + rowIndex + '_' + colIndex)\"\r\n [class.selected]=\"cell?.selected\"\r\n [class.dragging-over]=\"isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex]\"\r\n [class.has-control]=\"!!cell && !!cell.control && !!getControl(cell)\"\r\n (click)=\"onCellClicked(sectionIndex, rowIndex, colIndex)\"\r\n >\r\n\r\n\r\n @if (!isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex]) {\r\n\r\n @if (!!cell && !!cell.control && !!getControl(cell)) {\r\n <label contenteditable=\"true\"\r\n (blur)=\"onFieldCaptionEditEnd(cell, $event)\"\r\n (keydown.enter)=\"onFieldCaptionEditEnd(cell, $event); $event.preventDefault()\"\r\n [class.d-none]=\"!!getControl(cell)?.hidden\"\r\n [class.required]=\"!!cell && !!cell.control && !!getControl(cell) && isRequired(getControl(cell))\"\r\n >{{ cell.control.label || 'label' }}</label>\r\n\r\n @if (cell.control.controlType==='CALCULATED') {\r\n <div class=\"control-wrapper\" (click)=\"openSettingsForCell(cell, sectionIndex, rowIndex, colIndex)\">\r\n <core-control \r\n [control]=\"getControl(cell)!\" \r\n [form]=\"formDesign\"\r\n [checkError$]=\"checkError$\" />\r\n </div>\r\n } @else {\r\n <core-control \r\n [control]=\"getControl(cell)!\" \r\n [form]=\"formDesign\"\r\n [checkError$]=\"checkError$\" />\r\n }\r\n \r\n <div class=\"field-toolbar\">\r\n <ul>\r\n <li>\r\n <div class=\"field-tool pointer\" (click)=\"openSettingsForCell(cell, sectionIndex, rowIndex, colIndex)\" [appTooltip]=\"'Show settings'\">\r\n <i class=\"feather-settings\"></i>\r\n </div>\r\n </li>\r\n <li>\r\n <div class=\"field-tool pointer\" (click)=\"deleteField(row, sectionIndex, rowIndex, colIndex)\" [appTooltip]=\"'Remove field from cell'\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n \r\n } @else {\r\n <div class=\"placeholder\" [class.calculated]=\"!!section.forCalculatedFields\">\r\n {{ !!section.forCalculatedFields ? 'Drop calculated field here' : 'Drop here'}}\r\n </div>\r\n }\r\n\r\n @if (cell?.selected && canMergeCells(sectionIndex, rowIndex)) {\r\n <div class=\"merge-toolbar\">\r\n <button (click)=\"mergeCells(sectionIndex, rowIndex)\">\uD83D\uDD17 Merge</button>\r\n </div>\r\n }\r\n \r\n }\r\n\r\n </div>\r\n }\r\n </div>\r\n <div class=\"row-tool-bar\">\r\n <div class=\"icon-wrapper\" (click)=\"deleteRow(sectionIndex, rowIndex)\" [appTooltip]=\"'Delete row'\" [showAnyway]=\"true\"><i class=\"feather-x\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"addRow(sectionIndex)\" [appTooltip]=\"'Add row'\" [showAnyway]=\"true\"><i class=\"feather-arrow-down\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"insertRow(sectionIndex, rowIndex)\" [appTooltip]=\"'Insert row'\" [showAnyway]=\"true\"><i class=\"feather-corner-right-down\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"addColumn(row)\" [appTooltip]=\"'Add column'\" [showAnyway]=\"true\"><i class=\"feather-arrow-right\"></i></div>\r\n </div>\r\n </div>\r\n\r\n }\r\n </div>\r\n }\r\n \r\n \r\n </div>\r\n </form>\r\n </div>\r\n } @else if (!!$sections()) {\r\n\r\n @if(!!(injectedFields$ | async) && !!(injectedFields$ | async)!.length) {\r\n\r\n @if (!!coreFormDesignService.$afInstance().normalMode) {\r\n <live-form [$designMode]=\"true\" [$forKickOff]=\"true\" />\r\n } @else {\r\n <live-form [$designMode]=\"true\" [$forKickOff]=\"true\" ($onClose)=\"closePreview()\" />\r\n }\r\n\r\n } @else {\r\n <h2>COULD NOT UPDATE injectedFields$</h2>\r\n }\r\n\r\n } @else {\r\n <h2>$sections() empty / null / undefined</h2>\r\n }\r\n\r\n\r\n \r\n </div>\r\n @if ($loading()) {\r\n <core-toast-loading></core-toast-loading>\r\n }\r\n\r\n <ng-template #calculatedFieldsTooltip>\r\n <div style=\"max-width: 280px;\">\r\n <strong>Calculated Fields</strong><br />\r\n <p></p>\r\n These fields are hidden from the form and cannot be edited directly.<br /><br />\r\n - They are computed automatically during workflow execution.<br />\r\n - Each field depends on one or more standard input fields.<br />\r\n - The calculation is evaluated using either an SQL query engine (like <strong>Dapper</strong>) or an in-memory expression engine (like <strong>Dynamic Expresso</strong>).<br /><br />\r\n In both cases, the result is a <code>0</code> or <code>1</code>, representing <strong>false</strong> or <strong>true</strong>.<br /><br />\r\n These results can be used to influence workflow logic, rule trees, or approval paths.\r\n </div>\r\n </ng-template>\r\n \r\n</div>", styles: ["@charset \"UTF-8\";.core-form-design-container{position:relative;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));width:100%;overflow:hidden;background-color:#eff0f1;font-size:13px}.core-form-design-container .core-button-vns-container{margin-right:8px!important}.core-form-design-container .core-button-vns-container:last-child{background-color:#000;color:#fff;margin-right:0}.core-form-design-container .af-metadata-overlay{position:fixed;top:60px;left:66px;background:#fff;box-shadow:.4rem 0 2rem #0000002e;z-index:1000;width:1214px;height:calc(100vh - 75px);overflow-y:auto;pointer-events:none}.core-form-design-container .af-metadata-overlay.shown{pointer-events:auto}.core-form-design-container *{border-radius:0}.core-form-design-container ul,.core-form-design-container li{padding:0}.core-form-design-container li{max-width:200px}.core-form-design-container ul div.space{display:block;height:15px}.core-form-design-container li.full-width{max-width:100%}.core-form-design-container .field-setting-panel{display:block;position:fixed;width:360px;height:100vh;top:0;right:-360px;background-color:#fff;box-shadow:.4rem 0 2rem #0000002e;transition:right .5s ease-out}.core-form-design-container .field-setting-panel .close-wrapper{width:32px;height:32px;position:absolute;top:15px;right:15px;display:flex;background-color:#848484;border-radius:50%}.core-form-design-container .field-setting-panel .close-wrapper i{width:16px;height:16px;font-size:18px;color:#848484}.core-form-design-container .field-setting-panel .panel-caption{margin-bottom:1rem;padding-bottom:.5rem;border-bottom:1px solid #ddd;width:100%;overflow:hidden;text-wrap:nowrap;text-overflow:ellipsis}.core-form-design-container .field-setting-panel.calculated-type{width:500px;right:-500px}.core-form-design-container .field-setting-panel.calculated-type textarea{border-radius:8px;height:150px}.core-form-design-container .field-setting-panel.open{right:0}.core-form-design-container .form-design-left{position:absolute;top:var(--size-core-page-header-height);bottom:0;left:0;z-index:1;width:360px;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));padding:15px;padding-right:calc(15px + var(--size-scrollbar-width));background-color:#87ceeb;overflow-y:hidden}.core-form-design-container .form-design-left .category-name{color:#fff}.core-form-design-container .form-design-left .grid-buffer-wrapper{background-color:#fff;padding:15px}.core-form-design-container .form-design-left ul:last-child{padding-bottom:400px}.core-form-design-container .form-design-left .category-name{margin-bottom:15px}.core-form-design-container .form-design-left .json-preview{background-color:#fff;color:#333;padding:1rem 1.5rem;box-shadow:0 2px 6px #00000014;font-family:Fira Code,monospace;font-size:.85rem;word-break:keep-all;overflow-x:auto;line-height:1.5;width:330px;height:calc(100vh - 205px)}.core-form-design-container .form-design-left button{height:35px;border-radius:0;margin-bottom:15px;color:#fff;border:none;font-size:13px;background-color:transparent}.core-form-design-container .form-design-left:hover{overflow-y:auto;padding-right:15px}.core-form-design-container .form-design-right{width:100%;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));padding:15px 15px 15px 375px;overflow-y:auto}.core-form-design-container .form-design-right .form-wrapper{width:100%;overflow-y:visible;background-color:#fff}.core-form-design-container .form-design-right .form-wrapper button{margin-left:12px;padding:4px 10px;border:1px solid #ccc;cursor:pointer;transition:all .2s;width:110px}.core-form-design-container .form-design-right .form-wrapper button:hover{background-color:#e4f0ff;border-color:#007bff;color:#007bff}.core-form-design-container .form-design-right .form-wrapper .form-tool-bar{display:flex;align-items:center;justify-content:flex-end}.core-form-design-container .form-design-right .form-wrapper .form-tool-bar>button{width:150px;margin:0}.core-form-design-container .form-design-right .form-wrapper .form-cells{display:flex;flex-direction:column;gap:32px;padding:20px 15px 15px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder{padding:12px 15px;border:1px dashed #ccc;background-color:#fff;box-shadow:0 2px 6px #0000000a}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header{display:flex;position:relative;align-items:center;justify-content:flex-start;font-weight:600;margin-bottom:12px;color:#333}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-img{width:34px;height:34px;border-radius:50%;background-color:#d3d3d3;float:left;background-image:url(/assets/images/info.svg);background-repeat:no-repeat;background-position:center;margin-right:8px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-img.calculated{background-image:url(/assets/images/sql-icon.svg);background-color:transparent;border-radius:0}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-tool{position:absolute;right:5px;top:6px;display:none;z-index:2;color:gray}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-tool i{font-size:24px;color:#848484}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header:hover .section-tool{display:block}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .row-tool-bar{display:flex;align-items:center;justify-content:flex-end;margin-bottom:8px;height:24px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-row{display:flex;gap:15px;margin-bottom:15px;min-height:50px;background-color:#d3d3d3;padding:8px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell{flex:1;min-height:90px;background-color:#fcfcfc;border:1px dashed #ccc;position:relative;padding:20px 10px 10px;transition:border .2s ease-in-out}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell:before{content:attr(data-flex);position:absolute;top:2px;left:4px;font-size:10px;color:#999}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell label.required:after{content:\" *\";color:#ff040b}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar{position:absolute;right:7px;top:6px;display:none;z-index:2;color:gray}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul{display:flex}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul li div{display:flex;width:24px;height:24px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul li div i{font-size:18px;width:18px;height:18px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell.has-control:hover .field-toolbar{display:flex}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell.active-drop{border-color:#007bff;background-color:#eef6ff;transition:.2s}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .placeholder{display:flex;align-items:center;justify-content:center;background-color:#fff;color:#007bff;padding:15px 0;width:100%;cursor:default}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .placeholder.calculated{color:#ff4500}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .icon-wrapper{width:24px;height:24px;border-radius:50%;padding:0;cursor:pointer;display:none;color:gray;border:1px solid gray;margin-left:8px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .icon-wrapper i{font-size:18px;width:18px;height:18px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper:hover .icon-wrapper{display:flex}.core-form-design-container .form-design-right .form-wrapper .form-cell.selected{background-color:#dff6dd}.core-form-design-container .form-design-right .form-wrapper .merge-toolbar{text-align:center;margin-top:4px}.core-form-design-container .form-design-right .form-wrapper.live-form{padding-bottom:15px}.core-form-design-container .form-design-right .form-wrapper.live-form .live-form-header{padding:0 15px}.core-form-design-container .form-design-right .form-wrapper.live-form .live-form-header .preview-close-icon{position:absolute;right:7px;top:6px;z-index:2;color:gray;cursor:pointer}.core-form-design-container .form-design-right .form-wrapper.live-form .live-form-header .preview-close-icon i{font-size:18px}.core-form-design-container .drop-target{min-height:50px;min-width:50px;border:2px dashed transparent;transition:border .2s ease}.core-form-design-container .drop-target.active-drop{border-color:#007bff;background-color:#eaf4ff}.core-form-design-container .no-padding{padding:0!important}.core-form-design-container .modal-content-root{overflow:visible}\n", ".core-form-container{overflow-x:visible}.core-form-container>form .section{margin-top:var(--size-layout-block-cell-spacing)}.core-form-container>form .section:not(:first-child){margin-top:calc(var(--size-layout-block-cell-spacing) * 2)}.core-form-container>form .section .section-header-label{display:block;height:34px;line-height:34px;margin-bottom:15px;margin-left:12px}.core-form-container>form .section .section-header-label .section-img-wrapper{position:relative}.core-form-container>form .section .section-header-label .section-img-wrapper .section-img{position:absolute;width:34px;height:34px;border-radius:50%;background-color:#d3d3d3;float:left;background-image:url(/assets/images/info.svg);background-repeat:no-repeat;background-position:center}.core-form-container>form .section .section-header-label .section-img-wrapper .section-img.calculated{background-image:url(/assets/images/sql-icon.svg);border-radius:0;background-color:transparent}.core-form-container>form .section .section-header-label .section-calc-wrapper{width:34px;height:34px;display:flex;align-items:center;justify-content:center;background-color:#d3d3d3;border-radius:50%}.core-form-container>form .section .section-header-label .section-calc-wrapper i{width:24px;height:24px;font-size:24px;color:#1b4332}.core-form-container>form .section .section-header-label .section-caption{padding-left:40px;font-weight:700;color:#696969}.core-form-container .row{margin-left:var(--size-layout-block-cell-spacing) 0px;margin-right:var(--size-layout-block-cell-spacing) 0px}.core-form-container .row .grid-buffer{border:dotted 2px darkgray}.core-form-container .row .button-control{display:flex;align-items:flex-end}.core-form-container .form-row{margin:var(--size-layout-block-cell-spacing) 0px;display:flex;align-items:center;justify-content:center}.core-form-container .form-row>button{cursor:pointer;border-radius:0}.core-form-container .form-row>button:not(:first-child){margin-left:var(--size-layout-block-cell-spacing)}.core-form-container .dev-button{cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:13px;padding:8px;width:120px;border-radius:18px;box-shadow:.4rem 0 2rem #0000002e}.core-form-container .dev-button:not(:last-child){margin-right:15px}.core-form-container .dev-button:first-child{background-color:#dff6dd;border:1px #9fdc9d solid}.core-form-container .dev-button:last-child{background-color:#fff4ce;border:1px #ffda6a solid}.core-form-container .payload-preview{display:block;width:calc(100% - 48px);height:200px;white-space:pre-wrap;overflow-x:hidden;overflow-y:auto;background-color:#dff6dd;padding:24px;margin:24px;text-indent:-58px;color:#333!important;font-family:Fira Code,monospace;font-size:.85rem;word-break:keep-all;line-height:1.5}.core-form-container .payload-preview.validator-preview{background-color:#fff4ce}.core-form-container .bottom-template-wrapper{padding-left:12px;padding-right:12px}.core-form-container .w-100{width:100%}.core-form-container .pr18{padding-right:18px}\n", ".core-button-vns-container{height:30px;display:flex;align-items:center;justify-content:center;min-width:30px}.core-button-vns-container .action-wrapper{height:30px!important;width:30px!important;display:flex;align-items:center;justify-content:center}.core-button-vns-container .action-wrapper:has(i:hover){background-color:#e7e7e7;border-radius:50%}.core-button-vns-container .btn-for-form{border:none;border-radius:0;background-color:transparent;color:#000;min-width:120px}.core-button-vns-container button.last-child{background-color:#000;color:#fff}.core-button-vns-container .action-wrapper.last-child{background-color:var(--color-basic-orange);color:#fff;border-radius:50%}.core-button-vns-container .action-wrapper.last-child:hover{background-color:var(--color-basic-orange);box-shadow:0 1rem 3rem #0000002e}.core-button-vns-container .temporary-unavailable{user-select:none;-moz-user-select:none;-webkit-user-select:none;cursor:not-allowed!important;opacity:.5}.core-button-vns-container .temporary-unavailable:hover{background-color:transparent!important}\n"] }]
3270
+ ], animations: [slideFromTopFadeIn], template: "<div class=\"core-form-design-container fs-13\" [hotKeys]=\"['F3', 'F6', 'Escape']\">\r\n\r\n <core-page-header title=\"UI.COMPONENT_TITLE.WORKFLOW_FORM_DESIGN\" (buttonClick)=\"onCorePageHeaderButtonClicked($event)\"></core-page-header>\r\n\r\n <ng-template #formMetadata>\r\n <form-metadata></form-metadata>\r\n </ng-template>\r\n\r\n @if (coreFormDesignService.$showFormArrayDesign()) {\r\n <core-form-array-layout-editor />\r\n }\r\n\r\n @if (!coreFormDesignService.$isInWorkflowDesign()) {\r\n <aside class=\"af-metadata-overlay\" [@slideFromTopFadeIn]=\"coreFormDesignService.$showFormMetadata() ? 'in' : 'out'\"\r\n [class.shown]=\"coreFormDesignService.$showFormMetadata()\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"formMetadata\"></ng-container>\r\n </aside>\r\n }\r\n\r\n <div \r\n class=\"field-setting-panel\" \r\n [class.open]=\"coreFormDesignService.$fieldSettingPanelOpen()\" \r\n [class.calculated-type]=\"coreFormDesignService.$selectedCell()?.control?.type==='calculated'\"\r\n [ngStyle]=\"{ zIndex: $zIndex() }\"\r\n #settingPanel\r\n >\r\n @if (!!(this.coreFormDesignService.$selectedCell())) {\r\n <field-setting></field-setting>\r\n }\r\n </div>\r\n\r\n <div class=\"form-design-left\">\r\n\r\n @switch ($leftPanelMode()) {\r\n @case (enumLeftPanelMode.FieldCollection) {\r\n @for (category of controlCategories; track $index) {\r\n <div class=\"category-name\">\r\n {{ category.name }}\r\n </div>\r\n <ul>\r\n @for (control of category.controls; track $index) {\r\n <li draggable=\"true\" (dragstart)=\"onDragStart($event, control)\" [class.full-width]=\"control.controlType === 'SEEKER' || control.controlType === 'ATTACHMENT' || control.controlType === 'GRIDBUFFER'\">\r\n @if (control.controlType === 'GRIDBUFFER') {\r\n <div class=\"grid-buffer-wrapper\">\r\n <core-control [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\"></core-control>\r\n </div>\r\n } @else {\r\n <core-control [control]=\"control\" [form]=\"form\" [checkError$]=\"checkError$\"></core-control>\r\n }\r\n </li>\r\n <div class=\"space\"></div>\r\n }\r\n </ul>\r\n }\r\n }\r\n @case (enumLeftPanelMode.Json) {\r\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"switchJson()\">{{ $jsonMode() }}</button>\r\n @if ($jsonMode()==='selectedField') {\r\n <pre class=\"json-preview\">{{ coreFormDesignService.$currentControlJson() }}</pre>\r\n } @else {\r\n <pre class=\"json-preview\">{{ coreFormDesignService.$saveLiveJson() }}</pre>\r\n }\r\n \r\n }\r\n }\r\n\r\n </div>\r\n\r\n <div class=\"form-design-right\">\r\n\r\n <core-form-group-editor [$idAsInput]=\"true\" />\r\n <!-- <pre>{{ $injectedFieldsJson() }}</pre> -->\r\n\r\n \r\n <!-- @if (coreFormDesignService.$mode() === enumType.Default) {\r\n <div class=\"form-wrapper\">\r\n\r\n @if (!!coreFormDesignService.$isInWorkflowDesign()) {\r\n <form-metadata></form-metadata>\r\n }\r\n\r\n <form [formGroup]=\"formDesign\" autocomplete=\"off\">\r\n <div class=\"form-cells\">\r\n\r\n <div class=\"form-tool-bar\">\r\n @if (!$hasCalculatedSection()) {\r\n <button class=\"core-button-vns-container\" (click)=\"addCalculatedSection()\">+ Calculated fields</button>\r\n }\r\n <button class=\"core-button-vns-container\" (click)=\"addSection()\">+ Add Section</button>\r\n </div>\r\n \r\n @for (section of coreFormDesignService.$placeholderSections(); track $index; let sectionIndex = $index) {\r\n <div class=\"form-section-placeholder\">\r\n\r\n <div class=\"section-header\">\r\n\r\n <div class=\"section-img-wrapper\">\r\n <div class=\"section-img\" [class.calculated]=\"section.forCalculatedFields\"></div>\r\n </div>\r\n\r\n <label [attr.contenteditable]=\"!section.forCalculatedFields\"\r\n [htmlTooltip]=\"!!section.forCalculatedFields ? calculatedFieldsTooltip : null\"\r\n (blur)=\"onCaptionEditEnd(sectionIndex, $event)\"\r\n (keydown.enter)=\"onCaptionEditEnd(sectionIndex, $event); $event.preventDefault()\"\r\n >{{ section.caption }}</label>\r\n\r\n <div class=\"section-tool pointer\" (click)=\"deleteSection(sectionIndex)\" [appTooltip]=\"'Delete section'\" [showAnyway]=\"true\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n \r\n </div>\r\n \r\n @for (row of section.rows; track $index; let rowIndex = $index) {\r\n\r\n <div class=\"form-row-wrapper\">\r\n <div class=\"form-row\">\r\n @for (cell of filteredCells(row); track $index; let colIndex = $index) {\r\n <div class=\"form-cell drop-target\" \r\n [ngStyle]=\"{ flex: (cell.flexSize ?? 0) + ' 1 0%' }\"\r\n [attr.data-flex]=\"cell.flexSize ?? 0\"\r\n (drop)=\"onDropIntoCell($event, sectionIndex, rowIndex, colIndex)\"\r\n (dragover)=\"onDragOver($event, section, cell.control!)\"\r\n (dragenter)=\"onDragEnter(sectionIndex + '_' + rowIndex + '_' + colIndex)\"\r\n (dragleave)=\"onDragLeave(sectionIndex + '_' + rowIndex + '_' + colIndex)\"\r\n [class.selected]=\"cell?.selected\"\r\n [class.dragging-over]=\"isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex]\"\r\n [class.has-control]=\"!!cell && !!cell.control && !!getControl(cell)\"\r\n (click)=\"onCellClicked(sectionIndex, rowIndex, colIndex)\"\r\n >\r\n\r\n\r\n @if (!isDragOverMap[sectionIndex + '_' + rowIndex + '_' + colIndex]) {\r\n\r\n @if (!!cell && !!cell.control && !!getControl(cell)) {\r\n <label contenteditable=\"true\"\r\n (blur)=\"onFieldCaptionEditEnd(cell, $event)\"\r\n (keydown.enter)=\"onFieldCaptionEditEnd(cell, $event); $event.preventDefault()\"\r\n [class.d-none]=\"!!getControl(cell)?.hidden\"\r\n [class.required]=\"!!cell && !!cell.control && !!getControl(cell) && isRequired(getControl(cell))\"\r\n >{{ cell.control.label || 'label' }}</label>\r\n\r\n @if (cell.control.controlType==='CALCULATED') {\r\n <div class=\"control-wrapper\" (click)=\"openSettingsForCell(cell, sectionIndex, rowIndex, colIndex)\">\r\n <core-control \r\n [control]=\"getControl(cell)!\" \r\n [form]=\"formDesign\"\r\n [checkError$]=\"checkError$\" />\r\n </div>\r\n } @else {\r\n <core-control \r\n [control]=\"getControl(cell)!\" \r\n [form]=\"formDesign\"\r\n [checkError$]=\"checkError$\" />\r\n }\r\n \r\n <div class=\"field-toolbar\">\r\n <ul>\r\n <li>\r\n <div class=\"field-tool pointer\" (click)=\"openSettingsForCell(cell, sectionIndex, rowIndex, colIndex)\" [appTooltip]=\"'Show settings'\">\r\n <i class=\"feather-settings\"></i>\r\n </div>\r\n </li>\r\n <li>\r\n <div class=\"field-tool pointer\" (click)=\"deleteField(row, sectionIndex, rowIndex, colIndex)\" [appTooltip]=\"'Remove field from cell'\">\r\n <i class=\"feather-x\"></i>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n \r\n } @else {\r\n <div class=\"placeholder\" [class.calculated]=\"!!section.forCalculatedFields\">\r\n {{ !!section.forCalculatedFields ? 'Drop calculated field here' : 'Drop here'}}\r\n </div>\r\n }\r\n\r\n @if (cell?.selected && canMergeCells(sectionIndex, rowIndex)) {\r\n <div class=\"merge-toolbar\">\r\n <button (click)=\"mergeCells(sectionIndex, rowIndex)\">\uD83D\uDD17 Merge</button>\r\n </div>\r\n }\r\n \r\n }\r\n\r\n </div>\r\n }\r\n </div>\r\n <div class=\"row-tool-bar\">\r\n <div class=\"icon-wrapper\" (click)=\"deleteRow(sectionIndex, rowIndex)\" [appTooltip]=\"'Delete row'\" [showAnyway]=\"true\"><i class=\"feather-x\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"addRow(sectionIndex)\" [appTooltip]=\"'Add row'\" [showAnyway]=\"true\"><i class=\"feather-arrow-down\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"insertRow(sectionIndex, rowIndex)\" [appTooltip]=\"'Insert row'\" [showAnyway]=\"true\"><i class=\"feather-corner-right-down\"></i></div>\r\n <div class=\"icon-wrapper\" (click)=\"addColumn(row)\" [appTooltip]=\"'Add column'\" [showAnyway]=\"true\"><i class=\"feather-arrow-right\"></i></div>\r\n </div>\r\n </div>\r\n\r\n }\r\n </div>\r\n }\r\n \r\n \r\n </div>\r\n </form>\r\n </div>\r\n } @else if (!!$sections()) {\r\n\r\n @if(!!(injectedFields$ | async) && !!(injectedFields$ | async)!.length) {\r\n\r\n @if (!!coreFormDesignService.$afInstance().normalMode) {\r\n <live-form [$designMode]=\"true\" [$forKickOff]=\"true\" />\r\n } @else {\r\n <live-form [$designMode]=\"true\" [$forKickOff]=\"true\" ($onClose)=\"closePreview()\" />\r\n }\r\n\r\n } @else {\r\n <h2>COULD NOT UPDATE injectedFields$</h2>\r\n }\r\n\r\n } @else {\r\n <h2>$sections() empty / null / undefined</h2>\r\n } -->\r\n\r\n\r\n \r\n </div>\r\n @if ($loading()) {\r\n <core-toast-loading></core-toast-loading>\r\n }\r\n\r\n <ng-template #calculatedFieldsTooltip>\r\n <div style=\"max-width: 280px;\">\r\n <strong>Calculated Fields</strong><br />\r\n <p></p>\r\n These fields are hidden from the form and cannot be edited directly.<br /><br />\r\n - They are computed automatically during workflow execution.<br />\r\n - Each field depends on one or more standard input fields.<br />\r\n - The calculation is evaluated using either an SQL query engine (like <strong>Dapper</strong>) or an in-memory expression engine (like <strong>Dynamic Expresso</strong>).<br /><br />\r\n In both cases, the result is a <code>0</code> or <code>1</code>, representing <strong>false</strong> or <strong>true</strong>.<br /><br />\r\n These results can be used to influence workflow logic, rule trees, or approval paths.\r\n </div>\r\n </ng-template>\r\n \r\n</div>", styles: ["@charset \"UTF-8\";.core-form-design-container{position:relative;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));width:100%;overflow:hidden;background-color:#eff0f1;font-size:13px}.core-form-design-container .core-button-vns-container{margin-right:8px!important}.core-form-design-container .core-button-vns-container:last-child{background-color:#000;color:#fff;margin-right:0}.core-form-design-container .af-metadata-overlay{position:fixed;top:60px;left:66px;background:#fff;box-shadow:.4rem 0 2rem #0000002e;z-index:1000;width:1214px;height:calc(100vh - 75px);overflow-y:auto;pointer-events:none}.core-form-design-container .af-metadata-overlay.shown{pointer-events:auto}.core-form-design-container *{border-radius:0}.core-form-design-container ul,.core-form-design-container li{padding:0}.core-form-design-container li{max-width:200px}.core-form-design-container ul div.space{display:block;height:15px}.core-form-design-container li.full-width{max-width:100%}.core-form-design-container .field-setting-panel{display:block;position:fixed;width:360px;height:100vh;top:0;right:-360px;background-color:#fff;box-shadow:.4rem 0 2rem #0000002e;transition:right .5s ease-out}.core-form-design-container .field-setting-panel .close-wrapper{width:32px;height:32px;position:absolute;top:15px;right:15px;display:flex;background-color:#848484;border-radius:50%}.core-form-design-container .field-setting-panel .close-wrapper i{width:16px;height:16px;font-size:18px;color:#848484}.core-form-design-container .field-setting-panel .panel-caption{margin-bottom:1rem;padding-bottom:.5rem;border-bottom:1px solid #ddd;width:100%;overflow:hidden;text-wrap:nowrap;text-overflow:ellipsis}.core-form-design-container .field-setting-panel.calculated-type{width:500px;right:-500px}.core-form-design-container .field-setting-panel.calculated-type textarea{border-radius:8px;height:150px}.core-form-design-container .field-setting-panel.open{right:0}.core-form-design-container .form-design-left{position:absolute;top:var(--size-core-page-header-height);bottom:0;left:0;z-index:1;width:360px;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));padding:15px;padding-right:calc(15px + var(--size-scrollbar-width));background-color:#87ceeb;overflow-y:hidden}.core-form-design-container .form-design-left .category-name{color:#fff}.core-form-design-container .form-design-left .grid-buffer-wrapper{background-color:#fff;padding:15px}.core-form-design-container .form-design-left ul:last-child{padding-bottom:400px}.core-form-design-container .form-design-left .category-name{margin-bottom:15px}.core-form-design-container .form-design-left .json-preview{background-color:#fff;color:#333;padding:1rem 1.5rem;box-shadow:0 2px 6px #00000014;font-family:Fira Code,monospace;font-size:.85rem;word-break:keep-all;overflow-x:auto;line-height:1.5;width:330px;height:calc(100vh - 205px)}.core-form-design-container .form-design-left button{height:35px;border-radius:0;margin-bottom:15px;color:#fff;border:none;font-size:13px;background-color:transparent}.core-form-design-container .form-design-left:hover{overflow-y:auto;padding-right:15px}.core-form-design-container .form-design-right{width:100%;height:calc(100vh - var(--size-header-height) - var(--size-layout-block-cell-spacing));padding:15px 15px 15px 375px;overflow-y:auto}.core-form-design-container .form-design-right .form-wrapper{width:100%;overflow-y:visible;background-color:#fff}.core-form-design-container .form-design-right .form-wrapper button{margin-left:12px;padding:4px 10px;border:1px solid #ccc;cursor:pointer;transition:all .2s;width:110px}.core-form-design-container .form-design-right .form-wrapper button:hover{background-color:#e4f0ff;border-color:#007bff;color:#007bff}.core-form-design-container .form-design-right .form-wrapper .form-tool-bar{display:flex;align-items:center;justify-content:flex-end}.core-form-design-container .form-design-right .form-wrapper .form-tool-bar>button{width:150px;margin:0}.core-form-design-container .form-design-right .form-wrapper .form-cells{display:flex;flex-direction:column;gap:32px;padding:20px 15px 15px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder{padding:12px 15px;border:1px dashed #ccc;background-color:#fff;box-shadow:0 2px 6px #0000000a}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header{display:flex;position:relative;align-items:center;justify-content:flex-start;font-weight:600;margin-bottom:12px;color:#333}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-img{width:34px;height:34px;border-radius:50%;background-color:#d3d3d3;float:left;background-image:url(/assets/images/info.svg);background-repeat:no-repeat;background-position:center;margin-right:8px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-img.calculated{background-image:url(/assets/images/sql-icon.svg);background-color:transparent;border-radius:0}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-tool{position:absolute;right:5px;top:6px;display:none;z-index:2;color:gray}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header .section-tool i{font-size:24px;color:#848484}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-section-placeholder .section-header:hover .section-tool{display:block}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .row-tool-bar{display:flex;align-items:center;justify-content:flex-end;margin-bottom:8px;height:24px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-row{display:flex;gap:15px;margin-bottom:15px;min-height:50px;background-color:#d3d3d3;padding:8px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell{flex:1;min-height:90px;background-color:#fcfcfc;border:1px dashed #ccc;position:relative;padding:20px 10px 10px;transition:border .2s ease-in-out}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell:before{content:attr(data-flex);position:absolute;top:2px;left:4px;font-size:10px;color:#999}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell label.required:after{content:\" *\";color:#ff040b}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar{position:absolute;right:7px;top:6px;display:none;z-index:2;color:gray}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul{display:flex}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul li div{display:flex;width:24px;height:24px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell .field-toolbar ul li div i{font-size:18px;width:18px;height:18px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell.has-control:hover .field-toolbar{display:flex}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .form-cell.active-drop{border-color:#007bff;background-color:#eef6ff;transition:.2s}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .placeholder{display:flex;align-items:center;justify-content:center;background-color:#fff;color:#007bff;padding:15px 0;width:100%;cursor:default}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .placeholder.calculated{color:#ff4500}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .icon-wrapper{width:24px;height:24px;border-radius:50%;padding:0;cursor:pointer;display:none;color:gray;border:1px solid gray;margin-left:8px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper .icon-wrapper i{font-size:18px;width:18px;height:18px}.core-form-design-container .form-design-right .form-wrapper .form-cells .form-row-wrapper:hover .icon-wrapper{display:flex}.core-form-design-container .form-design-right .form-wrapper .form-cell.selected{background-color:#dff6dd}.core-form-design-container .form-design-right .form-wrapper .merge-toolbar{text-align:center;margin-top:4px}.core-form-design-container .form-design-right .form-wrapper.live-form{padding-bottom:15px}.core-form-design-container .form-design-right .form-wrapper.live-form .live-form-header{padding:0 15px}.core-form-design-container .form-design-right .form-wrapper.live-form .live-form-header .preview-close-icon{position:absolute;right:7px;top:6px;z-index:2;color:gray;cursor:pointer}.core-form-design-container .form-design-right .form-wrapper.live-form .live-form-header .preview-close-icon i{font-size:18px}.core-form-design-container .drop-target{min-height:50px;min-width:50px;border:2px dashed transparent;transition:border .2s ease}.core-form-design-container .drop-target.active-drop{border-color:#007bff;background-color:#eaf4ff}.core-form-design-container .no-padding{padding:0!important}.core-form-design-container .modal-content-root{overflow:visible}\n", ".core-form-container{overflow-x:visible}.core-form-container>form .section{margin-top:var(--size-layout-block-cell-spacing)}.core-form-container>form .section:not(:first-child){margin-top:calc(var(--size-layout-block-cell-spacing) * 2)}.core-form-container>form .section .section-header-label{display:block;height:34px;line-height:34px;margin-bottom:15px;margin-left:12px}.core-form-container>form .section .section-header-label .section-img-wrapper{position:relative}.core-form-container>form .section .section-header-label .section-img-wrapper .section-img{position:absolute;width:34px;height:34px;border-radius:50%;background-color:#d3d3d3;float:left;background-image:url(/assets/images/info.svg);background-repeat:no-repeat;background-position:center}.core-form-container>form .section .section-header-label .section-img-wrapper .section-img.calculated{background-image:url(/assets/images/sql-icon.svg);border-radius:0;background-color:transparent}.core-form-container>form .section .section-header-label .section-calc-wrapper{width:34px;height:34px;display:flex;align-items:center;justify-content:center;background-color:#d3d3d3;border-radius:50%}.core-form-container>form .section .section-header-label .section-calc-wrapper i{width:24px;height:24px;font-size:24px;color:#1b4332}.core-form-container>form .section .section-header-label .section-caption{padding-left:40px;font-weight:700;color:#696969}.core-form-container .row{margin-left:var(--size-layout-block-cell-spacing) 0px;margin-right:var(--size-layout-block-cell-spacing) 0px}.core-form-container .row .grid-buffer{border:dotted 2px darkgray}.core-form-container .row .button-control{display:flex;align-items:flex-end}.core-form-container .form-row{margin:var(--size-layout-block-cell-spacing) 0px;display:flex;align-items:center;justify-content:center}.core-form-container .form-row>button{cursor:pointer;border-radius:0}.core-form-container .form-row>button:not(:first-child){margin-left:var(--size-layout-block-cell-spacing)}.core-form-container .dev-button{cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:13px;padding:8px;width:120px;border-radius:18px;box-shadow:.4rem 0 2rem #0000002e}.core-form-container .dev-button:not(:last-child){margin-right:15px}.core-form-container .dev-button:first-child{background-color:#dff6dd;border:1px #9fdc9d solid}.core-form-container .dev-button:last-child{background-color:#fff4ce;border:1px #ffda6a solid}.core-form-container .payload-preview{display:block;width:calc(100% - 48px);height:200px;white-space:pre-wrap;overflow-x:hidden;overflow-y:auto;background-color:#dff6dd;padding:24px;margin:24px;text-indent:-58px;color:#333!important;font-family:Fira Code,monospace;font-size:.85rem;word-break:keep-all;line-height:1.5}.core-form-container .payload-preview.validator-preview{background-color:#fff4ce}.core-form-container .bottom-template-wrapper{padding-left:12px;padding-right:12px}.core-form-container .w-100{width:100%}.core-form-container .pr18{padding-right:18px}\n", ".core-button-vns-container{height:30px;display:flex;align-items:center;justify-content:center;min-width:30px}.core-button-vns-container .action-wrapper{height:30px!important;width:30px!important;display:flex;align-items:center;justify-content:center}.core-button-vns-container .action-wrapper:has(i:hover){background-color:#e7e7e7;border-radius:50%}.core-button-vns-container .btn-for-form{border:none;border-radius:0;background-color:transparent;color:#000;min-width:120px}.core-button-vns-container button.last-child{background-color:#000;color:#fff}.core-button-vns-container .action-wrapper.last-child{background-color:var(--color-basic-orange);color:#fff;border-radius:50%}.core-button-vns-container .action-wrapper.last-child:hover{background-color:var(--color-basic-orange);box-shadow:0 1rem 3rem #0000002e}.core-button-vns-container .temporary-unavailable{user-select:none;-moz-user-select:none;-webkit-user-select:none;cursor:not-allowed!important;opacity:.5}.core-button-vns-container .temporary-unavailable:hover{background-color:transparent!important}\n"] }]
2429
3271
  }], ctorParameters: () => [{ type: MultiLanguageService }] });
2430
3272
 
2431
3273
  var coreFormDesign_component = /*#__PURE__*/Object.freeze({
@@ -2434,4 +3276,4 @@ var coreFormDesign_component = /*#__PURE__*/Object.freeze({
2434
3276
  });
2435
3277
 
2436
3278
  export { BasePropsComponent as B, CoreFormDesignComponent as C, coreFormDesign_component as c };
2437
- //# sourceMappingURL=ngx-histaff-alpha-core-form-design.component-KQsI4L2g.mjs.map
3279
+ //# sourceMappingURL=ngx-histaff-alpha-core-form-design.component-CGf-jOqR.mjs.map