@sd-angular/core 19.0.0-beta.93 → 19.0.0-beta.95

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 (143) hide show
  1. package/README.md +2 -1
  2. package/components/anchor/src/components/anchor/anchor.component.d.ts +4 -1
  3. package/components/anchor/src/components/anchor-item/anchor-item.component.d.ts +2 -1
  4. package/components/anchor/src/components/anchor-vertical/anchor-vertical-list.component.d.ts +3 -1
  5. package/components/document-builder/src/components/header-footer-builder/header-footer-builder.component.d.ts +4 -1
  6. package/components/document-builder/src/document-builder.model.d.ts +2 -0
  7. package/components/editor/src/models/editor.model.d.ts +2 -0
  8. package/components/editor/src/plugins/image-upload/utils/validate.utils.d.ts +2 -1
  9. package/components/form-generic/src/components/form-builder/components/attribute-table/attribute-table.component.d.ts +4 -2
  10. package/components/form-generic/src/components/form-builder/components/attribute-template/attribute-template.component.d.ts +2 -2
  11. package/components/form-generic/src/components/form-builder/components/configure-validation/configure-validation.component.d.ts +2 -2
  12. package/components/form-generic/src/components/form-builder/components/group/attribute/group-attribute.component.d.ts +23 -0
  13. package/components/form-generic/src/components/form-builder/components/group/index.d.ts +1 -0
  14. package/components/form-generic/src/components/form-builder/components/index.d.ts +1 -0
  15. package/components/form-generic/src/components/form-builder/components/table/control/table-control.component.d.ts +3 -0
  16. package/components/form-generic/src/components/form-builder/form-builder.component.d.ts +61 -18
  17. package/components/form-generic/src/components/form-render/form-render.component.d.ts +2 -2
  18. package/components/form-generic/src/models/form-generic-component.model.d.ts +22 -2
  19. package/components/index.d.ts +1 -0
  20. package/components/modal/src/modal.component.d.ts +4 -1
  21. package/components/preview/index.d.ts +3 -0
  22. package/components/preview/src/preview-image/preview-image.component.d.ts +84 -24
  23. package/components/preview/src/preview-image/preview-image.types.d.ts +53 -0
  24. package/components/preview/src/preview-pdf/preview-pdf.component.d.ts +186 -0
  25. package/components/preview/src/preview-pdf/preview-pdf.types.d.ts +84 -0
  26. package/components/quick-action/src/quick-action.component.d.ts +5 -6
  27. package/components/splitter/src/splitter.component.d.ts +15 -2
  28. package/components/table/src/components/selector-action/selector-action.component.d.ts +1 -0
  29. package/components/table/src/table.component.d.ts +3 -2
  30. package/components/upload-file/src/upload-file.component.d.ts +4 -1
  31. package/configurations/src/sd-core.configuration.d.ts +2 -0
  32. package/fesm2022/sd-angular-core-components-anchor.mjs +19 -6
  33. package/fesm2022/sd-angular-core-components-anchor.mjs.map +1 -1
  34. package/fesm2022/sd-angular-core-components-button.mjs +1 -1
  35. package/fesm2022/sd-angular-core-components-button.mjs.map +1 -1
  36. package/fesm2022/sd-angular-core-components-code-editor.mjs +3 -2
  37. package/fesm2022/sd-angular-core-components-code-editor.mjs.map +1 -1
  38. package/fesm2022/sd-angular-core-components-document-builder.mjs +29 -8
  39. package/fesm2022/sd-angular-core-components-document-builder.mjs.map +1 -1
  40. package/fesm2022/sd-angular-core-components-editor.mjs +32 -17
  41. package/fesm2022/sd-angular-core-components-editor.mjs.map +1 -1
  42. package/fesm2022/sd-angular-core-components-form-generic.mjs +632 -315
  43. package/fesm2022/sd-angular-core-components-form-generic.mjs.map +1 -1
  44. package/fesm2022/sd-angular-core-components-history.mjs +3 -2
  45. package/fesm2022/sd-angular-core-components-history.mjs.map +1 -1
  46. package/fesm2022/sd-angular-core-components-import-excel.mjs +25 -23
  47. package/fesm2022/sd-angular-core-components-import-excel.mjs.map +1 -1
  48. package/fesm2022/sd-angular-core-components-modal.mjs +8 -3
  49. package/fesm2022/sd-angular-core-components-modal.mjs.map +1 -1
  50. package/fesm2022/sd-angular-core-components-preview.mjs +1963 -89
  51. package/fesm2022/sd-angular-core-components-preview.mjs.map +1 -1
  52. package/fesm2022/sd-angular-core-components-quick-action.mjs +8 -19
  53. package/fesm2022/sd-angular-core-components-quick-action.mjs.map +1 -1
  54. package/fesm2022/sd-angular-core-components-splitter.mjs +188 -18
  55. package/fesm2022/sd-angular-core-components-splitter.mjs.map +1 -1
  56. package/fesm2022/sd-angular-core-components-tab-router.mjs +3 -1
  57. package/fesm2022/sd-angular-core-components-tab-router.mjs.map +1 -1
  58. package/fesm2022/sd-angular-core-components-table.mjs +42 -32
  59. package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
  60. package/fesm2022/sd-angular-core-components-upload-file.mjs +28 -21
  61. package/fesm2022/sd-angular-core-components-upload-file.mjs.map +1 -1
  62. package/fesm2022/sd-angular-core-components.mjs +1 -0
  63. package/fesm2022/sd-angular-core-components.mjs.map +1 -1
  64. package/fesm2022/sd-angular-core-configurations.mjs.map +1 -1
  65. package/fesm2022/sd-angular-core-directives.mjs +6 -2
  66. package/fesm2022/sd-angular-core-directives.mjs.map +1 -1
  67. package/fesm2022/sd-angular-core-forms-autocomplete.mjs +3 -1
  68. package/fesm2022/sd-angular-core-forms-autocomplete.mjs.map +1 -1
  69. package/fesm2022/sd-angular-core-forms-checkbox.mjs +6 -13
  70. package/fesm2022/sd-angular-core-forms-checkbox.mjs.map +1 -1
  71. package/fesm2022/sd-angular-core-forms-chip-calendar.mjs +9 -6
  72. package/fesm2022/sd-angular-core-forms-chip-calendar.mjs.map +1 -1
  73. package/fesm2022/sd-angular-core-forms-chip.mjs +9 -13
  74. package/fesm2022/sd-angular-core-forms-chip.mjs.map +1 -1
  75. package/fesm2022/sd-angular-core-forms-date-range.mjs +36 -26
  76. package/fesm2022/sd-angular-core-forms-date-range.mjs.map +1 -1
  77. package/fesm2022/sd-angular-core-forms-date.mjs +34 -22
  78. package/fesm2022/sd-angular-core-forms-date.mjs.map +1 -1
  79. package/fesm2022/sd-angular-core-forms-datetime.mjs +102 -59
  80. package/fesm2022/sd-angular-core-forms-datetime.mjs.map +1 -1
  81. package/fesm2022/sd-angular-core-forms-input-number.mjs +5 -3
  82. package/fesm2022/sd-angular-core-forms-input-number.mjs.map +1 -1
  83. package/fesm2022/sd-angular-core-forms-input.mjs +13 -6
  84. package/fesm2022/sd-angular-core-forms-input.mjs.map +1 -1
  85. package/fesm2022/sd-angular-core-forms-radio.mjs +7 -14
  86. package/fesm2022/sd-angular-core-forms-radio.mjs.map +1 -1
  87. package/fesm2022/sd-angular-core-forms-select.mjs +3 -1
  88. package/fesm2022/sd-angular-core-forms-select.mjs.map +1 -1
  89. package/fesm2022/sd-angular-core-forms-switch.mjs +6 -14
  90. package/fesm2022/sd-angular-core-forms-switch.mjs.map +1 -1
  91. package/fesm2022/sd-angular-core-forms-textarea.mjs +8 -5
  92. package/fesm2022/sd-angular-core-forms-textarea.mjs.map +1 -1
  93. package/fesm2022/sd-angular-core-handlers.mjs +7 -6
  94. package/fesm2022/sd-angular-core-handlers.mjs.map +1 -1
  95. package/fesm2022/sd-angular-core-i18n.mjs +2327 -0
  96. package/fesm2022/sd-angular-core-i18n.mjs.map +1 -0
  97. package/fesm2022/sd-angular-core-interceptors.mjs +10 -6
  98. package/fesm2022/sd-angular-core-interceptors.mjs.map +1 -1
  99. package/fesm2022/sd-angular-core-models.mjs +9 -0
  100. package/fesm2022/sd-angular-core-models.mjs.map +1 -0
  101. package/fesm2022/sd-angular-core-modules-authom.mjs +1 -0
  102. package/fesm2022/sd-angular-core-modules-authom.mjs.map +1 -1
  103. package/fesm2022/sd-angular-core-modules-keycloak.mjs +1 -0
  104. package/fesm2022/sd-angular-core-modules-keycloak.mjs.map +1 -1
  105. package/fesm2022/sd-angular-core-modules-layout.mjs +112 -63
  106. package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
  107. package/fesm2022/sd-angular-core-services-confirm.mjs +15 -13
  108. package/fesm2022/sd-angular-core-services-confirm.mjs.map +1 -1
  109. package/fesm2022/sd-angular-core-services-docx.mjs +7 -7
  110. package/fesm2022/sd-angular-core-services-docx.mjs.map +1 -1
  111. package/fesm2022/sd-angular-core-services-excel.mjs +30 -24
  112. package/fesm2022/sd-angular-core-services-excel.mjs.map +1 -1
  113. package/fesm2022/sd-angular-core-utilities-extensions.mjs +52 -11
  114. package/fesm2022/sd-angular-core-utilities-extensions.mjs.map +1 -1
  115. package/fesm2022/sd-angular-core-utilities-models.mjs +30 -28
  116. package/fesm2022/sd-angular-core-utilities-models.mjs.map +1 -1
  117. package/forms/checkbox/src/checkbox.component.d.ts +3 -3
  118. package/forms/chip/src/chip.component.d.ts +3 -2
  119. package/forms/chip-calendar/src/chip-calendar.component.d.ts +3 -2
  120. package/forms/date/src/date.component.d.ts +2 -3
  121. package/forms/date-range/src/date-range.component.d.ts +2 -3
  122. package/forms/datetime/src/datetime.component.d.ts +1 -0
  123. package/forms/datetime/src/popup/sd-datetime-picker.component.d.ts +10 -11
  124. package/forms/radio/src/radio.component.d.ts +3 -3
  125. package/forms/switch/src/switch.component.d.ts +3 -3
  126. package/i18n/index.d.ts +5 -0
  127. package/i18n/src/en.d.ts +400 -0
  128. package/i18n/src/i18n.messages.d.ts +2 -0
  129. package/i18n/src/i18n.pipe.d.ts +9 -0
  130. package/i18n/src/i18n.service.d.ts +14 -0
  131. package/i18n/src/i18n.token.d.ts +1 -0
  132. package/i18n/src/i18n.types.d.ts +31 -0
  133. package/i18n/src/ja.d.ts +2 -0
  134. package/i18n/src/ko.d.ts +2 -0
  135. package/i18n/src/vi.d.ts +2 -0
  136. package/i18n/src/zh.d.ts +2 -0
  137. package/models/index.d.ts +1 -0
  138. package/models/src/language.model.d.ts +4 -0
  139. package/modules/layout/modules/home/components/home-page/home-page.component.d.ts +25 -0
  140. package/package.json +74 -66
  141. package/sd-angular-core-19.0.0-beta.95.tgz +0 -0
  142. package/services/confirm/src/lib/confirm.service.d.ts +1 -0
  143. package/sd-angular-core-19.0.0-beta.93.tgz +0 -0
@@ -1,27 +1,27 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, Inject, Optional, Injectable, Pipe, SecurityContext, Input, ChangeDetectionStrategy, Component, ViewChild, EventEmitter, Output, ViewChildren, QueryList } from '@angular/core';
2
+ import { InjectionToken, Inject, Optional, Injectable, Pipe, SecurityContext, Input, ChangeDetectionStrategy, Component, ViewChild, EventEmitter, Output, ViewChildren, QueryList, inject, input, ChangeDetectorRef, effect, untracked, viewChild, signal, computed } from '@angular/core';
3
3
  import { SdUtilities, DateUtilities as DateUtilities$1, StringUtilities, ArrayUtilities, NumberUtilities } from '@sd-angular/core/utilities/extensions';
4
4
  import { DateUtilities, SdUtilities as SdUtilities$1, StringUtilities as StringUtilities$1 } from '@sd-angular/core/utilities';
5
- import * as i5 from '@angular/cdk/drag-drop';
5
+ import * as i3 from '@angular/cdk/drag-drop';
6
6
  import { moveItemInArray, transferArrayItem, DragDropModule } from '@angular/cdk/drag-drop';
7
7
  import * as i1$2 from '@angular/common';
8
8
  import { CommonModule } from '@angular/common';
9
9
  import { FormGroup, FormControl } from '@angular/forms';
10
- import * as i1$4 from '@angular/material/icon';
10
+ import * as i2 from '@angular/material/icon';
11
11
  import { MatIconModule } from '@angular/material/icon';
12
- import * as i4 from '@angular/material/tooltip';
12
+ import * as i2$1 from '@angular/material/tooltip';
13
13
  import { MatTooltipModule } from '@angular/material/tooltip';
14
14
  import { SdBaseSecureComponent } from '@sd-angular/core/components/base';
15
15
  import { SdButton } from '@sd-angular/core/components/button';
16
16
  import { SdModal } from '@sd-angular/core/components/modal';
17
17
  import { SdInput as SdInput$1 } from '@sd-angular/core/forms/input';
18
18
  import { SdTextarea } from '@sd-angular/core/forms/textarea';
19
- import * as i1 from '@sd-angular/core/pipes';
20
- import { SdSafeHtmlPipe } from '@sd-angular/core/pipes';
19
+ import { SdNotifyService, SdConfirmService } from '@sd-angular/core/services';
21
20
  import { Subscription, Subject, filter, debounceTime, startWith, combineLatest } from 'rxjs';
22
21
  import { SdSection } from '@sd-angular/core/components/section';
23
22
  import { startWith as startWith$1, debounceTime as debounceTime$1 } from 'rxjs/operators';
24
23
  import { SD_EMPTY_STR } from '@sd-angular/core/utilities/models';
24
+ import * as i1 from '@sd-angular/core/pipes';
25
25
  import * as i1$1 from '@angular/platform-browser';
26
26
  import { SdInput, SdChip, SdChipCalendar, SdSelect, SdAutocomplete, SdRadio, SdInputNumber as SdInputNumber$1 } from '@sd-angular/core/forms';
27
27
  import { SdInputNumber } from '@sd-angular/core/forms/input-number';
@@ -31,14 +31,14 @@ import * as i1$3 from '@angular/router';
31
31
  import { SdUploadFile } from '@sd-angular/core/components/upload-file';
32
32
  import { SdSideDrawer } from '@sd-angular/core/components/side-drawer';
33
33
  import { SdTable, SdTabelCellDefDirective } from '@sd-angular/core/components/table';
34
+ import { TranslatePipe, I18nService } from '@sd-angular/core/i18n';
34
35
  import { SdAutocomplete as SdAutocomplete$1 } from '@sd-angular/core/forms/autocomplete';
35
36
  import { SdSelect as SdSelect$1 } from '@sd-angular/core/forms/select';
36
37
  import { SdSuffixDefDirective } from '@sd-angular/core/forms/directives';
37
38
  import { MatDividerModule } from '@angular/material/divider';
38
39
  import { SdLabel } from '@sd-angular/core/forms/label';
39
- import * as i1$5 from '@angular/material/menu';
40
+ import * as i1$4 from '@angular/material/menu';
40
41
  import { MatMenuModule } from '@angular/material/menu';
41
- import * as i1$6 from '@sd-angular/core/services';
42
42
 
43
43
  /* eslint-disable @typescript-eslint/no-explicit-any */
44
44
  const SD_FORM_GENERIC_CONFIGURATION = new InjectionToken('sd.form-generic.configuration');
@@ -155,67 +155,27 @@ const TableColumnTypes = [
155
155
  },
156
156
  ];
157
157
  const FormBuilderComponents = [
158
- {
159
- type: 'textfield',
160
- icon: '<svg class="svg" fill="currentcolor" viewBox="0 0 54 54"><path fill-rule="evenodd" d="M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zm-32 4v10h-2V22h2z"></path></svg>',
161
- name: 'Text field',
162
- },
163
- {
164
- type: 'textarea',
165
- icon: '<svg class="svg" fill="currentcolor" viewBox="0 0 54 54"><path fill-rule="evenodd" d="M45 13a3 3 0 0 1 3 3v22a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V16a3 3 0 0 1 3-3zm0 2H9a1 1 0 0 0-1 1v22a1 1 0 0 0 1 1h36a1 1 0 0 0 1-1V16a1 1 0 0 0-1-1m-1.136 15.5.849.849-6.364 6.364-.849-.849zm.264 3.5.849.849-2.828 2.828-.849-.849zM13 19v10h-2V19z"></path></svg>',
166
- name: 'Text area',
167
- },
168
- {
169
- type: 'chip-string',
170
- icon: '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#5f6368"><path d="M160-240q-33 0-56.5-23.5T80-320v-320q0-33 23.5-56.5T160-720h640q33 0 56.5 23.5T880-640v320q0 33-23.5 56.5T800-240H160Zm0-80h640v-320H160v320Zm130-40h60v-90h90v-60h-90v-90h-60v90h-90v60h90v90Zm-130 40v-320 320Z"/></svg>',
171
- name: 'Chip string',
172
- },
173
- {
174
- type: 'chip-calendar',
175
- icon: '<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#5f6368"><path d="M160-240q-33 0-56.5-23.5T80-320v-320q0-33 23.5-56.5T160-720h640q33 0 56.5 23.5T880-640v320q0 33-23.5 56.5T800-240H160Zm0-80h640v-320H160v320Zm130-40h60v-90h90v-60h-90v-90h-60v90h-90v60h90v90Zm-130 40v-320 320Z"/></svg>',
176
- name: 'Chip calendar',
177
- },
178
- {
179
- type: 'number',
180
- icon: '<svg class="svg" fill="currentcolor" viewBox="0 0 54 54"><path fill-rule="evenodd" d="M45 16a3 3 0 0 1 3 3v16a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V19a3 3 0 0 1 3-3zm0 2H9a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h36a1 1 0 0 0 1-1V19a1 1 0 0 0-1-1M35 28.444h7l-3.5 4zM35 26h7l-3.5-4z"></path></svg>',
181
- name: 'Number',
182
- },
183
- {
184
- type: 'datetime',
185
- icon: '<svg class="svg" fill="currentcolor" viewBox="0 0 54 54"><path fill-rule="evenodd" d="M37.908 13.418h-5.004v-2.354h-1.766v2.354H21.13v-2.354h-1.766v2.354H14.36a2.07 2.07 0 0 0-2.06 2.06v23.549a2.07 2.07 0 0 0 2.06 2.06h6.77v-1.766h-6.358a.707.707 0 0 1-.706-.706V15.89c0-.39.316-.707.706-.707h4.592v2.355h1.766v-2.355h10.008v2.355h1.766v-2.355h4.592a.71.71 0 0 1 .707.707v6.358h1.765v-6.77c0-1.133-.927-2.06-2.06-2.06"></path><path d="m35.13 37.603 1.237-1.237-3.468-3.475v-5.926h-1.754v6.654l3.984 3.984Z"></path><path fill-rule="evenodd" d="M23.08 36.962a9.678 9.678 0 1 0 17.883-7.408 9.678 9.678 0 0 0-17.882 7.408Zm4.54-10.292a7.924 7.924 0 1 1 8.805 13.177A7.924 7.924 0 0 1 27.62 26.67"></path></svg>',
186
- name: 'Date',
187
- },
188
- {
189
- type: 'select',
190
- icon: '<svg class="svg" fill="currentcolor" viewBox="0 0 54 54"><path fill-rule="evenodd" d="M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zm-12 7h9l-4.5 6-4.5-6z"></path></svg>',
191
- name: 'Select',
192
- },
193
- {
194
- type: 'radio',
195
- icon: '<svg class="svg" fill="currentcolor" viewBox="0 0 54 54"><path fill-rule="evenodd" d="M27 22c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5m0-5c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10m0 18a8 8 0 1 1 0-16 8 8 0 1 1 0 16"></path></svg>',
196
- name: 'Radio',
197
- },
198
- {
199
- type: 'checkbox',
200
- icon: '<svg class="svg" fill="currentcolor" viewBox="0 0 54 54"><path fill-rule="evenodd" d="M34 18H20a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V20a2 2 0 0 0-2-2m-9 14-5-5 1.41-1.41L25 29.17l7.59-7.59L34 23z"></path></svg>',
201
- name: 'Check box',
202
- },
203
- {
204
- type: 'html',
205
- icon: '<span style="font-size:32px" class="material-icons">code</span>',
206
- name: 'HTML',
207
- },
208
- {
209
- type: 'upload',
210
- icon: '<svg class="svg" fill="currentcolor" class="fjs-palette-field-icon" viewBox="0 0 54 54"><path fill-rule="evenodd" d="M34.636 21.91A3.818 3.818 0 1127 21.908a3.818 3.818 0 017.636 0zm-2 0A1.818 1.818 0 1129 21.908a1.818 1.818 0 013.636 0z" clip-rule="evenodd"></path><path fill-rule="evenodd" d="M15 13a2 2 0 00-2 2v24a2 2 0 002 2h24a2 2 0 002-2V15a2 2 0 00-2-2H15zm24 2H15v12.45l4.71-4.709a1.91 1.91 0 012.702 0l6.695 6.695 2.656-1.77a1.91 1.91 0 012.411.239L39 32.73V15zM15 39v-8.754a.975.975 0 00.168-.135l5.893-5.893 6.684 6.685a1.911 1.911 0 002.41.238l2.657-1.77 6.02 6.02c.052.051.108.097.168.135V39H15z" clip-rule="evenodd"></path></svg>',
211
- name: 'Upload',
212
- },
213
- {
214
- type: 'table',
215
- icon: '<span style="font-size:32px" class="material-icons">table_chart</span>',
216
- name: 'Table',
217
- },
158
+ // ── Basic ───────────────────────────────────────────────────
159
+ { type: 'textfield', symbol: 'text_fields', group: 'basic', name: 'Text field' },
160
+ { type: 'textarea', symbol: 'notes', group: 'basic', name: 'Text area' },
161
+ { type: 'number', symbol: '123', group: 'basic', name: 'Number' },
162
+ { type: 'datetime', symbol: 'calendar_month', group: 'basic', name: 'Date' },
163
+ // ── Choice ──────────────────────────────────────────────────
164
+ { type: 'select', symbol: 'arrow_drop_down_circle', group: 'choice', name: 'Select' },
165
+ { type: 'radio', symbol: 'radio_button_checked', group: 'choice', name: 'Radio' },
166
+ { type: 'checkbox', symbol: 'check_box', group: 'choice', name: 'Check box' },
167
+ // ── Advanced ────────────────────────────────────────────────
168
+ { type: 'chip-string', symbol: 'label', group: 'advanced', name: 'Chip string' },
169
+ { type: 'chip-calendar', symbol: 'event_note', group: 'advanced', name: 'Chip calendar' },
170
+ { type: 'upload', symbol: 'upload_file', group: 'advanced', name: 'Upload' },
171
+ { type: 'table', symbol: 'table_rows', group: 'advanced', name: 'Table' },
172
+ // ── Layout ──────────────────────────────────────────────────
173
+ // Break KHÔNG có trong palette — thêm qua per-row "+ Break" quick-add button.
174
+ { type: 'group', symbol: 'category', group: 'layout', name: 'Group' },
175
+ { type: 'html', symbol: 'code_blocks', group: 'layout', name: 'HTML' },
218
176
  ];
177
+ /** Lookup: component type → Material Symbol + label, used by attribute panel header. */
178
+ const COMPONENT_ICONS = FormBuilderComponents.reduce((acc, c) => ({ ...acc, [c.type]: { symbol: c.symbol, label: c.name } }), {});
219
179
  const GetComponentAttributes = (components) => {
220
180
  const attributes = [];
221
181
  if (components.length) {
@@ -970,7 +930,8 @@ class WhenExpressionPipe {
970
930
  };
971
931
  transform(hashed, component, entity) {
972
932
  // Group và html chỉ xử lý ẩn/hiện
973
- if (component.type === 'group' || component.type === 'html') {
933
+ if (component.type === 'group' || component.type === 'html' || component.type === 'break') {
934
+ // Break/html/group: chỉ tính hidden (validate/disabled không áp dụng).
974
935
  return {
975
936
  hidden: this.#hidden(component, entity),
976
937
  disabled: false,
@@ -2227,7 +2188,7 @@ class UploadComponent {
2227
2188
  return await this.sdUploadFile?.upload();
2228
2189
  };
2229
2190
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: UploadComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
2230
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: UploadComponent, isStandalone: true, selector: "lib-upload", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _validator: ["validator", "_validator"] }, viewQueries: [{ propertyName: "sdUploadFile", first: true, predicate: SdUploadFile, descendants: true }], ngImport: i0, template: "@if (component && entity) {\r\n @if (viewed || component.properties?.viewed) {\r\n <div class=\"text-secondary\">{{ component.label || component.key }}</div>\r\n <sd-upload-file\r\n [type]=\"component.properties?.type\"\r\n [form]=\"form\"\r\n [model]=\"entity[component.key!]\"\r\n align=\"left\"\r\n [args]=\"component.properties?.args\"\r\n disabled\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"></sd-upload-file>\r\n } @else {\r\n <sd-upload-file\r\n [type]=\"component.properties?.type\"\r\n [form]=\"form\"\r\n [label]=\"component.label || component.key\"\r\n [(model)]=\"entity[component.key!]\"\r\n [max]=\"component.properties?.max\"\r\n [maxSize]=\"component.properties?.maxSize\"\r\n [extensions]=\"component.properties?.extensions\"\r\n [args]=\"component.properties?.args\"\r\n align=\"left\"\r\n [required]=\"component.validate?.required || required\"\r\n [disabled]=\"disabled\"\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"></sd-upload-file>\r\n }\r\n}\r\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdUploadFile, selector: "sd-upload-file", inputs: ["args", "label", "key", "description", "previewWidth", "previewHeight", "align", "upload", "details", "download", "imageValidator", "maxSize", "maxWidth", "maxHeight", "scaleToPixel", "form", "name", "required", "type", "helperText", "max", "maxOfImage", "extensions", "disabled", "model"], outputs: ["loaded", "filesChanged", "modelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2191
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: UploadComponent, isStandalone: true, selector: "lib-upload", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _validator: ["validator", "_validator"] }, viewQueries: [{ propertyName: "sdUploadFile", first: true, predicate: SdUploadFile, descendants: true }], ngImport: i0, template: "@if (component && entity) {\r\n @if (viewed || component.properties?.viewed) {\r\n <div class=\"text-secondary\">{{ component.label || component.key }}</div>\r\n <sd-upload-file\r\n [type]=\"component.properties?.type\"\r\n [form]=\"form\"\r\n [model]=\"entity[component.key!]\"\r\n align=\"left\"\r\n [args]=\"component.properties?.args\"\r\n disabled\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"></sd-upload-file>\r\n } @else {\r\n <sd-upload-file\r\n [type]=\"component.properties?.type\"\r\n [form]=\"form\"\r\n [label]=\"component.label || component.key\"\r\n [(model)]=\"entity[component.key!]\"\r\n [max]=\"component.properties?.max\"\r\n [maxSize]=\"component.properties?.maxSize\"\r\n [extensions]=\"component.properties?.extensions\"\r\n [args]=\"component.properties?.args\"\r\n align=\"left\"\r\n [required]=\"component.validate?.required || required\"\r\n [disabled]=\"disabled\"\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"></sd-upload-file>\r\n }\r\n}\r\n", styles: [":host{display:contents;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdUploadFile, selector: "sd-upload-file", inputs: ["autoId", "args", "label", "key", "description", "previewWidth", "previewHeight", "align", "upload", "details", "download", "imageValidator", "maxSize", "maxWidth", "maxHeight", "scaleToPixel", "form", "name", "required", "type", "helperText", "max", "maxOfImage", "extensions", "disabled", "model"], outputs: ["loaded", "filesChanged", "modelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2231
2192
  }
2232
2193
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: UploadComponent, decorators: [{
2233
2194
  type: Component,
@@ -2608,7 +2569,9 @@ class TableComponent {
2608
2569
  }
2609
2570
  };
2610
2571
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
2611
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TableComponent, isStandalone: true, selector: "lib-table", inputs: { setVariables: "setVariables", form: "form", _component: ["component", "_component"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "table", first: true, predicate: SdTable, descendants: true }, { propertyName: "sideDrawer", first: true, predicate: SdSideDrawer, descendants: true }, { propertyName: "uploadFiles", predicate: SdUploadFile, descendants: true }], ngImport: i0, template: "@if(component && tableOption) {\r\n <div style=\"width: 100%\">\r\n <sd-table [option]=\"tableOption\">\r\n @for(key of imageKeys; track key) {\r\n <ng-template [sdTableCellDef]=\"key\" let-item=\"item\">\r\n <sd-upload-file\r\n type=\"image\"\r\n [model]=\"item[key]\"\r\n [args]=\"getArgs(key)\"\r\n (modelChange)=\"onFileUploadChange(item, key, $event)\"\r\n align=\"left\"\r\n disabled\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"></sd-upload-file>\r\n </ng-template>\r\n }\r\n @for(key of fileKeys; track key) {\r\n <ng-template [sdTableCellDef]=\"key\" let-item=\"item\">\r\n <sd-upload-file\r\n [model]=\"item[key]\"\r\n [args]=\"getArgs(key)\"\r\n (modelChange)=\"onFileUploadChange(item, key, $event)\"\r\n align=\"left\"\r\n disabled\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"></sd-upload-file>\r\n </ng-template>\r\n }\r\n </sd-table>\r\n @if(!viewed && !component.properties?.viewed) {\r\n <sd-button\r\n prefixIcon=\"add\"\r\n color=\"primary\"\r\n (click)=\"onDetail()\"\r\n [title]=\"component.properties?.titleButtonCreate || 'Th\u00EAm m\u1EDBi'\"></sd-button>\r\n }\r\n @if(!viewed && !component.properties?.viewed) {\r\n <sd-side-drawer title=\"Chi ti\u1EBFt\" width=\"500px\">\r\n <div sdTitle>\r\n <span>T\u1EA1o m\u1EDBi/c\u1EADp nh\u1EADt</span>\r\n </div>\r\n <div sdBody class=\"c-table-create-update\">\r\n @if(!!component.columns?.length) {\r\n <div class=\"row mx-0\">\r\n @for(column of component.columns;track column.key) {\r\n @let validate = formRenderColumn[column.key].validate;\r\n <div class=\"col-12 px-0 mt-16\">\r\n @if(column.type === 'string') {\r\n <sd-input\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"\r\n [pattern]=\"column.validate?.pattern\"\r\n [patternErrorMessage]=\"column.validate?.patternErrorMessage\"></sd-input>\r\n }@else if(column.type === 'number') {\r\n <sd-input-number\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"\r\n [min]=\"column.validate?.min\"></sd-input-number>\r\n }@else if(column.type === 'radio') {\r\n <sd-radio\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [name]=\"column.key\"\r\n [items]=\"column.values\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [required]=\"validate?.required\"></sd-radio>\r\n }@else if(column.type === 'values') {\r\n <sd-autocomplete\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [items]=\"columnValues[column.key]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [required]=\"validate?.required\"></sd-autocomplete>\r\n }@else if(column.type === 'date') {\r\n <sd-date\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"></sd-date>\r\n }@else if(column.type === 'datetime') {\r\n <sd-datetime\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"></sd-datetime>\r\n }@else if(column.type === 'image') {\r\n <sd-upload-file\r\n [label]=\"column.label\"\r\n type=\"image\"\r\n [(model)]=\"row[column.key]\"\r\n [args]=\"column.args\"\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"\r\n align=\"left\"></sd-upload-file>\r\n }@else if (column.type === 'file') {\r\n <sd-upload-file\r\n [label]=\"column.label\"\r\n type=\"file\"\r\n [(model)]=\"row[column.key]\"\r\n [args]=\"column.args\"\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"\r\n align=\"left\"></sd-upload-file>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n \r\n </div>\r\n <div sdFooter class=\"text-right pr-16\">\r\n <sd-button title=\"L\u01B0u\" prefixIcon=\"save\" color=\"primary\" type=\"fill\" (click)=\"onAccept()\"></sd-button>\r\n </div>\r\n </sd-side-drawer>\r\n }\r\n </div>\r\n}\r\n\r\n", styles: [":host{display:contents}.c-table-create-update{background:#fff;margin:-16px;padding:16px;height:calc(100vh - 97px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber$1, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdAutocomplete, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdUploadFile, selector: "sd-upload-file", inputs: ["args", "label", "key", "description", "previewWidth", "previewHeight", "align", "upload", "details", "download", "imageValidator", "maxSize", "maxWidth", "maxHeight", "scaleToPixel", "form", "name", "required", "type", "helperText", "max", "maxOfImage", "extensions", "disabled", "model"], outputs: ["loaded", "filesChanged", "modelChange"] }, { kind: "component", type: SdTable, selector: "sd-table", inputs: ["autoId", "option"] }, { kind: "directive", type: SdTabelCellDefDirective, selector: "[sdTableCellDef]", inputs: ["sdTableCellDef"] }, { kind: "component", type: SdSideDrawer, selector: "sd-side-drawer", inputs: ["title", "width", "hideClose", "disableBackdropClose", "drawerClass"], outputs: ["sdClosed"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdRadio, selector: "sd-radio", inputs: ["autoId", "name", "form", "label", "placeholder", "display", "model", "items", "valueField", "displayField", "required", "inlineError", "disabled", "viewed", "hyperlink"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2572
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TableComponent, isStandalone: true, selector: "lib-table", inputs: { setVariables: "setVariables", form: "form", _component: ["component", "_component"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "table", first: true, predicate: SdTable, descendants: true }, { propertyName: "sideDrawer", first: true, predicate: SdSideDrawer, descendants: true }, { propertyName: "uploadFiles", predicate: SdUploadFile, descendants: true }], ngImport: i0, template: "@if(component && tableOption) {\r\n <div style=\"width: 100%\">\r\n <sd-table [option]=\"tableOption\">\r\n @for(key of imageKeys; track key) {\r\n <ng-template [sdTableCellDef]=\"key\" let-item=\"item\">\r\n <sd-upload-file\r\n type=\"image\"\r\n [model]=\"item[key]\"\r\n [args]=\"getArgs(key)\"\r\n (modelChange)=\"onFileUploadChange(item, key, $event)\"\r\n align=\"left\"\r\n disabled\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"></sd-upload-file>\r\n </ng-template>\r\n }\r\n @for(key of fileKeys; track key) {\r\n <ng-template [sdTableCellDef]=\"key\" let-item=\"item\">\r\n <sd-upload-file\r\n [model]=\"item[key]\"\r\n [args]=\"getArgs(key)\"\r\n (modelChange)=\"onFileUploadChange(item, key, $event)\"\r\n align=\"left\"\r\n disabled\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"></sd-upload-file>\r\n </ng-template>\r\n }\r\n </sd-table>\r\n @if(!viewed && !component.properties?.viewed) {\r\n <sd-button\r\n prefixIcon=\"add\"\r\n color=\"primary\"\r\n (click)=\"onDetail()\"\r\n [title]=\"component.properties?.titleButtonCreate || ('core.component.form-builder.add-new' | translate)\"></sd-button>\r\n }\r\n @if(!viewed && !component.properties?.viewed) {\r\n <sd-side-drawer [title]=\"'core.component.form-builder.detail' | translate\" width=\"500px\">\r\n <div sdTitle>\r\n <span>{{ 'core.component.form-builder.create-update' | translate }}</span>\r\n </div>\r\n <div sdBody class=\"c-table-create-update\">\r\n @if(!!component.columns?.length) {\r\n <div class=\"row mx-0\">\r\n @for(column of component.columns;track column.key) {\r\n @let validate = formRenderColumn[column.key].validate;\r\n <div class=\"col-12 px-0 mt-16\">\r\n @if(column.type === 'string') {\r\n <sd-input\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"\r\n [pattern]=\"column.validate?.pattern\"\r\n [patternErrorMessage]=\"column.validate?.patternErrorMessage\"></sd-input>\r\n }@else if(column.type === 'number') {\r\n <sd-input-number\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"\r\n [min]=\"column.validate?.min\"></sd-input-number>\r\n }@else if(column.type === 'radio') {\r\n <sd-radio\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [name]=\"column.key\"\r\n [items]=\"column.values\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [required]=\"validate?.required\"></sd-radio>\r\n }@else if(column.type === 'values') {\r\n <sd-autocomplete\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [items]=\"columnValues[column.key]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [required]=\"validate?.required\"></sd-autocomplete>\r\n }@else if(column.type === 'date') {\r\n <sd-date\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"></sd-date>\r\n }@else if(column.type === 'datetime') {\r\n <sd-datetime\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"></sd-datetime>\r\n }@else if(column.type === 'image') {\r\n <sd-upload-file\r\n [label]=\"column.label\"\r\n type=\"image\"\r\n [(model)]=\"row[column.key]\"\r\n [args]=\"column.args\"\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"\r\n align=\"left\"></sd-upload-file>\r\n }@else if (column.type === 'file') {\r\n <sd-upload-file\r\n [label]=\"column.label\"\r\n type=\"file\"\r\n [(model)]=\"row[column.key]\"\r\n [args]=\"column.args\"\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"\r\n align=\"left\"></sd-upload-file>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n \r\n </div>\r\n <div sdFooter class=\"text-right pr-16\">\r\n <sd-button [title]=\"'core.component.form-builder.save' | translate\" prefixIcon=\"save\" color=\"primary\" type=\"fill\" (click)=\"onAccept()\"></sd-button>\r\n </div>\r\n </sd-side-drawer>\r\n }\r\n </div>\r\n}\r\n\r\n", styles: [":host{display:contents}.c-table-create-update{background:#fff;margin:-16px;padding:16px;height:calc(100vh - 97px)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber$1, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdAutocomplete, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdUploadFile, selector: "sd-upload-file", inputs: ["autoId", "args", "label", "key", "description", "previewWidth", "previewHeight", "align", "upload", "details", "download", "imageValidator", "maxSize", "maxWidth", "maxHeight", "scaleToPixel", "form", "name", "required", "type", "helperText", "max", "maxOfImage", "extensions", "disabled", "model"], outputs: ["loaded", "filesChanged", "modelChange"] }, { kind: "component", type: SdTable, selector: "sd-table", inputs: ["autoId", "option"] }, { kind: "directive", type: SdTabelCellDefDirective, selector: "[sdTableCellDef]", inputs: ["sdTableCellDef"] }, { kind: "component", type: SdSideDrawer, selector: "sd-side-drawer", inputs: ["title", "width", "hideClose", "disableBackdropClose", "drawerClass"], outputs: ["sdClosed"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdRadio, selector: "sd-radio", inputs: ["autoId", "name", "form", "label", "placeholder", "display", "model", "items", "valueField", "displayField", "required", "inlineError", "disabled", "viewed", "hyperlink"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdDate, selector: "sd-date", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "pipe", type:
2573
+ // Pipe cho phần viewed
2574
+ TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2612
2575
  }
2613
2576
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableComponent, decorators: [{
2614
2577
  type: Component,
@@ -2627,7 +2590,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
2627
2590
  SdDate,
2628
2591
  SdDatetime,
2629
2592
  // Pipe cho phần viewed
2630
- ], template: "@if(component && tableOption) {\r\n <div style=\"width: 100%\">\r\n <sd-table [option]=\"tableOption\">\r\n @for(key of imageKeys; track key) {\r\n <ng-template [sdTableCellDef]=\"key\" let-item=\"item\">\r\n <sd-upload-file\r\n type=\"image\"\r\n [model]=\"item[key]\"\r\n [args]=\"getArgs(key)\"\r\n (modelChange)=\"onFileUploadChange(item, key, $event)\"\r\n align=\"left\"\r\n disabled\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"></sd-upload-file>\r\n </ng-template>\r\n }\r\n @for(key of fileKeys; track key) {\r\n <ng-template [sdTableCellDef]=\"key\" let-item=\"item\">\r\n <sd-upload-file\r\n [model]=\"item[key]\"\r\n [args]=\"getArgs(key)\"\r\n (modelChange)=\"onFileUploadChange(item, key, $event)\"\r\n align=\"left\"\r\n disabled\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"></sd-upload-file>\r\n </ng-template>\r\n }\r\n </sd-table>\r\n @if(!viewed && !component.properties?.viewed) {\r\n <sd-button\r\n prefixIcon=\"add\"\r\n color=\"primary\"\r\n (click)=\"onDetail()\"\r\n [title]=\"component.properties?.titleButtonCreate || 'Th\u00EAm m\u1EDBi'\"></sd-button>\r\n }\r\n @if(!viewed && !component.properties?.viewed) {\r\n <sd-side-drawer title=\"Chi ti\u1EBFt\" width=\"500px\">\r\n <div sdTitle>\r\n <span>T\u1EA1o m\u1EDBi/c\u1EADp nh\u1EADt</span>\r\n </div>\r\n <div sdBody class=\"c-table-create-update\">\r\n @if(!!component.columns?.length) {\r\n <div class=\"row mx-0\">\r\n @for(column of component.columns;track column.key) {\r\n @let validate = formRenderColumn[column.key].validate;\r\n <div class=\"col-12 px-0 mt-16\">\r\n @if(column.type === 'string') {\r\n <sd-input\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"\r\n [pattern]=\"column.validate?.pattern\"\r\n [patternErrorMessage]=\"column.validate?.patternErrorMessage\"></sd-input>\r\n }@else if(column.type === 'number') {\r\n <sd-input-number\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"\r\n [min]=\"column.validate?.min\"></sd-input-number>\r\n }@else if(column.type === 'radio') {\r\n <sd-radio\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [name]=\"column.key\"\r\n [items]=\"column.values\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [required]=\"validate?.required\"></sd-radio>\r\n }@else if(column.type === 'values') {\r\n <sd-autocomplete\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [items]=\"columnValues[column.key]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [required]=\"validate?.required\"></sd-autocomplete>\r\n }@else if(column.type === 'date') {\r\n <sd-date\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"></sd-date>\r\n }@else if(column.type === 'datetime') {\r\n <sd-datetime\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"></sd-datetime>\r\n }@else if(column.type === 'image') {\r\n <sd-upload-file\r\n [label]=\"column.label\"\r\n type=\"image\"\r\n [(model)]=\"row[column.key]\"\r\n [args]=\"column.args\"\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"\r\n align=\"left\"></sd-upload-file>\r\n }@else if (column.type === 'file') {\r\n <sd-upload-file\r\n [label]=\"column.label\"\r\n type=\"file\"\r\n [(model)]=\"row[column.key]\"\r\n [args]=\"column.args\"\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"\r\n align=\"left\"></sd-upload-file>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n \r\n </div>\r\n <div sdFooter class=\"text-right pr-16\">\r\n <sd-button title=\"L\u01B0u\" prefixIcon=\"save\" color=\"primary\" type=\"fill\" (click)=\"onAccept()\"></sd-button>\r\n </div>\r\n </sd-side-drawer>\r\n }\r\n </div>\r\n}\r\n\r\n", styles: [":host{display:contents}.c-table-create-update{background:#fff;margin:-16px;padding:16px;height:calc(100vh - 97px)}\n"] }]
2593
+ TranslatePipe,
2594
+ ], template: "@if(component && tableOption) {\r\n <div style=\"width: 100%\">\r\n <sd-table [option]=\"tableOption\">\r\n @for(key of imageKeys; track key) {\r\n <ng-template [sdTableCellDef]=\"key\" let-item=\"item\">\r\n <sd-upload-file\r\n type=\"image\"\r\n [model]=\"item[key]\"\r\n [args]=\"getArgs(key)\"\r\n (modelChange)=\"onFileUploadChange(item, key, $event)\"\r\n align=\"left\"\r\n disabled\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"></sd-upload-file>\r\n </ng-template>\r\n }\r\n @for(key of fileKeys; track key) {\r\n <ng-template [sdTableCellDef]=\"key\" let-item=\"item\">\r\n <sd-upload-file\r\n [model]=\"item[key]\"\r\n [args]=\"getArgs(key)\"\r\n (modelChange)=\"onFileUploadChange(item, key, $event)\"\r\n align=\"left\"\r\n disabled\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"></sd-upload-file>\r\n </ng-template>\r\n }\r\n </sd-table>\r\n @if(!viewed && !component.properties?.viewed) {\r\n <sd-button\r\n prefixIcon=\"add\"\r\n color=\"primary\"\r\n (click)=\"onDetail()\"\r\n [title]=\"component.properties?.titleButtonCreate || ('core.component.form-builder.add-new' | translate)\"></sd-button>\r\n }\r\n @if(!viewed && !component.properties?.viewed) {\r\n <sd-side-drawer [title]=\"'core.component.form-builder.detail' | translate\" width=\"500px\">\r\n <div sdTitle>\r\n <span>{{ 'core.component.form-builder.create-update' | translate }}</span>\r\n </div>\r\n <div sdBody class=\"c-table-create-update\">\r\n @if(!!component.columns?.length) {\r\n <div class=\"row mx-0\">\r\n @for(column of component.columns;track column.key) {\r\n @let validate = formRenderColumn[column.key].validate;\r\n <div class=\"col-12 px-0 mt-16\">\r\n @if(column.type === 'string') {\r\n <sd-input\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"\r\n [pattern]=\"column.validate?.pattern\"\r\n [patternErrorMessage]=\"column.validate?.patternErrorMessage\"></sd-input>\r\n }@else if(column.type === 'number') {\r\n <sd-input-number\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"\r\n [min]=\"column.validate?.min\"></sd-input-number>\r\n }@else if(column.type === 'radio') {\r\n <sd-radio\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [name]=\"column.key\"\r\n [items]=\"column.values\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [required]=\"validate?.required\"></sd-radio>\r\n }@else if(column.type === 'values') {\r\n <sd-autocomplete\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [items]=\"columnValues[column.key]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [required]=\"validate?.required\"></sd-autocomplete>\r\n }@else if(column.type === 'date') {\r\n <sd-date\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"></sd-date>\r\n }@else if(column.type === 'datetime') {\r\n <sd-datetime\r\n [form]=\"form\"\r\n [label]=\"column.label\"\r\n [(model)]=\"row[column.key]\"\r\n [required]=\"validate?.required\"></sd-datetime>\r\n }@else if(column.type === 'image') {\r\n <sd-upload-file\r\n [label]=\"column.label\"\r\n type=\"image\"\r\n [(model)]=\"row[column.key]\"\r\n [args]=\"column.args\"\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"\r\n align=\"left\"></sd-upload-file>\r\n }@else if (column.type === 'file') {\r\n <sd-upload-file\r\n [label]=\"column.label\"\r\n type=\"file\"\r\n [(model)]=\"row[column.key]\"\r\n [args]=\"column.args\"\r\n previewWidth=\"50px\"\r\n previewHeight=\"50px\"\r\n align=\"left\"></sd-upload-file>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n \r\n </div>\r\n <div sdFooter class=\"text-right pr-16\">\r\n <sd-button [title]=\"'core.component.form-builder.save' | translate\" prefixIcon=\"save\" color=\"primary\" type=\"fill\" (click)=\"onAccept()\"></sd-button>\r\n </div>\r\n </sd-side-drawer>\r\n }\r\n </div>\r\n}\r\n\r\n", styles: [":host{display:contents}.c-table-create-update{background:#fff;margin:-16px;padding:16px;height:calc(100vh - 97px)}\n"] }]
2631
2595
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: FormGenericService }], propDecorators: { uploadFiles: [{
2632
2596
  type: ViewChildren,
2633
2597
  args: [SdUploadFile]
@@ -2859,7 +2823,7 @@ class LibItemComponent {
2859
2823
  await this.itemTable?.upload?.();
2860
2824
  };
2861
2825
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LibItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2862
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: LibItemComponent, isStandalone: true, selector: "lib-item", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _validator: ["validator", "_validator"] }, viewQueries: [{ propertyName: "itemUpload", first: true, predicate: UploadComponent, descendants: true }, { propertyName: "itemTable", first: true, predicate: TableComponent, descendants: true }], ngImport: i0, template: "@if (entity && component) {\r\n @if (component.type === 'textfield') {\r\n <div [class]=\"col\">\r\n <lib-textfield\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [validator]=\"validator\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-textfield>\r\n </div>\r\n } @else if (component.type === 'textarea') {\r\n <div [class]=\"col\">\r\n <lib-textarea\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-textarea>\r\n </div>\r\n } @else if (component.type === 'chip-string') {\r\n <div [class]=\"col\">\r\n <lib-chip-string\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-chip-string>\r\n </div>\r\n } @else if (component.type === 'chip-calendar') {\r\n <div [class]=\"col\">\r\n <lib-chip-calendar\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-chip-calendar>\r\n </div>\r\n } @else if (component.type === 'number') {\r\n <div [class]=\"col\">\r\n <lib-number\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-number>\r\n </div>\r\n }\r\n @if (component.type === 'select') {\r\n <div [class]=\"col\">\r\n <lib-select\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [component]=\"component\"\r\n [entity]=\"entity\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [validator]=\"validator\"\r\n [viewed]=\"viewed\"></lib-select>\r\n </div>\r\n } @else if (component.type === 'radio') {\r\n <div [class]=\"col\">\r\n <lib-radio\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [component]=\"component\"\r\n [entity]=\"entity\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-radio>\r\n </div>\r\n } @else if (component.type === 'datetime') {\r\n <div [class]=\"col\">\r\n <lib-datetime\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-datetime>\r\n </div>\r\n } @else if (component.type === 'upload') {\r\n <div [class]=\"col\">\r\n <lib-upload\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [component]=\"component\"\r\n [entity]=\"entity\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [validator]=\"validator\"\r\n [viewed]=\"viewed\">\r\n </lib-upload>\r\n </div>\r\n } @else if (component.type === 'table') {\r\n <div [class]=\"col\">\r\n <lib-table [setVariables]=\"setVariables\" [component]=\"component\" [(model)]=\"entity[component.key!]\" [viewed]=\"viewed\"></lib-table>\r\n </div>\r\n } @else if (component.type === 'html') {\r\n <div [class]=\"col\">\r\n <lib-html [setVariables]=\"setVariables\" [form]=\"form\" [entity]=\"entity\" [component]=\"component\" [viewed]=\"viewed\"> </lib-html>\r\n </div>\r\n }\r\n}\r\n", styles: [":host{display:contents}\n"], dependencies: [{ kind: "component", type: TextfieldComponent, selector: "lib-textfield", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: TextareaComponent, selector: "lib-textarea", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: ChipStringComponent, selector: "lib-chip-string", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: ChipCalendarComponent, selector: "lib-chip-calendar", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: NumberComponent, selector: "lib-number", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: DatetimeComponent, selector: "lib-datetime", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: SelectComponent, selector: "lib-select", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: RadioComponent, selector: "lib-radio", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: TableComponent, selector: "lib-table", inputs: ["setVariables", "form", "component", "required", "viewed", "model"], outputs: ["modelChange"] }, { kind: "component", type: UploadComponent, selector: "lib-upload", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: HtmlComponent, selector: "lib-html", inputs: ["setVariables", "form", "entity", "hashedValues", "component", "viewed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2826
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: LibItemComponent, isStandalone: true, selector: "lib-item", inputs: { setVariables: "setVariables", form: "form", _entity: ["entity", "_entity"], _component: ["component", "_component"], _disabled: ["disabled", "_disabled"], _required: ["required", "_required"], _viewed: ["viewed", "_viewed"], _validator: ["validator", "_validator"] }, viewQueries: [{ propertyName: "itemUpload", first: true, predicate: UploadComponent, descendants: true }, { propertyName: "itemTable", first: true, predicate: TableComponent, descendants: true }], ngImport: i0, template: "@if (entity && component) {\r\n @if (component.type === 'textfield') {\r\n <div [class]=\"col\">\r\n <lib-textfield\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [validator]=\"validator\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-textfield>\r\n </div>\r\n } @else if (component.type === 'textarea') {\r\n <div [class]=\"col\">\r\n <lib-textarea\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-textarea>\r\n </div>\r\n } @else if (component.type === 'chip-string') {\r\n <div [class]=\"col\">\r\n <lib-chip-string\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-chip-string>\r\n </div>\r\n } @else if (component.type === 'chip-calendar') {\r\n <div [class]=\"col\">\r\n <lib-chip-calendar\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-chip-calendar>\r\n </div>\r\n } @else if (component.type === 'number') {\r\n <div [class]=\"col\">\r\n <lib-number\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-number>\r\n </div>\r\n }\r\n @if (component.type === 'select') {\r\n <div [class]=\"col\">\r\n <lib-select\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [component]=\"component\"\r\n [entity]=\"entity\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [validator]=\"validator\"\r\n [viewed]=\"viewed\"></lib-select>\r\n </div>\r\n } @else if (component.type === 'radio') {\r\n <div [class]=\"col\">\r\n <lib-radio\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [component]=\"component\"\r\n [entity]=\"entity\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-radio>\r\n </div>\r\n } @else if (component.type === 'datetime') {\r\n <div [class]=\"col\">\r\n <lib-datetime\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-datetime>\r\n </div>\r\n } @else if (component.type === 'upload') {\r\n <div [class]=\"col\">\r\n <lib-upload\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [component]=\"component\"\r\n [entity]=\"entity\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [validator]=\"validator\"\r\n [viewed]=\"viewed\">\r\n </lib-upload>\r\n </div>\r\n } @else if (component.type === 'table') {\r\n <div [class]=\"col\">\r\n <lib-table [setVariables]=\"setVariables\" [component]=\"component\" [(model)]=\"entity[component.key!]\" [viewed]=\"viewed\"></lib-table>\r\n </div>\r\n } @else if (component.type === 'html') {\r\n <div [class]=\"col\">\r\n <lib-html [setVariables]=\"setVariables\" [form]=\"form\" [entity]=\"entity\" [component]=\"component\" [viewed]=\"viewed\"> </lib-html>\r\n </div>\r\n } @else if (component.type === 'break') {\r\n <!-- Break: empty 12-col placeholder \u00E9p xu\u1ED1ng d\u00F2ng. Kh\u00F4ng render g\u00EC runtime. -->\r\n <div class=\"col-12\" style=\"height: 0;\"></div>\r\n }\r\n}\r\n", styles: [":host{display:contents}\n"], dependencies: [{ kind: "component", type: TextfieldComponent, selector: "lib-textfield", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: TextareaComponent, selector: "lib-textarea", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: ChipStringComponent, selector: "lib-chip-string", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: ChipCalendarComponent, selector: "lib-chip-calendar", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: NumberComponent, selector: "lib-number", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: DatetimeComponent, selector: "lib-datetime", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: SelectComponent, selector: "lib-select", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: RadioComponent, selector: "lib-radio", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed"] }, { kind: "component", type: TableComponent, selector: "lib-table", inputs: ["setVariables", "form", "component", "required", "viewed", "model"], outputs: ["modelChange"] }, { kind: "component", type: UploadComponent, selector: "lib-upload", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "component", type: HtmlComponent, selector: "lib-html", inputs: ["setVariables", "form", "entity", "hashedValues", "component", "viewed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2863
2827
  }
2864
2828
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: LibItemComponent, decorators: [{
2865
2829
  type: Component,
@@ -2875,7 +2839,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
2875
2839
  TableComponent,
2876
2840
  UploadComponent,
2877
2841
  HtmlComponent
2878
- ], template: "@if (entity && component) {\r\n @if (component.type === 'textfield') {\r\n <div [class]=\"col\">\r\n <lib-textfield\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [validator]=\"validator\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-textfield>\r\n </div>\r\n } @else if (component.type === 'textarea') {\r\n <div [class]=\"col\">\r\n <lib-textarea\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-textarea>\r\n </div>\r\n } @else if (component.type === 'chip-string') {\r\n <div [class]=\"col\">\r\n <lib-chip-string\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-chip-string>\r\n </div>\r\n } @else if (component.type === 'chip-calendar') {\r\n <div [class]=\"col\">\r\n <lib-chip-calendar\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-chip-calendar>\r\n </div>\r\n } @else if (component.type === 'number') {\r\n <div [class]=\"col\">\r\n <lib-number\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-number>\r\n </div>\r\n }\r\n @if (component.type === 'select') {\r\n <div [class]=\"col\">\r\n <lib-select\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [component]=\"component\"\r\n [entity]=\"entity\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [validator]=\"validator\"\r\n [viewed]=\"viewed\"></lib-select>\r\n </div>\r\n } @else if (component.type === 'radio') {\r\n <div [class]=\"col\">\r\n <lib-radio\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [component]=\"component\"\r\n [entity]=\"entity\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-radio>\r\n </div>\r\n } @else if (component.type === 'datetime') {\r\n <div [class]=\"col\">\r\n <lib-datetime\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-datetime>\r\n </div>\r\n } @else if (component.type === 'upload') {\r\n <div [class]=\"col\">\r\n <lib-upload\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [component]=\"component\"\r\n [entity]=\"entity\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [validator]=\"validator\"\r\n [viewed]=\"viewed\">\r\n </lib-upload>\r\n </div>\r\n } @else if (component.type === 'table') {\r\n <div [class]=\"col\">\r\n <lib-table [setVariables]=\"setVariables\" [component]=\"component\" [(model)]=\"entity[component.key!]\" [viewed]=\"viewed\"></lib-table>\r\n </div>\r\n } @else if (component.type === 'html') {\r\n <div [class]=\"col\">\r\n <lib-html [setVariables]=\"setVariables\" [form]=\"form\" [entity]=\"entity\" [component]=\"component\" [viewed]=\"viewed\"> </lib-html>\r\n </div>\r\n }\r\n}\r\n", styles: [":host{display:contents}\n"] }]
2842
+ ], template: "@if (entity && component) {\r\n @if (component.type === 'textfield') {\r\n <div [class]=\"col\">\r\n <lib-textfield\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [validator]=\"validator\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-textfield>\r\n </div>\r\n } @else if (component.type === 'textarea') {\r\n <div [class]=\"col\">\r\n <lib-textarea\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-textarea>\r\n </div>\r\n } @else if (component.type === 'chip-string') {\r\n <div [class]=\"col\">\r\n <lib-chip-string\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-chip-string>\r\n </div>\r\n } @else if (component.type === 'chip-calendar') {\r\n <div [class]=\"col\">\r\n <lib-chip-calendar\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-chip-calendar>\r\n </div>\r\n } @else if (component.type === 'number') {\r\n <div [class]=\"col\">\r\n <lib-number\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-number>\r\n </div>\r\n }\r\n @if (component.type === 'select') {\r\n <div [class]=\"col\">\r\n <lib-select\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [component]=\"component\"\r\n [entity]=\"entity\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [validator]=\"validator\"\r\n [viewed]=\"viewed\"></lib-select>\r\n </div>\r\n } @else if (component.type === 'radio') {\r\n <div [class]=\"col\">\r\n <lib-radio\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [component]=\"component\"\r\n [entity]=\"entity\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-radio>\r\n </div>\r\n } @else if (component.type === 'datetime') {\r\n <div [class]=\"col\">\r\n <lib-datetime\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [viewed]=\"viewed\"></lib-datetime>\r\n </div>\r\n } @else if (component.type === 'upload') {\r\n <div [class]=\"col\">\r\n <lib-upload\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [component]=\"component\"\r\n [entity]=\"entity\"\r\n [required]=\"required\"\r\n [disabled]=\"disabled\"\r\n [validator]=\"validator\"\r\n [viewed]=\"viewed\">\r\n </lib-upload>\r\n </div>\r\n } @else if (component.type === 'table') {\r\n <div [class]=\"col\">\r\n <lib-table [setVariables]=\"setVariables\" [component]=\"component\" [(model)]=\"entity[component.key!]\" [viewed]=\"viewed\"></lib-table>\r\n </div>\r\n } @else if (component.type === 'html') {\r\n <div [class]=\"col\">\r\n <lib-html [setVariables]=\"setVariables\" [form]=\"form\" [entity]=\"entity\" [component]=\"component\" [viewed]=\"viewed\"> </lib-html>\r\n </div>\r\n } @else if (component.type === 'break') {\r\n <!-- Break: empty 12-col placeholder \u00E9p xu\u1ED1ng d\u00F2ng. Kh\u00F4ng render g\u00EC runtime. -->\r\n <div class=\"col-12\" style=\"height: 0;\"></div>\r\n }\r\n}\r\n", styles: [":host{display:contents}\n"] }]
2879
2843
  }], propDecorators: { itemUpload: [{
2880
2844
  type: ViewChild,
2881
2845
  args: [UploadComponent]
@@ -3099,13 +3063,15 @@ class SdFormRender extends SdBaseSecureComponent {
3099
3063
  }
3100
3064
  return messages;
3101
3065
  };
3102
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdFormRender, deps: [{ token: i0.ChangeDetectorRef }, { token: SD_FORM_GENERIC_CONFIGURATION }], target: i0.ɵɵFactoryTarget.Component });
3066
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdFormRender, deps: [{ token: i0.ChangeDetectorRef }, { token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
3103
3067
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdFormRender, isStandalone: true, selector: "sd-form-render", inputs: { form: "form", _configuration: ["configuration", "_configuration"], _default: ["defaultEntity", "_default"], _entity: ["entity", "_entity"], _properties: ["properties", "_properties"], _viewed: ["viewed", "_viewed"] }, viewQueries: [{ propertyName: "formRenderItems", predicate: LibItemComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (form && loadCompleted && hashedValues) {\r\n <div class=\"row mx-0\">\r\n @for (component of configuration.components; track component.id) {\r\n @let expression = hashedValues | whenExpression: component : formValue;\r\n @if (!expression.hidden) {\r\n @if (component.type === 'group') {\r\n @if (!!component.components.length) {\r\n <div class=\"col-12 mt-16\">\r\n <sd-section [title]=\"component.label\" [icon]=\"component.properties.icon\">\r\n <div class=\"row mx-0\">\r\n @for (childComponent of component.components; track childComponent.id) {\r\n @let childExpression = hashedValues | whenExpression: childComponent : formValue;\r\n @if (!childExpression.hidden) {\r\n <lib-item\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"childComponent\"\r\n [required]=\"childExpression.required\"\r\n [disabled]=\"childExpression.disabled\"\r\n [viewed]=\"viewed\"></lib-item>\r\n }\r\n }\r\n </div>\r\n </sd-section>\r\n </div>\r\n }\r\n } @else {\r\n <lib-item\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"expression.required\"\r\n [disabled]=\"expression.disabled\"\r\n [viewed]=\"viewed\"></lib-item>\r\n }\r\n }\r\n }\r\n <variable [variables]=\"configuration.variables\" [setVariables]=\"setVariables\" [form]=\"form\" [entity]=\"entity\" ></variable>\r\n </div>\r\n}\r\n", styles: [":host{display:contents}\n"], dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: LibItemComponent, selector: "lib-item", inputs: ["setVariables", "form", "entity", "component", "disabled", "required", "viewed", "validator"] }, { kind: "pipe", type: WhenExpressionPipe, name: "whenExpression" }, { kind: "component", type: VariableComponent, selector: "variable", inputs: ["variables", "setVariables", "form", "entity"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3104
3068
  }
3105
3069
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdFormRender, decorators: [{
3106
3070
  type: Component,
3107
3071
  args: [{ selector: 'sd-form-render', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, LibItemComponent, WhenExpressionPipe, VariableComponent], template: "@if (form && loadCompleted && hashedValues) {\r\n <div class=\"row mx-0\">\r\n @for (component of configuration.components; track component.id) {\r\n @let expression = hashedValues | whenExpression: component : formValue;\r\n @if (!expression.hidden) {\r\n @if (component.type === 'group') {\r\n @if (!!component.components.length) {\r\n <div class=\"col-12 mt-16\">\r\n <sd-section [title]=\"component.label\" [icon]=\"component.properties.icon\">\r\n <div class=\"row mx-0\">\r\n @for (childComponent of component.components; track childComponent.id) {\r\n @let childExpression = hashedValues | whenExpression: childComponent : formValue;\r\n @if (!childExpression.hidden) {\r\n <lib-item\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"childComponent\"\r\n [required]=\"childExpression.required\"\r\n [disabled]=\"childExpression.disabled\"\r\n [viewed]=\"viewed\"></lib-item>\r\n }\r\n }\r\n </div>\r\n </sd-section>\r\n </div>\r\n }\r\n } @else {\r\n <lib-item\r\n [setVariables]=\"setVariables\"\r\n [form]=\"form\"\r\n [entity]=\"entity\"\r\n [component]=\"component\"\r\n [required]=\"expression.required\"\r\n [disabled]=\"expression.disabled\"\r\n [viewed]=\"viewed\"></lib-item>\r\n }\r\n }\r\n }\r\n <variable [variables]=\"configuration.variables\" [setVariables]=\"setVariables\" [form]=\"form\" [entity]=\"entity\" ></variable>\r\n </div>\r\n}\r\n", styles: [":host{display:contents}\n"] }]
3108
3072
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
3073
+ type: Optional
3074
+ }, {
3109
3075
  type: Inject,
3110
3076
  args: [SD_FORM_GENERIC_CONFIGURATION]
3111
3077
  }] }], propDecorators: { formRenderItems: [{
@@ -3253,7 +3219,7 @@ class ExpressionBuilderComponent {
3253
3219
  }
3254
3220
  };
3255
3221
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ExpressionBuilderComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
3256
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ExpressionBuilderComponent, isStandalone: true, selector: "expression-builder", inputs: { label: "label", _attributes: ["attributes", "_attributes"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange", edit: "edit" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<!-- <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ (model | expressionQuery) || '--' }}</a> -->\r\n<sd-input [label]=\"label\" style=\"width: 100%;\" [model]=\"(model | expressionQuery) || '--'\" disabled hideInlineError>\r\n <ng-template sdSuffixDef>\r\n <sd-button\r\n prefixIcon=\"edit\"\r\n color=\"primary\"\r\n (click)=\"onEdit()\"\r\n type=\"link\"></sd-button>\r\n </ng-template>\r\n</sd-input>\r\n@if (expression) {\r\n <sd-modal title=\"Thi\u1EBFt l\u1EADp bi\u1EC3u th\u1EE9c\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button\r\n prefixIcon=\"calculate\"\r\n class=\"mr-4\"\r\n title=\"Nh\u00F3m \u0111i\u1EC1u ki\u1EC7n\"\r\n color=\"primary\"\r\n (click)=\"addCombinator(expression.conditions)\"></sd-button>\r\n <sd-button\r\n prefixIcon=\"add\"\r\n title=\"\u0110i\u1EC1u ki\u1EC7n\"\r\n color=\"primary\"\r\n (click)=\"addCondition(expression.conditions)\"\r\n type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv1 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv1 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"expression.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv1.type === 'condition') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 200px\"\r\n [(model)]=\"conditionLv1.field\"\r\n [items]=\"attributes\"\r\n (sdChange)=\"onChangeAttribute(conditionLv1)\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv1.field!];\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 100px\"\r\n [(model)]=\"conditionLv1.operator\"\r\n [items]=\"attributeOperators[fieldAttribute?.type || 'string']\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"!fieldAttribute?.type\"\r\n required\r\n hideInlineError></sd-select>\r\n @if (\r\n !!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL'\r\n ) {\r\n @if (fieldAttribute.type === 'string') {\r\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\r\n } @else if (fieldAttribute.type === 'number') {\r\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"conditionLv1.value\" hideInlineError></sd-input-number>\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"numberAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n } @else if (fieldAttribute.type === 'datetime' && conditionLv1.dayInfo) {\r\n <sd-select\r\n size=\"sm\"\r\n placeholder=\"Th\u1EDDi \u0111i\u1EC3m\"\r\n [form]=\"form\"\r\n style=\"width: 150px\"\r\n [items]=\"types\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv1.dayInfo.type\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n @if (conditionLv1.dayInfo.type === 'RELATED') {\r\n <sd-input-number\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 80px\"\r\n [(model)]=\"conditionLv1.dayInfo.relatedValue\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n [min]=\"1\"\r\n required\r\n hideInlineError>\r\n </sd-input-number>\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [items]=\"previouses\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv1.dayInfo.related\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (conditionLv1.dayInfo.type === 'DATETIME') {\r\n <sd-datetime\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n required\r\n hideInlineError>\r\n </sd-datetime>\r\n } @else if (conditionLv1.dayInfo.type === 'ATTRIBUTE') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"dateAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n }\r\n } @else if (fieldAttribute.type === 'boolean') {\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"[\r\n { value: true, display: fieldAttribute.displayOnTrue },\r\n { value: false, display: fieldAttribute.displayOnFalse }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-select>\r\n } @else if (fieldAttribute.type === 'values') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"fieldAttribute.values\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button class=\"ml-auto\" prefixIcon=\"delete\" tooltip=\"X\u00F3a\" (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n } @else if (conditionLv1.type === 'combinator') {\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button class=\"mr-4\" prefixIcon=\"delete\" tooltip=\"X\u00F3a\" (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n <sd-button\r\n prefixIcon=\"add\"\r\n title=\"\u0110i\u1EC1u ki\u1EC7n\"\r\n size=\"sm\"\r\n color=\"primary\"\r\n (click)=\"addCondition(conditionLv1.conditions)\"\r\n type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 2 -->\r\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv2 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv2 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"conditionLv1.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv2.type === 'condition') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 200px\"\r\n [(model)]=\"conditionLv2.field\"\r\n [items]=\"attributes\"\r\n (sdChange)=\"onChangeAttribute(conditionLv2)\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv2.field!];\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 100px\"\r\n [(model)]=\"conditionLv2.operator\"\r\n [items]=\"attributeOperators[fieldAttribute?.type || 'string']\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"!fieldAttribute?.type\"\r\n required\r\n hideInlineError></sd-select>\r\n @if (\r\n !!fieldAttribute?.type &&\r\n conditionLv2.operator &&\r\n conditionLv2.operator !== 'NULL' &&\r\n conditionLv2.operator !== 'NOT_NULL'\r\n ) {\r\n @if (fieldAttribute.type === 'string') {\r\n <sd-input\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n required\r\n hideInlineError></sd-input>\r\n } @else if (fieldAttribute.type === 'number') {\r\n <sd-input-number\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n hideInlineError></sd-input-number>\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"numberAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n } @else if (fieldAttribute.type === 'datetime' && conditionLv2.dayInfo) {\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n placeholder=\"Th\u1EDDi \u0111i\u1EC3m\"\r\n style=\"width: 150px\"\r\n [items]=\"types\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv2.dayInfo.type\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n @if (conditionLv2.dayInfo.type === 'RELATED') {\r\n <sd-input-number\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 80px\"\r\n [(model)]=\"conditionLv2.dayInfo.relatedValue\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n [min]=\"1\"\r\n required\r\n hideInlineError>\r\n </sd-input-number>\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [items]=\"previouses\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv2.dayInfo.related\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (conditionLv2.dayInfo.type === 'DATETIME') {\r\n <sd-datetime\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n required\r\n hideInlineError>\r\n </sd-datetime>\r\n } @else if (conditionLv2.dayInfo.type === 'ATTRIBUTE') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"dateAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n }\r\n } @else if (fieldAttribute.type === 'boolean') {\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"[\r\n { value: true, display: fieldAttribute.displayOnTrue },\r\n { value: false, display: fieldAttribute.displayOnFalse }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-select>\r\n } @else if (fieldAttribute.type === 'values') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"fieldAttribute.values\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button\r\n class=\"ml-auto\"\r\n prefixIcon=\"delete\"\r\n tooltip=\"X\u00F3a\"\r\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"X\u00E1c nh\u1EADn\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: ExpressionQueryPipe, name: "expressionQuery" }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "directive", type: SdSuffixDefDirective, selector: "[sdSuffixDef]" }, { kind: "ngmodule", type: MatIconModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3222
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ExpressionBuilderComponent, isStandalone: true, selector: "expression-builder", inputs: { label: "label", _attributes: ["attributes", "_attributes"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange", edit: "edit" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<!--\r\n FEEL-style expression trigger pill (M3 redesign).\r\n B\u1EA5m v\u00E0o pill m\u1EDF modal builder hi\u1EC7n t\u1EA1i (onEdit).\r\n-->\r\n<div class=\"fb-field\">\r\n @if (label) {\r\n <div class=\"fb-field__label\">{{ label }}</div>\r\n }\r\n @let exprText = model | expressionQuery;\r\n <div class=\"fb-expr\" (click)=\"onEdit()\" role=\"button\" tabindex=\"0\">\r\n <span class=\"fb-expr__badge\">FEEL</span>\r\n @if (exprText) {\r\n <span class=\"fb-expr__code mono\">{{ exprText }}</span>\r\n } @else {\r\n <span class=\"empty\">{{ 'core.component.form-builder.set-expression' | translate }}</span>\r\n }\r\n <button type=\"button\" class=\"fb-icon-btn\" (click)=\"onEdit(); $event.stopPropagation()\" aria-label=\"edit expression\">\r\n <span class=\"msi\">functions</span>\r\n </button>\r\n </div>\r\n</div>\r\n@if (expression) {\r\n <sd-modal [title]=\"'core.component.form-builder.set-expression' | translate\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button\r\n prefixIcon=\"calculate\"\r\n class=\"mr-4\"\r\n [title]=\"'core.component.form-builder.condition-group' | translate\"\r\n color=\"primary\"\r\n (click)=\"addCombinator(expression.conditions)\"></sd-button>\r\n <sd-button\r\n prefixIcon=\"add\"\r\n [title]=\"'core.component.form-builder.condition' | translate\"\r\n color=\"primary\"\r\n (click)=\"addCondition(expression.conditions)\"\r\n type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv1 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv1 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"expression.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv1.type === 'condition') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 200px\"\r\n [(model)]=\"conditionLv1.field\"\r\n [items]=\"attributes\"\r\n (sdChange)=\"onChangeAttribute(conditionLv1)\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv1.field!];\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 100px\"\r\n [(model)]=\"conditionLv1.operator\"\r\n [items]=\"attributeOperators[fieldAttribute?.type || 'string']\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"!fieldAttribute?.type\"\r\n required\r\n hideInlineError></sd-select>\r\n @if (\r\n !!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL'\r\n ) {\r\n @if (fieldAttribute.type === 'string') {\r\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\r\n } @else if (fieldAttribute.type === 'number') {\r\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"conditionLv1.value\" hideInlineError></sd-input-number>\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"numberAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n } @else if (fieldAttribute.type === 'datetime' && conditionLv1.dayInfo) {\r\n <sd-select\r\n size=\"sm\"\r\n [placeholder]=\"'core.component.form-builder.time' | translate\"\r\n [form]=\"form\"\r\n style=\"width: 150px\"\r\n [items]=\"types\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv1.dayInfo.type\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n @if (conditionLv1.dayInfo.type === 'RELATED') {\r\n <sd-input-number\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 80px\"\r\n [(model)]=\"conditionLv1.dayInfo.relatedValue\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n [min]=\"1\"\r\n required\r\n hideInlineError>\r\n </sd-input-number>\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [items]=\"previouses\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv1.dayInfo.related\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (conditionLv1.dayInfo.type === 'DATETIME') {\r\n <sd-datetime\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n required\r\n hideInlineError>\r\n </sd-datetime>\r\n } @else if (conditionLv1.dayInfo.type === 'ATTRIBUTE') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"dateAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n }\r\n } @else if (fieldAttribute.type === 'boolean') {\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"[\r\n { value: true, display: fieldAttribute.displayOnTrue },\r\n { value: false, display: fieldAttribute.displayOnFalse }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-select>\r\n } @else if (fieldAttribute.type === 'values') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"fieldAttribute.values\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button class=\"ml-auto\" prefixIcon=\"delete\" [tooltip]=\"'core.component.form-builder.delete' | translate\" (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n } @else if (conditionLv1.type === 'combinator') {\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button class=\"mr-4\" prefixIcon=\"delete\" [tooltip]=\"'core.component.form-builder.delete' | translate\" (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n <sd-button\r\n prefixIcon=\"add\"\r\n [title]=\"'core.component.form-builder.condition' | translate\"\r\n size=\"sm\"\r\n color=\"primary\"\r\n (click)=\"addCondition(conditionLv1.conditions)\"\r\n type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 2 -->\r\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv2 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv2 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"conditionLv1.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv2.type === 'condition') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 200px\"\r\n [(model)]=\"conditionLv2.field\"\r\n [items]=\"attributes\"\r\n (sdChange)=\"onChangeAttribute(conditionLv2)\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv2.field!];\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 100px\"\r\n [(model)]=\"conditionLv2.operator\"\r\n [items]=\"attributeOperators[fieldAttribute?.type || 'string']\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"!fieldAttribute?.type\"\r\n required\r\n hideInlineError></sd-select>\r\n @if (\r\n !!fieldAttribute?.type &&\r\n conditionLv2.operator &&\r\n conditionLv2.operator !== 'NULL' &&\r\n conditionLv2.operator !== 'NOT_NULL'\r\n ) {\r\n @if (fieldAttribute.type === 'string') {\r\n <sd-input\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n required\r\n hideInlineError></sd-input>\r\n } @else if (fieldAttribute.type === 'number') {\r\n <sd-input-number\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n hideInlineError></sd-input-number>\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"numberAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n } @else if (fieldAttribute.type === 'datetime' && conditionLv2.dayInfo) {\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n [placeholder]=\"'core.component.form-builder.time' | translate\"\r\n style=\"width: 150px\"\r\n [items]=\"types\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv2.dayInfo.type\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n @if (conditionLv2.dayInfo.type === 'RELATED') {\r\n <sd-input-number\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 80px\"\r\n [(model)]=\"conditionLv2.dayInfo.relatedValue\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n [min]=\"1\"\r\n required\r\n hideInlineError>\r\n </sd-input-number>\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [items]=\"previouses\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv2.dayInfo.related\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (conditionLv2.dayInfo.type === 'DATETIME') {\r\n <sd-datetime\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n required\r\n hideInlineError>\r\n </sd-datetime>\r\n } @else if (conditionLv2.dayInfo.type === 'ATTRIBUTE') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"dateAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n }\r\n } @else if (fieldAttribute.type === 'boolean') {\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"[\r\n { value: true, display: fieldAttribute.displayOnTrue },\r\n { value: false, display: fieldAttribute.displayOnFalse }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-select>\r\n } @else if (fieldAttribute.type === 'values') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"fieldAttribute.values\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button\r\n class=\"ml-auto\"\r\n prefixIcon=\"delete\"\r\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: ExpressionQueryPipe, name: "expressionQuery" }, { kind: "component", type: SdDatetime, selector: "sd-datetime", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "required", "disabled", "viewed", "showSeconds", "inlineError", "hyperlink", "appearance", "floatLabel", "min", "minDate", "max", "maxDate", "model"], outputs: ["modelChange", "sdChange", "sdFocus"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3257
3223
  }
3258
3224
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ExpressionBuilderComponent, decorators: [{
3259
3225
  type: Component,
@@ -3268,8 +3234,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
3268
3234
  ExpressionQueryPipe,
3269
3235
  SdDatetime,
3270
3236
  SdSuffixDefDirective,
3271
- MatIconModule
3272
- ], template: "<!-- <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ (model | expressionQuery) || '--' }}</a> -->\r\n<sd-input [label]=\"label\" style=\"width: 100%;\" [model]=\"(model | expressionQuery) || '--'\" disabled hideInlineError>\r\n <ng-template sdSuffixDef>\r\n <sd-button\r\n prefixIcon=\"edit\"\r\n color=\"primary\"\r\n (click)=\"onEdit()\"\r\n type=\"link\"></sd-button>\r\n </ng-template>\r\n</sd-input>\r\n@if (expression) {\r\n <sd-modal title=\"Thi\u1EBFt l\u1EADp bi\u1EC3u th\u1EE9c\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button\r\n prefixIcon=\"calculate\"\r\n class=\"mr-4\"\r\n title=\"Nh\u00F3m \u0111i\u1EC1u ki\u1EC7n\"\r\n color=\"primary\"\r\n (click)=\"addCombinator(expression.conditions)\"></sd-button>\r\n <sd-button\r\n prefixIcon=\"add\"\r\n title=\"\u0110i\u1EC1u ki\u1EC7n\"\r\n color=\"primary\"\r\n (click)=\"addCondition(expression.conditions)\"\r\n type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv1 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv1 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"expression.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv1.type === 'condition') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 200px\"\r\n [(model)]=\"conditionLv1.field\"\r\n [items]=\"attributes\"\r\n (sdChange)=\"onChangeAttribute(conditionLv1)\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv1.field!];\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 100px\"\r\n [(model)]=\"conditionLv1.operator\"\r\n [items]=\"attributeOperators[fieldAttribute?.type || 'string']\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"!fieldAttribute?.type\"\r\n required\r\n hideInlineError></sd-select>\r\n @if (\r\n !!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL'\r\n ) {\r\n @if (fieldAttribute.type === 'string') {\r\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\r\n } @else if (fieldAttribute.type === 'number') {\r\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"conditionLv1.value\" hideInlineError></sd-input-number>\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"numberAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n } @else if (fieldAttribute.type === 'datetime' && conditionLv1.dayInfo) {\r\n <sd-select\r\n size=\"sm\"\r\n placeholder=\"Th\u1EDDi \u0111i\u1EC3m\"\r\n [form]=\"form\"\r\n style=\"width: 150px\"\r\n [items]=\"types\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv1.dayInfo.type\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n @if (conditionLv1.dayInfo.type === 'RELATED') {\r\n <sd-input-number\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 80px\"\r\n [(model)]=\"conditionLv1.dayInfo.relatedValue\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n [min]=\"1\"\r\n required\r\n hideInlineError>\r\n </sd-input-number>\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [items]=\"previouses\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv1.dayInfo.related\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (conditionLv1.dayInfo.type === 'DATETIME') {\r\n <sd-datetime\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n required\r\n hideInlineError>\r\n </sd-datetime>\r\n } @else if (conditionLv1.dayInfo.type === 'ATTRIBUTE') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"dateAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n }\r\n } @else if (fieldAttribute.type === 'boolean') {\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"[\r\n { value: true, display: fieldAttribute.displayOnTrue },\r\n { value: false, display: fieldAttribute.displayOnFalse }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-select>\r\n } @else if (fieldAttribute.type === 'values') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"fieldAttribute.values\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button class=\"ml-auto\" prefixIcon=\"delete\" tooltip=\"X\u00F3a\" (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n } @else if (conditionLv1.type === 'combinator') {\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button class=\"mr-4\" prefixIcon=\"delete\" tooltip=\"X\u00F3a\" (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n <sd-button\r\n prefixIcon=\"add\"\r\n title=\"\u0110i\u1EC1u ki\u1EC7n\"\r\n size=\"sm\"\r\n color=\"primary\"\r\n (click)=\"addCondition(conditionLv1.conditions)\"\r\n type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 2 -->\r\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv2 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv2 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"conditionLv1.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv2.type === 'condition') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 200px\"\r\n [(model)]=\"conditionLv2.field\"\r\n [items]=\"attributes\"\r\n (sdChange)=\"onChangeAttribute(conditionLv2)\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv2.field!];\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 100px\"\r\n [(model)]=\"conditionLv2.operator\"\r\n [items]=\"attributeOperators[fieldAttribute?.type || 'string']\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"!fieldAttribute?.type\"\r\n required\r\n hideInlineError></sd-select>\r\n @if (\r\n !!fieldAttribute?.type &&\r\n conditionLv2.operator &&\r\n conditionLv2.operator !== 'NULL' &&\r\n conditionLv2.operator !== 'NOT_NULL'\r\n ) {\r\n @if (fieldAttribute.type === 'string') {\r\n <sd-input\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n required\r\n hideInlineError></sd-input>\r\n } @else if (fieldAttribute.type === 'number') {\r\n <sd-input-number\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n hideInlineError></sd-input-number>\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"numberAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n } @else if (fieldAttribute.type === 'datetime' && conditionLv2.dayInfo) {\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n placeholder=\"Th\u1EDDi \u0111i\u1EC3m\"\r\n style=\"width: 150px\"\r\n [items]=\"types\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv2.dayInfo.type\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n @if (conditionLv2.dayInfo.type === 'RELATED') {\r\n <sd-input-number\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 80px\"\r\n [(model)]=\"conditionLv2.dayInfo.relatedValue\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n [min]=\"1\"\r\n required\r\n hideInlineError>\r\n </sd-input-number>\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [items]=\"previouses\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv2.dayInfo.related\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (conditionLv2.dayInfo.type === 'DATETIME') {\r\n <sd-datetime\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n required\r\n hideInlineError>\r\n </sd-datetime>\r\n } @else if (conditionLv2.dayInfo.type === 'ATTRIBUTE') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"dateAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n }\r\n } @else if (fieldAttribute.type === 'boolean') {\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"[\r\n { value: true, display: fieldAttribute.displayOnTrue },\r\n { value: false, display: fieldAttribute.displayOnFalse }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-select>\r\n } @else if (fieldAttribute.type === 'values') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"fieldAttribute.values\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button\r\n class=\"ml-auto\"\r\n prefixIcon=\"delete\"\r\n tooltip=\"X\u00F3a\"\r\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"X\u00E1c nh\u1EADn\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
3237
+ MatIconModule, TranslatePipe
3238
+ ], template: "<!--\r\n FEEL-style expression trigger pill (M3 redesign).\r\n B\u1EA5m v\u00E0o pill m\u1EDF modal builder hi\u1EC7n t\u1EA1i (onEdit).\r\n-->\r\n<div class=\"fb-field\">\r\n @if (label) {\r\n <div class=\"fb-field__label\">{{ label }}</div>\r\n }\r\n @let exprText = model | expressionQuery;\r\n <div class=\"fb-expr\" (click)=\"onEdit()\" role=\"button\" tabindex=\"0\">\r\n <span class=\"fb-expr__badge\">FEEL</span>\r\n @if (exprText) {\r\n <span class=\"fb-expr__code mono\">{{ exprText }}</span>\r\n } @else {\r\n <span class=\"empty\">{{ 'core.component.form-builder.set-expression' | translate }}</span>\r\n }\r\n <button type=\"button\" class=\"fb-icon-btn\" (click)=\"onEdit(); $event.stopPropagation()\" aria-label=\"edit expression\">\r\n <span class=\"msi\">functions</span>\r\n </button>\r\n </div>\r\n</div>\r\n@if (expression) {\r\n <sd-modal [title]=\"'core.component.form-builder.set-expression' | translate\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button\r\n prefixIcon=\"calculate\"\r\n class=\"mr-4\"\r\n [title]=\"'core.component.form-builder.condition-group' | translate\"\r\n color=\"primary\"\r\n (click)=\"addCombinator(expression.conditions)\"></sd-button>\r\n <sd-button\r\n prefixIcon=\"add\"\r\n [title]=\"'core.component.form-builder.condition' | translate\"\r\n color=\"primary\"\r\n (click)=\"addCondition(expression.conditions)\"\r\n type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv1 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv1 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"expression.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv1.type === 'condition') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 200px\"\r\n [(model)]=\"conditionLv1.field\"\r\n [items]=\"attributes\"\r\n (sdChange)=\"onChangeAttribute(conditionLv1)\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv1.field!];\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 100px\"\r\n [(model)]=\"conditionLv1.operator\"\r\n [items]=\"attributeOperators[fieldAttribute?.type || 'string']\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"!fieldAttribute?.type\"\r\n required\r\n hideInlineError></sd-select>\r\n @if (\r\n !!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL'\r\n ) {\r\n @if (fieldAttribute.type === 'string') {\r\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\r\n } @else if (fieldAttribute.type === 'number') {\r\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"conditionLv1.value\" hideInlineError></sd-input-number>\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"numberAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n } @else if (fieldAttribute.type === 'datetime' && conditionLv1.dayInfo) {\r\n <sd-select\r\n size=\"sm\"\r\n [placeholder]=\"'core.component.form-builder.time' | translate\"\r\n [form]=\"form\"\r\n style=\"width: 150px\"\r\n [items]=\"types\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv1.dayInfo.type\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n @if (conditionLv1.dayInfo.type === 'RELATED') {\r\n <sd-input-number\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 80px\"\r\n [(model)]=\"conditionLv1.dayInfo.relatedValue\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n [min]=\"1\"\r\n required\r\n hideInlineError>\r\n </sd-input-number>\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [items]=\"previouses\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv1.dayInfo.related\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (conditionLv1.dayInfo.type === 'DATETIME') {\r\n <sd-datetime\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv1)\"\r\n required\r\n hideInlineError>\r\n </sd-datetime>\r\n } @else if (conditionLv1.dayInfo.type === 'ATTRIBUTE') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"dateAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n }\r\n } @else if (fieldAttribute.type === 'boolean') {\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"[\r\n { value: true, display: fieldAttribute.displayOnTrue },\r\n { value: false, display: fieldAttribute.displayOnFalse }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-select>\r\n } @else if (fieldAttribute.type === 'values') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv1.value\"\r\n [items]=\"fieldAttribute.values\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button class=\"ml-auto\" prefixIcon=\"delete\" [tooltip]=\"'core.component.form-builder.delete' | translate\" (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n } @else if (conditionLv1.type === 'combinator') {\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button class=\"mr-4\" prefixIcon=\"delete\" [tooltip]=\"'core.component.form-builder.delete' | translate\" (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n <sd-button\r\n prefixIcon=\"add\"\r\n [title]=\"'core.component.form-builder.condition' | translate\"\r\n size=\"sm\"\r\n color=\"primary\"\r\n (click)=\"addCondition(conditionLv1.conditions)\"\r\n type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 2 -->\r\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv2 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv2 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"conditionLv1.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv2.type === 'condition') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 200px\"\r\n [(model)]=\"conditionLv2.field\"\r\n [items]=\"attributes\"\r\n (sdChange)=\"onChangeAttribute(conditionLv2)\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv2.field!];\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 100px\"\r\n [(model)]=\"conditionLv2.operator\"\r\n [items]=\"attributeOperators[fieldAttribute?.type || 'string']\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"!fieldAttribute?.type\"\r\n required\r\n hideInlineError></sd-select>\r\n @if (\r\n !!fieldAttribute?.type &&\r\n conditionLv2.operator &&\r\n conditionLv2.operator !== 'NULL' &&\r\n conditionLv2.operator !== 'NOT_NULL'\r\n ) {\r\n @if (fieldAttribute.type === 'string') {\r\n <sd-input\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n required\r\n hideInlineError></sd-input>\r\n } @else if (fieldAttribute.type === 'number') {\r\n <sd-input-number\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n hideInlineError></sd-input-number>\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"numberAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n } @else if (fieldAttribute.type === 'datetime' && conditionLv2.dayInfo) {\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n [placeholder]=\"'core.component.form-builder.time' | translate\"\r\n style=\"width: 150px\"\r\n [items]=\"types\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv2.dayInfo.type\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n @if (conditionLv2.dayInfo.type === 'RELATED') {\r\n <sd-input-number\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"width: 80px\"\r\n [(model)]=\"conditionLv2.dayInfo.relatedValue\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n [min]=\"1\"\r\n required\r\n hideInlineError>\r\n </sd-input-number>\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [items]=\"previouses\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [(model)]=\"conditionLv2.dayInfo.related\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n required\r\n hideInlineError>\r\n </sd-select>\r\n } @else if (conditionLv2.dayInfo.type === 'DATETIME') {\r\n <sd-datetime\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n (sdChange)=\"onChangeDateInfo(conditionLv2)\"\r\n required\r\n hideInlineError>\r\n </sd-datetime>\r\n } @else if (conditionLv2.dayInfo.type === 'ATTRIBUTE') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"dateAttributes\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n }\r\n } @else if (fieldAttribute.type === 'boolean') {\r\n <sd-select\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"[\r\n { value: true, display: fieldAttribute.displayOnTrue },\r\n { value: false, display: fieldAttribute.displayOnFalse }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-select>\r\n } @else if (fieldAttribute.type === 'values') {\r\n <sd-autocomplete\r\n size=\"sm\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"conditionLv2.value\"\r\n [items]=\"fieldAttribute.values\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button\r\n class=\"ml-auto\"\r\n prefixIcon=\"delete\"\r\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
3273
3239
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { modal: [{
3274
3240
  type: ViewChild,
3275
3241
  args: [SdModal]
@@ -3444,11 +3410,11 @@ class AttributeInputNumber {
3444
3410
  this.modelChange.emit(value);
3445
3411
  };
3446
3412
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeInputNumber, deps: [], target: i0.ɵɵFactoryTarget.Component });
3447
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: AttributeInputNumber, isStandalone: true, selector: "attribute-input-number", inputs: { _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-input-number\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"model\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-input-number>\r\n</div> -->\r\n<sd-input-number\r\n class=\"py-8\"\r\n [label]=\"label!\"\r\n [(model)]=\"model\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-input-number>\r\n", dependencies: [{ kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }] });
3413
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: AttributeInputNumber, isStandalone: true, selector: "attribute-input-number", inputs: { _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-input-number\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"model\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-input-number>\r\n</div> -->\r\n<sd-input-number\r\n class=\"py-8\"\r\n size=\"sm\"\r\n [label]=\"label!\"\r\n [(model)]=\"model\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-input-number>\r\n", dependencies: [{ kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }] });
3448
3414
  }
3449
3415
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeInputNumber, decorators: [{
3450
3416
  type: Component,
3451
- args: [{ selector: 'attribute-input-number', imports: [SdInputNumber], template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-input-number\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"model\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-input-number>\r\n</div> -->\r\n<sd-input-number\r\n class=\"py-8\"\r\n [label]=\"label!\"\r\n [(model)]=\"model\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-input-number>\r\n" }]
3417
+ args: [{ selector: 'attribute-input-number', imports: [SdInputNumber], template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-input-number\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"model\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-input-number>\r\n</div> -->\r\n<sd-input-number\r\n class=\"py-8\"\r\n size=\"sm\"\r\n [label]=\"label!\"\r\n [(model)]=\"model\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-input-number>\r\n" }]
3452
3418
  }], propDecorators: { _label: [{
3453
3419
  type: Input,
3454
3420
  args: ['label']
@@ -3486,11 +3452,11 @@ class AttributeInput {
3486
3452
  this.sdChange.emit(value);
3487
3453
  };
3488
3454
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
3489
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: AttributeInput, isStandalone: true, selector: "attribute-input", inputs: { form: "form", _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-input style=\"width: 200px\" size=\"sm\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\r\n</div> -->\r\n<sd-input class=\"py-8\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\r\n", dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }] });
3455
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: AttributeInput, isStandalone: true, selector: "attribute-input", inputs: { form: "form", _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-input style=\"width: 200px\" size=\"sm\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\r\n</div> -->\r\n<sd-input class=\"py-8\" size=\"sm\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\r\n", dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }] });
3490
3456
  }
3491
3457
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeInput, decorators: [{
3492
3458
  type: Component,
3493
- args: [{ selector: 'attribute-input', imports: [SdInput$1], template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-input style=\"width: 200px\" size=\"sm\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\r\n</div> -->\r\n<sd-input class=\"py-8\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\r\n" }]
3459
+ args: [{ selector: 'attribute-input', imports: [SdInput$1], template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-input style=\"width: 200px\" size=\"sm\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\r\n</div> -->\r\n<sd-input class=\"py-8\" size=\"sm\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-input>\r\n" }]
3494
3460
  }], propDecorators: { form: [{
3495
3461
  type: Input
3496
3462
  }], _label: [{
@@ -3527,11 +3493,11 @@ class AttributeSwitch {
3527
3493
  this.modelChange.emit(!!value);
3528
3494
  };
3529
3495
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeSwitch, deps: [], target: i0.ɵɵFactoryTarget.Component });
3530
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: AttributeSwitch, isStandalone: true, selector: "attribute-switch", inputs: { form: "form", _label: ["label", "_label"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-switch size=\"sm\" [form]=\"form\" [(model)]=\"model\" (sdChange)=\"onChange($event)\" hideInlineError></sd-switch>\r\n</div> -->\r\n<sd-select\r\n class=\"py-8\"\r\n [label]=\"label!\"\r\n [form]=\"form\"\r\n [(model)]=\"model\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [items]=\"[\r\n { value: true, display: 'C\u00F3' },\r\n { value: false, display: 'Kh\u00F4ng' }\r\n ]\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-select>\r\n", dependencies: [{ kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }] });
3496
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: AttributeSwitch, isStandalone: true, selector: "attribute-switch", inputs: { form: "form", _label: ["label", "_label"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-switch size=\"sm\" [form]=\"form\" [(model)]=\"model\" (sdChange)=\"onChange($event)\" hideInlineError></sd-switch>\r\n</div> -->\r\n<sd-select\r\n class=\"py-8\"\r\n size=\"sm\"\r\n [label]=\"label!\"\r\n [form]=\"form\"\r\n [(model)]=\"model\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [items]=\"[\r\n { value: true, display: ('core.confirm.yes-short' | translate) },\r\n { value: false, display: ('core.confirm.no-short' | translate) }\r\n ]\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-select>\r\n", dependencies: [{ kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
3531
3497
  }
3532
3498
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeSwitch, decorators: [{
3533
3499
  type: Component,
3534
- args: [{ selector: 'attribute-switch', imports: [SdSelect$1], template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-switch size=\"sm\" [form]=\"form\" [(model)]=\"model\" (sdChange)=\"onChange($event)\" hideInlineError></sd-switch>\r\n</div> -->\r\n<sd-select\r\n class=\"py-8\"\r\n [label]=\"label!\"\r\n [form]=\"form\"\r\n [(model)]=\"model\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [items]=\"[\r\n { value: true, display: 'C\u00F3' },\r\n { value: false, display: 'Kh\u00F4ng' }\r\n ]\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-select>\r\n" }]
3500
+ args: [{ selector: 'attribute-switch', imports: [SdSelect$1, TranslatePipe], template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-switch size=\"sm\" [form]=\"form\" [(model)]=\"model\" (sdChange)=\"onChange($event)\" hideInlineError></sd-switch>\r\n</div> -->\r\n<sd-select\r\n class=\"py-8\"\r\n size=\"sm\"\r\n [label]=\"label!\"\r\n [form]=\"form\"\r\n [(model)]=\"model\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [items]=\"[\r\n { value: true, display: ('core.confirm.yes-short' | translate) },\r\n { value: false, display: ('core.confirm.no-short' | translate) }\r\n ]\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-select>\r\n" }]
3535
3501
  }], propDecorators: { form: [{
3536
3502
  type: Input
3537
3503
  }], _label: [{
@@ -3566,13 +3532,15 @@ class AttributeTemplate {
3566
3532
  }
3567
3533
  }
3568
3534
  };
3569
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeTemplate, deps: [{ token: SD_FORM_GENERIC_CONFIGURATION }], target: i0.ɵɵFactoryTarget.Component });
3570
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: AttributeTemplate, isStandalone: true, selector: "attribute-template", inputs: { _component: ["component", "_component"] }, outputs: { sdChange: "sdChange" }, ngImport: i0, template: "@if (templates.length) {\r\n <!-- <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">D\u1EEF li\u1EC7u m\u1EABu</div>\r\n <sd-autocomplete\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"component.template\"\r\n [items]=\"templates\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-autocomplete>\r\n </div> -->\r\n <sd-autocomplete\r\n class=\"py-8\"\r\n label=\"D\u1EEF li\u1EC7u m\u1EABu\"\r\n [(model)]=\"component.template\"\r\n [items]=\"templates\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-autocomplete>\r\n}\r\n", dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }] });
3535
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeTemplate, deps: [{ token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
3536
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: AttributeTemplate, isStandalone: true, selector: "attribute-template", inputs: { _component: ["component", "_component"] }, outputs: { sdChange: "sdChange" }, ngImport: i0, template: "@if (templates.length) {\r\n <!-- <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">D\u1EEF li\u1EC7u m\u1EABu</div>\r\n <sd-autocomplete\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"component.template\"\r\n [items]=\"templates\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-autocomplete>\r\n </div> -->\r\n <sd-autocomplete\r\n class=\"py-8\"\r\n size=\"sm\"\r\n [label]=\"'core.component.form-builder.template-data' | translate\"\r\n [(model)]=\"component.template\"\r\n [items]=\"templates\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-autocomplete>\r\n}\r\n", dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
3571
3537
  }
3572
3538
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeTemplate, decorators: [{
3573
3539
  type: Component,
3574
- args: [{ selector: 'attribute-template', imports: [SdAutocomplete$1], template: "@if (templates.length) {\r\n <!-- <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">D\u1EEF li\u1EC7u m\u1EABu</div>\r\n <sd-autocomplete\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"component.template\"\r\n [items]=\"templates\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-autocomplete>\r\n </div> -->\r\n <sd-autocomplete\r\n class=\"py-8\"\r\n label=\"D\u1EEF li\u1EC7u m\u1EABu\"\r\n [(model)]=\"component.template\"\r\n [items]=\"templates\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-autocomplete>\r\n}\r\n" }]
3540
+ args: [{ selector: 'attribute-template', imports: [SdAutocomplete$1, TranslatePipe], template: "@if (templates.length) {\r\n <!-- <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">D\u1EEF li\u1EC7u m\u1EABu</div>\r\n <sd-autocomplete\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"component.template\"\r\n [items]=\"templates\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-autocomplete>\r\n </div> -->\r\n <sd-autocomplete\r\n class=\"py-8\"\r\n size=\"sm\"\r\n [label]=\"'core.component.form-builder.template-data' | translate\"\r\n [(model)]=\"component.template\"\r\n [items]=\"templates\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-autocomplete>\r\n}\r\n" }]
3575
3541
  }], ctorParameters: () => [{ type: undefined, decorators: [{
3542
+ type: Optional
3543
+ }, {
3576
3544
  type: Inject,
3577
3545
  args: [SD_FORM_GENERIC_CONFIGURATION]
3578
3546
  }] }], propDecorators: { _component: [{
@@ -3606,11 +3574,11 @@ class AttributeTextarea {
3606
3574
  this.sdChange.emit(value);
3607
3575
  };
3608
3576
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
3609
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: AttributeTextarea, isStandalone: true, selector: "attribute-textarea", inputs: { form: "form", _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "<sd-textarea class=\"py-8\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-textarea>", dependencies: [{ kind: "component", type: SdTextarea, selector: "sd-textarea", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "rows", "hideInlineError", "required", "disabled", "viewed", "autoHeight", "maxlength", "pattern", "validator", "inlineError", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange"] }] });
3577
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: AttributeTextarea, isStandalone: true, selector: "attribute-textarea", inputs: { form: "form", _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "<sd-textarea class=\"py-8\" size=\"sm\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-textarea>", dependencies: [{ kind: "component", type: SdTextarea, selector: "sd-textarea", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "rows", "hideInlineError", "required", "disabled", "viewed", "autoHeight", "maxlength", "pattern", "validator", "inlineError", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange"] }] });
3610
3578
  }
3611
3579
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeTextarea, decorators: [{
3612
3580
  type: Component,
3613
- args: [{ selector: 'attribute-textarea', imports: [SdTextarea], template: "<sd-textarea class=\"py-8\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-textarea>" }]
3581
+ args: [{ selector: 'attribute-textarea', imports: [SdTextarea], template: "<sd-textarea class=\"py-8\" size=\"sm\" [label]=\"label!\" [form]=\"form\" [(model)]=\"model\" [disabled]=\"disabled\" (sdChange)=\"onChange($event)\" hideInlineError></sd-textarea>" }]
3614
3582
  }], propDecorators: { form: [{
3615
3583
  type: Input
3616
3584
  }], _label: [{
@@ -3698,11 +3666,11 @@ class TextfieldAttribute {
3698
3666
  }
3699
3667
  };
3700
3668
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TextfieldAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3701
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TextfieldAttribute, isStandalone: true, selector: "textfield-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" label=\"G\u1EE3i \u00FD\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n <attribute-input [form]=\"form\" label=\"Gi\u00E1 tr\u1ECB m\u1EB7c \u0111\u1ECBnh\" [(model)]=\"component.defaultValue\"></attribute-input>\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n <attribute-input-number label=\"K\u00FD t\u1EF1 t\u1ED1i \u0111a\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n <attribute-input label=\"Expression\" [(model)]=\"component.validate!.pattern\"></attribute-input>\r\n <attribute-input label=\"Expression message\" [(model)]=\"component.validate!.patternErrorMessage\"></attribute-input>\r\n </sd-section>\r\n}\r\n", dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3669
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TextfieldAttribute, isStandalone: true, selector: "textfield-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.default-value' | translate\" [(model)]=\"component.defaultValue\"></attribute-input>\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n <attribute-input-number [label]=\"'core.component.form-builder.maxlength' | translate\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n <attribute-input label=\"Expression\" [(model)]=\"component.validate!.pattern\"></attribute-input>\r\n <attribute-input label=\"Expression message\" [(model)]=\"component.validate!.patternErrorMessage\"></attribute-input>\r\n </div>\r\n </details>\r\n}\r\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3702
3670
  }
3703
3671
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TextfieldAttribute, decorators: [{
3704
3672
  type: Component,
3705
- args: [{ selector: 'textfield-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, AttributeTemplate, AttributeExpression, AttributeInput, AttributeInputNumber, AttributeSwitch, AttributeTextarea], template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" label=\"G\u1EE3i \u00FD\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n <attribute-input [form]=\"form\" label=\"Gi\u00E1 tr\u1ECB m\u1EB7c \u0111\u1ECBnh\" [(model)]=\"component.defaultValue\"></attribute-input>\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n <attribute-input-number label=\"K\u00FD t\u1EF1 t\u1ED1i \u0111a\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n <attribute-input label=\"Expression\" [(model)]=\"component.validate!.pattern\"></attribute-input>\r\n <attribute-input label=\"Expression message\" [(model)]=\"component.validate!.patternErrorMessage\"></attribute-input>\r\n </sd-section>\r\n}\r\n" }]
3673
+ args: [{ selector: 'textfield-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeExpression, AttributeInput, AttributeInputNumber, AttributeSwitch, AttributeTextarea, TranslatePipe], template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.default-value' | translate\" [(model)]=\"component.defaultValue\"></attribute-input>\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n <attribute-input-number [label]=\"'core.component.form-builder.maxlength' | translate\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n <attribute-input label=\"Expression\" [(model)]=\"component.validate!.pattern\"></attribute-input>\r\n <attribute-input label=\"Expression message\" [(model)]=\"component.validate!.patternErrorMessage\"></attribute-input>\r\n </div>\r\n </details>\r\n}\r\n" }]
3706
3674
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
3707
3675
  type: Input,
3708
3676
  args: [{ required: true }]
@@ -3742,11 +3710,11 @@ class TextFieldControl {
3742
3710
  this.#subscription.unsubscribe();
3743
3711
  }
3744
3712
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TextFieldControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3745
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TextFieldControl, isStandalone: true, selector: "textfield-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">\r\n Your input text\r\n </div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">{{component.defaultValue}}</div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;border-radius:4px;position:relative;padding:0 8px;color:#bfbfbf}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3713
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TextFieldControl, isStandalone: true, selector: "textfield-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">\r\n Your input text\r\n </div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">{{component.defaultValue}}</div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative;padding:0 8px;color:#bfbfbf}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3746
3714
  }
3747
3715
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TextFieldControl, decorators: [{
3748
3716
  type: Component,
3749
- args: [{ selector: 'textfield-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">\r\n Your input text\r\n </div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">{{component.defaultValue}}</div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;border-radius:4px;position:relative;padding:0 8px;color:#bfbfbf}\n"] }]
3717
+ args: [{ selector: 'textfield-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">\r\n Your input text\r\n </div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">{{component.defaultValue}}</div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative;padding:0 8px;color:#bfbfbf}\n"] }]
3750
3718
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
3751
3719
  type: Input,
3752
3720
  args: [{ alias: 'component', required: true }]
@@ -3798,11 +3766,11 @@ class TextareaAttribute {
3798
3766
  }
3799
3767
  };
3800
3768
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TextareaAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3801
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TextareaAttribute, isStandalone: true, selector: "textarea-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" label=\"G\u1EE3i \u00FD\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n <attribute-input-number label=\"K\u00FD t\u1EF1 t\u1ED1i \u0111a\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n}\r\n", dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3769
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TextareaAttribute, isStandalone: true, selector: "textarea-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n <attribute-input-number [label]=\"'core.component.form-builder.maxlength' | translate\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n}\r\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3802
3770
  }
3803
3771
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TextareaAttribute, decorators: [{
3804
3772
  type: Component,
3805
- args: [{ selector: 'textarea-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, AttributeTemplate, AttributeInput, AttributeInputNumber, AttributeSwitch, AttributeExpression, AttributeTextarea], template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" label=\"G\u1EE3i \u00FD\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n <attribute-input-number label=\"K\u00FD t\u1EF1 t\u1ED1i \u0111a\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n}\r\n" }]
3773
+ args: [{ selector: 'textarea-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeInputNumber, AttributeSwitch, AttributeExpression, AttributeTextarea, TranslatePipe], template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n <attribute-input-number [label]=\"'core.component.form-builder.maxlength' | translate\" [(model)]=\"component.validate!.maxlength\"></attribute-input-number>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n}\r\n" }]
3806
3774
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
3807
3775
  type: Input,
3808
3776
  args: [{ required: true }]
@@ -3843,11 +3811,11 @@ class TextareaControl {
3843
3811
  this.#subscription.unsubscribe();
3844
3812
  }
3845
3813
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TextareaControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3846
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TextareaControl, isStandalone: true, selector: "textarea-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">Your input text</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-textarea\"></div>\r\n </div>\r\n}\r\n", styles: [".c-textarea{width:100%;background:#fff;height:100px;border:1px solid #d3d3d3;border-radius:4px;position:relative}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3814
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TextareaControl, isStandalone: true, selector: "textarea-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">Your input text</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-textarea\"></div>\r\n </div>\r\n}\r\n", styles: [".c-textarea{width:100%;background:#fff;height:100px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3847
3815
  }
3848
3816
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TextareaControl, decorators: [{
3849
3817
  type: Component,
3850
- args: [{ selector: 'textarea-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">Your input text</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-textarea\"></div>\r\n </div>\r\n}\r\n", styles: [".c-textarea{width:100%;background:#fff;height:100px;border:1px solid #d3d3d3;border-radius:4px;position:relative}\n"] }]
3818
+ args: [{ selector: 'textarea-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">Your input text</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-textarea\"></div>\r\n </div>\r\n}\r\n", styles: [".c-textarea{width:100%;background:#fff;height:100px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}\n"] }]
3851
3819
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
3852
3820
  type: Input,
3853
3821
  args: [{ alias: 'component', required: true }]
@@ -3883,11 +3851,11 @@ class ChipStringControl {
3883
3851
  this.#subscription.unsubscribe();
3884
3852
  }
3885
3853
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ChipStringControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3886
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ChipStringControl, isStandalone: true, selector: "chip-string-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">One, Two, Three</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">\r\n <span class=\"c-chip\">One</span>\r\n <span class=\"c-chip\">Two</span>\r\n <span class=\"c-chip\">Three</span>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3854
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ChipStringControl, isStandalone: true, selector: "chip-string-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">One, Two, Three</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">\r\n <span class=\"c-chip\">One</span>\r\n <span class=\"c-chip\">Two</span>\r\n <span class=\"c-chip\">Three</span>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3887
3855
  }
3888
3856
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ChipStringControl, decorators: [{
3889
3857
  type: Component,
3890
- args: [{ selector: 'chip-string-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">One, Two, Three</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">\r\n <span class=\"c-chip\">One</span>\r\n <span class=\"c-chip\">Two</span>\r\n <span class=\"c-chip\">Three</span>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"] }]
3858
+ args: [{ selector: 'chip-string-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">One, Two, Three</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">\r\n <span class=\"c-chip\">One</span>\r\n <span class=\"c-chip\">Two</span>\r\n <span class=\"c-chip\">Three</span>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"] }]
3891
3859
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
3892
3860
  type: Input,
3893
3861
  args: [{ alias: 'component', required: true }]
@@ -3946,11 +3914,11 @@ class ChipStringAttribute {
3946
3914
  this.#changes.next();
3947
3915
  };
3948
3916
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ChipStringAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3949
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ChipStringAttribute, isStandalone: true, selector: "chip-string-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n @if (!component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n }\r\n}\r\n", dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3917
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ChipStringAttribute, isStandalone: true, selector: "chip-string-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n @if (!component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n }\r\n}\r\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3950
3918
  }
3951
3919
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ChipStringAttribute, decorators: [{
3952
3920
  type: Component,
3953
- args: [{ selector: 'chip-string-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, AttributeTemplate, AttributeInput, AttributeSwitch, AttributeExpression], template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n @if (!component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n }\r\n}\r\n" }]
3921
+ args: [{ selector: 'chip-string-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeSwitch, AttributeExpression, TranslatePipe], template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n @if (!component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n }\r\n}\r\n" }]
3954
3922
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
3955
3923
  type: Input,
3956
3924
  args: [{ required: true }]
@@ -3992,11 +3960,11 @@ class ChipCalendarControl {
3992
3960
  this.#subscription.unsubscribe();
3993
3961
  }
3994
3962
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ChipCalendarControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
3995
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ChipCalendarControl, isStandalone: true, selector: "chip-calendar-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">One, Two, Three</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">\r\n <span class=\"c-chip\">One</span>\r\n <span class=\"c-chip\">Two</span>\r\n <span class=\"c-chip\">Three</span>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3963
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ChipCalendarControl, isStandalone: true, selector: "chip-calendar-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">One, Two, Three</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">\r\n <span class=\"c-chip\">One</span>\r\n <span class=\"c-chip\">Two</span>\r\n <span class=\"c-chip\">Three</span>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3996
3964
  }
3997
3965
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ChipCalendarControl, decorators: [{
3998
3966
  type: Component,
3999
- args: [{ selector: 'chip-calendar-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">One, Two, Three</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">\r\n <span class=\"c-chip\">One</span>\r\n <span class=\"c-chip\">Two</span>\r\n <span class=\"c-chip\">Three</span>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"] }]
3967
+ args: [{ selector: 'chip-calendar-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">One, Two, Three</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">\r\n <span class=\"c-chip\">One</span>\r\n <span class=\"c-chip\">Two</span>\r\n <span class=\"c-chip\">Three</span>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-chip{display:inline-block;padding:2px 8px;background:#e0e0e0;border-radius:16px;font-size:13px;line-height:20px;margin:2px}\n"] }]
4000
3968
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
4001
3969
  type: Input,
4002
3970
  args: [{ alias: 'component', required: true }]
@@ -4055,11 +4023,11 @@ class ChipCalendarAttribute {
4055
4023
  this.#changes.next();
4056
4024
  };
4057
4025
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ChipCalendarAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4058
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ChipCalendarAttribute, isStandalone: true, selector: "chip-calendar-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n @if (!component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n }\r\n}\r\n", dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4026
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ChipCalendarAttribute, isStandalone: true, selector: "chip-calendar-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n @if (!component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n }\r\n}\r\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4059
4027
  }
4060
4028
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ChipCalendarAttribute, decorators: [{
4061
4029
  type: Component,
4062
- args: [{ selector: 'chip-calendar-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, AttributeTemplate, AttributeInput, AttributeSwitch, AttributeExpression], template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n @if (!component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n }\r\n}\r\n" }]
4030
+ args: [{ selector: 'chip-calendar-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeSwitch, AttributeExpression, TranslatePipe], template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n @if (!component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n }\r\n}\r\n" }]
4063
4031
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
4064
4032
  type: Input,
4065
4033
  args: [{ required: true }]
@@ -4121,11 +4089,11 @@ class NumberAttribute {
4121
4089
  }
4122
4090
  };
4123
4091
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: NumberAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4124
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: NumberAttribute, isStandalone: true, selector: "number-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" label=\"G\u1EE3i \u00FD\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n</sd-section>\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n <attribute-input-number label=\"Gi\u00E1 tr\u1ECB nh\u1ECF nh\u1EA5t\" [(model)]=\"component.validate!.min\"></attribute-input-number>\r\n <attribute-input-number label=\"Gi\u00E1 tr\u1ECB l\u1EDBn nh\u1EA5t\" [(model)]=\"component.validate!.max\"></attribute-input-number>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n}\r\n", dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4092
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: NumberAttribute, isStandalone: true, selector: "number-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n </div>\r\n</details>\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n <attribute-input-number [label]=\"'core.component.form-builder.min' | translate\" [(model)]=\"component.validate!.min\"></attribute-input-number>\r\n <attribute-input-number [label]=\"'core.component.form-builder.max' | translate\" [(model)]=\"component.validate!.max\"></attribute-input-number>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n}\r\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4125
4093
  }
4126
4094
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: NumberAttribute, decorators: [{
4127
4095
  type: Component,
4128
- args: [{ selector: 'number-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, AttributeTemplate, AttributeInput, AttributeInputNumber, AttributeSwitch, AttributeExpression, AttributeTextarea], template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" label=\"G\u1EE3i \u00FD\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n</sd-section>\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n <attribute-input-number label=\"Gi\u00E1 tr\u1ECB nh\u1ECF nh\u1EA5t\" [(model)]=\"component.validate!.min\"></attribute-input-number>\r\n <attribute-input-number label=\"Gi\u00E1 tr\u1ECB l\u1EDBn nh\u1EA5t\" [(model)]=\"component.validate!.max\"></attribute-input-number>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n}\r\n" }]
4096
+ args: [{ selector: 'number-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeInputNumber, AttributeSwitch, AttributeExpression, AttributeTextarea, TranslatePipe], template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n </div>\r\n</details>\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n <attribute-input-number [label]=\"'core.component.form-builder.min' | translate\" [(model)]=\"component.validate!.min\"></attribute-input-number>\r\n <attribute-input-number [label]=\"'core.component.form-builder.max' | translate\" [(model)]=\"component.validate!.max\"></attribute-input-number>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n}\r\n" }]
4129
4097
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
4130
4098
  type: Input,
4131
4099
  args: [{ required: true }]
@@ -4168,11 +4136,11 @@ class NumberControl {
4168
4136
  this.#subscription.unsubscribe();
4169
4137
  }
4170
4138
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: NumberControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4171
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: NumberControl, isStandalone: true, selector: "number-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">{{number}}</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\"></div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;border-radius:4px;position:relative}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4139
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: NumberControl, isStandalone: true, selector: "number-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">{{number}}</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\"></div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4172
4140
  }
4173
4141
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: NumberControl, decorators: [{
4174
4142
  type: Component,
4175
- args: [{ selector: 'number-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">{{number}}</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\"></div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;border-radius:4px;position:relative}\n"] }]
4143
+ args: [{ selector: 'number-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">{{number}}</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\"></div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}\n"] }]
4176
4144
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
4177
4145
  type: Input,
4178
4146
  args: [{ alias: 'component', required: true }]
@@ -4206,11 +4174,11 @@ class DatetimeControl {
4206
4174
  this.#subscription.unsubscribe();
4207
4175
  }
4208
4176
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DatetimeControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4209
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: DatetimeControl, isStandalone: true, selector: "datetime-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">{{ component.subtype === 'datetime' ? datetime : date }}</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">\r\n <svg viewBox=\"0 0 24 24\" width=\"24px\" height=\"24px\" fill=\"currentColor\" focusable=\"false\">\r\n <path\r\n d=\"M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z\"></path>\r\n </svg>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;position:relative;border-radius:4px}.c-input svg{position:absolute;top:2px;right:3px;color:#999}.label{font-weight:500}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4177
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: DatetimeControl, isStandalone: true, selector: "datetime-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">{{ component.subtype === 'datetime' ? datetime : date }}</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">\r\n <svg viewBox=\"0 0 24 24\" width=\"24px\" height=\"24px\" fill=\"currentColor\" focusable=\"false\">\r\n <path\r\n d=\"M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z\"></path>\r\n </svg>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);position:relative;border-radius:4px}.c-input svg{position:absolute;top:2px;right:3px;color:#999}.label{font-weight:500}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4210
4178
  }
4211
4179
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DatetimeControl, decorators: [{
4212
4180
  type: Component,
4213
- args: [{ selector: 'datetime-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [], template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">{{ component.subtype === 'datetime' ? datetime : date }}</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">\r\n <svg viewBox=\"0 0 24 24\" width=\"24px\" height=\"24px\" fill=\"currentColor\" focusable=\"false\">\r\n <path\r\n d=\"M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z\"></path>\r\n </svg>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;position:relative;border-radius:4px}.c-input svg{position:absolute;top:2px;right:3px;color:#999}.label{font-weight:500}\n"] }]
4181
+ args: [{ selector: 'datetime-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [], template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">{{ component.subtype === 'datetime' ? datetime : date }}</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input\">\r\n <svg viewBox=\"0 0 24 24\" width=\"24px\" height=\"24px\" fill=\"currentColor\" focusable=\"false\">\r\n <path\r\n d=\"M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z\"></path>\r\n </svg>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);position:relative;border-radius:4px}.c-input svg{position:absolute;top:2px;right:3px;color:#999}.label{font-weight:500}\n"] }]
4214
4182
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
4215
4183
  type: Input,
4216
4184
  args: [{ alias: 'component', required: true }]
@@ -4254,11 +4222,11 @@ class AttributeSelect {
4254
4222
  this.sdChange.emit(value);
4255
4223
  };
4256
4224
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
4257
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: AttributeSelect, isStandalone: true, selector: "attribute-select", inputs: { form: "form", _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _multiple: ["multiple", "_multiple"], _items: ["items", "_items"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-select\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [form]=\"form\"\r\n [(model)]=\"model\"\r\n [items]=\"items\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-select>\r\n</div> -->\r\n<sd-select\r\n class=\"py-8\"\r\n [label]=\"label!\"\r\n [form]=\"form\"\r\n [(model)]=\"model\"\r\n [items]=\"items\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-select>", dependencies: [{ kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }] });
4225
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.21", type: AttributeSelect, isStandalone: true, selector: "attribute-select", inputs: { form: "form", _label: ["label", "_label"], _disabled: ["disabled", "_disabled"], _multiple: ["multiple", "_multiple"], _items: ["items", "_items"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange", sdChange: "sdChange" }, ngImport: i0, template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-select\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [form]=\"form\"\r\n [(model)]=\"model\"\r\n [items]=\"items\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-select>\r\n</div> -->\r\n<sd-select\r\n class=\"py-8\"\r\n size=\"sm\"\r\n [label]=\"label!\"\r\n [form]=\"form\"\r\n [(model)]=\"model\"\r\n [items]=\"items\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-select>", dependencies: [{ kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }] });
4258
4226
  }
4259
4227
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeSelect, decorators: [{
4260
4228
  type: Component,
4261
- args: [{ selector: 'attribute-select', imports: [SdSelect$1], template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-select\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [form]=\"form\"\r\n [(model)]=\"model\"\r\n [items]=\"items\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-select>\r\n</div> -->\r\n<sd-select\r\n class=\"py-8\"\r\n [label]=\"label!\"\r\n [form]=\"form\"\r\n [(model)]=\"model\"\r\n [items]=\"items\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-select>" }]
4229
+ args: [{ selector: 'attribute-select', imports: [SdSelect$1], template: "<!-- <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <sd-select\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [form]=\"form\"\r\n [(model)]=\"model\"\r\n [items]=\"items\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-select>\r\n</div> -->\r\n<sd-select\r\n class=\"py-8\"\r\n size=\"sm\"\r\n [label]=\"label!\"\r\n [form]=\"form\"\r\n [(model)]=\"model\"\r\n [items]=\"items\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n [disabled]=\"disabled\"\r\n (sdChange)=\"onChange($event)\"\r\n hideInlineError></sd-select>" }]
4262
4230
  }], propDecorators: { form: [{
4263
4231
  type: Input
4264
4232
  }], _label: [{
@@ -4328,11 +4296,11 @@ class DatetimeAttribute {
4328
4296
  }
4329
4297
  };
4330
4298
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DatetimeAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4331
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: DatetimeAttribute, isStandalone: true, selector: "datetime-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [form]=\"form\" label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-select\r\n label=\"\u0110\u1ECBnh d\u1EA1ng\"\r\n [(model)]=\"component.subtype\"\r\n [items]=\"[\r\n { value: 'date', display: 'dd/MM/yyyy' },\r\n { value: 'datetime', display: 'dd/MM/yyyy HH:mm' }\r\n ]\"></attribute-select>\r\n <attribute-textarea [form]=\"form\" label=\"G\u1EE3i \u00FD\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n</sd-section>\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch [form]=\"form\" label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n}\r\n", dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4299
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: DatetimeAttribute, isStandalone: true, selector: "datetime-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-select\r\n [label]=\"'core.component.form-builder.format' | translate\"\r\n [(model)]=\"component.subtype\"\r\n [items]=\"[\r\n { value: 'date', display: 'dd/MM/yyyy' },\r\n { value: 'datetime', display: 'dd/MM/yyyy HH:mm' }\r\n ]\"></attribute-select>\r\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n </div>\r\n</details>\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n}\r\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4332
4300
  }
4333
4301
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: DatetimeAttribute, decorators: [{
4334
4302
  type: Component,
4335
- args: [{ selector: 'datetime-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, AttributeTemplate, AttributeInput, AttributeSwitch, AttributeSelect, AttributeExpression, AttributeTextarea], template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [form]=\"form\" label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-select\r\n label=\"\u0110\u1ECBnh d\u1EA1ng\"\r\n [(model)]=\"component.subtype\"\r\n [items]=\"[\r\n { value: 'date', display: 'dd/MM/yyyy' },\r\n { value: 'datetime', display: 'dd/MM/yyyy HH:mm' }\r\n ]\"></attribute-select>\r\n <attribute-textarea [form]=\"form\" label=\"G\u1EE3i \u00FD\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n</sd-section>\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch [form]=\"form\" label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n}\r\n" }]
4303
+ args: [{ selector: 'datetime-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeSwitch, AttributeSelect, AttributeExpression, AttributeTextarea, TranslatePipe], template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-select\r\n [label]=\"'core.component.form-builder.format' | translate\"\r\n [(model)]=\"component.subtype\"\r\n [items]=\"[\r\n { value: 'date', display: 'dd/MM/yyyy' },\r\n { value: 'datetime', display: 'dd/MM/yyyy HH:mm' }\r\n ]\"></attribute-select>\r\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.hint' | translate\" [(model)]=\"component.helperText\"></attribute-textarea>\r\n </div>\r\n</details>\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n}\r\n" }]
4336
4304
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
4337
4305
  type: Input,
4338
4306
  args: [{ required: true }]
@@ -4410,11 +4378,11 @@ let BuildQueries$1 = class BuildQueries {
4410
4378
  this.ref.markForCheck();
4411
4379
  };
4412
4380
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: BuildQueries, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4413
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: BuildQueries, isStandalone: true, selector: "build-queries", inputs: { components: "components", variables: "variables", label: "label", selections: "selections", _valuesKey: ["valuesKey", "_valuesKey"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "@if (!!selection?.queries?.items?.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n </div>\r\n <sd-modal title=\"Thi\u1EBFt l\u1EADp gi\u00E1 tr\u1ECB truy v\u1EA5n\" width=\"400px\">\r\n <div class=\"c-builder\">\r\n @for (property of leftProperties; track property.value) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <div style=\"width: 150px\">\r\n <div class=\"text-secondary\">{{ property.value }}</div>\r\n <div class=\"T16M\">{{ property.display }}</div>\r\n </div>\r\n <sd-autocomplete\r\n label=\"Tr\u01B0\u1EDDng l\u1EA5y gi\u00E1 tr\u1ECB\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"model![property.value]\"\r\n [items]=\"rightProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"X\u00E1c nh\u1EADn\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4381
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: BuildQueries, isStandalone: true, selector: "build-queries", inputs: { components: "components", variables: "variables", label: "label", selections: "selections", _valuesKey: ["valuesKey", "_valuesKey"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "@if (!!selection?.queries?.items?.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n </div>\r\n <sd-modal [title]=\"'core.component.form-builder.set-query-value' | translate\" width=\"400px\">\r\n <div class=\"c-builder\">\r\n @for (property of leftProperties; track property.value) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <div style=\"width: 150px\">\r\n <div class=\"text-secondary\">{{ property.value }}</div>\r\n <div class=\"T16M\">{{ property.display }}</div>\r\n </div>\r\n <sd-autocomplete\r\n [label]=\"'core.component.form-builder.value-source-field' | translate\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"model![property.value]\"\r\n [items]=\"rightProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4414
4382
  };
4415
4383
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: BuildQueries$1, decorators: [{
4416
4384
  type: Component,
4417
- args: [{ selector: 'build-queries', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdAutocomplete$1, SdButton, SdModal], template: "@if (!!selection?.queries?.items?.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n </div>\r\n <sd-modal title=\"Thi\u1EBFt l\u1EADp gi\u00E1 tr\u1ECB truy v\u1EA5n\" width=\"400px\">\r\n <div class=\"c-builder\">\r\n @for (property of leftProperties; track property.value) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <div style=\"width: 150px\">\r\n <div class=\"text-secondary\">{{ property.value }}</div>\r\n <div class=\"T16M\">{{ property.display }}</div>\r\n </div>\r\n <sd-autocomplete\r\n label=\"Tr\u01B0\u1EDDng l\u1EA5y gi\u00E1 tr\u1ECB\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"model![property.value]\"\r\n [items]=\"rightProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"X\u00E1c nh\u1EADn\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
4385
+ args: [{ selector: 'build-queries', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdAutocomplete$1, SdButton, SdModal, TranslatePipe], template: "@if (!!selection?.queries?.items?.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n </div>\r\n <sd-modal [title]=\"'core.component.form-builder.set-query-value' | translate\" width=\"400px\">\r\n <div class=\"c-builder\">\r\n @for (property of leftProperties; track property.value) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <div style=\"width: 150px\">\r\n <div class=\"text-secondary\">{{ property.value }}</div>\r\n <div class=\"T16M\">{{ property.display }}</div>\r\n </div>\r\n <sd-autocomplete\r\n [label]=\"'core.component.form-builder.value-source-field' | translate\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"model![property.value]\"\r\n [items]=\"rightProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
4418
4386
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { modal: [{
4419
4387
  type: ViewChild,
4420
4388
  args: [SdModal]
@@ -4525,11 +4493,11 @@ class BuildVariables {
4525
4493
  this.ref.markForCheck();
4526
4494
  };
4527
4495
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: BuildVariables, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4528
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: BuildVariables, isStandalone: true, selector: "build-variables", inputs: { components: "components", variables: "variables", label: "label", selections: "selections", _valuesKey: ["valuesKey", "_valuesKey"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "@if (!!selection?.variables?.items?.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n </div>\r\n <sd-modal title=\"Thi\u1EBFt l\u1EADp g\u00E1n gi\u00E1 tr\u1ECB khi thay \u0111\u1ED5i\" width=\"500px\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button prefixIcon=\"add\" title=\"Th\u00EAm tr\u01B0\u1EDDng\" color=\"primary\" (click)=\"addField()\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (item of items; track item.id; let idx = $index) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <sd-autocomplete\r\n label=\"Tr\u01B0\u1EDDng mu\u1ED1n g\u00E1n gi\u00E1 tr\u1ECB\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"item.key\"\r\n [items]=\"leftProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n <sd-autocomplete\r\n label=\"Gi\u00E1 tr\u1ECB mu\u1ED1n g\u00E1n\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"item.value\"\r\n [items]=\"rightProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"X\u00E1c nh\u1EADn\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4496
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: BuildVariables, isStandalone: true, selector: "build-variables", inputs: { components: "components", variables: "variables", label: "label", selections: "selections", _valuesKey: ["valuesKey", "_valuesKey"], _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "@if (!!selection?.variables?.items?.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n </div>\r\n <sd-modal [title]=\"'core.component.form-builder.set-on-change-assign' | translate\" width=\"500px\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-field' | translate\" color=\"primary\" (click)=\"addField()\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (item of items; track item.id; let idx = $index) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <sd-autocomplete\r\n [label]=\"'core.component.form-builder.target-field' | translate\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"item.key\"\r\n [items]=\"leftProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n <sd-autocomplete\r\n [label]=\"'core.component.form-builder.target-value' | translate\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"item.value\"\r\n [items]=\"rightProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4529
4497
  }
4530
4498
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: BuildVariables, decorators: [{
4531
4499
  type: Component,
4532
- args: [{ selector: 'build-variables', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdAutocomplete$1, SdButton, SdModal], template: "@if (!!selection?.variables?.items?.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n </div>\r\n <sd-modal title=\"Thi\u1EBFt l\u1EADp g\u00E1n gi\u00E1 tr\u1ECB khi thay \u0111\u1ED5i\" width=\"500px\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button prefixIcon=\"add\" title=\"Th\u00EAm tr\u01B0\u1EDDng\" color=\"primary\" (click)=\"addField()\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (item of items; track item.id; let idx = $index) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <sd-autocomplete\r\n label=\"Tr\u01B0\u1EDDng mu\u1ED1n g\u00E1n gi\u00E1 tr\u1ECB\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"item.key\"\r\n [items]=\"leftProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n <sd-autocomplete\r\n label=\"Gi\u00E1 tr\u1ECB mu\u1ED1n g\u00E1n\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"item.value\"\r\n [items]=\"rightProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"X\u00E1c nh\u1EADn\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
4500
+ args: [{ selector: 'build-variables', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdAutocomplete$1, SdButton, SdModal, TranslatePipe], template: "@if (!!selection?.variables?.items?.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n </div>\r\n <sd-modal [title]=\"'core.component.form-builder.set-on-change-assign' | translate\" width=\"500px\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-field' | translate\" color=\"primary\" (click)=\"addField()\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (item of items; track item.id; let idx = $index) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <sd-autocomplete\r\n [label]=\"'core.component.form-builder.target-field' | translate\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"item.key\"\r\n [items]=\"leftProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n <sd-autocomplete\r\n [label]=\"'core.component.form-builder.target-value' | translate\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"item.value\"\r\n [items]=\"rightProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
4533
4501
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { modal: [{
4534
4502
  type: ViewChild,
4535
4503
  args: [SdModal]
@@ -4623,11 +4591,11 @@ class AttributeSelection {
4623
4591
  this.ref.markForCheck();
4624
4592
  };
4625
4593
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeSelection, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
4626
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: AttributeSelection, isStandalone: true, selector: "attribute-selection", inputs: { components: "components", variables: "variables", component: "component", _valuesKey: ["valuesKey", "_valuesKey"], _values: ["values", "_values"] }, outputs: { valuesKeyChange: "valuesKeyChange", valuesChange: "valuesChange", sdChange: "sdChange" }, ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"D\u1EEF li\u1EC7u\" icon=\"format_list_bulleted\">\r\n @if (selections.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">D\u1EEF li\u1EC7u API</div>\r\n <sd-autocomplete\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"valuesKey\"\r\n [items]=\"selections\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChangeValuesKey($event)\"\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n <!-- N\u1EBFu l\u00E0 select t\u1EEB API th\u00EC cho ph\u00E9p truy\u1EC1n th\u00EAm Query -->\r\n\r\n @if (component.type === 'select' && !!valuesKey) {\r\n <build-queries\r\n label=\"\u0110i\u1EC1u ki\u1EC7n truy v\u1EA5n\"\r\n [selections]=\"selections\"\r\n [valuesKey]=\"valuesKey\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.query\"></build-queries>\r\n <build-variables\r\n label=\"G\u00E1n gi\u00E1 tr\u1ECB\"\r\n [selections]=\"selections\"\r\n [valuesKey]=\"valuesKey\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.setVariables\"></build-variables>\r\n <!-- <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">\u0110i\u1EC1u ki\u1EC7n truy v\u1EA5n</div>\r\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"component.properties!.query\" hideInlineError></sd-input>\r\n </div> -->\r\n }\r\n }\r\n @if (!valuesKey) {\r\n <div class=\"d-flex flex-column\" style=\"gap: 4px\">\r\n <div class=\"T14M\">D\u1EEF li\u1EC7u t\u0129nh</div>\r\n @for (item of values; track item.value; let idx = $index) {\r\n <div class=\"d-flex align-items-end py-4\" style=\"gap: 4px\">\r\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.value\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\r\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.label\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\r\n <sd-button prefixIcon=\"delete\" (click)=\"removeItem(idx)\" color=\"error\"></sd-button>\r\n </div>\r\n }\r\n <sd-button prefixIcon=\"add\" title=\"Th\u00EAm d\u1EEF li\u1EC7u\" (click)=\"addItem()\" color=\"primary\"></sd-button>\r\n </div>\r\n }\r\n</sd-section>\r\n", dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: BuildQueries$1, selector: "build-queries", inputs: ["components", "variables", "label", "selections", "valuesKey", "model"], outputs: ["modelChange"] }, { kind: "component", type: BuildVariables, selector: "build-variables", inputs: ["components", "variables", "label", "selections", "valuesKey", "model"], outputs: ["modelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4594
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: AttributeSelection, isStandalone: true, selector: "attribute-selection", inputs: { components: "components", variables: "variables", component: "component", _valuesKey: ["valuesKey", "_valuesKey"], _values: ["values", "_values"] }, outputs: { valuesKeyChange: "valuesKeyChange", valuesChange: "valuesChange", sdChange: "sdChange" }, ngImport: i0, template: "<sd-section class=\"mt-8\" [title]=\"'core.component.form-builder.data' | translate\" icon=\"format_list_bulleted\">\r\n @if (selections.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">{{ 'core.component.form-builder.data-api' | translate }}</div>\r\n <sd-autocomplete\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"valuesKey\"\r\n [items]=\"selections\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChangeValuesKey($event)\"\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n <!-- N\u1EBFu l\u00E0 select t\u1EEB API th\u00EC cho ph\u00E9p truy\u1EC1n th\u00EAm Query -->\r\n\r\n @if (component.type === 'select' && !!valuesKey) {\r\n <build-queries\r\n [label]=\"'core.component.form-builder.query-condition' | translate\"\r\n [selections]=\"selections\"\r\n [valuesKey]=\"valuesKey\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.query\"></build-queries>\r\n <build-variables\r\n [label]=\"'core.component.form-builder.assign-value' | translate\"\r\n [selections]=\"selections\"\r\n [valuesKey]=\"valuesKey\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.setVariables\"></build-variables>\r\n <!-- <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">\u0110i\u1EC1u ki\u1EC7n truy v\u1EA5n</div>\r\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"component.properties!.query\" hideInlineError></sd-input>\r\n </div> -->\r\n }\r\n }\r\n @if (!valuesKey) {\r\n <div class=\"d-flex flex-column\" style=\"gap: 4px\">\r\n <div class=\"T14M\">{{ 'core.component.form-builder.data-static' | translate }}</div>\r\n @for (item of values; track item.value; let idx = $index) {\r\n <div class=\"d-flex align-items-end py-4\" style=\"gap: 4px\">\r\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.value\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\r\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.label\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\r\n <sd-button prefixIcon=\"delete\" (click)=\"removeItem(idx)\" color=\"error\"></sd-button>\r\n </div>\r\n }\r\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-data' | translate\" (click)=\"addItem()\" color=\"primary\"></sd-button>\r\n </div>\r\n }\r\n</sd-section>\r\n", dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: BuildQueries$1, selector: "build-queries", inputs: ["components", "variables", "label", "selections", "valuesKey", "model"], outputs: ["modelChange"] }, { kind: "component", type: BuildVariables, selector: "build-variables", inputs: ["components", "variables", "label", "selections", "valuesKey", "model"], outputs: ["modelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4627
4595
  }
4628
4596
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeSelection, decorators: [{
4629
4597
  type: Component,
4630
- args: [{ selector: 'attribute-selection', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdInput$1, SdAutocomplete$1, SdButton, SdSection, BuildQueries$1, BuildVariables], template: "<sd-section class=\"mt-8\" title=\"D\u1EEF li\u1EC7u\" icon=\"format_list_bulleted\">\r\n @if (selections.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">D\u1EEF li\u1EC7u API</div>\r\n <sd-autocomplete\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"valuesKey\"\r\n [items]=\"selections\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChangeValuesKey($event)\"\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n <!-- N\u1EBFu l\u00E0 select t\u1EEB API th\u00EC cho ph\u00E9p truy\u1EC1n th\u00EAm Query -->\r\n\r\n @if (component.type === 'select' && !!valuesKey) {\r\n <build-queries\r\n label=\"\u0110i\u1EC1u ki\u1EC7n truy v\u1EA5n\"\r\n [selections]=\"selections\"\r\n [valuesKey]=\"valuesKey\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.query\"></build-queries>\r\n <build-variables\r\n label=\"G\u00E1n gi\u00E1 tr\u1ECB\"\r\n [selections]=\"selections\"\r\n [valuesKey]=\"valuesKey\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.setVariables\"></build-variables>\r\n <!-- <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">\u0110i\u1EC1u ki\u1EC7n truy v\u1EA5n</div>\r\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"component.properties!.query\" hideInlineError></sd-input>\r\n </div> -->\r\n }\r\n }\r\n @if (!valuesKey) {\r\n <div class=\"d-flex flex-column\" style=\"gap: 4px\">\r\n <div class=\"T14M\">D\u1EEF li\u1EC7u t\u0129nh</div>\r\n @for (item of values; track item.value; let idx = $index) {\r\n <div class=\"d-flex align-items-end py-4\" style=\"gap: 4px\">\r\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.value\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\r\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.label\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\r\n <sd-button prefixIcon=\"delete\" (click)=\"removeItem(idx)\" color=\"error\"></sd-button>\r\n </div>\r\n }\r\n <sd-button prefixIcon=\"add\" title=\"Th\u00EAm d\u1EEF li\u1EC7u\" (click)=\"addItem()\" color=\"primary\"></sd-button>\r\n </div>\r\n }\r\n</sd-section>\r\n" }]
4598
+ args: [{ selector: 'attribute-selection', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdInput$1, SdAutocomplete$1, SdButton, SdSection, BuildQueries$1, BuildVariables, TranslatePipe], template: "<sd-section class=\"mt-8\" [title]=\"'core.component.form-builder.data' | translate\" icon=\"format_list_bulleted\">\r\n @if (selections.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">{{ 'core.component.form-builder.data-api' | translate }}</div>\r\n <sd-autocomplete\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"valuesKey\"\r\n [items]=\"selections\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChangeValuesKey($event)\"\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n <!-- N\u1EBFu l\u00E0 select t\u1EEB API th\u00EC cho ph\u00E9p truy\u1EC1n th\u00EAm Query -->\r\n\r\n @if (component.type === 'select' && !!valuesKey) {\r\n <build-queries\r\n [label]=\"'core.component.form-builder.query-condition' | translate\"\r\n [selections]=\"selections\"\r\n [valuesKey]=\"valuesKey\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.query\"></build-queries>\r\n <build-variables\r\n [label]=\"'core.component.form-builder.assign-value' | translate\"\r\n [selections]=\"selections\"\r\n [valuesKey]=\"valuesKey\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.setVariables\"></build-variables>\r\n <!-- <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">\u0110i\u1EC1u ki\u1EC7n truy v\u1EA5n</div>\r\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"component.properties!.query\" hideInlineError></sd-input>\r\n </div> -->\r\n }\r\n }\r\n @if (!valuesKey) {\r\n <div class=\"d-flex flex-column\" style=\"gap: 4px\">\r\n <div class=\"T14M\">{{ 'core.component.form-builder.data-static' | translate }}</div>\r\n @for (item of values; track item.value; let idx = $index) {\r\n <div class=\"d-flex align-items-end py-4\" style=\"gap: 4px\">\r\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.value\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\r\n <sd-input style=\"width: 200px\" size=\"sm\" [(model)]=\"item.label\" (sdChange)=\"onChangeValues()\" hideInlineError></sd-input>\r\n <sd-button prefixIcon=\"delete\" (click)=\"removeItem(idx)\" color=\"error\"></sd-button>\r\n </div>\r\n }\r\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-data' | translate\" (click)=\"addItem()\" color=\"primary\"></sd-button>\r\n </div>\r\n }\r\n</sd-section>\r\n" }]
4631
4599
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: FormGenericService }], propDecorators: { components: [{
4632
4600
  type: Input,
4633
4601
  args: [{ required: true }]
@@ -4704,11 +4672,11 @@ class SelectAttribute {
4704
4672
  }
4705
4673
  };
4706
4674
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SelectAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4707
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SelectAttribute, isStandalone: true, selector: "select-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-switch label=\"Ch\u1ECDn nhi\u1EC1u\" [(model)]=\"component.properties!.multiple\"></attribute-switch>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <attribute-selection\r\n [components]=\"components\"\r\n [component]=\"component\"\r\n [variables]=\"variables\"\r\n [(valuesKey)]=\"component.valuesKey\"\r\n [(values)]=\"component.values\"\r\n (valuesKeyChange)=\"onChanges()\"\r\n (valuesChange)=\"onChanges()\"></attribute-selection>\r\n}\r\n", dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeSelection, selector: "attribute-selection", inputs: ["components", "variables", "component", "valuesKey", "values"], outputs: ["valuesKeyChange", "valuesChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4675
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SelectAttribute, isStandalone: true, selector: "select-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-switch [label]=\"'core.component.form-builder.multiple' | translate\" [(model)]=\"component.properties!.multiple\"></attribute-switch>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <attribute-selection\r\n [components]=\"components\"\r\n [component]=\"component\"\r\n [variables]=\"variables\"\r\n [(valuesKey)]=\"component.valuesKey\"\r\n [(values)]=\"component.values\"\r\n (valuesKeyChange)=\"onChanges()\"\r\n (valuesChange)=\"onChanges()\"></attribute-selection>\r\n}\r\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeSelection, selector: "attribute-selection", inputs: ["components", "variables", "component", "valuesKey", "values"], outputs: ["valuesKeyChange", "valuesChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4708
4676
  }
4709
4677
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SelectAttribute, decorators: [{
4710
4678
  type: Component,
4711
- args: [{ selector: 'select-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, AttributeTemplate, AttributeSelection, AttributeInput, AttributeSwitch, AttributeExpression], template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-switch label=\"Ch\u1ECDn nhi\u1EC1u\" [(model)]=\"component.properties!.multiple\"></attribute-switch>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <attribute-selection\r\n [components]=\"components\"\r\n [component]=\"component\"\r\n [variables]=\"variables\"\r\n [(valuesKey)]=\"component.valuesKey\"\r\n [(values)]=\"component.values\"\r\n (valuesKeyChange)=\"onChanges()\"\r\n (valuesChange)=\"onChanges()\"></attribute-selection>\r\n}\r\n" }]
4679
+ args: [{ selector: 'select-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeSelection, AttributeInput, AttributeSwitch, AttributeExpression, TranslatePipe], template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-switch [label]=\"'core.component.form-builder.multiple' | translate\" [(model)]=\"component.properties!.multiple\"></attribute-switch>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <attribute-selection\r\n [components]=\"components\"\r\n [component]=\"component\"\r\n [variables]=\"variables\"\r\n [(valuesKey)]=\"component.valuesKey\"\r\n [(values)]=\"component.values\"\r\n (valuesKeyChange)=\"onChanges()\"\r\n (valuesChange)=\"onChanges()\"></attribute-selection>\r\n}\r\n" }]
4712
4680
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
4713
4681
  type: Input,
4714
4682
  args: [{ required: true }]
@@ -4749,11 +4717,11 @@ class SelectControl {
4749
4717
  this.#subscription.unsubscribe();
4750
4718
  }
4751
4719
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SelectControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4752
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SelectControl, isStandalone: true, selector: "select-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">Your dropdown selection</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input c-select\">\r\n <svg width=\"8\" height=\"8\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n fill=\"currentColor\"\r\n stroke=\"currentColor\"\r\n stroke-width=\".5\"\r\n d=\"M7.75 1.336L4 6.125.258 1.335 0 1.54l4 5.125L8 1.54zm0 0\"></path>\r\n </svg>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;border-radius:4px;position:relative}.c-select svg{position:absolute;right:10px;top:10px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4720
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SelectControl, isStandalone: true, selector: "select-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">Your dropdown selection</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input c-select\">\r\n <svg width=\"8\" height=\"8\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n fill=\"currentColor\"\r\n stroke=\"currentColor\"\r\n stroke-width=\".5\"\r\n d=\"M7.75 1.336L4 6.125.258 1.335 0 1.54l4 5.125L8 1.54zm0 0\"></path>\r\n </svg>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-select svg{position:absolute;right:10px;top:10px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4753
4721
  }
4754
4722
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SelectControl, decorators: [{
4755
4723
  type: Component,
4756
- args: [{ selector: 'select-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">Your dropdown selection</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input c-select\">\r\n <svg width=\"8\" height=\"8\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n fill=\"currentColor\"\r\n stroke=\"currentColor\"\r\n stroke-width=\".5\"\r\n d=\"M7.75 1.336L4 6.125.258 1.335 0 1.54l4 5.125L8 1.54zm0 0\"></path>\r\n </svg>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;border-radius:4px;position:relative}.c-select svg{position:absolute;right:10px;top:10px}\n"] }]
4724
+ args: [{ selector: 'select-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">Your dropdown selection</div>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-input c-select\">\r\n <svg width=\"8\" height=\"8\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n fill=\"currentColor\"\r\n stroke=\"currentColor\"\r\n stroke-width=\".5\"\r\n d=\"M7.75 1.336L4 6.125.258 1.335 0 1.54l4 5.125L8 1.54zm0 0\"></path>\r\n </svg>\r\n </div>\r\n </div>\r\n}\r\n", styles: [".c-input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);border-radius:4px;position:relative}.c-select svg{position:absolute;right:10px;top:10px}\n"] }]
4757
4725
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
4758
4726
  type: Input,
4759
4727
  args: [{ alias: 'component', required: true }]
@@ -4852,11 +4820,11 @@ class RadioAttribute {
4852
4820
  this.#changes.next();
4853
4821
  };
4854
4822
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: RadioAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4855
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: RadioAttribute, isStandalone: true, selector: "radio-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n <attribute-select\r\n [form]=\"form\"\r\n label=\"B\u1ED1 c\u1EE5c\"\r\n [(model)]=\"component.properties!.direction\"\r\n [items]=\"[\r\n { value: 'row', display: 'Ngang' },\r\n { value: 'column', display: 'D\u1ECDc' }\r\n ]\"></attribute-select>\r\n </sd-section>\r\n @if (!component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n }\r\n <attribute-selection\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [component]=\"component\"\r\n [(valuesKey)]=\"component.valuesKey\"\r\n [(values)]=\"component.values\"\r\n (valuesKeyChange)=\"onChanges()\"\r\n (valuesChange)=\"onChanges()\"></attribute-selection>\r\n}\r\n", dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeSelection, selector: "attribute-selection", inputs: ["components", "variables", "component", "valuesKey", "values"], outputs: ["valuesKeyChange", "valuesChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4823
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: RadioAttribute, isStandalone: true, selector: "radio-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n <attribute-select\r\n [form]=\"form\"\r\n [label]=\"'core.component.form-builder.layout' | translate\"\r\n [(model)]=\"component.properties!.direction\"\r\n [items]=\"[\r\n { value: 'row', display: 'Ngang' },\r\n { value: 'column', display: ('core.component.form-builder.vertical' | translate) }\r\n ]\"></attribute-select>\r\n </div>\r\n </details>\r\n @if (!component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n }\r\n <attribute-selection\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [component]=\"component\"\r\n [(valuesKey)]=\"component.valuesKey\"\r\n [(values)]=\"component.values\"\r\n (valuesKeyChange)=\"onChanges()\"\r\n (valuesChange)=\"onChanges()\"></attribute-selection>\r\n}\r\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeSelection, selector: "attribute-selection", inputs: ["components", "variables", "component", "valuesKey", "values"], outputs: ["valuesKeyChange", "valuesChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4856
4824
  }
4857
4825
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: RadioAttribute, decorators: [{
4858
4826
  type: Component,
4859
- args: [{ selector: 'radio-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, AttributeTemplate, AttributeSelection, AttributeInput, AttributeSwitch, AttributeSelect, AttributeExpression], template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n <attribute-select\r\n [form]=\"form\"\r\n label=\"B\u1ED1 c\u1EE5c\"\r\n [(model)]=\"component.properties!.direction\"\r\n [items]=\"[\r\n { value: 'row', display: 'Ngang' },\r\n { value: 'column', display: 'D\u1ECDc' }\r\n ]\"></attribute-select>\r\n </sd-section>\r\n @if (!component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n }\r\n <attribute-selection\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [component]=\"component\"\r\n [(valuesKey)]=\"component.valuesKey\"\r\n [(values)]=\"component.values\"\r\n (valuesKeyChange)=\"onChanges()\"\r\n (valuesChange)=\"onChanges()\"></attribute-selection>\r\n}\r\n" }]
4827
+ args: [{ selector: 'radio-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeSelection, AttributeInput, AttributeSwitch, AttributeSelect, AttributeExpression, TranslatePipe], template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n @if (component.properties!.viewed) {\r\n <attribute-input label=\"Hyperlink\" [(model)]=\"component.properties!.hyperlink\"></attribute-input>\r\n }\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n <attribute-select\r\n [form]=\"form\"\r\n [label]=\"'core.component.form-builder.layout' | translate\"\r\n [(model)]=\"component.properties!.direction\"\r\n [items]=\"[\r\n { value: 'row', display: 'Ngang' },\r\n { value: 'column', display: ('core.component.form-builder.vertical' | translate) }\r\n ]\"></attribute-select>\r\n </div>\r\n </details>\r\n @if (!component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n }\r\n <attribute-selection\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [component]=\"component\"\r\n [(valuesKey)]=\"component.valuesKey\"\r\n [(values)]=\"component.values\"\r\n (valuesKeyChange)=\"onChanges()\"\r\n (valuesChange)=\"onChanges()\"></attribute-selection>\r\n}\r\n" }]
4860
4828
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
4861
4829
  type: Input,
4862
4830
  args: [{ required: true }]
@@ -4875,11 +4843,11 @@ class CheckboxControl {
4875
4843
  this.component = component;
4876
4844
  }
4877
4845
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: CheckboxControl, deps: [], target: i0.ɵɵFactoryTarget.Component });
4878
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: CheckboxControl, isStandalone: true, selector: "checkbox-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">C\u00F3/Kh\u00F4ng</div>\r\n} @else {\r\n <div class=\"c-checkbox\">\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-box mr-4\"></div>\r\n <div class=\"T14R\">{{ component.label }}</div>\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@charset \"UTF-8\";.input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;position:relative}.c-checkbox .c-box{border:2px solid #828282;width:16px;height:16px;border-radius:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
4846
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: CheckboxControl, isStandalone: true, selector: "checkbox-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">{{ 'core.component.form-builder.yes-no' | translate }}</div>\r\n} @else {\r\n <div class=\"c-checkbox\">\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-box mr-4\"></div>\r\n <div class=\"T14R\">{{ component.label }}</div>\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@charset \"UTF-8\";.input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);position:relative}.c-checkbox .c-box{border:2px solid #828282;width:16px;height:16px;border-radius:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
4879
4847
  }
4880
4848
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: CheckboxControl, decorators: [{
4881
4849
  type: Component,
4882
- args: [{ selector: 'checkbox-control', imports: [CommonModule], template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">C\u00F3/Kh\u00F4ng</div>\r\n} @else {\r\n <div class=\"c-checkbox\">\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-box mr-4\"></div>\r\n <div class=\"T14R\">{{ component.label }}</div>\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@charset \"UTF-8\";.input{width:100%;background:#fff;height:30px;border:1px solid #d3d3d3;position:relative}.c-checkbox .c-box{border:2px solid #828282;width:16px;height:16px;border-radius:2px}\n"] }]
4850
+ args: [{ selector: 'checkbox-control', imports: [CommonModule, TranslatePipe], template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <div class=\"T14M\">{{ 'core.component.form-builder.yes-no' | translate }}</div>\r\n} @else {\r\n <div class=\"c-checkbox\">\r\n <div class=\"d-flex align-items-center\">\r\n <div class=\"c-box mr-4\"></div>\r\n <div class=\"T14R\">{{ component.label }}</div>\r\n </div>\r\n </div>\r\n}\r\n", styles: ["@charset \"UTF-8\";.input{width:100%;background:#fff;height:30px;border:1px solid var(--md-sys-color-outline-variant);position:relative}.c-checkbox .c-box{border:2px solid #828282;width:16px;height:16px;border-radius:2px}\n"] }]
4883
4851
  }], propDecorators: { _component: [{
4884
4852
  type: Input,
4885
4853
  args: [{ alias: 'component', required: true }]
@@ -4931,11 +4899,11 @@ class CheckboxAttribute {
4931
4899
  }
4932
4900
  };
4933
4901
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: CheckboxAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
4934
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: CheckboxAttribute, isStandalone: true, selector: "checkbox-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [form]=\"form\" label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n</sd-section>\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n}\r\n", dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4902
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: CheckboxAttribute, isStandalone: true, selector: "checkbox-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n </div>\r\n</details>\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n}\r\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4935
4903
  }
4936
4904
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: CheckboxAttribute, decorators: [{
4937
4905
  type: Component,
4938
- args: [{ selector: 'checkbox-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, AttributeTemplate, AttributeInput, AttributeSwitch, AttributeExpression], template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [form]=\"form\" label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n</sd-section>\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n}\r\n" }]
4906
+ args: [{ selector: 'checkbox-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeSwitch, AttributeExpression, TranslatePipe], template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n </div>\r\n</details>\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n}\r\n" }]
4939
4907
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
4940
4908
  type: Input,
4941
4909
  args: [{ required: true }]
@@ -5004,11 +4972,11 @@ class BuildQueries {
5004
4972
  this.ref.markForCheck();
5005
4973
  };
5006
4974
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: BuildQueries, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
5007
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: BuildQueries, isStandalone: true, selector: "build-queries", inputs: { label: "label", _queries: ["queries", "_queries"], components: "components", variables: "variables", _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "@if (!!leftProperties?.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n </div>\r\n <sd-modal title=\"Thi\u1EBFt l\u1EADp gi\u00E1 tr\u1ECB truy v\u1EA5n\" width=\"400px\">\r\n <div class=\"c-builder\">\r\n @for (property of leftProperties; track property.value) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <div class=\"T14M\" style=\"width: 150px\">{{ property.display }}</div>\r\n <sd-autocomplete\r\n label=\"Tr\u01B0\u1EDDng l\u1EA5y gi\u00E1 tr\u1ECB\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"model![property.value]\"\r\n [items]=\"rightProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"X\u00E1c nh\u1EADn\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4975
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: BuildQueries, isStandalone: true, selector: "build-queries", inputs: { label: "label", _queries: ["queries", "_queries"], components: "components", variables: "variables", _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "@if (!!leftProperties?.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n </div>\r\n <sd-modal [title]=\"'core.component.form-builder.set-query-value' | translate\" width=\"400px\">\r\n <div class=\"c-builder\">\r\n @for (property of leftProperties; track property.value) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <div class=\"T14M\" style=\"width: 150px\">{{ property.display }}</div>\r\n <sd-autocomplete\r\n [label]=\"'core.component.form-builder.value-source-field' | translate\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"model![property.value]\"\r\n [items]=\"rightProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5008
4976
  }
5009
4977
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: BuildQueries, decorators: [{
5010
4978
  type: Component,
5011
- args: [{ selector: 'build-queries', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdAutocomplete$1, SdButton, SdModal], template: "@if (!!leftProperties?.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n </div>\r\n <sd-modal title=\"Thi\u1EBFt l\u1EADp gi\u00E1 tr\u1ECB truy v\u1EA5n\" width=\"400px\">\r\n <div class=\"c-builder\">\r\n @for (property of leftProperties; track property.value) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <div class=\"T14M\" style=\"width: 150px\">{{ property.display }}</div>\r\n <sd-autocomplete\r\n label=\"Tr\u01B0\u1EDDng l\u1EA5y gi\u00E1 tr\u1ECB\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"model![property.value]\"\r\n [items]=\"rightProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"X\u00E1c nh\u1EADn\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
4979
+ args: [{ selector: 'build-queries', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdAutocomplete$1, SdButton, SdModal, TranslatePipe], template: "@if (!!leftProperties?.length) {\r\n <div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n </div>\r\n <sd-modal [title]=\"'core.component.form-builder.set-query-value' | translate\" width=\"400px\">\r\n <div class=\"c-builder\">\r\n @for (property of leftProperties; track property.value) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <div class=\"T14M\" style=\"width: 150px\">{{ property.display }}</div>\r\n <sd-autocomplete\r\n [label]=\"'core.component.form-builder.value-source-field' | translate\"\r\n [form]=\"form\"\r\n style=\"flex: 1\"\r\n [(model)]=\"model![property.value]\"\r\n [items]=\"rightProperties\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError></sd-autocomplete>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n </sd-modal>\r\n}\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
5012
4980
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { modal: [{
5013
4981
  type: ViewChild,
5014
4982
  args: [SdModal]
@@ -5105,11 +5073,11 @@ class HtmlAttribute {
5105
5073
  }
5106
5074
  };
5107
5075
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HtmlAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: FormGenericService }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5108
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: HtmlAttribute, isStandalone: true, selector: "html-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, outputs: { attributeChanges: "attributeChanges" }, ngImport: i0, template: "@if (!component.properties!.hidden) {\r\n <sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-select\r\n label=\"D\u1EEF li\u1EC7u m\u1EABu\"\r\n [(model)]=\"component.template\"\r\n [items]=\"definitionHtmls\"\r\n (sdChange)=\"onChangeDefinition($event)\"></attribute-select>\r\n <attribute-input [form]=\"form\" label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" label=\"N\u1ED9i dung\" [(model)]=\"component.content\"></attribute-textarea>\r\n @if (component.properties?.queries?.length) {\r\n <build-queries\r\n label=\"\u0110i\u1EC1u ki\u1EC7n truy v\u1EA5n\"\r\n [queries]=\"component.properties?.queries\"\r\n [components]=\"components\"\r\n [variables]=\"variables\" \r\n [(model)]=\"component.properties!.query\"></build-queries>\r\n }\r\n </sd-section>\r\n @if (component.properties?.variables?.length) {\r\n <sd-section class=\"mt-8\" title=\"Tham s\u1ED1\" icon=\"format_list_bulleted\">\r\n @for (variable of component.properties?.variables; track variable.key) {\r\n <attribute-input [form]=\"form\" [label]=\"variable.label\" [(model)]=\"variable.value\"></attribute-input>\r\n }\r\n </sd-section>\r\n }\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n </sd-section>\r\n}\r\n", dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: BuildQueries, selector: "build-queries", inputs: ["label", "queries", "components", "variables", "model"], outputs: ["modelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5076
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: HtmlAttribute, isStandalone: true, selector: "html-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, outputs: { attributeChanges: "attributeChanges" }, ngImport: i0, template: "@if (!component.properties!.hidden) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-select\r\n [label]=\"'core.component.form-builder.template-data' | translate\"\r\n [(model)]=\"component.template\"\r\n [items]=\"definitionHtmls\"\r\n (sdChange)=\"onChangeDefinition($event)\"></attribute-select>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.content' | translate\" [(model)]=\"component.content\"></attribute-textarea>\r\n @if (component.properties?.queries?.length) {\r\n <build-queries\r\n [label]=\"'core.component.form-builder.query-condition' | translate\"\r\n [queries]=\"component.properties?.queries\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.query\"></build-queries>\r\n }\r\n </div>\r\n </details>\r\n @if (component.properties?.variables?.length) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">format_list_bulleted</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n @for (variable of component.properties?.variables; track variable.key) {\r\n <attribute-input [form]=\"form\" [label]=\"variable.label\" [(model)]=\"variable.value\"></attribute-input>\r\n }\r\n </div>\r\n </details>\r\n }\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n </div>\r\n </details>\r\n}\r\n", dependencies: [{ kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeTextarea, selector: "attribute-textarea", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: BuildQueries, selector: "build-queries", inputs: ["label", "queries", "components", "variables", "model"], outputs: ["modelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5109
5077
  }
5110
5078
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HtmlAttribute, decorators: [{
5111
5079
  type: Component,
5112
- args: [{ selector: 'html-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, AttributeInput, AttributeSelect, AttributeExpression, AttributeTextarea, BuildQueries], template: "@if (!component.properties!.hidden) {\r\n <sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-select\r\n label=\"D\u1EEF li\u1EC7u m\u1EABu\"\r\n [(model)]=\"component.template\"\r\n [items]=\"definitionHtmls\"\r\n (sdChange)=\"onChangeDefinition($event)\"></attribute-select>\r\n <attribute-input [form]=\"form\" label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" label=\"N\u1ED9i dung\" [(model)]=\"component.content\"></attribute-textarea>\r\n @if (component.properties?.queries?.length) {\r\n <build-queries\r\n label=\"\u0110i\u1EC1u ki\u1EC7n truy v\u1EA5n\"\r\n [queries]=\"component.properties?.queries\"\r\n [components]=\"components\"\r\n [variables]=\"variables\" \r\n [(model)]=\"component.properties!.query\"></build-queries>\r\n }\r\n </sd-section>\r\n @if (component.properties?.variables?.length) {\r\n <sd-section class=\"mt-8\" title=\"Tham s\u1ED1\" icon=\"format_list_bulleted\">\r\n @for (variable of component.properties?.variables; track variable.key) {\r\n <attribute-input [form]=\"form\" [label]=\"variable.label\" [(model)]=\"variable.value\"></attribute-input>\r\n }\r\n </sd-section>\r\n }\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n </sd-section>\r\n}\r\n" }]
5080
+ args: [{ selector: 'html-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeInput, AttributeSelect, AttributeExpression, AttributeTextarea, BuildQueries, TranslatePipe], template: "@if (!component.properties!.hidden) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-select\r\n [label]=\"'core.component.form-builder.template-data' | translate\"\r\n [(model)]=\"component.template\"\r\n [items]=\"definitionHtmls\"\r\n (sdChange)=\"onChangeDefinition($event)\"></attribute-select>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\"></attribute-input>\r\n <attribute-textarea [form]=\"form\" [label]=\"'core.component.form-builder.content' | translate\" [(model)]=\"component.content\"></attribute-textarea>\r\n @if (component.properties?.queries?.length) {\r\n <build-queries\r\n [label]=\"'core.component.form-builder.query-condition' | translate\"\r\n [queries]=\"component.properties?.queries\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.query\"></build-queries>\r\n }\r\n </div>\r\n </details>\r\n @if (component.properties?.variables?.length) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">format_list_bulleted</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n @for (variable of component.properties?.variables; track variable.key) {\r\n <attribute-input [form]=\"form\" [label]=\"variable.label\" [(model)]=\"variable.value\"></attribute-input>\r\n }\r\n </div>\r\n </details>\r\n }\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n </div>\r\n </details>\r\n}\r\n" }]
5113
5081
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: FormGenericService }, { type: BuilderService }], propDecorators: { components: [{
5114
5082
  type: Input,
5115
5083
  args: [{ required: true }]
@@ -5166,11 +5134,11 @@ class HtmlControl {
5166
5134
  this.#subscription.unsubscribe();
5167
5135
  }
5168
5136
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HtmlControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
5169
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: HtmlControl, isStandalone: true, selector: "html-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (!content) {\r\n <div class=\"c-html d-flex align-items-center justify-content-center\">\r\n <span class=\"material-icons\"> html </span>\r\n </div>\r\n} @else {\r\n <div [innerHTML]=\"hashed | htmlPipe: content: component\"></div>\r\n}\r\n", styles: [".c-html{height:70px;border:1px solid #d3d3d3;padding:10px;background-color:#f4f4f4}.c-html .material-icons{font-size:48px}\n"], dependencies: [{ kind: "pipe", type: HtmlPipe, name: "htmlPipe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5137
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: HtmlControl, isStandalone: true, selector: "html-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (!content) {\r\n <div class=\"c-html d-flex align-items-center justify-content-center\">\r\n <span class=\"material-icons\"> html </span>\r\n </div>\r\n} @else {\r\n <div [innerHTML]=\"hashed | htmlPipe: content: component\"></div>\r\n}\r\n", styles: [".c-html{height:70px;border:1px solid var(--md-sys-color-outline-variant);padding:10px;background-color:#f4f4f4}.c-html .material-icons{font-size:48px}\n"], dependencies: [{ kind: "pipe", type: HtmlPipe, name: "htmlPipe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5170
5138
  }
5171
5139
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: HtmlControl, decorators: [{
5172
5140
  type: Component,
5173
- args: [{ selector: 'html-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HtmlPipe], template: "@if (!content) {\r\n <div class=\"c-html d-flex align-items-center justify-content-center\">\r\n <span class=\"material-icons\"> html </span>\r\n </div>\r\n} @else {\r\n <div [innerHTML]=\"hashed | htmlPipe: content: component\"></div>\r\n}\r\n", styles: [".c-html{height:70px;border:1px solid #d3d3d3;padding:10px;background-color:#f4f4f4}.c-html .material-icons{font-size:48px}\n"] }]
5141
+ args: [{ selector: 'html-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HtmlPipe], template: "@if (!content) {\r\n <div class=\"c-html d-flex align-items-center justify-content-center\">\r\n <span class=\"material-icons\"> html </span>\r\n </div>\r\n} @else {\r\n <div [innerHTML]=\"hashed | htmlPipe: content: component\"></div>\r\n}\r\n", styles: [".c-html{height:70px;border:1px solid var(--md-sys-color-outline-variant);padding:10px;background-color:#f4f4f4}.c-html .material-icons{font-size:48px}\n"] }]
5174
5142
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }, { type: FormGenericService }], propDecorators: { _component: [{
5175
5143
  type: Input,
5176
5144
  args: [{ alias: 'component', required: true }]
@@ -5237,11 +5205,11 @@ class AttributeParameter {
5237
5205
  this.ref.markForCheck();
5238
5206
  };
5239
5207
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeParameter, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
5240
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: AttributeParameter, isStandalone: true, selector: "attribute-parameter", inputs: { components: "components", label: "label", _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n</div>\r\n<sd-modal title=\"G\u00E1n gi\u00E1 tr\u1ECB Tham s\u1ED1\" width=\"500px\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button prefixIcon=\"add\" title=\"Th\u00EAm tr\u01B0\u1EDDng\" color=\"primary\" (click)=\"addField()\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (item of items; track item.id; let idx = $index) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <sd-input label=\"T\u00EAn tham s\u1ED1\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.key\" required hideInlineError></sd-input>\r\n <sd-input label=\"Gi\u00E1 tr\u1ECB t\u01B0\u01A1ng \u1EE9ng\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.value\" required hideInlineError></sd-input>\r\n <div style=\"width: 32px; min-width: 32px\">\r\n <sd-button\r\n prefixIcon=\"delete\"\r\n tooltip=\"X\u00F3a\"\r\n (click)=\"remove(idx)\"\r\n size=\"sm\"\r\n class=\"p-0\"\r\n ></sd-button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"X\u00E1c nh\u1EADn\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5208
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: AttributeParameter, isStandalone: true, selector: "attribute-parameter", inputs: { components: "components", label: "label", _model: ["model", "_model"] }, outputs: { modelChange: "modelChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n</div>\r\n<sd-modal [title]=\"'core.component.form-builder.assign-parameter-value' | translate\" width=\"500px\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-field' | translate\" color=\"primary\" (click)=\"addField()\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (item of items; track item.id; let idx = $index) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <sd-input [label]=\"'core.component.form-builder.parameter-name' | translate\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.key\" required hideInlineError></sd-input>\r\n <sd-input [label]=\"'core.component.form-builder.parameter-value' | translate\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.value\" required hideInlineError></sd-input>\r\n <div style=\"width: 32px; min-width: 32px\">\r\n <sd-button\r\n prefixIcon=\"delete\"\r\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"remove(idx)\"\r\n size=\"sm\"\r\n class=\"p-0\"\r\n ></sd-button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5241
5209
  }
5242
5210
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeParameter, decorators: [{
5243
5211
  type: Component,
5244
- args: [{ selector: 'attribute-parameter', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdButton, SdModal, SdInput], template: "<div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n</div>\r\n<sd-modal title=\"G\u00E1n gi\u00E1 tr\u1ECB Tham s\u1ED1\" width=\"500px\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button prefixIcon=\"add\" title=\"Th\u00EAm tr\u01B0\u1EDDng\" color=\"primary\" (click)=\"addField()\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (item of items; track item.id; let idx = $index) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <sd-input label=\"T\u00EAn tham s\u1ED1\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.key\" required hideInlineError></sd-input>\r\n <sd-input label=\"Gi\u00E1 tr\u1ECB t\u01B0\u01A1ng \u1EE9ng\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.value\" required hideInlineError></sd-input>\r\n <div style=\"width: 32px; min-width: 32px\">\r\n <sd-button\r\n prefixIcon=\"delete\"\r\n tooltip=\"X\u00F3a\"\r\n (click)=\"remove(idx)\"\r\n size=\"sm\"\r\n class=\"p-0\"\r\n ></sd-button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"X\u00E1c nh\u1EADn\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
5212
+ args: [{ selector: 'attribute-parameter', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdButton, SdModal, SdInput, TranslatePipe], template: "<div class=\"d-flex align-items-center py-4\">\r\n @if (label) {\r\n <div class=\"T14R\" style=\"flex: 1\">{{ label }}</div>\r\n }\r\n <div style=\"width: 200px\" class=\"d-flex align-items-center\">\r\n <a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{ queryString }}</a>\r\n </div>\r\n</div>\r\n<sd-modal [title]=\"'core.component.form-builder.assign-parameter-value' | translate\" width=\"500px\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.add-field' | translate\" color=\"primary\" (click)=\"addField()\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (item of items; track item.id; let idx = $index) {\r\n <div class=\"d-flex align-items-center py-8\" style=\"gap: 8px\">\r\n <sd-input [label]=\"'core.component.form-builder.parameter-name' | translate\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.key\" required hideInlineError></sd-input>\r\n <sd-input [label]=\"'core.component.form-builder.parameter-value' | translate\" [form]=\"form\" style=\"flex: 1\" [(model)]=\"item.value\" required hideInlineError></sd-input>\r\n <div style=\"width: 32px; min-width: 32px\">\r\n <sd-button\r\n prefixIcon=\"delete\"\r\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"remove(idx)\"\r\n size=\"sm\"\r\n class=\"p-0\"\r\n ></sd-button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
5245
5213
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { modal: [{
5246
5214
  type: ViewChild,
5247
5215
  args: [SdModal]
@@ -5272,15 +5240,17 @@ class UploadAttribute {
5272
5240
  this.extension = this.component.properties.extensions?.join(',') || '';
5273
5241
  }
5274
5242
  #subscription = new Subscription();
5243
+ #i18n = inject(I18nService);
5244
+ // Dropdown nguồn upload (mobile); display dịch qua i18n để hỗ trợ EN
5275
5245
  sources = [{
5276
5246
  value: 'ALL',
5277
- display: 'Tất cả'
5247
+ display: this.#i18n.t('core.component.form-builder.upload-source.all')
5278
5248
  }, {
5279
5249
  value: 'PHOTO_LIBRARY',
5280
- display: 'Chọn từ thư viện'
5250
+ display: this.#i18n.t('core.component.form-builder.upload-source.photo-library')
5281
5251
  }, {
5282
5252
  value: 'CAPTURE',
5283
- display: 'Chụp ảnh'
5253
+ display: this.#i18n.t('core.component.form-builder.upload-source.capture')
5284
5254
  }];
5285
5255
  constructor(ref, builderService) {
5286
5256
  this.ref = ref;
@@ -5324,11 +5294,11 @@ class UploadAttribute {
5324
5294
  ?.filter(val => !!val) || [];
5325
5295
  };
5326
5296
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: UploadAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5327
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: UploadAttribute, isStandalone: true, selector: "upload-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-select\r\n label=\"Lo\u1EA1i\"\r\n [(model)]=\"component.properties!.type\"\r\n [items]=\"[\r\n { value: 'file', display: 'T\u1EC7p' },\r\n { value: 'image', display: '\u1EA2nh' }\r\n ]\"></attribute-select>\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n <attribute-input-number label=\"SL t\u1EC7p/\u1EA3nh t\u1ED1i \u0111a\" [(model)]=\"component.properties!.max\"></attribute-input-number>\r\n <attribute-input-number label=\"Dung l\u01B0\u1EE3ng (Mb)\" [(model)]=\"component.properties!.maxSize\"></attribute-input-number>\r\n @if (component.properties!.type === 'file') {\r\n <attribute-input label=\"\u0110\u1ECBnh d\u1EA1ng (VD: png,jpg ...)\" [model]=\"extension\" (modelChange)=\"onChangeExtension($event)\"></attribute-input>\r\n }\r\n @if (component.properties!.type === 'image') {\r\n <attribute-select label=\"Ngu\u1ED3n (mobile)\" [(model)]=\"component.properties!.source\" [items]=\"sources\"></attribute-select>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"Tham s\u1ED1\" icon=\"settings\">\r\n <attribute-parameter label=\"G\u00E1n tham s\u1ED1\" [components]=\"components\" [(model)]=\"component.properties!.args\"></attribute-parameter>\r\n </sd-section>\r\n}\r\n", dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeParameter, selector: "attribute-parameter", inputs: ["components", "label", "model"], outputs: ["modelChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5297
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: UploadAttribute, isStandalone: true, selector: "upload-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-select\r\n [label]=\"'core.component.form-builder.type' | translate\"\r\n [(model)]=\"component.properties!.type\"\r\n [items]=\"[\r\n { value: 'file', display: ('core.component.form-builder.file' | translate) },\r\n { value: 'image', display: ('core.component.form-builder.image' | translate) }\r\n ]\"></attribute-select>\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n <attribute-input-number [label]=\"'core.component.form-builder.max-files' | translate\" [(model)]=\"component.properties!.max\"></attribute-input-number>\r\n <attribute-input-number [label]=\"'core.component.form-builder.size-mb' | translate\" [(model)]=\"component.properties!.maxSize\"></attribute-input-number>\r\n @if (component.properties!.type === 'file') {\r\n <attribute-input [label]=\"'core.component.form-builder.format-example' | translate\" [model]=\"extension\" (modelChange)=\"onChangeExtension($event)\"></attribute-input>\r\n }\r\n @if (component.properties!.type === 'image') {\r\n <attribute-select [label]=\"'core.component.form-builder.source-mobile' | translate\" [(model)]=\"component.properties!.source\" [items]=\"sources\"></attribute-select>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">settings</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-parameter [label]=\"'core.component.form-builder.assign-parameter' | translate\" [components]=\"components\" [(model)]=\"component.properties!.args\"></attribute-parameter>\r\n </div>\r\n </details>\r\n}\r\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeInputNumber, selector: "attribute-input-number", inputs: ["label", "disabled", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeParameter, selector: "attribute-parameter", inputs: ["components", "label", "model"], outputs: ["modelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5328
5298
  }
5329
5299
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: UploadAttribute, decorators: [{
5330
5300
  type: Component,
5331
- args: [{ selector: 'upload-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, AttributeTemplate, AttributeInput, AttributeInputNumber, AttributeSwitch, AttributeSelect, AttributeExpression, AttributeParameter], template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-select\r\n label=\"Lo\u1EA1i\"\r\n [(model)]=\"component.properties!.type\"\r\n [items]=\"[\r\n { value: 'file', display: 'T\u1EC7p' },\r\n { value: 'image', display: '\u1EA2nh' }\r\n ]\"></attribute-select>\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n <attribute-input-number label=\"SL t\u1EC7p/\u1EA3nh t\u1ED1i \u0111a\" [(model)]=\"component.properties!.max\"></attribute-input-number>\r\n <attribute-input-number label=\"Dung l\u01B0\u1EE3ng (Mb)\" [(model)]=\"component.properties!.maxSize\"></attribute-input-number>\r\n @if (component.properties!.type === 'file') {\r\n <attribute-input label=\"\u0110\u1ECBnh d\u1EA1ng (VD: png,jpg ...)\" [model]=\"extension\" (modelChange)=\"onChangeExtension($event)\"></attribute-input>\r\n }\r\n @if (component.properties!.type === 'image') {\r\n <attribute-select label=\"Ngu\u1ED3n (mobile)\" [(model)]=\"component.properties!.source\" [items]=\"sources\"></attribute-select>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"Tham s\u1ED1\" icon=\"settings\">\r\n <attribute-parameter label=\"G\u00E1n tham s\u1ED1\" [components]=\"components\" [(model)]=\"component.properties!.args\"></attribute-parameter>\r\n </sd-section>\r\n}\r\n" }]
5301
+ args: [{ selector: 'upload-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeInputNumber, AttributeSwitch, AttributeSelect, AttributeExpression, AttributeParameter, TranslatePipe], template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n <attribute-select\r\n [label]=\"'core.component.form-builder.type' | translate\"\r\n [(model)]=\"component.properties!.type\"\r\n [items]=\"[\r\n { value: 'file', display: ('core.component.form-builder.file' | translate) },\r\n { value: 'image', display: ('core.component.form-builder.image' | translate) }\r\n ]\"></attribute-select>\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n <attribute-input-number [label]=\"'core.component.form-builder.max-files' | translate\" [(model)]=\"component.properties!.max\"></attribute-input-number>\r\n <attribute-input-number [label]=\"'core.component.form-builder.size-mb' | translate\" [(model)]=\"component.properties!.maxSize\"></attribute-input-number>\r\n @if (component.properties!.type === 'file') {\r\n <attribute-input [label]=\"'core.component.form-builder.format-example' | translate\" [model]=\"extension\" (modelChange)=\"onChangeExtension($event)\"></attribute-input>\r\n }\r\n @if (component.properties!.type === 'image') {\r\n <attribute-select [label]=\"'core.component.form-builder.source-mobile' | translate\" [(model)]=\"component.properties!.source\" [items]=\"sources\"></attribute-select>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">settings</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-parameter [label]=\"'core.component.form-builder.assign-parameter' | translate\" [components]=\"components\" [(model)]=\"component.properties!.args\"></attribute-parameter>\r\n </div>\r\n </details>\r\n}\r\n" }]
5332
5302
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
5333
5303
  type: Input,
5334
5304
  args: [{ required: true }]
@@ -5368,11 +5338,11 @@ class UploadControl {
5368
5338
  this.#subscription.unsubscribe();
5369
5339
  }
5370
5340
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: UploadControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5371
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: UploadControl, isStandalone: true, selector: "upload-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <svg\r\n width=\"64\"\r\n height=\"64\"\r\n viewBox=\"0 0 1280 1280\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n stroke-linejoin=\"round\"\r\n stroke-miterlimit=\"2\"\r\n alt=\"This is an image placeholder\">\r\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\r\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\r\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\r\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\r\n </svg>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"c-upload-file d-flex align-items-center justify-content-between\">\r\n <svg\r\n width=\"64\"\r\n height=\"64\"\r\n viewBox=\"0 0 1280 1280\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n stroke-linejoin=\"round\"\r\n stroke-miterlimit=\"2\"\r\n alt=\"This is an image placeholder\">\r\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\r\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\r\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\r\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\r\n </svg>\r\n </div>\r\n}\r\n", styles: [".c-upload-file{border:1px solid #d3d3d3;padding:5px;color:#afafaf}.c-upload-file .material-icons{font-size:20px!important}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5341
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: UploadControl, isStandalone: true, selector: "upload-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <svg\r\n width=\"64\"\r\n height=\"64\"\r\n viewBox=\"0 0 1280 1280\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n stroke-linejoin=\"round\"\r\n stroke-miterlimit=\"2\"\r\n alt=\"This is an image placeholder\">\r\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\r\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\r\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\r\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\r\n </svg>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"c-upload-file d-flex align-items-center justify-content-between\">\r\n <svg\r\n width=\"64\"\r\n height=\"64\"\r\n viewBox=\"0 0 1280 1280\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n stroke-linejoin=\"round\"\r\n stroke-miterlimit=\"2\"\r\n alt=\"This is an image placeholder\">\r\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\r\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\r\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\r\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\r\n </svg>\r\n </div>\r\n}\r\n", styles: [".c-upload-file{border:1px solid var(--md-sys-color-outline-variant);padding:5px;color:#afafaf}.c-upload-file .material-icons{font-size:20px!important}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5372
5342
  }
5373
5343
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: UploadControl, decorators: [{
5374
5344
  type: Component,
5375
- args: [{ selector: 'upload-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <svg\r\n width=\"64\"\r\n height=\"64\"\r\n viewBox=\"0 0 1280 1280\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n stroke-linejoin=\"round\"\r\n stroke-miterlimit=\"2\"\r\n alt=\"This is an image placeholder\">\r\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\r\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\r\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\r\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\r\n </svg>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"c-upload-file d-flex align-items-center justify-content-between\">\r\n <svg\r\n width=\"64\"\r\n height=\"64\"\r\n viewBox=\"0 0 1280 1280\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n stroke-linejoin=\"round\"\r\n stroke-miterlimit=\"2\"\r\n alt=\"This is an image placeholder\">\r\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\r\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\r\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\r\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\r\n </svg>\r\n </div>\r\n}\r\n", styles: [".c-upload-file{border:1px solid #d3d3d3;padding:5px;color:#afafaf}.c-upload-file .material-icons{font-size:20px!important}\n"] }]
5345
+ args: [{ selector: 'upload-control', changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (component.properties?.viewed) {\r\n <div class=\"d-block T12R text-secondary\">\r\n {{ component.label }}\r\n </div>\r\n <svg\r\n width=\"64\"\r\n height=\"64\"\r\n viewBox=\"0 0 1280 1280\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n stroke-linejoin=\"round\"\r\n stroke-miterlimit=\"2\"\r\n alt=\"This is an image placeholder\">\r\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\r\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\r\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\r\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\r\n </svg>\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n <div class=\"c-upload-file d-flex align-items-center justify-content-between\">\r\n <svg\r\n width=\"64\"\r\n height=\"64\"\r\n viewBox=\"0 0 1280 1280\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n fill-rule=\"evenodd\"\r\n clip-rule=\"evenodd\"\r\n stroke-linejoin=\"round\"\r\n stroke-miterlimit=\"2\"\r\n alt=\"This is an image placeholder\">\r\n <path fill=\"#e5e9ed\" d=\"M0 0h1280v1280H0z\"></path>\r\n <path d=\"M910 410H370v470h540V410zm-57.333 57.333v355.334H427.333V467.333h425.334z\" fill=\"#cad3db\"></path>\r\n <path d=\"M810 770H480v-60l100-170 130 170 100-65v125z\" fill=\"#cad3db\"></path>\r\n <circle cx=\"750\" cy=\"550\" r=\"50\" fill=\"#cad3db\" transform=\"translate(10 10)\"></circle>\r\n </svg>\r\n </div>\r\n}\r\n", styles: [".c-upload-file{border:1px solid var(--md-sys-color-outline-variant);padding:5px;color:#afafaf}.c-upload-file .material-icons{font-size:20px!important}\n"] }]
5376
5346
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
5377
5347
  type: Input,
5378
5348
  args: [{ alias: 'component', required: true }]
@@ -5433,6 +5403,20 @@ class AttributeTable {
5433
5403
  };
5434
5404
  this.modal?.open();
5435
5405
  };
5406
+ // Map column type → Material Symbol icon (per design handoff form-builder redesign).
5407
+ columnTypeIcons = {
5408
+ string: 'text_fields',
5409
+ number: '123',
5410
+ boolean: 'check_box',
5411
+ bool: 'check_box',
5412
+ date: 'event',
5413
+ datetime: 'calendar_month',
5414
+ radio: 'radio_button_checked',
5415
+ values: 'arrow_drop_down_circle',
5416
+ image: 'image',
5417
+ file: 'attach_file',
5418
+ };
5419
+ columnTypeSymbol = (type) => this.columnTypeIcons[type || 'string'] ?? 'text_fields';
5436
5420
  selectedIdx = 0;
5437
5421
  editColumn = (idx) => {
5438
5422
  if (this.columns[idx]) {
@@ -5462,8 +5446,8 @@ class AttributeTable {
5462
5446
  }
5463
5447
  this.modal?.close();
5464
5448
  };
5465
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeTable, deps: [{ token: SD_FORM_GENERIC_CONFIGURATION }], target: i0.ɵɵFactoryTarget.Component });
5466
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: AttributeTable, isStandalone: true, selector: "attribute-table", inputs: { components: "components", variables: "variables", _columnsKey: ["columnsKey", "_columnsKey"], _columns: ["columns", "_columns"] }, outputs: { columnsKeyChange: "columnsKeyChange", columnsChange: "columnsChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"D\u1EEF li\u1EC7u\" icon=\"format_list_bulleted\">\r\n @if (tables.length) {\r\n <!-- <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">D\u1EEF li\u1EC7u c\u1ED9t</div>\r\n <sd-autocomplete\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"columnsKey\"\r\n [items]=\"tables\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChangeColumnsKey($event)\"\r\n hideInlineError></sd-autocomplete>\r\n </div> -->\r\n <sd-autocomplete\r\n class=\"py-8\"\r\n label=\"D\u1EEF li\u1EC7u c\u1ED9t\"\r\n [(model)]=\"columnsKey\"\r\n [items]=\"tables\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChangeColumnsKey($event)\"\r\n hideInlineError></sd-autocomplete>\r\n }\r\n @if (!columnsKey) {\r\n <div class=\"d-flex flex-column\" style=\"gap: 4px\">\r\n <div class=\"T14M\">Danh s\u00E1ch c\u1ED9t</div>\r\n @for (item of columns; track item.key; let idx = $index) {\r\n <div class=\"d-flex align-items-center py-4\" style=\"gap: 4px; justify-content: space-between\">\r\n <div class=\"d-flex flex-column\">\r\n <sd-label [label]=\"item.label\" [required]=\"item.validate?.required\"></sd-label>\r\n <div class=\"T12R text-secondary\">{{ item.key }}</div>\r\n </div>\r\n <div class=\"d-flex align-items-center\" style=\"gap: 4px\">\r\n <mat-icon class=\"text-secondary\" style=\"cursor: pointer\" [fontIcon]=\"'edit'\" (click)=\"editColumn(idx)\"></mat-icon>\r\n <mat-icon class=\"text-secondary\" style=\"cursor: pointer\" [fontIcon]=\"'cancel'\" (click)=\"removeColumn(idx)\"></mat-icon>\r\n </div>\r\n </div>\r\n }\r\n <sd-button prefixIcon=\"add\" title=\"Th\u00EAm c\u1ED9t\" (click)=\"addColumn()\" color=\"primary\"></sd-button>\r\n </div>\r\n }\r\n</sd-section>\r\n<sd-modal title=\"C\u1EA5u h\u00ECnh c\u1ED9t\" width=\"600px\">\r\n @if (column) {\r\n <sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-input [form]=\"form\" label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"column.key\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn c\u1ED9t\" [(model)]=\"column.label\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"Chi\u1EC1u r\u1ED9ng\" [(model)]=\"column.width\"></attribute-input>\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"column.validate!.required\"></attribute-switch>\r\n <attribute-select [form]=\"form\" label=\"Lo\u1EA1i d\u1EEF li\u1EC7u\" [(model)]=\"column.type\" [items]=\"types\"></attribute-select>\r\n </sd-section>\r\n @if (column.type === 'boolean') {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"info\">\r\n <attribute-input [form]=\"form\" label=\"Hi\u1EC3n th\u1ECB khi TRUE\" [(model)]=\"column.displayOnTrue\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"Hi\u1EC3n th\u1ECB khi FALSE\" [(model)]=\"column.displayOnFalse\"></attribute-input>\r\n </sd-section>\r\n } @else if (column.type === 'values') {\r\n <attribute-selection\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [component]=\"column\"\r\n [(valuesKey)]=\"column.valuesKey\"\r\n [(values)]=\"column.values\"></attribute-selection>\r\n } @else if (column.type === 'file' || column.type === 'image') {\r\n <sd-section class=\"mt-8\" title=\"Tham s\u1ED1\" icon=\"settings\">\r\n <attribute-parameter label=\"G\u00E1n tham s\u1ED1\" [components]=\"components\" [(model)]=\"column!.args\"></attribute-parameter>\r\n </sd-section>\r\n }\r\n }\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"L\u01B0u\" (click)=\"onConfirm()\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n", dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: SdLabel, selector: "sd-label", inputs: ["label", "description", "required", "helperText"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: AttributeSelection, selector: "attribute-selection", inputs: ["components", "variables", "component", "valuesKey", "values"], outputs: ["valuesKeyChange", "valuesChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeParameter, selector: "attribute-parameter", inputs: ["components", "label", "model"], outputs: ["modelChange"] }] });
5449
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeTable, deps: [{ token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
5450
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: AttributeTable, isStandalone: true, selector: "attribute-table", inputs: { components: "components", variables: "variables", _columnsKey: ["columnsKey", "_columnsKey"], _columns: ["columns", "_columns"] }, outputs: { columnsKeyChange: "columnsKeyChange", columnsChange: "columnsChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">view_column</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.column-list' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n @if (tables.length) {\r\n <sd-autocomplete\r\n class=\"py-8\"\r\n [label]=\"'core.component.form-builder.column-data' | translate\"\r\n [(model)]=\"columnsKey\"\r\n [items]=\"tables\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChangeColumnsKey($event)\"\r\n hideInlineError></sd-autocomplete>\r\n }\r\n @if (!columnsKey) {\r\n <div class=\"fb-columns-list\">\r\n @for (item of columns; track item.key; let idx = $index) {\r\n <div class=\"fb-column-row\" [class.is-active]=\"idx === selectedIdx\">\r\n <span class=\"fb-column-row__type-icon\"><span class=\"msi\">{{ columnTypeSymbol(item.type) }}</span></span>\r\n <div class=\"fb-column-row__meta\">\r\n <div class=\"fb-column-row__label\">\r\n {{ item.label }}\r\n @if (item.validate?.required) {\r\n <span class=\"fb-column-row__req\">*</span>\r\n }\r\n </div>\r\n <div class=\"fb-column-row__sub mono\">{{ item.key }} \u00B7 {{ item.type }}</div>\r\n </div>\r\n <button type=\"button\" class=\"fb-icon-btn\" [attr.aria-label]=\"'core.component.form-builder.column-config' | translate\" (click)=\"editColumn(idx)\">\r\n <span class=\"msi\">edit</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn danger\" [attr.aria-label]=\"'core.component.form-builder.delete' | translate\" (click)=\"removeColumn(idx)\">\r\n <span class=\"msi\">delete</span>\r\n </button>\r\n </div>\r\n }\r\n <a class=\"fb-add-link\" (click)=\"addColumn()\">\r\n <span class=\"msi\">add</span>\r\n {{ 'core.component.form-builder.add-column' | translate }}\r\n </a>\r\n </div>\r\n }\r\n </div>\r\n</details>\r\n\r\n<sd-modal [title]=\"'core.component.form-builder.column-config' | translate\" width=\"600px\">\r\n @if (column) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"column.key\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.column-name' | translate\" [(model)]=\"column.label\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.width' | translate\" [(model)]=\"column.width\"></attribute-input>\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"column.validate!.required\"></attribute-switch>\r\n <attribute-select [form]=\"form\" [label]=\"'core.component.form-builder.data-type' | translate\" [(model)]=\"column.type\" [items]=\"types\"></attribute-select>\r\n </div>\r\n </details>\r\n @if (column.type === 'boolean') {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.show-when-true' | translate\" [(model)]=\"column.displayOnTrue\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.show-when-false' | translate\" [(model)]=\"column.displayOnFalse\"></attribute-input>\r\n </div>\r\n </details>\r\n } @else if (column.type === 'values') {\r\n <attribute-selection\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [component]=\"column\"\r\n [(valuesKey)]=\"column.valuesKey\"\r\n [(values)]=\"column.values\"></attribute-selection>\r\n } @else if (column.type === 'file' || column.type === 'image') {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">settings</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-parameter [label]=\"'core.component.form-builder.assign-parameter' | translate\" [components]=\"components\" [(model)]=\"column!.args\"></attribute-parameter>\r\n </div>\r\n </details>\r\n }\r\n }\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"onConfirm()\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n", dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: AttributeSelection, selector: "attribute-selection", inputs: ["components", "variables", "component", "valuesKey", "values"], outputs: ["valuesKeyChange", "valuesChange", "sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSelect, selector: "attribute-select", inputs: ["form", "label", "disabled", "multiple", "items", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeParameter, selector: "attribute-parameter", inputs: ["components", "label", "model"], outputs: ["modelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
5467
5451
  }
5468
5452
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: AttributeTable, decorators: [{
5469
5453
  type: Component,
@@ -5473,15 +5457,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
5473
5457
  SdLabel,
5474
5458
  SdAutocomplete$1,
5475
5459
  SdButton,
5476
- SdSection,
5477
5460
  SdModal,
5478
5461
  AttributeSelection,
5479
5462
  AttributeInput,
5480
5463
  AttributeSelect,
5481
5464
  AttributeSwitch,
5482
- AttributeParameter
5483
- ], template: "<sd-section class=\"mt-8\" title=\"D\u1EEF li\u1EC7u\" icon=\"format_list_bulleted\">\r\n @if (tables.length) {\r\n <!-- <div class=\"d-flex align-items-center py-4\">\r\n <div class=\"T14M\" style=\"flex: 1\">D\u1EEF li\u1EC7u c\u1ED9t</div>\r\n <sd-autocomplete\r\n style=\"width: 200px\"\r\n size=\"sm\"\r\n [(model)]=\"columnsKey\"\r\n [items]=\"tables\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChangeColumnsKey($event)\"\r\n hideInlineError></sd-autocomplete>\r\n </div> -->\r\n <sd-autocomplete\r\n class=\"py-8\"\r\n label=\"D\u1EEF li\u1EC7u c\u1ED9t\"\r\n [(model)]=\"columnsKey\"\r\n [items]=\"tables\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChangeColumnsKey($event)\"\r\n hideInlineError></sd-autocomplete>\r\n }\r\n @if (!columnsKey) {\r\n <div class=\"d-flex flex-column\" style=\"gap: 4px\">\r\n <div class=\"T14M\">Danh s\u00E1ch c\u1ED9t</div>\r\n @for (item of columns; track item.key; let idx = $index) {\r\n <div class=\"d-flex align-items-center py-4\" style=\"gap: 4px; justify-content: space-between\">\r\n <div class=\"d-flex flex-column\">\r\n <sd-label [label]=\"item.label\" [required]=\"item.validate?.required\"></sd-label>\r\n <div class=\"T12R text-secondary\">{{ item.key }}</div>\r\n </div>\r\n <div class=\"d-flex align-items-center\" style=\"gap: 4px\">\r\n <mat-icon class=\"text-secondary\" style=\"cursor: pointer\" [fontIcon]=\"'edit'\" (click)=\"editColumn(idx)\"></mat-icon>\r\n <mat-icon class=\"text-secondary\" style=\"cursor: pointer\" [fontIcon]=\"'cancel'\" (click)=\"removeColumn(idx)\"></mat-icon>\r\n </div>\r\n </div>\r\n }\r\n <sd-button prefixIcon=\"add\" title=\"Th\u00EAm c\u1ED9t\" (click)=\"addColumn()\" color=\"primary\"></sd-button>\r\n </div>\r\n }\r\n</sd-section>\r\n<sd-modal title=\"C\u1EA5u h\u00ECnh c\u1ED9t\" width=\"600px\">\r\n @if (column) {\r\n <sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-input [form]=\"form\" label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"column.key\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn c\u1ED9t\" [(model)]=\"column.label\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"Chi\u1EC1u r\u1ED9ng\" [(model)]=\"column.width\"></attribute-input>\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"column.validate!.required\"></attribute-switch>\r\n <attribute-select [form]=\"form\" label=\"Lo\u1EA1i d\u1EEF li\u1EC7u\" [(model)]=\"column.type\" [items]=\"types\"></attribute-select>\r\n </sd-section>\r\n @if (column.type === 'boolean') {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"info\">\r\n <attribute-input [form]=\"form\" label=\"Hi\u1EC3n th\u1ECB khi TRUE\" [(model)]=\"column.displayOnTrue\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"Hi\u1EC3n th\u1ECB khi FALSE\" [(model)]=\"column.displayOnFalse\"></attribute-input>\r\n </sd-section>\r\n } @else if (column.type === 'values') {\r\n <attribute-selection\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [component]=\"column\"\r\n [(valuesKey)]=\"column.valuesKey\"\r\n [(values)]=\"column.values\"></attribute-selection>\r\n } @else if (column.type === 'file' || column.type === 'image') {\r\n <sd-section class=\"mt-8\" title=\"Tham s\u1ED1\" icon=\"settings\">\r\n <attribute-parameter label=\"G\u00E1n tham s\u1ED1\" [components]=\"components\" [(model)]=\"column!.args\"></attribute-parameter>\r\n </sd-section>\r\n }\r\n }\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"L\u01B0u\" (click)=\"onConfirm()\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n" }]
5465
+ AttributeParameter, TranslatePipe
5466
+ ], template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">view_column</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.column-list' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n @if (tables.length) {\r\n <sd-autocomplete\r\n class=\"py-8\"\r\n [label]=\"'core.component.form-builder.column-data' | translate\"\r\n [(model)]=\"columnsKey\"\r\n [items]=\"tables\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n (sdChange)=\"onChangeColumnsKey($event)\"\r\n hideInlineError></sd-autocomplete>\r\n }\r\n @if (!columnsKey) {\r\n <div class=\"fb-columns-list\">\r\n @for (item of columns; track item.key; let idx = $index) {\r\n <div class=\"fb-column-row\" [class.is-active]=\"idx === selectedIdx\">\r\n <span class=\"fb-column-row__type-icon\"><span class=\"msi\">{{ columnTypeSymbol(item.type) }}</span></span>\r\n <div class=\"fb-column-row__meta\">\r\n <div class=\"fb-column-row__label\">\r\n {{ item.label }}\r\n @if (item.validate?.required) {\r\n <span class=\"fb-column-row__req\">*</span>\r\n }\r\n </div>\r\n <div class=\"fb-column-row__sub mono\">{{ item.key }} \u00B7 {{ item.type }}</div>\r\n </div>\r\n <button type=\"button\" class=\"fb-icon-btn\" [attr.aria-label]=\"'core.component.form-builder.column-config' | translate\" (click)=\"editColumn(idx)\">\r\n <span class=\"msi\">edit</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn danger\" [attr.aria-label]=\"'core.component.form-builder.delete' | translate\" (click)=\"removeColumn(idx)\">\r\n <span class=\"msi\">delete</span>\r\n </button>\r\n </div>\r\n }\r\n <a class=\"fb-add-link\" (click)=\"addColumn()\">\r\n <span class=\"msi\">add</span>\r\n {{ 'core.component.form-builder.add-column' | translate }}\r\n </a>\r\n </div>\r\n }\r\n </div>\r\n</details>\r\n\r\n<sd-modal [title]=\"'core.component.form-builder.column-config' | translate\" width=\"600px\">\r\n @if (column) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"column.key\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.column-name' | translate\" [(model)]=\"column.label\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.width' | translate\" [(model)]=\"column.width\"></attribute-input>\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"column.validate!.required\"></attribute-switch>\r\n <attribute-select [form]=\"form\" [label]=\"'core.component.form-builder.data-type' | translate\" [(model)]=\"column.type\" [items]=\"types\"></attribute-select>\r\n </div>\r\n </details>\r\n @if (column.type === 'boolean') {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.show-when-true' | translate\" [(model)]=\"column.displayOnTrue\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.show-when-false' | translate\" [(model)]=\"column.displayOnFalse\"></attribute-input>\r\n </div>\r\n </details>\r\n } @else if (column.type === 'values') {\r\n <attribute-selection\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [component]=\"column\"\r\n [(valuesKey)]=\"column.valuesKey\"\r\n [(values)]=\"column.values\"></attribute-selection>\r\n } @else if (column.type === 'file' || column.type === 'image') {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">settings</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.parameter' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-parameter [label]=\"'core.component.form-builder.assign-parameter' | translate\" [components]=\"components\" [(model)]=\"column!.args\"></attribute-parameter>\r\n </div>\r\n </details>\r\n }\r\n }\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"onConfirm()\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n" }]
5484
5467
  }], ctorParameters: () => [{ type: undefined, decorators: [{
5468
+ type: Optional
5469
+ }, {
5485
5470
  type: Inject,
5486
5471
  args: [SD_FORM_GENERIC_CONFIGURATION]
5487
5472
  }] }], propDecorators: { modal: [{
@@ -5558,11 +5543,11 @@ class TableAttribute {
5558
5543
  this.#changes.next();
5559
5544
  };
5560
5545
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableAttribute, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5561
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TableAttribute, isStandalone: true, selector: "table-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <attribute-table\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(columnsKey)]=\"component.columnsKey\"\r\n [(columns)]=\"component.columns\"\r\n (columnsKeyChange)=\"onChanges()\"\r\n (columnsChange)=\"onChanges()\"></attribute-table>\r\n}\r\n", dependencies: [{ kind: "component", type: SdSection, selector: "sd-section", inputs: ["title", "subTitle", "icon", "iconColor", "collapsed", "collapsable", "hideHeader", "noPaddingBody"], outputs: ["collapsedChange"] }, { kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeTable, selector: "attribute-table", inputs: ["components", "variables", "columnsKey", "columns"], outputs: ["columnsKeyChange", "columnsChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5546
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TableAttribute, isStandalone: true, selector: "table-attribute", inputs: { components: "components", variables: "variables", _component: ["component", "_component"] }, ngImport: i0, template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <attribute-table\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(columnsKey)]=\"component.columnsKey\"\r\n [(columns)]=\"component.columns\"\r\n (columnsKeyChange)=\"onChanges()\"\r\n (columnsChange)=\"onChanges()\"></attribute-table>\r\n}\r\n", dependencies: [{ kind: "component", type: AttributeTemplate, selector: "attribute-template", inputs: ["component"], outputs: ["sdChange"] }, { kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeSwitch, selector: "attribute-switch", inputs: ["form", "label", "model"], outputs: ["modelChange"] }, { kind: "component", type: AttributeTable, selector: "attribute-table", inputs: ["components", "variables", "columnsKey", "columns"], outputs: ["columnsKeyChange", "columnsChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5562
5547
  }
5563
5548
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableAttribute, decorators: [{
5564
5549
  type: Component,
5565
- args: [{ selector: 'table-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdSection, AttributeTemplate, AttributeInput, AttributeSwitch, AttributeTable, AttributeExpression], template: "<sd-section class=\"mt-8\" title=\"Th\u00F4ng tin chung\" icon=\"info\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" label=\"T\u00EAn hi\u1EC3n th\u1ECB\" [(model)]=\"component.label\"></attribute-input>\r\n</sd-section>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <sd-section class=\"mt-8\" title=\"Hi\u1EC3n th\u1ECB\" icon=\"visibility\">\r\n <attribute-switch label=\"V\u00F4 hi\u1EC7u\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n label=\"Hi\u1EC3n th\u1ECB khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n label=\"\u1EA8n khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n label=\"V\u00F4 hi\u1EC7u khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <sd-section class=\"mt-8\" title=\"R\u00E0ng bu\u1ED9c\" icon=\"verified_user\">\r\n <attribute-switch [form]=\"form\" label=\"B\u1EAFt bu\u1ED9c\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n label=\"B\u1EAFt bu\u1ED9c khi\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </sd-section>\r\n <attribute-table\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(columnsKey)]=\"component.columnsKey\"\r\n [(columns)]=\"component.columns\"\r\n (columnsKeyChange)=\"onChanges()\"\r\n (columnsChange)=\"onChanges()\"></attribute-table>\r\n}\r\n" }]
5550
+ args: [{ selector: 'table-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeTemplate, AttributeInput, AttributeSwitch, AttributeTable, AttributeExpression, TranslatePipe], template: "<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-template [component]=\"component\" (sdChange)=\"onChangeTemplate($event)\"></attribute-template>\r\n <attribute-input [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"component.key\" [disabled]=\"!!component.template\"></attribute-input>\r\n <attribute-input [form]=\"form\" [label]=\"'core.component.form-builder.label' | translate\" [(model)]=\"component.label\"></attribute-input>\r\n </div>\r\n</details>\r\n\r\n@if (!component.properties!.hidden && !component.properties!.viewed) {\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [label]=\"'core.component.form-builder.disabled' | translate\" [(model)]=\"component.disabled\"></attribute-switch>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.visible-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.visibleWhenExpression\"></attribute-expression>\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.hiddenWhenExpression\"></attribute-expression>\r\n @if (!component.disabled) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.disabled-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.disabledWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">verified</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.validation' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-switch [form]=\"form\" [label]=\"'core.component.form-builder.required' | translate\" [(model)]=\"component.validate!.required\"></attribute-switch>\r\n @if (!component.validate!.required) {\r\n <attribute-expression\r\n [label]=\"'core.component.form-builder.required-when' | translate\"\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(model)]=\"component.properties!.requiredWhenExpression\"></attribute-expression>\r\n }\r\n </div>\r\n </details>\r\n <attribute-table\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [(columnsKey)]=\"component.columnsKey\"\r\n [(columns)]=\"component.columns\"\r\n (columnsKeyChange)=\"onChanges()\"\r\n (columnsChange)=\"onChanges()\"></attribute-table>\r\n}\r\n" }]
5566
5551
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { components: [{
5567
5552
  type: Input,
5568
5553
  args: [{ required: true }]
@@ -5602,17 +5587,103 @@ class TableControl {
5602
5587
  ngOnDestroy() {
5603
5588
  this.#subscription.unsubscribe();
5604
5589
  }
5590
+ columnIcon = (type) => {
5591
+ switch (type) {
5592
+ case 'number':
5593
+ return '123';
5594
+ case 'date':
5595
+ case 'datetime':
5596
+ return 'calendar_month';
5597
+ case 'boolean':
5598
+ return 'check_box';
5599
+ case 'file':
5600
+ return 'attach_file';
5601
+ case 'image':
5602
+ return 'image';
5603
+ case 'values':
5604
+ case 'radio':
5605
+ return 'radio_button_checked';
5606
+ case 'string':
5607
+ default:
5608
+ return 'text_fields';
5609
+ }
5610
+ };
5611
+ sampleRows = () => [0, 1, 2];
5612
+ cellPreview = (column, rowIndex) => {
5613
+ if (rowIndex === 0)
5614
+ return column.key || column.label || '-';
5615
+ if (column.type === 'number')
5616
+ return rowIndex + 1;
5617
+ if (column.type === 'boolean')
5618
+ return rowIndex === 1 ? '✓' : '—';
5619
+ if (column.type === 'date' || column.type === 'datetime')
5620
+ return '12/06/2026';
5621
+ if (column.type === 'file')
5622
+ return '—';
5623
+ return rowIndex === 1 ? 'Sample value' : '—';
5624
+ };
5605
5625
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableControl, deps: [{ token: i0.ChangeDetectorRef }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
5606
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TableControl, isStandalone: true, selector: "table-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "@if (component.properties?.viewed) {\r\n @if (component.columns?.length) {\r\n <div class=\"c-table\">\r\n <div class=\"c-header d-flex align-items-center bg-secondary-light\">\r\n @for (column of component.columns; track column.key) {\r\n <div class=\"c-item\" [style.width]=\"column.width\">\r\n {{ column.label }}\r\n </div>\r\n }\r\n </div>\r\n <div class=\"c-content\">\r\n <div class=\"row-table d-flex align-items-center\">\r\n @for (column of component.columns; track column.key) {\r\n <div class=\"c-item text-secondary\" [style.width]=\"column.width\">{{ column.key }}</div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n @if (component.columns?.length) {\r\n <div class=\"c-table\">\r\n <div class=\"c-header d-flex align-items-center bg-primary-light\">\r\n @for (column of component.columns; track column.key) {\r\n <div class=\"c-item\" [style.width]=\"column.width\">\r\n {{ column.label }}\r\n </div>\r\n }\r\n </div>\r\n <div class=\"c-content\">\r\n <div class=\"row-table d-flex align-items-center\">\r\n @for (column of component.columns; track column.key) {\r\n <div class=\"c-item text-secondary\" [style.width]=\"column.width\">{{ column.key }}</div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n}\r\n", styles: [".c-table{border:1px solid #ddd}.c-table .c-header{border:1px solid #ddd;border-bottom:0!important}.c-table .c-header .c-item{font-weight:500}.c-table .c-content{border:1px solid #ddd}.c-table .c-item{border:1px solid #ddd;padding:8px 10px;width:-webkit-fill-available;min-width:75px}.c-table .c-item h .spc{color:#ddd}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5626
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: TableControl, isStandalone: true, selector: "table-control", inputs: { _component: ["component", "_component"] }, ngImport: i0, template: "<div class=\"fb-table-control\" [class.is-viewed]=\"component.properties?.viewed\">\n <div class=\"fb-table-control__label\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span>*</span>\n }\n </div>\n\n @if (component.columns?.length) {\n <div class=\"fb-table-control__frame\">\n <div class=\"fb-table-control__header\">\n @for (column of component.columns; track column.key) {\n <div class=\"fb-table-control__cell\" [style.width]=\"column.width\">\n <span class=\"fb-table-control__icon msi\">{{ columnIcon(column.type) }}</span>\n <span>{{ column.label }}</span>\n @if (column.validate?.required) {\n <span class=\"fb-table-control__required\">*</span>\n }\n </div>\n }\n </div>\n\n <div class=\"fb-table-control__body\">\n @for (row of sampleRows(); track row) {\n <div class=\"fb-table-control__row\">\n @for (column of component.columns; track column.key) {\n <div class=\"fb-table-control__cell\" [style.width]=\"column.width\">\n {{ cellPreview(column, row) }}\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <button type=\"button\" class=\"fb-table-control__add\">\n <span>+</span>\n Add row\n </button>\n }\n</div>\n", styles: [".fb-table-control{display:flex;flex-direction:column;gap:8px;min-width:0;color:var(--sd-black500, #212121)}.fb-table-control__label{font-size:14px;line-height:20px;font-weight:600;color:var(--sd-black400, #757575)}.fb-table-control__label span{color:var(--sd-error, #F82C13)}.fb-table-control__frame{width:100%;min-width:0;overflow:hidden;border:1px solid var(--sd-black200, #E6E6E6);border-radius:10px;background:#fff}.fb-table-control__header,.fb-table-control__row{display:flex;min-width:max-content}.fb-table-control__header{min-height:44px;background:color-mix(in srgb,var(--sd-black100, #F2F2F2) 70%,#fff);border-bottom:1px solid var(--sd-black200, #E6E6E6)}.fb-table-control__row{min-height:42px;border-bottom:1px solid var(--sd-black200, #E6E6E6)}.fb-table-control__row:last-child{border-bottom:0}.fb-table-control__cell{flex:1 0 136px;min-width:96px;display:inline-flex;align-items:center;gap:7px;padding:10px 14px;color:var(--sd-black400, #757575);font-size:13px;line-height:18px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-right:0}.fb-table-control__cell:last-child{border-right:0}.fb-table-control__header .fb-table-control__cell{color:var(--sd-black400, #757575);font-weight:700}.fb-table-control__icon{width:16px;height:16px;flex:0 0 16px;display:inline-flex;align-items:center;justify-content:center;color:var(--sd-black400, #757575);font-size:16px;line-height:1;font-variation-settings:\"FILL\" 0,\"wght\" 300,\"GRAD\" 0,\"opsz\" 20}.fb-table-control__required{color:var(--sd-error, #F82C13)}.fb-table-control__add{align-self:flex-start;height:28px;border:0;background:transparent;color:var(--sd-primary, #2A66F4);display:inline-flex;align-items:center;gap:8px;padding:0 6px;font-size:14px;font-weight:600;cursor:default}.fb-table-control__add span{font-size:18px;line-height:1}.fb-table-control.is-viewed .fb-table-control__header{background:var(--sd-black100, #F2F2F2)}.fb-table-control.is-viewed .fb-table-control__add{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5607
5627
  }
5608
5628
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: TableControl, decorators: [{
5609
5629
  type: Component,
5610
- args: [{ selector: 'table-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "@if (component.properties?.viewed) {\r\n @if (component.columns?.length) {\r\n <div class=\"c-table\">\r\n <div class=\"c-header d-flex align-items-center bg-secondary-light\">\r\n @for (column of component.columns; track column.key) {\r\n <div class=\"c-item\" [style.width]=\"column.width\">\r\n {{ column.label }}\r\n </div>\r\n }\r\n </div>\r\n <div class=\"c-content\">\r\n <div class=\"row-table d-flex align-items-center\">\r\n @for (column of component.columns; track column.key) {\r\n <div class=\"c-item text-secondary\" [style.width]=\"column.width\">{{ column.key }}</div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n} @else {\r\n <div class=\"d-block mb-0 T14M\">\r\n {{ component.label }}\r\n @if (component.validate?.required) {\r\n <span class=\"text-error mb-2\">*</span>\r\n }\r\n </div>\r\n @if (component.columns?.length) {\r\n <div class=\"c-table\">\r\n <div class=\"c-header d-flex align-items-center bg-primary-light\">\r\n @for (column of component.columns; track column.key) {\r\n <div class=\"c-item\" [style.width]=\"column.width\">\r\n {{ column.label }}\r\n </div>\r\n }\r\n </div>\r\n <div class=\"c-content\">\r\n <div class=\"row-table d-flex align-items-center\">\r\n @for (column of component.columns; track column.key) {\r\n <div class=\"c-item text-secondary\" [style.width]=\"column.width\">{{ column.key }}</div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n}\r\n", styles: [".c-table{border:1px solid #ddd}.c-table .c-header{border:1px solid #ddd;border-bottom:0!important}.c-table .c-header .c-item{font-weight:500}.c-table .c-content{border:1px solid #ddd}.c-table .c-item{border:1px solid #ddd;padding:8px 10px;width:-webkit-fill-available;min-width:75px}.c-table .c-item h .spc{color:#ddd}\n"] }]
5630
+ args: [{ selector: 'table-control', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule], template: "<div class=\"fb-table-control\" [class.is-viewed]=\"component.properties?.viewed\">\n <div class=\"fb-table-control__label\">\n {{ component.label }}\n @if (component.validate?.required) {\n <span>*</span>\n }\n </div>\n\n @if (component.columns?.length) {\n <div class=\"fb-table-control__frame\">\n <div class=\"fb-table-control__header\">\n @for (column of component.columns; track column.key) {\n <div class=\"fb-table-control__cell\" [style.width]=\"column.width\">\n <span class=\"fb-table-control__icon msi\">{{ columnIcon(column.type) }}</span>\n <span>{{ column.label }}</span>\n @if (column.validate?.required) {\n <span class=\"fb-table-control__required\">*</span>\n }\n </div>\n }\n </div>\n\n <div class=\"fb-table-control__body\">\n @for (row of sampleRows(); track row) {\n <div class=\"fb-table-control__row\">\n @for (column of component.columns; track column.key) {\n <div class=\"fb-table-control__cell\" [style.width]=\"column.width\">\n {{ cellPreview(column, row) }}\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n <button type=\"button\" class=\"fb-table-control__add\">\n <span>+</span>\n Add row\n </button>\n }\n</div>\n", styles: [".fb-table-control{display:flex;flex-direction:column;gap:8px;min-width:0;color:var(--sd-black500, #212121)}.fb-table-control__label{font-size:14px;line-height:20px;font-weight:600;color:var(--sd-black400, #757575)}.fb-table-control__label span{color:var(--sd-error, #F82C13)}.fb-table-control__frame{width:100%;min-width:0;overflow:hidden;border:1px solid var(--sd-black200, #E6E6E6);border-radius:10px;background:#fff}.fb-table-control__header,.fb-table-control__row{display:flex;min-width:max-content}.fb-table-control__header{min-height:44px;background:color-mix(in srgb,var(--sd-black100, #F2F2F2) 70%,#fff);border-bottom:1px solid var(--sd-black200, #E6E6E6)}.fb-table-control__row{min-height:42px;border-bottom:1px solid var(--sd-black200, #E6E6E6)}.fb-table-control__row:last-child{border-bottom:0}.fb-table-control__cell{flex:1 0 136px;min-width:96px;display:inline-flex;align-items:center;gap:7px;padding:10px 14px;color:var(--sd-black400, #757575);font-size:13px;line-height:18px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;border-right:0}.fb-table-control__cell:last-child{border-right:0}.fb-table-control__header .fb-table-control__cell{color:var(--sd-black400, #757575);font-weight:700}.fb-table-control__icon{width:16px;height:16px;flex:0 0 16px;display:inline-flex;align-items:center;justify-content:center;color:var(--sd-black400, #757575);font-size:16px;line-height:1;font-variation-settings:\"FILL\" 0,\"wght\" 300,\"GRAD\" 0,\"opsz\" 20}.fb-table-control__required{color:var(--sd-error, #F82C13)}.fb-table-control__add{align-self:flex-start;height:28px;border:0;background:transparent;color:var(--sd-primary, #2A66F4);display:inline-flex;align-items:center;gap:8px;padding:0 6px;font-size:14px;font-weight:600;cursor:default}.fb-table-control__add span{font-size:18px;line-height:1}.fb-table-control.is-viewed .fb-table-control__header{background:var(--sd-black100, #F2F2F2)}.fb-table-control.is-viewed .fb-table-control__add{display:none}\n"] }]
5611
5631
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: BuilderService }], propDecorators: { _component: [{
5612
5632
  type: Input,
5613
5633
  args: [{ alias: 'component', required: true }]
5614
5634
  }] } });
5615
5635
 
5636
+ const ICON_PRESETS = ['category', 'folder', 'inventory_2', 'group_work', 'workspaces', 'view_quilt'];
5637
+ const COLOR_PRESETS = ['primary', 'secondary', 'success', 'warning', 'error'];
5638
+ class GroupAttribute {
5639
+ // ── constants ────────────────────────────────────────────────────────
5640
+ iconPresets = ICON_PRESETS;
5641
+ colorPresets = COLOR_PRESETS;
5642
+ componentIcons = COMPONENT_ICONS;
5643
+ form = new FormGroup({});
5644
+ // ── signal input ─────────────────────────────────────────────────────
5645
+ /** Required group reference. Mutated in place khi user pick icon/color/expression. */
5646
+ group = input.required();
5647
+ // ── injected services ────────────────────────────────────────────────
5648
+ #builderService = inject(BuilderService);
5649
+ #ref = inject(ChangeDetectorRef);
5650
+ constructor() {
5651
+ // Bảo đảm group có properties + defaults khi input ref thay đổi.
5652
+ // untracked() vì ta mutate group (không phải read signal) — tránh tạo cycle.
5653
+ effect(() => {
5654
+ const g = this.group();
5655
+ untracked(() => {
5656
+ if (!g.properties) {
5657
+ g.properties = { icon: 'category', color: 'primary' };
5658
+ }
5659
+ else {
5660
+ g.properties.icon = g.properties.icon || 'category';
5661
+ g.properties.color = g.properties.color || 'primary';
5662
+ }
5663
+ });
5664
+ });
5665
+ }
5666
+ pickIcon = (icon) => {
5667
+ this.group().properties.icon = icon;
5668
+ this.#builderService.componentEmitters.next(this.group());
5669
+ this.#ref.markForCheck();
5670
+ };
5671
+ pickColor = (color) => {
5672
+ this.group().properties.color = color;
5673
+ this.#builderService.componentEmitters.next(this.group());
5674
+ this.#ref.markForCheck();
5675
+ };
5676
+ symbolForChild = (c) => {
5677
+ return this.componentIcons[c.type]?.symbol ?? 'help';
5678
+ };
5679
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: GroupAttribute, deps: [], target: i0.ɵɵFactoryTarget.Component });
5680
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: GroupAttribute, isStandalone: true, selector: "group-attribute", inputs: { group: { classPropertyName: "group", publicName: "group", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@let g = group();\r\n\r\n<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-input [form]=\"form\" [(model)]=\"g.label\" [label]=\"'core.component.form-builder.label' | translate\"></attribute-input>\r\n\r\n <div class=\"fb-field\">\r\n <div class=\"fb-field__label\">{{ 'core.component.form-builder.group-icon' | translate }}</div>\r\n <div class=\"fb-icon-picker\">\r\n @for (icon of iconPresets; track icon) {\r\n <button type=\"button\" class=\"fb-icon-picker__btn\"\r\n [class.is-active]=\"g.properties.icon === icon\"\r\n (click)=\"pickIcon(icon)\">\r\n <span class=\"msi\">{{ icon }}</span>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"fb-field\">\r\n <div class=\"fb-field__label\">{{ 'core.component.form-builder.group-accent-color' | translate }}</div>\r\n <div class=\"fb-color-swatches\">\r\n @for (color of colorPresets; track color) {\r\n <span class=\"fb-color-swatch\"\r\n [class]=\"color\"\r\n [class.is-active]=\"g.properties.color === color\"\r\n (click)=\"pickColor(color)\"\r\n [attr.aria-label]=\"color\"></span>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</details>\r\n\r\n<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">account_tree</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.group-children' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n @if (!g.components?.length) {\r\n <div class=\"fb-children-empty\">{{ 'core.component.form-builder.group-no-children' | translate }}</div>\r\n } @else {\r\n <div class=\"fb-children-list\">\r\n @for (child of g.components; track child.id) {\r\n <div class=\"fb-child-row\">\r\n <span class=\"fb-child-row__icon\"><span class=\"msi\">{{ symbolForChild(child) }}</span></span>\r\n <span class=\"fb-child-row__label\">{{ child.label }}</span>\r\n <span class=\"fb-child-row__key\">{{ child.key }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</details>\r\n\r\n<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-expression\r\n [components]=\"[]\"\r\n [variables]=\"[]\"\r\n [(model)]=\"g.properties.visibleWhenExpression\"\r\n [label]=\"'core.component.form-builder.visible-when' | translate\">\r\n </attribute-expression>\r\n <attribute-expression\r\n [components]=\"[]\"\r\n [variables]=\"[]\"\r\n [(model)]=\"g.properties.hiddenWhenExpression\"\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\">\r\n </attribute-expression>\r\n </div>\r\n</details>\r\n", styles: [":host{display:block}.fb-children-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant);font-style:italic;padding:8px 0}\n"], dependencies: [{ kind: "component", type: AttributeInput, selector: "attribute-input", inputs: ["form", "label", "disabled", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: AttributeExpression, selector: "attribute-expression", inputs: ["components", "variables", "label", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5681
+ }
5682
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: GroupAttribute, decorators: [{
5683
+ type: Component,
5684
+ args: [{ selector: 'group-attribute', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AttributeInput, AttributeExpression, TranslatePipe], template: "@let g = group();\r\n\r\n<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">info</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.general' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-input [form]=\"form\" [(model)]=\"g.label\" [label]=\"'core.component.form-builder.label' | translate\"></attribute-input>\r\n\r\n <div class=\"fb-field\">\r\n <div class=\"fb-field__label\">{{ 'core.component.form-builder.group-icon' | translate }}</div>\r\n <div class=\"fb-icon-picker\">\r\n @for (icon of iconPresets; track icon) {\r\n <button type=\"button\" class=\"fb-icon-picker__btn\"\r\n [class.is-active]=\"g.properties.icon === icon\"\r\n (click)=\"pickIcon(icon)\">\r\n <span class=\"msi\">{{ icon }}</span>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"fb-field\">\r\n <div class=\"fb-field__label\">{{ 'core.component.form-builder.group-accent-color' | translate }}</div>\r\n <div class=\"fb-color-swatches\">\r\n @for (color of colorPresets; track color) {\r\n <span class=\"fb-color-swatch\"\r\n [class]=\"color\"\r\n [class.is-active]=\"g.properties.color === color\"\r\n (click)=\"pickColor(color)\"\r\n [attr.aria-label]=\"color\"></span>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</details>\r\n\r\n<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">account_tree</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.group-children' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n @if (!g.components?.length) {\r\n <div class=\"fb-children-empty\">{{ 'core.component.form-builder.group-no-children' | translate }}</div>\r\n } @else {\r\n <div class=\"fb-children-list\">\r\n @for (child of g.components; track child.id) {\r\n <div class=\"fb-child-row\">\r\n <span class=\"fb-child-row__icon\"><span class=\"msi\">{{ symbolForChild(child) }}</span></span>\r\n <span class=\"fb-child-row__label\">{{ child.label }}</span>\r\n <span class=\"fb-child-row__key\">{{ child.key }}</span>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</details>\r\n\r\n<details class=\"fb-section\" open>\r\n <summary class=\"fb-section__head\">\r\n <span class=\"msi\">visibility</span>\r\n <span class=\"fb-section__title\">{{ 'core.component.form-builder.display' | translate }}</span>\r\n <span class=\"msi chev\">chevron_right</span>\r\n </summary>\r\n <div class=\"fb-section__body\">\r\n <attribute-expression\r\n [components]=\"[]\"\r\n [variables]=\"[]\"\r\n [(model)]=\"g.properties.visibleWhenExpression\"\r\n [label]=\"'core.component.form-builder.visible-when' | translate\">\r\n </attribute-expression>\r\n <attribute-expression\r\n [components]=\"[]\"\r\n [variables]=\"[]\"\r\n [(model)]=\"g.properties.hiddenWhenExpression\"\r\n [label]=\"'core.component.form-builder.hidden-when' | translate\">\r\n </attribute-expression>\r\n </div>\r\n</details>\r\n", styles: [":host{display:block}.fb-children-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant);font-style:italic;padding:8px 0}\n"] }]
5685
+ }], ctorParameters: () => [] });
5686
+
5616
5687
  const ValidationAlerts = [
5617
5688
  {
5618
5689
  value: 'error',
@@ -5695,13 +5766,15 @@ class ConfigureValidationComponent {
5695
5766
  this.accept.emit(this.validations);
5696
5767
  this.modal?.close();
5697
5768
  };
5698
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ConfigureValidationComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: SD_FORM_GENERIC_CONFIGURATION }], target: i0.ɵɵFactoryTarget.Component });
5699
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ConfigureValidationComponent, isStandalone: true, selector: "configure-validation", outputs: { accept: "accept" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<sd-modal title=\"C\u1EA5u h\u00ECnh x\u00E1c th\u1EF1c l\u1ED7i/c\u1EA3nh b\u00E1o\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\r\n @for (validation of validations; track $index; let idx = $index) {\r\n <div class=\"mat-elevation-z2 position-relative p-8 mb-16\" style=\"border-radius: 8px;\">\r\n <div class=\"row mx-0\">\r\n <sd-select\r\n class=\"col-3\"\r\n label=\"Lo\u1EA1i th\u00F4ng b\u00E1o\"\r\n [(model)]=\"validation.alert\"\r\n [items]=\"alerts\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required></sd-select>\r\n @if (validation.type === 'expression') {\r\n <sd-input class=\"col-9\" [form]=\"form\" label=\"Th\u00F4ng b\u00E1o hi\u1EC3n th\u1ECB\" [(model)]=\"validation.message\" required></sd-input>\r\n <expression-builder class=\"col-12\" label=\"Bi\u1EC3u th\u1EE9c \u0111i\u1EC1u ki\u1EC7n\" [(model)]=\"validation.expression\" [attributes]=\"attributes\"></expression-builder>\r\n } @else if (validation.type === 'function') {\r\n <sd-select\r\n class=\"col-9\"\r\n [form]=\"form\"\r\n [(model)]=\"validation.code\"\r\n [items]=\"functions\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required></sd-select>\r\n }\r\n <mat-icon class=\"c-close-icon\" (click)=\"removaValidation(idx)\">delete</mat-icon>\r\n <!-- <sd-button\r\n \r\n prefixIcon=\"delete\"\r\n (click)=\"removaValidation(idx)\"\r\n color=\"error\"\r\n type=\"link\"></sd-button> -->\r\n </div>\r\n </div>\r\n }\r\n <sd-button title=\"Th\u00EAm x\u00E1c th\u1EF1c\" [matMenuTriggerFor]=\"menu\" prefixIcon=\"add\" color=\"primary\" type=\"link\"></sd-button>\r\n <mat-menu #menu=\"matMenu\">\r\n <button (click)=\"addValidation('expression')\" mat-menu-item type=\"button\">\r\n <!-- <mat-icon fontIcon=\"warning\"></mat-icon> -->\r\n <span>Bi\u1EC3u th\u1EE9c</span>\r\n </button>\r\n <button (click)=\"addValidation('function')\" mat-menu-item type=\"button\">\r\n <!-- <mat-icon fontIcon=\"error\"></mat-icon> -->\r\n <span>Ph\u01B0\u01A1ng th\u1EE9c s\u1EB5n c\u00F3</span>\r\n </button>\r\n </mat-menu>\r\n <ng-container sdFooter>\r\n <sd-button type=\"fill\" title=\"L\u01B0u\" (click)=\"updateValidations()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n", styles: [".text-primary{color:var(--sd-primary)!important}.bg-primary{background:var(--sd-primary)!important}.border-primary{border-color:var(--sd-primary)!important}.text-primary-light{color:var(--sd-primary-light)!important}.bg-primary-light{background:var(--sd-primary-light)!important}.border-primary-light{border-color:var(--sd-primary-light)!important}.text-primary-dark{color:var(--sd-primary-dark)!important}.bg-primary-dark{background:var(--sd-primary-dark)!important}.border-primary-dark{border-color:var(--sd-primary-dark)!important}.text-info{color:var(--sd-info)!important}.bg-info{background:var(--sd-info)!important}.border-info{border-color:var(--sd-info)!important}.text-info-light{color:var(--sd-info-light)!important}.bg-info-light{background:var(--sd-info-light)!important}.border-info-light{border-color:var(--sd-info-light)!important}.text-info-dark{color:var(--sd-info-dark)!important}.bg-info-dark{background:var(--sd-info-dark)!important}.border-info-dark{border-color:var(--sd-info-dark)!important}.text-success{color:var(--sd-success)!important}.bg-success{background:var(--sd-success)!important}.border-success{border-color:var(--sd-success)!important}.text-success-light{color:var(--sd-success-light)!important}.bg-success-light{background:var(--sd-success-light)!important}.border-success-light{border-color:var(--sd-success-light)!important}.text-success-dark{color:var(--sd-success-dark)!important}.bg-success-dark{background:var(--sd-success-dark)!important}.border-success-dark{border-color:var(--sd-success-dark)!important}.text-warning{color:var(--sd-warning)!important}.bg-warning{background:var(--sd-warning)!important}.border-warning{border-color:var(--sd-warning)!important}.text-warning-light{color:var(--sd-warning-light)!important}.bg-warning-light{background:var(--sd-warning-light)!important}.border-warning-light{border-color:var(--sd-warning-light)!important}.text-warning-dark{color:var(--sd-warning-dark)!important}.bg-warning-dark{background:var(--sd-warning-dark)!important}.border-warning-dark{border-color:var(--sd-warning-dark)!important}.text-error{color:var(--sd-error)!important}.bg-error{background:var(--sd-error)!important}.border-error{border-color:var(--sd-error)!important}.text-error-light{color:var(--sd-error-light)!important}.bg-error-light{background:var(--sd-error-light)!important}.border-error-light{border-color:var(--sd-error-light)!important}.text-error-dark{color:var(--sd-error-dark)!important}.bg-error-dark{background:var(--sd-error-dark)!important}.border-error-dark{border-color:var(--sd-error-dark)!important}.text-secondary{color:var(--sd-secondary)!important}.bg-secondary{background:var(--sd-secondary)!important}.border-secondary{border-color:var(--sd-secondary)!important}.text-secondary-light{color:var(--sd-secondary-light)!important}.bg-secondary-light{background:var(--sd-secondary-light)!important}.border-secondary-light{border-color:var(--sd-secondary-light)!important}.text-secondary-dark{color:var(--sd-secondary-dark)!important}.bg-secondary-dark{background:var(--sd-secondary-dark)!important}.border-secondary-dark{border-color:var(--sd-secondary-dark)!important}.text-light{color:var(--sd-light)!important}.bg-light{background:var(--sd-light)!important}.border-light{border-color:var(--sd-light)!important}.text-dark{color:var(--sd-dark)!important}.bg-dark{background:var(--sd-dark)!important}.border-dark{border-color:var(--sd-dark)!important}.text-black500{color:var(--sd-black500)!important}.bg-black500{background:var(--sd-black500)!important}.border-black500{border-color:var(--sd-black500)!important}.text-black400{color:var(--sd-black400)!important}.bg-black400{background:var(--sd-black400)!important}.border-black400{border-color:var(--sd-black400)!important}.text-black300{color:var(--sd-black300)!important}.bg-black300{background:var(--sd-black300)!important}.border-black300{border-color:var(--sd-black300)!important}.text-black200{color:var(--sd-black200)!important}.bg-black200{background:var(--sd-black200)!important}.border-black200{border-color:var(--sd-black200)!important}.text-black100{color:var(--sd-black100)!important}.bg-black100{background:var(--sd-black100)!important}.border-black100{border-color:var(--sd-black100)!important}.text-white{color:#fff!important}.bg-white{background:#fff!important}.border-white{border-color:#fff!important}.text-black{color:#000!important}.bg-black{background:#000!important}.border-black{border-color:#000!important}.c-close-icon{margin-left:auto;font-size:16px;width:16px;height:16px;cursor:pointer;border-radius:50%;color:var(--sd-error);top:4px;right:4px;position:absolute}.c-close-icon:hover{background-color:var(--sd-black200)}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$5.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$5.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$5.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: ExpressionBuilderComponent, selector: "expression-builder", inputs: ["label", "attributes", "model"], outputs: ["modelChange", "sdChange", "edit"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5769
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ConfigureValidationComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: SD_FORM_GENERIC_CONFIGURATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
5770
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: ConfigureValidationComponent, isStandalone: true, selector: "configure-validation", outputs: { accept: "accept" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<sd-modal [title]=\"'core.component.form-builder.config-validation-error-warning' | translate\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\r\n @for (validation of validations; track $index; let idx = $index) {\r\n <div class=\"mat-elevation-z2 position-relative p-8 mb-16\" style=\"border-radius: 8px;\">\r\n <div class=\"row mx-0\">\r\n <sd-select\r\n class=\"col-3\"\r\n [label]=\"'core.component.form-builder.message-type' | translate\"\r\n [(model)]=\"validation.alert\"\r\n [items]=\"alerts\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required></sd-select>\r\n @if (validation.type === 'expression') {\r\n <sd-input class=\"col-9\" [form]=\"form\" [label]=\"'core.component.form-builder.message-display' | translate\" [(model)]=\"validation.message\" required></sd-input>\r\n <expression-builder class=\"col-12\" [label]=\"'core.component.form-builder.condition-expression' | translate\" [(model)]=\"validation.expression\" [attributes]=\"attributes\"></expression-builder>\r\n } @else if (validation.type === 'function') {\r\n <sd-select\r\n class=\"col-9\"\r\n [form]=\"form\"\r\n [(model)]=\"validation.code\"\r\n [items]=\"functions\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required></sd-select>\r\n }\r\n <mat-icon class=\"c-close-icon\" (click)=\"removaValidation(idx)\">delete</mat-icon>\r\n <!-- <sd-button\r\n \r\n prefixIcon=\"delete\"\r\n (click)=\"removaValidation(idx)\"\r\n color=\"error\"\r\n type=\"link\"></sd-button> -->\r\n </div>\r\n </div>\r\n }\r\n <sd-button [title]=\"'core.component.form-builder.add-validation' | translate\" [matMenuTriggerFor]=\"menu\" prefixIcon=\"add\" color=\"primary\" type=\"link\"></sd-button>\r\n <mat-menu #menu=\"matMenu\">\r\n <button (click)=\"addValidation('expression')\" mat-menu-item type=\"button\">\r\n <!-- <mat-icon fontIcon=\"warning\"></mat-icon> -->\r\n <span>{{ 'core.component.form-builder.expression' | translate }}</span>\r\n </button>\r\n <button (click)=\"addValidation('function')\" mat-menu-item type=\"button\">\r\n <!-- <mat-icon fontIcon=\"error\"></mat-icon> -->\r\n <span>{{ 'core.component.form-builder.available-methods' | translate }}</span>\r\n </button>\r\n </mat-menu>\r\n <ng-container sdFooter>\r\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateValidations()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n", styles: [".text-primary{color:var(--sd-primary)!important}.bg-primary{background:var(--sd-primary)!important}.border-primary{border-color:var(--sd-primary)!important}.text-primary-light{color:var(--sd-primary-light)!important}.bg-primary-light{background:var(--sd-primary-light)!important}.border-primary-light{border-color:var(--sd-primary-light)!important}.text-primary-dark{color:var(--sd-primary-dark)!important}.bg-primary-dark{background:var(--sd-primary-dark)!important}.border-primary-dark{border-color:var(--sd-primary-dark)!important}.text-info{color:var(--sd-info)!important}.bg-info{background:var(--sd-info)!important}.border-info{border-color:var(--sd-info)!important}.text-info-light{color:var(--sd-info-light)!important}.bg-info-light{background:var(--sd-info-light)!important}.border-info-light{border-color:var(--sd-info-light)!important}.text-info-dark{color:var(--sd-info-dark)!important}.bg-info-dark{background:var(--sd-info-dark)!important}.border-info-dark{border-color:var(--sd-info-dark)!important}.text-success{color:var(--sd-success)!important}.bg-success{background:var(--sd-success)!important}.border-success{border-color:var(--sd-success)!important}.text-success-light{color:var(--sd-success-light)!important}.bg-success-light{background:var(--sd-success-light)!important}.border-success-light{border-color:var(--sd-success-light)!important}.text-success-dark{color:var(--sd-success-dark)!important}.bg-success-dark{background:var(--sd-success-dark)!important}.border-success-dark{border-color:var(--sd-success-dark)!important}.text-warning{color:var(--sd-warning)!important}.bg-warning{background:var(--sd-warning)!important}.border-warning{border-color:var(--sd-warning)!important}.text-warning-light{color:var(--sd-warning-light)!important}.bg-warning-light{background:var(--sd-warning-light)!important}.border-warning-light{border-color:var(--sd-warning-light)!important}.text-warning-dark{color:var(--sd-warning-dark)!important}.bg-warning-dark{background:var(--sd-warning-dark)!important}.border-warning-dark{border-color:var(--sd-warning-dark)!important}.text-error{color:var(--sd-error)!important}.bg-error{background:var(--sd-error)!important}.border-error{border-color:var(--sd-error)!important}.text-error-light{color:var(--sd-error-light)!important}.bg-error-light{background:var(--sd-error-light)!important}.border-error-light{border-color:var(--sd-error-light)!important}.text-error-dark{color:var(--sd-error-dark)!important}.bg-error-dark{background:var(--sd-error-dark)!important}.border-error-dark{border-color:var(--sd-error-dark)!important}.text-secondary{color:var(--sd-secondary)!important}.bg-secondary{background:var(--sd-secondary)!important}.border-secondary{border-color:var(--sd-secondary)!important}.text-secondary-light{color:var(--sd-secondary-light)!important}.bg-secondary-light{background:var(--sd-secondary-light)!important}.border-secondary-light{border-color:var(--sd-secondary-light)!important}.text-secondary-dark{color:var(--sd-secondary-dark)!important}.bg-secondary-dark{background:var(--sd-secondary-dark)!important}.border-secondary-dark{border-color:var(--sd-secondary-dark)!important}.text-light{color:var(--sd-light)!important}.bg-light{background:var(--sd-light)!important}.border-light{border-color:var(--sd-light)!important}.text-dark{color:var(--sd-dark)!important}.bg-dark{background:var(--sd-dark)!important}.border-dark{border-color:var(--sd-dark)!important}.text-black500{color:var(--sd-black500)!important}.bg-black500{background:var(--sd-black500)!important}.border-black500{border-color:var(--sd-black500)!important}.text-black400{color:var(--sd-black400)!important}.bg-black400{background:var(--sd-black400)!important}.border-black400{border-color:var(--sd-black400)!important}.text-black300{color:var(--sd-black300)!important}.bg-black300{background:var(--sd-black300)!important}.border-black300{border-color:var(--sd-black300)!important}.text-black200{color:var(--sd-black200)!important}.bg-black200{background:var(--sd-black200)!important}.border-black200{border-color:var(--sd-black200)!important}.text-black100{color:var(--sd-black100)!important}.bg-black100{background:var(--sd-black100)!important}.border-black100{border-color:var(--sd-black100)!important}.text-white{color:#fff!important}.bg-white{background:#fff!important}.border-white{border-color:#fff!important}.text-black{color:#000!important}.bg-black{background:#000!important}.border-black{border-color:#000!important}.c-close-icon{margin-left:auto;font-size:16px;width:16px;height:16px;cursor:pointer;border-radius:50%;color:var(--sd-error);top:4px;right:4px;position:absolute}.c-close-icon:hover{background-color:var(--sd-black200)}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1$4.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1$4.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1$4.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdInput, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: ExpressionBuilderComponent, selector: "expression-builder", inputs: ["label", "attributes", "model"], outputs: ["modelChange", "sdChange", "edit"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5700
5771
  }
5701
5772
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: ConfigureValidationComponent, decorators: [{
5702
5773
  type: Component,
5703
- args: [{ selector: 'configure-validation', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatMenuModule, SdModal, SdButton, SdInput, SdSelect, ExpressionBuilderComponent, MatIconModule], template: "<sd-modal title=\"C\u1EA5u h\u00ECnh x\u00E1c th\u1EF1c l\u1ED7i/c\u1EA3nh b\u00E1o\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\r\n @for (validation of validations; track $index; let idx = $index) {\r\n <div class=\"mat-elevation-z2 position-relative p-8 mb-16\" style=\"border-radius: 8px;\">\r\n <div class=\"row mx-0\">\r\n <sd-select\r\n class=\"col-3\"\r\n label=\"Lo\u1EA1i th\u00F4ng b\u00E1o\"\r\n [(model)]=\"validation.alert\"\r\n [items]=\"alerts\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required></sd-select>\r\n @if (validation.type === 'expression') {\r\n <sd-input class=\"col-9\" [form]=\"form\" label=\"Th\u00F4ng b\u00E1o hi\u1EC3n th\u1ECB\" [(model)]=\"validation.message\" required></sd-input>\r\n <expression-builder class=\"col-12\" label=\"Bi\u1EC3u th\u1EE9c \u0111i\u1EC1u ki\u1EC7n\" [(model)]=\"validation.expression\" [attributes]=\"attributes\"></expression-builder>\r\n } @else if (validation.type === 'function') {\r\n <sd-select\r\n class=\"col-9\"\r\n [form]=\"form\"\r\n [(model)]=\"validation.code\"\r\n [items]=\"functions\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required></sd-select>\r\n }\r\n <mat-icon class=\"c-close-icon\" (click)=\"removaValidation(idx)\">delete</mat-icon>\r\n <!-- <sd-button\r\n \r\n prefixIcon=\"delete\"\r\n (click)=\"removaValidation(idx)\"\r\n color=\"error\"\r\n type=\"link\"></sd-button> -->\r\n </div>\r\n </div>\r\n }\r\n <sd-button title=\"Th\u00EAm x\u00E1c th\u1EF1c\" [matMenuTriggerFor]=\"menu\" prefixIcon=\"add\" color=\"primary\" type=\"link\"></sd-button>\r\n <mat-menu #menu=\"matMenu\">\r\n <button (click)=\"addValidation('expression')\" mat-menu-item type=\"button\">\r\n <!-- <mat-icon fontIcon=\"warning\"></mat-icon> -->\r\n <span>Bi\u1EC3u th\u1EE9c</span>\r\n </button>\r\n <button (click)=\"addValidation('function')\" mat-menu-item type=\"button\">\r\n <!-- <mat-icon fontIcon=\"error\"></mat-icon> -->\r\n <span>Ph\u01B0\u01A1ng th\u1EE9c s\u1EB5n c\u00F3</span>\r\n </button>\r\n </mat-menu>\r\n <ng-container sdFooter>\r\n <sd-button type=\"fill\" title=\"L\u01B0u\" (click)=\"updateValidations()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n", styles: [".text-primary{color:var(--sd-primary)!important}.bg-primary{background:var(--sd-primary)!important}.border-primary{border-color:var(--sd-primary)!important}.text-primary-light{color:var(--sd-primary-light)!important}.bg-primary-light{background:var(--sd-primary-light)!important}.border-primary-light{border-color:var(--sd-primary-light)!important}.text-primary-dark{color:var(--sd-primary-dark)!important}.bg-primary-dark{background:var(--sd-primary-dark)!important}.border-primary-dark{border-color:var(--sd-primary-dark)!important}.text-info{color:var(--sd-info)!important}.bg-info{background:var(--sd-info)!important}.border-info{border-color:var(--sd-info)!important}.text-info-light{color:var(--sd-info-light)!important}.bg-info-light{background:var(--sd-info-light)!important}.border-info-light{border-color:var(--sd-info-light)!important}.text-info-dark{color:var(--sd-info-dark)!important}.bg-info-dark{background:var(--sd-info-dark)!important}.border-info-dark{border-color:var(--sd-info-dark)!important}.text-success{color:var(--sd-success)!important}.bg-success{background:var(--sd-success)!important}.border-success{border-color:var(--sd-success)!important}.text-success-light{color:var(--sd-success-light)!important}.bg-success-light{background:var(--sd-success-light)!important}.border-success-light{border-color:var(--sd-success-light)!important}.text-success-dark{color:var(--sd-success-dark)!important}.bg-success-dark{background:var(--sd-success-dark)!important}.border-success-dark{border-color:var(--sd-success-dark)!important}.text-warning{color:var(--sd-warning)!important}.bg-warning{background:var(--sd-warning)!important}.border-warning{border-color:var(--sd-warning)!important}.text-warning-light{color:var(--sd-warning-light)!important}.bg-warning-light{background:var(--sd-warning-light)!important}.border-warning-light{border-color:var(--sd-warning-light)!important}.text-warning-dark{color:var(--sd-warning-dark)!important}.bg-warning-dark{background:var(--sd-warning-dark)!important}.border-warning-dark{border-color:var(--sd-warning-dark)!important}.text-error{color:var(--sd-error)!important}.bg-error{background:var(--sd-error)!important}.border-error{border-color:var(--sd-error)!important}.text-error-light{color:var(--sd-error-light)!important}.bg-error-light{background:var(--sd-error-light)!important}.border-error-light{border-color:var(--sd-error-light)!important}.text-error-dark{color:var(--sd-error-dark)!important}.bg-error-dark{background:var(--sd-error-dark)!important}.border-error-dark{border-color:var(--sd-error-dark)!important}.text-secondary{color:var(--sd-secondary)!important}.bg-secondary{background:var(--sd-secondary)!important}.border-secondary{border-color:var(--sd-secondary)!important}.text-secondary-light{color:var(--sd-secondary-light)!important}.bg-secondary-light{background:var(--sd-secondary-light)!important}.border-secondary-light{border-color:var(--sd-secondary-light)!important}.text-secondary-dark{color:var(--sd-secondary-dark)!important}.bg-secondary-dark{background:var(--sd-secondary-dark)!important}.border-secondary-dark{border-color:var(--sd-secondary-dark)!important}.text-light{color:var(--sd-light)!important}.bg-light{background:var(--sd-light)!important}.border-light{border-color:var(--sd-light)!important}.text-dark{color:var(--sd-dark)!important}.bg-dark{background:var(--sd-dark)!important}.border-dark{border-color:var(--sd-dark)!important}.text-black500{color:var(--sd-black500)!important}.bg-black500{background:var(--sd-black500)!important}.border-black500{border-color:var(--sd-black500)!important}.text-black400{color:var(--sd-black400)!important}.bg-black400{background:var(--sd-black400)!important}.border-black400{border-color:var(--sd-black400)!important}.text-black300{color:var(--sd-black300)!important}.bg-black300{background:var(--sd-black300)!important}.border-black300{border-color:var(--sd-black300)!important}.text-black200{color:var(--sd-black200)!important}.bg-black200{background:var(--sd-black200)!important}.border-black200{border-color:var(--sd-black200)!important}.text-black100{color:var(--sd-black100)!important}.bg-black100{background:var(--sd-black100)!important}.border-black100{border-color:var(--sd-black100)!important}.text-white{color:#fff!important}.bg-white{background:#fff!important}.border-white{border-color:#fff!important}.text-black{color:#000!important}.bg-black{background:#000!important}.border-black{border-color:#000!important}.c-close-icon{margin-left:auto;font-size:16px;width:16px;height:16px;cursor:pointer;border-radius:50%;color:var(--sd-error);top:4px;right:4px;position:absolute}.c-close-icon:hover{background-color:var(--sd-black200)}\n"] }]
5774
+ args: [{ selector: 'configure-validation', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatMenuModule, SdModal, SdButton, SdInput, SdSelect, ExpressionBuilderComponent, MatIconModule, TranslatePipe], template: "<sd-modal [title]=\"'core.component.form-builder.config-validation-error-warning' | translate\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\r\n @for (validation of validations; track $index; let idx = $index) {\r\n <div class=\"mat-elevation-z2 position-relative p-8 mb-16\" style=\"border-radius: 8px;\">\r\n <div class=\"row mx-0\">\r\n <sd-select\r\n class=\"col-3\"\r\n [label]=\"'core.component.form-builder.message-type' | translate\"\r\n [(model)]=\"validation.alert\"\r\n [items]=\"alerts\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required></sd-select>\r\n @if (validation.type === 'expression') {\r\n <sd-input class=\"col-9\" [form]=\"form\" [label]=\"'core.component.form-builder.message-display' | translate\" [(model)]=\"validation.message\" required></sd-input>\r\n <expression-builder class=\"col-12\" [label]=\"'core.component.form-builder.condition-expression' | translate\" [(model)]=\"validation.expression\" [attributes]=\"attributes\"></expression-builder>\r\n } @else if (validation.type === 'function') {\r\n <sd-select\r\n class=\"col-9\"\r\n [form]=\"form\"\r\n [(model)]=\"validation.code\"\r\n [items]=\"functions\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required></sd-select>\r\n }\r\n <mat-icon class=\"c-close-icon\" (click)=\"removaValidation(idx)\">delete</mat-icon>\r\n <!-- <sd-button\r\n \r\n prefixIcon=\"delete\"\r\n (click)=\"removaValidation(idx)\"\r\n color=\"error\"\r\n type=\"link\"></sd-button> -->\r\n </div>\r\n </div>\r\n }\r\n <sd-button [title]=\"'core.component.form-builder.add-validation' | translate\" [matMenuTriggerFor]=\"menu\" prefixIcon=\"add\" color=\"primary\" type=\"link\"></sd-button>\r\n <mat-menu #menu=\"matMenu\">\r\n <button (click)=\"addValidation('expression')\" mat-menu-item type=\"button\">\r\n <!-- <mat-icon fontIcon=\"warning\"></mat-icon> -->\r\n <span>{{ 'core.component.form-builder.expression' | translate }}</span>\r\n </button>\r\n <button (click)=\"addValidation('function')\" mat-menu-item type=\"button\">\r\n <!-- <mat-icon fontIcon=\"error\"></mat-icon> -->\r\n <span>{{ 'core.component.form-builder.available-methods' | translate }}</span>\r\n </button>\r\n </mat-menu>\r\n <ng-container sdFooter>\r\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateValidations()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n", styles: [".text-primary{color:var(--sd-primary)!important}.bg-primary{background:var(--sd-primary)!important}.border-primary{border-color:var(--sd-primary)!important}.text-primary-light{color:var(--sd-primary-light)!important}.bg-primary-light{background:var(--sd-primary-light)!important}.border-primary-light{border-color:var(--sd-primary-light)!important}.text-primary-dark{color:var(--sd-primary-dark)!important}.bg-primary-dark{background:var(--sd-primary-dark)!important}.border-primary-dark{border-color:var(--sd-primary-dark)!important}.text-info{color:var(--sd-info)!important}.bg-info{background:var(--sd-info)!important}.border-info{border-color:var(--sd-info)!important}.text-info-light{color:var(--sd-info-light)!important}.bg-info-light{background:var(--sd-info-light)!important}.border-info-light{border-color:var(--sd-info-light)!important}.text-info-dark{color:var(--sd-info-dark)!important}.bg-info-dark{background:var(--sd-info-dark)!important}.border-info-dark{border-color:var(--sd-info-dark)!important}.text-success{color:var(--sd-success)!important}.bg-success{background:var(--sd-success)!important}.border-success{border-color:var(--sd-success)!important}.text-success-light{color:var(--sd-success-light)!important}.bg-success-light{background:var(--sd-success-light)!important}.border-success-light{border-color:var(--sd-success-light)!important}.text-success-dark{color:var(--sd-success-dark)!important}.bg-success-dark{background:var(--sd-success-dark)!important}.border-success-dark{border-color:var(--sd-success-dark)!important}.text-warning{color:var(--sd-warning)!important}.bg-warning{background:var(--sd-warning)!important}.border-warning{border-color:var(--sd-warning)!important}.text-warning-light{color:var(--sd-warning-light)!important}.bg-warning-light{background:var(--sd-warning-light)!important}.border-warning-light{border-color:var(--sd-warning-light)!important}.text-warning-dark{color:var(--sd-warning-dark)!important}.bg-warning-dark{background:var(--sd-warning-dark)!important}.border-warning-dark{border-color:var(--sd-warning-dark)!important}.text-error{color:var(--sd-error)!important}.bg-error{background:var(--sd-error)!important}.border-error{border-color:var(--sd-error)!important}.text-error-light{color:var(--sd-error-light)!important}.bg-error-light{background:var(--sd-error-light)!important}.border-error-light{border-color:var(--sd-error-light)!important}.text-error-dark{color:var(--sd-error-dark)!important}.bg-error-dark{background:var(--sd-error-dark)!important}.border-error-dark{border-color:var(--sd-error-dark)!important}.text-secondary{color:var(--sd-secondary)!important}.bg-secondary{background:var(--sd-secondary)!important}.border-secondary{border-color:var(--sd-secondary)!important}.text-secondary-light{color:var(--sd-secondary-light)!important}.bg-secondary-light{background:var(--sd-secondary-light)!important}.border-secondary-light{border-color:var(--sd-secondary-light)!important}.text-secondary-dark{color:var(--sd-secondary-dark)!important}.bg-secondary-dark{background:var(--sd-secondary-dark)!important}.border-secondary-dark{border-color:var(--sd-secondary-dark)!important}.text-light{color:var(--sd-light)!important}.bg-light{background:var(--sd-light)!important}.border-light{border-color:var(--sd-light)!important}.text-dark{color:var(--sd-dark)!important}.bg-dark{background:var(--sd-dark)!important}.border-dark{border-color:var(--sd-dark)!important}.text-black500{color:var(--sd-black500)!important}.bg-black500{background:var(--sd-black500)!important}.border-black500{border-color:var(--sd-black500)!important}.text-black400{color:var(--sd-black400)!important}.bg-black400{background:var(--sd-black400)!important}.border-black400{border-color:var(--sd-black400)!important}.text-black300{color:var(--sd-black300)!important}.bg-black300{background:var(--sd-black300)!important}.border-black300{border-color:var(--sd-black300)!important}.text-black200{color:var(--sd-black200)!important}.bg-black200{background:var(--sd-black200)!important}.border-black200{border-color:var(--sd-black200)!important}.text-black100{color:var(--sd-black100)!important}.bg-black100{background:var(--sd-black100)!important}.border-black100{border-color:var(--sd-black100)!important}.text-white{color:#fff!important}.bg-white{background:#fff!important}.border-white{border-color:#fff!important}.text-black{color:#000!important}.bg-black{background:#000!important}.border-black{border-color:#000!important}.c-close-icon{margin-left:auto;font-size:16px;width:16px;height:16px;cursor:pointer;border-radius:50%;color:var(--sd-error);top:4px;right:4px;position:absolute}.c-close-icon:hover{background-color:var(--sd-black200)}\n"] }]
5704
5775
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
5776
+ type: Optional
5777
+ }, {
5705
5778
  type: Inject,
5706
5779
  args: [SD_FORM_GENERIC_CONFIGURATION]
5707
5780
  }] }], propDecorators: { modal: [{
@@ -5715,96 +5788,117 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
5715
5788
  /* eslint-disable @typescript-eslint/no-explicit-any */
5716
5789
  /* eslint-disable @typescript-eslint/no-unused-vars */
5717
5790
  class SdFormBuilder extends SdBaseSecureComponent {
5718
- ref;
5719
- notifyService;
5720
- confirmService;
5721
- builderService;
5722
- popupViewJSON;
5723
- popupConfigureVariables;
5724
- configureValidation;
5725
- formRender;
5791
+ // ── viewChild signals (Angular 17+) ────────────────────────────────────
5792
+ popupViewJSON = viewChild('popupViewJSON');
5793
+ popupConfigureVariables = viewChild('popupConfigureVariables');
5794
+ configureValidation = viewChild(ConfigureValidationComponent);
5795
+ formRender = viewChild(SdFormRender);
5796
+ // ── injected services ──────────────────────────────────────────────────
5797
+ #ref = inject(ChangeDetectorRef);
5798
+ #notifyService = inject(SdNotifyService);
5799
+ #confirmService = inject(SdConfirmService);
5800
+ #builderService = inject(BuilderService);
5801
+ #i18n = inject(I18nService);
5726
5802
  form = new FormGroup({});
5727
- constructor(ref, notifyService, confirmService, builderService) {
5728
- super();
5729
- this.ref = ref;
5730
- this.notifyService = notifyService;
5731
- this.confirmService = confirmService;
5732
- this.builderService = builderService;
5733
- }
5803
+ // ── signal inputs ──────────────────────────────────────────────────────
5804
+ /** Input chính: schema form. Mỗi lần ref thay đổi → effect sẽ clone về local arrays. */
5805
+ formGeneric = input(undefined);
5806
+ // ── component registry (immutable) ─────────────────────────────────────
5807
+ formBuilderComponents = FormBuilderComponents;
5808
+ componentIcons = COMPONENT_ICONS;
5809
+ // ── palette state (signal + computed group buckets) ────────────────────
5810
+ paletteSearch = signal('');
5811
+ paletteGroups = computed(() => {
5812
+ const term = this.paletteSearch().trim().toLowerCase();
5813
+ const match = (c) => !term || c.name.toLowerCase().includes(term) || c.type.toLowerCase().includes(term);
5814
+ const buckets = { basic: [], choice: [], advanced: [], layout: [] };
5815
+ for (const c of this.formBuilderComponents) {
5816
+ if (match(c))
5817
+ buckets[c.group].push(c);
5818
+ }
5819
+ return [
5820
+ { key: 'basic', label: 'Basic', items: buckets.basic },
5821
+ { key: 'choice', label: 'Choice', items: buckets.choice },
5822
+ { key: 'advanced', label: 'Advanced', items: buckets.advanced },
5823
+ { key: 'layout', label: 'Layout', items: buckets.layout },
5824
+ ].filter(g => g.items.length > 0);
5825
+ });
5826
+ // ── local mutable state ────────────────────────────────────────────────
5827
+ // Components/variables/validations giữ là plain arrays vì code hiện tại
5828
+ // mutate in-place rất nhiều chỗ (push, splice, forEach …). Đổi sang signal
5829
+ // tốn rủi ro với rất ít lợi ích — chỉ markForCheck() khi cần.
5734
5830
  components = [];
5735
5831
  variables = [];
5736
5832
  validations = [];
5737
- // @Input('components') set _components(components: (SdFormGenericComponent | SdFormGenericGroup)[] | undefined | null) {
5738
- // // Luôn clone components để tránh ảnh hưởng đến tham số truyền vào
5739
- // if (Array.isArray(components)) {
5740
- // this.components = JSON.parse(JSON.stringify(components));
5741
- // } else {
5742
- // this.components = [];
5743
- // }
5744
- // this.#componentsChanges.next();
5745
- // }
5746
- // Mỗi lần mở popup thì sử dụng clone variables vào clonedVariables, khi nào bấm ok thì mới gán ngược lại clonedVariables vào variables
5833
+ /** Cloned variables dùng cho modal "Configure variables" (huỷ thì discard, ok thì gán ngược). */
5747
5834
  clonedVariables = [];
5748
- // @Input('variables') set _variables(variables: SdFormGenericVariable[] | undefined | null) {
5749
- // // Luôn clone components để tránh ảnh hưởng đến tham số truyền vào
5750
- // if (Array.isArray(variables)) {
5751
- // this.variables = JSON.parse(JSON.stringify(variables));
5752
- // } else {
5753
- // this.variables = [];
5754
- // }
5755
- // this.#variablesChanges.next();
5756
- // }
5757
- set _formGeneric(formGeneric) {
5758
- // Luôn clone (JSONS stringfy) để tránh ảnh hưởng đến tham số truyền vào
5759
- // Xử lý gán components
5760
- if (Array.isArray(formGeneric?.components)) {
5761
- this.components = JSON.parse(JSON.stringify(formGeneric?.components));
5762
- }
5763
- else {
5764
- this.components = [];
5765
- }
5766
- this.#componentsChanges.next();
5767
- // Xử lý gán variables
5768
- if (Array.isArray(formGeneric?.variables)) {
5769
- this.variables = JSON.parse(JSON.stringify(formGeneric?.variables));
5770
- }
5771
- else {
5772
- this.variables = [];
5773
- }
5774
- this.#variablesChanges.next();
5775
- // Xử lý gán validations
5776
- if (Array.isArray(formGeneric?.validations)) {
5777
- this.validations = JSON.parse(JSON.stringify(formGeneric?.validations));
5778
- }
5779
- else {
5780
- this.validations = [];
5781
- }
5782
- this.#validationsChanges.next();
5783
- }
5784
- formBuilderComponents = FormBuilderComponents;
5785
- selectedComponent;
5835
+ selectedComponent = signal(undefined);
5836
+ isPreview = signal(false);
5837
+ /** Signal toàn cục: TRUE khi BẤT KỲ cdkDrag nào đang active (palette, canvas, group, resize).
5838
+ * Trigger class `.fb-shell--dragging` để ẩn hover/actions/resize toàn diện, không phụ thuộc :has(). */
5839
+ isAnyDragging = signal(false);
5786
5840
  expand = true;
5787
5841
  dragDropRows = [];
5788
5842
  isDragging = false;
5789
5843
  targetItem = undefined;
5844
+ lastDragPointer;
5845
+ /** Handler chung cho mọi cdkDragStarted — set signal global true. */
5846
+ onAnyDragStarted = () => {
5847
+ this.isAnyDragging.set(true);
5848
+ };
5849
+ onAnyDragMoved = (event) => {
5850
+ this.lastDragPointer = event.pointerPosition;
5851
+ const rowEl = document
5852
+ .elementFromPoint(event.pointerPosition.x, event.pointerPosition.y)
5853
+ ?.closest('.fb-row');
5854
+ const rowIndex = rowEl?.id?.startsWith('row_') ? Number(rowEl.id.replace('row_', '')) : NaN;
5855
+ const row = Number.isNaN(rowIndex) ? undefined : this.dragDropRows.find(t => t.rowIndex === rowIndex);
5856
+ if (row && this.targetItem !== row) {
5857
+ this.targetItem = row;
5858
+ this.#ref.markForCheck();
5859
+ }
5860
+ };
5861
+ /** Handler chung cho mọi cdkDragEnded — set signal global false (dùng setTimeout 0
5862
+ * để chờ CDK xử lý xong drop event trước khi UI re-enable). */
5863
+ onAnyDragEnded = () => {
5864
+ setTimeout(() => {
5865
+ this.isAnyDragging.set(false);
5866
+ this.lastDragPointer = undefined;
5867
+ this.targetItem = undefined;
5868
+ this.#ref.markForCheck();
5869
+ }, 0);
5870
+ };
5790
5871
  #componentsChanges = new Subject();
5791
5872
  #variablesChanges = new Subject();
5792
5873
  #validationsChanges = new Subject();
5793
5874
  #subscription = new Subscription();
5794
- isPreview = false;
5875
+ constructor() {
5876
+ super();
5877
+ // Khi input `formGeneric` ref thay đổi: clone components/variables/validations
5878
+ // sang local arrays và bắn subject tương ứng cho stream debounced (syncRows).
5879
+ // untracked() bao bọc các mutation để không tạo cycle (effect chỉ tracks formGeneric()).
5880
+ effect(() => {
5881
+ const fg = this.formGeneric();
5882
+ untracked(() => {
5883
+ this.components = Array.isArray(fg?.components) ? JSON.parse(JSON.stringify(fg.components)) : [];
5884
+ this.variables = Array.isArray(fg?.variables) ? JSON.parse(JSON.stringify(fg.variables)) : [];
5885
+ this.validations = Array.isArray(fg?.validations) ? JSON.parse(JSON.stringify(fg.validations)) : [];
5886
+ this.#componentsChanges.next();
5887
+ this.#variablesChanges.next();
5888
+ this.#validationsChanges.next();
5889
+ });
5890
+ });
5891
+ }
5795
5892
  ngOnInit() {
5796
5893
  this.#subscription.add(this.#componentsChanges.pipe(debounceTime(200), startWith('')).subscribe(() => {
5797
- // Khi component thay đổi thì sync lại
5798
5894
  this.#syncComponentsToRows();
5799
- this.ref.markForCheck();
5895
+ this.#ref.markForCheck();
5800
5896
  }));
5801
5897
  this.#subscription.add(this.#variablesChanges.pipe(debounceTime(200), startWith('')).subscribe(() => {
5802
- // Khi component thay đổi thì sync lại
5803
- this.ref.markForCheck();
5898
+ this.#ref.markForCheck();
5804
5899
  }));
5805
5900
  this.#subscription.add(this.#validationsChanges.pipe(debounceTime(200), startWith('')).subscribe(() => {
5806
- // Khi component thay đổi thì sync lại
5807
- this.ref.markForCheck();
5901
+ this.#ref.markForCheck();
5808
5902
  }));
5809
5903
  }
5810
5904
  ngOnDestroy() {
@@ -5812,52 +5906,177 @@ class SdFormBuilder extends SdBaseSecureComponent {
5812
5906
  }
5813
5907
  addComponent = (item, index) => {
5814
5908
  const id = GenerateId();
5815
- const key = GenerateKey();
5816
- const formRenderComponent = {
5817
- id,
5818
- key,
5819
- type: item.type,
5820
- label: item.type,
5821
- layout: {
5822
- columns: '12',
5823
- },
5824
- validate: {
5825
- required: false,
5826
- },
5827
- disabled: false,
5828
- properties: {},
5829
- };
5909
+ let newComponent;
5910
+ if (item.type === 'group') {
5911
+ // Group là layout container, không có key/validate; có nested components[] + properties{icon,color}.
5912
+ newComponent = {
5913
+ id,
5914
+ type: 'group',
5915
+ label: 'Group',
5916
+ layout: { columns: '12' },
5917
+ components: [],
5918
+ properties: {
5919
+ icon: item.symbol || 'category',
5920
+ color: 'primary',
5921
+ },
5922
+ };
5923
+ }
5924
+ else if (item.type === 'break') {
5925
+ // Break: 12-col luôn, đóng vai trò row separator cố định. Extend base nên có key
5926
+ // (auto-gen cho stability) nhưng không hiển thị trong attribute panel.
5927
+ newComponent = {
5928
+ id,
5929
+ key: GenerateKey(),
5930
+ type: 'break',
5931
+ label: 'Break',
5932
+ layout: { columns: '12' },
5933
+ validate: {},
5934
+ disabled: false,
5935
+ properties: {},
5936
+ };
5937
+ }
5938
+ else {
5939
+ newComponent = {
5940
+ id,
5941
+ key: GenerateKey(),
5942
+ type: item.type,
5943
+ label: item.type,
5944
+ layout: { columns: '12' },
5945
+ validate: { required: false },
5946
+ disabled: false,
5947
+ properties: {},
5948
+ };
5949
+ }
5830
5950
  if (index !== undefined) {
5831
- this.components.splice(index, 0, formRenderComponent);
5951
+ this.components.splice(index, 0, newComponent);
5832
5952
  }
5833
5953
  else {
5834
- this.components.push(formRenderComponent);
5954
+ this.components.push(newComponent);
5835
5955
  }
5836
5956
  this.#recountTabIndex();
5837
- this.selectedComponent = this.components?.find(component => component.id === id);
5838
- this.selectComponent(this.selectedComponent);
5839
- this.ref.markForCheck();
5957
+ const created = this.components?.find(component => component.id === id);
5958
+ this.selectedComponent.set(created);
5959
+ this.selectComponent(created);
5960
+ this.#ref.markForCheck();
5961
+ };
5962
+ // ── Helpers cho UI mới ────────────────────────────────────────
5963
+ /** Symbol Material để render trên canvas item / attribute header. */
5964
+ symbolFor = (item) => {
5965
+ if (item.type === 'group')
5966
+ return item.properties?.icon || 'category';
5967
+ return this.componentIcons[item.type]?.symbol ?? 'help';
5968
+ };
5969
+ /** Human-readable type label (e.g. "Text field", "Date"). */
5970
+ typeLabelFor = (item) => {
5971
+ return this.componentIcons[item.type]?.label ?? item.type;
5972
+ };
5973
+ /** True nếu component có expression điều kiện — drives the "conditional" status chip. */
5974
+ hasConditional = (item) => {
5975
+ const p = item.properties || {};
5976
+ return !!(p.visibleWhenExpression || p.hiddenWhenExpression || p.disabledWhenExpression || p.requiredWhenExpression);
5977
+ };
5978
+ /** Map SdColor preset → 2 CSS var names cho header-bg và header-fg của group card. */
5979
+ groupColorVars = (color) => {
5980
+ switch (color) {
5981
+ case 'secondary':
5982
+ return { bg: 'var(--md-sys-color-secondary-container)', fg: 'var(--md-sys-color-on-secondary-container)' };
5983
+ case 'success':
5984
+ return { bg: 'var(--md-sys-color-success-container)', fg: 'var(--md-sys-color-success)' };
5985
+ case 'warning':
5986
+ return { bg: 'var(--md-sys-color-warning-container)', fg: 'var(--md-sys-color-warning)' };
5987
+ case 'error':
5988
+ return { bg: 'var(--md-sys-color-error-container)', fg: 'var(--md-sys-color-error)' };
5989
+ case 'primary':
5990
+ default:
5991
+ return { bg: 'var(--md-sys-color-primary-container)', fg: 'var(--md-sys-color-primary)' };
5992
+ }
5993
+ };
5994
+ /** Segmented Design/Preview toggle (replaces play_circle/stop_circle). */
5995
+ setMode = (preview) => {
5996
+ this.isPreview.set(preview);
5997
+ };
5998
+ /** Nested drop handler — when dragging a palette item or canvas item INTO a group body. */
5999
+ dropInGroup = (event, group) => {
6000
+ if (event.previousContainer === event.container) {
6001
+ moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
6002
+ return;
6003
+ }
6004
+ const dropped = event.previousContainer.data[event.previousIndex];
6005
+ if (dropped && 'symbol' in dropped) {
6006
+ // Palette → group: tạo component mới rồi push vào group.components.
6007
+ const item = dropped;
6008
+ if (item.type === 'group') {
6009
+ this.#notifyService.warning('Group lồng group chưa được hỗ trợ.');
6010
+ return;
6011
+ }
6012
+ const newComponent = this.#createComponentFromPalette(item);
6013
+ group.components.splice(event.currentIndex, 0, newComponent);
6014
+ this.selectedComponent.set(newComponent);
6015
+ this.#ref.markForCheck();
6016
+ }
6017
+ else {
6018
+ // Canvas → group: chuyển instance hiện có.
6019
+ const component = dropped;
6020
+ if (component.type === 'group') {
6021
+ this.#notifyService.warning('Group lồng group chưa được hỗ trợ.');
6022
+ return;
6023
+ }
6024
+ transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex);
6025
+ this.#syncRowsToComponents();
6026
+ }
6027
+ };
6028
+ /** Quick-add break sau row chỉ định.
6029
+ * Tính component index cuối cùng của row đó trong this.components, splice break vào sau.
6030
+ * Không qua palette — chỉ là utility action bám theo row trên canvas.
6031
+ */
6032
+ insertBreakAfter = (row) => {
6033
+ const lastItemId = row.items[row.items.length - 1]?.id;
6034
+ const insertAfter = lastItemId ? this.components.findIndex(c => c.id === lastItemId) : this.components.length - 1;
6035
+ const newBreak = {
6036
+ id: GenerateId(),
6037
+ key: GenerateKey(),
6038
+ type: 'break',
6039
+ label: 'Break',
6040
+ layout: { columns: '12' },
6041
+ validate: {},
6042
+ disabled: false,
6043
+ properties: {},
6044
+ };
6045
+ this.components.splice(insertAfter + 1, 0, newBreak);
6046
+ this.#recountTabIndex();
6047
+ this.#ref.markForCheck();
6048
+ };
6049
+ /** Remove a child component from a group's nested list. */
6050
+ removeFromGroup = (group, id) => {
6051
+ group.components = group.components.filter(c => c.id !== id);
6052
+ if (this.selectedComponent()?.id === id)
6053
+ this.selectedComponent.set(undefined);
6054
+ this.#ref.markForCheck();
5840
6055
  };
5841
6056
  removeComponent = (id) => {
5842
6057
  this.components = this.components.filter((t) => t.id !== id);
5843
6058
  this.#recountTabIndex();
5844
6059
  };
5845
6060
  selectComponent = (item) => {
5846
- this.selectedComponent = item;
5847
- this.ref.markForCheck();
6061
+ this.selectedComponent.set(item);
6062
+ this.#ref.markForCheck();
5848
6063
  };
5849
6064
  onClickedOutside = (e) => {
5850
6065
  const classList = e.target.classList;
5851
6066
  if (!classList.length || classList.contains('components') || classList.contains('cdk-drop-list')) {
5852
- this.selectedComponent = undefined;
6067
+ this.selectedComponent.set(undefined);
5853
6068
  }
5854
6069
  };
5855
6070
  clickFormContentEmpty = () => {
5856
6071
  if (!this.dragDropRows?.length) {
5857
- this.selectedComponent = undefined;
6072
+ this.selectedComponent.set(undefined);
5858
6073
  }
5859
6074
  };
5860
6075
  drop = (event) => {
6076
+ if (this.#dropIntoGroupAtPointer(event)) {
6077
+ this.#recountTabIndex();
6078
+ return;
6079
+ }
5861
6080
  if (event.previousContainer === event.container) {
5862
6081
  moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
5863
6082
  this.#syncRowsToComponents();
@@ -5872,7 +6091,7 @@ class SdFormBuilder extends SdBaseSecureComponent {
5872
6091
  }
5873
6092
  else {
5874
6093
  const drop = event.previousContainer.data[0];
5875
- if ('icon' in drop) {
6094
+ if (drop && 'symbol' in drop) {
5876
6095
  // transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex);
5877
6096
  const droppedItem = event.previousContainer.data[event.previousIndex];
5878
6097
  const rowIndex = event.currentIndex;
@@ -5898,8 +6117,9 @@ class SdFormBuilder extends SdBaseSecureComponent {
5898
6117
  this.isDragging = false;
5899
6118
  };
5900
6119
  onMouseover = (event, rowItem) => {
5901
- if (this.isDragging) {
6120
+ if (this.isDragging && this.targetItem !== rowItem) {
5902
6121
  this.targetItem = rowItem;
6122
+ this.#ref.markForCheck();
5903
6123
  }
5904
6124
  };
5905
6125
  // Mouseover thì phải có Focus không thì thẻ sẽ báo lỗi
@@ -5923,7 +6143,7 @@ class SdFormBuilder extends SdBaseSecureComponent {
5923
6143
  this.#syncRowsToComponents();
5924
6144
  }
5925
6145
  else {
5926
- this.notifyService.warning('Không thể di chuyển tới dòng này vì tổng kích thước vượt quá 12 cột');
6146
+ this.#notifyService.warning(this.#i18n.t('core.component.form-builder.row-overflow'));
5927
6147
  }
5928
6148
  }
5929
6149
  }
@@ -5946,8 +6166,9 @@ class SdFormBuilder extends SdBaseSecureComponent {
5946
6166
  };
5947
6167
  }
5948
6168
  });
5949
- if (this.selectedComponent && this.selectedComponent?.layout?.row) {
5950
- this.selectedComponent.layout.row = this.components.find(t => t.id === this.selectedComponent?.id)?.layout?.row;
6169
+ const sel = this.selectedComponent();
6170
+ if (sel && sel?.layout?.row) {
6171
+ sel.layout.row = this.components.find(t => t.id === sel.id)?.layout?.row;
5951
6172
  }
5952
6173
  this.#syncComponentsToRows();
5953
6174
  };
@@ -5982,6 +6203,94 @@ class SdFormBuilder extends SdBaseSecureComponent {
5982
6203
  // rải data ma trận droplist => schema.components
5983
6204
  this.components = this.dragDropRows?.map(e => e.items)?.reduce((current, next) => [...current, ...next], []) || [];
5984
6205
  };
6206
+ #createComponentFromPalette = (item) => {
6207
+ const id = GenerateId();
6208
+ if (item.type === 'group') {
6209
+ return {
6210
+ id,
6211
+ type: 'group',
6212
+ label: 'Group',
6213
+ layout: { columns: '12' },
6214
+ components: [],
6215
+ properties: {
6216
+ icon: item.symbol || 'category',
6217
+ color: 'primary',
6218
+ },
6219
+ };
6220
+ }
6221
+ if (item.type === 'break') {
6222
+ return {
6223
+ id,
6224
+ key: GenerateKey(),
6225
+ type: 'break',
6226
+ label: 'Break',
6227
+ layout: { columns: '12' },
6228
+ validate: {},
6229
+ disabled: false,
6230
+ properties: {},
6231
+ };
6232
+ }
6233
+ return {
6234
+ id,
6235
+ key: GenerateKey(),
6236
+ type: item.type,
6237
+ label: item.type,
6238
+ layout: { columns: '12' },
6239
+ validate: { required: false },
6240
+ disabled: false,
6241
+ properties: {},
6242
+ };
6243
+ };
6244
+ #dropIntoGroupAtPointer = (event) => {
6245
+ const dropPoint = event.dropPoint || this.lastDragPointer;
6246
+ if (!dropPoint)
6247
+ return false;
6248
+ const bodyEl = document.elementFromPoint(dropPoint.x, dropPoint.y)?.closest('.fb-group__body');
6249
+ const groupEl = bodyEl?.closest('.fb-group');
6250
+ const group = groupEl?.id ? this.#findGroupById(groupEl.id) : undefined;
6251
+ if (!group || event.container.data === group.components)
6252
+ return false;
6253
+ const dropped = event.previousContainer.data[event.previousIndex];
6254
+ if (!dropped)
6255
+ return false;
6256
+ if ('symbol' in dropped) {
6257
+ const paletteItem = dropped;
6258
+ if (paletteItem.type === 'group') {
6259
+ this.#notifyService.warning('Group lồng group chưa được hỗ trợ.');
6260
+ return true;
6261
+ }
6262
+ const created = this.#createComponentFromPalette(paletteItem);
6263
+ group.components.push(created);
6264
+ this.selectedComponent.set(created);
6265
+ }
6266
+ else {
6267
+ if (!('type' in dropped))
6268
+ return false;
6269
+ const component = dropped;
6270
+ if (component.type === 'group') {
6271
+ this.#notifyService.warning('Group lồng group chưa được hỗ trợ.');
6272
+ return true;
6273
+ }
6274
+ transferArrayItem(event.previousContainer.data, group.components, event.previousIndex, group.components.length);
6275
+ this.#syncRowsToComponents();
6276
+ this.selectedComponent.set(component);
6277
+ }
6278
+ this.#ref.markForCheck();
6279
+ return true;
6280
+ };
6281
+ #findGroupById = (id, items = this.components) => {
6282
+ for (const item of items) {
6283
+ if (item.type === 'group') {
6284
+ const group = item;
6285
+ if (group.id === id)
6286
+ return group;
6287
+ const nested = this.#findGroupById(id, group.components || []);
6288
+ if (nested)
6289
+ return nested;
6290
+ }
6291
+ }
6292
+ return undefined;
6293
+ };
5985
6294
  changeSizeControl = async (event, item, items, currentIndex) => {
5986
6295
  // const totalColumnInRow = items.map(k => k.layout.columns).reduce((acc, curr) => acc + parseInt(curr, 0), 0);
5987
6296
  const totalColumnBeforeItem = items
@@ -5997,14 +6306,10 @@ class SdFormBuilder extends SdBaseSecureComponent {
5997
6306
  const right = rect.right - left;
5998
6307
  const mouse = event.pointerPosition.x - left;
5999
6308
  const t = Math.round(12 / (100 / ((100 * mouse) / right))) - totalColumnBeforeItem;
6000
- if (t > 12) {
6001
- item.layout.columns = '12';
6002
- }
6003
- else if (t < 2) {
6004
- item.layout.columns = '2';
6005
- }
6006
- else {
6007
- item.layout.columns = `${t}`;
6309
+ // Clamp + skip-if-unchanged để tránh re-render mỗi pixel mouse di chuyển.
6310
+ const newCols = t > 12 ? '12' : t < 2 ? '2' : `${t}`;
6311
+ if (item.layout.columns !== newCols) {
6312
+ item.layout.columns = newCols;
6008
6313
  }
6009
6314
  // document.getElementById('test').innerHTML = `<pre>
6010
6315
  // left: ${left}
@@ -6019,15 +6324,44 @@ class SdFormBuilder extends SdBaseSecureComponent {
6019
6324
  dragEndChangeSizeControl = (event) => {
6020
6325
  this.#recountTabIndex();
6021
6326
  };
6327
+ /** Resize a child item INSIDE a group.
6328
+ * Math: lấy bounding của chính item, tính (mouse.x - item.left) / colWidth = newCols.
6329
+ * Cách này đúng cho cả flex-wrap (item ở wrap row 2+) vì dùng item-relative,
6330
+ * không phải sum-of-all-preceding-cols (sai khi item wrap xuống row mới).
6331
+ */
6332
+ changeSizeChildInGroup = (event, child, group) => {
6333
+ const groupEl = document.getElementById(group.id);
6334
+ const bodyEl = groupEl?.querySelector('.fb-group__body');
6335
+ const childEl = document.getElementById(child.id);
6336
+ if (!bodyEl || !childEl)
6337
+ return;
6338
+ const bodyRect = bodyEl.getBoundingClientRect();
6339
+ const childRect = childEl.getBoundingClientRect();
6340
+ // Width của 1 col trong group body (loại trừ padding nếu có).
6341
+ const bodyStyle = getComputedStyle(bodyEl);
6342
+ const padL = parseFloat(bodyStyle.paddingLeft) || 0;
6343
+ const padR = parseFloat(bodyStyle.paddingRight) || 0;
6344
+ const colWidth = (bodyRect.width - padL - padR) / 12;
6345
+ if (colWidth <= 0)
6346
+ return;
6347
+ // Mới: new right edge = mouse.x; new width = mouse.x - child.left
6348
+ const newWidth = event.pointerPosition.x - childRect.left;
6349
+ let newCols = Math.round(newWidth / colWidth);
6350
+ if (newCols < 2)
6351
+ newCols = 2;
6352
+ if (newCols > 12)
6353
+ newCols = 12;
6354
+ child.layout.columns = `${newCols}`;
6355
+ };
6022
6356
  onChangeViewed = (component) => {
6023
6357
  component.properties.viewed = !component.properties.viewed;
6024
6358
  // Emit khi có sự thay đổi để control và attribute lắng nghe và render lại
6025
- this.builderService.componentEmitters.next(component);
6359
+ this.#builderService.componentEmitters.next(component);
6026
6360
  };
6027
6361
  onChangeHidden = (component) => {
6028
6362
  component.properties.hidden = !component.properties.hidden;
6029
6363
  // Emit khi có sự thay đổi để control và attribute lắng nghe và render lại
6030
- this.builderService.componentEmitters.next(component);
6364
+ this.#builderService.componentEmitters.next(component);
6031
6365
  };
6032
6366
  // Duplicate component nhưng sẽ clear id và key để tránh trùng lặp
6033
6367
  onDuplicate = (component) => {
@@ -6036,16 +6370,17 @@ class SdFormBuilder extends SdBaseSecureComponent {
6036
6370
  clonedComponent.key = GenerateKey();
6037
6371
  this.components.push(clonedComponent);
6038
6372
  this.#recountTabIndex();
6039
- this.selectedComponent = this.components?.find(t => t.id === clonedComponent.id);
6040
- this.selectComponent(this.selectedComponent);
6041
- this.ref.markForCheck();
6373
+ const created = this.components?.find(t => t.id === clonedComponent.id);
6374
+ this.selectedComponent.set(created);
6375
+ this.selectComponent(created);
6376
+ this.#ref.markForCheck();
6042
6377
  };
6043
6378
  // Copy form hiện tại
6044
6379
  jsonString;
6045
6380
  viewJSON = () => {
6046
6381
  this.jsonString = JSON.stringify({ components: this.components });
6047
- this.popupViewJSON?.open();
6048
- this.ref.markForCheck();
6382
+ this.popupViewJSON()?.open();
6383
+ this.#ref.markForCheck();
6049
6384
  };
6050
6385
  updateJSON = () => {
6051
6386
  try {
@@ -6053,9 +6388,9 @@ class SdFormBuilder extends SdBaseSecureComponent {
6053
6388
  const json = JSON.parse(this.jsonString);
6054
6389
  if ('components' in json) {
6055
6390
  this.components = json['components'];
6056
- this.popupViewJSON?.close();
6391
+ this.popupViewJSON()?.close();
6057
6392
  this.#syncComponentsToRows();
6058
- this.ref.markForCheck();
6393
+ this.#ref.markForCheck();
6059
6394
  }
6060
6395
  else {
6061
6396
  throw new Error('Invalid JSON');
@@ -6064,13 +6399,13 @@ class SdFormBuilder extends SdBaseSecureComponent {
6064
6399
  }
6065
6400
  catch (err) {
6066
6401
  console.error(err);
6067
- this.notifyService.warning(err?.message);
6402
+ this.#notifyService.warning(err?.message);
6068
6403
  }
6069
6404
  };
6070
6405
  configureVariables = () => {
6071
6406
  this.clonedVariables = JSON.parse(JSON.stringify(this.variables || []));
6072
- this.popupConfigureVariables?.open();
6073
- this.ref.markForCheck();
6407
+ this.popupConfigureVariables()?.open();
6408
+ this.#ref.markForCheck();
6074
6409
  };
6075
6410
  addVariables = () => {
6076
6411
  this.clonedVariables.push({
@@ -6086,12 +6421,12 @@ class SdFormBuilder extends SdBaseSecureComponent {
6086
6421
  updateVariables = () => {
6087
6422
  if (this.form.invalid) {
6088
6423
  this.form.markAllAsTouched();
6089
- this.ref.markForCheck();
6424
+ this.#ref.markForCheck();
6090
6425
  return;
6091
6426
  }
6092
6427
  this.variables = this.clonedVariables;
6093
- this.popupConfigureVariables?.close();
6094
- this.ref.markForCheck();
6428
+ this.popupConfigureVariables()?.close();
6429
+ this.#ref.markForCheck();
6095
6430
  };
6096
6431
  // Chìa ra cho bên ngoài lấy components hiện tại
6097
6432
  getComponents = () => {
@@ -6113,33 +6448,31 @@ class SdFormBuilder extends SdBaseSecureComponent {
6113
6448
  };
6114
6449
  };
6115
6450
  openConfigureValidation = () => {
6116
- this.configureValidation?.open(this.getForm());
6451
+ this.configureValidation()?.open(this.getForm());
6117
6452
  };
6118
6453
  onUpdateValidations = (validations) => {
6119
6454
  this.validations = validations;
6120
6455
  };
6121
6456
  onValidate = async () => {
6122
- const errorMessages = await this.formRender?.getValidationMessages('error');
6457
+ const errorMessages = await this.formRender()?.getValidationMessages('error');
6123
6458
  if (errorMessages?.length) {
6124
- this.notifyService.error(errorMessages);
6459
+ this.#notifyService.error(errorMessages);
6125
6460
  return;
6126
6461
  }
6127
- const warningMessages = await this.formRender?.getValidationMessages('warning');
6462
+ const warningMessages = await this.formRender()?.getValidationMessages('warning');
6128
6463
  if (warningMessages?.length) {
6129
- this.confirmService.confirm(warningMessages.join(', ')).then(() => {
6130
- this.notifyService.success('Submit success');
6464
+ this.#confirmService.confirm(warningMessages.join(', ')).then(() => {
6465
+ this.#notifyService.success('Submit success');
6131
6466
  });
6132
6467
  }
6133
6468
  else {
6134
- this.notifyService.success('Submit success');
6469
+ this.#notifyService.success('Submit success');
6135
6470
  }
6136
6471
  };
6137
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdFormBuilder, deps: [{ token: i0.ChangeDetectorRef }, { token: i1$6.SdNotifyService }, { token: i1$6.SdConfirmService }, { token: BuilderService }], target: i0.ɵɵFactoryTarget.Component });
6138
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdFormBuilder, isStandalone: true, selector: "sd-form-builder", inputs: { _formGeneric: ["formGeneric", "_formGeneric"] }, viewQueries: [{ propertyName: "popupViewJSON", first: true, predicate: ["popupViewJSON"], descendants: true }, { propertyName: "popupConfigureVariables", first: true, predicate: ["popupConfigureVariables"], descendants: true }, { propertyName: "configureValidation", first: true, predicate: ConfigureValidationComponent, descendants: true }, { propertyName: "formRender", first: true, predicate: SdFormRender, descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"d-flex form-editor\">\r\n <div class=\"d-flex flex-column form-menu\">\r\n <div class=\"c-header\">Components</div>\r\n <div class=\"component-container\" style=\"flex: 1\">\r\n <div class=\"form-editor-group\" cdkDropList [cdkDropListData]=\"formBuilderComponents\" [cdkDropListEnterPredicate]=\"noReturnPredicate\">\r\n @for (formBuilderComponent of formBuilderComponents; track formBuilderComponent.type) {\r\n <div cdkDrag class=\"form-item\" (click)=\"addComponent(formBuilderComponent)\" aria-hidden=\"true\">\r\n <div class=\"c-form-item\">\r\n <span [innerHtml]=\"formBuilderComponent.icon | sdSafeHtml\"></span>\r\n <div class=\"title\">\r\n {{ formBuilderComponent.name }}\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex flex-column form-content\">\r\n <div class=\"c-header d-flex align-items-center justify-content-between\">\r\n <div>B\u1ED1 c\u1EE5c</div>\r\n <div class=\"d-flex align-items-center\" style=\"gap: 8px\">\r\n <mat-icon matTooltip=\"Xem JSON\" fontIcon=\"code\" (click)=\"viewJSON()\"></mat-icon>\r\n <mat-icon matTooltip=\"C\u1EA5u h\u00ECnh bi\u1EBFn\" fontIcon=\"scatter_plot\" (click)=\"configureVariables()\"></mat-icon>\r\n <mat-icon matTooltip=\"C\u1EA5u h\u00ECnh x\u00E1c th\u1EF1c c\u1EA3nh b\u00E1o/l\u1ED7i\" fontIcon=\"error\" (click)=\"openConfigureValidation()\"></mat-icon>\r\n <mat-icon\r\n [matTooltip]=\"isPreview ? 'Tr\u1EDF v\u1EC1 thi\u1EBFt k\u1EBF' : 'Xem th\u1EED'\"\r\n [fontIcon]=\"isPreview ? 'stop_circle' : 'play_circle'\"\r\n (click)=\"isPreview = !isPreview\"></mat-icon>\r\n </div>\r\n </div>\r\n <div class=\"p-12 components\" style=\"flex: 1; overflow-y: auto\" id=\"frmComponent\">\r\n @if (isPreview) {\r\n <sd-form-render [configuration]=\"{ components: this.components, validations: this.validations }\"></sd-form-render>\r\n <sd-button title=\"Validate\" (click)=\"onValidate()\"></sd-button>\r\n } @else {\r\n <div\r\n cdkDropList\r\n cdkDropListOrientation=\"vertical\"\r\n [cdkDropListData]=\"dragDropRows\"\r\n class=\"listY\"\r\n (cdkDropListDropped)=\"drop($event)\"\r\n (click)=\"clickFormContentEmpty()\"\r\n aria-hidden=\"true\">\r\n @for (row of dragDropRows; track row.rowIndex) {\r\n <div\r\n cdkDrag\r\n (mouseover)=\"onMouseover($event, row)\"\r\n (focus)=\"onFocus($event)\"\r\n id=\"row_{{ row.rowIndex }}\"\r\n class=\"row-item\"\r\n aria-hidden=\"true\">\r\n <div class=\"btn-drag-row-item\"><mat-icon matTooltip=\"K\u00E9o l\u00EAn / xu\u1ED1ng\">drag_indicator</mat-icon></div>\r\n <div\r\n class=\"c-row-item\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n [cdkDropListData]=\"row.items\"\r\n (cdkDropListDropped)=\"drop($event)\">\r\n @for (item of row.items; track item.id; let i = $index) {\r\n <div\r\n cdkDrag\r\n [id]=\"item.id\"\r\n class=\"component-item column-{{ item.layout?.columns || 12 }}\"\r\n [class.active]=\"item.id === selectedComponent?.id\"\r\n (click)=\"selectComponent(item)\"\r\n (clickOutside)=\"onClickedOutside($event)\"\r\n (cdkDragStarted)=\"dragStartComponentItem($event)\"\r\n (cdkDragEnded)=\"dragEndComponentItem($event)\"\r\n aria-hidden=\"true\">\r\n <div class=\"c-component-item\" [class.c-hidden]=\"item.properties?.hidden\">\r\n <div class=\"c-actions\">\r\n @if (item.type !== 'group') {\r\n <mat-icon\r\n [matTooltip]=\"item.properties?.viewed ? 'B\u1ECF ch\u1EC9 xem' : 'Ch\u1EC9 xem'\"\r\n (click)=\"onChangeViewed(item)\"\r\n fontSet=\"material-icons-outlined\"\r\n style=\"font-size: 16px; cursor: pointer\"\r\n [class.text-warning]=\"item.properties?.viewed\">\r\n edit_off\r\n </mat-icon>\r\n }\r\n <mat-icon\r\n matTooltip=\"Nh\u00E2n b\u1EA3n\"\r\n (click)=\"onDuplicate(item)\"\r\n fontSet=\"material-icons-outlined\"\r\n style=\"font-size: 16px; cursor: pointer\">\r\n content_copy\r\n </mat-icon>\r\n <mat-icon\r\n [matTooltip]=\"item.properties?.hidden ? 'Hi\u1EC7n' : '\u1EA8n'\"\r\n (click)=\"onChangeHidden(item)\"\r\n fontSet=\"material-icons-outlined\"\r\n style=\"font-size: 16px; cursor: pointer\"\r\n [class.text-warning]=\"item.properties?.hidden\">\r\n visibility_off\r\n </mat-icon>\r\n <mat-icon\r\n matTooltip=\"X\u00F3a\"\r\n (click)=\"removeComponent(item.id)\"\r\n fontSet=\"material-icons-outlined\"\r\n style=\"font-size: 16px; cursor: pointer\"\r\n class=\"text-error\">\r\n delete\r\n </mat-icon>\r\n </div>\r\n @if (item.type === 'textfield') {\r\n <textfield-control [component]=\"item\"></textfield-control>\r\n } @else if (item.type === 'textarea') {\r\n <textarea-control [component]=\"item\"></textarea-control>\r\n } @else if (item.type === 'chip-string') {\r\n <chip-string-control [component]=\"item\"></chip-string-control>\r\n } @else if (item.type === 'chip-calendar') {\r\n <chip-calendar-control [component]=\"item\"></chip-calendar-control>\r\n } @else if (item.type === 'number') {\r\n <number-control [component]=\"item\"></number-control>\r\n } @else if (item.type === 'datetime') {\r\n <datetime-control [component]=\"item\"></datetime-control>\r\n } @else if (item.type === 'select') {\r\n <select-control [component]=\"item\"></select-control>\r\n } @else if (item.type === 'radio') {\r\n <radio-control [component]=\"item\"></radio-control>\r\n } @else if (item.type === 'checkbox') {\r\n <checkbox-control [component]=\"item\"></checkbox-control>\r\n } @else if (item.type === 'html') {\r\n <html-control [component]=\"item\" #html></html-control>\r\n } @else if (item.type === 'upload') {\r\n <upload-control [component]=\"item\"></upload-control>\r\n } @else if (item.type === 'table') {\r\n <table-control [component]=\"item\"></table-control>\r\n }\r\n <div class=\"c-item-backdrop\"></div>\r\n </div>\r\n <div cdkDropList cdkDropListOrientation=\"horizontal\">\r\n <div\r\n cdkDrag\r\n (cdkDragMoved)=\"changeSizeControl($event, item, row.items, i)\"\r\n (cdkDragEnded)=\"dragEndChangeSizeControl($event)\"\r\n class=\"c-bar-resize-right\"\r\n matTooltip=\"Co d\u00E3n\"></div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"d-flex flex-column form-attributes\">\r\n <div class=\"c-header\">Thu\u1ED9c t\u00EDnh</div>\r\n @if (selectedComponent) {\r\n <div class=\"attributes\" style=\"flex: 1\" aria-hidden=\"true\">\r\n @if (selectedComponent.type === 'textfield') {\r\n <textfield-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></textfield-attribute>\r\n } @else if (selectedComponent.type === 'textarea') {\r\n <textarea-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></textarea-attribute>\r\n } @else if (selectedComponent.type === 'chip-string') {\r\n <chip-string-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></chip-string-attribute>\r\n } @else if (selectedComponent.type === 'chip-calendar') {\r\n <chip-calendar-attribute\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [component]=\"selectedComponent\"></chip-calendar-attribute>\r\n } @else if (selectedComponent.type === 'number') {\r\n <number-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></number-attribute>\r\n } @else if (selectedComponent.type === 'datetime') {\r\n <datetime-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></datetime-attribute>\r\n } @else if (selectedComponent.type === 'select') {\r\n <select-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></select-attribute>\r\n } @else if (selectedComponent.type === 'radio') {\r\n <radio-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></radio-attribute>\r\n } @else if (selectedComponent.type === 'checkbox') {\r\n <checkbox-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></checkbox-attribute>\r\n } @else if (selectedComponent.type === 'html') {\r\n <html-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></html-attribute>\r\n } @else if (selectedComponent.type === 'upload') {\r\n <upload-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></upload-attribute>\r\n } @else if (selectedComponent.type === 'table') {\r\n <table-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></table-attribute>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n<sd-modal title=\"JSON\" view=\"dialog\" width=\"80%\" #popupViewJSON>\r\n <sd-textarea [(model)]=\"jsonString\"></sd-textarea>\r\n <ng-container sdFooter>\r\n <sd-button type=\"fill\" title=\"L\u01B0u\" (click)=\"updateJSON()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n<sd-modal title=\"C\u1EA5u h\u00ECnh bi\u1EBFn\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\r\n @for (variable of clonedVariables; track variable.id) {\r\n <div class=\"d-flex align-items-center\" style=\"gap: 8px\">\r\n <sd-input [form]=\"form\" label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"variable.key\" required></sd-input>\r\n <sd-input [form]=\"form\" label=\"Nh\u00E3n hi\u1EC3n th\u1ECB\" [(model)]=\"variable.label\" required></sd-input>\r\n <sd-button prefixIcon=\"delete\" (click)=\"removeVariables(variable.id)\" color=\"error\"></sd-button>\r\n </div>\r\n }\r\n <a href=\"javascript:;\" (click)=\"addVariables()\">Th\u00EAm bi\u1EBFn</a>\r\n <ng-container sdFooter>\r\n <sd-button type=\"fill\" title=\"L\u01B0u\" (click)=\"updateVariables()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n<configure-validation (accept)=\"onUpdateValidations($event)\"></configure-validation>\r\n", styles: [":host::ng-deep .svg{width:40px}:host::ng-deep .mat-form-field.sd-sm.mat-form-field-appearance-outline .mat-form-field-infix input.mat-input-element{margin-top:7px!important}::ng-deep .component-item.cdk-drag-preview .c-component-item{display:none}::ng-deep .component-item.cdk-drag-dragging,::ng-deep .row-item.cdk-drag-dragging{box-shadow:0 4px 8px #0003;border:2px #0e7cfa dashed}::ng-deep .row-item.cdk-drag-preview .c-row-item,::ng-deep .row-item.cdk-drag-preview .btn-drag-row-item{display:none}::ng-deep .form-item.cdk-drag-preview{text-align:center}::ng-deep .form-item.cdk-drag-preview .c-form-item{text-align:center}::ng-deep .form-item.cdk-drag-preview .c-form-item .svg{width:40px}.form-editor{width:100%;height:100%}.form-editor .material-icons{color:#5f6368!important}.form-editor .material-icons:hover{color:#2626b4!important;cursor:pointer!important}.form-editor .c-header{font-weight:500;padding:5px 10px;background-color:#ebebeb;border-bottom:1px solid #d3d3d3;text-transform:uppercase}.form-editor .c-header:last-child{border-right:0!important}.form-editor .c-header a{font-size:12px}.form-editor .form-menu{width:120px}.form-editor .form-menu .component-container{overflow-y:hidden;background:#f6f8fc}.form-editor .form-menu .component-container:hover{overflow-y:auto!important}.form-editor .form-menu .form-editor-group{padding:5px 10px;display:flex;align-items:center;flex-wrap:wrap}.form-editor .form-menu .form-editor-group .form-item{height:68px;display:flex;align-items:center;justify-content:center;font-size:11px;-webkit-user-select:none;user-select:none;color:#333;background:#fff;border:1px solid transparent;width:100px;margin:6px}.form-editor .form-menu .form-editor-group .form-item:hover{background-color:#e7e7e7;border-color:#878b8f;cursor:pointer}.form-editor .form-menu .form-editor-group .form-item .c-form-item{text-align:center}.form-editor .form-menu .form-editor-group .form-item .c-form-item>div.title,.form-editor .form-menu .form-editor-group .form-item .c-form-item>span{text-align:center;white-space:nowrap;font-weight:500}.form-editor .form-content{flex:1;border-right:1px solid #d3d3d3;border-left:1px solid #d3d3d3}.form-editor .form-content .components{background:#fff}.form-editor .form-content .components .row-item{position:relative;transition:transform .2s ease,box-shadow .2s ease;cursor:grab}.form-editor .form-content .components .row-item:hover{outline:1px dashed #bbb;border-radius:8px}.form-editor .form-content .components .row-item:hover .btn-drag-row-item{display:grid}.form-editor .form-content .components .row-item .btn-drag-row-item{display:none;position:absolute;top:0;left:-12px;height:100%;z-index:2;place-items:center;cursor:grab}.form-editor .form-content .components .row-item .btn-drag-row-item mat-icon{font-size:24px;height:24px;width:24px;box-shadow:0 1px 2px #0000001a;background:#fff}.form-editor .form-content .components .component-item{padding:4px 8px;border:2px dashed transparent;position:relative;min-height:28px;cursor:grab;transition:transform .2s ease,box-shadow .2s ease;display:inline-block;margin:4px;border-radius:8px;vertical-align:bottom}.form-editor .form-content .components .component-item:active{cursor:grabbing;box-shadow:0 4px 8px #0003}.form-editor .form-content .components .component-item:hover{border:2px #0e7cfa dashed}.form-editor .form-content .components .component-item:hover .c-actions{display:flex;flex-direction:row;gap:4px}.form-editor .form-content .components .component-item:hover .c-bar-resize-right{display:block;cursor:w-resize}.form-editor .form-content .components .component-item:hover .c-bar-resize-right.disabled{display:none}.form-editor .form-content .components .component-item .c-component-item{overflow:hidden}.form-editor .form-content .components .component-item .c-actions{display:none;position:absolute;right:4px;z-index:2}.form-editor .form-content .components .component-item .c-bar-resize-right{display:none;width:8px;height:80%;position:absolute;top:10%;right:-5px;outline:2px #0e7cfa solid;border-radius:4px;color:#fff;background:#fff;z-index:2}.form-editor .form-content .components .component-item .c-item-backdrop{position:absolute;width:100%;height:100%;top:0;left:0;z-index:1}.form-editor .form-content .components .active{border:2px #0e7cfa solid;outline:1px #0e7cfa solid}.form-editor .form-content .components .column-2{width:calc(16.6666666667% - 8px)}.form-editor .form-content .components .column-3{width:calc(25% - 8px)}.form-editor .form-content .components .column-4{width:calc(33.3333333333% - 8px)}.form-editor .form-content .components .column-5{width:calc(41.6666666667% - 8px)}.form-editor .form-content .components .column-6{width:calc(50% - 8px)}.form-editor .form-content .components .column-7{width:calc(58.3333333333% - 8px)}.form-editor .form-content .components .column-8{width:calc(66.6666666667% - 8px)}.form-editor .form-content .components .column-9{width:calc(75% - 8px)}.form-editor .form-content .components .column-10{width:calc(83.3333333333% - 8px)}.form-editor .form-content .components .column-11{width:calc(91.6666666667% - 8px)}.form-editor .form-content .components .column-12{width:calc(100% - 8px)}.form-editor .form-attributes{width:300px}.form-editor .form-attributes .attributes{overflow-y:auto!important;padding:0 10px;background:#f6f8fc}.form-editor .form-attributes .attributes .group-attribute .title-group{font-weight:500;padding:5px 0;position:relative;cursor:pointer;margin-top:8px}.form-editor .form-attributes .attributes .group-attribute .title-group span{vertical-align:middle;display:inline-block}.form-editor .form-attributes .attributes .group-attribute .title-group mat-icon{vertical-align:middle;position:absolute;right:0}.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute{display:grid;margin-bottom:10px}.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute label{font-size:12px;font-weight:400;margin:0}.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute input,.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute select,.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute textarea{border:1px solid #d3d3d3;height:30px}.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute .select-options{padding:5px 0;border-bottom:1px solid #d3d3d3}.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute .select-options input{width:100%;margin-bottom:5px}.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute .select-options .material-icons{padding-top:22px}.preview-container{margin:0 -24px;position:relative}.preview-container .header-preview{border-bottom:1px solid #eee;padding:10px;font-size:14px;font-weight:500;position:sticky;top:0;background-color:#fff;z-index:9999}.preview-container .header-preview .material-icons:hover{color:#5f6368;cursor:pointer}.preview-container .content{padding:10px}.c-hidden{opacity:.5}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1$4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i5.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i5.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "pipe", type:
6139
- // Core Pipes
6140
- SdSafeHtmlPipe, name: "sdSafeHtml" }, { kind: "component", type:
6472
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdFormBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
6473
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdFormBuilder, isStandalone: true, selector: "sd-form-builder", inputs: { formGeneric: { classPropertyName: "formGeneric", publicName: "formGeneric", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "popupViewJSON", first: true, predicate: ["popupViewJSON"], descendants: true, isSignal: true }, { propertyName: "popupConfigureVariables", first: true, predicate: ["popupConfigureVariables"], descendants: true, isSignal: true }, { propertyName: "configureValidation", first: true, predicate: ConfigureValidationComponent, descendants: true, isSignal: true }, { propertyName: "formRender", first: true, predicate: SdFormRender, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- cdkDropListGroup: auto-connect t\u1EA5t c\u1EA3 cdkDropList trong palette, canvas rows, group bodies.\r\n [class.fb-shell--dragging]: JS-driven flag \u0111\u1EC3 \u1EA9n hover/actions/resize to\u00E0n di\u1EC7n\r\n trong l\u00FAc drag (CSS :has() kh\u00F4ng b\u1EAFt 100% tr\u01B0\u1EDDng h\u1EE3p v\u1EDBi CDK preview clone). -->\r\n<div class=\"fb-shell\" cdkDropListGroup [class.fb-shell--dragging]=\"isAnyDragging()\">\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 LEFT PALETTE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <aside class=\"fb-palette\">\r\n <div class=\"fb-panel-header\">\r\n <div class=\"fb-panel-header__title\">{{ 'core.component.form-builder.components' | translate }}</div>\r\n </div>\r\n\r\n <!-- Search pill -->\r\n <div class=\"fb-palette__search\">\r\n <span class=\"msi\" aria-hidden=\"true\">search</span>\r\n <input\r\n type=\"text\"\r\n [placeholder]=\"'core.component.form-builder.search-components' | translate\"\r\n [value]=\"paletteSearch()\"\r\n (input)=\"paletteSearch.set($any($event.target).value)\" />\r\n <span class=\"kbd\">\u2318K</span>\r\n </div>\r\n\r\n <div class=\"fb-palette__scroll\">\r\n @for (group of paletteGroups(); track group.key) {\r\n <div class=\"fb-palette__group-label\">{{ group.label }}</div>\r\n <div\r\n class=\"fb-palette__list\"\r\n cdkDropList\r\n [cdkDropListData]=\"group.items\"\r\n [cdkDropListEnterPredicate]=\"noReturnPredicate\">\r\n @for (formBuilderComponent of group.items; track formBuilderComponent.type) {\r\n <div\r\n cdkDrag\r\n class=\"fb-palette-item\"\r\n [matTooltip]=\"formBuilderComponent.name\"\r\n matTooltipPosition=\"right\"\n (click)=\"addComponent(formBuilderComponent)\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\"\n aria-hidden=\"true\">\n <span class=\"fb-palette-item__icon\"><span class=\"msi\">{{ formBuilderComponent.symbol }}</span></span>\r\n <span class=\"fb-palette-item__name\">{{ formBuilderComponent.name }}</span>\r\n <span class=\"fb-palette-item__drag\"><span class=\"msi\">drag_indicator</span></span>\r\n <!-- Generic drag preview: ch\u1EC9 icon (puck), label \u1EA9n -->\r\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </aside>\r\n\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 CENTER CANVAS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <section class=\"fb-canvas\">\r\n <header class=\"fb-canvas__header\">\r\n <div class=\"fb-canvas__title\">\r\n <span>{{ 'core.component.form-builder.layout' | translate }}</span>\r\n </div>\r\n <div class=\"fb-canvas__actions\">\r\n <!-- Toolbar cluster: view JSON / variables / validation -->\r\n <button\r\n type=\"button\"\r\n class=\"fb-icon-btn\"\r\n [matTooltip]=\"'core.component.form-builder.view-json' | translate\"\r\n (click)=\"viewJSON()\">\r\n <span class=\"msi\">data_object</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fb-icon-btn\"\r\n [matTooltip]=\"'core.component.form-builder.config-variable' | translate\"\r\n (click)=\"configureVariables()\">\r\n <span class=\"msi\">data_array</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fb-icon-btn\"\r\n [matTooltip]=\"'core.component.form-builder.config-validation-warning-error' | translate\"\r\n (click)=\"openConfigureValidation()\">\r\n <span class=\"msi\">rule</span>\r\n </button>\r\n\r\n <span class=\"fb-divider\"></span>\r\n\r\n <!-- M3 segmented Design/Preview toggle -->\r\n <div class=\"fb-mode-toggle\" role=\"tablist\">\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n [class.is-active]=\"!isPreview()\"\r\n (click)=\"setMode(false)\">\r\n <span class=\"msi\">edit</span>\r\n <span>{{ 'core.component.form-builder.design' | translate }}</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n [class.is-active]=\"isPreview()\"\r\n (click)=\"setMode(true)\">\r\n <span class=\"msi\">visibility</span>\r\n <span>{{ 'core.component.form-builder.preview' | translate }}</span>\r\n </button>\r\n </div>\r\n </div>\r\n </header>\r\n\r\n <div\r\n class=\"fb-canvas__body\"\r\n [class.is-preview]=\"isPreview()\"\r\n id=\"frmComponent\">\r\n @if (isPreview()) {\r\n <!-- \u2500\u2500 Preview mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"fb-preview-card\">\r\n <div class=\"fb-preview-card__chip\">\r\n <span class=\"msi\">visibility</span>\r\n {{ 'core.component.form-builder.preview-runtime' | translate }}\r\n </div>\r\n <sd-form-render [configuration]=\"{ components: this.components, validations: this.validations }\"></sd-form-render>\r\n <div class=\"fb-preview-card__footer\">\r\n <sd-button type=\"outline\" [title]=\"'core.component.form-builder.cancel' | translate\" (click)=\"setMode(false)\"></sd-button>\r\n <sd-button type=\"fill\" color=\"primary\" [title]=\"'core.component.form-builder.submit' | translate\" (click)=\"onValidate()\"></sd-button>\r\n </div>\r\n </div>\r\n } @else {\r\n <!-- \u2500\u2500 Design mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n @if (!dragDropRows.length) {\r\n <div class=\"fb-empty\">\r\n <div class=\"fb-empty__art\"><span class=\"msi\">dashboard_customize</span></div>\r\n <div class=\"fb-empty__title\">{{ 'core.component.form-builder.empty-title' | translate }}</div>\r\n <div class=\"fb-empty__hint\">\r\n {{ 'core.component.form-builder.empty-hint' | translate }}\r\n <span class=\"fb-empty__kbd\"><span class=\"msi\">keyboard</span>\u2318 K</span>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div\r\n cdkDropList\r\n cdkDropListOrientation=\"vertical\"\r\n [cdkDropListData]=\"dragDropRows\"\r\n (cdkDropListDropped)=\"drop($event)\"\r\n (click)=\"clickFormContentEmpty()\"\r\n aria-hidden=\"true\">\r\n @for (row of dragDropRows; track row.rowIndex) {\r\n <div\r\n cdkDrag\r\n class=\"fb-row\"\r\n (mouseover)=\"onMouseover($event, row)\"\r\n (focus)=\"onFocus($event)\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\"\n [class.is-drag-target]=\"targetItem === row\"\n [id]=\"'row_' + row.rowIndex\"\n aria-hidden=\"true\">\r\n <div class=\"fb-row__drag\" [matTooltip]=\"'core.component.form-builder.drag-vertically' | translate\" cdkDragHandle>\r\n <span class=\"msi\">drag_indicator</span>\r\n </div>\r\n <!-- Generic puck preview -->\r\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <!-- Quick-add break button \u2014 show on row hover, insert break after this row -->\r\n <button\r\n type=\"button\"\r\n class=\"fb-row-break-btn\"\r\n [matTooltip]=\"'core.component.form-builder.break' | translate\"\r\n matTooltipPosition=\"right\"\r\n (click)=\"insertBreakAfter(row); $event.stopPropagation()\">\r\n <span class=\"msi\">horizontal_rule</span>\r\n </button>\r\n\r\n <div\r\n class=\"fb-row__items\"\r\n style=\"display: flex; flex: 1; gap: var(--gap-2);\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n [cdkDropListData]=\"row.items\"\r\n (cdkDropListDropped)=\"drop($event)\">\r\n\r\n @for (item of row.items; track item.id; let i = $index) {\r\n <!-- Group component renders as outlined card with colored header bar -->\r\n @if (item.type === 'group') {\r\n @let g = $any(item);\r\n @let cv = groupColorVars(g.properties?.color);\r\n <div\r\n cdkDrag\r\n [id]=\"item.id\"\r\n class=\"fb-group column-{{ item.layout?.columns || 12 }}\"\r\n [class.fb-item]=\"false\"\r\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\r\n [class.is-hidden]=\"item.properties?.hidden\"\r\n [style.flex]=\"'0 0 calc(' + (+(item.layout?.columns || 12)) + '/12 * 100% - var(--gap-2))'\"\r\n [style.maxWidth]=\"'calc(' + (+(item.layout?.columns || 12)) + '/12 * 100% - var(--gap-2))'\"\r\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\r\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <!-- cdkDragHandle: ch\u1EC9 cho ph\u00E9p k\u00E9o group qua header \u2014 body free cho click v\u00E0o child. -->\r\n <div class=\"fb-group__header\" cdkDragHandle [style.background]=\"cv.bg\" [style.color]=\"cv.fg\">\r\n <span class=\"fb-group__icon\"><span class=\"msi\">{{ g.properties?.icon || 'category' }}</span></span>\r\n <span class=\"fb-group__label\">{{ item.label }}</span>\r\n @if (hasConditional(item)) {\r\n <span class=\"fb-group__conditional-chip\">\r\n <span class=\"msi\" style=\"font-size: 12px;\">bolt</span>\r\n {{ 'core.component.form-builder.conditional' | translate }}\r\n </span>\r\n }\r\n <span class=\"fb-group__count\">{{ g.components?.length || 0 }} fields</span>\r\n </div>\r\n <!-- Floating action toolbar -->\r\n <div class=\"fb-actions\">\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\r\n (click)=\"onDuplicate(item); $event.stopPropagation()\">\r\n <span class=\"msi\">content_copy</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [class.warning]=\"item.properties?.hidden\"\r\n [class.on]=\"item.properties?.hidden\"\r\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\r\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\r\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn danger\"\r\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\r\n <span class=\"msi\">delete</span>\r\n </button>\r\n </div>\r\n\r\n <div\n class=\"fb-group__body\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"g.components\"\n (cdkDropListDropped)=\"dropInGroup($event, g)\">\n @if (!g.components?.length) {\r\n <div class=\"fb-group__empty\">\r\n <span class=\"msi\" style=\"font-size: 16px; margin-right: 6px;\">south</span>\r\n {{ 'core.component.form-builder.group-drop-here' | translate }}\r\n </div>\r\n }\r\n @for (child of g.components; track child.id; let ci = $index) {\r\n <div\r\n cdkDrag\r\n [id]=\"child.id\"\r\n class=\"fb-item is-child column-{{ child.layout?.columns || 12 }}\"\r\n [class.is-selected]=\"child.id === selectedComponent()?.id\"\r\n [class.is-hidden]=\"child.properties?.hidden\"\r\n [class.is-readonly]=\"child.properties?.viewed\"\r\n (click)=\"selectComponent(child); $event.stopPropagation()\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\">\n <!-- Generic puck preview -->\r\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <ng-container\r\n *ngTemplateOutlet=\"controlTemplate; context: { $implicit: child }\">\r\n </ng-container>\r\n <!-- Resize handle cho group child \u2014 chia 12-col ngay trong group body.\r\n Wrapping cdkDropList c\u00F3 enterPredicate=false \u0111\u1EC3 KH\u00D4NG nh\u1EADn drop\r\n (ch\u1EC9 d\u00F9ng l\u00E0m context cho cdkDrag), tr\u00E1nh xung \u0111\u1ED9t v\u1EDBi group__body drop list. -->\r\n <div cdkDropList cdkDropListOrientation=\"horizontal\" [cdkDropListEnterPredicate]=\"noReturnPredicate\">\r\n <div\r\n cdkDrag\r\n cdkDragLockAxis=\"x\"\r\n class=\"fb-resize\"\r\n (cdkDragStarted)=\"onAnyDragStarted()\"\r\n (cdkDragMoved)=\"changeSizeChildInGroup($event, child, g)\"\r\n (cdkDragEnded)=\"dragEndChangeSizeControl($event); onAnyDragEnded()\"\r\n [matTooltip]=\"'core.component.form-builder.flex' | translate\"\r\n aria-label=\"resize\"></div>\r\n </div>\r\n <!-- Inline status chips for nested children -->\r\n @if (child.properties?.hidden) {\r\n <span class=\"fb-status-chip hidden\">\r\n <span class=\"msi\">visibility_off</span>\r\n {{ 'core.component.form-builder.hidden' | translate }}\r\n </span>\r\n } @else if (child.properties?.viewed) {\r\n <span class=\"fb-status-chip readonly\">\r\n <span class=\"msi\">edit_off</span>\r\n {{ 'core.component.form-builder.read-only' | translate }}\r\n </span>\r\n } @else if (hasConditional(child)) {\r\n <span class=\"fb-status-chip conditional\">\r\n <span class=\"msi\">bolt</span>\r\n {{ 'core.component.form-builder.conditional' | translate }}\r\n </span>\r\n }\r\n <div class=\"fb-actions\">\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [class.warning]=\"child.properties?.viewed\"\r\n [class.on]=\"child.properties?.viewed\"\r\n [matTooltip]=\"child.properties?.viewed ? ('core.component.form-builder.unset-readonly' | translate) : ('core.component.form-builder.set-readonly' | translate)\"\r\n (click)=\"onChangeViewed(child); $event.stopPropagation()\">\r\n <span class=\"msi\">edit_off</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\r\n (click)=\"onDuplicate(child); $event.stopPropagation()\">\r\n <span class=\"msi\">content_copy</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [class.warning]=\"child.properties?.hidden\"\r\n [class.on]=\"child.properties?.hidden\"\r\n [matTooltip]=\"child.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\r\n (click)=\"onChangeHidden(child); $event.stopPropagation()\">\r\n <span class=\"msi\">{{ child.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn danger\"\r\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"removeFromGroup(g, child.id); $event.stopPropagation()\">\r\n <span class=\"msi\">delete</span>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n } @else if (item.type === 'break') {\r\n <!-- Break: row separator c\u1ED1 \u0111\u1ECBnh. Render 12-col line, kh\u00F4ng c\u00F3 resize/edit attribute. -->\r\n <div\r\n cdkDrag\r\n [id]=\"item.id\"\r\n class=\"fb-item is-break column-12\"\r\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\r\n [class.is-hidden]=\"item.properties?.hidden\"\r\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\r\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <div class=\"fb-break-line\">\r\n <span class=\"msi\">horizontal_rule</span>\r\n <span class=\"fb-break-label\">{{ 'core.component.form-builder.break' | translate }}</span>\r\n </div>\r\n <div class=\"fb-actions\">\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [class.warning]=\"item.properties?.hidden\"\r\n [class.on]=\"item.properties?.hidden\"\r\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\r\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\r\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn danger\"\r\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\r\n <span class=\"msi\">delete</span>\r\n </button>\r\n </div>\r\n </div>\r\n } @else {\r\n <!-- Regular form component -->\r\n <div\r\n cdkDrag\r\n [id]=\"item.id\"\r\n class=\"fb-item column-{{ item.layout?.columns || 12 }}\"\r\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\r\n [class.is-hidden]=\"item.properties?.hidden\"\r\n [class.is-readonly]=\"item.properties?.viewed\"\r\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\r\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n\r\n <!-- Status chip (mutually exclusive priority: hidden > readonly > conditional) -->\r\n @if (item.properties?.hidden) {\r\n <span class=\"fb-status-chip hidden\">\r\n <span class=\"msi\">visibility_off</span>\r\n {{ 'core.component.form-builder.hidden' | translate }}\r\n </span>\r\n } @else if (item.properties?.viewed) {\r\n <span class=\"fb-status-chip readonly\">\r\n <span class=\"msi\">edit_off</span>\r\n {{ 'core.component.form-builder.read-only' | translate }}\r\n </span>\r\n } @else if (hasConditional(item)) {\r\n <span class=\"fb-status-chip conditional\">\r\n <span class=\"msi\">bolt</span>\r\n {{ 'core.component.form-builder.conditional' | translate }}\r\n </span>\r\n }\r\n\r\n <!-- Floating action toolbar pill -->\r\n <div class=\"fb-actions\">\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [class.warning]=\"item.properties?.viewed\"\r\n [class.on]=\"item.properties?.viewed\"\r\n [matTooltip]=\"item.properties?.viewed ? ('core.component.form-builder.unset-readonly' | translate) : ('core.component.form-builder.set-readonly' | translate)\"\r\n (click)=\"onChangeViewed(item); $event.stopPropagation()\">\r\n <span class=\"msi\">edit_off</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\r\n (click)=\"onDuplicate(item); $event.stopPropagation()\">\r\n <span class=\"msi\">content_copy</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [class.warning]=\"item.properties?.hidden\"\r\n [class.on]=\"item.properties?.hidden\"\r\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\r\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\r\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn danger\"\r\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\r\n <span class=\"msi\">delete</span>\r\n </button>\r\n </div>\r\n\r\n <ng-container\r\n *ngTemplateOutlet=\"controlTemplate; context: { $implicit: item }\">\r\n </ng-container>\r\n\r\n <!-- Resize handle (pill) \u2014 cdkDragLockAxis=\"x\" \u0111\u1EC3 ch\u1EC9 k\u00E9o ngang.\r\n Wrapping cdkDropList c\u00F3 enterPredicate=false, kh\u00F4ng nh\u1EADn drop. -->\r\n <div cdkDropList cdkDropListOrientation=\"horizontal\" [cdkDropListEnterPredicate]=\"noReturnPredicate\">\r\n <div\r\n cdkDrag\r\n cdkDragLockAxis=\"x\"\r\n class=\"fb-resize\"\r\n (cdkDragStarted)=\"onAnyDragStarted()\"\r\n (cdkDragMoved)=\"changeSizeControl($event, item, row.items, i)\"\r\n (cdkDragEnded)=\"dragEndChangeSizeControl($event); onAnyDragEnded()\"\r\n [matTooltip]=\"'core.component.form-builder.flex' | translate\"\r\n aria-label=\"resize\"></div>\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </section>\r\n\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 RIGHT ATTRIBUTES \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <aside class=\"fb-attrs\">\r\n <div class=\"fb-panel-header\">\r\n <div class=\"fb-panel-header__title\">{{ 'core.component.form-builder.attribute' | translate }}</div>\r\n </div>\r\n\r\n @let sel = selectedComponent();\r\n @if (sel) {\r\n <!-- Selection header: type icon + name + key/type -->\r\n <div class=\"fb-attrs__selection\">\r\n <span class=\"fb-attrs__sel-icon\"><span class=\"msi\">{{ symbolFor(sel) }}</span></span>\r\n <div class=\"fb-attrs__sel-meta\">\r\n <div class=\"fb-attrs__sel-name\">{{ $any(sel).label || ('core.component.form-builder.untitled' | translate) }}</div>\r\n <div class=\"fb-attrs__sel-key\">\r\n @if ($any(sel).key) {\r\n {{ $any(sel).key }} \u00B7 {{ typeLabelFor(sel) }}\r\n } @else {\r\n {{ typeLabelFor(sel) }}\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"fb-attrs__body\" aria-hidden=\"true\">\r\n @if (sel.type === 'textfield') {\r\n <textfield-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></textfield-attribute>\r\n } @else if (sel.type === 'textarea') {\r\n <textarea-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></textarea-attribute>\r\n } @else if (sel.type === 'chip-string') {\r\n <chip-string-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></chip-string-attribute>\r\n } @else if (sel.type === 'chip-calendar') {\r\n <chip-calendar-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></chip-calendar-attribute>\r\n } @else if (sel.type === 'number') {\r\n <number-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></number-attribute>\r\n } @else if (sel.type === 'datetime') {\r\n <datetime-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></datetime-attribute>\r\n } @else if (sel.type === 'select') {\r\n <select-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></select-attribute>\r\n } @else if (sel.type === 'radio') {\r\n <radio-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></radio-attribute>\r\n } @else if (sel.type === 'checkbox') {\r\n <checkbox-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></checkbox-attribute>\r\n } @else if (sel.type === 'html') {\r\n <html-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></html-attribute>\r\n } @else if (sel.type === 'upload') {\r\n <upload-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></upload-attribute>\r\n } @else if (sel.type === 'table') {\r\n <table-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></table-attribute>\r\n } @else if (sel.type === 'group') {\r\n <group-attribute [group]=\"$any(sel)\"></group-attribute>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"fb-attrs__placeholder\">\r\n <span class=\"msi\">ads_click</span>\r\n <div class=\"title\">{{ 'core.component.form-builder.no-selection-title' | translate }}</div>\r\n <div class=\"hint\">{{ 'core.component.form-builder.no-selection-hint' | translate }}</div>\r\n </div>\r\n }\r\n </aside>\r\n</div>\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Reusable control template \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<ng-template #controlTemplate let-item>\r\n @if (item.type === 'textfield') {\r\n <textfield-control [component]=\"item\"></textfield-control>\r\n } @else if (item.type === 'textarea') {\r\n <textarea-control [component]=\"item\"></textarea-control>\r\n } @else if (item.type === 'chip-string') {\r\n <chip-string-control [component]=\"item\"></chip-string-control>\r\n } @else if (item.type === 'chip-calendar') {\r\n <chip-calendar-control [component]=\"item\"></chip-calendar-control>\r\n } @else if (item.type === 'number') {\r\n <number-control [component]=\"item\"></number-control>\r\n } @else if (item.type === 'datetime') {\r\n <datetime-control [component]=\"item\"></datetime-control>\r\n } @else if (item.type === 'select') {\r\n <select-control [component]=\"item\"></select-control>\r\n } @else if (item.type === 'radio') {\r\n <radio-control [component]=\"item\"></radio-control>\r\n } @else if (item.type === 'checkbox') {\r\n <checkbox-control [component]=\"item\"></checkbox-control>\r\n } @else if (item.type === 'html') {\r\n <html-control [component]=\"item\"></html-control>\r\n } @else if (item.type === 'upload') {\r\n <upload-control [component]=\"item\"></upload-control>\r\n } @else if (item.type === 'table') {\r\n <table-control [component]=\"item\"></table-control>\r\n }\r\n</ng-template>\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 JSON / variables modals \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<sd-modal title=\"JSON\" view=\"dialog\" width=\"80%\" #popupViewJSON>\r\n <sd-textarea [(model)]=\"jsonString\"></sd-textarea>\r\n <ng-container sdFooter>\r\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateJSON()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n<sd-modal [title]=\"'core.component.form-builder.config-variable' | translate\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\r\n @for (variable of clonedVariables; track variable.id) {\r\n <div class=\"d-flex align-items-center\" style=\"gap: 8px\">\r\n <sd-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"variable.key\" required></sd-input>\r\n <sd-input [form]=\"form\" [label]=\"'core.component.form-builder.display-label' | translate\" [(model)]=\"variable.label\" required></sd-input>\r\n <sd-button prefixIcon=\"delete\" (click)=\"removeVariables(variable.id)\" color=\"error\"></sd-button>\r\n </div>\r\n }\r\n <a href=\"javascript:;\" (click)=\"addVariables()\">{{ 'core.component.form-builder.add-variable' | translate }}</a>\r\n <ng-container sdFooter>\r\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateVariables()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n<configure-validation (accept)=\"onUpdateValidations($event)\"></configure-validation>\r\n", styles: [":host{--md-sys-color-primary: var(--sd-primary, #2A66F4);--md-sys-color-on-primary: #ffffff;--md-sys-color-primary-container: var(--sd-primary-light, #EAF1FF);--md-sys-color-on-primary-container: var(--sd-primary, #2A66F4);--md-sys-color-info: var(--sd-info, #2962FF);--md-sys-color-info-container: var(--sd-info-light, #E7E9FF);--md-sys-color-secondary: #625b71;--md-sys-color-secondary-container: #e8def8;--md-sys-color-on-secondary-container: #1d192b;--md-sys-color-surface: #fbfafc;--md-sys-color-surface-container-lowest: #ffffff;--md-sys-color-surface-container-low: #f6f4f8;--md-sys-color-surface-container: #f1eef3;--md-sys-color-surface-container-high: #ebe8ee;--md-sys-color-surface-container-highest: #e6e2ea;--md-sys-color-on-surface: #1c1b1f;--md-sys-color-on-surface-variant: #49454e;--md-sys-color-outline: #79747e;--md-sys-color-outline-variant: #d6d2da;--md-sys-color-error: #b3261e;--md-sys-color-error-container: #f9dedc;--md-sys-color-warning: #8a5400;--md-sys-color-warning-container: #ffddb1;--md-sys-color-success: #1f6f43;--md-sys-color-success-container: #b7f0cb;--h-row: 28px;--h-field: 32px;--h-palette: 36px;--h-header: 36px;--h-section: 28px;--h-action-btn: 24px;--gap-1: 4px;--gap-2: 8px;--gap-3: 12px;--gap-4: 16px;--gap-5: 24px;--r-xs: 4px;--r-sm: 8px;--r-md: 12px;--r-lg: 16px;--r-xl: 28px;--r-pill: 999px;--elev-1: 0 1px 2px 0 rgba(0, 0, 0, .06);--elev-2: 0 2px 6px 0 rgba(0, 0, 0, .08), 0 1px 2px 0 rgba(0, 0, 0, .04);--elev-3: 0 6px 14px 0 rgba(0, 0, 0, .1), 0 2px 4px 0 rgba(0, 0, 0, .06);display:block;width:100%;height:100%;font-family:Roboto,system-ui,sans-serif;font-size:13px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface)}:host ::ng-deep .msi{font-family:Material Symbols Rounded;font-weight:400;font-style:normal;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;font-feature-settings:\"liga\";-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"wght\" 300,\"opsz\" 24,\"GRAD\" 0,\"FILL\" 0}:host ::ng-deep .msi.filled{font-variation-settings:\"wght\" 300,\"opsz\" 24,\"GRAD\" 0,\"FILL\" 1}:host ::ng-deep .mono{font-family:Roboto Mono,ui-monospace,monospace}:host ::ng-deep .fb-icon-btn{width:28px;height:28px;border-radius:var(--r-sm);border:none;background:transparent;color:var(--md-sys-color-on-surface-variant);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .12s ease,color .12s ease}:host ::ng-deep .fb-icon-btn:hover{background:color-mix(in srgb,var(--md-sys-color-on-surface) 8%,transparent);color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-icon-btn.is-active{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}:host ::ng-deep .fb-icon-btn.danger:hover{color:var(--md-sys-color-error);background:var(--md-sys-color-error-container)}:host ::ng-deep .fb-icon-btn.warning.on{color:var(--md-sys-color-warning);background:var(--md-sys-color-warning-container)}:host ::ng-deep .fb-icon-btn .msi{font-size:18px}:host ::ng-deep .fb-field{display:flex;flex-direction:column;gap:4px}:host ::ng-deep .fb-field__label{font-size:11px;font-weight:500;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field__input{height:var(--h-row);padding:0 10px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;display:flex;align-items:center;justify-content:space-between;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-field__input.placeholder{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field__input:focus-within,:host ::ng-deep .fb-field__input.focused{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}:host ::ng-deep .fb-field__input .msi{font-size:16px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field-row{display:flex;align-items:center;gap:var(--gap-2);justify-content:space-between}:host ::ng-deep .fb-switch{display:inline-flex;width:34px;height:18px;border-radius:999px;background:var(--md-sys-color-surface-container-highest);border:1.5px solid var(--md-sys-color-outline);padding:1px;align-items:center;cursor:pointer;position:relative;flex-shrink:0}:host ::ng-deep .fb-switch .fb-switch__thumb{width:12px;height:12px;border-radius:50%;background:var(--md-sys-color-outline)}:host ::ng-deep .fb-switch.on{background:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);justify-content:flex-end}:host ::ng-deep .fb-switch.on .fb-switch__thumb{background:var(--md-sys-color-on-primary);width:14px;height:14px}:host ::ng-deep .fb-expr{display:flex;align-items:center;gap:6px;height:var(--h-row);padding:0 6px 0 0;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-expr__badge{height:100%;display:inline-flex;align-items:center;justify-content:center;padding:0 6px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-family:Roboto Mono,monospace;font-size:10px;font-weight:500;border-radius:var(--r-xs) 0 0 var(--r-xs)}:host ::ng-deep .fb-expr__code{font-family:Roboto Mono,monospace;flex:1;font-size:11px;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-expr__code .var{color:var(--md-sys-color-primary);font-weight:500}:host ::ng-deep .fb-expr__code .op{color:var(--md-sys-color-error)}:host ::ng-deep .fb-expr__code .lit{color:var(--md-sys-color-success)}:host ::ng-deep .fb-expr .empty{color:var(--md-sys-color-on-surface-variant);font-style:italic;padding-left:6px;flex:1}:host ::ng-deep details.fb-section{border-bottom:1px solid var(--md-sys-color-outline-variant);margin:0;padding:0;background:transparent}:host ::ng-deep details.fb-section>summary{list-style:none}:host ::ng-deep details.fb-section>summary::-webkit-details-marker{display:none}:host ::ng-deep .fb-section__head{height:var(--h-section);padding:0 var(--gap-4);display:flex;align-items:center;gap:var(--gap-2);cursor:pointer;font-size:12px;font-weight:500;color:var(--md-sys-color-on-surface);-webkit-user-select:none;user-select:none}:host ::ng-deep .fb-section__head .msi{font-size:16px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-section__head .fb-section__title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .fb-section__head .chev{margin-left:auto;transition:transform .16s ease}:host ::ng-deep details.fb-section[open] .fb-section__head .chev{transform:rotate(90deg)}:host ::ng-deep .fb-section__body{padding:4px var(--gap-4) var(--gap-3);display:flex;flex-direction:column;gap:var(--gap-2)}:host ::ng-deep .fb-columns-list{display:flex;flex-direction:column;gap:var(--gap-1);padding-top:var(--gap-1)}:host ::ng-deep .fb-column-row{display:flex;align-items:center;gap:var(--gap-2);height:40px;padding:6px 10px;border-radius:var(--r-sm);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;cursor:pointer;transition:background .12s ease,border-color .12s ease,box-shadow .12s ease}:host ::ng-deep .fb-column-row:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}:host ::ng-deep .fb-column-row.is-active{border-color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}:host ::ng-deep .fb-column-row .fb-column-row__type-icon{width:28px;height:28px;border-radius:var(--r-sm);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}:host ::ng-deep .fb-column-row .fb-column-row__type-icon .msi{font-size:16px}:host ::ng-deep .fb-column-row .fb-column-row__meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__label{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__req{color:var(--md-sys-color-error);margin-left:2px;font-weight:600}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__sub{font-size:11px;color:var(--md-sys-color-on-surface-variant);font-family:Roboto Mono,ui-monospace,monospace;letter-spacing:.02em}:host ::ng-deep .cdk-drag-preview.fb-drag-preview,:host ::ng-deep .fb-drag-preview{width:36px;height:36px;min-width:36px;min-height:36px;max-width:36px;max-height:36px;box-sizing:border-box;border-radius:50%;background:var(--md-sys-color-primary, #6750a4);display:inline-flex;align-items:center;justify-content:center;box-shadow:0 10px 24px #00000042,0 3px 8px #00000024;border:3px solid var(--md-sys-color-on-primary, #ffffff);cursor:grabbing;pointer-events:none;-webkit-user-select:none;user-select:none;opacity:.96;overflow:hidden;z-index:10000}:host ::ng-deep .cdk-drag-preview.fb-drag-preview:after,:host ::ng-deep .fb-drag-preview:after{content:\"\";width:8px;height:8px;border-radius:50%;background:var(--md-sys-color-on-primary, #ffffff);opacity:.9}@keyframes fb-drop-pulse{0%,to{box-shadow:0 0 0 3px color-mix(in srgb,var(--md-sys-color-info) 16%,transparent)}50%{box-shadow:0 0 0 5px color-mix(in srgb,var(--md-sys-color-info) 24%,transparent)}}:host ::ng-deep .cdk-drag-placeholder{background:transparent!important;border:none!important;border-radius:999px!important;padding:0!important;transform:none!important;transition:none!important;pointer-events:none;overflow:hidden;animation:none!important;opacity:0!important}:host ::ng-deep .cdk-drag-placeholder>*{visibility:hidden!important;pointer-events:none!important}:host ::ng-deep .fb-palette__list>.cdk-drag-placeholder{display:none!important}:host ::ng-deep .fb-row__items>.cdk-drag-placeholder,:host ::ng-deep .fb-group__body>.cdk-drag-placeholder{width:0!important;min-width:0!important;max-width:0!important;height:auto!important;min-height:0!important;align-self:stretch;flex:0 0 0!important;margin:0!important}:host ::ng-deep [cdkDropListOrientation=vertical]>.cdk-drag-placeholder{width:auto!important;height:0!important;min-height:0!important;max-height:0!important;flex:0 0 0!important;margin:0!important;align-self:stretch}:host ::ng-deep .cdk-drop-list-receiving{background:color-mix(in srgb,var(--md-sys-color-primary) 3%,transparent);transition:background .16s ease}:host ::ng-deep .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-group__body.cdk-drop-list-dragging{background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent)!important;outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 78%,transparent);outline-offset:-6px;border-radius:var(--r-sm)}:host ::ng-deep .fb-resize.cdk-drag-preview{display:none!important}:host ::ng-deep .fb-shell--dragging .fb-item:hover,:host ::ng-deep .fb-shell--dragging .fb-group:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-item:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group:hover{border-color:transparent!important;background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-row:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row:hover{outline-color:transparent!important;background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-row:hover .fb-row__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row:hover .fb-row__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-row.is-drag-target,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row.is-drag-target{outline-color:color-mix(in srgb,var(--md-sys-color-info) 44%,transparent)!important;background:color-mix(in srgb,var(--md-sys-color-info) 4%,transparent)!important}:host ::ng-deep .fb-shell--dragging .fb-row__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-actions,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-actions{opacity:0!important;pointer-events:none!important;transform:translateY(-2px)!important}:host ::ng-deep .fb-shell--dragging .fb-resize,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-resize{opacity:0!important;pointer-events:none!important}:host ::ng-deep .fb-shell--dragging .fb-row-break-btn,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row-break-btn{opacity:0!important;pointer-events:none!important}:host ::ng-deep .fb-shell--dragging .fb-palette-item:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-palette-item:hover{background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-palette-item:hover .fb-palette-item__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-palette-item:hover .fb-palette-item__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-group__body,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body{min-height:80px!important;background:color-mix(in srgb,var(--md-sys-color-primary) 5%,transparent)!important;outline:2px dashed color-mix(in srgb,var(--md-sys-color-primary) 50%,transparent)!important;outline-offset:-6px;border-radius:var(--r-sm);transition:background .16s ease,outline .16s ease,min-height .16s ease}:host ::ng-deep .fb-shell--dragging .fb-group__empty,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__empty{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 55%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary) 7%,transparent);color:var(--md-sys-color-primary)}:host ::ng-deep .fb-shell--dragging .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-shell--dragging .fb-group__body.cdk-drop-list-dragging,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body.cdk-drop-list-dragging{background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)!important;outline:2px solid var(--md-sys-color-primary)!important}:host ::ng-deep .cdk-drag-animating{transition:transform .22s cubic-bezier(.2,0,0,1)!important}:host ::ng-deep .cdk-drag-dragging{transition:none!important}:host ::ng-deep .fb-item:not(.cdk-drag-dragging){transition:flex .12s cubic-bezier(.2,0,0,1),max-width .12s cubic-bezier(.2,0,0,1),border-color .12s,background .12s}.fb-shell{width:100%;height:100%;display:flex;background:var(--md-sys-color-surface);overflow:hidden;min-height:0}.fb-panel-header{height:var(--h-header);display:flex;align-items:center;justify-content:space-between;padding:0 var(--gap-3);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);flex-shrink:0}.fb-panel-header__title{font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.fb-panel-header__actions{display:flex;align-items:center;gap:2px}.fb-palette{width:220px;flex-shrink:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-right:1px solid var(--md-sys-color-outline-variant)}.fb-palette__scroll{flex:1;overflow-y:auto;padding-bottom:var(--gap-3)}.fb-palette__search{margin:var(--gap-3);height:32px;display:flex;align-items:center;gap:var(--gap-2);padding:0 var(--gap-3);border-radius:var(--r-pill);background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:13px;flex-shrink:0}.fb-palette__search .msi{font-size:18px}.fb-palette__search input{flex:1;border:none;outline:none;background:transparent;color:var(--md-sys-color-on-surface);font-size:13px;font-family:inherit}.fb-palette__search input::placeholder{color:var(--md-sys-color-on-surface-variant)}.fb-palette__search .kbd{font-family:Roboto Mono,monospace;font-size:10px;padding:1px 6px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant)}.fb-palette__group-label{font-size:11px;font-weight:500;letter-spacing:.04em;color:var(--md-sys-color-on-surface-variant);padding:var(--gap-3) var(--gap-4) var(--gap-1);text-transform:uppercase}.fb-palette__list{display:flex;flex-direction:column;padding:0 var(--gap-2)}.fb-palette-item{height:var(--h-palette);display:flex;align-items:center;gap:var(--gap-3);padding:0 var(--gap-3);border-radius:var(--r-sm);cursor:grab;color:var(--md-sys-color-on-surface);position:relative;-webkit-user-select:none;user-select:none}.fb-palette-item:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}.fb-palette-item .fb-palette-item__icon{width:24px;height:24px;border-radius:var(--r-xs);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);flex-shrink:0}.fb-palette-item .fb-palette-item__icon .msi{font-size:16px}.fb-palette-item .fb-palette-item__name{font-size:13px;font-weight:400}.fb-palette-item .fb-palette-item__drag{margin-left:auto;color:var(--md-sys-color-outline);opacity:0;transition:opacity .12s ease}.fb-palette-item .fb-palette-item__drag .msi{font-size:16px}.fb-palette-item:hover .fb-palette-item__drag{opacity:1}.fb-canvas{flex:1 1 0;min-width:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface);overflow:hidden}.fb-canvas__header{height:var(--h-header);display:flex;align-items:center;justify-content:space-between;padding:0 var(--gap-4);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);gap:var(--gap-3);flex-shrink:0}.fb-canvas__title{display:flex;align-items:center;gap:var(--gap-2);font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.fb-canvas__title .breadcrumb-sep{color:var(--md-sys-color-outline)}.fb-canvas__actions{display:flex;align-items:center;gap:var(--gap-2)}.fb-divider{width:1px;height:18px;background:var(--md-sys-color-outline-variant)}.fb-canvas__body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding:var(--gap-4);position:relative;background:var(--md-sys-color-surface);min-width:0}.fb-canvas__body.is-preview{background:var(--md-sys-color-surface-container-low);padding:32px}.fb-mode-toggle{display:inline-flex;height:28px;border:1px solid var(--md-sys-color-outline);border-radius:var(--r-pill);overflow:hidden;flex-shrink:0}.fb-mode-toggle button{border:0;background:transparent;padding:0 var(--gap-3);font-size:12px;font-weight:500;display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface-variant);cursor:pointer}.fb-mode-toggle button .msi{font-size:16px}.fb-mode-toggle button.is-active{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.fb-row{position:relative;display:flex;gap:var(--gap-2);padding:6px var(--gap-2);border-radius:var(--r-sm);margin-bottom:6px;min-width:0;transition:outline .12s ease,background .12s ease;outline:1px dashed transparent;outline-offset:-1px}.fb-row:hover{outline-color:var(--md-sys-color-outline-variant);background:color-mix(in srgb,var(--md-sys-color-primary) 3%,transparent)}.fb-row:hover .fb-row__drag{opacity:1}.fb-row.is-drag-target{outline-color:color-mix(in srgb,var(--md-sys-color-info) 44%,transparent);background:color-mix(in srgb,var(--md-sys-color-info) 4%,transparent)}.fb-row.is-drag-target:after{content:\"\";position:absolute;left:10px;right:10px;bottom:-3px;height:4px;border-radius:999px;background:var(--md-sys-color-info);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-info) 18%,transparent);pointer-events:none;animation:fb-drop-pulse .9s ease-in-out infinite;z-index:3}.fb-row__drag{position:absolute;left:-22px;top:50%;transform:translateY(-50%);width:18px;height:22px;border-radius:var(--r-xs);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);opacity:0;cursor:grab;z-index:2}.fb-row__drag .msi{font-size:14px}.fb-row-break-btn{position:absolute;right:-28px;top:50%;transform:translateY(-50%);width:22px;height:22px;border-radius:var(--r-pill);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);cursor:pointer;opacity:0;z-index:2;transition:opacity .12s ease,background .12s ease,color .12s ease}.fb-row-break-btn .msi{font-size:14px}.fb-row-break-btn:hover{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);border-color:transparent}.fb-row:hover .fb-row-break-btn{opacity:1}.fb-item{position:relative;border:1.5px dashed transparent;border-radius:var(--r-md);padding:var(--gap-2) var(--gap-3);min-height:56px;min-width:0;transition:border-color .12s ease,background .12s ease;background:transparent;cursor:grab;display:flex;flex-direction:column;gap:6px}.fb-item:hover{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,transparent)}.fb-item.is-selected{border:1.5px solid var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent)}.fb-item.is-hidden{opacity:.45}.fb-item.is-readonly:after{content:\"\";position:absolute;inset:0;border-radius:var(--r-md);background:repeating-linear-gradient(135deg,transparent 0 6px,color-mix(in srgb,var(--md-sys-color-on-surface) 4%,transparent) 6px 7px);pointer-events:none}.fb-item.column-2{flex:0 0 calc(16.6666666667% - var(--gap-2));max-width:calc(16.6666666667% - var(--gap-2))}.fb-item.column-3{flex:0 0 calc(25% - var(--gap-2));max-width:calc(25% - var(--gap-2))}.fb-item.column-4{flex:0 0 calc(33.3333333333% - var(--gap-2));max-width:calc(33.3333333333% - var(--gap-2))}.fb-item.column-5{flex:0 0 calc(41.6666666667% - var(--gap-2));max-width:calc(41.6666666667% - var(--gap-2))}.fb-item.column-6{flex:0 0 calc(50% - var(--gap-2));max-width:calc(50% - var(--gap-2))}.fb-item.column-7{flex:0 0 calc(58.3333333333% - var(--gap-2));max-width:calc(58.3333333333% - var(--gap-2))}.fb-item.column-8{flex:0 0 calc(66.6666666667% - var(--gap-2));max-width:calc(66.6666666667% - var(--gap-2))}.fb-item.column-9{flex:0 0 calc(75% - var(--gap-2));max-width:calc(75% - var(--gap-2))}.fb-item.column-10{flex:0 0 calc(83.3333333333% - var(--gap-2));max-width:calc(83.3333333333% - var(--gap-2))}.fb-item.column-11{flex:0 0 calc(91.6666666667% - var(--gap-2));max-width:calc(91.6666666667% - var(--gap-2))}.fb-item.column-12{flex:1 1 100%;max-width:100%}.fb-actions{position:absolute;top:-14px;right:8px;display:flex;align-items:center;gap:2px;padding:2px;border-radius:var(--r-pill);background:var(--md-sys-color-surface-container-lowest);box-shadow:var(--elev-2);border:1px solid var(--md-sys-color-outline-variant);z-index:4;opacity:0;transform:translateY(-2px);pointer-events:none;transition:opacity .12s ease,transform .12s ease}.fb-actions .fb-icon-btn{width:24px;height:24px}.fb-actions .fb-icon-btn .msi{font-size:16px}.fb-item:hover .fb-actions,.fb-item.is-selected .fb-actions{opacity:1;transform:translateY(0);pointer-events:auto}.fb-group>.fb-actions{top:6px;right:8px}.fb-group:hover>.fb-actions,.fb-group.is-selected>.fb-actions{opacity:1;transform:translateY(0);pointer-events:auto}.fb-status-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;height:18px;border-radius:var(--r-pill);font-size:10px;font-weight:500;letter-spacing:.02em;position:absolute;top:-9px;left:12px;z-index:3;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant)}.fb-status-chip .msi{font-size:12px}.fb-status-chip.readonly{color:var(--md-sys-color-warning);background:var(--md-sys-color-warning-container);border-color:transparent}.fb-status-chip.hidden{color:var(--md-sys-color-on-surface-variant)}.fb-status-chip.conditional{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);border-color:transparent}.fb-resize{position:absolute;top:8px;bottom:8px;right:-5px;width:6px;border-radius:999px;background:var(--md-sys-color-primary);display:flex;align-items:center;justify-content:center;cursor:col-resize;opacity:0;transition:opacity .12s ease;z-index:3}.fb-resize:before{content:\"\";width:2px;height:18px;background:var(--md-sys-color-on-primary);border-radius:999px}.fb-item:hover .fb-resize{opacity:1}.fb-item.is-break{min-height:28px;padding:8px var(--gap-3);justify-content:center}.fb-break-line{display:flex;align-items:center;gap:var(--gap-2);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:500;letter-spacing:.06em;text-transform:uppercase}.fb-break-line:before,.fb-break-line:after{content:\"\";flex:1;height:1px;background:var(--md-sys-color-outline-variant)}.fb-break-line .msi{display:none}.fb-break-line .fb-break-label{color:var(--md-sys-color-on-surface-variant)}.fb-drop-hint{height:36px;border-radius:var(--r-sm);border:1.5px dashed var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent);color:var(--md-sys-color-primary);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;gap:6px;margin:4px 0}.fb-drop-hint .msi{font-size:16px}.fb-group{background:var(--md-sys-color-surface-container-lowest);border-radius:var(--r-lg);border:1.5px dashed transparent;transition:border-color .12s ease,background .12s ease;position:relative;display:flex;flex-direction:column;overflow:visible;cursor:default}.fb-group:hover{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,transparent)}.fb-group.is-selected{border:1.5px solid var(--md-sys-color-primary)}.fb-group.is-hidden{opacity:.55}.fb-group__header{display:flex;align-items:center;gap:var(--gap-2);padding:8px 12px;border-top-left-radius:12px;border-top-right-radius:12px;cursor:grab}.fb-group__header:active{cursor:grabbing}.fb-group__header .fb-group__icon .msi{font-size:18px}.fb-group__header .fb-group__label{font-size:13px;font-weight:500}.fb-group__header .fb-group__count{margin-left:auto;font-size:10px;opacity:.75}.fb-group__conditional-chip{display:inline-flex;align-items:center;gap:4px;font-family:Roboto Mono,monospace;font-size:10px;padding:2px 8px;border-radius:var(--r-pill);background:color-mix(in srgb,currentColor 12%,transparent)}.fb-group__body{padding:12px;display:flex;flex-wrap:wrap;gap:var(--gap-2);min-height:60px;position:relative}.fb-group__empty{display:flex;align-items:center;justify-content:center;height:56px;border-radius:var(--r-sm);border:1.5px dashed var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-style:italic}.fb-empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--gap-3);color:var(--md-sys-color-on-surface-variant);text-align:center;padding:24px;pointer-events:none}.fb-empty__art{width:96px;height:96px;border-radius:var(--r-xl);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center}.fb-empty__art .msi{font-size:44px}.fb-empty__title{font-size:16px;font-weight:500;color:var(--md-sys-color-on-surface)}.fb-empty__hint{font-size:13px;max-width:320px;line-height:1.5}.fb-empty__kbd{display:inline-flex;align-items:center;gap:6px;font-family:Roboto Mono,monospace;font-size:11px;padding:4px 8px;border-radius:var(--r-xs);border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant)}.fb-empty__kbd .msi{font-size:12px}.fb-attrs{width:320px;flex-shrink:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-left:1px solid var(--md-sys-color-outline-variant)}.fb-attrs__selection{padding:var(--gap-3) var(--gap-4);display:flex;align-items:center;gap:var(--gap-2);border-bottom:1px solid var(--md-sys-color-outline-variant)}.fb-attrs__sel-icon{width:28px;height:28px;border-radius:var(--r-sm);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.fb-attrs__sel-icon .msi{font-size:18px}.fb-attrs__sel-meta{display:flex;flex-direction:column;min-width:0}.fb-attrs__sel-name{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-attrs__sel-key{font-family:Roboto Mono,monospace;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.fb-attrs__body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;min-width:0}.fb-attrs__placeholder{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--gap-2);padding:32px;color:var(--md-sys-color-on-surface-variant);text-align:center}.fb-attrs__placeholder .msi{font-size:32px;color:var(--md-sys-color-outline)}.fb-attrs__placeholder .title{font-size:13px;font-weight:500;color:var(--md-sys-color-on-surface)}.fb-attrs__placeholder .hint{font-size:12px;max-width:220px;line-height:1.5}.fb-preview-card{max-width:760px;margin:0 auto;background:var(--md-sys-color-surface-container-lowest);border-radius:var(--r-lg);padding:32px;box-shadow:var(--elev-1)}.fb-preview-card__chip{display:inline-flex;align-items:center;gap:6px;padding:2px 10px;height:22px;border-radius:var(--r-pill);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;margin-bottom:var(--gap-3)}.fb-preview-card__title{font-size:20px;font-weight:500;margin:0 0 var(--gap-4);color:var(--md-sys-color-on-surface)}.fb-preview-card__footer{display:flex;justify-content:flex-end;gap:var(--gap-2);margin-top:var(--gap-4);padding-top:var(--gap-4);border-top:1px solid var(--md-sys-color-outline-variant)}.fb-icon-picker{display:grid;grid-template-columns:repeat(6,1fr);gap:4px;margin-top:4px}.fb-icon-picker .fb-icon-picker__btn{height:28px;border-radius:var(--r-xs);border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.fb-icon-picker .fb-icon-picker__btn .msi{font-size:16px}.fb-icon-picker .fb-icon-picker__btn.is-active{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary)}.fb-icon-picker .fb-icon-picker__btn:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}.fb-color-swatches{display:flex;gap:var(--gap-2);margin-top:4px}.fb-color-swatches .fb-color-swatch{width:24px;height:24px;border-radius:50%;cursor:pointer;border:2px solid transparent}.fb-color-swatches .fb-color-swatch.is-active{border-color:var(--md-sys-color-on-surface)}.fb-color-swatches .fb-color-swatch.primary{background:var(--md-sys-color-primary)}.fb-color-swatches .fb-color-swatch.secondary{background:var(--md-sys-color-secondary)}.fb-color-swatches .fb-color-swatch.success{background:var(--md-sys-color-success)}.fb-color-swatches .fb-color-swatch.warning{background:var(--md-sys-color-warning)}.fb-color-swatches .fb-color-swatch.error{background:var(--md-sys-color-error)}.fb-children-list{display:flex;flex-direction:column;gap:4px}.fb-child-row{display:flex;align-items:center;gap:var(--gap-2);height:30px;padding:0 8px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px}.fb-child-row .fb-child-row__icon{width:22px;height:22px;border-radius:var(--r-xs);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.fb-child-row .fb-child-row__icon .msi{font-size:14px}.fb-child-row .fb-child-row__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fb-child-row .fb-child-row__key{font-family:Roboto Mono,monospace;font-size:10px;color:var(--md-sys-color-on-surface-variant)}.fb-child-row:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent)}.fb-add-link{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--md-sys-color-primary);cursor:pointer;padding:4px 0;text-decoration:none}.fb-add-link .msi{font-size:14px}.fb-add-link:hover{text-decoration:underline}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i3.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i3.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i3.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i3.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "directive", type: i3.CdkDragPreview, selector: "ng-template[cdkDragPreview]", inputs: ["data", "matchSize"] }, { kind: "component", type:
6141
6474
  // Controls
6142
- TextFieldControl, selector: "textfield-control", inputs: ["component"] }, { kind: "component", type: TextfieldAttribute, selector: "textfield-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: TextareaControl, selector: "textarea-control", inputs: ["component"] }, { kind: "component", type: TextareaAttribute, selector: "textarea-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: ChipStringControl, selector: "chip-string-control", inputs: ["component"] }, { kind: "component", type: ChipStringAttribute, selector: "chip-string-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: ChipCalendarControl, selector: "chip-calendar-control", inputs: ["component"] }, { kind: "component", type: ChipCalendarAttribute, selector: "chip-calendar-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: NumberControl, selector: "number-control", inputs: ["component"] }, { kind: "component", type: NumberAttribute, selector: "number-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: SelectControl, selector: "select-control", inputs: ["component"] }, { kind: "component", type: SelectAttribute, selector: "select-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: DatetimeControl, selector: "datetime-control", inputs: ["component"] }, { kind: "component", type: DatetimeAttribute, selector: "datetime-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: RadioControl, selector: "radio-control", inputs: ["component"] }, { kind: "component", type: RadioAttribute, selector: "radio-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: CheckboxControl, selector: "checkbox-control", inputs: ["component"] }, { kind: "component", type: CheckboxAttribute, selector: "checkbox-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: HtmlControl, selector: "html-control", inputs: ["component"] }, { kind: "component", type: HtmlAttribute, selector: "html-attribute", inputs: ["components", "variables", "component"], outputs: ["attributeChanges"] }, { kind: "component", type: UploadControl, selector: "upload-control", inputs: ["component"] }, { kind: "component", type: UploadAttribute, selector: "upload-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: TableControl, selector: "table-control", inputs: ["component"] }, { kind: "component", type: TableAttribute, selector: "table-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdTextarea, selector: "sd-textarea", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "rows", "hideInlineError", "required", "disabled", "viewed", "autoHeight", "maxlength", "pattern", "validator", "inlineError", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdFormRender, selector: "sd-form-render", inputs: ["form", "configuration", "defaultEntity", "entity", "properties", "viewed"] }, { kind: "component", type: ConfigureValidationComponent, selector: "configure-validation", outputs: ["accept"] }] });
6475
+ TextFieldControl, selector: "textfield-control", inputs: ["component"] }, { kind: "component", type: TextfieldAttribute, selector: "textfield-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: TextareaControl, selector: "textarea-control", inputs: ["component"] }, { kind: "component", type: TextareaAttribute, selector: "textarea-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: ChipStringControl, selector: "chip-string-control", inputs: ["component"] }, { kind: "component", type: ChipStringAttribute, selector: "chip-string-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: ChipCalendarControl, selector: "chip-calendar-control", inputs: ["component"] }, { kind: "component", type: ChipCalendarAttribute, selector: "chip-calendar-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: NumberControl, selector: "number-control", inputs: ["component"] }, { kind: "component", type: NumberAttribute, selector: "number-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: SelectControl, selector: "select-control", inputs: ["component"] }, { kind: "component", type: SelectAttribute, selector: "select-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: DatetimeControl, selector: "datetime-control", inputs: ["component"] }, { kind: "component", type: DatetimeAttribute, selector: "datetime-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: RadioControl, selector: "radio-control", inputs: ["component"] }, { kind: "component", type: RadioAttribute, selector: "radio-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: CheckboxControl, selector: "checkbox-control", inputs: ["component"] }, { kind: "component", type: CheckboxAttribute, selector: "checkbox-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: HtmlControl, selector: "html-control", inputs: ["component"] }, { kind: "component", type: HtmlAttribute, selector: "html-attribute", inputs: ["components", "variables", "component"], outputs: ["attributeChanges"] }, { kind: "component", type: UploadControl, selector: "upload-control", inputs: ["component"] }, { kind: "component", type: UploadAttribute, selector: "upload-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: TableControl, selector: "table-control", inputs: ["component"] }, { kind: "component", type: TableAttribute, selector: "table-attribute", inputs: ["components", "variables", "component"] }, { kind: "component", type: GroupAttribute, selector: "group-attribute", inputs: ["group"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdTextarea, selector: "sd-textarea", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "rows", "hideInlineError", "required", "disabled", "viewed", "autoHeight", "maxlength", "pattern", "validator", "inlineError", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdFormRender, selector: "sd-form-render", inputs: ["form", "configuration", "defaultEntity", "entity", "properties", "viewed"] }, { kind: "component", type: ConfigureValidationComponent, selector: "configure-validation", outputs: ["accept"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
6143
6476
  }
6144
6477
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdFormBuilder, decorators: [{
6145
6478
  type: Component,
@@ -6148,8 +6481,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
6148
6481
  MatIconModule,
6149
6482
  MatTooltipModule,
6150
6483
  DragDropModule,
6151
- // Core Pipes
6152
- SdSafeHtmlPipe,
6153
6484
  // Controls
6154
6485
  TextFieldControl,
6155
6486
  TextfieldAttribute,
@@ -6175,29 +6506,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
6175
6506
  UploadAttribute,
6176
6507
  TableControl,
6177
6508
  TableAttribute,
6509
+ GroupAttribute,
6178
6510
  SdModal,
6179
6511
  SdInput$1,
6180
6512
  SdTextarea,
6181
6513
  SdButton,
6182
6514
  SdFormRender,
6183
- ConfigureValidationComponent,
6184
- ], template: "<div class=\"d-flex form-editor\">\r\n <div class=\"d-flex flex-column form-menu\">\r\n <div class=\"c-header\">Components</div>\r\n <div class=\"component-container\" style=\"flex: 1\">\r\n <div class=\"form-editor-group\" cdkDropList [cdkDropListData]=\"formBuilderComponents\" [cdkDropListEnterPredicate]=\"noReturnPredicate\">\r\n @for (formBuilderComponent of formBuilderComponents; track formBuilderComponent.type) {\r\n <div cdkDrag class=\"form-item\" (click)=\"addComponent(formBuilderComponent)\" aria-hidden=\"true\">\r\n <div class=\"c-form-item\">\r\n <span [innerHtml]=\"formBuilderComponent.icon | sdSafeHtml\"></span>\r\n <div class=\"title\">\r\n {{ formBuilderComponent.name }}\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"d-flex flex-column form-content\">\r\n <div class=\"c-header d-flex align-items-center justify-content-between\">\r\n <div>B\u1ED1 c\u1EE5c</div>\r\n <div class=\"d-flex align-items-center\" style=\"gap: 8px\">\r\n <mat-icon matTooltip=\"Xem JSON\" fontIcon=\"code\" (click)=\"viewJSON()\"></mat-icon>\r\n <mat-icon matTooltip=\"C\u1EA5u h\u00ECnh bi\u1EBFn\" fontIcon=\"scatter_plot\" (click)=\"configureVariables()\"></mat-icon>\r\n <mat-icon matTooltip=\"C\u1EA5u h\u00ECnh x\u00E1c th\u1EF1c c\u1EA3nh b\u00E1o/l\u1ED7i\" fontIcon=\"error\" (click)=\"openConfigureValidation()\"></mat-icon>\r\n <mat-icon\r\n [matTooltip]=\"isPreview ? 'Tr\u1EDF v\u1EC1 thi\u1EBFt k\u1EBF' : 'Xem th\u1EED'\"\r\n [fontIcon]=\"isPreview ? 'stop_circle' : 'play_circle'\"\r\n (click)=\"isPreview = !isPreview\"></mat-icon>\r\n </div>\r\n </div>\r\n <div class=\"p-12 components\" style=\"flex: 1; overflow-y: auto\" id=\"frmComponent\">\r\n @if (isPreview) {\r\n <sd-form-render [configuration]=\"{ components: this.components, validations: this.validations }\"></sd-form-render>\r\n <sd-button title=\"Validate\" (click)=\"onValidate()\"></sd-button>\r\n } @else {\r\n <div\r\n cdkDropList\r\n cdkDropListOrientation=\"vertical\"\r\n [cdkDropListData]=\"dragDropRows\"\r\n class=\"listY\"\r\n (cdkDropListDropped)=\"drop($event)\"\r\n (click)=\"clickFormContentEmpty()\"\r\n aria-hidden=\"true\">\r\n @for (row of dragDropRows; track row.rowIndex) {\r\n <div\r\n cdkDrag\r\n (mouseover)=\"onMouseover($event, row)\"\r\n (focus)=\"onFocus($event)\"\r\n id=\"row_{{ row.rowIndex }}\"\r\n class=\"row-item\"\r\n aria-hidden=\"true\">\r\n <div class=\"btn-drag-row-item\"><mat-icon matTooltip=\"K\u00E9o l\u00EAn / xu\u1ED1ng\">drag_indicator</mat-icon></div>\r\n <div\r\n class=\"c-row-item\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n [cdkDropListData]=\"row.items\"\r\n (cdkDropListDropped)=\"drop($event)\">\r\n @for (item of row.items; track item.id; let i = $index) {\r\n <div\r\n cdkDrag\r\n [id]=\"item.id\"\r\n class=\"component-item column-{{ item.layout?.columns || 12 }}\"\r\n [class.active]=\"item.id === selectedComponent?.id\"\r\n (click)=\"selectComponent(item)\"\r\n (clickOutside)=\"onClickedOutside($event)\"\r\n (cdkDragStarted)=\"dragStartComponentItem($event)\"\r\n (cdkDragEnded)=\"dragEndComponentItem($event)\"\r\n aria-hidden=\"true\">\r\n <div class=\"c-component-item\" [class.c-hidden]=\"item.properties?.hidden\">\r\n <div class=\"c-actions\">\r\n @if (item.type !== 'group') {\r\n <mat-icon\r\n [matTooltip]=\"item.properties?.viewed ? 'B\u1ECF ch\u1EC9 xem' : 'Ch\u1EC9 xem'\"\r\n (click)=\"onChangeViewed(item)\"\r\n fontSet=\"material-icons-outlined\"\r\n style=\"font-size: 16px; cursor: pointer\"\r\n [class.text-warning]=\"item.properties?.viewed\">\r\n edit_off\r\n </mat-icon>\r\n }\r\n <mat-icon\r\n matTooltip=\"Nh\u00E2n b\u1EA3n\"\r\n (click)=\"onDuplicate(item)\"\r\n fontSet=\"material-icons-outlined\"\r\n style=\"font-size: 16px; cursor: pointer\">\r\n content_copy\r\n </mat-icon>\r\n <mat-icon\r\n [matTooltip]=\"item.properties?.hidden ? 'Hi\u1EC7n' : '\u1EA8n'\"\r\n (click)=\"onChangeHidden(item)\"\r\n fontSet=\"material-icons-outlined\"\r\n style=\"font-size: 16px; cursor: pointer\"\r\n [class.text-warning]=\"item.properties?.hidden\">\r\n visibility_off\r\n </mat-icon>\r\n <mat-icon\r\n matTooltip=\"X\u00F3a\"\r\n (click)=\"removeComponent(item.id)\"\r\n fontSet=\"material-icons-outlined\"\r\n style=\"font-size: 16px; cursor: pointer\"\r\n class=\"text-error\">\r\n delete\r\n </mat-icon>\r\n </div>\r\n @if (item.type === 'textfield') {\r\n <textfield-control [component]=\"item\"></textfield-control>\r\n } @else if (item.type === 'textarea') {\r\n <textarea-control [component]=\"item\"></textarea-control>\r\n } @else if (item.type === 'chip-string') {\r\n <chip-string-control [component]=\"item\"></chip-string-control>\r\n } @else if (item.type === 'chip-calendar') {\r\n <chip-calendar-control [component]=\"item\"></chip-calendar-control>\r\n } @else if (item.type === 'number') {\r\n <number-control [component]=\"item\"></number-control>\r\n } @else if (item.type === 'datetime') {\r\n <datetime-control [component]=\"item\"></datetime-control>\r\n } @else if (item.type === 'select') {\r\n <select-control [component]=\"item\"></select-control>\r\n } @else if (item.type === 'radio') {\r\n <radio-control [component]=\"item\"></radio-control>\r\n } @else if (item.type === 'checkbox') {\r\n <checkbox-control [component]=\"item\"></checkbox-control>\r\n } @else if (item.type === 'html') {\r\n <html-control [component]=\"item\" #html></html-control>\r\n } @else if (item.type === 'upload') {\r\n <upload-control [component]=\"item\"></upload-control>\r\n } @else if (item.type === 'table') {\r\n <table-control [component]=\"item\"></table-control>\r\n }\r\n <div class=\"c-item-backdrop\"></div>\r\n </div>\r\n <div cdkDropList cdkDropListOrientation=\"horizontal\">\r\n <div\r\n cdkDrag\r\n (cdkDragMoved)=\"changeSizeControl($event, item, row.items, i)\"\r\n (cdkDragEnded)=\"dragEndChangeSizeControl($event)\"\r\n class=\"c-bar-resize-right\"\r\n matTooltip=\"Co d\u00E3n\"></div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n <div class=\"d-flex flex-column form-attributes\">\r\n <div class=\"c-header\">Thu\u1ED9c t\u00EDnh</div>\r\n @if (selectedComponent) {\r\n <div class=\"attributes\" style=\"flex: 1\" aria-hidden=\"true\">\r\n @if (selectedComponent.type === 'textfield') {\r\n <textfield-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></textfield-attribute>\r\n } @else if (selectedComponent.type === 'textarea') {\r\n <textarea-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></textarea-attribute>\r\n } @else if (selectedComponent.type === 'chip-string') {\r\n <chip-string-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></chip-string-attribute>\r\n } @else if (selectedComponent.type === 'chip-calendar') {\r\n <chip-calendar-attribute\r\n [components]=\"components\"\r\n [variables]=\"variables\"\r\n [component]=\"selectedComponent\"></chip-calendar-attribute>\r\n } @else if (selectedComponent.type === 'number') {\r\n <number-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></number-attribute>\r\n } @else if (selectedComponent.type === 'datetime') {\r\n <datetime-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></datetime-attribute>\r\n } @else if (selectedComponent.type === 'select') {\r\n <select-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></select-attribute>\r\n } @else if (selectedComponent.type === 'radio') {\r\n <radio-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></radio-attribute>\r\n } @else if (selectedComponent.type === 'checkbox') {\r\n <checkbox-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></checkbox-attribute>\r\n } @else if (selectedComponent.type === 'html') {\r\n <html-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></html-attribute>\r\n } @else if (selectedComponent.type === 'upload') {\r\n <upload-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></upload-attribute>\r\n } @else if (selectedComponent.type === 'table') {\r\n <table-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"selectedComponent\"></table-attribute>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n<sd-modal title=\"JSON\" view=\"dialog\" width=\"80%\" #popupViewJSON>\r\n <sd-textarea [(model)]=\"jsonString\"></sd-textarea>\r\n <ng-container sdFooter>\r\n <sd-button type=\"fill\" title=\"L\u01B0u\" (click)=\"updateJSON()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n<sd-modal title=\"C\u1EA5u h\u00ECnh bi\u1EBFn\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\r\n @for (variable of clonedVariables; track variable.id) {\r\n <div class=\"d-flex align-items-center\" style=\"gap: 8px\">\r\n <sd-input [form]=\"form\" label=\"Tr\u01B0\u1EDDng d\u1EEF li\u1EC7u\" [(model)]=\"variable.key\" required></sd-input>\r\n <sd-input [form]=\"form\" label=\"Nh\u00E3n hi\u1EC3n th\u1ECB\" [(model)]=\"variable.label\" required></sd-input>\r\n <sd-button prefixIcon=\"delete\" (click)=\"removeVariables(variable.id)\" color=\"error\"></sd-button>\r\n </div>\r\n }\r\n <a href=\"javascript:;\" (click)=\"addVariables()\">Th\u00EAm bi\u1EBFn</a>\r\n <ng-container sdFooter>\r\n <sd-button type=\"fill\" title=\"L\u01B0u\" (click)=\"updateVariables()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n<configure-validation (accept)=\"onUpdateValidations($event)\"></configure-validation>\r\n", styles: [":host::ng-deep .svg{width:40px}:host::ng-deep .mat-form-field.sd-sm.mat-form-field-appearance-outline .mat-form-field-infix input.mat-input-element{margin-top:7px!important}::ng-deep .component-item.cdk-drag-preview .c-component-item{display:none}::ng-deep .component-item.cdk-drag-dragging,::ng-deep .row-item.cdk-drag-dragging{box-shadow:0 4px 8px #0003;border:2px #0e7cfa dashed}::ng-deep .row-item.cdk-drag-preview .c-row-item,::ng-deep .row-item.cdk-drag-preview .btn-drag-row-item{display:none}::ng-deep .form-item.cdk-drag-preview{text-align:center}::ng-deep .form-item.cdk-drag-preview .c-form-item{text-align:center}::ng-deep .form-item.cdk-drag-preview .c-form-item .svg{width:40px}.form-editor{width:100%;height:100%}.form-editor .material-icons{color:#5f6368!important}.form-editor .material-icons:hover{color:#2626b4!important;cursor:pointer!important}.form-editor .c-header{font-weight:500;padding:5px 10px;background-color:#ebebeb;border-bottom:1px solid #d3d3d3;text-transform:uppercase}.form-editor .c-header:last-child{border-right:0!important}.form-editor .c-header a{font-size:12px}.form-editor .form-menu{width:120px}.form-editor .form-menu .component-container{overflow-y:hidden;background:#f6f8fc}.form-editor .form-menu .component-container:hover{overflow-y:auto!important}.form-editor .form-menu .form-editor-group{padding:5px 10px;display:flex;align-items:center;flex-wrap:wrap}.form-editor .form-menu .form-editor-group .form-item{height:68px;display:flex;align-items:center;justify-content:center;font-size:11px;-webkit-user-select:none;user-select:none;color:#333;background:#fff;border:1px solid transparent;width:100px;margin:6px}.form-editor .form-menu .form-editor-group .form-item:hover{background-color:#e7e7e7;border-color:#878b8f;cursor:pointer}.form-editor .form-menu .form-editor-group .form-item .c-form-item{text-align:center}.form-editor .form-menu .form-editor-group .form-item .c-form-item>div.title,.form-editor .form-menu .form-editor-group .form-item .c-form-item>span{text-align:center;white-space:nowrap;font-weight:500}.form-editor .form-content{flex:1;border-right:1px solid #d3d3d3;border-left:1px solid #d3d3d3}.form-editor .form-content .components{background:#fff}.form-editor .form-content .components .row-item{position:relative;transition:transform .2s ease,box-shadow .2s ease;cursor:grab}.form-editor .form-content .components .row-item:hover{outline:1px dashed #bbb;border-radius:8px}.form-editor .form-content .components .row-item:hover .btn-drag-row-item{display:grid}.form-editor .form-content .components .row-item .btn-drag-row-item{display:none;position:absolute;top:0;left:-12px;height:100%;z-index:2;place-items:center;cursor:grab}.form-editor .form-content .components .row-item .btn-drag-row-item mat-icon{font-size:24px;height:24px;width:24px;box-shadow:0 1px 2px #0000001a;background:#fff}.form-editor .form-content .components .component-item{padding:4px 8px;border:2px dashed transparent;position:relative;min-height:28px;cursor:grab;transition:transform .2s ease,box-shadow .2s ease;display:inline-block;margin:4px;border-radius:8px;vertical-align:bottom}.form-editor .form-content .components .component-item:active{cursor:grabbing;box-shadow:0 4px 8px #0003}.form-editor .form-content .components .component-item:hover{border:2px #0e7cfa dashed}.form-editor .form-content .components .component-item:hover .c-actions{display:flex;flex-direction:row;gap:4px}.form-editor .form-content .components .component-item:hover .c-bar-resize-right{display:block;cursor:w-resize}.form-editor .form-content .components .component-item:hover .c-bar-resize-right.disabled{display:none}.form-editor .form-content .components .component-item .c-component-item{overflow:hidden}.form-editor .form-content .components .component-item .c-actions{display:none;position:absolute;right:4px;z-index:2}.form-editor .form-content .components .component-item .c-bar-resize-right{display:none;width:8px;height:80%;position:absolute;top:10%;right:-5px;outline:2px #0e7cfa solid;border-radius:4px;color:#fff;background:#fff;z-index:2}.form-editor .form-content .components .component-item .c-item-backdrop{position:absolute;width:100%;height:100%;top:0;left:0;z-index:1}.form-editor .form-content .components .active{border:2px #0e7cfa solid;outline:1px #0e7cfa solid}.form-editor .form-content .components .column-2{width:calc(16.6666666667% - 8px)}.form-editor .form-content .components .column-3{width:calc(25% - 8px)}.form-editor .form-content .components .column-4{width:calc(33.3333333333% - 8px)}.form-editor .form-content .components .column-5{width:calc(41.6666666667% - 8px)}.form-editor .form-content .components .column-6{width:calc(50% - 8px)}.form-editor .form-content .components .column-7{width:calc(58.3333333333% - 8px)}.form-editor .form-content .components .column-8{width:calc(66.6666666667% - 8px)}.form-editor .form-content .components .column-9{width:calc(75% - 8px)}.form-editor .form-content .components .column-10{width:calc(83.3333333333% - 8px)}.form-editor .form-content .components .column-11{width:calc(91.6666666667% - 8px)}.form-editor .form-content .components .column-12{width:calc(100% - 8px)}.form-editor .form-attributes{width:300px}.form-editor .form-attributes .attributes{overflow-y:auto!important;padding:0 10px;background:#f6f8fc}.form-editor .form-attributes .attributes .group-attribute .title-group{font-weight:500;padding:5px 0;position:relative;cursor:pointer;margin-top:8px}.form-editor .form-attributes .attributes .group-attribute .title-group span{vertical-align:middle;display:inline-block}.form-editor .form-attributes .attributes .group-attribute .title-group mat-icon{vertical-align:middle;position:absolute;right:0}.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute{display:grid;margin-bottom:10px}.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute label{font-size:12px;font-weight:400;margin:0}.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute input,.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute select,.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute textarea{border:1px solid #d3d3d3;height:30px}.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute .select-options{padding:5px 0;border-bottom:1px solid #d3d3d3}.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute .select-options input{width:100%;margin-bottom:5px}.form-editor .form-attributes .attributes .group-attribute .item-group .item-attribute .select-options .material-icons{padding-top:22px}.preview-container{margin:0 -24px;position:relative}.preview-container .header-preview{border-bottom:1px solid #eee;padding:10px;font-size:14px;font-weight:500;position:sticky;top:0;background-color:#fff;z-index:9999}.preview-container .header-preview .material-icons:hover{color:#5f6368;cursor:pointer}.preview-container .content{padding:10px}.c-hidden{opacity:.5}\n"] }]
6185
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1$6.SdNotifyService }, { type: i1$6.SdConfirmService }, { type: BuilderService }], propDecorators: { popupViewJSON: [{
6186
- type: ViewChild,
6187
- args: ['popupViewJSON']
6188
- }], popupConfigureVariables: [{
6189
- type: ViewChild,
6190
- args: ['popupConfigureVariables']
6191
- }], configureValidation: [{
6192
- type: ViewChild,
6193
- args: [ConfigureValidationComponent]
6194
- }], formRender: [{
6195
- type: ViewChild,
6196
- args: [SdFormRender]
6197
- }], _formGeneric: [{
6198
- type: Input,
6199
- args: ['formGeneric']
6200
- }] } });
6515
+ ConfigureValidationComponent, TranslatePipe
6516
+ ], template: "<!-- cdkDropListGroup: auto-connect t\u1EA5t c\u1EA3 cdkDropList trong palette, canvas rows, group bodies.\r\n [class.fb-shell--dragging]: JS-driven flag \u0111\u1EC3 \u1EA9n hover/actions/resize to\u00E0n di\u1EC7n\r\n trong l\u00FAc drag (CSS :has() kh\u00F4ng b\u1EAFt 100% tr\u01B0\u1EDDng h\u1EE3p v\u1EDBi CDK preview clone). -->\r\n<div class=\"fb-shell\" cdkDropListGroup [class.fb-shell--dragging]=\"isAnyDragging()\">\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 LEFT PALETTE \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <aside class=\"fb-palette\">\r\n <div class=\"fb-panel-header\">\r\n <div class=\"fb-panel-header__title\">{{ 'core.component.form-builder.components' | translate }}</div>\r\n </div>\r\n\r\n <!-- Search pill -->\r\n <div class=\"fb-palette__search\">\r\n <span class=\"msi\" aria-hidden=\"true\">search</span>\r\n <input\r\n type=\"text\"\r\n [placeholder]=\"'core.component.form-builder.search-components' | translate\"\r\n [value]=\"paletteSearch()\"\r\n (input)=\"paletteSearch.set($any($event.target).value)\" />\r\n <span class=\"kbd\">\u2318K</span>\r\n </div>\r\n\r\n <div class=\"fb-palette__scroll\">\r\n @for (group of paletteGroups(); track group.key) {\r\n <div class=\"fb-palette__group-label\">{{ group.label }}</div>\r\n <div\r\n class=\"fb-palette__list\"\r\n cdkDropList\r\n [cdkDropListData]=\"group.items\"\r\n [cdkDropListEnterPredicate]=\"noReturnPredicate\">\r\n @for (formBuilderComponent of group.items; track formBuilderComponent.type) {\r\n <div\r\n cdkDrag\r\n class=\"fb-palette-item\"\r\n [matTooltip]=\"formBuilderComponent.name\"\r\n matTooltipPosition=\"right\"\n (click)=\"addComponent(formBuilderComponent)\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\"\n aria-hidden=\"true\">\n <span class=\"fb-palette-item__icon\"><span class=\"msi\">{{ formBuilderComponent.symbol }}</span></span>\r\n <span class=\"fb-palette-item__name\">{{ formBuilderComponent.name }}</span>\r\n <span class=\"fb-palette-item__drag\"><span class=\"msi\">drag_indicator</span></span>\r\n <!-- Generic drag preview: ch\u1EC9 icon (puck), label \u1EA9n -->\r\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </aside>\r\n\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 CENTER CANVAS \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <section class=\"fb-canvas\">\r\n <header class=\"fb-canvas__header\">\r\n <div class=\"fb-canvas__title\">\r\n <span>{{ 'core.component.form-builder.layout' | translate }}</span>\r\n </div>\r\n <div class=\"fb-canvas__actions\">\r\n <!-- Toolbar cluster: view JSON / variables / validation -->\r\n <button\r\n type=\"button\"\r\n class=\"fb-icon-btn\"\r\n [matTooltip]=\"'core.component.form-builder.view-json' | translate\"\r\n (click)=\"viewJSON()\">\r\n <span class=\"msi\">data_object</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fb-icon-btn\"\r\n [matTooltip]=\"'core.component.form-builder.config-variable' | translate\"\r\n (click)=\"configureVariables()\">\r\n <span class=\"msi\">data_array</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n class=\"fb-icon-btn\"\r\n [matTooltip]=\"'core.component.form-builder.config-validation-warning-error' | translate\"\r\n (click)=\"openConfigureValidation()\">\r\n <span class=\"msi\">rule</span>\r\n </button>\r\n\r\n <span class=\"fb-divider\"></span>\r\n\r\n <!-- M3 segmented Design/Preview toggle -->\r\n <div class=\"fb-mode-toggle\" role=\"tablist\">\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n [class.is-active]=\"!isPreview()\"\r\n (click)=\"setMode(false)\">\r\n <span class=\"msi\">edit</span>\r\n <span>{{ 'core.component.form-builder.design' | translate }}</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n role=\"tab\"\r\n [class.is-active]=\"isPreview()\"\r\n (click)=\"setMode(true)\">\r\n <span class=\"msi\">visibility</span>\r\n <span>{{ 'core.component.form-builder.preview' | translate }}</span>\r\n </button>\r\n </div>\r\n </div>\r\n </header>\r\n\r\n <div\r\n class=\"fb-canvas__body\"\r\n [class.is-preview]=\"isPreview()\"\r\n id=\"frmComponent\">\r\n @if (isPreview()) {\r\n <!-- \u2500\u2500 Preview mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n <div class=\"fb-preview-card\">\r\n <div class=\"fb-preview-card__chip\">\r\n <span class=\"msi\">visibility</span>\r\n {{ 'core.component.form-builder.preview-runtime' | translate }}\r\n </div>\r\n <sd-form-render [configuration]=\"{ components: this.components, validations: this.validations }\"></sd-form-render>\r\n <div class=\"fb-preview-card__footer\">\r\n <sd-button type=\"outline\" [title]=\"'core.component.form-builder.cancel' | translate\" (click)=\"setMode(false)\"></sd-button>\r\n <sd-button type=\"fill\" color=\"primary\" [title]=\"'core.component.form-builder.submit' | translate\" (click)=\"onValidate()\"></sd-button>\r\n </div>\r\n </div>\r\n } @else {\r\n <!-- \u2500\u2500 Design mode \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 -->\r\n @if (!dragDropRows.length) {\r\n <div class=\"fb-empty\">\r\n <div class=\"fb-empty__art\"><span class=\"msi\">dashboard_customize</span></div>\r\n <div class=\"fb-empty__title\">{{ 'core.component.form-builder.empty-title' | translate }}</div>\r\n <div class=\"fb-empty__hint\">\r\n {{ 'core.component.form-builder.empty-hint' | translate }}\r\n <span class=\"fb-empty__kbd\"><span class=\"msi\">keyboard</span>\u2318 K</span>\r\n </div>\r\n </div>\r\n }\r\n\r\n <div\r\n cdkDropList\r\n cdkDropListOrientation=\"vertical\"\r\n [cdkDropListData]=\"dragDropRows\"\r\n (cdkDropListDropped)=\"drop($event)\"\r\n (click)=\"clickFormContentEmpty()\"\r\n aria-hidden=\"true\">\r\n @for (row of dragDropRows; track row.rowIndex) {\r\n <div\r\n cdkDrag\r\n class=\"fb-row\"\r\n (mouseover)=\"onMouseover($event, row)\"\r\n (focus)=\"onFocus($event)\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\"\n [class.is-drag-target]=\"targetItem === row\"\n [id]=\"'row_' + row.rowIndex\"\n aria-hidden=\"true\">\r\n <div class=\"fb-row__drag\" [matTooltip]=\"'core.component.form-builder.drag-vertically' | translate\" cdkDragHandle>\r\n <span class=\"msi\">drag_indicator</span>\r\n </div>\r\n <!-- Generic puck preview -->\r\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <!-- Quick-add break button \u2014 show on row hover, insert break after this row -->\r\n <button\r\n type=\"button\"\r\n class=\"fb-row-break-btn\"\r\n [matTooltip]=\"'core.component.form-builder.break' | translate\"\r\n matTooltipPosition=\"right\"\r\n (click)=\"insertBreakAfter(row); $event.stopPropagation()\">\r\n <span class=\"msi\">horizontal_rule</span>\r\n </button>\r\n\r\n <div\r\n class=\"fb-row__items\"\r\n style=\"display: flex; flex: 1; gap: var(--gap-2);\"\r\n cdkDropList\r\n cdkDropListOrientation=\"horizontal\"\r\n [cdkDropListData]=\"row.items\"\r\n (cdkDropListDropped)=\"drop($event)\">\r\n\r\n @for (item of row.items; track item.id; let i = $index) {\r\n <!-- Group component renders as outlined card with colored header bar -->\r\n @if (item.type === 'group') {\r\n @let g = $any(item);\r\n @let cv = groupColorVars(g.properties?.color);\r\n <div\r\n cdkDrag\r\n [id]=\"item.id\"\r\n class=\"fb-group column-{{ item.layout?.columns || 12 }}\"\r\n [class.fb-item]=\"false\"\r\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\r\n [class.is-hidden]=\"item.properties?.hidden\"\r\n [style.flex]=\"'0 0 calc(' + (+(item.layout?.columns || 12)) + '/12 * 100% - var(--gap-2))'\"\r\n [style.maxWidth]=\"'calc(' + (+(item.layout?.columns || 12)) + '/12 * 100% - var(--gap-2))'\"\r\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\r\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <!-- cdkDragHandle: ch\u1EC9 cho ph\u00E9p k\u00E9o group qua header \u2014 body free cho click v\u00E0o child. -->\r\n <div class=\"fb-group__header\" cdkDragHandle [style.background]=\"cv.bg\" [style.color]=\"cv.fg\">\r\n <span class=\"fb-group__icon\"><span class=\"msi\">{{ g.properties?.icon || 'category' }}</span></span>\r\n <span class=\"fb-group__label\">{{ item.label }}</span>\r\n @if (hasConditional(item)) {\r\n <span class=\"fb-group__conditional-chip\">\r\n <span class=\"msi\" style=\"font-size: 12px;\">bolt</span>\r\n {{ 'core.component.form-builder.conditional' | translate }}\r\n </span>\r\n }\r\n <span class=\"fb-group__count\">{{ g.components?.length || 0 }} fields</span>\r\n </div>\r\n <!-- Floating action toolbar -->\r\n <div class=\"fb-actions\">\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\r\n (click)=\"onDuplicate(item); $event.stopPropagation()\">\r\n <span class=\"msi\">content_copy</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [class.warning]=\"item.properties?.hidden\"\r\n [class.on]=\"item.properties?.hidden\"\r\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\r\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\r\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn danger\"\r\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\r\n <span class=\"msi\">delete</span>\r\n </button>\r\n </div>\r\n\r\n <div\n class=\"fb-group__body\"\n cdkDropList\n cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"g.components\"\n (cdkDropListDropped)=\"dropInGroup($event, g)\">\n @if (!g.components?.length) {\r\n <div class=\"fb-group__empty\">\r\n <span class=\"msi\" style=\"font-size: 16px; margin-right: 6px;\">south</span>\r\n {{ 'core.component.form-builder.group-drop-here' | translate }}\r\n </div>\r\n }\r\n @for (child of g.components; track child.id; let ci = $index) {\r\n <div\r\n cdkDrag\r\n [id]=\"child.id\"\r\n class=\"fb-item is-child column-{{ child.layout?.columns || 12 }}\"\r\n [class.is-selected]=\"child.id === selectedComponent()?.id\"\r\n [class.is-hidden]=\"child.properties?.hidden\"\r\n [class.is-readonly]=\"child.properties?.viewed\"\r\n (click)=\"selectComponent(child); $event.stopPropagation()\"\n (cdkDragStarted)=\"onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"onAnyDragEnded()\">\n <!-- Generic puck preview -->\r\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <ng-container\r\n *ngTemplateOutlet=\"controlTemplate; context: { $implicit: child }\">\r\n </ng-container>\r\n <!-- Resize handle cho group child \u2014 chia 12-col ngay trong group body.\r\n Wrapping cdkDropList c\u00F3 enterPredicate=false \u0111\u1EC3 KH\u00D4NG nh\u1EADn drop\r\n (ch\u1EC9 d\u00F9ng l\u00E0m context cho cdkDrag), tr\u00E1nh xung \u0111\u1ED9t v\u1EDBi group__body drop list. -->\r\n <div cdkDropList cdkDropListOrientation=\"horizontal\" [cdkDropListEnterPredicate]=\"noReturnPredicate\">\r\n <div\r\n cdkDrag\r\n cdkDragLockAxis=\"x\"\r\n class=\"fb-resize\"\r\n (cdkDragStarted)=\"onAnyDragStarted()\"\r\n (cdkDragMoved)=\"changeSizeChildInGroup($event, child, g)\"\r\n (cdkDragEnded)=\"dragEndChangeSizeControl($event); onAnyDragEnded()\"\r\n [matTooltip]=\"'core.component.form-builder.flex' | translate\"\r\n aria-label=\"resize\"></div>\r\n </div>\r\n <!-- Inline status chips for nested children -->\r\n @if (child.properties?.hidden) {\r\n <span class=\"fb-status-chip hidden\">\r\n <span class=\"msi\">visibility_off</span>\r\n {{ 'core.component.form-builder.hidden' | translate }}\r\n </span>\r\n } @else if (child.properties?.viewed) {\r\n <span class=\"fb-status-chip readonly\">\r\n <span class=\"msi\">edit_off</span>\r\n {{ 'core.component.form-builder.read-only' | translate }}\r\n </span>\r\n } @else if (hasConditional(child)) {\r\n <span class=\"fb-status-chip conditional\">\r\n <span class=\"msi\">bolt</span>\r\n {{ 'core.component.form-builder.conditional' | translate }}\r\n </span>\r\n }\r\n <div class=\"fb-actions\">\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [class.warning]=\"child.properties?.viewed\"\r\n [class.on]=\"child.properties?.viewed\"\r\n [matTooltip]=\"child.properties?.viewed ? ('core.component.form-builder.unset-readonly' | translate) : ('core.component.form-builder.set-readonly' | translate)\"\r\n (click)=\"onChangeViewed(child); $event.stopPropagation()\">\r\n <span class=\"msi\">edit_off</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\r\n (click)=\"onDuplicate(child); $event.stopPropagation()\">\r\n <span class=\"msi\">content_copy</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [class.warning]=\"child.properties?.hidden\"\r\n [class.on]=\"child.properties?.hidden\"\r\n [matTooltip]=\"child.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\r\n (click)=\"onChangeHidden(child); $event.stopPropagation()\">\r\n <span class=\"msi\">{{ child.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn danger\"\r\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"removeFromGroup(g, child.id); $event.stopPropagation()\">\r\n <span class=\"msi\">delete</span>\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n } @else if (item.type === 'break') {\r\n <!-- Break: row separator c\u1ED1 \u0111\u1ECBnh. Render 12-col line, kh\u00F4ng c\u00F3 resize/edit attribute. -->\r\n <div\r\n cdkDrag\r\n [id]=\"item.id\"\r\n class=\"fb-item is-break column-12\"\r\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\r\n [class.is-hidden]=\"item.properties?.hidden\"\r\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\r\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n <div class=\"fb-break-line\">\r\n <span class=\"msi\">horizontal_rule</span>\r\n <span class=\"fb-break-label\">{{ 'core.component.form-builder.break' | translate }}</span>\r\n </div>\r\n <div class=\"fb-actions\">\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [class.warning]=\"item.properties?.hidden\"\r\n [class.on]=\"item.properties?.hidden\"\r\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\r\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\r\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn danger\"\r\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\r\n <span class=\"msi\">delete</span>\r\n </button>\r\n </div>\r\n </div>\r\n } @else {\r\n <!-- Regular form component -->\r\n <div\r\n cdkDrag\r\n [id]=\"item.id\"\r\n class=\"fb-item column-{{ item.layout?.columns || 12 }}\"\r\n [class.is-selected]=\"item.id === selectedComponent()?.id\"\r\n [class.is-hidden]=\"item.properties?.hidden\"\r\n [class.is-readonly]=\"item.properties?.viewed\"\r\n (click)=\"selectComponent(item); $event.stopPropagation()\"\n (cdkDragStarted)=\"dragStartComponentItem($event); onAnyDragStarted()\"\n (cdkDragMoved)=\"onAnyDragMoved($event)\"\n (cdkDragEnded)=\"dragEndComponentItem($event); onAnyDragEnded()\"\n aria-hidden=\"true\">\n <!-- Generic puck preview -->\r\n <div *cdkDragPreview class=\"fb-drag-preview\"></div>\n\r\n <!-- Status chip (mutually exclusive priority: hidden > readonly > conditional) -->\r\n @if (item.properties?.hidden) {\r\n <span class=\"fb-status-chip hidden\">\r\n <span class=\"msi\">visibility_off</span>\r\n {{ 'core.component.form-builder.hidden' | translate }}\r\n </span>\r\n } @else if (item.properties?.viewed) {\r\n <span class=\"fb-status-chip readonly\">\r\n <span class=\"msi\">edit_off</span>\r\n {{ 'core.component.form-builder.read-only' | translate }}\r\n </span>\r\n } @else if (hasConditional(item)) {\r\n <span class=\"fb-status-chip conditional\">\r\n <span class=\"msi\">bolt</span>\r\n {{ 'core.component.form-builder.conditional' | translate }}\r\n </span>\r\n }\r\n\r\n <!-- Floating action toolbar pill -->\r\n <div class=\"fb-actions\">\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [class.warning]=\"item.properties?.viewed\"\r\n [class.on]=\"item.properties?.viewed\"\r\n [matTooltip]=\"item.properties?.viewed ? ('core.component.form-builder.unset-readonly' | translate) : ('core.component.form-builder.set-readonly' | translate)\"\r\n (click)=\"onChangeViewed(item); $event.stopPropagation()\">\r\n <span class=\"msi\">edit_off</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [matTooltip]=\"'core.component.form-builder.duplicate' | translate\"\r\n (click)=\"onDuplicate(item); $event.stopPropagation()\">\r\n <span class=\"msi\">content_copy</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn\"\r\n [class.warning]=\"item.properties?.hidden\"\r\n [class.on]=\"item.properties?.hidden\"\r\n [matTooltip]=\"item.properties?.hidden ? ('core.component.form-builder.show' | translate) : ('core.component.form-builder.hide' | translate)\"\r\n (click)=\"onChangeHidden(item); $event.stopPropagation()\">\r\n <span class=\"msi\">{{ item.properties?.hidden ? 'visibility_off' : 'visibility' }}</span>\r\n </button>\r\n <button type=\"button\" class=\"fb-icon-btn danger\"\r\n [matTooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"removeComponent(item.id); $event.stopPropagation()\">\r\n <span class=\"msi\">delete</span>\r\n </button>\r\n </div>\r\n\r\n <ng-container\r\n *ngTemplateOutlet=\"controlTemplate; context: { $implicit: item }\">\r\n </ng-container>\r\n\r\n <!-- Resize handle (pill) \u2014 cdkDragLockAxis=\"x\" \u0111\u1EC3 ch\u1EC9 k\u00E9o ngang.\r\n Wrapping cdkDropList c\u00F3 enterPredicate=false, kh\u00F4ng nh\u1EADn drop. -->\r\n <div cdkDropList cdkDropListOrientation=\"horizontal\" [cdkDropListEnterPredicate]=\"noReturnPredicate\">\r\n <div\r\n cdkDrag\r\n cdkDragLockAxis=\"x\"\r\n class=\"fb-resize\"\r\n (cdkDragStarted)=\"onAnyDragStarted()\"\r\n (cdkDragMoved)=\"changeSizeControl($event, item, row.items, i)\"\r\n (cdkDragEnded)=\"dragEndChangeSizeControl($event); onAnyDragEnded()\"\r\n [matTooltip]=\"'core.component.form-builder.flex' | translate\"\r\n aria-label=\"resize\"></div>\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n </section>\r\n\r\n <!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 RIGHT ATTRIBUTES \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n <aside class=\"fb-attrs\">\r\n <div class=\"fb-panel-header\">\r\n <div class=\"fb-panel-header__title\">{{ 'core.component.form-builder.attribute' | translate }}</div>\r\n </div>\r\n\r\n @let sel = selectedComponent();\r\n @if (sel) {\r\n <!-- Selection header: type icon + name + key/type -->\r\n <div class=\"fb-attrs__selection\">\r\n <span class=\"fb-attrs__sel-icon\"><span class=\"msi\">{{ symbolFor(sel) }}</span></span>\r\n <div class=\"fb-attrs__sel-meta\">\r\n <div class=\"fb-attrs__sel-name\">{{ $any(sel).label || ('core.component.form-builder.untitled' | translate) }}</div>\r\n <div class=\"fb-attrs__sel-key\">\r\n @if ($any(sel).key) {\r\n {{ $any(sel).key }} \u00B7 {{ typeLabelFor(sel) }}\r\n } @else {\r\n {{ typeLabelFor(sel) }}\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"fb-attrs__body\" aria-hidden=\"true\">\r\n @if (sel.type === 'textfield') {\r\n <textfield-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></textfield-attribute>\r\n } @else if (sel.type === 'textarea') {\r\n <textarea-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></textarea-attribute>\r\n } @else if (sel.type === 'chip-string') {\r\n <chip-string-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></chip-string-attribute>\r\n } @else if (sel.type === 'chip-calendar') {\r\n <chip-calendar-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></chip-calendar-attribute>\r\n } @else if (sel.type === 'number') {\r\n <number-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></number-attribute>\r\n } @else if (sel.type === 'datetime') {\r\n <datetime-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></datetime-attribute>\r\n } @else if (sel.type === 'select') {\r\n <select-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></select-attribute>\r\n } @else if (sel.type === 'radio') {\r\n <radio-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></radio-attribute>\r\n } @else if (sel.type === 'checkbox') {\r\n <checkbox-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></checkbox-attribute>\r\n } @else if (sel.type === 'html') {\r\n <html-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></html-attribute>\r\n } @else if (sel.type === 'upload') {\r\n <upload-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></upload-attribute>\r\n } @else if (sel.type === 'table') {\r\n <table-attribute [components]=\"components\" [variables]=\"variables\" [component]=\"sel\"></table-attribute>\r\n } @else if (sel.type === 'group') {\r\n <group-attribute [group]=\"$any(sel)\"></group-attribute>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"fb-attrs__placeholder\">\r\n <span class=\"msi\">ads_click</span>\r\n <div class=\"title\">{{ 'core.component.form-builder.no-selection-title' | translate }}</div>\r\n <div class=\"hint\">{{ 'core.component.form-builder.no-selection-hint' | translate }}</div>\r\n </div>\r\n }\r\n </aside>\r\n</div>\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 Reusable control template \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<ng-template #controlTemplate let-item>\r\n @if (item.type === 'textfield') {\r\n <textfield-control [component]=\"item\"></textfield-control>\r\n } @else if (item.type === 'textarea') {\r\n <textarea-control [component]=\"item\"></textarea-control>\r\n } @else if (item.type === 'chip-string') {\r\n <chip-string-control [component]=\"item\"></chip-string-control>\r\n } @else if (item.type === 'chip-calendar') {\r\n <chip-calendar-control [component]=\"item\"></chip-calendar-control>\r\n } @else if (item.type === 'number') {\r\n <number-control [component]=\"item\"></number-control>\r\n } @else if (item.type === 'datetime') {\r\n <datetime-control [component]=\"item\"></datetime-control>\r\n } @else if (item.type === 'select') {\r\n <select-control [component]=\"item\"></select-control>\r\n } @else if (item.type === 'radio') {\r\n <radio-control [component]=\"item\"></radio-control>\r\n } @else if (item.type === 'checkbox') {\r\n <checkbox-control [component]=\"item\"></checkbox-control>\r\n } @else if (item.type === 'html') {\r\n <html-control [component]=\"item\"></html-control>\r\n } @else if (item.type === 'upload') {\r\n <upload-control [component]=\"item\"></upload-control>\r\n } @else if (item.type === 'table') {\r\n <table-control [component]=\"item\"></table-control>\r\n }\r\n</ng-template>\r\n\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 JSON / variables modals \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<sd-modal title=\"JSON\" view=\"dialog\" width=\"80%\" #popupViewJSON>\r\n <sd-textarea [(model)]=\"jsonString\"></sd-textarea>\r\n <ng-container sdFooter>\r\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateJSON()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n<sd-modal [title]=\"'core.component.form-builder.config-variable' | translate\" view=\"dialog\" width=\"800px\" #popupConfigureVariables>\r\n @for (variable of clonedVariables; track variable.id) {\r\n <div class=\"d-flex align-items-center\" style=\"gap: 8px\">\r\n <sd-input [form]=\"form\" [label]=\"'core.component.form-builder.field-key' | translate\" [(model)]=\"variable.key\" required></sd-input>\r\n <sd-input [form]=\"form\" [label]=\"'core.component.form-builder.display-label' | translate\" [(model)]=\"variable.label\" required></sd-input>\r\n <sd-button prefixIcon=\"delete\" (click)=\"removeVariables(variable.id)\" color=\"error\"></sd-button>\r\n </div>\r\n }\r\n <a href=\"javascript:;\" (click)=\"addVariables()\">{{ 'core.component.form-builder.add-variable' | translate }}</a>\r\n <ng-container sdFooter>\r\n <sd-button type=\"fill\" [title]=\"'core.component.form-builder.save' | translate\" (click)=\"updateVariables()\" prefixIcon=\"save\" color=\"primary\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n<configure-validation (accept)=\"onUpdateValidations($event)\"></configure-validation>\r\n", styles: [":host{--md-sys-color-primary: var(--sd-primary, #2A66F4);--md-sys-color-on-primary: #ffffff;--md-sys-color-primary-container: var(--sd-primary-light, #EAF1FF);--md-sys-color-on-primary-container: var(--sd-primary, #2A66F4);--md-sys-color-info: var(--sd-info, #2962FF);--md-sys-color-info-container: var(--sd-info-light, #E7E9FF);--md-sys-color-secondary: #625b71;--md-sys-color-secondary-container: #e8def8;--md-sys-color-on-secondary-container: #1d192b;--md-sys-color-surface: #fbfafc;--md-sys-color-surface-container-lowest: #ffffff;--md-sys-color-surface-container-low: #f6f4f8;--md-sys-color-surface-container: #f1eef3;--md-sys-color-surface-container-high: #ebe8ee;--md-sys-color-surface-container-highest: #e6e2ea;--md-sys-color-on-surface: #1c1b1f;--md-sys-color-on-surface-variant: #49454e;--md-sys-color-outline: #79747e;--md-sys-color-outline-variant: #d6d2da;--md-sys-color-error: #b3261e;--md-sys-color-error-container: #f9dedc;--md-sys-color-warning: #8a5400;--md-sys-color-warning-container: #ffddb1;--md-sys-color-success: #1f6f43;--md-sys-color-success-container: #b7f0cb;--h-row: 28px;--h-field: 32px;--h-palette: 36px;--h-header: 36px;--h-section: 28px;--h-action-btn: 24px;--gap-1: 4px;--gap-2: 8px;--gap-3: 12px;--gap-4: 16px;--gap-5: 24px;--r-xs: 4px;--r-sm: 8px;--r-md: 12px;--r-lg: 16px;--r-xl: 28px;--r-pill: 999px;--elev-1: 0 1px 2px 0 rgba(0, 0, 0, .06);--elev-2: 0 2px 6px 0 rgba(0, 0, 0, .08), 0 1px 2px 0 rgba(0, 0, 0, .04);--elev-3: 0 6px 14px 0 rgba(0, 0, 0, .1), 0 2px 4px 0 rgba(0, 0, 0, .06);display:block;width:100%;height:100%;font-family:Roboto,system-ui,sans-serif;font-size:13px;color:var(--md-sys-color-on-surface);background:var(--md-sys-color-surface)}:host ::ng-deep .msi{font-family:Material Symbols Rounded;font-weight:400;font-style:normal;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;font-feature-settings:\"liga\";-webkit-font-feature-settings:\"liga\";-webkit-font-smoothing:antialiased;font-variation-settings:\"wght\" 300,\"opsz\" 24,\"GRAD\" 0,\"FILL\" 0}:host ::ng-deep .msi.filled{font-variation-settings:\"wght\" 300,\"opsz\" 24,\"GRAD\" 0,\"FILL\" 1}:host ::ng-deep .mono{font-family:Roboto Mono,ui-monospace,monospace}:host ::ng-deep .fb-icon-btn{width:28px;height:28px;border-radius:var(--r-sm);border:none;background:transparent;color:var(--md-sys-color-on-surface-variant);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:background .12s ease,color .12s ease}:host ::ng-deep .fb-icon-btn:hover{background:color-mix(in srgb,var(--md-sys-color-on-surface) 8%,transparent);color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-icon-btn.is-active{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container)}:host ::ng-deep .fb-icon-btn.danger:hover{color:var(--md-sys-color-error);background:var(--md-sys-color-error-container)}:host ::ng-deep .fb-icon-btn.warning.on{color:var(--md-sys-color-warning);background:var(--md-sys-color-warning-container)}:host ::ng-deep .fb-icon-btn .msi{font-size:18px}:host ::ng-deep .fb-field{display:flex;flex-direction:column;gap:4px}:host ::ng-deep .fb-field__label{font-size:11px;font-weight:500;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field__input{height:var(--h-row);padding:0 10px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;display:flex;align-items:center;justify-content:space-between;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-field__input.placeholder{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field__input:focus-within,:host ::ng-deep .fb-field__input.focused{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent)}:host ::ng-deep .fb-field__input .msi{font-size:16px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-field-row{display:flex;align-items:center;gap:var(--gap-2);justify-content:space-between}:host ::ng-deep .fb-switch{display:inline-flex;width:34px;height:18px;border-radius:999px;background:var(--md-sys-color-surface-container-highest);border:1.5px solid var(--md-sys-color-outline);padding:1px;align-items:center;cursor:pointer;position:relative;flex-shrink:0}:host ::ng-deep .fb-switch .fb-switch__thumb{width:12px;height:12px;border-radius:50%;background:var(--md-sys-color-outline)}:host ::ng-deep .fb-switch.on{background:var(--md-sys-color-primary);border-color:var(--md-sys-color-primary);justify-content:flex-end}:host ::ng-deep .fb-switch.on .fb-switch__thumb{background:var(--md-sys-color-on-primary);width:14px;height:14px}:host ::ng-deep .fb-expr{display:flex;align-items:center;gap:6px;height:var(--h-row);padding:0 6px 0 0;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-expr__badge{height:100%;display:inline-flex;align-items:center;justify-content:center;padding:0 6px;background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-family:Roboto Mono,monospace;font-size:10px;font-weight:500;border-radius:var(--r-xs) 0 0 var(--r-xs)}:host ::ng-deep .fb-expr__code{font-family:Roboto Mono,monospace;flex:1;font-size:11px;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-expr__code .var{color:var(--md-sys-color-primary);font-weight:500}:host ::ng-deep .fb-expr__code .op{color:var(--md-sys-color-error)}:host ::ng-deep .fb-expr__code .lit{color:var(--md-sys-color-success)}:host ::ng-deep .fb-expr .empty{color:var(--md-sys-color-on-surface-variant);font-style:italic;padding-left:6px;flex:1}:host ::ng-deep details.fb-section{border-bottom:1px solid var(--md-sys-color-outline-variant);margin:0;padding:0;background:transparent}:host ::ng-deep details.fb-section>summary{list-style:none}:host ::ng-deep details.fb-section>summary::-webkit-details-marker{display:none}:host ::ng-deep .fb-section__head{height:var(--h-section);padding:0 var(--gap-4);display:flex;align-items:center;gap:var(--gap-2);cursor:pointer;font-size:12px;font-weight:500;color:var(--md-sys-color-on-surface);-webkit-user-select:none;user-select:none}:host ::ng-deep .fb-section__head .msi{font-size:16px;color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .fb-section__head .fb-section__title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .fb-section__head .chev{margin-left:auto;transition:transform .16s ease}:host ::ng-deep details.fb-section[open] .fb-section__head .chev{transform:rotate(90deg)}:host ::ng-deep .fb-section__body{padding:4px var(--gap-4) var(--gap-3);display:flex;flex-direction:column;gap:var(--gap-2)}:host ::ng-deep .fb-columns-list{display:flex;flex-direction:column;gap:var(--gap-1);padding-top:var(--gap-1)}:host ::ng-deep .fb-column-row{display:flex;align-items:center;gap:var(--gap-2);height:40px;padding:6px 10px;border-radius:var(--r-sm);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px;cursor:pointer;transition:background .12s ease,border-color .12s ease,box-shadow .12s ease}:host ::ng-deep .fb-column-row:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent);border-color:color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}:host ::ng-deep .fb-column-row.is-active{border-color:var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent);box-shadow:0 0 0 1px color-mix(in srgb,var(--md-sys-color-primary) 30%,transparent)}:host ::ng-deep .fb-column-row .fb-column-row__type-icon{width:28px;height:28px;border-radius:var(--r-sm);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}:host ::ng-deep .fb-column-row .fb-column-row__type-icon .msi{font-size:16px}:host ::ng-deep .fb-column-row .fb-column-row__meta{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__label{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--md-sys-color-on-surface)}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__req{color:var(--md-sys-color-error);margin-left:2px;font-weight:600}:host ::ng-deep .fb-column-row .fb-column-row__meta .fb-column-row__sub{font-size:11px;color:var(--md-sys-color-on-surface-variant);font-family:Roboto Mono,ui-monospace,monospace;letter-spacing:.02em}:host ::ng-deep .cdk-drag-preview.fb-drag-preview,:host ::ng-deep .fb-drag-preview{width:36px;height:36px;min-width:36px;min-height:36px;max-width:36px;max-height:36px;box-sizing:border-box;border-radius:50%;background:var(--md-sys-color-primary, #6750a4);display:inline-flex;align-items:center;justify-content:center;box-shadow:0 10px 24px #00000042,0 3px 8px #00000024;border:3px solid var(--md-sys-color-on-primary, #ffffff);cursor:grabbing;pointer-events:none;-webkit-user-select:none;user-select:none;opacity:.96;overflow:hidden;z-index:10000}:host ::ng-deep .cdk-drag-preview.fb-drag-preview:after,:host ::ng-deep .fb-drag-preview:after{content:\"\";width:8px;height:8px;border-radius:50%;background:var(--md-sys-color-on-primary, #ffffff);opacity:.9}@keyframes fb-drop-pulse{0%,to{box-shadow:0 0 0 3px color-mix(in srgb,var(--md-sys-color-info) 16%,transparent)}50%{box-shadow:0 0 0 5px color-mix(in srgb,var(--md-sys-color-info) 24%,transparent)}}:host ::ng-deep .cdk-drag-placeholder{background:transparent!important;border:none!important;border-radius:999px!important;padding:0!important;transform:none!important;transition:none!important;pointer-events:none;overflow:hidden;animation:none!important;opacity:0!important}:host ::ng-deep .cdk-drag-placeholder>*{visibility:hidden!important;pointer-events:none!important}:host ::ng-deep .fb-palette__list>.cdk-drag-placeholder{display:none!important}:host ::ng-deep .fb-row__items>.cdk-drag-placeholder,:host ::ng-deep .fb-group__body>.cdk-drag-placeholder{width:0!important;min-width:0!important;max-width:0!important;height:auto!important;min-height:0!important;align-self:stretch;flex:0 0 0!important;margin:0!important}:host ::ng-deep [cdkDropListOrientation=vertical]>.cdk-drag-placeholder{width:auto!important;height:0!important;min-height:0!important;max-height:0!important;flex:0 0 0!important;margin:0!important;align-self:stretch}:host ::ng-deep .cdk-drop-list-receiving{background:color-mix(in srgb,var(--md-sys-color-primary) 3%,transparent);transition:background .16s ease}:host ::ng-deep .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-group__body.cdk-drop-list-dragging{background:color-mix(in srgb,var(--md-sys-color-primary) 10%,transparent)!important;outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 78%,transparent);outline-offset:-6px;border-radius:var(--r-sm)}:host ::ng-deep .fb-resize.cdk-drag-preview{display:none!important}:host ::ng-deep .fb-shell--dragging .fb-item:hover,:host ::ng-deep .fb-shell--dragging .fb-group:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-item:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group:hover{border-color:transparent!important;background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-row:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row:hover{outline-color:transparent!important;background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-row:hover .fb-row__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row:hover .fb-row__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-row.is-drag-target,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row.is-drag-target{outline-color:color-mix(in srgb,var(--md-sys-color-info) 44%,transparent)!important;background:color-mix(in srgb,var(--md-sys-color-info) 4%,transparent)!important}:host ::ng-deep .fb-shell--dragging .fb-row__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-actions,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-actions{opacity:0!important;pointer-events:none!important;transform:translateY(-2px)!important}:host ::ng-deep .fb-shell--dragging .fb-resize,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-resize{opacity:0!important;pointer-events:none!important}:host ::ng-deep .fb-shell--dragging .fb-row-break-btn,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-row-break-btn{opacity:0!important;pointer-events:none!important}:host ::ng-deep .fb-shell--dragging .fb-palette-item:hover,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-palette-item:hover{background:transparent!important}:host ::ng-deep .fb-shell--dragging .fb-palette-item:hover .fb-palette-item__drag,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-palette-item:hover .fb-palette-item__drag{opacity:0!important}:host ::ng-deep .fb-shell--dragging .fb-group__body,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body{min-height:80px!important;background:color-mix(in srgb,var(--md-sys-color-primary) 5%,transparent)!important;outline:2px dashed color-mix(in srgb,var(--md-sys-color-primary) 50%,transparent)!important;outline-offset:-6px;border-radius:var(--r-sm);transition:background .16s ease,outline .16s ease,min-height .16s ease}:host ::ng-deep .fb-shell--dragging .fb-group__empty,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__empty{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 55%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary) 7%,transparent);color:var(--md-sys-color-primary)}:host ::ng-deep .fb-shell--dragging .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-shell--dragging .fb-group__body.cdk-drop-list-dragging,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body.cdk-drop-list-receiving,:host ::ng-deep .fb-shell:has(.cdk-drag-dragging) .fb-group__body.cdk-drop-list-dragging{background:color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent)!important;outline:2px solid var(--md-sys-color-primary)!important}:host ::ng-deep .cdk-drag-animating{transition:transform .22s cubic-bezier(.2,0,0,1)!important}:host ::ng-deep .cdk-drag-dragging{transition:none!important}:host ::ng-deep .fb-item:not(.cdk-drag-dragging){transition:flex .12s cubic-bezier(.2,0,0,1),max-width .12s cubic-bezier(.2,0,0,1),border-color .12s,background .12s}.fb-shell{width:100%;height:100%;display:flex;background:var(--md-sys-color-surface);overflow:hidden;min-height:0}.fb-panel-header{height:var(--h-header);display:flex;align-items:center;justify-content:space-between;padding:0 var(--gap-3);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);flex-shrink:0}.fb-panel-header__title{font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.fb-panel-header__actions{display:flex;align-items:center;gap:2px}.fb-palette{width:220px;flex-shrink:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-right:1px solid var(--md-sys-color-outline-variant)}.fb-palette__scroll{flex:1;overflow-y:auto;padding-bottom:var(--gap-3)}.fb-palette__search{margin:var(--gap-3);height:32px;display:flex;align-items:center;gap:var(--gap-2);padding:0 var(--gap-3);border-radius:var(--r-pill);background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:13px;flex-shrink:0}.fb-palette__search .msi{font-size:18px}.fb-palette__search input{flex:1;border:none;outline:none;background:transparent;color:var(--md-sys-color-on-surface);font-size:13px;font-family:inherit}.fb-palette__search input::placeholder{color:var(--md-sys-color-on-surface-variant)}.fb-palette__search .kbd{font-family:Roboto Mono,monospace;font-size:10px;padding:1px 6px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant)}.fb-palette__group-label{font-size:11px;font-weight:500;letter-spacing:.04em;color:var(--md-sys-color-on-surface-variant);padding:var(--gap-3) var(--gap-4) var(--gap-1);text-transform:uppercase}.fb-palette__list{display:flex;flex-direction:column;padding:0 var(--gap-2)}.fb-palette-item{height:var(--h-palette);display:flex;align-items:center;gap:var(--gap-3);padding:0 var(--gap-3);border-radius:var(--r-sm);cursor:grab;color:var(--md-sys-color-on-surface);position:relative;-webkit-user-select:none;user-select:none}.fb-palette-item:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}.fb-palette-item .fb-palette-item__icon{width:24px;height:24px;border-radius:var(--r-xs);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);flex-shrink:0}.fb-palette-item .fb-palette-item__icon .msi{font-size:16px}.fb-palette-item .fb-palette-item__name{font-size:13px;font-weight:400}.fb-palette-item .fb-palette-item__drag{margin-left:auto;color:var(--md-sys-color-outline);opacity:0;transition:opacity .12s ease}.fb-palette-item .fb-palette-item__drag .msi{font-size:16px}.fb-palette-item:hover .fb-palette-item__drag{opacity:1}.fb-canvas{flex:1 1 0;min-width:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface);overflow:hidden}.fb-canvas__header{height:var(--h-header);display:flex;align-items:center;justify-content:space-between;padding:0 var(--gap-4);border-bottom:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface);gap:var(--gap-3);flex-shrink:0}.fb-canvas__title{display:flex;align-items:center;gap:var(--gap-2);font-size:11px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant)}.fb-canvas__title .breadcrumb-sep{color:var(--md-sys-color-outline)}.fb-canvas__actions{display:flex;align-items:center;gap:var(--gap-2)}.fb-divider{width:1px;height:18px;background:var(--md-sys-color-outline-variant)}.fb-canvas__body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;padding:var(--gap-4);position:relative;background:var(--md-sys-color-surface);min-width:0}.fb-canvas__body.is-preview{background:var(--md-sys-color-surface-container-low);padding:32px}.fb-mode-toggle{display:inline-flex;height:28px;border:1px solid var(--md-sys-color-outline);border-radius:var(--r-pill);overflow:hidden;flex-shrink:0}.fb-mode-toggle button{border:0;background:transparent;padding:0 var(--gap-3);font-size:12px;font-weight:500;display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-surface-variant);cursor:pointer}.fb-mode-toggle button .msi{font-size:16px}.fb-mode-toggle button.is-active{background:var(--md-sys-color-secondary-container);color:var(--md-sys-color-on-secondary-container)}.fb-row{position:relative;display:flex;gap:var(--gap-2);padding:6px var(--gap-2);border-radius:var(--r-sm);margin-bottom:6px;min-width:0;transition:outline .12s ease,background .12s ease;outline:1px dashed transparent;outline-offset:-1px}.fb-row:hover{outline-color:var(--md-sys-color-outline-variant);background:color-mix(in srgb,var(--md-sys-color-primary) 3%,transparent)}.fb-row:hover .fb-row__drag{opacity:1}.fb-row.is-drag-target{outline-color:color-mix(in srgb,var(--md-sys-color-info) 44%,transparent);background:color-mix(in srgb,var(--md-sys-color-info) 4%,transparent)}.fb-row.is-drag-target:after{content:\"\";position:absolute;left:10px;right:10px;bottom:-3px;height:4px;border-radius:999px;background:var(--md-sys-color-info);box-shadow:0 0 0 4px color-mix(in srgb,var(--md-sys-color-info) 18%,transparent);pointer-events:none;animation:fb-drop-pulse .9s ease-in-out infinite;z-index:3}.fb-row__drag{position:absolute;left:-22px;top:50%;transform:translateY(-50%);width:18px;height:22px;border-radius:var(--r-xs);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);opacity:0;cursor:grab;z-index:2}.fb-row__drag .msi{font-size:14px}.fb-row-break-btn{position:absolute;right:-28px;top:50%;transform:translateY(-50%);width:22px;height:22px;border-radius:var(--r-pill);display:inline-flex;align-items:center;justify-content:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-high);border:1px solid var(--md-sys-color-outline-variant);cursor:pointer;opacity:0;z-index:2;transition:opacity .12s ease,background .12s ease,color .12s ease}.fb-row-break-btn .msi{font-size:14px}.fb-row-break-btn:hover{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);border-color:transparent}.fb-row:hover .fb-row-break-btn{opacity:1}.fb-item{position:relative;border:1.5px dashed transparent;border-radius:var(--r-md);padding:var(--gap-2) var(--gap-3);min-height:56px;min-width:0;transition:border-color .12s ease,background .12s ease;background:transparent;cursor:grab;display:flex;flex-direction:column;gap:6px}.fb-item:hover{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,transparent)}.fb-item.is-selected{border:1.5px solid var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent)}.fb-item.is-hidden{opacity:.45}.fb-item.is-readonly:after{content:\"\";position:absolute;inset:0;border-radius:var(--r-md);background:repeating-linear-gradient(135deg,transparent 0 6px,color-mix(in srgb,var(--md-sys-color-on-surface) 4%,transparent) 6px 7px);pointer-events:none}.fb-item.column-2{flex:0 0 calc(16.6666666667% - var(--gap-2));max-width:calc(16.6666666667% - var(--gap-2))}.fb-item.column-3{flex:0 0 calc(25% - var(--gap-2));max-width:calc(25% - var(--gap-2))}.fb-item.column-4{flex:0 0 calc(33.3333333333% - var(--gap-2));max-width:calc(33.3333333333% - var(--gap-2))}.fb-item.column-5{flex:0 0 calc(41.6666666667% - var(--gap-2));max-width:calc(41.6666666667% - var(--gap-2))}.fb-item.column-6{flex:0 0 calc(50% - var(--gap-2));max-width:calc(50% - var(--gap-2))}.fb-item.column-7{flex:0 0 calc(58.3333333333% - var(--gap-2));max-width:calc(58.3333333333% - var(--gap-2))}.fb-item.column-8{flex:0 0 calc(66.6666666667% - var(--gap-2));max-width:calc(66.6666666667% - var(--gap-2))}.fb-item.column-9{flex:0 0 calc(75% - var(--gap-2));max-width:calc(75% - var(--gap-2))}.fb-item.column-10{flex:0 0 calc(83.3333333333% - var(--gap-2));max-width:calc(83.3333333333% - var(--gap-2))}.fb-item.column-11{flex:0 0 calc(91.6666666667% - var(--gap-2));max-width:calc(91.6666666667% - var(--gap-2))}.fb-item.column-12{flex:1 1 100%;max-width:100%}.fb-actions{position:absolute;top:-14px;right:8px;display:flex;align-items:center;gap:2px;padding:2px;border-radius:var(--r-pill);background:var(--md-sys-color-surface-container-lowest);box-shadow:var(--elev-2);border:1px solid var(--md-sys-color-outline-variant);z-index:4;opacity:0;transform:translateY(-2px);pointer-events:none;transition:opacity .12s ease,transform .12s ease}.fb-actions .fb-icon-btn{width:24px;height:24px}.fb-actions .fb-icon-btn .msi{font-size:16px}.fb-item:hover .fb-actions,.fb-item.is-selected .fb-actions{opacity:1;transform:translateY(0);pointer-events:auto}.fb-group>.fb-actions{top:6px;right:8px}.fb-group:hover>.fb-actions,.fb-group.is-selected>.fb-actions{opacity:1;transform:translateY(0);pointer-events:auto}.fb-status-chip{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;height:18px;border-radius:var(--r-pill);font-size:10px;font-weight:500;letter-spacing:.02em;position:absolute;top:-9px;left:12px;z-index:3;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant)}.fb-status-chip .msi{font-size:12px}.fb-status-chip.readonly{color:var(--md-sys-color-warning);background:var(--md-sys-color-warning-container);border-color:transparent}.fb-status-chip.hidden{color:var(--md-sys-color-on-surface-variant)}.fb-status-chip.conditional{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);border-color:transparent}.fb-resize{position:absolute;top:8px;bottom:8px;right:-5px;width:6px;border-radius:999px;background:var(--md-sys-color-primary);display:flex;align-items:center;justify-content:center;cursor:col-resize;opacity:0;transition:opacity .12s ease;z-index:3}.fb-resize:before{content:\"\";width:2px;height:18px;background:var(--md-sys-color-on-primary);border-radius:999px}.fb-item:hover .fb-resize{opacity:1}.fb-item.is-break{min-height:28px;padding:8px var(--gap-3);justify-content:center}.fb-break-line{display:flex;align-items:center;gap:var(--gap-2);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:500;letter-spacing:.06em;text-transform:uppercase}.fb-break-line:before,.fb-break-line:after{content:\"\";flex:1;height:1px;background:var(--md-sys-color-outline-variant)}.fb-break-line .msi{display:none}.fb-break-line .fb-break-label{color:var(--md-sys-color-on-surface-variant)}.fb-drop-hint{height:36px;border-radius:var(--r-sm);border:1.5px dashed var(--md-sys-color-primary);background:color-mix(in srgb,var(--md-sys-color-primary) 6%,transparent);color:var(--md-sys-color-primary);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:500;gap:6px;margin:4px 0}.fb-drop-hint .msi{font-size:16px}.fb-group{background:var(--md-sys-color-surface-container-lowest);border-radius:var(--r-lg);border:1.5px dashed transparent;transition:border-color .12s ease,background .12s ease;position:relative;display:flex;flex-direction:column;overflow:visible;cursor:default}.fb-group:hover{border-color:color-mix(in srgb,var(--md-sys-color-primary) 60%,transparent)}.fb-group.is-selected{border:1.5px solid var(--md-sys-color-primary)}.fb-group.is-hidden{opacity:.55}.fb-group__header{display:flex;align-items:center;gap:var(--gap-2);padding:8px 12px;border-top-left-radius:12px;border-top-right-radius:12px;cursor:grab}.fb-group__header:active{cursor:grabbing}.fb-group__header .fb-group__icon .msi{font-size:18px}.fb-group__header .fb-group__label{font-size:13px;font-weight:500}.fb-group__header .fb-group__count{margin-left:auto;font-size:10px;opacity:.75}.fb-group__conditional-chip{display:inline-flex;align-items:center;gap:4px;font-family:Roboto Mono,monospace;font-size:10px;padding:2px 8px;border-radius:var(--r-pill);background:color-mix(in srgb,currentColor 12%,transparent)}.fb-group__body{padding:12px;display:flex;flex-wrap:wrap;gap:var(--gap-2);min-height:60px;position:relative}.fb-group__empty{display:flex;align-items:center;justify-content:center;height:56px;border-radius:var(--r-sm);border:1.5px dashed var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);font-size:12px;font-style:italic}.fb-empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--gap-3);color:var(--md-sys-color-on-surface-variant);text-align:center;padding:24px;pointer-events:none}.fb-empty__art{width:96px;height:96px;border-radius:var(--r-xl);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center}.fb-empty__art .msi{font-size:44px}.fb-empty__title{font-size:16px;font-weight:500;color:var(--md-sys-color-on-surface)}.fb-empty__hint{font-size:13px;max-width:320px;line-height:1.5}.fb-empty__kbd{display:inline-flex;align-items:center;gap:6px;font-family:Roboto Mono,monospace;font-size:11px;padding:4px 8px;border-radius:var(--r-xs);border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface-variant)}.fb-empty__kbd .msi{font-size:12px}.fb-attrs{width:320px;flex-shrink:0;display:flex;flex-direction:column;background:var(--md-sys-color-surface-container-low);border-left:1px solid var(--md-sys-color-outline-variant)}.fb-attrs__selection{padding:var(--gap-3) var(--gap-4);display:flex;align-items:center;gap:var(--gap-2);border-bottom:1px solid var(--md-sys-color-outline-variant)}.fb-attrs__sel-icon{width:28px;height:28px;border-radius:var(--r-sm);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.fb-attrs__sel-icon .msi{font-size:18px}.fb-attrs__sel-meta{display:flex;flex-direction:column;min-width:0}.fb-attrs__sel-name{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.fb-attrs__sel-key{font-family:Roboto Mono,monospace;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.fb-attrs__body{flex:1 1 0;overflow-y:auto;overflow-x:hidden;min-width:0}.fb-attrs__placeholder{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--gap-2);padding:32px;color:var(--md-sys-color-on-surface-variant);text-align:center}.fb-attrs__placeholder .msi{font-size:32px;color:var(--md-sys-color-outline)}.fb-attrs__placeholder .title{font-size:13px;font-weight:500;color:var(--md-sys-color-on-surface)}.fb-attrs__placeholder .hint{font-size:12px;max-width:220px;line-height:1.5}.fb-preview-card{max-width:760px;margin:0 auto;background:var(--md-sys-color-surface-container-lowest);border-radius:var(--r-lg);padding:32px;box-shadow:var(--elev-1)}.fb-preview-card__chip{display:inline-flex;align-items:center;gap:6px;padding:2px 10px;height:22px;border-radius:var(--r-pill);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);font-size:10px;font-weight:500;letter-spacing:.08em;text-transform:uppercase;margin-bottom:var(--gap-3)}.fb-preview-card__title{font-size:20px;font-weight:500;margin:0 0 var(--gap-4);color:var(--md-sys-color-on-surface)}.fb-preview-card__footer{display:flex;justify-content:flex-end;gap:var(--gap-2);margin-top:var(--gap-4);padding-top:var(--gap-4);border-top:1px solid var(--md-sys-color-outline-variant)}.fb-icon-picker{display:grid;grid-template-columns:repeat(6,1fr);gap:4px;margin-top:4px}.fb-icon-picker .fb-icon-picker__btn{height:28px;border-radius:var(--r-xs);border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest);color:var(--md-sys-color-on-surface-variant);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}.fb-icon-picker .fb-icon-picker__btn .msi{font-size:16px}.fb-icon-picker .fb-icon-picker__btn.is-active{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary)}.fb-icon-picker .fb-icon-picker__btn:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent)}.fb-color-swatches{display:flex;gap:var(--gap-2);margin-top:4px}.fb-color-swatches .fb-color-swatch{width:24px;height:24px;border-radius:50%;cursor:pointer;border:2px solid transparent}.fb-color-swatches .fb-color-swatch.is-active{border-color:var(--md-sys-color-on-surface)}.fb-color-swatches .fb-color-swatch.primary{background:var(--md-sys-color-primary)}.fb-color-swatches .fb-color-swatch.secondary{background:var(--md-sys-color-secondary)}.fb-color-swatches .fb-color-swatch.success{background:var(--md-sys-color-success)}.fb-color-swatches .fb-color-swatch.warning{background:var(--md-sys-color-warning)}.fb-color-swatches .fb-color-swatch.error{background:var(--md-sys-color-error)}.fb-children-list{display:flex;flex-direction:column;gap:4px}.fb-child-row{display:flex;align-items:center;gap:var(--gap-2);height:30px;padding:0 8px;border-radius:var(--r-xs);background:var(--md-sys-color-surface-container-lowest);border:1px solid var(--md-sys-color-outline-variant);font-size:12px}.fb-child-row .fb-child-row__icon{width:22px;height:22px;border-radius:var(--r-xs);background:var(--md-sys-color-primary-container);color:var(--md-sys-color-primary);display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.fb-child-row .fb-child-row__icon .msi{font-size:14px}.fb-child-row .fb-child-row__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fb-child-row .fb-child-row__key{font-family:Roboto Mono,monospace;font-size:10px;color:var(--md-sys-color-on-surface-variant)}.fb-child-row:hover{background:color-mix(in srgb,var(--md-sys-color-primary) 4%,transparent)}.fb-add-link{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--md-sys-color-primary);cursor:pointer;padding:4px 0;text-decoration:none}.fb-add-link .msi{font-size:14px}.fb-add-link:hover{text-decoration:underline}\n"] }]
6517
+ }], ctorParameters: () => [] });
6201
6518
 
6202
6519
  /* eslint-disable @angular-eslint/no-input-rename */
6203
6520
  /* eslint-disable @typescript-eslint/no-explicit-any */
@@ -6364,11 +6681,11 @@ class SdFeelExpression extends SdBaseSecureComponent {
6364
6681
  return attributes;
6365
6682
  };
6366
6683
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdFeelExpression, deps: [{ token: i0.ChangeDetectorRef }, { token: ExpressionFeelPipe }, { token: FormGenericService }], target: i0.ɵɵFactoryTarget.Component });
6367
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdFeelExpression, isStandalone: true, selector: "sd-feel-expression", inputs: { components: "components", _expression: ["expression", "_expression"], _model: ["model", "_model"] }, outputs: { expressionChange: "expressionChange", modelChange: "modelChange", sdChange: "sdChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], usesInheritance: true, ngImport: i0, template: "<a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{model || '--'}}</a>\r\n@if (expression) {\r\n<sd-modal title=\"Thi\u1EBFt l\u1EADp bi\u1EC3u th\u1EE9c\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button prefixIcon=\"calculate\" class=\"mr-4\" title=\"Nh\u00F3m \u0111i\u1EC1u ki\u1EC7n\" color=\"primary\" (click)=\"addCombinator(expression.conditions)\"></sd-button>\r\n <sd-button prefixIcon=\"add\" title=\"\u0110i\u1EC1u ki\u1EC7n\" color=\"primary\" (click)=\"addCondition(expression.conditions)\" type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv1 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv1 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"expression.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv1.type === 'condition') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv1.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv1.field!];\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv1.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\r\n @if(!!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL') {\r\n @if(fieldAttribute.type === 'string') {\r\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\r\n } @else if(fieldAttribute.type === 'number') {\r\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input-number>\r\n } @else if(fieldAttribute.type === 'boolean') {\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\r\n }@else if(fieldAttribute.type === 'values') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button\r\n class=\"ml-auto\"\r\n prefixIcon=\"delete\"\r\n tooltip=\"X\u00F3a\"\r\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n \r\n } @else if (conditionLv1.type === 'combinator') {\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button\r\n class=\"mr-4\"\r\n prefixIcon=\"delete\"\r\n tooltip=\"X\u00F3a\"\r\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n <sd-button prefixIcon=\"add\" title=\"\u0110i\u1EC1u ki\u1EC7n\" size=\"sm\" color=\"primary\" (click)=\"addCondition(conditionLv1.conditions)\" type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 2 -->\r\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv2 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv2 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"conditionLv1.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv2.type === 'condition') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv2.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv2.field!];\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv2.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\r\n @if(!!fieldAttribute?.type && conditionLv2.operator && conditionLv2.operator !== 'NULL' && conditionLv2.operator !== 'NOT_NULL') {\r\n @if(fieldAttribute.type === 'string') {\r\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input>\r\n } @else if(fieldAttribute.type === 'number') {\r\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input-number>\r\n } @else if(fieldAttribute.type === 'boolean') {\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\r\n }@else if(fieldAttribute.type === 'values') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button\r\n class=\"ml-auto\"\r\n prefixIcon=\"delete\"\r\n tooltip=\"X\u00F3a\"\r\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\r\n \r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"X\u00E1c nh\u1EADn\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n}", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6684
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.21", type: SdFeelExpression, isStandalone: true, selector: "sd-feel-expression", inputs: { components: "components", _expression: ["expression", "_expression"], _model: ["model", "_model"] }, outputs: { expressionChange: "expressionChange", modelChange: "modelChange", sdChange: "sdChange" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], usesInheritance: true, ngImport: i0, template: "<a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{model || '--'}}</a>\r\n@if (expression) {\r\n<sd-modal [title]=\"'core.component.form-builder.set-expression' | translate\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button prefixIcon=\"calculate\" class=\"mr-4\" [title]=\"'core.component.form-builder.condition-group' | translate\" color=\"primary\" (click)=\"addCombinator(expression.conditions)\"></sd-button>\r\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.condition' | translate\" color=\"primary\" (click)=\"addCondition(expression.conditions)\" type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv1 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv1 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"expression.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv1.type === 'condition') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv1.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv1.field!];\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv1.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\r\n @if(!!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL') {\r\n @if(fieldAttribute.type === 'string') {\r\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\r\n } @else if(fieldAttribute.type === 'number') {\r\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input-number>\r\n } @else if(fieldAttribute.type === 'boolean') {\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\r\n }@else if(fieldAttribute.type === 'values') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button\r\n class=\"ml-auto\"\r\n prefixIcon=\"delete\"\r\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n \r\n } @else if (conditionLv1.type === 'combinator') {\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button\r\n class=\"mr-4\"\r\n prefixIcon=\"delete\"\r\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.condition' | translate\" size=\"sm\" color=\"primary\" (click)=\"addCondition(conditionLv1.conditions)\" type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 2 -->\r\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv2 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv2 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"conditionLv1.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv2.type === 'condition') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv2.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv2.field!];\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv2.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\r\n @if(!!fieldAttribute?.type && conditionLv2.operator && conditionLv2.operator !== 'NULL' && conditionLv2.operator !== 'NOT_NULL') {\r\n @if(fieldAttribute.type === 'string') {\r\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input>\r\n } @else if(fieldAttribute.type === 'number') {\r\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input-number>\r\n } @else if(fieldAttribute.type === 'boolean') {\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\r\n }@else if(fieldAttribute.type === 'values') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button\r\n class=\"ml-auto\"\r\n prefixIcon=\"delete\"\r\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\r\n \r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n}", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"], dependencies: [{ kind: "component", type: SdInput$1, selector: "sd-input", inputs: ["autoId", "name", "appearance", "floatLabel", "size", "form", "label", "helperText", "placeholder", "type", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "minlength", "maxlength", "pattern", "patternErrorMessage", "validator", "inlineError", "hyperlink", "tooltip", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdInputNumber, selector: "sd-input-number", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "hideInlineError", "blurOnEnter", "required", "readonly", "disabled", "viewed", "type", "precision", "format", "min", "max", "validator", "inlineError", "hyperlink", "appearance", "floatLabel", "model"], outputs: ["modelChange", "sdChange", "sdFocus", "sdBlur", "keyupEnter", "sdFocusForceBlur"] }, { kind: "component", type: SdSelect$1, selector: "sd-select", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "cacheChecksum", "limit", "hyperlink", "minWidthPanel", "hideInlineError", "required", "disabled", "viewed", "multiple", "validator", "inlineError", "appearance", "floatLabel", "items", "model"], outputs: ["modelChange", "sdChange", "sdSelection"] }, { kind: "component", type: SdAutocomplete$1, selector: "sd-autocomplete", inputs: ["autoId", "name", "size", "form", "label", "helperText", "placeholder", "valueField", "displayField", "disabledField", "limit", "cacheChecksum", "hyperlink", "items", "hideInlineError", "addable", "required", "disabled", "viewed", "validator", "inlineError", "appearance", "model"], outputs: ["modelChange", "sdChange", "sdSelection", "sdAdd"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "component", type: SdModal, selector: "sd-modal", inputs: ["autoId", "title", "color", "width", "height", "view", "modalClass", "lazyLoadContent", "hideClose", "disableBackdropClose"], outputs: ["sdClosed"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6368
6685
  }
6369
6686
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdFeelExpression, decorators: [{
6370
6687
  type: Component,
6371
- args: [{ selector: 'sd-feel-expression', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdInput$1, SdInputNumber, SdSelect$1, SdAutocomplete$1, SdButton, SdSelect$1, SdModal], template: "<a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{model || '--'}}</a>\r\n@if (expression) {\r\n<sd-modal title=\"Thi\u1EBFt l\u1EADp bi\u1EC3u th\u1EE9c\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button prefixIcon=\"calculate\" class=\"mr-4\" title=\"Nh\u00F3m \u0111i\u1EC1u ki\u1EC7n\" color=\"primary\" (click)=\"addCombinator(expression.conditions)\"></sd-button>\r\n <sd-button prefixIcon=\"add\" title=\"\u0110i\u1EC1u ki\u1EC7n\" color=\"primary\" (click)=\"addCondition(expression.conditions)\" type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv1 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv1 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"expression.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv1.type === 'condition') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv1.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv1.field!];\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv1.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\r\n @if(!!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL') {\r\n @if(fieldAttribute.type === 'string') {\r\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\r\n } @else if(fieldAttribute.type === 'number') {\r\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input-number>\r\n } @else if(fieldAttribute.type === 'boolean') {\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\r\n }@else if(fieldAttribute.type === 'values') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button\r\n class=\"ml-auto\"\r\n prefixIcon=\"delete\"\r\n tooltip=\"X\u00F3a\"\r\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n \r\n } @else if (conditionLv1.type === 'combinator') {\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button\r\n class=\"mr-4\"\r\n prefixIcon=\"delete\"\r\n tooltip=\"X\u00F3a\"\r\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n <sd-button prefixIcon=\"add\" title=\"\u0110i\u1EC1u ki\u1EC7n\" size=\"sm\" color=\"primary\" (click)=\"addCondition(conditionLv1.conditions)\" type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 2 -->\r\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv2 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv2 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"conditionLv1.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv2.type === 'condition') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv2.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv2.field!];\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv2.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\r\n @if(!!fieldAttribute?.type && conditionLv2.operator && conditionLv2.operator !== 'NULL' && conditionLv2.operator !== 'NOT_NULL') {\r\n @if(fieldAttribute.type === 'string') {\r\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input>\r\n } @else if(fieldAttribute.type === 'number') {\r\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input-number>\r\n } @else if(fieldAttribute.type === 'boolean') {\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\r\n }@else if(fieldAttribute.type === 'values') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button\r\n class=\"ml-auto\"\r\n prefixIcon=\"delete\"\r\n tooltip=\"X\u00F3a\"\r\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\r\n \r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" title=\"X\u00E1c nh\u1EADn\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n}", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
6688
+ args: [{ selector: 'sd-feel-expression', changeDetection: ChangeDetectionStrategy.OnPush, imports: [SdInput$1, SdInputNumber, SdSelect$1, SdAutocomplete$1, SdButton, SdSelect$1, SdModal, TranslatePipe], template: "<a class=\"T12R\" href=\"javascript:;\" (click)=\"edit()\">{{model || '--'}}</a>\r\n@if (expression) {\r\n<sd-modal [title]=\"'core.component.form-builder.set-expression' | translate\">\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button prefixIcon=\"calculate\" class=\"mr-4\" [title]=\"'core.component.form-builder.condition-group' | translate\" color=\"primary\" (click)=\"addCombinator(expression.conditions)\"></sd-button>\r\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.condition' | translate\" color=\"primary\" (click)=\"addCondition(expression.conditions)\" type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 1 -->\r\n @for (conditionLv1 of expression.conditions; track conditionLv1.key; let idxLv1 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv1 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv1 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"expression.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv1.type === 'condition') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv1.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv1.field!];\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv1.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\r\n @if(!!fieldAttribute?.type && conditionLv1.operator && conditionLv1.operator !== 'NULL' && conditionLv1.operator !== 'NOT_NULL') {\r\n @if(fieldAttribute.type === 'string') {\r\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input>\r\n } @else if(fieldAttribute.type === 'number') {\r\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" required hideInlineError></sd-input-number>\r\n } @else if(fieldAttribute.type === 'boolean') {\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\r\n }@else if(fieldAttribute.type === 'values') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv1.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button\r\n class=\"ml-auto\"\r\n prefixIcon=\"delete\"\r\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n \r\n } @else if (conditionLv1.type === 'combinator') {\r\n <div class=\"c-builder\">\r\n <div class=\"d-flex justify-content-end\">\r\n <sd-button\r\n class=\"mr-4\"\r\n prefixIcon=\"delete\"\r\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"remove(expression.conditions, idxLv1)\"></sd-button>\r\n <sd-button prefixIcon=\"add\" [title]=\"'core.component.form-builder.condition' | translate\" size=\"sm\" color=\"primary\" (click)=\"addCondition(conditionLv1.conditions)\" type=\"fill\"></sd-button>\r\n </div>\r\n <!-- C\u1EA5p 2 -->\r\n @for (conditionLv2 of conditionLv1.conditions; track conditionLv2.key; let idxLv2 = $index) {\r\n <div class=\"d-flex align-items-end py-8\" style=\"gap: 8px;\">\r\n <div class=\"c-condition\">\r\n <!-- D\u00F2ng 1 ch\u1EC9 hi\u1EC7n WHERE -->\r\n @if (idxLv2 === 0) {\r\n <div class=\"c-where\">WHERE</div>\r\n }\r\n <!-- D\u00F2ng 2 hi\u1EC3n th\u1ECB combinator -->\r\n @if (idxLv2 === 1) {\r\n <div class=\"c-select\">\r\n <sd-select\r\n size=\"sm\"\r\n [(model)]=\"conditionLv1.combinator\"\r\n [items]=\"[\r\n { value: '&&', display: 'AND' },\r\n { value: '||', display: 'OR' }\r\n ]\"\r\n valueField=\"value\"\r\n displayField=\"display\"\r\n required\r\n hideInlineError=\"\"></sd-select>\r\n </div>\r\n }\r\n </div>\r\n @if (conditionLv2.type === 'condition') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"width: 200px;\" [(model)]=\"conditionLv2.field\" [items]=\"attributes\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n @let fieldAttribute = attribute[conditionLv2.field!];\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"width: 100px;\" [(model)]=\"conditionLv2.operator\" [items]=\"attributeOperators[fieldAttribute?.type || 'string']\" valueField=\"value\" displayField=\"display\" [disabled]=\"!fieldAttribute?.type\" required hideInlineError></sd-select>\r\n @if(!!fieldAttribute?.type && conditionLv2.operator && conditionLv2.operator !== 'NULL' && conditionLv2.operator !== 'NOT_NULL') {\r\n @if(fieldAttribute.type === 'string') {\r\n <sd-input size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input>\r\n } @else if(fieldAttribute.type === 'number') {\r\n <sd-input-number size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" required hideInlineError></sd-input-number>\r\n } @else if(fieldAttribute.type === 'boolean') {\r\n <sd-select size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"[{value: true, display: fieldAttribute.displayOnTrue}, {value: false, display: fieldAttribute.displayOnFalse}]\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-select>\r\n }@else if(fieldAttribute.type === 'values') {\r\n <sd-autocomplete size=\"sm\" [form]=\"form\" style=\"flex:1\" [(model)]=\"conditionLv2.value\" [items]=\"fieldAttribute.values\" valueField=\"value\" displayField=\"display\" required hideInlineError></sd-autocomplete>\r\n }\r\n }\r\n <sd-button\r\n class=\"ml-auto\"\r\n prefixIcon=\"delete\"\r\n [tooltip]=\"'core.component.form-builder.delete' | translate\"\r\n (click)=\"remove(conditionLv1.conditions, idxLv1)\"></sd-button>\r\n \r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n </div>\r\n <ng-container sdFooter>\r\n <sd-button prefixIcon=\"save\" [title]=\"'core.component.form-builder.confirm' | translate\" (click)=\"onAccept()\" color=\"primary\" type=\"fill\"></sd-button>\r\n </ng-container>\r\n</sd-modal>\r\n}", styles: [".c-builder{padding:8px;width:100%;border:1px solid #e6e6e6;border-radius:4px}.c-builder .c-condition{width:80px}.c-builder .c-condition .c-where{width:80px;border:1px solid #e6e6e6;background-color:#f2f2f2;color:#757575;border-radius:4px;padding:4px;text-align:center}.c-builder .c-condition .c-select{margin-left:10px;width:70px}\n"] }]
6372
6689
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: ExpressionFeelPipe }, { type: FormGenericService }], propDecorators: { modal: [{
6373
6690
  type: ViewChild,
6374
6691
  args: [SdModal]
@@ -6393,5 +6710,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
6393
6710
  * Generated bundle index. Do not edit.
6394
6711
  */
6395
6712
 
6396
- export { AttributeOperators, DayInfoPreviouses, DayInfoTypes, EvaluateExpression, ExpressionToJavascriptExpression, FormBuilderComponents, GenerateId, GenerateKey, GetAttributes, GetComponentAttributes, GetDatetimeValue, GetVariableAttributes, Operators, SD_FORM_GENERIC_CONFIGURATION, SdFeelExpression, SdFormBuilder, SdFormRender, SdFormRenderService, SdFormatComponent, TableColumnTypes, TemplateToCondition };
6713
+ export { AttributeOperators, COMPONENT_ICONS, DayInfoPreviouses, DayInfoTypes, EvaluateExpression, ExpressionToJavascriptExpression, FormBuilderComponents, GenerateId, GenerateKey, GetAttributes, GetComponentAttributes, GetDatetimeValue, GetVariableAttributes, Operators, SD_FORM_GENERIC_CONFIGURATION, SdFeelExpression, SdFormBuilder, SdFormRender, SdFormRenderService, SdFormatComponent, TableColumnTypes, TemplateToCondition };
6397
6714
  //# sourceMappingURL=sd-angular-core-components-form-generic.mjs.map