@maro-tech/form 0.1.1 → 0.1.3
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/fesm2022/maro-tech-form.mjs +1073 -370
- package/fesm2022/maro-tech-form.mjs.map +1 -1
- package/package.json +1 -1
- package/types/maro-tech-form.d.ts +382 -80
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, Injectable, inject,
|
|
2
|
+
import { signal, Injectable, inject, EventEmitter, Output, HostBinding, Input, ChangeDetectionStrategy, Component, input, output, ViewChild, forwardRef, ChangeDetectorRef, HostListener, DestroyRef, ElementRef, booleanAttribute, ViewContainerRef, computed } from '@angular/core';
|
|
3
3
|
import { HttpClient } from '@angular/common/http';
|
|
4
|
+
import { throwError, forkJoin, map, Subject, debounceTime, distinctUntilChanged, of } from 'rxjs';
|
|
4
5
|
import * as i1$2 from '@angular/common';
|
|
5
6
|
import { CommonModule } from '@angular/common';
|
|
6
7
|
import * as i2 from '@angular/forms';
|
|
7
|
-
import {
|
|
8
|
+
import { NG_VALUE_ACCESSOR, FormsModule, NG_VALIDATORS } from '@angular/forms';
|
|
8
9
|
import { UiButtonComponent, UiToastService } from '@maro-tech/core';
|
|
10
|
+
import * as i1 from 'lucide-angular';
|
|
11
|
+
import { Camera, CameraOff, CalendarDays, ChevronLeft, ChevronRight, LucideAngularModule, Eye, EyeOff, X, ChevronDown, Check } from 'lucide-angular';
|
|
9
12
|
import { BrowserMultiFormatOneDReader } from '@zxing/browser';
|
|
10
13
|
import { DecodeHintType, BarcodeFormat } from '@zxing/library';
|
|
11
|
-
import * as i1 from 'lucide-angular';
|
|
12
|
-
import { CalendarDays, ChevronLeft, ChevronRight, LucideAngularModule, Eye, EyeOff, X, ChevronDown, Check } from 'lucide-angular';
|
|
13
14
|
import * as i1$1 from '@angular/cdk/drag-drop';
|
|
14
|
-
import {
|
|
15
|
-
import { forkJoin, map, Subject, debounceTime, distinctUntilChanged, of } from 'rxjs';
|
|
15
|
+
import { DragDropModule, moveItemInArray } from '@angular/cdk/drag-drop';
|
|
16
16
|
import { CdkConnectedOverlay, CdkOverlayOrigin } from '@angular/cdk/overlay';
|
|
17
17
|
import { Router } from '@angular/router';
|
|
18
18
|
|
|
@@ -56,9 +56,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
56
56
|
args: [{ providedIn: 'root' }]
|
|
57
57
|
}] });
|
|
58
58
|
|
|
59
|
+
const ACTION_PRINT = 'ACTION_PRINT';
|
|
60
|
+
const ACTION_FORM = 'ACTION_FORM';
|
|
61
|
+
const ACTION_API = 'ACTION_API';
|
|
62
|
+
const ACTION_SUBMIT = 'ACTION_SUBMIT';
|
|
63
|
+
const isDynamicFormContainerField = (field) => field.type === 'container';
|
|
64
|
+
const isDynamicFormTemplateField = (field) => field.type === 'template';
|
|
65
|
+
const isDynamicFormLookupField = (field) => field.type === 'select' || field.type === 'barcode';
|
|
66
|
+
const flattenDynamicFormFields = (fields) => {
|
|
67
|
+
const result = [];
|
|
68
|
+
for (const field of fields || []) {
|
|
69
|
+
if (!field) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
result.push(field);
|
|
73
|
+
if (isDynamicFormContainerField(field) && Array.isArray(field.fields) && field.fields.length) {
|
|
74
|
+
result.push(...flattenDynamicFormFields(field.fields));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
};
|
|
79
|
+
|
|
59
80
|
class UiFormLookupService {
|
|
60
81
|
http = inject(HttpClient);
|
|
61
82
|
lookup(field, value) {
|
|
83
|
+
if (!isDynamicFormLookupField(field)) {
|
|
84
|
+
return throwError(() => new Error('Lookup is not supported for this field type'));
|
|
85
|
+
}
|
|
62
86
|
const api = String(field.lookupApi || '').trim();
|
|
63
87
|
const endpoint = api
|
|
64
88
|
.replace(/:value/g, encodeURIComponent(value))
|
|
@@ -79,39 +103,103 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
79
103
|
type: Injectable
|
|
80
104
|
}] });
|
|
81
105
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
result.push(field);
|
|
95
|
-
if (isDynamicFormContainerField(field) && Array.isArray(field.fields) && field.fields.length) {
|
|
96
|
-
result.push(...flattenDynamicFormFields(field.fields));
|
|
97
|
-
}
|
|
106
|
+
class FieldFrameComponent {
|
|
107
|
+
label;
|
|
108
|
+
hint;
|
|
109
|
+
error;
|
|
110
|
+
required = false;
|
|
111
|
+
forId;
|
|
112
|
+
disabled = false;
|
|
113
|
+
actions = [];
|
|
114
|
+
get hasError() {
|
|
115
|
+
return !!String(this.error || '').trim();
|
|
98
116
|
}
|
|
99
|
-
|
|
100
|
-
};
|
|
117
|
+
actionTriggered = new EventEmitter();
|
|
118
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FieldFrameComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
119
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: FieldFrameComponent, isStandalone: true, selector: "field-frame", inputs: { label: "label", hint: "hint", error: "error", required: "required", forId: "forId", disabled: "disabled", actions: "actions" }, outputs: { actionTriggered: "actionTriggered" }, host: { properties: { "class.field-error": "this.hasError" } }, ngImport: i0, template: "<div class=\"relative w-full flex flex-col gap-1 text-[0.65rem] uppercase tracking-[0.3em] text-slate-500\">\n @if (label) {\n <label class=\"text-[0.7rem] font-semibold text-slate-600\" [attr.for]=\"forId\">\n {{ label }}\n @if (required) {\n <span aria-hidden=\"true\" class=\"text-rose-500\"> *</span>\n }\n </label>\n }\n\n <div class=\"flex items-end gap-2\">\n <div class=\"min-w-0 flex-1\">\n <ng-content />\n </div>\n\n @if (actions.length) {\n <div class=\"flex flex-none items-center gap-2 pb-0.5\">\n @for (action of actions; track action.id) {\n <ui-button\n type=\"button\"\n [variant]=\"action.variant ?? 'secondary'\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"actionTriggered.emit(action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </div>\n\n @if (hint) {\n <p class=\"text-[0.5rem] text-slate-500\">{{ hint }}</p>\n }\n @if (error) {\n <p class=\"absolute left-0 top-full z-10 mt-1 text-[0.5rem] text-red-500\">{{ error }}</p>\n }\n</div>\n", styles: [":host(.field-error) ::ng-deep [data-field-control]{border-color:#fca5a5;box-shadow:0 0 0 2px #fee2e2}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
120
|
+
}
|
|
121
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FieldFrameComponent, decorators: [{
|
|
122
|
+
type: Component,
|
|
123
|
+
args: [{ selector: 'field-frame', standalone: true, imports: [CommonModule, UiButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"relative w-full flex flex-col gap-1 text-[0.65rem] uppercase tracking-[0.3em] text-slate-500\">\n @if (label) {\n <label class=\"text-[0.7rem] font-semibold text-slate-600\" [attr.for]=\"forId\">\n {{ label }}\n @if (required) {\n <span aria-hidden=\"true\" class=\"text-rose-500\"> *</span>\n }\n </label>\n }\n\n <div class=\"flex items-end gap-2\">\n <div class=\"min-w-0 flex-1\">\n <ng-content />\n </div>\n\n @if (actions.length) {\n <div class=\"flex flex-none items-center gap-2 pb-0.5\">\n @for (action of actions; track action.id) {\n <ui-button\n type=\"button\"\n [variant]=\"action.variant ?? 'secondary'\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"actionTriggered.emit(action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </div>\n\n @if (hint) {\n <p class=\"text-[0.5rem] text-slate-500\">{{ hint }}</p>\n }\n @if (error) {\n <p class=\"absolute left-0 top-full z-10 mt-1 text-[0.5rem] text-red-500\">{{ error }}</p>\n }\n</div>\n", styles: [":host(.field-error) ::ng-deep [data-field-control]{border-color:#fca5a5;box-shadow:0 0 0 2px #fee2e2}\n"] }]
|
|
124
|
+
}], propDecorators: { label: [{
|
|
125
|
+
type: Input
|
|
126
|
+
}], hint: [{
|
|
127
|
+
type: Input
|
|
128
|
+
}], error: [{
|
|
129
|
+
type: Input
|
|
130
|
+
}], required: [{
|
|
131
|
+
type: Input
|
|
132
|
+
}], forId: [{
|
|
133
|
+
type: Input
|
|
134
|
+
}], disabled: [{
|
|
135
|
+
type: Input
|
|
136
|
+
}], actions: [{
|
|
137
|
+
type: Input
|
|
138
|
+
}], hasError: [{
|
|
139
|
+
type: HostBinding,
|
|
140
|
+
args: ['class.field-error']
|
|
141
|
+
}], actionTriggered: [{
|
|
142
|
+
type: Output
|
|
143
|
+
}] } });
|
|
101
144
|
|
|
102
|
-
class
|
|
145
|
+
class InputTextControlComponent {
|
|
146
|
+
placeholder;
|
|
147
|
+
name;
|
|
148
|
+
id;
|
|
149
|
+
type = 'text';
|
|
150
|
+
element = 'input';
|
|
151
|
+
rows = 4;
|
|
152
|
+
autocomplete;
|
|
153
|
+
pattern;
|
|
154
|
+
disabled = false;
|
|
155
|
+
value = '';
|
|
156
|
+
valueChange = new EventEmitter();
|
|
157
|
+
touched = new EventEmitter();
|
|
158
|
+
enterPressed = new EventEmitter();
|
|
159
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputTextControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
160
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: InputTextControlComponent, isStandalone: true, selector: "input-text-control", inputs: { placeholder: "placeholder", name: "name", id: "id", type: "type", element: "element", rows: "rows", autocomplete: "autocomplete", pattern: "pattern", disabled: "disabled", value: "value" }, outputs: { valueChange: "valueChange", touched: "touched", enterPressed: "enterPressed" }, ngImport: i0, template: "@if (element === 'textarea') {\n <textarea\n [attr.rows]=\"rows\"\n [attr.placeholder]=\"placeholder\"\n [attr.name]=\"name\"\n [attr.id]=\"id\"\n [disabled]=\"disabled\"\n data-field-control\n class=\"w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\"\n [value]=\"value\"\n (input)=\"valueChange.emit($any($event.target).value)\"\n (keydown.enter)=\"enterPressed.emit()\"\n (blur)=\"touched.emit()\"\n ></textarea>\n} @else {\n <input\n [attr.type]=\"type\"\n [attr.placeholder]=\"placeholder\"\n [attr.name]=\"name\"\n [attr.autocomplete]=\"autocomplete\"\n [attr.pattern]=\"pattern\"\n [disabled]=\"disabled\"\n data-field-control\n class=\"w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\"\n [attr.id]=\"id\"\n [value]=\"value\"\n (input)=\"valueChange.emit($any($event.target).value)\"\n (keydown.enter)=\"enterPressed.emit()\"\n (blur)=\"touched.emit()\"\n />\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
161
|
+
}
|
|
162
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputTextControlComponent, decorators: [{
|
|
163
|
+
type: Component,
|
|
164
|
+
args: [{ selector: 'input-text-control', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (element === 'textarea') {\n <textarea\n [attr.rows]=\"rows\"\n [attr.placeholder]=\"placeholder\"\n [attr.name]=\"name\"\n [attr.id]=\"id\"\n [disabled]=\"disabled\"\n data-field-control\n class=\"w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\"\n [value]=\"value\"\n (input)=\"valueChange.emit($any($event.target).value)\"\n (keydown.enter)=\"enterPressed.emit()\"\n (blur)=\"touched.emit()\"\n ></textarea>\n} @else {\n <input\n [attr.type]=\"type\"\n [attr.placeholder]=\"placeholder\"\n [attr.name]=\"name\"\n [attr.autocomplete]=\"autocomplete\"\n [attr.pattern]=\"pattern\"\n [disabled]=\"disabled\"\n data-field-control\n class=\"w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\"\n [attr.id]=\"id\"\n [value]=\"value\"\n (input)=\"valueChange.emit($any($event.target).value)\"\n (keydown.enter)=\"enterPressed.emit()\"\n (blur)=\"touched.emit()\"\n />\n}\n" }]
|
|
165
|
+
}], propDecorators: { placeholder: [{
|
|
166
|
+
type: Input
|
|
167
|
+
}], name: [{
|
|
168
|
+
type: Input
|
|
169
|
+
}], id: [{
|
|
170
|
+
type: Input
|
|
171
|
+
}], type: [{
|
|
172
|
+
type: Input
|
|
173
|
+
}], element: [{
|
|
174
|
+
type: Input
|
|
175
|
+
}], rows: [{
|
|
176
|
+
type: Input
|
|
177
|
+
}], autocomplete: [{
|
|
178
|
+
type: Input
|
|
179
|
+
}], pattern: [{
|
|
180
|
+
type: Input
|
|
181
|
+
}], disabled: [{
|
|
182
|
+
type: Input
|
|
183
|
+
}], value: [{
|
|
184
|
+
type: Input
|
|
185
|
+
}], valueChange: [{
|
|
186
|
+
type: Output
|
|
187
|
+
}], touched: [{
|
|
188
|
+
type: Output
|
|
189
|
+
}], enterPressed: [{
|
|
190
|
+
type: Output
|
|
191
|
+
}] } });
|
|
192
|
+
|
|
193
|
+
class InputBarcodeControlComponent {
|
|
194
|
+
cameraIcon = Camera;
|
|
195
|
+
cameraOffIcon = CameraOff;
|
|
103
196
|
value = input('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
104
197
|
label = input('Штрихкод', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
105
198
|
placeholder = input('Відскануйте або введіть штрихкод', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
106
199
|
hint = input('Сканер може просто ввести код і натиснути Enter.', ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
200
|
+
error = input('', ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
|
201
|
+
required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
107
202
|
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
108
|
-
autoOpen = input(true, ...(ngDevMode ? [{ debugName: "autoOpen" }] : /* istanbul ignore next */ []));
|
|
109
|
-
searchButtonLabel = input('Знайти', ...(ngDevMode ? [{ debugName: "searchButtonLabel" }] : /* istanbul ignore next */ []));
|
|
110
|
-
openCameraLabel = input('Відкрити камеру', ...(ngDevMode ? [{ debugName: "openCameraLabel" }] : /* istanbul ignore next */ []));
|
|
111
|
-
closeCameraLabel = input('Закрити камеру', ...(ngDevMode ? [{ debugName: "closeCameraLabel" }] : /* istanbul ignore next */ []));
|
|
112
|
-
cameraTitle = input('Камера', ...(ngDevMode ? [{ debugName: "cameraTitle" }] : /* istanbul ignore next */ []));
|
|
113
|
-
cameraStartingLabel = input('Запускаємо камеру…', ...(ngDevMode ? [{ debugName: "cameraStartingLabel" }] : /* istanbul ignore next */ []));
|
|
114
|
-
cameraHint = input('Наведіть камеру на штрихкод. Після зчитування код підставиться автоматично.', ...(ngDevMode ? [{ debugName: "cameraHint" }] : /* istanbul ignore next */ []));
|
|
115
203
|
valueChange = output();
|
|
116
204
|
scanned = output();
|
|
117
205
|
searchRequested = output();
|
|
@@ -138,9 +226,8 @@ class InputBarcodeComponent {
|
|
|
138
226
|
this.autoOpenQueued = false;
|
|
139
227
|
return;
|
|
140
228
|
}
|
|
141
|
-
if (
|
|
229
|
+
if (!this.disabled())
|
|
142
230
|
this.scheduleAutoOpen();
|
|
143
|
-
}
|
|
144
231
|
}
|
|
145
232
|
ngAfterViewInit() {
|
|
146
233
|
this.scheduleAutoOpen();
|
|
@@ -210,13 +297,13 @@ class InputBarcodeComponent {
|
|
|
210
297
|
this.stopCamera();
|
|
211
298
|
}
|
|
212
299
|
scheduleAutoOpen() {
|
|
213
|
-
if (typeof window === 'undefined' ||
|
|
300
|
+
if (typeof window === 'undefined' || this.disabled() || this.isCameraOpen() || this.isCameraStarting() || this.autoOpenQueued) {
|
|
214
301
|
return;
|
|
215
302
|
}
|
|
216
303
|
this.autoOpenQueued = true;
|
|
217
304
|
window.requestAnimationFrame(() => {
|
|
218
305
|
this.autoOpenQueued = false;
|
|
219
|
-
if (
|
|
306
|
+
if (this.disabled() || this.isCameraOpen() || this.isCameraStarting()) {
|
|
220
307
|
return;
|
|
221
308
|
}
|
|
222
309
|
void this.openCamera();
|
|
@@ -363,40 +450,24 @@ class InputBarcodeComponent {
|
|
|
363
450
|
return null;
|
|
364
451
|
}
|
|
365
452
|
}
|
|
366
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type:
|
|
367
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type:
|
|
368
|
-
<div class="space-y-2">
|
|
369
|
-
@if (label()) {
|
|
370
|
-
<label class="flex flex-col gap-1 text-[0.65rem] uppercase tracking-[0.3em] text-slate-500" for="barcode-scanner-input">
|
|
371
|
-
<span class="text-[0.7rem] font-semibold text-slate-600">
|
|
372
|
-
{{ label() }}
|
|
373
|
-
</span>
|
|
374
|
-
</label>
|
|
375
|
-
}
|
|
453
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputBarcodeControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
454
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: InputBarcodeControlComponent, isStandalone: true, selector: "input-barcode-control", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", scanned: "scanned", searchRequested: "searchRequested", cameraStateChange: "cameraStateChange" }, viewQueries: [{ propertyName: "cameraVideo", first: true, predicate: ["cameraVideo"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
376
455
|
|
|
377
|
-
<div class="flex items-start gap-2">
|
|
456
|
+
<div class="relative flex items-start gap-2">
|
|
378
457
|
<div class="min-w-0 flex-1">
|
|
379
|
-
<input
|
|
380
|
-
#barcodeInput
|
|
458
|
+
<input-text-control
|
|
381
459
|
id="barcode-scanner-input"
|
|
382
460
|
type="text"
|
|
383
461
|
autocomplete="off"
|
|
384
|
-
spellcheck="false"
|
|
385
462
|
[disabled]="disabled()"
|
|
386
|
-
[
|
|
387
|
-
(ngModelChange)="onValueChange($event)"
|
|
388
|
-
(keydown.enter)="requestSearch()"
|
|
389
|
-
class="w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200"
|
|
463
|
+
[value]="value()"
|
|
390
464
|
[placeholder]="placeholder()"
|
|
465
|
+
(valueChange)="onValueChange($event)"
|
|
466
|
+
(enterPressed)="requestSearch()"
|
|
391
467
|
/>
|
|
392
|
-
@if (hint()) {
|
|
393
|
-
<p class="mt-2 text-[0.5rem] text-slate-500">
|
|
394
|
-
{{ hint() }}
|
|
395
|
-
</p>
|
|
396
|
-
}
|
|
397
468
|
</div>
|
|
398
469
|
|
|
399
|
-
<div class="mt-0.5 flex flex-
|
|
470
|
+
<div class="mt-0.5 flex flex-row flex-wrap items-center gap-2">
|
|
400
471
|
<ui-button
|
|
401
472
|
type="button"
|
|
402
473
|
variant="secondary"
|
|
@@ -404,31 +475,35 @@ class InputBarcodeComponent {
|
|
|
404
475
|
[disabled]="disabled()"
|
|
405
476
|
(click)="requestSearch()"
|
|
406
477
|
>
|
|
407
|
-
|
|
408
|
-
</ui-button>
|
|
409
|
-
<ui-button
|
|
410
|
-
type="button"
|
|
411
|
-
variant="ghost"
|
|
412
|
-
size="sm"
|
|
413
|
-
[disabled]="disabled() || isCameraStarting()"
|
|
414
|
-
(click)="isCameraOpen() ? closeCamera() : openCamera()"
|
|
415
|
-
>
|
|
416
|
-
{{ isCameraOpen() ? closeCameraLabel() : openCameraLabel() }}
|
|
478
|
+
Знайти
|
|
417
479
|
</ui-button>
|
|
480
|
+
<ui-button
|
|
481
|
+
type="button"
|
|
482
|
+
variant="ghost"
|
|
483
|
+
size="sm"
|
|
484
|
+
[iconOnly]="true"
|
|
485
|
+
[icon]="isCameraOpen() ? cameraOffIcon : cameraIcon"
|
|
486
|
+
[ariaLabel]="isCameraOpen() ? 'Закрити камеру' : 'Відкрити камеру'"
|
|
487
|
+
[disabled]="disabled() || isCameraStarting()"
|
|
488
|
+
(click)="isCameraOpen() ? closeCamera() : openCamera()"
|
|
489
|
+
></ui-button>
|
|
418
490
|
</div>
|
|
419
491
|
</div>
|
|
420
492
|
|
|
493
|
+
@if (hint()) {
|
|
494
|
+
<p class="mt-2 text-[0.5rem] text-slate-500">{{ hint() }}</p>
|
|
495
|
+
}
|
|
421
496
|
@if (isCameraStarting()) {
|
|
422
497
|
<div class="rounded-xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-500">
|
|
423
|
-
|
|
498
|
+
Запускаємо камеру…
|
|
424
499
|
</div>
|
|
425
500
|
}
|
|
426
501
|
|
|
427
502
|
@if (isCameraOpen()) {
|
|
428
|
-
<section class="space-y-3 rounded-3xl border border-slate-200 bg-slate-950 p-3 text-white">
|
|
503
|
+
<section class="mt-3 space-y-3 rounded-3xl border border-slate-200 bg-slate-950 p-3 text-white">
|
|
429
504
|
<div class="flex items-center justify-between gap-3">
|
|
430
505
|
<div>
|
|
431
|
-
<p class="text-xs font-semibold uppercase tracking-[0.22em] text-slate-300"
|
|
506
|
+
<p class="text-xs font-semibold uppercase tracking-[0.22em] text-slate-300">Камера</p>
|
|
432
507
|
<p class="text-sm text-slate-200">{{ cameraStatus() }}</p>
|
|
433
508
|
</div>
|
|
434
509
|
<button
|
|
@@ -436,7 +511,7 @@ class InputBarcodeComponent {
|
|
|
436
511
|
class="rounded-full border border-slate-700 px-3 py-1 text-xs font-semibold text-slate-200 transition hover:border-slate-500 hover:text-white"
|
|
437
512
|
(click)="closeCamera()"
|
|
438
513
|
>
|
|
439
|
-
|
|
514
|
+
Закрити камеру
|
|
440
515
|
</button>
|
|
441
516
|
</div>
|
|
442
517
|
|
|
@@ -445,58 +520,42 @@ class InputBarcodeComponent {
|
|
|
445
520
|
</div>
|
|
446
521
|
|
|
447
522
|
<p class="text-xs text-slate-300">
|
|
448
|
-
|
|
523
|
+
Наведіть камеру на штрихкод.
|
|
449
524
|
</p>
|
|
450
525
|
</section>
|
|
451
526
|
}
|
|
452
527
|
|
|
453
528
|
@if (cameraError()) {
|
|
454
|
-
<div class="rounded-xl border border-
|
|
529
|
+
<div class="rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
|
|
455
530
|
{{ cameraError() }}
|
|
456
531
|
</div>
|
|
457
532
|
}
|
|
458
|
-
|
|
459
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "
|
|
533
|
+
|
|
534
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }, { kind: "component", type: InputTextControlComponent, selector: "input-text-control", inputs: ["placeholder", "name", "id", "type", "element", "rows", "autocomplete", "pattern", "disabled", "value"], outputs: ["valueChange", "touched", "enterPressed"] }] });
|
|
460
535
|
}
|
|
461
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type:
|
|
536
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputBarcodeControlComponent, decorators: [{
|
|
462
537
|
type: Component,
|
|
463
538
|
args: [{
|
|
464
|
-
selector: 'input-barcode',
|
|
539
|
+
selector: 'input-barcode-control',
|
|
465
540
|
standalone: true,
|
|
466
|
-
imports: [CommonModule,
|
|
541
|
+
imports: [CommonModule, UiButtonComponent, InputTextControlComponent],
|
|
467
542
|
template: `
|
|
468
|
-
<div class="space-y-2">
|
|
469
|
-
@if (label()) {
|
|
470
|
-
<label class="flex flex-col gap-1 text-[0.65rem] uppercase tracking-[0.3em] text-slate-500" for="barcode-scanner-input">
|
|
471
|
-
<span class="text-[0.7rem] font-semibold text-slate-600">
|
|
472
|
-
{{ label() }}
|
|
473
|
-
</span>
|
|
474
|
-
</label>
|
|
475
|
-
}
|
|
476
543
|
|
|
477
|
-
<div class="flex items-start gap-2">
|
|
544
|
+
<div class="relative flex items-start gap-2">
|
|
478
545
|
<div class="min-w-0 flex-1">
|
|
479
|
-
<input
|
|
480
|
-
#barcodeInput
|
|
546
|
+
<input-text-control
|
|
481
547
|
id="barcode-scanner-input"
|
|
482
548
|
type="text"
|
|
483
549
|
autocomplete="off"
|
|
484
|
-
spellcheck="false"
|
|
485
550
|
[disabled]="disabled()"
|
|
486
|
-
[
|
|
487
|
-
(ngModelChange)="onValueChange($event)"
|
|
488
|
-
(keydown.enter)="requestSearch()"
|
|
489
|
-
class="w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200"
|
|
551
|
+
[value]="value()"
|
|
490
552
|
[placeholder]="placeholder()"
|
|
553
|
+
(valueChange)="onValueChange($event)"
|
|
554
|
+
(enterPressed)="requestSearch()"
|
|
491
555
|
/>
|
|
492
|
-
@if (hint()) {
|
|
493
|
-
<p class="mt-2 text-[0.5rem] text-slate-500">
|
|
494
|
-
{{ hint() }}
|
|
495
|
-
</p>
|
|
496
|
-
}
|
|
497
556
|
</div>
|
|
498
557
|
|
|
499
|
-
<div class="mt-0.5 flex flex-
|
|
558
|
+
<div class="mt-0.5 flex flex-row flex-wrap items-center gap-2">
|
|
500
559
|
<ui-button
|
|
501
560
|
type="button"
|
|
502
561
|
variant="secondary"
|
|
@@ -504,31 +563,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
504
563
|
[disabled]="disabled()"
|
|
505
564
|
(click)="requestSearch()"
|
|
506
565
|
>
|
|
507
|
-
|
|
508
|
-
</ui-button>
|
|
509
|
-
<ui-button
|
|
510
|
-
type="button"
|
|
511
|
-
variant="ghost"
|
|
512
|
-
size="sm"
|
|
513
|
-
[disabled]="disabled() || isCameraStarting()"
|
|
514
|
-
(click)="isCameraOpen() ? closeCamera() : openCamera()"
|
|
515
|
-
>
|
|
516
|
-
{{ isCameraOpen() ? closeCameraLabel() : openCameraLabel() }}
|
|
566
|
+
Знайти
|
|
517
567
|
</ui-button>
|
|
568
|
+
<ui-button
|
|
569
|
+
type="button"
|
|
570
|
+
variant="ghost"
|
|
571
|
+
size="sm"
|
|
572
|
+
[iconOnly]="true"
|
|
573
|
+
[icon]="isCameraOpen() ? cameraOffIcon : cameraIcon"
|
|
574
|
+
[ariaLabel]="isCameraOpen() ? 'Закрити камеру' : 'Відкрити камеру'"
|
|
575
|
+
[disabled]="disabled() || isCameraStarting()"
|
|
576
|
+
(click)="isCameraOpen() ? closeCamera() : openCamera()"
|
|
577
|
+
></ui-button>
|
|
518
578
|
</div>
|
|
519
579
|
</div>
|
|
520
580
|
|
|
581
|
+
@if (hint()) {
|
|
582
|
+
<p class="mt-2 text-[0.5rem] text-slate-500">{{ hint() }}</p>
|
|
583
|
+
}
|
|
521
584
|
@if (isCameraStarting()) {
|
|
522
585
|
<div class="rounded-xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm text-slate-500">
|
|
523
|
-
|
|
586
|
+
Запускаємо камеру…
|
|
524
587
|
</div>
|
|
525
588
|
}
|
|
526
589
|
|
|
527
590
|
@if (isCameraOpen()) {
|
|
528
|
-
<section class="space-y-3 rounded-3xl border border-slate-200 bg-slate-950 p-3 text-white">
|
|
591
|
+
<section class="mt-3 space-y-3 rounded-3xl border border-slate-200 bg-slate-950 p-3 text-white">
|
|
529
592
|
<div class="flex items-center justify-between gap-3">
|
|
530
593
|
<div>
|
|
531
|
-
<p class="text-xs font-semibold uppercase tracking-[0.22em] text-slate-300"
|
|
594
|
+
<p class="text-xs font-semibold uppercase tracking-[0.22em] text-slate-300">Камера</p>
|
|
532
595
|
<p class="text-sm text-slate-200">{{ cameraStatus() }}</p>
|
|
533
596
|
</div>
|
|
534
597
|
<button
|
|
@@ -536,7 +599,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
536
599
|
class="rounded-full border border-slate-700 px-3 py-1 text-xs font-semibold text-slate-200 transition hover:border-slate-500 hover:text-white"
|
|
537
600
|
(click)="closeCamera()"
|
|
538
601
|
>
|
|
539
|
-
|
|
602
|
+
Закрити камеру
|
|
540
603
|
</button>
|
|
541
604
|
</div>
|
|
542
605
|
|
|
@@ -545,29 +608,115 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
545
608
|
</div>
|
|
546
609
|
|
|
547
610
|
<p class="text-xs text-slate-300">
|
|
548
|
-
|
|
611
|
+
Наведіть камеру на штрихкод.
|
|
549
612
|
</p>
|
|
550
613
|
</section>
|
|
551
614
|
}
|
|
552
615
|
|
|
553
616
|
@if (cameraError()) {
|
|
554
|
-
<div class="rounded-xl border border-
|
|
617
|
+
<div class="rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
|
|
555
618
|
{{ cameraError() }}
|
|
556
619
|
</div>
|
|
557
620
|
}
|
|
558
|
-
|
|
621
|
+
|
|
559
622
|
`,
|
|
560
623
|
}]
|
|
561
|
-
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }],
|
|
624
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], scanned: [{ type: i0.Output, args: ["scanned"] }], searchRequested: [{ type: i0.Output, args: ["searchRequested"] }], cameraStateChange: [{ type: i0.Output, args: ["cameraStateChange"] }], cameraVideo: [{
|
|
562
625
|
type: ViewChild,
|
|
563
626
|
args: ['cameraVideo']
|
|
564
627
|
}] } });
|
|
565
628
|
|
|
629
|
+
class InputBarcodeComponent {
|
|
630
|
+
value = '';
|
|
631
|
+
label = 'Штрихкод';
|
|
632
|
+
placeholder = 'Відскануйте або введіть штрихкод';
|
|
633
|
+
hint = 'Сканер може просто ввести код і натиснути Enter.';
|
|
634
|
+
error = '';
|
|
635
|
+
required = false;
|
|
636
|
+
disabled = false;
|
|
637
|
+
valueChange = new EventEmitter();
|
|
638
|
+
scanned = new EventEmitter();
|
|
639
|
+
searchRequested = new EventEmitter();
|
|
640
|
+
cameraStateChange = new EventEmitter();
|
|
641
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputBarcodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
642
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputBarcodeComponent, isStandalone: true, selector: "input-barcode", inputs: { value: "value", label: "label", placeholder: "placeholder", hint: "hint", error: "error", required: "required", disabled: "disabled" }, outputs: { valueChange: "valueChange", scanned: "scanned", searchRequested: "searchRequested", cameraStateChange: "cameraStateChange" }, ngImport: i0, template: `
|
|
643
|
+
<field-frame [label]="label" [error]="error" [required]="required" [forId]="'barcode-scanner-input'" [disabled]="disabled">
|
|
644
|
+
<input-barcode-control [value]="value" [label]="label" [placeholder]="placeholder" [hint]="hint" [error]="error" [required]="required" [disabled]="disabled" (valueChange)="valueChange.emit($event)" (scanned)="scanned.emit($event)" (searchRequested)="searchRequested.emit()" (cameraStateChange)="cameraStateChange.emit($event)" />
|
|
645
|
+
</field-frame>
|
|
646
|
+
`, isInline: true, dependencies: [{ kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputBarcodeControlComponent, selector: "input-barcode-control", inputs: ["value", "label", "placeholder", "hint", "error", "required", "disabled"], outputs: ["valueChange", "scanned", "searchRequested", "cameraStateChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
647
|
+
}
|
|
648
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputBarcodeComponent, decorators: [{
|
|
649
|
+
type: Component,
|
|
650
|
+
args: [{
|
|
651
|
+
selector: 'input-barcode',
|
|
652
|
+
standalone: true,
|
|
653
|
+
imports: [FieldFrameComponent, InputBarcodeControlComponent],
|
|
654
|
+
template: `
|
|
655
|
+
<field-frame [label]="label" [error]="error" [required]="required" [forId]="'barcode-scanner-input'" [disabled]="disabled">
|
|
656
|
+
<input-barcode-control [value]="value" [label]="label" [placeholder]="placeholder" [hint]="hint" [error]="error" [required]="required" [disabled]="disabled" (valueChange)="valueChange.emit($event)" (scanned)="scanned.emit($event)" (searchRequested)="searchRequested.emit()" (cameraStateChange)="cameraStateChange.emit($event)" />
|
|
657
|
+
</field-frame>
|
|
658
|
+
`,
|
|
659
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
660
|
+
}]
|
|
661
|
+
}], propDecorators: { value: [{
|
|
662
|
+
type: Input
|
|
663
|
+
}], label: [{
|
|
664
|
+
type: Input
|
|
665
|
+
}], placeholder: [{
|
|
666
|
+
type: Input
|
|
667
|
+
}], hint: [{
|
|
668
|
+
type: Input
|
|
669
|
+
}], error: [{
|
|
670
|
+
type: Input
|
|
671
|
+
}], required: [{
|
|
672
|
+
type: Input
|
|
673
|
+
}], disabled: [{
|
|
674
|
+
type: Input
|
|
675
|
+
}], valueChange: [{
|
|
676
|
+
type: Output
|
|
677
|
+
}], scanned: [{
|
|
678
|
+
type: Output
|
|
679
|
+
}], searchRequested: [{
|
|
680
|
+
type: Output
|
|
681
|
+
}], cameraStateChange: [{
|
|
682
|
+
type: Output
|
|
683
|
+
}] } });
|
|
684
|
+
|
|
685
|
+
class InputCheckboxControlComponent {
|
|
686
|
+
value = false;
|
|
687
|
+
disabled = false;
|
|
688
|
+
valueChange = new EventEmitter();
|
|
689
|
+
touched = new EventEmitter();
|
|
690
|
+
onValueChange(event) {
|
|
691
|
+
this.valueChange.emit(event.target.checked);
|
|
692
|
+
}
|
|
693
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputCheckboxControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
694
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputCheckboxControlComponent, isStandalone: true, selector: "input-checkbox-control", inputs: { value: "value", disabled: "disabled" }, outputs: { valueChange: "valueChange", touched: "touched" }, ngImport: i0, template: `<input data-field-control type="checkbox" class="h-4 w-4 rounded border-slate-300 text-slate-900 focus:ring-slate-400" [checked]="value" [disabled]="disabled" (change)="onValueChange($event)" (blur)="touched.emit()" />`, isInline: true });
|
|
695
|
+
}
|
|
696
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputCheckboxControlComponent, decorators: [{
|
|
697
|
+
type: Component,
|
|
698
|
+
args: [{
|
|
699
|
+
selector: 'input-checkbox-control',
|
|
700
|
+
standalone: true,
|
|
701
|
+
template: `<input data-field-control type="checkbox" class="h-4 w-4 rounded border-slate-300 text-slate-900 focus:ring-slate-400" [checked]="value" [disabled]="disabled" (change)="onValueChange($event)" (blur)="touched.emit()" />`,
|
|
702
|
+
}]
|
|
703
|
+
}], propDecorators: { value: [{
|
|
704
|
+
type: Input
|
|
705
|
+
}], disabled: [{
|
|
706
|
+
type: Input
|
|
707
|
+
}], valueChange: [{
|
|
708
|
+
type: Output
|
|
709
|
+
}], touched: [{
|
|
710
|
+
type: Output
|
|
711
|
+
}] } });
|
|
712
|
+
|
|
566
713
|
class InputCheckboxComponent {
|
|
567
714
|
label;
|
|
715
|
+
hint;
|
|
716
|
+
error;
|
|
717
|
+
required = false;
|
|
568
718
|
disabled = false;
|
|
569
719
|
value = false;
|
|
570
|
-
valueChange = new EventEmitter();
|
|
571
720
|
onChange = () => undefined;
|
|
572
721
|
onTouched = () => undefined;
|
|
573
722
|
writeValue(value) { this.value = !!value; }
|
|
@@ -578,22 +727,27 @@ class InputCheckboxComponent {
|
|
|
578
727
|
const value = event.target.checked;
|
|
579
728
|
this.value = value;
|
|
580
729
|
this.onChange(value);
|
|
581
|
-
|
|
730
|
+
}
|
|
731
|
+
handleValueChange(value) {
|
|
732
|
+
this.value = value;
|
|
733
|
+
this.onChange(value);
|
|
582
734
|
}
|
|
583
735
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputCheckboxComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
584
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputCheckboxComponent, isStandalone: true, selector: "input-checkbox", inputs: { label: "label",
|
|
736
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputCheckboxComponent, isStandalone: true, selector: "input-checkbox", inputs: { label: "label", hint: "hint", error: "error", required: "required", disabled: "disabled" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputCheckboxComponent), multi: true }], ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\">\n <input-checkbox-control [value]=\"value\" [disabled]=\"disabled\" (valueChange)=\"handleValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputCheckboxControlComponent, selector: "input-checkbox-control", inputs: ["value", "disabled"], outputs: ["valueChange", "touched"] }] });
|
|
585
737
|
}
|
|
586
738
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputCheckboxComponent, decorators: [{
|
|
587
739
|
type: Component,
|
|
588
|
-
args: [{ selector: 'input-checkbox', standalone: true, imports: [CommonModule], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputCheckboxComponent), multi: true }], template: "<label
|
|
740
|
+
args: [{ selector: 'input-checkbox', standalone: true, imports: [CommonModule, FieldFrameComponent, InputCheckboxControlComponent], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputCheckboxComponent), multi: true }], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\">\n <input-checkbox-control [value]=\"value\" [disabled]=\"disabled\" (valueChange)=\"handleValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n" }]
|
|
589
741
|
}], propDecorators: { label: [{
|
|
590
742
|
type: Input
|
|
591
|
-
}],
|
|
743
|
+
}], hint: [{
|
|
592
744
|
type: Input
|
|
593
|
-
}],
|
|
745
|
+
}], error: [{
|
|
746
|
+
type: Input
|
|
747
|
+
}], required: [{
|
|
748
|
+
type: Input
|
|
749
|
+
}], disabled: [{
|
|
594
750
|
type: Input
|
|
595
|
-
}], valueChange: [{
|
|
596
|
-
type: Output
|
|
597
751
|
}] } });
|
|
598
752
|
|
|
599
753
|
const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
@@ -618,6 +772,56 @@ const validateFormControl = (control, required, pattern, email = false) => {
|
|
|
618
772
|
return null;
|
|
619
773
|
};
|
|
620
774
|
|
|
775
|
+
class InputColorControlComponent {
|
|
776
|
+
id;
|
|
777
|
+
name;
|
|
778
|
+
disabled = false;
|
|
779
|
+
value = '#000000';
|
|
780
|
+
pickerValue = '#000000';
|
|
781
|
+
valueChange = new EventEmitter();
|
|
782
|
+
touched = new EventEmitter();
|
|
783
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputColorControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
784
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputColorControlComponent, isStandalone: true, selector: "input-color-control", inputs: { id: "id", name: "name", disabled: "disabled", value: "value", pickerValue: "pickerValue" }, outputs: { valueChange: "valueChange", touched: "touched" }, ngImport: i0, template: `
|
|
785
|
+
<div class="flex items-center gap-3">
|
|
786
|
+
<label data-field-control class="relative inline-flex h-11 w-11 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-white shadow-sm transition hover:border-slate-300" [class.cursor-not-allowed]="disabled" [class.opacity-60]="disabled" [attr.for]="id">
|
|
787
|
+
<span class="block h-9 w-9 rounded-full border border-black/10" [style.backgroundColor]="pickerValue"></span>
|
|
788
|
+
<input class="absolute inset-0 h-full w-full cursor-pointer opacity-0" type="color" [attr.id]="id" [attr.name]="name ? name + '-picker' : null" [disabled]="disabled" [value]="pickerValue" (input)="valueChange.emit($any($event.target).value)" (blur)="touched.emit()" />
|
|
789
|
+
</label>
|
|
790
|
+
<input data-field-control class="min-w-[110px] rounded-xl border border-slate-200 bg-slate-50 px-3 py-2 text-xs font-semibold uppercase text-slate-700 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200 disabled:cursor-not-allowed disabled:opacity-60" type="text" [attr.name]="name" [disabled]="disabled" [value]="value" (input)="valueChange.emit($any($event.target).value)" (blur)="touched.emit()" />
|
|
791
|
+
</div>
|
|
792
|
+
`, isInline: true });
|
|
793
|
+
}
|
|
794
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputColorControlComponent, decorators: [{
|
|
795
|
+
type: Component,
|
|
796
|
+
args: [{
|
|
797
|
+
selector: 'input-color-control',
|
|
798
|
+
standalone: true,
|
|
799
|
+
template: `
|
|
800
|
+
<div class="flex items-center gap-3">
|
|
801
|
+
<label data-field-control class="relative inline-flex h-11 w-11 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-white shadow-sm transition hover:border-slate-300" [class.cursor-not-allowed]="disabled" [class.opacity-60]="disabled" [attr.for]="id">
|
|
802
|
+
<span class="block h-9 w-9 rounded-full border border-black/10" [style.backgroundColor]="pickerValue"></span>
|
|
803
|
+
<input class="absolute inset-0 h-full w-full cursor-pointer opacity-0" type="color" [attr.id]="id" [attr.name]="name ? name + '-picker' : null" [disabled]="disabled" [value]="pickerValue" (input)="valueChange.emit($any($event.target).value)" (blur)="touched.emit()" />
|
|
804
|
+
</label>
|
|
805
|
+
<input data-field-control class="min-w-[110px] rounded-xl border border-slate-200 bg-slate-50 px-3 py-2 text-xs font-semibold uppercase text-slate-700 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200 disabled:cursor-not-allowed disabled:opacity-60" type="text" [attr.name]="name" [disabled]="disabled" [value]="value" (input)="valueChange.emit($any($event.target).value)" (blur)="touched.emit()" />
|
|
806
|
+
</div>
|
|
807
|
+
`,
|
|
808
|
+
}]
|
|
809
|
+
}], propDecorators: { id: [{
|
|
810
|
+
type: Input
|
|
811
|
+
}], name: [{
|
|
812
|
+
type: Input
|
|
813
|
+
}], disabled: [{
|
|
814
|
+
type: Input
|
|
815
|
+
}], value: [{
|
|
816
|
+
type: Input
|
|
817
|
+
}], pickerValue: [{
|
|
818
|
+
type: Input
|
|
819
|
+
}], valueChange: [{
|
|
820
|
+
type: Output
|
|
821
|
+
}], touched: [{
|
|
822
|
+
type: Output
|
|
823
|
+
}] } });
|
|
824
|
+
|
|
621
825
|
class InputColorComponent {
|
|
622
826
|
cdr = inject(ChangeDetectorRef);
|
|
623
827
|
label;
|
|
@@ -625,7 +829,6 @@ class InputColorComponent {
|
|
|
625
829
|
name;
|
|
626
830
|
id;
|
|
627
831
|
required = false;
|
|
628
|
-
fullWidth = false;
|
|
629
832
|
error;
|
|
630
833
|
disabled = false;
|
|
631
834
|
value = '#000000';
|
|
@@ -662,6 +865,10 @@ class InputColorComponent {
|
|
|
662
865
|
this.value = this.normalizeHexInput(value);
|
|
663
866
|
this.onChange(this.value);
|
|
664
867
|
}
|
|
868
|
+
handleValueChange(value) {
|
|
869
|
+
this.value = value;
|
|
870
|
+
this.onChange(value);
|
|
871
|
+
}
|
|
665
872
|
markTouched() {
|
|
666
873
|
this.onTouched();
|
|
667
874
|
}
|
|
@@ -676,25 +883,25 @@ class InputColorComponent {
|
|
|
676
883
|
return /^#([0-9a-fA-F]{6})$/.test(value.trim());
|
|
677
884
|
}
|
|
678
885
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputColorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
679
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
886
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputColorComponent, isStandalone: true, selector: "input-color", inputs: { label: "label", hint: "hint", name: "name", id: "id", required: "required", error: "error" }, providers: [
|
|
680
887
|
{
|
|
681
888
|
provide: NG_VALUE_ACCESSOR,
|
|
682
889
|
useExisting: forwardRef(() => InputColorComponent),
|
|
683
890
|
multi: true,
|
|
684
891
|
},
|
|
685
892
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputColorComponent), multi: true },
|
|
686
|
-
], ngImport: i0, template: "<
|
|
893
|
+
], ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\">\n <input-color-control [id]=\"controlId\" [name]=\"name\" [disabled]=\"disabled\" [value]=\"value\" [pickerValue]=\"pickerValue\" (valueChange)=\"handleValueChange($event)\" (touched)=\"markTouched()\" />\n</field-frame>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputColorControlComponent, selector: "input-color-control", inputs: ["id", "name", "disabled", "value", "pickerValue"], outputs: ["valueChange", "touched"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
687
894
|
}
|
|
688
895
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputColorComponent, decorators: [{
|
|
689
896
|
type: Component,
|
|
690
|
-
args: [{ selector: 'input-color', standalone: true, imports: [CommonModule, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
897
|
+
args: [{ selector: 'input-color', standalone: true, imports: [CommonModule, FormsModule, FieldFrameComponent, InputColorControlComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
691
898
|
{
|
|
692
899
|
provide: NG_VALUE_ACCESSOR,
|
|
693
900
|
useExisting: forwardRef(() => InputColorComponent),
|
|
694
901
|
multi: true,
|
|
695
902
|
},
|
|
696
903
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputColorComponent), multi: true },
|
|
697
|
-
], template: "<
|
|
904
|
+
], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\">\n <input-color-control [id]=\"controlId\" [name]=\"name\" [disabled]=\"disabled\" [value]=\"value\" [pickerValue]=\"pickerValue\" (valueChange)=\"handleValueChange($event)\" (touched)=\"markTouched()\" />\n</field-frame>\n" }]
|
|
698
905
|
}], propDecorators: { label: [{
|
|
699
906
|
type: Input
|
|
700
907
|
}], hint: [{
|
|
@@ -705,8 +912,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
705
912
|
type: Input
|
|
706
913
|
}], required: [{
|
|
707
914
|
type: Input
|
|
708
|
-
}], fullWidth: [{
|
|
709
|
-
type: Input
|
|
710
915
|
}], error: [{
|
|
711
916
|
type: Input
|
|
712
917
|
}] } });
|
|
@@ -733,7 +938,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
733
938
|
args: [{ providedIn: 'root' }]
|
|
734
939
|
}] });
|
|
735
940
|
|
|
736
|
-
class
|
|
941
|
+
class InputDateControlComponent {
|
|
737
942
|
cdr = inject(ChangeDetectorRef);
|
|
738
943
|
popupService = inject(UiPopupService);
|
|
739
944
|
closeActivePopup = () => this.closeCalendar();
|
|
@@ -749,7 +954,6 @@ class InputDateComponent {
|
|
|
749
954
|
nextMonthIcon = ChevronRight;
|
|
750
955
|
rows = 4;
|
|
751
956
|
required = false;
|
|
752
|
-
fullWidth = false;
|
|
753
957
|
autocomplete = 'off';
|
|
754
958
|
pattern;
|
|
755
959
|
error;
|
|
@@ -757,7 +961,7 @@ class InputDateComponent {
|
|
|
757
961
|
disabled = false;
|
|
758
962
|
value = '';
|
|
759
963
|
static nextId = 0;
|
|
760
|
-
generatedId = `input-date-${
|
|
964
|
+
generatedId = `input-date-${InputDateControlComponent.nextId++}`;
|
|
761
965
|
visibleMonth = this.startOfMonth(new Date());
|
|
762
966
|
calendarView = 'days';
|
|
763
967
|
isCalendarOpen = false;
|
|
@@ -966,26 +1170,26 @@ class InputDateComponent {
|
|
|
966
1170
|
const day = String(date.getDate()).padStart(2, '0');
|
|
967
1171
|
return `${year}-${month}-${day}`;
|
|
968
1172
|
}
|
|
969
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type:
|
|
970
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type:
|
|
1173
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputDateControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1174
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: InputDateControlComponent, isStandalone: true, selector: "input-date-control", inputs: { label: "label", hint: "hint", placeholder: "placeholder", name: "name", id: "id", rows: "rows", required: "required", autocomplete: "autocomplete", pattern: "pattern", error: "error", actions: "actions", disabled: "disabled" }, outputs: { actionTriggered: "actionTriggered" }, host: { listeners: { "document:click": "onDocumentClick()", "document:keydown.escape": "onEscape()" } }, providers: [
|
|
971
1175
|
{
|
|
972
1176
|
provide: NG_VALUE_ACCESSOR,
|
|
973
|
-
useExisting: forwardRef(() =>
|
|
1177
|
+
useExisting: forwardRef(() => InputDateControlComponent),
|
|
974
1178
|
multi: true,
|
|
975
1179
|
},
|
|
976
|
-
{ provide: NG_VALIDATORS, useExisting: forwardRef(() =>
|
|
977
|
-
], ngImport: i0, template: "
|
|
1180
|
+
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputDateControlComponent), multi: true },
|
|
1181
|
+
], ngImport: i0, template: "\n <div class=\"flex items-end gap-2\">\n <div class=\"min-w-0 flex-1\">\n @if (element === 'textarea') {\n <textarea\n [attr.rows]=\"rows\"\n [attr.placeholder]=\"placeholder\"\n [attr.name]=\"name\"\n [attr.id]=\"controlId\"\n [disabled]=\"disabled\"\n class=\"w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\"\n [value]=\"value\"\n (input)=\"onValueChange($any($event.target).value)\"\n (blur)=\"onTouched()\"\n ></textarea>\n } @else {\n <div class=\"relative\">\n <input\n data-field-control\n type=\"text\"\n [attr.placeholder]=\"placeholder ?? '\u0414\u0414.\u041C\u041C.\u0420\u0420\u0420\u0420'\"\n maxlength=\"10\"\n inputmode=\"numeric\"\n [attr.name]=\"name\"\n [attr.autocomplete]=\"autocomplete\"\n [disabled]=\"disabled\"\n class=\"w-full rounded-xl border border-slate-200 bg-white px-4 py-2 pr-10 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\"\n [attr.id]=\"controlId\"\n [value]=\"displayValue\"\n (click)=\"openCalendar($event)\"\n (keydown)=\"allowDateKey($event)\"\n (input)=\"onValueChange($any($event.target).value)\"\n (blur)=\"onTouched()\"\n />\n <lucide-icon\n [img]=\"calendarIcon\"\n class=\"pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400\"\n aria-hidden=\"true\"\n ></lucide-icon>\n\n @if (isCalendarOpen) {\n <div\n class=\"absolute left-0 top-full z-50 mt-2 w-[min(20rem,calc(100vw-2rem))] rounded-xl border border-slate-200 bg-white p-4 shadow-xl\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"mb-4 flex items-center justify-between\" [class.justify-center]=\"calendarView === 'months'\">\n @if (calendarView !== 'months') {\n <button\n type=\"button\"\n class=\"rounded-lg p-2 text-slate-500 transition hover:bg-slate-100 hover:text-slate-900\"\n aria-label=\"\u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456\u0439 \u043C\u0456\u0441\u044F\u0446\u044C\"\n (click)=\"changeMonth(-1, $event)\"\n >\n <lucide-icon [img]=\"previousMonthIcon\" class=\"h-4 w-4\"></lucide-icon>\n </button>\n }\n <div class=\"flex items-center gap-1\">\n <button\n type=\"button\"\n class=\"rounded-lg px-2 py-1 text-sm font-semibold capitalize text-slate-900 transition hover:bg-slate-100\"\n (click)=\"showMonthPicker($event)\"\n >\n {{ monthName }}\n </button>\n <button\n type=\"button\"\n class=\"rounded-lg px-2 py-1 text-sm font-semibold text-slate-900 transition hover:bg-slate-100\"\n (click)=\"showYearPicker($event)\"\n >\n {{ yearLabel }}\n </button>\n </div>\n @if (calendarView !== 'months') {\n <button\n type=\"button\"\n class=\"rounded-lg p-2 text-slate-500 transition hover:bg-slate-100 hover:text-slate-900\"\n aria-label=\"\u041D\u0430\u0441\u0442\u0443\u043F\u043D\u0438\u0439 \u043C\u0456\u0441\u044F\u0446\u044C\"\n (click)=\"changeMonth(1, $event)\"\n >\n <lucide-icon [img]=\"nextMonthIcon\" class=\"h-4 w-4\"></lucide-icon>\n </button>\n }\n </div>\n\n @if (calendarView === 'days') {\n <div class=\"mb-2 grid grid-cols-7 text-center text-xs font-medium text-slate-400\">\n @for (weekday of ['\u041F\u043D', '\u0412\u0442', '\u0421\u0440', '\u0427\u0442', '\u041F\u0442', '\u0421\u0431', '\u041D\u0434']; track weekday) {\n <span class=\"py-1\">{{ weekday }}</span>\n }\n </div>\n\n <div class=\"grid grid-cols-7 gap-1\">\n @for (day of calendarDays; track day.date) {\n <button\n type=\"button\"\n class=\"aspect-square rounded-lg text-sm transition hover:bg-slate-100 hover:text-slate-900\"\n [class.text-slate-300]=\"!day.currentMonth\"\n [class.text-slate-700]=\"day.currentMonth && !isSelected(day.date)\"\n [class.bg-slate-900]=\"isSelected(day.date)\"\n [class.text-white]=\"isSelected(day.date)\"\n (click)=\"selectDate(day.date, $event)\"\n >\n {{ day.day }}\n </button>\n }\n </div>\n } @else if (calendarView === 'months') {\n <div class=\"grid grid-cols-3 gap-2\">\n @for (month of monthOptions; track month.value) {\n <button\n type=\"button\"\n class=\"rounded-lg px-2 py-3 text-sm capitalize text-slate-700 transition hover:bg-slate-100 hover:text-slate-900\"\n [class.bg-slate-900]=\"isSelectedMonth(month.value)\"\n [class.text-white]=\"isSelectedMonth(month.value)\"\n (click)=\"selectMonth(month.value, $event)\"\n >\n {{ month.label }}\n </button>\n }\n </div>\n } @else {\n <div class=\"grid grid-cols-3 gap-2\">\n @for (year of yearOptions; track year) {\n <button\n type=\"button\"\n class=\"rounded-lg px-2 py-3 text-sm text-slate-700 transition hover:bg-slate-100 hover:text-slate-900\"\n [class.bg-slate-900]=\"isSelectedYear(year)\"\n [class.text-white]=\"isSelectedYear(year)\"\n (click)=\"selectYear(year, $event)\"\n >\n {{ year }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n </div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
978
1182
|
}
|
|
979
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type:
|
|
1183
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputDateControlComponent, decorators: [{
|
|
980
1184
|
type: Component,
|
|
981
|
-
args: [{ selector: 'input-date', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent, LucideAngularModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1185
|
+
args: [{ selector: 'input-date-control', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent, LucideAngularModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
982
1186
|
{
|
|
983
1187
|
provide: NG_VALUE_ACCESSOR,
|
|
984
|
-
useExisting: forwardRef(() =>
|
|
1188
|
+
useExisting: forwardRef(() => InputDateControlComponent),
|
|
985
1189
|
multi: true,
|
|
986
1190
|
},
|
|
987
|
-
{ provide: NG_VALIDATORS, useExisting: forwardRef(() =>
|
|
988
|
-
], template: "
|
|
1191
|
+
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputDateControlComponent), multi: true },
|
|
1192
|
+
], template: "\n <div class=\"flex items-end gap-2\">\n <div class=\"min-w-0 flex-1\">\n @if (element === 'textarea') {\n <textarea\n [attr.rows]=\"rows\"\n [attr.placeholder]=\"placeholder\"\n [attr.name]=\"name\"\n [attr.id]=\"controlId\"\n [disabled]=\"disabled\"\n class=\"w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\"\n [value]=\"value\"\n (input)=\"onValueChange($any($event.target).value)\"\n (blur)=\"onTouched()\"\n ></textarea>\n } @else {\n <div class=\"relative\">\n <input\n data-field-control\n type=\"text\"\n [attr.placeholder]=\"placeholder ?? '\u0414\u0414.\u041C\u041C.\u0420\u0420\u0420\u0420'\"\n maxlength=\"10\"\n inputmode=\"numeric\"\n [attr.name]=\"name\"\n [attr.autocomplete]=\"autocomplete\"\n [disabled]=\"disabled\"\n class=\"w-full rounded-xl border border-slate-200 bg-white px-4 py-2 pr-10 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\"\n [attr.id]=\"controlId\"\n [value]=\"displayValue\"\n (click)=\"openCalendar($event)\"\n (keydown)=\"allowDateKey($event)\"\n (input)=\"onValueChange($any($event.target).value)\"\n (blur)=\"onTouched()\"\n />\n <lucide-icon\n [img]=\"calendarIcon\"\n class=\"pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400\"\n aria-hidden=\"true\"\n ></lucide-icon>\n\n @if (isCalendarOpen) {\n <div\n class=\"absolute left-0 top-full z-50 mt-2 w-[min(20rem,calc(100vw-2rem))] rounded-xl border border-slate-200 bg-white p-4 shadow-xl\"\n (click)=\"$event.stopPropagation()\"\n >\n <div class=\"mb-4 flex items-center justify-between\" [class.justify-center]=\"calendarView === 'months'\">\n @if (calendarView !== 'months') {\n <button\n type=\"button\"\n class=\"rounded-lg p-2 text-slate-500 transition hover:bg-slate-100 hover:text-slate-900\"\n aria-label=\"\u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456\u0439 \u043C\u0456\u0441\u044F\u0446\u044C\"\n (click)=\"changeMonth(-1, $event)\"\n >\n <lucide-icon [img]=\"previousMonthIcon\" class=\"h-4 w-4\"></lucide-icon>\n </button>\n }\n <div class=\"flex items-center gap-1\">\n <button\n type=\"button\"\n class=\"rounded-lg px-2 py-1 text-sm font-semibold capitalize text-slate-900 transition hover:bg-slate-100\"\n (click)=\"showMonthPicker($event)\"\n >\n {{ monthName }}\n </button>\n <button\n type=\"button\"\n class=\"rounded-lg px-2 py-1 text-sm font-semibold text-slate-900 transition hover:bg-slate-100\"\n (click)=\"showYearPicker($event)\"\n >\n {{ yearLabel }}\n </button>\n </div>\n @if (calendarView !== 'months') {\n <button\n type=\"button\"\n class=\"rounded-lg p-2 text-slate-500 transition hover:bg-slate-100 hover:text-slate-900\"\n aria-label=\"\u041D\u0430\u0441\u0442\u0443\u043F\u043D\u0438\u0439 \u043C\u0456\u0441\u044F\u0446\u044C\"\n (click)=\"changeMonth(1, $event)\"\n >\n <lucide-icon [img]=\"nextMonthIcon\" class=\"h-4 w-4\"></lucide-icon>\n </button>\n }\n </div>\n\n @if (calendarView === 'days') {\n <div class=\"mb-2 grid grid-cols-7 text-center text-xs font-medium text-slate-400\">\n @for (weekday of ['\u041F\u043D', '\u0412\u0442', '\u0421\u0440', '\u0427\u0442', '\u041F\u0442', '\u0421\u0431', '\u041D\u0434']; track weekday) {\n <span class=\"py-1\">{{ weekday }}</span>\n }\n </div>\n\n <div class=\"grid grid-cols-7 gap-1\">\n @for (day of calendarDays; track day.date) {\n <button\n type=\"button\"\n class=\"aspect-square rounded-lg text-sm transition hover:bg-slate-100 hover:text-slate-900\"\n [class.text-slate-300]=\"!day.currentMonth\"\n [class.text-slate-700]=\"day.currentMonth && !isSelected(day.date)\"\n [class.bg-slate-900]=\"isSelected(day.date)\"\n [class.text-white]=\"isSelected(day.date)\"\n (click)=\"selectDate(day.date, $event)\"\n >\n {{ day.day }}\n </button>\n }\n </div>\n } @else if (calendarView === 'months') {\n <div class=\"grid grid-cols-3 gap-2\">\n @for (month of monthOptions; track month.value) {\n <button\n type=\"button\"\n class=\"rounded-lg px-2 py-3 text-sm capitalize text-slate-700 transition hover:bg-slate-100 hover:text-slate-900\"\n [class.bg-slate-900]=\"isSelectedMonth(month.value)\"\n [class.text-white]=\"isSelectedMonth(month.value)\"\n (click)=\"selectMonth(month.value, $event)\"\n >\n {{ month.label }}\n </button>\n }\n </div>\n } @else {\n <div class=\"grid grid-cols-3 gap-2\">\n @for (year of yearOptions; track year) {\n <button\n type=\"button\"\n class=\"rounded-lg px-2 py-3 text-sm text-slate-700 transition hover:bg-slate-100 hover:text-slate-900\"\n [class.bg-slate-900]=\"isSelectedYear(year)\"\n [class.text-white]=\"isSelectedYear(year)\"\n (click)=\"selectYear(year, $event)\"\n >\n {{ year }}\n </button>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n\n </div>\n" }]
|
|
989
1193
|
}], propDecorators: { label: [{
|
|
990
1194
|
type: Input
|
|
991
1195
|
}], hint: [{
|
|
@@ -1000,8 +1204,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1000
1204
|
type: Input
|
|
1001
1205
|
}], required: [{
|
|
1002
1206
|
type: Input
|
|
1003
|
-
}], fullWidth: [{
|
|
1004
|
-
type: Input
|
|
1005
1207
|
}], autocomplete: [{
|
|
1006
1208
|
type: Input
|
|
1007
1209
|
}], pattern: [{
|
|
@@ -1010,6 +1212,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1010
1212
|
type: Input
|
|
1011
1213
|
}], actions: [{
|
|
1012
1214
|
type: Input
|
|
1215
|
+
}], disabled: [{
|
|
1216
|
+
type: Input
|
|
1013
1217
|
}], actionTriggered: [{
|
|
1014
1218
|
type: Output
|
|
1015
1219
|
}], onDocumentClick: [{
|
|
@@ -1020,7 +1224,68 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1020
1224
|
args: ['document:keydown.escape']
|
|
1021
1225
|
}] } });
|
|
1022
1226
|
|
|
1023
|
-
class
|
|
1227
|
+
class InputDateComponent {
|
|
1228
|
+
control;
|
|
1229
|
+
label;
|
|
1230
|
+
hint;
|
|
1231
|
+
error;
|
|
1232
|
+
placeholder;
|
|
1233
|
+
name;
|
|
1234
|
+
id;
|
|
1235
|
+
required = false;
|
|
1236
|
+
disabled = false;
|
|
1237
|
+
autocomplete = 'off';
|
|
1238
|
+
pattern;
|
|
1239
|
+
rows = 4;
|
|
1240
|
+
actions = [];
|
|
1241
|
+
actionTriggered = new EventEmitter();
|
|
1242
|
+
pendingValue = '';
|
|
1243
|
+
onChange = () => undefined;
|
|
1244
|
+
onTouched = () => undefined;
|
|
1245
|
+
ngAfterViewInit() { this.control?.registerOnChange((value) => this.onChange(value)); this.control?.registerOnTouched(() => this.onTouched()); this.control?.writeValue(this.pendingValue); }
|
|
1246
|
+
writeValue(value) { this.pendingValue = value; this.control?.writeValue(value); }
|
|
1247
|
+
registerOnChange(fn) { this.onChange = fn; }
|
|
1248
|
+
registerOnTouched(fn) { this.onTouched = fn; }
|
|
1249
|
+
setDisabledState(value) { this.disabled = value; }
|
|
1250
|
+
validate(control) { return validateFormControl(control, this.required, this.pattern); }
|
|
1251
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputDateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1252
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputDateComponent, isStandalone: true, selector: "input-date", inputs: { label: "label", hint: "hint", error: "error", placeholder: "placeholder", name: "name", id: "id", required: "required", disabled: "disabled", autocomplete: "autocomplete", pattern: "pattern", rows: "rows", actions: "actions" }, outputs: { actionTriggered: "actionTriggered" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputDateComponent), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => InputDateComponent), multi: true }], viewQueries: [{ propertyName: "control", first: true, predicate: InputDateControlComponent, descendants: true }], ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"id\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"actionTriggered.emit($event)\">\n <input-date-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"id\" [required]=\"required\" [disabled]=\"disabled\" [autocomplete]=\"autocomplete\" [pattern]=\"pattern\" [rows]=\"rows\" />\n</field-frame>\n", dependencies: [{ kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputDateControlComponent, selector: "input-date-control", inputs: ["label", "hint", "placeholder", "name", "id", "rows", "required", "autocomplete", "pattern", "error", "actions", "disabled"], outputs: ["actionTriggered"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1253
|
+
}
|
|
1254
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputDateComponent, decorators: [{
|
|
1255
|
+
type: Component,
|
|
1256
|
+
args: [{ selector: 'input-date', standalone: true, imports: [FieldFrameComponent, InputDateControlComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputDateComponent), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => InputDateComponent), multi: true }], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"id\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"actionTriggered.emit($event)\">\n <input-date-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"id\" [required]=\"required\" [disabled]=\"disabled\" [autocomplete]=\"autocomplete\" [pattern]=\"pattern\" [rows]=\"rows\" />\n</field-frame>\n" }]
|
|
1257
|
+
}], propDecorators: { control: [{
|
|
1258
|
+
type: ViewChild,
|
|
1259
|
+
args: [InputDateControlComponent]
|
|
1260
|
+
}], label: [{
|
|
1261
|
+
type: Input
|
|
1262
|
+
}], hint: [{
|
|
1263
|
+
type: Input
|
|
1264
|
+
}], error: [{
|
|
1265
|
+
type: Input
|
|
1266
|
+
}], placeholder: [{
|
|
1267
|
+
type: Input
|
|
1268
|
+
}], name: [{
|
|
1269
|
+
type: Input
|
|
1270
|
+
}], id: [{
|
|
1271
|
+
type: Input
|
|
1272
|
+
}], required: [{
|
|
1273
|
+
type: Input
|
|
1274
|
+
}], disabled: [{
|
|
1275
|
+
type: Input
|
|
1276
|
+
}], autocomplete: [{
|
|
1277
|
+
type: Input
|
|
1278
|
+
}], pattern: [{
|
|
1279
|
+
type: Input
|
|
1280
|
+
}], rows: [{
|
|
1281
|
+
type: Input
|
|
1282
|
+
}], actions: [{
|
|
1283
|
+
type: Input
|
|
1284
|
+
}], actionTriggered: [{
|
|
1285
|
+
type: Output
|
|
1286
|
+
}] } });
|
|
1287
|
+
|
|
1288
|
+
class InputDatetimeControlComponent {
|
|
1024
1289
|
cdr = inject(ChangeDetectorRef);
|
|
1025
1290
|
popupService = inject(UiPopupService);
|
|
1026
1291
|
closeActivePopup = () => this.closeCalendar();
|
|
@@ -1031,7 +1296,6 @@ class InputDatetimeComponent {
|
|
|
1031
1296
|
id;
|
|
1032
1297
|
rows = 4;
|
|
1033
1298
|
required = false;
|
|
1034
|
-
fullWidth = false;
|
|
1035
1299
|
autocomplete = 'off';
|
|
1036
1300
|
pattern;
|
|
1037
1301
|
error;
|
|
@@ -1048,7 +1312,7 @@ class InputDatetimeComponent {
|
|
|
1048
1312
|
selectedHour = 12;
|
|
1049
1313
|
selectedMinute = 0;
|
|
1050
1314
|
static nextId = 0;
|
|
1051
|
-
generatedId = `input-datetime-${
|
|
1315
|
+
generatedId = `input-datetime-${InputDatetimeControlComponent.nextId++}`;
|
|
1052
1316
|
actionTriggered = new EventEmitter();
|
|
1053
1317
|
onChange = () => undefined;
|
|
1054
1318
|
onTouched = () => undefined;
|
|
@@ -1118,18 +1382,18 @@ class InputDatetimeComponent {
|
|
|
1118
1382
|
startOfMonth(date) { return new Date(date.getFullYear(), date.getMonth(), 1); }
|
|
1119
1383
|
parseDate(value) { const [year, month, day] = value.split('-').map(Number); return year && month && day ? new Date(year, month - 1, day) : null; }
|
|
1120
1384
|
toDateValue(date) { return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`; }
|
|
1121
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type:
|
|
1122
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type:
|
|
1123
|
-
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() =>
|
|
1124
|
-
{ provide: NG_VALIDATORS, useExisting: forwardRef(() =>
|
|
1125
|
-
], ngImport: i0, template: "
|
|
1385
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputDatetimeControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1386
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: InputDatetimeControlComponent, isStandalone: true, selector: "input-datetime-control", inputs: { label: "label", hint: "hint", placeholder: "placeholder", name: "name", id: "id", rows: "rows", required: "required", autocomplete: "autocomplete", pattern: "pattern", error: "error", actions: "actions", disabled: "disabled" }, outputs: { actionTriggered: "actionTriggered" }, host: { listeners: { "document:click": "onDocumentClick()", "document:keydown.escape": "onEscape()" } }, providers: [
|
|
1387
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputDatetimeControlComponent), multi: true },
|
|
1388
|
+
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputDatetimeControlComponent), multi: true },
|
|
1389
|
+
], ngImport: i0, template: " <div class=\"flex items-end gap-2\"><div class=\"min-w-0 flex-1\"><div class=\"relative\">\n <input data-field-control type=\"text\" [attr.placeholder]=\"placeholder ?? '\u0414\u0414.\u041C\u041C.\u0420\u0420\u0420\u0420 \u0413\u0413:\u0425\u0425'\" maxlength=\"16\" inputmode=\"numeric\" [attr.name]=\"name\" [attr.autocomplete]=\"autocomplete\" [disabled]=\"disabled\" class=\"w-full rounded-xl border border-slate-200 bg-white px-4 py-2 pr-10 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\" [attr.id]=\"controlId\" [value]=\"displayValue\" (click)=\"openCalendar($event)\" (keydown)=\"allowDateKey($event)\" (input)=\"onValueChange($any($event.target).value)\" (blur)=\"onTouched()\" />\n <lucide-icon [img]=\"calendarIcon\" class=\"pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400\"></lucide-icon>\n @if (isCalendarOpen) { <div class=\"absolute left-0 top-full z-50 mt-2 w-[min(22rem,calc(100vw-2rem))] rounded-xl border border-slate-200 bg-white p-4 shadow-xl\" (click)=\"$event.stopPropagation()\">\n <div class=\"mb-4 flex items-center justify-between\" [class.justify-center]=\"calendarView === 'months'\">\n @if (calendarView !== 'months') { <button type=\"button\" class=\"rounded-lg p-2 text-slate-500 hover:bg-slate-100\" aria-label=\"\u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456\u0439 \u043F\u0435\u0440\u0456\u043E\u0434\" (click)=\"changeMonth(-1, $event)\"><lucide-icon [img]=\"previousMonthIcon\" class=\"h-4 w-4\"></lucide-icon></button> }\n <div class=\"flex items-center gap-1\"><button type=\"button\" class=\"rounded-lg px-2 py-1 text-sm font-semibold capitalize text-slate-900 hover:bg-slate-100\" (click)=\"showMonthPicker($event)\">{{ monthName }}</button><button type=\"button\" class=\"rounded-lg px-2 py-1 text-sm font-semibold text-slate-900 hover:bg-slate-100\" (click)=\"showYearPicker($event)\">{{ yearLabel }}</button></div>\n @if (calendarView !== 'months') { <button type=\"button\" class=\"rounded-lg p-2 text-slate-500 hover:bg-slate-100\" aria-label=\"\u041D\u0430\u0441\u0442\u0443\u043F\u043D\u0438\u0439 \u043F\u0435\u0440\u0456\u043E\u0434\" (click)=\"changeMonth(1, $event)\"><lucide-icon [img]=\"nextMonthIcon\" class=\"h-4 w-4\"></lucide-icon></button> }\n </div>\n @if (calendarView === 'days') {\n <div class=\"mb-2 grid grid-cols-7 text-center text-xs font-medium text-slate-400\">@for (weekday of ['\u041F\u043D','\u0412\u0442','\u0421\u0440','\u0427\u0442','\u041F\u0442','\u0421\u0431','\u041D\u0434']; track weekday) { <span class=\"py-1\">{{ weekday }}</span> }</div>\n <div class=\"grid grid-cols-7 gap-1\">@for (day of calendarDays; track day.date) { <button type=\"button\" class=\"aspect-square rounded-lg text-sm hover:bg-slate-100 hover:text-slate-900\" [class.text-slate-300]=\"!day.currentMonth\" [class.text-slate-700]=\"day.currentMonth && !isSelected(day.date)\" [class.bg-slate-900]=\"isSelected(day.date)\" [class.text-white]=\"isSelected(day.date)\" (click)=\"selectDate(day.date, $event)\">{{ day.day }}</button> }</div>\n <div class=\"mt-4 grid grid-cols-2 gap-2 border-t border-slate-100 pt-3\"><label class=\"text-[0.65rem] font-medium text-slate-500\">\u0413\u043E\u0434\u0438\u043D\u0438<input type=\"number\" min=\"0\" max=\"23\" [value]=\"selectedHour\" (input)=\"selectedHour = +$any($event.target).value; onTimeChange()\" class=\"mt-1 w-full rounded-xl border border-slate-200 px-3 py-2 text-sm focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\" /></label><label class=\"text-[0.65rem] font-medium text-slate-500\">\u0425\u0432\u0438\u043B\u0438\u043D\u0438<input type=\"number\" min=\"0\" max=\"59\" [value]=\"selectedMinute\" (input)=\"selectedMinute = +$any($event.target).value; onTimeChange()\" class=\"mt-1 w-full rounded-xl border border-slate-200 px-3 py-2 text-sm focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\" /></label></div>\n } @else if (calendarView === 'months') { <div class=\"grid grid-cols-3 gap-2\">@for (month of monthOptions; track month.value) { <button type=\"button\" class=\"rounded-lg px-2 py-3 text-sm capitalize text-slate-700 hover:bg-slate-100 hover:text-slate-900\" [class.bg-slate-900]=\"isSelectedMonth(month.value)\" [class.text-white]=\"isSelectedMonth(month.value)\" (click)=\"selectMonth(month.value, $event)\">{{ month.label }}</button> }</div>\n } @else { <div class=\"grid grid-cols-3 gap-2\">@for (year of yearOptions; track year) { <button type=\"button\" class=\"rounded-lg px-2 py-3 text-sm text-slate-700 hover:bg-slate-100 hover:text-slate-900\" [class.bg-slate-900]=\"isSelectedYear(year)\" [class.text-white]=\"isSelectedYear(year)\" (click)=\"selectYear(year, $event)\">{{ year }}</button> }</div> }\n </div> }\n </div></div>\n </div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1126
1390
|
}
|
|
1127
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type:
|
|
1391
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputDatetimeControlComponent, decorators: [{
|
|
1128
1392
|
type: Component,
|
|
1129
|
-
args: [{ selector: 'input-datetime', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent, LucideAngularModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1130
|
-
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() =>
|
|
1131
|
-
{ provide: NG_VALIDATORS, useExisting: forwardRef(() =>
|
|
1132
|
-
], template: "
|
|
1393
|
+
args: [{ selector: 'input-datetime-control', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent, LucideAngularModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1394
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputDatetimeControlComponent), multi: true },
|
|
1395
|
+
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputDatetimeControlComponent), multi: true },
|
|
1396
|
+
], template: " <div class=\"flex items-end gap-2\"><div class=\"min-w-0 flex-1\"><div class=\"relative\">\n <input data-field-control type=\"text\" [attr.placeholder]=\"placeholder ?? '\u0414\u0414.\u041C\u041C.\u0420\u0420\u0420\u0420 \u0413\u0413:\u0425\u0425'\" maxlength=\"16\" inputmode=\"numeric\" [attr.name]=\"name\" [attr.autocomplete]=\"autocomplete\" [disabled]=\"disabled\" class=\"w-full rounded-xl border border-slate-200 bg-white px-4 py-2 pr-10 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\" [attr.id]=\"controlId\" [value]=\"displayValue\" (click)=\"openCalendar($event)\" (keydown)=\"allowDateKey($event)\" (input)=\"onValueChange($any($event.target).value)\" (blur)=\"onTouched()\" />\n <lucide-icon [img]=\"calendarIcon\" class=\"pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400\"></lucide-icon>\n @if (isCalendarOpen) { <div class=\"absolute left-0 top-full z-50 mt-2 w-[min(22rem,calc(100vw-2rem))] rounded-xl border border-slate-200 bg-white p-4 shadow-xl\" (click)=\"$event.stopPropagation()\">\n <div class=\"mb-4 flex items-center justify-between\" [class.justify-center]=\"calendarView === 'months'\">\n @if (calendarView !== 'months') { <button type=\"button\" class=\"rounded-lg p-2 text-slate-500 hover:bg-slate-100\" aria-label=\"\u041F\u043E\u043F\u0435\u0440\u0435\u0434\u043D\u0456\u0439 \u043F\u0435\u0440\u0456\u043E\u0434\" (click)=\"changeMonth(-1, $event)\"><lucide-icon [img]=\"previousMonthIcon\" class=\"h-4 w-4\"></lucide-icon></button> }\n <div class=\"flex items-center gap-1\"><button type=\"button\" class=\"rounded-lg px-2 py-1 text-sm font-semibold capitalize text-slate-900 hover:bg-slate-100\" (click)=\"showMonthPicker($event)\">{{ monthName }}</button><button type=\"button\" class=\"rounded-lg px-2 py-1 text-sm font-semibold text-slate-900 hover:bg-slate-100\" (click)=\"showYearPicker($event)\">{{ yearLabel }}</button></div>\n @if (calendarView !== 'months') { <button type=\"button\" class=\"rounded-lg p-2 text-slate-500 hover:bg-slate-100\" aria-label=\"\u041D\u0430\u0441\u0442\u0443\u043F\u043D\u0438\u0439 \u043F\u0435\u0440\u0456\u043E\u0434\" (click)=\"changeMonth(1, $event)\"><lucide-icon [img]=\"nextMonthIcon\" class=\"h-4 w-4\"></lucide-icon></button> }\n </div>\n @if (calendarView === 'days') {\n <div class=\"mb-2 grid grid-cols-7 text-center text-xs font-medium text-slate-400\">@for (weekday of ['\u041F\u043D','\u0412\u0442','\u0421\u0440','\u0427\u0442','\u041F\u0442','\u0421\u0431','\u041D\u0434']; track weekday) { <span class=\"py-1\">{{ weekday }}</span> }</div>\n <div class=\"grid grid-cols-7 gap-1\">@for (day of calendarDays; track day.date) { <button type=\"button\" class=\"aspect-square rounded-lg text-sm hover:bg-slate-100 hover:text-slate-900\" [class.text-slate-300]=\"!day.currentMonth\" [class.text-slate-700]=\"day.currentMonth && !isSelected(day.date)\" [class.bg-slate-900]=\"isSelected(day.date)\" [class.text-white]=\"isSelected(day.date)\" (click)=\"selectDate(day.date, $event)\">{{ day.day }}</button> }</div>\n <div class=\"mt-4 grid grid-cols-2 gap-2 border-t border-slate-100 pt-3\"><label class=\"text-[0.65rem] font-medium text-slate-500\">\u0413\u043E\u0434\u0438\u043D\u0438<input type=\"number\" min=\"0\" max=\"23\" [value]=\"selectedHour\" (input)=\"selectedHour = +$any($event.target).value; onTimeChange()\" class=\"mt-1 w-full rounded-xl border border-slate-200 px-3 py-2 text-sm focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\" /></label><label class=\"text-[0.65rem] font-medium text-slate-500\">\u0425\u0432\u0438\u043B\u0438\u043D\u0438<input type=\"number\" min=\"0\" max=\"59\" [value]=\"selectedMinute\" (input)=\"selectedMinute = +$any($event.target).value; onTimeChange()\" class=\"mt-1 w-full rounded-xl border border-slate-200 px-3 py-2 text-sm focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\" /></label></div>\n } @else if (calendarView === 'months') { <div class=\"grid grid-cols-3 gap-2\">@for (month of monthOptions; track month.value) { <button type=\"button\" class=\"rounded-lg px-2 py-3 text-sm capitalize text-slate-700 hover:bg-slate-100 hover:text-slate-900\" [class.bg-slate-900]=\"isSelectedMonth(month.value)\" [class.text-white]=\"isSelectedMonth(month.value)\" (click)=\"selectMonth(month.value, $event)\">{{ month.label }}</button> }</div>\n } @else { <div class=\"grid grid-cols-3 gap-2\">@for (year of yearOptions; track year) { <button type=\"button\" class=\"rounded-lg px-2 py-3 text-sm text-slate-700 hover:bg-slate-100 hover:text-slate-900\" [class.bg-slate-900]=\"isSelectedYear(year)\" [class.text-white]=\"isSelectedYear(year)\" (click)=\"selectYear(year, $event)\">{{ year }}</button> }</div> }\n </div> }\n </div></div>\n </div>\n" }]
|
|
1133
1397
|
}], propDecorators: { label: [{
|
|
1134
1398
|
type: Input
|
|
1135
1399
|
}], hint: [{
|
|
@@ -1144,8 +1408,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1144
1408
|
type: Input
|
|
1145
1409
|
}], required: [{
|
|
1146
1410
|
type: Input
|
|
1147
|
-
}], fullWidth: [{
|
|
1148
|
-
type: Input
|
|
1149
1411
|
}], autocomplete: [{
|
|
1150
1412
|
type: Input
|
|
1151
1413
|
}], pattern: [{
|
|
@@ -1154,6 +1416,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1154
1416
|
type: Input
|
|
1155
1417
|
}], actions: [{
|
|
1156
1418
|
type: Input
|
|
1419
|
+
}], disabled: [{
|
|
1420
|
+
type: Input
|
|
1157
1421
|
}], actionTriggered: [{
|
|
1158
1422
|
type: Output
|
|
1159
1423
|
}], onDocumentClick: [{
|
|
@@ -1164,6 +1428,103 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1164
1428
|
args: ['document:keydown.escape']
|
|
1165
1429
|
}] } });
|
|
1166
1430
|
|
|
1431
|
+
class InputDatetimeComponent {
|
|
1432
|
+
control;
|
|
1433
|
+
label;
|
|
1434
|
+
hint;
|
|
1435
|
+
error;
|
|
1436
|
+
placeholder;
|
|
1437
|
+
name;
|
|
1438
|
+
id;
|
|
1439
|
+
required = false;
|
|
1440
|
+
disabled = false;
|
|
1441
|
+
autocomplete = 'off';
|
|
1442
|
+
pattern;
|
|
1443
|
+
rows = 4;
|
|
1444
|
+
actions = [];
|
|
1445
|
+
actionTriggered = new EventEmitter();
|
|
1446
|
+
pendingValue = '';
|
|
1447
|
+
onChange = () => undefined;
|
|
1448
|
+
onTouched = () => undefined;
|
|
1449
|
+
ngAfterViewInit() { this.control?.registerOnChange((value) => this.onChange(value)); this.control?.registerOnTouched(() => this.onTouched()); this.control?.writeValue(this.pendingValue); }
|
|
1450
|
+
writeValue(value) { this.pendingValue = value; this.control?.writeValue(value); }
|
|
1451
|
+
registerOnChange(fn) { this.onChange = fn; }
|
|
1452
|
+
registerOnTouched(fn) { this.onTouched = fn; }
|
|
1453
|
+
setDisabledState(value) { this.disabled = value; }
|
|
1454
|
+
validate(control) { return validateFormControl(control, this.required, this.pattern); }
|
|
1455
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputDatetimeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1456
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputDatetimeComponent, isStandalone: true, selector: "input-datetime", inputs: { label: "label", hint: "hint", error: "error", placeholder: "placeholder", name: "name", id: "id", required: "required", disabled: "disabled", autocomplete: "autocomplete", pattern: "pattern", rows: "rows", actions: "actions" }, outputs: { actionTriggered: "actionTriggered" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputDatetimeComponent), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => InputDatetimeComponent), multi: true }], viewQueries: [{ propertyName: "control", first: true, predicate: InputDatetimeControlComponent, descendants: true }], ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"id\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"actionTriggered.emit($event)\">\n <input-datetime-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"id\" [required]=\"required\" [disabled]=\"disabled\" [autocomplete]=\"autocomplete\" [pattern]=\"pattern\" [rows]=\"rows\" />\n</field-frame>\n", dependencies: [{ kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputDatetimeControlComponent, selector: "input-datetime-control", inputs: ["label", "hint", "placeholder", "name", "id", "rows", "required", "autocomplete", "pattern", "error", "actions", "disabled"], outputs: ["actionTriggered"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1457
|
+
}
|
|
1458
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputDatetimeComponent, decorators: [{
|
|
1459
|
+
type: Component,
|
|
1460
|
+
args: [{ selector: 'input-datetime', standalone: true, imports: [FieldFrameComponent, InputDatetimeControlComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputDatetimeComponent), multi: true }, { provide: NG_VALIDATORS, useExisting: forwardRef(() => InputDatetimeComponent), multi: true }], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"id\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"actionTriggered.emit($event)\">\n <input-datetime-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"id\" [required]=\"required\" [disabled]=\"disabled\" [autocomplete]=\"autocomplete\" [pattern]=\"pattern\" [rows]=\"rows\" />\n</field-frame>\n" }]
|
|
1461
|
+
}], propDecorators: { control: [{
|
|
1462
|
+
type: ViewChild,
|
|
1463
|
+
args: [InputDatetimeControlComponent]
|
|
1464
|
+
}], label: [{
|
|
1465
|
+
type: Input
|
|
1466
|
+
}], hint: [{
|
|
1467
|
+
type: Input
|
|
1468
|
+
}], error: [{
|
|
1469
|
+
type: Input
|
|
1470
|
+
}], placeholder: [{
|
|
1471
|
+
type: Input
|
|
1472
|
+
}], name: [{
|
|
1473
|
+
type: Input
|
|
1474
|
+
}], id: [{
|
|
1475
|
+
type: Input
|
|
1476
|
+
}], required: [{
|
|
1477
|
+
type: Input
|
|
1478
|
+
}], disabled: [{
|
|
1479
|
+
type: Input
|
|
1480
|
+
}], autocomplete: [{
|
|
1481
|
+
type: Input
|
|
1482
|
+
}], pattern: [{
|
|
1483
|
+
type: Input
|
|
1484
|
+
}], rows: [{
|
|
1485
|
+
type: Input
|
|
1486
|
+
}], actions: [{
|
|
1487
|
+
type: Input
|
|
1488
|
+
}], actionTriggered: [{
|
|
1489
|
+
type: Output
|
|
1490
|
+
}] } });
|
|
1491
|
+
|
|
1492
|
+
class InputEmailControlComponent {
|
|
1493
|
+
placeholder;
|
|
1494
|
+
name;
|
|
1495
|
+
id;
|
|
1496
|
+
autocomplete;
|
|
1497
|
+
pattern;
|
|
1498
|
+
disabled = false;
|
|
1499
|
+
value = '';
|
|
1500
|
+
valueChange = new EventEmitter();
|
|
1501
|
+
touched = new EventEmitter();
|
|
1502
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputEmailControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1503
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputEmailControlComponent, isStandalone: true, selector: "input-email-control", inputs: { placeholder: "placeholder", name: "name", id: "id", autocomplete: "autocomplete", pattern: "pattern", disabled: "disabled", value: "value" }, outputs: { valueChange: "valueChange", touched: "touched" }, ngImport: i0, template: `<input-text-control [placeholder]="placeholder" [name]="name" [id]="id" type="email" [autocomplete]="autocomplete" [pattern]="pattern" [disabled]="disabled" [value]="value" (valueChange)="valueChange.emit($event)" (touched)="touched.emit()" />`, isInline: true, dependencies: [{ kind: "component", type: InputTextControlComponent, selector: "input-text-control", inputs: ["placeholder", "name", "id", "type", "element", "rows", "autocomplete", "pattern", "disabled", "value"], outputs: ["valueChange", "touched", "enterPressed"] }] });
|
|
1504
|
+
}
|
|
1505
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputEmailControlComponent, decorators: [{
|
|
1506
|
+
type: Component,
|
|
1507
|
+
args: [{ selector: 'input-email-control', standalone: true, imports: [InputTextControlComponent], template: `<input-text-control [placeholder]="placeholder" [name]="name" [id]="id" type="email" [autocomplete]="autocomplete" [pattern]="pattern" [disabled]="disabled" [value]="value" (valueChange)="valueChange.emit($event)" (touched)="touched.emit()" />` }]
|
|
1508
|
+
}], propDecorators: { placeholder: [{
|
|
1509
|
+
type: Input
|
|
1510
|
+
}], name: [{
|
|
1511
|
+
type: Input
|
|
1512
|
+
}], id: [{
|
|
1513
|
+
type: Input
|
|
1514
|
+
}], autocomplete: [{
|
|
1515
|
+
type: Input
|
|
1516
|
+
}], pattern: [{
|
|
1517
|
+
type: Input
|
|
1518
|
+
}], disabled: [{
|
|
1519
|
+
type: Input
|
|
1520
|
+
}], value: [{
|
|
1521
|
+
type: Input
|
|
1522
|
+
}], valueChange: [{
|
|
1523
|
+
type: Output
|
|
1524
|
+
}], touched: [{
|
|
1525
|
+
type: Output
|
|
1526
|
+
}] } });
|
|
1527
|
+
|
|
1167
1528
|
class InputEmailComponent {
|
|
1168
1529
|
cdr = inject(ChangeDetectorRef);
|
|
1169
1530
|
label;
|
|
@@ -1175,7 +1536,6 @@ class InputEmailComponent {
|
|
|
1175
1536
|
element = 'input';
|
|
1176
1537
|
rows = 4;
|
|
1177
1538
|
required = false;
|
|
1178
|
-
fullWidth = false;
|
|
1179
1539
|
autocomplete;
|
|
1180
1540
|
pattern;
|
|
1181
1541
|
error;
|
|
@@ -1214,25 +1574,25 @@ class InputEmailComponent {
|
|
|
1214
1574
|
this.actionTriggered.emit(action);
|
|
1215
1575
|
}
|
|
1216
1576
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputEmailComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1217
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1577
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputEmailComponent, isStandalone: true, selector: "input-email", inputs: { label: "label", hint: "hint", placeholder: "placeholder", name: "name", id: "id", rows: "rows", required: "required", autocomplete: "autocomplete", pattern: "pattern", error: "error", actions: "actions" }, outputs: { actionTriggered: "actionTriggered" }, providers: [
|
|
1218
1578
|
{
|
|
1219
1579
|
provide: NG_VALUE_ACCESSOR,
|
|
1220
1580
|
useExisting: forwardRef(() => InputEmailComponent),
|
|
1221
1581
|
multi: true,
|
|
1222
1582
|
},
|
|
1223
1583
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputEmailComponent), multi: true },
|
|
1224
|
-
], ngImport: i0, template: "<
|
|
1584
|
+
], ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"triggerAction($event)\">\n <input-email-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"controlId\" [autocomplete]=\"autocomplete\" [pattern]=\"pattern\" [disabled]=\"disabled\" [value]=\"value\" (valueChange)=\"onValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputEmailControlComponent, selector: "input-email-control", inputs: ["placeholder", "name", "id", "autocomplete", "pattern", "disabled", "value"], outputs: ["valueChange", "touched"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1225
1585
|
}
|
|
1226
1586
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputEmailComponent, decorators: [{
|
|
1227
1587
|
type: Component,
|
|
1228
|
-
args: [{ selector: 'input-email', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1588
|
+
args: [{ selector: 'input-email', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent, FieldFrameComponent, InputEmailControlComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1229
1589
|
{
|
|
1230
1590
|
provide: NG_VALUE_ACCESSOR,
|
|
1231
1591
|
useExisting: forwardRef(() => InputEmailComponent),
|
|
1232
1592
|
multi: true,
|
|
1233
1593
|
},
|
|
1234
1594
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputEmailComponent), multi: true },
|
|
1235
|
-
], template: "<
|
|
1595
|
+
], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"triggerAction($event)\">\n <input-email-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"controlId\" [autocomplete]=\"autocomplete\" [pattern]=\"pattern\" [disabled]=\"disabled\" [value]=\"value\" (valueChange)=\"onValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n" }]
|
|
1236
1596
|
}], propDecorators: { label: [{
|
|
1237
1597
|
type: Input
|
|
1238
1598
|
}], hint: [{
|
|
@@ -1247,8 +1607,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1247
1607
|
type: Input
|
|
1248
1608
|
}], required: [{
|
|
1249
1609
|
type: Input
|
|
1250
|
-
}], fullWidth: [{
|
|
1251
|
-
type: Input
|
|
1252
1610
|
}], autocomplete: [{
|
|
1253
1611
|
type: Input
|
|
1254
1612
|
}], pattern: [{
|
|
@@ -1261,6 +1619,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1261
1619
|
type: Output
|
|
1262
1620
|
}] } });
|
|
1263
1621
|
|
|
1622
|
+
class InputNumberControlComponent {
|
|
1623
|
+
placeholder;
|
|
1624
|
+
name;
|
|
1625
|
+
id;
|
|
1626
|
+
disabled = false;
|
|
1627
|
+
value = '';
|
|
1628
|
+
valueChange = new EventEmitter();
|
|
1629
|
+
touched = new EventEmitter();
|
|
1630
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputNumberControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1631
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputNumberControlComponent, isStandalone: true, selector: "input-number-control", inputs: { placeholder: "placeholder", name: "name", id: "id", disabled: "disabled", value: "value" }, outputs: { valueChange: "valueChange", touched: "touched" }, ngImport: i0, template: `<input-text-control [placeholder]="placeholder" [name]="name" [id]="id" type="number" [disabled]="disabled" [value]="value" (valueChange)="valueChange.emit($event)" (touched)="touched.emit()" />`, isInline: true, dependencies: [{ kind: "component", type: InputTextControlComponent, selector: "input-text-control", inputs: ["placeholder", "name", "id", "type", "element", "rows", "autocomplete", "pattern", "disabled", "value"], outputs: ["valueChange", "touched", "enterPressed"] }] });
|
|
1632
|
+
}
|
|
1633
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputNumberControlComponent, decorators: [{
|
|
1634
|
+
type: Component,
|
|
1635
|
+
args: [{ selector: 'input-number-control', standalone: true, imports: [InputTextControlComponent], template: `<input-text-control [placeholder]="placeholder" [name]="name" [id]="id" type="number" [disabled]="disabled" [value]="value" (valueChange)="valueChange.emit($event)" (touched)="touched.emit()" />` }]
|
|
1636
|
+
}], propDecorators: { placeholder: [{
|
|
1637
|
+
type: Input
|
|
1638
|
+
}], name: [{
|
|
1639
|
+
type: Input
|
|
1640
|
+
}], id: [{
|
|
1641
|
+
type: Input
|
|
1642
|
+
}], disabled: [{
|
|
1643
|
+
type: Input
|
|
1644
|
+
}], value: [{
|
|
1645
|
+
type: Input
|
|
1646
|
+
}], valueChange: [{
|
|
1647
|
+
type: Output
|
|
1648
|
+
}], touched: [{
|
|
1649
|
+
type: Output
|
|
1650
|
+
}] } });
|
|
1651
|
+
|
|
1264
1652
|
class InputNumberComponent {
|
|
1265
1653
|
cdr = inject(ChangeDetectorRef);
|
|
1266
1654
|
label;
|
|
@@ -1272,7 +1660,6 @@ class InputNumberComponent {
|
|
|
1272
1660
|
element = 'input';
|
|
1273
1661
|
rows = 4;
|
|
1274
1662
|
required = false;
|
|
1275
|
-
fullWidth = false;
|
|
1276
1663
|
autocomplete;
|
|
1277
1664
|
disabled = false;
|
|
1278
1665
|
pattern;
|
|
@@ -1314,25 +1701,25 @@ class InputNumberComponent {
|
|
|
1314
1701
|
this.actionTriggered.emit(action);
|
|
1315
1702
|
}
|
|
1316
1703
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputNumberComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1317
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1704
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputNumberComponent, isStandalone: true, selector: "input-number", inputs: { label: "label", hint: "hint", placeholder: "placeholder", name: "name", id: "id", rows: "rows", required: "required", autocomplete: "autocomplete", disabled: "disabled", pattern: "pattern", error: "error", actions: "actions" }, outputs: { actionTriggered: "actionTriggered" }, providers: [
|
|
1318
1705
|
{
|
|
1319
1706
|
provide: NG_VALUE_ACCESSOR,
|
|
1320
1707
|
useExisting: forwardRef(() => InputNumberComponent),
|
|
1321
1708
|
multi: true,
|
|
1322
1709
|
},
|
|
1323
1710
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputNumberComponent), multi: true },
|
|
1324
|
-
], ngImport: i0, template: "<
|
|
1711
|
+
], ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"triggerAction($event)\">\n <input-number-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"controlId\" [disabled]=\"disabled\" [value]=\"value\" (valueChange)=\"onValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n", styles: ["input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{appearance:none;-webkit-appearance:none;margin:0}\n", "input[type=number]{-moz-appearance:textfield}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputNumberControlComponent, selector: "input-number-control", inputs: ["placeholder", "name", "id", "disabled", "value"], outputs: ["valueChange", "touched"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1325
1712
|
}
|
|
1326
1713
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputNumberComponent, decorators: [{
|
|
1327
1714
|
type: Component,
|
|
1328
|
-
args: [{ selector: 'input-number', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1715
|
+
args: [{ selector: 'input-number', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent, FieldFrameComponent, InputNumberControlComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1329
1716
|
{
|
|
1330
1717
|
provide: NG_VALUE_ACCESSOR,
|
|
1331
1718
|
useExisting: forwardRef(() => InputNumberComponent),
|
|
1332
1719
|
multi: true,
|
|
1333
1720
|
},
|
|
1334
1721
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputNumberComponent), multi: true },
|
|
1335
|
-
], template: "<
|
|
1722
|
+
], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"triggerAction($event)\">\n <input-number-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"controlId\" [disabled]=\"disabled\" [value]=\"value\" (valueChange)=\"onValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n", styles: ["input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{appearance:none;-webkit-appearance:none;margin:0}\n", "input[type=number]{-moz-appearance:textfield}\n"] }]
|
|
1336
1723
|
}], propDecorators: { label: [{
|
|
1337
1724
|
type: Input
|
|
1338
1725
|
}], hint: [{
|
|
@@ -1347,8 +1734,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1347
1734
|
type: Input
|
|
1348
1735
|
}], required: [{
|
|
1349
1736
|
type: Input
|
|
1350
|
-
}], fullWidth: [{
|
|
1351
|
-
type: Input
|
|
1352
1737
|
}], autocomplete: [{
|
|
1353
1738
|
type: Input
|
|
1354
1739
|
}], disabled: [{
|
|
@@ -1363,6 +1748,64 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1363
1748
|
type: Output
|
|
1364
1749
|
}] } });
|
|
1365
1750
|
|
|
1751
|
+
class InputPasswordControlComponent {
|
|
1752
|
+
showIcon = Eye;
|
|
1753
|
+
hideIcon = EyeOff;
|
|
1754
|
+
placeholder;
|
|
1755
|
+
name;
|
|
1756
|
+
id;
|
|
1757
|
+
autocomplete;
|
|
1758
|
+
pattern;
|
|
1759
|
+
disabled = false;
|
|
1760
|
+
value = '';
|
|
1761
|
+
valueChange = new EventEmitter();
|
|
1762
|
+
touched = new EventEmitter();
|
|
1763
|
+
visible = false;
|
|
1764
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputPasswordControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1765
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputPasswordControlComponent, isStandalone: true, selector: "input-password-control", inputs: { placeholder: "placeholder", name: "name", id: "id", autocomplete: "autocomplete", pattern: "pattern", disabled: "disabled", value: "value" }, outputs: { valueChange: "valueChange", touched: "touched" }, ngImport: i0, template: `
|
|
1766
|
+
<div class="relative">
|
|
1767
|
+
<input data-field-control [attr.type]="visible ? 'text' : 'password'" [attr.placeholder]="placeholder" [attr.name]="name" [attr.autocomplete]="autocomplete" [attr.pattern]="pattern" [disabled]="disabled" class="w-full rounded-xl border border-slate-200 bg-white px-4 py-2 pr-10 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200" [attr.id]="id" [value]="value" (input)="valueChange.emit($any($event.target).value)" (blur)="touched.emit()" />
|
|
1768
|
+
<button type="button" class="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 transition hover:text-slate-700 focus:outline-none focus:ring-2 focus:ring-slate-200" [attr.aria-label]="visible ? 'Сховати пароль' : 'Показати пароль'" [disabled]="disabled" (mousedown)="$event.preventDefault()" (click)="visible = !visible">
|
|
1769
|
+
<lucide-icon [img]="visible ? hideIcon : showIcon" class="h-4 w-4" aria-hidden="true"></lucide-icon>
|
|
1770
|
+
</button>
|
|
1771
|
+
</div>
|
|
1772
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }] });
|
|
1773
|
+
}
|
|
1774
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputPasswordControlComponent, decorators: [{
|
|
1775
|
+
type: Component,
|
|
1776
|
+
args: [{
|
|
1777
|
+
selector: 'input-password-control',
|
|
1778
|
+
standalone: true,
|
|
1779
|
+
imports: [CommonModule, LucideAngularModule],
|
|
1780
|
+
template: `
|
|
1781
|
+
<div class="relative">
|
|
1782
|
+
<input data-field-control [attr.type]="visible ? 'text' : 'password'" [attr.placeholder]="placeholder" [attr.name]="name" [attr.autocomplete]="autocomplete" [attr.pattern]="pattern" [disabled]="disabled" class="w-full rounded-xl border border-slate-200 bg-white px-4 py-2 pr-10 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200" [attr.id]="id" [value]="value" (input)="valueChange.emit($any($event.target).value)" (blur)="touched.emit()" />
|
|
1783
|
+
<button type="button" class="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 transition hover:text-slate-700 focus:outline-none focus:ring-2 focus:ring-slate-200" [attr.aria-label]="visible ? 'Сховати пароль' : 'Показати пароль'" [disabled]="disabled" (mousedown)="$event.preventDefault()" (click)="visible = !visible">
|
|
1784
|
+
<lucide-icon [img]="visible ? hideIcon : showIcon" class="h-4 w-4" aria-hidden="true"></lucide-icon>
|
|
1785
|
+
</button>
|
|
1786
|
+
</div>
|
|
1787
|
+
`,
|
|
1788
|
+
}]
|
|
1789
|
+
}], propDecorators: { placeholder: [{
|
|
1790
|
+
type: Input
|
|
1791
|
+
}], name: [{
|
|
1792
|
+
type: Input
|
|
1793
|
+
}], id: [{
|
|
1794
|
+
type: Input
|
|
1795
|
+
}], autocomplete: [{
|
|
1796
|
+
type: Input
|
|
1797
|
+
}], pattern: [{
|
|
1798
|
+
type: Input
|
|
1799
|
+
}], disabled: [{
|
|
1800
|
+
type: Input
|
|
1801
|
+
}], value: [{
|
|
1802
|
+
type: Input
|
|
1803
|
+
}], valueChange: [{
|
|
1804
|
+
type: Output
|
|
1805
|
+
}], touched: [{
|
|
1806
|
+
type: Output
|
|
1807
|
+
}] } });
|
|
1808
|
+
|
|
1366
1809
|
class InputPasswordComponent {
|
|
1367
1810
|
cdr = inject(ChangeDetectorRef);
|
|
1368
1811
|
label;
|
|
@@ -1376,7 +1819,6 @@ class InputPasswordComponent {
|
|
|
1376
1819
|
element = 'input';
|
|
1377
1820
|
rows = 4;
|
|
1378
1821
|
required = false;
|
|
1379
|
-
fullWidth = false;
|
|
1380
1822
|
autocomplete;
|
|
1381
1823
|
pattern;
|
|
1382
1824
|
error;
|
|
@@ -1421,25 +1863,25 @@ class InputPasswordComponent {
|
|
|
1421
1863
|
this.actionTriggered.emit(action);
|
|
1422
1864
|
}
|
|
1423
1865
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputPasswordComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1424
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1866
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputPasswordComponent, isStandalone: true, selector: "input-password", inputs: { label: "label", hint: "hint", placeholder: "placeholder", name: "name", id: "id", rows: "rows", required: "required", autocomplete: "autocomplete", pattern: "pattern", error: "error", actions: "actions" }, outputs: { actionTriggered: "actionTriggered" }, providers: [
|
|
1425
1867
|
{
|
|
1426
1868
|
provide: NG_VALUE_ACCESSOR,
|
|
1427
1869
|
useExisting: forwardRef(() => InputPasswordComponent),
|
|
1428
1870
|
multi: true,
|
|
1429
1871
|
},
|
|
1430
1872
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputPasswordComponent), multi: true },
|
|
1431
|
-
], ngImport: i0, template: "<
|
|
1873
|
+
], ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"triggerAction($event)\">\n <input-password-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"controlId\" [autocomplete]=\"autocomplete\" [pattern]=\"pattern\" [disabled]=\"disabled\" [value]=\"value\" (valueChange)=\"onValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputPasswordControlComponent, selector: "input-password-control", inputs: ["placeholder", "name", "id", "autocomplete", "pattern", "disabled", "value"], outputs: ["valueChange", "touched"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1432
1874
|
}
|
|
1433
1875
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputPasswordComponent, decorators: [{
|
|
1434
1876
|
type: Component,
|
|
1435
|
-
args: [{ selector: 'input-password', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent, LucideAngularModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1877
|
+
args: [{ selector: 'input-password', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent, LucideAngularModule, FieldFrameComponent, InputPasswordControlComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1436
1878
|
{
|
|
1437
1879
|
provide: NG_VALUE_ACCESSOR,
|
|
1438
1880
|
useExisting: forwardRef(() => InputPasswordComponent),
|
|
1439
1881
|
multi: true,
|
|
1440
1882
|
},
|
|
1441
1883
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputPasswordComponent), multi: true },
|
|
1442
|
-
], template: "<
|
|
1884
|
+
], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"triggerAction($event)\">\n <input-password-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"controlId\" [autocomplete]=\"autocomplete\" [pattern]=\"pattern\" [disabled]=\"disabled\" [value]=\"value\" (valueChange)=\"onValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n" }]
|
|
1443
1885
|
}], propDecorators: { label: [{
|
|
1444
1886
|
type: Input
|
|
1445
1887
|
}], hint: [{
|
|
@@ -1454,8 +1896,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1454
1896
|
type: Input
|
|
1455
1897
|
}], required: [{
|
|
1456
1898
|
type: Input
|
|
1457
|
-
}], fullWidth: [{
|
|
1458
|
-
type: Input
|
|
1459
1899
|
}], autocomplete: [{
|
|
1460
1900
|
type: Input
|
|
1461
1901
|
}], pattern: [{
|
|
@@ -1479,7 +1919,6 @@ class InputTextComponent {
|
|
|
1479
1919
|
element = 'input';
|
|
1480
1920
|
rows = 4;
|
|
1481
1921
|
required = false;
|
|
1482
|
-
fullWidth = false;
|
|
1483
1922
|
autocomplete;
|
|
1484
1923
|
pattern;
|
|
1485
1924
|
error;
|
|
@@ -1518,25 +1957,25 @@ class InputTextComponent {
|
|
|
1518
1957
|
this.actionTriggered.emit(action);
|
|
1519
1958
|
}
|
|
1520
1959
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputTextComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1521
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1960
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputTextComponent, isStandalone: true, selector: "input-text", inputs: { label: "label", hint: "hint", placeholder: "placeholder", name: "name", id: "id", rows: "rows", required: "required", autocomplete: "autocomplete", pattern: "pattern", error: "error", actions: "actions" }, outputs: { actionTriggered: "actionTriggered" }, providers: [
|
|
1522
1961
|
{
|
|
1523
1962
|
provide: NG_VALUE_ACCESSOR,
|
|
1524
1963
|
useExisting: forwardRef(() => InputTextComponent),
|
|
1525
1964
|
multi: true,
|
|
1526
1965
|
},
|
|
1527
1966
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputTextComponent), multi: true },
|
|
1528
|
-
], ngImport: i0, template: "<
|
|
1967
|
+
], ngImport: i0, template: "<field-frame\n [label]=\"label\"\n [hint]=\"hint\"\n [error]=\"error\"\n [required]=\"required\"\n [forId]=\"controlId\"\n [disabled]=\"disabled\"\n [actions]=\"actions\"\n (actionTriggered)=\"triggerAction($event)\"\n>\n <input-text-control\n [placeholder]=\"placeholder\"\n [name]=\"name\"\n [id]=\"controlId\"\n [type]=\"type\"\n [element]=\"element\"\n [rows]=\"rows\"\n [autocomplete]=\"autocomplete\"\n [pattern]=\"pattern\"\n [disabled]=\"disabled\"\n [value]=\"value\"\n (valueChange)=\"onValueChange($event)\"\n (touched)=\"onTouched()\"\n />\n</field-frame>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputTextControlComponent, selector: "input-text-control", inputs: ["placeholder", "name", "id", "type", "element", "rows", "autocomplete", "pattern", "disabled", "value"], outputs: ["valueChange", "touched", "enterPressed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1529
1968
|
}
|
|
1530
1969
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputTextComponent, decorators: [{
|
|
1531
1970
|
type: Component,
|
|
1532
|
-
args: [{ selector: 'input-text', standalone: true, imports: [CommonModule, FormsModule,
|
|
1971
|
+
args: [{ selector: 'input-text', standalone: true, imports: [CommonModule, FormsModule, FieldFrameComponent, InputTextControlComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1533
1972
|
{
|
|
1534
1973
|
provide: NG_VALUE_ACCESSOR,
|
|
1535
1974
|
useExisting: forwardRef(() => InputTextComponent),
|
|
1536
1975
|
multi: true,
|
|
1537
1976
|
},
|
|
1538
1977
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputTextComponent), multi: true },
|
|
1539
|
-
], template: "<
|
|
1978
|
+
], template: "<field-frame\n [label]=\"label\"\n [hint]=\"hint\"\n [error]=\"error\"\n [required]=\"required\"\n [forId]=\"controlId\"\n [disabled]=\"disabled\"\n [actions]=\"actions\"\n (actionTriggered)=\"triggerAction($event)\"\n>\n <input-text-control\n [placeholder]=\"placeholder\"\n [name]=\"name\"\n [id]=\"controlId\"\n [type]=\"type\"\n [element]=\"element\"\n [rows]=\"rows\"\n [autocomplete]=\"autocomplete\"\n [pattern]=\"pattern\"\n [disabled]=\"disabled\"\n [value]=\"value\"\n (valueChange)=\"onValueChange($event)\"\n (touched)=\"onTouched()\"\n />\n</field-frame>\n" }]
|
|
1540
1979
|
}], propDecorators: { label: [{
|
|
1541
1980
|
type: Input
|
|
1542
1981
|
}], hint: [{
|
|
@@ -1551,8 +1990,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1551
1990
|
type: Input
|
|
1552
1991
|
}], required: [{
|
|
1553
1992
|
type: Input
|
|
1554
|
-
}], fullWidth: [{
|
|
1555
|
-
type: Input
|
|
1556
1993
|
}], autocomplete: [{
|
|
1557
1994
|
type: Input
|
|
1558
1995
|
}], pattern: [{
|
|
@@ -1565,6 +2002,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1565
2002
|
type: Output
|
|
1566
2003
|
}] } });
|
|
1567
2004
|
|
|
2005
|
+
class InputTextareaControlComponent {
|
|
2006
|
+
placeholder;
|
|
2007
|
+
name;
|
|
2008
|
+
id;
|
|
2009
|
+
rows = 4;
|
|
2010
|
+
disabled = false;
|
|
2011
|
+
value = '';
|
|
2012
|
+
valueChange = new EventEmitter();
|
|
2013
|
+
touched = new EventEmitter();
|
|
2014
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputTextareaControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2015
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputTextareaControlComponent, isStandalone: true, selector: "input-textarea-control", inputs: { placeholder: "placeholder", name: "name", id: "id", rows: "rows", disabled: "disabled", value: "value" }, outputs: { valueChange: "valueChange", touched: "touched" }, ngImport: i0, template: `<input-text-control [placeholder]="placeholder" [name]="name" [id]="id" element="textarea" [rows]="rows" [disabled]="disabled" [value]="value" (valueChange)="valueChange.emit($event)" (touched)="touched.emit()" />`, isInline: true, dependencies: [{ kind: "component", type: InputTextControlComponent, selector: "input-text-control", inputs: ["placeholder", "name", "id", "type", "element", "rows", "autocomplete", "pattern", "disabled", "value"], outputs: ["valueChange", "touched", "enterPressed"] }] });
|
|
2016
|
+
}
|
|
2017
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputTextareaControlComponent, decorators: [{
|
|
2018
|
+
type: Component,
|
|
2019
|
+
args: [{ selector: 'input-textarea-control', standalone: true, imports: [InputTextControlComponent], template: `<input-text-control [placeholder]="placeholder" [name]="name" [id]="id" element="textarea" [rows]="rows" [disabled]="disabled" [value]="value" (valueChange)="valueChange.emit($event)" (touched)="touched.emit()" />` }]
|
|
2020
|
+
}], propDecorators: { placeholder: [{
|
|
2021
|
+
type: Input
|
|
2022
|
+
}], name: [{
|
|
2023
|
+
type: Input
|
|
2024
|
+
}], id: [{
|
|
2025
|
+
type: Input
|
|
2026
|
+
}], rows: [{
|
|
2027
|
+
type: Input
|
|
2028
|
+
}], disabled: [{
|
|
2029
|
+
type: Input
|
|
2030
|
+
}], value: [{
|
|
2031
|
+
type: Input
|
|
2032
|
+
}], valueChange: [{
|
|
2033
|
+
type: Output
|
|
2034
|
+
}], touched: [{
|
|
2035
|
+
type: Output
|
|
2036
|
+
}] } });
|
|
2037
|
+
|
|
1568
2038
|
class InputTextareaComponent {
|
|
1569
2039
|
cdr = inject(ChangeDetectorRef);
|
|
1570
2040
|
label;
|
|
@@ -1576,7 +2046,6 @@ class InputTextareaComponent {
|
|
|
1576
2046
|
element = 'textarea';
|
|
1577
2047
|
rows = 4;
|
|
1578
2048
|
required = false;
|
|
1579
|
-
fullWidth = false;
|
|
1580
2049
|
autocomplete;
|
|
1581
2050
|
pattern;
|
|
1582
2051
|
error;
|
|
@@ -1615,25 +2084,25 @@ class InputTextareaComponent {
|
|
|
1615
2084
|
this.actionTriggered.emit(action);
|
|
1616
2085
|
}
|
|
1617
2086
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputTextareaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1618
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
2087
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputTextareaComponent, isStandalone: true, selector: "input-textarea", inputs: { label: "label", hint: "hint", placeholder: "placeholder", name: "name", id: "id", rows: "rows", required: "required", autocomplete: "autocomplete", pattern: "pattern", error: "error", actions: "actions" }, outputs: { actionTriggered: "actionTriggered" }, providers: [
|
|
1619
2088
|
{
|
|
1620
2089
|
provide: NG_VALUE_ACCESSOR,
|
|
1621
2090
|
useExisting: forwardRef(() => InputTextareaComponent),
|
|
1622
2091
|
multi: true,
|
|
1623
2092
|
},
|
|
1624
2093
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputTextareaComponent), multi: true },
|
|
1625
|
-
], ngImport: i0, template: "<
|
|
2094
|
+
], ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"triggerAction($event)\">\n <input-textarea-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"controlId\" [rows]=\"rows\" [disabled]=\"disabled\" [value]=\"value\" (valueChange)=\"onValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputTextareaControlComponent, selector: "input-textarea-control", inputs: ["placeholder", "name", "id", "rows", "disabled", "value"], outputs: ["valueChange", "touched"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1626
2095
|
}
|
|
1627
2096
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputTextareaComponent, decorators: [{
|
|
1628
2097
|
type: Component,
|
|
1629
|
-
args: [{ selector: 'input-textarea', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
2098
|
+
args: [{ selector: 'input-textarea', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent, FieldFrameComponent, InputTextareaControlComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
1630
2099
|
{
|
|
1631
2100
|
provide: NG_VALUE_ACCESSOR,
|
|
1632
2101
|
useExisting: forwardRef(() => InputTextareaComponent),
|
|
1633
2102
|
multi: true,
|
|
1634
2103
|
},
|
|
1635
2104
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputTextareaComponent), multi: true },
|
|
1636
|
-
], template: "<
|
|
2105
|
+
], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"triggerAction($event)\">\n <input-textarea-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"controlId\" [rows]=\"rows\" [disabled]=\"disabled\" [value]=\"value\" (valueChange)=\"onValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n" }]
|
|
1637
2106
|
}], propDecorators: { label: [{
|
|
1638
2107
|
type: Input
|
|
1639
2108
|
}], hint: [{
|
|
@@ -1648,8 +2117,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1648
2117
|
type: Input
|
|
1649
2118
|
}], required: [{
|
|
1650
2119
|
type: Input
|
|
1651
|
-
}], fullWidth: [{
|
|
1652
|
-
type: Input
|
|
1653
2120
|
}], autocomplete: [{
|
|
1654
2121
|
type: Input
|
|
1655
2122
|
}], pattern: [{
|
|
@@ -1662,15 +2129,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1662
2129
|
type: Output
|
|
1663
2130
|
}] } });
|
|
1664
2131
|
|
|
2132
|
+
class InputFileControlComponent {
|
|
2133
|
+
accept;
|
|
2134
|
+
multiple = false;
|
|
2135
|
+
disabled = false;
|
|
2136
|
+
selectedFiles = [];
|
|
2137
|
+
filesSelected = new EventEmitter();
|
|
2138
|
+
removeFile = new EventEmitter();
|
|
2139
|
+
touched = new EventEmitter();
|
|
2140
|
+
onFilesSelected(event) {
|
|
2141
|
+
const input = event.target;
|
|
2142
|
+
this.filesSelected.emit(Array.from(input.files ?? []));
|
|
2143
|
+
input.value = '';
|
|
2144
|
+
}
|
|
2145
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputFileControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2146
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: InputFileControlComponent, isStandalone: true, selector: "input-file-control", inputs: { accept: "accept", multiple: "multiple", disabled: "disabled", selectedFiles: "selectedFiles" }, outputs: { filesSelected: "filesSelected", removeFile: "removeFile", touched: "touched" }, ngImport: i0, template: "<input data-field-control type=\"file\" class=\"rounded-xl border border-slate-200 bg-white px-3 py-2 text-sm normal-case tracking-normal text-slate-800 file:mr-3 file:rounded-lg file:border-0 file:bg-slate-900 file:px-3 file:py-2 file:text-sm file:font-medium file:text-white\" [attr.accept]=\"accept ?? null\" [attr.multiple]=\"multiple ? '' : null\" [disabled]=\"disabled\" (change)=\"onFilesSelected($event)\" (blur)=\"touched.emit()\" />\n@if (selectedFiles.length) {\n <div class=\"mt-1 flex flex-col gap-1 text-[0.7rem] font-normal normal-case tracking-normal text-slate-700\">\n @for (file of selectedFiles; track file.name + file.size; let i = $index) {\n <div class=\"flex items-center justify-between rounded border border-slate-200 bg-slate-50 px-2 py-1\">\n <span class=\"truncate pr-2\">{{ file.name }}</span>\n <button type=\"button\" class=\"text-rose-600\" [disabled]=\"disabled\" (click)=\"removeFile.emit(i)\">\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438</button>\n </div>\n }\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
2147
|
+
}
|
|
2148
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputFileControlComponent, decorators: [{
|
|
2149
|
+
type: Component,
|
|
2150
|
+
args: [{ selector: 'input-file-control', standalone: true, imports: [CommonModule], template: "<input data-field-control type=\"file\" class=\"rounded-xl border border-slate-200 bg-white px-3 py-2 text-sm normal-case tracking-normal text-slate-800 file:mr-3 file:rounded-lg file:border-0 file:bg-slate-900 file:px-3 file:py-2 file:text-sm file:font-medium file:text-white\" [attr.accept]=\"accept ?? null\" [attr.multiple]=\"multiple ? '' : null\" [disabled]=\"disabled\" (change)=\"onFilesSelected($event)\" (blur)=\"touched.emit()\" />\n@if (selectedFiles.length) {\n <div class=\"mt-1 flex flex-col gap-1 text-[0.7rem] font-normal normal-case tracking-normal text-slate-700\">\n @for (file of selectedFiles; track file.name + file.size; let i = $index) {\n <div class=\"flex items-center justify-between rounded border border-slate-200 bg-slate-50 px-2 py-1\">\n <span class=\"truncate pr-2\">{{ file.name }}</span>\n <button type=\"button\" class=\"text-rose-600\" [disabled]=\"disabled\" (click)=\"removeFile.emit(i)\">\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438</button>\n </div>\n }\n </div>\n}\n" }]
|
|
2151
|
+
}], propDecorators: { accept: [{
|
|
2152
|
+
type: Input
|
|
2153
|
+
}], multiple: [{
|
|
2154
|
+
type: Input
|
|
2155
|
+
}], disabled: [{
|
|
2156
|
+
type: Input
|
|
2157
|
+
}], selectedFiles: [{
|
|
2158
|
+
type: Input
|
|
2159
|
+
}], filesSelected: [{
|
|
2160
|
+
type: Output
|
|
2161
|
+
}], removeFile: [{
|
|
2162
|
+
type: Output
|
|
2163
|
+
}], touched: [{
|
|
2164
|
+
type: Output
|
|
2165
|
+
}] } });
|
|
2166
|
+
|
|
1665
2167
|
class InputFileComponent {
|
|
1666
2168
|
label;
|
|
1667
2169
|
hint;
|
|
2170
|
+
error;
|
|
2171
|
+
required = false;
|
|
1668
2172
|
accept;
|
|
1669
2173
|
multiple = false;
|
|
1670
2174
|
disabled = false;
|
|
1671
|
-
value = null;
|
|
1672
|
-
valueChange = new EventEmitter();
|
|
1673
2175
|
filesChange = new EventEmitter();
|
|
2176
|
+
value = null;
|
|
1674
2177
|
onChange = () => undefined;
|
|
1675
2178
|
onTouched = () => undefined;
|
|
1676
2179
|
writeValue(value) { this.value = value; }
|
|
@@ -1688,39 +2191,85 @@ class InputFileComponent {
|
|
|
1688
2191
|
const value = this.multiple ? files : (files[0] ?? null);
|
|
1689
2192
|
this.value = value;
|
|
1690
2193
|
this.onChange(value);
|
|
1691
|
-
this.valueChange.emit(value);
|
|
1692
2194
|
this.filesChange.emit(files);
|
|
1693
|
-
input.value = '';
|
|
2195
|
+
input.value = '';
|
|
2196
|
+
}
|
|
2197
|
+
handleFilesSelected(files) {
|
|
2198
|
+
const value = this.multiple ? files : (files[0] ?? null);
|
|
2199
|
+
this.value = value;
|
|
2200
|
+
this.onChange(value);
|
|
2201
|
+
this.filesChange.emit(files);
|
|
1694
2202
|
}
|
|
1695
2203
|
remove(index) {
|
|
1696
2204
|
const files = this.selectedFiles.filter((_file, fileIndex) => fileIndex !== index);
|
|
1697
2205
|
const value = this.multiple ? files : (files[0] ?? null);
|
|
1698
2206
|
this.value = value;
|
|
1699
2207
|
this.onChange(value);
|
|
1700
|
-
this.valueChange.emit(value);
|
|
1701
2208
|
this.filesChange.emit(files);
|
|
1702
2209
|
}
|
|
1703
2210
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputFileComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1704
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
2211
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputFileComponent, isStandalone: true, selector: "input-file", inputs: { label: "label", hint: "hint", error: "error", required: "required", accept: "accept", multiple: "multiple", disabled: "disabled" }, outputs: { filesChange: "filesChange" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputFileComponent), multi: true }], ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\">\n <input-file-control [accept]=\"accept\" [multiple]=\"multiple\" [disabled]=\"disabled\" [selectedFiles]=\"selectedFiles\" (filesSelected)=\"handleFilesSelected($event)\" (removeFile)=\"remove($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputFileControlComponent, selector: "input-file-control", inputs: ["accept", "multiple", "disabled", "selectedFiles"], outputs: ["filesSelected", "removeFile", "touched"] }] });
|
|
1705
2212
|
}
|
|
1706
2213
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputFileComponent, decorators: [{
|
|
1707
2214
|
type: Component,
|
|
1708
|
-
args: [{ selector: 'input-file', standalone: true, imports: [CommonModule], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputFileComponent), multi: true }], template: "<label
|
|
2215
|
+
args: [{ selector: 'input-file', standalone: true, imports: [CommonModule, FieldFrameComponent, InputFileControlComponent], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputFileComponent), multi: true }], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\">\n <input-file-control [accept]=\"accept\" [multiple]=\"multiple\" [disabled]=\"disabled\" [selectedFiles]=\"selectedFiles\" (filesSelected)=\"handleFilesSelected($event)\" (removeFile)=\"remove($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n" }]
|
|
1709
2216
|
}], propDecorators: { label: [{
|
|
1710
2217
|
type: Input
|
|
1711
2218
|
}], hint: [{
|
|
1712
2219
|
type: Input
|
|
2220
|
+
}], error: [{
|
|
2221
|
+
type: Input
|
|
2222
|
+
}], required: [{
|
|
2223
|
+
type: Input
|
|
1713
2224
|
}], accept: [{
|
|
1714
2225
|
type: Input
|
|
1715
2226
|
}], multiple: [{
|
|
1716
2227
|
type: Input
|
|
1717
2228
|
}], disabled: [{
|
|
1718
2229
|
type: Input
|
|
1719
|
-
}],
|
|
2230
|
+
}], filesChange: [{
|
|
2231
|
+
type: Output
|
|
2232
|
+
}] } });
|
|
2233
|
+
|
|
2234
|
+
class InputPhotoControlComponent {
|
|
2235
|
+
accept = 'image/*';
|
|
2236
|
+
multiple = false;
|
|
2237
|
+
disabled = false;
|
|
2238
|
+
canSelectMore = true;
|
|
2239
|
+
previews = [];
|
|
2240
|
+
filesSelected = new EventEmitter();
|
|
2241
|
+
removed = new EventEmitter();
|
|
2242
|
+
dropped = new EventEmitter();
|
|
2243
|
+
touched = new EventEmitter();
|
|
2244
|
+
selectFiles(event) {
|
|
2245
|
+
const input = event.target;
|
|
2246
|
+
this.filesSelected.emit(Array.from(input.files ?? []));
|
|
2247
|
+
input.value = '';
|
|
2248
|
+
this.touched.emit();
|
|
2249
|
+
}
|
|
2250
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputPhotoControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2251
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: InputPhotoControlComponent, isStandalone: true, selector: "input-photo-control", inputs: { accept: "accept", multiple: "multiple", disabled: "disabled", canSelectMore: "canSelectMore", previews: "previews" }, outputs: { filesSelected: "filesSelected", removed: "removed", dropped: "dropped", touched: "touched" }, ngImport: i0, template: "<button data-field-control type=\"button\" class=\"flex min-h-24 w-full items-center justify-center rounded-xl border border-dashed border-slate-300 bg-slate-50 px-4 py-3 text-xs font-semibold uppercase tracking-[0.15em] text-slate-600 transition hover:bg-slate-100 disabled:opacity-60\" [disabled]=\"disabled || !canSelectMore\" (click)=\"photoInput.click()\">\n {{ previews.length ? '\u0414\u043E\u0434\u0430\u0442\u0438 \u0449\u0435 \u0444\u0430\u0439\u043B' : '\u041E\u0431\u0440\u0430\u0442\u0438 \u0444\u0430\u0439\u043B' }}\n</button>\n<input #photoInput type=\"file\" class=\"hidden\" [attr.accept]=\"accept\" [attr.multiple]=\"multiple && canSelectMore ? '' : null\" [disabled]=\"disabled\" (change)=\"selectFiles($event)\" />\n@if (previews.length) {\n <div class=\"mt-2 grid grid-cols-2 gap-2 md:grid-cols-4\" cdkDropList cdkDropListOrientation=\"mixed\" [cdkDropListData]=\"previews\" (cdkDropListDropped)=\"dropped.emit($event)\">\n @for (preview of previews; track preview.url; let i = $index) {\n <div class=\"relative overflow-hidden rounded-lg border border-slate-200 bg-slate-50\" cdkDrag [cdkDragDisabled]=\"disabled || preview.source === 'file'\">\n @if (preview.isImage) { <img [src]=\"preview.url\" [alt]=\"preview.name\" class=\"h-28 w-full object-cover\" /> }\n @else { <div class=\"flex h-28 items-center justify-center px-2 text-center text-[0.65rem] text-slate-600\">{{ preview.name }}</div> }\n <div class=\"absolute left-1 top-1 rounded bg-slate-900/85 px-2 py-1 text-[10px] font-semibold text-white\">#{{ i + 1 }}</div>\n <button type=\"button\" class=\"absolute right-1 top-1 rounded bg-white/95 px-2 py-1 text-[10px] text-rose-600\" [disabled]=\"disabled\" (click)=\"removed.emit(i)\">\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438</button>\n </div>\n }\n </div>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1$1.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1$1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }] });
|
|
2252
|
+
}
|
|
2253
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputPhotoControlComponent, decorators: [{
|
|
2254
|
+
type: Component,
|
|
2255
|
+
args: [{ selector: 'input-photo-control', standalone: true, imports: [CommonModule, DragDropModule], template: "<button data-field-control type=\"button\" class=\"flex min-h-24 w-full items-center justify-center rounded-xl border border-dashed border-slate-300 bg-slate-50 px-4 py-3 text-xs font-semibold uppercase tracking-[0.15em] text-slate-600 transition hover:bg-slate-100 disabled:opacity-60\" [disabled]=\"disabled || !canSelectMore\" (click)=\"photoInput.click()\">\n {{ previews.length ? '\u0414\u043E\u0434\u0430\u0442\u0438 \u0449\u0435 \u0444\u0430\u0439\u043B' : '\u041E\u0431\u0440\u0430\u0442\u0438 \u0444\u0430\u0439\u043B' }}\n</button>\n<input #photoInput type=\"file\" class=\"hidden\" [attr.accept]=\"accept\" [attr.multiple]=\"multiple && canSelectMore ? '' : null\" [disabled]=\"disabled\" (change)=\"selectFiles($event)\" />\n@if (previews.length) {\n <div class=\"mt-2 grid grid-cols-2 gap-2 md:grid-cols-4\" cdkDropList cdkDropListOrientation=\"mixed\" [cdkDropListData]=\"previews\" (cdkDropListDropped)=\"dropped.emit($event)\">\n @for (preview of previews; track preview.url; let i = $index) {\n <div class=\"relative overflow-hidden rounded-lg border border-slate-200 bg-slate-50\" cdkDrag [cdkDragDisabled]=\"disabled || preview.source === 'file'\">\n @if (preview.isImage) { <img [src]=\"preview.url\" [alt]=\"preview.name\" class=\"h-28 w-full object-cover\" /> }\n @else { <div class=\"flex h-28 items-center justify-center px-2 text-center text-[0.65rem] text-slate-600\">{{ preview.name }}</div> }\n <div class=\"absolute left-1 top-1 rounded bg-slate-900/85 px-2 py-1 text-[10px] font-semibold text-white\">#{{ i + 1 }}</div>\n <button type=\"button\" class=\"absolute right-1 top-1 rounded bg-white/95 px-2 py-1 text-[10px] text-rose-600\" [disabled]=\"disabled\" (click)=\"removed.emit(i)\">\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438</button>\n </div>\n }\n </div>\n}\n" }]
|
|
2256
|
+
}], propDecorators: { accept: [{
|
|
1720
2257
|
type: Input
|
|
1721
|
-
}],
|
|
2258
|
+
}], multiple: [{
|
|
2259
|
+
type: Input
|
|
2260
|
+
}], disabled: [{
|
|
2261
|
+
type: Input
|
|
2262
|
+
}], canSelectMore: [{
|
|
2263
|
+
type: Input
|
|
2264
|
+
}], previews: [{
|
|
2265
|
+
type: Input
|
|
2266
|
+
}], filesSelected: [{
|
|
1722
2267
|
type: Output
|
|
1723
|
-
}],
|
|
2268
|
+
}], removed: [{
|
|
2269
|
+
type: Output
|
|
2270
|
+
}], dropped: [{
|
|
2271
|
+
type: Output
|
|
2272
|
+
}], touched: [{
|
|
1724
2273
|
type: Output
|
|
1725
2274
|
}] } });
|
|
1726
2275
|
|
|
@@ -1728,14 +2277,15 @@ class InputPhotoComponent {
|
|
|
1728
2277
|
http = inject(HttpClient);
|
|
1729
2278
|
label;
|
|
1730
2279
|
hint;
|
|
2280
|
+
error;
|
|
2281
|
+
required = false;
|
|
1731
2282
|
accept = 'image/*';
|
|
1732
2283
|
multiple = false;
|
|
1733
2284
|
limit = Number.MAX_SAFE_INTEGER;
|
|
1734
2285
|
disabled = false;
|
|
1735
|
-
value = null;
|
|
1736
|
-
valueChange = new EventEmitter();
|
|
1737
2286
|
filesChange = new EventEmitter();
|
|
1738
2287
|
uploadingChange = new EventEmitter();
|
|
2288
|
+
value = null;
|
|
1739
2289
|
pendingFiles = [];
|
|
1740
2290
|
previews = [];
|
|
1741
2291
|
uploading = false;
|
|
@@ -1750,7 +2300,7 @@ class InputPhotoComponent {
|
|
|
1750
2300
|
registerOnTouched(fn) { this.onTouched = fn; }
|
|
1751
2301
|
setDisabledState(isDisabled) { this.disabled = isDisabled; }
|
|
1752
2302
|
ngOnChanges(changes) {
|
|
1753
|
-
if (changes['
|
|
2303
|
+
if (changes['multiple'])
|
|
1754
2304
|
this.rebuildPreviews();
|
|
1755
2305
|
}
|
|
1756
2306
|
ngOnDestroy() {
|
|
@@ -1771,6 +2321,15 @@ class InputPhotoComponent {
|
|
|
1771
2321
|
this.rebuildPreviews();
|
|
1772
2322
|
this.uploadFiles(accepted);
|
|
1773
2323
|
}
|
|
2324
|
+
handleFilesSelected(files) {
|
|
2325
|
+
if (!files.length || this.disabled)
|
|
2326
|
+
return;
|
|
2327
|
+
const accepted = this.multiple ? files.slice(0, Math.max(0, this.normalizedLimit - this.ids.length - this.pendingFiles.length)) : [files[0]];
|
|
2328
|
+
this.pendingFiles = this.multiple ? [...this.pendingFiles, ...accepted] : [accepted[0]];
|
|
2329
|
+
this.filesChange.emit(this.pendingFiles);
|
|
2330
|
+
this.rebuildPreviews();
|
|
2331
|
+
this.uploadFiles(accepted);
|
|
2332
|
+
}
|
|
1774
2333
|
remove(index) {
|
|
1775
2334
|
const ids = [...this.ids];
|
|
1776
2335
|
if (index < ids.length) {
|
|
@@ -1801,7 +2360,6 @@ class InputPhotoComponent {
|
|
|
1801
2360
|
emitValue(value) {
|
|
1802
2361
|
this.value = value;
|
|
1803
2362
|
this.onChange(value);
|
|
1804
|
-
this.valueChange.emit(value);
|
|
1805
2363
|
this.rebuildPreviews(value);
|
|
1806
2364
|
}
|
|
1807
2365
|
uploadFiles(files) {
|
|
@@ -1862,15 +2420,19 @@ class InputPhotoComponent {
|
|
|
1862
2420
|
return normalized.startsWith('image/') || normalized === 'application/pdf';
|
|
1863
2421
|
}
|
|
1864
2422
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputPhotoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1865
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
2423
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputPhotoComponent, isStandalone: true, selector: "input-photo", inputs: { label: "label", hint: "hint", error: "error", required: "required", accept: "accept", multiple: "multiple", limit: "limit", disabled: "disabled" }, outputs: { filesChange: "filesChange", uploadingChange: "uploadingChange" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputPhotoComponent), multi: true }], usesOnChanges: true, ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\">\n <input-photo-control [accept]=\"accept\" [multiple]=\"multiple\" [disabled]=\"disabled\" [canSelectMore]=\"canSelectMore\" [previews]=\"previews\" (filesSelected)=\"handleFilesSelected($event)\" (removed)=\"remove($event)\" (dropped)=\"drop($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputPhotoControlComponent, selector: "input-photo-control", inputs: ["accept", "multiple", "disabled", "canSelectMore", "previews"], outputs: ["filesSelected", "removed", "dropped", "touched"] }] });
|
|
1866
2424
|
}
|
|
1867
2425
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputPhotoComponent, decorators: [{
|
|
1868
2426
|
type: Component,
|
|
1869
|
-
args: [{ selector: 'input-photo', standalone: true, imports: [CommonModule, DragDropModule], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputPhotoComponent), multi: true }], template: "<
|
|
2427
|
+
args: [{ selector: 'input-photo', standalone: true, imports: [CommonModule, DragDropModule, FieldFrameComponent, InputPhotoControlComponent], providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputPhotoComponent), multi: true }], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\">\n <input-photo-control [accept]=\"accept\" [multiple]=\"multiple\" [disabled]=\"disabled\" [canSelectMore]=\"canSelectMore\" [previews]=\"previews\" (filesSelected)=\"handleFilesSelected($event)\" (removed)=\"remove($event)\" (dropped)=\"drop($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n" }]
|
|
1870
2428
|
}], propDecorators: { label: [{
|
|
1871
2429
|
type: Input
|
|
1872
2430
|
}], hint: [{
|
|
1873
2431
|
type: Input
|
|
2432
|
+
}], error: [{
|
|
2433
|
+
type: Input
|
|
2434
|
+
}], required: [{
|
|
2435
|
+
type: Input
|
|
1874
2436
|
}], accept: [{
|
|
1875
2437
|
type: Input
|
|
1876
2438
|
}], multiple: [{
|
|
@@ -1879,17 +2441,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
1879
2441
|
type: Input
|
|
1880
2442
|
}], disabled: [{
|
|
1881
2443
|
type: Input
|
|
1882
|
-
}], value: [{
|
|
1883
|
-
type: Input
|
|
1884
|
-
}], valueChange: [{
|
|
1885
|
-
type: Output
|
|
1886
2444
|
}], filesChange: [{
|
|
1887
2445
|
type: Output
|
|
1888
2446
|
}], uploadingChange: [{
|
|
1889
2447
|
type: Output
|
|
1890
2448
|
}] } });
|
|
1891
2449
|
|
|
1892
|
-
class
|
|
2450
|
+
class InputSelectControlComponent {
|
|
1893
2451
|
closeIcon = X;
|
|
1894
2452
|
chevronDownIcon = ChevronDown;
|
|
1895
2453
|
checkIcon = Check;
|
|
@@ -1902,16 +2460,14 @@ class InputSelectComponent {
|
|
|
1902
2460
|
placeholder;
|
|
1903
2461
|
name;
|
|
1904
2462
|
data;
|
|
2463
|
+
dataParams = {};
|
|
1905
2464
|
required = false;
|
|
1906
|
-
fullWidth = false;
|
|
1907
2465
|
disabled = false;
|
|
1908
2466
|
multiple = false;
|
|
1909
2467
|
includeBlankOption = false;
|
|
1910
2468
|
blankOptionLabel = 'Оберіть…';
|
|
1911
2469
|
emptyStateLabel = 'Немає варіантів для вибору';
|
|
1912
2470
|
searchable = true;
|
|
1913
|
-
remoteSearch = false;
|
|
1914
|
-
searchPlaceholder = 'Пошук...';
|
|
1915
2471
|
_options = [];
|
|
1916
2472
|
set options(value) {
|
|
1917
2473
|
this._options = value ?? [];
|
|
@@ -1975,7 +2531,7 @@ class InputSelectComponent {
|
|
|
1975
2531
|
});
|
|
1976
2532
|
}
|
|
1977
2533
|
ngOnChanges(changes) {
|
|
1978
|
-
if ('data' in changes) {
|
|
2534
|
+
if ('data' in changes || 'dataParams' in changes) {
|
|
1979
2535
|
this.reloadDictionaryOptions();
|
|
1980
2536
|
}
|
|
1981
2537
|
}
|
|
@@ -2086,7 +2642,7 @@ class InputSelectComponent {
|
|
|
2086
2642
|
}
|
|
2087
2643
|
get visibleOptions() {
|
|
2088
2644
|
const options = this.getRenderOptions();
|
|
2089
|
-
if (!this.searchable || this.
|
|
2645
|
+
if (!this.searchable || this.getDictionaryName() || !this.searchTerm.trim()) {
|
|
2090
2646
|
return options;
|
|
2091
2647
|
}
|
|
2092
2648
|
const search = this.searchTerm.trim().toLowerCase();
|
|
@@ -2233,32 +2789,37 @@ class InputSelectComponent {
|
|
|
2233
2789
|
const params = new URLSearchParams();
|
|
2234
2790
|
if (query?.trim())
|
|
2235
2791
|
params.set('q', query.trim());
|
|
2792
|
+
for (const [key, value] of Object.entries(this.dataParams || {})) {
|
|
2793
|
+
if (value !== null && value !== undefined && String(value).trim()) {
|
|
2794
|
+
params.set(key, String(value));
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2236
2797
|
const suffix = params.toString() ? `?${params.toString()}` : '';
|
|
2237
2798
|
return this.http.get(`/api/suggest/${encodeURIComponent(name)}${suffix}`);
|
|
2238
2799
|
}
|
|
2239
2800
|
loadSuggestItem(name, key) {
|
|
2240
2801
|
return this.http.get(`/api/suggest/${encodeURIComponent(name)}/${encodeURIComponent(key)}`);
|
|
2241
2802
|
}
|
|
2242
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type:
|
|
2243
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type:
|
|
2803
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputSelectControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2804
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: InputSelectControlComponent, isStandalone: true, selector: "input-select-control", inputs: { label: "label", placeholder: "placeholder", name: "name", data: "data", dataParams: "dataParams", required: "required", disabled: "disabled", multiple: ["multiple", "multiple", booleanAttribute], includeBlankOption: "includeBlankOption", blankOptionLabel: "blankOptionLabel", emptyStateLabel: "emptyStateLabel", searchable: "searchable", options: "options", error: "error", hint: "hint", triggerClass: "triggerClass", panelClass: "panelClass" }, outputs: { valueChange: "valueChange", searchChange: "searchChange" }, host: { listeners: { "document:click": "onDocumentClick()", "document:keydown.escape": "onEscape()" } }, providers: [
|
|
2244
2805
|
{
|
|
2245
2806
|
provide: NG_VALUE_ACCESSOR,
|
|
2246
|
-
useExisting: forwardRef(() =>
|
|
2807
|
+
useExisting: forwardRef(() => InputSelectControlComponent),
|
|
2247
2808
|
multi: true,
|
|
2248
2809
|
},
|
|
2249
|
-
{ provide: NG_VALIDATORS, useExisting: forwardRef(() =>
|
|
2250
|
-
], viewQueries: [{ propertyName: "dropdownTrigger", first: true, predicate: ["dropdownTrigger"], descendants: true, read: ElementRef, static: true }], usesOnChanges: true, ngImport: i0, template: "<div
|
|
2810
|
+
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputSelectControlComponent), multi: true },
|
|
2811
|
+
], viewQueries: [{ propertyName: "dropdownTrigger", first: true, predicate: ["dropdownTrigger"], descendants: true, read: ElementRef, static: true }], usesOnChanges: true, ngImport: i0, template: " <div class=\"relative w-full\">\n\n <button\n data-field-control\n cdkOverlayOrigin\n #dropdownTrigger=\"cdkOverlayOrigin\"\n type=\"button\"\n class=\"flex min-h-10 w-full flex-nowrap items-center gap-2 rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-900 transition hover:border-slate-300 focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\"\n [class]=\"triggerClass\"\n [class.opacity-50]=\"disabled\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown($event)\"\n >\n\n <span class=\"flex min-w-0 flex-1 flex-wrap items-center gap-2\" [class.-ml-2]=\"multiple\">\n <!-- MULTIPLE MODE -->\n @if (multiple) {\n\n @if (selectedOptions.length) {\n\n @for (option of selectedOptions; track option.value) {\n <span\n class=\"inline-flex h-6 shrink-0 items-center gap-1 rounded-md bg-slate-100 px-2 text-xs font-medium text-slate-700\"\n >\n {{ option.label }}\n\n <span\n role=\"button\"\n tabindex=\"0\"\n class=\"text-slate-400 hover:text-rose-500 transition-colors\"\n (click)=\"removeOption(option, $event)\"\n (keydown.enter)=\"removeOption(option, $event)\"\n (keydown.space)=\"$event.preventDefault(); removeOption(option, $event)\"\n >\n <lucide-icon [img]=\"closeIcon\" class=\"h-4 w-4 shrink-0\"></lucide-icon>\n </span>\n </span>\n }\n\n } @else {\n <span class=\"text-slate-400\">\n {{ placeholder ?? blankOptionLabel }}\n </span>\n }\n\n } @else {\n\n <!-- SINGLE MODE -->\n @if (selectedOptions[0]?.imageUrl) {\n <img [src]=\"selectedOptions[0]?.imageUrl\" alt=\"\" class=\"h-7 w-7 rounded object-cover\" />\n }\n <span class=\"min-w-0 truncate\">\n {{ selectedOptions[0]?.label ?? placeholder ?? blankOptionLabel }}\n </span>\n\n }\n </span>\n\n <lucide-icon [img]=\"chevronDownIcon\" class=\"shrink-0 text-xs text-slate-400\"></lucide-icon>\n\n </button>\n\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"dropdownTrigger\"\n [cdkConnectedOverlayOpen]=\"isOpen\"\n [cdkConnectedOverlayHasBackdrop]=\"false\"\n [cdkConnectedOverlayPositions]=\"dropdownPositions\"\n [cdkConnectedOverlayViewportMargin]=\"popupViewportMargin\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n [cdkConnectedOverlayPush]=\"true\"\n (detach)=\"closeDropdown()\"\n >\n <!-- DROPDOWN -->\n <div\n class=\"z-50 w-full max-w-[calc(100vw-2rem)] rounded-xl border border-slate-200 bg-white shadow-lg\"\n [style.width.px]=\"popupWidth\"\n [style.max-width]=\"'calc(100vw - 2rem)'\"\n [class]=\"panelClass\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (searchable) {\n <div class=\"border-b border-slate-100 p-2\">\n <input\n type=\"text\"\n class=\"w-full rounded-xl border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900 outline-none transition focus:border-slate-900 focus:ring-2 focus:ring-slate-200\"\n placeholder=\"\u041F\u043E\u0448\u0443\u043A...\"\n [ngModel]=\"searchTerm\"\n (ngModelChange)=\"onSearchChange($event)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n </div>\n }\n\n <div class=\"max-h-60 overflow-auto\">\n @if (!visibleOptions.length) {\n <div class=\"px-4 py-3 text-sm text-slate-500\">\n @if (isDictionaryLoading && data) {\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F...\n } @else {\n {{ emptyStateLabel }}\n }\n </div>\n } @else {\n @for (option of visibleOptions; track trackOption($index, option)) {\n <button\n type=\"button\"\n class=\"flex w-full items-start justify-between gap-3 whitespace-normal break-words px-4 py-2 text-left text-sm hover:bg-slate-50\"\n [class.bg-slate-100]=\"isSelected(option)\"\n (click)=\"selectOption(option, $event)\"\n >\n <span class=\"flex min-w-0 flex-1 items-center gap-2\">\n @if (option.imageUrl) {\n <img [src]=\"option.imageUrl\" alt=\"\" class=\"h-8 w-8 shrink-0 rounded object-cover\" />\n }\n <span class=\"whitespace-normal break-words\">{{ option.label }}</span>\n </span>\n\n @if (isSelected(option)) {\n <lucide-icon [img]=\"checkIcon\" class=\"text-xs text-sky-500\"></lucide-icon>\n }\n </button>\n }\n }\n </div>\n\n </div>\n </ng-template>\n\n </div>\n", dependencies: [{ kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i1.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "ngmodule", type: CommonModule }, { 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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2251
2812
|
}
|
|
2252
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type:
|
|
2813
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputSelectControlComponent, decorators: [{
|
|
2253
2814
|
type: Component,
|
|
2254
|
-
args: [{ selector: 'input-select', standalone: true, imports: [LucideAngularModule, CommonModule, FormsModule, CdkConnectedOverlay, CdkOverlayOrigin], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
2815
|
+
args: [{ selector: 'input-select-control', standalone: true, imports: [LucideAngularModule, CommonModule, FormsModule, CdkConnectedOverlay, CdkOverlayOrigin], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
2255
2816
|
{
|
|
2256
2817
|
provide: NG_VALUE_ACCESSOR,
|
|
2257
|
-
useExisting: forwardRef(() =>
|
|
2818
|
+
useExisting: forwardRef(() => InputSelectControlComponent),
|
|
2258
2819
|
multi: true,
|
|
2259
2820
|
},
|
|
2260
|
-
{ provide: NG_VALIDATORS, useExisting: forwardRef(() =>
|
|
2261
|
-
], template: "<div
|
|
2821
|
+
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputSelectControlComponent), multi: true },
|
|
2822
|
+
], template: " <div class=\"relative w-full\">\n\n <button\n data-field-control\n cdkOverlayOrigin\n #dropdownTrigger=\"cdkOverlayOrigin\"\n type=\"button\"\n class=\"flex min-h-10 w-full flex-nowrap items-center gap-2 rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-900 transition hover:border-slate-300 focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200\"\n [class]=\"triggerClass\"\n [class.opacity-50]=\"disabled\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown($event)\"\n >\n\n <span class=\"flex min-w-0 flex-1 flex-wrap items-center gap-2\" [class.-ml-2]=\"multiple\">\n <!-- MULTIPLE MODE -->\n @if (multiple) {\n\n @if (selectedOptions.length) {\n\n @for (option of selectedOptions; track option.value) {\n <span\n class=\"inline-flex h-6 shrink-0 items-center gap-1 rounded-md bg-slate-100 px-2 text-xs font-medium text-slate-700\"\n >\n {{ option.label }}\n\n <span\n role=\"button\"\n tabindex=\"0\"\n class=\"text-slate-400 hover:text-rose-500 transition-colors\"\n (click)=\"removeOption(option, $event)\"\n (keydown.enter)=\"removeOption(option, $event)\"\n (keydown.space)=\"$event.preventDefault(); removeOption(option, $event)\"\n >\n <lucide-icon [img]=\"closeIcon\" class=\"h-4 w-4 shrink-0\"></lucide-icon>\n </span>\n </span>\n }\n\n } @else {\n <span class=\"text-slate-400\">\n {{ placeholder ?? blankOptionLabel }}\n </span>\n }\n\n } @else {\n\n <!-- SINGLE MODE -->\n @if (selectedOptions[0]?.imageUrl) {\n <img [src]=\"selectedOptions[0]?.imageUrl\" alt=\"\" class=\"h-7 w-7 rounded object-cover\" />\n }\n <span class=\"min-w-0 truncate\">\n {{ selectedOptions[0]?.label ?? placeholder ?? blankOptionLabel }}\n </span>\n\n }\n </span>\n\n <lucide-icon [img]=\"chevronDownIcon\" class=\"shrink-0 text-xs text-slate-400\"></lucide-icon>\n\n </button>\n\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"dropdownTrigger\"\n [cdkConnectedOverlayOpen]=\"isOpen\"\n [cdkConnectedOverlayHasBackdrop]=\"false\"\n [cdkConnectedOverlayPositions]=\"dropdownPositions\"\n [cdkConnectedOverlayViewportMargin]=\"popupViewportMargin\"\n [cdkConnectedOverlayFlexibleDimensions]=\"true\"\n [cdkConnectedOverlayPush]=\"true\"\n (detach)=\"closeDropdown()\"\n >\n <!-- DROPDOWN -->\n <div\n class=\"z-50 w-full max-w-[calc(100vw-2rem)] rounded-xl border border-slate-200 bg-white shadow-lg\"\n [style.width.px]=\"popupWidth\"\n [style.max-width]=\"'calc(100vw - 2rem)'\"\n [class]=\"panelClass\"\n (click)=\"$event.stopPropagation()\"\n >\n @if (searchable) {\n <div class=\"border-b border-slate-100 p-2\">\n <input\n type=\"text\"\n class=\"w-full rounded-xl border border-slate-200 bg-white px-3 py-2 text-sm text-slate-900 outline-none transition focus:border-slate-900 focus:ring-2 focus:ring-slate-200\"\n placeholder=\"\u041F\u043E\u0448\u0443\u043A...\"\n [ngModel]=\"searchTerm\"\n (ngModelChange)=\"onSearchChange($event)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n />\n </div>\n }\n\n <div class=\"max-h-60 overflow-auto\">\n @if (!visibleOptions.length) {\n <div class=\"px-4 py-3 text-sm text-slate-500\">\n @if (isDictionaryLoading && data) {\n \u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F...\n } @else {\n {{ emptyStateLabel }}\n }\n </div>\n } @else {\n @for (option of visibleOptions; track trackOption($index, option)) {\n <button\n type=\"button\"\n class=\"flex w-full items-start justify-between gap-3 whitespace-normal break-words px-4 py-2 text-left text-sm hover:bg-slate-50\"\n [class.bg-slate-100]=\"isSelected(option)\"\n (click)=\"selectOption(option, $event)\"\n >\n <span class=\"flex min-w-0 flex-1 items-center gap-2\">\n @if (option.imageUrl) {\n <img [src]=\"option.imageUrl\" alt=\"\" class=\"h-8 w-8 shrink-0 rounded object-cover\" />\n }\n <span class=\"whitespace-normal break-words\">{{ option.label }}</span>\n </span>\n\n @if (isSelected(option)) {\n <lucide-icon [img]=\"checkIcon\" class=\"text-xs text-sky-500\"></lucide-icon>\n }\n </button>\n }\n }\n </div>\n\n </div>\n </ng-template>\n\n </div>\n" }]
|
|
2262
2823
|
}], ctorParameters: () => [], propDecorators: { label: [{
|
|
2263
2824
|
type: Input
|
|
2264
2825
|
}], placeholder: [{
|
|
@@ -2267,9 +2828,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
2267
2828
|
type: Input
|
|
2268
2829
|
}], data: [{
|
|
2269
2830
|
type: Input
|
|
2270
|
-
}],
|
|
2831
|
+
}], dataParams: [{
|
|
2271
2832
|
type: Input
|
|
2272
|
-
}],
|
|
2833
|
+
}], required: [{
|
|
2273
2834
|
type: Input
|
|
2274
2835
|
}], disabled: [{
|
|
2275
2836
|
type: Input
|
|
@@ -2284,10 +2845,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
2284
2845
|
type: Input
|
|
2285
2846
|
}], searchable: [{
|
|
2286
2847
|
type: Input
|
|
2287
|
-
}], remoteSearch: [{
|
|
2288
|
-
type: Input
|
|
2289
|
-
}], searchPlaceholder: [{
|
|
2290
|
-
type: Input
|
|
2291
2848
|
}], options: [{
|
|
2292
2849
|
type: Input
|
|
2293
2850
|
}], error: [{
|
|
@@ -2313,6 +2870,139 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
2313
2870
|
args: ['document:keydown.escape']
|
|
2314
2871
|
}] } });
|
|
2315
2872
|
|
|
2873
|
+
class InputSelectComponent {
|
|
2874
|
+
control;
|
|
2875
|
+
label;
|
|
2876
|
+
hint;
|
|
2877
|
+
error;
|
|
2878
|
+
placeholder;
|
|
2879
|
+
name;
|
|
2880
|
+
data;
|
|
2881
|
+
dataParams = {};
|
|
2882
|
+
required = false;
|
|
2883
|
+
disabled = false;
|
|
2884
|
+
multiple = false;
|
|
2885
|
+
includeBlankOption = false;
|
|
2886
|
+
blankOptionLabel = 'Оберіть…';
|
|
2887
|
+
emptyStateLabel = 'Немає варіантів для вибору';
|
|
2888
|
+
searchable = true;
|
|
2889
|
+
options = [];
|
|
2890
|
+
triggerClass = '';
|
|
2891
|
+
panelClass = '';
|
|
2892
|
+
valueChange = new EventEmitter();
|
|
2893
|
+
searchChange = new EventEmitter();
|
|
2894
|
+
pendingValue = null;
|
|
2895
|
+
onChange = () => undefined;
|
|
2896
|
+
onTouched = () => undefined;
|
|
2897
|
+
ngAfterViewInit() {
|
|
2898
|
+
this.control?.registerOnChange((value) => {
|
|
2899
|
+
this.onChange(value);
|
|
2900
|
+
this.valueChange.emit(value);
|
|
2901
|
+
});
|
|
2902
|
+
this.control?.registerOnTouched(() => this.onTouched());
|
|
2903
|
+
this.control?.writeValue(this.pendingValue);
|
|
2904
|
+
}
|
|
2905
|
+
writeValue(value) {
|
|
2906
|
+
this.pendingValue = value;
|
|
2907
|
+
this.control?.writeValue(value);
|
|
2908
|
+
}
|
|
2909
|
+
registerOnChange(fn) { this.onChange = fn; }
|
|
2910
|
+
registerOnTouched(fn) { this.onTouched = fn; }
|
|
2911
|
+
setDisabledState(isDisabled) { this.disabled = isDisabled; }
|
|
2912
|
+
validate(control) { return validateFormControl(control, this.required); }
|
|
2913
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2914
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "21.2.19", type: InputSelectComponent, isStandalone: true, selector: "input-select", inputs: { label: "label", hint: "hint", error: "error", placeholder: "placeholder", name: "name", data: "data", dataParams: "dataParams", required: "required", disabled: "disabled", multiple: ["multiple", "multiple", booleanAttribute], includeBlankOption: "includeBlankOption", blankOptionLabel: "blankOptionLabel", emptyStateLabel: "emptyStateLabel", searchable: "searchable", options: "options", triggerClass: "triggerClass", panelClass: "panelClass" }, outputs: { valueChange: "valueChange", searchChange: "searchChange" }, providers: [
|
|
2915
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputSelectComponent), multi: true },
|
|
2916
|
+
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputSelectComponent), multi: true },
|
|
2917
|
+
], viewQueries: [{ propertyName: "control", first: true, predicate: InputSelectControlComponent, descendants: true }], ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [disabled]=\"disabled\">\n <input-select-control\n [placeholder]=\"placeholder\"\n [name]=\"name\"\n [data]=\"data\"\n [dataParams]=\"dataParams\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [multiple]=\"multiple\"\n [includeBlankOption]=\"includeBlankOption\"\n [blankOptionLabel]=\"blankOptionLabel\"\n [emptyStateLabel]=\"emptyStateLabel\"\n [searchable]=\"searchable\"\n [options]=\"options\"\n [triggerClass]=\"triggerClass\"\n [panelClass]=\"panelClass\"\n (valueChange)=\"valueChange.emit($event)\"\n (searchChange)=\"searchChange.emit($event)\"\n />\n</field-frame>\n", dependencies: [{ kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputSelectControlComponent, selector: "input-select-control", inputs: ["label", "placeholder", "name", "data", "dataParams", "required", "disabled", "multiple", "includeBlankOption", "blankOptionLabel", "emptyStateLabel", "searchable", "options", "error", "hint", "triggerClass", "panelClass"], outputs: ["valueChange", "searchChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2918
|
+
}
|
|
2919
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputSelectComponent, decorators: [{
|
|
2920
|
+
type: Component,
|
|
2921
|
+
args: [{ selector: 'input-select', standalone: true, imports: [FieldFrameComponent, InputSelectControlComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
2922
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => InputSelectComponent), multi: true },
|
|
2923
|
+
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputSelectComponent), multi: true },
|
|
2924
|
+
], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [disabled]=\"disabled\">\n <input-select-control\n [placeholder]=\"placeholder\"\n [name]=\"name\"\n [data]=\"data\"\n [dataParams]=\"dataParams\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [multiple]=\"multiple\"\n [includeBlankOption]=\"includeBlankOption\"\n [blankOptionLabel]=\"blankOptionLabel\"\n [emptyStateLabel]=\"emptyStateLabel\"\n [searchable]=\"searchable\"\n [options]=\"options\"\n [triggerClass]=\"triggerClass\"\n [panelClass]=\"panelClass\"\n (valueChange)=\"valueChange.emit($event)\"\n (searchChange)=\"searchChange.emit($event)\"\n />\n</field-frame>\n" }]
|
|
2925
|
+
}], propDecorators: { control: [{
|
|
2926
|
+
type: ViewChild,
|
|
2927
|
+
args: [InputSelectControlComponent]
|
|
2928
|
+
}], label: [{
|
|
2929
|
+
type: Input
|
|
2930
|
+
}], hint: [{
|
|
2931
|
+
type: Input
|
|
2932
|
+
}], error: [{
|
|
2933
|
+
type: Input
|
|
2934
|
+
}], placeholder: [{
|
|
2935
|
+
type: Input
|
|
2936
|
+
}], name: [{
|
|
2937
|
+
type: Input
|
|
2938
|
+
}], data: [{
|
|
2939
|
+
type: Input
|
|
2940
|
+
}], dataParams: [{
|
|
2941
|
+
type: Input
|
|
2942
|
+
}], required: [{
|
|
2943
|
+
type: Input
|
|
2944
|
+
}], disabled: [{
|
|
2945
|
+
type: Input
|
|
2946
|
+
}], multiple: [{
|
|
2947
|
+
type: Input,
|
|
2948
|
+
args: [{ transform: booleanAttribute }]
|
|
2949
|
+
}], includeBlankOption: [{
|
|
2950
|
+
type: Input
|
|
2951
|
+
}], blankOptionLabel: [{
|
|
2952
|
+
type: Input
|
|
2953
|
+
}], emptyStateLabel: [{
|
|
2954
|
+
type: Input
|
|
2955
|
+
}], searchable: [{
|
|
2956
|
+
type: Input
|
|
2957
|
+
}], options: [{
|
|
2958
|
+
type: Input
|
|
2959
|
+
}], triggerClass: [{
|
|
2960
|
+
type: Input
|
|
2961
|
+
}], panelClass: [{
|
|
2962
|
+
type: Input
|
|
2963
|
+
}], valueChange: [{
|
|
2964
|
+
type: Output
|
|
2965
|
+
}], searchChange: [{
|
|
2966
|
+
type: Output
|
|
2967
|
+
}] } });
|
|
2968
|
+
|
|
2969
|
+
class InputSlugControlComponent {
|
|
2970
|
+
placeholder;
|
|
2971
|
+
name;
|
|
2972
|
+
id;
|
|
2973
|
+
autocomplete = 'off';
|
|
2974
|
+
disabled = false;
|
|
2975
|
+
value = '';
|
|
2976
|
+
valueChange = new EventEmitter();
|
|
2977
|
+
touched = new EventEmitter();
|
|
2978
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputSlugControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2979
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputSlugControlComponent, isStandalone: true, selector: "input-slug-control", inputs: { placeholder: "placeholder", name: "name", id: "id", autocomplete: "autocomplete", disabled: "disabled", value: "value" }, outputs: { valueChange: "valueChange", touched: "touched" }, ngImport: i0, template: `<input data-field-control type="text" class="w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200" [attr.placeholder]="placeholder" [attr.name]="name" [attr.autocomplete]="autocomplete" [disabled]="disabled" [attr.id]="id" [value]="value" (input)="valueChange.emit($any($event.target).value)" (blur)="touched.emit()" />`, isInline: true });
|
|
2980
|
+
}
|
|
2981
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputSlugControlComponent, decorators: [{
|
|
2982
|
+
type: Component,
|
|
2983
|
+
args: [{
|
|
2984
|
+
selector: 'input-slug-control',
|
|
2985
|
+
standalone: true,
|
|
2986
|
+
template: `<input data-field-control type="text" class="w-full rounded-xl border border-slate-200 bg-white px-4 py-2 text-sm text-slate-900 placeholder:text-slate-400 transition focus:border-slate-900 focus:outline-none focus:ring-2 focus:ring-slate-200" [attr.placeholder]="placeholder" [attr.name]="name" [attr.autocomplete]="autocomplete" [disabled]="disabled" [attr.id]="id" [value]="value" (input)="valueChange.emit($any($event.target).value)" (blur)="touched.emit()" />`,
|
|
2987
|
+
}]
|
|
2988
|
+
}], propDecorators: { placeholder: [{
|
|
2989
|
+
type: Input
|
|
2990
|
+
}], name: [{
|
|
2991
|
+
type: Input
|
|
2992
|
+
}], id: [{
|
|
2993
|
+
type: Input
|
|
2994
|
+
}], autocomplete: [{
|
|
2995
|
+
type: Input
|
|
2996
|
+
}], disabled: [{
|
|
2997
|
+
type: Input
|
|
2998
|
+
}], value: [{
|
|
2999
|
+
type: Input
|
|
3000
|
+
}], valueChange: [{
|
|
3001
|
+
type: Output
|
|
3002
|
+
}], touched: [{
|
|
3003
|
+
type: Output
|
|
3004
|
+
}] } });
|
|
3005
|
+
|
|
2316
3006
|
class InputSlugComponent {
|
|
2317
3007
|
label;
|
|
2318
3008
|
hint;
|
|
@@ -2320,7 +3010,6 @@ class InputSlugComponent {
|
|
|
2320
3010
|
name;
|
|
2321
3011
|
id;
|
|
2322
3012
|
required = false;
|
|
2323
|
-
fullWidth = false;
|
|
2324
3013
|
autocomplete = 'off';
|
|
2325
3014
|
error;
|
|
2326
3015
|
invalidInput = new EventEmitter();
|
|
@@ -2355,6 +3044,13 @@ class InputSlugComponent {
|
|
|
2355
3044
|
this.value = normalized;
|
|
2356
3045
|
this.onChange(normalized);
|
|
2357
3046
|
}
|
|
3047
|
+
handleValueChange(value) {
|
|
3048
|
+
const normalized = this.normalizeSlug(value);
|
|
3049
|
+
if (value !== normalized)
|
|
3050
|
+
this.invalidInput.emit();
|
|
3051
|
+
this.value = normalized;
|
|
3052
|
+
this.onChange(normalized);
|
|
3053
|
+
}
|
|
2358
3054
|
normalizeSlug(value) {
|
|
2359
3055
|
return (value ?? '')
|
|
2360
3056
|
.toLowerCase()
|
|
@@ -2362,25 +3058,25 @@ class InputSlugComponent {
|
|
|
2362
3058
|
.replace(/[^a-z0-9_]/g, '');
|
|
2363
3059
|
}
|
|
2364
3060
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputSlugComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2365
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
3061
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputSlugComponent, isStandalone: true, selector: "input-slug", inputs: { label: "label", hint: "hint", placeholder: "placeholder", name: "name", id: "id", required: "required", autocomplete: "autocomplete", error: "error" }, outputs: { invalidInput: "invalidInput" }, providers: [
|
|
2366
3062
|
{
|
|
2367
3063
|
provide: NG_VALUE_ACCESSOR,
|
|
2368
3064
|
useExisting: forwardRef(() => InputSlugComponent),
|
|
2369
3065
|
multi: true,
|
|
2370
3066
|
},
|
|
2371
3067
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputSlugComponent), multi: true },
|
|
2372
|
-
], ngImport: i0, template: "<
|
|
3068
|
+
], ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\">\n <input-slug-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"controlId\" [autocomplete]=\"autocomplete\" [disabled]=\"disabled\" [value]=\"value\" (valueChange)=\"handleValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputSlugControlComponent, selector: "input-slug-control", inputs: ["placeholder", "name", "id", "autocomplete", "disabled", "value"], outputs: ["valueChange", "touched"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2373
3069
|
}
|
|
2374
3070
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputSlugComponent, decorators: [{
|
|
2375
3071
|
type: Component,
|
|
2376
|
-
args: [{ selector: 'input-slug', standalone: true, imports: [CommonModule, FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
3072
|
+
args: [{ selector: 'input-slug', standalone: true, imports: [CommonModule, FormsModule, FieldFrameComponent, InputSlugControlComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
2377
3073
|
{
|
|
2378
3074
|
provide: NG_VALUE_ACCESSOR,
|
|
2379
3075
|
useExisting: forwardRef(() => InputSlugComponent),
|
|
2380
3076
|
multi: true,
|
|
2381
3077
|
},
|
|
2382
3078
|
{ provide: NG_VALIDATORS, useExisting: forwardRef(() => InputSlugComponent), multi: true },
|
|
2383
|
-
], template: "<
|
|
3079
|
+
], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\">\n <input-slug-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"controlId\" [autocomplete]=\"autocomplete\" [disabled]=\"disabled\" [value]=\"value\" (valueChange)=\"handleValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n" }]
|
|
2384
3080
|
}], propDecorators: { label: [{
|
|
2385
3081
|
type: Input
|
|
2386
3082
|
}], hint: [{
|
|
@@ -2393,8 +3089,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
2393
3089
|
type: Input
|
|
2394
3090
|
}], required: [{
|
|
2395
3091
|
type: Input
|
|
2396
|
-
}], fullWidth: [{
|
|
2397
|
-
type: Input
|
|
2398
3092
|
}], autocomplete: [{
|
|
2399
3093
|
type: Input
|
|
2400
3094
|
}], error: [{
|
|
@@ -2423,9 +3117,10 @@ const UI_FORM_INPUT_REGISTRY = {
|
|
|
2423
3117
|
class FieldInputComponent {
|
|
2424
3118
|
field;
|
|
2425
3119
|
value;
|
|
3120
|
+
model = {};
|
|
2426
3121
|
error = '';
|
|
2427
3122
|
disabled = false;
|
|
2428
|
-
|
|
3123
|
+
visibleActions = [];
|
|
2429
3124
|
valueChange = new EventEmitter();
|
|
2430
3125
|
actionTriggered = new EventEmitter();
|
|
2431
3126
|
lookupRequested = new EventEmitter();
|
|
@@ -2476,11 +3171,17 @@ class FieldInputComponent {
|
|
|
2476
3171
|
if (!this.componentRef || !this.field)
|
|
2477
3172
|
return;
|
|
2478
3173
|
const field = this.field;
|
|
3174
|
+
const config = field;
|
|
2479
3175
|
const setInput = (name, value) => this.componentRef?.setInput(name, value);
|
|
2480
3176
|
const inputType = String(field.type || 'text');
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
3177
|
+
if (field.label !== undefined)
|
|
3178
|
+
setInput('label', field.label);
|
|
3179
|
+
if (field.hint !== undefined)
|
|
3180
|
+
setInput('hint', field.hint);
|
|
3181
|
+
setInput('error', this.error);
|
|
3182
|
+
if (typeof field.required === 'boolean')
|
|
3183
|
+
setInput('required', field.required);
|
|
3184
|
+
// FieldInput only adapts the dynamic field to the selected control.
|
|
2484
3185
|
switch (inputType) {
|
|
2485
3186
|
case 'text':
|
|
2486
3187
|
case 'number':
|
|
@@ -2489,57 +3190,48 @@ class FieldInputComponent {
|
|
|
2489
3190
|
case 'email':
|
|
2490
3191
|
case 'password':
|
|
2491
3192
|
case 'textarea':
|
|
3193
|
+
setInput('actions', this.visibleActions);
|
|
2492
3194
|
setInput('name', field.id);
|
|
2493
3195
|
setInput('id', field.id);
|
|
2494
3196
|
setInput('placeholder', field.placeholder);
|
|
2495
|
-
setInput('pattern',
|
|
2496
|
-
setInput('rows',
|
|
2497
|
-
setInput('fullWidth', fullWidth);
|
|
3197
|
+
setInput('pattern', config['pattern']);
|
|
3198
|
+
setInput('rows', config['rows'] ?? 4);
|
|
2498
3199
|
break;
|
|
2499
3200
|
case 'slug':
|
|
2500
3201
|
setInput('name', field.id);
|
|
2501
3202
|
setInput('id', field.id);
|
|
2502
3203
|
setInput('placeholder', field.placeholder);
|
|
2503
|
-
setInput('fullWidth', fullWidth);
|
|
2504
3204
|
break;
|
|
2505
3205
|
case 'select':
|
|
2506
3206
|
setInput('name', field.id);
|
|
2507
3207
|
setInput('placeholder', field.placeholder);
|
|
2508
|
-
setInput('data',
|
|
2509
|
-
|
|
2510
|
-
setInput('
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
setInput('
|
|
2514
|
-
setInput('
|
|
3208
|
+
setInput('data', config['data']);
|
|
3209
|
+
const dataParams = config['dataParams'];
|
|
3210
|
+
setInput('dataParams', Object.fromEntries(Object.entries(dataParams || {})
|
|
3211
|
+
.map(([key, fieldId]) => [key, this.model[fieldId]])
|
|
3212
|
+
.filter(([, value]) => value !== undefined && value !== null)));
|
|
3213
|
+
setInput('options', config['options'] || []);
|
|
3214
|
+
setInput('multiple', !!config['multiple']);
|
|
3215
|
+
if (typeof config['searchable'] === 'boolean') {
|
|
3216
|
+
setInput('searchable', config['searchable']);
|
|
3217
|
+
}
|
|
2515
3218
|
break;
|
|
2516
3219
|
case 'color':
|
|
2517
3220
|
setInput('name', field.id);
|
|
2518
3221
|
setInput('id', field.id);
|
|
2519
|
-
setInput('required', false);
|
|
2520
|
-
setInput('fullWidth', fullWidth);
|
|
2521
3222
|
break;
|
|
2522
3223
|
case 'file':
|
|
2523
|
-
setInput('accept',
|
|
2524
|
-
setInput('multiple', !!
|
|
3224
|
+
setInput('accept', config['accept']);
|
|
3225
|
+
setInput('multiple', !!config['multiple']);
|
|
2525
3226
|
break;
|
|
2526
3227
|
case 'photo':
|
|
2527
|
-
setInput('accept',
|
|
2528
|
-
setInput('multiple', !!
|
|
2529
|
-
setInput('limit',
|
|
3228
|
+
setInput('accept', config['accept'] || 'image/*');
|
|
3229
|
+
setInput('multiple', !!config['multiple']);
|
|
3230
|
+
setInput('limit', config['limit'] ?? 0);
|
|
2530
3231
|
break;
|
|
2531
3232
|
case 'barcode':
|
|
2532
|
-
setInput('label', '');
|
|
2533
|
-
setInput('hint', '');
|
|
2534
3233
|
setInput('placeholder', field.placeholder);
|
|
2535
3234
|
setInput('disabled', this.disabled);
|
|
2536
|
-
setInput('autoOpen', field.autoOpen !== false);
|
|
2537
|
-
setInput('searchButtonLabel', field.searchButtonLabel || 'Знайти');
|
|
2538
|
-
setInput('openCameraLabel', field.openCameraLabel || 'Відкрити камеру');
|
|
2539
|
-
setInput('closeCameraLabel', field.closeCameraLabel || 'Закрити камеру');
|
|
2540
|
-
setInput('cameraTitle', field.cameraTitle || 'Камера');
|
|
2541
|
-
setInput('cameraStartingLabel', field.cameraStartingLabel || 'Запускаємо камеру…');
|
|
2542
|
-
setInput('cameraHint', field.cameraHint || 'Наведіть камеру на штрихкод. Після зчитування код підставиться автоматично.');
|
|
2543
3235
|
setInput('value', this.value ?? '');
|
|
2544
3236
|
break;
|
|
2545
3237
|
case 'checkbox':
|
|
@@ -2550,95 +3242,31 @@ class FieldInputComponent {
|
|
|
2550
3242
|
instance.setDisabledState?.(this.disabled);
|
|
2551
3243
|
}
|
|
2552
3244
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FieldInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2553
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
2554
|
-
<
|
|
2555
|
-
|
|
2556
|
-
<label class="text-[0.7rem] font-semibold uppercase tracking-[0.2em] text-slate-600" [attr.for]="field.id">
|
|
2557
|
-
{{ field.label }}
|
|
2558
|
-
@if (field.required) { <span aria-hidden="true" class="text-rose-500"> *</span> }
|
|
2559
|
-
</label>
|
|
2560
|
-
}
|
|
2561
|
-
|
|
2562
|
-
<div class="flex items-start gap-2" [class.rounded-xl]="!!error" [class.ring-2]="!!error" [class.ring-rose-200]="!!error">
|
|
2563
|
-
<div class="min-w-0 w-full flex-1">
|
|
2564
|
-
<ng-container #inputContainer></ng-container>
|
|
2565
|
-
</div>
|
|
2566
|
-
|
|
2567
|
-
@if (actions.length) {
|
|
2568
|
-
<div class="flex flex-none items-center gap-2 pt-0.5">
|
|
2569
|
-
@for (action of actions; track action.id) {
|
|
2570
|
-
<ui-button
|
|
2571
|
-
type="button"
|
|
2572
|
-
[variant]="action.variant ?? 'secondary'"
|
|
2573
|
-
[icon]="action.icon || ''"
|
|
2574
|
-
[size]="action.size || 'sm'"
|
|
2575
|
-
[disabled]="disabled"
|
|
2576
|
-
(click)="actionTriggered.emit(action)"
|
|
2577
|
-
>
|
|
2578
|
-
{{ action.label }}
|
|
2579
|
-
</ui-button>
|
|
2580
|
-
}
|
|
2581
|
-
</div>
|
|
2582
|
-
}
|
|
2583
|
-
</div>
|
|
2584
|
-
|
|
2585
|
-
@if (field.hint) { <p class="text-[0.5rem] text-slate-500">{{ field.hint }}</p> }
|
|
2586
|
-
@if (error) { <p class="text-[0.65rem] text-rose-500">{{ error }}</p> }
|
|
2587
|
-
</div>
|
|
2588
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }] });
|
|
3245
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: FieldInputComponent, isStandalone: true, selector: "field-input", inputs: { field: "field", value: "value", model: "model", error: "error", disabled: "disabled", visibleActions: "visibleActions" }, outputs: { valueChange: "valueChange", actionTriggered: "actionTriggered", lookupRequested: "lookupRequested", barcodeScanned: "barcodeScanned", filesChange: "filesChange", uploadingChange: "uploadingChange" }, viewQueries: [{ propertyName: "inputContainer", first: true, predicate: ["inputContainer"], descendants: true, read: ViewContainerRef }], usesOnChanges: true, ngImport: i0, template: `
|
|
3246
|
+
<ng-container #inputContainer></ng-container>
|
|
3247
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
2589
3248
|
}
|
|
2590
3249
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: FieldInputComponent, decorators: [{
|
|
2591
3250
|
type: Component,
|
|
2592
3251
|
args: [{
|
|
2593
3252
|
selector: 'field-input',
|
|
2594
3253
|
standalone: true,
|
|
2595
|
-
imports: [CommonModule
|
|
3254
|
+
imports: [CommonModule],
|
|
2596
3255
|
template: `
|
|
2597
|
-
<
|
|
2598
|
-
@if (field.label) {
|
|
2599
|
-
<label class="text-[0.7rem] font-semibold uppercase tracking-[0.2em] text-slate-600" [attr.for]="field.id">
|
|
2600
|
-
{{ field.label }}
|
|
2601
|
-
@if (field.required) { <span aria-hidden="true" class="text-rose-500"> *</span> }
|
|
2602
|
-
</label>
|
|
2603
|
-
}
|
|
2604
|
-
|
|
2605
|
-
<div class="flex items-start gap-2" [class.rounded-xl]="!!error" [class.ring-2]="!!error" [class.ring-rose-200]="!!error">
|
|
2606
|
-
<div class="min-w-0 w-full flex-1">
|
|
2607
|
-
<ng-container #inputContainer></ng-container>
|
|
2608
|
-
</div>
|
|
2609
|
-
|
|
2610
|
-
@if (actions.length) {
|
|
2611
|
-
<div class="flex flex-none items-center gap-2 pt-0.5">
|
|
2612
|
-
@for (action of actions; track action.id) {
|
|
2613
|
-
<ui-button
|
|
2614
|
-
type="button"
|
|
2615
|
-
[variant]="action.variant ?? 'secondary'"
|
|
2616
|
-
[icon]="action.icon || ''"
|
|
2617
|
-
[size]="action.size || 'sm'"
|
|
2618
|
-
[disabled]="disabled"
|
|
2619
|
-
(click)="actionTriggered.emit(action)"
|
|
2620
|
-
>
|
|
2621
|
-
{{ action.label }}
|
|
2622
|
-
</ui-button>
|
|
2623
|
-
}
|
|
2624
|
-
</div>
|
|
2625
|
-
}
|
|
2626
|
-
</div>
|
|
2627
|
-
|
|
2628
|
-
@if (field.hint) { <p class="text-[0.5rem] text-slate-500">{{ field.hint }}</p> }
|
|
2629
|
-
@if (error) { <p class="text-[0.65rem] text-rose-500">{{ error }}</p> }
|
|
2630
|
-
</div>
|
|
3256
|
+
<ng-container #inputContainer></ng-container>
|
|
2631
3257
|
`,
|
|
2632
3258
|
}]
|
|
2633
3259
|
}], propDecorators: { field: [{
|
|
2634
3260
|
type: Input
|
|
2635
3261
|
}], value: [{
|
|
2636
3262
|
type: Input
|
|
3263
|
+
}], model: [{
|
|
3264
|
+
type: Input
|
|
2637
3265
|
}], error: [{
|
|
2638
3266
|
type: Input
|
|
2639
3267
|
}], disabled: [{
|
|
2640
3268
|
type: Input
|
|
2641
|
-
}],
|
|
3269
|
+
}], visibleActions: [{
|
|
2642
3270
|
type: Input
|
|
2643
3271
|
}], valueChange: [{
|
|
2644
3272
|
type: Output
|
|
@@ -2898,6 +3526,8 @@ class DynamicFormComponent {
|
|
|
2898
3526
|
this.runFieldLookup(field);
|
|
2899
3527
|
}
|
|
2900
3528
|
runFieldLookup(field, overrideValue) {
|
|
3529
|
+
if (!isDynamicFormLookupField(field))
|
|
3530
|
+
return;
|
|
2901
3531
|
const api = String(field.lookupApi || '').trim();
|
|
2902
3532
|
if (!api)
|
|
2903
3533
|
return;
|
|
@@ -3047,7 +3677,7 @@ class DynamicFormComponent {
|
|
|
3047
3677
|
].filter(Boolean).join(' ');
|
|
3048
3678
|
}
|
|
3049
3679
|
getContainerContentClass(field) {
|
|
3050
|
-
const className = String(field.contentClassName || '').trim();
|
|
3680
|
+
const className = String(this.isContainerField(field) ? field.contentClassName || '' : '').trim();
|
|
3051
3681
|
const layout = this.isContainerField(field) ? field.layout : undefined;
|
|
3052
3682
|
return [
|
|
3053
3683
|
layout === 'stack' ? 'space-y-4' : 'grid grid-cols-1 gap-4 md:grid-cols-12',
|
|
@@ -3090,6 +3720,8 @@ class DynamicFormComponent {
|
|
|
3090
3720
|
return classes[span] || classes[12];
|
|
3091
3721
|
}
|
|
3092
3722
|
applyLookupResponse(field, response) {
|
|
3723
|
+
if (!isDynamicFormLookupField(field))
|
|
3724
|
+
return;
|
|
3093
3725
|
const lookupMap = field.lookupMap || {};
|
|
3094
3726
|
const mapped = Object.entries(lookupMap).reduce((acc, [targetField, sourcePath]) => {
|
|
3095
3727
|
acc[targetField] = this.resolveTemplateValue(response, sourcePath);
|
|
@@ -3121,11 +3753,11 @@ class DynamicFormComponent {
|
|
|
3121
3753
|
return this.getFlatFields().filter((field) => field.type !== 'container' && field.type !== 'template');
|
|
3122
3754
|
}
|
|
3123
3755
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: DynamicFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3124
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: DynamicFormComponent, isStandalone: true, selector: "dynamic-form", inputs: { fields: "fields", value: "value", errors: "errors", submitLabel: "submitLabel", showSubmit: "showSubmit", disabled: "disabled" }, outputs: { valueChange: "valueChange", lookupCompleted: "lookupCompleted", submitted: "submitted", filesChange: "filesChange", uploadingChange: "uploadingChange", fieldActionTriggered: "fieldActionTriggered" }, providers: [UiFormContext, UiFormLookupService], usesOnChanges: true, ngImport: i0, template: "<form class=\"grid grid-cols-1 gap-4 md:grid-cols-12\" (ngSubmit)=\"submitForm()\" #dynamicForm=\"ngForm\">\n <ng-template #renderField let-field>\n @if (isFieldVisible(field)) {\n @if (isContainerField(field)) {\n @if (getContainerTag(field) === 'aside') {\n <aside [ngClass]=\"getContainerClass(field)\">\n @if (field.label || field.title || getActions(field).length || field.hint) {\n <header class=\"flex flex-col gap-3 border-b border-slate-100 pb-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n @if (field.label || field.title) {\n <p class=\"text-xs font-semibold uppercase tracking-[0.22em] text-slate-500\">\n {{ field.label || field.title }}\n </p>\n }\n @if (field.hint) {\n <h3 class=\"mt-1 text-lg font-semibold text-slate-900\">{{ field.hint }}</h3>\n }\n </div>\n\n @if (getActions(field).length) {\n <div class=\"flex flex-wrap gap-2 md:justify-end\">\n @for (action of getActions(field); track action.id; let i = $index) {\n <ui-button\n [variant]=\"action.variant || (i === 0 ? 'primary' : 'ghost')\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"onFieldActionTriggered(field.id, action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </header>\n }\n\n <div [ngClass]=\"getContainerContentClass(field)\">\n @for (child of field.fields; track child.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: child }\"></ng-container>\n }\n </div>\n </aside>\n } @else if (getContainerTag(field) === 'fieldset') {\n <fieldset [ngClass]=\"getContainerClass(field)\">\n @if (field.label || field.title || getActions(field).length || field.hint) {\n <header class=\"flex flex-col gap-3 border-b border-slate-100 pb-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n @if (field.label || field.title) {\n <legend class=\"text-lg font-semibold text-slate-900\">{{ field.label || field.title }}</legend>\n }\n @if (field.hint) {\n <p class=\"mt-1 text-sm text-slate-500\">{{ field.hint }}</p>\n }\n </div>\n\n @if (getActions(field).length) {\n <div class=\"flex flex-wrap gap-2 md:justify-end\">\n @for (action of getActions(field); track action.id; let i = $index) {\n <ui-button\n [variant]=\"action.variant || (i === 0 ? 'primary' : 'ghost')\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"onFieldActionTriggered(field.id, action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </header>\n }\n\n <div [ngClass]=\"getContainerContentClass(field)\">\n @for (child of field.fields; track child.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: child }\"></ng-container>\n }\n </div>\n </fieldset>\n } @else {\n <section [ngClass]=\"getContainerClass(field)\">\n @if (field.label || field.title || getActions(field).length || field.hint) {\n <header class=\"flex flex-col gap-3 border-b border-slate-100 pb-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n @if (field.label || field.title) {\n <h3 class=\"text-lg font-semibold text-slate-900\">{{ field.label || field.title }}</h3>\n }\n @if (field.hint) {\n <p class=\"mt-1 text-sm text-slate-500\">{{ field.hint }}</p>\n }\n </div>\n\n @if (getActions(field).length) {\n <div class=\"flex flex-wrap gap-2 md:justify-end\">\n @for (action of getActions(field); track action.id; let i = $index) {\n <ui-button\n [variant]=\"action.variant || (i === 0 ? 'primary' : 'ghost')\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"onFieldActionTriggered(field.id, action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </header>\n }\n\n <div [ngClass]=\"getContainerContentClass(field)\">\n @for (child of field.fields; track child.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: child }\"></ng-container>\n }\n </div>\n </section>\n }\n } @else if (isTemplateField(field)) {\n <div [ngClass]=\"resolveClassName(field.className)\" [innerHTML]=\"renderTemplate(field)\"></div>\n } @else {\n <div [ngClass]=\"getFieldClass(field)\">\n <field-input\n [field]=\"field\"\n [value]=\"modelSignal()[field.id]\"\n [disabled]=\"disabled || isFieldDisabled(field) || isLookupLoading(field.id)\"\n [error]=\"errors[field.id] ?? getLookupError(field.id)\"\n [
|
|
3756
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: DynamicFormComponent, isStandalone: true, selector: "dynamic-form", inputs: { fields: "fields", value: "value", errors: "errors", submitLabel: "submitLabel", showSubmit: "showSubmit", disabled: "disabled" }, outputs: { valueChange: "valueChange", lookupCompleted: "lookupCompleted", submitted: "submitted", filesChange: "filesChange", uploadingChange: "uploadingChange", fieldActionTriggered: "fieldActionTriggered" }, providers: [UiFormContext, UiFormLookupService], usesOnChanges: true, ngImport: i0, template: "<form class=\"grid grid-cols-1 gap-4 md:grid-cols-12\" (ngSubmit)=\"submitForm()\" #dynamicForm=\"ngForm\">\n <ng-template #renderField let-field>\n @if (isFieldVisible(field)) {\n @if (isContainerField(field)) {\n @if (getContainerTag(field) === 'aside') {\n <aside [ngClass]=\"getContainerClass(field)\">\n @if (field.label || field.title || getActions(field).length || field.hint) {\n <header class=\"flex flex-col gap-3 border-b border-slate-100 pb-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n @if (field.label || field.title) {\n <p class=\"text-xs font-semibold uppercase tracking-[0.22em] text-slate-500\">\n {{ field.label || field.title }}\n </p>\n }\n @if (field.hint) {\n <h3 class=\"mt-1 text-lg font-semibold text-slate-900\">{{ field.hint }}</h3>\n }\n </div>\n\n @if (getActions(field).length) {\n <div class=\"flex flex-wrap gap-2 md:justify-end\">\n @for (action of getActions(field); track action.id; let i = $index) {\n <ui-button\n [variant]=\"action.variant || (i === 0 ? 'primary' : 'ghost')\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"onFieldActionTriggered(field.id, action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </header>\n }\n\n <div [ngClass]=\"getContainerContentClass(field)\">\n @for (child of field.fields; track child.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: child }\"></ng-container>\n }\n </div>\n </aside>\n } @else if (getContainerTag(field) === 'fieldset') {\n <fieldset [ngClass]=\"getContainerClass(field)\">\n @if (field.label || field.title || getActions(field).length || field.hint) {\n <header class=\"flex flex-col gap-3 border-b border-slate-100 pb-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n @if (field.label || field.title) {\n <legend class=\"text-lg font-semibold text-slate-900\">{{ field.label || field.title }}</legend>\n }\n @if (field.hint) {\n <p class=\"mt-1 text-sm text-slate-500\">{{ field.hint }}</p>\n }\n </div>\n\n @if (getActions(field).length) {\n <div class=\"flex flex-wrap gap-2 md:justify-end\">\n @for (action of getActions(field); track action.id; let i = $index) {\n <ui-button\n [variant]=\"action.variant || (i === 0 ? 'primary' : 'ghost')\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"onFieldActionTriggered(field.id, action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </header>\n }\n\n <div [ngClass]=\"getContainerContentClass(field)\">\n @for (child of field.fields; track child.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: child }\"></ng-container>\n }\n </div>\n </fieldset>\n } @else {\n <section [ngClass]=\"getContainerClass(field)\">\n @if (field.label || field.title || getActions(field).length || field.hint) {\n <header class=\"flex flex-col gap-3 border-b border-slate-100 pb-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n @if (field.label || field.title) {\n <h3 class=\"text-lg font-semibold text-slate-900\">{{ field.label || field.title }}</h3>\n }\n @if (field.hint) {\n <p class=\"mt-1 text-sm text-slate-500\">{{ field.hint }}</p>\n }\n </div>\n\n @if (getActions(field).length) {\n <div class=\"flex flex-wrap gap-2 md:justify-end\">\n @for (action of getActions(field); track action.id; let i = $index) {\n <ui-button\n [variant]=\"action.variant || (i === 0 ? 'primary' : 'ghost')\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"onFieldActionTriggered(field.id, action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </header>\n }\n\n <div [ngClass]=\"getContainerContentClass(field)\">\n @for (child of field.fields; track child.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: child }\"></ng-container>\n }\n </div>\n </section>\n }\n } @else if (isTemplateField(field)) {\n <div [ngClass]=\"resolveClassName(field.className)\" [innerHTML]=\"renderTemplate(field)\"></div>\n } @else {\n <div [ngClass]=\"getFieldClass(field)\">\n <field-input\n [field]=\"field\"\n [value]=\"modelSignal()[field.id]\"\n [model]=\"modelSignal()\"\n [disabled]=\"disabled || isFieldDisabled(field) || isLookupLoading(field.id)\"\n [error]=\"errors[field.id] ?? getLookupError(field.id)\"\n [visibleActions]=\"resolveFieldActions(field)\"\n (valueChange)=\"onFieldValueChange(field, $event)\"\n (actionTriggered)=\"onFieldActionTriggered(field.id, $event)\"\n (lookupRequested)=\"runBarcodeLookup(field)\"\n (barcodeScanned)=\"onBarcodeScanned(field, $event)\"\n (filesChange)=\"filesChange.emit({ fieldId: field.id, files: $event })\"\n (uploadingChange)=\"uploadingChange.emit($event)\"\n ></field-input>\n </div>\n }\n }\n </ng-template>\n\n @for (field of fields; track field.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: field }\"></ng-container>\n }\n\n @if (showSubmit) {\n <div class=\"flex justify-end md:col-span-12\">\n <button\n type=\"submit\"\n class=\"inline-flex items-center rounded-xl bg-slate-900 px-4 py-2 text-sm font-medium text-white transition hover:bg-slate-800 disabled:opacity-50\"\n [disabled]=\"disabled || !dynamicForm.form.valid\"\n >\n {{ submitLabel }}\n </button>\n </div>\n }\n</form>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["variant", "size", "disabled", "fullWidth", "type", "withShadow", "icon", "iconOnly", "ariaLabel"] }, { kind: "component", type: FieldInputComponent, selector: "field-input", inputs: ["field", "value", "model", "error", "disabled", "visibleActions"], outputs: ["valueChange", "actionTriggered", "lookupRequested", "barcodeScanned", "filesChange", "uploadingChange"] }] });
|
|
3125
3757
|
}
|
|
3126
3758
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: DynamicFormComponent, decorators: [{
|
|
3127
3759
|
type: Component,
|
|
3128
|
-
args: [{ selector: 'dynamic-form', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent, FieldInputComponent], providers: [UiFormContext, UiFormLookupService], template: "<form class=\"grid grid-cols-1 gap-4 md:grid-cols-12\" (ngSubmit)=\"submitForm()\" #dynamicForm=\"ngForm\">\n <ng-template #renderField let-field>\n @if (isFieldVisible(field)) {\n @if (isContainerField(field)) {\n @if (getContainerTag(field) === 'aside') {\n <aside [ngClass]=\"getContainerClass(field)\">\n @if (field.label || field.title || getActions(field).length || field.hint) {\n <header class=\"flex flex-col gap-3 border-b border-slate-100 pb-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n @if (field.label || field.title) {\n <p class=\"text-xs font-semibold uppercase tracking-[0.22em] text-slate-500\">\n {{ field.label || field.title }}\n </p>\n }\n @if (field.hint) {\n <h3 class=\"mt-1 text-lg font-semibold text-slate-900\">{{ field.hint }}</h3>\n }\n </div>\n\n @if (getActions(field).length) {\n <div class=\"flex flex-wrap gap-2 md:justify-end\">\n @for (action of getActions(field); track action.id; let i = $index) {\n <ui-button\n [variant]=\"action.variant || (i === 0 ? 'primary' : 'ghost')\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"onFieldActionTriggered(field.id, action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </header>\n }\n\n <div [ngClass]=\"getContainerContentClass(field)\">\n @for (child of field.fields; track child.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: child }\"></ng-container>\n }\n </div>\n </aside>\n } @else if (getContainerTag(field) === 'fieldset') {\n <fieldset [ngClass]=\"getContainerClass(field)\">\n @if (field.label || field.title || getActions(field).length || field.hint) {\n <header class=\"flex flex-col gap-3 border-b border-slate-100 pb-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n @if (field.label || field.title) {\n <legend class=\"text-lg font-semibold text-slate-900\">{{ field.label || field.title }}</legend>\n }\n @if (field.hint) {\n <p class=\"mt-1 text-sm text-slate-500\">{{ field.hint }}</p>\n }\n </div>\n\n @if (getActions(field).length) {\n <div class=\"flex flex-wrap gap-2 md:justify-end\">\n @for (action of getActions(field); track action.id; let i = $index) {\n <ui-button\n [variant]=\"action.variant || (i === 0 ? 'primary' : 'ghost')\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"onFieldActionTriggered(field.id, action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </header>\n }\n\n <div [ngClass]=\"getContainerContentClass(field)\">\n @for (child of field.fields; track child.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: child }\"></ng-container>\n }\n </div>\n </fieldset>\n } @else {\n <section [ngClass]=\"getContainerClass(field)\">\n @if (field.label || field.title || getActions(field).length || field.hint) {\n <header class=\"flex flex-col gap-3 border-b border-slate-100 pb-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n @if (field.label || field.title) {\n <h3 class=\"text-lg font-semibold text-slate-900\">{{ field.label || field.title }}</h3>\n }\n @if (field.hint) {\n <p class=\"mt-1 text-sm text-slate-500\">{{ field.hint }}</p>\n }\n </div>\n\n @if (getActions(field).length) {\n <div class=\"flex flex-wrap gap-2 md:justify-end\">\n @for (action of getActions(field); track action.id; let i = $index) {\n <ui-button\n [variant]=\"action.variant || (i === 0 ? 'primary' : 'ghost')\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"onFieldActionTriggered(field.id, action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </header>\n }\n\n <div [ngClass]=\"getContainerContentClass(field)\">\n @for (child of field.fields; track child.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: child }\"></ng-container>\n }\n </div>\n </section>\n }\n } @else if (isTemplateField(field)) {\n <div [ngClass]=\"resolveClassName(field.className)\" [innerHTML]=\"renderTemplate(field)\"></div>\n } @else {\n <div [ngClass]=\"getFieldClass(field)\">\n <field-input\n [field]=\"field\"\n [value]=\"modelSignal()[field.id]\"\n [disabled]=\"disabled || isFieldDisabled(field) || isLookupLoading(field.id)\"\n [error]=\"errors[field.id] ?? getLookupError(field.id)\"\n [
|
|
3760
|
+
args: [{ selector: 'dynamic-form', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent, FieldInputComponent], providers: [UiFormContext, UiFormLookupService], template: "<form class=\"grid grid-cols-1 gap-4 md:grid-cols-12\" (ngSubmit)=\"submitForm()\" #dynamicForm=\"ngForm\">\n <ng-template #renderField let-field>\n @if (isFieldVisible(field)) {\n @if (isContainerField(field)) {\n @if (getContainerTag(field) === 'aside') {\n <aside [ngClass]=\"getContainerClass(field)\">\n @if (field.label || field.title || getActions(field).length || field.hint) {\n <header class=\"flex flex-col gap-3 border-b border-slate-100 pb-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n @if (field.label || field.title) {\n <p class=\"text-xs font-semibold uppercase tracking-[0.22em] text-slate-500\">\n {{ field.label || field.title }}\n </p>\n }\n @if (field.hint) {\n <h3 class=\"mt-1 text-lg font-semibold text-slate-900\">{{ field.hint }}</h3>\n }\n </div>\n\n @if (getActions(field).length) {\n <div class=\"flex flex-wrap gap-2 md:justify-end\">\n @for (action of getActions(field); track action.id; let i = $index) {\n <ui-button\n [variant]=\"action.variant || (i === 0 ? 'primary' : 'ghost')\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"onFieldActionTriggered(field.id, action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </header>\n }\n\n <div [ngClass]=\"getContainerContentClass(field)\">\n @for (child of field.fields; track child.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: child }\"></ng-container>\n }\n </div>\n </aside>\n } @else if (getContainerTag(field) === 'fieldset') {\n <fieldset [ngClass]=\"getContainerClass(field)\">\n @if (field.label || field.title || getActions(field).length || field.hint) {\n <header class=\"flex flex-col gap-3 border-b border-slate-100 pb-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n @if (field.label || field.title) {\n <legend class=\"text-lg font-semibold text-slate-900\">{{ field.label || field.title }}</legend>\n }\n @if (field.hint) {\n <p class=\"mt-1 text-sm text-slate-500\">{{ field.hint }}</p>\n }\n </div>\n\n @if (getActions(field).length) {\n <div class=\"flex flex-wrap gap-2 md:justify-end\">\n @for (action of getActions(field); track action.id; let i = $index) {\n <ui-button\n [variant]=\"action.variant || (i === 0 ? 'primary' : 'ghost')\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"onFieldActionTriggered(field.id, action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </header>\n }\n\n <div [ngClass]=\"getContainerContentClass(field)\">\n @for (child of field.fields; track child.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: child }\"></ng-container>\n }\n </div>\n </fieldset>\n } @else {\n <section [ngClass]=\"getContainerClass(field)\">\n @if (field.label || field.title || getActions(field).length || field.hint) {\n <header class=\"flex flex-col gap-3 border-b border-slate-100 pb-3 md:flex-row md:items-center md:justify-between\">\n <div class=\"min-w-0\">\n @if (field.label || field.title) {\n <h3 class=\"text-lg font-semibold text-slate-900\">{{ field.label || field.title }}</h3>\n }\n @if (field.hint) {\n <p class=\"mt-1 text-sm text-slate-500\">{{ field.hint }}</p>\n }\n </div>\n\n @if (getActions(field).length) {\n <div class=\"flex flex-wrap gap-2 md:justify-end\">\n @for (action of getActions(field); track action.id; let i = $index) {\n <ui-button\n [variant]=\"action.variant || (i === 0 ? 'primary' : 'ghost')\"\n [icon]=\"action.icon || ''\"\n size=\"sm\"\n [disabled]=\"disabled\"\n (click)=\"onFieldActionTriggered(field.id, action)\"\n >\n {{ action.label }}\n </ui-button>\n }\n </div>\n }\n </header>\n }\n\n <div [ngClass]=\"getContainerContentClass(field)\">\n @for (child of field.fields; track child.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: child }\"></ng-container>\n }\n </div>\n </section>\n }\n } @else if (isTemplateField(field)) {\n <div [ngClass]=\"resolveClassName(field.className)\" [innerHTML]=\"renderTemplate(field)\"></div>\n } @else {\n <div [ngClass]=\"getFieldClass(field)\">\n <field-input\n [field]=\"field\"\n [value]=\"modelSignal()[field.id]\"\n [model]=\"modelSignal()\"\n [disabled]=\"disabled || isFieldDisabled(field) || isLookupLoading(field.id)\"\n [error]=\"errors[field.id] ?? getLookupError(field.id)\"\n [visibleActions]=\"resolveFieldActions(field)\"\n (valueChange)=\"onFieldValueChange(field, $event)\"\n (actionTriggered)=\"onFieldActionTriggered(field.id, $event)\"\n (lookupRequested)=\"runBarcodeLookup(field)\"\n (barcodeScanned)=\"onBarcodeScanned(field, $event)\"\n (filesChange)=\"filesChange.emit({ fieldId: field.id, files: $event })\"\n (uploadingChange)=\"uploadingChange.emit($event)\"\n ></field-input>\n </div>\n }\n }\n </ng-template>\n\n @for (field of fields; track field.id) {\n <ng-container *ngTemplateOutlet=\"renderField; context: { $implicit: field }\"></ng-container>\n }\n\n @if (showSubmit) {\n <div class=\"flex justify-end md:col-span-12\">\n <button\n type=\"submit\"\n class=\"inline-flex items-center rounded-xl bg-slate-900 px-4 py-2 text-sm font-medium text-white transition hover:bg-slate-800 disabled:opacity-50\"\n [disabled]=\"disabled || !dynamicForm.form.valid\"\n >\n {{ submitLabel }}\n </button>\n </div>\n }\n</form>\n" }]
|
|
3129
3761
|
}], propDecorators: { fields: [{
|
|
3130
3762
|
type: Input
|
|
3131
3763
|
}], value: [{
|
|
@@ -3353,6 +3985,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
3353
3985
|
args: [{ selector: 'form-modal', standalone: true, imports: [CommonModule, UiButtonComponent, DynamicFormComponent], template: "@if (isOpen()) {\n <div class=\"fixed inset-0 z-50 flex min-h-full items-center justify-center overflow-y-auto bg-slate-950/40 p-4 sm:p-6\" role=\"dialog\" aria-modal=\"true\">\n <div class=\"my-0 flex min-h-0 max-h-[calc(100vh-2rem)] w-full flex-col overflow-hidden rounded-2xl bg-slate-50 shadow-2xl sm:max-h-[calc(100vh-3rem)]\" [ngClass]=\"panelClass()\">\n <div class=\"flex shrink-0 items-center justify-between border-b border-slate-200 bg-white px-5 py-4 sm:px-6\">\n <h2 class=\"text-lg font-semibold\">{{ formConfig()?.title || 'Form' }}</h2>\n <button type=\"button\" class=\"text-xl text-slate-400 hover:text-slate-900\" aria-label=\"Close\" (click)=\"close()\">\u00D7</button>\n </div>\n <div class=\"min-h-0 flex-1 overflow-y-auto p-4 sm:p-6\">\n @if (isLoading()) {\n <p class=\"text-sm text-slate-500\">Loading form\u2026</p>\n } @else {\n <dynamic-form [fields]=\"fields()\" [value]=\"formValue()\" [disabled]=\"isLoading() || isSubmitting() || isActionRunning()\" [showSubmit]=\"false\" (valueChange)=\"onValueChange($event)\" (lookupCompleted)=\"onLookupCompleted($event)\" (uploadingChange)=\"onUploadingChange($event)\" (fieldActionTriggered)=\"onFieldActionTriggered($event)\"></dynamic-form>\n }\n </div>\n <div class=\"relative z-10 flex shrink-0 justify-end gap-3 border-t border-slate-200 bg-white px-5 py-4 sm:px-6\">\n <ui-button variant=\"ghost\" (click)=\"close()\">{{ cancelLabel() }}</ui-button>\n @if (submitAction()) { <ui-button variant=\"primary\" [disabled]=\"isLoading() || isSubmitting() || isUploading()\" (click)=\"confirm()\">{{ submitLabel() }}</ui-button> }\n </div>\n </div>\n </div>\n}\n" }]
|
|
3354
3986
|
}], propDecorators: { formId: [{ type: i0.Input, args: [{ isSignal: true, alias: "formId", required: false }] }], recordId: [{ type: i0.Input, args: [{ isSignal: true, alias: "recordId", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], isOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpen", required: false }] }], cancelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cancelLabel", required: false }] }], initialValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialValue", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], completed: [{ type: i0.Output, args: ["completed"] }] } });
|
|
3355
3987
|
|
|
3988
|
+
class InputBaseControlComponent {
|
|
3989
|
+
placeholder;
|
|
3990
|
+
name;
|
|
3991
|
+
id;
|
|
3992
|
+
type = 'text';
|
|
3993
|
+
element = 'input';
|
|
3994
|
+
rows = 4;
|
|
3995
|
+
autocomplete;
|
|
3996
|
+
pattern;
|
|
3997
|
+
disabled = false;
|
|
3998
|
+
value = '';
|
|
3999
|
+
valueChange = new EventEmitter();
|
|
4000
|
+
touched = new EventEmitter();
|
|
4001
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputBaseControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4002
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputBaseControlComponent, isStandalone: true, selector: "input-base-control", inputs: { placeholder: "placeholder", name: "name", id: "id", type: "type", element: "element", rows: "rows", autocomplete: "autocomplete", pattern: "pattern", disabled: "disabled", value: "value" }, outputs: { valueChange: "valueChange", touched: "touched" }, ngImport: i0, template: `<input-text-control [placeholder]="placeholder" [name]="name" [id]="id" [type]="type" [element]="element" [rows]="rows" [autocomplete]="autocomplete" [pattern]="pattern" [disabled]="disabled" [value]="value" (valueChange)="valueChange.emit($event)" (touched)="touched.emit()" />`, isInline: true, dependencies: [{ kind: "component", type: InputTextControlComponent, selector: "input-text-control", inputs: ["placeholder", "name", "id", "type", "element", "rows", "autocomplete", "pattern", "disabled", "value"], outputs: ["valueChange", "touched", "enterPressed"] }] });
|
|
4003
|
+
}
|
|
4004
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputBaseControlComponent, decorators: [{
|
|
4005
|
+
type: Component,
|
|
4006
|
+
args: [{ selector: 'input-base-control', standalone: true, imports: [InputTextControlComponent], template: `<input-text-control [placeholder]="placeholder" [name]="name" [id]="id" [type]="type" [element]="element" [rows]="rows" [autocomplete]="autocomplete" [pattern]="pattern" [disabled]="disabled" [value]="value" (valueChange)="valueChange.emit($event)" (touched)="touched.emit()" />` }]
|
|
4007
|
+
}], propDecorators: { placeholder: [{
|
|
4008
|
+
type: Input
|
|
4009
|
+
}], name: [{
|
|
4010
|
+
type: Input
|
|
4011
|
+
}], id: [{
|
|
4012
|
+
type: Input
|
|
4013
|
+
}], type: [{
|
|
4014
|
+
type: Input
|
|
4015
|
+
}], element: [{
|
|
4016
|
+
type: Input
|
|
4017
|
+
}], rows: [{
|
|
4018
|
+
type: Input
|
|
4019
|
+
}], autocomplete: [{
|
|
4020
|
+
type: Input
|
|
4021
|
+
}], pattern: [{
|
|
4022
|
+
type: Input
|
|
4023
|
+
}], disabled: [{
|
|
4024
|
+
type: Input
|
|
4025
|
+
}], value: [{
|
|
4026
|
+
type: Input
|
|
4027
|
+
}], valueChange: [{
|
|
4028
|
+
type: Output
|
|
4029
|
+
}], touched: [{
|
|
4030
|
+
type: Output
|
|
4031
|
+
}] } });
|
|
4032
|
+
|
|
3356
4033
|
class InputComponent {
|
|
3357
4034
|
cdr = inject(ChangeDetectorRef);
|
|
3358
4035
|
label;
|
|
@@ -3364,7 +4041,6 @@ class InputComponent {
|
|
|
3364
4041
|
element = 'input';
|
|
3365
4042
|
rows = 4;
|
|
3366
4043
|
required = false;
|
|
3367
|
-
fullWidth = false;
|
|
3368
4044
|
autocomplete;
|
|
3369
4045
|
pattern;
|
|
3370
4046
|
error;
|
|
@@ -3402,23 +4078,23 @@ class InputComponent {
|
|
|
3402
4078
|
this.actionTriggered.emit(action);
|
|
3403
4079
|
}
|
|
3404
4080
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3405
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
4081
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputComponent, isStandalone: true, selector: "input-base", inputs: { label: "label", hint: "hint", placeholder: "placeholder", name: "name", id: "id", type: "type", element: "element", rows: "rows", required: "required", autocomplete: "autocomplete", pattern: "pattern", error: "error", actions: "actions" }, outputs: { actionTriggered: "actionTriggered" }, providers: [
|
|
3406
4082
|
{
|
|
3407
4083
|
provide: NG_VALUE_ACCESSOR,
|
|
3408
4084
|
useExisting: forwardRef(() => InputComponent),
|
|
3409
4085
|
multi: true,
|
|
3410
4086
|
},
|
|
3411
|
-
], ngImport: i0, template: "<
|
|
4087
|
+
], ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"triggerAction($event)\">\n <input-base-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"controlId\" [type]=\"type\" [element]=\"element\" [rows]=\"rows\" [autocomplete]=\"autocomplete\" [pattern]=\"pattern\" [disabled]=\"disabled\" [value]=\"value\" (valueChange)=\"onValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }, { kind: "component", type: InputBaseControlComponent, selector: "input-base-control", inputs: ["placeholder", "name", "id", "type", "element", "rows", "autocomplete", "pattern", "disabled", "value"], outputs: ["valueChange", "touched"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3412
4088
|
}
|
|
3413
4089
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputComponent, decorators: [{
|
|
3414
4090
|
type: Component,
|
|
3415
|
-
args: [{ selector: 'input-base', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
4091
|
+
args: [{ selector: 'input-base', standalone: true, imports: [CommonModule, FormsModule, UiButtonComponent, FieldFrameComponent, InputBaseControlComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
3416
4092
|
{
|
|
3417
4093
|
provide: NG_VALUE_ACCESSOR,
|
|
3418
4094
|
useExisting: forwardRef(() => InputComponent),
|
|
3419
4095
|
multi: true,
|
|
3420
4096
|
},
|
|
3421
|
-
], template: "<
|
|
4097
|
+
], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\" [forId]=\"controlId\" [disabled]=\"disabled\" [actions]=\"actions\" (actionTriggered)=\"triggerAction($event)\">\n <input-base-control [placeholder]=\"placeholder\" [name]=\"name\" [id]=\"controlId\" [type]=\"type\" [element]=\"element\" [rows]=\"rows\" [autocomplete]=\"autocomplete\" [pattern]=\"pattern\" [disabled]=\"disabled\" [value]=\"value\" (valueChange)=\"onValueChange($event)\" (touched)=\"onTouched()\" />\n</field-frame>\n" }]
|
|
3422
4098
|
}], propDecorators: { label: [{
|
|
3423
4099
|
type: Input
|
|
3424
4100
|
}], hint: [{
|
|
@@ -3437,8 +4113,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
3437
4113
|
type: Input
|
|
3438
4114
|
}], required: [{
|
|
3439
4115
|
type: Input
|
|
3440
|
-
}], fullWidth: [{
|
|
3441
|
-
type: Input
|
|
3442
4116
|
}], autocomplete: [{
|
|
3443
4117
|
type: Input
|
|
3444
4118
|
}], pattern: [{
|
|
@@ -3454,6 +4128,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
3454
4128
|
class InputPhotoGalleryComponent {
|
|
3455
4129
|
http = inject(HttpClient);
|
|
3456
4130
|
label = 'Фото';
|
|
4131
|
+
hint;
|
|
4132
|
+
error;
|
|
4133
|
+
required = false;
|
|
3457
4134
|
orderLabel = 'Порядок фото (перетягуй)';
|
|
3458
4135
|
imageIds = [];
|
|
3459
4136
|
disabled = false;
|
|
@@ -3594,13 +4271,19 @@ class InputPhotoGalleryComponent {
|
|
|
3594
4271
|
return this.http.post('/api/files/', formData).pipe(map((response) => ({ imageId: response.id })));
|
|
3595
4272
|
}
|
|
3596
4273
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputPhotoGalleryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3597
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: InputPhotoGalleryComponent, isStandalone: true, selector: "input-photo-gallery", inputs: { label: "label", orderLabel: "orderLabel", imageIds: "imageIds", disabled: "disabled", afterUpload: "afterUpload", resolveImageUrl: "resolveImageUrl", notify: "notify" }, outputs: { imageIdsChange: "imageIdsChange" }, usesOnChanges: true, ngImport: i0, template: "<label
|
|
4274
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.19", type: InputPhotoGalleryComponent, isStandalone: true, selector: "input-photo-gallery", inputs: { label: "label", hint: "hint", error: "error", required: "required", orderLabel: "orderLabel", imageIds: "imageIds", disabled: "disabled", afterUpload: "afterUpload", resolveImageUrl: "resolveImageUrl", notify: "notify" }, outputs: { imageIdsChange: "imageIdsChange" }, usesOnChanges: true, ngImport: i0, template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\">\n <p class=\"mb-2 text-xs uppercase tracking-[0.2em] text-slate-500\">{{ orderLabel }}</p>\n <div data-field-control class=\"grid gap-3 md:grid-cols-4\" cdkDropList [cdkDropListData]=\"entries\" (cdkDropListDropped)=\"onDrop($event)\">\n @for (entry of entries; let i = $index; track entry.clientKey + '-' + i) {\n <div class=\"image-drag-item relative overflow-hidden rounded-xl border border-slate-200 bg-white\" cdkDrag [cdkDragDisabled]=\"disabled || (!entry.imageId && !entry.file)\">\n <label class=\"block h-full w-full cursor-pointer\">\n @if (entry.preview) {\n <img [src]=\"entry.preview\" alt=\"photo\" class=\"h-48 w-full object-cover\" />\n } @else {\n <button type=\"button\" class=\"flex h-48 w-full items-center justify-center bg-slate-50 text-xs text-slate-500\" (click)=\"openFilePicker(fileInput, $event)\">+ \u0414\u043E\u0434\u0430\u0442\u0438 \u0444\u043E\u0442\u043E</button>\n }\n <input #fileInput type=\"file\" class=\"hidden\" [disabled]=\"disabled\" multiple (change)=\"onFilesChange($event, i)\" />\n </label>\n @if (entry.imageId || entry.file) {\n @if (i === 0) {\n <span class=\"absolute left-2 top-2 rounded-full border border-slate-200 bg-white/95 px-2 py-1 text-[10px] font-semibold uppercase tracking-[0.15em] text-slate-700\">\u041E\u0431\u043A\u043B\u0430\u0434\u0438\u043D\u043A\u0430</span>\n }\n <span class=\"absolute left-2 bottom-2 rounded-full bg-slate-900/85 px-2 py-1 text-[10px] font-semibold text-white\">#{{ i + 1 }}</span>\n <button type=\"button\" class=\"absolute right-2 top-2 rounded-full bg-white/95 px-2 py-1 text-xs text-rose-600 shadow\" [disabled]=\"disabled\" (click)=\"removeAt(i)\">\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438</button>\n }\n </div>\n }\n </div>\n <div class=\"mt-1 text-xs text-slate-500\">\u041A\u0456\u043B\u044C\u043A\u0456\u0441\u0442\u044C \u0444\u043E\u0442\u043E: {{ photoCount }}</div>\n</field-frame>\n", styles: [".image-drag-item.cdk-drag-preview{transform:scale(1.03) rotate(.6deg);box-shadow:0 28px 60px #0f172a66;border-radius:.9rem}.image-drag-item.cdk-drag-placeholder{opacity:.4;outline:2px dashed #94a3b8;outline-offset:4px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1$1.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1$1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }] });
|
|
3598
4275
|
}
|
|
3599
4276
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputPhotoGalleryComponent, decorators: [{
|
|
3600
4277
|
type: Component,
|
|
3601
|
-
args: [{ selector: 'input-photo-gallery', standalone: true, imports: [CommonModule, DragDropModule], template: "<label
|
|
4278
|
+
args: [{ selector: 'input-photo-gallery', standalone: true, imports: [CommonModule, DragDropModule, FieldFrameComponent], template: "<field-frame [label]=\"label\" [hint]=\"hint\" [error]=\"error\" [required]=\"required\">\n <p class=\"mb-2 text-xs uppercase tracking-[0.2em] text-slate-500\">{{ orderLabel }}</p>\n <div data-field-control class=\"grid gap-3 md:grid-cols-4\" cdkDropList [cdkDropListData]=\"entries\" (cdkDropListDropped)=\"onDrop($event)\">\n @for (entry of entries; let i = $index; track entry.clientKey + '-' + i) {\n <div class=\"image-drag-item relative overflow-hidden rounded-xl border border-slate-200 bg-white\" cdkDrag [cdkDragDisabled]=\"disabled || (!entry.imageId && !entry.file)\">\n <label class=\"block h-full w-full cursor-pointer\">\n @if (entry.preview) {\n <img [src]=\"entry.preview\" alt=\"photo\" class=\"h-48 w-full object-cover\" />\n } @else {\n <button type=\"button\" class=\"flex h-48 w-full items-center justify-center bg-slate-50 text-xs text-slate-500\" (click)=\"openFilePicker(fileInput, $event)\">+ \u0414\u043E\u0434\u0430\u0442\u0438 \u0444\u043E\u0442\u043E</button>\n }\n <input #fileInput type=\"file\" class=\"hidden\" [disabled]=\"disabled\" multiple (change)=\"onFilesChange($event, i)\" />\n </label>\n @if (entry.imageId || entry.file) {\n @if (i === 0) {\n <span class=\"absolute left-2 top-2 rounded-full border border-slate-200 bg-white/95 px-2 py-1 text-[10px] font-semibold uppercase tracking-[0.15em] text-slate-700\">\u041E\u0431\u043A\u043B\u0430\u0434\u0438\u043D\u043A\u0430</span>\n }\n <span class=\"absolute left-2 bottom-2 rounded-full bg-slate-900/85 px-2 py-1 text-[10px] font-semibold text-white\">#{{ i + 1 }}</span>\n <button type=\"button\" class=\"absolute right-2 top-2 rounded-full bg-white/95 px-2 py-1 text-xs text-rose-600 shadow\" [disabled]=\"disabled\" (click)=\"removeAt(i)\">\u0412\u0438\u0434\u0430\u043B\u0438\u0442\u0438</button>\n }\n </div>\n }\n </div>\n <div class=\"mt-1 text-xs text-slate-500\">\u041A\u0456\u043B\u044C\u043A\u0456\u0441\u0442\u044C \u0444\u043E\u0442\u043E: {{ photoCount }}</div>\n</field-frame>\n", styles: [".image-drag-item.cdk-drag-preview{transform:scale(1.03) rotate(.6deg);box-shadow:0 28px 60px #0f172a66;border-radius:.9rem}.image-drag-item.cdk-drag-placeholder{opacity:.4;outline:2px dashed #94a3b8;outline-offset:4px}\n"] }]
|
|
3602
4279
|
}], propDecorators: { label: [{
|
|
3603
4280
|
type: Input
|
|
4281
|
+
}], hint: [{
|
|
4282
|
+
type: Input
|
|
4283
|
+
}], error: [{
|
|
4284
|
+
type: Input
|
|
4285
|
+
}], required: [{
|
|
4286
|
+
type: Input
|
|
3604
4287
|
}], orderLabel: [{
|
|
3605
4288
|
type: Input
|
|
3606
4289
|
}], imageIds: [{
|
|
@@ -3618,6 +4301,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
3618
4301
|
}] } });
|
|
3619
4302
|
|
|
3620
4303
|
class InputRangeSliderComponent {
|
|
4304
|
+
label;
|
|
4305
|
+
hint;
|
|
4306
|
+
error;
|
|
4307
|
+
required = false;
|
|
3621
4308
|
min = 0;
|
|
3622
4309
|
max = 100;
|
|
3623
4310
|
step = 1;
|
|
@@ -3707,7 +4394,8 @@ class InputRangeSliderComponent {
|
|
|
3707
4394
|
input.value = String(value);
|
|
3708
4395
|
}
|
|
3709
4396
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputRangeSliderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3710
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputRangeSliderComponent, isStandalone: true, selector: "input-range-slider", inputs: { min: "min", max: "max", step: "step", startValue: "startValue", endValue: "endValue", startLabel: "startLabel", endLabel: "endLabel" }, outputs: { startValueChange: "startValueChange", endValueChange: "endValueChange", interactionEnd: "interactionEnd" }, viewQueries: [{ propertyName: "startInput", first: true, predicate: ["startInput"], descendants: true }, { propertyName: "endInput", first: true, predicate: ["endInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
4397
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.19", type: InputRangeSliderComponent, isStandalone: true, selector: "input-range-slider", inputs: { label: "label", hint: "hint", error: "error", required: "required", min: "min", max: "max", step: "step", startValue: "startValue", endValue: "endValue", startLabel: "startLabel", endLabel: "endLabel" }, outputs: { startValueChange: "startValueChange", endValueChange: "endValueChange", interactionEnd: "interactionEnd" }, viewQueries: [{ propertyName: "startInput", first: true, predicate: ["startInput"], descendants: true }, { propertyName: "endInput", first: true, predicate: ["endInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
4398
|
+
<field-frame [label]="label" [hint]="hint" [error]="error" [required]="required">
|
|
3711
4399
|
<div class="range-slider">
|
|
3712
4400
|
<div class="range-slider__track"></div>
|
|
3713
4401
|
<div
|
|
@@ -3718,6 +4406,7 @@ class InputRangeSliderComponent {
|
|
|
3718
4406
|
|
|
3719
4407
|
<input
|
|
3720
4408
|
#startInput
|
|
4409
|
+
data-field-control
|
|
3721
4410
|
class="range-slider__input"
|
|
3722
4411
|
type="range"
|
|
3723
4412
|
[min]="safeMin"
|
|
@@ -3730,6 +4419,7 @@ class InputRangeSliderComponent {
|
|
|
3730
4419
|
|
|
3731
4420
|
<input
|
|
3732
4421
|
#endInput
|
|
4422
|
+
data-field-control
|
|
3733
4423
|
class="range-slider__input"
|
|
3734
4424
|
type="range"
|
|
3735
4425
|
[min]="safeMin"
|
|
@@ -3740,11 +4430,13 @@ class InputRangeSliderComponent {
|
|
|
3740
4430
|
(input)="onEndInput($event)"
|
|
3741
4431
|
(change)="interactionEnd.emit()">
|
|
3742
4432
|
</div>
|
|
3743
|
-
|
|
4433
|
+
</field-frame>
|
|
4434
|
+
`, isInline: true, styles: [".range-slider{position:relative;height:2rem;width:100%;display:flex;align-items:center}.range-slider__track,.range-slider__range{position:absolute;left:0;right:0;height:6px;border-radius:999px}.range-slider__track{background:#dbe1ea}.range-slider__range{background:linear-gradient(90deg,#334155,#0f172a)}.range-slider__input{pointer-events:none;position:absolute;left:0;width:100%;height:2rem;margin:0;background:transparent;appearance:none;-webkit-appearance:none}.range-slider__input::-webkit-slider-runnable-track{height:6px;background:transparent}.range-slider__input::-moz-range-track{height:6px;background:transparent}.range-slider__input::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;pointer-events:auto;width:20px;height:20px;margin-top:-7px;border-radius:50%;border:2px solid #ffffff;background:#0f172a;box-shadow:0 8px 22px #0f172a38;cursor:pointer}.range-slider__input::-moz-range-thumb{pointer-events:auto;width:20px;height:20px;border-radius:50%;border:2px solid #ffffff;background:#0f172a;box-shadow:0 8px 22px #0f172a38;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: FieldFrameComponent, selector: "field-frame", inputs: ["label", "hint", "error", "required", "forId", "disabled", "actions"], outputs: ["actionTriggered"] }] });
|
|
3744
4435
|
}
|
|
3745
4436
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImport: i0, type: InputRangeSliderComponent, decorators: [{
|
|
3746
4437
|
type: Component,
|
|
3747
|
-
args: [{ selector: 'input-range-slider', standalone: true, imports: [CommonModule], template: `
|
|
4438
|
+
args: [{ selector: 'input-range-slider', standalone: true, imports: [CommonModule, FieldFrameComponent], template: `
|
|
4439
|
+
<field-frame [label]="label" [hint]="hint" [error]="error" [required]="required">
|
|
3748
4440
|
<div class="range-slider">
|
|
3749
4441
|
<div class="range-slider__track"></div>
|
|
3750
4442
|
<div
|
|
@@ -3755,6 +4447,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
3755
4447
|
|
|
3756
4448
|
<input
|
|
3757
4449
|
#startInput
|
|
4450
|
+
data-field-control
|
|
3758
4451
|
class="range-slider__input"
|
|
3759
4452
|
type="range"
|
|
3760
4453
|
[min]="safeMin"
|
|
@@ -3767,6 +4460,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
3767
4460
|
|
|
3768
4461
|
<input
|
|
3769
4462
|
#endInput
|
|
4463
|
+
data-field-control
|
|
3770
4464
|
class="range-slider__input"
|
|
3771
4465
|
type="range"
|
|
3772
4466
|
[min]="safeMin"
|
|
@@ -3777,8 +4471,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
3777
4471
|
(input)="onEndInput($event)"
|
|
3778
4472
|
(change)="interactionEnd.emit()">
|
|
3779
4473
|
</div>
|
|
4474
|
+
</field-frame>
|
|
3780
4475
|
`, styles: [".range-slider{position:relative;height:2rem;width:100%;display:flex;align-items:center}.range-slider__track,.range-slider__range{position:absolute;left:0;right:0;height:6px;border-radius:999px}.range-slider__track{background:#dbe1ea}.range-slider__range{background:linear-gradient(90deg,#334155,#0f172a)}.range-slider__input{pointer-events:none;position:absolute;left:0;width:100%;height:2rem;margin:0;background:transparent;appearance:none;-webkit-appearance:none}.range-slider__input::-webkit-slider-runnable-track{height:6px;background:transparent}.range-slider__input::-moz-range-track{height:6px;background:transparent}.range-slider__input::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;pointer-events:auto;width:20px;height:20px;margin-top:-7px;border-radius:50%;border:2px solid #ffffff;background:#0f172a;box-shadow:0 8px 22px #0f172a38;cursor:pointer}.range-slider__input::-moz-range-thumb{pointer-events:auto;width:20px;height:20px;border-radius:50%;border:2px solid #ffffff;background:#0f172a;box-shadow:0 8px 22px #0f172a38;cursor:pointer}\n"] }]
|
|
3781
|
-
}], propDecorators: {
|
|
4476
|
+
}], propDecorators: { label: [{
|
|
4477
|
+
type: Input
|
|
4478
|
+
}], hint: [{
|
|
4479
|
+
type: Input
|
|
4480
|
+
}], error: [{
|
|
4481
|
+
type: Input
|
|
4482
|
+
}], required: [{
|
|
4483
|
+
type: Input
|
|
4484
|
+
}], min: [{
|
|
3782
4485
|
type: Input
|
|
3783
4486
|
}], max: [{
|
|
3784
4487
|
type: Input
|
|
@@ -3810,5 +4513,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.19", ngImpo
|
|
|
3810
4513
|
* Generated bundle index. Do not edit.
|
|
3811
4514
|
*/
|
|
3812
4515
|
|
|
3813
|
-
export { ACTION_API, ACTION_FORM, ACTION_PRINT, ACTION_SUBMIT, DynamicFormComponent, FieldInputComponent, FormModalComponent, InputBarcodeComponent, InputCheckboxComponent, InputColorComponent, InputComponent, InputDateComponent, InputDatetimeComponent, InputEmailComponent, InputFileComponent, InputNumberComponent, InputPasswordComponent, InputPhotoComponent, InputPhotoGalleryComponent, InputRangeSliderComponent, InputSelectComponent, InputSlugComponent, InputTextComponent, InputTextareaComponent, MaroFormsApiService, UI_FORM_INPUT_REGISTRY, UiFormContext, UiFormLookupService, flattenDynamicFormFields, isDynamicFormContainerField, isDynamicFormTemplateField };
|
|
4516
|
+
export { ACTION_API, ACTION_FORM, ACTION_PRINT, ACTION_SUBMIT, DynamicFormComponent, FieldFrameComponent, FieldInputComponent, FormModalComponent, InputBarcodeComponent, InputBarcodeControlComponent, InputBaseControlComponent, InputCheckboxComponent, InputCheckboxControlComponent, InputColorComponent, InputColorControlComponent, InputComponent, InputDateComponent, InputDateControlComponent, InputDatetimeComponent, InputDatetimeControlComponent, InputEmailComponent, InputEmailControlComponent, InputFileComponent, InputFileControlComponent, InputNumberComponent, InputNumberControlComponent, InputPasswordComponent, InputPasswordControlComponent, InputPhotoComponent, InputPhotoControlComponent, InputPhotoGalleryComponent, InputRangeSliderComponent, InputSelectComponent, InputSelectControlComponent, InputSlugComponent, InputSlugControlComponent, InputTextComponent, InputTextControlComponent, InputTextareaComponent, InputTextareaControlComponent, MaroFormsApiService, UI_FORM_INPUT_REGISTRY, UiFormContext, UiFormLookupService, flattenDynamicFormFields, isDynamicFormContainerField, isDynamicFormLookupField, isDynamicFormTemplateField };
|
|
3814
4517
|
//# sourceMappingURL=maro-tech-form.mjs.map
|