@praxisui/metadata-editor 0.0.1
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/LICENSE +7 -0
- package/README.md +114 -0
- package/fesm2022/praxisui-metadata-editor.mjs +4182 -0
- package/fesm2022/praxisui-metadata-editor.mjs.map +1 -0
- package/index.d.ts +237 -0
- package/package.json +35 -0
|
@@ -0,0 +1,4182 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Injectable, inject, Component, Input, EventEmitter, Output, signal } from '@angular/core';
|
|
3
|
+
import * as i3 from '@angular/forms';
|
|
4
|
+
import { FormControl, FormGroup, ReactiveFormsModule, FormsModule } from '@angular/forms';
|
|
5
|
+
import * as i3$1 from '@angular/common';
|
|
6
|
+
import { CommonModule } from '@angular/common';
|
|
7
|
+
import { DynamicFieldLoaderDirective } from '@praxisui/dynamic-fields';
|
|
8
|
+
import * as i2$1 from '@praxisui/core';
|
|
9
|
+
import { FieldControlType, PraxisIconDirective } from '@praxisui/core';
|
|
10
|
+
import * as i5 from '@angular/material/expansion';
|
|
11
|
+
import { MatExpansionModule } from '@angular/material/expansion';
|
|
12
|
+
import * as i6 from '@angular/material/icon';
|
|
13
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
14
|
+
import * as i5$1 from '@angular/material/button';
|
|
15
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
16
|
+
import * as i1 from '@angular/material/dialog';
|
|
17
|
+
import { MatDialogRef, MatDialogModule } from '@angular/material/dialog';
|
|
18
|
+
import * as i8 from '@angular/material/tooltip';
|
|
19
|
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
20
|
+
import * as i2 from '@angular/material/list';
|
|
21
|
+
import { MatListModule } from '@angular/material/list';
|
|
22
|
+
import { SETTINGS_PANEL_DATA } from '@praxisui/settings-panel';
|
|
23
|
+
import { BehaviorSubject } from 'rxjs';
|
|
24
|
+
import * as i7 from '@angular/material/input';
|
|
25
|
+
import { MatInputModule } from '@angular/material/input';
|
|
26
|
+
import { MatChipsModule } from '@angular/material/chips';
|
|
27
|
+
import { MatDividerModule } from '@angular/material/divider';
|
|
28
|
+
import * as i8$1 from '@angular/material/select';
|
|
29
|
+
import { MatSelectModule } from '@angular/material/select';
|
|
30
|
+
import * as i9 from '@angular/material/checkbox';
|
|
31
|
+
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
32
|
+
import * as i11 from '@angular/material/menu';
|
|
33
|
+
import { MatMenuModule } from '@angular/material/menu';
|
|
34
|
+
import * as i12 from '@angular/cdk/scrolling';
|
|
35
|
+
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
36
|
+
|
|
37
|
+
class ConfigRegistryService {
|
|
38
|
+
map = new Map();
|
|
39
|
+
register(controlType, props) {
|
|
40
|
+
this.map.set(controlType, props);
|
|
41
|
+
}
|
|
42
|
+
getProperties(controlType) {
|
|
43
|
+
return this.map.get(controlType) ?? [];
|
|
44
|
+
}
|
|
45
|
+
list() {
|
|
46
|
+
return Array.from(this.map.entries()).map(([ct, props]) => ({
|
|
47
|
+
controlType: ct,
|
|
48
|
+
count: props.length,
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ConfigRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
52
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ConfigRegistryService, providedIn: 'root' });
|
|
53
|
+
}
|
|
54
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ConfigRegistryService, decorators: [{
|
|
55
|
+
type: Injectable,
|
|
56
|
+
args: [{ providedIn: 'root' }]
|
|
57
|
+
}] });
|
|
58
|
+
|
|
59
|
+
class ContextValidatorRegistryService {
|
|
60
|
+
map = new Map();
|
|
61
|
+
register(controlType, validator) {
|
|
62
|
+
const list = this.map.get(controlType) ?? [];
|
|
63
|
+
list.push(validator);
|
|
64
|
+
this.map.set(controlType, list);
|
|
65
|
+
}
|
|
66
|
+
get(controlType) {
|
|
67
|
+
return this.map.get(controlType) ?? [];
|
|
68
|
+
}
|
|
69
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ContextValidatorRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
70
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ContextValidatorRegistryService, providedIn: 'root' });
|
|
71
|
+
}
|
|
72
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: ContextValidatorRegistryService, decorators: [{
|
|
73
|
+
type: Injectable,
|
|
74
|
+
args: [{ providedIn: 'root' }]
|
|
75
|
+
}] });
|
|
76
|
+
|
|
77
|
+
class SchemaNormalizerService {
|
|
78
|
+
/** Normaliza propriedades e aplica defaultValue resolvendo do seed por dot-path. */
|
|
79
|
+
normalize(properties, seed) {
|
|
80
|
+
const out = properties.map((p) => {
|
|
81
|
+
const clone = { ...p };
|
|
82
|
+
// normalizar options se for string simples
|
|
83
|
+
if (Array.isArray(clone.options)) {
|
|
84
|
+
clone.options = clone.options.map((opt) => typeof opt === 'string' ? { value: opt, text: opt } : opt);
|
|
85
|
+
}
|
|
86
|
+
// pattern/regex
|
|
87
|
+
if (clone.pattern && typeof clone.pattern === 'string') {
|
|
88
|
+
const str = String(clone.pattern);
|
|
89
|
+
const match = /^\/(.*)\/([gimsuy]*)$/.exec(str);
|
|
90
|
+
if (match) {
|
|
91
|
+
try {
|
|
92
|
+
clone.pattern = new RegExp(match[1], match[2]);
|
|
93
|
+
}
|
|
94
|
+
catch { }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// aplicar defaultValue do seed se existir
|
|
98
|
+
if (seed && clone.defaultValue === undefined) {
|
|
99
|
+
const val = this.getByPath(seed, clone.name);
|
|
100
|
+
if (val !== undefined) {
|
|
101
|
+
// Stringify complex defaults for textarea-friendly editors
|
|
102
|
+
const needsJson = (clone.editorType === 'textarea' &&
|
|
103
|
+
(clone.name === 'options' ||
|
|
104
|
+
clone.name === 'filterCriteria' ||
|
|
105
|
+
clone.name === 'paletteSettings.colors' ||
|
|
106
|
+
clone.name === 'views' ||
|
|
107
|
+
clone.name === 'adaptiveSubtitle'));
|
|
108
|
+
clone.defaultValue = needsJson && typeof val !== 'string' ? JSON.stringify(val, null, 2) : val;
|
|
109
|
+
try {
|
|
110
|
+
if (clone.name === 'resourcePath' ||
|
|
111
|
+
clone.name === 'filterCriteria' ||
|
|
112
|
+
clone.name === 'optionLabelKey' ||
|
|
113
|
+
clone.name === 'optionValueKey' ||
|
|
114
|
+
clone.name === 'options' ||
|
|
115
|
+
clone.name === 'paletteSettings.colors' ||
|
|
116
|
+
clone.name === 'views') {
|
|
117
|
+
console.debug('[SchemaNormalizer] default from seed', {
|
|
118
|
+
name: clone.name,
|
|
119
|
+
value: needsJson && typeof val !== 'string' ? JSON.stringify(val) : val,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// Extra diagnostics for Rating editor fields
|
|
123
|
+
if ([
|
|
124
|
+
'max',
|
|
125
|
+
'allowHalf',
|
|
126
|
+
'precision',
|
|
127
|
+
'selection',
|
|
128
|
+
'size',
|
|
129
|
+
'icon',
|
|
130
|
+
'emptyIcon',
|
|
131
|
+
'svgIcon',
|
|
132
|
+
'svgIconOutline',
|
|
133
|
+
'ratingColor',
|
|
134
|
+
'outlineColor',
|
|
135
|
+
'readonly',
|
|
136
|
+
'tabIndex',
|
|
137
|
+
'ariaLabel',
|
|
138
|
+
].includes(clone.name)) {
|
|
139
|
+
console.debug('[SchemaNormalizer][RATING] default from seed', {
|
|
140
|
+
name: clone.name,
|
|
141
|
+
value: val,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch { }
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
else if (seed && clone.defaultValue !== undefined) {
|
|
149
|
+
// Log when a property defines its own defaultValue and thus does not read from seed
|
|
150
|
+
try {
|
|
151
|
+
if (clone.name === 'resourcePath' ||
|
|
152
|
+
clone.name === 'filterCriteria' ||
|
|
153
|
+
clone.name === 'optionLabelKey' ||
|
|
154
|
+
clone.name === 'optionValueKey' ||
|
|
155
|
+
clone.name === 'options') {
|
|
156
|
+
const val = this.getByPath(seed, clone.name);
|
|
157
|
+
console.debug('[SchemaNormalizer] default preserved (property default overrides seed)', {
|
|
158
|
+
name: clone.name,
|
|
159
|
+
propertyDefault: clone.defaultValue,
|
|
160
|
+
seedValue: val,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch { }
|
|
165
|
+
}
|
|
166
|
+
return clone;
|
|
167
|
+
});
|
|
168
|
+
try {
|
|
169
|
+
const names = out.map((p) => p.name);
|
|
170
|
+
const defPreview = out
|
|
171
|
+
.filter((p) => ['resourcePath', 'filterCriteria', 'optionLabelKey', 'optionValueKey'].includes(p.name))
|
|
172
|
+
.map((p) => ({ name: p.name, defaultValue: p.defaultValue }));
|
|
173
|
+
console.debug('[SchemaNormalizer] normalize summary', { names, defPreview });
|
|
174
|
+
}
|
|
175
|
+
catch { }
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
178
|
+
/** Lê valor por dot-path */
|
|
179
|
+
getByPath(obj, path) {
|
|
180
|
+
return path.split('.').reduce((acc, key) => (acc == null ? acc : acc[key]), obj);
|
|
181
|
+
}
|
|
182
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: SchemaNormalizerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
183
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: SchemaNormalizerService, providedIn: 'root' });
|
|
184
|
+
}
|
|
185
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: SchemaNormalizerService, decorators: [{
|
|
186
|
+
type: Injectable,
|
|
187
|
+
args: [{ providedIn: 'root' }]
|
|
188
|
+
}] });
|
|
189
|
+
|
|
190
|
+
class DynamicFormFactoryService {
|
|
191
|
+
fb;
|
|
192
|
+
ctxValidators;
|
|
193
|
+
constructor(fb, ctxValidators) {
|
|
194
|
+
this.fb = fb;
|
|
195
|
+
this.ctxValidators = ctxValidators;
|
|
196
|
+
}
|
|
197
|
+
createEditorForm(controlType, props, seed) {
|
|
198
|
+
const group = this.fb.group({});
|
|
199
|
+
for (const p of props) {
|
|
200
|
+
const ctrl = new FormControl(p.defaultValue ?? null, { validators: p.validators ?? [] });
|
|
201
|
+
this.assignControlByPath(group, p.name, ctrl);
|
|
202
|
+
try {
|
|
203
|
+
if (p.name === 'resourcePath' ||
|
|
204
|
+
p.name === 'filterCriteria' ||
|
|
205
|
+
p.name === 'optionLabelKey' ||
|
|
206
|
+
p.name === 'optionValueKey') {
|
|
207
|
+
console.debug('[EditorForm] control init', {
|
|
208
|
+
name: p.name,
|
|
209
|
+
defaultValue: p.defaultValue ?? null,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch { }
|
|
214
|
+
}
|
|
215
|
+
const formValidators = this.ctxValidators.get(controlType);
|
|
216
|
+
if (formValidators.length) {
|
|
217
|
+
group.addValidators(formValidators);
|
|
218
|
+
}
|
|
219
|
+
return group;
|
|
220
|
+
}
|
|
221
|
+
getControlByPath(form, path) {
|
|
222
|
+
return form.get(path);
|
|
223
|
+
}
|
|
224
|
+
setValueByPath(form, path, value) {
|
|
225
|
+
form.get(path)?.setValue(value);
|
|
226
|
+
}
|
|
227
|
+
extractPatch(form) {
|
|
228
|
+
const patch = form.getRawValue();
|
|
229
|
+
try {
|
|
230
|
+
console.debug('[EditorForm] extractPatch', patch);
|
|
231
|
+
}
|
|
232
|
+
catch { }
|
|
233
|
+
return patch;
|
|
234
|
+
}
|
|
235
|
+
mergeIntoFieldDefinition(base, patch) {
|
|
236
|
+
return this.deepMerge(base, patch);
|
|
237
|
+
}
|
|
238
|
+
assignControlByPath(group, path, ctrl) {
|
|
239
|
+
const parts = path.split('.');
|
|
240
|
+
let current = group;
|
|
241
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
242
|
+
const key = parts[i];
|
|
243
|
+
const next = current.get(key);
|
|
244
|
+
if (!next) {
|
|
245
|
+
const child = this.fb.group({});
|
|
246
|
+
current.addControl(key, child);
|
|
247
|
+
current = child;
|
|
248
|
+
}
|
|
249
|
+
else if (next instanceof FormGroup) {
|
|
250
|
+
current = next;
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
// Overwrite non-group path with group to respect dot-notation
|
|
254
|
+
const child = this.fb.group({});
|
|
255
|
+
current.removeControl(key);
|
|
256
|
+
current.addControl(key, child);
|
|
257
|
+
current = child;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
current.addControl(parts[parts.length - 1], ctrl);
|
|
261
|
+
}
|
|
262
|
+
deepMerge(target, source) {
|
|
263
|
+
if (source == null || typeof source !== 'object')
|
|
264
|
+
return target;
|
|
265
|
+
const result = Array.isArray(target) ? [...target] : { ...target };
|
|
266
|
+
for (const [k, v] of Object.entries(source)) {
|
|
267
|
+
if (v && typeof v === 'object' && !Array.isArray(v)) {
|
|
268
|
+
result[k] = this.deepMerge(result[k] ?? {}, v);
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
result[k] = v;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return result;
|
|
275
|
+
}
|
|
276
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DynamicFormFactoryService, deps: [{ token: i3.FormBuilder }, { token: ContextValidatorRegistryService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
277
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DynamicFormFactoryService, providedIn: 'root' });
|
|
278
|
+
}
|
|
279
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DynamicFormFactoryService, decorators: [{
|
|
280
|
+
type: Injectable,
|
|
281
|
+
args: [{ providedIn: 'root' }]
|
|
282
|
+
}], ctorParameters: () => [{ type: i3.FormBuilder }, { type: ContextValidatorRegistryService }] });
|
|
283
|
+
|
|
284
|
+
class EditorComponentRegistryService {
|
|
285
|
+
registry = new Map();
|
|
286
|
+
cache = new Map();
|
|
287
|
+
register(editorType, loader) {
|
|
288
|
+
this.registry.set(editorType, loader);
|
|
289
|
+
}
|
|
290
|
+
async get(editorType) {
|
|
291
|
+
if (this.cache.has(editorType)) {
|
|
292
|
+
return this.cache.get(editorType);
|
|
293
|
+
}
|
|
294
|
+
const loader = this.registry.get(editorType);
|
|
295
|
+
if (!loader)
|
|
296
|
+
return null;
|
|
297
|
+
const type = await loader();
|
|
298
|
+
if (type)
|
|
299
|
+
this.cache.set(editorType, type);
|
|
300
|
+
return type ?? null;
|
|
301
|
+
}
|
|
302
|
+
isRegistered(editorType) {
|
|
303
|
+
return this.registry.has(editorType);
|
|
304
|
+
}
|
|
305
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: EditorComponentRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
306
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: EditorComponentRegistryService, providedIn: 'root' });
|
|
307
|
+
}
|
|
308
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: EditorComponentRegistryService, decorators: [{
|
|
309
|
+
type: Injectable,
|
|
310
|
+
args: [{ providedIn: 'root' }]
|
|
311
|
+
}] });
|
|
312
|
+
|
|
313
|
+
class RegexHelpDialogComponent {
|
|
314
|
+
dialogRef = inject((MatDialogRef));
|
|
315
|
+
presets = [
|
|
316
|
+
{ label: 'Apenas letras (ASCII)', pattern: '/^[a-zA-Z]+$/' },
|
|
317
|
+
{ label: 'Apenas dígitos', pattern: '/^\\d+$/' },
|
|
318
|
+
{ label: 'Email simples', pattern: '/^\\w+@[\\w.-]+\\.[A-Za-z]{2,}$/' },
|
|
319
|
+
{ label: 'URL básica (http/https)', pattern: '/^(https?:\\/\\/)?[\\w.-]+(\\\\.[\\w.-]+)+[\\w\\-._~:?#@!$&\'()*+,;=\\/]*$/' },
|
|
320
|
+
{ label: 'Pelo menos 8 caracteres', pattern: '/^.{8,}$/' },
|
|
321
|
+
{ label: 'CEP brasileiro (#####-###)', pattern: '/^\\d{5}-\\d{3}$/' },
|
|
322
|
+
{ label: 'CPF (###.###.###-##)', pattern: '/^\\d{3}\\.\\d{3}\\.\\d{3}-\\d{2}$/' },
|
|
323
|
+
{ label: 'CNPJ (##.###.###/####-##)', pattern: '/^\\d{2}\\.\\d{3}\\.\\d{3}\\/\\d{4}-\\d{2}$/' },
|
|
324
|
+
{ label: 'Telefone (Brasil) com DDD', pattern: '/^\\(\\d{2}\\) \\d{4,5}-\\d{4}$/' },
|
|
325
|
+
{ label: 'Somente hex (0-9 A-F)', pattern: '/^[0-9A-Fa-f]+$/' },
|
|
326
|
+
{ label: 'Código postal (US ZIP)', pattern: '/^\\d{5}(-\\d{4})?$/' },
|
|
327
|
+
{ label: 'Data (YYYY-MM-DD)', pattern: '/^\\d{4}-\\d{2}-\\d{2}$/' },
|
|
328
|
+
{ label: 'Hora (HH:MM 24h)', pattern: '/^([01]\\d|2[0-3]):[0-5]\\d$/' },
|
|
329
|
+
{ label: 'Slug (letras, dígitos, hífen)', pattern: '/^[a-z0-9-]+$/' },
|
|
330
|
+
{ label: 'Username (3-16, alfanum., _ -)', pattern: '/^[a-zA-Z0-9_-]{3,16}$/' },
|
|
331
|
+
{ label: 'Senha forte (8+, maiúsc., minúsc., dígito)', pattern: '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{8,}$/' },
|
|
332
|
+
{ label: 'IPv4', pattern: '/^(25[0-5]|2[0-4]\\d|[01]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[01]?\\d?\\d)){3}$/' },
|
|
333
|
+
{ label: 'MAC address', pattern: '/^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$/' },
|
|
334
|
+
{ label: 'Hashtag (#palavra)', pattern: '/^#\\w+$/' },
|
|
335
|
+
{ label: 'Menção (@usuario)', pattern: '/^@\\w+$/' },
|
|
336
|
+
{ label: 'Palavra específica (foo)', pattern: '/\\bfoo\\b/' },
|
|
337
|
+
{ label: 'Não conter espaços', pattern: '/^\\S+$/' },
|
|
338
|
+
{ label: 'Início com letra', pattern: '/^[A-Za-z].*$/' },
|
|
339
|
+
{ label: 'Termina com ponto final', pattern: '/.*\\.$/' },
|
|
340
|
+
{ label: 'Número com 2 casas decimais', pattern: '/^\\d+(,\\d{2}|\\.\\d{2})$/' },
|
|
341
|
+
{ label: 'Hex color (#RRGGBB)', pattern: '/^#?[A-Fa-f0-9]{6}$/' },
|
|
342
|
+
{ label: 'UUID v4', pattern: '/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i' },
|
|
343
|
+
{ label: 'DOM id (letra inicial)', pattern: '/^[A-Za-z][-A-Za-z0-9_:.]*$/' },
|
|
344
|
+
{ label: 'Base64', pattern: '/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/' },
|
|
345
|
+
];
|
|
346
|
+
choose(pattern) {
|
|
347
|
+
this.dialogRef.close(pattern);
|
|
348
|
+
}
|
|
349
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: RegexHelpDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
350
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: RegexHelpDialogComponent, isStandalone: true, selector: "praxis-regex-help-dialog", ngImport: i0, template: `
|
|
351
|
+
<h2 mat-dialog-title>Modelos de Expressões Regulares</h2>
|
|
352
|
+
<div mat-dialog-content>
|
|
353
|
+
<p>Selecione um dos modelos abaixo para preencher o campo ou use como base:</p>
|
|
354
|
+
<mat-nav-list dense>
|
|
355
|
+
@for (r of presets; track r.pattern) {
|
|
356
|
+
<a mat-list-item (click)="choose(r.pattern)" style="cursor: pointer;">
|
|
357
|
+
<span matListItemTitle><code>{{ r.pattern }}</code></span>
|
|
358
|
+
<span matListItemLine>{{ r.label }}</span>
|
|
359
|
+
</a>
|
|
360
|
+
}
|
|
361
|
+
</mat-nav-list>
|
|
362
|
+
<p style="margin-top: 12px;">Recursos úteis:</p>
|
|
363
|
+
<ul>
|
|
364
|
+
<li><a href="https://regex101.com/" target="_blank" rel="noreferrer noopener">regex101.com</a> — Teste e depure regex</li>
|
|
365
|
+
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions" target="_blank" rel="noreferrer noopener">MDN: Regular expressions</a></li>
|
|
366
|
+
</ul>
|
|
367
|
+
</div>
|
|
368
|
+
<div mat-dialog-actions>
|
|
369
|
+
<button class="mat-mdc-button mdc-button" mat-dialog-close>Fechar</button>
|
|
370
|
+
</div>
|
|
371
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i2.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i2.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: i2.MatListItemLine, selector: "[matListItemLine]" }, { kind: "directive", type: i2.MatListItemTitle, selector: "[matListItemTitle]" }, { kind: "ngmodule", type: MatButtonModule }] });
|
|
372
|
+
}
|
|
373
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: RegexHelpDialogComponent, decorators: [{
|
|
374
|
+
type: Component,
|
|
375
|
+
args: [{
|
|
376
|
+
selector: 'praxis-regex-help-dialog',
|
|
377
|
+
standalone: true,
|
|
378
|
+
imports: [CommonModule, MatDialogModule, MatListModule, MatButtonModule],
|
|
379
|
+
template: `
|
|
380
|
+
<h2 mat-dialog-title>Modelos de Expressões Regulares</h2>
|
|
381
|
+
<div mat-dialog-content>
|
|
382
|
+
<p>Selecione um dos modelos abaixo para preencher o campo ou use como base:</p>
|
|
383
|
+
<mat-nav-list dense>
|
|
384
|
+
@for (r of presets; track r.pattern) {
|
|
385
|
+
<a mat-list-item (click)="choose(r.pattern)" style="cursor: pointer;">
|
|
386
|
+
<span matListItemTitle><code>{{ r.pattern }}</code></span>
|
|
387
|
+
<span matListItemLine>{{ r.label }}</span>
|
|
388
|
+
</a>
|
|
389
|
+
}
|
|
390
|
+
</mat-nav-list>
|
|
391
|
+
<p style="margin-top: 12px;">Recursos úteis:</p>
|
|
392
|
+
<ul>
|
|
393
|
+
<li><a href="https://regex101.com/" target="_blank" rel="noreferrer noopener">regex101.com</a> — Teste e depure regex</li>
|
|
394
|
+
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions" target="_blank" rel="noreferrer noopener">MDN: Regular expressions</a></li>
|
|
395
|
+
</ul>
|
|
396
|
+
</div>
|
|
397
|
+
<div mat-dialog-actions>
|
|
398
|
+
<button class="mat-mdc-button mdc-button" mat-dialog-close>Fechar</button>
|
|
399
|
+
</div>
|
|
400
|
+
`,
|
|
401
|
+
}]
|
|
402
|
+
}] });
|
|
403
|
+
|
|
404
|
+
class DynamicEditorRendererComponent {
|
|
405
|
+
dialog;
|
|
406
|
+
iconPicker;
|
|
407
|
+
properties = [];
|
|
408
|
+
form;
|
|
409
|
+
fields = [];
|
|
410
|
+
groupFields = {};
|
|
411
|
+
groupOrder = [];
|
|
412
|
+
groupRows = {};
|
|
413
|
+
// Evita reentrância: cria loaders após o primeiro tick
|
|
414
|
+
ready = false;
|
|
415
|
+
ngOnChanges(changes) {
|
|
416
|
+
if (changes['properties']) {
|
|
417
|
+
const mapped = this.properties.map((p) => this.toFieldMetadata(p));
|
|
418
|
+
this.fields = mapped;
|
|
419
|
+
const groupMap = new Map();
|
|
420
|
+
const rowMap = new Map();
|
|
421
|
+
for (const f of mapped) {
|
|
422
|
+
const g = f._group || 'Geral';
|
|
423
|
+
if (!groupMap.has(g))
|
|
424
|
+
groupMap.set(g, []);
|
|
425
|
+
groupMap.get(g).push(f);
|
|
426
|
+
const rowKey = f._row || `${f.name}`;
|
|
427
|
+
if (!rowMap.has(g))
|
|
428
|
+
rowMap.set(g, new Map());
|
|
429
|
+
const rmap = rowMap.get(g);
|
|
430
|
+
if (!rmap.has(rowKey))
|
|
431
|
+
rmap.set(rowKey, []);
|
|
432
|
+
rmap.get(rowKey).push(f);
|
|
433
|
+
}
|
|
434
|
+
this.groupFields = Object.fromEntries(groupMap.entries());
|
|
435
|
+
this.groupOrder = Array.from(groupMap.keys()).sort((a, b) => this.groupWeight(a) - this.groupWeight(b));
|
|
436
|
+
const rows = {};
|
|
437
|
+
for (const g of this.groupOrder) {
|
|
438
|
+
const rmap = rowMap.get(g);
|
|
439
|
+
rows[g] = Array.from(rmap.values());
|
|
440
|
+
}
|
|
441
|
+
this.groupRows = rows;
|
|
442
|
+
// Ativar loaders após agrupar propriedades
|
|
443
|
+
queueMicrotask?.(() => (this.ready = true));
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
toFieldMetadata(p) {
|
|
447
|
+
const controlType = this.mapEditorType(p.editorType);
|
|
448
|
+
const meta = {
|
|
449
|
+
name: p.name,
|
|
450
|
+
label: p.label,
|
|
451
|
+
controlType,
|
|
452
|
+
placeholder: p.placeholder,
|
|
453
|
+
// Ajuda contextual padrão quando ausente
|
|
454
|
+
hint: p.hint,
|
|
455
|
+
options: Array.isArray(p.options) ? p.options : undefined,
|
|
456
|
+
required: p.required,
|
|
457
|
+
// meta auxiliar de agrupamento (não exportado)
|
|
458
|
+
_group: p.group || 'Geral',
|
|
459
|
+
_inline: p.inline || false,
|
|
460
|
+
_row: p.row || undefined,
|
|
461
|
+
// validators do EditorProperty já foram aplicados ao FormControl pela fábrica,
|
|
462
|
+
// mas manter aqui não prejudica e habilita exibição de mensagens padrão.
|
|
463
|
+
validators: undefined,
|
|
464
|
+
};
|
|
465
|
+
// Priorização de campos principais (agrupa em uma linha "core")
|
|
466
|
+
const coreNames = new Set(['controlType', 'label', 'placeholder']);
|
|
467
|
+
if (coreNames.has(p.name) && !meta._row)
|
|
468
|
+
meta._row = '__core';
|
|
469
|
+
// Campos menores e de baixa relevância visual (agrupados inline)
|
|
470
|
+
const smallNames = new Set([
|
|
471
|
+
'prefix',
|
|
472
|
+
'suffix',
|
|
473
|
+
'prefixIcon',
|
|
474
|
+
'suffixIcon',
|
|
475
|
+
'prefixIconColor',
|
|
476
|
+
'suffixIconColor',
|
|
477
|
+
'icon',
|
|
478
|
+
]);
|
|
479
|
+
if (smallNames.has(p.name)) {
|
|
480
|
+
meta._inline = true;
|
|
481
|
+
if (!meta._row)
|
|
482
|
+
meta._row = '__affixes';
|
|
483
|
+
}
|
|
484
|
+
// Apenas campos de ícone devem receber o hint de Material Symbols
|
|
485
|
+
if (this.isIconField(p.name) && !meta.hint) {
|
|
486
|
+
meta.hint = 'Use o nome do ícone (Material Symbols)';
|
|
487
|
+
}
|
|
488
|
+
// Booleans em linha (switches) para melhor densidade
|
|
489
|
+
const booleanLike = new Set([
|
|
490
|
+
'required',
|
|
491
|
+
'disabled',
|
|
492
|
+
'readonly',
|
|
493
|
+
'showCharCount',
|
|
494
|
+
'showClear',
|
|
495
|
+
'autoFocus',
|
|
496
|
+
'hideLabel',
|
|
497
|
+
]);
|
|
498
|
+
if (p.editorType === 'checkbox' || booleanLike.has(p.name)) {
|
|
499
|
+
meta._inline = true;
|
|
500
|
+
if (!meta._row)
|
|
501
|
+
meta._row = '__toggles';
|
|
502
|
+
}
|
|
503
|
+
// Mensagem padrão de atenção ao trocar tipo de campo
|
|
504
|
+
if (p.name === 'controlType' && !meta.hint) {
|
|
505
|
+
meta.hint = 'Alterar o tipo pode impactar configurações e validações';
|
|
506
|
+
}
|
|
507
|
+
if (p.editorType === 'number') {
|
|
508
|
+
// Defaults for numeric editors
|
|
509
|
+
if (/minlength|maxlength/i.test(p.name)) {
|
|
510
|
+
meta.min = 0;
|
|
511
|
+
meta.step = 1;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
// no editor-specific overrides for textarea sizing here (reverted)
|
|
515
|
+
return meta;
|
|
516
|
+
}
|
|
517
|
+
// Priorização das seções
|
|
518
|
+
groupWeight(group) {
|
|
519
|
+
const key = group.toLowerCase();
|
|
520
|
+
const order = [
|
|
521
|
+
'geral',
|
|
522
|
+
'apresent',
|
|
523
|
+
'valida',
|
|
524
|
+
'formato',
|
|
525
|
+
'comport',
|
|
526
|
+
'material',
|
|
527
|
+
'ações',
|
|
528
|
+
'acess',
|
|
529
|
+
];
|
|
530
|
+
const idx = order.findIndex((k) => key.includes(k));
|
|
531
|
+
return idx >= 0 ? idx : 999;
|
|
532
|
+
}
|
|
533
|
+
// No section open by default
|
|
534
|
+
isInitiallyExpanded(_group) {
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
// (preview removed by request)
|
|
538
|
+
rowClass(row) {
|
|
539
|
+
// Linha compacta (toggles) quando todos são inline
|
|
540
|
+
if (row.every((f) => !!f._inline))
|
|
541
|
+
return 'row-inline';
|
|
542
|
+
// Se não for inline e houver 2 ou 3 itens, usar colunas iguais
|
|
543
|
+
const n = row.length;
|
|
544
|
+
if (n === 2)
|
|
545
|
+
return 'row-2';
|
|
546
|
+
if (n === 3)
|
|
547
|
+
return 'row-3';
|
|
548
|
+
return '';
|
|
549
|
+
}
|
|
550
|
+
mapEditorType(t) {
|
|
551
|
+
switch (t) {
|
|
552
|
+
case 'text':
|
|
553
|
+
return FieldControlType.INPUT;
|
|
554
|
+
case 'number':
|
|
555
|
+
return FieldControlType.NUMERIC_TEXT_BOX;
|
|
556
|
+
case 'textarea':
|
|
557
|
+
return FieldControlType.TEXTAREA;
|
|
558
|
+
case 'select':
|
|
559
|
+
return FieldControlType.SELECT;
|
|
560
|
+
case 'checkbox':
|
|
561
|
+
// Para booleano simples, usamos o toggle
|
|
562
|
+
return FieldControlType.TOGGLE;
|
|
563
|
+
case 'date':
|
|
564
|
+
return FieldControlType.DATE_INPUT;
|
|
565
|
+
case 'datetime-local':
|
|
566
|
+
return FieldControlType.DATETIME_LOCAL_INPUT;
|
|
567
|
+
case 'color':
|
|
568
|
+
return FieldControlType.COLOR_INPUT;
|
|
569
|
+
case 'colorPicker':
|
|
570
|
+
return FieldControlType.COLOR_PICKER;
|
|
571
|
+
default:
|
|
572
|
+
return FieldControlType.INPUT;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
groupIcon(group) {
|
|
576
|
+
const key = group.toLowerCase();
|
|
577
|
+
if (key.includes('valida'))
|
|
578
|
+
return 'rule';
|
|
579
|
+
if (key.includes('formato') || key.includes('másc'))
|
|
580
|
+
return 'format_shapes';
|
|
581
|
+
if (key.includes('apresent'))
|
|
582
|
+
return 'display_settings';
|
|
583
|
+
if (key.includes('lista') || key.includes('opç'))
|
|
584
|
+
return 'list';
|
|
585
|
+
return 'tune';
|
|
586
|
+
}
|
|
587
|
+
constructor(dialog, iconPicker) {
|
|
588
|
+
this.dialog = dialog;
|
|
589
|
+
this.iconPicker = iconPicker;
|
|
590
|
+
}
|
|
591
|
+
isIconField(path) {
|
|
592
|
+
if (!path)
|
|
593
|
+
return false;
|
|
594
|
+
// Supports: prefixIcon, suffixIcon, icon, clearButton.icon, any *.icon
|
|
595
|
+
return path === 'prefixIcon' || path === 'suffixIcon' || path === 'icon' || /(^|\.)icon$/.test(path);
|
|
596
|
+
}
|
|
597
|
+
openRegexHelp() {
|
|
598
|
+
const ref = this.dialog.open(RegexHelpDialogComponent, {
|
|
599
|
+
width: '720px',
|
|
600
|
+
});
|
|
601
|
+
ref.afterClosed().subscribe((selected) => {
|
|
602
|
+
if (!selected)
|
|
603
|
+
return;
|
|
604
|
+
const ctrl = this.form?.get('pattern');
|
|
605
|
+
ctrl?.setValue(selected);
|
|
606
|
+
ctrl?.markAsDirty();
|
|
607
|
+
this.form?.markAsDirty();
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
async openIconPicker(path) {
|
|
611
|
+
const current = this.form?.get(path)?.value;
|
|
612
|
+
const picked = await this.iconPicker.openDialog({ value: current });
|
|
613
|
+
if (picked !== undefined) {
|
|
614
|
+
this.form?.get(path)?.setValue(picked);
|
|
615
|
+
this.form?.markAsDirty();
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DynamicEditorRendererComponent, deps: [{ token: i1.MatDialog }, { token: i2$1.IconPickerService }], target: i0.ɵɵFactoryTarget.Component });
|
|
619
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: DynamicEditorRendererComponent, isStandalone: true, selector: "praxis-dynamic-editor-renderer", inputs: { properties: "properties", form: "form" }, usesOnChanges: true, ngImport: i0, template: `
|
|
620
|
+
<ng-template #item let-field="field" let-index="index" let-content="content">
|
|
621
|
+
<div class="editor-item" style="position: relative;">
|
|
622
|
+
<ng-container [ngTemplateOutlet]="content"></ng-container>
|
|
623
|
+
<!-- Botão de ajuda para regex, posicionado como sufixo visual do campo -->
|
|
624
|
+
<button
|
|
625
|
+
*ngIf="field.name === 'pattern'"
|
|
626
|
+
type="button"
|
|
627
|
+
mat-icon-button
|
|
628
|
+
class="regex-help-btn decorator-btn"
|
|
629
|
+
(click)="openRegexHelp()"
|
|
630
|
+
aria-label="Exemplos de regex"
|
|
631
|
+
matTooltip="Exemplos de regex"
|
|
632
|
+
>
|
|
633
|
+
<mat-icon [praxisIcon]="'search'"></mat-icon>
|
|
634
|
+
</button>
|
|
635
|
+
<!-- Botão para escolher ícone (prefix/suffix) -->
|
|
636
|
+
<button
|
|
637
|
+
*ngIf="isIconField(field.name)"
|
|
638
|
+
type="button"
|
|
639
|
+
mat-icon-button
|
|
640
|
+
class="icon-picker-btn decorator-btn"
|
|
641
|
+
(click)="openIconPicker(field.name)"
|
|
642
|
+
aria-label="Escolher ícone"
|
|
643
|
+
matTooltip="Escolher ícone"
|
|
644
|
+
>
|
|
645
|
+
<mat-icon [praxisIcon]="'apps'"></mat-icon>
|
|
646
|
+
</button>
|
|
647
|
+
</div>
|
|
648
|
+
</ng-template>
|
|
649
|
+
|
|
650
|
+
<div class="editor-surface">
|
|
651
|
+
<mat-accordion class="section-accordion" multi>
|
|
652
|
+
<mat-expansion-panel class="section-card" *ngFor="let g of groupOrder">
|
|
653
|
+
<mat-expansion-panel-header class="section-header">
|
|
654
|
+
<mat-panel-title>
|
|
655
|
+
<span class="section-title">
|
|
656
|
+
<mat-icon class="section-icon" [praxisIcon]="groupIcon(g)"></mat-icon>
|
|
657
|
+
{{ g }}
|
|
658
|
+
</span>
|
|
659
|
+
</mat-panel-title>
|
|
660
|
+
</mat-expansion-panel-header>
|
|
661
|
+
|
|
662
|
+
<div *ngFor="let row of groupRows[g]" class="editor-row" [ngClass]="rowClass(row)">
|
|
663
|
+
<ng-container *ngIf="ready"
|
|
664
|
+
dynamicFieldLoader
|
|
665
|
+
[fields]="row"
|
|
666
|
+
[formGroup]="form"
|
|
667
|
+
[itemTemplate]="item">
|
|
668
|
+
</ng-container>
|
|
669
|
+
</div>
|
|
670
|
+
</mat-expansion-panel>
|
|
671
|
+
</mat-accordion>
|
|
672
|
+
</div>
|
|
673
|
+
`, isInline: true, styles: [":host{display:block}.editor-surface{padding:8px 8px 2px;border-radius:12px;background:transparent}.section-accordion{display:block}.section-card{margin:6px 0 8px;border-radius:12px;border:1px solid rgba(0,0,0,.08);overflow:hidden}.section-card.mat-expanded{border-color:color-mix(in srgb,var(--mat-sys-primary, #3f51b5) 20%,transparent);box-shadow:0 2px 10px #0000000d}.section-card .mat-expansion-panel-body{padding:12px 12px 8px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-surface, var(--sicoob-bg-elev-1)) 2%),transparent)}.section-header{background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-surface, var(--sicoob-bg-elev-2)) 92%,var(--md-sys-color-primary, var(--sicoob-primary-default))) 0%,var(--md-sys-color-surface, var(--sicoob-bg-elev-2)) 100%);border-bottom:1px solid var(--md-sys-color-outline-variant, var(--sicoob-stroke-medium));padding:2px 8px;min-height:32px;display:flex;align-items:center}.section-header .mat-expansion-panel-header-title,.section-header .mat-expansion-panel-header-description{display:flex;align-items:center}.section-title{display:inline-flex;align-items:center;gap:6px;font-weight:600;letter-spacing:.2px;color:var(--mat-sys-color-on-surface, var(--md-sys-color-on-surface, rgba(0,0,0,.87)));font-size:.9rem;line-height:1.2}.section-icon{color:var(--mat-sys-color-primary, var(--md-sys-color-primary, #3f51b5));opacity:.9}.editor-row{display:flex;gap:12px;align-items:flex-start;flex-wrap:wrap;margin-bottom:8px}.editor-row>praxis-field-shell{flex:1 1 100%;min-width:280px}.editor-row praxis-field-shell .mat-mdc-form-field{width:100%;margin-bottom:8px}.editor-row.row-inline>praxis-field-shell{flex:0 0 auto}.editor-row.row-2>praxis-field-shell{flex:1 1 calc(50% - 12px);min-width:260px}.editor-row.row-3>praxis-field-shell{flex:1 1 calc(33.333% - 12px);min-width:220px}.editor-row>praxis-field-shell[data-field-name=controlType],.editor-row>praxis-field-shell[data-field-name=label],.editor-row>praxis-field-shell[data-field-name=placeholder]{flex:1 1 calc(50% - 12px);min-width:300px}praxis-field-shell[data-field-name=label] .mdc-floating-label,praxis-field-shell[data-field-name=placeholder] .mdc-floating-label{font-weight:600}.editor-row>praxis-field-shell[data-field-name=prefix],.editor-row>praxis-field-shell[data-field-name=suffix],.editor-row>praxis-field-shell[data-field-name=prefixIcon],.editor-row>praxis-field-shell[data-field-name=suffixIcon],.editor-row>praxis-field-shell[data-field-name=prefixIconColor],.editor-row>praxis-field-shell[data-field-name=suffixIconColor]{flex:0 0 200px;min-width:160px}.decorator-btn{position:absolute;right:6px;top:8px;z-index:2;color:var(--mat-sys-primary, #3f51b5);opacity:.85}praxis-field-shell[data-field-name=showCharCount] .mdc-switch{transform:scale(1.05)}praxis-field-shell[data-field-name=showCharCount] .mat-mdc-slide-toggle{font-weight:600}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field-hint{display:flex;align-items:center;gap:8px;background:#ffab001f;border:1px solid rgba(255,171,0,.35);color:#ffca28;padding:8px 10px;border-radius:6px;line-height:1.3;white-space:normal}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field-hint:before{content:\"\\26a0\\fe0f\";display:inline-block}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field-subscript-wrapper{margin-top:6px;margin-bottom:10px;min-height:auto}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field{margin-bottom:16px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i5.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i5.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i5.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i5.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
|
|
674
|
+
}
|
|
675
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: DynamicEditorRendererComponent, decorators: [{
|
|
676
|
+
type: Component,
|
|
677
|
+
args: [{ selector: 'praxis-dynamic-editor-renderer', standalone: true, imports: [
|
|
678
|
+
CommonModule,
|
|
679
|
+
ReactiveFormsModule,
|
|
680
|
+
DynamicFieldLoaderDirective,
|
|
681
|
+
MatExpansionModule,
|
|
682
|
+
MatIconModule,
|
|
683
|
+
MatButtonModule,
|
|
684
|
+
MatDialogModule,
|
|
685
|
+
MatTooltipModule,
|
|
686
|
+
PraxisIconDirective,
|
|
687
|
+
], template: `
|
|
688
|
+
<ng-template #item let-field="field" let-index="index" let-content="content">
|
|
689
|
+
<div class="editor-item" style="position: relative;">
|
|
690
|
+
<ng-container [ngTemplateOutlet]="content"></ng-container>
|
|
691
|
+
<!-- Botão de ajuda para regex, posicionado como sufixo visual do campo -->
|
|
692
|
+
<button
|
|
693
|
+
*ngIf="field.name === 'pattern'"
|
|
694
|
+
type="button"
|
|
695
|
+
mat-icon-button
|
|
696
|
+
class="regex-help-btn decorator-btn"
|
|
697
|
+
(click)="openRegexHelp()"
|
|
698
|
+
aria-label="Exemplos de regex"
|
|
699
|
+
matTooltip="Exemplos de regex"
|
|
700
|
+
>
|
|
701
|
+
<mat-icon [praxisIcon]="'search'"></mat-icon>
|
|
702
|
+
</button>
|
|
703
|
+
<!-- Botão para escolher ícone (prefix/suffix) -->
|
|
704
|
+
<button
|
|
705
|
+
*ngIf="isIconField(field.name)"
|
|
706
|
+
type="button"
|
|
707
|
+
mat-icon-button
|
|
708
|
+
class="icon-picker-btn decorator-btn"
|
|
709
|
+
(click)="openIconPicker(field.name)"
|
|
710
|
+
aria-label="Escolher ícone"
|
|
711
|
+
matTooltip="Escolher ícone"
|
|
712
|
+
>
|
|
713
|
+
<mat-icon [praxisIcon]="'apps'"></mat-icon>
|
|
714
|
+
</button>
|
|
715
|
+
</div>
|
|
716
|
+
</ng-template>
|
|
717
|
+
|
|
718
|
+
<div class="editor-surface">
|
|
719
|
+
<mat-accordion class="section-accordion" multi>
|
|
720
|
+
<mat-expansion-panel class="section-card" *ngFor="let g of groupOrder">
|
|
721
|
+
<mat-expansion-panel-header class="section-header">
|
|
722
|
+
<mat-panel-title>
|
|
723
|
+
<span class="section-title">
|
|
724
|
+
<mat-icon class="section-icon" [praxisIcon]="groupIcon(g)"></mat-icon>
|
|
725
|
+
{{ g }}
|
|
726
|
+
</span>
|
|
727
|
+
</mat-panel-title>
|
|
728
|
+
</mat-expansion-panel-header>
|
|
729
|
+
|
|
730
|
+
<div *ngFor="let row of groupRows[g]" class="editor-row" [ngClass]="rowClass(row)">
|
|
731
|
+
<ng-container *ngIf="ready"
|
|
732
|
+
dynamicFieldLoader
|
|
733
|
+
[fields]="row"
|
|
734
|
+
[formGroup]="form"
|
|
735
|
+
[itemTemplate]="item">
|
|
736
|
+
</ng-container>
|
|
737
|
+
</div>
|
|
738
|
+
</mat-expansion-panel>
|
|
739
|
+
</mat-accordion>
|
|
740
|
+
</div>
|
|
741
|
+
`, styles: [":host{display:block}.editor-surface{padding:8px 8px 2px;border-radius:12px;background:transparent}.section-accordion{display:block}.section-card{margin:6px 0 8px;border-radius:12px;border:1px solid rgba(0,0,0,.08);overflow:hidden}.section-card.mat-expanded{border-color:color-mix(in srgb,var(--mat-sys-primary, #3f51b5) 20%,transparent);box-shadow:0 2px 10px #0000000d}.section-card .mat-expansion-panel-body{padding:12px 12px 8px;background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-surface, var(--sicoob-bg-elev-1)) 2%),transparent)}.section-header{background:linear-gradient(180deg,color-mix(in srgb,var(--md-sys-color-surface, var(--sicoob-bg-elev-2)) 92%,var(--md-sys-color-primary, var(--sicoob-primary-default))) 0%,var(--md-sys-color-surface, var(--sicoob-bg-elev-2)) 100%);border-bottom:1px solid var(--md-sys-color-outline-variant, var(--sicoob-stroke-medium));padding:2px 8px;min-height:32px;display:flex;align-items:center}.section-header .mat-expansion-panel-header-title,.section-header .mat-expansion-panel-header-description{display:flex;align-items:center}.section-title{display:inline-flex;align-items:center;gap:6px;font-weight:600;letter-spacing:.2px;color:var(--mat-sys-color-on-surface, var(--md-sys-color-on-surface, rgba(0,0,0,.87)));font-size:.9rem;line-height:1.2}.section-icon{color:var(--mat-sys-color-primary, var(--md-sys-color-primary, #3f51b5));opacity:.9}.editor-row{display:flex;gap:12px;align-items:flex-start;flex-wrap:wrap;margin-bottom:8px}.editor-row>praxis-field-shell{flex:1 1 100%;min-width:280px}.editor-row praxis-field-shell .mat-mdc-form-field{width:100%;margin-bottom:8px}.editor-row.row-inline>praxis-field-shell{flex:0 0 auto}.editor-row.row-2>praxis-field-shell{flex:1 1 calc(50% - 12px);min-width:260px}.editor-row.row-3>praxis-field-shell{flex:1 1 calc(33.333% - 12px);min-width:220px}.editor-row>praxis-field-shell[data-field-name=controlType],.editor-row>praxis-field-shell[data-field-name=label],.editor-row>praxis-field-shell[data-field-name=placeholder]{flex:1 1 calc(50% - 12px);min-width:300px}praxis-field-shell[data-field-name=label] .mdc-floating-label,praxis-field-shell[data-field-name=placeholder] .mdc-floating-label{font-weight:600}.editor-row>praxis-field-shell[data-field-name=prefix],.editor-row>praxis-field-shell[data-field-name=suffix],.editor-row>praxis-field-shell[data-field-name=prefixIcon],.editor-row>praxis-field-shell[data-field-name=suffixIcon],.editor-row>praxis-field-shell[data-field-name=prefixIconColor],.editor-row>praxis-field-shell[data-field-name=suffixIconColor]{flex:0 0 200px;min-width:160px}.decorator-btn{position:absolute;right:6px;top:8px;z-index:2;color:var(--mat-sys-primary, #3f51b5);opacity:.85}praxis-field-shell[data-field-name=showCharCount] .mdc-switch{transform:scale(1.05)}praxis-field-shell[data-field-name=showCharCount] .mat-mdc-slide-toggle{font-weight:600}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field-hint{display:flex;align-items:center;gap:8px;background:#ffab001f;border:1px solid rgba(255,171,0,.35);color:#ffca28;padding:8px 10px;border-radius:6px;line-height:1.3;white-space:normal}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field-hint:before{content:\"\\26a0\\fe0f\";display:inline-block}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field-subscript-wrapper{margin-top:6px;margin-bottom:10px;min-height:auto}praxis-field-shell[data-field-name=controlType] .mat-mdc-form-field{margin-bottom:16px}\n"] }]
|
|
742
|
+
}], ctorParameters: () => [{ type: i1.MatDialog }, { type: i2$1.IconPickerService }], propDecorators: { properties: [{
|
|
743
|
+
type: Input
|
|
744
|
+
}], form: [{
|
|
745
|
+
type: Input
|
|
746
|
+
}] } });
|
|
747
|
+
|
|
748
|
+
const inputProperties = [
|
|
749
|
+
// Geral
|
|
750
|
+
{ name: 'label', label: 'Label', editorType: 'text', placeholder: 'Rótulo do campo', group: 'Geral' },
|
|
751
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
752
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
753
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:search). Use o seletor ao lado para buscar." },
|
|
754
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
755
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
756
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
757
|
+
{ name: 'prefix', label: 'Texto (prefixo)', editorType: 'text', group: 'Geral' },
|
|
758
|
+
{ name: 'suffix', label: 'Texto (sufixo)', editorType: 'text', group: 'Geral' },
|
|
759
|
+
{ name: 'showCharacterCount', label: 'Mostrar contador de caracteres', editorType: 'checkbox', group: 'Geral' },
|
|
760
|
+
// Validação
|
|
761
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
762
|
+
{ name: 'minLength', label: 'Mínimo de caracteres', editorType: 'number', group: 'Validação', row: 'validacao.minmax' },
|
|
763
|
+
{ name: 'maxLength', label: 'Máximo de caracteres', editorType: 'number', group: 'Validação', row: 'validacao.minmax' },
|
|
764
|
+
{ name: 'pattern', label: 'Pattern (regex)', editorType: 'text', hint: 'Ex.: /^foo.*/i', group: 'Validação' },
|
|
765
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
766
|
+
{ name: 'validators.minLengthMessage', label: 'Mensagem: mínimo', editorType: 'text', group: 'Validação' },
|
|
767
|
+
{ name: 'validators.maxLengthMessage', label: 'Mensagem: máximo', editorType: 'text', group: 'Validação' },
|
|
768
|
+
{ name: 'validators.patternMessage', label: 'Mensagem: padrão inválido', editorType: 'text', group: 'Validação' },
|
|
769
|
+
// Máscara/Formato
|
|
770
|
+
{ name: 'mask', label: 'Máscara', editorType: 'text', group: 'Formato/Comportamento' },
|
|
771
|
+
{
|
|
772
|
+
name: 'textTransform',
|
|
773
|
+
label: 'Transformação de texto',
|
|
774
|
+
editorType: 'select',
|
|
775
|
+
group: 'Formato/Comportamento',
|
|
776
|
+
options: [
|
|
777
|
+
{ value: 'none', text: 'Nenhuma' },
|
|
778
|
+
{ value: 'uppercase', text: 'MAIÚSCULAS (CSS)' },
|
|
779
|
+
{ value: 'lowercase', text: 'minúsculas (CSS)' },
|
|
780
|
+
{ value: 'capitalize', text: 'Capitalizar (CSS)' },
|
|
781
|
+
{ value: 'titleCase', text: 'Title Case' },
|
|
782
|
+
{ value: 'sentenceCase', text: 'Sentence case' },
|
|
783
|
+
{ value: 'kebab', text: 'kebab-case' },
|
|
784
|
+
{ value: 'snake', text: 'snake_case' },
|
|
785
|
+
{ value: 'camel', text: 'camelCase' },
|
|
786
|
+
{ value: 'pascal', text: 'PascalCase' },
|
|
787
|
+
{ value: 'slugify', text: 'slugify (a-z0-9-)' },
|
|
788
|
+
{ value: 'trim', text: 'trim (remover bordas)' },
|
|
789
|
+
{ value: 'collapseWhitespace', text: 'collapseWhitespace (normalizar espaços)' },
|
|
790
|
+
{ value: 'removeDiacritics', text: 'removeDiacritics (sem acentos)' },
|
|
791
|
+
],
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
name: 'textTransformApply',
|
|
795
|
+
label: 'Aplicar em',
|
|
796
|
+
editorType: 'select',
|
|
797
|
+
group: 'Formato/Comportamento',
|
|
798
|
+
defaultValue: 'displayOnly',
|
|
799
|
+
options: [
|
|
800
|
+
{ value: 'displayOnly', text: 'Exibição (visual)' },
|
|
801
|
+
{ value: 'saveOnly', text: 'Salvar (persistência)' },
|
|
802
|
+
{ value: 'both', text: 'Ambos' },
|
|
803
|
+
],
|
|
804
|
+
},
|
|
805
|
+
// Formato/Comportamento
|
|
806
|
+
{ name: 'autocomplete', label: 'Autocomplete', editorType: 'text', group: 'Formato/Comportamento' },
|
|
807
|
+
{ name: 'spellcheck', label: 'Verificação ortográfica', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comportamento.toggles1', inline: true },
|
|
808
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comportamento.toggles1', inline: true },
|
|
809
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comportamento.toggles1', inline: true },
|
|
810
|
+
{
|
|
811
|
+
name: 'inputMode',
|
|
812
|
+
label: 'Modo de entrada (mobile)',
|
|
813
|
+
editorType: 'select',
|
|
814
|
+
group: 'Formato/Comportamento',
|
|
815
|
+
options: [
|
|
816
|
+
{ value: 'text', text: 'Texto' },
|
|
817
|
+
{ value: 'numeric', text: 'Numérico' },
|
|
818
|
+
{ value: 'decimal', text: 'Decimal' },
|
|
819
|
+
{ value: 'tel', text: 'Telefone' },
|
|
820
|
+
{ value: 'email', text: 'Email' },
|
|
821
|
+
{ value: 'url', text: 'URL' },
|
|
822
|
+
{ value: 'search', text: 'Busca' },
|
|
823
|
+
],
|
|
824
|
+
},
|
|
825
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comportamento.toggles2', inline: true },
|
|
826
|
+
{
|
|
827
|
+
name: 'inputType',
|
|
828
|
+
label: 'Tipo de input (HTML5)',
|
|
829
|
+
editorType: 'select',
|
|
830
|
+
group: 'Formato/Comportamento',
|
|
831
|
+
options: [
|
|
832
|
+
{ value: 'text', text: 'Texto' },
|
|
833
|
+
{ value: 'email', text: 'Email' },
|
|
834
|
+
{ value: 'password', text: 'Senha' },
|
|
835
|
+
{ value: 'tel', text: 'Telefone' },
|
|
836
|
+
{ value: 'url', text: 'URL' },
|
|
837
|
+
{ value: 'search', text: 'Busca' },
|
|
838
|
+
{ value: 'number', text: 'Número' },
|
|
839
|
+
{ value: 'date', text: 'Data' },
|
|
840
|
+
{ value: 'datetime-local', text: 'Data/Hora local' },
|
|
841
|
+
{ value: 'time', text: 'Hora' },
|
|
842
|
+
{ value: 'month', text: 'Mês' },
|
|
843
|
+
{ value: 'week', text: 'Semana' },
|
|
844
|
+
{ value: 'color', text: 'Cor' },
|
|
845
|
+
],
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
name: 'validators.validationTrigger',
|
|
849
|
+
label: 'Gatilho de validação',
|
|
850
|
+
editorType: 'select',
|
|
851
|
+
group: 'Formato/Comportamento',
|
|
852
|
+
row: 'comportamento.validation',
|
|
853
|
+
inline: true,
|
|
854
|
+
options: [
|
|
855
|
+
{ value: 'change', text: 'Ao digitar' },
|
|
856
|
+
{ value: 'blur', text: 'Ao sair do campo' },
|
|
857
|
+
{ value: 'submit', text: 'Ao submeter' },
|
|
858
|
+
{ value: 'immediate', text: 'Imediato' },
|
|
859
|
+
],
|
|
860
|
+
},
|
|
861
|
+
{
|
|
862
|
+
name: 'validators.validationDebounce',
|
|
863
|
+
label: 'Debounce de validação (ms)',
|
|
864
|
+
editorType: 'number',
|
|
865
|
+
group: 'Formato/Comportamento',
|
|
866
|
+
row: 'comportamento.validation',
|
|
867
|
+
inline: true,
|
|
868
|
+
},
|
|
869
|
+
{ name: 'validators.showInlineErrors', label: 'Mostrar erros inline', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
870
|
+
{
|
|
871
|
+
name: 'validators.errorPosition',
|
|
872
|
+
label: 'Posição do erro',
|
|
873
|
+
editorType: 'select',
|
|
874
|
+
group: 'Formato/Comportamento',
|
|
875
|
+
options: [
|
|
876
|
+
{ value: 'bottom', text: 'Abaixo' },
|
|
877
|
+
{ value: 'top', text: 'Acima' },
|
|
878
|
+
{ value: 'tooltip', text: 'Tooltip' },
|
|
879
|
+
],
|
|
880
|
+
},
|
|
881
|
+
// Material Design
|
|
882
|
+
{
|
|
883
|
+
name: 'materialDesign.appearance',
|
|
884
|
+
label: 'Aparência',
|
|
885
|
+
editorType: 'select',
|
|
886
|
+
group: 'Material Design',
|
|
887
|
+
options: [
|
|
888
|
+
{ value: 'fill', text: 'Fill' },
|
|
889
|
+
{ value: 'outline', text: 'Outline' },
|
|
890
|
+
],
|
|
891
|
+
},
|
|
892
|
+
{
|
|
893
|
+
name: 'materialDesign.color',
|
|
894
|
+
label: 'Cor do tema',
|
|
895
|
+
editorType: 'select',
|
|
896
|
+
group: 'Material Design',
|
|
897
|
+
options: [
|
|
898
|
+
{ value: 'primary', text: 'Primária' },
|
|
899
|
+
{ value: 'accent', text: 'Acento' },
|
|
900
|
+
{ value: 'warn', text: 'Alerta' },
|
|
901
|
+
],
|
|
902
|
+
},
|
|
903
|
+
{
|
|
904
|
+
name: 'materialDesign.floatLabel',
|
|
905
|
+
label: 'Comportamento do label',
|
|
906
|
+
editorType: 'select',
|
|
907
|
+
group: 'Material Design',
|
|
908
|
+
options: [
|
|
909
|
+
{ value: 'auto', text: 'Auto' },
|
|
910
|
+
{ value: 'always', text: 'Sempre' },
|
|
911
|
+
],
|
|
912
|
+
},
|
|
913
|
+
{
|
|
914
|
+
name: 'materialDesign.subscriptSizing',
|
|
915
|
+
label: 'Subscript sizing',
|
|
916
|
+
editorType: 'select',
|
|
917
|
+
group: 'Material Design',
|
|
918
|
+
options: [
|
|
919
|
+
{ value: 'fixed', text: 'Fixo' },
|
|
920
|
+
{ value: 'dynamic', text: 'Dinâmico' },
|
|
921
|
+
],
|
|
922
|
+
},
|
|
923
|
+
{ name: 'materialDesign.hideRequiredMarker', label: 'Ocultar * obrigatório', editorType: 'checkbox', group: 'Material Design' },
|
|
924
|
+
// Estado de erro e interações avançadas
|
|
925
|
+
{
|
|
926
|
+
name: 'errorStateMatcher',
|
|
927
|
+
label: 'Estratégia de erro',
|
|
928
|
+
editorType: 'select',
|
|
929
|
+
group: 'Material Design',
|
|
930
|
+
options: [
|
|
931
|
+
{ value: 'default', text: 'Padrão' },
|
|
932
|
+
{ value: 'showOnDirtyAndInvalid', text: 'Mostrar ao sujar e inválido' },
|
|
933
|
+
{ value: 'showOnSubmitted', text: 'Mostrar ao enviar' },
|
|
934
|
+
{ value: 'showImmediately', text: 'Mostrar imediatamente' },
|
|
935
|
+
],
|
|
936
|
+
},
|
|
937
|
+
{ name: 'disabledInteractive', label: 'Desabilitado interativo', editorType: 'checkbox', group: 'Material Design' },
|
|
938
|
+
// Botão limpar (clear)
|
|
939
|
+
{ name: 'clearButton.enabled', label: 'Clear: habilitar', editorType: 'checkbox', group: 'Ações' },
|
|
940
|
+
{ name: 'clearButton.icon', label: 'Clear: ícone', editorType: 'text', group: 'Ações', hint: "Material Symbols (ex.: mi:clear). Use o seletor ao lado para buscar." },
|
|
941
|
+
{ name: 'clearButton.iconColor', label: 'Clear: cor do ícone', editorType: 'color', group: 'Ações', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
942
|
+
{ name: 'clearButton.tooltip', label: 'Clear: tooltip', editorType: 'text', group: 'Ações' },
|
|
943
|
+
{ name: 'clearButton.ariaLabel', label: 'Clear: aria-label', editorType: 'text', group: 'Ações' },
|
|
944
|
+
{ name: 'clearButton.showOnlyWhenFilled', label: 'Clear: só quando preenchido', editorType: 'checkbox', group: 'Ações' },
|
|
945
|
+
// Acessibilidade / Avançado
|
|
946
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
947
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
948
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
949
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
950
|
+
{ name: 'dataAttributes', label: 'Data attributes (JSON)', editorType: 'textarea', hint: '{ "testId": "input-a" }', group: 'Acessibilidade' },
|
|
951
|
+
// Valor padrão
|
|
952
|
+
{ name: 'defaultValue', label: 'Valor padrão', editorType: 'text', group: 'Geral' },
|
|
953
|
+
];
|
|
954
|
+
|
|
955
|
+
// Editor de metadados para componentes SELECT-like
|
|
956
|
+
// Paridade com INPUT: grupos, linhas e propriedades canônicas
|
|
957
|
+
const selectProperties = [
|
|
958
|
+
// 1) Geral
|
|
959
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
960
|
+
{ name: 'defaultValue', label: 'Valor padrão', editorType: 'text', group: 'Geral' },
|
|
961
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
962
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
963
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:list). Use o seletor ao lado para buscar." },
|
|
964
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
965
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
966
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
967
|
+
{ name: 'prefix', label: 'Texto (prefixo)', editorType: 'text', group: 'Geral' },
|
|
968
|
+
{ name: 'suffix', label: 'Texto (sufixo)', editorType: 'text', group: 'Geral' },
|
|
969
|
+
// 2) Dados/Opções
|
|
970
|
+
{
|
|
971
|
+
name: 'options',
|
|
972
|
+
label: 'Opções (estáticas)',
|
|
973
|
+
editorType: 'textarea',
|
|
974
|
+
group: 'Dados/Opções',
|
|
975
|
+
hint: 'JSON: [{ "value":1, "text":"Um" }] ou linhas: valor|rótulo',
|
|
976
|
+
},
|
|
977
|
+
{ name: 'emptyOptionText', label: 'Texto da opção vazia', editorType: 'text', group: 'Dados/Opções' },
|
|
978
|
+
{ name: 'multiple', label: 'Múltipla seleção', editorType: 'checkbox', group: 'Dados/Opções', row: 'dados.inline1', inline: true },
|
|
979
|
+
{ name: 'optionLabelKey', label: 'Chave do rótulo (remoto)', editorType: 'text', group: 'Dados/Opções' },
|
|
980
|
+
{ name: 'optionValueKey', label: 'Chave do valor (remoto)', editorType: 'text', group: 'Dados/Opções' },
|
|
981
|
+
// 3) Fonte Remota
|
|
982
|
+
{ name: 'resourcePath', label: 'Resource Path', editorType: 'text', group: 'Fonte Remota' },
|
|
983
|
+
{
|
|
984
|
+
name: 'loadOn',
|
|
985
|
+
label: 'Carregar em',
|
|
986
|
+
editorType: 'select',
|
|
987
|
+
group: 'Fonte Remota',
|
|
988
|
+
options: [
|
|
989
|
+
{ value: 'open', text: 'Ao abrir (padrão)' },
|
|
990
|
+
{ value: 'init', text: 'Na inicialização' },
|
|
991
|
+
{ value: 'none', text: 'Nenhum (manual)' },
|
|
992
|
+
],
|
|
993
|
+
hint: "Define quando o async-select realiza a primeira busca remota",
|
|
994
|
+
},
|
|
995
|
+
{ name: 'filterCriteria', label: 'Critérios de filtro (JSON)', editorType: 'textarea', group: 'Fonte Remota', hint: '{ "active": true }' },
|
|
996
|
+
// 3.1) Dependências (Cascata Nativa – Fase 1)
|
|
997
|
+
{ name: 'dependencyFields', label: 'Campos dependentes (CSV ou JSON)', editorType: 'text', group: 'Fonte Remota', hint: "Ex.: rotaId,destinoReqId" },
|
|
998
|
+
{ name: 'resetOnDependentChange', label: 'Resetar ao mudar dependentes', editorType: 'checkbox', group: 'Fonte Remota' },
|
|
999
|
+
{ name: 'enableDependencyCascade', label: 'Habilitar cascata nativa', editorType: 'checkbox', group: 'Fonte Remota', hint: 'Desative quando Connections controlarem filterCriteria' },
|
|
1000
|
+
{ name: 'dependencyFilterMap', label: 'Mapeamento de filtros (JSON)', editorType: 'textarea', group: 'Fonte Remota', hint: '{ "rotaId": "rotaId", "destinoReqId": { "key": "destinoId", "valuePath": "id" } }' },
|
|
1001
|
+
{ name: 'dependencyValuePath', label: 'Value path padrão (dep.)', editorType: 'text', group: 'Fonte Remota', hint: "Ex.: 'id' (default) ou 'code'" },
|
|
1002
|
+
{
|
|
1003
|
+
name: 'dependencyMergeStrategy',
|
|
1004
|
+
label: 'Merge de filtros (dep.)',
|
|
1005
|
+
editorType: 'select',
|
|
1006
|
+
group: 'Fonte Remota',
|
|
1007
|
+
options: [
|
|
1008
|
+
{ value: 'merge', text: 'merge (padrão)' },
|
|
1009
|
+
{ value: 'replace', text: 'replace (apenas chaves mapeadas)' },
|
|
1010
|
+
],
|
|
1011
|
+
hint: 'merge preserva chaves externas; replace substitui apenas chaves mapeadas',
|
|
1012
|
+
},
|
|
1013
|
+
{ name: 'dependencyDebounceMs', label: 'Debounce (ms) dependentes', editorType: 'number', group: 'Fonte Remota', hint: 'Padrão: 150' },
|
|
1014
|
+
{
|
|
1015
|
+
name: 'dependencyLoadOnChange',
|
|
1016
|
+
label: 'Recarregar ao mudar dependentes',
|
|
1017
|
+
editorType: 'select',
|
|
1018
|
+
group: 'Fonte Remota',
|
|
1019
|
+
options: [
|
|
1020
|
+
{ value: 'respectLoadOn', text: 'Respeitar loadOn (padrão)' },
|
|
1021
|
+
{ value: 'immediate', text: 'Imediato' },
|
|
1022
|
+
{ value: 'manual', text: 'Manual (Connections disparam)' },
|
|
1023
|
+
],
|
|
1024
|
+
},
|
|
1025
|
+
// 4) Formato/Comportamento
|
|
1026
|
+
{ name: 'selectAll', label: 'Selecionar todos', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.inline1', inline: true },
|
|
1027
|
+
{ name: 'searchable', label: 'Buscável', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.inline1', inline: true },
|
|
1028
|
+
{ name: 'maxSelections', label: 'Máximo de seleções', editorType: 'number', group: 'Formato/Comportamento' },
|
|
1029
|
+
// 5) Validação
|
|
1030
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1031
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1032
|
+
// 6) Material Design
|
|
1033
|
+
{
|
|
1034
|
+
name: 'materialDesign.appearance',
|
|
1035
|
+
label: 'Aparência',
|
|
1036
|
+
editorType: 'select',
|
|
1037
|
+
group: 'Material Design',
|
|
1038
|
+
options: [
|
|
1039
|
+
{ value: 'fill', text: 'Fill' },
|
|
1040
|
+
{ value: 'outline', text: 'Outline' },
|
|
1041
|
+
],
|
|
1042
|
+
},
|
|
1043
|
+
{
|
|
1044
|
+
name: 'materialDesign.color',
|
|
1045
|
+
label: 'Cor do tema',
|
|
1046
|
+
editorType: 'select',
|
|
1047
|
+
group: 'Material Design',
|
|
1048
|
+
options: [
|
|
1049
|
+
{ value: 'primary', text: 'Primária' },
|
|
1050
|
+
{ value: 'accent', text: 'Acento' },
|
|
1051
|
+
{ value: 'warn', text: 'Alerta' },
|
|
1052
|
+
],
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
name: 'materialDesign.floatLabel',
|
|
1056
|
+
label: 'Comportamento do label',
|
|
1057
|
+
editorType: 'select',
|
|
1058
|
+
group: 'Material Design',
|
|
1059
|
+
options: [
|
|
1060
|
+
{ value: 'auto', text: 'Auto' },
|
|
1061
|
+
{ value: 'always', text: 'Sempre' },
|
|
1062
|
+
],
|
|
1063
|
+
},
|
|
1064
|
+
{
|
|
1065
|
+
name: 'materialDesign.subscriptSizing',
|
|
1066
|
+
label: 'Subscript sizing',
|
|
1067
|
+
editorType: 'select',
|
|
1068
|
+
group: 'Material Design',
|
|
1069
|
+
options: [
|
|
1070
|
+
{ value: 'fixed', text: 'Fixo' },
|
|
1071
|
+
{ value: 'dynamic', text: 'Dinâmico' },
|
|
1072
|
+
],
|
|
1073
|
+
},
|
|
1074
|
+
{ name: 'materialDesign.hideRequiredMarker', label: 'Ocultar * obrigatório', editorType: 'checkbox', group: 'Material Design' },
|
|
1075
|
+
{
|
|
1076
|
+
name: 'errorStateMatcher',
|
|
1077
|
+
label: 'Estratégia de erro',
|
|
1078
|
+
editorType: 'select',
|
|
1079
|
+
group: 'Material Design',
|
|
1080
|
+
options: [
|
|
1081
|
+
{ value: 'default', text: 'Padrão' },
|
|
1082
|
+
{ value: 'showOnDirtyAndInvalid', text: 'Mostrar ao sujar e inválido' },
|
|
1083
|
+
{ value: 'showOnSubmitted', text: 'Mostrar ao enviar' },
|
|
1084
|
+
{ value: 'showImmediately', text: 'Mostrar imediatamente' },
|
|
1085
|
+
],
|
|
1086
|
+
},
|
|
1087
|
+
// 7) Acessibilidade
|
|
1088
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1089
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
1090
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
1091
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
1092
|
+
{ name: 'dataAttributes', label: 'Data attributes (JSON)', editorType: 'textarea', group: 'Acessibilidade', hint: '{ "testId": "select-a" }' },
|
|
1093
|
+
// 8) Ações (Clear)
|
|
1094
|
+
{ name: 'clearButton.enabled', label: 'Clear: habilitar', editorType: 'checkbox', group: 'Ações', row: 'clear.inline1', inline: true },
|
|
1095
|
+
{ name: 'clearButton.icon', label: 'Clear: ícone', editorType: 'text', group: 'Ações', row: 'clear.inline2', hint: "Material Symbols (ex.: mi:clear). Use o seletor ao lado para buscar." },
|
|
1096
|
+
{ name: 'clearButton.iconColor', label: 'Clear: cor do ícone', editorType: 'color', group: 'Ações', row: 'clear.inline2', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1097
|
+
{ name: 'clearButton.tooltip', label: 'Clear: tooltip', editorType: 'text', group: 'Ações', row: 'clear.inline2' },
|
|
1098
|
+
{ name: 'clearButton.ariaLabel', label: 'Clear: aria-label', editorType: 'text', group: 'Ações', row: 'clear.inline2' },
|
|
1099
|
+
{ name: 'clearButton.showOnlyWhenFilled', label: 'Clear: só quando preenchido', editorType: 'checkbox', group: 'Ações', row: 'clear.inline1', inline: true },
|
|
1100
|
+
];
|
|
1101
|
+
|
|
1102
|
+
const transferListProperties = [
|
|
1103
|
+
// Geral
|
|
1104
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1105
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1106
|
+
// Dados/Opções
|
|
1107
|
+
{
|
|
1108
|
+
name: 'options',
|
|
1109
|
+
label: 'Opções (estáticas)',
|
|
1110
|
+
editorType: 'textarea',
|
|
1111
|
+
group: 'Dados/Opções',
|
|
1112
|
+
hint: 'JSON: [{ "value":1, "text":"Um" }] ou linhas: valor|rótulo',
|
|
1113
|
+
},
|
|
1114
|
+
{ name: 'optionLabelKey', label: 'Chave do rótulo (remoto)', editorType: 'text', group: 'Dados/Opções' },
|
|
1115
|
+
{ name: 'optionValueKey', label: 'Chave do valor (remoto)', editorType: 'text', group: 'Dados/Opções' },
|
|
1116
|
+
// Fonte Remota
|
|
1117
|
+
{ name: 'resourcePath', label: 'Resource Path', editorType: 'text', group: 'Fonte Remota' },
|
|
1118
|
+
{ name: 'filterCriteria', label: 'Critérios de filtro (JSON)', editorType: 'textarea', group: 'Fonte Remota', hint: '{ "active": true }' },
|
|
1119
|
+
{ name: 'searchable', label: 'Buscável', editorType: 'checkbox', group: 'Fonte Remota', row: 'fonte.inline1', inline: true },
|
|
1120
|
+
// Formato/Comportamento
|
|
1121
|
+
{ name: 'maxSelections', label: 'Máximo de seleções', editorType: 'number', group: 'Formato/Comportamento' },
|
|
1122
|
+
// Validação
|
|
1123
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1124
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1125
|
+
// Acessibilidade
|
|
1126
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1127
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
1128
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
1129
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
1130
|
+
{ name: 'dataAttributes', label: 'Data attributes (JSON)', editorType: 'textarea', group: 'Acessibilidade', hint: '{ "testId": "transfer-a" }' },
|
|
1131
|
+
// Ações (Clear)
|
|
1132
|
+
{ name: 'clearButton.enabled', label: 'Clear: habilitar', editorType: 'checkbox', group: 'Ações' },
|
|
1133
|
+
{ name: 'clearButton.icon', label: 'Clear: ícone', editorType: 'text', group: 'Ações', hint: "Material Symbols (ex.: mi:clear). Use o seletor ao lado para buscar." },
|
|
1134
|
+
{ name: 'clearButton.iconColor', label: 'Clear: cor do ícone', editorType: 'color', group: 'Ações', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1135
|
+
{ name: 'clearButton.tooltip', label: 'Clear: tooltip', editorType: 'text', group: 'Ações' },
|
|
1136
|
+
{ name: 'clearButton.ariaLabel', label: 'Clear: aria-label', editorType: 'text', group: 'Ações' },
|
|
1137
|
+
{ name: 'clearButton.showOnlyWhenFilled', label: 'Clear: só quando preenchido', editorType: 'checkbox', group: 'Ações' },
|
|
1138
|
+
];
|
|
1139
|
+
|
|
1140
|
+
const radioProperties = [
|
|
1141
|
+
// Geral
|
|
1142
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1143
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1144
|
+
// Dados/Opções
|
|
1145
|
+
{
|
|
1146
|
+
name: 'providerOptions',
|
|
1147
|
+
label: 'Opções (estáticas)',
|
|
1148
|
+
editorType: 'textarea',
|
|
1149
|
+
group: 'Dados/Opções',
|
|
1150
|
+
hint: 'JSON: [{ "value":1, "text":"Um" }] ou linhas: valor|rótulo',
|
|
1151
|
+
},
|
|
1152
|
+
{ name: 'optionLabelKey', label: 'Chave do rótulo (remoto)', editorType: 'text', group: 'Dados/Opções' },
|
|
1153
|
+
{ name: 'optionValueKey', label: 'Chave do valor (remoto)', editorType: 'text', group: 'Dados/Opções' },
|
|
1154
|
+
// Fonte Remota
|
|
1155
|
+
{ name: 'resourcePath', label: 'Resource Path', editorType: 'text', group: 'Fonte Remota' },
|
|
1156
|
+
{ name: 'filterCriteria', label: 'Critérios de filtro (JSON)', editorType: 'text', group: 'Fonte Remota', hint: '{ "active": true }' },
|
|
1157
|
+
// Formato/Comportamento
|
|
1158
|
+
{ name: 'color', label: 'Cor', editorType: 'select', group: 'Material Design', options: [
|
|
1159
|
+
{ value: 'primary', text: 'Primária' },
|
|
1160
|
+
{ value: 'accent', text: 'Acento' },
|
|
1161
|
+
{ value: 'warn', text: 'Alerta' },
|
|
1162
|
+
] },
|
|
1163
|
+
{ name: 'layout', label: 'Layout', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
1164
|
+
{ value: 'horizontal', text: 'Horizontal' },
|
|
1165
|
+
{ value: 'vertical', text: 'Vertical' },
|
|
1166
|
+
] },
|
|
1167
|
+
{ name: 'labelPosition', label: 'Posição do label', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
1168
|
+
{ value: 'before', text: 'Antes' },
|
|
1169
|
+
{ value: 'after', text: 'Depois' },
|
|
1170
|
+
] },
|
|
1171
|
+
// Validação
|
|
1172
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1173
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1174
|
+
// Acessibilidade
|
|
1175
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1176
|
+
];
|
|
1177
|
+
|
|
1178
|
+
const buttonToggleProperties = [
|
|
1179
|
+
// Geral
|
|
1180
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1181
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1182
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Geral' },
|
|
1183
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Geral' },
|
|
1184
|
+
// Dados/Opções
|
|
1185
|
+
{
|
|
1186
|
+
name: 'options',
|
|
1187
|
+
label: 'Opções (estáticas)',
|
|
1188
|
+
editorType: 'textarea',
|
|
1189
|
+
group: 'Dados/Opções',
|
|
1190
|
+
hint: 'JSON: [{ "value":1, "text":"Um" }] ou linhas: valor|rótulo',
|
|
1191
|
+
},
|
|
1192
|
+
{ name: 'optionLabelKey', label: 'Chave do rótulo (remoto)', editorType: 'text', group: 'Dados/Opções' },
|
|
1193
|
+
{ name: 'optionValueKey', label: 'Chave do valor (remoto)', editorType: 'text', group: 'Dados/Opções' },
|
|
1194
|
+
// Fonte Remota
|
|
1195
|
+
{ name: 'resourcePath', label: 'Resource Path', editorType: 'text', group: 'Fonte Remota' },
|
|
1196
|
+
{ name: 'filterCriteria', label: 'Critérios de filtro (JSON)', editorType: 'textarea', group: 'Fonte Remota', hint: '{ "active": true }' },
|
|
1197
|
+
// Formato/Comportamento
|
|
1198
|
+
{ name: 'multiple', label: 'Múltipla seleção', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.inline1', inline: true },
|
|
1199
|
+
{ name: 'maxSelections', label: 'Máximo de seleções', editorType: 'number', group: 'Formato/Comportamento' },
|
|
1200
|
+
// Material Design
|
|
1201
|
+
{ name: 'appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
1202
|
+
{ value: 'legacy', text: 'Legacy' },
|
|
1203
|
+
{ value: 'standard', text: 'Standard' },
|
|
1204
|
+
] },
|
|
1205
|
+
// Validação
|
|
1206
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1207
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1208
|
+
// Acessibilidade
|
|
1209
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1210
|
+
];
|
|
1211
|
+
|
|
1212
|
+
const treeSelectProperties = [
|
|
1213
|
+
// Geral
|
|
1214
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1215
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1216
|
+
// Dados/Opções
|
|
1217
|
+
{
|
|
1218
|
+
name: 'options',
|
|
1219
|
+
label: 'Nós (estáticos)',
|
|
1220
|
+
editorType: 'textarea',
|
|
1221
|
+
group: 'Dados/Opções',
|
|
1222
|
+
hint: 'JSON: [{ "value":1, "label":"Um", children:[...] }]',
|
|
1223
|
+
},
|
|
1224
|
+
// Formato/Comportamento
|
|
1225
|
+
{ name: 'searchable', label: 'Buscável', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.inline1', inline: true },
|
|
1226
|
+
{ name: 'leafOnly', label: 'Permitir apenas folhas', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.inline1', inline: true },
|
|
1227
|
+
{ name: 'autoExpandOnSearch', label: 'Auto-expansão ao buscar', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.inline2', inline: true },
|
|
1228
|
+
{ name: 'returnPath', label: 'Retornar caminho', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.inline2', inline: true },
|
|
1229
|
+
{ name: 'returnObject', label: 'Retornar objeto', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.inline2', inline: true },
|
|
1230
|
+
// Validação
|
|
1231
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1232
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1233
|
+
// Acessibilidade
|
|
1234
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1235
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
1236
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
1237
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
1238
|
+
{ name: 'dataAttributes', label: 'Data attributes (JSON)', editorType: 'textarea', group: 'Acessibilidade', hint: '{ "testId": "tree-a" }' },
|
|
1239
|
+
// Ações (Clear)
|
|
1240
|
+
{ name: 'clearButton.enabled', label: 'Clear: habilitar', editorType: 'checkbox', group: 'Ações' },
|
|
1241
|
+
{ name: 'clearButton.icon', label: 'Clear: ícone', editorType: 'text', group: 'Ações', hint: "Material Symbols (ex.: mi:clear). Use o seletor ao lado para buscar." },
|
|
1242
|
+
{ name: 'clearButton.iconColor', label: 'Clear: cor do ícone', editorType: 'color', group: 'Ações', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1243
|
+
{ name: 'clearButton.tooltip', label: 'Clear: tooltip', editorType: 'text', group: 'Ações' },
|
|
1244
|
+
{ name: 'clearButton.ariaLabel', label: 'Clear: aria-label', editorType: 'text', group: 'Ações' },
|
|
1245
|
+
{ name: 'clearButton.showOnlyWhenFilled', label: 'Clear: só quando preenchido', editorType: 'checkbox', group: 'Ações' },
|
|
1246
|
+
];
|
|
1247
|
+
|
|
1248
|
+
// Properties for Material Textarea editor (parity with INPUT where applicable)
|
|
1249
|
+
const textareaProperties = [
|
|
1250
|
+
// Geral / Apresentação
|
|
1251
|
+
{ name: 'label', label: 'Label', editorType: 'text', placeholder: 'Rótulo do campo', group: 'Geral' },
|
|
1252
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
1253
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1254
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:edit). Use o seletor ao lado para buscar." },
|
|
1255
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1256
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
1257
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1258
|
+
{ name: 'prefix', label: 'Texto (prefixo)', editorType: 'text', group: 'Geral' },
|
|
1259
|
+
{ name: 'suffix', label: 'Texto (sufixo)', editorType: 'text', group: 'Geral' },
|
|
1260
|
+
{ name: 'defaultValue', label: 'Valor padrão', editorType: 'text', group: 'Geral' },
|
|
1261
|
+
// Validação
|
|
1262
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1263
|
+
{ name: 'minLength', label: 'Mínimo de caracteres', editorType: 'number', group: 'Validação', row: 'validacao.minmax' },
|
|
1264
|
+
{ name: 'maxLength', label: 'Máximo de caracteres', editorType: 'number', group: 'Validação', row: 'validacao.minmax' },
|
|
1265
|
+
{ name: 'pattern', label: 'Pattern (regex)', editorType: 'text', hint: 'Ex.: /^foo.*/i', group: 'Validação' },
|
|
1266
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1267
|
+
{ name: 'validators.minLengthMessage', label: 'Mensagem: mínimo', editorType: 'text', group: 'Validação' },
|
|
1268
|
+
{ name: 'validators.maxLengthMessage', label: 'Mensagem: máximo', editorType: 'text', group: 'Validação' },
|
|
1269
|
+
{ name: 'validators.patternMessage', label: 'Mensagem: padrão inválido', editorType: 'text', group: 'Validação' },
|
|
1270
|
+
// fase 2: minWords + mensagem
|
|
1271
|
+
// { name: 'validators.minWords', label: 'Mínimo de palavras', editorType: 'number', group: 'Validação', row: 'validacao.minwords' },
|
|
1272
|
+
// { name: 'validators.minWordsMessage', label: 'Mensagem: poucas palavras', editorType: 'text', group: 'Validação', row: 'validacao.minwords' },
|
|
1273
|
+
// Formato/Comportamento
|
|
1274
|
+
{
|
|
1275
|
+
name: 'textTransform',
|
|
1276
|
+
label: 'Transformação de texto',
|
|
1277
|
+
editorType: 'select',
|
|
1278
|
+
group: 'Formato/Comportamento',
|
|
1279
|
+
options: [
|
|
1280
|
+
{ value: 'none', text: 'Nenhuma' },
|
|
1281
|
+
{ value: 'uppercase', text: 'MAIÚSCULAS (CSS)' },
|
|
1282
|
+
{ value: 'lowercase', text: 'minúsculas (CSS)' },
|
|
1283
|
+
{ value: 'capitalize', text: 'Capitalizar (CSS)' },
|
|
1284
|
+
{ value: 'titleCase', text: 'Title Case' },
|
|
1285
|
+
{ value: 'sentenceCase', text: 'Sentence case' },
|
|
1286
|
+
{ value: 'kebab', text: 'kebab-case' },
|
|
1287
|
+
{ value: 'snake', text: 'snake_case' },
|
|
1288
|
+
{ value: 'camel', text: 'camelCase' },
|
|
1289
|
+
{ value: 'pascal', text: 'PascalCase' },
|
|
1290
|
+
{ value: 'slugify', text: 'slugify (a-z0-9-)' },
|
|
1291
|
+
{ value: 'trim', text: 'trim (remover bordas)' },
|
|
1292
|
+
{ value: 'collapseWhitespace', text: 'collapseWhitespace (normalizar espaços)' },
|
|
1293
|
+
{ value: 'removeDiacritics', text: 'removeDiacritics (sem acentos)' },
|
|
1294
|
+
],
|
|
1295
|
+
},
|
|
1296
|
+
{
|
|
1297
|
+
name: 'textTransformApply',
|
|
1298
|
+
label: 'Aplicar em',
|
|
1299
|
+
editorType: 'select',
|
|
1300
|
+
group: 'Formato/Comportamento',
|
|
1301
|
+
defaultValue: 'displayOnly',
|
|
1302
|
+
options: [
|
|
1303
|
+
{ value: 'displayOnly', text: 'Exibição (visual)' },
|
|
1304
|
+
{ value: 'saveOnly', text: 'Salvar (persistência)' },
|
|
1305
|
+
{ value: 'both', text: 'Ambos' },
|
|
1306
|
+
],
|
|
1307
|
+
},
|
|
1308
|
+
{ name: 'showCharacterCount', label: 'Mostrar contador de caracteres', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
1309
|
+
{ name: 'rows', label: 'Linhas (rows)', editorType: 'number', group: 'Formato/Comportamento', row: 'formato.size' },
|
|
1310
|
+
{ name: 'cols', label: 'Colunas (cols)', editorType: 'number', group: 'Formato/Comportamento', row: 'formato.size' },
|
|
1311
|
+
{
|
|
1312
|
+
name: 'wrap',
|
|
1313
|
+
label: 'Quebra de linha (wrap)',
|
|
1314
|
+
editorType: 'select',
|
|
1315
|
+
group: 'Formato/Comportamento',
|
|
1316
|
+
options: [
|
|
1317
|
+
{ value: 'soft', text: 'Soft (visual, sem \n)' },
|
|
1318
|
+
{ value: 'hard', text: 'Hard (visual + \n)' },
|
|
1319
|
+
{ value: 'off', text: 'Off (sem quebra automática)' },
|
|
1320
|
+
],
|
|
1321
|
+
},
|
|
1322
|
+
{ name: 'autoResize', label: 'Auto-resize (CDK)', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'formato.autosize', inline: true },
|
|
1323
|
+
{ name: 'minRows', label: 'Mín. linhas', editorType: 'number', group: 'Formato/Comportamento', row: 'formato.autosize', inline: true },
|
|
1324
|
+
{ name: 'maxRows', label: 'Máx. linhas', editorType: 'number', group: 'Formato/Comportamento', row: 'formato.autosize', inline: true },
|
|
1325
|
+
{ name: 'resize', label: 'Redimensionamento (CSS resize)', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
1326
|
+
{ value: 'none', text: 'Nenhum' },
|
|
1327
|
+
{ value: 'vertical', text: 'Vertical' },
|
|
1328
|
+
{ value: 'horizontal', text: 'Horizontal' },
|
|
1329
|
+
{ value: 'both', text: 'Ambos' },
|
|
1330
|
+
] },
|
|
1331
|
+
{ name: 'textAreaMode', label: 'Modo de edição', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
1332
|
+
{ value: 'plain', text: 'Texto (normal)' },
|
|
1333
|
+
{ value: 'code', text: 'Código (genérico)' },
|
|
1334
|
+
{ value: 'markdown', text: 'Markdown' },
|
|
1335
|
+
{ value: 'json', text: 'JSON' },
|
|
1336
|
+
{ value: 'xml', text: 'XML' },
|
|
1337
|
+
{ value: 'sql', text: 'SQL' },
|
|
1338
|
+
{ value: 'log', text: 'Log' },
|
|
1339
|
+
] },
|
|
1340
|
+
{ name: 'showStats', label: 'Mostrar estatísticas (palavras/linhas)', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
1341
|
+
// Formato/Comportamento
|
|
1342
|
+
{ name: 'autocomplete', label: 'Autocomplete', editorType: 'text', group: 'Formato/Comportamento' },
|
|
1343
|
+
{ name: 'spellcheck', label: 'Verificação ortográfica', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comportamento.toggles1', inline: true },
|
|
1344
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comportamento.toggles1', inline: true },
|
|
1345
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comportamento.toggles1', inline: true },
|
|
1346
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comportamento.toggles2', inline: true },
|
|
1347
|
+
{ name: 'enableTabIndent', label: 'Tab: inserir indentação', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comportamento.toggles2', inline: true },
|
|
1348
|
+
{ name: 'tabSize', label: 'Tamanho da indentação (espaços)', editorType: 'number', group: 'Formato/Comportamento', row: 'comportamento.toggles2', inline: true },
|
|
1349
|
+
{ name: 'maxLines', label: 'Máx. de linhas (bloqueia Enter)', editorType: 'number', group: 'Formato/Comportamento', row: 'comportamento.validation', inline: true },
|
|
1350
|
+
{
|
|
1351
|
+
name: 'validators.validationTrigger',
|
|
1352
|
+
label: 'Gatilho de validação',
|
|
1353
|
+
editorType: 'select',
|
|
1354
|
+
group: 'Formato/Comportamento',
|
|
1355
|
+
row: 'comportamento.validation',
|
|
1356
|
+
inline: true,
|
|
1357
|
+
options: [
|
|
1358
|
+
{ value: 'change', text: 'Ao digitar' },
|
|
1359
|
+
{ value: 'blur', text: 'Ao sair do campo' },
|
|
1360
|
+
{ value: 'submit', text: 'Ao submeter' },
|
|
1361
|
+
{ value: 'immediate', text: 'Imediato' },
|
|
1362
|
+
],
|
|
1363
|
+
},
|
|
1364
|
+
{ name: 'validators.validationDebounce', label: 'Debounce de validação (ms)', editorType: 'number', group: 'Formato/Comportamento', row: 'comportamento.validation', inline: true },
|
|
1365
|
+
{ name: 'validators.showInlineErrors', label: 'Mostrar erros inline', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
1366
|
+
{
|
|
1367
|
+
name: 'validators.errorPosition',
|
|
1368
|
+
label: 'Posição do erro',
|
|
1369
|
+
editorType: 'select',
|
|
1370
|
+
group: 'Formato/Comportamento',
|
|
1371
|
+
options: [
|
|
1372
|
+
{ value: 'bottom', text: 'Abaixo' },
|
|
1373
|
+
{ value: 'top', text: 'Acima' },
|
|
1374
|
+
{ value: 'tooltip', text: 'Tooltip' },
|
|
1375
|
+
],
|
|
1376
|
+
},
|
|
1377
|
+
// Material Design
|
|
1378
|
+
{
|
|
1379
|
+
name: 'materialDesign.appearance',
|
|
1380
|
+
label: 'Aparência',
|
|
1381
|
+
editorType: 'select',
|
|
1382
|
+
group: 'Material Design',
|
|
1383
|
+
options: [
|
|
1384
|
+
{ value: 'fill', text: 'Fill' },
|
|
1385
|
+
{ value: 'outline', text: 'Outline' },
|
|
1386
|
+
],
|
|
1387
|
+
},
|
|
1388
|
+
{
|
|
1389
|
+
name: 'materialDesign.color',
|
|
1390
|
+
label: 'Cor do tema',
|
|
1391
|
+
editorType: 'select',
|
|
1392
|
+
group: 'Material Design',
|
|
1393
|
+
options: [
|
|
1394
|
+
{ value: 'primary', text: 'Primária' },
|
|
1395
|
+
{ value: 'accent', text: 'Acento' },
|
|
1396
|
+
{ value: 'warn', text: 'Alerta' },
|
|
1397
|
+
],
|
|
1398
|
+
},
|
|
1399
|
+
{
|
|
1400
|
+
name: 'materialDesign.floatLabel',
|
|
1401
|
+
label: 'Comportamento do label',
|
|
1402
|
+
editorType: 'select',
|
|
1403
|
+
group: 'Material Design',
|
|
1404
|
+
options: [
|
|
1405
|
+
{ value: 'auto', text: 'Auto' },
|
|
1406
|
+
{ value: 'always', text: 'Sempre' },
|
|
1407
|
+
],
|
|
1408
|
+
},
|
|
1409
|
+
{
|
|
1410
|
+
name: 'materialDesign.subscriptSizing',
|
|
1411
|
+
label: 'Subscript sizing',
|
|
1412
|
+
editorType: 'select',
|
|
1413
|
+
group: 'Material Design',
|
|
1414
|
+
options: [
|
|
1415
|
+
{ value: 'fixed', text: 'Fixo' },
|
|
1416
|
+
{ value: 'dynamic', text: 'Dinâmico' },
|
|
1417
|
+
],
|
|
1418
|
+
},
|
|
1419
|
+
{ name: 'materialDesign.hideRequiredMarker', label: 'Ocultar * obrigatório', editorType: 'checkbox', group: 'Material Design' },
|
|
1420
|
+
{
|
|
1421
|
+
name: 'errorStateMatcher',
|
|
1422
|
+
label: 'Estratégia de erro',
|
|
1423
|
+
editorType: 'select',
|
|
1424
|
+
group: 'Material Design',
|
|
1425
|
+
options: [
|
|
1426
|
+
{ value: 'default', text: 'Padrão' },
|
|
1427
|
+
{ value: 'showOnDirtyAndInvalid', text: 'Mostrar ao sujar e inválido' },
|
|
1428
|
+
{ value: 'showOnSubmitted', text: 'Mostrar ao enviar' },
|
|
1429
|
+
{ value: 'showImmediately', text: 'Mostrar imediatamente' },
|
|
1430
|
+
],
|
|
1431
|
+
},
|
|
1432
|
+
// Acessibilidade
|
|
1433
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1434
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
1435
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
1436
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
1437
|
+
{ name: 'dataAttributes', label: 'Data attributes (JSON)', editorType: 'textarea', hint: '{ "testId": "textarea-a" }', group: 'Acessibilidade' },
|
|
1438
|
+
// Ações (clear)
|
|
1439
|
+
{ name: 'clearButton.enabled', label: 'Clear: habilitar', editorType: 'checkbox', group: 'Ações' },
|
|
1440
|
+
{ name: 'clearButton.iconColor', label: 'Clear: cor do ícone', editorType: 'color', group: 'Ações', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1441
|
+
{ name: 'clearButton.icon', label: 'Clear: ícone', editorType: 'text', group: 'Ações', hint: "Material Symbols (ex.: mi:clear). Use o seletor ao lado para buscar." },
|
|
1442
|
+
{ name: 'clearButton.tooltip', label: 'Clear: tooltip', editorType: 'text', group: 'Ações' },
|
|
1443
|
+
{ name: 'clearButton.ariaLabel', label: 'Clear: aria-label', editorType: 'text', group: 'Ações' },
|
|
1444
|
+
{ name: 'clearButton.showOnlyWhenFilled', label: 'Clear: só quando preenchido', editorType: 'checkbox', group: 'Ações' },
|
|
1445
|
+
];
|
|
1446
|
+
|
|
1447
|
+
// Editor de metadados para NUMBER (numericTextBox)
|
|
1448
|
+
// Paridade com INPUT, cobrindo grupos e propriedades canônicas
|
|
1449
|
+
const numberProperties = [
|
|
1450
|
+
// 1) Geral
|
|
1451
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1452
|
+
{ name: 'defaultValue', label: 'Valor padrão', editorType: 'number', group: 'Geral' },
|
|
1453
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
1454
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1455
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: 'Material Symbols (ex.: mi:...). Use o seletor ao lado para buscar.' },
|
|
1456
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1457
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: 'Material Symbols (ex.: mi:...). Use o seletor ao lado para buscar.' },
|
|
1458
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1459
|
+
{ name: 'prefix', label: 'Texto (prefixo)', editorType: 'text', group: 'Geral' },
|
|
1460
|
+
{ name: 'suffix', label: 'Texto (sufixo)', editorType: 'text', group: 'Geral' },
|
|
1461
|
+
// 2) Validação
|
|
1462
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1463
|
+
{ name: 'min', label: 'Mínimo', editorType: 'number', group: 'Validação', row: 'validacao.minmax', inline: true },
|
|
1464
|
+
{ name: 'max', label: 'Máximo', editorType: 'number', group: 'Validação', row: 'validacao.minmax', inline: true },
|
|
1465
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1466
|
+
{ name: 'validators.minMessage', label: 'Mensagem: mínimo', editorType: 'text', group: 'Validação' },
|
|
1467
|
+
{ name: 'validators.maxMessage', label: 'Mensagem: máximo', editorType: 'text', group: 'Validação' },
|
|
1468
|
+
// 3) Formato/Comportamento
|
|
1469
|
+
{ name: 'step', label: 'Step (incremento)', editorType: 'number', group: 'Formato/Comportamento' },
|
|
1470
|
+
{ name: 'numberFormat.decimalPlaces', label: 'Casas decimais', editorType: 'number', group: 'Formato/Comportamento', row: 'formato.decimais', inline: true },
|
|
1471
|
+
{ name: 'showGrouping', label: 'Agrupar milhares', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'formato.decimais', inline: true, hint: 'Fase 1: aplica apenas formatação visual básica' },
|
|
1472
|
+
{
|
|
1473
|
+
name: 'inputMode',
|
|
1474
|
+
label: 'Modo de entrada',
|
|
1475
|
+
editorType: 'select',
|
|
1476
|
+
group: 'Formato/Comportamento',
|
|
1477
|
+
options: [
|
|
1478
|
+
{ value: 'numeric', text: 'Numérico' },
|
|
1479
|
+
{ value: 'decimal', text: 'Decimal' },
|
|
1480
|
+
],
|
|
1481
|
+
},
|
|
1482
|
+
// 4) Formato/Comportamento
|
|
1483
|
+
{ name: 'autocomplete', label: 'Autocomplete', editorType: 'text', group: 'Formato/Comportamento' },
|
|
1484
|
+
{ name: 'spellcheck', label: 'Verificação ortográfica', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.toggles1', inline: true },
|
|
1485
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.toggles1', inline: true },
|
|
1486
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.toggles1', inline: true },
|
|
1487
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.toggles2', inline: true },
|
|
1488
|
+
{
|
|
1489
|
+
name: 'validators.validationTrigger',
|
|
1490
|
+
label: 'Gatilho de validação',
|
|
1491
|
+
editorType: 'select',
|
|
1492
|
+
group: 'Formato/Comportamento',
|
|
1493
|
+
row: 'comp.validation',
|
|
1494
|
+
inline: true,
|
|
1495
|
+
options: [
|
|
1496
|
+
{ value: 'change', text: 'Ao digitar' },
|
|
1497
|
+
{ value: 'blur', text: 'Ao sair do campo' },
|
|
1498
|
+
{ value: 'submit', text: 'Ao submeter' },
|
|
1499
|
+
{ value: 'immediate', text: 'Imediato' },
|
|
1500
|
+
],
|
|
1501
|
+
},
|
|
1502
|
+
{ name: 'validators.validationDebounce', label: 'Debounce (ms)', editorType: 'number', group: 'Formato/Comportamento', row: 'comp.validation', inline: true },
|
|
1503
|
+
{ name: 'validators.showInlineErrors', label: 'Mostrar erros inline', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
1504
|
+
{
|
|
1505
|
+
name: 'validators.errorPosition',
|
|
1506
|
+
label: 'Posição do erro',
|
|
1507
|
+
editorType: 'select',
|
|
1508
|
+
group: 'Formato/Comportamento',
|
|
1509
|
+
options: [
|
|
1510
|
+
{ value: 'bottom', text: 'Abaixo' },
|
|
1511
|
+
{ value: 'top', text: 'Acima' },
|
|
1512
|
+
{ value: 'tooltip', text: 'Tooltip' },
|
|
1513
|
+
],
|
|
1514
|
+
},
|
|
1515
|
+
// 5) Material Design
|
|
1516
|
+
{
|
|
1517
|
+
name: 'materialDesign.appearance',
|
|
1518
|
+
label: 'Aparência',
|
|
1519
|
+
editorType: 'select',
|
|
1520
|
+
group: 'Material Design',
|
|
1521
|
+
options: [
|
|
1522
|
+
{ value: 'fill', text: 'Fill' },
|
|
1523
|
+
{ value: 'outline', text: 'Outline' },
|
|
1524
|
+
],
|
|
1525
|
+
},
|
|
1526
|
+
{
|
|
1527
|
+
name: 'materialDesign.color',
|
|
1528
|
+
label: 'Cor do tema',
|
|
1529
|
+
editorType: 'select',
|
|
1530
|
+
group: 'Material Design',
|
|
1531
|
+
options: [
|
|
1532
|
+
{ value: 'primary', text: 'Primária' },
|
|
1533
|
+
{ value: 'accent', text: 'Acento' },
|
|
1534
|
+
{ value: 'warn', text: 'Alerta' },
|
|
1535
|
+
],
|
|
1536
|
+
},
|
|
1537
|
+
{
|
|
1538
|
+
name: 'materialDesign.floatLabel',
|
|
1539
|
+
label: 'Comportamento do label',
|
|
1540
|
+
editorType: 'select',
|
|
1541
|
+
group: 'Material Design',
|
|
1542
|
+
options: [
|
|
1543
|
+
{ value: 'auto', text: 'Auto' },
|
|
1544
|
+
{ value: 'always', text: 'Sempre' },
|
|
1545
|
+
],
|
|
1546
|
+
},
|
|
1547
|
+
{
|
|
1548
|
+
name: 'materialDesign.subscriptSizing',
|
|
1549
|
+
label: 'Subscript sizing',
|
|
1550
|
+
editorType: 'select',
|
|
1551
|
+
group: 'Material Design',
|
|
1552
|
+
options: [
|
|
1553
|
+
{ value: 'fixed', text: 'Fixo' },
|
|
1554
|
+
{ value: 'dynamic', text: 'Dinâmico' },
|
|
1555
|
+
],
|
|
1556
|
+
},
|
|
1557
|
+
{ name: 'materialDesign.hideRequiredMarker', label: 'Ocultar * obrigatório', editorType: 'checkbox', group: 'Material Design' },
|
|
1558
|
+
{
|
|
1559
|
+
name: 'errorStateMatcher',
|
|
1560
|
+
label: 'Estratégia de erro',
|
|
1561
|
+
editorType: 'select',
|
|
1562
|
+
group: 'Material Design',
|
|
1563
|
+
options: [
|
|
1564
|
+
{ value: 'default', text: 'Padrão' },
|
|
1565
|
+
{ value: 'showOnDirtyAndInvalid', text: 'Mostrar ao sujar e inválido' },
|
|
1566
|
+
{ value: 'showOnSubmitted', text: 'Mostrar ao enviar' },
|
|
1567
|
+
{ value: 'showImmediately', text: 'Mostrar imediatamente' },
|
|
1568
|
+
],
|
|
1569
|
+
},
|
|
1570
|
+
// 6) Acessibilidade
|
|
1571
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1572
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
1573
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
1574
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
1575
|
+
{ name: 'dataAttributes', label: 'Data attributes (JSON)', editorType: 'textarea', group: 'Acessibilidade', hint: '{ "testId": "number-a" }' },
|
|
1576
|
+
// 7) Ações (Clear)
|
|
1577
|
+
{ name: 'clearButton.enabled', label: 'Clear: habilitar', editorType: 'checkbox', group: 'Ações', row: 'acoes.inline1', inline: true },
|
|
1578
|
+
{ name: 'clearButton.icon', label: 'Clear: ícone', editorType: 'text', group: 'Ações', row: 'acoes.inline2', hint: 'Material Symbols (ex.: mi:clear). Use o seletor ao lado para buscar.' },
|
|
1579
|
+
{ name: 'clearButton.iconColor', label: 'Clear: cor do ícone', editorType: 'color', group: 'Ações', row: 'acoes.inline2', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1580
|
+
{ name: 'clearButton.tooltip', label: 'Clear: tooltip', editorType: 'text', group: 'Ações', row: 'acoes.inline2' },
|
|
1581
|
+
{ name: 'clearButton.ariaLabel', label: 'Clear: aria-label', editorType: 'text', group: 'Ações', row: 'acoes.inline2' },
|
|
1582
|
+
{ name: 'clearButton.showOnlyWhenFilled', label: 'Clear: só quando preenchido', editorType: 'checkbox', group: 'Ações', row: 'acoes.inline1', inline: true },
|
|
1583
|
+
];
|
|
1584
|
+
|
|
1585
|
+
const dateProperties = [
|
|
1586
|
+
// Geral
|
|
1587
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1588
|
+
{ name: 'defaultValue', label: 'Valor padrão', editorType: 'date', group: 'Geral', hint: 'Data (YYYY-MM-DD)' },
|
|
1589
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
1590
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1591
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:calendar_today). Use o seletor ao lado para buscar." },
|
|
1592
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1593
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
1594
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1595
|
+
{ name: 'prefix', label: 'Texto (prefixo)', editorType: 'text', group: 'Geral' },
|
|
1596
|
+
{ name: 'suffix', label: 'Texto (sufixo)', editorType: 'text', group: 'Geral' },
|
|
1597
|
+
// Validação
|
|
1598
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1599
|
+
{ name: 'minDate', label: 'Mínima', editorType: 'date', group: 'Validação', row: 'val.minmax' },
|
|
1600
|
+
{ name: 'maxDate', label: 'Máxima', editorType: 'date', group: 'Validação', row: 'val.minmax' },
|
|
1601
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1602
|
+
{ name: 'validators.minMessage', label: 'Mensagem: data mínima', editorType: 'text', group: 'Validação' },
|
|
1603
|
+
{ name: 'validators.maxMessage', label: 'Mensagem: data máxima', editorType: 'text', group: 'Validação' },
|
|
1604
|
+
// Formato/Comportamento
|
|
1605
|
+
{ name: 'startView', label: 'Visão inicial', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
1606
|
+
{ value: 'month', text: 'Mês' },
|
|
1607
|
+
{ value: 'year', text: 'Ano' },
|
|
1608
|
+
{ value: 'multi-year', text: 'Décadas' },
|
|
1609
|
+
] },
|
|
1610
|
+
{ name: 'startAt', label: 'Abrir em', editorType: 'date', group: 'Formato/Comportamento' },
|
|
1611
|
+
{ name: 'touchUi', label: 'Touch UI', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1612
|
+
{ name: 'closeOnSelect', label: 'Fechar ao selecionar', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1613
|
+
// Material Design
|
|
1614
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
1615
|
+
{ value: 'fill', text: 'Fill' },
|
|
1616
|
+
{ value: 'outline', text: 'Outline' },
|
|
1617
|
+
] },
|
|
1618
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
1619
|
+
{ value: 'primary', text: 'Primária' },
|
|
1620
|
+
{ value: 'accent', text: 'Acento' },
|
|
1621
|
+
{ value: 'warn', text: 'Alerta' },
|
|
1622
|
+
] },
|
|
1623
|
+
{ name: 'materialDesign.floatLabel', label: 'Comportamento do label', editorType: 'select', group: 'Material Design', options: [
|
|
1624
|
+
{ value: 'auto', text: 'Auto' },
|
|
1625
|
+
{ value: 'always', text: 'Sempre' },
|
|
1626
|
+
] },
|
|
1627
|
+
{ name: 'materialDesign.subscriptSizing', label: 'Subscript sizing', editorType: 'select', group: 'Material Design', options: [
|
|
1628
|
+
{ value: 'fixed', text: 'Fixo' },
|
|
1629
|
+
{ value: 'dynamic', text: 'Dinâmico' },
|
|
1630
|
+
] },
|
|
1631
|
+
{ name: 'materialDesign.hideRequiredMarker', label: 'Ocultar * obrigatório', editorType: 'checkbox', group: 'Material Design' },
|
|
1632
|
+
{ name: 'errorStateMatcher', label: 'Estratégia de erro', editorType: 'select', group: 'Material Design', options: [
|
|
1633
|
+
{ value: 'default', text: 'Padrão' },
|
|
1634
|
+
{ value: 'showOnDirtyAndInvalid', text: 'Mostrar ao sujar e inválido' },
|
|
1635
|
+
{ value: 'showOnSubmitted', text: 'Mostrar ao enviar' },
|
|
1636
|
+
{ value: 'showImmediately', text: 'Mostrar imediatamente' },
|
|
1637
|
+
] },
|
|
1638
|
+
// Acessibilidade
|
|
1639
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1640
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
1641
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
1642
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
1643
|
+
{ name: 'dataAttributes', label: 'Data attributes (JSON)', editorType: 'textarea', group: 'Acessibilidade' },
|
|
1644
|
+
// Ações
|
|
1645
|
+
{ name: 'clearButton.enabled', label: 'Clear: habilitar', editorType: 'checkbox', group: 'Ações', row: 'clear.inline1', inline: true },
|
|
1646
|
+
{ name: 'clearButton.icon', label: 'Clear: ícone', editorType: 'text', group: 'Ações', row: 'clear.inline2', hint: "Material Symbols (ex.: mi:clear). Use o seletor ao lado para buscar." },
|
|
1647
|
+
{ name: 'clearButton.iconColor', label: 'Clear: cor do ícone', editorType: 'color', group: 'Ações', row: 'clear.inline2', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1648
|
+
{ name: 'clearButton.tooltip', label: 'Clear: tooltip', editorType: 'text', group: 'Ações', row: 'clear.inline2' },
|
|
1649
|
+
{ name: 'clearButton.ariaLabel', label: 'Clear: aria-label', editorType: 'text', group: 'Ações', row: 'clear.inline2' },
|
|
1650
|
+
{ name: 'clearButton.showOnlyWhenFilled', label: 'Clear: só quando preenchido', editorType: 'checkbox', group: 'Ações', row: 'clear.inline1', inline: true },
|
|
1651
|
+
];
|
|
1652
|
+
|
|
1653
|
+
const dateRangeProperties = [
|
|
1654
|
+
// Geral
|
|
1655
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1656
|
+
{ name: 'defaultValue.startDate', label: 'Valor padrão (início)', editorType: 'date', group: 'Geral' },
|
|
1657
|
+
{ name: 'defaultValue.endDate', label: 'Valor padrão (fim)', editorType: 'date', group: 'Geral' },
|
|
1658
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1659
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:date_range). Use o seletor ao lado para buscar." },
|
|
1660
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1661
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
1662
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1663
|
+
// Placeholders específicos
|
|
1664
|
+
{ name: 'startPlaceholder', label: 'Placeholder (início)', editorType: 'text', group: 'Geral' },
|
|
1665
|
+
{ name: 'endPlaceholder', label: 'Placeholder (fim)', editorType: 'text', group: 'Geral' },
|
|
1666
|
+
// Validação
|
|
1667
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1668
|
+
{ name: 'minDate', label: 'Mínima', editorType: 'date', group: 'Validação', row: 'val.minmax' },
|
|
1669
|
+
{ name: 'maxDate', label: 'Máxima', editorType: 'date', group: 'Validação', row: 'val.minmax' },
|
|
1670
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1671
|
+
// Formato/Comportamento
|
|
1672
|
+
{ name: 'startView', label: 'Visão inicial', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
1673
|
+
{ value: 'month', text: 'Mês' },
|
|
1674
|
+
{ value: 'year', text: 'Ano' },
|
|
1675
|
+
{ value: 'multi-year', text: 'Décadas' },
|
|
1676
|
+
] },
|
|
1677
|
+
{ name: 'startAt', label: 'Abrir em', editorType: 'date', group: 'Formato/Comportamento' },
|
|
1678
|
+
{ name: 'touchUi', label: 'Touch UI', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1679
|
+
// Material Design
|
|
1680
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
1681
|
+
{ value: 'fill', text: 'Fill' },
|
|
1682
|
+
{ value: 'outline', text: 'Outline' },
|
|
1683
|
+
] },
|
|
1684
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
1685
|
+
{ value: 'primary', text: 'Primária' },
|
|
1686
|
+
{ value: 'accent', text: 'Acento' },
|
|
1687
|
+
{ value: 'warn', text: 'Alerta' },
|
|
1688
|
+
] },
|
|
1689
|
+
{ name: 'materialDesign.floatLabel', label: 'Comportamento do label', editorType: 'select', group: 'Material Design', options: [
|
|
1690
|
+
{ value: 'auto', text: 'Auto' },
|
|
1691
|
+
{ value: 'always', text: 'Sempre' },
|
|
1692
|
+
] },
|
|
1693
|
+
{ name: 'materialDesign.subscriptSizing', label: 'Subscript sizing', editorType: 'select', group: 'Material Design', options: [
|
|
1694
|
+
{ value: 'fixed', text: 'Fixo' },
|
|
1695
|
+
{ value: 'dynamic', text: 'Dinâmico' },
|
|
1696
|
+
] },
|
|
1697
|
+
{ name: 'materialDesign.hideRequiredMarker', label: 'Ocultar * obrigatório', editorType: 'checkbox', group: 'Material Design' },
|
|
1698
|
+
{ name: 'errorStateMatcher', label: 'Estratégia de erro', editorType: 'select', group: 'Material Design', options: [
|
|
1699
|
+
{ value: 'default', text: 'Padrão' },
|
|
1700
|
+
{ value: 'showOnDirtyAndInvalid', text: 'Mostrar ao sujar e inválido' },
|
|
1701
|
+
{ value: 'showOnSubmitted', text: 'Mostrar ao enviar' },
|
|
1702
|
+
{ value: 'showImmediately', text: 'Mostrar imediatamente' },
|
|
1703
|
+
] },
|
|
1704
|
+
// Acessibilidade
|
|
1705
|
+
{ name: 'startAriaLabel', label: 'ARIA (início)', editorType: 'text', group: 'Acessibilidade' },
|
|
1706
|
+
{ name: 'endAriaLabel', label: 'ARIA (fim)', editorType: 'text', group: 'Acessibilidade' },
|
|
1707
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
1708
|
+
{ name: 'dataAttributes', label: 'Data attributes (JSON)', editorType: 'textarea', group: 'Acessibilidade' },
|
|
1709
|
+
];
|
|
1710
|
+
|
|
1711
|
+
const datetimeLocalProperties = [
|
|
1712
|
+
// Geral
|
|
1713
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1714
|
+
{ name: 'defaultValue', label: 'Valor padrão (YYYY-MM-DDTHH:mm)', editorType: 'text', group: 'Geral' },
|
|
1715
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
1716
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1717
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:schedule). Use o seletor ao lado para buscar." },
|
|
1718
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1719
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
1720
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1721
|
+
// Validação
|
|
1722
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1723
|
+
{ name: 'min', label: 'Mínimo (YYYY-MM-DDTHH:mm)', editorType: 'text', group: 'Validação', row: 'val.minmax' },
|
|
1724
|
+
{ name: 'max', label: 'Máximo (YYYY-MM-DDTHH:mm)', editorType: 'text', group: 'Validação', row: 'val.minmax' },
|
|
1725
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1726
|
+
{ name: 'validators.minMessage', label: 'Mensagem: mínimo', editorType: 'text', group: 'Validação' },
|
|
1727
|
+
{ name: 'validators.maxMessage', label: 'Mensagem: máximo', editorType: 'text', group: 'Validação' },
|
|
1728
|
+
// Formato/Comportamento
|
|
1729
|
+
{ name: 'step', label: 'Step (segundos)', editorType: 'number', group: 'Formato/Comportamento' },
|
|
1730
|
+
{ name: 'inputMode', label: 'Modo de entrada (mobile)', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
1731
|
+
{ value: 'text', text: 'Texto' },
|
|
1732
|
+
{ value: 'numeric', text: 'Numérico' },
|
|
1733
|
+
{ value: 'decimal', text: 'Decimal' },
|
|
1734
|
+
{ value: 'tel', text: 'Telefone' },
|
|
1735
|
+
{ value: 'email', text: 'Email' },
|
|
1736
|
+
{ value: 'url', text: 'URL' },
|
|
1737
|
+
{ value: 'search', text: 'Busca' },
|
|
1738
|
+
] },
|
|
1739
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1740
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1741
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1742
|
+
{ name: 'autocomplete', label: 'Autocomplete', editorType: 'text', group: 'Formato/Comportamento' },
|
|
1743
|
+
// Material Design
|
|
1744
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
1745
|
+
{ value: 'fill', text: 'Fill' },
|
|
1746
|
+
{ value: 'outline', text: 'Outline' },
|
|
1747
|
+
] },
|
|
1748
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
1749
|
+
{ value: 'primary', text: 'Primária' },
|
|
1750
|
+
{ value: 'accent', text: 'Acento' },
|
|
1751
|
+
{ value: 'warn', text: 'Alerta' },
|
|
1752
|
+
] },
|
|
1753
|
+
{ name: 'materialDesign.floatLabel', label: 'Comportamento do label', editorType: 'select', group: 'Material Design', options: [
|
|
1754
|
+
{ value: 'auto', text: 'Auto' },
|
|
1755
|
+
{ value: 'always', text: 'Sempre' },
|
|
1756
|
+
] },
|
|
1757
|
+
{ name: 'materialDesign.subscriptSizing', label: 'Subscript sizing', editorType: 'select', group: 'Material Design', options: [
|
|
1758
|
+
{ value: 'fixed', text: 'Fixo' },
|
|
1759
|
+
{ value: 'dynamic', text: 'Dinâmico' },
|
|
1760
|
+
] },
|
|
1761
|
+
{ name: 'materialDesign.hideRequiredMarker', label: 'Ocultar * obrigatório', editorType: 'checkbox', group: 'Material Design' },
|
|
1762
|
+
{ name: 'errorStateMatcher', label: 'Estratégia de erro', editorType: 'select', group: 'Material Design', options: [
|
|
1763
|
+
{ value: 'default', text: 'Padrão' },
|
|
1764
|
+
{ value: 'showOnDirtyAndInvalid', text: 'Mostrar ao sujar e inválido' },
|
|
1765
|
+
{ value: 'showOnSubmitted', text: 'Mostrar ao enviar' },
|
|
1766
|
+
{ value: 'showImmediately', text: 'Mostrar imediatamente' },
|
|
1767
|
+
] },
|
|
1768
|
+
// Acessibilidade
|
|
1769
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1770
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
1771
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
1772
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
1773
|
+
{ name: 'dataAttributes', label: 'Data attributes (JSON)', editorType: 'textarea', group: 'Acessibilidade' },
|
|
1774
|
+
// Ações: Não expõe Clear (componente não implementa botão de limpar)
|
|
1775
|
+
];
|
|
1776
|
+
|
|
1777
|
+
// Native <input type="date"> editor properties
|
|
1778
|
+
const dateInputProperties = [
|
|
1779
|
+
// Geral
|
|
1780
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1781
|
+
{ name: 'defaultValue', label: 'Valor padrão (YYYY-MM-DD)', editorType: 'date', group: 'Geral' },
|
|
1782
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
1783
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1784
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:event). Use o seletor ao lado para buscar." },
|
|
1785
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1786
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
1787
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1788
|
+
{ name: 'prefix', label: 'Texto (prefixo)', editorType: 'text', group: 'Geral' },
|
|
1789
|
+
{ name: 'suffix', label: 'Texto (sufixo)', editorType: 'text', group: 'Geral' },
|
|
1790
|
+
// Validação
|
|
1791
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1792
|
+
{ name: 'min', label: 'Mínima (YYYY-MM-DD)', editorType: 'date', group: 'Validação', row: 'val.minmax' },
|
|
1793
|
+
{ name: 'max', label: 'Máxima (YYYY-MM-DD)', editorType: 'date', group: 'Validação', row: 'val.minmax' },
|
|
1794
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1795
|
+
// Formato/Comportamento
|
|
1796
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1797
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1798
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1799
|
+
{ name: 'autocomplete', label: 'Autocomplete', editorType: 'text', group: 'Formato/Comportamento' },
|
|
1800
|
+
// Material Design
|
|
1801
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
1802
|
+
{ value: 'fill', text: 'Fill' },
|
|
1803
|
+
{ value: 'outline', text: 'Outline' },
|
|
1804
|
+
] },
|
|
1805
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
1806
|
+
{ value: 'primary', text: 'Primária' },
|
|
1807
|
+
{ value: 'accent', text: 'Acento' },
|
|
1808
|
+
{ value: 'warn', text: 'Alerta' },
|
|
1809
|
+
] },
|
|
1810
|
+
{ name: 'materialDesign.floatLabel', label: 'Comportamento do label', editorType: 'select', group: 'Material Design', options: [
|
|
1811
|
+
{ value: 'auto', text: 'Auto' },
|
|
1812
|
+
{ value: 'always', text: 'Sempre' },
|
|
1813
|
+
] },
|
|
1814
|
+
{ name: 'materialDesign.subscriptSizing', label: 'Subscript sizing', editorType: 'select', group: 'Material Design', options: [
|
|
1815
|
+
{ value: 'fixed', text: 'Fixo' },
|
|
1816
|
+
{ value: 'dynamic', text: 'Dinâmico' },
|
|
1817
|
+
] },
|
|
1818
|
+
{ name: 'materialDesign.hideRequiredMarker', label: 'Ocultar * obrigatório', editorType: 'checkbox', group: 'Material Design' },
|
|
1819
|
+
{ name: 'errorStateMatcher', label: 'Estratégia de erro', editorType: 'select', group: 'Material Design', options: [
|
|
1820
|
+
{ value: 'default', text: 'Padrão' },
|
|
1821
|
+
{ value: 'showOnDirtyAndInvalid', text: 'Mostrar ao sujar e inválido' },
|
|
1822
|
+
{ value: 'showOnSubmitted', text: 'Mostrar ao enviar' },
|
|
1823
|
+
{ value: 'showImmediately', text: 'Mostrar imediatamente' },
|
|
1824
|
+
] },
|
|
1825
|
+
// Acessibilidade
|
|
1826
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1827
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
1828
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
1829
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
1830
|
+
{ name: 'dataAttributes', label: 'Data attributes (JSON)', editorType: 'textarea', group: 'Acessibilidade' },
|
|
1831
|
+
// Ações: Não expõe Clear (componente não implementa botão de limpar)
|
|
1832
|
+
];
|
|
1833
|
+
|
|
1834
|
+
const timeInputProperties = [
|
|
1835
|
+
// Geral
|
|
1836
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1837
|
+
{ name: 'defaultValue', label: 'Valor padrão (HH:mm)', editorType: 'text', group: 'Geral', hint: 'Ex.: 08:30' },
|
|
1838
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
1839
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1840
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:schedule). Use o seletor ao lado para buscar." },
|
|
1841
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1842
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
1843
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1844
|
+
{ name: 'prefix', label: 'Texto (prefixo)', editorType: 'text', group: 'Geral' },
|
|
1845
|
+
{ name: 'suffix', label: 'Texto (sufixo)', editorType: 'text', group: 'Geral' },
|
|
1846
|
+
// Validação
|
|
1847
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1848
|
+
{ name: 'min', label: 'Mínimo (HH:mm)', editorType: 'text', group: 'Validação', row: 'val.minmax' },
|
|
1849
|
+
{ name: 'max', label: 'Máximo (HH:mm)', editorType: 'text', group: 'Validação', row: 'val.minmax' },
|
|
1850
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1851
|
+
// Formato/Comportamento
|
|
1852
|
+
{ name: 'step', label: 'Step (segundos)', editorType: 'number', group: 'Formato/Comportamento' },
|
|
1853
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1854
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1855
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1856
|
+
{ name: 'autocomplete', label: 'Autocomplete', editorType: 'text', group: 'Formato/Comportamento' },
|
|
1857
|
+
{ name: 'inputMode', label: 'Modo de entrada', editorType: 'text', group: 'Formato/Comportamento' },
|
|
1858
|
+
// Material Design
|
|
1859
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
1860
|
+
{ value: 'fill', text: 'Fill' },
|
|
1861
|
+
{ value: 'outline', text: 'Outline' },
|
|
1862
|
+
] },
|
|
1863
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
1864
|
+
{ value: 'primary', text: 'Primária' },
|
|
1865
|
+
{ value: 'accent', text: 'Acento' },
|
|
1866
|
+
{ value: 'warn', text: 'Alerta' },
|
|
1867
|
+
] },
|
|
1868
|
+
{ name: 'materialDesign.floatLabel', label: 'Comportamento do label', editorType: 'select', group: 'Material Design', options: [
|
|
1869
|
+
{ value: 'auto', text: 'Auto' },
|
|
1870
|
+
{ value: 'always', text: 'Sempre' },
|
|
1871
|
+
] },
|
|
1872
|
+
{ name: 'materialDesign.subscriptSizing', label: 'Subscript sizing', editorType: 'select', group: 'Material Design', options: [
|
|
1873
|
+
{ value: 'fixed', text: 'Fixo' },
|
|
1874
|
+
{ value: 'dynamic', text: 'Dinâmico' },
|
|
1875
|
+
] },
|
|
1876
|
+
{ name: 'materialDesign.hideRequiredMarker', label: 'Ocultar * obrigatório', editorType: 'checkbox', group: 'Material Design' },
|
|
1877
|
+
{ name: 'errorStateMatcher', label: 'Estratégia de erro', editorType: 'select', group: 'Material Design', options: [
|
|
1878
|
+
{ value: 'default', text: 'Padrão' },
|
|
1879
|
+
{ value: 'showOnDirtyAndInvalid', text: 'Mostrar ao sujar e inválido' },
|
|
1880
|
+
{ value: 'showOnSubmitted', text: 'Mostrar ao enviar' },
|
|
1881
|
+
{ value: 'showImmediately', text: 'Mostrar imediatamente' },
|
|
1882
|
+
] },
|
|
1883
|
+
// Acessibilidade
|
|
1884
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1885
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
1886
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
1887
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
1888
|
+
{ name: 'dataAttributes', label: 'Data attributes (JSON)', editorType: 'textarea', group: 'Acessibilidade' },
|
|
1889
|
+
];
|
|
1890
|
+
|
|
1891
|
+
const timePickerProperties = [
|
|
1892
|
+
// Geral
|
|
1893
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1894
|
+
{ name: 'defaultValue', label: 'Valor padrão (exibição)', editorType: 'text', group: 'Geral' },
|
|
1895
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1896
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: 'Material Symbols (ex.: mi:...). Use o seletor ao lado para buscar.' },
|
|
1897
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1898
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: 'Material Symbols (ex.: mi:...). Use o seletor ao lado para buscar.' },
|
|
1899
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1900
|
+
// Validação
|
|
1901
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1902
|
+
{ name: 'min', label: 'Mínimo (HH:mm[:ss])', editorType: 'text', group: 'Validação', row: 'val.minmax' },
|
|
1903
|
+
{ name: 'max', label: 'Máximo (HH:mm[:ss])', editorType: 'text', group: 'Validação', row: 'val.minmax' },
|
|
1904
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1905
|
+
// Comportamento
|
|
1906
|
+
{ name: 'interval', label: 'Intervalo (segundos ou 30m)', editorType: 'text', group: 'Formato/Comportamento' },
|
|
1907
|
+
{ name: 'timeOptions', label: 'Opções (uma por linha)', editorType: 'textarea', group: 'Formato/Comportamento' },
|
|
1908
|
+
{ name: 'openOnClick', label: 'Abrir ao clicar', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1909
|
+
{ name: 'touchUi', label: 'Touch UI', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.inline1', inline: true },
|
|
1910
|
+
{ name: 'format', label: 'Formato', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
1911
|
+
{ value: '24h', text: '24 horas' },
|
|
1912
|
+
{ value: '12h', text: '12 horas' },
|
|
1913
|
+
] },
|
|
1914
|
+
{ name: 'showSeconds', label: 'Exibir segundos', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
1915
|
+
{ name: 'stepMinute', label: 'Passo (min)', editorType: 'number', group: 'Formato/Comportamento', row: 'fmt.steps', inline: true },
|
|
1916
|
+
{ name: 'stepSecond', label: 'Passo (seg)', editorType: 'number', group: 'Formato/Comportamento', row: 'fmt.steps', inline: true },
|
|
1917
|
+
{ name: 'timeFilter', label: 'Filtro (id função)', editorType: 'text', group: 'Formato/Comportamento' },
|
|
1918
|
+
// Material/A11y/Ações básicas
|
|
1919
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
1920
|
+
{ value: 'fill', text: 'Fill' },
|
|
1921
|
+
{ value: 'outline', text: 'Outline' },
|
|
1922
|
+
] },
|
|
1923
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
1924
|
+
{ value: 'primary', text: 'Primária' },
|
|
1925
|
+
{ value: 'accent', text: 'Acento' },
|
|
1926
|
+
{ value: 'warn', text: 'Alerta' },
|
|
1927
|
+
] },
|
|
1928
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1929
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
1930
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
1931
|
+
];
|
|
1932
|
+
|
|
1933
|
+
const timeRangeProperties = [
|
|
1934
|
+
// Geral (defaultValue como objeto start/end)
|
|
1935
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1936
|
+
{ name: 'defaultValue.start', label: 'Início (HH:mm)', editorType: 'text', group: 'Geral', row: 'geral.range', inline: true },
|
|
1937
|
+
{ name: 'defaultValue.end', label: 'Fim (HH:mm)', editorType: 'text', group: 'Geral', row: 'geral.range', inline: true },
|
|
1938
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1939
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: 'Material Symbols (ex.: mi:...). Use o seletor ao lado para buscar.' },
|
|
1940
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1941
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: 'Material Symbols (ex.: mi:...). Use o seletor ao lado para buscar.' },
|
|
1942
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1943
|
+
// Validação
|
|
1944
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1945
|
+
{ name: 'min', label: 'Min (HH:mm)', editorType: 'text', group: 'Validação', row: 'val.minmax', inline: true },
|
|
1946
|
+
{ name: 'max', label: 'Max (HH:mm)', editorType: 'text', group: 'Validação', row: 'val.minmax', inline: true },
|
|
1947
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
1948
|
+
// Comportamento
|
|
1949
|
+
{ name: 'step', label: 'Step (segundos)', editorType: 'number', group: 'Formato/Comportamento' },
|
|
1950
|
+
{ name: 'touchUi', label: 'Touch UI', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
1951
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
1952
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
1953
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
1954
|
+
// Material/A11y
|
|
1955
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
1956
|
+
{ value: 'fill', text: 'Fill' },
|
|
1957
|
+
{ value: 'outline', text: 'Outline' },
|
|
1958
|
+
] },
|
|
1959
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
1960
|
+
{ value: 'primary', text: 'Primária' },
|
|
1961
|
+
{ value: 'accent', text: 'Acento' },
|
|
1962
|
+
{ value: 'warn', text: 'Alerta' },
|
|
1963
|
+
] },
|
|
1964
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1965
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
1966
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
1967
|
+
];
|
|
1968
|
+
|
|
1969
|
+
const monthInputProperties = [
|
|
1970
|
+
// Geral
|
|
1971
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
1972
|
+
{ name: 'defaultValue', label: 'Valor padrão (YYYY-MM)', editorType: 'text', group: 'Geral' },
|
|
1973
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
1974
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
1975
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:calendar_view_month). Use o seletor ao lado para buscar." },
|
|
1976
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1977
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: 'Material Symbols (ex.: mi:...). Use o seletor ao lado para buscar.' },
|
|
1978
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
1979
|
+
// Validação
|
|
1980
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
1981
|
+
{ name: 'min', label: 'Mínimo (YYYY-MM)', editorType: 'text', group: 'Validação', row: 'val.minmax' },
|
|
1982
|
+
{ name: 'max', label: 'Máximo (YYYY-MM)', editorType: 'text', group: 'Validação', row: 'val.minmax' },
|
|
1983
|
+
// Material/A11y/Ações
|
|
1984
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
1985
|
+
{ value: 'fill', text: 'Fill' },
|
|
1986
|
+
{ value: 'outline', text: 'Outline' },
|
|
1987
|
+
] },
|
|
1988
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
1989
|
+
{ value: 'primary', text: 'Primária' },
|
|
1990
|
+
{ value: 'accent', text: 'Acento' },
|
|
1991
|
+
{ value: 'warn', text: 'Alerta' },
|
|
1992
|
+
] },
|
|
1993
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
1994
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
1995
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
1996
|
+
];
|
|
1997
|
+
|
|
1998
|
+
const weekInputProperties = [
|
|
1999
|
+
// Geral
|
|
2000
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2001
|
+
{ name: 'defaultValue', label: 'Valor padrão (YYYY-Www)', editorType: 'text', group: 'Geral' },
|
|
2002
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
2003
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2004
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:date_range). Use o seletor ao lado para buscar." },
|
|
2005
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2006
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: 'Material Symbols (ex.: mi:...). Use o seletor ao lado para buscar.' },
|
|
2007
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2008
|
+
// Validação
|
|
2009
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2010
|
+
{ name: 'min', label: 'Mínimo (YYYY-Www)', editorType: 'text', group: 'Validação', row: 'val.minmax' },
|
|
2011
|
+
{ name: 'max', label: 'Máximo (YYYY-Www)', editorType: 'text', group: 'Validação', row: 'val.minmax' },
|
|
2012
|
+
// Material/A11y
|
|
2013
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
2014
|
+
{ value: 'fill', text: 'Fill' },
|
|
2015
|
+
{ value: 'outline', text: 'Outline' },
|
|
2016
|
+
] },
|
|
2017
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
2018
|
+
{ value: 'primary', text: 'Primária' },
|
|
2019
|
+
{ value: 'accent', text: 'Acento' },
|
|
2020
|
+
{ value: 'warn', text: 'Alerta' },
|
|
2021
|
+
] },
|
|
2022
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
2023
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
2024
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
2025
|
+
];
|
|
2026
|
+
|
|
2027
|
+
const emailInputProperties = [
|
|
2028
|
+
// Geral
|
|
2029
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2030
|
+
{ name: 'defaultValue', label: 'Valor padrão', editorType: 'text', group: 'Geral' },
|
|
2031
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
2032
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2033
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:mail). Use o seletor ao lado para buscar." },
|
|
2034
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2035
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
2036
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2037
|
+
{ name: 'prefix', label: 'Texto (prefixo)', editorType: 'text', group: 'Geral' },
|
|
2038
|
+
{ name: 'suffix', label: 'Texto (sufixo)', editorType: 'text', group: 'Geral' },
|
|
2039
|
+
// Validação
|
|
2040
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2041
|
+
{ name: 'minLength', label: 'Mín. caracteres', editorType: 'number', group: 'Validação', row: 'val.len', inline: true },
|
|
2042
|
+
{ name: 'maxLength', label: 'Máx. caracteres', editorType: 'number', group: 'Validação', row: 'val.len', inline: true },
|
|
2043
|
+
{ name: 'pattern', label: 'Regex', editorType: 'text', group: 'Validação' },
|
|
2044
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
2045
|
+
{ name: 'validators.minLengthMessage', label: 'Mensagem: minLength', editorType: 'text', group: 'Validação' },
|
|
2046
|
+
{ name: 'validators.maxLengthMessage', label: 'Mensagem: maxLength', editorType: 'text', group: 'Validação' },
|
|
2047
|
+
{ name: 'validators.patternMessage', label: 'Mensagem: regex', editorType: 'text', group: 'Validação' },
|
|
2048
|
+
// Comportamento
|
|
2049
|
+
{ name: 'autocomplete', label: 'Autocomplete', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2050
|
+
{ name: 'spellcheck', label: 'Verificação ortográfica', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2051
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2052
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2053
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2054
|
+
{ name: 'inputMode', label: 'Modo de entrada', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2055
|
+
// Material/A11y/Ações
|
|
2056
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
2057
|
+
{ value: 'fill', text: 'Fill' },
|
|
2058
|
+
{ value: 'outline', text: 'Outline' },
|
|
2059
|
+
] },
|
|
2060
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
2061
|
+
{ value: 'primary', text: 'Primária' },
|
|
2062
|
+
{ value: 'accent', text: 'Acento' },
|
|
2063
|
+
{ value: 'warn', text: 'Alerta' },
|
|
2064
|
+
] },
|
|
2065
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
2066
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
2067
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
2068
|
+
];
|
|
2069
|
+
|
|
2070
|
+
const passwordInputProperties = [
|
|
2071
|
+
// Geral
|
|
2072
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2073
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
2074
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2075
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:lock). Use o seletor ao lado para buscar." },
|
|
2076
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2077
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
2078
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2079
|
+
// Validação
|
|
2080
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2081
|
+
{ name: 'minLength', label: 'Mín. caracteres', editorType: 'number', group: 'Validação', row: 'val.len', inline: true },
|
|
2082
|
+
{ name: 'maxLength', label: 'Máx. caracteres', editorType: 'number', group: 'Validação', row: 'val.len', inline: true },
|
|
2083
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
2084
|
+
{ name: 'validators.minLengthMessage', label: 'Mensagem: minLength', editorType: 'text', group: 'Validação' },
|
|
2085
|
+
{ name: 'validators.maxLengthMessage', label: 'Mensagem: maxLength', editorType: 'text', group: 'Validação' },
|
|
2086
|
+
// Comportamento
|
|
2087
|
+
{ name: 'autocomplete', label: 'Autocomplete', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2088
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2089
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2090
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2091
|
+
// Material/A11y
|
|
2092
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
2093
|
+
{ value: 'fill', text: 'Fill' },
|
|
2094
|
+
{ value: 'outline', text: 'Outline' },
|
|
2095
|
+
] },
|
|
2096
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
2097
|
+
{ value: 'primary', text: 'Primária' },
|
|
2098
|
+
{ value: 'accent', text: 'Acento' },
|
|
2099
|
+
{ value: 'warn', text: 'Alerta' },
|
|
2100
|
+
] },
|
|
2101
|
+
];
|
|
2102
|
+
|
|
2103
|
+
const urlInputProperties = [
|
|
2104
|
+
// Geral
|
|
2105
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2106
|
+
{ name: 'defaultValue', label: 'Valor padrão (URL)', editorType: 'text', group: 'Geral' },
|
|
2107
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
2108
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2109
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:link). Use o seletor ao lado para buscar." },
|
|
2110
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2111
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
2112
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2113
|
+
// Validação
|
|
2114
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2115
|
+
{ name: 'pattern', label: 'Regex', editorType: 'text', group: 'Validação' },
|
|
2116
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
2117
|
+
{ name: 'validators.patternMessage', label: 'Mensagem: regex', editorType: 'text', group: 'Validação' },
|
|
2118
|
+
// Comportamento
|
|
2119
|
+
{ name: 'autocomplete', label: 'Autocomplete', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2120
|
+
{ name: 'spellcheck', label: 'Verificação ortográfica', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2121
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2122
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2123
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2124
|
+
];
|
|
2125
|
+
|
|
2126
|
+
const searchInputProperties = [
|
|
2127
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2128
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
2129
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2130
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:search). Use o seletor ao lado para buscar." },
|
|
2131
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2132
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
2133
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2134
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2135
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
2136
|
+
{ name: 'autocomplete', label: 'Autocomplete', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2137
|
+
];
|
|
2138
|
+
|
|
2139
|
+
const phoneInputProperties = [
|
|
2140
|
+
// Geral
|
|
2141
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2142
|
+
{ name: 'defaultValue', label: 'Valor padrão', editorType: 'text', group: 'Geral' },
|
|
2143
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
2144
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2145
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:call). Use o seletor ao lado para buscar." },
|
|
2146
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2147
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
2148
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2149
|
+
// Validação
|
|
2150
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2151
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
2152
|
+
// Comportamento
|
|
2153
|
+
{ name: 'autocomplete', label: 'Autocomplete', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2154
|
+
{ name: 'spellcheck', label: 'Verificação ortográfica', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2155
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2156
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2157
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2158
|
+
{ name: 'inputMode', label: 'Modo de entrada', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2159
|
+
];
|
|
2160
|
+
|
|
2161
|
+
const colorInputProperties = [
|
|
2162
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2163
|
+
{ name: 'defaultValue', label: 'Valor padrão (#RRGGBB)', editorType: 'text', group: 'Geral' },
|
|
2164
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
2165
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2166
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:palette). Use o seletor ao lado para buscar." },
|
|
2167
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2168
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
2169
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2170
|
+
{ name: 'prefix', label: 'Texto (prefixo)', editorType: 'text', group: 'Geral' },
|
|
2171
|
+
{ name: 'suffix', label: 'Texto (sufixo)', editorType: 'text', group: 'Geral' },
|
|
2172
|
+
// Palette / Preview
|
|
2173
|
+
{ name: 'palettePreset', label: 'Paleta (preset)', editorType: 'select', group: 'Palette', options: [
|
|
2174
|
+
{ value: 'material', text: 'Material' },
|
|
2175
|
+
{ value: 'office', text: 'Office' },
|
|
2176
|
+
{ value: 'basic', text: 'Básico' },
|
|
2177
|
+
] },
|
|
2178
|
+
{ name: 'paletteColors', label: 'Paleta: cores (JSON ou linhas)', editorType: 'textarea', group: 'Palette', hint: "JSON array ou uma cor por linha (#hex ou rgba/hsl)" },
|
|
2179
|
+
{ name: 'columns', label: 'Paleta: colunas', editorType: 'number', group: 'Palette', defaultValue: 8 },
|
|
2180
|
+
{ name: 'popupWidth', label: 'Popup width (px ou CSS)', editorType: 'text', group: 'Preview/Popup', defaultValue: '320' },
|
|
2181
|
+
{ name: 'preview', label: 'Mostrar preview', editorType: 'checkbox', group: 'Preview/Popup' },
|
|
2182
|
+
{ name: 'showRecent', label: 'Mostrar recentes', editorType: 'checkbox', group: 'Preview/Popup' },
|
|
2183
|
+
{ name: 'maxRecent', label: 'Qtd. de recentes', editorType: 'number', group: 'Preview/Popup', defaultValue: 12 },
|
|
2184
|
+
{ name: 'showNativeOption', label: 'Mostrar seletor nativo', editorType: 'checkbox', group: 'Preview/Popup' },
|
|
2185
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2186
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
2187
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2188
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2189
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2190
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
2191
|
+
{ value: 'fill', text: 'Fill' },
|
|
2192
|
+
{ value: 'outline', text: 'Outline' },
|
|
2193
|
+
] },
|
|
2194
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
2195
|
+
{ value: 'primary', text: 'Primária' },
|
|
2196
|
+
{ value: 'accent', text: 'Acento' },
|
|
2197
|
+
{ value: 'warn', text: 'Alerta' },
|
|
2198
|
+
] },
|
|
2199
|
+
{ name: 'materialDesign.floatLabel', label: 'Comportamento do label', editorType: 'select', group: 'Material Design', options: [
|
|
2200
|
+
{ value: 'auto', text: 'Auto' },
|
|
2201
|
+
{ value: 'always', text: 'Sempre' },
|
|
2202
|
+
] },
|
|
2203
|
+
{ name: 'materialDesign.subscriptSizing', label: 'Subscript sizing', editorType: 'select', group: 'Material Design', options: [
|
|
2204
|
+
{ value: 'fixed', text: 'Fixo' },
|
|
2205
|
+
{ value: 'dynamic', text: 'Dinâmico' },
|
|
2206
|
+
] },
|
|
2207
|
+
{ name: 'materialDesign.hideRequiredMarker', label: 'Ocultar * obrigatório', editorType: 'checkbox', group: 'Material Design' },
|
|
2208
|
+
// Acessibilidade
|
|
2209
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
2210
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
2211
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
2212
|
+
];
|
|
2213
|
+
|
|
2214
|
+
// ColorPicker v2 property editor (pdx-color-picker)
|
|
2215
|
+
const colorPickerProperties = [
|
|
2216
|
+
// Geral
|
|
2217
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2218
|
+
{ name: 'defaultValue', label: 'Valor padrão', editorType: 'text', group: 'Geral', hint: '#rrggbb, rgba(), ...' },
|
|
2219
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2220
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Geral' },
|
|
2221
|
+
// Formato/Comportamento
|
|
2222
|
+
{
|
|
2223
|
+
name: 'format',
|
|
2224
|
+
label: 'Formato de saída',
|
|
2225
|
+
editorType: 'select',
|
|
2226
|
+
group: 'Formato/Comportamento',
|
|
2227
|
+
defaultValue: 'rgba',
|
|
2228
|
+
options: [
|
|
2229
|
+
{ value: 'hex', text: 'HEX' },
|
|
2230
|
+
{ value: 'rgb', text: 'RGB' },
|
|
2231
|
+
{ value: 'rgba', text: 'RGBA' },
|
|
2232
|
+
{ value: 'hsl', text: 'HSL' },
|
|
2233
|
+
],
|
|
2234
|
+
},
|
|
2235
|
+
// Views e Preview
|
|
2236
|
+
{
|
|
2237
|
+
name: 'views',
|
|
2238
|
+
label: "Views (JSON: ['gradient','palette'])",
|
|
2239
|
+
editorType: 'textarea',
|
|
2240
|
+
group: 'Views/Preview',
|
|
2241
|
+
hint: "JSON array. Ex.: ['gradient','palette']",
|
|
2242
|
+
defaultValue: "['gradient','palette']",
|
|
2243
|
+
},
|
|
2244
|
+
{
|
|
2245
|
+
name: 'activeView',
|
|
2246
|
+
label: 'View ativa',
|
|
2247
|
+
editorType: 'select',
|
|
2248
|
+
group: 'Views/Preview',
|
|
2249
|
+
options: [
|
|
2250
|
+
{ value: 'gradient', text: 'Gradient' },
|
|
2251
|
+
{ value: 'palette', text: 'Palette' },
|
|
2252
|
+
],
|
|
2253
|
+
},
|
|
2254
|
+
{ name: 'preview', label: 'Mostrar preview (pane)', editorType: 'checkbox', group: 'Views/Preview' },
|
|
2255
|
+
{ name: 'clearButton', label: 'Botão Clear', editorType: 'checkbox', group: 'Views/Preview' },
|
|
2256
|
+
{
|
|
2257
|
+
name: 'actionsLayout',
|
|
2258
|
+
label: 'Ações (layout)',
|
|
2259
|
+
editorType: 'select',
|
|
2260
|
+
group: 'Views/Preview',
|
|
2261
|
+
defaultValue: 'end',
|
|
2262
|
+
options: [
|
|
2263
|
+
{ value: 'start', text: 'Início' },
|
|
2264
|
+
{ value: 'end', text: 'Fim' },
|
|
2265
|
+
],
|
|
2266
|
+
},
|
|
2267
|
+
// Adaptive e Popup
|
|
2268
|
+
{ name: 'adaptiveMode', label: 'Adaptive (BottomSheet/Drawer)', editorType: 'checkbox', group: 'Adaptive/Popup' },
|
|
2269
|
+
{ name: 'adaptiveTitle', label: 'Adaptive title', editorType: 'text', group: 'Adaptive/Popup' },
|
|
2270
|
+
{ name: 'adaptiveSubtitle', label: 'Adaptive subtitle', editorType: 'text', group: 'Adaptive/Popup' },
|
|
2271
|
+
{ name: 'popupSettings.width', label: 'Popup width (px ou CSS)', editorType: 'text', group: 'Adaptive/Popup', defaultValue: '340' },
|
|
2272
|
+
// Gradient
|
|
2273
|
+
{ name: 'gradientSettings.showOpacity', label: 'Gradiente: transparência (alpha)', editorType: 'checkbox', group: 'Gradient' },
|
|
2274
|
+
{
|
|
2275
|
+
name: 'gradientSettings.channel',
|
|
2276
|
+
label: 'Gradiente: canal',
|
|
2277
|
+
editorType: 'select',
|
|
2278
|
+
group: 'Gradient',
|
|
2279
|
+
defaultValue: 'hsv',
|
|
2280
|
+
options: [
|
|
2281
|
+
{ value: 'hsv', text: 'HSV' },
|
|
2282
|
+
{ value: 'hsl', text: 'HSL' },
|
|
2283
|
+
],
|
|
2284
|
+
},
|
|
2285
|
+
// Palette
|
|
2286
|
+
{
|
|
2287
|
+
name: 'paletteSettings.preset',
|
|
2288
|
+
label: 'Palette: preset',
|
|
2289
|
+
editorType: 'select',
|
|
2290
|
+
group: 'Palette',
|
|
2291
|
+
defaultValue: 'material',
|
|
2292
|
+
options: [
|
|
2293
|
+
{ value: 'material', text: 'Material' },
|
|
2294
|
+
{ value: 'office', text: 'Office' },
|
|
2295
|
+
{ value: 'basic', text: 'Básico' },
|
|
2296
|
+
],
|
|
2297
|
+
},
|
|
2298
|
+
{
|
|
2299
|
+
name: 'paletteSettings.colors',
|
|
2300
|
+
label: 'Palette: cores (JSON ou linhas)',
|
|
2301
|
+
editorType: 'textarea',
|
|
2302
|
+
group: 'Palette',
|
|
2303
|
+
hint: "JSON array ou uma cor por linha (#hex ou rgba/hsl)",
|
|
2304
|
+
},
|
|
2305
|
+
{ name: 'paletteSettings.columns', label: 'Palette: colunas', editorType: 'number', group: 'Palette', defaultValue: 8 },
|
|
2306
|
+
// Tema/Estilo
|
|
2307
|
+
{
|
|
2308
|
+
name: 'fillMode',
|
|
2309
|
+
label: 'Fill mode',
|
|
2310
|
+
editorType: 'select',
|
|
2311
|
+
group: 'Theming',
|
|
2312
|
+
defaultValue: 'solid',
|
|
2313
|
+
options: [
|
|
2314
|
+
{ value: 'solid', text: 'Solid' },
|
|
2315
|
+
{ value: 'flat', text: 'Flat' },
|
|
2316
|
+
{ value: 'outline', text: 'Outline' },
|
|
2317
|
+
],
|
|
2318
|
+
},
|
|
2319
|
+
{
|
|
2320
|
+
name: 'rounded',
|
|
2321
|
+
label: 'Rounded',
|
|
2322
|
+
editorType: 'select',
|
|
2323
|
+
group: 'Theming',
|
|
2324
|
+
defaultValue: 'medium',
|
|
2325
|
+
options: [
|
|
2326
|
+
{ value: 'none', text: 'None' },
|
|
2327
|
+
{ value: 'small', text: 'Small' },
|
|
2328
|
+
{ value: 'medium', text: 'Medium' },
|
|
2329
|
+
{ value: 'large', text: 'Large' },
|
|
2330
|
+
{ value: 'full', text: 'Full' },
|
|
2331
|
+
],
|
|
2332
|
+
},
|
|
2333
|
+
{
|
|
2334
|
+
name: 'size',
|
|
2335
|
+
label: 'Size',
|
|
2336
|
+
editorType: 'select',
|
|
2337
|
+
group: 'Theming',
|
|
2338
|
+
defaultValue: 'medium',
|
|
2339
|
+
options: [
|
|
2340
|
+
{ value: 'small', text: 'Small' },
|
|
2341
|
+
{ value: 'medium', text: 'Medium' },
|
|
2342
|
+
{ value: 'large', text: 'Large' },
|
|
2343
|
+
],
|
|
2344
|
+
},
|
|
2345
|
+
{ name: 'icon', label: 'Ícone', editorType: 'text', group: 'Theming', hint: "Material Symbols (ex.: mi:palette). Use o seletor ao lado para buscar." },
|
|
2346
|
+
{ name: 'svgIcon', label: 'SVG icon', editorType: 'text', group: 'Theming' },
|
|
2347
|
+
{ name: 'iconClass', label: 'Icon class (JSON/string)', editorType: 'textarea', group: 'Theming', hint: 'string | string[] | Record<string, boolean>' },
|
|
2348
|
+
// Acessibilidade/Comportamento
|
|
2349
|
+
{ name: 'tabindex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
2350
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2351
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2352
|
+
];
|
|
2353
|
+
|
|
2354
|
+
const ratingProperties = [
|
|
2355
|
+
// Geral
|
|
2356
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2357
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2358
|
+
{ name: 'max', label: 'Quantidade de itens', editorType: 'number', group: 'Formato/Comportamento', hint: 'Ex.: 5' },
|
|
2359
|
+
{ name: 'allowHalf', label: 'Permitir meio ícone', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2360
|
+
{ name: 'selection', label: 'Modo de seleção', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2361
|
+
{ value: 'continuous', text: 'Contínuo' },
|
|
2362
|
+
{ value: 'single', text: 'Único' },
|
|
2363
|
+
] },
|
|
2364
|
+
{ name: 'size', label: 'Tamanho', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2365
|
+
{ value: 'small', text: 'Pequeno' },
|
|
2366
|
+
{ value: 'medium', text: 'Médio' },
|
|
2367
|
+
{ value: 'large', text: 'Grande' },
|
|
2368
|
+
] },
|
|
2369
|
+
{ name: 'icon', label: 'Ícone preenchido', editorType: 'text', group: 'Formato/Comportamento', hint: 'Material Symbols (ex.: mi:star). Use o seletor ao lado para buscar.' },
|
|
2370
|
+
{ name: 'emptyIcon', label: 'Ícone vazio', editorType: 'text', group: 'Formato/Comportamento', hint: 'Material Symbols (ex.: mi:star_border). Use o seletor ao lado para buscar.' },
|
|
2371
|
+
{ name: 'svgIcon', label: 'SVG (preenchido)', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2372
|
+
{ name: 'svgIconOutline', label: 'SVG (vazio)', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2373
|
+
// Cores/Comportamento
|
|
2374
|
+
{ name: 'ratingColor', label: 'Cor do preenchimento', editorType: 'color', group: 'Formato/Comportamento', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2375
|
+
{ name: 'outlineColor', label: 'Cor do contorno', editorType: 'color', group: 'Formato/Comportamento', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2376
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2377
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2378
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
2379
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
2380
|
+
];
|
|
2381
|
+
|
|
2382
|
+
const chipInputProperties = [
|
|
2383
|
+
// Geral
|
|
2384
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2385
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
2386
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2387
|
+
// Dados/Opções
|
|
2388
|
+
{ name: 'options', label: 'Opções (JSON ou linhas valor|rótulo)', editorType: 'textarea', group: 'Dados/Opções' },
|
|
2389
|
+
{ name: 'resourcePath', label: 'Resource Path (remoto)', editorType: 'text', group: 'Dados/Opções', row: 'dados.remoto', inline: true },
|
|
2390
|
+
{ name: 'filterCriteria', label: 'Critérios de filtro (JSON)', editorType: 'textarea', group: 'Dados/Opções', hint: '{ "active": true }' },
|
|
2391
|
+
{ name: 'optionLabelKey', label: 'Chave do rótulo (remoto)', editorType: 'text', group: 'Dados/Opções', row: 'dados.keys', inline: true },
|
|
2392
|
+
{ name: 'optionValueKey', label: 'Chave do valor (remoto)', editorType: 'text', group: 'Dados/Opções', row: 'dados.keys', inline: true },
|
|
2393
|
+
// Formato/Comportamento
|
|
2394
|
+
{ name: 'maxSelections', label: 'Máx. seleções', editorType: 'number', group: 'Formato/Comportamento' },
|
|
2395
|
+
{ name: 'removable', label: 'Removível', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.flags', inline: true },
|
|
2396
|
+
{ name: 'addOnBlur', label: 'Adicionar ao sair', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'comp.flags', inline: true },
|
|
2397
|
+
{ name: 'searchable', label: 'Pesquisável', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2398
|
+
{ name: 'minLength', label: 'Mín. caracteres busca', editorType: 'number', group: 'Formato/Comportamento', row: 'comp.search', inline: true },
|
|
2399
|
+
{ name: 'validationDebounce', label: 'Debounce busca (ms)', editorType: 'number', group: 'Formato/Comportamento', row: 'comp.search', inline: true },
|
|
2400
|
+
// Validação
|
|
2401
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2402
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
2403
|
+
// Material Design
|
|
2404
|
+
{
|
|
2405
|
+
name: 'materialDesign.appearance',
|
|
2406
|
+
label: 'Aparência',
|
|
2407
|
+
editorType: 'select',
|
|
2408
|
+
group: 'Material Design',
|
|
2409
|
+
options: [
|
|
2410
|
+
{ value: 'fill', text: 'Fill' },
|
|
2411
|
+
{ value: 'outline', text: 'Outline' },
|
|
2412
|
+
],
|
|
2413
|
+
},
|
|
2414
|
+
{
|
|
2415
|
+
name: 'materialDesign.color',
|
|
2416
|
+
label: 'Cor do tema',
|
|
2417
|
+
editorType: 'select',
|
|
2418
|
+
group: 'Material Design',
|
|
2419
|
+
options: [
|
|
2420
|
+
{ value: 'primary', text: 'Primária' },
|
|
2421
|
+
{ value: 'accent', text: 'Acento' },
|
|
2422
|
+
{ value: 'warn', text: 'Alerta' },
|
|
2423
|
+
],
|
|
2424
|
+
},
|
|
2425
|
+
{
|
|
2426
|
+
name: 'materialDesign.floatLabel',
|
|
2427
|
+
label: 'Comportamento do label',
|
|
2428
|
+
editorType: 'select',
|
|
2429
|
+
group: 'Material Design',
|
|
2430
|
+
options: [
|
|
2431
|
+
{ value: 'auto', text: 'Auto' },
|
|
2432
|
+
{ value: 'always', text: 'Sempre' },
|
|
2433
|
+
],
|
|
2434
|
+
},
|
|
2435
|
+
{
|
|
2436
|
+
name: 'materialDesign.subscriptSizing',
|
|
2437
|
+
label: 'Subscript sizing',
|
|
2438
|
+
editorType: 'select',
|
|
2439
|
+
group: 'Material Design',
|
|
2440
|
+
options: [
|
|
2441
|
+
{ value: 'fixed', text: 'Fixo' },
|
|
2442
|
+
{ value: 'dynamic', text: 'Dinâmico' },
|
|
2443
|
+
],
|
|
2444
|
+
},
|
|
2445
|
+
{ name: 'materialDesign.hideRequiredMarker', label: 'Ocultar * obrigatório', editorType: 'checkbox', group: 'Material Design' },
|
|
2446
|
+
// Acessibilidade
|
|
2447
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
2448
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
2449
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
2450
|
+
{ name: 'tabIndex', label: 'TabIndex', editorType: 'number', group: 'Acessibilidade' },
|
|
2451
|
+
{ name: 'dataAttributes', label: 'Data attributes (JSON)', editorType: 'textarea', group: 'Acessibilidade', hint: '{ "testId": "chips-a" }' },
|
|
2452
|
+
// Ações (Clear)
|
|
2453
|
+
{ name: 'clearButton.enabled', label: 'Clear: habilitar', editorType: 'checkbox', group: 'Ações' },
|
|
2454
|
+
{ name: 'clearButton.icon', label: 'Clear: ícone', editorType: 'text', group: 'Ações', hint: "Material Symbols (ex.: mi:clear). Use o seletor ao lado para buscar." },
|
|
2455
|
+
{ name: 'clearButton.iconColor', label: 'Clear: cor do ícone', editorType: 'color', group: 'Ações', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2456
|
+
{ name: 'clearButton.tooltip', label: 'Clear: tooltip', editorType: 'text', group: 'Ações' },
|
|
2457
|
+
{ name: 'clearButton.ariaLabel', label: 'Clear: aria-label', editorType: 'text', group: 'Ações' },
|
|
2458
|
+
{ name: 'clearButton.showOnlyWhenFilled', label: 'Clear: só quando preenchido', editorType: 'checkbox', group: 'Ações' },
|
|
2459
|
+
];
|
|
2460
|
+
|
|
2461
|
+
const checkboxGroupProperties = [
|
|
2462
|
+
// Dados/Opções
|
|
2463
|
+
{ name: 'options', label: 'Opções (JSON ou linhas valor|rótulo)', editorType: 'textarea', group: 'Dados/Opções' },
|
|
2464
|
+
{ name: 'resourcePath', label: 'Recurso (remoto)', editorType: 'text', group: 'Dados/Opções', row: 'dados.remoto', inline: true },
|
|
2465
|
+
{ name: 'filterCriteria', label: 'Filtro (JSON)', editorType: 'textarea', group: 'Dados/Opções' },
|
|
2466
|
+
{ name: 'optionLabelKey', label: 'Chave rótulo', editorType: 'text', group: 'Dados/Opções', row: 'dados.keys', inline: true },
|
|
2467
|
+
{ name: 'optionValueKey', label: 'Chave valor', editorType: 'text', group: 'Dados/Opções', row: 'dados.keys', inline: true },
|
|
2468
|
+
// Formato/Comportamento
|
|
2469
|
+
{ name: 'searchable', label: 'Pesquisável', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2470
|
+
{ name: 'selectAll', label: 'Selecionar todos', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2471
|
+
{ name: 'maxSelections', label: 'Máx. seleções', editorType: 'number', group: 'Formato/Comportamento' },
|
|
2472
|
+
{ name: 'layout', label: 'Layout', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2473
|
+
{ value: 'horizontal', text: 'Horizontal' },
|
|
2474
|
+
{ value: 'vertical', text: 'Vertical' },
|
|
2475
|
+
] },
|
|
2476
|
+
{ name: 'labelPosition', label: 'Posição do label', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2477
|
+
{ value: 'before', text: 'Antes' },
|
|
2478
|
+
{ value: 'after', text: 'Depois' },
|
|
2479
|
+
] },
|
|
2480
|
+
{ name: 'color', label: 'Cor', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2481
|
+
{ value: 'primary', text: 'Primária' },
|
|
2482
|
+
{ value: 'accent', text: 'Acento' },
|
|
2483
|
+
{ value: 'warn', text: 'Alerta' },
|
|
2484
|
+
] },
|
|
2485
|
+
{ name: 'indeterminate', label: 'Indeterminado', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2486
|
+
{ name: 'linkText', label: 'Texto do link', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2487
|
+
{ name: 'linkUrl', label: 'URL do link', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2488
|
+
{ name: 'linkTarget', label: 'Alvo do link', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2489
|
+
{ value: '_self', text: 'Mesma janela' },
|
|
2490
|
+
{ value: '_blank', text: 'Nova janela' },
|
|
2491
|
+
] },
|
|
2492
|
+
// Geral/Validação
|
|
2493
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2494
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2495
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2496
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
2497
|
+
// Acessibilidade
|
|
2498
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
2499
|
+
];
|
|
2500
|
+
|
|
2501
|
+
const toggleProperties = [
|
|
2502
|
+
// Geral
|
|
2503
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2504
|
+
{ name: 'defaultValue', label: 'Valor padrão (boolean)', editorType: 'checkbox', group: 'Geral' },
|
|
2505
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2506
|
+
// Material Design
|
|
2507
|
+
{ name: 'color', label: 'Cor', editorType: 'select', group: 'Material Design', options: [
|
|
2508
|
+
{ value: 'primary', text: 'Primária' },
|
|
2509
|
+
{ value: 'accent', text: 'Acento' },
|
|
2510
|
+
{ value: 'warn', text: 'Alerta' },
|
|
2511
|
+
] },
|
|
2512
|
+
// Formato/Comportamento
|
|
2513
|
+
{ name: 'labelPosition', label: 'Posição do label', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2514
|
+
{ value: 'before', text: 'Antes' },
|
|
2515
|
+
{ value: 'after', text: 'Depois' },
|
|
2516
|
+
] },
|
|
2517
|
+
{ name: 'hideIcon', label: 'Ocultar ícone', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2518
|
+
{ name: 'disableRipple', label: 'Desabilitar ripple', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2519
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2520
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2521
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2522
|
+
// Validação
|
|
2523
|
+
{ name: 'requiredTrue', label: 'Exigir verdadeiro', editorType: 'checkbox', group: 'Validação' },
|
|
2524
|
+
{ name: 'validators.requiredTrueMessage', label: 'Mensagem: exigir verdadeiro', editorType: 'text', group: 'Validação' },
|
|
2525
|
+
// Acessibilidade
|
|
2526
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
2527
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
2528
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
2529
|
+
];
|
|
2530
|
+
|
|
2531
|
+
const sliderProperties = [
|
|
2532
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2533
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2534
|
+
{ name: 'min', label: 'Mínimo', editorType: 'number', group: 'Validação', row: 'val.minmax', inline: true },
|
|
2535
|
+
{ name: 'max', label: 'Máximo', editorType: 'number', group: 'Validação', row: 'val.minmax', inline: true },
|
|
2536
|
+
{ name: 'validators.minMessage', label: 'Mensagem: mínimo', editorType: 'text', group: 'Validação' },
|
|
2537
|
+
{ name: 'validators.maxMessage', label: 'Mensagem: máximo', editorType: 'text', group: 'Validação' },
|
|
2538
|
+
{ name: 'step', label: 'Step', editorType: 'number', group: 'Formato/Comportamento' },
|
|
2539
|
+
{ name: 'thumbLabel', label: 'Thumb label', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2540
|
+
{ name: 'vertical', label: 'Vertical', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.flags', inline: true },
|
|
2541
|
+
{ name: 'showTicks', label: 'Ticks', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2542
|
+
{ value: false, text: 'Sem ticks' },
|
|
2543
|
+
{ value: true, text: 'Com ticks' },
|
|
2544
|
+
{ value: 'auto', text: 'Auto' },
|
|
2545
|
+
] },
|
|
2546
|
+
{ name: 'discrete', label: 'Discreto', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2547
|
+
{ name: 'invert', label: 'Inverter', editorType: 'checkbox', group: 'Formato/Comportamento', row: 'fmt.flags', inline: true },
|
|
2548
|
+
{ name: 'color', label: 'Cor', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2549
|
+
{ value: 'primary', text: 'Primária' },
|
|
2550
|
+
{ value: 'accent', text: 'Acento' },
|
|
2551
|
+
{ value: 'warn', text: 'Alerta' },
|
|
2552
|
+
] },
|
|
2553
|
+
];
|
|
2554
|
+
|
|
2555
|
+
const rangeSliderProperties = [
|
|
2556
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2557
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2558
|
+
{ name: 'mode', label: 'Modo', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2559
|
+
{ value: 'single', text: 'Único' },
|
|
2560
|
+
{ value: 'range', text: 'Faixa' },
|
|
2561
|
+
] },
|
|
2562
|
+
{ name: 'min', label: 'Mínimo', editorType: 'number', group: 'Validação', row: 'val.minmax', inline: true },
|
|
2563
|
+
{ name: 'max', label: 'Máximo', editorType: 'number', group: 'Validação', row: 'val.minmax', inline: true },
|
|
2564
|
+
{ name: 'validators.minMessage', label: 'Mensagem: mínimo', editorType: 'text', group: 'Validação' },
|
|
2565
|
+
{ name: 'validators.maxMessage', label: 'Mensagem: máximo', editorType: 'text', group: 'Validação' },
|
|
2566
|
+
{ name: 'step', label: 'Step', editorType: 'number', group: 'Formato/Comportamento' },
|
|
2567
|
+
{ name: 'thumbLabel', label: 'Thumb label', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2568
|
+
{ name: 'showTicks', label: 'Ticks', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2569
|
+
{ value: false, text: 'Sem ticks' },
|
|
2570
|
+
{ value: true, text: 'Com ticks' },
|
|
2571
|
+
{ value: 'auto', text: 'Auto' },
|
|
2572
|
+
] },
|
|
2573
|
+
{ name: 'discrete', label: 'Discreto', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2574
|
+
{ name: 'vertical', label: 'Vertical', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2575
|
+
{ name: 'invert', label: 'Inverter', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2576
|
+
{ name: 'minDistance', label: 'Distância mínima', editorType: 'number', group: 'Validação', row: 'val.distance', inline: true },
|
|
2577
|
+
{ name: 'maxDistance', label: 'Distância máxima', editorType: 'number', group: 'Validação', row: 'val.distance', inline: true },
|
|
2578
|
+
{ name: 'validators.rangeMessage', label: 'Mensagem: ordem do range', editorType: 'text', group: 'Validação' },
|
|
2579
|
+
{ name: 'validators.distanceMessage', label: 'Mensagem: distância', editorType: 'text', group: 'Validação' },
|
|
2580
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2581
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
2582
|
+
{ name: 'displayWith', label: 'DisplayWith (id função)', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2583
|
+
{ name: 'showInputs', label: 'Mostrar inputs', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2584
|
+
{ name: 'color', label: 'Cor', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2585
|
+
{ value: 'primary', text: 'Primária' },
|
|
2586
|
+
{ value: 'accent', text: 'Acento' },
|
|
2587
|
+
{ value: 'warn', text: 'Alerta' },
|
|
2588
|
+
] },
|
|
2589
|
+
];
|
|
2590
|
+
|
|
2591
|
+
const currencyInputProperties = [
|
|
2592
|
+
// Geral
|
|
2593
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2594
|
+
{ name: 'defaultValue', label: 'Valor padrão', editorType: 'number', group: 'Geral' },
|
|
2595
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
2596
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2597
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: 'Material Symbols (ex.: mi:...). Use o seletor ao lado para buscar.' },
|
|
2598
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2599
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: 'Material Symbols (ex.: mi:...). Use o seletor ao lado para buscar.' },
|
|
2600
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2601
|
+
{ name: 'prefix', label: 'Texto (prefixo)', editorType: 'text', group: 'Geral' },
|
|
2602
|
+
{ name: 'suffix', label: 'Texto (sufixo)', editorType: 'text', group: 'Geral' },
|
|
2603
|
+
// Validação
|
|
2604
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2605
|
+
{ name: 'min', label: 'Mínimo', editorType: 'number', group: 'Validação', row: 'val.minmax', inline: true },
|
|
2606
|
+
{ name: 'max', label: 'Máximo', editorType: 'number', group: 'Validação', row: 'val.minmax', inline: true },
|
|
2607
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
2608
|
+
{ name: 'validators.minMessage', label: 'Mensagem: mínimo', editorType: 'text', group: 'Validação' },
|
|
2609
|
+
{ name: 'validators.maxMessage', label: 'Mensagem: máximo', editorType: 'text', group: 'Validação' },
|
|
2610
|
+
// Formato/Comportamento
|
|
2611
|
+
{ name: 'numberFormat.currency', label: 'Moeda', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2612
|
+
{ name: 'numberFormat.currencyPosition', label: 'Posição moeda', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2613
|
+
{ value: 'before', text: 'Antes' },
|
|
2614
|
+
{ value: 'after', text: 'Depois' },
|
|
2615
|
+
] },
|
|
2616
|
+
{ name: 'numberFormat.decimalPlaces', label: 'Casas decimais', editorType: 'number', group: 'Formato/Comportamento' },
|
|
2617
|
+
{ name: 'numberFormat.locale', label: 'Locale', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2618
|
+
{ name: 'showGrouping', label: 'Agrupar milhares', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2619
|
+
// Material/A11y/Ações
|
|
2620
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
2621
|
+
{ value: 'fill', text: 'Fill' },
|
|
2622
|
+
{ value: 'outline', text: 'Outline' },
|
|
2623
|
+
] },
|
|
2624
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
2625
|
+
{ value: 'primary', text: 'Primária' },
|
|
2626
|
+
{ value: 'accent', text: 'Acento' },
|
|
2627
|
+
{ value: 'warn', text: 'Alerta' },
|
|
2628
|
+
] },
|
|
2629
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
2630
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
2631
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
2632
|
+
// Sem Clear: componente não implementa botão de limpar
|
|
2633
|
+
];
|
|
2634
|
+
|
|
2635
|
+
const cpfCnpjProperties = [
|
|
2636
|
+
// Geral
|
|
2637
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2638
|
+
{ name: 'defaultValue', label: 'Valor padrão', editorType: 'text', group: 'Geral' },
|
|
2639
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
2640
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2641
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:badge). Use o seletor ao lado para buscar." },
|
|
2642
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2643
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
2644
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2645
|
+
{ name: 'prefix', label: 'Texto (prefixo)', editorType: 'text', group: 'Geral' },
|
|
2646
|
+
{ name: 'suffix', label: 'Texto (sufixo)', editorType: 'text', group: 'Geral' },
|
|
2647
|
+
// Validação
|
|
2648
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2649
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
2650
|
+
{ name: 'validators.patternMessage', label: 'Mensagem: formato inválido', editorType: 'text', group: 'Validação' },
|
|
2651
|
+
// Formato/Comportamento
|
|
2652
|
+
{ name: 'documentType', label: 'Tipo de documento', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2653
|
+
{ value: 'auto', text: 'Auto' },
|
|
2654
|
+
{ value: 'cpf', text: 'CPF' },
|
|
2655
|
+
{ value: 'cnpj', text: 'CNPJ' },
|
|
2656
|
+
] },
|
|
2657
|
+
{ name: 'version', label: 'Versão (parsing)', editorType: 'select', group: 'Formato/Comportamento', options: [
|
|
2658
|
+
{ value: 'auto', text: 'Auto' },
|
|
2659
|
+
{ value: 'legacy', text: 'Legacy (numérico)' },
|
|
2660
|
+
{ value: 'alpha', text: 'Alpha (alfa-numérico para CNPJ)' },
|
|
2661
|
+
] },
|
|
2662
|
+
{ name: 'allowFormattedInput', label: 'Permitir entrada formatada', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2663
|
+
{ name: 'unmaskOnSubmit', label: 'Enviar sem máscara (modelo)', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2664
|
+
{ name: 'autocomplete', label: 'Autocomplete', editorType: 'text', group: 'Formato/Comportamento' },
|
|
2665
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2666
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2667
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2668
|
+
// Material Design
|
|
2669
|
+
{ name: 'materialDesign.appearance', label: 'Aparência', editorType: 'select', group: 'Material Design', options: [
|
|
2670
|
+
{ value: 'fill', text: 'Fill' },
|
|
2671
|
+
{ value: 'outline', text: 'Outline' },
|
|
2672
|
+
] },
|
|
2673
|
+
{ name: 'materialDesign.color', label: 'Cor do tema', editorType: 'select', group: 'Material Design', options: [
|
|
2674
|
+
{ value: 'primary', text: 'Primária' },
|
|
2675
|
+
{ value: 'accent', text: 'Acento' },
|
|
2676
|
+
{ value: 'warn', text: 'Alerta' },
|
|
2677
|
+
] },
|
|
2678
|
+
{ name: 'materialDesign.floatLabel', label: 'Comportamento do label', editorType: 'select', group: 'Material Design', options: [
|
|
2679
|
+
{ value: 'auto', text: 'Auto' },
|
|
2680
|
+
{ value: 'always', text: 'Sempre' },
|
|
2681
|
+
] },
|
|
2682
|
+
{ name: 'materialDesign.subscriptSizing', label: 'Subscript sizing', editorType: 'select', group: 'Material Design', options: [
|
|
2683
|
+
{ value: 'fixed', text: 'Fixo' },
|
|
2684
|
+
{ value: 'dynamic', text: 'Dinâmico' },
|
|
2685
|
+
] },
|
|
2686
|
+
{ name: 'materialDesign.hideRequiredMarker', label: 'Ocultar * obrigatório', editorType: 'checkbox', group: 'Material Design' },
|
|
2687
|
+
// Acessibilidade
|
|
2688
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
2689
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
2690
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
2691
|
+
];
|
|
2692
|
+
|
|
2693
|
+
const fileUploadProperties = [
|
|
2694
|
+
// Dados/Opções
|
|
2695
|
+
{ name: 'accept', label: 'Tipos aceitos (mimes/ext.)', editorType: 'text', group: 'Dados/Opções' },
|
|
2696
|
+
{ name: 'multiple', label: 'Múltiplos arquivos', editorType: 'checkbox', group: 'Dados/Opções' },
|
|
2697
|
+
{ name: 'maxSizeMB', label: 'Tamanho máx (MB)', editorType: 'number', group: 'Dados/Opções' },
|
|
2698
|
+
{ name: 'resourcePath', label: 'Recurso', editorType: 'text', group: 'Dados/Opções' },
|
|
2699
|
+
{ name: 'uploadUrl', label: 'Upload URL', editorType: 'text', group: 'Dados/Opções' },
|
|
2700
|
+
{ name: 'filterCriteria', label: 'Filtro (JSON)', editorType: 'textarea', group: 'Dados/Opções' },
|
|
2701
|
+
// Geral/Validação
|
|
2702
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2703
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2704
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2705
|
+
{ name: 'validators.requiredMessage', label: 'Mensagem: obrigatório', editorType: 'text', group: 'Validação' },
|
|
2706
|
+
// Acessibilidade
|
|
2707
|
+
{ name: 'ariaLabel', label: 'ARIA label', editorType: 'text', group: 'Acessibilidade' },
|
|
2708
|
+
{ name: 'ariaDescribedby', label: 'ARIA describedby', editorType: 'text', group: 'Acessibilidade' },
|
|
2709
|
+
{ name: 'ariaLabelledby', label: 'ARIA labelledby', editorType: 'text', group: 'Acessibilidade' },
|
|
2710
|
+
];
|
|
2711
|
+
|
|
2712
|
+
const yearInputProperties = [
|
|
2713
|
+
{ name: 'label', label: 'Label', editorType: 'text', group: 'Geral' },
|
|
2714
|
+
{ name: 'defaultValue', label: 'Valor padrão (YYYY)', editorType: 'number', group: 'Geral' },
|
|
2715
|
+
{ name: 'placeholder', label: 'Placeholder', editorType: 'text', group: 'Geral' },
|
|
2716
|
+
{ name: 'hint', label: 'Hint', editorType: 'text', group: 'Geral' },
|
|
2717
|
+
{ name: 'prefixIcon', label: 'Ícone (prefixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:calendar_month). Use o seletor ao lado para buscar." },
|
|
2718
|
+
{ name: 'prefixIconColor', label: 'Cor do ícone (prefixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2719
|
+
{ name: 'suffixIcon', label: 'Ícone (sufixo)', editorType: 'text', group: 'Geral', hint: "Material Symbols (ex.: mi:info). Use o seletor ao lado para buscar." },
|
|
2720
|
+
{ name: 'suffixIconColor', label: 'Cor do ícone (sufixo)', editorType: 'color', group: 'Geral', hint: 'primary/accent/warn ou cor CSS (ex.: #496ddb, rgb(73,109,219), red)' },
|
|
2721
|
+
// Validação/Comportamento
|
|
2722
|
+
{ name: 'required', label: 'Obrigatório', editorType: 'checkbox', group: 'Validação' },
|
|
2723
|
+
{ name: 'minYear', label: 'Ano mínimo', editorType: 'number', group: 'Validação', row: 'val.minmax', inline: true },
|
|
2724
|
+
{ name: 'maxYear', label: 'Ano máximo', editorType: 'number', group: 'Validação', row: 'val.minmax', inline: true },
|
|
2725
|
+
{ name: 'step', label: 'Step', editorType: 'number', group: 'Formato/Comportamento' },
|
|
2726
|
+
{ name: 'readonly', label: 'Somente leitura', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2727
|
+
{ name: 'disabled', label: 'Desabilitado', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2728
|
+
{ name: 'autoFocus', label: 'Focar automaticamente', editorType: 'checkbox', group: 'Formato/Comportamento' },
|
|
2729
|
+
];
|
|
2730
|
+
|
|
2731
|
+
/** Garante que minLength <= maxLength quando ambos definidos. */
|
|
2732
|
+
function minLenLeMaxLen(group) {
|
|
2733
|
+
const v = group.value || {};
|
|
2734
|
+
const min = v?.minLength;
|
|
2735
|
+
const max = v?.maxLength;
|
|
2736
|
+
if (min != null && max != null && Number(min) > Number(max)) {
|
|
2737
|
+
return { minLengthGtMaxLength: true };
|
|
2738
|
+
}
|
|
2739
|
+
return null;
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2742
|
+
class FieldMetadataEditorComponent {
|
|
2743
|
+
registry;
|
|
2744
|
+
normalizer;
|
|
2745
|
+
factory;
|
|
2746
|
+
ctxValidators;
|
|
2747
|
+
controlType;
|
|
2748
|
+
seed;
|
|
2749
|
+
applied = new EventEmitter();
|
|
2750
|
+
cancel = new EventEmitter();
|
|
2751
|
+
form;
|
|
2752
|
+
normalizedProps = [];
|
|
2753
|
+
initialSnapshot = null;
|
|
2754
|
+
baselineReady = false;
|
|
2755
|
+
// Lista de tipos suportados no editor (curada para os tipos com config disponível)
|
|
2756
|
+
typeOptions = [
|
|
2757
|
+
{ value: FieldControlType.INPUT, label: 'Texto (Input)' },
|
|
2758
|
+
{ value: FieldControlType.TEXTAREA, label: 'Texto longo (Textarea)' },
|
|
2759
|
+
{ value: FieldControlType.NUMERIC_TEXT_BOX, label: 'Número' },
|
|
2760
|
+
{ value: FieldControlType.CURRENCY_INPUT, label: 'Moeda' },
|
|
2761
|
+
{ value: FieldControlType.EMAIL_INPUT, label: 'E-mail' },
|
|
2762
|
+
{ value: FieldControlType.PASSWORD, label: 'Senha' },
|
|
2763
|
+
{ value: FieldControlType.URL_INPUT, label: 'URL' },
|
|
2764
|
+
{ value: FieldControlType.SEARCH_INPUT, label: 'Busca' },
|
|
2765
|
+
{ value: FieldControlType.PHONE, label: 'Telefone' },
|
|
2766
|
+
{ value: FieldControlType.SELECT, label: 'Seleção (Select)' },
|
|
2767
|
+
{ value: FieldControlType.MULTI_SELECT, label: 'Seleção múltipla' },
|
|
2768
|
+
{ value: FieldControlType.AUTO_COMPLETE, label: 'Auto-completar' },
|
|
2769
|
+
{ value: FieldControlType.SELECTION_LIST, label: 'Lista de seleção' },
|
|
2770
|
+
{ value: FieldControlType.TREE_SELECT, label: 'Árvore (Tree Select)' },
|
|
2771
|
+
{ value: FieldControlType.MULTI_SELECT_TREE, label: 'Árvore múltipla' },
|
|
2772
|
+
{ value: FieldControlType.RADIO, label: 'Opções (Radio)' },
|
|
2773
|
+
{ value: FieldControlType.BUTTON_TOGGLE, label: 'Alternador (Button Toggle)' },
|
|
2774
|
+
{ value: FieldControlType.CHECKBOX, label: 'Caixa de seleção' },
|
|
2775
|
+
{ value: FieldControlType.TOGGLE, label: 'Liga/Desliga (Toggle)' },
|
|
2776
|
+
{ value: FieldControlType.SLIDER, label: 'Slider' },
|
|
2777
|
+
{ value: FieldControlType.RANGE_SLIDER, label: 'Slider (intervalo)' },
|
|
2778
|
+
{ value: FieldControlType.DATE_INPUT, label: 'Data (Input)' },
|
|
2779
|
+
{ value: FieldControlType.DATE_RANGE, label: 'Intervalo de data' },
|
|
2780
|
+
{ value: FieldControlType.DATETIME_LOCAL_INPUT, label: 'Data e Hora (local)' },
|
|
2781
|
+
{ value: FieldControlType.TIME_INPUT, label: 'Hora (Input)' },
|
|
2782
|
+
{ value: FieldControlType.TIME_PICKER, label: 'Hora (Picker)' },
|
|
2783
|
+
{ value: FieldControlType.TIME_RANGE, label: 'Intervalo de hora' },
|
|
2784
|
+
{ value: FieldControlType.MONTH_INPUT, label: 'Mês' },
|
|
2785
|
+
{ value: FieldControlType.WEEK_INPUT, label: 'Semana' },
|
|
2786
|
+
{ value: FieldControlType.YEAR_INPUT, label: 'Ano' },
|
|
2787
|
+
{ value: FieldControlType.COLOR_INPUT, label: 'Cor (Input)' },
|
|
2788
|
+
{ value: FieldControlType.COLOR_PICKER, label: 'Cor (Picker)' },
|
|
2789
|
+
{ value: FieldControlType.RATING, label: 'Avaliação (Rating)' },
|
|
2790
|
+
{ value: FieldControlType.CHIP_INPUT, label: 'Chips' },
|
|
2791
|
+
{ value: FieldControlType.TRANSFER_LIST, label: 'Transferência de itens' },
|
|
2792
|
+
{ value: FieldControlType.CPF_CNPJ_INPUT, label: 'CPF/CNPJ' },
|
|
2793
|
+
{ value: FieldControlType.FILE_UPLOAD, label: 'Upload de Arquivo' },
|
|
2794
|
+
];
|
|
2795
|
+
// Settings Panel integration (contract: isDirty$, isValid$, isBusy$)
|
|
2796
|
+
isDirty$ = new BehaviorSubject(false);
|
|
2797
|
+
isValid$ = new BehaviorSubject(true);
|
|
2798
|
+
isBusy$ = new BehaviorSubject(false);
|
|
2799
|
+
constructor(registry, normalizer, factory, ctxValidators) {
|
|
2800
|
+
this.registry = registry;
|
|
2801
|
+
this.normalizer = normalizer;
|
|
2802
|
+
this.factory = factory;
|
|
2803
|
+
this.ctxValidators = ctxValidators;
|
|
2804
|
+
// Support SETTINGS_PANEL_DATA injection as input fallback
|
|
2805
|
+
const data = inject(SETTINGS_PANEL_DATA, { optional: true });
|
|
2806
|
+
if (data) {
|
|
2807
|
+
if (data.controlType)
|
|
2808
|
+
this.controlType = data.controlType;
|
|
2809
|
+
if (data.seed)
|
|
2810
|
+
this.seed = data.seed;
|
|
2811
|
+
// Bridge: allow host to receive patches even if saved$/applied$ are missed
|
|
2812
|
+
try {
|
|
2813
|
+
this.__hostApplyPatch = data.hostBridge?.applyPatch;
|
|
2814
|
+
}
|
|
2815
|
+
catch { }
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
ngOnInit() {
|
|
2819
|
+
try {
|
|
2820
|
+
const hasBridge = typeof this.__hostApplyPatch === 'function';
|
|
2821
|
+
(console.log || console.debug)('[FieldMetadataEditor] ngOnInit', { controlType: this.controlType, hasHostBridge: hasBridge });
|
|
2822
|
+
}
|
|
2823
|
+
catch { }
|
|
2824
|
+
this.rebuildEditorForType(this.controlType);
|
|
2825
|
+
}
|
|
2826
|
+
rebuildEditorForType(ct) {
|
|
2827
|
+
this.controlType = ct;
|
|
2828
|
+
let props = this.registry.getProperties(this.controlType);
|
|
2829
|
+
try {
|
|
2830
|
+
(console.log || console.debug)('[FieldMetadataEditor] init', {
|
|
2831
|
+
controlType: this.controlType,
|
|
2832
|
+
seedPreview: {
|
|
2833
|
+
resourcePath: this.seed?.resourcePath,
|
|
2834
|
+
optionLabelKey: this.seed?.optionLabelKey,
|
|
2835
|
+
optionValueKey: this.seed?.optionValueKey,
|
|
2836
|
+
filterCriteria: typeof this.seed?.filterCriteria === 'string'
|
|
2837
|
+
? this.seed?.filterCriteria
|
|
2838
|
+
: this.seed?.filterCriteria != null
|
|
2839
|
+
? JSON.stringify(this.seed?.filterCriteria)
|
|
2840
|
+
: undefined,
|
|
2841
|
+
},
|
|
2842
|
+
propsBefore: props.map((p) => p.name),
|
|
2843
|
+
});
|
|
2844
|
+
}
|
|
2845
|
+
catch { }
|
|
2846
|
+
// Fallback de registro mínimo para facilitar execução inicial
|
|
2847
|
+
if (!props.length) {
|
|
2848
|
+
if (this.controlType === FieldControlType.INPUT) {
|
|
2849
|
+
this.registry.register(this.controlType, inputProperties);
|
|
2850
|
+
props = inputProperties;
|
|
2851
|
+
}
|
|
2852
|
+
else if (
|
|
2853
|
+
// Aliases for select-like
|
|
2854
|
+
this.controlType === 'searchable-select' ||
|
|
2855
|
+
this.controlType === 'async-select') {
|
|
2856
|
+
this.registry.register(this.controlType, selectProperties);
|
|
2857
|
+
props = selectProperties;
|
|
2858
|
+
}
|
|
2859
|
+
else if (this.controlType === FieldControlType.NUMERIC_TEXT_BOX) {
|
|
2860
|
+
this.registry.register(this.controlType, numberProperties);
|
|
2861
|
+
props = numberProperties;
|
|
2862
|
+
}
|
|
2863
|
+
else if (this.controlType === FieldControlType.DATE_PICKER) {
|
|
2864
|
+
this.registry.register(this.controlType, dateProperties);
|
|
2865
|
+
props = dateProperties;
|
|
2866
|
+
}
|
|
2867
|
+
else if (this.controlType === FieldControlType.DATE_INPUT) {
|
|
2868
|
+
this.registry.register(this.controlType, dateInputProperties);
|
|
2869
|
+
props = dateInputProperties;
|
|
2870
|
+
}
|
|
2871
|
+
else if (this.controlType === FieldControlType.DATE_RANGE) {
|
|
2872
|
+
this.registry.register(this.controlType, dateRangeProperties);
|
|
2873
|
+
props = dateRangeProperties;
|
|
2874
|
+
}
|
|
2875
|
+
else if (this.controlType === FieldControlType.DATETIME_LOCAL_INPUT) {
|
|
2876
|
+
this.registry.register(this.controlType, datetimeLocalProperties);
|
|
2877
|
+
props = datetimeLocalProperties;
|
|
2878
|
+
}
|
|
2879
|
+
else if (this.controlType === FieldControlType.TIME_INPUT) {
|
|
2880
|
+
this.registry.register(this.controlType, timeInputProperties);
|
|
2881
|
+
props = timeInputProperties;
|
|
2882
|
+
}
|
|
2883
|
+
else if (this.controlType === FieldControlType.TIME_PICKER) {
|
|
2884
|
+
this.registry.register(this.controlType, timePickerProperties);
|
|
2885
|
+
props = timePickerProperties;
|
|
2886
|
+
}
|
|
2887
|
+
else if (this.controlType === FieldControlType.TIME_RANGE) {
|
|
2888
|
+
this.registry.register(this.controlType, timeRangeProperties);
|
|
2889
|
+
props = timeRangeProperties;
|
|
2890
|
+
}
|
|
2891
|
+
else if (this.controlType === FieldControlType.MONTH_INPUT) {
|
|
2892
|
+
this.registry.register(this.controlType, monthInputProperties);
|
|
2893
|
+
props = monthInputProperties;
|
|
2894
|
+
}
|
|
2895
|
+
else if (this.controlType === FieldControlType.WEEK_INPUT) {
|
|
2896
|
+
this.registry.register(this.controlType, weekInputProperties);
|
|
2897
|
+
props = weekInputProperties;
|
|
2898
|
+
}
|
|
2899
|
+
else if (this.controlType === FieldControlType.EMAIL_INPUT) {
|
|
2900
|
+
this.registry.register(this.controlType, emailInputProperties);
|
|
2901
|
+
props = emailInputProperties;
|
|
2902
|
+
}
|
|
2903
|
+
else if (this.controlType === FieldControlType.PASSWORD) {
|
|
2904
|
+
this.registry.register(this.controlType, passwordInputProperties);
|
|
2905
|
+
props = passwordInputProperties;
|
|
2906
|
+
}
|
|
2907
|
+
else if (this.controlType === FieldControlType.URL_INPUT) {
|
|
2908
|
+
this.registry.register(this.controlType, urlInputProperties);
|
|
2909
|
+
props = urlInputProperties;
|
|
2910
|
+
}
|
|
2911
|
+
else if (this.controlType === FieldControlType.SEARCH_INPUT) {
|
|
2912
|
+
this.registry.register(this.controlType, searchInputProperties);
|
|
2913
|
+
props = searchInputProperties;
|
|
2914
|
+
}
|
|
2915
|
+
else if (this.controlType === FieldControlType.PHONE) {
|
|
2916
|
+
this.registry.register(this.controlType, phoneInputProperties);
|
|
2917
|
+
props = phoneInputProperties;
|
|
2918
|
+
}
|
|
2919
|
+
else if (this.controlType === FieldControlType.COLOR_INPUT) {
|
|
2920
|
+
this.registry.register(this.controlType, colorInputProperties);
|
|
2921
|
+
props = colorInputProperties;
|
|
2922
|
+
}
|
|
2923
|
+
else if (this.controlType === FieldControlType.COLOR_PICKER) {
|
|
2924
|
+
this.registry.register(this.controlType, colorPickerProperties);
|
|
2925
|
+
props = colorPickerProperties;
|
|
2926
|
+
}
|
|
2927
|
+
else if (this.controlType === FieldControlType.RATING) {
|
|
2928
|
+
this.registry.register(this.controlType, ratingProperties);
|
|
2929
|
+
props = ratingProperties;
|
|
2930
|
+
}
|
|
2931
|
+
else if (this.controlType === FieldControlType.SELECT ||
|
|
2932
|
+
this.controlType === FieldControlType.MULTI_SELECT ||
|
|
2933
|
+
this.controlType === FieldControlType.AUTO_COMPLETE ||
|
|
2934
|
+
this.controlType === FieldControlType.SELECTION_LIST) {
|
|
2935
|
+
this.registry.register(this.controlType, selectProperties);
|
|
2936
|
+
props = selectProperties;
|
|
2937
|
+
}
|
|
2938
|
+
else if (this.controlType === FieldControlType.TEXTAREA) {
|
|
2939
|
+
this.registry.register(this.controlType, textareaProperties);
|
|
2940
|
+
props = textareaProperties;
|
|
2941
|
+
}
|
|
2942
|
+
else if (this.controlType === FieldControlType.TRANSFER_LIST) {
|
|
2943
|
+
this.registry.register(this.controlType, transferListProperties);
|
|
2944
|
+
props = transferListProperties;
|
|
2945
|
+
}
|
|
2946
|
+
else if (this.controlType === FieldControlType.RADIO) {
|
|
2947
|
+
this.registry.register(this.controlType, radioProperties);
|
|
2948
|
+
props = radioProperties;
|
|
2949
|
+
}
|
|
2950
|
+
else if (this.controlType === FieldControlType.BUTTON_TOGGLE) {
|
|
2951
|
+
this.registry.register(this.controlType, buttonToggleProperties);
|
|
2952
|
+
props = buttonToggleProperties;
|
|
2953
|
+
}
|
|
2954
|
+
else if (this.controlType === FieldControlType.CHIP_INPUT) {
|
|
2955
|
+
this.registry.register(this.controlType, chipInputProperties);
|
|
2956
|
+
props = chipInputProperties;
|
|
2957
|
+
}
|
|
2958
|
+
else if (this.controlType === FieldControlType.CHECKBOX) {
|
|
2959
|
+
this.registry.register(this.controlType, checkboxGroupProperties);
|
|
2960
|
+
props = checkboxGroupProperties;
|
|
2961
|
+
}
|
|
2962
|
+
else if (this.controlType === FieldControlType.TOGGLE) {
|
|
2963
|
+
this.registry.register(this.controlType, toggleProperties);
|
|
2964
|
+
props = toggleProperties;
|
|
2965
|
+
}
|
|
2966
|
+
else if (this.controlType === FieldControlType.SLIDER) {
|
|
2967
|
+
this.registry.register(this.controlType, sliderProperties);
|
|
2968
|
+
props = sliderProperties;
|
|
2969
|
+
}
|
|
2970
|
+
else if (this.controlType === FieldControlType.RANGE_SLIDER) {
|
|
2971
|
+
this.registry.register(this.controlType, rangeSliderProperties);
|
|
2972
|
+
props = rangeSliderProperties;
|
|
2973
|
+
}
|
|
2974
|
+
else if (this.controlType === FieldControlType.CURRENCY_INPUT) {
|
|
2975
|
+
this.registry.register(this.controlType, currencyInputProperties);
|
|
2976
|
+
props = currencyInputProperties;
|
|
2977
|
+
}
|
|
2978
|
+
else if (this.controlType === FieldControlType.CPF_CNPJ_INPUT) {
|
|
2979
|
+
this.registry.register(this.controlType, cpfCnpjProperties);
|
|
2980
|
+
props = cpfCnpjProperties;
|
|
2981
|
+
}
|
|
2982
|
+
else if (this.controlType === FieldControlType.FILE_UPLOAD) {
|
|
2983
|
+
this.registry.register(this.controlType, fileUploadProperties);
|
|
2984
|
+
props = fileUploadProperties;
|
|
2985
|
+
}
|
|
2986
|
+
else if (this.controlType === FieldControlType.YEAR_INPUT) {
|
|
2987
|
+
this.registry.register(this.controlType, yearInputProperties);
|
|
2988
|
+
props = yearInputProperties;
|
|
2989
|
+
}
|
|
2990
|
+
else if (this.controlType === FieldControlType.TREE_SELECT ||
|
|
2991
|
+
this.controlType === FieldControlType.MULTI_SELECT_TREE) {
|
|
2992
|
+
this.registry.register(this.controlType, treeSelectProperties);
|
|
2993
|
+
props = treeSelectProperties;
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
try {
|
|
2997
|
+
(console.log || console.debug)('[FieldMetadataEditor] props after registry resolution', {
|
|
2998
|
+
resolvedProps: props.map((p) => p.name),
|
|
2999
|
+
});
|
|
3000
|
+
}
|
|
3001
|
+
catch { }
|
|
3002
|
+
// Inject controlType selector into 'Geral' group so users can change field type
|
|
3003
|
+
try {
|
|
3004
|
+
const typeProp = {
|
|
3005
|
+
name: 'controlType',
|
|
3006
|
+
label: 'Tipo de campo',
|
|
3007
|
+
editorType: 'select',
|
|
3008
|
+
group: 'Geral',
|
|
3009
|
+
// Destaque visual e aviso claro sobre risco
|
|
3010
|
+
prefixIcon: 'warning',
|
|
3011
|
+
hint: '⚠️ Alterar o tipo de campo NÃO altera o tipo de dado na API. ' +
|
|
3012
|
+
'Isso pode causar erro ao salvar se o formato esperado for diferente.',
|
|
3013
|
+
options: this.typeOptions.map((o) => ({ value: o.value, text: o.label })),
|
|
3014
|
+
defaultValue: this.controlType,
|
|
3015
|
+
};
|
|
3016
|
+
props = [typeProp, ...props];
|
|
3017
|
+
}
|
|
3018
|
+
catch { }
|
|
3019
|
+
this.normalizedProps = this.normalizer.normalize(props, this.seed);
|
|
3020
|
+
try {
|
|
3021
|
+
console.debug('[FieldMetadataEditor] normalized props', {
|
|
3022
|
+
propNames: this.normalizedProps.map((p) => p.name),
|
|
3023
|
+
defaults: this.normalizedProps
|
|
3024
|
+
.filter((p) => ['resourcePath', 'filterCriteria', 'optionLabelKey', 'optionValueKey'].includes(p.name))
|
|
3025
|
+
.map((p) => ({ name: p.name, defaultValue: p.defaultValue })),
|
|
3026
|
+
optionsDefault: (() => {
|
|
3027
|
+
const opt = this.normalizedProps.find((p) => p.name === 'options');
|
|
3028
|
+
if (!opt)
|
|
3029
|
+
return undefined;
|
|
3030
|
+
const v = opt.defaultValue;
|
|
3031
|
+
return {
|
|
3032
|
+
type: v == null ? 'null' : typeof v,
|
|
3033
|
+
preview: typeof v === 'string' ? String(v).slice(0, 80) : undefined,
|
|
3034
|
+
lengthOrCount: Array.isArray(v)
|
|
3035
|
+
? v.length
|
|
3036
|
+
: (typeof v === 'string' ? v.length : undefined),
|
|
3037
|
+
};
|
|
3038
|
+
})(),
|
|
3039
|
+
});
|
|
3040
|
+
}
|
|
3041
|
+
catch { }
|
|
3042
|
+
// Inject default for providerOptions from seed.options when present (radio/editor-friendly name)
|
|
3043
|
+
try {
|
|
3044
|
+
const hasProviderOptions = this.normalizedProps.some((p) => p.name === 'providerOptions');
|
|
3045
|
+
const seedOptions = this.seed?.options;
|
|
3046
|
+
if (hasProviderOptions && seedOptions !== undefined) {
|
|
3047
|
+
const v = typeof seedOptions === 'string' ? seedOptions : (() => { try {
|
|
3048
|
+
return JSON.stringify(seedOptions, null, 2);
|
|
3049
|
+
}
|
|
3050
|
+
catch {
|
|
3051
|
+
return String(seedOptions);
|
|
3052
|
+
} })();
|
|
3053
|
+
this.normalizedProps = this.normalizedProps.map((p) => p.name === 'providerOptions' && p.defaultValue === undefined ? { ...p, defaultValue: v } : p);
|
|
3054
|
+
(console.log || console.debug)('[FieldMetadataEditor] providerOptions default injected from seed.options', {
|
|
3055
|
+
type: typeof seedOptions,
|
|
3056
|
+
lengthOrCount: Array.isArray(seedOptions) ? seedOptions.length : (typeof seedOptions === 'string' ? seedOptions.length : undefined),
|
|
3057
|
+
});
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
catch { }
|
|
3061
|
+
// Register contextual validators for INPUT/TEXTAREA (minLength <= maxLength)
|
|
3062
|
+
if (this.controlType === FieldControlType.INPUT ||
|
|
3063
|
+
this.controlType === FieldControlType.TEXTAREA) {
|
|
3064
|
+
const existing = this.ctxValidators.get(this.controlType);
|
|
3065
|
+
if (!existing.includes(minLenLeMaxLen)) {
|
|
3066
|
+
this.ctxValidators.register(this.controlType, minLenLeMaxLen);
|
|
3067
|
+
}
|
|
3068
|
+
}
|
|
3069
|
+
this.form = this.factory.createEditorForm(this.controlType, this.normalizedProps, this.seed);
|
|
3070
|
+
// Apply seed values into the form controls (only non-null/undefined)
|
|
3071
|
+
try {
|
|
3072
|
+
const getByPath = (obj, path) => {
|
|
3073
|
+
if (!obj || typeof obj !== 'object')
|
|
3074
|
+
return undefined;
|
|
3075
|
+
if (!path || typeof path !== 'string')
|
|
3076
|
+
return undefined;
|
|
3077
|
+
const parts = path.split('.');
|
|
3078
|
+
let curr = obj;
|
|
3079
|
+
for (const k of parts) {
|
|
3080
|
+
if (curr == null)
|
|
3081
|
+
return undefined;
|
|
3082
|
+
curr = curr[k];
|
|
3083
|
+
}
|
|
3084
|
+
return curr;
|
|
3085
|
+
};
|
|
3086
|
+
const subset = {};
|
|
3087
|
+
for (const p of this.normalizedProps || []) {
|
|
3088
|
+
const name = p?.name;
|
|
3089
|
+
if (!name)
|
|
3090
|
+
continue;
|
|
3091
|
+
const val = getByPath(this.seed, name);
|
|
3092
|
+
// Preserve false/0; skip only null/undefined
|
|
3093
|
+
if (val !== undefined && val !== null) {
|
|
3094
|
+
this.factory.setValueByPath(this.form, name, val);
|
|
3095
|
+
subset[name] = val;
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
// Also patch the form in a single call to ensure UI reflects values immediately
|
|
3099
|
+
try {
|
|
3100
|
+
this.form.patchValue(subset, { emitEvent: false });
|
|
3101
|
+
}
|
|
3102
|
+
catch { }
|
|
3103
|
+
// Diagnostics for Rating seeding after applying seed → form
|
|
3104
|
+
try {
|
|
3105
|
+
const ctU = String(this.controlType || '').toUpperCase();
|
|
3106
|
+
if (ctU === String(FieldControlType.RATING)) {
|
|
3107
|
+
const pick = (k) => this.form.get(k)?.value;
|
|
3108
|
+
console.debug('[FieldMetadataEditor][RATING] seeded form values', {
|
|
3109
|
+
max: pick('max'),
|
|
3110
|
+
allowHalf: pick('allowHalf'),
|
|
3111
|
+
selection: pick('selection'),
|
|
3112
|
+
size: pick('size'),
|
|
3113
|
+
icon: pick('icon'),
|
|
3114
|
+
emptyIcon: pick('emptyIcon'),
|
|
3115
|
+
svgIcon: pick('svgIcon'),
|
|
3116
|
+
svgIconOutline: pick('svgIconOutline'),
|
|
3117
|
+
ratingColor: pick('ratingColor'),
|
|
3118
|
+
outlineColor: pick('outlineColor'),
|
|
3119
|
+
readonly: pick('readonly'),
|
|
3120
|
+
tabIndex: pick('tabIndex'),
|
|
3121
|
+
ariaLabel: pick('ariaLabel'),
|
|
3122
|
+
});
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
catch { }
|
|
3126
|
+
}
|
|
3127
|
+
catch { }
|
|
3128
|
+
// Diagnostics: dump initial values for Rating editor
|
|
3129
|
+
try {
|
|
3130
|
+
const ctU = String(this.controlType || '').toUpperCase();
|
|
3131
|
+
if (ctU === String(FieldControlType.RATING)) {
|
|
3132
|
+
const pick = (k) => this.form.get(k)?.value;
|
|
3133
|
+
console.debug('[FieldMetadataEditor][RATING] initial form values', {
|
|
3134
|
+
max: pick('max'),
|
|
3135
|
+
allowHalf: pick('allowHalf'),
|
|
3136
|
+
selection: pick('selection'),
|
|
3137
|
+
size: pick('size'),
|
|
3138
|
+
icon: pick('icon'),
|
|
3139
|
+
emptyIcon: pick('emptyIcon'),
|
|
3140
|
+
svgIcon: pick('svgIcon'),
|
|
3141
|
+
svgIconOutline: pick('svgIconOutline'),
|
|
3142
|
+
ratingColor: pick('ratingColor'),
|
|
3143
|
+
outlineColor: pick('outlineColor'),
|
|
3144
|
+
readonly: pick('readonly'),
|
|
3145
|
+
tabIndex: pick('tabIndex'),
|
|
3146
|
+
ariaLabel: pick('ariaLabel'),
|
|
3147
|
+
});
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
catch { }
|
|
3151
|
+
// track validity/dirty with snapshot-based detection (avoid false dirty on init)
|
|
3152
|
+
this.isValid$.next(this.form.valid);
|
|
3153
|
+
this.form.statusChanges.subscribe(() => this.isValid$.next(this.form.valid));
|
|
3154
|
+
this.form.valueChanges.subscribe((val) => {
|
|
3155
|
+
if (!this.baselineReady) {
|
|
3156
|
+
// Ignore initial churn until baseline is captured
|
|
3157
|
+
return;
|
|
3158
|
+
}
|
|
3159
|
+
if (this.initialSnapshot == null) {
|
|
3160
|
+
this.initialSnapshot = val;
|
|
3161
|
+
if (this.isDirty$.value)
|
|
3162
|
+
this.isDirty$.next(false);
|
|
3163
|
+
try {
|
|
3164
|
+
(console.log || console.debug)('[FieldMetadataEditor] baseline set from first stable value');
|
|
3165
|
+
}
|
|
3166
|
+
catch { }
|
|
3167
|
+
return;
|
|
3168
|
+
}
|
|
3169
|
+
let same = false;
|
|
3170
|
+
try {
|
|
3171
|
+
same = JSON.stringify(val) === JSON.stringify(this.initialSnapshot);
|
|
3172
|
+
}
|
|
3173
|
+
catch {
|
|
3174
|
+
same = false;
|
|
3175
|
+
}
|
|
3176
|
+
const dirty = !same;
|
|
3177
|
+
if (dirty !== this.isDirty$.value) {
|
|
3178
|
+
try {
|
|
3179
|
+
(console.log || console.debug)('[FieldMetadataEditor] dirty ->', dirty);
|
|
3180
|
+
}
|
|
3181
|
+
catch { }
|
|
3182
|
+
this.isDirty$.next(dirty);
|
|
3183
|
+
}
|
|
3184
|
+
});
|
|
3185
|
+
// Defer baseline capture until next tick to absorb any programmatic value patches
|
|
3186
|
+
setTimeout(() => {
|
|
3187
|
+
try {
|
|
3188
|
+
this.initialSnapshot = this.form.getRawValue();
|
|
3189
|
+
this.baselineReady = true;
|
|
3190
|
+
if (this.isDirty$.value)
|
|
3191
|
+
this.isDirty$.next(false);
|
|
3192
|
+
(console.log || console.debug)('[FieldMetadataEditor] baseline captured (deferred)');
|
|
3193
|
+
}
|
|
3194
|
+
catch {
|
|
3195
|
+
this.baselineReady = true;
|
|
3196
|
+
}
|
|
3197
|
+
}, 0);
|
|
3198
|
+
}
|
|
3199
|
+
apply() {
|
|
3200
|
+
const raw = this.factory.extractPatch(this.form);
|
|
3201
|
+
const patch = this.buildDeltaPatch(raw, this.initialSnapshot);
|
|
3202
|
+
// Map editor-friendly 'providerOptions' back to canonical 'options'
|
|
3203
|
+
if (patch && patch.providerOptions !== undefined && patch.options === undefined) {
|
|
3204
|
+
patch.options = patch.providerOptions;
|
|
3205
|
+
delete patch.providerOptions;
|
|
3206
|
+
}
|
|
3207
|
+
// Sempre incluir controlType no patch quando presente
|
|
3208
|
+
patch.controlType = this.controlType;
|
|
3209
|
+
try {
|
|
3210
|
+
console.debug('[FieldMetadataEditor] apply() patch', patch);
|
|
3211
|
+
}
|
|
3212
|
+
catch { }
|
|
3213
|
+
try {
|
|
3214
|
+
const fn = this.__hostApplyPatch;
|
|
3215
|
+
if (typeof fn === 'function')
|
|
3216
|
+
fn(patch);
|
|
3217
|
+
}
|
|
3218
|
+
catch { }
|
|
3219
|
+
this.applied.emit(patch);
|
|
3220
|
+
}
|
|
3221
|
+
onSave() {
|
|
3222
|
+
return this.getSettingsValue();
|
|
3223
|
+
}
|
|
3224
|
+
// Settings Panel value provider API
|
|
3225
|
+
getSettingsValue() {
|
|
3226
|
+
const raw = this.factory.extractPatch(this.form);
|
|
3227
|
+
const patch = this.buildDeltaPatch(raw, this.initialSnapshot);
|
|
3228
|
+
if (patch && patch.providerOptions !== undefined && patch.options === undefined) {
|
|
3229
|
+
patch.options = patch.providerOptions;
|
|
3230
|
+
delete patch.providerOptions;
|
|
3231
|
+
}
|
|
3232
|
+
patch.controlType = this.controlType;
|
|
3233
|
+
try {
|
|
3234
|
+
console.debug('[FieldMetadataEditor] getSettingsValue() patch', patch);
|
|
3235
|
+
}
|
|
3236
|
+
catch { }
|
|
3237
|
+
return patch;
|
|
3238
|
+
}
|
|
3239
|
+
/**
|
|
3240
|
+
* Constrói um patch delta a partir do valor atual do form, removendo
|
|
3241
|
+
* chaves não alteradas e valores nulos/strings vazias (exceto boolean/zero).
|
|
3242
|
+
*/
|
|
3243
|
+
buildDeltaPatch(current, baseline) {
|
|
3244
|
+
try {
|
|
3245
|
+
const isObject = (v) => v != null && typeof v === 'object' && !Array.isArray(v);
|
|
3246
|
+
const changed = {};
|
|
3247
|
+
const keys = Object.keys(current || {});
|
|
3248
|
+
for (const k of keys) {
|
|
3249
|
+
const cv = current[k];
|
|
3250
|
+
const bv = baseline ? baseline[k] : undefined;
|
|
3251
|
+
const isNullish = cv === null || cv === undefined;
|
|
3252
|
+
const isEmptyString = typeof cv === 'string' && cv.trim() === '';
|
|
3253
|
+
// Preservar false/0 explicitamente; descartar null/undefined e strings vazias
|
|
3254
|
+
if (isNullish || isEmptyString)
|
|
3255
|
+
continue;
|
|
3256
|
+
if (isObject(cv)) {
|
|
3257
|
+
const nested = this.buildDeltaPatch(cv, isObject(bv) ? bv : undefined);
|
|
3258
|
+
if (nested && Object.keys(nested).length)
|
|
3259
|
+
changed[k] = nested;
|
|
3260
|
+
}
|
|
3261
|
+
else {
|
|
3262
|
+
// Incluir apenas se mudou em relação ao baseline ou se baseline não existe
|
|
3263
|
+
if (baseline === null || baseline === undefined || cv !== bv) {
|
|
3264
|
+
changed[k] = cv;
|
|
3265
|
+
}
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
return changed;
|
|
3269
|
+
}
|
|
3270
|
+
catch {
|
|
3271
|
+
// Fallback: retornar current quando algo falhar (melhor do que perder patch)
|
|
3272
|
+
return current;
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3275
|
+
reset() {
|
|
3276
|
+
this.form.reset(this.factory.extractPatch(this.form));
|
|
3277
|
+
this.isDirty$.next(false);
|
|
3278
|
+
}
|
|
3279
|
+
onControlTypeChange(next) {
|
|
3280
|
+
this.rebuildEditorForType(next);
|
|
3281
|
+
this.isDirty$.next(true);
|
|
3282
|
+
}
|
|
3283
|
+
// Template-safe change handler (avoid TS casts in template)
|
|
3284
|
+
onControlTypeChangeEvent(event) {
|
|
3285
|
+
const value = event.target?.value;
|
|
3286
|
+
if (value != null)
|
|
3287
|
+
this.onControlTypeChange(value);
|
|
3288
|
+
}
|
|
3289
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FieldMetadataEditorComponent, deps: [{ token: ConfigRegistryService }, { token: SchemaNormalizerService }, { token: DynamicFormFactoryService }, { token: ContextValidatorRegistryService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3290
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: FieldMetadataEditorComponent, isStandalone: true, selector: "praxis-field-metadata-editor", inputs: { controlType: "controlType", seed: "seed" }, outputs: { applied: "applied", cancel: "cancel" }, ngImport: i0, template: `
|
|
3291
|
+
<div class="p-3" *ngIf="form">
|
|
3292
|
+
<praxis-dynamic-editor-renderer
|
|
3293
|
+
[properties]="normalizedProps"
|
|
3294
|
+
[form]="form"
|
|
3295
|
+
></praxis-dynamic-editor-renderer>
|
|
3296
|
+
</div>
|
|
3297
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: DynamicEditorRendererComponent, selector: "praxis-dynamic-editor-renderer", inputs: ["properties", "form"] }] });
|
|
3298
|
+
}
|
|
3299
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FieldMetadataEditorComponent, decorators: [{
|
|
3300
|
+
type: Component,
|
|
3301
|
+
args: [{
|
|
3302
|
+
selector: 'praxis-field-metadata-editor',
|
|
3303
|
+
standalone: true,
|
|
3304
|
+
imports: [CommonModule, ReactiveFormsModule, DynamicEditorRendererComponent],
|
|
3305
|
+
template: `
|
|
3306
|
+
<div class="p-3" *ngIf="form">
|
|
3307
|
+
<praxis-dynamic-editor-renderer
|
|
3308
|
+
[properties]="normalizedProps"
|
|
3309
|
+
[form]="form"
|
|
3310
|
+
></praxis-dynamic-editor-renderer>
|
|
3311
|
+
</div>
|
|
3312
|
+
`,
|
|
3313
|
+
}]
|
|
3314
|
+
}], ctorParameters: () => [{ type: ConfigRegistryService }, { type: SchemaNormalizerService }, { type: DynamicFormFactoryService }, { type: ContextValidatorRegistryService }], propDecorators: { controlType: [{
|
|
3315
|
+
type: Input
|
|
3316
|
+
}], seed: [{
|
|
3317
|
+
type: Input
|
|
3318
|
+
}], applied: [{
|
|
3319
|
+
type: Output
|
|
3320
|
+
}], cancel: [{
|
|
3321
|
+
type: Output
|
|
3322
|
+
}] } });
|
|
3323
|
+
|
|
3324
|
+
class CascadeRulesService {
|
|
3325
|
+
getFieldLabelMap(fields) {
|
|
3326
|
+
const map = new Map();
|
|
3327
|
+
fields.forEach((f) => map.set(f.name, f.label || f.name));
|
|
3328
|
+
return map;
|
|
3329
|
+
}
|
|
3330
|
+
hydrateRule(field) {
|
|
3331
|
+
const deps = field.dependencyFields;
|
|
3332
|
+
if (!deps || deps.length === 0)
|
|
3333
|
+
return null;
|
|
3334
|
+
const vm = {
|
|
3335
|
+
targetField: field.name,
|
|
3336
|
+
dependencyFields: [...deps],
|
|
3337
|
+
enableDependencyCascade: field.enableDependencyCascade === false ? false : true,
|
|
3338
|
+
resetOnDependentChange: !!field.resetOnDependentChange,
|
|
3339
|
+
dependencyFilterMap: field.dependencyFilterMap || null,
|
|
3340
|
+
dependencyValuePath: field.dependencyValuePath || null,
|
|
3341
|
+
dependencyMergeStrategy: field.dependencyMergeStrategy || 'merge',
|
|
3342
|
+
dependencyDebounceMs: field.dependencyDebounceMs != null
|
|
3343
|
+
? Number(field.dependencyDebounceMs)
|
|
3344
|
+
: 150,
|
|
3345
|
+
dependencyLoadOnChange: field.dependencyLoadOnChange || 'respectLoadOn',
|
|
3346
|
+
};
|
|
3347
|
+
return vm;
|
|
3348
|
+
}
|
|
3349
|
+
dehydratePatch(rule) {
|
|
3350
|
+
const patch = {
|
|
3351
|
+
dependencyFields: rule.dependencyFields,
|
|
3352
|
+
enableDependencyCascade: rule.enableDependencyCascade,
|
|
3353
|
+
resetOnDependentChange: rule.resetOnDependentChange,
|
|
3354
|
+
dependencyMergeStrategy: rule.dependencyMergeStrategy || 'merge',
|
|
3355
|
+
dependencyLoadOnChange: rule.dependencyLoadOnChange || 'respectLoadOn',
|
|
3356
|
+
};
|
|
3357
|
+
if (rule.dependencyFilterMap != null)
|
|
3358
|
+
patch.dependencyFilterMap = rule.dependencyFilterMap;
|
|
3359
|
+
if (rule.dependencyValuePath != null)
|
|
3360
|
+
patch.dependencyValuePath = rule.dependencyValuePath;
|
|
3361
|
+
if (rule.dependencyDebounceMs != null)
|
|
3362
|
+
patch.dependencyDebounceMs = Number(rule.dependencyDebounceMs);
|
|
3363
|
+
return patch;
|
|
3364
|
+
}
|
|
3365
|
+
/** Suggest a basic mapping dep->dep and a default valuePath */
|
|
3366
|
+
suggest(rule, inferredValueKey) {
|
|
3367
|
+
const map = {};
|
|
3368
|
+
(rule.dependencyFields || []).forEach((dep) => (map[dep] = dep));
|
|
3369
|
+
return {
|
|
3370
|
+
...rule,
|
|
3371
|
+
dependencyFilterMap: Object.keys(map).length ? map : rule.dependencyFilterMap,
|
|
3372
|
+
dependencyValuePath: rule.dependencyValuePath || inferredValueKey || 'id',
|
|
3373
|
+
};
|
|
3374
|
+
}
|
|
3375
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: CascadeRulesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
3376
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: CascadeRulesService, providedIn: 'root' });
|
|
3377
|
+
}
|
|
3378
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: CascadeRulesService, decorators: [{
|
|
3379
|
+
type: Injectable,
|
|
3380
|
+
args: [{ providedIn: 'root' }]
|
|
3381
|
+
}] });
|
|
3382
|
+
|
|
3383
|
+
class CascadeManagerTabComponent {
|
|
3384
|
+
svc;
|
|
3385
|
+
fields = [];
|
|
3386
|
+
connections; // optional signal for conflicts
|
|
3387
|
+
apply = new EventEmitter();
|
|
3388
|
+
cancel = new EventEmitter();
|
|
3389
|
+
searchTerm = '';
|
|
3390
|
+
searchTimer = null;
|
|
3391
|
+
searchValue = '';
|
|
3392
|
+
rules = signal(new Map(), ...(ngDevMode ? [{ debugName: "rules" }] : []));
|
|
3393
|
+
selectedFieldSig = signal(null, ...(ngDevMode ? [{ debugName: "selectedFieldSig" }] : []));
|
|
3394
|
+
// Inline editor state (MVP)
|
|
3395
|
+
editing = signal(false, ...(ngDevMode ? [{ debugName: "editing" }] : []));
|
|
3396
|
+
editDepCsv = '';
|
|
3397
|
+
editEnable = true;
|
|
3398
|
+
editReset = false;
|
|
3399
|
+
editMerge = 'merge';
|
|
3400
|
+
editLoadOn = 'respectLoadOn';
|
|
3401
|
+
editDebounce = 150;
|
|
3402
|
+
editValuePath = '';
|
|
3403
|
+
editFilterMapJson = '';
|
|
3404
|
+
importMode = false;
|
|
3405
|
+
importJson = '';
|
|
3406
|
+
editMapRows = [];
|
|
3407
|
+
constructor(svc) {
|
|
3408
|
+
this.svc = svc;
|
|
3409
|
+
}
|
|
3410
|
+
ngOnInit() {
|
|
3411
|
+
// hydrate from input fields
|
|
3412
|
+
const map = new Map();
|
|
3413
|
+
for (const f of this.fields) {
|
|
3414
|
+
const vm = this.svc.hydrateRule(f);
|
|
3415
|
+
if (vm)
|
|
3416
|
+
map.set(f.name, vm);
|
|
3417
|
+
}
|
|
3418
|
+
this.rules.set(map);
|
|
3419
|
+
if (!this.selectedFieldSig() && this.fields.length) {
|
|
3420
|
+
this.selectedFieldSig.set(this.fields[0].name);
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
ngOnChanges(changes) {
|
|
3424
|
+
if (changes['fields'] && !changes['fields'].firstChange) {
|
|
3425
|
+
// Re-hydrate rules from incoming fields while preserving existing ones when possible
|
|
3426
|
+
const incoming = this.fields || [];
|
|
3427
|
+
const next = new Map();
|
|
3428
|
+
// keep existing for fields still present
|
|
3429
|
+
for (const f of incoming) {
|
|
3430
|
+
const existing = this.rules().get(f.name);
|
|
3431
|
+
const hydrated = this.svc.hydrateRule(f);
|
|
3432
|
+
if (hydrated)
|
|
3433
|
+
next.set(f.name, hydrated);
|
|
3434
|
+
else if (existing)
|
|
3435
|
+
next.set(f.name, existing);
|
|
3436
|
+
}
|
|
3437
|
+
this.rules.set(next);
|
|
3438
|
+
// preserve selection if still valid
|
|
3439
|
+
const sel = this.selectedField();
|
|
3440
|
+
if (sel && !incoming.some((f) => f.name === sel)) {
|
|
3441
|
+
this.selectedFieldSig.set(incoming[0]?.name ?? null);
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
}
|
|
3445
|
+
filteredFields() {
|
|
3446
|
+
const q = (this.searchValue || '').toLowerCase();
|
|
3447
|
+
const labelMap = this.svc.getFieldLabelMap(this.fields);
|
|
3448
|
+
return this.fields
|
|
3449
|
+
.filter((f) => !q || f.name.toLowerCase().includes(q) || (labelMap.get(f.name) || '').toLowerCase().includes(q))
|
|
3450
|
+
.sort((a, b) => (labelMap.get(a.name) || a.name).localeCompare(labelMap.get(b.name) || b.name));
|
|
3451
|
+
}
|
|
3452
|
+
labelFor(name) {
|
|
3453
|
+
return this.svc.getFieldLabelMap(this.fields).get(name) || name;
|
|
3454
|
+
}
|
|
3455
|
+
selectedField() {
|
|
3456
|
+
return this.selectedFieldSig();
|
|
3457
|
+
}
|
|
3458
|
+
selectField(name) {
|
|
3459
|
+
this.selectedFieldSig.set(name);
|
|
3460
|
+
this.editing.set(false);
|
|
3461
|
+
}
|
|
3462
|
+
hasRule(name) {
|
|
3463
|
+
return this.rules().has(name);
|
|
3464
|
+
}
|
|
3465
|
+
ruleFor(name) {
|
|
3466
|
+
return this.rules().get(name) || null;
|
|
3467
|
+
}
|
|
3468
|
+
isCascadeEnabled(name) {
|
|
3469
|
+
return (this.ruleFor(name)?.enableDependencyCascade ?? true) === true;
|
|
3470
|
+
}
|
|
3471
|
+
loadOnChange(name) {
|
|
3472
|
+
return this.ruleFor(name)?.dependencyLoadOnChange || 'respectLoadOn';
|
|
3473
|
+
}
|
|
3474
|
+
hasConflict(name) {
|
|
3475
|
+
if (!this.connections)
|
|
3476
|
+
return false;
|
|
3477
|
+
return this.connections.some((c) => c.toFieldName === name && (c.toInputPath || '').includes('filterCriteria'));
|
|
3478
|
+
}
|
|
3479
|
+
startEdit(name) {
|
|
3480
|
+
const existing = this.ruleFor(name);
|
|
3481
|
+
const base = existing || {
|
|
3482
|
+
targetField: name,
|
|
3483
|
+
dependencyFields: [],
|
|
3484
|
+
enableDependencyCascade: true,
|
|
3485
|
+
resetOnDependentChange: false,
|
|
3486
|
+
dependencyFilterMap: {},
|
|
3487
|
+
dependencyValuePath: 'id',
|
|
3488
|
+
dependencyMergeStrategy: 'merge',
|
|
3489
|
+
dependencyDebounceMs: 150,
|
|
3490
|
+
dependencyLoadOnChange: 'respectLoadOn',
|
|
3491
|
+
};
|
|
3492
|
+
const suggested = this.svc.suggest(base, 'id');
|
|
3493
|
+
// Bind to inline editor
|
|
3494
|
+
this.editDepCsv = suggested.dependencyFields.join(',');
|
|
3495
|
+
this.editEnable = suggested.enableDependencyCascade;
|
|
3496
|
+
this.editReset = suggested.resetOnDependentChange;
|
|
3497
|
+
this.editMerge = suggested.dependencyMergeStrategy || 'merge';
|
|
3498
|
+
this.editLoadOn = suggested.dependencyLoadOnChange || 'respectLoadOn';
|
|
3499
|
+
this.editDebounce = suggested.dependencyDebounceMs ?? 150;
|
|
3500
|
+
this.editValuePath = (typeof suggested.dependencyValuePath === 'string' ? suggested.dependencyValuePath : 'id') || '';
|
|
3501
|
+
try {
|
|
3502
|
+
this.editFilterMapJson = suggested.dependencyFilterMap ? JSON.stringify(suggested.dependencyFilterMap, null, 2) : '';
|
|
3503
|
+
}
|
|
3504
|
+
catch {
|
|
3505
|
+
this.editFilterMapJson = '';
|
|
3506
|
+
}
|
|
3507
|
+
// Build mapping rows from dependencies
|
|
3508
|
+
this.buildMapRowsFromDeps();
|
|
3509
|
+
this.editing.set(true);
|
|
3510
|
+
}
|
|
3511
|
+
edit(name) { this.startEdit(name); }
|
|
3512
|
+
cancelEdit() { this.editing.set(false); }
|
|
3513
|
+
saveEdit(name) {
|
|
3514
|
+
// Build rule from editor
|
|
3515
|
+
const deps = (this.editDepCsv || '')
|
|
3516
|
+
.split(',')
|
|
3517
|
+
.map((s) => s.trim())
|
|
3518
|
+
.filter((s) => !!s && s !== name);
|
|
3519
|
+
// Build map from rows; fallback to JSON when provided
|
|
3520
|
+
let map = {};
|
|
3521
|
+
this.editMapRows.forEach((r) => { if (!r.key && r.dep)
|
|
3522
|
+
r.key = r.dep; if (r.dep)
|
|
3523
|
+
map[r.dep] = r.valuePath ? { key: r.key || r.dep, valuePath: r.valuePath } : (r.key || r.dep); });
|
|
3524
|
+
const raw = (this.editFilterMapJson || '').trim();
|
|
3525
|
+
if (raw) {
|
|
3526
|
+
try {
|
|
3527
|
+
const fromJson = JSON.parse(raw);
|
|
3528
|
+
map = { ...map, ...fromJson };
|
|
3529
|
+
}
|
|
3530
|
+
catch {
|
|
3531
|
+
alert('Mapeamento de filtros inválido (JSON)');
|
|
3532
|
+
return;
|
|
3533
|
+
}
|
|
3534
|
+
}
|
|
3535
|
+
const rule = {
|
|
3536
|
+
targetField: name,
|
|
3537
|
+
dependencyFields: deps,
|
|
3538
|
+
enableDependencyCascade: this.editEnable,
|
|
3539
|
+
resetOnDependentChange: this.editReset,
|
|
3540
|
+
dependencyFilterMap: map,
|
|
3541
|
+
dependencyValuePath: this.buildValuePathOverrides(deps),
|
|
3542
|
+
dependencyMergeStrategy: this.editMerge,
|
|
3543
|
+
dependencyDebounceMs: this.editDebounce ?? 150,
|
|
3544
|
+
dependencyLoadOnChange: this.editLoadOn,
|
|
3545
|
+
};
|
|
3546
|
+
const next = new Map(this.rules());
|
|
3547
|
+
next.set(name, rule);
|
|
3548
|
+
this.rules.set(next);
|
|
3549
|
+
this.emitPatch();
|
|
3550
|
+
this.editing.set(false);
|
|
3551
|
+
}
|
|
3552
|
+
remove(name) {
|
|
3553
|
+
const next = new Map(this.rules());
|
|
3554
|
+
next.delete(name);
|
|
3555
|
+
this.rules.set(next);
|
|
3556
|
+
// Removing means clearing the cascade-related keys; send empty patch
|
|
3557
|
+
const patch = {
|
|
3558
|
+
[name]: {
|
|
3559
|
+
dependencyFields: [],
|
|
3560
|
+
enableDependencyCascade: false,
|
|
3561
|
+
resetOnDependentChange: false,
|
|
3562
|
+
dependencyFilterMap: undefined,
|
|
3563
|
+
dependencyValuePath: undefined,
|
|
3564
|
+
dependencyMergeStrategy: undefined,
|
|
3565
|
+
dependencyDebounceMs: undefined,
|
|
3566
|
+
dependencyLoadOnChange: undefined,
|
|
3567
|
+
},
|
|
3568
|
+
};
|
|
3569
|
+
this.apply.emit(patch);
|
|
3570
|
+
}
|
|
3571
|
+
quickSet(name, action) {
|
|
3572
|
+
const current = this.ruleFor(name);
|
|
3573
|
+
if (!current)
|
|
3574
|
+
return;
|
|
3575
|
+
const next = { ...current };
|
|
3576
|
+
if (action === 'disable')
|
|
3577
|
+
next.enableDependencyCascade = false;
|
|
3578
|
+
if (action === 'manual')
|
|
3579
|
+
next.dependencyLoadOnChange = 'manual';
|
|
3580
|
+
const map = new Map(this.rules());
|
|
3581
|
+
map.set(name, next);
|
|
3582
|
+
this.rules.set(map);
|
|
3583
|
+
this.emitPatch();
|
|
3584
|
+
}
|
|
3585
|
+
emitPatch() {
|
|
3586
|
+
const out = {};
|
|
3587
|
+
for (const [name, rule] of this.rules()) {
|
|
3588
|
+
out[name] = this.svc.dehydratePatch(rule);
|
|
3589
|
+
}
|
|
3590
|
+
this.apply.emit(out);
|
|
3591
|
+
}
|
|
3592
|
+
// Phase 2 helpers
|
|
3593
|
+
onSearchChange(val) {
|
|
3594
|
+
this.searchTerm = val;
|
|
3595
|
+
if (this.searchTimer)
|
|
3596
|
+
clearTimeout(this.searchTimer);
|
|
3597
|
+
this.searchTimer = setTimeout(() => (this.searchValue = this.searchTerm), 150);
|
|
3598
|
+
}
|
|
3599
|
+
onFieldKeydown(event, name) {
|
|
3600
|
+
if (event.key === 'Enter') {
|
|
3601
|
+
this.edit(name);
|
|
3602
|
+
event.preventDefault();
|
|
3603
|
+
}
|
|
3604
|
+
if (event.key.toLowerCase() === 'd' && (event.ctrlKey || event.metaKey)) { /* duplicate placeholder */
|
|
3605
|
+
event.preventDefault();
|
|
3606
|
+
}
|
|
3607
|
+
if (event.key === 'Delete') {
|
|
3608
|
+
this.remove(name);
|
|
3609
|
+
event.preventDefault();
|
|
3610
|
+
}
|
|
3611
|
+
}
|
|
3612
|
+
hasField(name) { return this.fields.some((f) => f.name === name); }
|
|
3613
|
+
toggleImport() { this.importMode = !this.importMode; this.importJson = ''; }
|
|
3614
|
+
exportRules() {
|
|
3615
|
+
const out = {};
|
|
3616
|
+
for (const [name, rule] of this.rules())
|
|
3617
|
+
out[name] = this.svc.dehydratePatch(rule);
|
|
3618
|
+
const json = JSON.stringify(out, null, 2);
|
|
3619
|
+
try {
|
|
3620
|
+
navigator.clipboard?.writeText(json);
|
|
3621
|
+
}
|
|
3622
|
+
catch { }
|
|
3623
|
+
alert('Regras exportadas para a área de transferência.');
|
|
3624
|
+
}
|
|
3625
|
+
applyImport() {
|
|
3626
|
+
let obj;
|
|
3627
|
+
try {
|
|
3628
|
+
obj = JSON.parse(this.importJson || '{}');
|
|
3629
|
+
}
|
|
3630
|
+
catch {
|
|
3631
|
+
alert('JSON inválido');
|
|
3632
|
+
return;
|
|
3633
|
+
}
|
|
3634
|
+
const next = new Map(this.rules());
|
|
3635
|
+
Object.keys(obj || {}).forEach((field) => {
|
|
3636
|
+
const patch = obj[field] || {};
|
|
3637
|
+
const vm = this.svc.hydrateRule({ ...patch, name: field }) || {
|
|
3638
|
+
targetField: field,
|
|
3639
|
+
dependencyFields: patch.dependencyFields || [],
|
|
3640
|
+
enableDependencyCascade: patch.enableDependencyCascade !== false,
|
|
3641
|
+
resetOnDependentChange: !!patch.resetOnDependentChange,
|
|
3642
|
+
dependencyFilterMap: patch.dependencyFilterMap || {},
|
|
3643
|
+
dependencyValuePath: patch.dependencyValuePath || 'id',
|
|
3644
|
+
dependencyMergeStrategy: patch.dependencyMergeStrategy || 'merge',
|
|
3645
|
+
dependencyDebounceMs: patch.dependencyDebounceMs ?? 150,
|
|
3646
|
+
dependencyLoadOnChange: patch.dependencyLoadOnChange || 'respectLoadOn',
|
|
3647
|
+
};
|
|
3648
|
+
next.set(field, vm);
|
|
3649
|
+
});
|
|
3650
|
+
this.rules.set(next);
|
|
3651
|
+
this.emitPatch();
|
|
3652
|
+
this.importMode = false;
|
|
3653
|
+
}
|
|
3654
|
+
startTemplate(name, tpl) {
|
|
3655
|
+
const hasR = this.hasField('rotaId');
|
|
3656
|
+
const hasD = this.hasField('destinoReqId');
|
|
3657
|
+
const deps = tpl === 'rota-destino' ? (hasR ? ['rotaId'] : []) : (hasR && hasD ? ['rotaId', 'destinoReqId'] : []);
|
|
3658
|
+
this.editDepCsv = deps.join(',');
|
|
3659
|
+
this.editEnable = true;
|
|
3660
|
+
this.editReset = true;
|
|
3661
|
+
this.editMerge = 'merge';
|
|
3662
|
+
this.editLoadOn = 'respectLoadOn';
|
|
3663
|
+
this.editDebounce = 150;
|
|
3664
|
+
this.editValuePath = 'id';
|
|
3665
|
+
this.buildMapRowsFromDeps();
|
|
3666
|
+
this.editing.set(true);
|
|
3667
|
+
}
|
|
3668
|
+
buildMapRowsFromDeps() {
|
|
3669
|
+
const deps = (this.editDepCsv || '').split(',').map((s) => s.trim()).filter(Boolean);
|
|
3670
|
+
const existing = (() => { try {
|
|
3671
|
+
return JSON.parse(this.editFilterMapJson || '{}');
|
|
3672
|
+
}
|
|
3673
|
+
catch {
|
|
3674
|
+
return {};
|
|
3675
|
+
} })();
|
|
3676
|
+
this.editMapRows = deps.map((dep) => {
|
|
3677
|
+
const entry = existing[dep];
|
|
3678
|
+
if (!entry)
|
|
3679
|
+
return { dep, key: dep };
|
|
3680
|
+
if (typeof entry === 'string')
|
|
3681
|
+
return { dep, key: entry };
|
|
3682
|
+
return { dep, key: entry.key || dep, valuePath: entry.valuePath };
|
|
3683
|
+
});
|
|
3684
|
+
}
|
|
3685
|
+
buildValuePathOverrides(deps) {
|
|
3686
|
+
// If any row defines a valuePath, return a record; else return default string
|
|
3687
|
+
const record = {};
|
|
3688
|
+
this.editMapRows.forEach((r) => { if (r.valuePath)
|
|
3689
|
+
record[r.dep] = r.valuePath; });
|
|
3690
|
+
const hasAny = Object.keys(record).length > 0;
|
|
3691
|
+
return hasAny ? record : (this.editValuePath || 'id');
|
|
3692
|
+
}
|
|
3693
|
+
buildPreview() {
|
|
3694
|
+
try {
|
|
3695
|
+
const deps = (this.editDepCsv || '').split(',').map((s) => s.trim()).filter(Boolean);
|
|
3696
|
+
const frag = {};
|
|
3697
|
+
this.editMapRows.forEach((r) => {
|
|
3698
|
+
const example = r.valuePath ? 123 : 123; // simple placeholder id
|
|
3699
|
+
const parts = (r.key || r.dep).split('.');
|
|
3700
|
+
let ref = frag;
|
|
3701
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
3702
|
+
const p = parts[i];
|
|
3703
|
+
ref[p] = ref[p] || {};
|
|
3704
|
+
ref = ref[p];
|
|
3705
|
+
}
|
|
3706
|
+
ref[parts[parts.length - 1]] = example;
|
|
3707
|
+
});
|
|
3708
|
+
return JSON.stringify(frag, null, 2);
|
|
3709
|
+
}
|
|
3710
|
+
catch {
|
|
3711
|
+
return '{}';
|
|
3712
|
+
}
|
|
3713
|
+
}
|
|
3714
|
+
copyPreview() { try {
|
|
3715
|
+
navigator.clipboard?.writeText(this.buildPreview());
|
|
3716
|
+
}
|
|
3717
|
+
catch { } }
|
|
3718
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: CascadeManagerTabComponent, deps: [{ token: CascadeRulesService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3719
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: CascadeManagerTabComponent, isStandalone: true, selector: "praxis-cascade-manager-tab", inputs: { fields: "fields", connections: "connections" }, outputs: { apply: "apply", cancel: "cancel" }, usesOnChanges: true, ngImport: i0, template: `
|
|
3720
|
+
<div class="cm-root">
|
|
3721
|
+
<!-- Left: Fields list -->
|
|
3722
|
+
<div class="cm-left">
|
|
3723
|
+
<mat-form-field appearance="outline" class="cm-search" subscriptSizing="dynamic">
|
|
3724
|
+
<mat-label>Buscar campos</mat-label>
|
|
3725
|
+
<input matInput [ngModel]="searchTerm" (ngModelChange)="onSearchChange($event)">
|
|
3726
|
+
</mat-form-field>
|
|
3727
|
+
<ng-container *ngIf="fields.length <= 50; else vscroll">
|
|
3728
|
+
<div>
|
|
3729
|
+
<div *ngFor="let f of filteredFields()" (click)="selectField(f.name)" class="field-item" [class.selected]="f.name===selectedField()" tabindex="0" (keydown)="onFieldKeydown($event, f.name)">
|
|
3730
|
+
<div>
|
|
3731
|
+
<div>{{ labelFor(f.name) }}</div>
|
|
3732
|
+
<small style="opacity:.7">{{ f.name }}</small>
|
|
3733
|
+
</div>
|
|
3734
|
+
<div class="rule-badges" *ngIf="hasRule(f.name)">
|
|
3735
|
+
<span class="rule-badge b-active" *ngIf="isCascadeEnabled(f.name)">Ativo</span>
|
|
3736
|
+
<span class="rule-badge b-manual" *ngIf="loadOnChange(f.name)==='manual'">Manual</span>
|
|
3737
|
+
<span class="rule-badge b-immediate" *ngIf="loadOnChange(f.name)==='immediate'">Immediate</span>
|
|
3738
|
+
</div>
|
|
3739
|
+
</div>
|
|
3740
|
+
</div>
|
|
3741
|
+
</ng-container>
|
|
3742
|
+
<ng-template #vscroll>
|
|
3743
|
+
<cdk-virtual-scroll-viewport itemSize="44" style="height: calc(100vh - 240px)">
|
|
3744
|
+
<div *cdkVirtualFor="let f of filteredFields()" (click)="selectField(f.name)" class="field-item" [class.selected]="f.name===selectedField()" tabindex="0" (keydown)="onFieldKeydown($event, f.name)">
|
|
3745
|
+
<div>
|
|
3746
|
+
<div>{{ labelFor(f.name) }}</div>
|
|
3747
|
+
<small style="opacity:.7">{{ f.name }}</small>
|
|
3748
|
+
</div>
|
|
3749
|
+
<div class="rule-badges" *ngIf="hasRule(f.name)">
|
|
3750
|
+
<span class="rule-badge b-active" *ngIf="isCascadeEnabled(f.name)">Ativo</span>
|
|
3751
|
+
<span class="rule-badge b-manual" *ngIf="loadOnChange(f.name)==='manual'">Manual</span>
|
|
3752
|
+
<span class="rule-badge b-immediate" *ngIf="loadOnChange(f.name)==='immediate'">Immediate</span>
|
|
3753
|
+
</div>
|
|
3754
|
+
</div>
|
|
3755
|
+
</cdk-virtual-scroll-viewport>
|
|
3756
|
+
</ng-template>
|
|
3757
|
+
</div>
|
|
3758
|
+
|
|
3759
|
+
<!-- Right: Rules for selected field -->
|
|
3760
|
+
<div class="cm-right" *ngIf="selectedField() as sel">
|
|
3761
|
+
<div class="cm-header">
|
|
3762
|
+
<div>
|
|
3763
|
+
<h3 style="margin:0">{{ labelFor(sel) }}</h3>
|
|
3764
|
+
<div style="opacity:.7">{{ sel }}</div>
|
|
3765
|
+
</div>
|
|
3766
|
+
<div>
|
|
3767
|
+
<button mat-stroked-button color="primary" (click)="exportRules()" style="margin-right:8px">Exportar</button>
|
|
3768
|
+
<button mat-stroked-button (click)="toggleImport()" style="margin-right:8px">Importar</button>
|
|
3769
|
+
<button mat-flat-button color="primary" [matMenuTriggerFor]="addMenu" [disabled]="editing()">Adicionar</button>
|
|
3770
|
+
<mat-menu #addMenu="matMenu">
|
|
3771
|
+
<button mat-menu-item (click)="startEdit(sel)"><mat-icon [praxisIcon]="'add'"></mat-icon><span>Em branco</span></button>
|
|
3772
|
+
<button mat-menu-item (click)="startTemplate(sel, 'rota-destino')" [disabled]="!hasField('rotaId') || !hasField('destinoReqId')"><mat-icon [praxisIcon]="'bolt'"></mat-icon><span>Rota → Destino (id)</span></button>
|
|
3773
|
+
<button mat-menu-item (click)="startTemplate(sel, 'rota-destino-propriedade')" [disabled]="!hasField('rotaId') || !hasField('destinoReqId')"><mat-icon [praxisIcon]="'bolt'"></mat-icon><span>Rota + Destino → Propriedade (ids)</span></button>
|
|
3774
|
+
</mat-menu>
|
|
3775
|
+
</div>
|
|
3776
|
+
</div>
|
|
3777
|
+
|
|
3778
|
+
<!-- Conflict banner (connections) -->
|
|
3779
|
+
<div class="banner" *ngIf="hasConflict(sel)">
|
|
3780
|
+
<mat-icon [praxisIcon]="'link_off'"></mat-icon>
|
|
3781
|
+
<div>
|
|
3782
|
+
Connections atualizam este campo (filterCriteria). Considere desativar a cascata nativa ou usar ‘manual’.
|
|
3783
|
+
</div>
|
|
3784
|
+
<span class="spacer"></span>
|
|
3785
|
+
<button mat-stroked-button color="primary" (click)="quickSet(sel,'disable')">Desativar</button>
|
|
3786
|
+
<button mat-stroked-button color="accent" (click)="quickSet(sel,'manual')">Definir manual</button>
|
|
3787
|
+
</div>
|
|
3788
|
+
|
|
3789
|
+
<div *ngIf="importMode" class="import-panel">
|
|
3790
|
+
<div style="display:flex; gap:8px; align-items:center; margin-bottom:8px"><mat-icon [praxisIcon]="'upload'"></mat-icon><strong>Importar regras (JSON)</strong></div>
|
|
3791
|
+
<textarea matInput rows="6" class="full" [(ngModel)]="importJson" placeholder='{ "campo": { "dependencyFields": ["dep"], ... } }'></textarea>
|
|
3792
|
+
<div style="display:flex; gap:8px; justify-content:flex-end; padding-top:8px">
|
|
3793
|
+
<button mat-stroked-button (click)="toggleImport()">Cancelar</button>
|
|
3794
|
+
<button mat-flat-button color="primary" (click)="applyImport()">Aplicar</button>
|
|
3795
|
+
</div>
|
|
3796
|
+
</div>
|
|
3797
|
+
|
|
3798
|
+
<div *ngIf="!ruleFor(sel)">
|
|
3799
|
+
<div class="rules-empty">Nenhuma regra de cascata. Clique em “Adicionar”.</div>
|
|
3800
|
+
</div>
|
|
3801
|
+
<div *ngIf="ruleFor(sel) as rule">
|
|
3802
|
+
<div class="rule-row">
|
|
3803
|
+
<div>
|
|
3804
|
+
<div><strong>Dependentes:</strong> {{ rule.dependencyFields.join(', ') || '—' }}</div>
|
|
3805
|
+
<div style="opacity:.7">Load on change: {{ rule.dependencyLoadOnChange || 'respectLoadOn' }} | Merge: {{ rule.dependencyMergeStrategy || 'merge' }}</div>
|
|
3806
|
+
</div>
|
|
3807
|
+
<div class="rule-actions">
|
|
3808
|
+
<button mat-icon-button matTooltip="Editar" (click)="edit(sel)"><mat-icon [praxisIcon]="'edit'"></mat-icon></button>
|
|
3809
|
+
<button mat-icon-button matTooltip="Duplicar" disabled><mat-icon [praxisIcon]="'content_copy'"></mat-icon></button>
|
|
3810
|
+
<button mat-icon-button matTooltip="Remover" (click)="remove(sel)"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
3811
|
+
</div>
|
|
3812
|
+
</div>
|
|
3813
|
+
</div>
|
|
3814
|
+
|
|
3815
|
+
<!-- Editor com seções -->
|
|
3816
|
+
<mat-expansion-panel [expanded]="editing()">
|
|
3817
|
+
<mat-expansion-panel-header>
|
|
3818
|
+
<mat-panel-title>Edição de Regra</mat-panel-title>
|
|
3819
|
+
<mat-panel-description>Configurar dependentes, execução e mapeamento</mat-panel-description>
|
|
3820
|
+
</mat-expansion-panel-header>
|
|
3821
|
+
|
|
3822
|
+
<!-- Básico -->
|
|
3823
|
+
<mat-expansion-panel [expanded]="true">
|
|
3824
|
+
<mat-expansion-panel-header>
|
|
3825
|
+
<mat-panel-title>Básico</mat-panel-title>
|
|
3826
|
+
</mat-expansion-panel-header>
|
|
3827
|
+
<div class="form-grid">
|
|
3828
|
+
<div class="form-row">
|
|
3829
|
+
<mat-form-field appearance="outline" class="full">
|
|
3830
|
+
<mat-label>Dependentes (CSV)</mat-label>
|
|
3831
|
+
<input matInput [(ngModel)]="editDepCsv">
|
|
3832
|
+
<mat-hint>Ex.: rotaId,destinoReqId</mat-hint>
|
|
3833
|
+
</mat-form-field>
|
|
3834
|
+
</div>
|
|
3835
|
+
<div class="form-row">
|
|
3836
|
+
<mat-checkbox [(ngModel)]="editEnable">Ativar cascata nativa</mat-checkbox>
|
|
3837
|
+
<mat-checkbox [(ngModel)]="editReset">Resetar ao mudar</mat-checkbox>
|
|
3838
|
+
</div>
|
|
3839
|
+
</div>
|
|
3840
|
+
</mat-expansion-panel>
|
|
3841
|
+
|
|
3842
|
+
<!-- Execução -->
|
|
3843
|
+
<mat-expansion-panel>
|
|
3844
|
+
<mat-expansion-panel-header>
|
|
3845
|
+
<mat-panel-title>Execução</mat-panel-title>
|
|
3846
|
+
</mat-expansion-panel-header>
|
|
3847
|
+
<div class="form-row">
|
|
3848
|
+
<mat-form-field appearance="outline">
|
|
3849
|
+
<mat-label>Carregar ao mudar</mat-label>
|
|
3850
|
+
<mat-select [(ngModel)]="editLoadOn">
|
|
3851
|
+
<mat-option value="respectLoadOn">Respeitar loadOn</mat-option>
|
|
3852
|
+
<mat-option value="immediate">Imediato</mat-option>
|
|
3853
|
+
<mat-option value="manual">Manual</mat-option>
|
|
3854
|
+
</mat-select>
|
|
3855
|
+
</mat-form-field>
|
|
3856
|
+
<mat-form-field appearance="outline">
|
|
3857
|
+
<mat-label>Merge de filtros</mat-label>
|
|
3858
|
+
<mat-select [(ngModel)]="editMerge">
|
|
3859
|
+
<mat-option value="merge">merge (padrão)</mat-option>
|
|
3860
|
+
<mat-option value="replace">replace</mat-option>
|
|
3861
|
+
</mat-select>
|
|
3862
|
+
</mat-form-field>
|
|
3863
|
+
<mat-form-field appearance="outline">
|
|
3864
|
+
<mat-label>Atraso (ms)</mat-label>
|
|
3865
|
+
<input matInput type="number" [(ngModel)]="editDebounce">
|
|
3866
|
+
</mat-form-field>
|
|
3867
|
+
</div>
|
|
3868
|
+
</mat-expansion-panel>
|
|
3869
|
+
|
|
3870
|
+
<!-- Extração de valor -->
|
|
3871
|
+
<mat-expansion-panel>
|
|
3872
|
+
<mat-expansion-panel-header>
|
|
3873
|
+
<mat-panel-title>Extração de valor</mat-panel-title>
|
|
3874
|
+
</mat-expansion-panel-header>
|
|
3875
|
+
<div class="form-row">
|
|
3876
|
+
<mat-form-field appearance="outline" class="full">
|
|
3877
|
+
<mat-label>ValuePath padrão</mat-label>
|
|
3878
|
+
<input matInput [(ngModel)]="editValuePath" placeholder="id">
|
|
3879
|
+
<mat-hint>Preenchido automaticamente a partir de optionValueKey() ou 'id'</mat-hint>
|
|
3880
|
+
</mat-form-field>
|
|
3881
|
+
</div>
|
|
3882
|
+
</mat-expansion-panel>
|
|
3883
|
+
|
|
3884
|
+
<!-- Mapeamento de filtros (tabela) -->
|
|
3885
|
+
<mat-expansion-panel>
|
|
3886
|
+
<mat-expansion-panel-header>
|
|
3887
|
+
<mat-panel-title>Mapeamento de filtros</mat-panel-title>
|
|
3888
|
+
</mat-expansion-panel-header>
|
|
3889
|
+
<table class="map-table" *ngIf="editMapRows.length; else noMap">
|
|
3890
|
+
<thead>
|
|
3891
|
+
<tr>
|
|
3892
|
+
<th>Dependente</th>
|
|
3893
|
+
<th>Chave (dot‑path)</th>
|
|
3894
|
+
<th>ValuePath (opcional)</th>
|
|
3895
|
+
</tr>
|
|
3896
|
+
</thead>
|
|
3897
|
+
<tbody>
|
|
3898
|
+
<tr *ngFor="let row of editMapRows; let i = index">
|
|
3899
|
+
<td>{{ row.dep }}</td>
|
|
3900
|
+
<td>
|
|
3901
|
+
<input matInput [(ngModel)]="row.key" placeholder="{{row.dep}}">
|
|
3902
|
+
</td>
|
|
3903
|
+
<td>
|
|
3904
|
+
<input matInput [(ngModel)]="row.valuePath" placeholder="{{editValuePath||'id'}}">
|
|
3905
|
+
</td>
|
|
3906
|
+
</tr>
|
|
3907
|
+
</tbody>
|
|
3908
|
+
</table>
|
|
3909
|
+
<ng-template #noMap>
|
|
3910
|
+
<div class="rules-empty">Defina dependentes para sugerir o mapeamento.</div>
|
|
3911
|
+
</ng-template>
|
|
3912
|
+
</mat-expansion-panel>
|
|
3913
|
+
|
|
3914
|
+
<!-- Preview -->
|
|
3915
|
+
<mat-expansion-panel>
|
|
3916
|
+
<mat-expansion-panel-header>
|
|
3917
|
+
<mat-panel-title>Preview</mat-panel-title>
|
|
3918
|
+
</mat-expansion-panel-header>
|
|
3919
|
+
<pre style="white-space: pre-wrap; background:#fafafa; padding:8px; border:1px solid #eee; border-radius:6px">{{ buildPreview() }}</pre>
|
|
3920
|
+
<div style="display:flex; justify-content:flex-end; padding-top:6px">
|
|
3921
|
+
<button mat-stroked-button (click)="copyPreview()">Copiar</button>
|
|
3922
|
+
</div>
|
|
3923
|
+
</mat-expansion-panel>
|
|
3924
|
+
|
|
3925
|
+
<div style="display:flex; gap:8px; justify-content:flex-end; padding:8px 0;">
|
|
3926
|
+
<button mat-stroked-button (click)="cancelEdit()">Cancelar</button>
|
|
3927
|
+
<button mat-flat-button color="primary" (click)="saveEdit(sel)">Salvar</button>
|
|
3928
|
+
</div>
|
|
3929
|
+
</mat-expansion-panel>
|
|
3930
|
+
</div>
|
|
3931
|
+
</div>
|
|
3932
|
+
`, isInline: true, styles: [":host{display:block}.cm-root{display:grid;grid-template-columns:320px 1fr;gap:16px;min-height:420px}.cm-left{border-right:1px solid rgba(0,0,0,.06);padding-right:8px}.cm-search{width:100%;margin-bottom:8px}.cm-right{padding-left:8px}.field-item{display:flex;align-items:center;justify-content:space-between;padding:6px 4px;cursor:pointer;border-radius:6px}.field-item.selected{background:#0000000a}.rule-badges{display:inline-flex;gap:6px}.rule-badge{font-size:10px;padding:2px 6px;border-radius:10px}.b-active{background:#e8f5e9;color:#2e7d32}.b-manual{background:#eceff1;color:#455a64}.b-immediate{background:#fff3e0;color:#ef6c00}.b-conflict{background:#ffebee;color:#c62828}.cm-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.rules-empty{opacity:.7;font-style:italic;padding:8px 0}.rule-row{display:grid;grid-template-columns:1fr auto;align-items:center;padding:8px 0;border-bottom:1px dashed rgba(0,0,0,.06)}.rule-actions button{margin-left:4px}.banner{background:#fff8e1;color:#6d4c41;padding:8px 12px;border:1px solid #ffe082;border-radius:6px;margin-bottom:8px;display:flex;gap:8px;align-items:center}.import-panel{background:#f5f5f5;border:1px solid #e0e0e0;border-radius:6px;padding:8px;margin-bottom:8px}.full{width:100%}.form-row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.form-grid{display:grid;gap:12px;padding:8px 0}.map-table{width:100%;border-collapse:collapse}.map-table th,.map-table td{padding:6px 8px;border-bottom:1px dashed rgba(0,0,0,.06)}.kbd{font-family:monospace;background:#eee;padding:0 4px;border-radius:3px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.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: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i5$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i5$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i7.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatListModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i8$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i8$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i5.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i5.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i5.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i5.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i11.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i11.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i11.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i12.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: i12.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "component", type: i12.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }] });
|
|
3933
|
+
}
|
|
3934
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: CascadeManagerTabComponent, decorators: [{
|
|
3935
|
+
type: Component,
|
|
3936
|
+
args: [{ selector: 'praxis-cascade-manager-tab', standalone: true, imports: [
|
|
3937
|
+
CommonModule,
|
|
3938
|
+
ReactiveFormsModule,
|
|
3939
|
+
FormsModule,
|
|
3940
|
+
MatIconModule,
|
|
3941
|
+
MatButtonModule,
|
|
3942
|
+
MatTooltipModule,
|
|
3943
|
+
MatInputModule,
|
|
3944
|
+
MatChipsModule,
|
|
3945
|
+
MatListModule,
|
|
3946
|
+
MatDividerModule,
|
|
3947
|
+
MatSelectModule,
|
|
3948
|
+
MatCheckboxModule,
|
|
3949
|
+
MatExpansionModule,
|
|
3950
|
+
MatMenuModule,
|
|
3951
|
+
ScrollingModule,
|
|
3952
|
+
PraxisIconDirective,
|
|
3953
|
+
], template: `
|
|
3954
|
+
<div class="cm-root">
|
|
3955
|
+
<!-- Left: Fields list -->
|
|
3956
|
+
<div class="cm-left">
|
|
3957
|
+
<mat-form-field appearance="outline" class="cm-search" subscriptSizing="dynamic">
|
|
3958
|
+
<mat-label>Buscar campos</mat-label>
|
|
3959
|
+
<input matInput [ngModel]="searchTerm" (ngModelChange)="onSearchChange($event)">
|
|
3960
|
+
</mat-form-field>
|
|
3961
|
+
<ng-container *ngIf="fields.length <= 50; else vscroll">
|
|
3962
|
+
<div>
|
|
3963
|
+
<div *ngFor="let f of filteredFields()" (click)="selectField(f.name)" class="field-item" [class.selected]="f.name===selectedField()" tabindex="0" (keydown)="onFieldKeydown($event, f.name)">
|
|
3964
|
+
<div>
|
|
3965
|
+
<div>{{ labelFor(f.name) }}</div>
|
|
3966
|
+
<small style="opacity:.7">{{ f.name }}</small>
|
|
3967
|
+
</div>
|
|
3968
|
+
<div class="rule-badges" *ngIf="hasRule(f.name)">
|
|
3969
|
+
<span class="rule-badge b-active" *ngIf="isCascadeEnabled(f.name)">Ativo</span>
|
|
3970
|
+
<span class="rule-badge b-manual" *ngIf="loadOnChange(f.name)==='manual'">Manual</span>
|
|
3971
|
+
<span class="rule-badge b-immediate" *ngIf="loadOnChange(f.name)==='immediate'">Immediate</span>
|
|
3972
|
+
</div>
|
|
3973
|
+
</div>
|
|
3974
|
+
</div>
|
|
3975
|
+
</ng-container>
|
|
3976
|
+
<ng-template #vscroll>
|
|
3977
|
+
<cdk-virtual-scroll-viewport itemSize="44" style="height: calc(100vh - 240px)">
|
|
3978
|
+
<div *cdkVirtualFor="let f of filteredFields()" (click)="selectField(f.name)" class="field-item" [class.selected]="f.name===selectedField()" tabindex="0" (keydown)="onFieldKeydown($event, f.name)">
|
|
3979
|
+
<div>
|
|
3980
|
+
<div>{{ labelFor(f.name) }}</div>
|
|
3981
|
+
<small style="opacity:.7">{{ f.name }}</small>
|
|
3982
|
+
</div>
|
|
3983
|
+
<div class="rule-badges" *ngIf="hasRule(f.name)">
|
|
3984
|
+
<span class="rule-badge b-active" *ngIf="isCascadeEnabled(f.name)">Ativo</span>
|
|
3985
|
+
<span class="rule-badge b-manual" *ngIf="loadOnChange(f.name)==='manual'">Manual</span>
|
|
3986
|
+
<span class="rule-badge b-immediate" *ngIf="loadOnChange(f.name)==='immediate'">Immediate</span>
|
|
3987
|
+
</div>
|
|
3988
|
+
</div>
|
|
3989
|
+
</cdk-virtual-scroll-viewport>
|
|
3990
|
+
</ng-template>
|
|
3991
|
+
</div>
|
|
3992
|
+
|
|
3993
|
+
<!-- Right: Rules for selected field -->
|
|
3994
|
+
<div class="cm-right" *ngIf="selectedField() as sel">
|
|
3995
|
+
<div class="cm-header">
|
|
3996
|
+
<div>
|
|
3997
|
+
<h3 style="margin:0">{{ labelFor(sel) }}</h3>
|
|
3998
|
+
<div style="opacity:.7">{{ sel }}</div>
|
|
3999
|
+
</div>
|
|
4000
|
+
<div>
|
|
4001
|
+
<button mat-stroked-button color="primary" (click)="exportRules()" style="margin-right:8px">Exportar</button>
|
|
4002
|
+
<button mat-stroked-button (click)="toggleImport()" style="margin-right:8px">Importar</button>
|
|
4003
|
+
<button mat-flat-button color="primary" [matMenuTriggerFor]="addMenu" [disabled]="editing()">Adicionar</button>
|
|
4004
|
+
<mat-menu #addMenu="matMenu">
|
|
4005
|
+
<button mat-menu-item (click)="startEdit(sel)"><mat-icon [praxisIcon]="'add'"></mat-icon><span>Em branco</span></button>
|
|
4006
|
+
<button mat-menu-item (click)="startTemplate(sel, 'rota-destino')" [disabled]="!hasField('rotaId') || !hasField('destinoReqId')"><mat-icon [praxisIcon]="'bolt'"></mat-icon><span>Rota → Destino (id)</span></button>
|
|
4007
|
+
<button mat-menu-item (click)="startTemplate(sel, 'rota-destino-propriedade')" [disabled]="!hasField('rotaId') || !hasField('destinoReqId')"><mat-icon [praxisIcon]="'bolt'"></mat-icon><span>Rota + Destino → Propriedade (ids)</span></button>
|
|
4008
|
+
</mat-menu>
|
|
4009
|
+
</div>
|
|
4010
|
+
</div>
|
|
4011
|
+
|
|
4012
|
+
<!-- Conflict banner (connections) -->
|
|
4013
|
+
<div class="banner" *ngIf="hasConflict(sel)">
|
|
4014
|
+
<mat-icon [praxisIcon]="'link_off'"></mat-icon>
|
|
4015
|
+
<div>
|
|
4016
|
+
Connections atualizam este campo (filterCriteria). Considere desativar a cascata nativa ou usar ‘manual’.
|
|
4017
|
+
</div>
|
|
4018
|
+
<span class="spacer"></span>
|
|
4019
|
+
<button mat-stroked-button color="primary" (click)="quickSet(sel,'disable')">Desativar</button>
|
|
4020
|
+
<button mat-stroked-button color="accent" (click)="quickSet(sel,'manual')">Definir manual</button>
|
|
4021
|
+
</div>
|
|
4022
|
+
|
|
4023
|
+
<div *ngIf="importMode" class="import-panel">
|
|
4024
|
+
<div style="display:flex; gap:8px; align-items:center; margin-bottom:8px"><mat-icon [praxisIcon]="'upload'"></mat-icon><strong>Importar regras (JSON)</strong></div>
|
|
4025
|
+
<textarea matInput rows="6" class="full" [(ngModel)]="importJson" placeholder='{ "campo": { "dependencyFields": ["dep"], ... } }'></textarea>
|
|
4026
|
+
<div style="display:flex; gap:8px; justify-content:flex-end; padding-top:8px">
|
|
4027
|
+
<button mat-stroked-button (click)="toggleImport()">Cancelar</button>
|
|
4028
|
+
<button mat-flat-button color="primary" (click)="applyImport()">Aplicar</button>
|
|
4029
|
+
</div>
|
|
4030
|
+
</div>
|
|
4031
|
+
|
|
4032
|
+
<div *ngIf="!ruleFor(sel)">
|
|
4033
|
+
<div class="rules-empty">Nenhuma regra de cascata. Clique em “Adicionar”.</div>
|
|
4034
|
+
</div>
|
|
4035
|
+
<div *ngIf="ruleFor(sel) as rule">
|
|
4036
|
+
<div class="rule-row">
|
|
4037
|
+
<div>
|
|
4038
|
+
<div><strong>Dependentes:</strong> {{ rule.dependencyFields.join(', ') || '—' }}</div>
|
|
4039
|
+
<div style="opacity:.7">Load on change: {{ rule.dependencyLoadOnChange || 'respectLoadOn' }} | Merge: {{ rule.dependencyMergeStrategy || 'merge' }}</div>
|
|
4040
|
+
</div>
|
|
4041
|
+
<div class="rule-actions">
|
|
4042
|
+
<button mat-icon-button matTooltip="Editar" (click)="edit(sel)"><mat-icon [praxisIcon]="'edit'"></mat-icon></button>
|
|
4043
|
+
<button mat-icon-button matTooltip="Duplicar" disabled><mat-icon [praxisIcon]="'content_copy'"></mat-icon></button>
|
|
4044
|
+
<button mat-icon-button matTooltip="Remover" (click)="remove(sel)"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
4045
|
+
</div>
|
|
4046
|
+
</div>
|
|
4047
|
+
</div>
|
|
4048
|
+
|
|
4049
|
+
<!-- Editor com seções -->
|
|
4050
|
+
<mat-expansion-panel [expanded]="editing()">
|
|
4051
|
+
<mat-expansion-panel-header>
|
|
4052
|
+
<mat-panel-title>Edição de Regra</mat-panel-title>
|
|
4053
|
+
<mat-panel-description>Configurar dependentes, execução e mapeamento</mat-panel-description>
|
|
4054
|
+
</mat-expansion-panel-header>
|
|
4055
|
+
|
|
4056
|
+
<!-- Básico -->
|
|
4057
|
+
<mat-expansion-panel [expanded]="true">
|
|
4058
|
+
<mat-expansion-panel-header>
|
|
4059
|
+
<mat-panel-title>Básico</mat-panel-title>
|
|
4060
|
+
</mat-expansion-panel-header>
|
|
4061
|
+
<div class="form-grid">
|
|
4062
|
+
<div class="form-row">
|
|
4063
|
+
<mat-form-field appearance="outline" class="full">
|
|
4064
|
+
<mat-label>Dependentes (CSV)</mat-label>
|
|
4065
|
+
<input matInput [(ngModel)]="editDepCsv">
|
|
4066
|
+
<mat-hint>Ex.: rotaId,destinoReqId</mat-hint>
|
|
4067
|
+
</mat-form-field>
|
|
4068
|
+
</div>
|
|
4069
|
+
<div class="form-row">
|
|
4070
|
+
<mat-checkbox [(ngModel)]="editEnable">Ativar cascata nativa</mat-checkbox>
|
|
4071
|
+
<mat-checkbox [(ngModel)]="editReset">Resetar ao mudar</mat-checkbox>
|
|
4072
|
+
</div>
|
|
4073
|
+
</div>
|
|
4074
|
+
</mat-expansion-panel>
|
|
4075
|
+
|
|
4076
|
+
<!-- Execução -->
|
|
4077
|
+
<mat-expansion-panel>
|
|
4078
|
+
<mat-expansion-panel-header>
|
|
4079
|
+
<mat-panel-title>Execução</mat-panel-title>
|
|
4080
|
+
</mat-expansion-panel-header>
|
|
4081
|
+
<div class="form-row">
|
|
4082
|
+
<mat-form-field appearance="outline">
|
|
4083
|
+
<mat-label>Carregar ao mudar</mat-label>
|
|
4084
|
+
<mat-select [(ngModel)]="editLoadOn">
|
|
4085
|
+
<mat-option value="respectLoadOn">Respeitar loadOn</mat-option>
|
|
4086
|
+
<mat-option value="immediate">Imediato</mat-option>
|
|
4087
|
+
<mat-option value="manual">Manual</mat-option>
|
|
4088
|
+
</mat-select>
|
|
4089
|
+
</mat-form-field>
|
|
4090
|
+
<mat-form-field appearance="outline">
|
|
4091
|
+
<mat-label>Merge de filtros</mat-label>
|
|
4092
|
+
<mat-select [(ngModel)]="editMerge">
|
|
4093
|
+
<mat-option value="merge">merge (padrão)</mat-option>
|
|
4094
|
+
<mat-option value="replace">replace</mat-option>
|
|
4095
|
+
</mat-select>
|
|
4096
|
+
</mat-form-field>
|
|
4097
|
+
<mat-form-field appearance="outline">
|
|
4098
|
+
<mat-label>Atraso (ms)</mat-label>
|
|
4099
|
+
<input matInput type="number" [(ngModel)]="editDebounce">
|
|
4100
|
+
</mat-form-field>
|
|
4101
|
+
</div>
|
|
4102
|
+
</mat-expansion-panel>
|
|
4103
|
+
|
|
4104
|
+
<!-- Extração de valor -->
|
|
4105
|
+
<mat-expansion-panel>
|
|
4106
|
+
<mat-expansion-panel-header>
|
|
4107
|
+
<mat-panel-title>Extração de valor</mat-panel-title>
|
|
4108
|
+
</mat-expansion-panel-header>
|
|
4109
|
+
<div class="form-row">
|
|
4110
|
+
<mat-form-field appearance="outline" class="full">
|
|
4111
|
+
<mat-label>ValuePath padrão</mat-label>
|
|
4112
|
+
<input matInput [(ngModel)]="editValuePath" placeholder="id">
|
|
4113
|
+
<mat-hint>Preenchido automaticamente a partir de optionValueKey() ou 'id'</mat-hint>
|
|
4114
|
+
</mat-form-field>
|
|
4115
|
+
</div>
|
|
4116
|
+
</mat-expansion-panel>
|
|
4117
|
+
|
|
4118
|
+
<!-- Mapeamento de filtros (tabela) -->
|
|
4119
|
+
<mat-expansion-panel>
|
|
4120
|
+
<mat-expansion-panel-header>
|
|
4121
|
+
<mat-panel-title>Mapeamento de filtros</mat-panel-title>
|
|
4122
|
+
</mat-expansion-panel-header>
|
|
4123
|
+
<table class="map-table" *ngIf="editMapRows.length; else noMap">
|
|
4124
|
+
<thead>
|
|
4125
|
+
<tr>
|
|
4126
|
+
<th>Dependente</th>
|
|
4127
|
+
<th>Chave (dot‑path)</th>
|
|
4128
|
+
<th>ValuePath (opcional)</th>
|
|
4129
|
+
</tr>
|
|
4130
|
+
</thead>
|
|
4131
|
+
<tbody>
|
|
4132
|
+
<tr *ngFor="let row of editMapRows; let i = index">
|
|
4133
|
+
<td>{{ row.dep }}</td>
|
|
4134
|
+
<td>
|
|
4135
|
+
<input matInput [(ngModel)]="row.key" placeholder="{{row.dep}}">
|
|
4136
|
+
</td>
|
|
4137
|
+
<td>
|
|
4138
|
+
<input matInput [(ngModel)]="row.valuePath" placeholder="{{editValuePath||'id'}}">
|
|
4139
|
+
</td>
|
|
4140
|
+
</tr>
|
|
4141
|
+
</tbody>
|
|
4142
|
+
</table>
|
|
4143
|
+
<ng-template #noMap>
|
|
4144
|
+
<div class="rules-empty">Defina dependentes para sugerir o mapeamento.</div>
|
|
4145
|
+
</ng-template>
|
|
4146
|
+
</mat-expansion-panel>
|
|
4147
|
+
|
|
4148
|
+
<!-- Preview -->
|
|
4149
|
+
<mat-expansion-panel>
|
|
4150
|
+
<mat-expansion-panel-header>
|
|
4151
|
+
<mat-panel-title>Preview</mat-panel-title>
|
|
4152
|
+
</mat-expansion-panel-header>
|
|
4153
|
+
<pre style="white-space: pre-wrap; background:#fafafa; padding:8px; border:1px solid #eee; border-radius:6px">{{ buildPreview() }}</pre>
|
|
4154
|
+
<div style="display:flex; justify-content:flex-end; padding-top:6px">
|
|
4155
|
+
<button mat-stroked-button (click)="copyPreview()">Copiar</button>
|
|
4156
|
+
</div>
|
|
4157
|
+
</mat-expansion-panel>
|
|
4158
|
+
|
|
4159
|
+
<div style="display:flex; gap:8px; justify-content:flex-end; padding:8px 0;">
|
|
4160
|
+
<button mat-stroked-button (click)="cancelEdit()">Cancelar</button>
|
|
4161
|
+
<button mat-flat-button color="primary" (click)="saveEdit(sel)">Salvar</button>
|
|
4162
|
+
</div>
|
|
4163
|
+
</mat-expansion-panel>
|
|
4164
|
+
</div>
|
|
4165
|
+
</div>
|
|
4166
|
+
`, styles: [":host{display:block}.cm-root{display:grid;grid-template-columns:320px 1fr;gap:16px;min-height:420px}.cm-left{border-right:1px solid rgba(0,0,0,.06);padding-right:8px}.cm-search{width:100%;margin-bottom:8px}.cm-right{padding-left:8px}.field-item{display:flex;align-items:center;justify-content:space-between;padding:6px 4px;cursor:pointer;border-radius:6px}.field-item.selected{background:#0000000a}.rule-badges{display:inline-flex;gap:6px}.rule-badge{font-size:10px;padding:2px 6px;border-radius:10px}.b-active{background:#e8f5e9;color:#2e7d32}.b-manual{background:#eceff1;color:#455a64}.b-immediate{background:#fff3e0;color:#ef6c00}.b-conflict{background:#ffebee;color:#c62828}.cm-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.rules-empty{opacity:.7;font-style:italic;padding:8px 0}.rule-row{display:grid;grid-template-columns:1fr auto;align-items:center;padding:8px 0;border-bottom:1px dashed rgba(0,0,0,.06)}.rule-actions button{margin-left:4px}.banner{background:#fff8e1;color:#6d4c41;padding:8px 12px;border:1px solid #ffe082;border-radius:6px;margin-bottom:8px;display:flex;gap:8px;align-items:center}.import-panel{background:#f5f5f5;border:1px solid #e0e0e0;border-radius:6px;padding:8px;margin-bottom:8px}.full{width:100%}.form-row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.form-grid{display:grid;gap:12px;padding:8px 0}.map-table{width:100%;border-collapse:collapse}.map-table th,.map-table td{padding:6px 8px;border-bottom:1px dashed rgba(0,0,0,.06)}.kbd{font-family:monospace;background:#eee;padding:0 4px;border-radius:3px}\n"] }]
|
|
4167
|
+
}], ctorParameters: () => [{ type: CascadeRulesService }], propDecorators: { fields: [{
|
|
4168
|
+
type: Input
|
|
4169
|
+
}], connections: [{
|
|
4170
|
+
type: Input
|
|
4171
|
+
}], apply: [{
|
|
4172
|
+
type: Output
|
|
4173
|
+
}], cancel: [{
|
|
4174
|
+
type: Output
|
|
4175
|
+
}] } });
|
|
4176
|
+
|
|
4177
|
+
/**
|
|
4178
|
+
* Generated bundle index. Do not edit.
|
|
4179
|
+
*/
|
|
4180
|
+
|
|
4181
|
+
export { CascadeManagerTabComponent, CascadeRulesService, ConfigRegistryService, ContextValidatorRegistryService, DynamicEditorRendererComponent, DynamicFormFactoryService, EditorComponentRegistryService, FieldMetadataEditorComponent, SchemaNormalizerService };
|
|
4182
|
+
//# sourceMappingURL=praxisui-metadata-editor.mjs.map
|