@sdcorejs/angular 21.1.3 → 21.1.4

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 (168) hide show
  1. package/README.md +17 -14
  2. package/fesm2022/sdcorejs-angular-components-anchor.mjs +14 -14
  3. package/fesm2022/sdcorejs-angular-components-anchor.mjs.map +1 -1
  4. package/fesm2022/sdcorejs-angular-components-audit-diff.mjs +332 -0
  5. package/fesm2022/sdcorejs-angular-components-audit-diff.mjs.map +1 -0
  6. package/fesm2022/sdcorejs-angular-components-badge.mjs +1 -0
  7. package/fesm2022/sdcorejs-angular-components-badge.mjs.map +1 -1
  8. package/fesm2022/sdcorejs-angular-components-breadcrumb.mjs +121 -0
  9. package/fesm2022/sdcorejs-angular-components-breadcrumb.mjs.map +1 -0
  10. package/fesm2022/sdcorejs-angular-components-data-state.mjs +68 -0
  11. package/fesm2022/sdcorejs-angular-components-data-state.mjs.map +1 -0
  12. package/fesm2022/sdcorejs-angular-components-document-builder.mjs +18 -23
  13. package/fesm2022/sdcorejs-angular-components-document-builder.mjs.map +1 -1
  14. package/fesm2022/sdcorejs-angular-components-editor.mjs +6 -4
  15. package/fesm2022/sdcorejs-angular-components-editor.mjs.map +1 -1
  16. package/fesm2022/sdcorejs-angular-components-form-generic.mjs +495 -838
  17. package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
  18. package/fesm2022/sdcorejs-angular-components-import-excel.mjs +24 -34
  19. package/fesm2022/sdcorejs-angular-components-import-excel.mjs.map +1 -1
  20. package/fesm2022/sdcorejs-angular-components-job-progress.mjs +97 -0
  21. package/fesm2022/sdcorejs-angular-components-job-progress.mjs.map +1 -0
  22. package/fesm2022/sdcorejs-angular-components-mini-editor.mjs +10 -20
  23. package/fesm2022/sdcorejs-angular-components-mini-editor.mjs.map +1 -1
  24. package/fesm2022/sdcorejs-angular-components-modal.mjs +61 -4
  25. package/fesm2022/sdcorejs-angular-components-modal.mjs.map +1 -1
  26. package/fesm2022/sdcorejs-angular-components-preview.mjs +1438 -218
  27. package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
  28. package/fesm2022/sdcorejs-angular-components-query-bar.mjs +4 -4
  29. package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
  30. package/fesm2022/sdcorejs-angular-components-query-builder.mjs +1 -1
  31. package/fesm2022/sdcorejs-angular-components-query-builder.mjs.map +1 -1
  32. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +39 -2
  33. package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
  34. package/fesm2022/sdcorejs-angular-components-tab-router.mjs +16 -22
  35. package/fesm2022/sdcorejs-angular-components-tab-router.mjs.map +1 -1
  36. package/fesm2022/sdcorejs-angular-components-tab.mjs +48 -4
  37. package/fesm2022/sdcorejs-angular-components-tab.mjs.map +1 -1
  38. package/fesm2022/sdcorejs-angular-components-table.mjs +96 -63
  39. package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
  40. package/fesm2022/sdcorejs-angular-components-tree.mjs +186 -17
  41. package/fesm2022/sdcorejs-angular-components-tree.mjs.map +1 -1
  42. package/fesm2022/sdcorejs-angular-components-upload-file.mjs +15 -22
  43. package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
  44. package/fesm2022/sdcorejs-angular-components.mjs +4 -0
  45. package/fesm2022/sdcorejs-angular-components.mjs.map +1 -1
  46. package/fesm2022/sdcorejs-angular-directives.mjs +29 -41
  47. package/fesm2022/sdcorejs-angular-directives.mjs.map +1 -1
  48. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +7 -7
  49. package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
  50. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs +20 -71
  51. package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
  52. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +6 -3
  53. package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
  54. package/fesm2022/sdcorejs-angular-forms-chip.mjs +6 -3
  55. package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
  56. package/fesm2022/sdcorejs-angular-forms-date-range.mjs +16 -13
  57. package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
  58. package/fesm2022/sdcorejs-angular-forms-date.mjs +42 -65
  59. package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
  60. package/fesm2022/sdcorejs-angular-forms-datetime.mjs +51 -66
  61. package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
  62. package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs +384 -0
  63. package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs.map +1 -0
  64. package/fesm2022/sdcorejs-angular-forms-input-color.mjs +1 -1
  65. package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
  66. package/fesm2022/sdcorejs-angular-forms-input-number.mjs +7 -5
  67. package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
  68. package/fesm2022/sdcorejs-angular-forms-input.mjs +290 -56
  69. package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
  70. package/fesm2022/sdcorejs-angular-forms-models.mjs +155 -2
  71. package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
  72. package/fesm2022/sdcorejs-angular-forms-radio.mjs +44 -66
  73. package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
  74. package/fesm2022/sdcorejs-angular-forms-select.mjs +6 -20
  75. package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
  76. package/fesm2022/sdcorejs-angular-forms-switch.mjs +19 -64
  77. package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
  78. package/fesm2022/sdcorejs-angular-forms-textarea.mjs +6 -5
  79. package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
  80. package/fesm2022/sdcorejs-angular-forms-time-range.mjs +277 -0
  81. package/fesm2022/sdcorejs-angular-forms-time-range.mjs.map +1 -0
  82. package/fesm2022/sdcorejs-angular-forms-time.mjs +307 -0
  83. package/fesm2022/sdcorejs-angular-forms-time.mjs.map +1 -0
  84. package/fesm2022/sdcorejs-angular-forms-tree-select.mjs +210 -0
  85. package/fesm2022/sdcorejs-angular-forms-tree-select.mjs.map +1 -0
  86. package/fesm2022/sdcorejs-angular-forms.mjs +73 -4
  87. package/fesm2022/sdcorejs-angular-forms.mjs.map +1 -1
  88. package/fesm2022/sdcorejs-angular-i18n.mjs +355 -10
  89. package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
  90. package/fesm2022/sdcorejs-angular-interceptors.mjs +12 -17
  91. package/fesm2022/sdcorejs-angular-interceptors.mjs.map +1 -1
  92. package/fesm2022/sdcorejs-angular-modules-layout.mjs +861 -80
  93. package/fesm2022/sdcorejs-angular-modules-layout.mjs.map +1 -1
  94. package/fesm2022/sdcorejs-angular-pipes.mjs +5 -7
  95. package/fesm2022/sdcorejs-angular-pipes.mjs.map +1 -1
  96. package/fesm2022/sdcorejs-angular-services-api.mjs +407 -137
  97. package/fesm2022/sdcorejs-angular-services-api.mjs.map +1 -1
  98. package/fesm2022/sdcorejs-angular-services-cache.mjs +515 -105
  99. package/fesm2022/sdcorejs-angular-services-cache.mjs.map +1 -1
  100. package/fesm2022/sdcorejs-angular-services-confirm.mjs +5 -7
  101. package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
  102. package/fesm2022/sdcorejs-angular-services-docx.mjs +7 -10
  103. package/fesm2022/sdcorejs-angular-services-docx.mjs.map +1 -1
  104. package/fesm2022/sdcorejs-angular-services-loading.mjs +339 -74
  105. package/fesm2022/sdcorejs-angular-services-loading.mjs.map +1 -1
  106. package/fesm2022/sdcorejs-angular-services-notify.mjs +7 -10
  107. package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
  108. package/fesm2022/sdcorejs-angular-services-persistence.mjs +899 -0
  109. package/fesm2022/sdcorejs-angular-services-persistence.mjs.map +1 -0
  110. package/fesm2022/sdcorejs-angular-services-storage.mjs +324 -122
  111. package/fesm2022/sdcorejs-angular-services-storage.mjs.map +1 -1
  112. package/fesm2022/sdcorejs-angular-services-task.mjs +389 -0
  113. package/fesm2022/sdcorejs-angular-services-task.mjs.map +1 -0
  114. package/fesm2022/sdcorejs-angular-services-unsaved-changes.mjs +255 -0
  115. package/fesm2022/sdcorejs-angular-services-unsaved-changes.mjs.map +1 -0
  116. package/fesm2022/sdcorejs-angular-services-viewport.mjs +76 -0
  117. package/fesm2022/sdcorejs-angular-services-viewport.mjs.map +1 -0
  118. package/fesm2022/sdcorejs-angular-services.mjs +4 -0
  119. package/fesm2022/sdcorejs-angular-services.mjs.map +1 -1
  120. package/package.json +49 -1
  121. package/types/sdcorejs-angular-components-audit-diff.d.ts +74 -0
  122. package/types/sdcorejs-angular-components-badge.d.ts +1 -1
  123. package/types/sdcorejs-angular-components-breadcrumb.d.ts +53 -0
  124. package/types/sdcorejs-angular-components-data-state.d.ts +44 -0
  125. package/types/sdcorejs-angular-components-document-builder.d.ts +5 -5
  126. package/types/sdcorejs-angular-components-form-generic.d.ts +67 -104
  127. package/types/sdcorejs-angular-components-import-excel.d.ts +4 -14
  128. package/types/sdcorejs-angular-components-job-progress.d.ts +38 -0
  129. package/types/sdcorejs-angular-components-mini-editor.d.ts +9 -9
  130. package/types/sdcorejs-angular-components-modal.d.ts +7 -1
  131. package/types/sdcorejs-angular-components-preview.d.ts +181 -28
  132. package/types/sdcorejs-angular-components-side-drawer.d.ts +7 -1
  133. package/types/sdcorejs-angular-components-tab.d.ts +9 -2
  134. package/types/sdcorejs-angular-components-table.d.ts +8 -7
  135. package/types/sdcorejs-angular-components-tree.d.ts +24 -2
  136. package/types/sdcorejs-angular-components-upload-file.d.ts +5 -4
  137. package/types/sdcorejs-angular-components.d.ts +4 -0
  138. package/types/sdcorejs-angular-directives.d.ts +10 -8
  139. package/types/sdcorejs-angular-forms-autocomplete.d.ts +3 -4
  140. package/types/sdcorejs-angular-forms-checkbox.d.ts +4 -8
  141. package/types/sdcorejs-angular-forms-date-range.d.ts +6 -7
  142. package/types/sdcorejs-angular-forms-date.d.ts +2 -2
  143. package/types/sdcorejs-angular-forms-datetime.d.ts +2 -2
  144. package/types/sdcorejs-angular-forms-entity-picker.d.ts +128 -0
  145. package/types/sdcorejs-angular-forms-input-number.d.ts +1 -1
  146. package/types/sdcorejs-angular-forms-input.d.ts +74 -11
  147. package/types/sdcorejs-angular-forms-models.d.ts +86 -3
  148. package/types/sdcorejs-angular-forms-radio.d.ts +12 -8
  149. package/types/sdcorejs-angular-forms-switch.d.ts +4 -7
  150. package/types/sdcorejs-angular-forms-time-range.d.ts +98 -0
  151. package/types/sdcorejs-angular-forms-time.d.ts +117 -0
  152. package/types/sdcorejs-angular-forms-tree-select.d.ts +76 -0
  153. package/types/sdcorejs-angular-forms.d.ts +15 -5
  154. package/types/sdcorejs-angular-i18n.d.ts +68 -2
  155. package/types/sdcorejs-angular-interceptors.d.ts +5 -6
  156. package/types/sdcorejs-angular-modules-layout.d.ts +288 -15
  157. package/types/sdcorejs-angular-pipes.d.ts +2 -2
  158. package/types/sdcorejs-angular-services-api.d.ts +68 -24
  159. package/types/sdcorejs-angular-services-cache.d.ts +52 -16
  160. package/types/sdcorejs-angular-services-confirm.d.ts +3 -2
  161. package/types/sdcorejs-angular-services-docx.d.ts +2 -3
  162. package/types/sdcorejs-angular-services-loading.d.ts +16 -8
  163. package/types/sdcorejs-angular-services-persistence.d.ts +159 -0
  164. package/types/sdcorejs-angular-services-storage.d.ts +26 -8
  165. package/types/sdcorejs-angular-services-task.d.ts +104 -0
  166. package/types/sdcorejs-angular-services-unsaved-changes.d.ts +83 -0
  167. package/types/sdcorejs-angular-services-viewport.d.ts +42 -0
  168. package/types/sdcorejs-angular-services.d.ts +4 -0
@@ -2,9 +2,9 @@ import { Utilities } from '@sdcorejs/utils/fns';
2
2
  import * as i1 from '@angular/common';
3
3
  import { CommonModule } from '@angular/common';
4
4
  import * as i0 from '@angular/core';
5
- import { inject, ChangeDetectorRef, input, booleanAttribute, model, contentChild, output, computed, effect, ChangeDetectionStrategy, Component } from '@angular/core';
5
+ import { inject, ChangeDetectorRef, input, booleanAttribute, model, contentChild, output, computed, ChangeDetectionStrategy, Component } from '@angular/core';
6
6
  import * as i2 from '@angular/forms';
7
- import { NgForm, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
7
+ import { Validators, ReactiveFormsModule } from '@angular/forms';
8
8
  import * as i3 from '@angular/material/form-field';
9
9
  import { MatFormFieldModule } from '@angular/material/form-field';
10
10
  import * as i4 from '@angular/material/radio';
@@ -12,7 +12,7 @@ import { MatRadioModule } from '@angular/material/radio';
12
12
  import { MatTooltipModule } from '@angular/material/tooltip';
13
13
  import { Subscription } from 'rxjs';
14
14
  import { SdSuffixDefDirective, SdLabelDefDirective, SdViewDefDirective } from '@sdcorejs/angular/forms/directives';
15
- import { SdFormControl, sdViewedTransform, sdViewedInline, sdFormControlState, SdInlineErrorValidator } from '@sdcorejs/angular/forms/models';
15
+ import { SdFormControl, sdViewedTransform, sdViewedInline, sdFormControlState, ɵsdFormControlConnector as _sdFormControlConnector, SdInlineErrorValidator } from '@sdcorejs/angular/forms/models';
16
16
  import { sdIsEmpty, sdSerializeDataValue } from '@sdcorejs/angular/utilities/data-state';
17
17
  import { TranslatePipe } from '@sdcorejs/angular/i18n';
18
18
  import { SdEmptyPipe } from '@sdcorejs/angular/pipes';
@@ -22,26 +22,16 @@ import { SdHrefDirective } from '@sdcorejs/angular/directives';
22
22
  class SdRadio {
23
23
  #ref = inject(ChangeDetectorRef);
24
24
  id = `I${Utilities.generateUuid()}`;
25
- #name = Utilities.generateUuid();
25
+ labelId = `${this.id}-label`;
26
+ errorId = `${this.id}-error`;
27
+ #defaultName = Utilities.generateUuid();
26
28
  formControl = new SdFormControl();
27
29
  #subscription = new Subscription();
28
30
  // Inputs — accept null|undefined at boundary, transform to canonical
29
31
  autoIdInput = input(undefined, { ...(ngDevMode ? { debugName: "autoIdInput" } : /* istanbul ignore next */ {}), alias: 'autoId',
30
32
  transform: (v) => v ?? undefined });
31
33
  name = input(undefined, { ...(ngDevMode ? { debugName: "name" } : /* istanbul ignore next */ {}), transform: (v) => v ?? undefined });
32
- // why: parent may bind NgForm (template-driven), FormGroup (reactive), or a wrapper with `.form`.
33
- // Transform once at the input boundary so the rest of the component only deals with FormGroup.
34
- form = input(undefined, { ...(ngDevMode ? { debugName: "form" } : /* istanbul ignore next */ {}), transform: (val) => {
35
- if (!val)
36
- return undefined;
37
- if (val instanceof NgForm)
38
- return val.form;
39
- if (val instanceof FormGroup)
40
- return val;
41
- if (val?.form instanceof FormGroup)
42
- return val.form;
43
- return undefined;
44
- } });
34
+ form = input(undefined, ...(ngDevMode ? [{ debugName: "form" }] : /* istanbul ignore next */ []));
45
35
  label = input(undefined, { ...(ngDevMode ? { debugName: "label" } : /* istanbul ignore next */ {}), transform: (v) => v ?? undefined });
46
36
  placeholder = input(undefined, { ...(ngDevMode ? { debugName: "placeholder" } : /* istanbul ignore next */ {}), transform: (v) => v ?? undefined });
47
37
  display = input('row', { ...(ngDevMode ? { debugName: "display" } : /* istanbul ignore next */ {}), transform: (v) => v || 'row' });
@@ -79,6 +69,19 @@ class SdRadio {
79
69
  dataEmpty = computed(() => (sdIsEmpty(this.#state().value) ? 'true' : 'false'), ...(ngDevMode ? [{ debugName: "dataEmpty" }] : /* istanbul ignore next */ []));
80
70
  dataValue = computed(() => sdSerializeDataValue(this.#state().value), ...(ngDevMode ? [{ debugName: "dataValue" }] : /* istanbul ignore next */ []));
81
71
  dataRequired = computed(() => (this.required() ? 'true' : 'false'), ...(ngDevMode ? [{ debugName: "dataRequired" }] : /* istanbul ignore next */ []));
72
+ visibleError = computed(() => {
73
+ if (!this.#state().touched)
74
+ return undefined;
75
+ if (this.formControl.hasError('required'))
76
+ return 'required';
77
+ if (this.formControl.hasError('inlineError'))
78
+ return 'inlineError';
79
+ return undefined;
80
+ }, ...(ngDevMode ? [{ debugName: "visibleError" }] : /* istanbul ignore next */ []));
81
+ ariaLabelledBy = computed(() => (this.sdLabelDef()?.templateRef || this.label() ? this.labelId : undefined), ...(ngDevMode ? [{ debugName: "ariaLabelledBy" }] : /* istanbul ignore next */ []));
82
+ ariaLabel = computed(() => (this.ariaLabelledBy() ? undefined : this.placeholder() || undefined), ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
83
+ ariaDescribedBy = computed(() => (this.visibleError() ? this.errorId : undefined), ...(ngDevMode ? [{ debugName: "ariaDescribedBy" }] : /* istanbul ignore next */ []));
84
+ ariaInvalid = computed(() => (this.#state().invalid ? 'true' : 'false'), ...(ngDevMode ? [{ debugName: "ariaInvalid" }] : /* istanbul ignore next */ []));
82
85
  viewedText = computed(() => {
83
86
  const items = this.items();
84
87
  const vField = this.valueField();
@@ -87,68 +90,43 @@ class SdRadio {
87
90
  const match = items.find(e => this.formControl?.value?.toString() === e?.[vField]?.toString());
88
91
  return match?.[dField] ?? '';
89
92
  }, ...(ngDevMode ? [{ debugName: "viewedText" }] : /* istanbul ignore next */ []));
90
- constructor() {
91
- effect(() => {
92
- const val = this.name();
93
- if (val)
94
- this.#name = val;
95
- });
96
- effect(() => {
97
- const value = this.model();
98
- if (value !== this.formControl.value) {
99
- this.formControl.setValue(value, { emitEvent: false });
100
- }
101
- });
102
- effect(() => {
103
- if (this.disabled())
104
- this.formControl.disable();
105
- else
106
- this.formControl.enable();
107
- });
108
- effect(() => {
109
- this.required();
110
- this.inlineError();
111
- this.#updateValidator();
112
- });
113
- }
114
- ngOnInit() {
115
- this.#subscription.add(this.formControl.sdChanges.subscribe(() => {
116
- this.#ref.markForCheck();
117
- }));
118
- }
119
- ngAfterViewInit() {
120
- this.#subscription.add(this.formControl.valueChanges.subscribe(value => {
93
+ #formConnector = _sdFormControlConnector({
94
+ form: this.form,
95
+ name: computed(() => this.name() || this.#defaultName),
96
+ control: computed(() => this.formControl),
97
+ model: this.model,
98
+ writeModel: value => {
121
99
  const vField = this.valueField();
122
100
  this.model.set(value);
123
101
  this.sdChange.emit(value);
124
102
  this.sdSelection.emit({
125
103
  value,
126
- item: this.items().find(e => value?.toString() === e?.[vField]?.toString()),
104
+ item: this.items().find(item => value?.toString() === item?.[vField]?.toString()),
127
105
  });
106
+ },
107
+ validators: computed(() => {
108
+ const validators = [];
109
+ if (this.required())
110
+ validators.push(Validators.required);
111
+ if (this.inlineError())
112
+ validators.push(SdInlineErrorValidator);
113
+ return validators;
114
+ }),
115
+ disabled: this.disabled,
116
+ });
117
+ ngOnInit() {
118
+ this.#subscription.add(this.formControl.sdChanges.subscribe(() => {
119
+ this.#ref.markForCheck();
128
120
  }));
129
- this.form()?.addControl(this.#name, this.formControl);
130
121
  }
131
122
  ngOnDestroy() {
132
123
  this.#subscription.unsubscribe();
133
- this.form()?.removeControl(this.#name);
134
124
  }
135
- #updateValidator = () => {
136
- this.formControl.clearValidators();
137
- const validators = [];
138
- if (this.required()) {
139
- validators.push(Validators.required);
140
- }
141
- if (this.inlineError()) {
142
- validators.push(SdInlineErrorValidator);
143
- }
144
- this.formControl.setValidators(validators);
145
- this.formControl.updateValueAndValidity();
146
- };
147
125
  reValidate = () => {
148
126
  this.formControl.updateValueAndValidity({ emitEvent: true });
149
127
  };
150
128
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SdRadio, deps: [], target: i0.ɵɵFactoryTarget.Component });
151
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SdRadio, isStandalone: true, selector: "sd-radio", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: true, transformFunction: null }, displayField: { classPropertyName: "displayField", publicName: "displayField", isSignal: true, isRequired: true, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, inlineError: { classPropertyName: "inlineError", publicName: "inlineError", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, viewed: { classPropertyName: "viewed", publicName: "viewed", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, hyperlink: { classPropertyName: "hyperlink", publicName: "hyperlink", isSignal: true, isRequired: false, transformFunction: null }, model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { model: "modelChange", sdChange: "sdChange", sdSelection: "sdSelection" }, host: { properties: { "class.sd-c-primary": "color() === 'primary'", "class.sd-c-secondary": "color() === 'secondary'", "class.sd-c-info": "color() === 'info'", "class.sd-c-success": "color() === 'success'", "class.sd-c-warning": "color() === 'warning'", "class.sd-c-error": "color() === 'error'" } }, queries: [{ propertyName: "sdSuffixDef", first: true, predicate: SdSuffixDefDirective, descendants: true, isSignal: true }, { propertyName: "sdLabelDef", first: true, predicate: SdLabelDefDirective, descendants: true, isSignal: true }, { propertyName: "sdViewDef", first: true, predicate: SdViewDefDirective, descendants: true, isSignal: true }], ngImport: i0, template: "@let _sdLabelDef = sdLabelDef();\n@let _label = label();\n@let _display = display();\n@let _valueField = valueField();\n@let _hyperlink = hyperlink();\n\n@if (isViewed()) {\n @if (_sdLabelDef?.templateRef) {\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\n } @else if (_label) {\n <div class=\"T14R text-secondary\">{{ _label }}</div>\n }\n @if (_hyperlink) {\n <!-- N\u1EBFu c\u00F3 hyperlink th\u00EC d\u00F9ng th\u1EBB a -->\n <a [sdHref]=\"_hyperlink!\">{{ viewedText() }}</a>\n } @else {\n <!-- Ngo\u00E0i ra d\u00F9ng th\u1EBB m\u1EB7c \u0111\u1ECBnh -->\n <div class=\"T14M\">{{ viewedText() | sdEmpty }}</div>\n }\n} @else {\n <section [ngClass]=\"{ 'c-section': _display === 'row' }\">\n @if (_sdLabelDef?.templateRef) {\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\n } @else if (_label) {\n <sd-label [label]=\"_label!\" [required]=\"required()\"></sd-label>\n }\n <mat-radio-group\n [class.c-radio-group-column]=\"_display === 'column'\"\n [class.c-radio-group-row]=\"_display === 'row'\"\n [formControl]=\"formControl\"\n [attr.data-autoId]=\"autoId()\"\n [attr.data-disabled]=\"dataDisabled()\"\n [attr.data-empty]=\"dataEmpty()\"\n [attr.data-value]=\"dataValue()\"\n [attr.data-required]=\"dataRequired()\">\n @for (item of normalizedItems(); track item[valueField()]) {\n <mat-radio-button [class.m-0]=\"_display === 'column'\" [class.mr-16]=\"_display === 'row'\" [value]=\"item[_valueField]\">\n {{ item[displayField()] }}\n </mat-radio-button>\n }\n </mat-radio-group>\n\n @if (formControl.errors?.['required'] && formControl.touched) {\n <mat-error>\n {{ 'core.form.radio.required' | translate }}\n </mat-error>\n } @else if (formControl.errors?.['inlineError'] && formControl.touched) {\n <mat-error>\n {{ inlineError() }}\n </mat-error>\n }\n </section>\n}\n", styles: [":host{height:100%;display:flex;flex-direction:column}:host ::ng-deep label.mdc-label{margin-bottom:0}:host{--sd-c: var(--sd-primary)}:host(.sd-c-secondary){--sd-c: var(--sd-secondary)}:host(.sd-c-info){--sd-c: var(--sd-info)}:host(.sd-c-success){--sd-c: var(--sd-success)}:host(.sd-c-warning){--sd-c: var(--sd-warning)}:host(.sd-c-error){--sd-c: var(--sd-error)}:host ::ng-deep .mat-mdc-radio-button,:host ::ng-deep .mat-mdc-radio-group,:host ::ng-deep .mdc-radio{--mdc-radio-selected-icon-color: var(--sd-c) !important;--mdc-radio-selected-focus-icon-color: var(--sd-c) !important;--mdc-radio-selected-hover-icon-color: var(--sd-c) !important;--mdc-radio-selected-pressed-icon-color: var(--sd-c) !important;--mdc-radio-selected-focus-state-layer-color: var(--sd-c) !important;--mdc-radio-selected-hover-state-layer-color: var(--sd-c) !important;--mat-radio-selected-icon-color: var(--sd-c) !important;--mat-radio-selected-focus-icon-color: var(--sd-c) !important;--mat-radio-selected-hover-icon-color: var(--sd-c) !important;--mat-radio-selected-pressed-icon-color: var(--sd-c) !important;--mat-radio-checked-ripple-color: var(--sd-c) !important;--mat-radio-checked-state-layer-color: var(--sd-c) !important}.c-section{align-content:center;align-items:center}.c-radio-group-column{flex:1;display:flex;flex-direction:column;align-items:flex-start}.c-radio-group-row{flex:1;display:flex;flex-direction:row;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i4.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i4.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "component", type: SdLabel, selector: "sd-label", inputs: ["label", "description", "required", "helperText"] }, { kind: "directive", type: SdHrefDirective, selector: "a[sdHref]", inputs: ["sdHref"] }, { kind: "pipe", type: SdEmptyPipe, name: "sdEmpty" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
129
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SdRadio, isStandalone: true, selector: "sd-radio", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, form: { classPropertyName: "form", publicName: "form", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: true, transformFunction: null }, displayField: { classPropertyName: "displayField", publicName: "displayField", isSignal: true, isRequired: true, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, inlineError: { classPropertyName: "inlineError", publicName: "inlineError", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, viewed: { classPropertyName: "viewed", publicName: "viewed", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, hyperlink: { classPropertyName: "hyperlink", publicName: "hyperlink", isSignal: true, isRequired: false, transformFunction: null }, model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { model: "modelChange", sdChange: "sdChange", sdSelection: "sdSelection" }, host: { properties: { "class.sd-c-primary": "color() === 'primary'", "class.sd-c-secondary": "color() === 'secondary'", "class.sd-c-info": "color() === 'info'", "class.sd-c-success": "color() === 'success'", "class.sd-c-warning": "color() === 'warning'", "class.sd-c-error": "color() === 'error'" } }, queries: [{ propertyName: "sdSuffixDef", first: true, predicate: SdSuffixDefDirective, descendants: true, isSignal: true }, { propertyName: "sdLabelDef", first: true, predicate: SdLabelDefDirective, descendants: true, isSignal: true }, { propertyName: "sdViewDef", first: true, predicate: SdViewDefDirective, descendants: true, isSignal: true }], ngImport: i0, template: "@let _sdLabelDef = sdLabelDef();\n@let _sdSuffixDef = sdSuffixDef();\n@let _label = label();\n@let _display = display();\n@let _valueField = valueField();\n@let _hyperlink = hyperlink();\n\n@if (isViewed()) {\n @if (_sdLabelDef?.templateRef) {\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\n } @else if (_label) {\n <div class=\"T14R text-secondary\">{{ _label }}</div>\n }\n @if (_hyperlink) {\n <!-- N\u1EBFu c\u00F3 hyperlink th\u00EC d\u00F9ng th\u1EBB a -->\n <a [sdHref]=\"_hyperlink!\">{{ viewedText() || placeholder() }}</a>\n } @else {\n <!-- Ngo\u00E0i ra d\u00F9ng th\u1EBB m\u1EB7c \u0111\u1ECBnh -->\n <div class=\"T14M\">{{ viewedText() || placeholder() | sdEmpty }}</div>\n }\n} @else {\n <section [ngClass]=\"{ 'c-section': _display === 'row' }\">\n @if (_sdLabelDef?.templateRef) {\n <div [id]=\"labelId\"><ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container></div>\n } @else if (_label) {\n <sd-label [attr.id]=\"labelId\" [label]=\"_label!\" [required]=\"required()\"></sd-label>\n }\n <mat-radio-group\n [class.c-radio-group-column]=\"_display === 'column'\"\n [class.c-radio-group-row]=\"_display === 'row'\"\n [formControl]=\"formControl\"\n [attr.data-autoId]=\"autoId()\"\n [attr.data-disabled]=\"dataDisabled()\"\n [attr.data-empty]=\"dataEmpty()\"\n [attr.data-value]=\"dataValue()\"\n [attr.data-required]=\"dataRequired()\"\n [attr.aria-labelledby]=\"ariaLabelledBy()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n [attr.aria-invalid]=\"ariaInvalid()\"\n [attr.aria-required]=\"dataRequired()\">\n @for (item of normalizedItems(); track item[valueField()]) {\n <mat-radio-button [class.m-0]=\"_display === 'column'\" [class.mr-16]=\"_display === 'row'\" [value]=\"item[_valueField]\">\n {{ item[displayField()] }}\n </mat-radio-button>\n }\n </mat-radio-group>\n\n @if (_sdSuffixDef?.templateRef) {\n <ng-container *ngTemplateOutlet=\"_sdSuffixDef!.templateRef\"> </ng-container>\n }\n\n @if (visibleError() === 'required') {\n <mat-error [id]=\"errorId\">\n {{ 'core.form.radio.required' | translate }}\n </mat-error>\n } @else if (visibleError() === 'inlineError') {\n <mat-error [id]=\"errorId\">\n {{ inlineError() }}\n </mat-error>\n }\n </section>\n}\n", styles: [":host{height:100%;display:flex;flex-direction:column}:host ::ng-deep label.mdc-label{margin-bottom:0}:host{--sd-c: var(--sd-primary)}:host(.sd-c-secondary){--sd-c: var(--sd-secondary)}:host(.sd-c-info){--sd-c: var(--sd-info)}:host(.sd-c-success){--sd-c: var(--sd-success)}:host(.sd-c-warning){--sd-c: var(--sd-warning)}:host(.sd-c-error){--sd-c: var(--sd-error)}:host ::ng-deep .mat-mdc-radio-button,:host ::ng-deep .mat-mdc-radio-group,:host ::ng-deep .mdc-radio{--mdc-radio-selected-icon-color: var(--sd-c) !important;--mdc-radio-selected-focus-icon-color: var(--sd-c) !important;--mdc-radio-selected-hover-icon-color: var(--sd-c) !important;--mdc-radio-selected-pressed-icon-color: var(--sd-c) !important;--mdc-radio-selected-focus-state-layer-color: var(--sd-c) !important;--mdc-radio-selected-hover-state-layer-color: var(--sd-c) !important;--mat-radio-selected-icon-color: var(--sd-c) !important;--mat-radio-selected-focus-icon-color: var(--sd-c) !important;--mat-radio-selected-hover-icon-color: var(--sd-c) !important;--mat-radio-selected-pressed-icon-color: var(--sd-c) !important;--mat-radio-checked-ripple-color: var(--sd-c) !important;--mat-radio-checked-state-layer-color: var(--sd-c) !important}.c-section{align-content:center;align-items:center}.c-radio-group-column{flex:1;display:flex;flex-direction:column;align-items:flex-start}.c-radio-group-row{flex:1;display:flex;flex-direction:row;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i4.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i4.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "component", type: SdLabel, selector: "sd-label", inputs: ["label", "description", "required", "helperText"] }, { kind: "directive", type: SdHrefDirective, selector: "a[sdHref]", inputs: ["sdHref"] }, { kind: "pipe", type: SdEmptyPipe, name: "sdEmpty" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
152
130
  }
153
131
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SdRadio, decorators: [{
154
132
  type: Component,
@@ -171,8 +149,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
171
149
  SdEmptyPipe,
172
150
  SdHrefDirective,
173
151
  TranslatePipe,
174
- ], template: "@let _sdLabelDef = sdLabelDef();\n@let _label = label();\n@let _display = display();\n@let _valueField = valueField();\n@let _hyperlink = hyperlink();\n\n@if (isViewed()) {\n @if (_sdLabelDef?.templateRef) {\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\n } @else if (_label) {\n <div class=\"T14R text-secondary\">{{ _label }}</div>\n }\n @if (_hyperlink) {\n <!-- N\u1EBFu c\u00F3 hyperlink th\u00EC d\u00F9ng th\u1EBB a -->\n <a [sdHref]=\"_hyperlink!\">{{ viewedText() }}</a>\n } @else {\n <!-- Ngo\u00E0i ra d\u00F9ng th\u1EBB m\u1EB7c \u0111\u1ECBnh -->\n <div class=\"T14M\">{{ viewedText() | sdEmpty }}</div>\n }\n} @else {\n <section [ngClass]=\"{ 'c-section': _display === 'row' }\">\n @if (_sdLabelDef?.templateRef) {\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\n } @else if (_label) {\n <sd-label [label]=\"_label!\" [required]=\"required()\"></sd-label>\n }\n <mat-radio-group\n [class.c-radio-group-column]=\"_display === 'column'\"\n [class.c-radio-group-row]=\"_display === 'row'\"\n [formControl]=\"formControl\"\n [attr.data-autoId]=\"autoId()\"\n [attr.data-disabled]=\"dataDisabled()\"\n [attr.data-empty]=\"dataEmpty()\"\n [attr.data-value]=\"dataValue()\"\n [attr.data-required]=\"dataRequired()\">\n @for (item of normalizedItems(); track item[valueField()]) {\n <mat-radio-button [class.m-0]=\"_display === 'column'\" [class.mr-16]=\"_display === 'row'\" [value]=\"item[_valueField]\">\n {{ item[displayField()] }}\n </mat-radio-button>\n }\n </mat-radio-group>\n\n @if (formControl.errors?.['required'] && formControl.touched) {\n <mat-error>\n {{ 'core.form.radio.required' | translate }}\n </mat-error>\n } @else if (formControl.errors?.['inlineError'] && formControl.touched) {\n <mat-error>\n {{ inlineError() }}\n </mat-error>\n }\n </section>\n}\n", styles: [":host{height:100%;display:flex;flex-direction:column}:host ::ng-deep label.mdc-label{margin-bottom:0}:host{--sd-c: var(--sd-primary)}:host(.sd-c-secondary){--sd-c: var(--sd-secondary)}:host(.sd-c-info){--sd-c: var(--sd-info)}:host(.sd-c-success){--sd-c: var(--sd-success)}:host(.sd-c-warning){--sd-c: var(--sd-warning)}:host(.sd-c-error){--sd-c: var(--sd-error)}:host ::ng-deep .mat-mdc-radio-button,:host ::ng-deep .mat-mdc-radio-group,:host ::ng-deep .mdc-radio{--mdc-radio-selected-icon-color: var(--sd-c) !important;--mdc-radio-selected-focus-icon-color: var(--sd-c) !important;--mdc-radio-selected-hover-icon-color: var(--sd-c) !important;--mdc-radio-selected-pressed-icon-color: var(--sd-c) !important;--mdc-radio-selected-focus-state-layer-color: var(--sd-c) !important;--mdc-radio-selected-hover-state-layer-color: var(--sd-c) !important;--mat-radio-selected-icon-color: var(--sd-c) !important;--mat-radio-selected-focus-icon-color: var(--sd-c) !important;--mat-radio-selected-hover-icon-color: var(--sd-c) !important;--mat-radio-selected-pressed-icon-color: var(--sd-c) !important;--mat-radio-checked-ripple-color: var(--sd-c) !important;--mat-radio-checked-state-layer-color: var(--sd-c) !important}.c-section{align-content:center;align-items:center}.c-radio-group-column{flex:1;display:flex;flex-direction:column;align-items:flex-start}.c-radio-group-row{flex:1;display:flex;flex-direction:row;align-items:center}\n"] }]
175
- }], ctorParameters: () => [], propDecorators: { autoIdInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoId", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: true }] }], displayField: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayField", required: true }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], inlineError: [{ type: i0.Input, args: [{ isSignal: true, alias: "inlineError", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], viewed: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewed", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], hyperlink: [{ type: i0.Input, args: [{ isSignal: true, alias: "hyperlink", required: false }] }], model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }, { type: i0.Output, args: ["modelChange"] }], sdSuffixDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdSuffixDefDirective), { isSignal: true }] }], sdLabelDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdLabelDefDirective), { isSignal: true }] }], sdViewDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdViewDefDirective), { isSignal: true }] }], sdChange: [{ type: i0.Output, args: ["sdChange"] }], sdSelection: [{ type: i0.Output, args: ["sdSelection"] }] } });
152
+ ], template: "@let _sdLabelDef = sdLabelDef();\n@let _sdSuffixDef = sdSuffixDef();\n@let _label = label();\n@let _display = display();\n@let _valueField = valueField();\n@let _hyperlink = hyperlink();\n\n@if (isViewed()) {\n @if (_sdLabelDef?.templateRef) {\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\n } @else if (_label) {\n <div class=\"T14R text-secondary\">{{ _label }}</div>\n }\n @if (_hyperlink) {\n <!-- N\u1EBFu c\u00F3 hyperlink th\u00EC d\u00F9ng th\u1EBB a -->\n <a [sdHref]=\"_hyperlink!\">{{ viewedText() || placeholder() }}</a>\n } @else {\n <!-- Ngo\u00E0i ra d\u00F9ng th\u1EBB m\u1EB7c \u0111\u1ECBnh -->\n <div class=\"T14M\">{{ viewedText() || placeholder() | sdEmpty }}</div>\n }\n} @else {\n <section [ngClass]=\"{ 'c-section': _display === 'row' }\">\n @if (_sdLabelDef?.templateRef) {\n <div [id]=\"labelId\"><ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container></div>\n } @else if (_label) {\n <sd-label [attr.id]=\"labelId\" [label]=\"_label!\" [required]=\"required()\"></sd-label>\n }\n <mat-radio-group\n [class.c-radio-group-column]=\"_display === 'column'\"\n [class.c-radio-group-row]=\"_display === 'row'\"\n [formControl]=\"formControl\"\n [attr.data-autoId]=\"autoId()\"\n [attr.data-disabled]=\"dataDisabled()\"\n [attr.data-empty]=\"dataEmpty()\"\n [attr.data-value]=\"dataValue()\"\n [attr.data-required]=\"dataRequired()\"\n [attr.aria-labelledby]=\"ariaLabelledBy()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n [attr.aria-invalid]=\"ariaInvalid()\"\n [attr.aria-required]=\"dataRequired()\">\n @for (item of normalizedItems(); track item[valueField()]) {\n <mat-radio-button [class.m-0]=\"_display === 'column'\" [class.mr-16]=\"_display === 'row'\" [value]=\"item[_valueField]\">\n {{ item[displayField()] }}\n </mat-radio-button>\n }\n </mat-radio-group>\n\n @if (_sdSuffixDef?.templateRef) {\n <ng-container *ngTemplateOutlet=\"_sdSuffixDef!.templateRef\"> </ng-container>\n }\n\n @if (visibleError() === 'required') {\n <mat-error [id]=\"errorId\">\n {{ 'core.form.radio.required' | translate }}\n </mat-error>\n } @else if (visibleError() === 'inlineError') {\n <mat-error [id]=\"errorId\">\n {{ inlineError() }}\n </mat-error>\n }\n </section>\n}\n", styles: [":host{height:100%;display:flex;flex-direction:column}:host ::ng-deep label.mdc-label{margin-bottom:0}:host{--sd-c: var(--sd-primary)}:host(.sd-c-secondary){--sd-c: var(--sd-secondary)}:host(.sd-c-info){--sd-c: var(--sd-info)}:host(.sd-c-success){--sd-c: var(--sd-success)}:host(.sd-c-warning){--sd-c: var(--sd-warning)}:host(.sd-c-error){--sd-c: var(--sd-error)}:host ::ng-deep .mat-mdc-radio-button,:host ::ng-deep .mat-mdc-radio-group,:host ::ng-deep .mdc-radio{--mdc-radio-selected-icon-color: var(--sd-c) !important;--mdc-radio-selected-focus-icon-color: var(--sd-c) !important;--mdc-radio-selected-hover-icon-color: var(--sd-c) !important;--mdc-radio-selected-pressed-icon-color: var(--sd-c) !important;--mdc-radio-selected-focus-state-layer-color: var(--sd-c) !important;--mdc-radio-selected-hover-state-layer-color: var(--sd-c) !important;--mat-radio-selected-icon-color: var(--sd-c) !important;--mat-radio-selected-focus-icon-color: var(--sd-c) !important;--mat-radio-selected-hover-icon-color: var(--sd-c) !important;--mat-radio-selected-pressed-icon-color: var(--sd-c) !important;--mat-radio-checked-ripple-color: var(--sd-c) !important;--mat-radio-checked-state-layer-color: var(--sd-c) !important}.c-section{align-content:center;align-items:center}.c-radio-group-column{flex:1;display:flex;flex-direction:column;align-items:flex-start}.c-radio-group-row{flex:1;display:flex;flex-direction:row;align-items:center}\n"] }]
153
+ }], propDecorators: { autoIdInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoId", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: true }] }], displayField: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayField", required: true }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], inlineError: [{ type: i0.Input, args: [{ isSignal: true, alias: "inlineError", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], viewed: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewed", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], hyperlink: [{ type: i0.Input, args: [{ isSignal: true, alias: "hyperlink", required: false }] }], model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }, { type: i0.Output, args: ["modelChange"] }], sdSuffixDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdSuffixDefDirective), { isSignal: true }] }], sdLabelDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdLabelDefDirective), { isSignal: true }] }], sdViewDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdViewDefDirective), { isSignal: true }] }], sdChange: [{ type: i0.Output, args: ["sdChange"] }], sdSelection: [{ type: i0.Output, args: ["sdSelection"] }] } });
176
154
 
177
155
  /**
178
156
  * Generated bundle index. Do not edit.
@@ -1 +1 @@
1
- {"version":3,"file":"sdcorejs-angular-forms-radio.mjs","sources":["../../../projects/sdcorejs-angular/forms/radio/src/radio.component.ts","../../../projects/sdcorejs-angular/forms/radio/src/radio.component.html","../../../projects/sdcorejs-angular/forms/radio/sdcorejs-angular-forms-radio.ts"],"sourcesContent":["import { Utilities } from '@sdcorejs/utils/fns';\n\nimport { CommonModule } from '@angular/common';\nimport {\n AfterViewInit,\n booleanAttribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n computed,\n contentChild,\n effect,\n inject,\n input,\n model,\n OnDestroy,\n OnInit,\n output,\n} from '@angular/core';\nimport { FormGroup, NgForm, ReactiveFormsModule, ValidatorFn, Validators } from '@angular/forms';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatRadioModule } from '@angular/material/radio';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { Subscription } from 'rxjs';\n\nimport { SdLabelDefDirective, SdSuffixDefDirective, SdViewDefDirective } from '@sdcorejs/angular/forms/directives';\n\nimport {\n SdFormControl,\n SdInlineErrorValidator,\n sdFormControlState,\n SdViewed,\n SdViewedInput,\n sdViewedInline,\n sdViewedTransform,\n} from '@sdcorejs/angular/forms/models';\nimport { sdIsEmpty, sdSerializeDataValue } from '@sdcorejs/angular/utilities/data-state';\nimport { Color } from '@sdcorejs/utils/models';\nimport { TranslatePipe } from '@sdcorejs/angular/i18n';\nimport { SdEmptyPipe } from '@sdcorejs/angular/pipes';\nimport { SdLabel } from '@sdcorejs/angular/forms/label';\nimport { SdHrefDirective } from '@sdcorejs/angular/directives';\n\n@Component({\n selector: 'sd-radio',\n templateUrl: './radio.component.html',\n styleUrl: './radio.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n host: {\n // why: host class .sd-c-<x> + default sd-c-primary cho fallback. Thay data-sd-color\n // để tránh edge case host-attr-binding không reactive trong vài cảnh build pipeline.\n '[class.sd-c-primary]': \"color() === 'primary'\",\n '[class.sd-c-secondary]': \"color() === 'secondary'\",\n '[class.sd-c-info]': \"color() === 'info'\",\n '[class.sd-c-success]': \"color() === 'success'\",\n '[class.sd-c-warning]': \"color() === 'warning'\",\n '[class.sd-c-error]': \"color() === 'error'\",\n },\n imports: [\n CommonModule,\n ReactiveFormsModule,\n MatTooltipModule,\n MatFormFieldModule,\n MatRadioModule,\n SdLabel,\n SdEmptyPipe,\n SdHrefDirective,\n TranslatePipe,\n ],\n})\nexport class SdRadio implements OnInit, AfterViewInit, OnDestroy {\n readonly #ref = inject(ChangeDetectorRef);\n\n id = `I${Utilities.generateUuid()}`;\n #name = Utilities.generateUuid();\n formControl = new SdFormControl();\n #subscription = new Subscription();\n\n // Inputs — accept null|undefined at boundary, transform to canonical\n readonly autoIdInput = input<string | undefined, string | null | undefined>(undefined, {\n alias: 'autoId',\n transform: (v): string | undefined => v ?? undefined,\n });\n readonly name = input<string | undefined, string | null | undefined>(undefined, {\n transform: (v): string | undefined => v ?? undefined,\n });\n // why: parent may bind NgForm (template-driven), FormGroup (reactive), or a wrapper with `.form`.\n // Transform once at the input boundary so the rest of the component only deals with FormGroup.\n readonly form = input<FormGroup | undefined, any>(undefined, {\n transform: (val: any): FormGroup | undefined => {\n if (!val) return undefined;\n if (val instanceof NgForm) return val.form;\n if (val instanceof FormGroup) return val;\n if (val?.form instanceof FormGroup) return val.form;\n return undefined;\n },\n });\n readonly label = input<string | undefined, string | null | undefined>(undefined, {\n transform: (v): string | undefined => v ?? undefined,\n });\n readonly placeholder = input<string | undefined, string | null | undefined>(undefined, {\n transform: (v): string | undefined => v ?? undefined,\n });\n readonly display = input<'row' | 'column', 'row' | 'column' | null | undefined>('row', {\n transform: (v): 'row' | 'column' => v || 'row',\n });\n readonly items = input<any[], any[] | null | undefined>([], {\n transform: (v): any[] => (Array.isArray(v) ? v : []),\n });\n readonly valueField = input.required<string>();\n readonly displayField = input.required<string>();\n readonly required = input(false, { transform: booleanAttribute });\n readonly inlineError = input<string | undefined, string | null | undefined>(undefined, {\n transform: (v): string | undefined => v ?? undefined,\n });\n readonly disabled = input(false, { transform: booleanAttribute });\n /** Display mode: `false` edit · `true` static view · `'inline'` interactive (disabled `'inline'` → static). */\n readonly viewed = input<SdViewed, SdViewedInput>(false, { transform: sdViewedTransform });\n\n // why: tri-state viewed — `'inline'` keeps the radio group interactive; disabled `'inline'` → static.\n readonly #viewedState = sdViewedInline(this.viewed, undefined, this.disabled);\n /** `true` when the static read-only view should render. */\n readonly isViewed = this.#viewedState.isViewed;\n // why: legacy callers pass `null` → fallback to 'primary'. Color enum mở rộng hơn ThemePalette,\n // áp dụng qua host attr [data-sd-color] + SCSS override MDC token vars (mat [color] không nhận 'success'/'info'/...).\n readonly color = input<Color, Color | null | undefined>('primary', {\n transform: (v): Color => v || 'primary',\n });\n readonly hyperlink = input<string | undefined, string | null | undefined>(undefined, {\n transform: (v): string | undefined => v ?? undefined,\n });\n\n // Two-way model\n readonly model = model<number | string | boolean | undefined | null>(undefined);\n\n // Content children\n readonly sdSuffixDef = contentChild(SdSuffixDefDirective);\n readonly sdLabelDef = contentChild(SdLabelDefDirective);\n readonly sdViewDef = contentChild(SdViewDefDirective);\n\n // Outputs (modelChange auto-generated by model() signal)\n readonly sdChange = output<unknown>();\n readonly sdSelection = output<{ value: any | any[]; item?: any }>();\n\n // Computed (template bindings)\n readonly autoId = computed(() => (this.autoIdInput() ? `forms-radio-${this.autoIdInput()}` : undefined));\n // Kept for back-compat with templates that read `normalizedItems()` — alias of items()\n readonly normalizedItems = computed(() => this.items());\n readonly #state = sdFormControlState(computed(() => this.formControl));\n readonly dataDisabled = computed(() => (this.#state().disabled ? 'true' : 'false'));\n readonly dataEmpty = computed(() => (sdIsEmpty(this.#state().value) ? 'true' : 'false'));\n readonly dataValue = computed(() => sdSerializeDataValue(this.#state().value));\n readonly dataRequired = computed(() => (this.required() ? 'true' : 'false'));\n\n readonly viewedText = computed(() => {\n const items = this.items();\n const vField = this.valueField();\n const dField = this.displayField();\n // why: tìm item match value rồi trả về string ở `displayField`, không trả nguyên object (sẽ in [object Object]).\n const match = items.find(e => this.formControl?.value?.toString() === e?.[vField]?.toString());\n return match?.[dField] ?? '';\n });\n\n constructor() {\n effect(() => {\n const val = this.name();\n if (val) this.#name = val;\n });\n\n effect(() => {\n const value = this.model();\n if (value !== this.formControl.value) {\n this.formControl.setValue(value, { emitEvent: false });\n }\n });\n\n effect(() => {\n if (this.disabled()) this.formControl.disable();\n else this.formControl.enable();\n });\n\n effect(() => {\n this.required();\n this.inlineError();\n this.#updateValidator();\n });\n }\n\n ngOnInit() {\n this.#subscription.add(\n this.formControl.sdChanges.subscribe(() => {\n this.#ref.markForCheck();\n })\n );\n }\n\n ngAfterViewInit() {\n this.#subscription.add(\n this.formControl.valueChanges.subscribe(value => {\n const vField = this.valueField();\n this.model.set(value);\n this.sdChange.emit(value);\n this.sdSelection.emit({\n value,\n item: this.items().find(e => value?.toString() === e?.[vField]?.toString()),\n });\n })\n );\n this.form()?.addControl(this.#name, this.formControl);\n }\n\n ngOnDestroy() {\n this.#subscription.unsubscribe();\n this.form()?.removeControl(this.#name);\n }\n\n #updateValidator = () => {\n this.formControl.clearValidators();\n const validators: ValidatorFn[] = [];\n if (this.required()) {\n validators.push(Validators.required);\n }\n if (this.inlineError()) {\n validators.push(SdInlineErrorValidator);\n }\n this.formControl.setValidators(validators);\n this.formControl.updateValueAndValidity();\n };\n\n reValidate = () => {\n this.formControl.updateValueAndValidity({ emitEvent: true });\n };\n}\n","@let _sdLabelDef = sdLabelDef();\n@let _label = label();\n@let _display = display();\n@let _valueField = valueField();\n@let _hyperlink = hyperlink();\n\n@if (isViewed()) {\n @if (_sdLabelDef?.templateRef) {\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\n } @else if (_label) {\n <div class=\"T14R text-secondary\">{{ _label }}</div>\n }\n @if (_hyperlink) {\n <!-- Nếu có hyperlink thì dùng thẻ a -->\n <a [sdHref]=\"_hyperlink!\">{{ viewedText() }}</a>\n } @else {\n <!-- Ngoài ra dùng thẻ mặc định -->\n <div class=\"T14M\">{{ viewedText() | sdEmpty }}</div>\n }\n} @else {\n <section [ngClass]=\"{ 'c-section': _display === 'row' }\">\n @if (_sdLabelDef?.templateRef) {\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\n } @else if (_label) {\n <sd-label [label]=\"_label!\" [required]=\"required()\"></sd-label>\n }\n <mat-radio-group\n [class.c-radio-group-column]=\"_display === 'column'\"\n [class.c-radio-group-row]=\"_display === 'row'\"\n [formControl]=\"formControl\"\n [attr.data-autoId]=\"autoId()\"\n [attr.data-disabled]=\"dataDisabled()\"\n [attr.data-empty]=\"dataEmpty()\"\n [attr.data-value]=\"dataValue()\"\n [attr.data-required]=\"dataRequired()\">\n @for (item of normalizedItems(); track item[valueField()]) {\n <mat-radio-button [class.m-0]=\"_display === 'column'\" [class.mr-16]=\"_display === 'row'\" [value]=\"item[_valueField]\">\n {{ item[displayField()] }}\n </mat-radio-button>\n }\n </mat-radio-group>\n\n @if (formControl.errors?.['required'] && formControl.touched) {\n <mat-error>\n {{ 'core.form.radio.required' | translate }}\n </mat-error>\n } @else if (formControl.errors?.['inlineError'] && formControl.touched) {\n <mat-error>\n {{ inlineError() }}\n </mat-error>\n }\n </section>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sdcorejs-angular-forms-radio.mjs","sources":["../../../projects/sdcorejs-angular/forms/radio/src/radio.component.ts","../../../projects/sdcorejs-angular/forms/radio/src/radio.component.html","../../../projects/sdcorejs-angular/forms/radio/sdcorejs-angular-forms-radio.ts"],"sourcesContent":["import { Utilities } from '@sdcorejs/utils/fns';\n\nimport { CommonModule } from '@angular/common';\nimport {\n booleanAttribute,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n computed,\n contentChild,\n inject,\n input,\n model,\n OnDestroy,\n OnInit,\n output,\n} from '@angular/core';\nimport { ReactiveFormsModule, ValidatorFn, Validators } from '@angular/forms';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatRadioModule } from '@angular/material/radio';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { Subscription } from 'rxjs';\n\nimport { SdLabelDefDirective, SdSuffixDefDirective, SdViewDefDirective } from '@sdcorejs/angular/forms/directives';\n\nimport {\n SdFormControl,\n SdInlineErrorValidator,\n sdFormControlState,\n SdViewed,\n SdViewedInput,\n sdViewedInline,\n sdViewedTransform,\n ɵsdFormControlConnector,\n ɵSdFormControlParent,\n} from '@sdcorejs/angular/forms/models';\nimport { sdIsEmpty, sdSerializeDataValue } from '@sdcorejs/angular/utilities/data-state';\nimport { Color } from '@sdcorejs/utils/models';\nimport { TranslatePipe } from '@sdcorejs/angular/i18n';\nimport { SdEmptyPipe } from '@sdcorejs/angular/pipes';\nimport { SdLabel } from '@sdcorejs/angular/forms/label';\nimport { SdHrefDirective } from '@sdcorejs/angular/directives';\n\n@Component({\n selector: 'sd-radio',\n templateUrl: './radio.component.html',\n styleUrl: './radio.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n host: {\n // why: host class .sd-c-<x> + default sd-c-primary cho fallback. Thay data-sd-color\n // để tránh edge case host-attr-binding không reactive trong vài cảnh build pipeline.\n '[class.sd-c-primary]': \"color() === 'primary'\",\n '[class.sd-c-secondary]': \"color() === 'secondary'\",\n '[class.sd-c-info]': \"color() === 'info'\",\n '[class.sd-c-success]': \"color() === 'success'\",\n '[class.sd-c-warning]': \"color() === 'warning'\",\n '[class.sd-c-error]': \"color() === 'error'\",\n },\n imports: [\n CommonModule,\n ReactiveFormsModule,\n MatTooltipModule,\n MatFormFieldModule,\n MatRadioModule,\n SdLabel,\n SdEmptyPipe,\n SdHrefDirective,\n TranslatePipe,\n ],\n})\nexport class SdRadio implements OnInit, OnDestroy {\n readonly #ref = inject(ChangeDetectorRef);\n\n readonly id = `I${Utilities.generateUuid()}`;\n readonly labelId = `${this.id}-label`;\n readonly errorId = `${this.id}-error`;\n readonly #defaultName = Utilities.generateUuid();\n formControl = new SdFormControl();\n #subscription = new Subscription();\n\n // Inputs — accept null|undefined at boundary, transform to canonical\n readonly autoIdInput = input<string | undefined, string | null | undefined>(undefined, {\n alias: 'autoId',\n transform: (v): string | undefined => v ?? undefined,\n });\n readonly name = input<string | undefined, string | null | undefined>(undefined, {\n transform: (v): string | undefined => v ?? undefined,\n });\n readonly form = input<ɵSdFormControlParent>(undefined);\n readonly label = input<string | undefined, string | null | undefined>(undefined, {\n transform: (v): string | undefined => v ?? undefined,\n });\n readonly placeholder = input<string | undefined, string | null | undefined>(undefined, {\n transform: (v): string | undefined => v ?? undefined,\n });\n readonly display = input<'row' | 'column', 'row' | 'column' | null | undefined>('row', {\n transform: (v): 'row' | 'column' => v || 'row',\n });\n readonly items = input<any[], any[] | null | undefined>([], {\n transform: (v): any[] => (Array.isArray(v) ? v : []),\n });\n readonly valueField = input.required<string>();\n readonly displayField = input.required<string>();\n readonly required = input(false, { transform: booleanAttribute });\n readonly inlineError = input<string | undefined, string | null | undefined>(undefined, {\n transform: (v): string | undefined => v ?? undefined,\n });\n readonly disabled = input(false, { transform: booleanAttribute });\n /** Display mode: `false` edit · `true` static view · `'inline'` interactive (disabled `'inline'` → static). */\n readonly viewed = input<SdViewed, SdViewedInput>(false, { transform: sdViewedTransform });\n\n // why: tri-state viewed — `'inline'` keeps the radio group interactive; disabled `'inline'` → static.\n readonly #viewedState = sdViewedInline(this.viewed, undefined, this.disabled);\n /** `true` when the static read-only view should render. */\n readonly isViewed = this.#viewedState.isViewed;\n // why: legacy callers pass `null` → fallback to 'primary'. Color enum mở rộng hơn ThemePalette,\n // áp dụng qua host attr [data-sd-color] + SCSS override MDC token vars (mat [color] không nhận 'success'/'info'/...).\n readonly color = input<Color, Color | null | undefined>('primary', {\n transform: (v): Color => v || 'primary',\n });\n readonly hyperlink = input<string | undefined, string | null | undefined>(undefined, {\n transform: (v): string | undefined => v ?? undefined,\n });\n\n // Two-way model\n readonly model = model<number | string | boolean | undefined | null>(undefined);\n\n // Content children\n readonly sdSuffixDef = contentChild(SdSuffixDefDirective);\n readonly sdLabelDef = contentChild(SdLabelDefDirective);\n readonly sdViewDef = contentChild(SdViewDefDirective);\n\n // Outputs (modelChange auto-generated by model() signal)\n readonly sdChange = output<unknown>();\n readonly sdSelection = output<{ value: any | any[]; item?: any }>();\n\n // Computed (template bindings)\n readonly autoId = computed(() => (this.autoIdInput() ? `forms-radio-${this.autoIdInput()}` : undefined));\n // Kept for back-compat with templates that read `normalizedItems()` — alias of items()\n readonly normalizedItems = computed(() => this.items());\n readonly #state = sdFormControlState(computed(() => this.formControl));\n readonly dataDisabled = computed(() => (this.#state().disabled ? 'true' : 'false'));\n readonly dataEmpty = computed(() => (sdIsEmpty(this.#state().value) ? 'true' : 'false'));\n readonly dataValue = computed(() => sdSerializeDataValue(this.#state().value));\n readonly dataRequired = computed(() => (this.required() ? 'true' : 'false'));\n readonly visibleError = computed<'required' | 'inlineError' | undefined>(() => {\n if (!this.#state().touched) return undefined;\n if (this.formControl.hasError('required')) return 'required';\n if (this.formControl.hasError('inlineError')) return 'inlineError';\n return undefined;\n });\n readonly ariaLabelledBy = computed(() => (this.sdLabelDef()?.templateRef || this.label() ? this.labelId : undefined));\n readonly ariaLabel = computed(() => (this.ariaLabelledBy() ? undefined : this.placeholder() || undefined));\n readonly ariaDescribedBy = computed(() => (this.visibleError() ? this.errorId : undefined));\n readonly ariaInvalid = computed(() => (this.#state().invalid ? 'true' : 'false'));\n\n readonly viewedText = computed(() => {\n const items = this.items();\n const vField = this.valueField();\n const dField = this.displayField();\n // why: tìm item match value rồi trả về string ở `displayField`, không trả nguyên object (sẽ in [object Object]).\n const match = items.find(e => this.formControl?.value?.toString() === e?.[vField]?.toString());\n return match?.[dField] ?? '';\n });\n\n readonly #formConnector = ɵsdFormControlConnector<\n number | string | boolean | undefined | null,\n number | string | boolean | undefined | null\n >({\n form: this.form,\n name: computed(() => this.name() || this.#defaultName),\n control: computed(() => this.formControl),\n model: this.model,\n writeModel: value => {\n const vField = this.valueField();\n this.model.set(value);\n this.sdChange.emit(value);\n this.sdSelection.emit({\n value,\n item: this.items().find(item => value?.toString() === item?.[vField]?.toString()),\n });\n },\n validators: computed(() => {\n const validators: ValidatorFn[] = [];\n if (this.required()) validators.push(Validators.required);\n if (this.inlineError()) validators.push(SdInlineErrorValidator);\n return validators;\n }),\n disabled: this.disabled,\n });\n\n ngOnInit() {\n this.#subscription.add(\n this.formControl.sdChanges.subscribe(() => {\n this.#ref.markForCheck();\n })\n );\n }\n\n ngOnDestroy() {\n this.#subscription.unsubscribe();\n }\n\n reValidate = () => {\n this.formControl.updateValueAndValidity({ emitEvent: true });\n };\n}\n","@let _sdLabelDef = sdLabelDef();\n@let _sdSuffixDef = sdSuffixDef();\n@let _label = label();\n@let _display = display();\n@let _valueField = valueField();\n@let _hyperlink = hyperlink();\n\n@if (isViewed()) {\n @if (_sdLabelDef?.templateRef) {\n <ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container>\n } @else if (_label) {\n <div class=\"T14R text-secondary\">{{ _label }}</div>\n }\n @if (_hyperlink) {\n <!-- Nếu có hyperlink thì dùng thẻ a -->\n <a [sdHref]=\"_hyperlink!\">{{ viewedText() || placeholder() }}</a>\n } @else {\n <!-- Ngoài ra dùng thẻ mặc định -->\n <div class=\"T14M\">{{ viewedText() || placeholder() | sdEmpty }}</div>\n }\n} @else {\n <section [ngClass]=\"{ 'c-section': _display === 'row' }\">\n @if (_sdLabelDef?.templateRef) {\n <div [id]=\"labelId\"><ng-container *ngTemplateOutlet=\"_sdLabelDef!.templateRef\"> </ng-container></div>\n } @else if (_label) {\n <sd-label [attr.id]=\"labelId\" [label]=\"_label!\" [required]=\"required()\"></sd-label>\n }\n <mat-radio-group\n [class.c-radio-group-column]=\"_display === 'column'\"\n [class.c-radio-group-row]=\"_display === 'row'\"\n [formControl]=\"formControl\"\n [attr.data-autoId]=\"autoId()\"\n [attr.data-disabled]=\"dataDisabled()\"\n [attr.data-empty]=\"dataEmpty()\"\n [attr.data-value]=\"dataValue()\"\n [attr.data-required]=\"dataRequired()\"\n [attr.aria-labelledby]=\"ariaLabelledBy()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.aria-describedby]=\"ariaDescribedBy()\"\n [attr.aria-invalid]=\"ariaInvalid()\"\n [attr.aria-required]=\"dataRequired()\">\n @for (item of normalizedItems(); track item[valueField()]) {\n <mat-radio-button [class.m-0]=\"_display === 'column'\" [class.mr-16]=\"_display === 'row'\" [value]=\"item[_valueField]\">\n {{ item[displayField()] }}\n </mat-radio-button>\n }\n </mat-radio-group>\n\n @if (_sdSuffixDef?.templateRef) {\n <ng-container *ngTemplateOutlet=\"_sdSuffixDef!.templateRef\"> </ng-container>\n }\n\n @if (visibleError() === 'required') {\n <mat-error [id]=\"errorId\">\n {{ 'core.form.radio.required' | translate }}\n </mat-error>\n } @else if (visibleError() === 'inlineError') {\n <mat-error [id]=\"errorId\">\n {{ inlineError() }}\n </mat-error>\n }\n </section>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["ɵsdFormControlConnector"],"mappings":"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"}
@@ -18,7 +18,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
18
18
  import { SdView } from '@sdcorejs/angular/components/view';
19
19
  import { SdItemDefDefDirective, SdViewDefDirective } from '@sdcorejs/angular/forms/directives';
20
20
  import { SdLabel } from '@sdcorejs/angular/forms/label';
21
- import { SD_FORM_CONFIGURATION, sdFormControlState, sdViewedTransform, sdViewedInline, SdFormControl, HandleSdCustomValidator, SdInlineErrorValidator } from '@sdcorejs/angular/forms/models';
21
+ import { SD_FORM_CONFIGURATION, sdFormControlState, sdViewedTransform, sdViewedInline, SdFormControl, ɵsdFormControlConnector as _sdFormControlConnector, HandleSdCustomValidator, SdInlineErrorValidator } from '@sdcorejs/angular/forms/models';
22
22
  import { I18nService } from '@sdcorejs/angular/i18n';
23
23
  import { sdIsEmpty, sdSerializeDataValue } from '@sdcorejs/angular/utilities/data-state';
24
24
  import { Utilities, StringUtilities, ArrayUtilities } from '@sdcorejs/angular/utilities/extensions';
@@ -170,6 +170,11 @@ class SdSelect {
170
170
  // 4. INTERNAL STATE & STREAMS
171
171
  // ==========================================
172
172
  formControl = new SdFormControl();
173
+ #formConnector = _sdFormControlConnector({
174
+ form: this.form,
175
+ name: this.name,
176
+ control: computed(() => this.formControl),
177
+ });
173
178
  inputControl = new FormControl('');
174
179
  loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
175
180
  focused = signal(false, ...(ngDevMode ? [{ debugName: "focused" }] : /* istanbul ignore next */ []));
@@ -328,25 +333,6 @@ class SdSelect {
328
333
  const inl = this.inlineError();
329
334
  untracked(() => this.#updateValidator(req, val, inl));
330
335
  });
331
- // ==========================================
332
- // EFFECT: QUẢN LÝ FORM GROUP & CONTROL
333
- // ==========================================
334
- effect(onCleanup => {
335
- // 1. Lấy giá trị mới nhất của form và name
336
- const formGroup = this.form();
337
- const controlName = this.name();
338
- if (formGroup && controlName) {
339
- // 2. Thêm control vào form
340
- formGroup.addControl(controlName, this.formControl);
341
- // 3. Đăng ký hàm dọn dẹp (Cleanup)
342
- onCleanup(() => {
343
- // Hàm này sẽ tự động chạy trong 2 trường hợp:
344
- // - Khi Component bị Destroy (thay thế ngOnDestroy)
345
- // - Khi form() hoặc name() thay đổi giá trị (nó sẽ gỡ control cũ ra trước khi add cái mới vào)
346
- formGroup.removeControl(controlName);
347
- });
348
- }
349
- });
350
336
  effect(() => {
351
337
  const actions = this.footerActions();
352
338
  const context = this.footerActionContext();