@sdcorejs/angular 21.1.3 → 21.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -14
- package/fesm2022/sdcorejs-angular-components-anchor.mjs +14 -14
- package/fesm2022/sdcorejs-angular-components-anchor.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-audit-diff.mjs +332 -0
- package/fesm2022/sdcorejs-angular-components-audit-diff.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-components-badge.mjs +1 -0
- package/fesm2022/sdcorejs-angular-components-badge.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-breadcrumb.mjs +121 -0
- package/fesm2022/sdcorejs-angular-components-breadcrumb.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-components-data-state.mjs +68 -0
- package/fesm2022/sdcorejs-angular-components-data-state.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-components-document-builder.mjs +18 -23
- package/fesm2022/sdcorejs-angular-components-document-builder.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-editor.mjs +6 -4
- package/fesm2022/sdcorejs-angular-components-editor.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-form-generic.mjs +495 -838
- package/fesm2022/sdcorejs-angular-components-form-generic.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-import-excel.mjs +24 -34
- package/fesm2022/sdcorejs-angular-components-import-excel.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-job-progress.mjs +97 -0
- package/fesm2022/sdcorejs-angular-components-job-progress.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-components-mini-editor.mjs +10 -20
- package/fesm2022/sdcorejs-angular-components-mini-editor.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-modal.mjs +61 -4
- package/fesm2022/sdcorejs-angular-components-modal.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-preview.mjs +1438 -218
- package/fesm2022/sdcorejs-angular-components-preview.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-query-bar.mjs +4 -4
- package/fesm2022/sdcorejs-angular-components-query-bar.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-query-builder.mjs +1 -1
- package/fesm2022/sdcorejs-angular-components-query-builder.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-side-drawer.mjs +39 -2
- package/fesm2022/sdcorejs-angular-components-side-drawer.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-tab-router.mjs +16 -22
- package/fesm2022/sdcorejs-angular-components-tab-router.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-tab.mjs +48 -4
- package/fesm2022/sdcorejs-angular-components-tab.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-table.mjs +96 -63
- package/fesm2022/sdcorejs-angular-components-table.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-tree.mjs +186 -17
- package/fesm2022/sdcorejs-angular-components-tree.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components-upload-file.mjs +15 -22
- package/fesm2022/sdcorejs-angular-components-upload-file.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-components.mjs +4 -0
- package/fesm2022/sdcorejs-angular-components.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-directives.mjs +29 -41
- package/fesm2022/sdcorejs-angular-directives.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs +7 -7
- package/fesm2022/sdcorejs-angular-forms-autocomplete.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-checkbox.mjs +20 -71
- package/fesm2022/sdcorejs-angular-forms-checkbox.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs +6 -3
- package/fesm2022/sdcorejs-angular-forms-chip-calendar.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-chip.mjs +6 -3
- package/fesm2022/sdcorejs-angular-forms-chip.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-date-range.mjs +16 -13
- package/fesm2022/sdcorejs-angular-forms-date-range.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-date.mjs +42 -65
- package/fesm2022/sdcorejs-angular-forms-date.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-datetime.mjs +51 -66
- package/fesm2022/sdcorejs-angular-forms-datetime.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs +384 -0
- package/fesm2022/sdcorejs-angular-forms-entity-picker.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-forms-input-color.mjs +1 -1
- package/fesm2022/sdcorejs-angular-forms-input-color.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-input-number.mjs +7 -5
- package/fesm2022/sdcorejs-angular-forms-input-number.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-input.mjs +290 -56
- package/fesm2022/sdcorejs-angular-forms-input.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-models.mjs +155 -2
- package/fesm2022/sdcorejs-angular-forms-models.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-radio.mjs +44 -66
- package/fesm2022/sdcorejs-angular-forms-radio.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-select.mjs +6 -20
- package/fesm2022/sdcorejs-angular-forms-select.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-switch.mjs +19 -64
- package/fesm2022/sdcorejs-angular-forms-switch.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-textarea.mjs +6 -5
- package/fesm2022/sdcorejs-angular-forms-textarea.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-forms-time-range.mjs +277 -0
- package/fesm2022/sdcorejs-angular-forms-time-range.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-forms-time.mjs +307 -0
- package/fesm2022/sdcorejs-angular-forms-time.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-forms-tree-select.mjs +210 -0
- package/fesm2022/sdcorejs-angular-forms-tree-select.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-forms.mjs +73 -4
- package/fesm2022/sdcorejs-angular-forms.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-i18n.mjs +375 -10
- package/fesm2022/sdcorejs-angular-i18n.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-interceptors.mjs +12 -17
- package/fesm2022/sdcorejs-angular-interceptors.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-modules-layout.mjs +994 -168
- package/fesm2022/sdcorejs-angular-modules-layout.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-pipes.mjs +5 -7
- package/fesm2022/sdcorejs-angular-pipes.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-api.mjs +407 -137
- package/fesm2022/sdcorejs-angular-services-api.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-cache.mjs +515 -105
- package/fesm2022/sdcorejs-angular-services-cache.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-confirm.mjs +5 -7
- package/fesm2022/sdcorejs-angular-services-confirm.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-docx.mjs +7 -10
- package/fesm2022/sdcorejs-angular-services-docx.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-loading.mjs +339 -74
- package/fesm2022/sdcorejs-angular-services-loading.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-notify.mjs +7 -10
- package/fesm2022/sdcorejs-angular-services-notify.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-persistence.mjs +899 -0
- package/fesm2022/sdcorejs-angular-services-persistence.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-services-storage.mjs +324 -122
- package/fesm2022/sdcorejs-angular-services-storage.mjs.map +1 -1
- package/fesm2022/sdcorejs-angular-services-task.mjs +389 -0
- package/fesm2022/sdcorejs-angular-services-task.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-services-unsaved-changes.mjs +255 -0
- package/fesm2022/sdcorejs-angular-services-unsaved-changes.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-services-viewport.mjs +76 -0
- package/fesm2022/sdcorejs-angular-services-viewport.mjs.map +1 -0
- package/fesm2022/sdcorejs-angular-services.mjs +4 -0
- package/fesm2022/sdcorejs-angular-services.mjs.map +1 -1
- package/package.json +49 -1
- package/types/sdcorejs-angular-components-audit-diff.d.ts +74 -0
- package/types/sdcorejs-angular-components-badge.d.ts +1 -1
- package/types/sdcorejs-angular-components-breadcrumb.d.ts +53 -0
- package/types/sdcorejs-angular-components-data-state.d.ts +44 -0
- package/types/sdcorejs-angular-components-document-builder.d.ts +5 -5
- package/types/sdcorejs-angular-components-form-generic.d.ts +67 -104
- package/types/sdcorejs-angular-components-import-excel.d.ts +4 -14
- package/types/sdcorejs-angular-components-job-progress.d.ts +38 -0
- package/types/sdcorejs-angular-components-mini-editor.d.ts +9 -9
- package/types/sdcorejs-angular-components-modal.d.ts +7 -1
- package/types/sdcorejs-angular-components-preview.d.ts +181 -28
- package/types/sdcorejs-angular-components-side-drawer.d.ts +7 -1
- package/types/sdcorejs-angular-components-tab.d.ts +9 -2
- package/types/sdcorejs-angular-components-table.d.ts +8 -7
- package/types/sdcorejs-angular-components-tree.d.ts +24 -2
- package/types/sdcorejs-angular-components-upload-file.d.ts +5 -4
- package/types/sdcorejs-angular-components.d.ts +4 -0
- package/types/sdcorejs-angular-directives.d.ts +10 -8
- package/types/sdcorejs-angular-forms-autocomplete.d.ts +3 -4
- package/types/sdcorejs-angular-forms-checkbox.d.ts +4 -8
- package/types/sdcorejs-angular-forms-date-range.d.ts +6 -7
- package/types/sdcorejs-angular-forms-date.d.ts +2 -2
- package/types/sdcorejs-angular-forms-datetime.d.ts +2 -2
- package/types/sdcorejs-angular-forms-entity-picker.d.ts +128 -0
- package/types/sdcorejs-angular-forms-input-number.d.ts +1 -1
- package/types/sdcorejs-angular-forms-input.d.ts +74 -11
- package/types/sdcorejs-angular-forms-models.d.ts +86 -3
- package/types/sdcorejs-angular-forms-radio.d.ts +12 -8
- package/types/sdcorejs-angular-forms-switch.d.ts +4 -7
- package/types/sdcorejs-angular-forms-time-range.d.ts +98 -0
- package/types/sdcorejs-angular-forms-time.d.ts +117 -0
- package/types/sdcorejs-angular-forms-tree-select.d.ts +76 -0
- package/types/sdcorejs-angular-forms.d.ts +15 -5
- package/types/sdcorejs-angular-i18n.d.ts +72 -2
- package/types/sdcorejs-angular-interceptors.d.ts +5 -6
- package/types/sdcorejs-angular-modules-layout.d.ts +354 -17
- package/types/sdcorejs-angular-pipes.d.ts +2 -2
- package/types/sdcorejs-angular-services-api.d.ts +68 -24
- package/types/sdcorejs-angular-services-cache.d.ts +52 -16
- package/types/sdcorejs-angular-services-confirm.d.ts +3 -2
- package/types/sdcorejs-angular-services-docx.d.ts +2 -3
- package/types/sdcorejs-angular-services-loading.d.ts +16 -8
- package/types/sdcorejs-angular-services-persistence.d.ts +159 -0
- package/types/sdcorejs-angular-services-storage.d.ts +26 -8
- package/types/sdcorejs-angular-services-task.d.ts +104 -0
- package/types/sdcorejs-angular-services-unsaved-changes.d.ts +83 -0
- package/types/sdcorejs-angular-services-viewport.d.ts +42 -0
- package/types/sdcorejs-angular-services.d.ts +4 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i1 from '@angular/common';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { viewChild, contentChild, input, computed, inject, ChangeDetectorRef, booleanAttribute, model, output, EventEmitter, effect, untracked, Output, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
4
|
+
import { viewChild, contentChild, input, computed, inject, ChangeDetectorRef, booleanAttribute, model, output, EventEmitter, signal, effect, untracked, Output, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
5
5
|
import { Utilities } from '@sdcorejs/utils/fns';
|
|
6
6
|
import * as i2 from '@angular/forms';
|
|
7
7
|
import { NgForm, FormGroup, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
@@ -16,13 +16,157 @@ import { SdView } from '@sdcorejs/angular/components/view';
|
|
|
16
16
|
import { SdInlineText } from '@sdcorejs/angular/forms/inline-text';
|
|
17
17
|
import { SdSuffixDefDirective, SdViewDefDirective } from '@sdcorejs/angular/forms/directives';
|
|
18
18
|
import { SdLabel } from '@sdcorejs/angular/forms/label';
|
|
19
|
-
import { sdFormControlState, SD_FORM_CONFIGURATION, sdViewedTransform,
|
|
19
|
+
import { sdFormControlState, SD_FORM_CONFIGURATION, sdViewedTransform, SdFormControl, SdInlineErrorValidator, HandleSdCustomValidator, ɵsdFormControlConnector as _sdFormControlConnector, sdViewedInline } from '@sdcorejs/angular/forms/models';
|
|
20
20
|
import { sdIsEmpty, sdSerializeDataValue } from '@sdcorejs/angular/utilities/data-state';
|
|
21
21
|
import { I18nService, TranslatePipe } from '@sdcorejs/angular/i18n';
|
|
22
22
|
import { VALIDATION_PATTERNS } from '@sdcorejs/utils/constants';
|
|
23
23
|
import { Subscription } from 'rxjs';
|
|
24
24
|
import { SdIcon } from '@sdcorejs/angular/modules/icon';
|
|
25
25
|
|
|
26
|
+
const DEFAULT_TOKENS = {
|
|
27
|
+
'#': { pattern: /[0-9]/ },
|
|
28
|
+
'9': { pattern: /[0-9]/, optional: true },
|
|
29
|
+
A: { pattern: /[A-Za-z]/ },
|
|
30
|
+
a: { pattern: /[A-Za-z]/, optional: true },
|
|
31
|
+
'*': { pattern: /[A-Za-z0-9]/ },
|
|
32
|
+
'?': { pattern: /[A-Za-z0-9]/, optional: true },
|
|
33
|
+
};
|
|
34
|
+
function tokenAccepts(token, value) {
|
|
35
|
+
token.pattern.lastIndex = 0;
|
|
36
|
+
const accepted = token.pattern.test(value);
|
|
37
|
+
token.pattern.lastIndex = 0;
|
|
38
|
+
return accepted;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates a dependency-free slot mask.
|
|
42
|
+
*
|
|
43
|
+
* Default tokens: `#` required digit, `9` optional digit, `A`/`a` required/optional
|
|
44
|
+
* letter, and `*`/`?` required/optional alphanumeric. Every other character is a
|
|
45
|
+
* display literal and never leaks into the raw model.
|
|
46
|
+
*/
|
|
47
|
+
function sdCreateInputMask(pattern, options = {}) {
|
|
48
|
+
if (!pattern)
|
|
49
|
+
throw new Error('Input mask pattern must not be empty.');
|
|
50
|
+
const tokens = { ...DEFAULT_TOKENS, ...options.tokens };
|
|
51
|
+
const slots = [];
|
|
52
|
+
const literals = [];
|
|
53
|
+
const units = Array.from(pattern, (value, unitIndex) => {
|
|
54
|
+
const token = tokens[value];
|
|
55
|
+
if (token) {
|
|
56
|
+
const slot = { unitIndex, slotIndex: slots.length, token };
|
|
57
|
+
slots.push(slot);
|
|
58
|
+
return slot;
|
|
59
|
+
}
|
|
60
|
+
const literal = { unitIndex, value };
|
|
61
|
+
literals.push(literal);
|
|
62
|
+
return literal;
|
|
63
|
+
});
|
|
64
|
+
if (slots.length === 0)
|
|
65
|
+
throw new Error('Input mask pattern must contain at least one token.');
|
|
66
|
+
const literalValues = new Set(literals.map(item => item.value));
|
|
67
|
+
const convert = (source, sourceSelectionStart, sourceSelectionEnd, sourceIsDisplay) => {
|
|
68
|
+
const assigned = [];
|
|
69
|
+
let unitCursor = 0;
|
|
70
|
+
let invalid = false;
|
|
71
|
+
for (let sourceIndex = 0; sourceIndex < source.length; sourceIndex += 1) {
|
|
72
|
+
const value = source[sourceIndex];
|
|
73
|
+
let consumed = false;
|
|
74
|
+
// why: literals are consumed at the pattern cursor, not filtered globally;
|
|
75
|
+
// a global filter would corrupt raw digits in masks with prefixes such as `+84`.
|
|
76
|
+
while (unitCursor < units.length) {
|
|
77
|
+
const unit = units[unitCursor];
|
|
78
|
+
if ('value' in unit) {
|
|
79
|
+
unitCursor += 1;
|
|
80
|
+
if (sourceIsDisplay && value === unit.value) {
|
|
81
|
+
consumed = true;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (tokenAccepts(unit.token, value)) {
|
|
87
|
+
assigned.push({
|
|
88
|
+
slotIndex: unit.slotIndex,
|
|
89
|
+
unitIndex: unit.unitIndex,
|
|
90
|
+
value: unit.token.transform?.(value) ?? value,
|
|
91
|
+
sourceIndex,
|
|
92
|
+
});
|
|
93
|
+
unitCursor += 1;
|
|
94
|
+
consumed = true;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
if (sourceIsDisplay && literalValues.has(value)) {
|
|
98
|
+
consumed = true;
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
if (unit.token.optional) {
|
|
102
|
+
unitCursor += 1;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
invalid = true;
|
|
106
|
+
consumed = true;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
if (!consumed)
|
|
110
|
+
invalid = true;
|
|
111
|
+
}
|
|
112
|
+
const assignedByUnit = new Map(assigned.map(item => [item.unitIndex, item]));
|
|
113
|
+
const lastFilledUnit = assigned.at(-1)?.unitIndex ?? -1;
|
|
114
|
+
let display = '';
|
|
115
|
+
let acceptedCount = 0;
|
|
116
|
+
const displayPositionByAcceptedCount = new Map([[0, 0]]);
|
|
117
|
+
for (const unit of units) {
|
|
118
|
+
if ('token' in unit) {
|
|
119
|
+
const item = assignedByUnit.get(unit.unitIndex);
|
|
120
|
+
if (!item)
|
|
121
|
+
continue;
|
|
122
|
+
display += item.value;
|
|
123
|
+
acceptedCount += 1;
|
|
124
|
+
displayPositionByAcceptedCount.set(acceptedCount, display.length);
|
|
125
|
+
}
|
|
126
|
+
else if (unit.unitIndex < lastFilledUnit) {
|
|
127
|
+
display += unit.value;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const raw = assigned.map(item => item.value).join('');
|
|
131
|
+
const hasEveryRequiredSlot = slots.every((slot, index) => slot.token.optional || assigned.some(item => item.slotIndex === index));
|
|
132
|
+
const status = invalid ? 'invalid' : raw.length === 0 ? 'empty' : hasEveryRequiredSlot ? 'valid' : 'incomplete';
|
|
133
|
+
const acceptedBefore = (position) => assigned.filter(item => item.sourceIndex < Math.max(0, position)).length;
|
|
134
|
+
const mapSelection = (position) => {
|
|
135
|
+
const count = acceptedBefore(position);
|
|
136
|
+
return displayPositionByAcceptedCount.get(count) ?? display.length;
|
|
137
|
+
};
|
|
138
|
+
return {
|
|
139
|
+
raw,
|
|
140
|
+
display,
|
|
141
|
+
status,
|
|
142
|
+
selectionStart: mapSelection(sourceSelectionStart),
|
|
143
|
+
selectionEnd: mapSelection(sourceSelectionEnd),
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
return {
|
|
147
|
+
inputMode: options.inputMode ?? (slots.every(slot => tokenAccepts(slot.token, '0')) ? 'numeric' : 'text'),
|
|
148
|
+
maxDisplayLength: pattern.length,
|
|
149
|
+
format: raw => {
|
|
150
|
+
const source = raw == null ? '' : String(raw);
|
|
151
|
+
return convert(source, source.length, source.length, false);
|
|
152
|
+
},
|
|
153
|
+
parse: (display, selectionStart = display.length, selectionEnd = selectionStart) => convert(display, selectionStart ?? display.length, selectionEnd ?? selectionStart ?? display.length, true),
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/** Common business masks. Models remain raw strings; separators are display-only. */
|
|
157
|
+
const SD_INPUT_MASKS = {
|
|
158
|
+
VN_PHONE: sdCreateInputMask('#### ### ###', { inputMode: 'tel' }),
|
|
159
|
+
VN_ID: sdCreateInputMask('#### #### ####', { inputMode: 'numeric' }),
|
|
160
|
+
VN_TAX_CODE: sdCreateInputMask('##########-999', { inputMode: 'numeric' }),
|
|
161
|
+
BANK_ACCOUNT: sdCreateInputMask('######99999999999999', { inputMode: 'numeric' }),
|
|
162
|
+
BUSINESS_CODE: sdCreateInputMask('****-????????????', { inputMode: 'text' }),
|
|
163
|
+
};
|
|
164
|
+
function sdResolveInputMask(mask) {
|
|
165
|
+
if (!mask)
|
|
166
|
+
return undefined;
|
|
167
|
+
return typeof mask === 'string' ? SD_INPUT_MASKS[mask] : mask;
|
|
168
|
+
}
|
|
169
|
+
|
|
26
170
|
// Back-compat: SdPatternType cũ → ValidationPatternType mới.
|
|
27
171
|
// 3 key đã đổi tên trong @sdcorejs/utils v1.x.
|
|
28
172
|
const LEGACY_PATTERN_ALIAS = {
|
|
@@ -104,6 +248,11 @@ class SdInput {
|
|
|
104
248
|
helperText = input(...(ngDevMode ? [undefined, { debugName: "helperText" }] : /* istanbul ignore next */ []));
|
|
105
249
|
placeholder = input(...(ngDevMode ? [undefined, { debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
106
250
|
type = input('text', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
|
|
251
|
+
mask = input(...(ngDevMode ? [undefined, { debugName: "mask" }] : /* istanbul ignore next */ []));
|
|
252
|
+
maskAdapter = computed(() => sdResolveInputMask(this.mask()), ...(ngDevMode ? [{ debugName: "maskAdapter" }] : /* istanbul ignore next */ []));
|
|
253
|
+
effectiveType = computed(() => (this.maskAdapter() ? 'text' : this.type()), ...(ngDevMode ? [{ debugName: "effectiveType" }] : /* istanbul ignore next */ []));
|
|
254
|
+
inputMode = computed(() => this.maskAdapter()?.inputMode, ...(ngDevMode ? [{ debugName: "inputMode" }] : /* istanbul ignore next */ []));
|
|
255
|
+
maxDisplayLength = computed(() => this.maskAdapter()?.maxDisplayLength, ...(ngDevMode ? [{ debugName: "maxDisplayLength" }] : /* istanbul ignore next */ []));
|
|
107
256
|
hideInlineError = input(false, { ...(ngDevMode ? { debugName: "hideInlineError" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
108
257
|
blurOnEnter = input(false, { ...(ngDevMode ? { debugName: "blurOnEnter" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
109
258
|
/** Whether to show the value-gated clear button in edit and inline modes. */
|
|
@@ -113,9 +262,6 @@ class SdInput {
|
|
|
113
262
|
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
114
263
|
/** Display mode: `false` edit · `true` static view · `'inline'` borderless inline-edit (no panel — the input IS the face). */
|
|
115
264
|
viewed = input(false, { ...(ngDevMode ? { debugName: "viewed" } : /* istanbul ignore next */ {}), transform: sdViewedTransform });
|
|
116
|
-
// Tri-state `viewed` — shared primitive. Input has NO panel; in `'inline'` the input is rendered
|
|
117
|
-
// borderless/transparent (looks like text), always editable — clicking/focusing it edits directly.
|
|
118
|
-
#viewedState = sdViewedInline(this.viewed, () => this.#focusActiveInput(), this.disabled);
|
|
119
265
|
/** Focus whichever input is live: the inline primitive in `'inline'` mode, else the mat input. */
|
|
120
266
|
#focusActiveInput = () => {
|
|
121
267
|
const inline = this.inlineRef();
|
|
@@ -124,12 +270,6 @@ class SdInput {
|
|
|
124
270
|
else
|
|
125
271
|
this.control()?.nativeElement?.focus();
|
|
126
272
|
};
|
|
127
|
-
/** `true` when `viewed === 'inline'`. */
|
|
128
|
-
isInline = this.#viewedState.isInline;
|
|
129
|
-
/** `true` when `viewed === true` (static view, no input). */
|
|
130
|
-
isViewed = this.#viewedState.isViewed;
|
|
131
|
-
/** Focus the inline input. No-op unless `viewed='inline'`. */
|
|
132
|
-
enterInlineEdit = () => this.#viewedState.enterInlineEdit();
|
|
133
273
|
/** View display template: `sdViewDef` overrides the projected `#sdValue` for the static view (unified). */
|
|
134
274
|
viewTemplate = computed(() => this.sdViewDef()?.templateRef ?? this.sdValueTemplate(), ...(ngDevMode ? [{ debugName: "viewTemplate" }] : /* istanbul ignore next */ []));
|
|
135
275
|
minlength = input(undefined, { ...(ngDevMode ? { debugName: "minlength" } : /* istanbul ignore next */ {}), transform: v => (v == null ? undefined : Number(v)) });
|
|
@@ -173,6 +313,10 @@ class SdInput {
|
|
|
173
313
|
return this.#i18n.t('core.form.input.required');
|
|
174
314
|
if (errors['maxlength'])
|
|
175
315
|
return this.#i18n.t('core.form.input.maxlength', { max: this.maxlength() ?? '' });
|
|
316
|
+
if (errors['maskIncomplete'])
|
|
317
|
+
return this.#i18n.t('core.form.input.mask-incomplete');
|
|
318
|
+
if (errors['maskInvalid'])
|
|
319
|
+
return this.#i18n.t('core.form.input.mask-invalid');
|
|
176
320
|
if (errors['pattern'])
|
|
177
321
|
return this.resolvedPatternErrorMsg() || this.#i18n.t('core.form.input.invalid-pattern');
|
|
178
322
|
if (errors['customValidator'])
|
|
@@ -196,37 +340,105 @@ class SdInput {
|
|
|
196
340
|
// "commit filter" (sẽ over-reload). `cleared` là intent rõ ràng cho action
|
|
197
341
|
// X (clear button) — consumer như column-filter dùng để fire reload ngay.
|
|
198
342
|
cleared = output();
|
|
199
|
-
//
|
|
343
|
+
// why: focus handling reads EventEmitter.observed before emitting a forced blur event.
|
|
200
344
|
sdFocusForceBlur = new EventEmitter();
|
|
201
345
|
formControl = new SdFormControl();
|
|
346
|
+
/** Display-only control used by the input element while a mask is active. */
|
|
347
|
+
displayControl = new SdFormControl();
|
|
348
|
+
activeControl = computed(() => (this.maskAdapter() ? this.displayControl : this.formControl), ...(ngDevMode ? [{ debugName: "activeControl" }] : /* istanbul ignore next */ []));
|
|
349
|
+
maskStatus = signal('empty', ...(ngDevMode ? [{ debugName: "maskStatus" }] : /* istanbul ignore next */ []));
|
|
350
|
+
displayValue = computed(() => {
|
|
351
|
+
const adapter = this.maskAdapter();
|
|
352
|
+
return adapter ? adapter.format(this.formControl.value == null ? '' : String(this.formControl.value)).display : this.formControl.value;
|
|
353
|
+
}, ...(ngDevMode ? [{ debugName: "displayValue" }] : /* istanbul ignore next */ []));
|
|
202
354
|
#subscription = new Subscription();
|
|
355
|
+
#isComposing = false;
|
|
356
|
+
#pendingMaskResult;
|
|
203
357
|
isFocused = false;
|
|
358
|
+
#validators = computed(() => {
|
|
359
|
+
const validators = [];
|
|
360
|
+
const min = this.minlength();
|
|
361
|
+
const max = this.maxlength();
|
|
362
|
+
const pattern = this.resolvedPattern();
|
|
363
|
+
if (min && min > 0)
|
|
364
|
+
validators.push(Validators.minLength(min));
|
|
365
|
+
if (max && max > 0)
|
|
366
|
+
validators.push(Validators.maxLength(max));
|
|
367
|
+
if (pattern)
|
|
368
|
+
validators.push(Validators.pattern(pattern));
|
|
369
|
+
if (this.maskAdapter()) {
|
|
370
|
+
const maskStatus = this.maskStatus();
|
|
371
|
+
validators.push(() => {
|
|
372
|
+
if (maskStatus === 'invalid')
|
|
373
|
+
return { maskInvalid: true };
|
|
374
|
+
if (maskStatus === 'incomplete')
|
|
375
|
+
return { maskIncomplete: true };
|
|
376
|
+
return null;
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
if (this.inlineError())
|
|
380
|
+
validators.push(SdInlineErrorValidator);
|
|
381
|
+
return validators;
|
|
382
|
+
}, ...(ngDevMode ? [{ debugName: "#validators" }] : /* istanbul ignore next */ []));
|
|
383
|
+
#asyncValidators = computed(() => {
|
|
384
|
+
const validator = this.validator();
|
|
385
|
+
return validator ? [HandleSdCustomValidator(validator)] : [];
|
|
386
|
+
}, ...(ngDevMode ? [{ debugName: "#asyncValidators" }] : /* istanbul ignore next */ []));
|
|
387
|
+
#formConnector = _sdFormControlConnector({
|
|
388
|
+
form: this.form,
|
|
389
|
+
name: this.name,
|
|
390
|
+
control: computed(() => this.formControl),
|
|
391
|
+
validators: this.#validators,
|
|
392
|
+
asyncValidators: this.#asyncValidators,
|
|
393
|
+
required: this.required,
|
|
394
|
+
disabled: this.disabled,
|
|
395
|
+
readonly: this.readonly,
|
|
396
|
+
viewed: this.viewed,
|
|
397
|
+
validationError: computed(() => this.errorMessage()),
|
|
398
|
+
});
|
|
399
|
+
/** Shared reactive form policy consumed by template-facing state below. */
|
|
400
|
+
connectorState = this.#formConnector.state;
|
|
401
|
+
isReadonly = computed(() => this.connectorState().readonly, ...(ngDevMode ? [{ debugName: "isReadonly" }] : /* istanbul ignore next */ []));
|
|
402
|
+
visibleErrorMessage = computed(() => this.connectorState().validationError, ...(ngDevMode ? [{ debugName: "visibleErrorMessage" }] : /* istanbul ignore next */ []));
|
|
403
|
+
// Tri-state `viewed` — shared primitive. Input has NO panel; in `'inline'` the input is rendered
|
|
404
|
+
// borderless/transparent (looks like text), always editable — clicking/focusing it edits directly.
|
|
405
|
+
#viewedState = sdViewedInline(computed(() => this.connectorState().viewed), () => this.#focusActiveInput(), this.disabled);
|
|
406
|
+
/** `true` when `viewed === 'inline'`. */
|
|
407
|
+
isInline = this.#viewedState.isInline;
|
|
408
|
+
/** `true` when `viewed === true` (static view, no input). */
|
|
409
|
+
isViewed = this.#viewedState.isViewed;
|
|
410
|
+
/** Focus the inline input. No-op unless `viewed='inline'`. */
|
|
411
|
+
enterInlineEdit = () => this.#viewedState.enterInlineEdit();
|
|
204
412
|
constructor() {
|
|
205
413
|
effect(() => {
|
|
206
414
|
const val = this.valueModel();
|
|
415
|
+
const adapter = this.maskAdapter();
|
|
207
416
|
untracked(() => {
|
|
208
417
|
if (this.formControl.value !== val) {
|
|
209
418
|
this.formControl.setValue(val, { emitEvent: false });
|
|
210
419
|
}
|
|
420
|
+
if (adapter) {
|
|
421
|
+
const rawValue = val == null ? '' : String(val);
|
|
422
|
+
const result = this.#pendingMaskResult?.raw === rawValue ? this.#pendingMaskResult : adapter.format(rawValue);
|
|
423
|
+
this.#pendingMaskResult = undefined;
|
|
424
|
+
this.maskStatus.set(result.status);
|
|
425
|
+
if (this.displayControl.value !== result.display) {
|
|
426
|
+
this.displayControl.setValue(result.display, { emitEvent: false });
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
this.maskStatus.set('empty');
|
|
431
|
+
}
|
|
211
432
|
});
|
|
212
433
|
});
|
|
213
434
|
effect(() => {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
this.formControl.enable({ emitEvent: false });
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
effect(() => {
|
|
222
|
-
const req = this.required();
|
|
223
|
-
const min = this.minlength();
|
|
224
|
-
const max = this.maxlength();
|
|
225
|
-
const pat = this.resolvedPattern();
|
|
226
|
-
const inl = this.inlineError();
|
|
227
|
-
const val = this.validator();
|
|
435
|
+
const masked = !!this.maskAdapter();
|
|
436
|
+
const disabled = this.disabled();
|
|
228
437
|
untracked(() => {
|
|
229
|
-
|
|
438
|
+
if (masked && disabled)
|
|
439
|
+
this.displayControl.disable({ emitEvent: false });
|
|
440
|
+
else
|
|
441
|
+
this.displayControl.enable({ emitEvent: false });
|
|
230
442
|
});
|
|
231
443
|
});
|
|
232
444
|
}
|
|
@@ -237,37 +449,15 @@ class SdInput {
|
|
|
237
449
|
}
|
|
238
450
|
ngAfterViewInit() {
|
|
239
451
|
this.#subscription.add(this.formControl.valueChanges.subscribe(this.#onChange));
|
|
240
|
-
|
|
241
|
-
formGroup?.addControl(this.name(), this.formControl);
|
|
452
|
+
this.#subscription.add(this.displayControl.valueChanges.subscribe(value => this.#onMaskedDisplayChange(value)));
|
|
242
453
|
this.#ref.detectChanges();
|
|
243
454
|
}
|
|
244
455
|
ngOnDestroy() {
|
|
245
|
-
const formGroup = this.form();
|
|
246
|
-
formGroup?.removeControl(this.name());
|
|
247
456
|
this.#subscription.unsubscribe();
|
|
248
457
|
}
|
|
249
458
|
reValidate = () => {
|
|
250
459
|
this.formControl.updateValueAndValidity();
|
|
251
460
|
};
|
|
252
|
-
#updateValidator = (req, min, max, pat, inl, val) => {
|
|
253
|
-
const validators = [];
|
|
254
|
-
const asyncValidators = [];
|
|
255
|
-
if (req)
|
|
256
|
-
validators.push(Validators.required);
|
|
257
|
-
if (min && min > 0)
|
|
258
|
-
validators.push(Validators.minLength(min));
|
|
259
|
-
if (max && max > 0)
|
|
260
|
-
validators.push(Validators.maxLength(max));
|
|
261
|
-
if (pat)
|
|
262
|
-
validators.push(Validators.pattern(pat));
|
|
263
|
-
if (inl)
|
|
264
|
-
validators.push(SdInlineErrorValidator);
|
|
265
|
-
if (val)
|
|
266
|
-
asyncValidators.push(HandleSdCustomValidator(val));
|
|
267
|
-
this.formControl.setValidators(validators.length ? validators : null);
|
|
268
|
-
this.formControl.setAsyncValidators(asyncValidators.length ? asyncValidators : null);
|
|
269
|
-
this.formControl.updateValueAndValidity({ emitEvent: false });
|
|
270
|
-
};
|
|
271
461
|
getCurrentLength = () => {
|
|
272
462
|
return (this.formControl.value ?? '').toString().length;
|
|
273
463
|
};
|
|
@@ -280,6 +470,48 @@ class SdInput {
|
|
|
280
470
|
this.valueModel.set(value);
|
|
281
471
|
this.sdChange.emit(value);
|
|
282
472
|
};
|
|
473
|
+
#onMaskedDisplayChange(value) {
|
|
474
|
+
const adapter = this.maskAdapter();
|
|
475
|
+
if (!adapter || this.#isComposing)
|
|
476
|
+
return;
|
|
477
|
+
const nativeInput = this.control()?.nativeElement;
|
|
478
|
+
const display = value == null ? '' : String(value);
|
|
479
|
+
const result = adapter.parse(display, nativeInput?.selectionStart, nativeInput?.selectionEnd);
|
|
480
|
+
this.#applyMaskResult(result);
|
|
481
|
+
}
|
|
482
|
+
#applyMaskResult(result) {
|
|
483
|
+
this.maskStatus.set(result.status);
|
|
484
|
+
if (this.displayControl.value !== result.display) {
|
|
485
|
+
this.displayControl.setValue(result.display, { emitEvent: false });
|
|
486
|
+
}
|
|
487
|
+
if (this.formControl.value !== result.raw) {
|
|
488
|
+
this.#pendingMaskResult = this.valueModel() === result.raw ? undefined : result;
|
|
489
|
+
this.formControl.setValue(result.raw);
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
this.#pendingMaskResult = undefined;
|
|
493
|
+
this.formControl.updateValueAndValidity({ emitEvent: false });
|
|
494
|
+
}
|
|
495
|
+
queueMicrotask(() => {
|
|
496
|
+
const nativeInput = this.control()?.nativeElement;
|
|
497
|
+
if (nativeInput) {
|
|
498
|
+
nativeInput.setSelectionRange(result.selectionStart, result.selectionEnd);
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
onCompositionStart() {
|
|
503
|
+
if (this.maskAdapter())
|
|
504
|
+
this.#isComposing = true;
|
|
505
|
+
}
|
|
506
|
+
onCompositionEnd(event) {
|
|
507
|
+
const adapter = this.maskAdapter();
|
|
508
|
+
if (!adapter)
|
|
509
|
+
return;
|
|
510
|
+
this.#isComposing = false;
|
|
511
|
+
const target = event.target;
|
|
512
|
+
const display = target?.value ?? String(this.displayControl.value ?? '');
|
|
513
|
+
this.#applyMaskResult(adapter.parse(display, target?.selectionStart, target?.selectionEnd));
|
|
514
|
+
}
|
|
283
515
|
// why: dựa trên valueModel() (signal model-input) thay vì formControl.value —
|
|
284
516
|
// khi bị wrap (vd <sd-input-color>) effect set formControl chạy SAU lúc template
|
|
285
517
|
// eval nên formControl.value chưa kịp có; valueModel() thì có ngay. Method (không
|
|
@@ -297,13 +529,15 @@ class SdInput {
|
|
|
297
529
|
// why: clear là thao tác chủ động → model về null (không phải '' hay undefined).
|
|
298
530
|
// undefined chỉ dành cho trạng thái pristine chưa từng nhập.
|
|
299
531
|
this.formControl.setValue(null, { emitEvent: false });
|
|
532
|
+
this.displayControl.setValue('', { emitEvent: false });
|
|
533
|
+
this.maskStatus.set('empty');
|
|
300
534
|
this.valueModel.set(null);
|
|
301
535
|
this.sdChange.emit(null);
|
|
302
536
|
this.cleared.emit();
|
|
303
537
|
};
|
|
304
538
|
onKeyupEnter = () => {
|
|
305
539
|
const val = (this.formControl.value ?? '').toString();
|
|
306
|
-
if (val.length > val.trim().length) {
|
|
540
|
+
if (!this.maskAdapter() && val.length > val.trim().length) {
|
|
307
541
|
this.formControl.setValue(val.trim());
|
|
308
542
|
}
|
|
309
543
|
this.keyupEnter.emit(this.formControl.value);
|
|
@@ -322,7 +556,7 @@ class SdInput {
|
|
|
322
556
|
onBlur = () => {
|
|
323
557
|
this.isFocused = false;
|
|
324
558
|
const val = (this.formControl.value ?? '').toString();
|
|
325
|
-
if (val.length > val.trim().length) {
|
|
559
|
+
if (!this.maskAdapter() && val.length > val.trim().length) {
|
|
326
560
|
this.formControl.setValue(val.trim());
|
|
327
561
|
}
|
|
328
562
|
this.sdBlur.emit(this.formControl.value);
|
|
@@ -350,7 +584,7 @@ class SdInput {
|
|
|
350
584
|
}, 100);
|
|
351
585
|
};
|
|
352
586
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SdInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
353
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SdInput, isStandalone: true, selector: "sd-input", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, appearanceInput: { classPropertyName: "appearanceInput", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, floatLabel: { classPropertyName: "floatLabel", publicName: "floatLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", 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 }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, hideInlineError: { classPropertyName: "hideInlineError", publicName: "hideInlineError", isSignal: true, isRequired: false, transformFunction: null }, blurOnEnter: { classPropertyName: "blurOnEnter", publicName: "blurOnEnter", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", 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 }, minlength: { classPropertyName: "minlength", publicName: "minlength", isSignal: true, isRequired: false, transformFunction: null }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: false, transformFunction: null }, patternErrorMessage: { classPropertyName: "patternErrorMessage", publicName: "patternErrorMessage", isSignal: true, isRequired: false, transformFunction: null }, validator: { classPropertyName: "validator", publicName: "validator", isSignal: true, isRequired: false, transformFunction: null }, inlineError: { classPropertyName: "inlineError", publicName: "inlineError", isSignal: true, isRequired: false, transformFunction: null }, hyperlink: { classPropertyName: "hyperlink", publicName: "hyperlink", isSignal: true, isRequired: false, transformFunction: null }, valueModel: { classPropertyName: "valueModel", publicName: "model", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueModel: "modelChange", sdChange: "sdChange", sdFocus: "sdFocus", sdBlur: "sdBlur", keyupEnter: "keyupEnter", cleared: "cleared", sdFocusForceBlur: "sdFocusForceBlur" }, host: { properties: { "class.sd-has-label": "!!label()", "class.sd-viewed": "isViewed() || isInline()" } }, queries: [{ propertyName: "sdLabelTemplate", first: true, predicate: ["sdLabel"], descendants: true, isSignal: true }, { propertyName: "sdValueTemplate", first: true, predicate: ["sdValue"], descendants: true, isSignal: true }, { propertyName: "sdSuffixDef", first: true, predicate: SdSuffixDefDirective, descendants: true, isSignal: true }, { propertyName: "sdViewDef", first: true, predicate: SdViewDefDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "control", first: true, predicate: ["control"], descendants: true, isSignal: true }, { propertyName: "inlineRef", first: true, predicate: SdInlineText, descendants: true, isSignal: true }], ngImport: i0, template: "@let _label = label();\n@let _appearance = appearance();\n@let _hideInlineError = hideInlineError();\n@let _helperText = helperText();\n@let _maxLength = maxlength();\n@let _errorMessage = errorMessage();\n@let _required = required();\n@let _isInline = isInline();\n\n@if (isViewed()) {\n <sd-view\n [label]=\"_label\"\n [labelTemplate]=\"sdLabelTemplate()\"\n [value]=\"formControl.value\"\n [display]=\"formControl.value\"\n [hyperlink]=\"hyperlink()\"\n [valueTemplate]=\"viewTemplate()\">\n </sd-view>\n} @else if (_isInline) {\n <sd-inline-text\n [control]=\"formControl\"\n [placeholder]=\"placeholder() || _label || ''\"\n [clearable]=\"clearable() && !_required\"\n [autoId]=\"autoId()\"\n [state]=\"formControl.invalid && formControl.touched ? 'error' : 'auto'\"\n (sdFocus)=\"onFocus()\"\n (sdBlur)=\"onBlur()\"\n (keyupEnter)=\"onKeyupEnter()\"\n (cleared)=\"cleared.emit()\">\n </sd-inline-text>\n} @else {\n @if (!_appearance) {\n <ng-content select=\"[sdLabel]\">\n @if (_label) {\n <sd-label [label]=\"_label\" [required]=\"_required\"></sd-label>\n }\n </ng-content>\n }\n\n <div\n class=\"d-flex align-items-center sd-input-container\"\n [class.c-focused]=\"isFocused\"\n [class.c-disabled]=\"formControl.disabled\"\n (click)=\"onClick()\"\n aria-hidden=\"true\">\n <div class=\"sd-input-field-wrap\">\n <mat-form-field\n [class.sd-md]=\"size() === 'md'\"\n [class.sd-sm]=\"size() === 'sm'\"\n [class.hide-inline-error]=\"_hideInlineError\"\n [appearance]=\"_appearance!\"\n [floatLabel]=\"floatLabel()\">\n @if (_appearance && _label) {\n <mat-label class=\"sd-form-field-label\">\n <span>{{ _label }}</span>\n @if (_helperText) {\n <sd-icon [matTooltip]=\"_helperText\" matTooltipPosition=\"below\" name=\"info\"></sd-icon>\n }\n </mat-label>\n }\n\n <input\n aria-hidden=\"true\"\n [id]=\"id\"\n [formControl]=\"formControl\"\n [type]=\"type()\"\n #control\n matInput\n [placeholder]=\"placeholder() || _label || ''\"\n (keyup.enter)=\"onKeyupEnter()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n [required]=\"_required\"\n [readonly]=\"readonly()\"\n [autocomplete]=\"id\"\n autocorrect=\"off\"\n [step]=\"1\"\n [attr.data-autoId]=\"autoId()\"\n [attr.data-disabled]=\"dataDisabled()\"\n [attr.data-invalid]=\"dataInvalid()\"\n [attr.data-empty]=\"dataEmpty()\"\n [attr.data-value]=\"dataValue()\"\n [attr.data-required]=\"dataRequired()\"\n [attr.data-maxlength]=\"dataMaxLength()\"\n [attr.data-minlength]=\"dataMinLength()\"\n [attr.data-pattern]=\"dataPattern()\"\n [attr.data-error-message]=\"dataErrorMessage()\" />\n\n @if (!_hideInlineError && _errorMessage && formControl.touched) {\n <mat-error>{{ _errorMessage }}</mat-error>\n }\n\n <!-- why: n\u00FAt clear render TR\u01AF\u1EDAC error icon. Clear hover-gated (visibility:hidden) v\u1EABn\n chi\u1EBFm ch\u1ED7 trong layout \u2192 n\u1EBFu \u0111\u1EE9ng sau s\u1EBD \u0111\u1EA9y error icon \"t\u1EE5t v\u00E0o trong\". \u0110\u1EE9ng tr\u01B0\u1EDBc\n th\u00EC error icon n\u1EB1m s\u00E1t m\u00E9p ph\u1EA3i, clear gi\u1EEF slot v\u00F4 h\u00ECnh b\u00EAn tr\u00E1i. -->\n @if (showClear()) {\n <button type=\"button\" class=\"sd-clear-btn sd-hover\" matSuffix (click)=\"clear($event)\" title=\"X\u00F3a\" aria-label=\"X\u00F3a\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n }\n\n @if (_hideInlineError && _errorMessage && formControl.touched) {\n <sd-icon matSuffix class=\"sd-error-icon\" [matTooltip]=\"_errorMessage\" matTooltipPosition=\"above\" name=\"error\"></sd-icon>\n }\n\n @if (sdSuffixDef()?.templateRef; as suffixRef) {\n <ng-container matSuffix>\n <ng-container *ngTemplateOutlet=\"suffixRef\"></ng-container>\n </ng-container>\n }\n <!-- <ng-container matSuffix>\n <ng-content select=\"[sdSuffix]\"></ng-content>\n </ng-container> -->\n </mat-form-field>\n\n @if (_maxLength && !_hideInlineError && !formControl.disabled) {\n <div\n class=\"sd-maxlength-counter\"\n [class.sd-maxlength-counter--visible]=\"isFocused\"\n [class.sd-maxlength-counter--exceeded]=\"isMaxlengthExceeded()\"\n [attr.title]=\"isMaxlengthExceeded() ? ('core.form.input.exceeded' | translate) : null\">\n {{ getCurrentLength() }}/{{ _maxLength }}\n </div>\n }\n </div>\n </div>\n}\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-primary-contrast{color:var(--sd-primary-contrast)!important}.bg-primary-contrast{background:var(--sd-primary-contrast)!important}.border-primary-contrast{border-color:var(--sd-primary-contrast)!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-secondary-contrast{color:var(--sd-secondary-contrast)!important}.bg-secondary-contrast{background:var(--sd-secondary-contrast)!important}.border-secondary-contrast{border-color:var(--sd-secondary-contrast)!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-info-contrast{color:var(--sd-info-contrast)!important}.bg-info-contrast{background:var(--sd-info-contrast)!important}.border-info-contrast{border-color:var(--sd-info-contrast)!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-success-contrast{color:var(--sd-success-contrast)!important}.bg-success-contrast{background:var(--sd-success-contrast)!important}.border-success-contrast{border-color:var(--sd-success-contrast)!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-warning-contrast{color:var(--sd-warning-contrast)!important}.bg-warning-contrast{background:var(--sd-warning-contrast)!important}.border-warning-contrast{border-color:var(--sd-warning-contrast)!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-error-contrast{color:var(--sd-error-contrast)!important}.bg-error-contrast{background:var(--sd-error-contrast)!important}.border-error-contrast{border-color:var(--sd-error-contrast)!important}.text-surface{color:var(--sd-surface)!important}.bg-surface{background:var(--sd-surface)!important}.border-surface{border-color:var(--sd-surface)!important}.text-surface-muted{color:var(--sd-surface-muted)!important}.bg-surface-muted{background:var(--sd-surface-muted)!important}.border-surface-muted{border-color:var(--sd-surface-muted)!important}.text-text{color:var(--sd-text)!important}.bg-text{background:var(--sd-text)!important}.border-text{border-color:var(--sd-text)!important}.text-text-secondary{color:var(--sd-text-secondary)!important}.bg-text-secondary{background:var(--sd-text-secondary)!important}.border-text-secondary{border-color:var(--sd-text-secondary)!important}.text-text-muted{color:var(--sd-text-muted)!important}.bg-text-muted{background:var(--sd-text-muted)!important}.border-text-muted{border-color:var(--sd-text-muted)!important}.text-border{color:var(--sd-border)!important}.bg-border{background:var(--sd-border)!important}.border-border{border-color:var(--sd-border)!important}.text-border-strong{color:var(--sd-border-strong)!important}.bg-border-strong{background:var(--sd-border-strong)!important}.border-border-strong{border-color:var(--sd-border-strong)!important}.text-disabled-bg{color:var(--sd-disabled-bg)!important}.bg-disabled-bg{background:var(--sd-disabled-bg)!important}.border-disabled-bg{border-color:var(--sd-disabled-bg)!important}.text-disabled-text{color:var(--sd-disabled-text)!important}.bg-disabled-text{background:var(--sd-disabled-text)!important}.border-disabled-text{border-color:var(--sd-disabled-text)!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}.text-secondary{color:var(--sd-text-secondary)!important}.text-muted{color:var(--sd-text-muted)!important}.text-body{color:var(--sd-text)!important}.bg-muted{background:var(--sd-surface-muted)!important}:host{display:block}:host(.sd-has-label){padding-top:4px}:host(.sd-viewed){padding-top:0}:host ::ng-deep .mat-mdc-form-field.mat-form-field-appearance-outline.mat-form-field-disabled .mat-mdc-text-field-wrapper{background:var(--sd-disabled-bg)}:host ::ng-deep .mat-mdc-form-field input.mat-mdc-input-element:disabled{color:var(--sd-disabled-text)!important}:host ::ng-deep .mat-mdc-form-field .mat-mdc-placeholder-required{color:var(--sd-error)}.sd-input-field-wrap{position:relative;flex:1;min-width:0}.sd-maxlength-counter{position:absolute;right:4px;top:calc(100% - 16px);opacity:0;font-size:10px;line-height:1.1;color:#00000061;pointer-events:none;transition:opacity .12s ease;z-index:1}.sd-maxlength-counter--exceeded{color:var(--sd-error);font-weight:600}:host ::ng-deep .sd-input-container.c-focused .sd-maxlength-counter,:host ::ng-deep .sd-input-container:hover .sd-maxlength-counter,:host ::ng-deep .sd-input-container .sd-maxlength-counter.sd-maxlength-counter--visible{opacity:1}.sd-md:hover .btn-copy{visibility:visible}\n"], dependencies: [{ kind: "component", type: SdIcon, selector: "sd-icon", inputs: ["name", "fontIcon", "color", "set", "fontSet", "size", "strokeWidth", "absoluteStrokeWidth", "ariaLabel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: SdLabel, selector: "sd-label", inputs: ["label", "description", "required", "helperText"] }, { kind: "component", type: SdView, selector: "sd-view", inputs: ["label", "value", "display", "hyperlink", "labelTemplate", "valueTemplate", "selectedItems"] }, { kind: "component", type: SdInlineText, selector: "sd-inline-text", inputs: ["value", "control", "placeholder", "disabled", "clearable", "state", "chrome", "autoId", "autofocus", "minSize"], outputs: ["valueChange", "cleared", "keyupEnter", "keydownEscape", "sdFocus", "sdBlur", "sdKeydown", "sdPaste", "sdCompositionStart", "sdCompositionEnd"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
587
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.17", type: SdInput, isStandalone: true, selector: "sd-input", inputs: { autoIdInput: { classPropertyName: "autoIdInput", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, appearanceInput: { classPropertyName: "appearanceInput", publicName: "appearance", isSignal: true, isRequired: false, transformFunction: null }, floatLabel: { classPropertyName: "floatLabel", publicName: "floatLabel", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", 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 }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, mask: { classPropertyName: "mask", publicName: "mask", isSignal: true, isRequired: false, transformFunction: null }, hideInlineError: { classPropertyName: "hideInlineError", publicName: "hideInlineError", isSignal: true, isRequired: false, transformFunction: null }, blurOnEnter: { classPropertyName: "blurOnEnter", publicName: "blurOnEnter", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", 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 }, minlength: { classPropertyName: "minlength", publicName: "minlength", isSignal: true, isRequired: false, transformFunction: null }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: false, transformFunction: null }, patternErrorMessage: { classPropertyName: "patternErrorMessage", publicName: "patternErrorMessage", isSignal: true, isRequired: false, transformFunction: null }, validator: { classPropertyName: "validator", publicName: "validator", isSignal: true, isRequired: false, transformFunction: null }, inlineError: { classPropertyName: "inlineError", publicName: "inlineError", isSignal: true, isRequired: false, transformFunction: null }, hyperlink: { classPropertyName: "hyperlink", publicName: "hyperlink", isSignal: true, isRequired: false, transformFunction: null }, valueModel: { classPropertyName: "valueModel", publicName: "model", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueModel: "modelChange", sdChange: "sdChange", sdFocus: "sdFocus", sdBlur: "sdBlur", keyupEnter: "keyupEnter", cleared: "cleared", sdFocusForceBlur: "sdFocusForceBlur" }, host: { properties: { "class.sd-has-label": "!!label()", "class.sd-viewed": "isViewed() || isInline()" } }, queries: [{ propertyName: "sdLabelTemplate", first: true, predicate: ["sdLabel"], descendants: true, isSignal: true }, { propertyName: "sdValueTemplate", first: true, predicate: ["sdValue"], descendants: true, isSignal: true }, { propertyName: "sdSuffixDef", first: true, predicate: SdSuffixDefDirective, descendants: true, isSignal: true }, { propertyName: "sdViewDef", first: true, predicate: SdViewDefDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "control", first: true, predicate: ["control"], descendants: true, isSignal: true }, { propertyName: "inlineRef", first: true, predicate: SdInlineText, descendants: true, isSignal: true }], ngImport: i0, template: "@let _label = label();\n@let _appearance = appearance();\n@let _hideInlineError = hideInlineError();\n@let _helperText = helperText();\n@let _maxLength = maxlength();\n@let _errorMessage = visibleErrorMessage();\n@let _required = required();\n@let _isInline = isInline();\n\n@if (isViewed()) {\n <sd-view\n [label]=\"_label\"\n [labelTemplate]=\"sdLabelTemplate()\"\n [value]=\"formControl.value\"\n [display]=\"displayValue()\"\n [hyperlink]=\"hyperlink()\"\n [valueTemplate]=\"viewTemplate()\">\n </sd-view>\n} @else if (_isInline) {\n <sd-inline-text\n [control]=\"activeControl()\"\n [placeholder]=\"placeholder() || _label || ''\"\n [clearable]=\"clearable() && !_required\"\n [autoId]=\"autoId()\"\n [state]=\"connectorState().invalid ? 'error' : 'auto'\"\n (sdFocus)=\"onFocus()\"\n (sdBlur)=\"onBlur()\"\n (keyupEnter)=\"onKeyupEnter()\"\n (cleared)=\"cleared.emit()\">\n </sd-inline-text>\n} @else {\n @if (!_appearance) {\n <ng-content select=\"[sdLabel]\">\n @if (_label) {\n <sd-label [label]=\"_label\" [required]=\"_required\"></sd-label>\n }\n </ng-content>\n }\n\n <div\n class=\"d-flex align-items-center sd-input-container\"\n [class.c-focused]=\"isFocused\"\n [class.c-disabled]=\"formControl.disabled\"\n (click)=\"onClick()\"\n aria-hidden=\"true\">\n <div class=\"sd-input-field-wrap\">\n <mat-form-field\n [class.sd-md]=\"size() === 'md'\"\n [class.sd-sm]=\"size() === 'sm'\"\n [class.hide-inline-error]=\"_hideInlineError\"\n [appearance]=\"_appearance!\"\n [floatLabel]=\"floatLabel()\">\n @if (_appearance && _label) {\n <mat-label class=\"sd-form-field-label\">\n <span>{{ _label }}</span>\n @if (_helperText) {\n <sd-icon [matTooltip]=\"_helperText\" matTooltipPosition=\"below\" name=\"info\"></sd-icon>\n }\n </mat-label>\n }\n\n <input\n aria-hidden=\"true\"\n [id]=\"id\"\n [formControl]=\"activeControl()\"\n [type]=\"effectiveType()\"\n #control\n matInput\n [placeholder]=\"placeholder() || _label || ''\"\n (keyup.enter)=\"onKeyupEnter()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n [required]=\"_required\"\n [readonly]=\"isReadonly()\"\n [autocomplete]=\"id\"\n autocorrect=\"off\"\n [step]=\"1\"\n [attr.inputmode]=\"inputMode()\"\n [attr.maxlength]=\"maxDisplayLength()\"\n [attr.data-autoId]=\"autoId()\"\n [attr.data-disabled]=\"dataDisabled()\"\n [attr.data-invalid]=\"dataInvalid()\"\n [attr.data-empty]=\"dataEmpty()\"\n [attr.data-value]=\"dataValue()\"\n [attr.data-required]=\"dataRequired()\"\n [attr.data-maxlength]=\"dataMaxLength()\"\n [attr.data-minlength]=\"dataMinLength()\"\n [attr.data-pattern]=\"dataPattern()\"\n [attr.data-error-message]=\"dataErrorMessage()\"\n (compositionstart)=\"onCompositionStart()\"\n (compositionend)=\"onCompositionEnd($event)\" />\n\n @if (!_hideInlineError && _errorMessage) {\n <mat-error>{{ _errorMessage }}</mat-error>\n }\n\n <!-- why: n\u00FAt clear render TR\u01AF\u1EDAC error icon. Clear hover-gated (visibility:hidden) v\u1EABn\n chi\u1EBFm ch\u1ED7 trong layout \u2192 n\u1EBFu \u0111\u1EE9ng sau s\u1EBD \u0111\u1EA9y error icon \"t\u1EE5t v\u00E0o trong\". \u0110\u1EE9ng tr\u01B0\u1EDBc\n th\u00EC error icon n\u1EB1m s\u00E1t m\u00E9p ph\u1EA3i, clear gi\u1EEF slot v\u00F4 h\u00ECnh b\u00EAn tr\u00E1i. -->\n @if (showClear()) {\n <button type=\"button\" class=\"sd-clear-btn sd-hover\" matSuffix (click)=\"clear($event)\" title=\"X\u00F3a\" aria-label=\"X\u00F3a\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n }\n\n @if (_hideInlineError && _errorMessage) {\n <sd-icon matSuffix class=\"sd-error-icon\" [matTooltip]=\"_errorMessage\" matTooltipPosition=\"above\" name=\"error\"></sd-icon>\n }\n\n @if (sdSuffixDef()?.templateRef; as suffixRef) {\n <ng-container matSuffix>\n <ng-container *ngTemplateOutlet=\"suffixRef\"></ng-container>\n </ng-container>\n }\n <!-- <ng-container matSuffix>\n <ng-content select=\"[sdSuffix]\"></ng-content>\n </ng-container> -->\n </mat-form-field>\n\n @if (_maxLength && !_hideInlineError && !formControl.disabled) {\n <div\n class=\"sd-maxlength-counter\"\n [class.sd-maxlength-counter--visible]=\"isFocused\"\n [class.sd-maxlength-counter--exceeded]=\"isMaxlengthExceeded()\"\n [attr.title]=\"isMaxlengthExceeded() ? ('core.form.input.exceeded' | translate) : null\">\n {{ getCurrentLength() }}/{{ _maxLength }}\n </div>\n }\n </div>\n </div>\n}\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-primary-contrast{color:var(--sd-primary-contrast)!important}.bg-primary-contrast{background:var(--sd-primary-contrast)!important}.border-primary-contrast{border-color:var(--sd-primary-contrast)!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-secondary-contrast{color:var(--sd-secondary-contrast)!important}.bg-secondary-contrast{background:var(--sd-secondary-contrast)!important}.border-secondary-contrast{border-color:var(--sd-secondary-contrast)!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-info-contrast{color:var(--sd-info-contrast)!important}.bg-info-contrast{background:var(--sd-info-contrast)!important}.border-info-contrast{border-color:var(--sd-info-contrast)!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-success-contrast{color:var(--sd-success-contrast)!important}.bg-success-contrast{background:var(--sd-success-contrast)!important}.border-success-contrast{border-color:var(--sd-success-contrast)!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-warning-contrast{color:var(--sd-warning-contrast)!important}.bg-warning-contrast{background:var(--sd-warning-contrast)!important}.border-warning-contrast{border-color:var(--sd-warning-contrast)!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-error-contrast{color:var(--sd-error-contrast)!important}.bg-error-contrast{background:var(--sd-error-contrast)!important}.border-error-contrast{border-color:var(--sd-error-contrast)!important}.text-surface{color:var(--sd-surface)!important}.bg-surface{background:var(--sd-surface)!important}.border-surface{border-color:var(--sd-surface)!important}.text-surface-muted{color:var(--sd-surface-muted)!important}.bg-surface-muted{background:var(--sd-surface-muted)!important}.border-surface-muted{border-color:var(--sd-surface-muted)!important}.text-text{color:var(--sd-text)!important}.bg-text{background:var(--sd-text)!important}.border-text{border-color:var(--sd-text)!important}.text-text-secondary{color:var(--sd-text-secondary)!important}.bg-text-secondary{background:var(--sd-text-secondary)!important}.border-text-secondary{border-color:var(--sd-text-secondary)!important}.text-text-muted{color:var(--sd-text-muted)!important}.bg-text-muted{background:var(--sd-text-muted)!important}.border-text-muted{border-color:var(--sd-text-muted)!important}.text-border{color:var(--sd-border)!important}.bg-border{background:var(--sd-border)!important}.border-border{border-color:var(--sd-border)!important}.text-border-strong{color:var(--sd-border-strong)!important}.bg-border-strong{background:var(--sd-border-strong)!important}.border-border-strong{border-color:var(--sd-border-strong)!important}.text-disabled-bg{color:var(--sd-disabled-bg)!important}.bg-disabled-bg{background:var(--sd-disabled-bg)!important}.border-disabled-bg{border-color:var(--sd-disabled-bg)!important}.text-disabled-text{color:var(--sd-disabled-text)!important}.bg-disabled-text{background:var(--sd-disabled-text)!important}.border-disabled-text{border-color:var(--sd-disabled-text)!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}.text-secondary{color:var(--sd-text-secondary)!important}.text-muted{color:var(--sd-text-muted)!important}.text-body{color:var(--sd-text)!important}.bg-muted{background:var(--sd-surface-muted)!important}:host{display:block}:host(.sd-has-label){padding-top:4px}:host(.sd-viewed){padding-top:0}:host ::ng-deep .mat-mdc-form-field.mat-form-field-appearance-outline.mat-form-field-disabled .mat-mdc-text-field-wrapper{background:var(--sd-disabled-bg)}:host ::ng-deep .mat-mdc-form-field input.mat-mdc-input-element:disabled{color:var(--sd-disabled-text)!important}:host ::ng-deep .mat-mdc-form-field .mat-mdc-placeholder-required{color:var(--sd-error)}.sd-input-field-wrap{position:relative;flex:1;min-width:0}.sd-maxlength-counter{position:absolute;right:4px;top:calc(100% - 16px);opacity:0;font-size:10px;line-height:1.1;color:#00000061;pointer-events:none;transition:opacity .12s ease;z-index:1}.sd-maxlength-counter--exceeded{color:var(--sd-error);font-weight:600}:host ::ng-deep .sd-input-container.c-focused .sd-maxlength-counter,:host ::ng-deep .sd-input-container:hover .sd-maxlength-counter,:host ::ng-deep .sd-input-container .sd-maxlength-counter.sd-maxlength-counter--visible{opacity:1}.sd-md:hover .btn-copy{visibility:visible}\n"], dependencies: [{ kind: "component", type: SdIcon, selector: "sd-icon", inputs: ["name", "fontIcon", "color", "set", "fontSet", "size", "strokeWidth", "absoluteStrokeWidth", "ariaLabel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: SdLabel, selector: "sd-label", inputs: ["label", "description", "required", "helperText"] }, { kind: "component", type: SdView, selector: "sd-view", inputs: ["label", "value", "display", "hyperlink", "labelTemplate", "valueTemplate", "selectedItems"] }, { kind: "component", type: SdInlineText, selector: "sd-inline-text", inputs: ["value", "control", "placeholder", "disabled", "clearable", "state", "chrome", "autoId", "autofocus", "minSize"], outputs: ["valueChange", "cleared", "keyupEnter", "keydownEscape", "sdFocus", "sdBlur", "sdKeydown", "sdPaste", "sdCompositionStart", "sdCompositionEnd"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
354
588
|
}
|
|
355
589
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: SdInput, decorators: [{
|
|
356
590
|
type: Component,
|
|
@@ -367,8 +601,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
367
601
|
SdView,
|
|
368
602
|
SdInlineText,
|
|
369
603
|
TranslatePipe,
|
|
370
|
-
], template: "@let _label = label();\n@let _appearance = appearance();\n@let _hideInlineError = hideInlineError();\n@let _helperText = helperText();\n@let _maxLength = maxlength();\n@let _errorMessage = errorMessage();\n@let _required = required();\n@let _isInline = isInline();\n\n@if (isViewed()) {\n <sd-view\n [label]=\"_label\"\n [labelTemplate]=\"sdLabelTemplate()\"\n [value]=\"formControl.value\"\n [display]=\"formControl.value\"\n [hyperlink]=\"hyperlink()\"\n [valueTemplate]=\"viewTemplate()\">\n </sd-view>\n} @else if (_isInline) {\n <sd-inline-text\n [control]=\"formControl\"\n [placeholder]=\"placeholder() || _label || ''\"\n [clearable]=\"clearable() && !_required\"\n [autoId]=\"autoId()\"\n [state]=\"formControl.invalid && formControl.touched ? 'error' : 'auto'\"\n (sdFocus)=\"onFocus()\"\n (sdBlur)=\"onBlur()\"\n (keyupEnter)=\"onKeyupEnter()\"\n (cleared)=\"cleared.emit()\">\n </sd-inline-text>\n} @else {\n @if (!_appearance) {\n <ng-content select=\"[sdLabel]\">\n @if (_label) {\n <sd-label [label]=\"_label\" [required]=\"_required\"></sd-label>\n }\n </ng-content>\n }\n\n <div\n class=\"d-flex align-items-center sd-input-container\"\n [class.c-focused]=\"isFocused\"\n [class.c-disabled]=\"formControl.disabled\"\n (click)=\"onClick()\"\n aria-hidden=\"true\">\n <div class=\"sd-input-field-wrap\">\n <mat-form-field\n [class.sd-md]=\"size() === 'md'\"\n [class.sd-sm]=\"size() === 'sm'\"\n [class.hide-inline-error]=\"_hideInlineError\"\n [appearance]=\"_appearance!\"\n [floatLabel]=\"floatLabel()\">\n @if (_appearance && _label) {\n <mat-label class=\"sd-form-field-label\">\n <span>{{ _label }}</span>\n @if (_helperText) {\n <sd-icon [matTooltip]=\"_helperText\" matTooltipPosition=\"below\" name=\"info\"></sd-icon>\n }\n </mat-label>\n }\n\n <input\n aria-hidden=\"true\"\n [id]=\"id\"\n [formControl]=\"formControl\"\n [type]=\"type()\"\n #control\n matInput\n [placeholder]=\"placeholder() || _label || ''\"\n (keyup.enter)=\"onKeyupEnter()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n [required]=\"_required\"\n [readonly]=\"readonly()\"\n [autocomplete]=\"id\"\n autocorrect=\"off\"\n [step]=\"1\"\n [attr.data-autoId]=\"autoId()\"\n [attr.data-disabled]=\"dataDisabled()\"\n [attr.data-invalid]=\"dataInvalid()\"\n [attr.data-empty]=\"dataEmpty()\"\n [attr.data-value]=\"dataValue()\"\n [attr.data-required]=\"dataRequired()\"\n [attr.data-maxlength]=\"dataMaxLength()\"\n [attr.data-minlength]=\"dataMinLength()\"\n [attr.data-pattern]=\"dataPattern()\"\n [attr.data-error-message]=\"dataErrorMessage()\" />\n\n @if (!_hideInlineError && _errorMessage && formControl.touched) {\n <mat-error>{{ _errorMessage }}</mat-error>\n }\n\n <!-- why: n\u00FAt clear render TR\u01AF\u1EDAC error icon. Clear hover-gated (visibility:hidden) v\u1EABn\n chi\u1EBFm ch\u1ED7 trong layout \u2192 n\u1EBFu \u0111\u1EE9ng sau s\u1EBD \u0111\u1EA9y error icon \"t\u1EE5t v\u00E0o trong\". \u0110\u1EE9ng tr\u01B0\u1EDBc\n th\u00EC error icon n\u1EB1m s\u00E1t m\u00E9p ph\u1EA3i, clear gi\u1EEF slot v\u00F4 h\u00ECnh b\u00EAn tr\u00E1i. -->\n @if (showClear()) {\n <button type=\"button\" class=\"sd-clear-btn sd-hover\" matSuffix (click)=\"clear($event)\" title=\"X\u00F3a\" aria-label=\"X\u00F3a\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n }\n\n @if (_hideInlineError && _errorMessage && formControl.touched) {\n <sd-icon matSuffix class=\"sd-error-icon\" [matTooltip]=\"_errorMessage\" matTooltipPosition=\"above\" name=\"error\"></sd-icon>\n }\n\n @if (sdSuffixDef()?.templateRef; as suffixRef) {\n <ng-container matSuffix>\n <ng-container *ngTemplateOutlet=\"suffixRef\"></ng-container>\n </ng-container>\n }\n <!-- <ng-container matSuffix>\n <ng-content select=\"[sdSuffix]\"></ng-content>\n </ng-container> -->\n </mat-form-field>\n\n @if (_maxLength && !_hideInlineError && !formControl.disabled) {\n <div\n class=\"sd-maxlength-counter\"\n [class.sd-maxlength-counter--visible]=\"isFocused\"\n [class.sd-maxlength-counter--exceeded]=\"isMaxlengthExceeded()\"\n [attr.title]=\"isMaxlengthExceeded() ? ('core.form.input.exceeded' | translate) : null\">\n {{ getCurrentLength() }}/{{ _maxLength }}\n </div>\n }\n </div>\n </div>\n}\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-primary-contrast{color:var(--sd-primary-contrast)!important}.bg-primary-contrast{background:var(--sd-primary-contrast)!important}.border-primary-contrast{border-color:var(--sd-primary-contrast)!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-secondary-contrast{color:var(--sd-secondary-contrast)!important}.bg-secondary-contrast{background:var(--sd-secondary-contrast)!important}.border-secondary-contrast{border-color:var(--sd-secondary-contrast)!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-info-contrast{color:var(--sd-info-contrast)!important}.bg-info-contrast{background:var(--sd-info-contrast)!important}.border-info-contrast{border-color:var(--sd-info-contrast)!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-success-contrast{color:var(--sd-success-contrast)!important}.bg-success-contrast{background:var(--sd-success-contrast)!important}.border-success-contrast{border-color:var(--sd-success-contrast)!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-warning-contrast{color:var(--sd-warning-contrast)!important}.bg-warning-contrast{background:var(--sd-warning-contrast)!important}.border-warning-contrast{border-color:var(--sd-warning-contrast)!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-error-contrast{color:var(--sd-error-contrast)!important}.bg-error-contrast{background:var(--sd-error-contrast)!important}.border-error-contrast{border-color:var(--sd-error-contrast)!important}.text-surface{color:var(--sd-surface)!important}.bg-surface{background:var(--sd-surface)!important}.border-surface{border-color:var(--sd-surface)!important}.text-surface-muted{color:var(--sd-surface-muted)!important}.bg-surface-muted{background:var(--sd-surface-muted)!important}.border-surface-muted{border-color:var(--sd-surface-muted)!important}.text-text{color:var(--sd-text)!important}.bg-text{background:var(--sd-text)!important}.border-text{border-color:var(--sd-text)!important}.text-text-secondary{color:var(--sd-text-secondary)!important}.bg-text-secondary{background:var(--sd-text-secondary)!important}.border-text-secondary{border-color:var(--sd-text-secondary)!important}.text-text-muted{color:var(--sd-text-muted)!important}.bg-text-muted{background:var(--sd-text-muted)!important}.border-text-muted{border-color:var(--sd-text-muted)!important}.text-border{color:var(--sd-border)!important}.bg-border{background:var(--sd-border)!important}.border-border{border-color:var(--sd-border)!important}.text-border-strong{color:var(--sd-border-strong)!important}.bg-border-strong{background:var(--sd-border-strong)!important}.border-border-strong{border-color:var(--sd-border-strong)!important}.text-disabled-bg{color:var(--sd-disabled-bg)!important}.bg-disabled-bg{background:var(--sd-disabled-bg)!important}.border-disabled-bg{border-color:var(--sd-disabled-bg)!important}.text-disabled-text{color:var(--sd-disabled-text)!important}.bg-disabled-text{background:var(--sd-disabled-text)!important}.border-disabled-text{border-color:var(--sd-disabled-text)!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}.text-secondary{color:var(--sd-text-secondary)!important}.text-muted{color:var(--sd-text-muted)!important}.text-body{color:var(--sd-text)!important}.bg-muted{background:var(--sd-surface-muted)!important}:host{display:block}:host(.sd-has-label){padding-top:4px}:host(.sd-viewed){padding-top:0}:host ::ng-deep .mat-mdc-form-field.mat-form-field-appearance-outline.mat-form-field-disabled .mat-mdc-text-field-wrapper{background:var(--sd-disabled-bg)}:host ::ng-deep .mat-mdc-form-field input.mat-mdc-input-element:disabled{color:var(--sd-disabled-text)!important}:host ::ng-deep .mat-mdc-form-field .mat-mdc-placeholder-required{color:var(--sd-error)}.sd-input-field-wrap{position:relative;flex:1;min-width:0}.sd-maxlength-counter{position:absolute;right:4px;top:calc(100% - 16px);opacity:0;font-size:10px;line-height:1.1;color:#00000061;pointer-events:none;transition:opacity .12s ease;z-index:1}.sd-maxlength-counter--exceeded{color:var(--sd-error);font-weight:600}:host ::ng-deep .sd-input-container.c-focused .sd-maxlength-counter,:host ::ng-deep .sd-input-container:hover .sd-maxlength-counter,:host ::ng-deep .sd-input-container .sd-maxlength-counter.sd-maxlength-counter--visible{opacity:1}.sd-md:hover .btn-copy{visibility:visible}\n"] }]
|
|
371
|
-
}], ctorParameters: () => [], propDecorators: { control: [{ type: i0.ViewChild, args: ['control', { isSignal: true }] }], inlineRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SdInlineText), { isSignal: true }] }], sdLabelTemplate: [{ type: i0.ContentChild, args: ['sdLabel', { isSignal: true }] }], sdValueTemplate: [{ type: i0.ContentChild, args: ['sdValue', { isSignal: true }] }], sdSuffixDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdSuffixDefDirective), { isSignal: true }] }], sdViewDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdViewDefDirective), { isSignal: true }] }], autoIdInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoId", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], appearanceInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], floatLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "floatLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], hideInlineError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideInlineError", required: false }] }], blurOnEnter: [{ type: i0.Input, args: [{ isSignal: true, alias: "blurOnEnter", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], viewed: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewed", required: false }] }], minlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minlength", required: false }] }], maxlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxlength", required: false }] }], pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: false }] }], patternErrorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "patternErrorMessage", required: false }] }], validator: [{ type: i0.Input, args: [{ isSignal: true, alias: "validator", required: false }] }], inlineError: [{ type: i0.Input, args: [{ isSignal: true, alias: "inlineError", required: false }] }], hyperlink: [{ type: i0.Input, args: [{ isSignal: true, alias: "hyperlink", required: false }] }], valueModel: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }, { type: i0.Output, args: ["modelChange"] }], sdChange: [{ type: i0.Output, args: ["sdChange"] }], sdFocus: [{ type: i0.Output, args: ["sdFocus"] }], sdBlur: [{ type: i0.Output, args: ["sdBlur"] }], keyupEnter: [{ type: i0.Output, args: ["keyupEnter"] }], cleared: [{ type: i0.Output, args: ["cleared"] }], sdFocusForceBlur: [{
|
|
604
|
+
], template: "@let _label = label();\n@let _appearance = appearance();\n@let _hideInlineError = hideInlineError();\n@let _helperText = helperText();\n@let _maxLength = maxlength();\n@let _errorMessage = visibleErrorMessage();\n@let _required = required();\n@let _isInline = isInline();\n\n@if (isViewed()) {\n <sd-view\n [label]=\"_label\"\n [labelTemplate]=\"sdLabelTemplate()\"\n [value]=\"formControl.value\"\n [display]=\"displayValue()\"\n [hyperlink]=\"hyperlink()\"\n [valueTemplate]=\"viewTemplate()\">\n </sd-view>\n} @else if (_isInline) {\n <sd-inline-text\n [control]=\"activeControl()\"\n [placeholder]=\"placeholder() || _label || ''\"\n [clearable]=\"clearable() && !_required\"\n [autoId]=\"autoId()\"\n [state]=\"connectorState().invalid ? 'error' : 'auto'\"\n (sdFocus)=\"onFocus()\"\n (sdBlur)=\"onBlur()\"\n (keyupEnter)=\"onKeyupEnter()\"\n (cleared)=\"cleared.emit()\">\n </sd-inline-text>\n} @else {\n @if (!_appearance) {\n <ng-content select=\"[sdLabel]\">\n @if (_label) {\n <sd-label [label]=\"_label\" [required]=\"_required\"></sd-label>\n }\n </ng-content>\n }\n\n <div\n class=\"d-flex align-items-center sd-input-container\"\n [class.c-focused]=\"isFocused\"\n [class.c-disabled]=\"formControl.disabled\"\n (click)=\"onClick()\"\n aria-hidden=\"true\">\n <div class=\"sd-input-field-wrap\">\n <mat-form-field\n [class.sd-md]=\"size() === 'md'\"\n [class.sd-sm]=\"size() === 'sm'\"\n [class.hide-inline-error]=\"_hideInlineError\"\n [appearance]=\"_appearance!\"\n [floatLabel]=\"floatLabel()\">\n @if (_appearance && _label) {\n <mat-label class=\"sd-form-field-label\">\n <span>{{ _label }}</span>\n @if (_helperText) {\n <sd-icon [matTooltip]=\"_helperText\" matTooltipPosition=\"below\" name=\"info\"></sd-icon>\n }\n </mat-label>\n }\n\n <input\n aria-hidden=\"true\"\n [id]=\"id\"\n [formControl]=\"activeControl()\"\n [type]=\"effectiveType()\"\n #control\n matInput\n [placeholder]=\"placeholder() || _label || ''\"\n (keyup.enter)=\"onKeyupEnter()\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n [required]=\"_required\"\n [readonly]=\"isReadonly()\"\n [autocomplete]=\"id\"\n autocorrect=\"off\"\n [step]=\"1\"\n [attr.inputmode]=\"inputMode()\"\n [attr.maxlength]=\"maxDisplayLength()\"\n [attr.data-autoId]=\"autoId()\"\n [attr.data-disabled]=\"dataDisabled()\"\n [attr.data-invalid]=\"dataInvalid()\"\n [attr.data-empty]=\"dataEmpty()\"\n [attr.data-value]=\"dataValue()\"\n [attr.data-required]=\"dataRequired()\"\n [attr.data-maxlength]=\"dataMaxLength()\"\n [attr.data-minlength]=\"dataMinLength()\"\n [attr.data-pattern]=\"dataPattern()\"\n [attr.data-error-message]=\"dataErrorMessage()\"\n (compositionstart)=\"onCompositionStart()\"\n (compositionend)=\"onCompositionEnd($event)\" />\n\n @if (!_hideInlineError && _errorMessage) {\n <mat-error>{{ _errorMessage }}</mat-error>\n }\n\n <!-- why: n\u00FAt clear render TR\u01AF\u1EDAC error icon. Clear hover-gated (visibility:hidden) v\u1EABn\n chi\u1EBFm ch\u1ED7 trong layout \u2192 n\u1EBFu \u0111\u1EE9ng sau s\u1EBD \u0111\u1EA9y error icon \"t\u1EE5t v\u00E0o trong\". \u0110\u1EE9ng tr\u01B0\u1EDBc\n th\u00EC error icon n\u1EB1m s\u00E1t m\u00E9p ph\u1EA3i, clear gi\u1EEF slot v\u00F4 h\u00ECnh b\u00EAn tr\u00E1i. -->\n @if (showClear()) {\n <button type=\"button\" class=\"sd-clear-btn sd-hover\" matSuffix (click)=\"clear($event)\" title=\"X\u00F3a\" aria-label=\"X\u00F3a\">\n <sd-icon name=\"close\"></sd-icon>\n </button>\n }\n\n @if (_hideInlineError && _errorMessage) {\n <sd-icon matSuffix class=\"sd-error-icon\" [matTooltip]=\"_errorMessage\" matTooltipPosition=\"above\" name=\"error\"></sd-icon>\n }\n\n @if (sdSuffixDef()?.templateRef; as suffixRef) {\n <ng-container matSuffix>\n <ng-container *ngTemplateOutlet=\"suffixRef\"></ng-container>\n </ng-container>\n }\n <!-- <ng-container matSuffix>\n <ng-content select=\"[sdSuffix]\"></ng-content>\n </ng-container> -->\n </mat-form-field>\n\n @if (_maxLength && !_hideInlineError && !formControl.disabled) {\n <div\n class=\"sd-maxlength-counter\"\n [class.sd-maxlength-counter--visible]=\"isFocused\"\n [class.sd-maxlength-counter--exceeded]=\"isMaxlengthExceeded()\"\n [attr.title]=\"isMaxlengthExceeded() ? ('core.form.input.exceeded' | translate) : null\">\n {{ getCurrentLength() }}/{{ _maxLength }}\n </div>\n }\n </div>\n </div>\n}\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-primary-contrast{color:var(--sd-primary-contrast)!important}.bg-primary-contrast{background:var(--sd-primary-contrast)!important}.border-primary-contrast{border-color:var(--sd-primary-contrast)!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-secondary-contrast{color:var(--sd-secondary-contrast)!important}.bg-secondary-contrast{background:var(--sd-secondary-contrast)!important}.border-secondary-contrast{border-color:var(--sd-secondary-contrast)!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-info-contrast{color:var(--sd-info-contrast)!important}.bg-info-contrast{background:var(--sd-info-contrast)!important}.border-info-contrast{border-color:var(--sd-info-contrast)!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-success-contrast{color:var(--sd-success-contrast)!important}.bg-success-contrast{background:var(--sd-success-contrast)!important}.border-success-contrast{border-color:var(--sd-success-contrast)!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-warning-contrast{color:var(--sd-warning-contrast)!important}.bg-warning-contrast{background:var(--sd-warning-contrast)!important}.border-warning-contrast{border-color:var(--sd-warning-contrast)!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-error-contrast{color:var(--sd-error-contrast)!important}.bg-error-contrast{background:var(--sd-error-contrast)!important}.border-error-contrast{border-color:var(--sd-error-contrast)!important}.text-surface{color:var(--sd-surface)!important}.bg-surface{background:var(--sd-surface)!important}.border-surface{border-color:var(--sd-surface)!important}.text-surface-muted{color:var(--sd-surface-muted)!important}.bg-surface-muted{background:var(--sd-surface-muted)!important}.border-surface-muted{border-color:var(--sd-surface-muted)!important}.text-text{color:var(--sd-text)!important}.bg-text{background:var(--sd-text)!important}.border-text{border-color:var(--sd-text)!important}.text-text-secondary{color:var(--sd-text-secondary)!important}.bg-text-secondary{background:var(--sd-text-secondary)!important}.border-text-secondary{border-color:var(--sd-text-secondary)!important}.text-text-muted{color:var(--sd-text-muted)!important}.bg-text-muted{background:var(--sd-text-muted)!important}.border-text-muted{border-color:var(--sd-text-muted)!important}.text-border{color:var(--sd-border)!important}.bg-border{background:var(--sd-border)!important}.border-border{border-color:var(--sd-border)!important}.text-border-strong{color:var(--sd-border-strong)!important}.bg-border-strong{background:var(--sd-border-strong)!important}.border-border-strong{border-color:var(--sd-border-strong)!important}.text-disabled-bg{color:var(--sd-disabled-bg)!important}.bg-disabled-bg{background:var(--sd-disabled-bg)!important}.border-disabled-bg{border-color:var(--sd-disabled-bg)!important}.text-disabled-text{color:var(--sd-disabled-text)!important}.bg-disabled-text{background:var(--sd-disabled-text)!important}.border-disabled-text{border-color:var(--sd-disabled-text)!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}.text-secondary{color:var(--sd-text-secondary)!important}.text-muted{color:var(--sd-text-muted)!important}.text-body{color:var(--sd-text)!important}.bg-muted{background:var(--sd-surface-muted)!important}:host{display:block}:host(.sd-has-label){padding-top:4px}:host(.sd-viewed){padding-top:0}:host ::ng-deep .mat-mdc-form-field.mat-form-field-appearance-outline.mat-form-field-disabled .mat-mdc-text-field-wrapper{background:var(--sd-disabled-bg)}:host ::ng-deep .mat-mdc-form-field input.mat-mdc-input-element:disabled{color:var(--sd-disabled-text)!important}:host ::ng-deep .mat-mdc-form-field .mat-mdc-placeholder-required{color:var(--sd-error)}.sd-input-field-wrap{position:relative;flex:1;min-width:0}.sd-maxlength-counter{position:absolute;right:4px;top:calc(100% - 16px);opacity:0;font-size:10px;line-height:1.1;color:#00000061;pointer-events:none;transition:opacity .12s ease;z-index:1}.sd-maxlength-counter--exceeded{color:var(--sd-error);font-weight:600}:host ::ng-deep .sd-input-container.c-focused .sd-maxlength-counter,:host ::ng-deep .sd-input-container:hover .sd-maxlength-counter,:host ::ng-deep .sd-input-container .sd-maxlength-counter.sd-maxlength-counter--visible{opacity:1}.sd-md:hover .btn-copy{visibility:visible}\n"] }]
|
|
605
|
+
}], ctorParameters: () => [], propDecorators: { control: [{ type: i0.ViewChild, args: ['control', { isSignal: true }] }], inlineRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SdInlineText), { isSignal: true }] }], sdLabelTemplate: [{ type: i0.ContentChild, args: ['sdLabel', { isSignal: true }] }], sdValueTemplate: [{ type: i0.ContentChild, args: ['sdValue', { isSignal: true }] }], sdSuffixDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdSuffixDefDirective), { isSignal: true }] }], sdViewDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SdViewDefDirective), { isSignal: true }] }], autoIdInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoId", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], appearanceInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], floatLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "floatLabel", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], form: [{ type: i0.Input, args: [{ isSignal: true, alias: "form", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], mask: [{ type: i0.Input, args: [{ isSignal: true, alias: "mask", required: false }] }], hideInlineError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideInlineError", required: false }] }], blurOnEnter: [{ type: i0.Input, args: [{ isSignal: true, alias: "blurOnEnter", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], viewed: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewed", required: false }] }], minlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minlength", required: false }] }], maxlength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxlength", required: false }] }], pattern: [{ type: i0.Input, args: [{ isSignal: true, alias: "pattern", required: false }] }], patternErrorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "patternErrorMessage", required: false }] }], validator: [{ type: i0.Input, args: [{ isSignal: true, alias: "validator", required: false }] }], inlineError: [{ type: i0.Input, args: [{ isSignal: true, alias: "inlineError", required: false }] }], hyperlink: [{ type: i0.Input, args: [{ isSignal: true, alias: "hyperlink", required: false }] }], valueModel: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }, { type: i0.Output, args: ["modelChange"] }], sdChange: [{ type: i0.Output, args: ["sdChange"] }], sdFocus: [{ type: i0.Output, args: ["sdFocus"] }], sdBlur: [{ type: i0.Output, args: ["sdBlur"] }], keyupEnter: [{ type: i0.Output, args: ["keyupEnter"] }], cleared: [{ type: i0.Output, args: ["cleared"] }], sdFocusForceBlur: [{
|
|
372
606
|
type: Output
|
|
373
607
|
}] } });
|
|
374
608
|
|
|
@@ -376,5 +610,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImpo
|
|
|
376
610
|
* Generated bundle index. Do not edit.
|
|
377
611
|
*/
|
|
378
612
|
|
|
379
|
-
export { SdInput };
|
|
613
|
+
export { SD_INPUT_MASKS, SdInput, sdCreateInputMask, sdResolveInputMask };
|
|
380
614
|
//# sourceMappingURL=sdcorejs-angular-forms-input.mjs.map
|