@praxisui/tabs 3.0.0-beta.6 → 3.0.0-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/praxisui-tabs.mjs +1256 -474
- package/fesm2022/praxisui-tabs.mjs.map +1 -1
- package/index.d.ts +118 -37
- package/package.json +4 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Inject, Component,
|
|
2
|
+
import { inject, Inject, Component, EventEmitter, signal, Output, Input, ChangeDetectionStrategy, ENVIRONMENT_INITIALIZER } from '@angular/core';
|
|
3
3
|
import { ActivatedRoute } from '@angular/router';
|
|
4
4
|
import * as i1$1 from '@angular/common';
|
|
5
5
|
import { CommonModule } from '@angular/common';
|
|
@@ -10,7 +10,7 @@ import { MatIconModule } from '@angular/material/icon';
|
|
|
10
10
|
import * as i11 from '@angular/material/tooltip';
|
|
11
11
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
12
12
|
import * as i1 from '@praxisui/core';
|
|
13
|
-
import { PraxisIconDirective, deepMerge, ASYNC_CONFIG_STORAGE, ComponentKeyService, LoggerService, EmptyStateCardComponent, DynamicWidgetLoaderDirective, ComponentMetadataRegistry } from '@praxisui/core';
|
|
13
|
+
import { providePraxisI18n, PraxisI18nService, PraxisIconDirective, providePraxisI18nConfig, deepMerge, ASYNC_CONFIG_STORAGE, ComponentKeyService, LoggerService, EmptyStateCardComponent, DynamicWidgetLoaderDirective, ComponentMetadataRegistry } from '@praxisui/core';
|
|
14
14
|
import * as i6$1 from '@angular/material/button';
|
|
15
15
|
import { MatButtonModule } from '@angular/material/button';
|
|
16
16
|
import * as i3 from '@angular/forms';
|
|
@@ -31,32 +31,548 @@ import { MatSnackBar } from '@angular/material/snack-bar';
|
|
|
31
31
|
import { take, takeUntil } from 'rxjs/operators';
|
|
32
32
|
import { BaseAiAdapter, PraxisAiAssistantComponent } from '@praxisui/ai';
|
|
33
33
|
|
|
34
|
+
const DOCUMENT_KIND = 'praxis.tabs.editor';
|
|
35
|
+
const DOCUMENT_VERSION = 1;
|
|
36
|
+
function createTabsAuthoringDocument(source) {
|
|
37
|
+
return normalizeTabsAuthoringDocument({
|
|
38
|
+
kind: DOCUMENT_KIND,
|
|
39
|
+
version: DOCUMENT_VERSION,
|
|
40
|
+
config: source.config ?? {},
|
|
41
|
+
bindings: source.bindings,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function normalizeTabsAuthoringDocument(doc) {
|
|
45
|
+
return {
|
|
46
|
+
kind: DOCUMENT_KIND,
|
|
47
|
+
version: DOCUMENT_VERSION,
|
|
48
|
+
config: normalizeTabsConfig(doc?.config),
|
|
49
|
+
bindings: normalizeBindings(doc?.bindings),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function validateTabsAuthoringDocument(doc, _context) {
|
|
53
|
+
const normalized = normalizeTabsAuthoringDocument(doc);
|
|
54
|
+
const diagnostics = [];
|
|
55
|
+
validateModeAmbiguity(normalized.config, diagnostics);
|
|
56
|
+
validateDuplicateTabIds(normalized.config, diagnostics);
|
|
57
|
+
validateDuplicateLinkIds(normalized.config, diagnostics);
|
|
58
|
+
validateUnsupportedGuidedFields(normalized.config, diagnostics);
|
|
59
|
+
return diagnostics;
|
|
60
|
+
}
|
|
61
|
+
function toCanonicalTabsConfig(doc, _context) {
|
|
62
|
+
const normalized = normalizeTabsAuthoringDocument(doc);
|
|
63
|
+
return normalizeTabsConfig(stripUnsupportedAuthoringFields(normalized.config));
|
|
64
|
+
}
|
|
65
|
+
function buildTabsApplyPlan(doc, runtime, options) {
|
|
66
|
+
const normalized = normalizeTabsAuthoringDocument(doc);
|
|
67
|
+
const bindingsPatch = normalized.bindings;
|
|
68
|
+
const diff = deriveBindingsDiff(bindingsPatch, runtime?.currentBindings);
|
|
69
|
+
const diagnostics = validateTabsAuthoringDocument(normalized, runtime);
|
|
70
|
+
return {
|
|
71
|
+
canonicalConfig: toCanonicalTabsConfig(normalized, runtime),
|
|
72
|
+
bindingsPatch,
|
|
73
|
+
persistence: {
|
|
74
|
+
saveConfig: options?.saveConfig === true,
|
|
75
|
+
saveBindings: options?.saveBindings === true,
|
|
76
|
+
},
|
|
77
|
+
runtime: {
|
|
78
|
+
refreshSelection: true,
|
|
79
|
+
rebuildLazyState: true,
|
|
80
|
+
refreshPersistenceScope: diff.requiresPersistenceKeyRefresh,
|
|
81
|
+
},
|
|
82
|
+
diff,
|
|
83
|
+
diagnostics,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function serializeTabsAuthoringDocument(doc) {
|
|
87
|
+
return normalizeTabsAuthoringDocument(doc);
|
|
88
|
+
}
|
|
89
|
+
function normalizeTabsConfig(config) {
|
|
90
|
+
const next = cloneJson(config ?? {});
|
|
91
|
+
if (!Array.isArray(next.tabs) || next.tabs.length === 0) {
|
|
92
|
+
delete next.tabs;
|
|
93
|
+
}
|
|
94
|
+
if (!next.nav || typeof next.nav !== 'object') {
|
|
95
|
+
delete next.nav;
|
|
96
|
+
}
|
|
97
|
+
else if (!Array.isArray(next.nav.links) || next.nav.links.length === 0) {
|
|
98
|
+
delete next.nav.links;
|
|
99
|
+
}
|
|
100
|
+
if (next.group) {
|
|
101
|
+
next.group.selectedIndex = clampIndex(next.group.selectedIndex, next.tabs?.length ?? 0);
|
|
102
|
+
}
|
|
103
|
+
if (next.nav) {
|
|
104
|
+
next.nav.selectedIndex = clampIndex(next.nav.selectedIndex, next.nav.links?.length ?? 0);
|
|
105
|
+
}
|
|
106
|
+
if (Array.isArray(next.nav?.links)) {
|
|
107
|
+
next.nav.links = next.nav.links.map((link) => {
|
|
108
|
+
const copy = { ...link };
|
|
109
|
+
delete copy.active;
|
|
110
|
+
return copy;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return next;
|
|
114
|
+
}
|
|
115
|
+
function normalizeBindings(bindings) {
|
|
116
|
+
if (!bindings)
|
|
117
|
+
return undefined;
|
|
118
|
+
const next = {
|
|
119
|
+
tabsId: normalizeNullableString(bindings.tabsId),
|
|
120
|
+
componentInstanceId: normalizeNullableString(bindings.componentInstanceId),
|
|
121
|
+
};
|
|
122
|
+
if (next.tabsId === undefined && next.componentInstanceId === undefined) {
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
return next;
|
|
126
|
+
}
|
|
127
|
+
function deriveBindingsDiff(next, current) {
|
|
128
|
+
const normalizedNext = normalizeBindings(next) ?? {};
|
|
129
|
+
const normalizedCurrent = normalizeBindings(current) ?? {};
|
|
130
|
+
const tabsIdChanged = normalizedNext.tabsId !== normalizedCurrent.tabsId;
|
|
131
|
+
const componentInstanceIdChanged = normalizedNext.componentInstanceId !== normalizedCurrent.componentInstanceId;
|
|
132
|
+
return {
|
|
133
|
+
tabsIdChanged,
|
|
134
|
+
componentInstanceIdChanged,
|
|
135
|
+
requiresPersistenceKeyRefresh: tabsIdChanged || componentInstanceIdChanged,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function validateModeAmbiguity(config, diagnostics) {
|
|
139
|
+
if (config.tabs?.length && config.nav?.links?.length) {
|
|
140
|
+
diagnostics.push(warnDiagnostic('tabs.config.mode.ambiguous', 'Tabs authoring must resolve to a single primary mode: group or nav.', 'config'));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function validateDuplicateTabIds(config, diagnostics) {
|
|
144
|
+
const seen = new Set();
|
|
145
|
+
(config.tabs ?? []).forEach((tab, index) => {
|
|
146
|
+
const id = normalizeId(tab.id);
|
|
147
|
+
if (!id)
|
|
148
|
+
return;
|
|
149
|
+
if (seen.has(id)) {
|
|
150
|
+
diagnostics.push(errorDiagnostic('tabs.config.tabs.id.duplicate', 'Duplicate tab id detected.', `config.tabs[${index}].id`));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
seen.add(id);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function validateDuplicateLinkIds(config, diagnostics) {
|
|
157
|
+
const seen = new Set();
|
|
158
|
+
(config.nav?.links ?? []).forEach((link, index) => {
|
|
159
|
+
const id = normalizeId(link.id);
|
|
160
|
+
if (!id)
|
|
161
|
+
return;
|
|
162
|
+
if (seen.has(id)) {
|
|
163
|
+
diagnostics.push(errorDiagnostic('tabs.config.nav.links.id.duplicate', 'Duplicate nav link id detected.', `config.nav.links[${index}].id`));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
seen.add(id);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
function validateUnsupportedGuidedFields(config, diagnostics) {
|
|
170
|
+
if (config.group?.contentTabIndex !== undefined) {
|
|
171
|
+
diagnostics.push(infoDiagnostic('tabs.config.group.contentTabIndex.unsupported', 'group.contentTabIndex is outside the supported authoring surface.', 'config.group.contentTabIndex'));
|
|
172
|
+
}
|
|
173
|
+
if (config.accessibility?.ariaLabels !== undefined) {
|
|
174
|
+
diagnostics.push(infoDiagnostic('tabs.config.accessibility.ariaLabels.unsupported', 'accessibility.ariaLabels is outside the supported authoring surface.', 'config.accessibility.ariaLabels'));
|
|
175
|
+
}
|
|
176
|
+
if (config.accessibility?.keyboardNavigation !== undefined) {
|
|
177
|
+
diagnostics.push(infoDiagnostic('tabs.config.accessibility.keyboardNavigation.unsupported', 'accessibility.keyboardNavigation is outside the supported authoring surface.', 'config.accessibility.keyboardNavigation'));
|
|
178
|
+
}
|
|
179
|
+
if (config.appearance?.tokens?.['inactive-ripple-color'] !== undefined) {
|
|
180
|
+
diagnostics.push(infoDiagnostic('tabs.config.appearance.tokens.inactiveRippleColor.unsupported', 'appearance.tokens.inactive-ripple-color is outside the supported authoring surface.', 'config.appearance.tokens.inactive-ripple-color'));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function stripUnsupportedAuthoringFields(config) {
|
|
184
|
+
const next = cloneJson(config);
|
|
185
|
+
if (next.group) {
|
|
186
|
+
delete next.group.contentTabIndex;
|
|
187
|
+
}
|
|
188
|
+
if (next.accessibility) {
|
|
189
|
+
delete next.accessibility.ariaLabels;
|
|
190
|
+
delete next.accessibility.keyboardNavigation;
|
|
191
|
+
}
|
|
192
|
+
if (next.appearance?.tokens) {
|
|
193
|
+
delete next.appearance.tokens['inactive-ripple-color'];
|
|
194
|
+
}
|
|
195
|
+
if (Array.isArray(next.nav?.links)) {
|
|
196
|
+
next.nav.links = next.nav.links.map((link) => {
|
|
197
|
+
const copy = { ...link };
|
|
198
|
+
delete copy.active;
|
|
199
|
+
return copy;
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
return next;
|
|
203
|
+
}
|
|
204
|
+
function clampIndex(index, size) {
|
|
205
|
+
if (size <= 0)
|
|
206
|
+
return 0;
|
|
207
|
+
const numeric = Number(index);
|
|
208
|
+
const safe = Number.isFinite(numeric) ? Math.trunc(numeric) : 0;
|
|
209
|
+
return Math.min(Math.max(safe, 0), size - 1);
|
|
210
|
+
}
|
|
211
|
+
function normalizeNullableString(value) {
|
|
212
|
+
if (value === undefined)
|
|
213
|
+
return undefined;
|
|
214
|
+
if (value === null)
|
|
215
|
+
return null;
|
|
216
|
+
if (typeof value !== 'string')
|
|
217
|
+
return null;
|
|
218
|
+
const trimmed = value.trim();
|
|
219
|
+
return trimmed || null;
|
|
220
|
+
}
|
|
221
|
+
function normalizeId(value) {
|
|
222
|
+
if (typeof value !== 'string')
|
|
223
|
+
return null;
|
|
224
|
+
const trimmed = value.trim();
|
|
225
|
+
return trimmed || null;
|
|
226
|
+
}
|
|
227
|
+
function cloneJson(value) {
|
|
228
|
+
return JSON.parse(JSON.stringify(value ?? null));
|
|
229
|
+
}
|
|
230
|
+
function errorDiagnostic(code, message, path) {
|
|
231
|
+
return { level: 'error', code, message, path };
|
|
232
|
+
}
|
|
233
|
+
function warnDiagnostic(code, message, path) {
|
|
234
|
+
return { level: 'warning', code, message, path };
|
|
235
|
+
}
|
|
236
|
+
function infoDiagnostic(code, message, path) {
|
|
237
|
+
return { level: 'info', code, message, path };
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const PRAXIS_TABS_I18N_NAMESPACE = 'praxisTabs';
|
|
241
|
+
const PRAXIS_TABS_PT_BR = {
|
|
242
|
+
'settings.title': 'Configurar abas',
|
|
243
|
+
'settings.resetPreferences': 'Redefinir preferencias de abas',
|
|
244
|
+
'settings.resetDone': 'Preferencias de abas redefinidas',
|
|
245
|
+
'quickSetup.title': 'Criar abas rapidamente',
|
|
246
|
+
'emptyState.title': 'Nenhuma aba configurada',
|
|
247
|
+
'emptyState.description': 'Crie rapidamente suas abas ou abra o editor completo.',
|
|
248
|
+
'emptyState.primaryAction': 'Criar abas rapidamente',
|
|
249
|
+
'emptyState.secondaryAddEmpty': 'Adicionar aba vazia',
|
|
250
|
+
'emptyState.secondaryOpenEditor': 'Abrir editor completo',
|
|
251
|
+
'emptyState.navTitle': 'Sem conteudo neste link',
|
|
252
|
+
'emptyState.navDescription': 'Adicione conteudo ou use o editor para configurar.',
|
|
253
|
+
'emptyState.tabTitle': 'Sem conteudo nesta aba',
|
|
254
|
+
'emptyState.tabDescription': 'Adicione conteudo ou use o editor para configurar.',
|
|
255
|
+
'emptyState.openEditor': 'Abrir editor',
|
|
256
|
+
'chrome.closeTab': 'Fechar aba',
|
|
257
|
+
'chrome.moveTabLeft': 'Mover aba para esquerda',
|
|
258
|
+
'chrome.moveTabRight': 'Mover aba para direita',
|
|
259
|
+
'chrome.editTabs': 'Editar abas',
|
|
260
|
+
'defaults.newTabLabel': 'New Tab',
|
|
261
|
+
'defaults.newLinkLabel': 'New Link',
|
|
262
|
+
'editor.tabs.behavior': 'Comportamento',
|
|
263
|
+
'editor.tabs.group': 'Grupo',
|
|
264
|
+
'editor.tabs.nav': 'Navegacao',
|
|
265
|
+
'editor.tabs.json': 'JSON',
|
|
266
|
+
'editor.tabs.style': 'Estilo',
|
|
267
|
+
'editor.tabs.items': 'Abas',
|
|
268
|
+
'editor.tabs.accessibility': 'Acessibilidade',
|
|
269
|
+
'editor.tabs.links': 'Links',
|
|
270
|
+
'editor.actions.format': 'Formatar',
|
|
271
|
+
'editor.actions.reset': 'Resetar',
|
|
272
|
+
'editor.actions.clearTokens': 'Limpar tokens',
|
|
273
|
+
'editor.actions.addTab': 'Adicionar aba',
|
|
274
|
+
'editor.actions.addLink': 'Adicionar link',
|
|
275
|
+
'editor.actions.add': 'Adicionar',
|
|
276
|
+
'editor.actions.removeLabel': 'Remover rotulo',
|
|
277
|
+
'editor.actions.dragToReorder': 'Arrastar para reordenar',
|
|
278
|
+
'editor.actions.removeComponent': 'Remover componente',
|
|
279
|
+
'editor.fields.groupAlignTabs': 'Alinhamento das abas',
|
|
280
|
+
'editor.fields.groupHeaderPosition': 'Posicao do header',
|
|
281
|
+
'editor.fields.selectedIndex': 'Indice selecionado',
|
|
282
|
+
'editor.fields.animationDuration': 'Duracao da animacao',
|
|
283
|
+
'editor.fields.mode': 'Modo principal',
|
|
284
|
+
'editor.fields.color': 'Cor (M2)',
|
|
285
|
+
'editor.fields.backgroundColor': 'Cor de fundo (M2)',
|
|
286
|
+
'editor.fields.ariaLabel': 'aria-label',
|
|
287
|
+
'editor.fields.ariaLabelledby': 'aria-labelledby',
|
|
288
|
+
'editor.fields.jsonConfig': 'Configuracao JSON',
|
|
289
|
+
'editor.fields.themeClass': 'Classe de tema (opcional)',
|
|
290
|
+
'editor.fields.density': 'Densidade',
|
|
291
|
+
'editor.fields.customCss': 'CSS a ser injetado no componente',
|
|
292
|
+
'editor.fields.addLabel': 'Adicionar rotulo',
|
|
293
|
+
'editor.fields.inputsJson': 'Inputs (JSON)',
|
|
294
|
+
'editor.fields.outputsJson': 'Outputs (JSON)',
|
|
295
|
+
'editor.fields.id': 'ID',
|
|
296
|
+
'editor.fields.label': 'Rotulo',
|
|
297
|
+
'editor.fields.labelClass': 'Classe do rotulo',
|
|
298
|
+
'editor.fields.bodyClass': 'Classe do conteudo',
|
|
299
|
+
'editor.fields.resourcePath': 'Recurso (resourcePath)',
|
|
300
|
+
'editor.fields.addComponent': 'Adicionar componente',
|
|
301
|
+
'editor.fields.selectPlaceholder': '(selecione)',
|
|
302
|
+
'editor.fields.placeholder.animationDuration': '500ms',
|
|
303
|
+
'editor.fields.placeholder.themeClass': 'ex.: tabs-accented',
|
|
304
|
+
'editor.fields.placeholder.resourcePath': 'ex.: usuarios',
|
|
305
|
+
'editor.hints.selectedIndex': 'selectedIndex',
|
|
306
|
+
'editor.hints.animationDuration': 'animationDuration',
|
|
307
|
+
'editor.hints.preferTokens': 'Preferir tokens em Estilo.',
|
|
308
|
+
'editor.hints.tokenValueHelp': 'Valores aceitam CSS vars ou cores hex/rgb.',
|
|
309
|
+
'editor.json.valid': 'JSON valido',
|
|
310
|
+
'editor.json.invalidPrefix': 'JSON invalido:',
|
|
311
|
+
'editor.json.syntaxError': 'Erro de sintaxe JSON',
|
|
312
|
+
'editor.sections.tokens': 'Tokens (Material 3)',
|
|
313
|
+
'editor.sections.customCss': 'CSS personalizado',
|
|
314
|
+
'editor.sections.scssSnippet': 'Snippet SCSS (para uso em styles.scss)',
|
|
315
|
+
'editor.mode.group': 'Grupo de abas',
|
|
316
|
+
'editor.mode.nav': 'Navegacao por links',
|
|
317
|
+
'editor.diagnostics.title': 'Diagnosticos de authoring',
|
|
318
|
+
'editor.diagnostics.error': 'Erro',
|
|
319
|
+
'editor.diagnostics.warning': 'Aviso',
|
|
320
|
+
'editor.diagnostics.info': 'Informacao',
|
|
321
|
+
'editor.cards.tab': 'Aba',
|
|
322
|
+
'editor.cards.link': 'Link',
|
|
323
|
+
'editor.presets.title': 'Presets:',
|
|
324
|
+
'editor.presets.primary': 'Primario',
|
|
325
|
+
'editor.presets.neutral': 'Neutro',
|
|
326
|
+
'editor.presets.highContrast': 'Alto contraste',
|
|
327
|
+
'editor.density.default': 'Padrao',
|
|
328
|
+
'editor.density.compact': 'Compacta',
|
|
329
|
+
'editor.density.comfortable': 'Confortavel',
|
|
330
|
+
'editor.density.spacious': 'Espacosa',
|
|
331
|
+
'editor.options.none': '(nenhuma)',
|
|
332
|
+
'editor.options.default': 'Padrao',
|
|
333
|
+
'editor.options.start': 'Inicio',
|
|
334
|
+
'editor.options.center': 'Centro',
|
|
335
|
+
'editor.options.end': 'Fim',
|
|
336
|
+
'editor.options.aboveDefault': 'Acima (padrao)',
|
|
337
|
+
'editor.options.above': 'Acima',
|
|
338
|
+
'editor.options.below': 'Abaixo',
|
|
339
|
+
'editor.options.primary': 'Primary',
|
|
340
|
+
'editor.options.accent': 'Accent',
|
|
341
|
+
'editor.options.warn': 'Warn',
|
|
342
|
+
'editor.templates.form': 'Form',
|
|
343
|
+
'editor.templates.table': 'Tabela',
|
|
344
|
+
'editor.templates.crud': 'CRUD',
|
|
345
|
+
'editor.placeholders.tokenValue': 'var(--md-sys-color-primary) / #RRGGBB',
|
|
346
|
+
'editor.placeholders.customCssExample': '.praxis-tabs-root .mdc-tab__text-label { font-weight: 600; }',
|
|
347
|
+
'editor.tokens.activeIndicator': 'Indicador ativo',
|
|
348
|
+
'editor.tokens.activeLabel': 'Texto ativo',
|
|
349
|
+
'editor.tokens.activeHoverIndicator': 'Indicador ativo (hover)',
|
|
350
|
+
'editor.tokens.activeHoverLabel': 'Texto ativo (hover)',
|
|
351
|
+
'editor.tokens.activeFocusIndicator': 'Indicador ativo (focus)',
|
|
352
|
+
'editor.tokens.activeFocusLabel': 'Texto ativo (focus)',
|
|
353
|
+
'editor.tokens.inactiveLabel': 'Texto inativo',
|
|
354
|
+
'editor.tokens.inactiveHoverLabel': 'Texto inativo (hover)',
|
|
355
|
+
'editor.tokens.inactiveFocusLabel': 'Texto inativo (focus)',
|
|
356
|
+
'editor.tokens.paginationIcon': 'Icones de paginacao',
|
|
357
|
+
'editor.tokens.divider': 'Divisor/linha',
|
|
358
|
+
'editor.tokens.headerBackground': 'Fundo do header',
|
|
359
|
+
'editor.toggles.closeable': 'Fechavel',
|
|
360
|
+
'editor.toggles.lazyLoad': 'Carregar sob demanda',
|
|
361
|
+
'editor.toggles.reorderable': 'Reordenavel',
|
|
362
|
+
'editor.toggles.dynamicHeight': 'Altura dinamica',
|
|
363
|
+
'editor.toggles.fitInkBarToContent': 'Indicador ajustado ao conteudo',
|
|
364
|
+
'editor.toggles.disablePagination': 'Sem paginacao',
|
|
365
|
+
'editor.toggles.disableRipple': 'Sem ripple',
|
|
366
|
+
'editor.toggles.preserveContent': 'Preservar conteudo',
|
|
367
|
+
'editor.toggles.stretchTabs': 'Esticar abas',
|
|
368
|
+
'editor.toggles.highContrast': 'Alto contraste',
|
|
369
|
+
'editor.toggles.reduceMotion': 'Reduzir movimento',
|
|
370
|
+
'editor.toggles.disabled': 'Desativada',
|
|
371
|
+
'editor.toggles.linkDisabled': 'Desativado',
|
|
372
|
+
'editor.empty.noLinks': 'Nenhum link definido.',
|
|
373
|
+
'editor.empty.noTabs': 'Nenhuma aba definida.',
|
|
374
|
+
'quickSetup.mode.group': 'Grupo de abas',
|
|
375
|
+
'quickSetup.mode.nav': 'Navegacao por links',
|
|
376
|
+
'quickSetup.fields.addLabelPlaceholder': 'Ex.: Dados Gerais',
|
|
377
|
+
'quickSetup.hints.emptyLabels': 'Adicione um ou mais rotulos para criar as abas.',
|
|
378
|
+
};
|
|
379
|
+
const PRAXIS_TABS_EN_US = {
|
|
380
|
+
'settings.title': 'Configure tabs',
|
|
381
|
+
'settings.resetPreferences': 'Reset tab preferences',
|
|
382
|
+
'settings.resetDone': 'Tab preferences reset',
|
|
383
|
+
'quickSetup.title': 'Create tabs quickly',
|
|
384
|
+
'emptyState.title': 'No tabs configured',
|
|
385
|
+
'emptyState.description': 'Create tabs quickly or open the full editor.',
|
|
386
|
+
'emptyState.primaryAction': 'Create tabs quickly',
|
|
387
|
+
'emptyState.secondaryAddEmpty': 'Add empty tab',
|
|
388
|
+
'emptyState.secondaryOpenEditor': 'Open full editor',
|
|
389
|
+
'emptyState.navTitle': 'No content in this link',
|
|
390
|
+
'emptyState.navDescription': 'Add content or use the editor to configure it.',
|
|
391
|
+
'emptyState.tabTitle': 'No content in this tab',
|
|
392
|
+
'emptyState.tabDescription': 'Add content or use the editor to configure it.',
|
|
393
|
+
'emptyState.openEditor': 'Open editor',
|
|
394
|
+
'chrome.closeTab': 'Close tab',
|
|
395
|
+
'chrome.moveTabLeft': 'Move tab left',
|
|
396
|
+
'chrome.moveTabRight': 'Move tab right',
|
|
397
|
+
'chrome.editTabs': 'Edit tabs',
|
|
398
|
+
'defaults.newTabLabel': 'New Tab',
|
|
399
|
+
'defaults.newLinkLabel': 'New Link',
|
|
400
|
+
'editor.tabs.behavior': 'Behavior',
|
|
401
|
+
'editor.tabs.group': 'Group',
|
|
402
|
+
'editor.tabs.nav': 'Navigation',
|
|
403
|
+
'editor.tabs.json': 'JSON',
|
|
404
|
+
'editor.tabs.style': 'Style',
|
|
405
|
+
'editor.tabs.items': 'Tabs',
|
|
406
|
+
'editor.tabs.accessibility': 'Accessibility',
|
|
407
|
+
'editor.tabs.links': 'Links',
|
|
408
|
+
'editor.actions.format': 'Format',
|
|
409
|
+
'editor.actions.reset': 'Reset',
|
|
410
|
+
'editor.actions.clearTokens': 'Clear tokens',
|
|
411
|
+
'editor.actions.addTab': 'Add tab',
|
|
412
|
+
'editor.actions.addLink': 'Add link',
|
|
413
|
+
'editor.actions.add': 'Add',
|
|
414
|
+
'editor.actions.removeLabel': 'Remove label',
|
|
415
|
+
'editor.actions.dragToReorder': 'Drag to reorder',
|
|
416
|
+
'editor.actions.removeComponent': 'Remove component',
|
|
417
|
+
'editor.fields.groupAlignTabs': 'Tab alignment',
|
|
418
|
+
'editor.fields.groupHeaderPosition': 'Header position',
|
|
419
|
+
'editor.fields.selectedIndex': 'Selected index',
|
|
420
|
+
'editor.fields.animationDuration': 'Animation duration',
|
|
421
|
+
'editor.fields.mode': 'Primary mode',
|
|
422
|
+
'editor.fields.color': 'Color (M2)',
|
|
423
|
+
'editor.fields.backgroundColor': 'Background color (M2)',
|
|
424
|
+
'editor.fields.ariaLabel': 'aria-label',
|
|
425
|
+
'editor.fields.ariaLabelledby': 'aria-labelledby',
|
|
426
|
+
'editor.fields.jsonConfig': 'JSON configuration',
|
|
427
|
+
'editor.fields.themeClass': 'Theme class (optional)',
|
|
428
|
+
'editor.fields.density': 'Density',
|
|
429
|
+
'editor.fields.customCss': 'CSS injected into the component',
|
|
430
|
+
'editor.fields.addLabel': 'Add label',
|
|
431
|
+
'editor.fields.inputsJson': 'Inputs (JSON)',
|
|
432
|
+
'editor.fields.outputsJson': 'Outputs (JSON)',
|
|
433
|
+
'editor.fields.id': 'ID',
|
|
434
|
+
'editor.fields.label': 'Label',
|
|
435
|
+
'editor.fields.labelClass': 'Label class',
|
|
436
|
+
'editor.fields.bodyClass': 'Body class',
|
|
437
|
+
'editor.fields.resourcePath': 'Resource (resourcePath)',
|
|
438
|
+
'editor.fields.addComponent': 'Add component',
|
|
439
|
+
'editor.fields.selectPlaceholder': '(select)',
|
|
440
|
+
'editor.fields.placeholder.animationDuration': '500ms',
|
|
441
|
+
'editor.fields.placeholder.themeClass': 'e.g. tabs-accented',
|
|
442
|
+
'editor.fields.placeholder.resourcePath': 'e.g. users',
|
|
443
|
+
'editor.hints.selectedIndex': 'selectedIndex',
|
|
444
|
+
'editor.hints.animationDuration': 'animationDuration',
|
|
445
|
+
'editor.hints.preferTokens': 'Prefer tokens in Style.',
|
|
446
|
+
'editor.hints.tokenValueHelp': 'Values accept CSS vars or hex/rgb colors.',
|
|
447
|
+
'editor.json.valid': 'Valid JSON',
|
|
448
|
+
'editor.json.invalidPrefix': 'Invalid JSON:',
|
|
449
|
+
'editor.json.syntaxError': 'JSON syntax error',
|
|
450
|
+
'editor.sections.tokens': 'Tokens (Material 3)',
|
|
451
|
+
'editor.sections.customCss': 'Custom CSS',
|
|
452
|
+
'editor.sections.scssSnippet': 'SCSS snippet (for styles.scss)',
|
|
453
|
+
'editor.mode.group': 'Tab group',
|
|
454
|
+
'editor.mode.nav': 'Link navigation',
|
|
455
|
+
'editor.diagnostics.title': 'Authoring diagnostics',
|
|
456
|
+
'editor.diagnostics.error': 'Error',
|
|
457
|
+
'editor.diagnostics.warning': 'Warning',
|
|
458
|
+
'editor.diagnostics.info': 'Info',
|
|
459
|
+
'editor.cards.tab': 'Tab',
|
|
460
|
+
'editor.cards.link': 'Link',
|
|
461
|
+
'editor.presets.title': 'Presets:',
|
|
462
|
+
'editor.presets.primary': 'Primary',
|
|
463
|
+
'editor.presets.neutral': 'Neutral',
|
|
464
|
+
'editor.presets.highContrast': 'High contrast',
|
|
465
|
+
'editor.density.default': 'Default',
|
|
466
|
+
'editor.density.compact': 'Compact',
|
|
467
|
+
'editor.density.comfortable': 'Comfortable',
|
|
468
|
+
'editor.density.spacious': 'Spacious',
|
|
469
|
+
'editor.options.none': '(none)',
|
|
470
|
+
'editor.options.default': 'Default',
|
|
471
|
+
'editor.options.start': 'Start',
|
|
472
|
+
'editor.options.center': 'Center',
|
|
473
|
+
'editor.options.end': 'End',
|
|
474
|
+
'editor.options.aboveDefault': 'Above (default)',
|
|
475
|
+
'editor.options.above': 'Above',
|
|
476
|
+
'editor.options.below': 'Below',
|
|
477
|
+
'editor.options.primary': 'Primary',
|
|
478
|
+
'editor.options.accent': 'Accent',
|
|
479
|
+
'editor.options.warn': 'Warn',
|
|
480
|
+
'editor.templates.form': 'Form',
|
|
481
|
+
'editor.templates.table': 'Table',
|
|
482
|
+
'editor.templates.crud': 'CRUD',
|
|
483
|
+
'editor.placeholders.tokenValue': 'var(--md-sys-color-primary) / #RRGGBB',
|
|
484
|
+
'editor.placeholders.customCssExample': '.praxis-tabs-root .mdc-tab__text-label { font-weight: 600; }',
|
|
485
|
+
'editor.tokens.activeIndicator': 'Active indicator',
|
|
486
|
+
'editor.tokens.activeLabel': 'Active label',
|
|
487
|
+
'editor.tokens.activeHoverIndicator': 'Active indicator (hover)',
|
|
488
|
+
'editor.tokens.activeHoverLabel': 'Active label (hover)',
|
|
489
|
+
'editor.tokens.activeFocusIndicator': 'Active indicator (focus)',
|
|
490
|
+
'editor.tokens.activeFocusLabel': 'Active label (focus)',
|
|
491
|
+
'editor.tokens.inactiveLabel': 'Inactive label',
|
|
492
|
+
'editor.tokens.inactiveHoverLabel': 'Inactive label (hover)',
|
|
493
|
+
'editor.tokens.inactiveFocusLabel': 'Inactive label (focus)',
|
|
494
|
+
'editor.tokens.paginationIcon': 'Pagination icons',
|
|
495
|
+
'editor.tokens.divider': 'Divider',
|
|
496
|
+
'editor.tokens.headerBackground': 'Header background',
|
|
497
|
+
'editor.toggles.closeable': 'Closeable',
|
|
498
|
+
'editor.toggles.lazyLoad': 'Lazy load',
|
|
499
|
+
'editor.toggles.reorderable': 'Reorderable',
|
|
500
|
+
'editor.toggles.dynamicHeight': 'Dynamic height',
|
|
501
|
+
'editor.toggles.fitInkBarToContent': 'Fit indicator to content',
|
|
502
|
+
'editor.toggles.disablePagination': 'Disable pagination',
|
|
503
|
+
'editor.toggles.disableRipple': 'Disable ripple',
|
|
504
|
+
'editor.toggles.preserveContent': 'Preserve content',
|
|
505
|
+
'editor.toggles.stretchTabs': 'Stretch tabs',
|
|
506
|
+
'editor.toggles.highContrast': 'High contrast',
|
|
507
|
+
'editor.toggles.reduceMotion': 'Reduce motion',
|
|
508
|
+
'editor.toggles.disabled': 'Disabled',
|
|
509
|
+
'editor.toggles.linkDisabled': 'Disabled',
|
|
510
|
+
'editor.empty.noLinks': 'No links defined.',
|
|
511
|
+
'editor.empty.noTabs': 'No tabs defined.',
|
|
512
|
+
'quickSetup.mode.group': 'Tab group',
|
|
513
|
+
'quickSetup.mode.nav': 'Link navigation',
|
|
514
|
+
'quickSetup.fields.addLabelPlaceholder': 'e.g. General Data',
|
|
515
|
+
'quickSetup.hints.emptyLabels': 'Add one or more labels to create the tabs.',
|
|
516
|
+
};
|
|
517
|
+
function createPraxisTabsI18nConfig() {
|
|
518
|
+
return {
|
|
519
|
+
fallbackLocale: 'pt-BR',
|
|
520
|
+
namespaces: {
|
|
521
|
+
[PRAXIS_TABS_I18N_NAMESPACE]: {
|
|
522
|
+
'pt-BR': PRAXIS_TABS_PT_BR,
|
|
523
|
+
'en-US': PRAXIS_TABS_EN_US,
|
|
524
|
+
},
|
|
525
|
+
},
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
const PRAXIS_TABS_I18N_CONFIG = createPraxisTabsI18nConfig();
|
|
529
|
+
function providePraxisTabsI18n() {
|
|
530
|
+
return providePraxisI18n(PRAXIS_TABS_I18N_CONFIG);
|
|
531
|
+
}
|
|
532
|
+
|
|
34
533
|
class PraxisTabsConfigEditor {
|
|
35
534
|
registry;
|
|
535
|
+
i18n = inject(PraxisI18nService);
|
|
536
|
+
primaryMode = 'group';
|
|
537
|
+
editedDocument;
|
|
36
538
|
editedConfig;
|
|
37
|
-
|
|
539
|
+
initialDocument;
|
|
540
|
+
bindings;
|
|
38
541
|
jsonText = '';
|
|
39
542
|
isValid = true;
|
|
40
543
|
errorMsg = '';
|
|
544
|
+
diagnostics = [];
|
|
41
545
|
componentOptions = [];
|
|
42
546
|
selectedTabWidgetId = {};
|
|
43
547
|
selectedLinkWidgetId = {};
|
|
44
548
|
quickResourcePathTab = {};
|
|
45
549
|
quickResourcePathLink = {};
|
|
550
|
+
t(key, fallback) {
|
|
551
|
+
return this.i18n.t(key, undefined, fallback, PRAXIS_TABS_I18N_NAMESPACE);
|
|
552
|
+
}
|
|
553
|
+
diagnosticLevelLabel(level) {
|
|
554
|
+
if (level === 'error') {
|
|
555
|
+
return this.t('editor.diagnostics.error', 'Erro');
|
|
556
|
+
}
|
|
557
|
+
if (level === 'warning') {
|
|
558
|
+
return this.t('editor.diagnostics.warning', 'Aviso');
|
|
559
|
+
}
|
|
560
|
+
return this.t('editor.diagnostics.info', 'Informacao');
|
|
561
|
+
}
|
|
46
562
|
// Simplified token list we support at runtime
|
|
47
563
|
tokenList = [
|
|
48
|
-
{ key: 'active-indicator-color',
|
|
49
|
-
{ key: 'active-label-text-color',
|
|
50
|
-
{ key: 'active-hover-indicator-color',
|
|
51
|
-
{ key: 'active-hover-label-text-color',
|
|
52
|
-
{ key: 'active-focus-indicator-color',
|
|
53
|
-
{ key: 'active-focus-label-text-color',
|
|
54
|
-
{ key: 'inactive-label-text-color',
|
|
55
|
-
{ key: 'inactive-hover-label-text-color',
|
|
56
|
-
{ key: 'inactive-focus-label-text-color',
|
|
57
|
-
{ key: 'pagination-icon-color',
|
|
58
|
-
{ key: 'divider-color',
|
|
59
|
-
{ key: 'background-color',
|
|
564
|
+
{ key: 'active-indicator-color', labelKey: 'editor.tokens.activeIndicator', fallback: 'Indicador ativo' },
|
|
565
|
+
{ key: 'active-label-text-color', labelKey: 'editor.tokens.activeLabel', fallback: 'Texto ativo' },
|
|
566
|
+
{ key: 'active-hover-indicator-color', labelKey: 'editor.tokens.activeHoverIndicator', fallback: 'Indicador ativo (hover)' },
|
|
567
|
+
{ key: 'active-hover-label-text-color', labelKey: 'editor.tokens.activeHoverLabel', fallback: 'Texto ativo (hover)' },
|
|
568
|
+
{ key: 'active-focus-indicator-color', labelKey: 'editor.tokens.activeFocusIndicator', fallback: 'Indicador ativo (focus)' },
|
|
569
|
+
{ key: 'active-focus-label-text-color', labelKey: 'editor.tokens.activeFocusLabel', fallback: 'Texto ativo (focus)' },
|
|
570
|
+
{ key: 'inactive-label-text-color', labelKey: 'editor.tokens.inactiveLabel', fallback: 'Texto inativo' },
|
|
571
|
+
{ key: 'inactive-hover-label-text-color', labelKey: 'editor.tokens.inactiveHoverLabel', fallback: 'Texto inativo (hover)' },
|
|
572
|
+
{ key: 'inactive-focus-label-text-color', labelKey: 'editor.tokens.inactiveFocusLabel', fallback: 'Texto inativo (focus)' },
|
|
573
|
+
{ key: 'pagination-icon-color', labelKey: 'editor.tokens.paginationIcon', fallback: 'Icones de paginacao' },
|
|
574
|
+
{ key: 'divider-color', labelKey: 'editor.tokens.divider', fallback: 'Divisor/linha' },
|
|
575
|
+
{ key: 'background-color', labelKey: 'editor.tokens.headerBackground', fallback: 'Fundo do header' },
|
|
60
576
|
];
|
|
61
577
|
presets = {
|
|
62
578
|
primary: {
|
|
@@ -92,50 +608,101 @@ class PraxisTabsConfigEditor {
|
|
|
92
608
|
isBusy$ = new BehaviorSubject(false);
|
|
93
609
|
constructor(data, registry) {
|
|
94
610
|
this.registry = registry;
|
|
95
|
-
const
|
|
96
|
-
this.
|
|
97
|
-
this.
|
|
98
|
-
this.
|
|
99
|
-
this.
|
|
611
|
+
const incomingDocument = normalizeTabsAuthoringDocument(data?.document ?? createTabsAuthoringDocument({ config: {} }));
|
|
612
|
+
this.initialDocument = structuredClone(incomingDocument);
|
|
613
|
+
this.editedDocument = structuredClone(incomingDocument);
|
|
614
|
+
this.editedConfig = this.editedDocument.config;
|
|
615
|
+
this.bindings = this.editedDocument.bindings;
|
|
616
|
+
this.primaryMode = this.inferPrimaryMode(this.editedConfig);
|
|
617
|
+
this.jsonText = this.stringify(this.editedDocument);
|
|
100
618
|
this.updateDirty();
|
|
619
|
+
this.refreshDiagnostics();
|
|
101
620
|
this.componentOptions = this.registry.getAll().map((m) => ({ id: m.id, friendlyName: m.friendlyName }));
|
|
102
621
|
}
|
|
622
|
+
inferPrimaryMode(config) {
|
|
623
|
+
return config?.nav?.links?.length ? 'nav' : 'group';
|
|
624
|
+
}
|
|
625
|
+
setPrimaryMode(mode) {
|
|
626
|
+
if (this.primaryMode === mode)
|
|
627
|
+
return;
|
|
628
|
+
this.primaryMode = mode;
|
|
629
|
+
if (mode === 'group') {
|
|
630
|
+
delete this.editedConfig.nav;
|
|
631
|
+
if (!this.editedConfig.group) {
|
|
632
|
+
this.editedConfig.group = { selectedIndex: 0 };
|
|
633
|
+
}
|
|
634
|
+
if (!Array.isArray(this.editedConfig.tabs)) {
|
|
635
|
+
this.editedConfig.tabs = [];
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
delete this.editedConfig.tabs;
|
|
640
|
+
if (!this.editedConfig.nav) {
|
|
641
|
+
this.editedConfig.nav = { links: [], selectedIndex: 0 };
|
|
642
|
+
}
|
|
643
|
+
if (!Array.isArray(this.editedConfig.nav.links)) {
|
|
644
|
+
this.editedConfig.nav.links = [];
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
this.onAppearanceChange();
|
|
648
|
+
}
|
|
103
649
|
updateDirty() {
|
|
104
|
-
this.isDirty$.next(JSON.stringify(this.
|
|
650
|
+
this.isDirty$.next(JSON.stringify(this.initialDocument) !== JSON.stringify(this.editedDocument));
|
|
651
|
+
}
|
|
652
|
+
syncEditedDocumentFromConfig() {
|
|
653
|
+
this.editedDocument = createTabsAuthoringDocument({
|
|
654
|
+
config: this.editedConfig,
|
|
655
|
+
bindings: this.bindings,
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
syncEditorStateFromDocument(document) {
|
|
659
|
+
this.editedDocument = structuredClone(document);
|
|
660
|
+
this.editedConfig = this.editedDocument.config;
|
|
661
|
+
this.bindings = this.editedDocument.bindings;
|
|
662
|
+
this.primaryMode = this.inferPrimaryMode(this.editedConfig);
|
|
663
|
+
}
|
|
664
|
+
refreshDiagnostics() {
|
|
665
|
+
this.syncEditedDocumentFromConfig();
|
|
666
|
+
this.diagnostics = validateTabsAuthoringDocument(this.editedDocument);
|
|
667
|
+
this.isValid$.next(this.isValid && !this.diagnostics.some((item) => item.level === 'error'));
|
|
105
668
|
}
|
|
106
669
|
onJsonTextChange(text) {
|
|
107
670
|
try {
|
|
108
|
-
const parsed = JSON.parse(text);
|
|
671
|
+
const parsed = normalizeTabsAuthoringDocument(JSON.parse(text));
|
|
109
672
|
this.errorMsg = '';
|
|
110
673
|
this.isValid = true;
|
|
111
|
-
this.
|
|
112
|
-
this.editedConfig = parsed;
|
|
674
|
+
this.syncEditorStateFromDocument(parsed);
|
|
113
675
|
this.updateDirty();
|
|
676
|
+
this.refreshDiagnostics();
|
|
114
677
|
}
|
|
115
678
|
catch (e) {
|
|
116
679
|
this.isValid = false;
|
|
117
680
|
this.isValid$.next(false);
|
|
118
|
-
this.errorMsg = e?.message || 'Erro de sintaxe JSON';
|
|
681
|
+
this.errorMsg = e?.message || this.t('editor.json.syntaxError', 'Erro de sintaxe JSON');
|
|
682
|
+
this.diagnostics = [];
|
|
119
683
|
}
|
|
120
684
|
}
|
|
121
685
|
// stringify helper is public to be used in the template
|
|
122
686
|
formatJson() {
|
|
123
687
|
if (!this.isValid)
|
|
124
688
|
return;
|
|
125
|
-
this.
|
|
689
|
+
this.syncEditedDocumentFromConfig();
|
|
690
|
+
this.jsonText = this.stringify(this.editedDocument);
|
|
126
691
|
}
|
|
127
692
|
getSettingsValue() {
|
|
128
|
-
|
|
693
|
+
this.syncEditedDocumentFromConfig();
|
|
694
|
+
return this.editedDocument;
|
|
129
695
|
}
|
|
130
696
|
onSave() {
|
|
131
|
-
|
|
697
|
+
this.syncEditedDocumentFromConfig();
|
|
698
|
+
return this.editedDocument;
|
|
132
699
|
}
|
|
133
700
|
reset() {
|
|
134
|
-
this.
|
|
135
|
-
this.jsonText = this.stringify(this.
|
|
701
|
+
this.syncEditorStateFromDocument(this.initialDocument);
|
|
702
|
+
this.jsonText = this.stringify(this.editedDocument);
|
|
136
703
|
this.isValid = true;
|
|
137
|
-
this.isValid$.next(true);
|
|
138
704
|
this.updateDirty();
|
|
705
|
+
this.refreshDiagnostics();
|
|
139
706
|
}
|
|
140
707
|
// Appearance helpers
|
|
141
708
|
get appearance() {
|
|
@@ -144,8 +711,10 @@ class PraxisTabsConfigEditor {
|
|
|
144
711
|
return ap;
|
|
145
712
|
}
|
|
146
713
|
onAppearanceChange() {
|
|
714
|
+
this.syncEditedDocumentFromConfig();
|
|
147
715
|
this.updateDirty();
|
|
148
|
-
this.jsonText = this.stringify(this.
|
|
716
|
+
this.jsonText = this.stringify(this.editedDocument);
|
|
717
|
+
this.refreshDiagnostics();
|
|
149
718
|
}
|
|
150
719
|
onTokenChange(key, value) {
|
|
151
720
|
const ap = this.appearance;
|
|
@@ -212,7 +781,10 @@ class PraxisTabsConfigEditor {
|
|
|
212
781
|
addTab() {
|
|
213
782
|
if (!this.editedConfig.tabs)
|
|
214
783
|
this.editedConfig.tabs = [];
|
|
215
|
-
this.editedConfig.tabs.push({
|
|
784
|
+
this.editedConfig.tabs.push({
|
|
785
|
+
id: `tab${(this.editedConfig.tabs.length + 1)}`,
|
|
786
|
+
textLabel: this.t('defaults.newTabLabel', 'New Tab'),
|
|
787
|
+
});
|
|
216
788
|
this.onAppearanceChange();
|
|
217
789
|
}
|
|
218
790
|
removeTab(index) {
|
|
@@ -284,7 +856,10 @@ class PraxisTabsConfigEditor {
|
|
|
284
856
|
addLink() {
|
|
285
857
|
if (!this.nav.links)
|
|
286
858
|
this.nav.links = [];
|
|
287
|
-
this.nav.links.push({
|
|
859
|
+
this.nav.links.push({
|
|
860
|
+
id: `link${this.nav.links.length + 1}`,
|
|
861
|
+
label: this.t('defaults.newLinkLabel', 'New Link'),
|
|
862
|
+
});
|
|
288
863
|
this.onAppearanceChange();
|
|
289
864
|
}
|
|
290
865
|
removeLink(index) {
|
|
@@ -378,181 +953,207 @@ class PraxisTabsConfigEditor {
|
|
|
378
953
|
this.onAppearanceChange();
|
|
379
954
|
}
|
|
380
955
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTabsConfigEditor, deps: [{ token: SETTINGS_PANEL_DATA }, { token: i1.ComponentMetadataRegistry }], target: i0.ɵɵFactoryTarget.Component });
|
|
381
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: PraxisTabsConfigEditor, isStandalone: true, selector: "praxis-tabs-config-editor", ngImport: i0, template: `
|
|
956
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: PraxisTabsConfigEditor, isStandalone: true, selector: "praxis-tabs-config-editor", providers: [providePraxisI18nConfig(PRAXIS_TABS_I18N_CONFIG)], ngImport: i0, template: `
|
|
957
|
+
<div class="editor-shell">
|
|
958
|
+
<div class="editor-topbar">
|
|
959
|
+
<mat-form-field appearance="outline" class="editor-mode-field">
|
|
960
|
+
<mat-label>{{ t('editor.fields.mode', 'Modo principal') }}</mat-label>
|
|
961
|
+
<select matNativeControl [ngModel]="primaryMode" (ngModelChange)="setPrimaryMode($event)">
|
|
962
|
+
<option value="group">{{ t('editor.mode.group', 'Grupo de abas') }}</option>
|
|
963
|
+
<option value="nav">{{ t('editor.mode.nav', 'Navegacao por links') }}</option>
|
|
964
|
+
</select>
|
|
965
|
+
</mat-form-field>
|
|
966
|
+
</div>
|
|
967
|
+
|
|
968
|
+
<div *ngIf="diagnostics.length" class="editor-diagnostics">
|
|
969
|
+
<div class="editor-diagnostics-title">{{ t('editor.diagnostics.title', 'Diagnosticos de authoring') }}</div>
|
|
970
|
+
<div
|
|
971
|
+
*ngFor="let diagnostic of diagnostics"
|
|
972
|
+
class="editor-diagnostic"
|
|
973
|
+
[class.level-error]="diagnostic.level === 'error'"
|
|
974
|
+
[class.level-warning]="diagnostic.level === 'warning'"
|
|
975
|
+
[class.level-info]="diagnostic.level === 'info'"
|
|
976
|
+
>
|
|
977
|
+
<strong>{{ diagnosticLevelLabel(diagnostic.level) }}</strong>
|
|
978
|
+
<span>{{ diagnostic.message }}</span>
|
|
979
|
+
<code *ngIf="diagnostic.path">{{ diagnostic.path }}</code>
|
|
980
|
+
</div>
|
|
981
|
+
</div>
|
|
982
|
+
|
|
382
983
|
<mat-tab-group class="editor-tabs">
|
|
383
|
-
<mat-tab label="Comportamento">
|
|
984
|
+
<mat-tab [label]="t('editor.tabs.behavior', 'Comportamento')">
|
|
384
985
|
<div class="editor-section">
|
|
385
986
|
<div class="editor-row">
|
|
386
|
-
<mat-slide-toggle [(ngModel)]="behavior.closeable" (ngModelChange)="onAppearanceChange()">Fechavel</mat-slide-toggle>
|
|
387
|
-
<mat-slide-toggle [(ngModel)]="behavior.lazyLoad" (ngModelChange)="onAppearanceChange()">Carregar sob demanda</mat-slide-toggle>
|
|
388
|
-
<mat-slide-toggle [(ngModel)]="behavior.reorderable" (ngModelChange)="onAppearanceChange()">Reordenavel</mat-slide-toggle>
|
|
987
|
+
<mat-slide-toggle [(ngModel)]="behavior.closeable" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.closeable', 'Fechavel') }}</mat-slide-toggle>
|
|
988
|
+
<mat-slide-toggle [(ngModel)]="behavior.lazyLoad" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.lazyLoad', 'Carregar sob demanda') }}</mat-slide-toggle>
|
|
989
|
+
<mat-slide-toggle [(ngModel)]="behavior.reorderable" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.reorderable', 'Reordenavel') }}</mat-slide-toggle>
|
|
389
990
|
</div>
|
|
390
991
|
</div>
|
|
391
992
|
</mat-tab>
|
|
392
|
-
<mat-tab label="Grupo">
|
|
993
|
+
<mat-tab [label]="t('editor.tabs.group', 'Grupo')" [disabled]="primaryMode !== 'group'">
|
|
393
994
|
<div class="editor-section">
|
|
394
995
|
<div class="editor-grid two">
|
|
395
|
-
<mat-form-field appearance="outline"><mat-label>Alinhamento das abas</mat-label>
|
|
996
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.groupAlignTabs', 'Alinhamento das abas') }}</mat-label>
|
|
396
997
|
<select matNativeControl [(ngModel)]="group.alignTabs" (ngModelChange)="onAppearanceChange()">
|
|
397
|
-
<option [ngValue]="undefined">Padrao</option>
|
|
398
|
-
<option value="start">Inicio</option>
|
|
399
|
-
<option value="center">Centro</option>
|
|
400
|
-
<option value="end">Fim</option>
|
|
998
|
+
<option [ngValue]="undefined">{{ t('editor.options.default', 'Padrao') }}</option>
|
|
999
|
+
<option value="start">{{ t('editor.options.start', 'Inicio') }}</option>
|
|
1000
|
+
<option value="center">{{ t('editor.options.center', 'Centro') }}</option>
|
|
1001
|
+
<option value="end">{{ t('editor.options.end', 'Fim') }}</option>
|
|
401
1002
|
</select>
|
|
402
1003
|
</mat-form-field>
|
|
403
|
-
<mat-form-field appearance="outline"><mat-label>Posicao do header</mat-label>
|
|
1004
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.groupHeaderPosition', 'Posicao do header') }}</mat-label>
|
|
404
1005
|
<select matNativeControl [(ngModel)]="group.headerPosition" (ngModelChange)="onAppearanceChange()">
|
|
405
|
-
<option [ngValue]="undefined">Acima (padrao)</option>
|
|
406
|
-
<option value="above">Acima</option>
|
|
407
|
-
<option value="below">Abaixo</option>
|
|
1006
|
+
<option [ngValue]="undefined">{{ t('editor.options.aboveDefault', 'Acima (padrao)') }}</option>
|
|
1007
|
+
<option value="above">{{ t('editor.options.above', 'Acima') }}</option>
|
|
1008
|
+
<option value="below">{{ t('editor.options.below', 'Abaixo') }}</option>
|
|
408
1009
|
</select>
|
|
409
1010
|
</mat-form-field>
|
|
410
|
-
<mat-form-field appearance="outline"><mat-label>Indice selecionado</mat-label>
|
|
1011
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.selectedIndex', 'Indice selecionado') }}</mat-label>
|
|
411
1012
|
<input matInput type="number" [(ngModel)]="group.selectedIndex" (ngModelChange)="onAppearanceChange()" />
|
|
412
1013
|
<button
|
|
413
1014
|
mat-icon-button
|
|
414
1015
|
matSuffix
|
|
415
1016
|
class="help-icon-button"
|
|
416
1017
|
type="button"
|
|
417
|
-
[matTooltip]="'selectedIndex'"
|
|
1018
|
+
[matTooltip]="t('editor.hints.selectedIndex', 'selectedIndex')"
|
|
418
1019
|
matTooltipPosition="above"
|
|
419
1020
|
>
|
|
420
1021
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
421
1022
|
</button>
|
|
422
1023
|
</mat-form-field>
|
|
423
|
-
<mat-form-field appearance="outline"><mat-label>Duracao da animacao</mat-label>
|
|
424
|
-
<input matInput [(ngModel)]="group.animationDuration" (ngModelChange)="onAppearanceChange()" placeholder="500ms" />
|
|
1024
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.animationDuration', 'Duracao da animacao') }}</mat-label>
|
|
1025
|
+
<input matInput [(ngModel)]="group.animationDuration" (ngModelChange)="onAppearanceChange()" [placeholder]="t('editor.fields.placeholder.animationDuration', '500ms')" />
|
|
425
1026
|
<button
|
|
426
1027
|
mat-icon-button
|
|
427
1028
|
matSuffix
|
|
428
1029
|
class="help-icon-button"
|
|
429
1030
|
type="button"
|
|
430
|
-
[matTooltip]="'animationDuration'"
|
|
1031
|
+
[matTooltip]="t('editor.hints.animationDuration', 'animationDuration')"
|
|
431
1032
|
matTooltipPosition="above"
|
|
432
1033
|
>
|
|
433
1034
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
434
1035
|
</button>
|
|
435
1036
|
</mat-form-field>
|
|
436
|
-
<mat-form-field appearance="outline"><mat-label>Cor (M2)</mat-label>
|
|
1037
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.color', 'Cor (M2)') }}</mat-label>
|
|
437
1038
|
<select matNativeControl [(ngModel)]="group.color" (ngModelChange)="onAppearanceChange()">
|
|
438
|
-
<option [ngValue]="undefined">(nenhuma)</option>
|
|
439
|
-
<option value="primary">Primary</option>
|
|
440
|
-
<option value="accent">Accent</option>
|
|
441
|
-
<option value="warn">Warn</option>
|
|
1039
|
+
<option [ngValue]="undefined">{{ t('editor.options.none', '(nenhuma)') }}</option>
|
|
1040
|
+
<option value="primary">{{ t('editor.options.primary', 'Primary') }}</option>
|
|
1041
|
+
<option value="accent">{{ t('editor.options.accent', 'Accent') }}</option>
|
|
1042
|
+
<option value="warn">{{ t('editor.options.warn', 'Warn') }}</option>
|
|
442
1043
|
</select>
|
|
443
1044
|
<button
|
|
444
1045
|
mat-icon-button
|
|
445
1046
|
matSuffix
|
|
446
1047
|
class="help-icon-button"
|
|
447
1048
|
type="button"
|
|
448
|
-
[matTooltip]="'Preferir tokens em Estilo.'"
|
|
1049
|
+
[matTooltip]="t('editor.hints.preferTokens', 'Preferir tokens em Estilo.')"
|
|
449
1050
|
matTooltipPosition="above"
|
|
450
1051
|
>
|
|
451
1052
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
452
1053
|
</button>
|
|
453
1054
|
</mat-form-field>
|
|
454
|
-
<mat-form-field appearance="outline"><mat-label>Cor de fundo (M2)</mat-label>
|
|
1055
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.backgroundColor', 'Cor de fundo (M2)') }}</mat-label>
|
|
455
1056
|
<select matNativeControl [(ngModel)]="group.backgroundColor" (ngModelChange)="onAppearanceChange()">
|
|
456
|
-
<option [ngValue]="undefined">(nenhuma)</option>
|
|
457
|
-
<option value="primary">Primary</option>
|
|
458
|
-
<option value="accent">Accent</option>
|
|
459
|
-
<option value="warn">Warn</option>
|
|
1057
|
+
<option [ngValue]="undefined">{{ t('editor.options.none', '(nenhuma)') }}</option>
|
|
1058
|
+
<option value="primary">{{ t('editor.options.primary', 'Primary') }}</option>
|
|
1059
|
+
<option value="accent">{{ t('editor.options.accent', 'Accent') }}</option>
|
|
1060
|
+
<option value="warn">{{ t('editor.options.warn', 'Warn') }}</option>
|
|
460
1061
|
</select>
|
|
461
1062
|
<button
|
|
462
1063
|
mat-icon-button
|
|
463
1064
|
matSuffix
|
|
464
1065
|
class="help-icon-button"
|
|
465
1066
|
type="button"
|
|
466
|
-
[matTooltip]="'Preferir tokens em Estilo.'"
|
|
1067
|
+
[matTooltip]="t('editor.hints.preferTokens', 'Preferir tokens em Estilo.')"
|
|
467
1068
|
matTooltipPosition="above"
|
|
468
1069
|
>
|
|
469
1070
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
470
1071
|
</button>
|
|
471
1072
|
</mat-form-field>
|
|
472
|
-
<mat-form-field appearance="outline"><mat-label>aria-label</mat-label>
|
|
1073
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.ariaLabel', 'aria-label') }}</mat-label>
|
|
473
1074
|
<input matInput [(ngModel)]="group.ariaLabel" (ngModelChange)="onAppearanceChange()" />
|
|
474
1075
|
</mat-form-field>
|
|
475
|
-
<mat-form-field appearance="outline"><mat-label>aria-labelledby</mat-label>
|
|
1076
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.ariaLabelledby', 'aria-labelledby') }}</mat-label>
|
|
476
1077
|
<input matInput [(ngModel)]="group.ariaLabelledby" (ngModelChange)="onAppearanceChange()" />
|
|
477
1078
|
</mat-form-field>
|
|
478
1079
|
</div>
|
|
479
1080
|
<div class="editor-row">
|
|
480
|
-
<mat-slide-toggle [(ngModel)]="group.dynamicHeight" (ngModelChange)="onAppearanceChange()">Altura dinamica</mat-slide-toggle>
|
|
481
|
-
<mat-slide-toggle [(ngModel)]="group.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">Indicador ajustado ao conteudo</mat-slide-toggle>
|
|
482
|
-
<mat-slide-toggle [(ngModel)]="group.disablePagination" (ngModelChange)="onAppearanceChange()">Sem paginacao</mat-slide-toggle>
|
|
483
|
-
<mat-slide-toggle [(ngModel)]="group.disableRipple" (ngModelChange)="onAppearanceChange()">Sem ripple</mat-slide-toggle>
|
|
484
|
-
<mat-slide-toggle [(ngModel)]="group.preserveContent" (ngModelChange)="onAppearanceChange()">Preservar conteudo</mat-slide-toggle>
|
|
485
|
-
<mat-slide-toggle [(ngModel)]="group.stretchTabs" (ngModelChange)="onAppearanceChange()">Esticar abas</mat-slide-toggle>
|
|
1081
|
+
<mat-slide-toggle [(ngModel)]="group.dynamicHeight" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.dynamicHeight', 'Altura dinamica') }}</mat-slide-toggle>
|
|
1082
|
+
<mat-slide-toggle [(ngModel)]="group.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.fitInkBarToContent', 'Indicador ajustado ao conteudo') }}</mat-slide-toggle>
|
|
1083
|
+
<mat-slide-toggle [(ngModel)]="group.disablePagination" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disablePagination', 'Sem paginacao') }}</mat-slide-toggle>
|
|
1084
|
+
<mat-slide-toggle [(ngModel)]="group.disableRipple" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disableRipple', 'Sem ripple') }}</mat-slide-toggle>
|
|
1085
|
+
<mat-slide-toggle [(ngModel)]="group.preserveContent" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.preserveContent', 'Preservar conteudo') }}</mat-slide-toggle>
|
|
1086
|
+
<mat-slide-toggle [(ngModel)]="group.stretchTabs" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.stretchTabs', 'Esticar abas') }}</mat-slide-toggle>
|
|
486
1087
|
</div>
|
|
487
1088
|
</div>
|
|
488
1089
|
</mat-tab>
|
|
489
1090
|
|
|
490
|
-
<mat-tab label="
|
|
1091
|
+
<mat-tab [label]="t('editor.tabs.nav', 'Navegacao')" [disabled]="primaryMode !== 'nav'">
|
|
491
1092
|
<div class="editor-section">
|
|
492
1093
|
<div class="editor-grid two">
|
|
493
|
-
<mat-form-field appearance="outline"><mat-label>Indice selecionado</mat-label>
|
|
1094
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.selectedIndex', 'Indice selecionado') }}</mat-label>
|
|
494
1095
|
<input matInput type="number" [(ngModel)]="nav.selectedIndex" (ngModelChange)="onAppearanceChange()" />
|
|
495
1096
|
<button
|
|
496
1097
|
mat-icon-button
|
|
497
1098
|
matSuffix
|
|
498
1099
|
class="help-icon-button"
|
|
499
1100
|
type="button"
|
|
500
|
-
[matTooltip]="'selectedIndex'"
|
|
1101
|
+
[matTooltip]="t('editor.hints.selectedIndex', 'selectedIndex')"
|
|
501
1102
|
matTooltipPosition="above"
|
|
502
1103
|
>
|
|
503
1104
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
504
1105
|
</button>
|
|
505
1106
|
</mat-form-field>
|
|
506
|
-
<mat-form-field appearance="outline"><mat-label>Duracao da animacao</mat-label>
|
|
507
|
-
<input matInput [(ngModel)]="nav.animationDuration" (ngModelChange)="onAppearanceChange()" placeholder="500ms" />
|
|
1107
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.animationDuration', 'Duracao da animacao') }}</mat-label>
|
|
1108
|
+
<input matInput [(ngModel)]="nav.animationDuration" (ngModelChange)="onAppearanceChange()" [placeholder]="t('editor.fields.placeholder.animationDuration', '500ms')" />
|
|
508
1109
|
<button
|
|
509
1110
|
mat-icon-button
|
|
510
1111
|
matSuffix
|
|
511
1112
|
class="help-icon-button"
|
|
512
1113
|
type="button"
|
|
513
|
-
[matTooltip]="'animationDuration'"
|
|
1114
|
+
[matTooltip]="t('editor.hints.animationDuration', 'animationDuration')"
|
|
514
1115
|
matTooltipPosition="above"
|
|
515
1116
|
>
|
|
516
1117
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
517
1118
|
</button>
|
|
518
1119
|
</mat-form-field>
|
|
519
|
-
<mat-form-field appearance="outline"><mat-label>aria-label</mat-label>
|
|
1120
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.ariaLabel', 'aria-label') }}</mat-label>
|
|
520
1121
|
<input matInput [(ngModel)]="nav.ariaLabel" (ngModelChange)="onAppearanceChange()" />
|
|
521
1122
|
</mat-form-field>
|
|
522
|
-
<mat-form-field appearance="outline"><mat-label>aria-labelledby</mat-label>
|
|
1123
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.ariaLabelledby', 'aria-labelledby') }}</mat-label>
|
|
523
1124
|
<input matInput [(ngModel)]="nav.ariaLabelledby" (ngModelChange)="onAppearanceChange()" />
|
|
524
1125
|
</mat-form-field>
|
|
525
|
-
<mat-form-field appearance="outline"><mat-label>Cor (M2)</mat-label>
|
|
1126
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.color', 'Cor (M2)') }}</mat-label>
|
|
526
1127
|
<select matNativeControl [(ngModel)]="nav.color" (ngModelChange)="onAppearanceChange()">
|
|
527
|
-
<option [ngValue]="undefined">(nenhuma)</option>
|
|
528
|
-
<option value="primary">Primary</option>
|
|
529
|
-
<option value="accent">Accent</option>
|
|
530
|
-
<option value="warn">Warn</option>
|
|
1128
|
+
<option [ngValue]="undefined">{{ t('editor.options.none', '(nenhuma)') }}</option>
|
|
1129
|
+
<option value="primary">{{ t('editor.options.primary', 'Primary') }}</option>
|
|
1130
|
+
<option value="accent">{{ t('editor.options.accent', 'Accent') }}</option>
|
|
1131
|
+
<option value="warn">{{ t('editor.options.warn', 'Warn') }}</option>
|
|
531
1132
|
</select>
|
|
532
1133
|
<button
|
|
533
1134
|
mat-icon-button
|
|
534
1135
|
matSuffix
|
|
535
1136
|
class="help-icon-button"
|
|
536
1137
|
type="button"
|
|
537
|
-
[matTooltip]="'Preferir tokens em Estilo.'"
|
|
1138
|
+
[matTooltip]="t('editor.hints.preferTokens', 'Preferir tokens em Estilo.')"
|
|
538
1139
|
matTooltipPosition="above"
|
|
539
1140
|
>
|
|
540
1141
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
541
1142
|
</button>
|
|
542
1143
|
</mat-form-field>
|
|
543
|
-
<mat-form-field appearance="outline"><mat-label>Cor de fundo (M2)</mat-label>
|
|
1144
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.backgroundColor', 'Cor de fundo (M2)') }}</mat-label>
|
|
544
1145
|
<select matNativeControl [(ngModel)]="nav.backgroundColor" (ngModelChange)="onAppearanceChange()">
|
|
545
|
-
<option [ngValue]="undefined">(nenhuma)</option>
|
|
546
|
-
<option value="primary">Primary</option>
|
|
547
|
-
<option value="accent">Accent</option>
|
|
548
|
-
<option value="warn">Warn</option>
|
|
1146
|
+
<option [ngValue]="undefined">{{ t('editor.options.none', '(nenhuma)') }}</option>
|
|
1147
|
+
<option value="primary">{{ t('editor.options.primary', 'Primary') }}</option>
|
|
1148
|
+
<option value="accent">{{ t('editor.options.accent', 'Accent') }}</option>
|
|
1149
|
+
<option value="warn">{{ t('editor.options.warn', 'Warn') }}</option>
|
|
549
1150
|
</select>
|
|
550
1151
|
<button
|
|
551
1152
|
mat-icon-button
|
|
552
1153
|
matSuffix
|
|
553
1154
|
class="help-icon-button"
|
|
554
1155
|
type="button"
|
|
555
|
-
[matTooltip]="'Preferir tokens em Estilo.'"
|
|
1156
|
+
[matTooltip]="t('editor.hints.preferTokens', 'Preferir tokens em Estilo.')"
|
|
556
1157
|
matTooltipPosition="above"
|
|
557
1158
|
>
|
|
558
1159
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
@@ -560,26 +1161,26 @@ class PraxisTabsConfigEditor {
|
|
|
560
1161
|
</mat-form-field>
|
|
561
1162
|
</div>
|
|
562
1163
|
<div class="editor-row">
|
|
563
|
-
<mat-slide-toggle [(ngModel)]="nav.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">Indicador ajustado ao conteudo</mat-slide-toggle>
|
|
564
|
-
<mat-slide-toggle [(ngModel)]="nav.disablePagination" (ngModelChange)="onAppearanceChange()">Sem paginacao</mat-slide-toggle>
|
|
565
|
-
<mat-slide-toggle [(ngModel)]="nav.disableRipple" (ngModelChange)="onAppearanceChange()">Sem ripple</mat-slide-toggle>
|
|
566
|
-
<mat-slide-toggle [(ngModel)]="nav.stretchTabs" (ngModelChange)="onAppearanceChange()">Esticar abas</mat-slide-toggle>
|
|
1164
|
+
<mat-slide-toggle [(ngModel)]="nav.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.fitInkBarToContent', 'Indicador ajustado ao conteudo') }}</mat-slide-toggle>
|
|
1165
|
+
<mat-slide-toggle [(ngModel)]="nav.disablePagination" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disablePagination', 'Sem paginacao') }}</mat-slide-toggle>
|
|
1166
|
+
<mat-slide-toggle [(ngModel)]="nav.disableRipple" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disableRipple', 'Sem ripple') }}</mat-slide-toggle>
|
|
1167
|
+
<mat-slide-toggle [(ngModel)]="nav.stretchTabs" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.stretchTabs', 'Esticar abas') }}</mat-slide-toggle>
|
|
567
1168
|
</div>
|
|
568
1169
|
</div>
|
|
569
1170
|
</mat-tab>
|
|
570
|
-
<mat-tab label="JSON">
|
|
1171
|
+
<mat-tab [label]="t('editor.tabs.json', 'JSON')">
|
|
571
1172
|
<div class="editor-section">
|
|
572
1173
|
<div class="editor-toolbar">
|
|
573
|
-
<button mat-button (click)="formatJson()" [disabled]="!isValid">
|
|
574
|
-
<mat-icon [praxisIcon]="'format_align_left'"></mat-icon>Formatar
|
|
1174
|
+
<button mat-button (click)="formatJson()" [disabled]="!isValid">
|
|
1175
|
+
<mat-icon [praxisIcon]="'format_align_left'"></mat-icon>{{ t('editor.actions.format', 'Formatar') }}
|
|
575
1176
|
</button>
|
|
576
|
-
<button mat-button (click)="reset()">
|
|
577
|
-
<mat-icon [praxisIcon]="'restart_alt'"></mat-icon>Resetar
|
|
1177
|
+
<button mat-button (click)="reset()">
|
|
1178
|
+
<mat-icon [praxisIcon]="'restart_alt'"></mat-icon>{{ t('editor.actions.reset', 'Resetar') }}
|
|
578
1179
|
</button>
|
|
579
1180
|
</div>
|
|
580
1181
|
|
|
581
1182
|
<mat-form-field appearance="outline" class="json-textarea-field full">
|
|
582
|
-
<mat-label>Configuracao JSON</mat-label>
|
|
1183
|
+
<mat-label>{{ t('editor.fields.jsonConfig', 'Configuracao JSON') }}</mat-label>
|
|
583
1184
|
<textarea
|
|
584
1185
|
matInput
|
|
585
1186
|
[(ngModel)]="jsonText"
|
|
@@ -588,84 +1189,84 @@ class PraxisTabsConfigEditor {
|
|
|
588
1189
|
spellcheck="false"
|
|
589
1190
|
class="editor-json"
|
|
590
1191
|
></textarea>
|
|
591
|
-
<mat-hint *ngIf="isValid">JSON valido</mat-hint>
|
|
592
|
-
<mat-error *ngIf="!isValid && jsonText">JSON invalido: {{ errorMsg }}</mat-error>
|
|
1192
|
+
<mat-hint *ngIf="isValid">{{ t('editor.json.valid', 'JSON valido') }}</mat-hint>
|
|
1193
|
+
<mat-error *ngIf="!isValid && jsonText">{{ t('editor.json.invalidPrefix', 'JSON invalido:') }} {{ errorMsg }}</mat-error>
|
|
593
1194
|
</mat-form-field>
|
|
594
1195
|
</div>
|
|
595
1196
|
</mat-tab>
|
|
596
1197
|
|
|
597
|
-
<mat-tab label="Estilo">
|
|
1198
|
+
<mat-tab [label]="t('editor.tabs.style', 'Estilo')">
|
|
598
1199
|
<div class="editor-section editor-section-lg">
|
|
599
1200
|
<div class="editor-row">
|
|
600
|
-
<span class="editor-muted">Presets
|
|
1201
|
+
<span class="editor-muted">{{ t('editor.presets.title', 'Presets:') }}</span>
|
|
601
1202
|
<button mat-button color="primary" (click)="applyPreset('primary')">
|
|
602
1203
|
<mat-icon [praxisIcon]="'palette'"></mat-icon>
|
|
603
|
-
|
|
1204
|
+
{{ t('editor.presets.primary', 'Primario') }}
|
|
604
1205
|
</button>
|
|
605
1206
|
<button mat-button (click)="applyPreset('neutral')">
|
|
606
1207
|
<mat-icon [praxisIcon]="'contrast'"></mat-icon>
|
|
607
|
-
Neutro
|
|
1208
|
+
{{ t('editor.presets.neutral', 'Neutro') }}
|
|
608
1209
|
</button>
|
|
609
1210
|
<button mat-button (click)="applyPreset('high-contrast')">
|
|
610
1211
|
<mat-icon [praxisIcon]="'visibility'"></mat-icon>
|
|
611
|
-
Alto contraste
|
|
1212
|
+
{{ t('editor.presets.highContrast', 'Alto contraste') }}
|
|
612
1213
|
</button>
|
|
613
1214
|
<button mat-button (click)="clearTokens()">
|
|
614
1215
|
<mat-icon [praxisIcon]="'backspace'"></mat-icon>
|
|
615
|
-
Limpar tokens
|
|
1216
|
+
{{ t('editor.actions.clearTokens', 'Limpar tokens') }}
|
|
616
1217
|
</button>
|
|
617
1218
|
</div>
|
|
618
1219
|
|
|
619
1220
|
<div class="editor-grid two tight">
|
|
620
1221
|
<mat-form-field appearance="outline">
|
|
621
|
-
<mat-label>Classe de tema (opcional)</mat-label>
|
|
622
|
-
<input matInput [(ngModel)]="appearance.themeClass" (ngModelChange)="onAppearanceChange()" placeholder="ex.: tabs-accented" />
|
|
1222
|
+
<mat-label>{{ t('editor.fields.themeClass', 'Classe de tema (opcional)') }}</mat-label>
|
|
1223
|
+
<input matInput [(ngModel)]="appearance.themeClass" (ngModelChange)="onAppearanceChange()" [placeholder]="t('editor.fields.placeholder.themeClass', 'ex.: tabs-accented')" />
|
|
623
1224
|
</mat-form-field>
|
|
624
1225
|
|
|
625
1226
|
<mat-form-field appearance="outline">
|
|
626
|
-
<mat-label>Densidade</mat-label>
|
|
1227
|
+
<mat-label>{{ t('editor.fields.density', 'Densidade') }}</mat-label>
|
|
627
1228
|
<select matNativeControl [(ngModel)]="appearance.density" (ngModelChange)="onAppearanceChange()">
|
|
628
|
-
<option [ngValue]="undefined">Padrao</option>
|
|
629
|
-
<option value="compact">Compacta</option>
|
|
630
|
-
<option value="comfortable">Confortavel</option>
|
|
631
|
-
<option value="spacious">Espacosa</option>
|
|
1229
|
+
<option [ngValue]="undefined">{{ t('editor.density.default', 'Padrao') }}</option>
|
|
1230
|
+
<option value="compact">{{ t('editor.density.compact', 'Compacta') }}</option>
|
|
1231
|
+
<option value="comfortable">{{ t('editor.density.comfortable', 'Confortavel') }}</option>
|
|
1232
|
+
<option value="spacious">{{ t('editor.density.spacious', 'Espacosa') }}</option>
|
|
632
1233
|
</select>
|
|
633
1234
|
</mat-form-field>
|
|
634
1235
|
</div>
|
|
635
1236
|
|
|
636
1237
|
<div>
|
|
637
1238
|
<div class="editor-title-row">
|
|
638
|
-
<h3 class="editor-title">Tokens (Material 3)</h3>
|
|
1239
|
+
<h3 class="editor-title">{{ t('editor.sections.tokens', 'Tokens (Material 3)') }}</h3>
|
|
639
1240
|
<button
|
|
640
1241
|
mat-icon-button
|
|
641
1242
|
class="help-icon-button"
|
|
642
1243
|
type="button"
|
|
643
|
-
[matTooltip]="'Valores aceitam CSS vars
|
|
1244
|
+
[matTooltip]="t('editor.hints.tokenValueHelp', 'Valores aceitam CSS vars ou cores hex/rgb.')"
|
|
644
1245
|
matTooltipPosition="above"
|
|
645
1246
|
>
|
|
646
1247
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
647
1248
|
</button>
|
|
648
1249
|
</div>
|
|
649
1250
|
<div class="editor-grid two">
|
|
650
|
-
<ng-container *ngFor="let
|
|
1251
|
+
<ng-container *ngFor="let token of tokenList">
|
|
651
1252
|
<mat-form-field appearance="outline">
|
|
652
|
-
<mat-label>{{ t.
|
|
653
|
-
<input matInput placeholder="var(--md-sys-color-primary) / #RRGGBB" [ngModel]="appearance.tokens?.[
|
|
1253
|
+
<mat-label>{{ t(token.labelKey, token.fallback) }}</mat-label>
|
|
1254
|
+
<input matInput [placeholder]="t('editor.placeholders.tokenValue', 'var(--md-sys-color-primary) / #RRGGBB')" [ngModel]="appearance.tokens?.[token.key]" (ngModelChange)="onTokenChange(token.key, $event)" />
|
|
654
1255
|
</mat-form-field>
|
|
655
1256
|
</ng-container>
|
|
656
1257
|
</div>
|
|
657
1258
|
</div>
|
|
658
1259
|
|
|
659
1260
|
<div>
|
|
660
|
-
<h3 class="editor-title">CSS personalizado</h3>
|
|
1261
|
+
<h3 class="editor-title">{{ t('editor.sections.customCss', 'CSS personalizado') }}</h3>
|
|
661
1262
|
<mat-form-field appearance="outline" class="json-textarea-field full">
|
|
662
|
-
<mat-label>CSS a ser injetado no componente</mat-label>
|
|
663
|
-
<textarea matInput rows="10" [(ngModel)]="appearance.customCss" (ngModelChange)="onAppearanceChange()" placeholder=".praxis-tabs-root .mdc-tab__text-label { font-weight: 600; }"></textarea>
|
|
1263
|
+
<mat-label>{{ t('editor.fields.customCss', 'CSS a ser injetado no componente') }}</mat-label>
|
|
1264
|
+
<textarea matInput rows="10" [(ngModel)]="appearance.customCss" (ngModelChange)="onAppearanceChange()" [placeholder]="t('editor.placeholders.customCssExample', '.praxis-tabs-root .mdc-tab__text-label { font-weight: 600; }')"></textarea>
|
|
664
1265
|
</mat-form-field>
|
|
665
1266
|
</div>
|
|
666
1267
|
|
|
667
1268
|
<div>
|
|
668
|
-
<h3 class="editor-title">Snippet SCSS (para uso em styles.scss)</h3>
|
|
1269
|
+
<h3 class="editor-title">{{ t('editor.sections.scssSnippet', 'Snippet SCSS (para uso em styles.scss)') }}</h3>
|
|
669
1270
|
<pre class="editor-code">
|
|
670
1271
|
@use '@angular/material' as mat;
|
|
671
1272
|
{{ scssSnippet() }}
|
|
@@ -674,76 +1275,76 @@ class PraxisTabsConfigEditor {
|
|
|
674
1275
|
</div>
|
|
675
1276
|
</mat-tab>
|
|
676
1277
|
|
|
677
|
-
<mat-tab label="Abas">
|
|
1278
|
+
<mat-tab [label]="t('editor.tabs.items', 'Abas')" [disabled]="primaryMode !== 'group'">
|
|
678
1279
|
<div class="editor-section">
|
|
679
|
-
<button mat-stroked-button color="primary" (click)="addTab()"><mat-icon [praxisIcon]="'add'"></mat-icon>Adicionar aba</button>
|
|
1280
|
+
<button mat-stroked-button color="primary" (click)="addTab()"><mat-icon [praxisIcon]="'add'"></mat-icon>{{ t('editor.actions.addTab', 'Adicionar aba') }}</button>
|
|
680
1281
|
<div *ngIf="editedConfig.tabs?.length; else noTabs" class="editor-grid">
|
|
681
|
-
<div *ngFor="let
|
|
1282
|
+
<div *ngFor="let tab of editedConfig.tabs; let i = index" class="editor-card">
|
|
682
1283
|
<div class="editor-card-header">
|
|
683
|
-
<strong class="editor-card-title">Aba #{{ i+1 }}</strong>
|
|
1284
|
+
<strong class="editor-card-title">{{ t('editor.cards.tab', 'Aba') }} #{{ i+1 }}</strong>
|
|
684
1285
|
<button mat-icon-button (click)="moveTab(i, -1)" [disabled]="i===0"><mat-icon [praxisIcon]="'arrow_upward'"></mat-icon></button>
|
|
685
1286
|
<button mat-icon-button (click)="moveTab(i, 1)" [disabled]="i===editedConfig.tabs!.length-1"><mat-icon [praxisIcon]="'arrow_downward'"></mat-icon></button>
|
|
686
1287
|
<button mat-icon-button color="warn" (click)="removeTab(i)"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
687
1288
|
</div>
|
|
688
1289
|
<div class="editor-grid two tight">
|
|
689
|
-
<mat-form-field appearance="outline"><mat-label>ID</mat-label>
|
|
690
|
-
<input matInput [(ngModel)]="
|
|
1290
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.id', 'ID') }}</mat-label>
|
|
1291
|
+
<input matInput [(ngModel)]="tab.id" (ngModelChange)="onAppearanceChange()" />
|
|
691
1292
|
</mat-form-field>
|
|
692
|
-
<mat-form-field appearance="outline"><mat-label>Rotulo</mat-label>
|
|
693
|
-
<input matInput [(ngModel)]="
|
|
1293
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.label', 'Rotulo') }}</mat-label>
|
|
1294
|
+
<input matInput [(ngModel)]="tab.textLabel" (ngModelChange)="onAppearanceChange()" />
|
|
694
1295
|
</mat-form-field>
|
|
695
|
-
<mat-form-field appearance="outline"><mat-label>Classe do rotulo</mat-label>
|
|
696
|
-
<input matInput [(ngModel)]="
|
|
1296
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.labelClass', 'Classe do rotulo') }}</mat-label>
|
|
1297
|
+
<input matInput [(ngModel)]="tab.labelClass" (ngModelChange)="onAppearanceChange()" />
|
|
697
1298
|
</mat-form-field>
|
|
698
|
-
<mat-form-field appearance="outline"><mat-label>Classe do conteudo</mat-label>
|
|
699
|
-
<input matInput [(ngModel)]="
|
|
1299
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.bodyClass', 'Classe do conteudo') }}</mat-label>
|
|
1300
|
+
<input matInput [(ngModel)]="tab.bodyClass" (ngModelChange)="onAppearanceChange()" />
|
|
700
1301
|
</mat-form-field>
|
|
701
|
-
|
|
702
|
-
<input matInput [(ngModel)]="
|
|
1302
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.ariaLabel', 'aria-label') }}</mat-label>
|
|
1303
|
+
<input matInput [(ngModel)]="tab.ariaLabel" (ngModelChange)="onAppearanceChange()" />
|
|
703
1304
|
</mat-form-field>
|
|
704
|
-
|
|
705
|
-
<input matInput [(ngModel)]="
|
|
1305
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.ariaLabelledby', 'aria-labelledby') }}</mat-label>
|
|
1306
|
+
<input matInput [(ngModel)]="tab.ariaLabelledby" (ngModelChange)="onAppearanceChange()" />
|
|
706
1307
|
</mat-form-field>
|
|
707
1308
|
</div>
|
|
708
|
-
<mat-slide-toggle [(ngModel)]="
|
|
1309
|
+
<mat-slide-toggle [(ngModel)]="tab.disabled" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disabled', 'Desativada') }}</mat-slide-toggle>
|
|
709
1310
|
|
|
710
1311
|
<!-- Widgets (componentes dinâmicos) -->
|
|
711
1312
|
<div class="editor-divider editor-grid">
|
|
712
1313
|
<div class="editor-row">
|
|
713
1314
|
<mat-form-field appearance="outline" class="editor-field-min">
|
|
714
|
-
<mat-label>Adicionar componente</mat-label>
|
|
1315
|
+
<mat-label>{{ t('editor.fields.addComponent', 'Adicionar componente') }}</mat-label>
|
|
715
1316
|
<select matNativeControl [(ngModel)]="selectedTabWidgetId[i]">
|
|
716
|
-
<option [ngValue]="''">(selecione)</option>
|
|
1317
|
+
<option [ngValue]="''">{{ t('editor.fields.selectPlaceholder', '(selecione)') }}</option>
|
|
717
1318
|
<option *ngFor="let c of componentOptions" [ngValue]="c.id">{{ c.friendlyName || c.id }}</option>
|
|
718
1319
|
</select>
|
|
719
1320
|
</mat-form-field>
|
|
720
|
-
<button mat-stroked-button (click)="addWidgetToTab(i)"><mat-icon [praxisIcon]="'add'"></mat-icon>Adicionar</button>
|
|
1321
|
+
<button mat-stroked-button (click)="addWidgetToTab(i)"><mat-icon [praxisIcon]="'add'"></mat-icon>{{ t('editor.actions.add', 'Adicionar') }}</button>
|
|
721
1322
|
<span class="editor-spacer"></span>
|
|
722
1323
|
<mat-form-field appearance="outline" class="editor-field-240">
|
|
723
|
-
<mat-label>Recurso (resourcePath)</mat-label>
|
|
724
|
-
<input matInput [(ngModel)]="quickResourcePathTab[i]" placeholder="ex.: usuarios" />
|
|
1324
|
+
<mat-label>{{ t('editor.fields.resourcePath', 'Recurso (resourcePath)') }}</mat-label>
|
|
1325
|
+
<input matInput [(ngModel)]="quickResourcePathTab[i]" [placeholder]="t('editor.fields.placeholder.resourcePath', 'ex.: usuarios')" />
|
|
725
1326
|
</mat-form-field>
|
|
726
|
-
<button mat-button (click)="addPresetToTab(i, 'form')"><mat-icon [praxisIcon]="'description'"></mat-icon>Form</button>
|
|
727
|
-
<button mat-button (click)="addPresetToTab(i, 'table')"><mat-icon [praxisIcon]="'grid_on'"></mat-icon>Tabela</button>
|
|
728
|
-
<button mat-button (click)="addPresetToTab(i, 'crud')"><mat-icon [praxisIcon]="'dynamic_form'"></mat-icon>CRUD</button>
|
|
1327
|
+
<button mat-button (click)="addPresetToTab(i, 'form')"><mat-icon [praxisIcon]="'description'"></mat-icon>{{ t('editor.templates.form', 'Form') }}</button>
|
|
1328
|
+
<button mat-button (click)="addPresetToTab(i, 'table')"><mat-icon [praxisIcon]="'grid_on'"></mat-icon>{{ t('editor.templates.table', 'Tabela') }}</button>
|
|
1329
|
+
<button mat-button (click)="addPresetToTab(i, 'crud')"><mat-icon [praxisIcon]="'dynamic_form'"></mat-icon>{{ t('editor.templates.crud', 'CRUD') }}</button>
|
|
729
1330
|
</div>
|
|
730
1331
|
|
|
731
|
-
|
|
732
|
-
|
|
1332
|
+
<div *ngIf="tab.widgets?.length" class="editor-grid" cdkDropList [cdkDropListData]="tab.widgets || []" (cdkDropListDropped)="onTabWidgetDrop(i, $event)">
|
|
1333
|
+
<div *ngFor="let w of tab.widgets; let wi = index" cdkDrag class="editor-card dashed">
|
|
733
1334
|
<div class="editor-card-header">
|
|
734
|
-
<button mat-icon-button cdkDragHandle matTooltip="Arrastar para reordenar" aria-label="Arrastar para reordenar">
|
|
1335
|
+
<button mat-icon-button cdkDragHandle [matTooltip]="t('editor.actions.dragToReorder', 'Arrastar para reordenar')" [attr.aria-label]="t('editor.actions.dragToReorder', 'Arrastar para reordenar')">
|
|
735
1336
|
<mat-icon [praxisIcon]="'drag_indicator'"></mat-icon>
|
|
736
1337
|
</button>
|
|
737
1338
|
<strong class="editor-card-title">{{ getCompName(w.id) }}</strong>
|
|
738
|
-
<button mat-icon-button color="warn" (click)="removeWidgetFromTab(i, wi)" matTooltip="Remover componente" aria-label="Remover componente"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
1339
|
+
<button mat-icon-button color="warn" (click)="removeWidgetFromTab(i, wi)" [matTooltip]="t('editor.actions.removeComponent', 'Remover componente')" [attr.aria-label]="t('editor.actions.removeComponent', 'Remover componente')"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
739
1340
|
</div>
|
|
740
1341
|
<div class="editor-grid two tight">
|
|
741
1342
|
<mat-form-field appearance="outline">
|
|
742
|
-
<mat-label>Inputs (JSON)</mat-label>
|
|
1343
|
+
<mat-label>{{ t('editor.fields.inputsJson', 'Inputs (JSON)') }}</mat-label>
|
|
743
1344
|
<textarea matInput rows="4" [ngModel]="stringify(w.inputs)" (ngModelChange)="updateWidgetInputsTab(i, wi, $event)"></textarea>
|
|
744
1345
|
</mat-form-field>
|
|
745
1346
|
<mat-form-field appearance="outline">
|
|
746
|
-
<mat-label>Outputs (JSON)</mat-label>
|
|
1347
|
+
<mat-label>{{ t('editor.fields.outputsJson', 'Outputs (JSON)') }}</mat-label>
|
|
747
1348
|
<textarea matInput rows="4" [ngModel]="stringify(w.outputs)" (ngModelChange)="updateWidgetOutputsTab(i, wi, $event)"></textarea>
|
|
748
1349
|
</mat-form-field>
|
|
749
1350
|
</div>
|
|
@@ -752,82 +1353,81 @@ class PraxisTabsConfigEditor {
|
|
|
752
1353
|
</div>
|
|
753
1354
|
</div>
|
|
754
1355
|
</div>
|
|
755
|
-
<ng-template #noTabs><em class="editor-muted">Nenhuma aba definida
|
|
1356
|
+
<ng-template #noTabs><em class="editor-muted">{{ t('editor.empty.noTabs', 'Nenhuma aba definida.') }}</em></ng-template>
|
|
756
1357
|
</div>
|
|
757
1358
|
</mat-tab>
|
|
758
1359
|
|
|
759
|
-
<mat-tab label="Acessibilidade">
|
|
1360
|
+
<mat-tab [label]="t('editor.tabs.accessibility', 'Acessibilidade')">
|
|
760
1361
|
<div class="editor-section">
|
|
761
1362
|
<div class="editor-row">
|
|
762
|
-
<mat-slide-toggle [(ngModel)]="accessibility.highContrast" (ngModelChange)="onAppearanceChange()">Alto contraste</mat-slide-toggle>
|
|
763
|
-
<mat-slide-toggle [(ngModel)]="accessibility.reduceMotion" (ngModelChange)="onAppearanceChange()">Reduzir movimento</mat-slide-toggle>
|
|
1363
|
+
<mat-slide-toggle [(ngModel)]="accessibility.highContrast" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.highContrast', 'Alto contraste') }}</mat-slide-toggle>
|
|
1364
|
+
<mat-slide-toggle [(ngModel)]="accessibility.reduceMotion" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.reduceMotion', 'Reduzir movimento') }}</mat-slide-toggle>
|
|
764
1365
|
</div>
|
|
765
1366
|
</div>
|
|
766
1367
|
</mat-tab>
|
|
767
1368
|
|
|
768
|
-
<mat-tab label="Links">
|
|
1369
|
+
<mat-tab [label]="t('editor.tabs.links', 'Links')" [disabled]="primaryMode !== 'nav'">
|
|
769
1370
|
<div class="editor-section">
|
|
770
|
-
<button mat-stroked-button color="primary" (click)="addLink()"><mat-icon [praxisIcon]="'add_link'"></mat-icon>Adicionar link</button>
|
|
1371
|
+
<button mat-stroked-button color="primary" (click)="addLink()"><mat-icon [praxisIcon]="'add_link'"></mat-icon>{{ t('editor.actions.addLink', 'Adicionar link') }}</button>
|
|
771
1372
|
<div *ngIf="nav.links?.length; else noLinks" class="editor-grid">
|
|
772
1373
|
<div *ngFor="let l of nav.links; let i = index" class="editor-card">
|
|
773
1374
|
<div class="editor-card-header">
|
|
774
|
-
<strong class="editor-card-title">Link #{{ i+1 }}</strong>
|
|
1375
|
+
<strong class="editor-card-title">{{ t('editor.cards.link', 'Link') }} #{{ i+1 }}</strong>
|
|
775
1376
|
<button mat-icon-button (click)="moveLink(i, -1)" [disabled]="i===0"><mat-icon [praxisIcon]="'arrow_upward'"></mat-icon></button>
|
|
776
1377
|
<button mat-icon-button (click)="moveLink(i, 1)" [disabled]="i===nav.links!.length-1"><mat-icon [praxisIcon]="'arrow_downward'"></mat-icon></button>
|
|
777
1378
|
<button mat-icon-button color="warn" (click)="removeLink(i)"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
778
1379
|
</div>
|
|
779
1380
|
<div class="editor-grid two tight">
|
|
780
|
-
<mat-form-field appearance="outline"><mat-label>ID</mat-label>
|
|
1381
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.id', 'ID') }}</mat-label>
|
|
781
1382
|
<input matInput [(ngModel)]="l.id" (ngModelChange)="onAppearanceChange()" />
|
|
782
1383
|
</mat-form-field>
|
|
783
|
-
<mat-form-field appearance="outline"><mat-label>Rotulo</mat-label>
|
|
1384
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.label', 'Rotulo') }}</mat-label>
|
|
784
1385
|
<input matInput [(ngModel)]="l.label" (ngModelChange)="onAppearanceChange()" />
|
|
785
1386
|
</mat-form-field>
|
|
786
1387
|
</div>
|
|
787
1388
|
<div class="editor-row">
|
|
788
|
-
<mat-slide-toggle [(ngModel)]="l.
|
|
789
|
-
<mat-slide-toggle [(ngModel)]="l.
|
|
790
|
-
<mat-slide-toggle [(ngModel)]="l.
|
|
791
|
-
<mat-slide-toggle [(ngModel)]="l.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">Indicador ajustado ao conteudo</mat-slide-toggle>
|
|
1389
|
+
<mat-slide-toggle [(ngModel)]="l.disabled" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.linkDisabled', 'Desativado') }}</mat-slide-toggle>
|
|
1390
|
+
<mat-slide-toggle [(ngModel)]="l.disableRipple" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disableRipple', 'Sem ripple') }}</mat-slide-toggle>
|
|
1391
|
+
<mat-slide-toggle [(ngModel)]="l.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.fitInkBarToContent', 'Indicador ajustado ao conteudo') }}</mat-slide-toggle>
|
|
792
1392
|
</div>
|
|
793
1393
|
|
|
794
1394
|
<!-- Widgets para Links -->
|
|
795
1395
|
<div class="editor-divider editor-grid">
|
|
796
1396
|
<div class="editor-row">
|
|
797
1397
|
<mat-form-field appearance="outline" class="editor-field-min">
|
|
798
|
-
<mat-label>Adicionar componente</mat-label>
|
|
1398
|
+
<mat-label>{{ t('editor.fields.addComponent', 'Adicionar componente') }}</mat-label>
|
|
799
1399
|
<select matNativeControl [(ngModel)]="selectedLinkWidgetId[i]">
|
|
800
|
-
<option [ngValue]="''">(selecione)</option>
|
|
1400
|
+
<option [ngValue]="''">{{ t('editor.fields.selectPlaceholder', '(selecione)') }}</option>
|
|
801
1401
|
<option *ngFor="let c of componentOptions" [ngValue]="c.id">{{ c.friendlyName || c.id }}</option>
|
|
802
1402
|
</select>
|
|
803
1403
|
</mat-form-field>
|
|
804
|
-
<button mat-stroked-button (click)="addWidgetToLink(i)"><mat-icon [praxisIcon]="'add'"></mat-icon>Adicionar</button>
|
|
1404
|
+
<button mat-stroked-button (click)="addWidgetToLink(i)"><mat-icon [praxisIcon]="'add'"></mat-icon>{{ t('editor.actions.add', 'Adicionar') }}</button>
|
|
805
1405
|
<span class="editor-spacer"></span>
|
|
806
1406
|
<mat-form-field appearance="outline" class="editor-field-240">
|
|
807
|
-
<mat-label>Recurso (resourcePath)</mat-label>
|
|
808
|
-
<input matInput [(ngModel)]="quickResourcePathLink[i]" placeholder="ex.: usuarios" />
|
|
1407
|
+
<mat-label>{{ t('editor.fields.resourcePath', 'Recurso (resourcePath)') }}</mat-label>
|
|
1408
|
+
<input matInput [(ngModel)]="quickResourcePathLink[i]" [placeholder]="t('editor.fields.placeholder.resourcePath', 'ex.: usuarios')" />
|
|
809
1409
|
</mat-form-field>
|
|
810
|
-
<button mat-button (click)="addPresetToLink(i, 'form')"><mat-icon [praxisIcon]="'description'"></mat-icon>Form</button>
|
|
811
|
-
<button mat-button (click)="addPresetToLink(i, 'table')"><mat-icon [praxisIcon]="'grid_on'"></mat-icon>Tabela</button>
|
|
812
|
-
<button mat-button (click)="addPresetToLink(i, 'crud')"><mat-icon [praxisIcon]="'dynamic_form'"></mat-icon>CRUD</button>
|
|
1410
|
+
<button mat-button (click)="addPresetToLink(i, 'form')"><mat-icon [praxisIcon]="'description'"></mat-icon>{{ t('editor.templates.form', 'Form') }}</button>
|
|
1411
|
+
<button mat-button (click)="addPresetToLink(i, 'table')"><mat-icon [praxisIcon]="'grid_on'"></mat-icon>{{ t('editor.templates.table', 'Tabela') }}</button>
|
|
1412
|
+
<button mat-button (click)="addPresetToLink(i, 'crud')"><mat-icon [praxisIcon]="'dynamic_form'"></mat-icon>{{ t('editor.templates.crud', 'CRUD') }}</button>
|
|
813
1413
|
</div>
|
|
814
1414
|
|
|
815
1415
|
<div *ngIf="l.widgets?.length" class="editor-grid" cdkDropList [cdkDropListData]="l.widgets || []" (cdkDropListDropped)="onLinkWidgetDrop(i, $event)">
|
|
816
1416
|
<div *ngFor="let w of l.widgets; let wi = index" cdkDrag class="editor-card dashed">
|
|
817
1417
|
<div class="editor-card-header">
|
|
818
|
-
<button mat-icon-button cdkDragHandle matTooltip="Arrastar para reordenar" aria-label="Arrastar para reordenar">
|
|
1418
|
+
<button mat-icon-button cdkDragHandle [matTooltip]="t('editor.actions.dragToReorder', 'Arrastar para reordenar')" [attr.aria-label]="t('editor.actions.dragToReorder', 'Arrastar para reordenar')">
|
|
819
1419
|
<mat-icon [praxisIcon]="'drag_indicator'"></mat-icon>
|
|
820
1420
|
</button>
|
|
821
1421
|
<strong class="editor-card-title">{{ getCompName(w.id) }}</strong>
|
|
822
|
-
<button mat-icon-button color="warn" (click)="removeWidgetFromLink(i, wi)" matTooltip="Remover componente" aria-label="Remover componente"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
1422
|
+
<button mat-icon-button color="warn" (click)="removeWidgetFromLink(i, wi)" [matTooltip]="t('editor.actions.removeComponent', 'Remover componente')" [attr.aria-label]="t('editor.actions.removeComponent', 'Remover componente')"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
823
1423
|
</div>
|
|
824
1424
|
<div class="editor-grid two tight">
|
|
825
1425
|
<mat-form-field appearance="outline">
|
|
826
|
-
<mat-label>Inputs (JSON)</mat-label>
|
|
1426
|
+
<mat-label>{{ t('editor.fields.inputsJson', 'Inputs (JSON)') }}</mat-label>
|
|
827
1427
|
<textarea matInput rows="4" [ngModel]="stringify(w.inputs)" (ngModelChange)="updateWidgetInputsLink(i, wi, $event)"></textarea>
|
|
828
1428
|
</mat-form-field>
|
|
829
1429
|
<mat-form-field appearance="outline">
|
|
830
|
-
<mat-label>Outputs (JSON)</mat-label>
|
|
1430
|
+
<mat-label>{{ t('editor.fields.outputsJson', 'Outputs (JSON)') }}</mat-label>
|
|
831
1431
|
<textarea matInput rows="4" [ngModel]="stringify(w.outputs)" (ngModelChange)="updateWidgetOutputsLink(i, wi, $event)"></textarea>
|
|
832
1432
|
</mat-form-field>
|
|
833
1433
|
</div>
|
|
@@ -836,11 +1436,12 @@ class PraxisTabsConfigEditor {
|
|
|
836
1436
|
</div>
|
|
837
1437
|
</div>
|
|
838
1438
|
</div>
|
|
839
|
-
<ng-template #noLinks><em class="editor-muted">Nenhum link definido
|
|
1439
|
+
<ng-template #noLinks><em class="editor-muted">{{ t('editor.empty.noLinks', 'Nenhum link definido.') }}</em></ng-template>
|
|
840
1440
|
</div>
|
|
841
1441
|
</mat-tab>
|
|
842
1442
|
</mat-tab-group>
|
|
843
|
-
|
|
1443
|
+
</div>
|
|
1444
|
+
`, isInline: true, styles: [":host{display:block;color:var(--md-sys-color-on-surface)}.editor-shell{display:grid;gap:12px}.editor-topbar{display:flex;align-items:start;justify-content:flex-start}.editor-mode-field{width:min(320px,100%)}.editor-diagnostics{display:grid;gap:8px}.editor-diagnostics-title{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.editor-diagnostic{display:grid;gap:4px;padding:10px 12px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface)}.editor-diagnostic code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;color:var(--md-sys-color-on-surface-variant)}.editor-diagnostic.level-error{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-color:var(--md-sys-color-error)}.editor-diagnostic.level-warning{background:var(--md-sys-color-tertiary-container, var(--md-sys-color-surface-container));color:var(--md-sys-color-on-tertiary-container, var(--md-sys-color-on-surface));border-color:var(--md-sys-color-outline-variant)}.editor-tabs{--editor-surface: var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));--editor-border: 1px solid var(--md-sys-color-outline-variant);--editor-radius: 12px;--editor-muted: var(--md-sys-color-on-surface-variant)}.editor-section{padding:12px;display:grid;gap:12px;background:var(--editor-surface);border:var(--editor-border);border-radius:var(--editor-radius)}.editor-section-lg{gap:16px}.editor-row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}.editor-grid{display:grid;gap:12px}.editor-grid.two{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.editor-grid.tight{gap:8px}.editor-toolbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center}.editor-muted{color:var(--editor-muted)}.editor-title{margin:6px 0 8px;font-size:1rem}.editor-title-row{display:flex;align-items:center;gap:8px}.editor-code{white-space:pre-wrap;background:var(--md-sys-color-surface-container);padding:8px;border-radius:6px;border:1px solid var(--md-sys-color-outline-variant)}.editor-card{border:1px solid var(--md-sys-color-outline-variant);padding:10px;border-radius:10px;display:grid;gap:8px;background:var(--md-sys-color-surface)}.editor-card.dashed{border-style:dashed}.editor-card-header{display:flex;align-items:center;gap:8px}.editor-card-title{flex:1;font-weight:600}.editor-divider{border-top:1px solid var(--md-sys-color-outline-variant);padding-top:8px}.editor-spacer{flex:1}.editor-field-min{min-width:260px}.editor-section .editor-field-min{width:260px;max-width:260px}.editor-field-240{width:240px}.editor-section .editor-field-240{width:240px;max-width:240px}.editor-json{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.editor-section .mat-mdc-form-field{width:100%;max-width:520px;--mdc-outlined-text-field-container-height: 48px;--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-outline);--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-error-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-focus-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-hover-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-label-text-color: var(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-supporting-text-color: var(--md-sys-color-on-surface-variant)}.editor-section .mat-mdc-form-field.full{max-width:none}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { 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.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i3$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i3$1.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i5.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6$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: i6$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i9.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i10.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i10.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i10.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
|
|
844
1445
|
}
|
|
845
1446
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTabsConfigEditor, decorators: [{
|
|
846
1447
|
type: Component,
|
|
@@ -856,181 +1457,207 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
856
1457
|
MatSlideToggleModule,
|
|
857
1458
|
DragDropModule,
|
|
858
1459
|
MatTooltipModule,
|
|
859
|
-
], template: `
|
|
1460
|
+
], providers: [providePraxisI18nConfig(PRAXIS_TABS_I18N_CONFIG)], template: `
|
|
1461
|
+
<div class="editor-shell">
|
|
1462
|
+
<div class="editor-topbar">
|
|
1463
|
+
<mat-form-field appearance="outline" class="editor-mode-field">
|
|
1464
|
+
<mat-label>{{ t('editor.fields.mode', 'Modo principal') }}</mat-label>
|
|
1465
|
+
<select matNativeControl [ngModel]="primaryMode" (ngModelChange)="setPrimaryMode($event)">
|
|
1466
|
+
<option value="group">{{ t('editor.mode.group', 'Grupo de abas') }}</option>
|
|
1467
|
+
<option value="nav">{{ t('editor.mode.nav', 'Navegacao por links') }}</option>
|
|
1468
|
+
</select>
|
|
1469
|
+
</mat-form-field>
|
|
1470
|
+
</div>
|
|
1471
|
+
|
|
1472
|
+
<div *ngIf="diagnostics.length" class="editor-diagnostics">
|
|
1473
|
+
<div class="editor-diagnostics-title">{{ t('editor.diagnostics.title', 'Diagnosticos de authoring') }}</div>
|
|
1474
|
+
<div
|
|
1475
|
+
*ngFor="let diagnostic of diagnostics"
|
|
1476
|
+
class="editor-diagnostic"
|
|
1477
|
+
[class.level-error]="diagnostic.level === 'error'"
|
|
1478
|
+
[class.level-warning]="diagnostic.level === 'warning'"
|
|
1479
|
+
[class.level-info]="diagnostic.level === 'info'"
|
|
1480
|
+
>
|
|
1481
|
+
<strong>{{ diagnosticLevelLabel(diagnostic.level) }}</strong>
|
|
1482
|
+
<span>{{ diagnostic.message }}</span>
|
|
1483
|
+
<code *ngIf="diagnostic.path">{{ diagnostic.path }}</code>
|
|
1484
|
+
</div>
|
|
1485
|
+
</div>
|
|
1486
|
+
|
|
860
1487
|
<mat-tab-group class="editor-tabs">
|
|
861
|
-
<mat-tab label="Comportamento">
|
|
1488
|
+
<mat-tab [label]="t('editor.tabs.behavior', 'Comportamento')">
|
|
862
1489
|
<div class="editor-section">
|
|
863
1490
|
<div class="editor-row">
|
|
864
|
-
<mat-slide-toggle [(ngModel)]="behavior.closeable" (ngModelChange)="onAppearanceChange()">Fechavel</mat-slide-toggle>
|
|
865
|
-
<mat-slide-toggle [(ngModel)]="behavior.lazyLoad" (ngModelChange)="onAppearanceChange()">Carregar sob demanda</mat-slide-toggle>
|
|
866
|
-
<mat-slide-toggle [(ngModel)]="behavior.reorderable" (ngModelChange)="onAppearanceChange()">Reordenavel</mat-slide-toggle>
|
|
1491
|
+
<mat-slide-toggle [(ngModel)]="behavior.closeable" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.closeable', 'Fechavel') }}</mat-slide-toggle>
|
|
1492
|
+
<mat-slide-toggle [(ngModel)]="behavior.lazyLoad" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.lazyLoad', 'Carregar sob demanda') }}</mat-slide-toggle>
|
|
1493
|
+
<mat-slide-toggle [(ngModel)]="behavior.reorderable" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.reorderable', 'Reordenavel') }}</mat-slide-toggle>
|
|
867
1494
|
</div>
|
|
868
1495
|
</div>
|
|
869
1496
|
</mat-tab>
|
|
870
|
-
<mat-tab label="Grupo">
|
|
1497
|
+
<mat-tab [label]="t('editor.tabs.group', 'Grupo')" [disabled]="primaryMode !== 'group'">
|
|
871
1498
|
<div class="editor-section">
|
|
872
1499
|
<div class="editor-grid two">
|
|
873
|
-
<mat-form-field appearance="outline"><mat-label>Alinhamento das abas</mat-label>
|
|
1500
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.groupAlignTabs', 'Alinhamento das abas') }}</mat-label>
|
|
874
1501
|
<select matNativeControl [(ngModel)]="group.alignTabs" (ngModelChange)="onAppearanceChange()">
|
|
875
|
-
<option [ngValue]="undefined">Padrao</option>
|
|
876
|
-
<option value="start">Inicio</option>
|
|
877
|
-
<option value="center">Centro</option>
|
|
878
|
-
<option value="end">Fim</option>
|
|
1502
|
+
<option [ngValue]="undefined">{{ t('editor.options.default', 'Padrao') }}</option>
|
|
1503
|
+
<option value="start">{{ t('editor.options.start', 'Inicio') }}</option>
|
|
1504
|
+
<option value="center">{{ t('editor.options.center', 'Centro') }}</option>
|
|
1505
|
+
<option value="end">{{ t('editor.options.end', 'Fim') }}</option>
|
|
879
1506
|
</select>
|
|
880
1507
|
</mat-form-field>
|
|
881
|
-
<mat-form-field appearance="outline"><mat-label>Posicao do header</mat-label>
|
|
1508
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.groupHeaderPosition', 'Posicao do header') }}</mat-label>
|
|
882
1509
|
<select matNativeControl [(ngModel)]="group.headerPosition" (ngModelChange)="onAppearanceChange()">
|
|
883
|
-
<option [ngValue]="undefined">Acima (padrao)</option>
|
|
884
|
-
<option value="above">Acima</option>
|
|
885
|
-
<option value="below">Abaixo</option>
|
|
1510
|
+
<option [ngValue]="undefined">{{ t('editor.options.aboveDefault', 'Acima (padrao)') }}</option>
|
|
1511
|
+
<option value="above">{{ t('editor.options.above', 'Acima') }}</option>
|
|
1512
|
+
<option value="below">{{ t('editor.options.below', 'Abaixo') }}</option>
|
|
886
1513
|
</select>
|
|
887
1514
|
</mat-form-field>
|
|
888
|
-
<mat-form-field appearance="outline"><mat-label>Indice selecionado</mat-label>
|
|
1515
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.selectedIndex', 'Indice selecionado') }}</mat-label>
|
|
889
1516
|
<input matInput type="number" [(ngModel)]="group.selectedIndex" (ngModelChange)="onAppearanceChange()" />
|
|
890
1517
|
<button
|
|
891
1518
|
mat-icon-button
|
|
892
1519
|
matSuffix
|
|
893
1520
|
class="help-icon-button"
|
|
894
1521
|
type="button"
|
|
895
|
-
[matTooltip]="'selectedIndex'"
|
|
1522
|
+
[matTooltip]="t('editor.hints.selectedIndex', 'selectedIndex')"
|
|
896
1523
|
matTooltipPosition="above"
|
|
897
1524
|
>
|
|
898
1525
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
899
1526
|
</button>
|
|
900
1527
|
</mat-form-field>
|
|
901
|
-
<mat-form-field appearance="outline"><mat-label>Duracao da animacao</mat-label>
|
|
902
|
-
<input matInput [(ngModel)]="group.animationDuration" (ngModelChange)="onAppearanceChange()" placeholder="500ms" />
|
|
1528
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.animationDuration', 'Duracao da animacao') }}</mat-label>
|
|
1529
|
+
<input matInput [(ngModel)]="group.animationDuration" (ngModelChange)="onAppearanceChange()" [placeholder]="t('editor.fields.placeholder.animationDuration', '500ms')" />
|
|
903
1530
|
<button
|
|
904
1531
|
mat-icon-button
|
|
905
1532
|
matSuffix
|
|
906
1533
|
class="help-icon-button"
|
|
907
1534
|
type="button"
|
|
908
|
-
[matTooltip]="'animationDuration'"
|
|
1535
|
+
[matTooltip]="t('editor.hints.animationDuration', 'animationDuration')"
|
|
909
1536
|
matTooltipPosition="above"
|
|
910
1537
|
>
|
|
911
1538
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
912
1539
|
</button>
|
|
913
1540
|
</mat-form-field>
|
|
914
|
-
<mat-form-field appearance="outline"><mat-label>Cor (M2)</mat-label>
|
|
1541
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.color', 'Cor (M2)') }}</mat-label>
|
|
915
1542
|
<select matNativeControl [(ngModel)]="group.color" (ngModelChange)="onAppearanceChange()">
|
|
916
|
-
<option [ngValue]="undefined">(nenhuma)</option>
|
|
917
|
-
<option value="primary">Primary</option>
|
|
918
|
-
<option value="accent">Accent</option>
|
|
919
|
-
<option value="warn">Warn</option>
|
|
1543
|
+
<option [ngValue]="undefined">{{ t('editor.options.none', '(nenhuma)') }}</option>
|
|
1544
|
+
<option value="primary">{{ t('editor.options.primary', 'Primary') }}</option>
|
|
1545
|
+
<option value="accent">{{ t('editor.options.accent', 'Accent') }}</option>
|
|
1546
|
+
<option value="warn">{{ t('editor.options.warn', 'Warn') }}</option>
|
|
920
1547
|
</select>
|
|
921
1548
|
<button
|
|
922
1549
|
mat-icon-button
|
|
923
1550
|
matSuffix
|
|
924
1551
|
class="help-icon-button"
|
|
925
1552
|
type="button"
|
|
926
|
-
[matTooltip]="'Preferir tokens em Estilo.'"
|
|
1553
|
+
[matTooltip]="t('editor.hints.preferTokens', 'Preferir tokens em Estilo.')"
|
|
927
1554
|
matTooltipPosition="above"
|
|
928
1555
|
>
|
|
929
1556
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
930
1557
|
</button>
|
|
931
1558
|
</mat-form-field>
|
|
932
|
-
<mat-form-field appearance="outline"><mat-label>Cor de fundo (M2)</mat-label>
|
|
1559
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.backgroundColor', 'Cor de fundo (M2)') }}</mat-label>
|
|
933
1560
|
<select matNativeControl [(ngModel)]="group.backgroundColor" (ngModelChange)="onAppearanceChange()">
|
|
934
|
-
<option [ngValue]="undefined">(nenhuma)</option>
|
|
935
|
-
<option value="primary">Primary</option>
|
|
936
|
-
<option value="accent">Accent</option>
|
|
937
|
-
<option value="warn">Warn</option>
|
|
1561
|
+
<option [ngValue]="undefined">{{ t('editor.options.none', '(nenhuma)') }}</option>
|
|
1562
|
+
<option value="primary">{{ t('editor.options.primary', 'Primary') }}</option>
|
|
1563
|
+
<option value="accent">{{ t('editor.options.accent', 'Accent') }}</option>
|
|
1564
|
+
<option value="warn">{{ t('editor.options.warn', 'Warn') }}</option>
|
|
938
1565
|
</select>
|
|
939
1566
|
<button
|
|
940
1567
|
mat-icon-button
|
|
941
1568
|
matSuffix
|
|
942
1569
|
class="help-icon-button"
|
|
943
1570
|
type="button"
|
|
944
|
-
[matTooltip]="'Preferir tokens em Estilo.'"
|
|
1571
|
+
[matTooltip]="t('editor.hints.preferTokens', 'Preferir tokens em Estilo.')"
|
|
945
1572
|
matTooltipPosition="above"
|
|
946
1573
|
>
|
|
947
1574
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
948
1575
|
</button>
|
|
949
1576
|
</mat-form-field>
|
|
950
|
-
<mat-form-field appearance="outline"><mat-label>aria-label</mat-label>
|
|
1577
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.ariaLabel', 'aria-label') }}</mat-label>
|
|
951
1578
|
<input matInput [(ngModel)]="group.ariaLabel" (ngModelChange)="onAppearanceChange()" />
|
|
952
1579
|
</mat-form-field>
|
|
953
|
-
<mat-form-field appearance="outline"><mat-label>aria-labelledby</mat-label>
|
|
1580
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.ariaLabelledby', 'aria-labelledby') }}</mat-label>
|
|
954
1581
|
<input matInput [(ngModel)]="group.ariaLabelledby" (ngModelChange)="onAppearanceChange()" />
|
|
955
1582
|
</mat-form-field>
|
|
956
1583
|
</div>
|
|
957
1584
|
<div class="editor-row">
|
|
958
|
-
<mat-slide-toggle [(ngModel)]="group.dynamicHeight" (ngModelChange)="onAppearanceChange()">Altura dinamica</mat-slide-toggle>
|
|
959
|
-
<mat-slide-toggle [(ngModel)]="group.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">Indicador ajustado ao conteudo</mat-slide-toggle>
|
|
960
|
-
<mat-slide-toggle [(ngModel)]="group.disablePagination" (ngModelChange)="onAppearanceChange()">Sem paginacao</mat-slide-toggle>
|
|
961
|
-
<mat-slide-toggle [(ngModel)]="group.disableRipple" (ngModelChange)="onAppearanceChange()">Sem ripple</mat-slide-toggle>
|
|
962
|
-
<mat-slide-toggle [(ngModel)]="group.preserveContent" (ngModelChange)="onAppearanceChange()">Preservar conteudo</mat-slide-toggle>
|
|
963
|
-
<mat-slide-toggle [(ngModel)]="group.stretchTabs" (ngModelChange)="onAppearanceChange()">Esticar abas</mat-slide-toggle>
|
|
1585
|
+
<mat-slide-toggle [(ngModel)]="group.dynamicHeight" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.dynamicHeight', 'Altura dinamica') }}</mat-slide-toggle>
|
|
1586
|
+
<mat-slide-toggle [(ngModel)]="group.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.fitInkBarToContent', 'Indicador ajustado ao conteudo') }}</mat-slide-toggle>
|
|
1587
|
+
<mat-slide-toggle [(ngModel)]="group.disablePagination" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disablePagination', 'Sem paginacao') }}</mat-slide-toggle>
|
|
1588
|
+
<mat-slide-toggle [(ngModel)]="group.disableRipple" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disableRipple', 'Sem ripple') }}</mat-slide-toggle>
|
|
1589
|
+
<mat-slide-toggle [(ngModel)]="group.preserveContent" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.preserveContent', 'Preservar conteudo') }}</mat-slide-toggle>
|
|
1590
|
+
<mat-slide-toggle [(ngModel)]="group.stretchTabs" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.stretchTabs', 'Esticar abas') }}</mat-slide-toggle>
|
|
964
1591
|
</div>
|
|
965
1592
|
</div>
|
|
966
1593
|
</mat-tab>
|
|
967
1594
|
|
|
968
|
-
<mat-tab label="
|
|
1595
|
+
<mat-tab [label]="t('editor.tabs.nav', 'Navegacao')" [disabled]="primaryMode !== 'nav'">
|
|
969
1596
|
<div class="editor-section">
|
|
970
1597
|
<div class="editor-grid two">
|
|
971
|
-
<mat-form-field appearance="outline"><mat-label>Indice selecionado</mat-label>
|
|
1598
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.selectedIndex', 'Indice selecionado') }}</mat-label>
|
|
972
1599
|
<input matInput type="number" [(ngModel)]="nav.selectedIndex" (ngModelChange)="onAppearanceChange()" />
|
|
973
1600
|
<button
|
|
974
1601
|
mat-icon-button
|
|
975
1602
|
matSuffix
|
|
976
1603
|
class="help-icon-button"
|
|
977
1604
|
type="button"
|
|
978
|
-
[matTooltip]="'selectedIndex'"
|
|
1605
|
+
[matTooltip]="t('editor.hints.selectedIndex', 'selectedIndex')"
|
|
979
1606
|
matTooltipPosition="above"
|
|
980
1607
|
>
|
|
981
1608
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
982
1609
|
</button>
|
|
983
1610
|
</mat-form-field>
|
|
984
|
-
<mat-form-field appearance="outline"><mat-label>Duracao da animacao</mat-label>
|
|
985
|
-
<input matInput [(ngModel)]="nav.animationDuration" (ngModelChange)="onAppearanceChange()" placeholder="500ms" />
|
|
1611
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.animationDuration', 'Duracao da animacao') }}</mat-label>
|
|
1612
|
+
<input matInput [(ngModel)]="nav.animationDuration" (ngModelChange)="onAppearanceChange()" [placeholder]="t('editor.fields.placeholder.animationDuration', '500ms')" />
|
|
986
1613
|
<button
|
|
987
1614
|
mat-icon-button
|
|
988
1615
|
matSuffix
|
|
989
1616
|
class="help-icon-button"
|
|
990
1617
|
type="button"
|
|
991
|
-
[matTooltip]="'animationDuration'"
|
|
1618
|
+
[matTooltip]="t('editor.hints.animationDuration', 'animationDuration')"
|
|
992
1619
|
matTooltipPosition="above"
|
|
993
1620
|
>
|
|
994
1621
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
995
1622
|
</button>
|
|
996
1623
|
</mat-form-field>
|
|
997
|
-
<mat-form-field appearance="outline"><mat-label>aria-label</mat-label>
|
|
1624
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.ariaLabel', 'aria-label') }}</mat-label>
|
|
998
1625
|
<input matInput [(ngModel)]="nav.ariaLabel" (ngModelChange)="onAppearanceChange()" />
|
|
999
1626
|
</mat-form-field>
|
|
1000
|
-
<mat-form-field appearance="outline"><mat-label>aria-labelledby</mat-label>
|
|
1627
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.ariaLabelledby', 'aria-labelledby') }}</mat-label>
|
|
1001
1628
|
<input matInput [(ngModel)]="nav.ariaLabelledby" (ngModelChange)="onAppearanceChange()" />
|
|
1002
1629
|
</mat-form-field>
|
|
1003
|
-
<mat-form-field appearance="outline"><mat-label>Cor (M2)</mat-label>
|
|
1630
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.color', 'Cor (M2)') }}</mat-label>
|
|
1004
1631
|
<select matNativeControl [(ngModel)]="nav.color" (ngModelChange)="onAppearanceChange()">
|
|
1005
|
-
<option [ngValue]="undefined">(nenhuma)</option>
|
|
1006
|
-
<option value="primary">Primary</option>
|
|
1007
|
-
<option value="accent">Accent</option>
|
|
1008
|
-
<option value="warn">Warn</option>
|
|
1632
|
+
<option [ngValue]="undefined">{{ t('editor.options.none', '(nenhuma)') }}</option>
|
|
1633
|
+
<option value="primary">{{ t('editor.options.primary', 'Primary') }}</option>
|
|
1634
|
+
<option value="accent">{{ t('editor.options.accent', 'Accent') }}</option>
|
|
1635
|
+
<option value="warn">{{ t('editor.options.warn', 'Warn') }}</option>
|
|
1009
1636
|
</select>
|
|
1010
1637
|
<button
|
|
1011
1638
|
mat-icon-button
|
|
1012
1639
|
matSuffix
|
|
1013
1640
|
class="help-icon-button"
|
|
1014
1641
|
type="button"
|
|
1015
|
-
[matTooltip]="'Preferir tokens em Estilo.'"
|
|
1642
|
+
[matTooltip]="t('editor.hints.preferTokens', 'Preferir tokens em Estilo.')"
|
|
1016
1643
|
matTooltipPosition="above"
|
|
1017
1644
|
>
|
|
1018
1645
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1019
1646
|
</button>
|
|
1020
1647
|
</mat-form-field>
|
|
1021
|
-
<mat-form-field appearance="outline"><mat-label>Cor de fundo (M2)</mat-label>
|
|
1648
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.backgroundColor', 'Cor de fundo (M2)') }}</mat-label>
|
|
1022
1649
|
<select matNativeControl [(ngModel)]="nav.backgroundColor" (ngModelChange)="onAppearanceChange()">
|
|
1023
|
-
<option [ngValue]="undefined">(nenhuma)</option>
|
|
1024
|
-
<option value="primary">Primary</option>
|
|
1025
|
-
<option value="accent">Accent</option>
|
|
1026
|
-
<option value="warn">Warn</option>
|
|
1650
|
+
<option [ngValue]="undefined">{{ t('editor.options.none', '(nenhuma)') }}</option>
|
|
1651
|
+
<option value="primary">{{ t('editor.options.primary', 'Primary') }}</option>
|
|
1652
|
+
<option value="accent">{{ t('editor.options.accent', 'Accent') }}</option>
|
|
1653
|
+
<option value="warn">{{ t('editor.options.warn', 'Warn') }}</option>
|
|
1027
1654
|
</select>
|
|
1028
1655
|
<button
|
|
1029
1656
|
mat-icon-button
|
|
1030
1657
|
matSuffix
|
|
1031
1658
|
class="help-icon-button"
|
|
1032
1659
|
type="button"
|
|
1033
|
-
[matTooltip]="'Preferir tokens em Estilo.'"
|
|
1660
|
+
[matTooltip]="t('editor.hints.preferTokens', 'Preferir tokens em Estilo.')"
|
|
1034
1661
|
matTooltipPosition="above"
|
|
1035
1662
|
>
|
|
1036
1663
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
@@ -1038,26 +1665,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
1038
1665
|
</mat-form-field>
|
|
1039
1666
|
</div>
|
|
1040
1667
|
<div class="editor-row">
|
|
1041
|
-
<mat-slide-toggle [(ngModel)]="nav.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">Indicador ajustado ao conteudo</mat-slide-toggle>
|
|
1042
|
-
<mat-slide-toggle [(ngModel)]="nav.disablePagination" (ngModelChange)="onAppearanceChange()">Sem paginacao</mat-slide-toggle>
|
|
1043
|
-
<mat-slide-toggle [(ngModel)]="nav.disableRipple" (ngModelChange)="onAppearanceChange()">Sem ripple</mat-slide-toggle>
|
|
1044
|
-
<mat-slide-toggle [(ngModel)]="nav.stretchTabs" (ngModelChange)="onAppearanceChange()">Esticar abas</mat-slide-toggle>
|
|
1668
|
+
<mat-slide-toggle [(ngModel)]="nav.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.fitInkBarToContent', 'Indicador ajustado ao conteudo') }}</mat-slide-toggle>
|
|
1669
|
+
<mat-slide-toggle [(ngModel)]="nav.disablePagination" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disablePagination', 'Sem paginacao') }}</mat-slide-toggle>
|
|
1670
|
+
<mat-slide-toggle [(ngModel)]="nav.disableRipple" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disableRipple', 'Sem ripple') }}</mat-slide-toggle>
|
|
1671
|
+
<mat-slide-toggle [(ngModel)]="nav.stretchTabs" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.stretchTabs', 'Esticar abas') }}</mat-slide-toggle>
|
|
1045
1672
|
</div>
|
|
1046
1673
|
</div>
|
|
1047
1674
|
</mat-tab>
|
|
1048
|
-
<mat-tab label="JSON">
|
|
1675
|
+
<mat-tab [label]="t('editor.tabs.json', 'JSON')">
|
|
1049
1676
|
<div class="editor-section">
|
|
1050
1677
|
<div class="editor-toolbar">
|
|
1051
|
-
<button mat-button (click)="formatJson()" [disabled]="!isValid">
|
|
1052
|
-
<mat-icon [praxisIcon]="'format_align_left'"></mat-icon>Formatar
|
|
1678
|
+
<button mat-button (click)="formatJson()" [disabled]="!isValid">
|
|
1679
|
+
<mat-icon [praxisIcon]="'format_align_left'"></mat-icon>{{ t('editor.actions.format', 'Formatar') }}
|
|
1053
1680
|
</button>
|
|
1054
|
-
<button mat-button (click)="reset()">
|
|
1055
|
-
<mat-icon [praxisIcon]="'restart_alt'"></mat-icon>Resetar
|
|
1681
|
+
<button mat-button (click)="reset()">
|
|
1682
|
+
<mat-icon [praxisIcon]="'restart_alt'"></mat-icon>{{ t('editor.actions.reset', 'Resetar') }}
|
|
1056
1683
|
</button>
|
|
1057
1684
|
</div>
|
|
1058
1685
|
|
|
1059
1686
|
<mat-form-field appearance="outline" class="json-textarea-field full">
|
|
1060
|
-
<mat-label>Configuracao JSON</mat-label>
|
|
1687
|
+
<mat-label>{{ t('editor.fields.jsonConfig', 'Configuracao JSON') }}</mat-label>
|
|
1061
1688
|
<textarea
|
|
1062
1689
|
matInput
|
|
1063
1690
|
[(ngModel)]="jsonText"
|
|
@@ -1066,84 +1693,84 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
1066
1693
|
spellcheck="false"
|
|
1067
1694
|
class="editor-json"
|
|
1068
1695
|
></textarea>
|
|
1069
|
-
<mat-hint *ngIf="isValid">JSON valido</mat-hint>
|
|
1070
|
-
<mat-error *ngIf="!isValid && jsonText">JSON invalido: {{ errorMsg }}</mat-error>
|
|
1696
|
+
<mat-hint *ngIf="isValid">{{ t('editor.json.valid', 'JSON valido') }}</mat-hint>
|
|
1697
|
+
<mat-error *ngIf="!isValid && jsonText">{{ t('editor.json.invalidPrefix', 'JSON invalido:') }} {{ errorMsg }}</mat-error>
|
|
1071
1698
|
</mat-form-field>
|
|
1072
1699
|
</div>
|
|
1073
1700
|
</mat-tab>
|
|
1074
1701
|
|
|
1075
|
-
<mat-tab label="Estilo">
|
|
1702
|
+
<mat-tab [label]="t('editor.tabs.style', 'Estilo')">
|
|
1076
1703
|
<div class="editor-section editor-section-lg">
|
|
1077
1704
|
<div class="editor-row">
|
|
1078
|
-
<span class="editor-muted">Presets
|
|
1705
|
+
<span class="editor-muted">{{ t('editor.presets.title', 'Presets:') }}</span>
|
|
1079
1706
|
<button mat-button color="primary" (click)="applyPreset('primary')">
|
|
1080
1707
|
<mat-icon [praxisIcon]="'palette'"></mat-icon>
|
|
1081
|
-
|
|
1708
|
+
{{ t('editor.presets.primary', 'Primario') }}
|
|
1082
1709
|
</button>
|
|
1083
1710
|
<button mat-button (click)="applyPreset('neutral')">
|
|
1084
1711
|
<mat-icon [praxisIcon]="'contrast'"></mat-icon>
|
|
1085
|
-
Neutro
|
|
1712
|
+
{{ t('editor.presets.neutral', 'Neutro') }}
|
|
1086
1713
|
</button>
|
|
1087
1714
|
<button mat-button (click)="applyPreset('high-contrast')">
|
|
1088
1715
|
<mat-icon [praxisIcon]="'visibility'"></mat-icon>
|
|
1089
|
-
Alto contraste
|
|
1716
|
+
{{ t('editor.presets.highContrast', 'Alto contraste') }}
|
|
1090
1717
|
</button>
|
|
1091
1718
|
<button mat-button (click)="clearTokens()">
|
|
1092
1719
|
<mat-icon [praxisIcon]="'backspace'"></mat-icon>
|
|
1093
|
-
Limpar tokens
|
|
1720
|
+
{{ t('editor.actions.clearTokens', 'Limpar tokens') }}
|
|
1094
1721
|
</button>
|
|
1095
1722
|
</div>
|
|
1096
1723
|
|
|
1097
1724
|
<div class="editor-grid two tight">
|
|
1098
1725
|
<mat-form-field appearance="outline">
|
|
1099
|
-
<mat-label>Classe de tema (opcional)</mat-label>
|
|
1100
|
-
<input matInput [(ngModel)]="appearance.themeClass" (ngModelChange)="onAppearanceChange()" placeholder="ex.: tabs-accented" />
|
|
1726
|
+
<mat-label>{{ t('editor.fields.themeClass', 'Classe de tema (opcional)') }}</mat-label>
|
|
1727
|
+
<input matInput [(ngModel)]="appearance.themeClass" (ngModelChange)="onAppearanceChange()" [placeholder]="t('editor.fields.placeholder.themeClass', 'ex.: tabs-accented')" />
|
|
1101
1728
|
</mat-form-field>
|
|
1102
1729
|
|
|
1103
1730
|
<mat-form-field appearance="outline">
|
|
1104
|
-
<mat-label>Densidade</mat-label>
|
|
1731
|
+
<mat-label>{{ t('editor.fields.density', 'Densidade') }}</mat-label>
|
|
1105
1732
|
<select matNativeControl [(ngModel)]="appearance.density" (ngModelChange)="onAppearanceChange()">
|
|
1106
|
-
<option [ngValue]="undefined">Padrao</option>
|
|
1107
|
-
<option value="compact">Compacta</option>
|
|
1108
|
-
<option value="comfortable">Confortavel</option>
|
|
1109
|
-
<option value="spacious">Espacosa</option>
|
|
1733
|
+
<option [ngValue]="undefined">{{ t('editor.density.default', 'Padrao') }}</option>
|
|
1734
|
+
<option value="compact">{{ t('editor.density.compact', 'Compacta') }}</option>
|
|
1735
|
+
<option value="comfortable">{{ t('editor.density.comfortable', 'Confortavel') }}</option>
|
|
1736
|
+
<option value="spacious">{{ t('editor.density.spacious', 'Espacosa') }}</option>
|
|
1110
1737
|
</select>
|
|
1111
1738
|
</mat-form-field>
|
|
1112
1739
|
</div>
|
|
1113
1740
|
|
|
1114
1741
|
<div>
|
|
1115
1742
|
<div class="editor-title-row">
|
|
1116
|
-
<h3 class="editor-title">Tokens (Material 3)</h3>
|
|
1743
|
+
<h3 class="editor-title">{{ t('editor.sections.tokens', 'Tokens (Material 3)') }}</h3>
|
|
1117
1744
|
<button
|
|
1118
1745
|
mat-icon-button
|
|
1119
1746
|
class="help-icon-button"
|
|
1120
1747
|
type="button"
|
|
1121
|
-
[matTooltip]="'Valores aceitam CSS vars
|
|
1748
|
+
[matTooltip]="t('editor.hints.tokenValueHelp', 'Valores aceitam CSS vars ou cores hex/rgb.')"
|
|
1122
1749
|
matTooltipPosition="above"
|
|
1123
1750
|
>
|
|
1124
1751
|
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1125
1752
|
</button>
|
|
1126
1753
|
</div>
|
|
1127
1754
|
<div class="editor-grid two">
|
|
1128
|
-
<ng-container *ngFor="let
|
|
1755
|
+
<ng-container *ngFor="let token of tokenList">
|
|
1129
1756
|
<mat-form-field appearance="outline">
|
|
1130
|
-
<mat-label>{{ t.
|
|
1131
|
-
<input matInput placeholder="var(--md-sys-color-primary) / #RRGGBB" [ngModel]="appearance.tokens?.[
|
|
1757
|
+
<mat-label>{{ t(token.labelKey, token.fallback) }}</mat-label>
|
|
1758
|
+
<input matInput [placeholder]="t('editor.placeholders.tokenValue', 'var(--md-sys-color-primary) / #RRGGBB')" [ngModel]="appearance.tokens?.[token.key]" (ngModelChange)="onTokenChange(token.key, $event)" />
|
|
1132
1759
|
</mat-form-field>
|
|
1133
1760
|
</ng-container>
|
|
1134
1761
|
</div>
|
|
1135
1762
|
</div>
|
|
1136
1763
|
|
|
1137
1764
|
<div>
|
|
1138
|
-
<h3 class="editor-title">CSS personalizado</h3>
|
|
1765
|
+
<h3 class="editor-title">{{ t('editor.sections.customCss', 'CSS personalizado') }}</h3>
|
|
1139
1766
|
<mat-form-field appearance="outline" class="json-textarea-field full">
|
|
1140
|
-
<mat-label>CSS a ser injetado no componente</mat-label>
|
|
1141
|
-
<textarea matInput rows="10" [(ngModel)]="appearance.customCss" (ngModelChange)="onAppearanceChange()" placeholder=".praxis-tabs-root .mdc-tab__text-label { font-weight: 600; }"></textarea>
|
|
1767
|
+
<mat-label>{{ t('editor.fields.customCss', 'CSS a ser injetado no componente') }}</mat-label>
|
|
1768
|
+
<textarea matInput rows="10" [(ngModel)]="appearance.customCss" (ngModelChange)="onAppearanceChange()" [placeholder]="t('editor.placeholders.customCssExample', '.praxis-tabs-root .mdc-tab__text-label { font-weight: 600; }')"></textarea>
|
|
1142
1769
|
</mat-form-field>
|
|
1143
1770
|
</div>
|
|
1144
1771
|
|
|
1145
1772
|
<div>
|
|
1146
|
-
<h3 class="editor-title">Snippet SCSS (para uso em styles.scss)</h3>
|
|
1773
|
+
<h3 class="editor-title">{{ t('editor.sections.scssSnippet', 'Snippet SCSS (para uso em styles.scss)') }}</h3>
|
|
1147
1774
|
<pre class="editor-code">
|
|
1148
1775
|
@use '@angular/material' as mat;
|
|
1149
1776
|
{{ scssSnippet() }}
|
|
@@ -1152,76 +1779,76 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
1152
1779
|
</div>
|
|
1153
1780
|
</mat-tab>
|
|
1154
1781
|
|
|
1155
|
-
<mat-tab label="Abas">
|
|
1782
|
+
<mat-tab [label]="t('editor.tabs.items', 'Abas')" [disabled]="primaryMode !== 'group'">
|
|
1156
1783
|
<div class="editor-section">
|
|
1157
|
-
<button mat-stroked-button color="primary" (click)="addTab()"><mat-icon [praxisIcon]="'add'"></mat-icon>Adicionar aba</button>
|
|
1784
|
+
<button mat-stroked-button color="primary" (click)="addTab()"><mat-icon [praxisIcon]="'add'"></mat-icon>{{ t('editor.actions.addTab', 'Adicionar aba') }}</button>
|
|
1158
1785
|
<div *ngIf="editedConfig.tabs?.length; else noTabs" class="editor-grid">
|
|
1159
|
-
<div *ngFor="let
|
|
1786
|
+
<div *ngFor="let tab of editedConfig.tabs; let i = index" class="editor-card">
|
|
1160
1787
|
<div class="editor-card-header">
|
|
1161
|
-
<strong class="editor-card-title">Aba #{{ i+1 }}</strong>
|
|
1788
|
+
<strong class="editor-card-title">{{ t('editor.cards.tab', 'Aba') }} #{{ i+1 }}</strong>
|
|
1162
1789
|
<button mat-icon-button (click)="moveTab(i, -1)" [disabled]="i===0"><mat-icon [praxisIcon]="'arrow_upward'"></mat-icon></button>
|
|
1163
1790
|
<button mat-icon-button (click)="moveTab(i, 1)" [disabled]="i===editedConfig.tabs!.length-1"><mat-icon [praxisIcon]="'arrow_downward'"></mat-icon></button>
|
|
1164
1791
|
<button mat-icon-button color="warn" (click)="removeTab(i)"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
1165
1792
|
</div>
|
|
1166
1793
|
<div class="editor-grid two tight">
|
|
1167
|
-
<mat-form-field appearance="outline"><mat-label>ID</mat-label>
|
|
1168
|
-
<input matInput [(ngModel)]="
|
|
1794
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.id', 'ID') }}</mat-label>
|
|
1795
|
+
<input matInput [(ngModel)]="tab.id" (ngModelChange)="onAppearanceChange()" />
|
|
1169
1796
|
</mat-form-field>
|
|
1170
|
-
<mat-form-field appearance="outline"><mat-label>Rotulo</mat-label>
|
|
1171
|
-
<input matInput [(ngModel)]="
|
|
1797
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.label', 'Rotulo') }}</mat-label>
|
|
1798
|
+
<input matInput [(ngModel)]="tab.textLabel" (ngModelChange)="onAppearanceChange()" />
|
|
1172
1799
|
</mat-form-field>
|
|
1173
|
-
<mat-form-field appearance="outline"><mat-label>Classe do rotulo</mat-label>
|
|
1174
|
-
<input matInput [(ngModel)]="
|
|
1800
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.labelClass', 'Classe do rotulo') }}</mat-label>
|
|
1801
|
+
<input matInput [(ngModel)]="tab.labelClass" (ngModelChange)="onAppearanceChange()" />
|
|
1175
1802
|
</mat-form-field>
|
|
1176
|
-
<mat-form-field appearance="outline"><mat-label>Classe do conteudo</mat-label>
|
|
1177
|
-
<input matInput [(ngModel)]="
|
|
1803
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.bodyClass', 'Classe do conteudo') }}</mat-label>
|
|
1804
|
+
<input matInput [(ngModel)]="tab.bodyClass" (ngModelChange)="onAppearanceChange()" />
|
|
1178
1805
|
</mat-form-field>
|
|
1179
|
-
|
|
1180
|
-
<input matInput [(ngModel)]="
|
|
1806
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.ariaLabel', 'aria-label') }}</mat-label>
|
|
1807
|
+
<input matInput [(ngModel)]="tab.ariaLabel" (ngModelChange)="onAppearanceChange()" />
|
|
1181
1808
|
</mat-form-field>
|
|
1182
|
-
|
|
1183
|
-
<input matInput [(ngModel)]="
|
|
1809
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.ariaLabelledby', 'aria-labelledby') }}</mat-label>
|
|
1810
|
+
<input matInput [(ngModel)]="tab.ariaLabelledby" (ngModelChange)="onAppearanceChange()" />
|
|
1184
1811
|
</mat-form-field>
|
|
1185
1812
|
</div>
|
|
1186
|
-
<mat-slide-toggle [(ngModel)]="
|
|
1813
|
+
<mat-slide-toggle [(ngModel)]="tab.disabled" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disabled', 'Desativada') }}</mat-slide-toggle>
|
|
1187
1814
|
|
|
1188
1815
|
<!-- Widgets (componentes dinâmicos) -->
|
|
1189
1816
|
<div class="editor-divider editor-grid">
|
|
1190
1817
|
<div class="editor-row">
|
|
1191
1818
|
<mat-form-field appearance="outline" class="editor-field-min">
|
|
1192
|
-
<mat-label>Adicionar componente</mat-label>
|
|
1819
|
+
<mat-label>{{ t('editor.fields.addComponent', 'Adicionar componente') }}</mat-label>
|
|
1193
1820
|
<select matNativeControl [(ngModel)]="selectedTabWidgetId[i]">
|
|
1194
|
-
<option [ngValue]="''">(selecione)</option>
|
|
1821
|
+
<option [ngValue]="''">{{ t('editor.fields.selectPlaceholder', '(selecione)') }}</option>
|
|
1195
1822
|
<option *ngFor="let c of componentOptions" [ngValue]="c.id">{{ c.friendlyName || c.id }}</option>
|
|
1196
1823
|
</select>
|
|
1197
1824
|
</mat-form-field>
|
|
1198
|
-
<button mat-stroked-button (click)="addWidgetToTab(i)"><mat-icon [praxisIcon]="'add'"></mat-icon>Adicionar</button>
|
|
1825
|
+
<button mat-stroked-button (click)="addWidgetToTab(i)"><mat-icon [praxisIcon]="'add'"></mat-icon>{{ t('editor.actions.add', 'Adicionar') }}</button>
|
|
1199
1826
|
<span class="editor-spacer"></span>
|
|
1200
1827
|
<mat-form-field appearance="outline" class="editor-field-240">
|
|
1201
|
-
<mat-label>Recurso (resourcePath)</mat-label>
|
|
1202
|
-
<input matInput [(ngModel)]="quickResourcePathTab[i]" placeholder="ex.: usuarios" />
|
|
1828
|
+
<mat-label>{{ t('editor.fields.resourcePath', 'Recurso (resourcePath)') }}</mat-label>
|
|
1829
|
+
<input matInput [(ngModel)]="quickResourcePathTab[i]" [placeholder]="t('editor.fields.placeholder.resourcePath', 'ex.: usuarios')" />
|
|
1203
1830
|
</mat-form-field>
|
|
1204
|
-
<button mat-button (click)="addPresetToTab(i, 'form')"><mat-icon [praxisIcon]="'description'"></mat-icon>Form</button>
|
|
1205
|
-
<button mat-button (click)="addPresetToTab(i, 'table')"><mat-icon [praxisIcon]="'grid_on'"></mat-icon>Tabela</button>
|
|
1206
|
-
<button mat-button (click)="addPresetToTab(i, 'crud')"><mat-icon [praxisIcon]="'dynamic_form'"></mat-icon>CRUD</button>
|
|
1831
|
+
<button mat-button (click)="addPresetToTab(i, 'form')"><mat-icon [praxisIcon]="'description'"></mat-icon>{{ t('editor.templates.form', 'Form') }}</button>
|
|
1832
|
+
<button mat-button (click)="addPresetToTab(i, 'table')"><mat-icon [praxisIcon]="'grid_on'"></mat-icon>{{ t('editor.templates.table', 'Tabela') }}</button>
|
|
1833
|
+
<button mat-button (click)="addPresetToTab(i, 'crud')"><mat-icon [praxisIcon]="'dynamic_form'"></mat-icon>{{ t('editor.templates.crud', 'CRUD') }}</button>
|
|
1207
1834
|
</div>
|
|
1208
1835
|
|
|
1209
|
-
|
|
1210
|
-
|
|
1836
|
+
<div *ngIf="tab.widgets?.length" class="editor-grid" cdkDropList [cdkDropListData]="tab.widgets || []" (cdkDropListDropped)="onTabWidgetDrop(i, $event)">
|
|
1837
|
+
<div *ngFor="let w of tab.widgets; let wi = index" cdkDrag class="editor-card dashed">
|
|
1211
1838
|
<div class="editor-card-header">
|
|
1212
|
-
<button mat-icon-button cdkDragHandle matTooltip="Arrastar para reordenar" aria-label="Arrastar para reordenar">
|
|
1839
|
+
<button mat-icon-button cdkDragHandle [matTooltip]="t('editor.actions.dragToReorder', 'Arrastar para reordenar')" [attr.aria-label]="t('editor.actions.dragToReorder', 'Arrastar para reordenar')">
|
|
1213
1840
|
<mat-icon [praxisIcon]="'drag_indicator'"></mat-icon>
|
|
1214
1841
|
</button>
|
|
1215
1842
|
<strong class="editor-card-title">{{ getCompName(w.id) }}</strong>
|
|
1216
|
-
<button mat-icon-button color="warn" (click)="removeWidgetFromTab(i, wi)" matTooltip="Remover componente" aria-label="Remover componente"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
1843
|
+
<button mat-icon-button color="warn" (click)="removeWidgetFromTab(i, wi)" [matTooltip]="t('editor.actions.removeComponent', 'Remover componente')" [attr.aria-label]="t('editor.actions.removeComponent', 'Remover componente')"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
1217
1844
|
</div>
|
|
1218
1845
|
<div class="editor-grid two tight">
|
|
1219
1846
|
<mat-form-field appearance="outline">
|
|
1220
|
-
<mat-label>Inputs (JSON)</mat-label>
|
|
1847
|
+
<mat-label>{{ t('editor.fields.inputsJson', 'Inputs (JSON)') }}</mat-label>
|
|
1221
1848
|
<textarea matInput rows="4" [ngModel]="stringify(w.inputs)" (ngModelChange)="updateWidgetInputsTab(i, wi, $event)"></textarea>
|
|
1222
1849
|
</mat-form-field>
|
|
1223
1850
|
<mat-form-field appearance="outline">
|
|
1224
|
-
<mat-label>Outputs (JSON)</mat-label>
|
|
1851
|
+
<mat-label>{{ t('editor.fields.outputsJson', 'Outputs (JSON)') }}</mat-label>
|
|
1225
1852
|
<textarea matInput rows="4" [ngModel]="stringify(w.outputs)" (ngModelChange)="updateWidgetOutputsTab(i, wi, $event)"></textarea>
|
|
1226
1853
|
</mat-form-field>
|
|
1227
1854
|
</div>
|
|
@@ -1230,82 +1857,81 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
1230
1857
|
</div>
|
|
1231
1858
|
</div>
|
|
1232
1859
|
</div>
|
|
1233
|
-
<ng-template #noTabs><em class="editor-muted">Nenhuma aba definida
|
|
1860
|
+
<ng-template #noTabs><em class="editor-muted">{{ t('editor.empty.noTabs', 'Nenhuma aba definida.') }}</em></ng-template>
|
|
1234
1861
|
</div>
|
|
1235
1862
|
</mat-tab>
|
|
1236
1863
|
|
|
1237
|
-
<mat-tab label="Acessibilidade">
|
|
1864
|
+
<mat-tab [label]="t('editor.tabs.accessibility', 'Acessibilidade')">
|
|
1238
1865
|
<div class="editor-section">
|
|
1239
1866
|
<div class="editor-row">
|
|
1240
|
-
<mat-slide-toggle [(ngModel)]="accessibility.highContrast" (ngModelChange)="onAppearanceChange()">Alto contraste</mat-slide-toggle>
|
|
1241
|
-
<mat-slide-toggle [(ngModel)]="accessibility.reduceMotion" (ngModelChange)="onAppearanceChange()">Reduzir movimento</mat-slide-toggle>
|
|
1867
|
+
<mat-slide-toggle [(ngModel)]="accessibility.highContrast" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.highContrast', 'Alto contraste') }}</mat-slide-toggle>
|
|
1868
|
+
<mat-slide-toggle [(ngModel)]="accessibility.reduceMotion" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.reduceMotion', 'Reduzir movimento') }}</mat-slide-toggle>
|
|
1242
1869
|
</div>
|
|
1243
1870
|
</div>
|
|
1244
1871
|
</mat-tab>
|
|
1245
1872
|
|
|
1246
|
-
<mat-tab label="Links">
|
|
1873
|
+
<mat-tab [label]="t('editor.tabs.links', 'Links')" [disabled]="primaryMode !== 'nav'">
|
|
1247
1874
|
<div class="editor-section">
|
|
1248
|
-
<button mat-stroked-button color="primary" (click)="addLink()"><mat-icon [praxisIcon]="'add_link'"></mat-icon>Adicionar link</button>
|
|
1875
|
+
<button mat-stroked-button color="primary" (click)="addLink()"><mat-icon [praxisIcon]="'add_link'"></mat-icon>{{ t('editor.actions.addLink', 'Adicionar link') }}</button>
|
|
1249
1876
|
<div *ngIf="nav.links?.length; else noLinks" class="editor-grid">
|
|
1250
1877
|
<div *ngFor="let l of nav.links; let i = index" class="editor-card">
|
|
1251
1878
|
<div class="editor-card-header">
|
|
1252
|
-
<strong class="editor-card-title">Link #{{ i+1 }}</strong>
|
|
1879
|
+
<strong class="editor-card-title">{{ t('editor.cards.link', 'Link') }} #{{ i+1 }}</strong>
|
|
1253
1880
|
<button mat-icon-button (click)="moveLink(i, -1)" [disabled]="i===0"><mat-icon [praxisIcon]="'arrow_upward'"></mat-icon></button>
|
|
1254
1881
|
<button mat-icon-button (click)="moveLink(i, 1)" [disabled]="i===nav.links!.length-1"><mat-icon [praxisIcon]="'arrow_downward'"></mat-icon></button>
|
|
1255
1882
|
<button mat-icon-button color="warn" (click)="removeLink(i)"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
1256
1883
|
</div>
|
|
1257
1884
|
<div class="editor-grid two tight">
|
|
1258
|
-
<mat-form-field appearance="outline"><mat-label>ID</mat-label>
|
|
1885
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.id', 'ID') }}</mat-label>
|
|
1259
1886
|
<input matInput [(ngModel)]="l.id" (ngModelChange)="onAppearanceChange()" />
|
|
1260
1887
|
</mat-form-field>
|
|
1261
|
-
<mat-form-field appearance="outline"><mat-label>Rotulo</mat-label>
|
|
1888
|
+
<mat-form-field appearance="outline"><mat-label>{{ t('editor.fields.label', 'Rotulo') }}</mat-label>
|
|
1262
1889
|
<input matInput [(ngModel)]="l.label" (ngModelChange)="onAppearanceChange()" />
|
|
1263
1890
|
</mat-form-field>
|
|
1264
1891
|
</div>
|
|
1265
1892
|
<div class="editor-row">
|
|
1266
|
-
<mat-slide-toggle [(ngModel)]="l.
|
|
1267
|
-
<mat-slide-toggle [(ngModel)]="l.
|
|
1268
|
-
<mat-slide-toggle [(ngModel)]="l.
|
|
1269
|
-
<mat-slide-toggle [(ngModel)]="l.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">Indicador ajustado ao conteudo</mat-slide-toggle>
|
|
1893
|
+
<mat-slide-toggle [(ngModel)]="l.disabled" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.linkDisabled', 'Desativado') }}</mat-slide-toggle>
|
|
1894
|
+
<mat-slide-toggle [(ngModel)]="l.disableRipple" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.disableRipple', 'Sem ripple') }}</mat-slide-toggle>
|
|
1895
|
+
<mat-slide-toggle [(ngModel)]="l.fitInkBarToContent" (ngModelChange)="onAppearanceChange()">{{ t('editor.toggles.fitInkBarToContent', 'Indicador ajustado ao conteudo') }}</mat-slide-toggle>
|
|
1270
1896
|
</div>
|
|
1271
1897
|
|
|
1272
1898
|
<!-- Widgets para Links -->
|
|
1273
1899
|
<div class="editor-divider editor-grid">
|
|
1274
1900
|
<div class="editor-row">
|
|
1275
1901
|
<mat-form-field appearance="outline" class="editor-field-min">
|
|
1276
|
-
<mat-label>Adicionar componente</mat-label>
|
|
1902
|
+
<mat-label>{{ t('editor.fields.addComponent', 'Adicionar componente') }}</mat-label>
|
|
1277
1903
|
<select matNativeControl [(ngModel)]="selectedLinkWidgetId[i]">
|
|
1278
|
-
<option [ngValue]="''">(selecione)</option>
|
|
1904
|
+
<option [ngValue]="''">{{ t('editor.fields.selectPlaceholder', '(selecione)') }}</option>
|
|
1279
1905
|
<option *ngFor="let c of componentOptions" [ngValue]="c.id">{{ c.friendlyName || c.id }}</option>
|
|
1280
1906
|
</select>
|
|
1281
1907
|
</mat-form-field>
|
|
1282
|
-
<button mat-stroked-button (click)="addWidgetToLink(i)"><mat-icon [praxisIcon]="'add'"></mat-icon>Adicionar</button>
|
|
1908
|
+
<button mat-stroked-button (click)="addWidgetToLink(i)"><mat-icon [praxisIcon]="'add'"></mat-icon>{{ t('editor.actions.add', 'Adicionar') }}</button>
|
|
1283
1909
|
<span class="editor-spacer"></span>
|
|
1284
1910
|
<mat-form-field appearance="outline" class="editor-field-240">
|
|
1285
|
-
<mat-label>Recurso (resourcePath)</mat-label>
|
|
1286
|
-
<input matInput [(ngModel)]="quickResourcePathLink[i]" placeholder="ex.: usuarios" />
|
|
1911
|
+
<mat-label>{{ t('editor.fields.resourcePath', 'Recurso (resourcePath)') }}</mat-label>
|
|
1912
|
+
<input matInput [(ngModel)]="quickResourcePathLink[i]" [placeholder]="t('editor.fields.placeholder.resourcePath', 'ex.: usuarios')" />
|
|
1287
1913
|
</mat-form-field>
|
|
1288
|
-
<button mat-button (click)="addPresetToLink(i, 'form')"><mat-icon [praxisIcon]="'description'"></mat-icon>Form</button>
|
|
1289
|
-
<button mat-button (click)="addPresetToLink(i, 'table')"><mat-icon [praxisIcon]="'grid_on'"></mat-icon>Tabela</button>
|
|
1290
|
-
<button mat-button (click)="addPresetToLink(i, 'crud')"><mat-icon [praxisIcon]="'dynamic_form'"></mat-icon>CRUD</button>
|
|
1914
|
+
<button mat-button (click)="addPresetToLink(i, 'form')"><mat-icon [praxisIcon]="'description'"></mat-icon>{{ t('editor.templates.form', 'Form') }}</button>
|
|
1915
|
+
<button mat-button (click)="addPresetToLink(i, 'table')"><mat-icon [praxisIcon]="'grid_on'"></mat-icon>{{ t('editor.templates.table', 'Tabela') }}</button>
|
|
1916
|
+
<button mat-button (click)="addPresetToLink(i, 'crud')"><mat-icon [praxisIcon]="'dynamic_form'"></mat-icon>{{ t('editor.templates.crud', 'CRUD') }}</button>
|
|
1291
1917
|
</div>
|
|
1292
1918
|
|
|
1293
1919
|
<div *ngIf="l.widgets?.length" class="editor-grid" cdkDropList [cdkDropListData]="l.widgets || []" (cdkDropListDropped)="onLinkWidgetDrop(i, $event)">
|
|
1294
1920
|
<div *ngFor="let w of l.widgets; let wi = index" cdkDrag class="editor-card dashed">
|
|
1295
1921
|
<div class="editor-card-header">
|
|
1296
|
-
<button mat-icon-button cdkDragHandle matTooltip="Arrastar para reordenar" aria-label="Arrastar para reordenar">
|
|
1922
|
+
<button mat-icon-button cdkDragHandle [matTooltip]="t('editor.actions.dragToReorder', 'Arrastar para reordenar')" [attr.aria-label]="t('editor.actions.dragToReorder', 'Arrastar para reordenar')">
|
|
1297
1923
|
<mat-icon [praxisIcon]="'drag_indicator'"></mat-icon>
|
|
1298
1924
|
</button>
|
|
1299
1925
|
<strong class="editor-card-title">{{ getCompName(w.id) }}</strong>
|
|
1300
|
-
<button mat-icon-button color="warn" (click)="removeWidgetFromLink(i, wi)" matTooltip="Remover componente" aria-label="Remover componente"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
1926
|
+
<button mat-icon-button color="warn" (click)="removeWidgetFromLink(i, wi)" [matTooltip]="t('editor.actions.removeComponent', 'Remover componente')" [attr.aria-label]="t('editor.actions.removeComponent', 'Remover componente')"><mat-icon [praxisIcon]="'delete'"></mat-icon></button>
|
|
1301
1927
|
</div>
|
|
1302
1928
|
<div class="editor-grid two tight">
|
|
1303
1929
|
<mat-form-field appearance="outline">
|
|
1304
|
-
<mat-label>Inputs (JSON)</mat-label>
|
|
1930
|
+
<mat-label>{{ t('editor.fields.inputsJson', 'Inputs (JSON)') }}</mat-label>
|
|
1305
1931
|
<textarea matInput rows="4" [ngModel]="stringify(w.inputs)" (ngModelChange)="updateWidgetInputsLink(i, wi, $event)"></textarea>
|
|
1306
1932
|
</mat-form-field>
|
|
1307
1933
|
<mat-form-field appearance="outline">
|
|
1308
|
-
<mat-label>Outputs (JSON)</mat-label>
|
|
1934
|
+
<mat-label>{{ t('editor.fields.outputsJson', 'Outputs (JSON)') }}</mat-label>
|
|
1309
1935
|
<textarea matInput rows="4" [ngModel]="stringify(w.outputs)" (ngModelChange)="updateWidgetOutputsLink(i, wi, $event)"></textarea>
|
|
1310
1936
|
</mat-form-field>
|
|
1311
1937
|
</div>
|
|
@@ -1314,26 +1940,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
1314
1940
|
</div>
|
|
1315
1941
|
</div>
|
|
1316
1942
|
</div>
|
|
1317
|
-
<ng-template #noLinks><em class="editor-muted">Nenhum link definido
|
|
1943
|
+
<ng-template #noLinks><em class="editor-muted">{{ t('editor.empty.noLinks', 'Nenhum link definido.') }}</em></ng-template>
|
|
1318
1944
|
</div>
|
|
1319
1945
|
</mat-tab>
|
|
1320
1946
|
</mat-tab-group>
|
|
1321
|
-
|
|
1947
|
+
</div>
|
|
1948
|
+
`, styles: [":host{display:block;color:var(--md-sys-color-on-surface)}.editor-shell{display:grid;gap:12px}.editor-topbar{display:flex;align-items:start;justify-content:flex-start}.editor-mode-field{width:min(320px,100%)}.editor-diagnostics{display:grid;gap:8px}.editor-diagnostics-title{font-size:.95rem;font-weight:600;color:var(--md-sys-color-on-surface)}.editor-diagnostic{display:grid;gap:4px;padding:10px 12px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);color:var(--md-sys-color-on-surface)}.editor-diagnostic code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;color:var(--md-sys-color-on-surface-variant)}.editor-diagnostic.level-error{background:var(--md-sys-color-error-container);color:var(--md-sys-color-on-error-container);border-color:var(--md-sys-color-error)}.editor-diagnostic.level-warning{background:var(--md-sys-color-tertiary-container, var(--md-sys-color-surface-container));color:var(--md-sys-color-on-tertiary-container, var(--md-sys-color-on-surface));border-color:var(--md-sys-color-outline-variant)}.editor-tabs{--editor-surface: var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));--editor-border: 1px solid var(--md-sys-color-outline-variant);--editor-radius: 12px;--editor-muted: var(--md-sys-color-on-surface-variant)}.editor-section{padding:12px;display:grid;gap:12px;background:var(--editor-surface);border:var(--editor-border);border-radius:var(--editor-radius)}.editor-section-lg{gap:16px}.editor-row{display:flex;gap:10px;flex-wrap:wrap;align-items:center}.editor-grid{display:grid;gap:12px}.editor-grid.two{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.editor-grid.tight{gap:8px}.editor-toolbar{display:flex;gap:8px;flex-wrap:wrap;align-items:center}.editor-muted{color:var(--editor-muted)}.editor-title{margin:6px 0 8px;font-size:1rem}.editor-title-row{display:flex;align-items:center;gap:8px}.editor-code{white-space:pre-wrap;background:var(--md-sys-color-surface-container);padding:8px;border-radius:6px;border:1px solid var(--md-sys-color-outline-variant)}.editor-card{border:1px solid var(--md-sys-color-outline-variant);padding:10px;border-radius:10px;display:grid;gap:8px;background:var(--md-sys-color-surface)}.editor-card.dashed{border-style:dashed}.editor-card-header{display:flex;align-items:center;gap:8px}.editor-card-title{flex:1;font-weight:600}.editor-divider{border-top:1px solid var(--md-sys-color-outline-variant);padding-top:8px}.editor-spacer{flex:1}.editor-field-min{min-width:260px}.editor-section .editor-field-min{width:260px;max-width:260px}.editor-field-240{width:240px}.editor-section .editor-field-240{width:240px;max-width:240px}.editor-json{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.editor-section .mat-mdc-form-field{width:100%;max-width:520px;--mdc-outlined-text-field-container-height: 48px;--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-outline);--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-error-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-focus-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-hover-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-label-text-color: var(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-supporting-text-color: var(--md-sys-color-on-surface-variant)}.editor-section .mat-mdc-form-field.full{max-width:none}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}\n"] }]
|
|
1322
1949
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
1323
1950
|
type: Inject,
|
|
1324
1951
|
args: [SETTINGS_PANEL_DATA]
|
|
1325
1952
|
}] }, { type: i1.ComponentMetadataRegistry }] });
|
|
1326
1953
|
|
|
1327
1954
|
class TabsQuickSetupComponent {
|
|
1955
|
+
i18n = inject(PraxisI18nService);
|
|
1956
|
+
document;
|
|
1328
1957
|
model = { mode: 'group', labels: [], dynamicHeight: true, stretchTabs: true };
|
|
1329
1958
|
initial = { ...this.model };
|
|
1330
1959
|
newLabel = '';
|
|
1331
1960
|
isDirty$ = new BehaviorSubject(false);
|
|
1332
1961
|
isValid$ = new BehaviorSubject(false);
|
|
1333
1962
|
isBusy$ = new BehaviorSubject(false);
|
|
1963
|
+
t(key, fallback) {
|
|
1964
|
+
return this.i18n.t(key, undefined, fallback, PRAXIS_TABS_I18N_NAMESPACE);
|
|
1965
|
+
}
|
|
1334
1966
|
constructor(data) {
|
|
1335
|
-
|
|
1336
|
-
|
|
1967
|
+
const incomingDocument = normalizeTabsAuthoringDocument(data?.document ?? createTabsAuthoringDocument({ config: {} }));
|
|
1968
|
+
this.document = structuredClone(incomingDocument);
|
|
1969
|
+
const cfg = this.document.config;
|
|
1337
1970
|
if (cfg) {
|
|
1338
1971
|
if (cfg.tabs?.length) {
|
|
1339
1972
|
this.model.mode = 'group';
|
|
@@ -1400,50 +2033,56 @@ class TabsQuickSetupComponent {
|
|
|
1400
2033
|
},
|
|
1401
2034
|
};
|
|
1402
2035
|
}
|
|
2036
|
+
buildOutputDocument() {
|
|
2037
|
+
return createTabsAuthoringDocument({
|
|
2038
|
+
config: this.buildConfig(),
|
|
2039
|
+
bindings: this.document?.bindings,
|
|
2040
|
+
});
|
|
2041
|
+
}
|
|
1403
2042
|
getSettingsValue() {
|
|
1404
|
-
return
|
|
2043
|
+
return this.buildOutputDocument();
|
|
1405
2044
|
}
|
|
1406
2045
|
onSave() {
|
|
1407
|
-
return
|
|
2046
|
+
return this.buildOutputDocument();
|
|
1408
2047
|
}
|
|
1409
2048
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TabsQuickSetupComponent, deps: [{ token: SETTINGS_PANEL_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
1410
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: TabsQuickSetupComponent, isStandalone: true, selector: "praxis-tabs-quick-setup", ngImport: i0, template: `
|
|
2049
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: TabsQuickSetupComponent, isStandalone: true, selector: "praxis-tabs-quick-setup", providers: [providePraxisI18nConfig(PRAXIS_TABS_I18N_CONFIG)], ngImport: i0, template: `
|
|
1411
2050
|
<div class="setup-root">
|
|
1412
2051
|
<div class="setup-row">
|
|
1413
2052
|
<button mat-stroked-button [color]="model.mode==='group' ? 'primary' : undefined" (click)="setMode('group')">
|
|
1414
2053
|
<mat-icon [praxisIcon]="'tab'"></mat-icon>
|
|
1415
|
-
Grupo de abas
|
|
2054
|
+
{{ t('quickSetup.mode.group', 'Grupo de abas') }}
|
|
1416
2055
|
</button>
|
|
1417
2056
|
<button mat-stroked-button [color]="model.mode==='nav' ? 'primary' : undefined" (click)="setMode('nav')">
|
|
1418
2057
|
<mat-icon [praxisIcon]="'segment'"></mat-icon>
|
|
1419
|
-
Navegacao por links
|
|
2058
|
+
{{ t('quickSetup.mode.nav', 'Navegacao por links') }}
|
|
1420
2059
|
</button>
|
|
1421
2060
|
</div>
|
|
1422
2061
|
|
|
1423
2062
|
<div class="setup-grid">
|
|
1424
2063
|
<mat-form-field appearance="outline">
|
|
1425
|
-
<mat-label>Adicionar rotulo</mat-label>
|
|
1426
|
-
<input matInput [(ngModel)]="newLabel" (keyup.enter)="addLabel()" placeholder="Ex.: Dados Gerais" />
|
|
2064
|
+
<mat-label>{{ t('editor.fields.addLabel', 'Adicionar rotulo') }}</mat-label>
|
|
2065
|
+
<input matInput [(ngModel)]="newLabel" (keyup.enter)="addLabel()" [placeholder]="t('quickSetup.fields.addLabelPlaceholder', 'Ex.: Dados Gerais')" />
|
|
1427
2066
|
</mat-form-field>
|
|
1428
2067
|
<button mat-flat-button color="primary" (click)="addLabel()">
|
|
1429
2068
|
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
1430
|
-
Adicionar
|
|
2069
|
+
{{ t('editor.actions.add', 'Adicionar') }}
|
|
1431
2070
|
</button>
|
|
1432
2071
|
</div>
|
|
1433
2072
|
|
|
1434
2073
|
<div *ngIf="model.labels.length; else emptyLabels" class="setup-row wrap">
|
|
1435
2074
|
<div *ngFor="let l of model.labels; let i = index" class="chip">
|
|
1436
2075
|
<span>{{ l }}</span>
|
|
1437
|
-
<button mat-icon-button (click)="removeLabel(i)" aria-label="Remover rotulo"><mat-icon [praxisIcon]="'close'"></mat-icon></button>
|
|
2076
|
+
<button mat-icon-button (click)="removeLabel(i)" [attr.aria-label]="t('editor.actions.removeLabel', 'Remover rotulo')"><mat-icon [praxisIcon]="'close'"></mat-icon></button>
|
|
1438
2077
|
</div>
|
|
1439
2078
|
</div>
|
|
1440
2079
|
<ng-template #emptyLabels>
|
|
1441
|
-
<em class="hint">Adicione um ou mais rotulos para criar as abas
|
|
2080
|
+
<em class="hint">{{ t('quickSetup.hints.emptyLabels', 'Adicione um ou mais rotulos para criar as abas.') }}</em>
|
|
1442
2081
|
</ng-template>
|
|
1443
2082
|
|
|
1444
2083
|
<div class="setup-row">
|
|
1445
|
-
<mat-slide-toggle [(ngModel)]="model.dynamicHeight">Altura dinamica</mat-slide-toggle>
|
|
1446
|
-
<mat-slide-toggle [(ngModel)]="model.stretchTabs">Esticar abas</mat-slide-toggle>
|
|
2084
|
+
<mat-slide-toggle [(ngModel)]="model.dynamicHeight" (ngModelChange)="updateState()">{{ t('editor.toggles.dynamicHeight', 'Altura dinamica') }}</mat-slide-toggle>
|
|
2085
|
+
<mat-slide-toggle [(ngModel)]="model.stretchTabs" (ngModelChange)="updateState()">{{ t('editor.toggles.stretchTabs', 'Esticar abas') }}</mat-slide-toggle>
|
|
1447
2086
|
</div>
|
|
1448
2087
|
</div>
|
|
1449
2088
|
`, isInline: true, styles: [":host{display:block;color:var(--md-sys-color-on-surface)}.setup-root{display:grid;gap:12px;padding:8px;background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.setup-row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.setup-row.wrap{flex-wrap:wrap}.setup-grid{display:grid;grid-template-columns:1fr auto;gap:8px;align-items:start}.setup-root .mat-mdc-form-field{width:100%;max-width:520px;--mdc-outlined-text-field-container-height: 48px;--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-outline);--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-error-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-focus-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-hover-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-label-text-color: var(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-supporting-text-color: var(--md-sys-color-on-surface-variant)}.chip{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:16px;background:var(--md-sys-color-surface)}.hint{color:var(--md-sys-color-on-surface-variant)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6$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: i6$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i9.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }] });
|
|
@@ -1459,43 +2098,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
1459
2098
|
PraxisIconDirective,
|
|
1460
2099
|
MatButtonModule,
|
|
1461
2100
|
MatSlideToggleModule,
|
|
1462
|
-
], template: `
|
|
2101
|
+
], providers: [providePraxisI18nConfig(PRAXIS_TABS_I18N_CONFIG)], template: `
|
|
1463
2102
|
<div class="setup-root">
|
|
1464
2103
|
<div class="setup-row">
|
|
1465
2104
|
<button mat-stroked-button [color]="model.mode==='group' ? 'primary' : undefined" (click)="setMode('group')">
|
|
1466
2105
|
<mat-icon [praxisIcon]="'tab'"></mat-icon>
|
|
1467
|
-
Grupo de abas
|
|
2106
|
+
{{ t('quickSetup.mode.group', 'Grupo de abas') }}
|
|
1468
2107
|
</button>
|
|
1469
2108
|
<button mat-stroked-button [color]="model.mode==='nav' ? 'primary' : undefined" (click)="setMode('nav')">
|
|
1470
2109
|
<mat-icon [praxisIcon]="'segment'"></mat-icon>
|
|
1471
|
-
Navegacao por links
|
|
2110
|
+
{{ t('quickSetup.mode.nav', 'Navegacao por links') }}
|
|
1472
2111
|
</button>
|
|
1473
2112
|
</div>
|
|
1474
2113
|
|
|
1475
2114
|
<div class="setup-grid">
|
|
1476
2115
|
<mat-form-field appearance="outline">
|
|
1477
|
-
<mat-label>Adicionar rotulo</mat-label>
|
|
1478
|
-
<input matInput [(ngModel)]="newLabel" (keyup.enter)="addLabel()" placeholder="Ex.: Dados Gerais" />
|
|
2116
|
+
<mat-label>{{ t('editor.fields.addLabel', 'Adicionar rotulo') }}</mat-label>
|
|
2117
|
+
<input matInput [(ngModel)]="newLabel" (keyup.enter)="addLabel()" [placeholder]="t('quickSetup.fields.addLabelPlaceholder', 'Ex.: Dados Gerais')" />
|
|
1479
2118
|
</mat-form-field>
|
|
1480
2119
|
<button mat-flat-button color="primary" (click)="addLabel()">
|
|
1481
2120
|
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
1482
|
-
Adicionar
|
|
2121
|
+
{{ t('editor.actions.add', 'Adicionar') }}
|
|
1483
2122
|
</button>
|
|
1484
2123
|
</div>
|
|
1485
2124
|
|
|
1486
2125
|
<div *ngIf="model.labels.length; else emptyLabels" class="setup-row wrap">
|
|
1487
2126
|
<div *ngFor="let l of model.labels; let i = index" class="chip">
|
|
1488
2127
|
<span>{{ l }}</span>
|
|
1489
|
-
<button mat-icon-button (click)="removeLabel(i)" aria-label="Remover rotulo"><mat-icon [praxisIcon]="'close'"></mat-icon></button>
|
|
2128
|
+
<button mat-icon-button (click)="removeLabel(i)" [attr.aria-label]="t('editor.actions.removeLabel', 'Remover rotulo')"><mat-icon [praxisIcon]="'close'"></mat-icon></button>
|
|
1490
2129
|
</div>
|
|
1491
2130
|
</div>
|
|
1492
2131
|
<ng-template #emptyLabels>
|
|
1493
|
-
<em class="hint">Adicione um ou mais rotulos para criar as abas
|
|
2132
|
+
<em class="hint">{{ t('quickSetup.hints.emptyLabels', 'Adicione um ou mais rotulos para criar as abas.') }}</em>
|
|
1494
2133
|
</ng-template>
|
|
1495
2134
|
|
|
1496
2135
|
<div class="setup-row">
|
|
1497
|
-
<mat-slide-toggle [(ngModel)]="model.dynamicHeight">Altura dinamica</mat-slide-toggle>
|
|
1498
|
-
<mat-slide-toggle [(ngModel)]="model.stretchTabs">Esticar abas</mat-slide-toggle>
|
|
2136
|
+
<mat-slide-toggle [(ngModel)]="model.dynamicHeight" (ngModelChange)="updateState()">{{ t('editor.toggles.dynamicHeight', 'Altura dinamica') }}</mat-slide-toggle>
|
|
2137
|
+
<mat-slide-toggle [(ngModel)]="model.stretchTabs" (ngModelChange)="updateState()">{{ t('editor.toggles.stretchTabs', 'Esticar abas') }}</mat-slide-toggle>
|
|
1499
2138
|
</div>
|
|
1500
2139
|
</div>
|
|
1501
2140
|
`, styles: [":host{display:block;color:var(--md-sys-color-on-surface)}.setup-root{display:grid;gap:12px;padding:8px;background:var(--md-sys-color-surface-container-lowest, var(--md-sys-color-surface));border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.setup-row{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.setup-row.wrap{flex-wrap:wrap}.setup-grid{display:grid;grid-template-columns:1fr auto;gap:8px;align-items:start}.setup-root .mat-mdc-form-field{width:100%;max-width:520px;--mdc-outlined-text-field-container-height: 48px;--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-hover-outline-color: var(--md-sys-color-outline);--mdc-outlined-text-field-focus-outline-color: var(--md-sys-color-primary);--mdc-outlined-text-field-error-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-focus-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-error-hover-outline-color: var(--md-sys-color-error);--mdc-outlined-text-field-label-text-color: var(--md-sys-color-on-surface-variant);--mdc-outlined-text-field-input-text-color: var(--md-sys-color-on-surface);--mdc-outlined-text-field-supporting-text-color: var(--md-sys-color-on-surface-variant)}.chip{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:16px;background:var(--md-sys-color-surface)}.hint{color:var(--md-sys-color-on-surface-variant)}\n"] }]
|
|
@@ -1717,6 +2356,7 @@ class TabsAiAdapter extends BaseAiAdapter {
|
|
|
1717
2356
|
}
|
|
1718
2357
|
|
|
1719
2358
|
class PraxisTabs {
|
|
2359
|
+
i18n = inject(PraxisI18nService);
|
|
1720
2360
|
settings = inject(SettingsPanelService);
|
|
1721
2361
|
storage = inject(ASYNC_CONFIG_STORAGE);
|
|
1722
2362
|
snack = inject(MatSnackBar);
|
|
@@ -1749,6 +2389,7 @@ class PraxisTabs {
|
|
|
1749
2389
|
groupLoaded = new Set();
|
|
1750
2390
|
navLoaded = new Set();
|
|
1751
2391
|
destroy$ = new Subject();
|
|
2392
|
+
widgetDefinitionCache = new WeakMap();
|
|
1752
2393
|
ngOnInit() {
|
|
1753
2394
|
this.syncSelectionFromConfig();
|
|
1754
2395
|
// Load stored config if tabsId provided
|
|
@@ -1929,31 +2570,31 @@ class PraxisTabs {
|
|
|
1929
2570
|
}
|
|
1930
2571
|
openEditor() {
|
|
1931
2572
|
const key = this.storageKey() || this.tabsId || 'default';
|
|
2573
|
+
const initialDocument = createTabsAuthoringDocument({
|
|
2574
|
+
config: this.config ?? {},
|
|
2575
|
+
bindings: this.currentTabsBindings(),
|
|
2576
|
+
});
|
|
1932
2577
|
const ref = this.settings.open({
|
|
1933
2578
|
id: `praxis-tabs-editor:${key}`,
|
|
1934
|
-
title: 'Configurar
|
|
2579
|
+
title: this.t('settings.title', 'Configurar abas'),
|
|
1935
2580
|
content: {
|
|
1936
2581
|
component: PraxisTabsConfigEditor,
|
|
1937
|
-
inputs: {
|
|
2582
|
+
inputs: { document: initialDocument },
|
|
1938
2583
|
},
|
|
1939
2584
|
});
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
const
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
this.persistConfig(this.config);
|
|
1954
|
-
this.syncSelectionFromConfig();
|
|
1955
|
-
}
|
|
1956
|
-
});
|
|
2585
|
+
const applyDocument = (value) => {
|
|
2586
|
+
const document = normalizeTabsAuthoringDocument(value);
|
|
2587
|
+
const plan = buildTabsApplyPlan(document, {
|
|
2588
|
+
currentBindings: this.currentTabsBindings(),
|
|
2589
|
+
currentConfig: this.config,
|
|
2590
|
+
}, {
|
|
2591
|
+
saveConfig: true,
|
|
2592
|
+
saveBindings: false,
|
|
2593
|
+
});
|
|
2594
|
+
this.applyTabsAuthoringPlan(plan);
|
|
2595
|
+
};
|
|
2596
|
+
ref.applied$.pipe(takeUntil(this.destroy$)).subscribe(applyDocument);
|
|
2597
|
+
ref.saved$.pipe(takeUntil(this.destroy$)).subscribe(applyDocument);
|
|
1957
2598
|
}
|
|
1958
2599
|
addEmptyTab() {
|
|
1959
2600
|
const next = produce(this.config || {}, (draft) => {
|
|
@@ -1961,7 +2602,10 @@ class PraxisTabs {
|
|
|
1961
2602
|
draft.group = { selectedIndex: 0 };
|
|
1962
2603
|
if (!draft.tabs)
|
|
1963
2604
|
draft.tabs = [];
|
|
1964
|
-
draft.tabs.push({
|
|
2605
|
+
draft.tabs.push({
|
|
2606
|
+
id: `tab${(draft.tabs.length || 0) + 1}`,
|
|
2607
|
+
textLabel: this.t('defaults.newTabLabel', 'New Tab'),
|
|
2608
|
+
});
|
|
1965
2609
|
draft.group.selectedIndex = (draft.tabs.length || 1) - 1;
|
|
1966
2610
|
});
|
|
1967
2611
|
this.config = next;
|
|
@@ -1978,31 +2622,69 @@ class PraxisTabs {
|
|
|
1978
2622
|
}
|
|
1979
2623
|
catch { }
|
|
1980
2624
|
try {
|
|
1981
|
-
this.snack.open('
|
|
2625
|
+
this.snack.open(this.t('settings.resetDone', 'Preferencias de abas redefinidas'), undefined, { duration: 2000 });
|
|
1982
2626
|
}
|
|
1983
2627
|
catch { }
|
|
1984
2628
|
// keep current in-memory config; caller may choose to reload
|
|
1985
2629
|
}
|
|
1986
2630
|
openQuickSetup() {
|
|
1987
2631
|
const key = this.storageKey() || this.tabsId || 'default';
|
|
2632
|
+
const initialDocument = createTabsAuthoringDocument({
|
|
2633
|
+
config: this.config ?? {},
|
|
2634
|
+
bindings: this.currentTabsBindings(),
|
|
2635
|
+
});
|
|
1988
2636
|
const ref = this.settings.open({
|
|
1989
2637
|
id: `praxis-tabs-quick-setup:${key}`,
|
|
1990
|
-
title: 'Criar abas rapidamente',
|
|
2638
|
+
title: this.t('quickSetup.title', 'Criar abas rapidamente'),
|
|
1991
2639
|
content: {
|
|
1992
2640
|
component: TabsQuickSetupComponent,
|
|
1993
|
-
inputs: {
|
|
2641
|
+
inputs: { document: initialDocument },
|
|
1994
2642
|
},
|
|
1995
2643
|
});
|
|
1996
|
-
const
|
|
1997
|
-
const
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
this.
|
|
2001
|
-
|
|
2002
|
-
|
|
2644
|
+
const applyDocument = (value) => {
|
|
2645
|
+
const document = normalizeTabsAuthoringDocument(value);
|
|
2646
|
+
const plan = buildTabsApplyPlan(document, {
|
|
2647
|
+
currentBindings: this.currentTabsBindings(),
|
|
2648
|
+
currentConfig: this.config,
|
|
2649
|
+
}, {
|
|
2650
|
+
saveConfig: true,
|
|
2651
|
+
saveBindings: false,
|
|
2652
|
+
});
|
|
2653
|
+
this.applyTabsAuthoringPlan(plan);
|
|
2003
2654
|
};
|
|
2004
|
-
ref.applied$.pipe(takeUntil(this.destroy$)).subscribe(
|
|
2005
|
-
ref.saved$.pipe(takeUntil(this.destroy$)).subscribe(
|
|
2655
|
+
ref.applied$.pipe(takeUntil(this.destroy$)).subscribe(applyDocument);
|
|
2656
|
+
ref.saved$.pipe(takeUntil(this.destroy$)).subscribe(applyDocument);
|
|
2657
|
+
}
|
|
2658
|
+
currentTabsBindings() {
|
|
2659
|
+
return {
|
|
2660
|
+
tabsId: this.tabsId ?? null,
|
|
2661
|
+
componentInstanceId: this.componentInstanceId ?? null,
|
|
2662
|
+
};
|
|
2663
|
+
}
|
|
2664
|
+
t(key, fallback) {
|
|
2665
|
+
return this.i18n.t(key, undefined, fallback, PRAXIS_TABS_I18N_NAMESPACE);
|
|
2666
|
+
}
|
|
2667
|
+
applyTabsAuthoringPlan(plan) {
|
|
2668
|
+
if (plan.diagnostics.some((item) => item.level === 'error')) {
|
|
2669
|
+
return;
|
|
2670
|
+
}
|
|
2671
|
+
this.config = plan.canonicalConfig;
|
|
2672
|
+
this.syncSelectionFromConfig();
|
|
2673
|
+
if (plan.runtime.rebuildLazyState) {
|
|
2674
|
+
this.groupLoaded.clear();
|
|
2675
|
+
this.navLoaded.clear();
|
|
2676
|
+
const groupIndex = this.selectedIndexSignal();
|
|
2677
|
+
const navIndex = this.currentNavIndex();
|
|
2678
|
+
if ((this.config?.tabs?.length ?? 0) > 0) {
|
|
2679
|
+
this.groupLoaded.add(groupIndex);
|
|
2680
|
+
}
|
|
2681
|
+
if ((this.config?.nav?.links?.length ?? 0) > 0) {
|
|
2682
|
+
this.navLoaded.add(navIndex);
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
if (plan.persistence.saveConfig) {
|
|
2686
|
+
this.persistConfig(this.config);
|
|
2687
|
+
}
|
|
2006
2688
|
}
|
|
2007
2689
|
storageKey() {
|
|
2008
2690
|
const id = this.componentKeyId();
|
|
@@ -2086,8 +2768,42 @@ class PraxisTabs {
|
|
|
2086
2768
|
const hasLinks = !!(this.config?.nav?.links && this.config.nav.links.length > 0);
|
|
2087
2769
|
return !(hasTabs || hasLinks);
|
|
2088
2770
|
}
|
|
2089
|
-
|
|
2090
|
-
|
|
2771
|
+
trackNavLink(index, link) {
|
|
2772
|
+
return link.id || `${link.label || 'nav-link'}:${index}`;
|
|
2773
|
+
}
|
|
2774
|
+
trackTab(index, tab) {
|
|
2775
|
+
return tab.id || tab.textLabel || `tab:${index}`;
|
|
2776
|
+
}
|
|
2777
|
+
trackWidgetDefinition(index, widget) {
|
|
2778
|
+
return widget.childWidgetKey || widget.id || `widget:${index}`;
|
|
2779
|
+
}
|
|
2780
|
+
resolveWidgetDefinition(widget) {
|
|
2781
|
+
const cached = this.widgetDefinitionCache.get(widget);
|
|
2782
|
+
if (cached) {
|
|
2783
|
+
return cached;
|
|
2784
|
+
}
|
|
2785
|
+
const clone = this.cloneWidgetDefinition(widget);
|
|
2786
|
+
this.widgetDefinitionCache.set(widget, clone);
|
|
2787
|
+
return clone;
|
|
2788
|
+
}
|
|
2789
|
+
emitWidgetEvent(path, ev) {
|
|
2790
|
+
this.widgetEvent.emit({
|
|
2791
|
+
...ev,
|
|
2792
|
+
path: [...path, ...(ev.path || [])],
|
|
2793
|
+
});
|
|
2794
|
+
}
|
|
2795
|
+
tabEventPath(tabId, tabIndex) {
|
|
2796
|
+
return [
|
|
2797
|
+
{ kind: 'tabs', id: this.tabsId },
|
|
2798
|
+
{ kind: 'tab', id: tabId, index: tabIndex },
|
|
2799
|
+
];
|
|
2800
|
+
}
|
|
2801
|
+
linkEventPath(linkId, linkIndex) {
|
|
2802
|
+
return [
|
|
2803
|
+
{ kind: 'tabs', id: this.tabsId },
|
|
2804
|
+
{ kind: 'nav', id: this.tabsId },
|
|
2805
|
+
{ kind: 'link', id: linkId, index: linkIndex },
|
|
2806
|
+
];
|
|
2091
2807
|
}
|
|
2092
2808
|
styleScopeId() {
|
|
2093
2809
|
const scopeSeed = [this.tabsId, this.componentInstanceId]
|
|
@@ -2226,8 +2942,17 @@ class PraxisTabs {
|
|
|
2226
2942
|
}
|
|
2227
2943
|
return rules.length ? rules.join('\n') : null;
|
|
2228
2944
|
}
|
|
2945
|
+
cloneWidgetDefinition(widget) {
|
|
2946
|
+
try {
|
|
2947
|
+
if (typeof structuredClone === 'function') {
|
|
2948
|
+
return structuredClone(widget);
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
catch { }
|
|
2952
|
+
return JSON.parse(JSON.stringify(widget));
|
|
2953
|
+
}
|
|
2229
2954
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTabs, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2230
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: PraxisTabs, isStandalone: true, selector: "praxis-tabs", inputs: { config: "config", tabsId: "tabsId", componentInstanceId: "componentInstanceId", enableCustomization: "enableCustomization", form: "form", context: "context" }, outputs: { animationDone: "animationDone", focusChange: "focusChange", selectedIndexChange: "selectedIndexChange", selectedTabChange: "selectedTabChange", indexFocused: "indexFocused", selectFocusedIndex: "selectFocusedIndex", widgetEvent: "widgetEvent" }, usesOnChanges: true, ngImport: i0, template: `
|
|
2955
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: PraxisTabs, isStandalone: true, selector: "praxis-tabs", inputs: { config: "config", tabsId: "tabsId", componentInstanceId: "componentInstanceId", enableCustomization: "enableCustomization", form: "form", context: "context" }, outputs: { animationDone: "animationDone", focusChange: "focusChange", selectedIndexChange: "selectedIndexChange", selectedTabChange: "selectedTabChange", indexFocused: "indexFocused", selectFocusedIndex: "selectFocusedIndex", widgetEvent: "widgetEvent" }, providers: [providePraxisI18nConfig(PRAXIS_TABS_I18N_CONFIG)], usesOnChanges: true, ngImport: i0, template: `
|
|
2231
2956
|
<div
|
|
2232
2957
|
class="praxis-tabs-root"
|
|
2233
2958
|
[class.density-compact]="config?.appearance?.density === 'compact'"
|
|
@@ -2251,12 +2976,12 @@ class PraxisTabs {
|
|
|
2251
2976
|
<ng-container *ngIf="isEmptyGlobal(); else notEmpty">
|
|
2252
2977
|
<praxis-empty-state-card
|
|
2253
2978
|
icon="tab"
|
|
2254
|
-
[title]="'Nenhuma aba configurada'"
|
|
2255
|
-
[description]="'Crie rapidamente suas abas ou abra o editor completo.'"
|
|
2256
|
-
[primaryAction]="{ label: 'Criar abas rapidamente', icon: 'add', action: openQuickSetup.bind(this) }"
|
|
2979
|
+
[title]="t('emptyState.title', 'Nenhuma aba configurada')"
|
|
2980
|
+
[description]="t('emptyState.description', 'Crie rapidamente suas abas ou abra o editor completo.')"
|
|
2981
|
+
[primaryAction]="{ label: t('emptyState.primaryAction', 'Criar abas rapidamente'), icon: 'add', action: openQuickSetup.bind(this) }"
|
|
2257
2982
|
[secondaryActions]="[
|
|
2258
|
-
{ label: 'Adicionar aba vazia', icon: 'tab', action: addEmptyTab.bind(this) },
|
|
2259
|
-
{ label: 'Abrir editor completo', icon: 'tune', action: openEditor.bind(this) }
|
|
2983
|
+
{ label: t('emptyState.secondaryAddEmpty', 'Adicionar aba vazia'), icon: 'tab', action: addEmptyTab.bind(this) },
|
|
2984
|
+
{ label: t('emptyState.secondaryOpenEditor', 'Abrir editor completo'), icon: 'tune', action: openEditor.bind(this) }
|
|
2260
2985
|
]"
|
|
2261
2986
|
></praxis-empty-state-card>
|
|
2262
2987
|
</ng-container>
|
|
@@ -2285,7 +3010,7 @@ class PraxisTabs {
|
|
|
2285
3010
|
>
|
|
2286
3011
|
<a
|
|
2287
3012
|
mat-tab-link
|
|
2288
|
-
*ngFor="let link of config?.nav?.links; let i = index"
|
|
3013
|
+
*ngFor="let link of config?.nav?.links; let i = index; trackBy: trackNavLink"
|
|
2289
3014
|
cdkDrag
|
|
2290
3015
|
[cdkDragDisabled]="!config?.behavior?.reorderable"
|
|
2291
3016
|
cdkDragLockAxis="x"
|
|
@@ -2317,11 +3042,11 @@ class PraxisTabs {
|
|
|
2317
3042
|
></ng-container>
|
|
2318
3043
|
</ng-container>
|
|
2319
3044
|
<ng-container *ngIf="l.widgets?.length">
|
|
2320
|
-
<ng-container *ngFor="let w of l.widgets; let wi = index">
|
|
3045
|
+
<ng-container *ngFor="let w of l.widgets; let wi = index; trackBy: trackWidgetDefinition">
|
|
2321
3046
|
<ng-container
|
|
2322
|
-
[dynamicWidgetLoader]="w"
|
|
3047
|
+
[dynamicWidgetLoader]="resolveWidgetDefinition(w)"
|
|
2323
3048
|
[context]="context || {}"
|
|
2324
|
-
(widgetEvent)="emitWidgetEvent(
|
|
3049
|
+
(widgetEvent)="emitWidgetEvent(linkEventPath(l.id, currentNavIndex()), $event)"
|
|
2325
3050
|
></ng-container>
|
|
2326
3051
|
</ng-container>
|
|
2327
3052
|
</ng-container>
|
|
@@ -2330,9 +3055,9 @@ class PraxisTabs {
|
|
|
2330
3055
|
<praxis-empty-state-card
|
|
2331
3056
|
[inline]="true"
|
|
2332
3057
|
icon="add_to_queue"
|
|
2333
|
-
[title]="'Sem
|
|
2334
|
-
[description]="'Adicione
|
|
2335
|
-
[primaryAction]="{ label: 'Abrir editor', icon: 'tune', action: openEditor.bind(this) }"
|
|
3058
|
+
[title]="t('emptyState.navTitle', 'Sem conteudo neste link')"
|
|
3059
|
+
[description]="t('emptyState.navDescription', 'Adicione conteudo ou use o editor para configurar.')"
|
|
3060
|
+
[primaryAction]="{ label: t('emptyState.openEditor', 'Abrir editor'), icon: 'tune', action: openEditor.bind(this) }"
|
|
2336
3061
|
></praxis-empty-state-card>
|
|
2337
3062
|
</ng-template>
|
|
2338
3063
|
</ng-container>
|
|
@@ -2364,16 +3089,16 @@ class PraxisTabs {
|
|
|
2364
3089
|
class="praxis-tabs-group"
|
|
2365
3090
|
>
|
|
2366
3091
|
<mat-tab
|
|
2367
|
-
*ngFor="let
|
|
2368
|
-
[disabled]="
|
|
2369
|
-
[labelClass]="
|
|
2370
|
-
[bodyClass]="
|
|
2371
|
-
[id]="
|
|
2372
|
-
[attr.aria-label]="
|
|
2373
|
-
[attr.aria-labelledby]="
|
|
3092
|
+
*ngFor="let tab of config?.tabs; let i = index; trackBy: trackTab"
|
|
3093
|
+
[disabled]="tab.disabled"
|
|
3094
|
+
[labelClass]="tab.labelClass ?? ''"
|
|
3095
|
+
[bodyClass]="tab.bodyClass ?? ''"
|
|
3096
|
+
[id]="tab.id || ''"
|
|
3097
|
+
[attr.aria-label]="tab.ariaLabel || null"
|
|
3098
|
+
[attr.aria-labelledby]="tab.ariaLabelledby || null"
|
|
2374
3099
|
>
|
|
2375
3100
|
<ng-template mat-tab-label>
|
|
2376
|
-
<span>{{
|
|
3101
|
+
<span>{{ tab.textLabel }}</span>
|
|
2377
3102
|
<button
|
|
2378
3103
|
*ngIf="config?.behavior?.closeable"
|
|
2379
3104
|
mat-icon-button
|
|
@@ -2381,7 +3106,7 @@ class PraxisTabs {
|
|
|
2381
3106
|
(click)="closeTab(i); $event.stopPropagation()"
|
|
2382
3107
|
(keydown.enter)="$event.stopPropagation()"
|
|
2383
3108
|
(keydown.space)="$event.stopPropagation()"
|
|
2384
|
-
aria-label="Fechar aba"
|
|
3109
|
+
[attr.aria-label]="t('chrome.closeTab', 'Fechar aba')"
|
|
2385
3110
|
>
|
|
2386
3111
|
<mat-icon fontIcon="close"></mat-icon>
|
|
2387
3112
|
</button>
|
|
@@ -2393,7 +3118,7 @@ class PraxisTabs {
|
|
|
2393
3118
|
(keydown.enter)="$event.stopPropagation()"
|
|
2394
3119
|
(keydown.space)="$event.stopPropagation()"
|
|
2395
3120
|
[disabled]="i===0"
|
|
2396
|
-
aria-label="Mover aba para esquerda"
|
|
3121
|
+
[attr.aria-label]="t('chrome.moveTabLeft', 'Mover aba para esquerda')"
|
|
2397
3122
|
>
|
|
2398
3123
|
<mat-icon fontIcon="arrow_back"></mat-icon>
|
|
2399
3124
|
</button>
|
|
@@ -2404,7 +3129,7 @@ class PraxisTabs {
|
|
|
2404
3129
|
(keydown.enter)="$event.stopPropagation()"
|
|
2405
3130
|
(keydown.space)="$event.stopPropagation()"
|
|
2406
3131
|
[disabled]="i===(config?.tabs?.length||1)-1"
|
|
2407
|
-
aria-label="Mover aba para direita"
|
|
3132
|
+
[attr.aria-label]="t('chrome.moveTabRight', 'Mover aba para direita')"
|
|
2408
3133
|
>
|
|
2409
3134
|
<mat-icon fontIcon="arrow_forward"></mat-icon>
|
|
2410
3135
|
</button>
|
|
@@ -2412,20 +3137,20 @@ class PraxisTabs {
|
|
|
2412
3137
|
</ng-template>
|
|
2413
3138
|
|
|
2414
3139
|
<ng-template matTabContent>
|
|
2415
|
-
<ng-container *ngIf="(
|
|
2416
|
-
<ng-container *ngIf="
|
|
3140
|
+
<ng-container *ngIf="(tab.content?.length || tab.widgets?.length) && groupContentReady(i); else emptyTab">
|
|
3141
|
+
<ng-container *ngIf="tab.content && form">
|
|
2417
3142
|
<ng-container
|
|
2418
3143
|
dynamicFieldLoader
|
|
2419
|
-
[fields]="
|
|
3144
|
+
[fields]="tab.content || []"
|
|
2420
3145
|
[formGroup]="form!"
|
|
2421
3146
|
></ng-container>
|
|
2422
3147
|
</ng-container>
|
|
2423
|
-
<ng-container *ngIf="
|
|
2424
|
-
<ng-container *ngFor="let w of
|
|
3148
|
+
<ng-container *ngIf="tab.widgets?.length">
|
|
3149
|
+
<ng-container *ngFor="let w of tab.widgets; let wi = index; trackBy: trackWidgetDefinition">
|
|
2425
3150
|
<ng-container
|
|
2426
|
-
[dynamicWidgetLoader]="w"
|
|
3151
|
+
[dynamicWidgetLoader]="resolveWidgetDefinition(w)"
|
|
2427
3152
|
[context]="context || {}"
|
|
2428
|
-
(widgetEvent)="emitWidgetEvent(
|
|
3153
|
+
(widgetEvent)="emitWidgetEvent(tabEventPath(tab.id, i), $event)"
|
|
2429
3154
|
></ng-container>
|
|
2430
3155
|
</ng-container>
|
|
2431
3156
|
</ng-container>
|
|
@@ -2434,9 +3159,9 @@ class PraxisTabs {
|
|
|
2434
3159
|
<praxis-empty-state-card
|
|
2435
3160
|
[inline]="true"
|
|
2436
3161
|
icon="dashboard_customize"
|
|
2437
|
-
[title]="'Sem
|
|
2438
|
-
[description]="'Adicione
|
|
2439
|
-
[primaryAction]="{ label: 'Abrir editor', icon: 'tune', action: openEditor.bind(this) }"
|
|
3162
|
+
[title]="t('emptyState.tabTitle', 'Sem conteudo nesta aba')"
|
|
3163
|
+
[description]="t('emptyState.tabDescription', 'Adicione conteudo ou use o editor para configurar.')"
|
|
3164
|
+
[primaryAction]="{ label: t('emptyState.openEditor', 'Abrir editor'), icon: 'tune', action: openEditor.bind(this) }"
|
|
2440
3165
|
></praxis-empty-state-card>
|
|
2441
3166
|
</ng-template>
|
|
2442
3167
|
</ng-template>
|
|
@@ -2450,7 +3175,7 @@ class PraxisTabs {
|
|
|
2450
3175
|
*ngIf="enableCustomization"
|
|
2451
3176
|
mat-fab
|
|
2452
3177
|
class="edit-fab"
|
|
2453
|
-
aria-label="Editar
|
|
3178
|
+
[attr.aria-label]="t('chrome.editTabs', 'Editar abas')"
|
|
2454
3179
|
(click)="openEditor()"
|
|
2455
3180
|
>
|
|
2456
3181
|
<mat-icon fontIcon="edit"></mat-icon>
|
|
@@ -2459,18 +3184,18 @@ class PraxisTabs {
|
|
|
2459
3184
|
*ngIf="enableCustomization && tabsId"
|
|
2460
3185
|
mat-mini-fab
|
|
2461
3186
|
class="edit-fab edit-fab-secondary"
|
|
2462
|
-
aria-label="Redefinir
|
|
3187
|
+
[attr.aria-label]="t('settings.resetPreferences', 'Redefinir preferencias de abas')"
|
|
2463
3188
|
(click)="resetPreferences()"
|
|
2464
|
-
matTooltip="Redefinir
|
|
3189
|
+
[matTooltip]="t('settings.resetPreferences', 'Redefinir preferencias de abas')"
|
|
2465
3190
|
>
|
|
2466
3191
|
<mat-icon [praxisIcon]="'restart_alt'"></mat-icon>
|
|
2467
3192
|
</button>
|
|
2468
3193
|
</div>
|
|
2469
|
-
`, isInline: true, styles: [".praxis-tabs-root{position:relative;display:block}.praxis-tabs-group.align-start .mat-mdc-tab-header{justify-content:flex-start}.praxis-tabs-group.align-center .mat-mdc-tab-header{justify-content:center}.praxis-tabs-group.align-end .mat-mdc-tab-header{justify-content:flex-end}.density-compact .mat-mdc-tab-body-content{padding:8px}.density-comfortable .mat-mdc-tab-body-content{padding:16px}.density-spacious .mat-mdc-tab-body-content{padding:24px}.tabs-ai-assistant{position:absolute;right:12px;bottom:72px;z-index:3}.edit-fab{position:absolute;right:12px;bottom:12px;z-index:2}.edit-fab-secondary{right:56px}.tab-empty{padding:16px;color:var(--md-sys-color-on-surface-variant);font-style:italic}.high-contrast{filter:contrast(1.2)}.reduce-motion{--mat-animation-duration: 0ms}.drag-handle{display:inline-flex;align-items:center;vertical-align:middle;margin-right:4px;cursor:grab}:host-context(.pdx-gridster-item) .praxis-tabs-root{display:flex;flex-direction:column;height:100%;min-height:0}:host-context(.pdx-gridster-item) .praxis-tabs-group,:host-context(.pdx-gridster-item) .mat-mdc-tab-group{flex:1 1 auto;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-wrapper,:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{height:100%;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{overflow:auto}:host-context(.pdx-gridster-item) .praxis-tabnav-content{flex:1 1 auto;min-height:0;overflow:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i3$1.MatTabContent, selector: "[matTabContent]" }, { kind: "directive", type: i3$1.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i3$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i3$1.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i3$1.MatTabNav, selector: "[mat-tab-nav-bar]", inputs: ["fitInkBarToContent", "mat-stretch-tabs", "animationDuration", "backgroundColor", "disableRipple", "color", "tabPanel"], exportAs: ["matTabNavBar", "matTabNav"] }, { kind: "component", type: i3$1.MatTabNavPanel, selector: "mat-tab-nav-panel", inputs: ["id"], exportAs: ["matTabNavPanel"] }, { kind: "component", type: i3$1.MatTabLink, selector: "[mat-tab-link], [matTabLink]", inputs: ["active", "disabled", "disableRipple", "tabIndex", "id"], exportAs: ["matTabLink"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i10.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i10.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i10.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent"], exportAs: ["dynamicWidgetLoader"] }, { kind: "component", type: PraxisAiAssistantComponent, selector: "praxis-ai-assistant", inputs: ["adapter", "riskPolicy", "allowManualPatchEdit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3194
|
+
`, isInline: true, styles: [".praxis-tabs-root{position:relative;display:block}.praxis-tabs-group.align-start .mat-mdc-tab-header{justify-content:flex-start}.praxis-tabs-group.align-center .mat-mdc-tab-header{justify-content:center}.praxis-tabs-group.align-end .mat-mdc-tab-header{justify-content:flex-end}.density-compact .mat-mdc-tab-body-content{padding:8px}.density-comfortable .mat-mdc-tab-body-content{padding:16px}.density-spacious .mat-mdc-tab-body-content{padding:24px}.tabs-ai-assistant{position:absolute;right:12px;bottom:72px;z-index:3}.edit-fab{position:absolute;right:12px;bottom:12px;z-index:2}.edit-fab-secondary{right:56px}.tab-empty{padding:16px;color:var(--md-sys-color-on-surface-variant);font-style:italic}.high-contrast{filter:contrast(1.2)}.reduce-motion{--mat-animation-duration: 0ms}.drag-handle{display:inline-flex;align-items:center;vertical-align:middle;margin-right:4px;cursor:grab}:host-context(.pdx-gridster-item) .praxis-tabs-root{display:flex;flex-direction:column;height:100%;min-height:0}:host-context(.pdx-gridster-item) .praxis-tabs-group,:host-context(.pdx-gridster-item) .mat-mdc-tab-group{flex:1 1 auto;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-wrapper,:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{height:100%;min-height:0}:host-context(.pdx-gridster-item) .mat-mdc-tab-body-content{overflow:auto}:host-context(.pdx-gridster-item) .praxis-tabnav-content{flex:1 1 auto;min-height:0;overflow:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i3$1.MatTabContent, selector: "[matTabContent]" }, { kind: "directive", type: i3$1.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i3$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i3$1.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i3$1.MatTabNav, selector: "[mat-tab-nav-bar]", inputs: ["fitInkBarToContent", "mat-stretch-tabs", "animationDuration", "backgroundColor", "disableRipple", "color", "tabPanel"], exportAs: ["matTabNavBar", "matTabNav"] }, { kind: "component", type: i3$1.MatTabNavPanel, selector: "mat-tab-nav-panel", inputs: ["id"], exportAs: ["matTabNavPanel"] }, { kind: "component", type: i3$1.MatTabLink, selector: "[mat-tab-link], [matTabLink]", inputs: ["active", "disabled", "disableRipple", "tabIndex", "id"], exportAs: ["matTabLink"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6$1.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6$1.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i10.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i10.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i10.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "ownerWidgetKey", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent", "widgetDiagnostic"], exportAs: ["dynamicWidgetLoader"] }, { kind: "component", type: PraxisAiAssistantComponent, selector: "praxis-ai-assistant", inputs: ["adapter", "riskPolicy", "allowManualPatchEdit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2470
3195
|
}
|
|
2471
3196
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisTabs, decorators: [{
|
|
2472
3197
|
type: Component,
|
|
2473
|
-
args: [{ selector: 'praxis-tabs', standalone: true, imports: [
|
|
3198
|
+
args: [{ selector: 'praxis-tabs', standalone: true, providers: [providePraxisI18nConfig(PRAXIS_TABS_I18N_CONFIG)], imports: [
|
|
2474
3199
|
CommonModule,
|
|
2475
3200
|
ReactiveFormsModule,
|
|
2476
3201
|
MatTabsModule,
|
|
@@ -2507,12 +3232,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2507
3232
|
<ng-container *ngIf="isEmptyGlobal(); else notEmpty">
|
|
2508
3233
|
<praxis-empty-state-card
|
|
2509
3234
|
icon="tab"
|
|
2510
|
-
[title]="'Nenhuma aba configurada'"
|
|
2511
|
-
[description]="'Crie rapidamente suas abas ou abra o editor completo.'"
|
|
2512
|
-
[primaryAction]="{ label: 'Criar abas rapidamente', icon: 'add', action: openQuickSetup.bind(this) }"
|
|
3235
|
+
[title]="t('emptyState.title', 'Nenhuma aba configurada')"
|
|
3236
|
+
[description]="t('emptyState.description', 'Crie rapidamente suas abas ou abra o editor completo.')"
|
|
3237
|
+
[primaryAction]="{ label: t('emptyState.primaryAction', 'Criar abas rapidamente'), icon: 'add', action: openQuickSetup.bind(this) }"
|
|
2513
3238
|
[secondaryActions]="[
|
|
2514
|
-
{ label: 'Adicionar aba vazia', icon: 'tab', action: addEmptyTab.bind(this) },
|
|
2515
|
-
{ label: 'Abrir editor completo', icon: 'tune', action: openEditor.bind(this) }
|
|
3239
|
+
{ label: t('emptyState.secondaryAddEmpty', 'Adicionar aba vazia'), icon: 'tab', action: addEmptyTab.bind(this) },
|
|
3240
|
+
{ label: t('emptyState.secondaryOpenEditor', 'Abrir editor completo'), icon: 'tune', action: openEditor.bind(this) }
|
|
2516
3241
|
]"
|
|
2517
3242
|
></praxis-empty-state-card>
|
|
2518
3243
|
</ng-container>
|
|
@@ -2541,7 +3266,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2541
3266
|
>
|
|
2542
3267
|
<a
|
|
2543
3268
|
mat-tab-link
|
|
2544
|
-
*ngFor="let link of config?.nav?.links; let i = index"
|
|
3269
|
+
*ngFor="let link of config?.nav?.links; let i = index; trackBy: trackNavLink"
|
|
2545
3270
|
cdkDrag
|
|
2546
3271
|
[cdkDragDisabled]="!config?.behavior?.reorderable"
|
|
2547
3272
|
cdkDragLockAxis="x"
|
|
@@ -2573,11 +3298,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2573
3298
|
></ng-container>
|
|
2574
3299
|
</ng-container>
|
|
2575
3300
|
<ng-container *ngIf="l.widgets?.length">
|
|
2576
|
-
<ng-container *ngFor="let w of l.widgets; let wi = index">
|
|
3301
|
+
<ng-container *ngFor="let w of l.widgets; let wi = index; trackBy: trackWidgetDefinition">
|
|
2577
3302
|
<ng-container
|
|
2578
|
-
[dynamicWidgetLoader]="w"
|
|
3303
|
+
[dynamicWidgetLoader]="resolveWidgetDefinition(w)"
|
|
2579
3304
|
[context]="context || {}"
|
|
2580
|
-
(widgetEvent)="emitWidgetEvent(
|
|
3305
|
+
(widgetEvent)="emitWidgetEvent(linkEventPath(l.id, currentNavIndex()), $event)"
|
|
2581
3306
|
></ng-container>
|
|
2582
3307
|
</ng-container>
|
|
2583
3308
|
</ng-container>
|
|
@@ -2586,9 +3311,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2586
3311
|
<praxis-empty-state-card
|
|
2587
3312
|
[inline]="true"
|
|
2588
3313
|
icon="add_to_queue"
|
|
2589
|
-
[title]="'Sem
|
|
2590
|
-
[description]="'Adicione
|
|
2591
|
-
[primaryAction]="{ label: 'Abrir editor', icon: 'tune', action: openEditor.bind(this) }"
|
|
3314
|
+
[title]="t('emptyState.navTitle', 'Sem conteudo neste link')"
|
|
3315
|
+
[description]="t('emptyState.navDescription', 'Adicione conteudo ou use o editor para configurar.')"
|
|
3316
|
+
[primaryAction]="{ label: t('emptyState.openEditor', 'Abrir editor'), icon: 'tune', action: openEditor.bind(this) }"
|
|
2592
3317
|
></praxis-empty-state-card>
|
|
2593
3318
|
</ng-template>
|
|
2594
3319
|
</ng-container>
|
|
@@ -2620,16 +3345,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2620
3345
|
class="praxis-tabs-group"
|
|
2621
3346
|
>
|
|
2622
3347
|
<mat-tab
|
|
2623
|
-
*ngFor="let
|
|
2624
|
-
[disabled]="
|
|
2625
|
-
[labelClass]="
|
|
2626
|
-
[bodyClass]="
|
|
2627
|
-
[id]="
|
|
2628
|
-
[attr.aria-label]="
|
|
2629
|
-
[attr.aria-labelledby]="
|
|
3348
|
+
*ngFor="let tab of config?.tabs; let i = index; trackBy: trackTab"
|
|
3349
|
+
[disabled]="tab.disabled"
|
|
3350
|
+
[labelClass]="tab.labelClass ?? ''"
|
|
3351
|
+
[bodyClass]="tab.bodyClass ?? ''"
|
|
3352
|
+
[id]="tab.id || ''"
|
|
3353
|
+
[attr.aria-label]="tab.ariaLabel || null"
|
|
3354
|
+
[attr.aria-labelledby]="tab.ariaLabelledby || null"
|
|
2630
3355
|
>
|
|
2631
3356
|
<ng-template mat-tab-label>
|
|
2632
|
-
<span>{{
|
|
3357
|
+
<span>{{ tab.textLabel }}</span>
|
|
2633
3358
|
<button
|
|
2634
3359
|
*ngIf="config?.behavior?.closeable"
|
|
2635
3360
|
mat-icon-button
|
|
@@ -2637,7 +3362,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2637
3362
|
(click)="closeTab(i); $event.stopPropagation()"
|
|
2638
3363
|
(keydown.enter)="$event.stopPropagation()"
|
|
2639
3364
|
(keydown.space)="$event.stopPropagation()"
|
|
2640
|
-
aria-label="Fechar aba"
|
|
3365
|
+
[attr.aria-label]="t('chrome.closeTab', 'Fechar aba')"
|
|
2641
3366
|
>
|
|
2642
3367
|
<mat-icon fontIcon="close"></mat-icon>
|
|
2643
3368
|
</button>
|
|
@@ -2649,7 +3374,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2649
3374
|
(keydown.enter)="$event.stopPropagation()"
|
|
2650
3375
|
(keydown.space)="$event.stopPropagation()"
|
|
2651
3376
|
[disabled]="i===0"
|
|
2652
|
-
aria-label="Mover aba para esquerda"
|
|
3377
|
+
[attr.aria-label]="t('chrome.moveTabLeft', 'Mover aba para esquerda')"
|
|
2653
3378
|
>
|
|
2654
3379
|
<mat-icon fontIcon="arrow_back"></mat-icon>
|
|
2655
3380
|
</button>
|
|
@@ -2660,7 +3385,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2660
3385
|
(keydown.enter)="$event.stopPropagation()"
|
|
2661
3386
|
(keydown.space)="$event.stopPropagation()"
|
|
2662
3387
|
[disabled]="i===(config?.tabs?.length||1)-1"
|
|
2663
|
-
aria-label="Mover aba para direita"
|
|
3388
|
+
[attr.aria-label]="t('chrome.moveTabRight', 'Mover aba para direita')"
|
|
2664
3389
|
>
|
|
2665
3390
|
<mat-icon fontIcon="arrow_forward"></mat-icon>
|
|
2666
3391
|
</button>
|
|
@@ -2668,20 +3393,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2668
3393
|
</ng-template>
|
|
2669
3394
|
|
|
2670
3395
|
<ng-template matTabContent>
|
|
2671
|
-
<ng-container *ngIf="(
|
|
2672
|
-
<ng-container *ngIf="
|
|
3396
|
+
<ng-container *ngIf="(tab.content?.length || tab.widgets?.length) && groupContentReady(i); else emptyTab">
|
|
3397
|
+
<ng-container *ngIf="tab.content && form">
|
|
2673
3398
|
<ng-container
|
|
2674
3399
|
dynamicFieldLoader
|
|
2675
|
-
[fields]="
|
|
3400
|
+
[fields]="tab.content || []"
|
|
2676
3401
|
[formGroup]="form!"
|
|
2677
3402
|
></ng-container>
|
|
2678
3403
|
</ng-container>
|
|
2679
|
-
<ng-container *ngIf="
|
|
2680
|
-
<ng-container *ngFor="let w of
|
|
3404
|
+
<ng-container *ngIf="tab.widgets?.length">
|
|
3405
|
+
<ng-container *ngFor="let w of tab.widgets; let wi = index; trackBy: trackWidgetDefinition">
|
|
2681
3406
|
<ng-container
|
|
2682
|
-
[dynamicWidgetLoader]="w"
|
|
3407
|
+
[dynamicWidgetLoader]="resolveWidgetDefinition(w)"
|
|
2683
3408
|
[context]="context || {}"
|
|
2684
|
-
(widgetEvent)="emitWidgetEvent(
|
|
3409
|
+
(widgetEvent)="emitWidgetEvent(tabEventPath(tab.id, i), $event)"
|
|
2685
3410
|
></ng-container>
|
|
2686
3411
|
</ng-container>
|
|
2687
3412
|
</ng-container>
|
|
@@ -2690,9 +3415,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2690
3415
|
<praxis-empty-state-card
|
|
2691
3416
|
[inline]="true"
|
|
2692
3417
|
icon="dashboard_customize"
|
|
2693
|
-
[title]="'Sem
|
|
2694
|
-
[description]="'Adicione
|
|
2695
|
-
[primaryAction]="{ label: 'Abrir editor', icon: 'tune', action: openEditor.bind(this) }"
|
|
3418
|
+
[title]="t('emptyState.tabTitle', 'Sem conteudo nesta aba')"
|
|
3419
|
+
[description]="t('emptyState.tabDescription', 'Adicione conteudo ou use o editor para configurar.')"
|
|
3420
|
+
[primaryAction]="{ label: t('emptyState.openEditor', 'Abrir editor'), icon: 'tune', action: openEditor.bind(this) }"
|
|
2696
3421
|
></praxis-empty-state-card>
|
|
2697
3422
|
</ng-template>
|
|
2698
3423
|
</ng-template>
|
|
@@ -2706,7 +3431,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2706
3431
|
*ngIf="enableCustomization"
|
|
2707
3432
|
mat-fab
|
|
2708
3433
|
class="edit-fab"
|
|
2709
|
-
aria-label="Editar
|
|
3434
|
+
[attr.aria-label]="t('chrome.editTabs', 'Editar abas')"
|
|
2710
3435
|
(click)="openEditor()"
|
|
2711
3436
|
>
|
|
2712
3437
|
<mat-icon fontIcon="edit"></mat-icon>
|
|
@@ -2715,9 +3440,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2715
3440
|
*ngIf="enableCustomization && tabsId"
|
|
2716
3441
|
mat-mini-fab
|
|
2717
3442
|
class="edit-fab edit-fab-secondary"
|
|
2718
|
-
aria-label="Redefinir
|
|
3443
|
+
[attr.aria-label]="t('settings.resetPreferences', 'Redefinir preferencias de abas')"
|
|
2719
3444
|
(click)="resetPreferences()"
|
|
2720
|
-
matTooltip="Redefinir
|
|
3445
|
+
[matTooltip]="t('settings.resetPreferences', 'Redefinir preferencias de abas')"
|
|
2721
3446
|
>
|
|
2722
3447
|
<mat-icon [praxisIcon]="'restart_alt'"></mat-icon>
|
|
2723
3448
|
</button>
|
|
@@ -2752,6 +3477,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2752
3477
|
type: Output
|
|
2753
3478
|
}] } });
|
|
2754
3479
|
|
|
3480
|
+
const PRAXIS_TABS_PORTS = [
|
|
3481
|
+
{
|
|
3482
|
+
id: 'context',
|
|
3483
|
+
label: 'Contexto',
|
|
3484
|
+
direction: 'input',
|
|
3485
|
+
semanticKind: 'view-context',
|
|
3486
|
+
schema: {
|
|
3487
|
+
id: 'Record<string, unknown>',
|
|
3488
|
+
kind: 'ts-type',
|
|
3489
|
+
ref: 'Record<string, unknown>',
|
|
3490
|
+
},
|
|
3491
|
+
description: 'Contexto de visualizacao entregue ao container e aos widgets internos.',
|
|
3492
|
+
exposure: { public: true, group: 'context' },
|
|
3493
|
+
},
|
|
3494
|
+
{
|
|
3495
|
+
id: 'config',
|
|
3496
|
+
label: 'Configuracao',
|
|
3497
|
+
direction: 'input',
|
|
3498
|
+
semanticKind: 'config-fragment',
|
|
3499
|
+
schema: {
|
|
3500
|
+
id: 'TabsMetadata',
|
|
3501
|
+
kind: 'ts-type',
|
|
3502
|
+
ref: 'TabsMetadata',
|
|
3503
|
+
},
|
|
3504
|
+
description: 'Fragmento canonico de configuracao das tabs/nav e dos widgets internos.',
|
|
3505
|
+
exposure: { public: true, group: 'config' },
|
|
3506
|
+
},
|
|
3507
|
+
{
|
|
3508
|
+
id: 'selectedIndexChange',
|
|
3509
|
+
label: 'Troca de indice selecionado',
|
|
3510
|
+
direction: 'output',
|
|
3511
|
+
semanticKind: 'event',
|
|
3512
|
+
schema: {
|
|
3513
|
+
id: 'number',
|
|
3514
|
+
kind: 'ts-type',
|
|
3515
|
+
ref: 'number',
|
|
3516
|
+
},
|
|
3517
|
+
cardinality: 'stream',
|
|
3518
|
+
description: 'Evento canonico emitido quando a selecao de aba muda.',
|
|
3519
|
+
exposure: { public: true, group: 'events' },
|
|
3520
|
+
},
|
|
3521
|
+
{
|
|
3522
|
+
id: 'widgetEvent',
|
|
3523
|
+
label: 'Evento interno de widget',
|
|
3524
|
+
direction: 'output',
|
|
3525
|
+
semanticKind: 'event',
|
|
3526
|
+
schema: {
|
|
3527
|
+
id: 'WidgetEventEnvelope',
|
|
3528
|
+
kind: 'ts-type',
|
|
3529
|
+
ref: 'WidgetEventEnvelope',
|
|
3530
|
+
},
|
|
3531
|
+
cardinality: 'stream',
|
|
3532
|
+
description: 'Bridge composta temporaria para eventos internos de widgets. Nao representa o contrato final de nested ports.',
|
|
3533
|
+
exposure: { public: true, advanced: true, group: 'composite' },
|
|
3534
|
+
},
|
|
3535
|
+
];
|
|
2755
3536
|
const PRAXIS_TABS_COMPONENT_METADATA = {
|
|
2756
3537
|
id: 'praxis-tabs',
|
|
2757
3538
|
selector: 'praxis-tabs',
|
|
@@ -2802,9 +3583,9 @@ const PRAXIS_TABS_COMPONENT_METADATA = {
|
|
|
2802
3583
|
{ name: 'selectFocusedIndex', type: 'number', label: 'Selecionar foco' },
|
|
2803
3584
|
{
|
|
2804
3585
|
name: 'widgetEvent',
|
|
2805
|
-
type:
|
|
3586
|
+
type: 'WidgetEventEnvelope',
|
|
2806
3587
|
label: 'Evento interno',
|
|
2807
|
-
description: 'Eventos reemitidos de componentes dinâmicos dentro da aba/link',
|
|
3588
|
+
description: 'Eventos reemitidos de componentes dinâmicos dentro da aba/link, enriquecidos com contexto hierárquico em `path`.',
|
|
2808
3589
|
},
|
|
2809
3590
|
],
|
|
2810
3591
|
actions: [
|
|
@@ -2881,6 +3662,7 @@ const PRAXIS_TABS_COMPONENT_METADATA = {
|
|
|
2881
3662
|
],
|
|
2882
3663
|
tags: ['widget', 'tabs', 'configurable', 'stable'],
|
|
2883
3664
|
lib: '@praxisui/tabs',
|
|
3665
|
+
ports: PRAXIS_TABS_PORTS,
|
|
2884
3666
|
};
|
|
2885
3667
|
function providePraxisTabsMetadata() {
|
|
2886
3668
|
return {
|
|
@@ -2901,5 +3683,5 @@ function providePraxisTabsMetadata() {
|
|
|
2901
3683
|
* Generated bundle index. Do not edit.
|
|
2902
3684
|
*/
|
|
2903
3685
|
|
|
2904
|
-
export { PRAXIS_TABS_COMPONENT_METADATA, PraxisTabs, PraxisTabsConfigEditor, TABS_AI_CAPABILITIES, providePraxisTabsMetadata };
|
|
3686
|
+
export { PRAXIS_TABS_COMPONENT_METADATA, PRAXIS_TABS_I18N_CONFIG, PRAXIS_TABS_I18N_NAMESPACE, PraxisTabs, PraxisTabsConfigEditor, TABS_AI_CAPABILITIES, buildTabsApplyPlan, createPraxisTabsI18nConfig, createTabsAuthoringDocument, normalizeTabsAuthoringDocument, providePraxisTabsI18n, providePraxisTabsMetadata, serializeTabsAuthoringDocument, toCanonicalTabsConfig, validateTabsAuthoringDocument };
|
|
2905
3687
|
//# sourceMappingURL=praxisui-tabs.mjs.map
|