@praxisui/page-builder 9.0.23 → 9.0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -1
- package/ai/component-registry.json +2 -2
- package/fesm2022/praxisui-page-builder.mjs +2195 -2071
- package/package.json +4 -4
- package/types/praxisui-page-builder.d.ts +19 -3
|
@@ -7,7 +7,7 @@ import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
|
|
7
7
|
import * as i2$1 from '@angular/material/icon';
|
|
8
8
|
import { MatIconModule } from '@angular/material/icon';
|
|
9
9
|
import * as i2$2 from '@praxisui/core';
|
|
10
|
-
import { PraxisIconDirective, BUILTIN_SHELL_PRESETS, PraxisIconButtonComponent,
|
|
10
|
+
import { PraxisIconDirective, providePraxisI18n, BUILTIN_SHELL_PRESETS, PraxisIconButtonComponent, PraxisI18nService, GLOBAL_ACTION_CATALOG, getGlobalActionCatalog, PRAXIS_GLOBAL_ACTION_CATALOG, SurfaceOpenActionEditorComponent, BUILTIN_PAGE_LAYOUT_PRESETS, BUILTIN_PAGE_THEME_PRESETS, SETTINGS_PANEL_DATA as SETTINGS_PANEL_DATA$1, NestedWidgetConfigAccessor, deepMerge, generateId, ComponentMetadataRegistry, ObservabilityDashboardService, PraxisRuntimeComponentObservationRegistryService, domainKnowledgeTimelineToRichContentDocument, DomainRuleService, DomainKnowledgeService, SETTINGS_PANEL_BRIDGE, DynamicWidgetPageComponent, DYNAMIC_PAGE_SHELL_EDITOR } from '@praxisui/core';
|
|
11
11
|
import * as i3 from '@angular/material/tooltip';
|
|
12
12
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
13
13
|
import * as i3$1 from '@angular/material/form-field';
|
|
@@ -184,6 +184,11 @@ class FloatingToolbarComponent {
|
|
|
184
184
|
previewActive = false;
|
|
185
185
|
connectionMode = false;
|
|
186
186
|
modeLabel = '';
|
|
187
|
+
addLabel = 'Insert component';
|
|
188
|
+
saveLabel = 'Save page';
|
|
189
|
+
undoLabel = 'Undo';
|
|
190
|
+
redoLabel = 'Redo';
|
|
191
|
+
settingsLabel = 'Page settings';
|
|
187
192
|
previewLabel = 'Pre-visualizar';
|
|
188
193
|
exitPreviewLabel = 'Voltar para edicao';
|
|
189
194
|
add = new EventEmitter();
|
|
@@ -193,7 +198,7 @@ class FloatingToolbarComponent {
|
|
|
193
198
|
preview = new EventEmitter();
|
|
194
199
|
save = new EventEmitter();
|
|
195
200
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: FloatingToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
196
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: FloatingToolbarComponent, isStandalone: true, selector: "praxis-floating-toolbar", inputs: { visible: "visible", canUndo: "canUndo", canRedo: "canRedo", showSave: "showSave", showPreview: "showPreview", editingEnabled: "editingEnabled", previewActive: "previewActive", connectionMode: "connectionMode", modeLabel: "modeLabel", previewLabel: "previewLabel", exitPreviewLabel: "exitPreviewLabel" }, outputs: { add: "add", undo: "undo", redo: "redo", settings: "settings", preview: "preview", save: "save" }, ngImport: i0, template: `
|
|
201
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: FloatingToolbarComponent, isStandalone: true, selector: "praxis-floating-toolbar", inputs: { visible: "visible", canUndo: "canUndo", canRedo: "canRedo", showSave: "showSave", showPreview: "showPreview", editingEnabled: "editingEnabled", previewActive: "previewActive", connectionMode: "connectionMode", modeLabel: "modeLabel", addLabel: "addLabel", saveLabel: "saveLabel", undoLabel: "undoLabel", redoLabel: "redoLabel", settingsLabel: "settingsLabel", previewLabel: "previewLabel", exitPreviewLabel: "exitPreviewLabel" }, outputs: { add: "add", undo: "undo", redo: "redo", settings: "settings", preview: "preview", save: "save" }, ngImport: i0, template: `
|
|
197
202
|
@if (visible) {
|
|
198
203
|
<div
|
|
199
204
|
class="pdx-floating-toolbar"
|
|
@@ -204,25 +209,25 @@ class FloatingToolbarComponent {
|
|
|
204
209
|
<span class="pdx-mode-chip" [attr.data-testid]="'page-builder-toolbar-mode'">{{ modeLabel }}</span>
|
|
205
210
|
}
|
|
206
211
|
<div class="pdx-actions">
|
|
207
|
-
<button mat-mini-fab color="primary" (click)="add.emit()" [disabled]="!editingEnabled" [matTooltip]="
|
|
212
|
+
<button mat-mini-fab color="primary" (click)="add.emit()" [disabled]="!editingEnabled" [matTooltip]="addLabel" [attr.aria-label]="addLabel">
|
|
208
213
|
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
209
214
|
</button>
|
|
210
215
|
@if (showSave) {
|
|
211
|
-
<button mat-mini-fab color="accent" (click)="save.emit()" [disabled]="!editingEnabled" [matTooltip]="
|
|
216
|
+
<button mat-mini-fab color="accent" (click)="save.emit()" [disabled]="!editingEnabled" [matTooltip]="saveLabel" [attr.aria-label]="saveLabel">
|
|
212
217
|
<mat-icon [praxisIcon]="'save'"></mat-icon>
|
|
213
218
|
</button>
|
|
214
219
|
}
|
|
215
220
|
@if (canUndo) {
|
|
216
|
-
<button mat-mini-fab (click)="undo.emit()" [disabled]="!editingEnabled" [matTooltip]="
|
|
221
|
+
<button mat-mini-fab (click)="undo.emit()" [disabled]="!editingEnabled" [matTooltip]="undoLabel" [attr.aria-label]="undoLabel">
|
|
217
222
|
<mat-icon [praxisIcon]="'undo'"></mat-icon>
|
|
218
223
|
</button>
|
|
219
224
|
}
|
|
220
225
|
@if (canRedo) {
|
|
221
|
-
<button mat-mini-fab (click)="redo.emit()" [disabled]="!editingEnabled" [matTooltip]="
|
|
226
|
+
<button mat-mini-fab (click)="redo.emit()" [disabled]="!editingEnabled" [matTooltip]="redoLabel" [attr.aria-label]="redoLabel">
|
|
222
227
|
<mat-icon [praxisIcon]="'redo'"></mat-icon>
|
|
223
228
|
</button>
|
|
224
229
|
}
|
|
225
|
-
<button mat-mini-fab (click)="settings.emit()" [disabled]="!editingEnabled" [matTooltip]="
|
|
230
|
+
<button mat-mini-fab (click)="settings.emit()" [disabled]="!editingEnabled" [matTooltip]="settingsLabel" [attr.aria-label]="settingsLabel">
|
|
226
231
|
<mat-icon [praxisIcon]="'settings'"></mat-icon>
|
|
227
232
|
</button>
|
|
228
233
|
@if (showPreview) {
|
|
@@ -256,25 +261,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
256
261
|
<span class="pdx-mode-chip" [attr.data-testid]="'page-builder-toolbar-mode'">{{ modeLabel }}</span>
|
|
257
262
|
}
|
|
258
263
|
<div class="pdx-actions">
|
|
259
|
-
<button mat-mini-fab color="primary" (click)="add.emit()" [disabled]="!editingEnabled" [matTooltip]="
|
|
264
|
+
<button mat-mini-fab color="primary" (click)="add.emit()" [disabled]="!editingEnabled" [matTooltip]="addLabel" [attr.aria-label]="addLabel">
|
|
260
265
|
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
261
266
|
</button>
|
|
262
267
|
@if (showSave) {
|
|
263
|
-
<button mat-mini-fab color="accent" (click)="save.emit()" [disabled]="!editingEnabled" [matTooltip]="
|
|
268
|
+
<button mat-mini-fab color="accent" (click)="save.emit()" [disabled]="!editingEnabled" [matTooltip]="saveLabel" [attr.aria-label]="saveLabel">
|
|
264
269
|
<mat-icon [praxisIcon]="'save'"></mat-icon>
|
|
265
270
|
</button>
|
|
266
271
|
}
|
|
267
272
|
@if (canUndo) {
|
|
268
|
-
<button mat-mini-fab (click)="undo.emit()" [disabled]="!editingEnabled" [matTooltip]="
|
|
273
|
+
<button mat-mini-fab (click)="undo.emit()" [disabled]="!editingEnabled" [matTooltip]="undoLabel" [attr.aria-label]="undoLabel">
|
|
269
274
|
<mat-icon [praxisIcon]="'undo'"></mat-icon>
|
|
270
275
|
</button>
|
|
271
276
|
}
|
|
272
277
|
@if (canRedo) {
|
|
273
|
-
<button mat-mini-fab (click)="redo.emit()" [disabled]="!editingEnabled" [matTooltip]="
|
|
278
|
+
<button mat-mini-fab (click)="redo.emit()" [disabled]="!editingEnabled" [matTooltip]="redoLabel" [attr.aria-label]="redoLabel">
|
|
274
279
|
<mat-icon [praxisIcon]="'redo'"></mat-icon>
|
|
275
280
|
</button>
|
|
276
281
|
}
|
|
277
|
-
<button mat-mini-fab (click)="settings.emit()" [disabled]="!editingEnabled" [matTooltip]="
|
|
282
|
+
<button mat-mini-fab (click)="settings.emit()" [disabled]="!editingEnabled" [matTooltip]="settingsLabel" [attr.aria-label]="settingsLabel">
|
|
278
283
|
<mat-icon [praxisIcon]="'settings'"></mat-icon>
|
|
279
284
|
</button>
|
|
280
285
|
@if (showPreview) {
|
|
@@ -312,6 +317,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
312
317
|
type: Input
|
|
313
318
|
}], modeLabel: [{
|
|
314
319
|
type: Input
|
|
320
|
+
}], addLabel: [{
|
|
321
|
+
type: Input
|
|
322
|
+
}], saveLabel: [{
|
|
323
|
+
type: Input
|
|
324
|
+
}], undoLabel: [{
|
|
325
|
+
type: Input
|
|
326
|
+
}], redoLabel: [{
|
|
327
|
+
type: Input
|
|
328
|
+
}], settingsLabel: [{
|
|
329
|
+
type: Input
|
|
315
330
|
}], previewLabel: [{
|
|
316
331
|
type: Input
|
|
317
332
|
}], exitPreviewLabel: [{
|
|
@@ -330,2032 +345,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
330
345
|
type: Output
|
|
331
346
|
}] } });
|
|
332
347
|
|
|
333
|
-
class ComponentPaletteDialogComponent {
|
|
334
|
-
dialogRef;
|
|
335
|
-
registry;
|
|
336
|
-
data;
|
|
337
|
-
query = signal('', ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
|
|
338
|
-
all = signal([], ...(ngDevMode ? [{ debugName: "all" }] : /* istanbul ignore next */ []));
|
|
339
|
-
filtered = computed(() => this.applyFilters(), ...(ngDevMode ? [{ debugName: "filtered" }] : /* istanbul ignore next */ []));
|
|
340
|
-
density = computed(() => {
|
|
341
|
-
const n = this.filtered().length;
|
|
342
|
-
if (n <= 4)
|
|
343
|
-
return 'roomy';
|
|
344
|
-
if (n > 12)
|
|
345
|
-
return 'dense';
|
|
346
|
-
return 'normal';
|
|
347
|
-
}, ...(ngDevMode ? [{ debugName: "density" }] : /* istanbul ignore next */ []));
|
|
348
|
-
constructor(dialogRef, registry, data) {
|
|
349
|
-
this.dialogRef = dialogRef;
|
|
350
|
-
this.registry = registry;
|
|
351
|
-
this.data = data;
|
|
352
|
-
}
|
|
353
|
-
ngOnInit() {
|
|
354
|
-
this.all.set(this.buildEntries(this.registry.getAll()));
|
|
355
|
-
}
|
|
356
|
-
select(entry) {
|
|
357
|
-
this.dialogRef.close({
|
|
358
|
-
componentId: entry.componentId,
|
|
359
|
-
...(entry.presetId ? { presetId: entry.presetId } : {}),
|
|
360
|
-
...(entry.inputs ? { inputs: entry.inputs } : {}),
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
trackById = (_, entry) => entry.key;
|
|
364
|
-
getPreview(entry) {
|
|
365
|
-
return entry.description;
|
|
366
|
-
}
|
|
367
|
-
// Create effect in injection context (field initializer is allowed)
|
|
368
|
-
_adjustSizeEffect = effect(() => {
|
|
369
|
-
const n = this.filtered().length;
|
|
370
|
-
let width = '720px';
|
|
371
|
-
if (n <= 4)
|
|
372
|
-
width = '560px';
|
|
373
|
-
else if (n <= 8)
|
|
374
|
-
width = '680px';
|
|
375
|
-
const container = this.dialogRef._containerInstance;
|
|
376
|
-
if (container && container._config) {
|
|
377
|
-
container._config.width = width;
|
|
378
|
-
}
|
|
379
|
-
}, ...(ngDevMode ? [{ debugName: "_adjustSizeEffect" }] : /* istanbul ignore next */ []));
|
|
380
|
-
applyFilters() {
|
|
381
|
-
const list = (this.all() || []);
|
|
382
|
-
const q = (this.query() || '').toLowerCase();
|
|
383
|
-
const allowIds = new Set((this.data?.allowedWidgetIds || []).map((s) => s.toLowerCase()));
|
|
384
|
-
const allowTags = new Set((this.data?.allowedWidgetTags || []).map((s) => s.toLowerCase()));
|
|
385
|
-
const allowPresets = new Set((this.data?.allowedPresetIds || []).map((s) => s.toLowerCase()));
|
|
386
|
-
const metadataById = new Map(this.registry.getAll().map((meta) => [meta.id, meta]));
|
|
387
|
-
return list.filter((entry) => {
|
|
388
|
-
const meta = metadataById.get(entry.componentId);
|
|
389
|
-
if (!meta)
|
|
390
|
-
return false;
|
|
391
|
-
if (q && !entry.searchText.includes(q)) {
|
|
392
|
-
return false;
|
|
393
|
-
}
|
|
394
|
-
if (allowIds.size > 0 && !allowIds.has((meta.id || '').toLowerCase()))
|
|
395
|
-
return false;
|
|
396
|
-
if (allowTags.size > 0 && !meta.tags?.some(t => allowTags.has(t.toLowerCase())))
|
|
397
|
-
return false;
|
|
398
|
-
if (entry.presetId && allowPresets.size > 0 && !allowPresets.has(entry.presetId.toLowerCase()))
|
|
399
|
-
return false;
|
|
400
|
-
if (typeof this.data?.predicate === 'function' && !this.data.predicate(meta))
|
|
401
|
-
return false;
|
|
402
|
-
return true;
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
buildEntries(metadata) {
|
|
406
|
-
return metadata.flatMap((meta) => {
|
|
407
|
-
const baseEntry = {
|
|
408
|
-
key: meta.id,
|
|
409
|
-
componentId: meta.id,
|
|
410
|
-
title: meta.friendlyName || meta.id,
|
|
411
|
-
description: meta.description || meta.selector,
|
|
412
|
-
icon: meta.icon || 'widgets',
|
|
413
|
-
badges: this.buildBadges(meta, false),
|
|
414
|
-
searchText: `${meta.id} ${meta.friendlyName || ''} ${meta.description || ''} ${meta.selector || ''} ${this.buildBadgeSearchText(meta, false)}`.toLowerCase(),
|
|
415
|
-
};
|
|
416
|
-
const presets = (meta.insertionPresets ?? []).map((preset) => ({
|
|
417
|
-
key: `${meta.id}::${preset.id}`,
|
|
418
|
-
componentId: meta.id,
|
|
419
|
-
presetId: preset.id,
|
|
420
|
-
title: `${meta.friendlyName || meta.id} · ${preset.label}`,
|
|
421
|
-
description: preset.description || meta.description || meta.selector,
|
|
422
|
-
icon: preset.icon || meta.icon || 'widgets',
|
|
423
|
-
badges: this.buildBadges(meta, true),
|
|
424
|
-
searchText: `${meta.id} ${meta.friendlyName || ''} ${preset.label} ${preset.description || ''} ${meta.description || ''} ${this.buildBadgeSearchText(meta, true)}`.toLowerCase(),
|
|
425
|
-
inputs: preset.inputs ? JSON.parse(JSON.stringify(preset.inputs)) : undefined,
|
|
426
|
-
}));
|
|
427
|
-
return [baseEntry, ...presets];
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
buildBadges(meta, isPreset) {
|
|
431
|
-
const badges = [];
|
|
432
|
-
const tags = new Set((meta.tags ?? []).map((tag) => tag.toLowerCase()));
|
|
433
|
-
if (meta.configEditor?.component) {
|
|
434
|
-
badges.push({
|
|
435
|
-
label: 'Config editor',
|
|
436
|
-
icon: 'tune',
|
|
437
|
-
tone: 'ready',
|
|
438
|
-
description: 'This component publishes a canonical settings-panel editor for its input contract.',
|
|
439
|
-
});
|
|
440
|
-
}
|
|
441
|
-
if (meta.authoringManifestRef?.componentId) {
|
|
442
|
-
badges.push({
|
|
443
|
-
label: 'AI authoring',
|
|
444
|
-
icon: 'auto_awesome',
|
|
445
|
-
tone: 'ready',
|
|
446
|
-
description: 'This component owner publishes a canonical AI authoring manifest for governed changes.',
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
if (meta.ports?.length || meta.actions?.length || meta.commands?.length) {
|
|
450
|
-
badges.push({
|
|
451
|
-
label: 'Governed',
|
|
452
|
-
icon: 'account_tree',
|
|
453
|
-
tone: 'ready',
|
|
454
|
-
description: 'This component exposes semantic ports, actions, or commands for governed composition.',
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
if (isPreset) {
|
|
458
|
-
badges.push({
|
|
459
|
-
label: 'Preset',
|
|
460
|
-
icon: 'auto_awesome_motion',
|
|
461
|
-
tone: 'info',
|
|
462
|
-
description: 'This entry inserts a curated preset without changing the component contract.',
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
if (this.hasDataSourceInputs(meta) || tags.has('data') || tags.has('analytics')) {
|
|
466
|
-
badges.push({
|
|
467
|
-
label: 'Data source',
|
|
468
|
-
icon: 'database',
|
|
469
|
-
tone: 'info',
|
|
470
|
-
description: 'This component commonly needs schema, API, resource, or dataset context.',
|
|
471
|
-
});
|
|
472
|
-
}
|
|
473
|
-
if (tags.has('deprecated') || tags.has('legacy') || /legacy|legado|deprecated/i.test(meta.description || '')) {
|
|
474
|
-
badges.push({
|
|
475
|
-
label: 'Legacy',
|
|
476
|
-
icon: 'history',
|
|
477
|
-
tone: 'warning',
|
|
478
|
-
description: 'This entry is retained for compatibility and should not be the default for new canonical authoring.',
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
if (tags.has('demo') || tags.has('host') || /host-only|host|demo/i.test(`${meta.friendlyName} ${meta.description || ''}`)) {
|
|
482
|
-
badges.push({
|
|
483
|
-
label: 'Host/demo',
|
|
484
|
-
icon: 'science',
|
|
485
|
-
tone: 'neutral',
|
|
486
|
-
description: 'This entry depends on host/demo semantics and may need governance before public reuse.',
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
return badges;
|
|
490
|
-
}
|
|
491
|
-
buildBadgeSearchText(meta, isPreset) {
|
|
492
|
-
return this.buildBadges(meta, isPreset)
|
|
493
|
-
.map((badge) => `${badge.label} ${badge.description}`)
|
|
494
|
-
.join(' ');
|
|
495
|
-
}
|
|
496
|
-
hasDataSourceInputs(meta) {
|
|
497
|
-
return (meta.inputs ?? []).some((input) => /resource|schema|api|data(source)?|endpoint|resolver/i.test(input.name));
|
|
498
|
-
}
|
|
499
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ComponentPaletteDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: i2$2.ComponentMetadataRegistry }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
500
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ComponentPaletteDialogComponent, isStandalone: true, selector: "praxis-component-palette-dialog", ngImport: i0, template: `
|
|
501
|
-
<h2 mat-dialog-title>
|
|
502
|
-
<div class="dlg-title">
|
|
503
|
-
<mat-icon class="dlg-icon" [praxisIcon]="'widgets'"></mat-icon>
|
|
504
|
-
<div class="dlg-texts">
|
|
505
|
-
<div class="dlg-head">{{ data?.title || 'Inserir componente' }}</div>
|
|
506
|
-
<div class="dlg-sub">Escolha um componente para adicionar à página · {{ filtered().length }} disponíveis</div>
|
|
507
|
-
</div>
|
|
508
|
-
</div>
|
|
509
|
-
</h2>
|
|
510
|
-
<div mat-dialog-content class="pdx-palette-content">
|
|
511
|
-
<mat-form-field class="pdx-palette-search" appearance="outline">
|
|
512
|
-
<mat-label>Buscar componente</mat-label>
|
|
513
|
-
<mat-icon matPrefix [praxisIcon]="'search'"></mat-icon>
|
|
514
|
-
<input
|
|
515
|
-
matInput
|
|
516
|
-
type="search"
|
|
517
|
-
[ngModel]="query()"
|
|
518
|
-
(ngModelChange)="query.set($event)"
|
|
519
|
-
placeholder="Nome, capability ou readiness"
|
|
520
|
-
data-testid="component-palette-search"
|
|
521
|
-
/>
|
|
522
|
-
</mat-form-field>
|
|
523
|
-
@if (filtered().length) {
|
|
524
|
-
<div [class]="'pdx-grid ' + density()">
|
|
525
|
-
@for (entry of filtered(); track trackById($index, entry)) {
|
|
526
|
-
<button
|
|
527
|
-
class="pdx-card mat-elevation-z2"
|
|
528
|
-
type="button"
|
|
529
|
-
[attr.aria-label]="'Adicionar ' + entry.title"
|
|
530
|
-
(click)="select(entry)"
|
|
531
|
-
>
|
|
532
|
-
<div class="pdx-card-icon">
|
|
533
|
-
<mat-icon [praxisIcon]="entry.icon"></mat-icon>
|
|
534
|
-
</div>
|
|
535
|
-
<div class="pdx-card-body">
|
|
536
|
-
<div class="pdx-card-title">{{ entry.title }}</div>
|
|
537
|
-
<div class="pdx-card-desc">{{ entry.description }}</div>
|
|
538
|
-
@if (entry.badges.length) {
|
|
539
|
-
<div class="pdx-card-badges">
|
|
540
|
-
@for (badge of entry.badges; track badge) {
|
|
541
|
-
<span
|
|
542
|
-
class="pdx-card-badge"
|
|
543
|
-
[class]="'pdx-card-badge ' + badge.tone"
|
|
544
|
-
[title]="badge.description"
|
|
545
|
-
>
|
|
546
|
-
<mat-icon [praxisIcon]="badge.icon" aria-hidden="true"></mat-icon>
|
|
547
|
-
{{ badge.label }}
|
|
548
|
-
</span>
|
|
549
|
-
}
|
|
550
|
-
</div>
|
|
551
|
-
}
|
|
552
|
-
</div>
|
|
553
|
-
</button>
|
|
554
|
-
}
|
|
555
|
-
</div>
|
|
556
|
-
} @else {
|
|
557
|
-
<div class="pdx-empty">
|
|
558
|
-
<mat-icon [praxisIcon]="'sentiment_dissatisfied'"></mat-icon>
|
|
559
|
-
<div>Nenhum componente disponível</div>
|
|
560
|
-
</div>
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
</div>
|
|
564
|
-
<div mat-dialog-actions align="end">
|
|
565
|
-
<button mat-stroked-button color="primary" mat-dialog-close>Cancelar</button>
|
|
566
|
-
</div>
|
|
567
|
-
`, isInline: true, styles: [":host{display:block}h2[mat-dialog-title]{margin:0;padding:12px 24px 10px;border-bottom:1px solid var(--md-sys-color-outline-variant)}.dlg-title{display:flex;align-items:center;gap:10px}.dlg-icon{color:var(--md-sys-color-primary)}.dlg-head{font-size:18px;font-weight:600;line-height:1.2}.dlg-sub{font-size:12px;opacity:.85;color:var(--md-sys-color-on-surface-variant)}.pdx-palette-content{min-width:480px;max-width:920px;padding-top:8px}.pdx-palette-search{width:100%;margin-bottom:12px}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}.pdx-grid.dense{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-grid.roomy{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}.pdx-card{appearance:none;position:relative;display:grid;grid-template-columns:44px 1fr;grid-template-rows:auto auto;gap:10px;padding:14px;border:1px solid transparent;border-radius:14px;cursor:pointer;outline:none;color:inherit;font:inherit;min-height:92px;text-align:left;background:var(--md-sys-color-surface);border-color:var(--md-sys-color-outline-variant);transition:box-shadow .2s ease,background .25s ease,transform .06s ease}.pdx-grid.dense .pdx-card{padding:10px;border-radius:12px;min-height:84px}.pdx-grid.roomy .pdx-card{padding:16px;border-radius:16px;min-height:100px}.pdx-card:focus,.pdx-card:hover{box-shadow:var(--mat-elevation-level4);background:var(--md-sys-color-surface-container-low);border-color:var(--md-sys-color-primary)}.pdx-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-card:active{transform:translateY(1px)}.pdx-card-icon{grid-row:span 2;display:flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary)}.pdx-card-title{font-weight:600;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-card-desc{color:var(--md-sys-color-on-surface-variant);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.pdx-card-badges{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.pdx-card-badge{display:inline-flex;align-items:center;gap:4px;min-height:22px;padding:2px 8px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-highest);font-size:11px;line-height:1.2;font-weight:600;letter-spacing:.01em}.pdx-card-badge mat-icon{width:14px;height:14px;font-size:14px}.pdx-card-badge.ready{color:var(--md-sys-color-primary);border-color:color-mix(in srgb,var(--md-sys-color-primary) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary-container) 72%,transparent)}.pdx-card-badge.info{color:var(--md-sys-color-tertiary);border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 38%,transparent);background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 68%,transparent)}.pdx-card-badge.warning{color:var(--md-sys-color-error);border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container) 62%,transparent)}.pdx-empty{padding:24px;display:grid;place-items:center;color:var(--md-sys-color-on-surface-variant);gap:8px}@media(max-width:600px){.pdx-palette-content{min-width:320px}.pdx-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.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: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
568
|
-
}
|
|
569
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ComponentPaletteDialogComponent, decorators: [{
|
|
570
|
-
type: Component,
|
|
571
|
-
args: [{ selector: 'praxis-component-palette-dialog', standalone: true, imports: [FormsModule, MatDialogModule, MatFormFieldModule, MatInputModule, MatIconModule, MatButtonModule, PraxisIconDirective], template: `
|
|
572
|
-
<h2 mat-dialog-title>
|
|
573
|
-
<div class="dlg-title">
|
|
574
|
-
<mat-icon class="dlg-icon" [praxisIcon]="'widgets'"></mat-icon>
|
|
575
|
-
<div class="dlg-texts">
|
|
576
|
-
<div class="dlg-head">{{ data?.title || 'Inserir componente' }}</div>
|
|
577
|
-
<div class="dlg-sub">Escolha um componente para adicionar à página · {{ filtered().length }} disponíveis</div>
|
|
578
|
-
</div>
|
|
579
|
-
</div>
|
|
580
|
-
</h2>
|
|
581
|
-
<div mat-dialog-content class="pdx-palette-content">
|
|
582
|
-
<mat-form-field class="pdx-palette-search" appearance="outline">
|
|
583
|
-
<mat-label>Buscar componente</mat-label>
|
|
584
|
-
<mat-icon matPrefix [praxisIcon]="'search'"></mat-icon>
|
|
585
|
-
<input
|
|
586
|
-
matInput
|
|
587
|
-
type="search"
|
|
588
|
-
[ngModel]="query()"
|
|
589
|
-
(ngModelChange)="query.set($event)"
|
|
590
|
-
placeholder="Nome, capability ou readiness"
|
|
591
|
-
data-testid="component-palette-search"
|
|
592
|
-
/>
|
|
593
|
-
</mat-form-field>
|
|
594
|
-
@if (filtered().length) {
|
|
595
|
-
<div [class]="'pdx-grid ' + density()">
|
|
596
|
-
@for (entry of filtered(); track trackById($index, entry)) {
|
|
597
|
-
<button
|
|
598
|
-
class="pdx-card mat-elevation-z2"
|
|
599
|
-
type="button"
|
|
600
|
-
[attr.aria-label]="'Adicionar ' + entry.title"
|
|
601
|
-
(click)="select(entry)"
|
|
602
|
-
>
|
|
603
|
-
<div class="pdx-card-icon">
|
|
604
|
-
<mat-icon [praxisIcon]="entry.icon"></mat-icon>
|
|
605
|
-
</div>
|
|
606
|
-
<div class="pdx-card-body">
|
|
607
|
-
<div class="pdx-card-title">{{ entry.title }}</div>
|
|
608
|
-
<div class="pdx-card-desc">{{ entry.description }}</div>
|
|
609
|
-
@if (entry.badges.length) {
|
|
610
|
-
<div class="pdx-card-badges">
|
|
611
|
-
@for (badge of entry.badges; track badge) {
|
|
612
|
-
<span
|
|
613
|
-
class="pdx-card-badge"
|
|
614
|
-
[class]="'pdx-card-badge ' + badge.tone"
|
|
615
|
-
[title]="badge.description"
|
|
616
|
-
>
|
|
617
|
-
<mat-icon [praxisIcon]="badge.icon" aria-hidden="true"></mat-icon>
|
|
618
|
-
{{ badge.label }}
|
|
619
|
-
</span>
|
|
620
|
-
}
|
|
621
|
-
</div>
|
|
622
|
-
}
|
|
623
|
-
</div>
|
|
624
|
-
</button>
|
|
625
|
-
}
|
|
626
|
-
</div>
|
|
627
|
-
} @else {
|
|
628
|
-
<div class="pdx-empty">
|
|
629
|
-
<mat-icon [praxisIcon]="'sentiment_dissatisfied'"></mat-icon>
|
|
630
|
-
<div>Nenhum componente disponível</div>
|
|
631
|
-
</div>
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
</div>
|
|
635
|
-
<div mat-dialog-actions align="end">
|
|
636
|
-
<button mat-stroked-button color="primary" mat-dialog-close>Cancelar</button>
|
|
637
|
-
</div>
|
|
638
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}h2[mat-dialog-title]{margin:0;padding:12px 24px 10px;border-bottom:1px solid var(--md-sys-color-outline-variant)}.dlg-title{display:flex;align-items:center;gap:10px}.dlg-icon{color:var(--md-sys-color-primary)}.dlg-head{font-size:18px;font-weight:600;line-height:1.2}.dlg-sub{font-size:12px;opacity:.85;color:var(--md-sys-color-on-surface-variant)}.pdx-palette-content{min-width:480px;max-width:920px;padding-top:8px}.pdx-palette-search{width:100%;margin-bottom:12px}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}.pdx-grid.dense{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-grid.roomy{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}.pdx-card{appearance:none;position:relative;display:grid;grid-template-columns:44px 1fr;grid-template-rows:auto auto;gap:10px;padding:14px;border:1px solid transparent;border-radius:14px;cursor:pointer;outline:none;color:inherit;font:inherit;min-height:92px;text-align:left;background:var(--md-sys-color-surface);border-color:var(--md-sys-color-outline-variant);transition:box-shadow .2s ease,background .25s ease,transform .06s ease}.pdx-grid.dense .pdx-card{padding:10px;border-radius:12px;min-height:84px}.pdx-grid.roomy .pdx-card{padding:16px;border-radius:16px;min-height:100px}.pdx-card:focus,.pdx-card:hover{box-shadow:var(--mat-elevation-level4);background:var(--md-sys-color-surface-container-low);border-color:var(--md-sys-color-primary)}.pdx-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-card:active{transform:translateY(1px)}.pdx-card-icon{grid-row:span 2;display:flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary)}.pdx-card-title{font-weight:600;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-card-desc{color:var(--md-sys-color-on-surface-variant);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.pdx-card-badges{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.pdx-card-badge{display:inline-flex;align-items:center;gap:4px;min-height:22px;padding:2px 8px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-highest);font-size:11px;line-height:1.2;font-weight:600;letter-spacing:.01em}.pdx-card-badge mat-icon{width:14px;height:14px;font-size:14px}.pdx-card-badge.ready{color:var(--md-sys-color-primary);border-color:color-mix(in srgb,var(--md-sys-color-primary) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary-container) 72%,transparent)}.pdx-card-badge.info{color:var(--md-sys-color-tertiary);border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 38%,transparent);background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 68%,transparent)}.pdx-card-badge.warning{color:var(--md-sys-color-error);border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container) 62%,transparent)}.pdx-empty{padding:24px;display:grid;place-items:center;color:var(--md-sys-color-on-surface-variant);gap:8px}@media(max-width:600px){.pdx-palette-content{min-width:320px}.pdx-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}\n"] }]
|
|
639
|
-
}], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: i2$2.ComponentMetadataRegistry }, { type: undefined, decorators: [{
|
|
640
|
-
type: Inject,
|
|
641
|
-
args: [MAT_DIALOG_DATA]
|
|
642
|
-
}] }] });
|
|
643
|
-
|
|
644
|
-
const BUILTIN_PRESET_LABELS = {
|
|
645
|
-
'dark-glass': 'Dark Glass',
|
|
646
|
-
'light-neutral': 'Light Neutral',
|
|
647
|
-
graphite: 'Graphite',
|
|
648
|
-
frameless: 'Frameless',
|
|
649
|
-
'data-panel': 'Data Panel',
|
|
650
|
-
'chart-panel': 'Chart Panel',
|
|
651
|
-
'metric-panel': 'Metric Panel',
|
|
652
|
-
'executive-card': 'Executive Card',
|
|
653
|
-
'filter-bar': 'Filter Bar',
|
|
654
|
-
};
|
|
655
|
-
const BUILTIN_PRESET_OPTIONS = Object.keys(BUILTIN_SHELL_PRESETS).map((id) => ({
|
|
656
|
-
id,
|
|
657
|
-
label: BUILTIN_PRESET_LABELS[id] ?? id,
|
|
658
|
-
}));
|
|
659
|
-
const BUILTIN_PRESET_MAP = BUILTIN_SHELL_PRESETS;
|
|
660
|
-
const SET_INPUT_PRESETS = {
|
|
661
|
-
'praxis-dynamic-form': [
|
|
662
|
-
{
|
|
663
|
-
input: 'mode',
|
|
664
|
-
label: 'Modo',
|
|
665
|
-
icon: 'toggle_on',
|
|
666
|
-
values: [
|
|
667
|
-
{ label: 'Visualização', value: 'view', icon: 'visibility' },
|
|
668
|
-
{ label: 'Edição', value: 'edit', icon: 'edit' },
|
|
669
|
-
{ label: 'Criação', value: 'create', icon: 'add' },
|
|
670
|
-
],
|
|
671
|
-
},
|
|
672
|
-
{
|
|
673
|
-
input: 'schemaSource',
|
|
674
|
-
label: 'Fonte do schema',
|
|
675
|
-
icon: 'schema',
|
|
676
|
-
values: [
|
|
677
|
-
{ label: 'Recurso', value: 'resource' },
|
|
678
|
-
{ label: 'Filtro', value: 'filter' },
|
|
679
|
-
],
|
|
680
|
-
},
|
|
681
|
-
{
|
|
682
|
-
input: 'notifyIfOutdated',
|
|
683
|
-
label: 'Notificação de schema',
|
|
684
|
-
icon: 'notification_important',
|
|
685
|
-
values: [
|
|
686
|
-
{ label: 'Inline', value: 'inline' },
|
|
687
|
-
{ label: 'Snackbar', value: 'snackbar' },
|
|
688
|
-
{ label: 'Ambos', value: 'both' },
|
|
689
|
-
{ label: 'Nenhum', value: 'none' },
|
|
690
|
-
],
|
|
691
|
-
},
|
|
692
|
-
{
|
|
693
|
-
input: 'removeEmptyContainersOnSave',
|
|
694
|
-
label: 'Remover containers vazios',
|
|
695
|
-
icon: 'cleaning_services',
|
|
696
|
-
values: [
|
|
697
|
-
{ label: 'Ativar', value: true },
|
|
698
|
-
{ label: 'Desativar', value: false },
|
|
699
|
-
],
|
|
700
|
-
},
|
|
701
|
-
{
|
|
702
|
-
input: 'autoOpenSettingsOnOutdated',
|
|
703
|
-
label: 'Abrir editor automático',
|
|
704
|
-
icon: 'open_in_new',
|
|
705
|
-
values: [
|
|
706
|
-
{ label: 'Ativar', value: true },
|
|
707
|
-
{ label: 'Desativar', value: false },
|
|
708
|
-
],
|
|
709
|
-
},
|
|
710
|
-
{
|
|
711
|
-
input: 'readonlyModeGlobal',
|
|
712
|
-
label: 'Somente leitura global',
|
|
713
|
-
icon: 'lock',
|
|
714
|
-
values: [
|
|
715
|
-
{ label: 'Ativar', value: true },
|
|
716
|
-
{ label: 'Desativar', value: false },
|
|
717
|
-
],
|
|
718
|
-
},
|
|
719
|
-
{
|
|
720
|
-
input: 'disabledModeGlobal',
|
|
721
|
-
label: 'Desabilitar global',
|
|
722
|
-
icon: 'block',
|
|
723
|
-
values: [
|
|
724
|
-
{ label: 'Ativar', value: true },
|
|
725
|
-
{ label: 'Desativar', value: false },
|
|
726
|
-
],
|
|
727
|
-
},
|
|
728
|
-
{
|
|
729
|
-
input: 'presentationModeGlobal',
|
|
730
|
-
label: 'Modo apresentação',
|
|
731
|
-
icon: 'slideshow',
|
|
732
|
-
values: [
|
|
733
|
-
{ label: 'Ativar', value: true },
|
|
734
|
-
{ label: 'Desativar', value: false },
|
|
735
|
-
],
|
|
736
|
-
},
|
|
737
|
-
{
|
|
738
|
-
input: 'visibleGlobal',
|
|
739
|
-
label: 'Visibilidade global',
|
|
740
|
-
icon: 'visibility',
|
|
741
|
-
values: [
|
|
742
|
-
{ label: 'Exibir', value: true },
|
|
743
|
-
{ label: 'Ocultar', value: false },
|
|
744
|
-
],
|
|
745
|
-
},
|
|
746
|
-
],
|
|
747
|
-
'praxis-table': [
|
|
748
|
-
{
|
|
749
|
-
input: 'showToolbar',
|
|
750
|
-
label: 'Toolbar',
|
|
751
|
-
icon: 'toolbar',
|
|
752
|
-
values: [
|
|
753
|
-
{ label: 'Exibir', value: true },
|
|
754
|
-
{ label: 'Ocultar', value: false },
|
|
755
|
-
],
|
|
756
|
-
},
|
|
757
|
-
{
|
|
758
|
-
input: 'toolbarV2',
|
|
759
|
-
label: 'Toolbar v2',
|
|
760
|
-
icon: 'view_compact',
|
|
761
|
-
values: [
|
|
762
|
-
{ label: 'Ativar', value: true },
|
|
763
|
-
{ label: 'Desativar', value: false },
|
|
764
|
-
],
|
|
765
|
-
},
|
|
766
|
-
{
|
|
767
|
-
input: 'autoDelete',
|
|
768
|
-
label: 'Auto delete',
|
|
769
|
-
icon: 'delete_forever',
|
|
770
|
-
values: [
|
|
771
|
-
{ label: 'Ativar', value: true },
|
|
772
|
-
{ label: 'Desativar', value: false },
|
|
773
|
-
],
|
|
774
|
-
},
|
|
775
|
-
{
|
|
776
|
-
input: 'dense',
|
|
777
|
-
label: 'Modo compacto',
|
|
778
|
-
icon: 'compress',
|
|
779
|
-
values: [
|
|
780
|
-
{ label: 'Ativar', value: true },
|
|
781
|
-
{ label: 'Desativar', value: false },
|
|
782
|
-
],
|
|
783
|
-
},
|
|
784
|
-
],
|
|
785
|
-
'praxis-stepper': [
|
|
786
|
-
{
|
|
787
|
-
input: 'inputs.config.orientation',
|
|
788
|
-
label: 'Orientação',
|
|
789
|
-
icon: 'swap_vert',
|
|
790
|
-
values: [
|
|
791
|
-
{ label: 'Horizontal', value: 'horizontal' },
|
|
792
|
-
{ label: 'Vertical', value: 'vertical' },
|
|
793
|
-
],
|
|
794
|
-
},
|
|
795
|
-
{
|
|
796
|
-
input: 'inputs.config.headerPosition',
|
|
797
|
-
label: 'Posição do cabeçalho',
|
|
798
|
-
icon: 'vertical_align_top',
|
|
799
|
-
values: [
|
|
800
|
-
{ label: 'Topo', value: 'top' },
|
|
801
|
-
{ label: 'Base', value: 'bottom' },
|
|
802
|
-
],
|
|
803
|
-
},
|
|
804
|
-
{
|
|
805
|
-
input: 'inputs.config.linear',
|
|
806
|
-
label: 'Modo linear',
|
|
807
|
-
icon: 'linear_scale',
|
|
808
|
-
values: [
|
|
809
|
-
{ label: 'Ativar', value: true },
|
|
810
|
-
{ label: 'Desativar', value: false },
|
|
811
|
-
],
|
|
812
|
-
},
|
|
813
|
-
{
|
|
814
|
-
input: 'inputs.config.navigation.variant',
|
|
815
|
-
label: 'Navegação (variante)',
|
|
816
|
-
icon: 'tune',
|
|
817
|
-
values: [
|
|
818
|
-
{ label: 'Basic', value: 'basic' },
|
|
819
|
-
{ label: 'Flat', value: 'flat' },
|
|
820
|
-
{ label: 'Stroked', value: 'stroked' },
|
|
821
|
-
{ label: 'Raised', value: 'raised' },
|
|
822
|
-
],
|
|
823
|
-
},
|
|
824
|
-
{
|
|
825
|
-
input: 'inputs.config.navigation.align',
|
|
826
|
-
label: 'Navegação (alinhamento)',
|
|
827
|
-
icon: 'format_align_center',
|
|
828
|
-
values: [
|
|
829
|
-
{ label: 'Início', value: 'start' },
|
|
830
|
-
{ label: 'Centro', value: 'center' },
|
|
831
|
-
{ label: 'Fim', value: 'end' },
|
|
832
|
-
{ label: 'Espaçado', value: 'space-between' },
|
|
833
|
-
],
|
|
834
|
-
},
|
|
835
|
-
{
|
|
836
|
-
input: 'labelPosition',
|
|
837
|
-
label: 'Posição do rótulo',
|
|
838
|
-
icon: 'format_align_center',
|
|
839
|
-
values: [
|
|
840
|
-
{ label: 'Abaixo', value: 'bottom' },
|
|
841
|
-
{ label: 'Ao lado', value: 'end' },
|
|
842
|
-
],
|
|
843
|
-
},
|
|
844
|
-
{
|
|
845
|
-
input: 'density',
|
|
846
|
-
label: 'Densidade',
|
|
847
|
-
icon: 'density_small',
|
|
848
|
-
values: [
|
|
849
|
-
{ label: 'Padrão', value: 'default' },
|
|
850
|
-
{ label: 'Confortável', value: 'comfortable' },
|
|
851
|
-
{ label: 'Compacto', value: 'compact' },
|
|
852
|
-
],
|
|
853
|
-
},
|
|
854
|
-
],
|
|
855
|
-
'praxis-expansion': [
|
|
856
|
-
{
|
|
857
|
-
input: 'strictValidation',
|
|
858
|
-
label: 'Validação estrita',
|
|
859
|
-
icon: 'rule',
|
|
860
|
-
values: [
|
|
861
|
-
{ label: 'Ativar', value: true },
|
|
862
|
-
{ label: 'Desativar', value: false },
|
|
863
|
-
],
|
|
864
|
-
},
|
|
865
|
-
],
|
|
866
|
-
};
|
|
867
|
-
class WidgetShellEditorComponent {
|
|
868
|
-
registry;
|
|
869
|
-
form = new FormGroup({
|
|
870
|
-
kind: new FormControl('dashboard-card', { nonNullable: true }),
|
|
871
|
-
preset: new FormControl('', { nonNullable: true }),
|
|
872
|
-
applyToAll: new FormControl(false, { nonNullable: true }),
|
|
873
|
-
title: new FormControl('', { nonNullable: true }),
|
|
874
|
-
subtitle: new FormControl('', { nonNullable: true }),
|
|
875
|
-
icon: new FormControl('', { nonNullable: true }),
|
|
876
|
-
showHeader: new FormControl('auto', { nonNullable: true }),
|
|
877
|
-
collapsible: new FormControl(true, { nonNullable: true }),
|
|
878
|
-
cardBg: new FormControl('', { nonNullable: true }),
|
|
879
|
-
cardBorder: new FormControl('', { nonNullable: true }),
|
|
880
|
-
cardRadius: new FormControl('', { nonNullable: true }),
|
|
881
|
-
cardShadow: new FormControl('', { nonNullable: true }),
|
|
882
|
-
headerBg: new FormControl('', { nonNullable: true }),
|
|
883
|
-
headerBorder: new FormControl('', { nonNullable: true }),
|
|
884
|
-
titleColor: new FormControl('', { nonNullable: true }),
|
|
885
|
-
subtitleColor: new FormControl('', { nonNullable: true }),
|
|
886
|
-
iconColor: new FormControl('', { nonNullable: true }),
|
|
887
|
-
bodyBg: new FormControl('', { nonNullable: true }),
|
|
888
|
-
bodyColor: new FormControl('', { nonNullable: true }),
|
|
889
|
-
bodyPadding: new FormControl('', { nonNullable: true }),
|
|
890
|
-
titleSize: new FormControl('', { nonNullable: true }),
|
|
891
|
-
titleWeight: new FormControl('', { nonNullable: true }),
|
|
892
|
-
subtitleSize: new FormControl('', { nonNullable: true }),
|
|
893
|
-
actions: new FormArray([]),
|
|
894
|
-
});
|
|
895
|
-
initialShell = new BehaviorSubject(null);
|
|
896
|
-
dirtySubject = new BehaviorSubject(false);
|
|
897
|
-
validSubject = new BehaviorSubject(true);
|
|
898
|
-
busySubject = new BehaviorSubject(false);
|
|
899
|
-
isDirty$ = this.dirtySubject.asObservable();
|
|
900
|
-
isValid$ = this.validSubject.asObservable();
|
|
901
|
-
isBusy$ = this.busySubject.asObservable();
|
|
902
|
-
snapshot = '';
|
|
903
|
-
initialTitle;
|
|
904
|
-
initialSubtitle;
|
|
905
|
-
actionCopySources = new WeakMap();
|
|
906
|
-
presetOptions = [...BUILTIN_PRESET_OPTIONS];
|
|
907
|
-
presets = { ...BUILTIN_PRESET_MAP };
|
|
908
|
-
availableActions = [];
|
|
909
|
-
actionQuery = new FormControl('', { nonNullable: true });
|
|
910
|
-
showScopeShell = true;
|
|
911
|
-
showScopeAny = true;
|
|
912
|
-
showScopeToolbar = false;
|
|
913
|
-
showScopeContext = false;
|
|
914
|
-
setInputPresets = [];
|
|
915
|
-
setInputTarget = new FormControl('', { nonNullable: true });
|
|
916
|
-
setInputValue = new FormControl(null);
|
|
917
|
-
previewCollapsed = false;
|
|
918
|
-
previewExpanded = false;
|
|
919
|
-
pagePreset = null;
|
|
920
|
-
constructor(data, registry) {
|
|
921
|
-
this.registry = registry;
|
|
922
|
-
const customPresets = data?.presets || {};
|
|
923
|
-
const customOptions = Object.keys(customPresets).map((id) => ({ id, label: id }));
|
|
924
|
-
this.presetOptions = [...BUILTIN_PRESET_OPTIONS, ...customOptions];
|
|
925
|
-
this.presets = { ...BUILTIN_PRESET_MAP, ...customPresets };
|
|
926
|
-
this.pagePreset = data?.pagePreset || null;
|
|
927
|
-
const shell = data?.shell || null;
|
|
928
|
-
this.initialShell.next(shell);
|
|
929
|
-
this.applyShell(shell);
|
|
930
|
-
this.loadAvailableActions(data?.widgetType || null);
|
|
931
|
-
this.loadSetInputPresets(data?.widgetType || null);
|
|
932
|
-
this.form.valueChanges
|
|
933
|
-
.pipe(takeUntilDestroyed())
|
|
934
|
-
.subscribe(() => {
|
|
935
|
-
this.validSubject.next(this.form.valid);
|
|
936
|
-
const current = this.snapshotValue();
|
|
937
|
-
this.dirtySubject.next(current !== this.snapshot);
|
|
938
|
-
});
|
|
939
|
-
this.form.controls.preset.valueChanges
|
|
940
|
-
.pipe(takeUntilDestroyed())
|
|
941
|
-
.subscribe((value) => {
|
|
942
|
-
if (!value && this.form.controls.applyToAll.value) {
|
|
943
|
-
this.form.controls.applyToAll.setValue(false, { emitEvent: false });
|
|
944
|
-
}
|
|
945
|
-
});
|
|
946
|
-
this.setInputTarget.valueChanges
|
|
947
|
-
.pipe(takeUntilDestroyed())
|
|
948
|
-
.subscribe(() => {
|
|
949
|
-
const next = this.currentSetInputValues()[0];
|
|
950
|
-
if (next)
|
|
951
|
-
this.setInputValue.setValue(next.value, { emitEvent: false });
|
|
952
|
-
});
|
|
953
|
-
}
|
|
954
|
-
get actions() {
|
|
955
|
-
return this.form.controls.actions;
|
|
956
|
-
}
|
|
957
|
-
get hasAvailableActions() {
|
|
958
|
-
return !!this.availableActions.length;
|
|
959
|
-
}
|
|
960
|
-
addAction(seed) {
|
|
961
|
-
this.actions.push(this.createActionGroup(seed));
|
|
962
|
-
}
|
|
963
|
-
removeAction(index) {
|
|
964
|
-
this.actions.removeAt(index);
|
|
965
|
-
}
|
|
966
|
-
getSettingsValue() {
|
|
967
|
-
return this.buildResult();
|
|
968
|
-
}
|
|
969
|
-
onSave() {
|
|
970
|
-
return this.buildResult();
|
|
971
|
-
}
|
|
972
|
-
reset() {
|
|
973
|
-
const shell = this.initialShell.value;
|
|
974
|
-
this.applyShell(shell);
|
|
975
|
-
}
|
|
976
|
-
applyShell(shell) {
|
|
977
|
-
this.initialTitle = shell?.title;
|
|
978
|
-
this.initialSubtitle = shell?.subtitle;
|
|
979
|
-
const showHeader = shell?.showHeader == null ? 'auto' : shell.showHeader ? 'true' : 'false';
|
|
980
|
-
const window = shell?.windowActions || {};
|
|
981
|
-
const appearance = shell?.appearance || {};
|
|
982
|
-
const card = appearance.card || {};
|
|
983
|
-
const header = appearance.header || {};
|
|
984
|
-
const body = appearance.body || {};
|
|
985
|
-
const typography = appearance.typography || {};
|
|
986
|
-
this.form.setControl('actions', new FormArray((shell?.actions || []).map((a) => this.createActionGroup(a))));
|
|
987
|
-
this.form.setValue({
|
|
988
|
-
kind: shell?.kind === 'none' ? 'none' : 'dashboard-card',
|
|
989
|
-
preset: shell?.preset || '',
|
|
990
|
-
applyToAll: false,
|
|
991
|
-
title: this.editableText(shell?.title),
|
|
992
|
-
subtitle: this.editableText(shell?.subtitle),
|
|
993
|
-
icon: shell?.icon || '',
|
|
994
|
-
showHeader,
|
|
995
|
-
collapsible: window.collapsible !== false,
|
|
996
|
-
cardBg: card.background || '',
|
|
997
|
-
cardBorder: card.borderColor || '',
|
|
998
|
-
cardRadius: card.borderRadius || '',
|
|
999
|
-
cardShadow: card.shadow || '',
|
|
1000
|
-
headerBg: header.background || '',
|
|
1001
|
-
headerBorder: header.borderColor || '',
|
|
1002
|
-
titleColor: header.titleColor || '',
|
|
1003
|
-
subtitleColor: header.subtitleColor || '',
|
|
1004
|
-
iconColor: header.iconColor || '',
|
|
1005
|
-
bodyBg: body.background || '',
|
|
1006
|
-
bodyColor: body.textColor || '',
|
|
1007
|
-
bodyPadding: body.padding || '',
|
|
1008
|
-
titleSize: typography.titleSize || '',
|
|
1009
|
-
titleWeight: typography.titleWeight || '',
|
|
1010
|
-
subtitleSize: typography.subtitleSize || '',
|
|
1011
|
-
actions: this.actions.value,
|
|
1012
|
-
}, { emitEvent: false });
|
|
1013
|
-
this.snapshot = this.snapshotValue();
|
|
1014
|
-
this.dirtySubject.next(false);
|
|
1015
|
-
this.validSubject.next(this.form.valid);
|
|
1016
|
-
}
|
|
1017
|
-
loadAvailableActions(widgetType) {
|
|
1018
|
-
if (!widgetType || !this.registry) {
|
|
1019
|
-
this.availableActions = [];
|
|
1020
|
-
return;
|
|
1021
|
-
}
|
|
1022
|
-
const meta = this.registry.get(widgetType);
|
|
1023
|
-
const actions = (meta?.actions || []).map((action) => ({
|
|
1024
|
-
kind: 'action',
|
|
1025
|
-
id: action.id,
|
|
1026
|
-
label: action.label || action.id,
|
|
1027
|
-
icon: action.icon,
|
|
1028
|
-
scope: action.scope || 'any',
|
|
1029
|
-
emit: action.emit,
|
|
1030
|
-
command: action.command,
|
|
1031
|
-
description: action.description,
|
|
1032
|
-
payloadExample: action.payloadSchema?.example,
|
|
1033
|
-
}));
|
|
1034
|
-
const commands = (meta?.commands || []).map((command) => ({
|
|
1035
|
-
kind: 'command',
|
|
1036
|
-
id: command.name,
|
|
1037
|
-
label: command.label || command.name,
|
|
1038
|
-
icon: command.icon,
|
|
1039
|
-
scope: 'any',
|
|
1040
|
-
command: command.name,
|
|
1041
|
-
description: command.description,
|
|
1042
|
-
payloadExample: command.payloadSchema?.example,
|
|
1043
|
-
}));
|
|
1044
|
-
this.availableActions = [...actions, ...commands];
|
|
1045
|
-
}
|
|
1046
|
-
createActionGroup(seed) {
|
|
1047
|
-
const group = new FormGroup({
|
|
1048
|
-
id: new FormControl(seed?.id || '', { nonNullable: true, validators: [Validators.required] }),
|
|
1049
|
-
label: new FormControl(this.editableText(seed?.label), { nonNullable: true }),
|
|
1050
|
-
icon: new FormControl(seed?.icon || '', { nonNullable: true }),
|
|
1051
|
-
variant: new FormControl(seed?.variant || 'text', { nonNullable: true }),
|
|
1052
|
-
placement: new FormControl(seed?.placement || 'header', { nonNullable: true }),
|
|
1053
|
-
emit: new FormControl(seed?.emit || '', { nonNullable: true }),
|
|
1054
|
-
tooltip: new FormControl(this.editableText(seed?.tooltip), { nonNullable: true }),
|
|
1055
|
-
command: new FormControl(seed?.command || '', { nonNullable: true }),
|
|
1056
|
-
payload: new FormControl(seed?.payload != null ? JSON.stringify(seed.payload) : '', { nonNullable: true }),
|
|
1057
|
-
visible: new FormControl(seed?.visible !== false, { nonNullable: true }),
|
|
1058
|
-
disabled: new FormControl(!!seed?.disabled, { nonNullable: true }),
|
|
1059
|
-
});
|
|
1060
|
-
this.actionCopySources.set(group, { label: seed?.label, tooltip: seed?.tooltip });
|
|
1061
|
-
return group;
|
|
1062
|
-
}
|
|
1063
|
-
buildShell() {
|
|
1064
|
-
const raw = this.form.getRawValue();
|
|
1065
|
-
if (raw.kind === 'none') {
|
|
1066
|
-
return { kind: 'none' };
|
|
1067
|
-
}
|
|
1068
|
-
const shell = {};
|
|
1069
|
-
if (raw.preset)
|
|
1070
|
-
shell.preset = raw.preset;
|
|
1071
|
-
const title = this.preserveTextDescriptor(this.initialTitle, raw.title);
|
|
1072
|
-
const subtitle = this.preserveTextDescriptor(this.initialSubtitle, raw.subtitle);
|
|
1073
|
-
if (title)
|
|
1074
|
-
shell.title = title;
|
|
1075
|
-
if (subtitle)
|
|
1076
|
-
shell.subtitle = subtitle;
|
|
1077
|
-
if (raw.icon.trim())
|
|
1078
|
-
shell.icon = raw.icon.trim();
|
|
1079
|
-
if (raw.showHeader !== 'auto')
|
|
1080
|
-
shell.showHeader = raw.showHeader === 'true';
|
|
1081
|
-
const windowActions = {};
|
|
1082
|
-
if (!raw.collapsible)
|
|
1083
|
-
windowActions.collapsible = false;
|
|
1084
|
-
if (Object.keys(windowActions).length)
|
|
1085
|
-
shell.windowActions = windowActions;
|
|
1086
|
-
const actions = this.actions.controls
|
|
1087
|
-
.map((group) => this.normalizeAction(group.getRawValue(), this.actionCopySources.get(group)))
|
|
1088
|
-
.filter((a) => a.id);
|
|
1089
|
-
if (actions.length)
|
|
1090
|
-
shell.actions = actions;
|
|
1091
|
-
const appearance = this.buildAppearance(raw);
|
|
1092
|
-
if (appearance)
|
|
1093
|
-
shell.appearance = appearance;
|
|
1094
|
-
return shell;
|
|
1095
|
-
}
|
|
1096
|
-
buildResult() {
|
|
1097
|
-
const raw = this.form.getRawValue();
|
|
1098
|
-
const shell = this.buildShell();
|
|
1099
|
-
const applyToAll = !!raw.applyToAll && !!raw.preset;
|
|
1100
|
-
return {
|
|
1101
|
-
shell,
|
|
1102
|
-
applyToAll,
|
|
1103
|
-
pagePreset: applyToAll ? raw.preset : undefined,
|
|
1104
|
-
};
|
|
1105
|
-
}
|
|
1106
|
-
buildAppearance(raw) {
|
|
1107
|
-
const card = {};
|
|
1108
|
-
const header = {};
|
|
1109
|
-
const body = {};
|
|
1110
|
-
const typography = {};
|
|
1111
|
-
if (raw.cardBg)
|
|
1112
|
-
card.background = raw.cardBg.trim();
|
|
1113
|
-
if (raw.cardBorder)
|
|
1114
|
-
card.borderColor = raw.cardBorder.trim();
|
|
1115
|
-
if (raw.cardRadius)
|
|
1116
|
-
card.borderRadius = raw.cardRadius.trim();
|
|
1117
|
-
if (raw.cardShadow)
|
|
1118
|
-
card.shadow = raw.cardShadow.trim();
|
|
1119
|
-
if (raw.headerBg)
|
|
1120
|
-
header.background = raw.headerBg.trim();
|
|
1121
|
-
if (raw.headerBorder)
|
|
1122
|
-
header.borderColor = raw.headerBorder.trim();
|
|
1123
|
-
if (raw.titleColor)
|
|
1124
|
-
header.titleColor = raw.titleColor.trim();
|
|
1125
|
-
if (raw.subtitleColor)
|
|
1126
|
-
header.subtitleColor = raw.subtitleColor.trim();
|
|
1127
|
-
if (raw.iconColor)
|
|
1128
|
-
header.iconColor = raw.iconColor.trim();
|
|
1129
|
-
if (raw.bodyBg)
|
|
1130
|
-
body.background = raw.bodyBg.trim();
|
|
1131
|
-
if (raw.bodyColor)
|
|
1132
|
-
body.textColor = raw.bodyColor.trim();
|
|
1133
|
-
if (raw.bodyPadding)
|
|
1134
|
-
body.padding = raw.bodyPadding.trim();
|
|
1135
|
-
if (raw.titleSize)
|
|
1136
|
-
typography.titleSize = raw.titleSize.trim();
|
|
1137
|
-
if (raw.titleWeight)
|
|
1138
|
-
typography.titleWeight = raw.titleWeight.trim();
|
|
1139
|
-
if (raw.subtitleSize)
|
|
1140
|
-
typography.subtitleSize = raw.subtitleSize.trim();
|
|
1141
|
-
const appearance = {};
|
|
1142
|
-
if (Object.keys(card).length)
|
|
1143
|
-
appearance.card = card;
|
|
1144
|
-
if (Object.keys(header).length)
|
|
1145
|
-
appearance.header = header;
|
|
1146
|
-
if (Object.keys(body).length)
|
|
1147
|
-
appearance.body = body;
|
|
1148
|
-
if (Object.keys(typography).length)
|
|
1149
|
-
appearance.typography = typography;
|
|
1150
|
-
return Object.keys(appearance).length ? appearance : undefined;
|
|
1151
|
-
}
|
|
1152
|
-
previewVars() {
|
|
1153
|
-
const appearance = this.buildPreviewAppearance();
|
|
1154
|
-
return {
|
|
1155
|
-
'--pdx-shell-card-bg': appearance?.card?.background || null,
|
|
1156
|
-
'--pdx-shell-card-border': appearance?.card?.borderColor || null,
|
|
1157
|
-
'--pdx-shell-card-radius': appearance?.card?.borderRadius || null,
|
|
1158
|
-
'--pdx-shell-card-shadow': appearance?.card?.shadow || null,
|
|
1159
|
-
'--pdx-shell-header-bg': appearance?.header?.background || null,
|
|
1160
|
-
'--pdx-shell-header-border': appearance?.header?.borderColor || null,
|
|
1161
|
-
'--pdx-shell-title-color': appearance?.header?.titleColor || null,
|
|
1162
|
-
'--pdx-shell-subtitle-color': appearance?.header?.subtitleColor || null,
|
|
1163
|
-
'--pdx-shell-icon-color': appearance?.header?.iconColor || null,
|
|
1164
|
-
'--pdx-shell-body-bg': appearance?.body?.background || null,
|
|
1165
|
-
'--pdx-shell-body-color': appearance?.body?.textColor || null,
|
|
1166
|
-
'--pdx-shell-body-padding': appearance?.body?.padding || null,
|
|
1167
|
-
'--pdx-shell-title-size': appearance?.typography?.titleSize || null,
|
|
1168
|
-
'--pdx-shell-title-weight': appearance?.typography?.titleWeight || null,
|
|
1169
|
-
'--pdx-shell-subtitle-size': appearance?.typography?.subtitleSize || null,
|
|
1170
|
-
};
|
|
1171
|
-
}
|
|
1172
|
-
previewShowHeader() {
|
|
1173
|
-
const raw = this.form.getRawValue();
|
|
1174
|
-
if (raw.kind === 'none')
|
|
1175
|
-
return false;
|
|
1176
|
-
if (raw.showHeader === 'true')
|
|
1177
|
-
return true;
|
|
1178
|
-
if (raw.showHeader === 'false')
|
|
1179
|
-
return false;
|
|
1180
|
-
return !!(raw.title || raw.subtitle || raw.icon);
|
|
1181
|
-
}
|
|
1182
|
-
previewTitle() {
|
|
1183
|
-
const title = this.editableText(this.form.controls.title.value).trim();
|
|
1184
|
-
return title || 'Titulo do card';
|
|
1185
|
-
}
|
|
1186
|
-
previewSubtitle() {
|
|
1187
|
-
const subtitle = this.editableText(this.form.controls.subtitle.value).trim();
|
|
1188
|
-
return subtitle || 'Subtitulo opcional';
|
|
1189
|
-
}
|
|
1190
|
-
buildPreviewAppearance() {
|
|
1191
|
-
const raw = this.form.getRawValue();
|
|
1192
|
-
const presetId = raw.preset || this.pagePreset || '';
|
|
1193
|
-
const base = presetId ? this.presets[presetId] : undefined;
|
|
1194
|
-
const override = this.buildAppearance(raw);
|
|
1195
|
-
return this.mergeAppearance(base, override);
|
|
1196
|
-
}
|
|
1197
|
-
mergeAppearance(base, override) {
|
|
1198
|
-
if (!base && !override)
|
|
1199
|
-
return undefined;
|
|
1200
|
-
const out = {};
|
|
1201
|
-
const mergeSection = (key) => {
|
|
1202
|
-
const a = (base && base[key]) || undefined;
|
|
1203
|
-
const b = (override && override[key]) || undefined;
|
|
1204
|
-
if (!a && !b)
|
|
1205
|
-
return;
|
|
1206
|
-
out[key] = { ...(a || {}), ...(b || {}) };
|
|
1207
|
-
};
|
|
1208
|
-
mergeSection('card');
|
|
1209
|
-
mergeSection('header');
|
|
1210
|
-
mergeSection('body');
|
|
1211
|
-
mergeSection('typography');
|
|
1212
|
-
return out;
|
|
1213
|
-
}
|
|
1214
|
-
togglePreviewCollapse() {
|
|
1215
|
-
this.previewCollapsed = !this.previewCollapsed;
|
|
1216
|
-
}
|
|
1217
|
-
togglePreviewExpand() {
|
|
1218
|
-
this.previewExpanded = !this.previewExpanded;
|
|
1219
|
-
}
|
|
1220
|
-
previewHeaderActions() {
|
|
1221
|
-
const actions = this.previewActions().filter((a) => (a.placement || 'header') === 'header');
|
|
1222
|
-
return actions.slice(0, 3);
|
|
1223
|
-
}
|
|
1224
|
-
previewOverflowCount() {
|
|
1225
|
-
const actions = this.previewActions().filter((a) => (a.placement || 'header') === 'header');
|
|
1226
|
-
return Math.max(0, actions.length - 3);
|
|
1227
|
-
}
|
|
1228
|
-
previewWindowActions() {
|
|
1229
|
-
return this.previewActions().filter((a) => (a.placement || 'header') === 'window');
|
|
1230
|
-
}
|
|
1231
|
-
normalizeAction(raw, source) {
|
|
1232
|
-
const action = { id: String(raw.id || '').trim() };
|
|
1233
|
-
const label = String(raw.label || '').trim();
|
|
1234
|
-
const icon = String(raw.icon || '').trim();
|
|
1235
|
-
const emit = String(raw.emit || '').trim();
|
|
1236
|
-
const tooltip = String(raw.tooltip || '').trim();
|
|
1237
|
-
const command = String(raw.command || '').trim();
|
|
1238
|
-
const normalizedLabel = this.preserveTextDescriptor(source?.label, label);
|
|
1239
|
-
const normalizedTooltip = this.preserveTextDescriptor(source?.tooltip, tooltip);
|
|
1240
|
-
if (normalizedLabel)
|
|
1241
|
-
action.label = normalizedLabel;
|
|
1242
|
-
if (icon)
|
|
1243
|
-
action.icon = icon;
|
|
1244
|
-
if (emit)
|
|
1245
|
-
action.emit = emit;
|
|
1246
|
-
if (normalizedTooltip)
|
|
1247
|
-
action.tooltip = normalizedTooltip;
|
|
1248
|
-
if (command)
|
|
1249
|
-
action.command = command;
|
|
1250
|
-
if (raw.variant && raw.variant !== 'text')
|
|
1251
|
-
action.variant = raw.variant;
|
|
1252
|
-
if (raw.placement && raw.placement !== 'header')
|
|
1253
|
-
action.placement = raw.placement;
|
|
1254
|
-
if (raw.visible === false)
|
|
1255
|
-
action.visible = false;
|
|
1256
|
-
if (raw.disabled === true)
|
|
1257
|
-
action.disabled = true;
|
|
1258
|
-
const payload = this.tryParsePayload(raw.payload);
|
|
1259
|
-
if (payload !== undefined)
|
|
1260
|
-
action.payload = payload;
|
|
1261
|
-
return action;
|
|
1262
|
-
}
|
|
1263
|
-
editableText(value) {
|
|
1264
|
-
if (typeof value === 'string')
|
|
1265
|
-
return value;
|
|
1266
|
-
return value?.text || value?.key || '';
|
|
1267
|
-
}
|
|
1268
|
-
preserveTextDescriptor(source, editedValue) {
|
|
1269
|
-
const edited = String(editedValue ?? '').trim();
|
|
1270
|
-
if (!edited)
|
|
1271
|
-
return undefined;
|
|
1272
|
-
if (source && typeof source === 'object') {
|
|
1273
|
-
const authoredText = this.editableText(source).trim();
|
|
1274
|
-
return edited === authoredText ? { ...source } : edited;
|
|
1275
|
-
}
|
|
1276
|
-
return edited;
|
|
1277
|
-
}
|
|
1278
|
-
tryParsePayload(raw) {
|
|
1279
|
-
const value = String(raw || '').trim();
|
|
1280
|
-
if (!value)
|
|
1281
|
-
return undefined;
|
|
1282
|
-
try {
|
|
1283
|
-
return JSON.parse(value);
|
|
1284
|
-
}
|
|
1285
|
-
catch {
|
|
1286
|
-
return value;
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1289
|
-
snapshotValue() {
|
|
1290
|
-
try {
|
|
1291
|
-
return JSON.stringify(this.buildResult());
|
|
1292
|
-
}
|
|
1293
|
-
catch {
|
|
1294
|
-
return '';
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
1297
|
-
filteredAvailableActions() {
|
|
1298
|
-
const query = this.actionQuery.value.trim().toLowerCase();
|
|
1299
|
-
const scopes = new Set();
|
|
1300
|
-
if (this.showScopeShell)
|
|
1301
|
-
scopes.add('shell');
|
|
1302
|
-
if (this.showScopeAny)
|
|
1303
|
-
scopes.add('any');
|
|
1304
|
-
if (this.showScopeToolbar)
|
|
1305
|
-
scopes.add('toolbar');
|
|
1306
|
-
if (this.showScopeContext)
|
|
1307
|
-
scopes.add('context');
|
|
1308
|
-
return this.availableActions.filter((action) => {
|
|
1309
|
-
const scope = action.scope || 'any';
|
|
1310
|
-
if (!scopes.has(scope))
|
|
1311
|
-
return false;
|
|
1312
|
-
if (!query)
|
|
1313
|
-
return true;
|
|
1314
|
-
const hay = [
|
|
1315
|
-
action.label,
|
|
1316
|
-
action.id,
|
|
1317
|
-
action.description,
|
|
1318
|
-
action.emit,
|
|
1319
|
-
action.command,
|
|
1320
|
-
]
|
|
1321
|
-
.filter(Boolean)
|
|
1322
|
-
.join(' ')
|
|
1323
|
-
.toLowerCase();
|
|
1324
|
-
return hay.includes(query);
|
|
1325
|
-
});
|
|
1326
|
-
}
|
|
1327
|
-
isActionSelected(action) {
|
|
1328
|
-
return this.findActionIndex(action) >= 0;
|
|
1329
|
-
}
|
|
1330
|
-
toggleAvailableAction(action) {
|
|
1331
|
-
const idx = this.findActionIndex(action);
|
|
1332
|
-
if (idx >= 0) {
|
|
1333
|
-
this.removeAction(idx);
|
|
1334
|
-
return;
|
|
1335
|
-
}
|
|
1336
|
-
this.addAction({
|
|
1337
|
-
id: action.id,
|
|
1338
|
-
label: action.label,
|
|
1339
|
-
icon: action.icon,
|
|
1340
|
-
emit: action.emit,
|
|
1341
|
-
command: action.command,
|
|
1342
|
-
payload: action.payloadExample,
|
|
1343
|
-
});
|
|
1344
|
-
}
|
|
1345
|
-
scopeLabel(scope) {
|
|
1346
|
-
const value = scope || 'any';
|
|
1347
|
-
if (value === 'shell')
|
|
1348
|
-
return 'Shell';
|
|
1349
|
-
if (value === 'toolbar')
|
|
1350
|
-
return 'Toolbar';
|
|
1351
|
-
if (value === 'context')
|
|
1352
|
-
return 'Context';
|
|
1353
|
-
return 'Any';
|
|
1354
|
-
}
|
|
1355
|
-
stringifyPayload(payload) {
|
|
1356
|
-
if (payload === null)
|
|
1357
|
-
return 'null';
|
|
1358
|
-
if (payload === undefined)
|
|
1359
|
-
return 'undefined';
|
|
1360
|
-
if (typeof payload === 'string')
|
|
1361
|
-
return payload;
|
|
1362
|
-
try {
|
|
1363
|
-
return JSON.stringify(payload);
|
|
1364
|
-
}
|
|
1365
|
-
catch {
|
|
1366
|
-
return String(payload);
|
|
1367
|
-
}
|
|
1368
|
-
}
|
|
1369
|
-
displayInputPath(path) {
|
|
1370
|
-
const trimmed = String(path || '').trim();
|
|
1371
|
-
if (!trimmed)
|
|
1372
|
-
return '';
|
|
1373
|
-
return trimmed.replace(/^inputs\./, '');
|
|
1374
|
-
}
|
|
1375
|
-
extractActionInput(actionValue) {
|
|
1376
|
-
const payload = this.tryParsePayload(actionValue?.payload);
|
|
1377
|
-
const input = typeof payload?.input === 'string' ? payload.input.trim() : '';
|
|
1378
|
-
return input;
|
|
1379
|
-
}
|
|
1380
|
-
showActionInputPath(actionValue) {
|
|
1381
|
-
const command = String(actionValue?.command || '').trim();
|
|
1382
|
-
if (command !== 'pdx:set-input')
|
|
1383
|
-
return false;
|
|
1384
|
-
return !!this.extractActionInput(actionValue);
|
|
1385
|
-
}
|
|
1386
|
-
currentSetInputValues() {
|
|
1387
|
-
const preset = this.setInputPresets.find((p) => p.input === this.setInputTarget.value);
|
|
1388
|
-
return preset?.values || [];
|
|
1389
|
-
}
|
|
1390
|
-
addSetInputAction() {
|
|
1391
|
-
const preset = this.setInputPresets.find((p) => p.input === this.setInputTarget.value);
|
|
1392
|
-
if (!preset)
|
|
1393
|
-
return;
|
|
1394
|
-
const selected = this.currentSetInputValues().find((v) => v.value === this.setInputValue.value);
|
|
1395
|
-
if (!selected)
|
|
1396
|
-
return;
|
|
1397
|
-
const label = `${preset.label}: ${selected.label}`;
|
|
1398
|
-
const payload = { input: preset.input, value: selected.value };
|
|
1399
|
-
this.addAction({
|
|
1400
|
-
id: `set-${preset.input}-${String(selected.value)}`,
|
|
1401
|
-
label,
|
|
1402
|
-
icon: selected.icon || preset.icon,
|
|
1403
|
-
command: 'pdx:set-input',
|
|
1404
|
-
payload,
|
|
1405
|
-
variant: 'text',
|
|
1406
|
-
placement: 'header',
|
|
1407
|
-
});
|
|
1408
|
-
}
|
|
1409
|
-
findActionIndex(action) {
|
|
1410
|
-
const values = this.actions.getRawValue();
|
|
1411
|
-
return values.findIndex((a) => {
|
|
1412
|
-
if (a.id !== action.id)
|
|
1413
|
-
return false;
|
|
1414
|
-
if (action.command && a.command)
|
|
1415
|
-
return a.command === action.command;
|
|
1416
|
-
if (action.emit && a.emit)
|
|
1417
|
-
return a.emit === action.emit;
|
|
1418
|
-
return true;
|
|
1419
|
-
});
|
|
1420
|
-
}
|
|
1421
|
-
previewActions() {
|
|
1422
|
-
return (this.actions.getRawValue() || [])
|
|
1423
|
-
.map((a) => this.normalizeAction(a))
|
|
1424
|
-
.filter((a) => a.id && a.visible !== false);
|
|
1425
|
-
}
|
|
1426
|
-
loadSetInputPresets(widgetType) {
|
|
1427
|
-
if (!widgetType) {
|
|
1428
|
-
this.setInputPresets = [];
|
|
1429
|
-
return;
|
|
1430
|
-
}
|
|
1431
|
-
this.setInputPresets = SET_INPUT_PRESETS[widgetType] || [];
|
|
1432
|
-
const first = this.setInputPresets[0];
|
|
1433
|
-
if (first) {
|
|
1434
|
-
this.setInputTarget.setValue(first.input, { emitEvent: false });
|
|
1435
|
-
const firstValue = first.values[0];
|
|
1436
|
-
if (firstValue)
|
|
1437
|
-
this.setInputValue.setValue(firstValue.value, { emitEvent: false });
|
|
1438
|
-
}
|
|
1439
|
-
}
|
|
1440
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: WidgetShellEditorComponent, deps: [{ token: SETTINGS_PANEL_DATA, optional: true }, { token: i2$2.ComponentMetadataRegistry, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
1441
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: WidgetShellEditorComponent, isStandalone: true, selector: "praxis-widget-shell-editor", ngImport: i0, template: `
|
|
1442
|
-
<div class="shell-editor">
|
|
1443
|
-
<p class="shell-intro">
|
|
1444
|
-
Defina a identidade, a aparência e as ações do card. Use a prévia para conferir o resultado antes de salvar.
|
|
1445
|
-
</p>
|
|
1446
|
-
|
|
1447
|
-
<div class="shell-section">Geral</div>
|
|
1448
|
-
<div class="shell-grid">
|
|
1449
|
-
<mat-form-field appearance="outline">
|
|
1450
|
-
<mat-label>Tipo de card</mat-label>
|
|
1451
|
-
<mat-select [formControl]="form.controls.kind">
|
|
1452
|
-
<mat-option value="dashboard-card">Dashboard Card</mat-option>
|
|
1453
|
-
<mat-option value="none">Sem shell</mat-option>
|
|
1454
|
-
</mat-select>
|
|
1455
|
-
</mat-form-field>
|
|
1456
|
-
<mat-form-field appearance="outline">
|
|
1457
|
-
<mat-label>Preset</mat-label>
|
|
1458
|
-
<mat-select [formControl]="form.controls.preset">
|
|
1459
|
-
<mat-option value="">Nenhum</mat-option>
|
|
1460
|
-
@if (pagePreset) {
|
|
1461
|
-
<mat-option [value]="pagePreset">Usar preset da página ({{ pagePreset }})</mat-option>
|
|
1462
|
-
}
|
|
1463
|
-
@for (p of presetOptions; track p) {
|
|
1464
|
-
<mat-option [value]="p.id">{{ p.label }}</mat-option>
|
|
1465
|
-
}
|
|
1466
|
-
</mat-select>
|
|
1467
|
-
</mat-form-field>
|
|
1468
|
-
@if (!form.controls.preset.value && pagePreset) {
|
|
1469
|
-
<div class="shell-hint">
|
|
1470
|
-
Preset da página: {{ pagePreset }}
|
|
1471
|
-
</div>
|
|
1472
|
-
}
|
|
1473
|
-
@if (form.controls.preset.value) {
|
|
1474
|
-
<mat-checkbox [formControl]="form.controls.applyToAll">
|
|
1475
|
-
Aplicar preset como padrão da página
|
|
1476
|
-
</mat-checkbox>
|
|
1477
|
-
}
|
|
1478
|
-
<mat-form-field appearance="outline">
|
|
1479
|
-
<mat-label>Ícone</mat-label>
|
|
1480
|
-
<input matInput [formControl]="form.controls.icon" placeholder="ex: badge" />
|
|
1481
|
-
</mat-form-field>
|
|
1482
|
-
<mat-form-field appearance="outline">
|
|
1483
|
-
<mat-label>Título</mat-label>
|
|
1484
|
-
<input matInput [formControl]="form.controls.title" />
|
|
1485
|
-
</mat-form-field>
|
|
1486
|
-
<mat-form-field appearance="outline" class="shell-field--wide">
|
|
1487
|
-
<mat-label>Subtítulo</mat-label>
|
|
1488
|
-
<input matInput [formControl]="form.controls.subtitle" />
|
|
1489
|
-
</mat-form-field>
|
|
1490
|
-
<mat-form-field appearance="outline">
|
|
1491
|
-
<mat-label>Mostrar cabeçalho</mat-label>
|
|
1492
|
-
<mat-select [formControl]="form.controls.showHeader">
|
|
1493
|
-
<mat-option value="auto">Automático</mat-option>
|
|
1494
|
-
<mat-option value="true">Sempre</mat-option>
|
|
1495
|
-
<mat-option value="false">Nunca</mat-option>
|
|
1496
|
-
</mat-select>
|
|
1497
|
-
</mat-form-field>
|
|
1498
|
-
</div>
|
|
1499
|
-
|
|
1500
|
-
<div class="shell-section">Controles de janela</div>
|
|
1501
|
-
<div class="shell-flags">
|
|
1502
|
-
<mat-checkbox [formControl]="form.controls.collapsible">Permitir recolher</mat-checkbox>
|
|
1503
|
-
</div>
|
|
1504
|
-
|
|
1505
|
-
<mat-divider></mat-divider>
|
|
1506
|
-
|
|
1507
|
-
<div class="shell-section">Aparência</div>
|
|
1508
|
-
<div class="shell-grid">
|
|
1509
|
-
<mat-form-field appearance="outline">
|
|
1510
|
-
<mat-label>Fundo do card</mat-label>
|
|
1511
|
-
<input matInput [formControl]="form.controls.cardBg" placeholder="ex: #0b1220" />
|
|
1512
|
-
</mat-form-field>
|
|
1513
|
-
<mat-form-field appearance="outline">
|
|
1514
|
-
<mat-label>Cor da borda</mat-label>
|
|
1515
|
-
<input matInput [formControl]="form.controls.cardBorder" placeholder="ex: rgba(255,255,255,0.12)" />
|
|
1516
|
-
</mat-form-field>
|
|
1517
|
-
<mat-form-field appearance="outline">
|
|
1518
|
-
<mat-label>Raio da borda</mat-label>
|
|
1519
|
-
<input matInput [formControl]="form.controls.cardRadius" placeholder="ex: 14px" />
|
|
1520
|
-
</mat-form-field>
|
|
1521
|
-
<mat-form-field appearance="outline">
|
|
1522
|
-
<mat-label>Sombra</mat-label>
|
|
1523
|
-
<input matInput [formControl]="form.controls.cardShadow" placeholder="ex: 0 10px 30px rgba(0,0,0,0.2)" />
|
|
1524
|
-
</mat-form-field>
|
|
1525
|
-
<mat-form-field appearance="outline">
|
|
1526
|
-
<mat-label>Fundo do cabeçalho</mat-label>
|
|
1527
|
-
<input matInput [formControl]="form.controls.headerBg" placeholder="ex: linear-gradient(...)" />
|
|
1528
|
-
</mat-form-field>
|
|
1529
|
-
<mat-form-field appearance="outline">
|
|
1530
|
-
<mat-label>Borda do cabeçalho</mat-label>
|
|
1531
|
-
<input matInput [formControl]="form.controls.headerBorder" placeholder="ex: rgba(255,255,255,0.08)" />
|
|
1532
|
-
</mat-form-field>
|
|
1533
|
-
<mat-form-field appearance="outline">
|
|
1534
|
-
<mat-label>Cor do título</mat-label>
|
|
1535
|
-
<input matInput [formControl]="form.controls.titleColor" placeholder="ex: #e6edf3" />
|
|
1536
|
-
</mat-form-field>
|
|
1537
|
-
<mat-form-field appearance="outline">
|
|
1538
|
-
<mat-label>Cor do subtítulo</mat-label>
|
|
1539
|
-
<input matInput [formControl]="form.controls.subtitleColor" placeholder="ex: #9fb0c4" />
|
|
1540
|
-
</mat-form-field>
|
|
1541
|
-
<mat-form-field appearance="outline">
|
|
1542
|
-
<mat-label>Cor do ícone</mat-label>
|
|
1543
|
-
<input matInput [formControl]="form.controls.iconColor" placeholder="ex: #8ab4ff" />
|
|
1544
|
-
</mat-form-field>
|
|
1545
|
-
<mat-form-field appearance="outline">
|
|
1546
|
-
<mat-label>Fundo do corpo</mat-label>
|
|
1547
|
-
<input matInput [formControl]="form.controls.bodyBg" placeholder="ex: transparent" />
|
|
1548
|
-
</mat-form-field>
|
|
1549
|
-
<mat-form-field appearance="outline">
|
|
1550
|
-
<mat-label>Cor do texto do corpo</mat-label>
|
|
1551
|
-
<input matInput [formControl]="form.controls.bodyColor" placeholder="ex: #e6edf3" />
|
|
1552
|
-
</mat-form-field>
|
|
1553
|
-
<mat-form-field appearance="outline">
|
|
1554
|
-
<mat-label>Padding do corpo</mat-label>
|
|
1555
|
-
<input matInput [formControl]="form.controls.bodyPadding" placeholder="ex: 10px 12px 12px" />
|
|
1556
|
-
</mat-form-field>
|
|
1557
|
-
<mat-form-field appearance="outline">
|
|
1558
|
-
<mat-label>Tamanho do título</mat-label>
|
|
1559
|
-
<input matInput [formControl]="form.controls.titleSize" placeholder="ex: 14px" />
|
|
1560
|
-
</mat-form-field>
|
|
1561
|
-
<mat-form-field appearance="outline">
|
|
1562
|
-
<mat-label>Peso do título</mat-label>
|
|
1563
|
-
<input matInput [formControl]="form.controls.titleWeight" placeholder="ex: 600" />
|
|
1564
|
-
</mat-form-field>
|
|
1565
|
-
<mat-form-field appearance="outline">
|
|
1566
|
-
<mat-label>Tamanho do subtítulo</mat-label>
|
|
1567
|
-
<input matInput [formControl]="form.controls.subtitleSize" placeholder="ex: 12px" />
|
|
1568
|
-
</mat-form-field>
|
|
1569
|
-
</div>
|
|
1570
|
-
|
|
1571
|
-
<div class="shell-preview" [ngStyle]="previewVars()">
|
|
1572
|
-
<div class="shell-preview-card" [class.no-shell]="form.controls.kind.value === 'none'" [class.expanded]="previewExpanded">
|
|
1573
|
-
@if (previewShowHeader()) {
|
|
1574
|
-
<div class="shell-preview-header">
|
|
1575
|
-
<div class="shell-preview-title">
|
|
1576
|
-
@if (form.controls.icon.value) {
|
|
1577
|
-
<mat-icon [praxisIcon]="form.controls.icon.value"></mat-icon>
|
|
1578
|
-
}
|
|
1579
|
-
<div class="shell-preview-text">
|
|
1580
|
-
<div class="shell-preview-title-text">{{ previewTitle() }}</div>
|
|
1581
|
-
<div class="shell-preview-subtitle">{{ previewSubtitle() }}</div>
|
|
1582
|
-
</div>
|
|
1583
|
-
</div>
|
|
1584
|
-
<div class="shell-preview-actions">
|
|
1585
|
-
@for (action of previewHeaderActions(); track action.id) {
|
|
1586
|
-
<button
|
|
1587
|
-
type="button"
|
|
1588
|
-
[disabled]="action.disabled"
|
|
1589
|
-
[ngClass]="action.variant === 'outlined' ? 'pdx-preview-outlined' : 'pdx-preview-text'"
|
|
1590
|
-
mat-button
|
|
1591
|
-
>
|
|
1592
|
-
@if (action.icon) {
|
|
1593
|
-
<mat-icon [praxisIcon]="action.icon"></mat-icon>
|
|
1594
|
-
}
|
|
1595
|
-
<span class="pdx-preview-label">{{ action.label || action.id }}</span>
|
|
1596
|
-
</button>
|
|
1597
|
-
}
|
|
1598
|
-
@if (previewOverflowCount()) {
|
|
1599
|
-
<button
|
|
1600
|
-
praxisIconButton="more_horiz"
|
|
1601
|
-
size="compact"
|
|
1602
|
-
type="button"
|
|
1603
|
-
aria-label="Mais ações"
|
|
1604
|
-
></button>
|
|
1605
|
-
}
|
|
1606
|
-
@for (action of previewWindowActions(); track action.id) {
|
|
1607
|
-
@if (action.icon) {
|
|
1608
|
-
<button
|
|
1609
|
-
[praxisIconButton]="action.icon"
|
|
1610
|
-
size="compact"
|
|
1611
|
-
type="button"
|
|
1612
|
-
[disabled]="action.disabled"
|
|
1613
|
-
[attr.aria-label]="action.label || action.id"
|
|
1614
|
-
></button>
|
|
1615
|
-
}
|
|
1616
|
-
}
|
|
1617
|
-
<button
|
|
1618
|
-
[praxisIconButton]="previewCollapsed ? 'unfold_more' : 'unfold_less'"
|
|
1619
|
-
size="compact"
|
|
1620
|
-
type="button"
|
|
1621
|
-
(click)="togglePreviewCollapse()"
|
|
1622
|
-
aria-label="Recolher"
|
|
1623
|
-
></button>
|
|
1624
|
-
<button
|
|
1625
|
-
[praxisIconButton]="previewExpanded ? 'close_fullscreen' : 'open_in_full'"
|
|
1626
|
-
size="compact"
|
|
1627
|
-
type="button"
|
|
1628
|
-
(click)="togglePreviewExpand()"
|
|
1629
|
-
aria-label="Expandir"
|
|
1630
|
-
></button>
|
|
1631
|
-
</div>
|
|
1632
|
-
</div>
|
|
1633
|
-
}
|
|
1634
|
-
<div class="shell-preview-body" [class.hidden]="previewCollapsed">Conteudo do widget</div>
|
|
1635
|
-
</div>
|
|
1636
|
-
</div>
|
|
1637
|
-
|
|
1638
|
-
<mat-divider></mat-divider>
|
|
1639
|
-
|
|
1640
|
-
@if (hasAvailableActions) {
|
|
1641
|
-
<div class="shell-section">Ações disponíveis</div>
|
|
1642
|
-
}
|
|
1643
|
-
@if (hasAvailableActions) {
|
|
1644
|
-
<div class="shell-available">
|
|
1645
|
-
<div class="shell-available-toolbar">
|
|
1646
|
-
<mat-form-field appearance="outline">
|
|
1647
|
-
<mat-label>Buscar ação</mat-label>
|
|
1648
|
-
<input matInput [formControl]="actionQuery" placeholder="ex: export, editar, submit" />
|
|
1649
|
-
</mat-form-field>
|
|
1650
|
-
<div class="shell-available-filters">
|
|
1651
|
-
<mat-checkbox [(ngModel)]="showScopeShell">Shell</mat-checkbox>
|
|
1652
|
-
<mat-checkbox [(ngModel)]="showScopeAny">Any</mat-checkbox>
|
|
1653
|
-
<mat-checkbox [(ngModel)]="showScopeToolbar">Toolbar</mat-checkbox>
|
|
1654
|
-
<mat-checkbox [(ngModel)]="showScopeContext">Context</mat-checkbox>
|
|
1655
|
-
</div>
|
|
1656
|
-
</div>
|
|
1657
|
-
<div class="shell-available-list">
|
|
1658
|
-
@for (action of filteredAvailableActions(); track action) {
|
|
1659
|
-
<div class="shell-available-item">
|
|
1660
|
-
<div class="shell-available-main">
|
|
1661
|
-
<div class="shell-available-title">
|
|
1662
|
-
@if (action.icon) {
|
|
1663
|
-
<mat-icon [praxisIcon]="action.icon"></mat-icon>
|
|
1664
|
-
}
|
|
1665
|
-
<div class="shell-available-text">
|
|
1666
|
-
<div class="shell-available-label">{{ action.label }}</div>
|
|
1667
|
-
<div class="shell-available-meta">
|
|
1668
|
-
<span class="shell-badge">{{ action.kind === 'command' ? 'Comando' : 'Ação' }}</span>
|
|
1669
|
-
<span class="shell-badge">{{ scopeLabel(action.scope) }}</span>
|
|
1670
|
-
<span class="shell-code">id: {{ action.id }}</span>
|
|
1671
|
-
@if (action.emit) {
|
|
1672
|
-
<span class="shell-code">emit: {{ action.emit }}</span>
|
|
1673
|
-
}
|
|
1674
|
-
@if (action.command) {
|
|
1675
|
-
<span class="shell-code">command: {{ action.command }}</span>
|
|
1676
|
-
}
|
|
1677
|
-
</div>
|
|
1678
|
-
</div>
|
|
1679
|
-
</div>
|
|
1680
|
-
@if (action.description) {
|
|
1681
|
-
<div class="shell-available-desc">{{ action.description }}</div>
|
|
1682
|
-
}
|
|
1683
|
-
@if (action.payloadExample !== undefined) {
|
|
1684
|
-
<div class="shell-available-payload">
|
|
1685
|
-
<span class="shell-code">payload: {{ stringifyPayload(action.payloadExample) }}</span>
|
|
1686
|
-
</div>
|
|
1687
|
-
}
|
|
1688
|
-
@if (action.scope === 'context') {
|
|
1689
|
-
<div class="shell-available-warning">
|
|
1690
|
-
Essa ação depende de item/linha selecionado; payload fixo pode não funcionar.
|
|
1691
|
-
</div>
|
|
1692
|
-
}
|
|
1693
|
-
</div>
|
|
1694
|
-
<div class="shell-available-actions">
|
|
1695
|
-
<button
|
|
1696
|
-
mat-stroked-button
|
|
1697
|
-
type="button"
|
|
1698
|
-
[color]="isActionSelected(action) ? 'warn' : 'primary'"
|
|
1699
|
-
(click)="toggleAvailableAction(action)"
|
|
1700
|
-
>
|
|
1701
|
-
{{ isActionSelected(action) ? 'Remover' : 'Adicionar' }}
|
|
1702
|
-
</button>
|
|
1703
|
-
</div>
|
|
1704
|
-
</div>
|
|
1705
|
-
}
|
|
1706
|
-
</div>
|
|
1707
|
-
</div>
|
|
1708
|
-
} @else {
|
|
1709
|
-
<div class="shell-empty">Nenhuma ação registrada para este componente.</div>
|
|
1710
|
-
}
|
|
1711
|
-
|
|
1712
|
-
@if (hasAvailableActions) {
|
|
1713
|
-
<mat-divider></mat-divider>
|
|
1714
|
-
}
|
|
1715
|
-
|
|
1716
|
-
@if (setInputPresets.length) {
|
|
1717
|
-
<div class="shell-section">Ações rápidas (inputs)</div>
|
|
1718
|
-
}
|
|
1719
|
-
@if (setInputPresets.length) {
|
|
1720
|
-
<div class="shell-quick-inputs">
|
|
1721
|
-
<mat-form-field appearance="outline">
|
|
1722
|
-
<mat-label>Input</mat-label>
|
|
1723
|
-
<mat-select [formControl]="setInputTarget">
|
|
1724
|
-
@for (preset of setInputPresets; track preset) {
|
|
1725
|
-
<mat-option [value]="preset.input">
|
|
1726
|
-
@if (preset.icon) {
|
|
1727
|
-
<mat-icon [praxisIcon]="preset.icon"></mat-icon>
|
|
1728
|
-
}
|
|
1729
|
-
{{ preset.label }}
|
|
1730
|
-
</mat-option>
|
|
1731
|
-
}
|
|
1732
|
-
</mat-select>
|
|
1733
|
-
</mat-form-field>
|
|
1734
|
-
@if (setInputTarget.value) {
|
|
1735
|
-
<div class="shell-input-path">
|
|
1736
|
-
Input: {{ displayInputPath(setInputTarget.value) }}
|
|
1737
|
-
</div>
|
|
1738
|
-
}
|
|
1739
|
-
<mat-form-field appearance="outline">
|
|
1740
|
-
<mat-label>Valor</mat-label>
|
|
1741
|
-
<mat-select [formControl]="setInputValue">
|
|
1742
|
-
@for (option of currentSetInputValues(); track option) {
|
|
1743
|
-
<mat-option [value]="option.value">
|
|
1744
|
-
@if (option.icon) {
|
|
1745
|
-
<mat-icon [praxisIcon]="option.icon"></mat-icon>
|
|
1746
|
-
}
|
|
1747
|
-
{{ option.label }}
|
|
1748
|
-
</mat-option>
|
|
1749
|
-
}
|
|
1750
|
-
</mat-select>
|
|
1751
|
-
</mat-form-field>
|
|
1752
|
-
<button mat-flat-button color="primary" type="button" (click)="addSetInputAction()">
|
|
1753
|
-
Adicionar ação
|
|
1754
|
-
</button>
|
|
1755
|
-
</div>
|
|
1756
|
-
}
|
|
1757
|
-
|
|
1758
|
-
<div class="shell-section shell-actions-head">
|
|
1759
|
-
<div>Ações do cabeçalho</div>
|
|
1760
|
-
<button mat-flat-button color="primary" type="button" (click)="addAction()">Adicionar ação</button>
|
|
1761
|
-
</div>
|
|
1762
|
-
|
|
1763
|
-
@if (actions.controls.length) {
|
|
1764
|
-
<div class="shell-actions">
|
|
1765
|
-
@for (action of actions.controls; track action; let i = $index) {
|
|
1766
|
-
<div class="shell-action" [formGroup]="action">
|
|
1767
|
-
<div class="shell-action-row">
|
|
1768
|
-
<mat-form-field appearance="outline">
|
|
1769
|
-
<mat-label>ID</mat-label>
|
|
1770
|
-
<input matInput formControlName="id" />
|
|
1771
|
-
</mat-form-field>
|
|
1772
|
-
<mat-form-field appearance="outline">
|
|
1773
|
-
<mat-label>Label</mat-label>
|
|
1774
|
-
<input matInput formControlName="label" />
|
|
1775
|
-
</mat-form-field>
|
|
1776
|
-
<mat-form-field appearance="outline">
|
|
1777
|
-
<mat-label>Ícone</mat-label>
|
|
1778
|
-
<input matInput formControlName="icon" />
|
|
1779
|
-
</mat-form-field>
|
|
1780
|
-
</div>
|
|
1781
|
-
<div class="shell-action-row">
|
|
1782
|
-
<mat-form-field appearance="outline">
|
|
1783
|
-
<mat-label>Variante</mat-label>
|
|
1784
|
-
<mat-select formControlName="variant">
|
|
1785
|
-
<mat-option value="text">Texto</mat-option>
|
|
1786
|
-
<mat-option value="outlined">Outlined</mat-option>
|
|
1787
|
-
<mat-option value="icon">Ícone</mat-option>
|
|
1788
|
-
</mat-select>
|
|
1789
|
-
</mat-form-field>
|
|
1790
|
-
<mat-form-field appearance="outline">
|
|
1791
|
-
<mat-label>Posição</mat-label>
|
|
1792
|
-
<mat-select formControlName="placement">
|
|
1793
|
-
<mat-option value="header">Cabeçalho</mat-option>
|
|
1794
|
-
<mat-option value="window">Janela</mat-option>
|
|
1795
|
-
</mat-select>
|
|
1796
|
-
</mat-form-field>
|
|
1797
|
-
<mat-form-field appearance="outline">
|
|
1798
|
-
<mat-label>Emit</mat-label>
|
|
1799
|
-
<input matInput formControlName="emit" placeholder="ex: editar" />
|
|
1800
|
-
</mat-form-field>
|
|
1801
|
-
<mat-form-field appearance="outline">
|
|
1802
|
-
<mat-label>Tooltip</mat-label>
|
|
1803
|
-
<input matInput formControlName="tooltip" />
|
|
1804
|
-
</mat-form-field>
|
|
1805
|
-
</div>
|
|
1806
|
-
<div class="shell-action-row">
|
|
1807
|
-
<mat-form-field appearance="outline">
|
|
1808
|
-
<mat-label>Command</mat-label>
|
|
1809
|
-
<input matInput formControlName="command" placeholder="ex: add-item" />
|
|
1810
|
-
</mat-form-field>
|
|
1811
|
-
<mat-form-field appearance="outline">
|
|
1812
|
-
<mat-label>Payload (JSON)</mat-label>
|
|
1813
|
-
<textarea matInput rows="2" formControlName="payload" placeholder='ex: {"foo":"bar"}'></textarea>
|
|
1814
|
-
</mat-form-field>
|
|
1815
|
-
<mat-checkbox formControlName="visible">Visível</mat-checkbox>
|
|
1816
|
-
<mat-checkbox formControlName="disabled">Desabilitado</mat-checkbox>
|
|
1817
|
-
</div>
|
|
1818
|
-
@if (showActionInputPath(action.value)) {
|
|
1819
|
-
<div class="shell-action-hint">
|
|
1820
|
-
Input: {{ displayInputPath(extractActionInput(action.value)) }}
|
|
1821
|
-
</div>
|
|
1822
|
-
}
|
|
1823
|
-
<div class="shell-action-actions">
|
|
1824
|
-
<button mat-stroked-button color="warn" type="button" (click)="removeAction(i)">Remover</button>
|
|
1825
|
-
</div>
|
|
1826
|
-
</div>
|
|
1827
|
-
}
|
|
1828
|
-
</div>
|
|
1829
|
-
} @else {
|
|
1830
|
-
<div class="shell-empty">Nenhuma ação configurada.</div>
|
|
1831
|
-
}
|
|
1832
|
-
|
|
1833
|
-
</div>
|
|
1834
|
-
`, isInline: true, styles: [".shell-editor{display:grid;gap:20px;padding:12px 4px 20px}.shell-intro{margin:0;max-width:68ch;color:var(--md-sys-color-on-surface-variant);font-size:14px;line-height:1.5}.shell-section{margin:4px 0 -8px;color:var(--md-sys-color-on-surface);font-size:14px;font-weight:650;line-height:1.4}.shell-grid{display:grid;gap:12px 16px;grid-template-columns:repeat(2,minmax(0,1fr));align-items:start}.shell-field--wide{grid-column:1 / -1}.shell-flags{display:flex;gap:16px;align-items:center}.shell-actions-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.shell-available{display:grid;gap:12px}.shell-available-toolbar{display:grid;gap:12px;grid-template-columns:minmax(200px,1fr)}.shell-available-filters{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.shell-available-list{display:grid;gap:10px}.shell-available-item{display:grid;gap:8px;grid-template-columns:1fr auto;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;background:var(--md-sys-color-surface-container-low)}.shell-available-title{display:flex;align-items:center;gap:10px}.shell-available-text{display:grid;gap:4px}.shell-available-label{font-weight:600}.shell-available-meta{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-available-payload{font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-warning{font-size:11px;color:var(--md-sys-color-error)}.shell-available-actions{display:flex;align-items:flex-start;justify-content:flex-end}.shell-badge{padding:2px 6px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);font-size:10px}.shell-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.shell-actions{display:grid;gap:12px}.shell-action{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;display:grid;gap:8px}.shell-action-row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.shell-action-actions{display:flex;justify-content:flex-end}.shell-action-hint,.shell-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-hint{align-self:center;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-quick-inputs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));align-items:end}.shell-input-path{font-size:12px;color:var(--md-sys-color-on-surface-variant);align-self:center}.shell-editor .mat-mdc-form-field{width:100%}.shell-preview{border:1px dashed var(--md-sys-color-outline-variant);border-radius:12px;padding:12px}.shell-preview-card{background:var(--pdx-shell-card-bg, var(--md-sys-color-surface));border:1px solid var(--pdx-shell-card-border, var(--md-sys-color-outline-variant));border-radius:var(--pdx-shell-card-radius, 14px);box-shadow:var(--pdx-shell-card-shadow, var(--mat-elevation-level2));overflow:hidden}.shell-preview-card.no-shell{background:transparent;border:none;box-shadow:none}.shell-preview-card.expanded{box-shadow:var(--pdx-shell-card-shadow, 0 16px 34px rgba(0,0,0,.32));transform:scale(1.01)}.shell-preview-header{display:flex;align-items:center;gap:12px;padding:10px 12px 8px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.shell-preview-title{display:flex;align-items:center;gap:10px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.shell-preview-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.shell-preview-text{min-width:0}.shell-preview-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 14px);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-subtitle{font-size:var(--pdx-shell-subtitle-size, 12px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-actions{display:flex;align-items:center;gap:6px}.pdx-preview-text{padding:0 8px}.pdx-preview-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-preview-label{font-size:12px;font-weight:500}.shell-preview-body{padding:var(--pdx-shell-body-padding, 10px 12px 12px 12px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit);font-size:12px}.shell-preview-body.hidden{display:none}@media(max-width:640px){.shell-editor{padding-inline:0}.shell-grid{grid-template-columns:minmax(0,1fr)}.shell-field--wide{grid-column:auto}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i6.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.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: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1835
|
-
}
|
|
1836
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: WidgetShellEditorComponent, decorators: [{
|
|
1837
|
-
type: Component,
|
|
1838
|
-
args: [{ selector: 'praxis-widget-shell-editor', standalone: true, imports: [
|
|
1839
|
-
CommonModule,
|
|
1840
|
-
FormsModule,
|
|
1841
|
-
ReactiveFormsModule,
|
|
1842
|
-
MatButtonModule,
|
|
1843
|
-
MatCheckboxModule,
|
|
1844
|
-
MatDividerModule,
|
|
1845
|
-
MatFormFieldModule,
|
|
1846
|
-
MatIconModule,
|
|
1847
|
-
MatInputModule,
|
|
1848
|
-
MatSelectModule,
|
|
1849
|
-
PraxisIconButtonComponent,
|
|
1850
|
-
PraxisIconDirective,
|
|
1851
|
-
], template: `
|
|
1852
|
-
<div class="shell-editor">
|
|
1853
|
-
<p class="shell-intro">
|
|
1854
|
-
Defina a identidade, a aparência e as ações do card. Use a prévia para conferir o resultado antes de salvar.
|
|
1855
|
-
</p>
|
|
1856
|
-
|
|
1857
|
-
<div class="shell-section">Geral</div>
|
|
1858
|
-
<div class="shell-grid">
|
|
1859
|
-
<mat-form-field appearance="outline">
|
|
1860
|
-
<mat-label>Tipo de card</mat-label>
|
|
1861
|
-
<mat-select [formControl]="form.controls.kind">
|
|
1862
|
-
<mat-option value="dashboard-card">Dashboard Card</mat-option>
|
|
1863
|
-
<mat-option value="none">Sem shell</mat-option>
|
|
1864
|
-
</mat-select>
|
|
1865
|
-
</mat-form-field>
|
|
1866
|
-
<mat-form-field appearance="outline">
|
|
1867
|
-
<mat-label>Preset</mat-label>
|
|
1868
|
-
<mat-select [formControl]="form.controls.preset">
|
|
1869
|
-
<mat-option value="">Nenhum</mat-option>
|
|
1870
|
-
@if (pagePreset) {
|
|
1871
|
-
<mat-option [value]="pagePreset">Usar preset da página ({{ pagePreset }})</mat-option>
|
|
1872
|
-
}
|
|
1873
|
-
@for (p of presetOptions; track p) {
|
|
1874
|
-
<mat-option [value]="p.id">{{ p.label }}</mat-option>
|
|
1875
|
-
}
|
|
1876
|
-
</mat-select>
|
|
1877
|
-
</mat-form-field>
|
|
1878
|
-
@if (!form.controls.preset.value && pagePreset) {
|
|
1879
|
-
<div class="shell-hint">
|
|
1880
|
-
Preset da página: {{ pagePreset }}
|
|
1881
|
-
</div>
|
|
1882
|
-
}
|
|
1883
|
-
@if (form.controls.preset.value) {
|
|
1884
|
-
<mat-checkbox [formControl]="form.controls.applyToAll">
|
|
1885
|
-
Aplicar preset como padrão da página
|
|
1886
|
-
</mat-checkbox>
|
|
1887
|
-
}
|
|
1888
|
-
<mat-form-field appearance="outline">
|
|
1889
|
-
<mat-label>Ícone</mat-label>
|
|
1890
|
-
<input matInput [formControl]="form.controls.icon" placeholder="ex: badge" />
|
|
1891
|
-
</mat-form-field>
|
|
1892
|
-
<mat-form-field appearance="outline">
|
|
1893
|
-
<mat-label>Título</mat-label>
|
|
1894
|
-
<input matInput [formControl]="form.controls.title" />
|
|
1895
|
-
</mat-form-field>
|
|
1896
|
-
<mat-form-field appearance="outline" class="shell-field--wide">
|
|
1897
|
-
<mat-label>Subtítulo</mat-label>
|
|
1898
|
-
<input matInput [formControl]="form.controls.subtitle" />
|
|
1899
|
-
</mat-form-field>
|
|
1900
|
-
<mat-form-field appearance="outline">
|
|
1901
|
-
<mat-label>Mostrar cabeçalho</mat-label>
|
|
1902
|
-
<mat-select [formControl]="form.controls.showHeader">
|
|
1903
|
-
<mat-option value="auto">Automático</mat-option>
|
|
1904
|
-
<mat-option value="true">Sempre</mat-option>
|
|
1905
|
-
<mat-option value="false">Nunca</mat-option>
|
|
1906
|
-
</mat-select>
|
|
1907
|
-
</mat-form-field>
|
|
1908
|
-
</div>
|
|
1909
|
-
|
|
1910
|
-
<div class="shell-section">Controles de janela</div>
|
|
1911
|
-
<div class="shell-flags">
|
|
1912
|
-
<mat-checkbox [formControl]="form.controls.collapsible">Permitir recolher</mat-checkbox>
|
|
1913
|
-
</div>
|
|
1914
|
-
|
|
1915
|
-
<mat-divider></mat-divider>
|
|
1916
|
-
|
|
1917
|
-
<div class="shell-section">Aparência</div>
|
|
1918
|
-
<div class="shell-grid">
|
|
1919
|
-
<mat-form-field appearance="outline">
|
|
1920
|
-
<mat-label>Fundo do card</mat-label>
|
|
1921
|
-
<input matInput [formControl]="form.controls.cardBg" placeholder="ex: #0b1220" />
|
|
1922
|
-
</mat-form-field>
|
|
1923
|
-
<mat-form-field appearance="outline">
|
|
1924
|
-
<mat-label>Cor da borda</mat-label>
|
|
1925
|
-
<input matInput [formControl]="form.controls.cardBorder" placeholder="ex: rgba(255,255,255,0.12)" />
|
|
1926
|
-
</mat-form-field>
|
|
1927
|
-
<mat-form-field appearance="outline">
|
|
1928
|
-
<mat-label>Raio da borda</mat-label>
|
|
1929
|
-
<input matInput [formControl]="form.controls.cardRadius" placeholder="ex: 14px" />
|
|
1930
|
-
</mat-form-field>
|
|
1931
|
-
<mat-form-field appearance="outline">
|
|
1932
|
-
<mat-label>Sombra</mat-label>
|
|
1933
|
-
<input matInput [formControl]="form.controls.cardShadow" placeholder="ex: 0 10px 30px rgba(0,0,0,0.2)" />
|
|
1934
|
-
</mat-form-field>
|
|
1935
|
-
<mat-form-field appearance="outline">
|
|
1936
|
-
<mat-label>Fundo do cabeçalho</mat-label>
|
|
1937
|
-
<input matInput [formControl]="form.controls.headerBg" placeholder="ex: linear-gradient(...)" />
|
|
1938
|
-
</mat-form-field>
|
|
1939
|
-
<mat-form-field appearance="outline">
|
|
1940
|
-
<mat-label>Borda do cabeçalho</mat-label>
|
|
1941
|
-
<input matInput [formControl]="form.controls.headerBorder" placeholder="ex: rgba(255,255,255,0.08)" />
|
|
1942
|
-
</mat-form-field>
|
|
1943
|
-
<mat-form-field appearance="outline">
|
|
1944
|
-
<mat-label>Cor do título</mat-label>
|
|
1945
|
-
<input matInput [formControl]="form.controls.titleColor" placeholder="ex: #e6edf3" />
|
|
1946
|
-
</mat-form-field>
|
|
1947
|
-
<mat-form-field appearance="outline">
|
|
1948
|
-
<mat-label>Cor do subtítulo</mat-label>
|
|
1949
|
-
<input matInput [formControl]="form.controls.subtitleColor" placeholder="ex: #9fb0c4" />
|
|
1950
|
-
</mat-form-field>
|
|
1951
|
-
<mat-form-field appearance="outline">
|
|
1952
|
-
<mat-label>Cor do ícone</mat-label>
|
|
1953
|
-
<input matInput [formControl]="form.controls.iconColor" placeholder="ex: #8ab4ff" />
|
|
1954
|
-
</mat-form-field>
|
|
1955
|
-
<mat-form-field appearance="outline">
|
|
1956
|
-
<mat-label>Fundo do corpo</mat-label>
|
|
1957
|
-
<input matInput [formControl]="form.controls.bodyBg" placeholder="ex: transparent" />
|
|
1958
|
-
</mat-form-field>
|
|
1959
|
-
<mat-form-field appearance="outline">
|
|
1960
|
-
<mat-label>Cor do texto do corpo</mat-label>
|
|
1961
|
-
<input matInput [formControl]="form.controls.bodyColor" placeholder="ex: #e6edf3" />
|
|
1962
|
-
</mat-form-field>
|
|
1963
|
-
<mat-form-field appearance="outline">
|
|
1964
|
-
<mat-label>Padding do corpo</mat-label>
|
|
1965
|
-
<input matInput [formControl]="form.controls.bodyPadding" placeholder="ex: 10px 12px 12px" />
|
|
1966
|
-
</mat-form-field>
|
|
1967
|
-
<mat-form-field appearance="outline">
|
|
1968
|
-
<mat-label>Tamanho do título</mat-label>
|
|
1969
|
-
<input matInput [formControl]="form.controls.titleSize" placeholder="ex: 14px" />
|
|
1970
|
-
</mat-form-field>
|
|
1971
|
-
<mat-form-field appearance="outline">
|
|
1972
|
-
<mat-label>Peso do título</mat-label>
|
|
1973
|
-
<input matInput [formControl]="form.controls.titleWeight" placeholder="ex: 600" />
|
|
1974
|
-
</mat-form-field>
|
|
1975
|
-
<mat-form-field appearance="outline">
|
|
1976
|
-
<mat-label>Tamanho do subtítulo</mat-label>
|
|
1977
|
-
<input matInput [formControl]="form.controls.subtitleSize" placeholder="ex: 12px" />
|
|
1978
|
-
</mat-form-field>
|
|
1979
|
-
</div>
|
|
1980
|
-
|
|
1981
|
-
<div class="shell-preview" [ngStyle]="previewVars()">
|
|
1982
|
-
<div class="shell-preview-card" [class.no-shell]="form.controls.kind.value === 'none'" [class.expanded]="previewExpanded">
|
|
1983
|
-
@if (previewShowHeader()) {
|
|
1984
|
-
<div class="shell-preview-header">
|
|
1985
|
-
<div class="shell-preview-title">
|
|
1986
|
-
@if (form.controls.icon.value) {
|
|
1987
|
-
<mat-icon [praxisIcon]="form.controls.icon.value"></mat-icon>
|
|
1988
|
-
}
|
|
1989
|
-
<div class="shell-preview-text">
|
|
1990
|
-
<div class="shell-preview-title-text">{{ previewTitle() }}</div>
|
|
1991
|
-
<div class="shell-preview-subtitle">{{ previewSubtitle() }}</div>
|
|
1992
|
-
</div>
|
|
1993
|
-
</div>
|
|
1994
|
-
<div class="shell-preview-actions">
|
|
1995
|
-
@for (action of previewHeaderActions(); track action.id) {
|
|
1996
|
-
<button
|
|
1997
|
-
type="button"
|
|
1998
|
-
[disabled]="action.disabled"
|
|
1999
|
-
[ngClass]="action.variant === 'outlined' ? 'pdx-preview-outlined' : 'pdx-preview-text'"
|
|
2000
|
-
mat-button
|
|
2001
|
-
>
|
|
2002
|
-
@if (action.icon) {
|
|
2003
|
-
<mat-icon [praxisIcon]="action.icon"></mat-icon>
|
|
2004
|
-
}
|
|
2005
|
-
<span class="pdx-preview-label">{{ action.label || action.id }}</span>
|
|
2006
|
-
</button>
|
|
2007
|
-
}
|
|
2008
|
-
@if (previewOverflowCount()) {
|
|
2009
|
-
<button
|
|
2010
|
-
praxisIconButton="more_horiz"
|
|
2011
|
-
size="compact"
|
|
2012
|
-
type="button"
|
|
2013
|
-
aria-label="Mais ações"
|
|
2014
|
-
></button>
|
|
2015
|
-
}
|
|
2016
|
-
@for (action of previewWindowActions(); track action.id) {
|
|
2017
|
-
@if (action.icon) {
|
|
2018
|
-
<button
|
|
2019
|
-
[praxisIconButton]="action.icon"
|
|
2020
|
-
size="compact"
|
|
2021
|
-
type="button"
|
|
2022
|
-
[disabled]="action.disabled"
|
|
2023
|
-
[attr.aria-label]="action.label || action.id"
|
|
2024
|
-
></button>
|
|
2025
|
-
}
|
|
2026
|
-
}
|
|
2027
|
-
<button
|
|
2028
|
-
[praxisIconButton]="previewCollapsed ? 'unfold_more' : 'unfold_less'"
|
|
2029
|
-
size="compact"
|
|
2030
|
-
type="button"
|
|
2031
|
-
(click)="togglePreviewCollapse()"
|
|
2032
|
-
aria-label="Recolher"
|
|
2033
|
-
></button>
|
|
2034
|
-
<button
|
|
2035
|
-
[praxisIconButton]="previewExpanded ? 'close_fullscreen' : 'open_in_full'"
|
|
2036
|
-
size="compact"
|
|
2037
|
-
type="button"
|
|
2038
|
-
(click)="togglePreviewExpand()"
|
|
2039
|
-
aria-label="Expandir"
|
|
2040
|
-
></button>
|
|
2041
|
-
</div>
|
|
2042
|
-
</div>
|
|
2043
|
-
}
|
|
2044
|
-
<div class="shell-preview-body" [class.hidden]="previewCollapsed">Conteudo do widget</div>
|
|
2045
|
-
</div>
|
|
2046
|
-
</div>
|
|
2047
|
-
|
|
2048
|
-
<mat-divider></mat-divider>
|
|
2049
|
-
|
|
2050
|
-
@if (hasAvailableActions) {
|
|
2051
|
-
<div class="shell-section">Ações disponíveis</div>
|
|
2052
|
-
}
|
|
2053
|
-
@if (hasAvailableActions) {
|
|
2054
|
-
<div class="shell-available">
|
|
2055
|
-
<div class="shell-available-toolbar">
|
|
2056
|
-
<mat-form-field appearance="outline">
|
|
2057
|
-
<mat-label>Buscar ação</mat-label>
|
|
2058
|
-
<input matInput [formControl]="actionQuery" placeholder="ex: export, editar, submit" />
|
|
2059
|
-
</mat-form-field>
|
|
2060
|
-
<div class="shell-available-filters">
|
|
2061
|
-
<mat-checkbox [(ngModel)]="showScopeShell">Shell</mat-checkbox>
|
|
2062
|
-
<mat-checkbox [(ngModel)]="showScopeAny">Any</mat-checkbox>
|
|
2063
|
-
<mat-checkbox [(ngModel)]="showScopeToolbar">Toolbar</mat-checkbox>
|
|
2064
|
-
<mat-checkbox [(ngModel)]="showScopeContext">Context</mat-checkbox>
|
|
2065
|
-
</div>
|
|
2066
|
-
</div>
|
|
2067
|
-
<div class="shell-available-list">
|
|
2068
|
-
@for (action of filteredAvailableActions(); track action) {
|
|
2069
|
-
<div class="shell-available-item">
|
|
2070
|
-
<div class="shell-available-main">
|
|
2071
|
-
<div class="shell-available-title">
|
|
2072
|
-
@if (action.icon) {
|
|
2073
|
-
<mat-icon [praxisIcon]="action.icon"></mat-icon>
|
|
2074
|
-
}
|
|
2075
|
-
<div class="shell-available-text">
|
|
2076
|
-
<div class="shell-available-label">{{ action.label }}</div>
|
|
2077
|
-
<div class="shell-available-meta">
|
|
2078
|
-
<span class="shell-badge">{{ action.kind === 'command' ? 'Comando' : 'Ação' }}</span>
|
|
2079
|
-
<span class="shell-badge">{{ scopeLabel(action.scope) }}</span>
|
|
2080
|
-
<span class="shell-code">id: {{ action.id }}</span>
|
|
2081
|
-
@if (action.emit) {
|
|
2082
|
-
<span class="shell-code">emit: {{ action.emit }}</span>
|
|
2083
|
-
}
|
|
2084
|
-
@if (action.command) {
|
|
2085
|
-
<span class="shell-code">command: {{ action.command }}</span>
|
|
2086
|
-
}
|
|
2087
|
-
</div>
|
|
2088
|
-
</div>
|
|
2089
|
-
</div>
|
|
2090
|
-
@if (action.description) {
|
|
2091
|
-
<div class="shell-available-desc">{{ action.description }}</div>
|
|
2092
|
-
}
|
|
2093
|
-
@if (action.payloadExample !== undefined) {
|
|
2094
|
-
<div class="shell-available-payload">
|
|
2095
|
-
<span class="shell-code">payload: {{ stringifyPayload(action.payloadExample) }}</span>
|
|
2096
|
-
</div>
|
|
2097
|
-
}
|
|
2098
|
-
@if (action.scope === 'context') {
|
|
2099
|
-
<div class="shell-available-warning">
|
|
2100
|
-
Essa ação depende de item/linha selecionado; payload fixo pode não funcionar.
|
|
2101
|
-
</div>
|
|
2102
|
-
}
|
|
2103
|
-
</div>
|
|
2104
|
-
<div class="shell-available-actions">
|
|
2105
|
-
<button
|
|
2106
|
-
mat-stroked-button
|
|
2107
|
-
type="button"
|
|
2108
|
-
[color]="isActionSelected(action) ? 'warn' : 'primary'"
|
|
2109
|
-
(click)="toggleAvailableAction(action)"
|
|
2110
|
-
>
|
|
2111
|
-
{{ isActionSelected(action) ? 'Remover' : 'Adicionar' }}
|
|
2112
|
-
</button>
|
|
2113
|
-
</div>
|
|
2114
|
-
</div>
|
|
2115
|
-
}
|
|
2116
|
-
</div>
|
|
2117
|
-
</div>
|
|
2118
|
-
} @else {
|
|
2119
|
-
<div class="shell-empty">Nenhuma ação registrada para este componente.</div>
|
|
2120
|
-
}
|
|
2121
|
-
|
|
2122
|
-
@if (hasAvailableActions) {
|
|
2123
|
-
<mat-divider></mat-divider>
|
|
2124
|
-
}
|
|
2125
|
-
|
|
2126
|
-
@if (setInputPresets.length) {
|
|
2127
|
-
<div class="shell-section">Ações rápidas (inputs)</div>
|
|
2128
|
-
}
|
|
2129
|
-
@if (setInputPresets.length) {
|
|
2130
|
-
<div class="shell-quick-inputs">
|
|
2131
|
-
<mat-form-field appearance="outline">
|
|
2132
|
-
<mat-label>Input</mat-label>
|
|
2133
|
-
<mat-select [formControl]="setInputTarget">
|
|
2134
|
-
@for (preset of setInputPresets; track preset) {
|
|
2135
|
-
<mat-option [value]="preset.input">
|
|
2136
|
-
@if (preset.icon) {
|
|
2137
|
-
<mat-icon [praxisIcon]="preset.icon"></mat-icon>
|
|
2138
|
-
}
|
|
2139
|
-
{{ preset.label }}
|
|
2140
|
-
</mat-option>
|
|
2141
|
-
}
|
|
2142
|
-
</mat-select>
|
|
2143
|
-
</mat-form-field>
|
|
2144
|
-
@if (setInputTarget.value) {
|
|
2145
|
-
<div class="shell-input-path">
|
|
2146
|
-
Input: {{ displayInputPath(setInputTarget.value) }}
|
|
2147
|
-
</div>
|
|
2148
|
-
}
|
|
2149
|
-
<mat-form-field appearance="outline">
|
|
2150
|
-
<mat-label>Valor</mat-label>
|
|
2151
|
-
<mat-select [formControl]="setInputValue">
|
|
2152
|
-
@for (option of currentSetInputValues(); track option) {
|
|
2153
|
-
<mat-option [value]="option.value">
|
|
2154
|
-
@if (option.icon) {
|
|
2155
|
-
<mat-icon [praxisIcon]="option.icon"></mat-icon>
|
|
2156
|
-
}
|
|
2157
|
-
{{ option.label }}
|
|
2158
|
-
</mat-option>
|
|
2159
|
-
}
|
|
2160
|
-
</mat-select>
|
|
2161
|
-
</mat-form-field>
|
|
2162
|
-
<button mat-flat-button color="primary" type="button" (click)="addSetInputAction()">
|
|
2163
|
-
Adicionar ação
|
|
2164
|
-
</button>
|
|
2165
|
-
</div>
|
|
2166
|
-
}
|
|
2167
|
-
|
|
2168
|
-
<div class="shell-section shell-actions-head">
|
|
2169
|
-
<div>Ações do cabeçalho</div>
|
|
2170
|
-
<button mat-flat-button color="primary" type="button" (click)="addAction()">Adicionar ação</button>
|
|
2171
|
-
</div>
|
|
2172
|
-
|
|
2173
|
-
@if (actions.controls.length) {
|
|
2174
|
-
<div class="shell-actions">
|
|
2175
|
-
@for (action of actions.controls; track action; let i = $index) {
|
|
2176
|
-
<div class="shell-action" [formGroup]="action">
|
|
2177
|
-
<div class="shell-action-row">
|
|
2178
|
-
<mat-form-field appearance="outline">
|
|
2179
|
-
<mat-label>ID</mat-label>
|
|
2180
|
-
<input matInput formControlName="id" />
|
|
2181
|
-
</mat-form-field>
|
|
2182
|
-
<mat-form-field appearance="outline">
|
|
2183
|
-
<mat-label>Label</mat-label>
|
|
2184
|
-
<input matInput formControlName="label" />
|
|
2185
|
-
</mat-form-field>
|
|
2186
|
-
<mat-form-field appearance="outline">
|
|
2187
|
-
<mat-label>Ícone</mat-label>
|
|
2188
|
-
<input matInput formControlName="icon" />
|
|
2189
|
-
</mat-form-field>
|
|
2190
|
-
</div>
|
|
2191
|
-
<div class="shell-action-row">
|
|
2192
|
-
<mat-form-field appearance="outline">
|
|
2193
|
-
<mat-label>Variante</mat-label>
|
|
2194
|
-
<mat-select formControlName="variant">
|
|
2195
|
-
<mat-option value="text">Texto</mat-option>
|
|
2196
|
-
<mat-option value="outlined">Outlined</mat-option>
|
|
2197
|
-
<mat-option value="icon">Ícone</mat-option>
|
|
2198
|
-
</mat-select>
|
|
2199
|
-
</mat-form-field>
|
|
2200
|
-
<mat-form-field appearance="outline">
|
|
2201
|
-
<mat-label>Posição</mat-label>
|
|
2202
|
-
<mat-select formControlName="placement">
|
|
2203
|
-
<mat-option value="header">Cabeçalho</mat-option>
|
|
2204
|
-
<mat-option value="window">Janela</mat-option>
|
|
2205
|
-
</mat-select>
|
|
2206
|
-
</mat-form-field>
|
|
2207
|
-
<mat-form-field appearance="outline">
|
|
2208
|
-
<mat-label>Emit</mat-label>
|
|
2209
|
-
<input matInput formControlName="emit" placeholder="ex: editar" />
|
|
2210
|
-
</mat-form-field>
|
|
2211
|
-
<mat-form-field appearance="outline">
|
|
2212
|
-
<mat-label>Tooltip</mat-label>
|
|
2213
|
-
<input matInput formControlName="tooltip" />
|
|
2214
|
-
</mat-form-field>
|
|
2215
|
-
</div>
|
|
2216
|
-
<div class="shell-action-row">
|
|
2217
|
-
<mat-form-field appearance="outline">
|
|
2218
|
-
<mat-label>Command</mat-label>
|
|
2219
|
-
<input matInput formControlName="command" placeholder="ex: add-item" />
|
|
2220
|
-
</mat-form-field>
|
|
2221
|
-
<mat-form-field appearance="outline">
|
|
2222
|
-
<mat-label>Payload (JSON)</mat-label>
|
|
2223
|
-
<textarea matInput rows="2" formControlName="payload" placeholder='ex: {"foo":"bar"}'></textarea>
|
|
2224
|
-
</mat-form-field>
|
|
2225
|
-
<mat-checkbox formControlName="visible">Visível</mat-checkbox>
|
|
2226
|
-
<mat-checkbox formControlName="disabled">Desabilitado</mat-checkbox>
|
|
2227
|
-
</div>
|
|
2228
|
-
@if (showActionInputPath(action.value)) {
|
|
2229
|
-
<div class="shell-action-hint">
|
|
2230
|
-
Input: {{ displayInputPath(extractActionInput(action.value)) }}
|
|
2231
|
-
</div>
|
|
2232
|
-
}
|
|
2233
|
-
<div class="shell-action-actions">
|
|
2234
|
-
<button mat-stroked-button color="warn" type="button" (click)="removeAction(i)">Remover</button>
|
|
2235
|
-
</div>
|
|
2236
|
-
</div>
|
|
2237
|
-
}
|
|
2238
|
-
</div>
|
|
2239
|
-
} @else {
|
|
2240
|
-
<div class="shell-empty">Nenhuma ação configurada.</div>
|
|
2241
|
-
}
|
|
2242
|
-
|
|
2243
|
-
</div>
|
|
2244
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".shell-editor{display:grid;gap:20px;padding:12px 4px 20px}.shell-intro{margin:0;max-width:68ch;color:var(--md-sys-color-on-surface-variant);font-size:14px;line-height:1.5}.shell-section{margin:4px 0 -8px;color:var(--md-sys-color-on-surface);font-size:14px;font-weight:650;line-height:1.4}.shell-grid{display:grid;gap:12px 16px;grid-template-columns:repeat(2,minmax(0,1fr));align-items:start}.shell-field--wide{grid-column:1 / -1}.shell-flags{display:flex;gap:16px;align-items:center}.shell-actions-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.shell-available{display:grid;gap:12px}.shell-available-toolbar{display:grid;gap:12px;grid-template-columns:minmax(200px,1fr)}.shell-available-filters{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.shell-available-list{display:grid;gap:10px}.shell-available-item{display:grid;gap:8px;grid-template-columns:1fr auto;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;background:var(--md-sys-color-surface-container-low)}.shell-available-title{display:flex;align-items:center;gap:10px}.shell-available-text{display:grid;gap:4px}.shell-available-label{font-weight:600}.shell-available-meta{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-available-payload{font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-warning{font-size:11px;color:var(--md-sys-color-error)}.shell-available-actions{display:flex;align-items:flex-start;justify-content:flex-end}.shell-badge{padding:2px 6px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);font-size:10px}.shell-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.shell-actions{display:grid;gap:12px}.shell-action{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;display:grid;gap:8px}.shell-action-row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.shell-action-actions{display:flex;justify-content:flex-end}.shell-action-hint,.shell-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-hint{align-self:center;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-quick-inputs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));align-items:end}.shell-input-path{font-size:12px;color:var(--md-sys-color-on-surface-variant);align-self:center}.shell-editor .mat-mdc-form-field{width:100%}.shell-preview{border:1px dashed var(--md-sys-color-outline-variant);border-radius:12px;padding:12px}.shell-preview-card{background:var(--pdx-shell-card-bg, var(--md-sys-color-surface));border:1px solid var(--pdx-shell-card-border, var(--md-sys-color-outline-variant));border-radius:var(--pdx-shell-card-radius, 14px);box-shadow:var(--pdx-shell-card-shadow, var(--mat-elevation-level2));overflow:hidden}.shell-preview-card.no-shell{background:transparent;border:none;box-shadow:none}.shell-preview-card.expanded{box-shadow:var(--pdx-shell-card-shadow, 0 16px 34px rgba(0,0,0,.32));transform:scale(1.01)}.shell-preview-header{display:flex;align-items:center;gap:12px;padding:10px 12px 8px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.shell-preview-title{display:flex;align-items:center;gap:10px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.shell-preview-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.shell-preview-text{min-width:0}.shell-preview-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 14px);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-subtitle{font-size:var(--pdx-shell-subtitle-size, 12px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-actions{display:flex;align-items:center;gap:6px}.pdx-preview-text{padding:0 8px}.pdx-preview-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-preview-label{font-size:12px;font-weight:500}.shell-preview-body{padding:var(--pdx-shell-body-padding, 10px 12px 12px 12px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit);font-size:12px}.shell-preview-body.hidden{display:none}@media(max-width:640px){.shell-editor{padding-inline:0}.shell-grid{grid-template-columns:minmax(0,1fr)}.shell-field--wide{grid-column:auto}}\n"] }]
|
|
2245
|
-
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
2246
|
-
type: Optional
|
|
2247
|
-
}, {
|
|
2248
|
-
type: Inject,
|
|
2249
|
-
args: [SETTINGS_PANEL_DATA]
|
|
2250
|
-
}] }, { type: i2$2.ComponentMetadataRegistry, decorators: [{
|
|
2251
|
-
type: Optional
|
|
2252
|
-
}] }] });
|
|
2253
|
-
|
|
2254
|
-
function buildConnectionsViewerModel(page) {
|
|
2255
|
-
const widgets = page?.widgets ?? [];
|
|
2256
|
-
const links = page?.composition?.links ?? [];
|
|
2257
|
-
const counts = new Map();
|
|
2258
|
-
for (const widget of widgets) {
|
|
2259
|
-
counts.set(widget.key, { incoming: 0, outgoing: 0 });
|
|
2260
|
-
}
|
|
2261
|
-
const edges = links.map((link) => {
|
|
2262
|
-
const fromWidgetId = link.from.kind === 'component-port' ? link.from.ref.widget : null;
|
|
2263
|
-
const toWidgetId = link.to.kind === 'component-port' ? link.to.ref.widget : null;
|
|
2264
|
-
const fromNestedPath = link.from.kind === 'component-port' && link.from.ref.nestedPath?.length
|
|
2265
|
-
? clone$2(link.from.ref.nestedPath)
|
|
2266
|
-
: null;
|
|
2267
|
-
const toNestedPath = link.to.kind === 'component-port' && link.to.ref.nestedPath?.length
|
|
2268
|
-
? clone$2(link.to.ref.nestedPath)
|
|
2269
|
-
: null;
|
|
2270
|
-
const toStatePath = link.to.kind === 'state' ? link.to.ref.path : null;
|
|
2271
|
-
const diagnosticReasons = [];
|
|
2272
|
-
if (fromWidgetId && !counts.has(fromWidgetId)) {
|
|
2273
|
-
diagnosticReasons.push('missing-source-widget');
|
|
2274
|
-
}
|
|
2275
|
-
if (toWidgetId && !counts.has(toWidgetId)) {
|
|
2276
|
-
diagnosticReasons.push('missing-target-widget');
|
|
2277
|
-
}
|
|
2278
|
-
if (fromWidgetId) {
|
|
2279
|
-
const current = counts.get(fromWidgetId) ?? { incoming: 0, outgoing: 0 };
|
|
2280
|
-
current.outgoing += 1;
|
|
2281
|
-
counts.set(fromWidgetId, current);
|
|
2282
|
-
}
|
|
2283
|
-
if (toWidgetId) {
|
|
2284
|
-
const current = counts.get(toWidgetId) ?? { incoming: 0, outgoing: 0 };
|
|
2285
|
-
current.incoming += 1;
|
|
2286
|
-
counts.set(toWidgetId, current);
|
|
2287
|
-
}
|
|
2288
|
-
return {
|
|
2289
|
-
id: link.id,
|
|
2290
|
-
fromKind: link.from.kind,
|
|
2291
|
-
fromWidgetId,
|
|
2292
|
-
fromEndpointId: link.from.kind === 'component-port'
|
|
2293
|
-
? buildComponentEndpointId(link.from.ref.widget, link.from.ref.nestedPath)
|
|
2294
|
-
: null,
|
|
2295
|
-
fromNestedPath,
|
|
2296
|
-
fromPort: link.from.kind === 'component-port' ? link.from.ref.port : null,
|
|
2297
|
-
toKind: link.to.kind,
|
|
2298
|
-
toWidgetId,
|
|
2299
|
-
toEndpointId: link.to.kind === 'component-port'
|
|
2300
|
-
? buildComponentEndpointId(link.to.ref.widget, link.to.ref.nestedPath)
|
|
2301
|
-
: null,
|
|
2302
|
-
toNestedPath,
|
|
2303
|
-
toPort: link.to.kind === 'component-port' ? link.to.ref.port : null,
|
|
2304
|
-
toStatePath,
|
|
2305
|
-
intent: link.intent,
|
|
2306
|
-
hasCondition: !!link.condition,
|
|
2307
|
-
hasTransform: !!link.transform?.steps?.length,
|
|
2308
|
-
hasPolicy: !!link.policy && Object.keys(link.policy).length > 0,
|
|
2309
|
-
hasDiagnostics: diagnosticReasons.length > 0,
|
|
2310
|
-
diagnosticReasons,
|
|
2311
|
-
link,
|
|
2312
|
-
};
|
|
2313
|
-
});
|
|
2314
|
-
const nodes = widgets.map((widget) => {
|
|
2315
|
-
const counter = counts.get(widget.key) ?? { incoming: 0, outgoing: 0 };
|
|
2316
|
-
return {
|
|
2317
|
-
widgetId: widget.key,
|
|
2318
|
-
componentType: widget.definition?.id ?? 'unknown',
|
|
2319
|
-
incomingCount: counter.incoming,
|
|
2320
|
-
outgoingCount: counter.outgoing,
|
|
2321
|
-
};
|
|
2322
|
-
});
|
|
2323
|
-
return {
|
|
2324
|
-
nodes,
|
|
2325
|
-
edges,
|
|
2326
|
-
totalLinks: edges.length,
|
|
2327
|
-
conditionLinks: edges.filter((edge) => edge.hasCondition).length,
|
|
2328
|
-
transformLinks: edges.filter((edge) => edge.hasTransform).length,
|
|
2329
|
-
policyLinks: edges.filter((edge) => edge.hasPolicy).length,
|
|
2330
|
-
diagnosticLinks: edges.filter((edge) => edge.hasDiagnostics).length,
|
|
2331
|
-
};
|
|
2332
|
-
}
|
|
2333
|
-
function buildComponentEndpointId(ownerWidgetKey, nestedPath) {
|
|
2334
|
-
if (!nestedPath?.length) {
|
|
2335
|
-
return ownerWidgetKey;
|
|
2336
|
-
}
|
|
2337
|
-
return `${ownerWidgetKey}${nestedPath
|
|
2338
|
-
.map((segment) => `/${formatPathSegment$1(segment)}`)
|
|
2339
|
-
.join('')}`;
|
|
2340
|
-
}
|
|
2341
|
-
function formatPathSegment$1(segment) {
|
|
2342
|
-
if (segment.kind === 'widget') {
|
|
2343
|
-
const identity = segment.key
|
|
2344
|
-
|| segment.componentType
|
|
2345
|
-
|| (typeof segment.index === 'number' ? String(segment.index) : 'unknown');
|
|
2346
|
-
return `widget:${identity}`;
|
|
2347
|
-
}
|
|
2348
|
-
return [
|
|
2349
|
-
segment.kind,
|
|
2350
|
-
segment.id || segment.key || segment.index,
|
|
2351
|
-
].filter((part) => part !== undefined && part !== '').join(':');
|
|
2352
|
-
}
|
|
2353
|
-
function clone$2(value) {
|
|
2354
|
-
if (value == null || typeof value !== 'object')
|
|
2355
|
-
return value;
|
|
2356
|
-
return JSON.parse(JSON.stringify(value));
|
|
2357
|
-
}
|
|
2358
|
-
|
|
2359
348
|
const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
2360
349
|
'praxis.pageBuilder.editor.title': 'Page settings',
|
|
2361
350
|
'praxis.pageBuilder.editor.subtitle': 'Define layout, themes, grouping and declarative state without leaving the canonical dynamic page flow.',
|
|
@@ -2515,6 +504,33 @@ const PRAXIS_PAGE_BUILDER_EN_US = {
|
|
|
2515
504
|
'praxis.pageBuilder.editor.preview.deviceCanvasHint': 'Existing canvas item overrides are preserved.',
|
|
2516
505
|
'praxis.pageBuilder.toolbar.preview': 'Preview',
|
|
2517
506
|
'praxis.pageBuilder.toolbar.exitPreview': 'Back to editing',
|
|
507
|
+
'praxis.pageBuilder.toolbar.add': 'Insert component',
|
|
508
|
+
'praxis.pageBuilder.toolbar.save': 'Save page',
|
|
509
|
+
'praxis.pageBuilder.toolbar.undo': 'Undo',
|
|
510
|
+
'praxis.pageBuilder.toolbar.redo': 'Redo',
|
|
511
|
+
'praxis.pageBuilder.toolbar.settings': 'Page settings',
|
|
512
|
+
'praxis.pageBuilder.palette.title': 'Insert component',
|
|
513
|
+
'praxis.pageBuilder.palette.subtitle': 'Choose a component to add to the page',
|
|
514
|
+
'praxis.pageBuilder.palette.available': 'available',
|
|
515
|
+
'praxis.pageBuilder.palette.searchLabel': 'Search components',
|
|
516
|
+
'praxis.pageBuilder.palette.searchPlaceholder': 'Name, capability, or readiness',
|
|
517
|
+
'praxis.pageBuilder.palette.addAria': 'Add',
|
|
518
|
+
'praxis.pageBuilder.palette.empty': 'No components available',
|
|
519
|
+
'praxis.pageBuilder.palette.cancel': 'Cancel',
|
|
520
|
+
'praxis.pageBuilder.palette.badges.configEditor.label': 'Config editor',
|
|
521
|
+
'praxis.pageBuilder.palette.badges.configEditor.description': 'Publishes a canonical settings-panel editor for its input contract.',
|
|
522
|
+
'praxis.pageBuilder.palette.badges.aiAuthoring.label': 'AI authoring',
|
|
523
|
+
'praxis.pageBuilder.palette.badges.aiAuthoring.description': 'Publishes a canonical AI authoring manifest for governed changes.',
|
|
524
|
+
'praxis.pageBuilder.palette.badges.governed.label': 'Governed',
|
|
525
|
+
'praxis.pageBuilder.palette.badges.governed.description': 'Exposes semantic ports, actions, or commands for governed composition.',
|
|
526
|
+
'praxis.pageBuilder.palette.badges.preset.label': 'Preset',
|
|
527
|
+
'praxis.pageBuilder.palette.badges.preset.description': 'Inserts a curated preset without changing the component contract.',
|
|
528
|
+
'praxis.pageBuilder.palette.badges.dataSource.label': 'Data source',
|
|
529
|
+
'praxis.pageBuilder.palette.badges.dataSource.description': 'Uses schema, API, resource, or dataset context.',
|
|
530
|
+
'praxis.pageBuilder.palette.badges.legacy.label': 'Legacy',
|
|
531
|
+
'praxis.pageBuilder.palette.badges.legacy.description': 'Retained for compatibility; avoid as the default for new canonical authoring.',
|
|
532
|
+
'praxis.pageBuilder.palette.badges.hostDemo.label': 'Host/demo',
|
|
533
|
+
'praxis.pageBuilder.palette.badges.hostDemo.description': 'Depends on host/demo semantics and may need governance before public reuse.',
|
|
2518
534
|
'praxis.pageBuilder.builderMode.editing': 'Editing',
|
|
2519
535
|
'praxis.pageBuilder.builderMode.connections': 'Connections',
|
|
2520
536
|
'praxis.pageBuilder.builderMode.ai': 'AI',
|
|
@@ -3142,6 +1158,33 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
3142
1158
|
'praxis.pageBuilder.editor.preview.deviceCanvasHint': 'Sobrescritas existentes dos itens do canvas são preservadas.',
|
|
3143
1159
|
'praxis.pageBuilder.toolbar.preview': 'Pré-visualizar',
|
|
3144
1160
|
'praxis.pageBuilder.toolbar.exitPreview': 'Voltar para edição',
|
|
1161
|
+
'praxis.pageBuilder.toolbar.add': 'Inserir componente',
|
|
1162
|
+
'praxis.pageBuilder.toolbar.save': 'Salvar página',
|
|
1163
|
+
'praxis.pageBuilder.toolbar.undo': 'Desfazer',
|
|
1164
|
+
'praxis.pageBuilder.toolbar.redo': 'Refazer',
|
|
1165
|
+
'praxis.pageBuilder.toolbar.settings': 'Configurações da página',
|
|
1166
|
+
'praxis.pageBuilder.palette.title': 'Inserir componente',
|
|
1167
|
+
'praxis.pageBuilder.palette.subtitle': 'Escolha um componente para adicionar à página',
|
|
1168
|
+
'praxis.pageBuilder.palette.available': 'disponíveis',
|
|
1169
|
+
'praxis.pageBuilder.palette.searchLabel': 'Buscar componentes',
|
|
1170
|
+
'praxis.pageBuilder.palette.searchPlaceholder': 'Nome, capacidade ou prontidão',
|
|
1171
|
+
'praxis.pageBuilder.palette.addAria': 'Adicionar',
|
|
1172
|
+
'praxis.pageBuilder.palette.empty': 'Nenhum componente disponível',
|
|
1173
|
+
'praxis.pageBuilder.palette.cancel': 'Cancelar',
|
|
1174
|
+
'praxis.pageBuilder.palette.badges.configEditor.label': 'Editor de configuração',
|
|
1175
|
+
'praxis.pageBuilder.palette.badges.configEditor.description': 'Publica um editor canônico de configurações para o contrato de inputs.',
|
|
1176
|
+
'praxis.pageBuilder.palette.badges.aiAuthoring.label': 'Autoria com IA',
|
|
1177
|
+
'praxis.pageBuilder.palette.badges.aiAuthoring.description': 'Publica um manifesto canônico de autoria por IA para mudanças governadas.',
|
|
1178
|
+
'praxis.pageBuilder.palette.badges.governed.label': 'Governado',
|
|
1179
|
+
'praxis.pageBuilder.palette.badges.governed.description': 'Expõe portas, ações ou comandos semânticos para composição governada.',
|
|
1180
|
+
'praxis.pageBuilder.palette.badges.preset.label': 'Predefinição',
|
|
1181
|
+
'praxis.pageBuilder.palette.badges.preset.description': 'Insere uma predefinição curada sem alterar o contrato do componente.',
|
|
1182
|
+
'praxis.pageBuilder.palette.badges.dataSource.label': 'Fonte de dados',
|
|
1183
|
+
'praxis.pageBuilder.palette.badges.dataSource.description': 'Usa contexto de schema, API, recurso ou conjunto de dados.',
|
|
1184
|
+
'praxis.pageBuilder.palette.badges.legacy.label': 'Legado',
|
|
1185
|
+
'praxis.pageBuilder.palette.badges.legacy.description': 'Mantido por compatibilidade; evite como padrão em nova autoria canônica.',
|
|
1186
|
+
'praxis.pageBuilder.palette.badges.hostDemo.label': 'Host/demo',
|
|
1187
|
+
'praxis.pageBuilder.palette.badges.hostDemo.description': 'Depende de semântica do host/demo e pode exigir governança antes do reúso público.',
|
|
3145
1188
|
'praxis.pageBuilder.builderMode.editing': 'Edição',
|
|
3146
1189
|
'praxis.pageBuilder.builderMode.connections': 'Conexões',
|
|
3147
1190
|
'praxis.pageBuilder.builderMode.ai': 'IA',
|
|
@@ -3610,36 +1653,2067 @@ const PRAXIS_PAGE_BUILDER_PT_BR = {
|
|
|
3610
1653
|
'praxis.pageBuilder.agentic.errors.generic': 'Falha na autoria com IA.',
|
|
3611
1654
|
};
|
|
3612
1655
|
|
|
3613
|
-
function createPraxisPageBuilderI18nConfig(options = {}) {
|
|
3614
|
-
const dictionaries = {
|
|
3615
|
-
'pt-BR': {
|
|
3616
|
-
...PRAXIS_PAGE_BUILDER_PT_BR,
|
|
3617
|
-
...(options.dictionaries?.['pt-BR'] ?? {}),
|
|
3618
|
-
},
|
|
3619
|
-
'en-US': {
|
|
3620
|
-
...PRAXIS_PAGE_BUILDER_EN_US,
|
|
3621
|
-
...(options.dictionaries?.['en-US'] ?? {}),
|
|
3622
|
-
},
|
|
3623
|
-
};
|
|
3624
|
-
for (const [locale, dictionary] of Object.entries(options.dictionaries ?? {})) {
|
|
3625
|
-
if (locale === 'pt-BR' || locale === 'en-US')
|
|
3626
|
-
continue;
|
|
3627
|
-
dictionaries[locale] = { ...(dictionaries[locale] ?? {}), ...dictionary };
|
|
1656
|
+
function createPraxisPageBuilderI18nConfig(options = {}) {
|
|
1657
|
+
const dictionaries = {
|
|
1658
|
+
'pt-BR': {
|
|
1659
|
+
...PRAXIS_PAGE_BUILDER_PT_BR,
|
|
1660
|
+
...(options.dictionaries?.['pt-BR'] ?? {}),
|
|
1661
|
+
},
|
|
1662
|
+
'en-US': {
|
|
1663
|
+
...PRAXIS_PAGE_BUILDER_EN_US,
|
|
1664
|
+
...(options.dictionaries?.['en-US'] ?? {}),
|
|
1665
|
+
},
|
|
1666
|
+
};
|
|
1667
|
+
for (const [locale, dictionary] of Object.entries(options.dictionaries ?? {})) {
|
|
1668
|
+
if (locale === 'pt-BR' || locale === 'en-US')
|
|
1669
|
+
continue;
|
|
1670
|
+
dictionaries[locale] = { ...(dictionaries[locale] ?? {}), ...dictionary };
|
|
1671
|
+
}
|
|
1672
|
+
return {
|
|
1673
|
+
locale: options.locale,
|
|
1674
|
+
fallbackLocale: options.fallbackLocale ?? 'pt-BR',
|
|
1675
|
+
dictionaries,
|
|
1676
|
+
};
|
|
1677
|
+
}
|
|
1678
|
+
function providePraxisPageBuilderI18n(options = {}) {
|
|
1679
|
+
return providePraxisI18n(createPraxisPageBuilderI18nConfig(options));
|
|
1680
|
+
}
|
|
1681
|
+
function resolvePraxisPageBuilderText(i18n, key, fallback) {
|
|
1682
|
+
const namespacedKey = key.startsWith('praxis.pageBuilder.')
|
|
1683
|
+
? key
|
|
1684
|
+
: `praxis.pageBuilder.${key}`;
|
|
1685
|
+
return i18n.t(namespacedKey, undefined, fallback) || fallback;
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
class ComponentPaletteDialogComponent {
|
|
1689
|
+
dialogRef;
|
|
1690
|
+
registry;
|
|
1691
|
+
i18n;
|
|
1692
|
+
data;
|
|
1693
|
+
query = signal('', ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
|
|
1694
|
+
all = signal([], ...(ngDevMode ? [{ debugName: "all" }] : /* istanbul ignore next */ []));
|
|
1695
|
+
filtered = computed(() => this.applyFilters(), ...(ngDevMode ? [{ debugName: "filtered" }] : /* istanbul ignore next */ []));
|
|
1696
|
+
density = computed(() => {
|
|
1697
|
+
const n = this.filtered().length;
|
|
1698
|
+
if (n <= 4)
|
|
1699
|
+
return 'roomy';
|
|
1700
|
+
if (n > 12)
|
|
1701
|
+
return 'dense';
|
|
1702
|
+
return 'normal';
|
|
1703
|
+
}, ...(ngDevMode ? [{ debugName: "density" }] : /* istanbul ignore next */ []));
|
|
1704
|
+
constructor(dialogRef, registry, i18n, data) {
|
|
1705
|
+
this.dialogRef = dialogRef;
|
|
1706
|
+
this.registry = registry;
|
|
1707
|
+
this.i18n = i18n;
|
|
1708
|
+
this.data = data;
|
|
1709
|
+
}
|
|
1710
|
+
ngOnInit() {
|
|
1711
|
+
this.all.set(this.buildEntries(this.registry.getAll()));
|
|
1712
|
+
}
|
|
1713
|
+
select(entry) {
|
|
1714
|
+
this.dialogRef.close({
|
|
1715
|
+
componentId: entry.componentId,
|
|
1716
|
+
...(entry.presetId ? { presetId: entry.presetId } : {}),
|
|
1717
|
+
...(entry.inputs ? { inputs: entry.inputs } : {}),
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1720
|
+
trackById = (_, entry) => entry.key;
|
|
1721
|
+
getPreview(entry) {
|
|
1722
|
+
return entry.description;
|
|
1723
|
+
}
|
|
1724
|
+
tx(key, fallback) {
|
|
1725
|
+
return resolvePraxisPageBuilderText(this.i18n, key, fallback);
|
|
1726
|
+
}
|
|
1727
|
+
// Create effect in injection context (field initializer is allowed)
|
|
1728
|
+
_adjustSizeEffect = effect(() => {
|
|
1729
|
+
const n = this.filtered().length;
|
|
1730
|
+
let width = '720px';
|
|
1731
|
+
if (n <= 4)
|
|
1732
|
+
width = '560px';
|
|
1733
|
+
else if (n <= 8)
|
|
1734
|
+
width = '680px';
|
|
1735
|
+
const container = this.dialogRef._containerInstance;
|
|
1736
|
+
if (container && container._config) {
|
|
1737
|
+
container._config.width = width;
|
|
1738
|
+
}
|
|
1739
|
+
}, ...(ngDevMode ? [{ debugName: "_adjustSizeEffect" }] : /* istanbul ignore next */ []));
|
|
1740
|
+
applyFilters() {
|
|
1741
|
+
const list = (this.all() || []);
|
|
1742
|
+
const q = (this.query() || '').toLowerCase();
|
|
1743
|
+
const allowIds = new Set((this.data?.allowedWidgetIds || []).map((s) => s.toLowerCase()));
|
|
1744
|
+
const allowTags = new Set((this.data?.allowedWidgetTags || []).map((s) => s.toLowerCase()));
|
|
1745
|
+
const allowPresets = new Set((this.data?.allowedPresetIds || []).map((s) => s.toLowerCase()));
|
|
1746
|
+
const metadataById = new Map(this.registry.getAll().map((meta) => [meta.id, meta]));
|
|
1747
|
+
return list.filter((entry) => {
|
|
1748
|
+
const meta = metadataById.get(entry.componentId);
|
|
1749
|
+
if (!meta)
|
|
1750
|
+
return false;
|
|
1751
|
+
if (q && !entry.searchText.includes(q)) {
|
|
1752
|
+
return false;
|
|
1753
|
+
}
|
|
1754
|
+
if (allowIds.size > 0 && !allowIds.has((meta.id || '').toLowerCase()))
|
|
1755
|
+
return false;
|
|
1756
|
+
if (allowTags.size > 0 && !meta.tags?.some(t => allowTags.has(t.toLowerCase())))
|
|
1757
|
+
return false;
|
|
1758
|
+
if (entry.presetId && allowPresets.size > 0 && !allowPresets.has(entry.presetId.toLowerCase()))
|
|
1759
|
+
return false;
|
|
1760
|
+
if (typeof this.data?.predicate === 'function' && !this.data.predicate(meta))
|
|
1761
|
+
return false;
|
|
1762
|
+
return true;
|
|
1763
|
+
});
|
|
1764
|
+
}
|
|
1765
|
+
buildEntries(metadata) {
|
|
1766
|
+
return metadata.flatMap((meta) => {
|
|
1767
|
+
const baseEntry = {
|
|
1768
|
+
key: meta.id,
|
|
1769
|
+
componentId: meta.id,
|
|
1770
|
+
title: meta.friendlyName || meta.id,
|
|
1771
|
+
description: meta.description || meta.selector,
|
|
1772
|
+
icon: meta.icon || 'widgets',
|
|
1773
|
+
badges: this.buildBadges(meta, false),
|
|
1774
|
+
searchText: `${meta.id} ${meta.friendlyName || ''} ${meta.description || ''} ${meta.selector || ''} ${this.buildBadgeSearchText(meta, false)}`.toLowerCase(),
|
|
1775
|
+
};
|
|
1776
|
+
const presets = (meta.insertionPresets ?? []).map((preset) => ({
|
|
1777
|
+
key: `${meta.id}::${preset.id}`,
|
|
1778
|
+
componentId: meta.id,
|
|
1779
|
+
presetId: preset.id,
|
|
1780
|
+
title: `${meta.friendlyName || meta.id} · ${preset.label}`,
|
|
1781
|
+
description: preset.description || meta.description || meta.selector,
|
|
1782
|
+
icon: preset.icon || meta.icon || 'widgets',
|
|
1783
|
+
badges: this.buildBadges(meta, true),
|
|
1784
|
+
searchText: `${meta.id} ${meta.friendlyName || ''} ${preset.label} ${preset.description || ''} ${meta.description || ''} ${this.buildBadgeSearchText(meta, true)}`.toLowerCase(),
|
|
1785
|
+
inputs: preset.inputs ? JSON.parse(JSON.stringify(preset.inputs)) : undefined,
|
|
1786
|
+
}));
|
|
1787
|
+
return [baseEntry, ...presets];
|
|
1788
|
+
});
|
|
1789
|
+
}
|
|
1790
|
+
buildBadges(meta, isPreset) {
|
|
1791
|
+
const badges = [];
|
|
1792
|
+
const tags = new Set((meta.tags ?? []).map((tag) => tag.toLowerCase()));
|
|
1793
|
+
if (meta.configEditor?.component) {
|
|
1794
|
+
badges.push({
|
|
1795
|
+
label: this.tx('palette.badges.configEditor.label', 'Config editor'),
|
|
1796
|
+
icon: 'tune',
|
|
1797
|
+
tone: 'ready',
|
|
1798
|
+
description: this.tx('palette.badges.configEditor.description', 'This component publishes a canonical settings-panel editor for its input contract.'),
|
|
1799
|
+
});
|
|
1800
|
+
}
|
|
1801
|
+
if (meta.authoringManifestRef?.componentId) {
|
|
1802
|
+
badges.push({
|
|
1803
|
+
label: this.tx('palette.badges.aiAuthoring.label', 'AI authoring'),
|
|
1804
|
+
icon: 'auto_awesome',
|
|
1805
|
+
tone: 'ready',
|
|
1806
|
+
description: this.tx('palette.badges.aiAuthoring.description', 'This component owner publishes a canonical AI authoring manifest for governed changes.'),
|
|
1807
|
+
});
|
|
1808
|
+
}
|
|
1809
|
+
if (meta.ports?.length || meta.actions?.length || meta.commands?.length) {
|
|
1810
|
+
badges.push({
|
|
1811
|
+
label: this.tx('palette.badges.governed.label', 'Governed'),
|
|
1812
|
+
icon: 'account_tree',
|
|
1813
|
+
tone: 'ready',
|
|
1814
|
+
description: this.tx('palette.badges.governed.description', 'This component exposes semantic ports, actions, or commands for governed composition.'),
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1817
|
+
if (isPreset) {
|
|
1818
|
+
badges.push({
|
|
1819
|
+
label: this.tx('palette.badges.preset.label', 'Preset'),
|
|
1820
|
+
icon: 'auto_awesome_motion',
|
|
1821
|
+
tone: 'info',
|
|
1822
|
+
description: this.tx('palette.badges.preset.description', 'This entry inserts a curated preset without changing the component contract.'),
|
|
1823
|
+
});
|
|
1824
|
+
}
|
|
1825
|
+
if (this.hasDataSourceInputs(meta) || tags.has('data') || tags.has('analytics')) {
|
|
1826
|
+
badges.push({
|
|
1827
|
+
label: this.tx('palette.badges.dataSource.label', 'Data source'),
|
|
1828
|
+
icon: 'database',
|
|
1829
|
+
tone: 'info',
|
|
1830
|
+
description: this.tx('palette.badges.dataSource.description', 'This component commonly needs schema, API, resource, or dataset context.'),
|
|
1831
|
+
});
|
|
1832
|
+
}
|
|
1833
|
+
if (tags.has('deprecated') || tags.has('legacy') || /legacy|legado|deprecated/i.test(meta.description || '')) {
|
|
1834
|
+
badges.push({
|
|
1835
|
+
label: this.tx('palette.badges.legacy.label', 'Legacy'),
|
|
1836
|
+
icon: 'history',
|
|
1837
|
+
tone: 'warning',
|
|
1838
|
+
description: this.tx('palette.badges.legacy.description', 'This entry is retained for compatibility and should not be the default for new canonical authoring.'),
|
|
1839
|
+
});
|
|
1840
|
+
}
|
|
1841
|
+
if (tags.has('demo') || tags.has('host') || /host-only|host|demo/i.test(`${meta.friendlyName} ${meta.description || ''}`)) {
|
|
1842
|
+
badges.push({
|
|
1843
|
+
label: this.tx('palette.badges.hostDemo.label', 'Host/demo'),
|
|
1844
|
+
icon: 'science',
|
|
1845
|
+
tone: 'neutral',
|
|
1846
|
+
description: this.tx('palette.badges.hostDemo.description', 'This entry depends on host/demo semantics and may need governance before public reuse.'),
|
|
1847
|
+
});
|
|
1848
|
+
}
|
|
1849
|
+
return badges;
|
|
1850
|
+
}
|
|
1851
|
+
buildBadgeSearchText(meta, isPreset) {
|
|
1852
|
+
return this.buildBadges(meta, isPreset)
|
|
1853
|
+
.map((badge) => `${badge.label} ${badge.description}`)
|
|
1854
|
+
.join(' ');
|
|
1855
|
+
}
|
|
1856
|
+
hasDataSourceInputs(meta) {
|
|
1857
|
+
return (meta.inputs ?? []).some((input) => /resource|schema|api|data(source)?|endpoint|resolver/i.test(input.name));
|
|
1858
|
+
}
|
|
1859
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ComponentPaletteDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: i2$2.ComponentMetadataRegistry }, { token: i2$2.PraxisI18nService }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
1860
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: ComponentPaletteDialogComponent, isStandalone: true, selector: "praxis-component-palette-dialog", providers: [providePraxisPageBuilderI18n()], ngImport: i0, template: `
|
|
1861
|
+
<h2 mat-dialog-title>
|
|
1862
|
+
<div class="dlg-title">
|
|
1863
|
+
<mat-icon class="dlg-icon" [praxisIcon]="'widgets'"></mat-icon>
|
|
1864
|
+
<div class="dlg-texts">
|
|
1865
|
+
<div class="dlg-head">{{ data?.title || tx('palette.title', 'Inserir componente') }}</div>
|
|
1866
|
+
<div class="dlg-sub">{{ tx('palette.subtitle', 'Escolha um componente para adicionar à página') }} · {{ filtered().length }} {{ tx('palette.available', 'disponíveis') }}</div>
|
|
1867
|
+
</div>
|
|
1868
|
+
</div>
|
|
1869
|
+
</h2>
|
|
1870
|
+
<div mat-dialog-content class="pdx-palette-content">
|
|
1871
|
+
<mat-form-field class="pdx-palette-search" appearance="outline">
|
|
1872
|
+
<mat-label>{{ tx('palette.searchLabel', 'Buscar componente') }}</mat-label>
|
|
1873
|
+
<mat-icon matPrefix [praxisIcon]="'search'"></mat-icon>
|
|
1874
|
+
<input
|
|
1875
|
+
matInput
|
|
1876
|
+
type="search"
|
|
1877
|
+
[ngModel]="query()"
|
|
1878
|
+
(ngModelChange)="query.set($event)"
|
|
1879
|
+
[placeholder]="tx('palette.searchPlaceholder', 'Nome, capability ou readiness')"
|
|
1880
|
+
data-testid="component-palette-search"
|
|
1881
|
+
/>
|
|
1882
|
+
</mat-form-field>
|
|
1883
|
+
@if (filtered().length) {
|
|
1884
|
+
<div [class]="'pdx-grid ' + density()">
|
|
1885
|
+
@for (entry of filtered(); track trackById($index, entry)) {
|
|
1886
|
+
<button
|
|
1887
|
+
class="pdx-card mat-elevation-z2"
|
|
1888
|
+
type="button"
|
|
1889
|
+
[attr.aria-label]="tx('palette.addAria', 'Adicionar') + ' ' + entry.title"
|
|
1890
|
+
(click)="select(entry)"
|
|
1891
|
+
>
|
|
1892
|
+
<div class="pdx-card-icon">
|
|
1893
|
+
<mat-icon [praxisIcon]="entry.icon"></mat-icon>
|
|
1894
|
+
</div>
|
|
1895
|
+
<div class="pdx-card-body">
|
|
1896
|
+
<div class="pdx-card-title">{{ entry.title }}</div>
|
|
1897
|
+
<div class="pdx-card-desc">{{ entry.description }}</div>
|
|
1898
|
+
@if (entry.badges.length) {
|
|
1899
|
+
<div class="pdx-card-badges">
|
|
1900
|
+
@for (badge of entry.badges; track badge) {
|
|
1901
|
+
<span
|
|
1902
|
+
class="pdx-card-badge"
|
|
1903
|
+
[class]="'pdx-card-badge ' + badge.tone"
|
|
1904
|
+
[title]="badge.description"
|
|
1905
|
+
>
|
|
1906
|
+
<mat-icon [praxisIcon]="badge.icon" aria-hidden="true"></mat-icon>
|
|
1907
|
+
{{ badge.label }}
|
|
1908
|
+
</span>
|
|
1909
|
+
}
|
|
1910
|
+
</div>
|
|
1911
|
+
}
|
|
1912
|
+
</div>
|
|
1913
|
+
</button>
|
|
1914
|
+
}
|
|
1915
|
+
</div>
|
|
1916
|
+
} @else {
|
|
1917
|
+
<div class="pdx-empty">
|
|
1918
|
+
<mat-icon [praxisIcon]="'sentiment_dissatisfied'"></mat-icon>
|
|
1919
|
+
<div>{{ tx('palette.empty', 'Nenhum componente disponível') }}</div>
|
|
1920
|
+
</div>
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
</div>
|
|
1924
|
+
<div mat-dialog-actions align="end">
|
|
1925
|
+
<button mat-stroked-button color="primary" mat-dialog-close>{{ tx('palette.cancel', 'Cancelar') }}</button>
|
|
1926
|
+
</div>
|
|
1927
|
+
`, isInline: true, styles: [":host{display:block}h2[mat-dialog-title]{margin:0;padding:12px 24px 10px;border-bottom:1px solid var(--md-sys-color-outline-variant)}.dlg-title{display:flex;align-items:center;gap:10px}.dlg-icon{color:var(--md-sys-color-primary)}.dlg-head{font-size:18px;font-weight:600;line-height:1.2}.dlg-sub{font-size:12px;opacity:.85;color:var(--md-sys-color-on-surface-variant)}.pdx-palette-content{min-width:480px;max-width:920px;padding-top:8px}.pdx-palette-search{width:100%;margin-bottom:12px}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}.pdx-grid.dense{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-grid.roomy{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}.pdx-card{appearance:none;position:relative;display:grid;grid-template-columns:44px 1fr;grid-template-rows:auto auto;gap:10px;padding:14px;border:1px solid transparent;border-radius:14px;cursor:pointer;outline:none;color:inherit;font:inherit;min-height:92px;text-align:left;background:var(--md-sys-color-surface);border-color:var(--md-sys-color-outline-variant);transition:box-shadow .2s ease,background .25s ease,transform .06s ease}.pdx-grid.dense .pdx-card{padding:10px;border-radius:12px;min-height:84px}.pdx-grid.roomy .pdx-card{padding:16px;border-radius:16px;min-height:100px}.pdx-card:focus,.pdx-card:hover{box-shadow:var(--mat-elevation-level4);background:var(--md-sys-color-surface-container-low);border-color:var(--md-sys-color-primary)}.pdx-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-card:active{transform:translateY(1px)}.pdx-card-icon{grid-row:span 2;display:flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary)}.pdx-card-title{font-weight:600;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-card-desc{color:var(--md-sys-color-on-surface-variant);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.pdx-card-badges{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.pdx-card-badge{display:inline-flex;align-items:center;gap:4px;min-height:22px;padding:2px 8px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-highest);font-size:11px;line-height:1.2;font-weight:600;letter-spacing:.01em}.pdx-card-badge mat-icon{width:14px;height:14px;font-size:14px}.pdx-card-badge.ready{color:var(--md-sys-color-primary);border-color:color-mix(in srgb,var(--md-sys-color-primary) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary-container) 72%,transparent)}.pdx-card-badge.info{color:var(--md-sys-color-tertiary);border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 38%,transparent);background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 68%,transparent)}.pdx-card-badge.warning{color:var(--md-sys-color-error);border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container) 62%,transparent)}.pdx-empty{padding:24px;display:grid;place-items:center;color:var(--md-sys-color-on-surface-variant);gap:8px}@media(max-width:600px){.pdx-palette-content{min-width:320px}.pdx-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3$1.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.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: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1928
|
+
}
|
|
1929
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: ComponentPaletteDialogComponent, decorators: [{
|
|
1930
|
+
type: Component,
|
|
1931
|
+
args: [{ selector: 'praxis-component-palette-dialog', standalone: true, imports: [FormsModule, MatDialogModule, MatFormFieldModule, MatInputModule, MatIconModule, MatButtonModule, PraxisIconDirective], template: `
|
|
1932
|
+
<h2 mat-dialog-title>
|
|
1933
|
+
<div class="dlg-title">
|
|
1934
|
+
<mat-icon class="dlg-icon" [praxisIcon]="'widgets'"></mat-icon>
|
|
1935
|
+
<div class="dlg-texts">
|
|
1936
|
+
<div class="dlg-head">{{ data?.title || tx('palette.title', 'Inserir componente') }}</div>
|
|
1937
|
+
<div class="dlg-sub">{{ tx('palette.subtitle', 'Escolha um componente para adicionar à página') }} · {{ filtered().length }} {{ tx('palette.available', 'disponíveis') }}</div>
|
|
1938
|
+
</div>
|
|
1939
|
+
</div>
|
|
1940
|
+
</h2>
|
|
1941
|
+
<div mat-dialog-content class="pdx-palette-content">
|
|
1942
|
+
<mat-form-field class="pdx-palette-search" appearance="outline">
|
|
1943
|
+
<mat-label>{{ tx('palette.searchLabel', 'Buscar componente') }}</mat-label>
|
|
1944
|
+
<mat-icon matPrefix [praxisIcon]="'search'"></mat-icon>
|
|
1945
|
+
<input
|
|
1946
|
+
matInput
|
|
1947
|
+
type="search"
|
|
1948
|
+
[ngModel]="query()"
|
|
1949
|
+
(ngModelChange)="query.set($event)"
|
|
1950
|
+
[placeholder]="tx('palette.searchPlaceholder', 'Nome, capability ou readiness')"
|
|
1951
|
+
data-testid="component-palette-search"
|
|
1952
|
+
/>
|
|
1953
|
+
</mat-form-field>
|
|
1954
|
+
@if (filtered().length) {
|
|
1955
|
+
<div [class]="'pdx-grid ' + density()">
|
|
1956
|
+
@for (entry of filtered(); track trackById($index, entry)) {
|
|
1957
|
+
<button
|
|
1958
|
+
class="pdx-card mat-elevation-z2"
|
|
1959
|
+
type="button"
|
|
1960
|
+
[attr.aria-label]="tx('palette.addAria', 'Adicionar') + ' ' + entry.title"
|
|
1961
|
+
(click)="select(entry)"
|
|
1962
|
+
>
|
|
1963
|
+
<div class="pdx-card-icon">
|
|
1964
|
+
<mat-icon [praxisIcon]="entry.icon"></mat-icon>
|
|
1965
|
+
</div>
|
|
1966
|
+
<div class="pdx-card-body">
|
|
1967
|
+
<div class="pdx-card-title">{{ entry.title }}</div>
|
|
1968
|
+
<div class="pdx-card-desc">{{ entry.description }}</div>
|
|
1969
|
+
@if (entry.badges.length) {
|
|
1970
|
+
<div class="pdx-card-badges">
|
|
1971
|
+
@for (badge of entry.badges; track badge) {
|
|
1972
|
+
<span
|
|
1973
|
+
class="pdx-card-badge"
|
|
1974
|
+
[class]="'pdx-card-badge ' + badge.tone"
|
|
1975
|
+
[title]="badge.description"
|
|
1976
|
+
>
|
|
1977
|
+
<mat-icon [praxisIcon]="badge.icon" aria-hidden="true"></mat-icon>
|
|
1978
|
+
{{ badge.label }}
|
|
1979
|
+
</span>
|
|
1980
|
+
}
|
|
1981
|
+
</div>
|
|
1982
|
+
}
|
|
1983
|
+
</div>
|
|
1984
|
+
</button>
|
|
1985
|
+
}
|
|
1986
|
+
</div>
|
|
1987
|
+
} @else {
|
|
1988
|
+
<div class="pdx-empty">
|
|
1989
|
+
<mat-icon [praxisIcon]="'sentiment_dissatisfied'"></mat-icon>
|
|
1990
|
+
<div>{{ tx('palette.empty', 'Nenhum componente disponível') }}</div>
|
|
1991
|
+
</div>
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
</div>
|
|
1995
|
+
<div mat-dialog-actions align="end">
|
|
1996
|
+
<button mat-stroked-button color="primary" mat-dialog-close>{{ tx('palette.cancel', 'Cancelar') }}</button>
|
|
1997
|
+
</div>
|
|
1998
|
+
`, providers: [providePraxisPageBuilderI18n()], changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}h2[mat-dialog-title]{margin:0;padding:12px 24px 10px;border-bottom:1px solid var(--md-sys-color-outline-variant)}.dlg-title{display:flex;align-items:center;gap:10px}.dlg-icon{color:var(--md-sys-color-primary)}.dlg-head{font-size:18px;font-weight:600;line-height:1.2}.dlg-sub{font-size:12px;opacity:.85;color:var(--md-sys-color-on-surface-variant)}.pdx-palette-content{min-width:480px;max-width:920px;padding-top:8px}.pdx-palette-search{width:100%;margin-bottom:12px}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:14px}.pdx-grid.dense{grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-grid.roomy{grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:16px}.pdx-card{appearance:none;position:relative;display:grid;grid-template-columns:44px 1fr;grid-template-rows:auto auto;gap:10px;padding:14px;border:1px solid transparent;border-radius:14px;cursor:pointer;outline:none;color:inherit;font:inherit;min-height:92px;text-align:left;background:var(--md-sys-color-surface);border-color:var(--md-sys-color-outline-variant);transition:box-shadow .2s ease,background .25s ease,transform .06s ease}.pdx-grid.dense .pdx-card{padding:10px;border-radius:12px;min-height:84px}.pdx-grid.roomy .pdx-card{padding:16px;border-radius:16px;min-height:100px}.pdx-card:focus,.pdx-card:hover{box-shadow:var(--mat-elevation-level4);background:var(--md-sys-color-surface-container-low);border-color:var(--md-sys-color-primary)}.pdx-card:focus-visible{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}.pdx-card:active{transform:translateY(1px)}.pdx-card-icon{grid-row:span 2;display:flex;align-items:center;justify-content:center;color:var(--md-sys-color-primary)}.pdx-card-title{font-weight:600;line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pdx-card-desc{color:var(--md-sys-color-on-surface-variant);display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden;word-break:break-word}.pdx-card-badges{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.pdx-card-badge{display:inline-flex;align-items:center;gap:4px;min-height:22px;padding:2px 8px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container-highest);font-size:11px;line-height:1.2;font-weight:600;letter-spacing:.01em}.pdx-card-badge mat-icon{width:14px;height:14px;font-size:14px}.pdx-card-badge.ready{color:var(--md-sys-color-primary);border-color:color-mix(in srgb,var(--md-sys-color-primary) 45%,transparent);background:color-mix(in srgb,var(--md-sys-color-primary-container) 72%,transparent)}.pdx-card-badge.info{color:var(--md-sys-color-tertiary);border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 38%,transparent);background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 68%,transparent)}.pdx-card-badge.warning{color:var(--md-sys-color-error);border-color:color-mix(in srgb,var(--md-sys-color-error) 35%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container) 62%,transparent)}.pdx-empty{padding:24px;display:grid;place-items:center;color:var(--md-sys-color-on-surface-variant);gap:8px}@media(max-width:600px){.pdx-palette-content{min-width:320px}.pdx-grid{grid-template-columns:repeat(auto-fill,minmax(200px,1fr))}}\n"] }]
|
|
1999
|
+
}], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: i2$2.ComponentMetadataRegistry }, { type: i2$2.PraxisI18nService }, { type: undefined, decorators: [{
|
|
2000
|
+
type: Inject,
|
|
2001
|
+
args: [MAT_DIALOG_DATA]
|
|
2002
|
+
}] }] });
|
|
2003
|
+
|
|
2004
|
+
const BUILTIN_PRESET_LABELS = {
|
|
2005
|
+
'dark-glass': 'Dark Glass',
|
|
2006
|
+
'light-neutral': 'Light Neutral',
|
|
2007
|
+
graphite: 'Graphite',
|
|
2008
|
+
frameless: 'Frameless',
|
|
2009
|
+
'data-panel': 'Data Panel',
|
|
2010
|
+
'chart-panel': 'Chart Panel',
|
|
2011
|
+
'metric-panel': 'Metric Panel',
|
|
2012
|
+
'executive-card': 'Executive Card',
|
|
2013
|
+
'filter-bar': 'Filter Bar',
|
|
2014
|
+
};
|
|
2015
|
+
const BUILTIN_PRESET_OPTIONS = Object.keys(BUILTIN_SHELL_PRESETS).map((id) => ({
|
|
2016
|
+
id,
|
|
2017
|
+
label: BUILTIN_PRESET_LABELS[id] ?? id,
|
|
2018
|
+
}));
|
|
2019
|
+
const BUILTIN_PRESET_MAP = BUILTIN_SHELL_PRESETS;
|
|
2020
|
+
const SET_INPUT_PRESETS = {
|
|
2021
|
+
'praxis-dynamic-form': [
|
|
2022
|
+
{
|
|
2023
|
+
input: 'mode',
|
|
2024
|
+
label: 'Modo',
|
|
2025
|
+
icon: 'toggle_on',
|
|
2026
|
+
values: [
|
|
2027
|
+
{ label: 'Visualização', value: 'view', icon: 'visibility' },
|
|
2028
|
+
{ label: 'Edição', value: 'edit', icon: 'edit' },
|
|
2029
|
+
{ label: 'Criação', value: 'create', icon: 'add' },
|
|
2030
|
+
],
|
|
2031
|
+
},
|
|
2032
|
+
{
|
|
2033
|
+
input: 'schemaSource',
|
|
2034
|
+
label: 'Fonte do schema',
|
|
2035
|
+
icon: 'schema',
|
|
2036
|
+
values: [
|
|
2037
|
+
{ label: 'Recurso', value: 'resource' },
|
|
2038
|
+
{ label: 'Filtro', value: 'filter' },
|
|
2039
|
+
],
|
|
2040
|
+
},
|
|
2041
|
+
{
|
|
2042
|
+
input: 'notifyIfOutdated',
|
|
2043
|
+
label: 'Notificação de schema',
|
|
2044
|
+
icon: 'notification_important',
|
|
2045
|
+
values: [
|
|
2046
|
+
{ label: 'Inline', value: 'inline' },
|
|
2047
|
+
{ label: 'Snackbar', value: 'snackbar' },
|
|
2048
|
+
{ label: 'Ambos', value: 'both' },
|
|
2049
|
+
{ label: 'Nenhum', value: 'none' },
|
|
2050
|
+
],
|
|
2051
|
+
},
|
|
2052
|
+
{
|
|
2053
|
+
input: 'removeEmptyContainersOnSave',
|
|
2054
|
+
label: 'Remover containers vazios',
|
|
2055
|
+
icon: 'cleaning_services',
|
|
2056
|
+
values: [
|
|
2057
|
+
{ label: 'Ativar', value: true },
|
|
2058
|
+
{ label: 'Desativar', value: false },
|
|
2059
|
+
],
|
|
2060
|
+
},
|
|
2061
|
+
{
|
|
2062
|
+
input: 'autoOpenSettingsOnOutdated',
|
|
2063
|
+
label: 'Abrir editor automático',
|
|
2064
|
+
icon: 'open_in_new',
|
|
2065
|
+
values: [
|
|
2066
|
+
{ label: 'Ativar', value: true },
|
|
2067
|
+
{ label: 'Desativar', value: false },
|
|
2068
|
+
],
|
|
2069
|
+
},
|
|
2070
|
+
{
|
|
2071
|
+
input: 'readonlyModeGlobal',
|
|
2072
|
+
label: 'Somente leitura global',
|
|
2073
|
+
icon: 'lock',
|
|
2074
|
+
values: [
|
|
2075
|
+
{ label: 'Ativar', value: true },
|
|
2076
|
+
{ label: 'Desativar', value: false },
|
|
2077
|
+
],
|
|
2078
|
+
},
|
|
2079
|
+
{
|
|
2080
|
+
input: 'disabledModeGlobal',
|
|
2081
|
+
label: 'Desabilitar global',
|
|
2082
|
+
icon: 'block',
|
|
2083
|
+
values: [
|
|
2084
|
+
{ label: 'Ativar', value: true },
|
|
2085
|
+
{ label: 'Desativar', value: false },
|
|
2086
|
+
],
|
|
2087
|
+
},
|
|
2088
|
+
{
|
|
2089
|
+
input: 'presentationModeGlobal',
|
|
2090
|
+
label: 'Modo apresentação',
|
|
2091
|
+
icon: 'slideshow',
|
|
2092
|
+
values: [
|
|
2093
|
+
{ label: 'Ativar', value: true },
|
|
2094
|
+
{ label: 'Desativar', value: false },
|
|
2095
|
+
],
|
|
2096
|
+
},
|
|
2097
|
+
{
|
|
2098
|
+
input: 'visibleGlobal',
|
|
2099
|
+
label: 'Visibilidade global',
|
|
2100
|
+
icon: 'visibility',
|
|
2101
|
+
values: [
|
|
2102
|
+
{ label: 'Exibir', value: true },
|
|
2103
|
+
{ label: 'Ocultar', value: false },
|
|
2104
|
+
],
|
|
2105
|
+
},
|
|
2106
|
+
],
|
|
2107
|
+
'praxis-table': [
|
|
2108
|
+
{
|
|
2109
|
+
input: 'showToolbar',
|
|
2110
|
+
label: 'Toolbar',
|
|
2111
|
+
icon: 'toolbar',
|
|
2112
|
+
values: [
|
|
2113
|
+
{ label: 'Exibir', value: true },
|
|
2114
|
+
{ label: 'Ocultar', value: false },
|
|
2115
|
+
],
|
|
2116
|
+
},
|
|
2117
|
+
{
|
|
2118
|
+
input: 'toolbarV2',
|
|
2119
|
+
label: 'Toolbar v2',
|
|
2120
|
+
icon: 'view_compact',
|
|
2121
|
+
values: [
|
|
2122
|
+
{ label: 'Ativar', value: true },
|
|
2123
|
+
{ label: 'Desativar', value: false },
|
|
2124
|
+
],
|
|
2125
|
+
},
|
|
2126
|
+
{
|
|
2127
|
+
input: 'autoDelete',
|
|
2128
|
+
label: 'Auto delete',
|
|
2129
|
+
icon: 'delete_forever',
|
|
2130
|
+
values: [
|
|
2131
|
+
{ label: 'Ativar', value: true },
|
|
2132
|
+
{ label: 'Desativar', value: false },
|
|
2133
|
+
],
|
|
2134
|
+
},
|
|
2135
|
+
{
|
|
2136
|
+
input: 'dense',
|
|
2137
|
+
label: 'Modo compacto',
|
|
2138
|
+
icon: 'compress',
|
|
2139
|
+
values: [
|
|
2140
|
+
{ label: 'Ativar', value: true },
|
|
2141
|
+
{ label: 'Desativar', value: false },
|
|
2142
|
+
],
|
|
2143
|
+
},
|
|
2144
|
+
],
|
|
2145
|
+
'praxis-stepper': [
|
|
2146
|
+
{
|
|
2147
|
+
input: 'inputs.config.orientation',
|
|
2148
|
+
label: 'Orientação',
|
|
2149
|
+
icon: 'swap_vert',
|
|
2150
|
+
values: [
|
|
2151
|
+
{ label: 'Horizontal', value: 'horizontal' },
|
|
2152
|
+
{ label: 'Vertical', value: 'vertical' },
|
|
2153
|
+
],
|
|
2154
|
+
},
|
|
2155
|
+
{
|
|
2156
|
+
input: 'inputs.config.headerPosition',
|
|
2157
|
+
label: 'Posição do cabeçalho',
|
|
2158
|
+
icon: 'vertical_align_top',
|
|
2159
|
+
values: [
|
|
2160
|
+
{ label: 'Topo', value: 'top' },
|
|
2161
|
+
{ label: 'Base', value: 'bottom' },
|
|
2162
|
+
],
|
|
2163
|
+
},
|
|
2164
|
+
{
|
|
2165
|
+
input: 'inputs.config.linear',
|
|
2166
|
+
label: 'Modo linear',
|
|
2167
|
+
icon: 'linear_scale',
|
|
2168
|
+
values: [
|
|
2169
|
+
{ label: 'Ativar', value: true },
|
|
2170
|
+
{ label: 'Desativar', value: false },
|
|
2171
|
+
],
|
|
2172
|
+
},
|
|
2173
|
+
{
|
|
2174
|
+
input: 'inputs.config.navigation.variant',
|
|
2175
|
+
label: 'Navegação (variante)',
|
|
2176
|
+
icon: 'tune',
|
|
2177
|
+
values: [
|
|
2178
|
+
{ label: 'Basic', value: 'basic' },
|
|
2179
|
+
{ label: 'Flat', value: 'flat' },
|
|
2180
|
+
{ label: 'Stroked', value: 'stroked' },
|
|
2181
|
+
{ label: 'Raised', value: 'raised' },
|
|
2182
|
+
],
|
|
2183
|
+
},
|
|
2184
|
+
{
|
|
2185
|
+
input: 'inputs.config.navigation.align',
|
|
2186
|
+
label: 'Navegação (alinhamento)',
|
|
2187
|
+
icon: 'format_align_center',
|
|
2188
|
+
values: [
|
|
2189
|
+
{ label: 'Início', value: 'start' },
|
|
2190
|
+
{ label: 'Centro', value: 'center' },
|
|
2191
|
+
{ label: 'Fim', value: 'end' },
|
|
2192
|
+
{ label: 'Espaçado', value: 'space-between' },
|
|
2193
|
+
],
|
|
2194
|
+
},
|
|
2195
|
+
{
|
|
2196
|
+
input: 'labelPosition',
|
|
2197
|
+
label: 'Posição do rótulo',
|
|
2198
|
+
icon: 'format_align_center',
|
|
2199
|
+
values: [
|
|
2200
|
+
{ label: 'Abaixo', value: 'bottom' },
|
|
2201
|
+
{ label: 'Ao lado', value: 'end' },
|
|
2202
|
+
],
|
|
2203
|
+
},
|
|
2204
|
+
{
|
|
2205
|
+
input: 'density',
|
|
2206
|
+
label: 'Densidade',
|
|
2207
|
+
icon: 'density_small',
|
|
2208
|
+
values: [
|
|
2209
|
+
{ label: 'Padrão', value: 'default' },
|
|
2210
|
+
{ label: 'Confortável', value: 'comfortable' },
|
|
2211
|
+
{ label: 'Compacto', value: 'compact' },
|
|
2212
|
+
],
|
|
2213
|
+
},
|
|
2214
|
+
],
|
|
2215
|
+
'praxis-expansion': [
|
|
2216
|
+
{
|
|
2217
|
+
input: 'strictValidation',
|
|
2218
|
+
label: 'Validação estrita',
|
|
2219
|
+
icon: 'rule',
|
|
2220
|
+
values: [
|
|
2221
|
+
{ label: 'Ativar', value: true },
|
|
2222
|
+
{ label: 'Desativar', value: false },
|
|
2223
|
+
],
|
|
2224
|
+
},
|
|
2225
|
+
],
|
|
2226
|
+
};
|
|
2227
|
+
class WidgetShellEditorComponent {
|
|
2228
|
+
registry;
|
|
2229
|
+
form = new FormGroup({
|
|
2230
|
+
kind: new FormControl('dashboard-card', { nonNullable: true }),
|
|
2231
|
+
preset: new FormControl('', { nonNullable: true }),
|
|
2232
|
+
applyToAll: new FormControl(false, { nonNullable: true }),
|
|
2233
|
+
title: new FormControl('', { nonNullable: true }),
|
|
2234
|
+
subtitle: new FormControl('', { nonNullable: true }),
|
|
2235
|
+
icon: new FormControl('', { nonNullable: true }),
|
|
2236
|
+
showHeader: new FormControl('auto', { nonNullable: true }),
|
|
2237
|
+
collapsible: new FormControl(true, { nonNullable: true }),
|
|
2238
|
+
cardBg: new FormControl('', { nonNullable: true }),
|
|
2239
|
+
cardBorder: new FormControl('', { nonNullable: true }),
|
|
2240
|
+
cardRadius: new FormControl('', { nonNullable: true }),
|
|
2241
|
+
cardShadow: new FormControl('', { nonNullable: true }),
|
|
2242
|
+
headerBg: new FormControl('', { nonNullable: true }),
|
|
2243
|
+
headerBorder: new FormControl('', { nonNullable: true }),
|
|
2244
|
+
titleColor: new FormControl('', { nonNullable: true }),
|
|
2245
|
+
subtitleColor: new FormControl('', { nonNullable: true }),
|
|
2246
|
+
iconColor: new FormControl('', { nonNullable: true }),
|
|
2247
|
+
bodyBg: new FormControl('', { nonNullable: true }),
|
|
2248
|
+
bodyColor: new FormControl('', { nonNullable: true }),
|
|
2249
|
+
bodyPadding: new FormControl('', { nonNullable: true }),
|
|
2250
|
+
titleSize: new FormControl('', { nonNullable: true }),
|
|
2251
|
+
titleWeight: new FormControl('', { nonNullable: true }),
|
|
2252
|
+
subtitleSize: new FormControl('', { nonNullable: true }),
|
|
2253
|
+
actions: new FormArray([]),
|
|
2254
|
+
});
|
|
2255
|
+
initialShell = new BehaviorSubject(null);
|
|
2256
|
+
dirtySubject = new BehaviorSubject(false);
|
|
2257
|
+
validSubject = new BehaviorSubject(true);
|
|
2258
|
+
busySubject = new BehaviorSubject(false);
|
|
2259
|
+
isDirty$ = this.dirtySubject.asObservable();
|
|
2260
|
+
isValid$ = this.validSubject.asObservable();
|
|
2261
|
+
isBusy$ = this.busySubject.asObservable();
|
|
2262
|
+
snapshot = '';
|
|
2263
|
+
initialTitle;
|
|
2264
|
+
initialSubtitle;
|
|
2265
|
+
actionCopySources = new WeakMap();
|
|
2266
|
+
presetOptions = [...BUILTIN_PRESET_OPTIONS];
|
|
2267
|
+
presets = { ...BUILTIN_PRESET_MAP };
|
|
2268
|
+
availableActions = [];
|
|
2269
|
+
actionQuery = new FormControl('', { nonNullable: true });
|
|
2270
|
+
showScopeShell = true;
|
|
2271
|
+
showScopeAny = true;
|
|
2272
|
+
showScopeToolbar = false;
|
|
2273
|
+
showScopeContext = false;
|
|
2274
|
+
setInputPresets = [];
|
|
2275
|
+
setInputTarget = new FormControl('', { nonNullable: true });
|
|
2276
|
+
setInputValue = new FormControl(null);
|
|
2277
|
+
previewCollapsed = false;
|
|
2278
|
+
previewExpanded = false;
|
|
2279
|
+
pagePreset = null;
|
|
2280
|
+
constructor(data, registry) {
|
|
2281
|
+
this.registry = registry;
|
|
2282
|
+
const customPresets = data?.presets || {};
|
|
2283
|
+
const customOptions = Object.keys(customPresets).map((id) => ({ id, label: id }));
|
|
2284
|
+
this.presetOptions = [...BUILTIN_PRESET_OPTIONS, ...customOptions];
|
|
2285
|
+
this.presets = { ...BUILTIN_PRESET_MAP, ...customPresets };
|
|
2286
|
+
this.pagePreset = data?.pagePreset || null;
|
|
2287
|
+
const shell = data?.shell || null;
|
|
2288
|
+
this.initialShell.next(shell);
|
|
2289
|
+
this.applyShell(shell);
|
|
2290
|
+
this.loadAvailableActions(data?.widgetType || null);
|
|
2291
|
+
this.loadSetInputPresets(data?.widgetType || null);
|
|
2292
|
+
this.form.valueChanges
|
|
2293
|
+
.pipe(takeUntilDestroyed())
|
|
2294
|
+
.subscribe(() => {
|
|
2295
|
+
this.validSubject.next(this.form.valid);
|
|
2296
|
+
const current = this.snapshotValue();
|
|
2297
|
+
this.dirtySubject.next(current !== this.snapshot);
|
|
2298
|
+
});
|
|
2299
|
+
this.form.controls.preset.valueChanges
|
|
2300
|
+
.pipe(takeUntilDestroyed())
|
|
2301
|
+
.subscribe((value) => {
|
|
2302
|
+
if (!value && this.form.controls.applyToAll.value) {
|
|
2303
|
+
this.form.controls.applyToAll.setValue(false, { emitEvent: false });
|
|
2304
|
+
}
|
|
2305
|
+
});
|
|
2306
|
+
this.setInputTarget.valueChanges
|
|
2307
|
+
.pipe(takeUntilDestroyed())
|
|
2308
|
+
.subscribe(() => {
|
|
2309
|
+
const next = this.currentSetInputValues()[0];
|
|
2310
|
+
if (next)
|
|
2311
|
+
this.setInputValue.setValue(next.value, { emitEvent: false });
|
|
2312
|
+
});
|
|
2313
|
+
}
|
|
2314
|
+
get actions() {
|
|
2315
|
+
return this.form.controls.actions;
|
|
2316
|
+
}
|
|
2317
|
+
get hasAvailableActions() {
|
|
2318
|
+
return !!this.availableActions.length;
|
|
2319
|
+
}
|
|
2320
|
+
addAction(seed) {
|
|
2321
|
+
this.actions.push(this.createActionGroup(seed));
|
|
2322
|
+
}
|
|
2323
|
+
removeAction(index) {
|
|
2324
|
+
this.actions.removeAt(index);
|
|
2325
|
+
}
|
|
2326
|
+
getSettingsValue() {
|
|
2327
|
+
return this.buildResult();
|
|
2328
|
+
}
|
|
2329
|
+
onSave() {
|
|
2330
|
+
return this.buildResult();
|
|
2331
|
+
}
|
|
2332
|
+
reset() {
|
|
2333
|
+
const shell = this.initialShell.value;
|
|
2334
|
+
this.applyShell(shell);
|
|
2335
|
+
}
|
|
2336
|
+
applyShell(shell) {
|
|
2337
|
+
this.initialTitle = shell?.title;
|
|
2338
|
+
this.initialSubtitle = shell?.subtitle;
|
|
2339
|
+
const showHeader = shell?.showHeader == null ? 'auto' : shell.showHeader ? 'true' : 'false';
|
|
2340
|
+
const window = shell?.windowActions || {};
|
|
2341
|
+
const appearance = shell?.appearance || {};
|
|
2342
|
+
const card = appearance.card || {};
|
|
2343
|
+
const header = appearance.header || {};
|
|
2344
|
+
const body = appearance.body || {};
|
|
2345
|
+
const typography = appearance.typography || {};
|
|
2346
|
+
this.form.setControl('actions', new FormArray((shell?.actions || []).map((a) => this.createActionGroup(a))));
|
|
2347
|
+
this.form.setValue({
|
|
2348
|
+
kind: shell?.kind === 'none' ? 'none' : 'dashboard-card',
|
|
2349
|
+
preset: shell?.preset || '',
|
|
2350
|
+
applyToAll: false,
|
|
2351
|
+
title: this.editableText(shell?.title),
|
|
2352
|
+
subtitle: this.editableText(shell?.subtitle),
|
|
2353
|
+
icon: shell?.icon || '',
|
|
2354
|
+
showHeader,
|
|
2355
|
+
collapsible: window.collapsible !== false,
|
|
2356
|
+
cardBg: card.background || '',
|
|
2357
|
+
cardBorder: card.borderColor || '',
|
|
2358
|
+
cardRadius: card.borderRadius || '',
|
|
2359
|
+
cardShadow: card.shadow || '',
|
|
2360
|
+
headerBg: header.background || '',
|
|
2361
|
+
headerBorder: header.borderColor || '',
|
|
2362
|
+
titleColor: header.titleColor || '',
|
|
2363
|
+
subtitleColor: header.subtitleColor || '',
|
|
2364
|
+
iconColor: header.iconColor || '',
|
|
2365
|
+
bodyBg: body.background || '',
|
|
2366
|
+
bodyColor: body.textColor || '',
|
|
2367
|
+
bodyPadding: body.padding || '',
|
|
2368
|
+
titleSize: typography.titleSize || '',
|
|
2369
|
+
titleWeight: typography.titleWeight || '',
|
|
2370
|
+
subtitleSize: typography.subtitleSize || '',
|
|
2371
|
+
actions: this.actions.value,
|
|
2372
|
+
}, { emitEvent: false });
|
|
2373
|
+
this.snapshot = this.snapshotValue();
|
|
2374
|
+
this.dirtySubject.next(false);
|
|
2375
|
+
this.validSubject.next(this.form.valid);
|
|
2376
|
+
}
|
|
2377
|
+
loadAvailableActions(widgetType) {
|
|
2378
|
+
if (!widgetType || !this.registry) {
|
|
2379
|
+
this.availableActions = [];
|
|
2380
|
+
return;
|
|
2381
|
+
}
|
|
2382
|
+
const meta = this.registry.get(widgetType);
|
|
2383
|
+
const actions = (meta?.actions || []).map((action) => ({
|
|
2384
|
+
kind: 'action',
|
|
2385
|
+
id: action.id,
|
|
2386
|
+
label: action.label || action.id,
|
|
2387
|
+
icon: action.icon,
|
|
2388
|
+
scope: action.scope || 'any',
|
|
2389
|
+
emit: action.emit,
|
|
2390
|
+
command: action.command,
|
|
2391
|
+
description: action.description,
|
|
2392
|
+
payloadExample: action.payloadSchema?.example,
|
|
2393
|
+
}));
|
|
2394
|
+
const commands = (meta?.commands || []).map((command) => ({
|
|
2395
|
+
kind: 'command',
|
|
2396
|
+
id: command.name,
|
|
2397
|
+
label: command.label || command.name,
|
|
2398
|
+
icon: command.icon,
|
|
2399
|
+
scope: 'any',
|
|
2400
|
+
command: command.name,
|
|
2401
|
+
description: command.description,
|
|
2402
|
+
payloadExample: command.payloadSchema?.example,
|
|
2403
|
+
}));
|
|
2404
|
+
this.availableActions = [...actions, ...commands];
|
|
2405
|
+
}
|
|
2406
|
+
createActionGroup(seed) {
|
|
2407
|
+
const group = new FormGroup({
|
|
2408
|
+
id: new FormControl(seed?.id || '', { nonNullable: true, validators: [Validators.required] }),
|
|
2409
|
+
label: new FormControl(this.editableText(seed?.label), { nonNullable: true }),
|
|
2410
|
+
icon: new FormControl(seed?.icon || '', { nonNullable: true }),
|
|
2411
|
+
variant: new FormControl(seed?.variant || 'text', { nonNullable: true }),
|
|
2412
|
+
placement: new FormControl(seed?.placement || 'header', { nonNullable: true }),
|
|
2413
|
+
emit: new FormControl(seed?.emit || '', { nonNullable: true }),
|
|
2414
|
+
tooltip: new FormControl(this.editableText(seed?.tooltip), { nonNullable: true }),
|
|
2415
|
+
command: new FormControl(seed?.command || '', { nonNullable: true }),
|
|
2416
|
+
payload: new FormControl(seed?.payload != null ? JSON.stringify(seed.payload) : '', { nonNullable: true }),
|
|
2417
|
+
visible: new FormControl(seed?.visible !== false, { nonNullable: true }),
|
|
2418
|
+
disabled: new FormControl(!!seed?.disabled, { nonNullable: true }),
|
|
2419
|
+
});
|
|
2420
|
+
this.actionCopySources.set(group, { label: seed?.label, tooltip: seed?.tooltip });
|
|
2421
|
+
return group;
|
|
2422
|
+
}
|
|
2423
|
+
buildShell() {
|
|
2424
|
+
const raw = this.form.getRawValue();
|
|
2425
|
+
if (raw.kind === 'none') {
|
|
2426
|
+
return { kind: 'none' };
|
|
2427
|
+
}
|
|
2428
|
+
const shell = {};
|
|
2429
|
+
if (raw.preset)
|
|
2430
|
+
shell.preset = raw.preset;
|
|
2431
|
+
const title = this.preserveTextDescriptor(this.initialTitle, raw.title);
|
|
2432
|
+
const subtitle = this.preserveTextDescriptor(this.initialSubtitle, raw.subtitle);
|
|
2433
|
+
if (title)
|
|
2434
|
+
shell.title = title;
|
|
2435
|
+
if (subtitle)
|
|
2436
|
+
shell.subtitle = subtitle;
|
|
2437
|
+
if (raw.icon.trim())
|
|
2438
|
+
shell.icon = raw.icon.trim();
|
|
2439
|
+
if (raw.showHeader !== 'auto')
|
|
2440
|
+
shell.showHeader = raw.showHeader === 'true';
|
|
2441
|
+
const windowActions = {};
|
|
2442
|
+
if (!raw.collapsible)
|
|
2443
|
+
windowActions.collapsible = false;
|
|
2444
|
+
if (Object.keys(windowActions).length)
|
|
2445
|
+
shell.windowActions = windowActions;
|
|
2446
|
+
const actions = this.actions.controls
|
|
2447
|
+
.map((group) => this.normalizeAction(group.getRawValue(), this.actionCopySources.get(group)))
|
|
2448
|
+
.filter((a) => a.id);
|
|
2449
|
+
if (actions.length)
|
|
2450
|
+
shell.actions = actions;
|
|
2451
|
+
const appearance = this.buildAppearance(raw);
|
|
2452
|
+
if (appearance)
|
|
2453
|
+
shell.appearance = appearance;
|
|
2454
|
+
return shell;
|
|
2455
|
+
}
|
|
2456
|
+
buildResult() {
|
|
2457
|
+
const raw = this.form.getRawValue();
|
|
2458
|
+
const shell = this.buildShell();
|
|
2459
|
+
const applyToAll = !!raw.applyToAll && !!raw.preset;
|
|
2460
|
+
return {
|
|
2461
|
+
shell,
|
|
2462
|
+
applyToAll,
|
|
2463
|
+
pagePreset: applyToAll ? raw.preset : undefined,
|
|
2464
|
+
};
|
|
2465
|
+
}
|
|
2466
|
+
buildAppearance(raw) {
|
|
2467
|
+
const card = {};
|
|
2468
|
+
const header = {};
|
|
2469
|
+
const body = {};
|
|
2470
|
+
const typography = {};
|
|
2471
|
+
if (raw.cardBg)
|
|
2472
|
+
card.background = raw.cardBg.trim();
|
|
2473
|
+
if (raw.cardBorder)
|
|
2474
|
+
card.borderColor = raw.cardBorder.trim();
|
|
2475
|
+
if (raw.cardRadius)
|
|
2476
|
+
card.borderRadius = raw.cardRadius.trim();
|
|
2477
|
+
if (raw.cardShadow)
|
|
2478
|
+
card.shadow = raw.cardShadow.trim();
|
|
2479
|
+
if (raw.headerBg)
|
|
2480
|
+
header.background = raw.headerBg.trim();
|
|
2481
|
+
if (raw.headerBorder)
|
|
2482
|
+
header.borderColor = raw.headerBorder.trim();
|
|
2483
|
+
if (raw.titleColor)
|
|
2484
|
+
header.titleColor = raw.titleColor.trim();
|
|
2485
|
+
if (raw.subtitleColor)
|
|
2486
|
+
header.subtitleColor = raw.subtitleColor.trim();
|
|
2487
|
+
if (raw.iconColor)
|
|
2488
|
+
header.iconColor = raw.iconColor.trim();
|
|
2489
|
+
if (raw.bodyBg)
|
|
2490
|
+
body.background = raw.bodyBg.trim();
|
|
2491
|
+
if (raw.bodyColor)
|
|
2492
|
+
body.textColor = raw.bodyColor.trim();
|
|
2493
|
+
if (raw.bodyPadding)
|
|
2494
|
+
body.padding = raw.bodyPadding.trim();
|
|
2495
|
+
if (raw.titleSize)
|
|
2496
|
+
typography.titleSize = raw.titleSize.trim();
|
|
2497
|
+
if (raw.titleWeight)
|
|
2498
|
+
typography.titleWeight = raw.titleWeight.trim();
|
|
2499
|
+
if (raw.subtitleSize)
|
|
2500
|
+
typography.subtitleSize = raw.subtitleSize.trim();
|
|
2501
|
+
const appearance = {};
|
|
2502
|
+
if (Object.keys(card).length)
|
|
2503
|
+
appearance.card = card;
|
|
2504
|
+
if (Object.keys(header).length)
|
|
2505
|
+
appearance.header = header;
|
|
2506
|
+
if (Object.keys(body).length)
|
|
2507
|
+
appearance.body = body;
|
|
2508
|
+
if (Object.keys(typography).length)
|
|
2509
|
+
appearance.typography = typography;
|
|
2510
|
+
return Object.keys(appearance).length ? appearance : undefined;
|
|
2511
|
+
}
|
|
2512
|
+
previewVars() {
|
|
2513
|
+
const appearance = this.buildPreviewAppearance();
|
|
2514
|
+
return {
|
|
2515
|
+
'--pdx-shell-card-bg': appearance?.card?.background || null,
|
|
2516
|
+
'--pdx-shell-card-border': appearance?.card?.borderColor || null,
|
|
2517
|
+
'--pdx-shell-card-radius': appearance?.card?.borderRadius || null,
|
|
2518
|
+
'--pdx-shell-card-shadow': appearance?.card?.shadow || null,
|
|
2519
|
+
'--pdx-shell-header-bg': appearance?.header?.background || null,
|
|
2520
|
+
'--pdx-shell-header-border': appearance?.header?.borderColor || null,
|
|
2521
|
+
'--pdx-shell-title-color': appearance?.header?.titleColor || null,
|
|
2522
|
+
'--pdx-shell-subtitle-color': appearance?.header?.subtitleColor || null,
|
|
2523
|
+
'--pdx-shell-icon-color': appearance?.header?.iconColor || null,
|
|
2524
|
+
'--pdx-shell-body-bg': appearance?.body?.background || null,
|
|
2525
|
+
'--pdx-shell-body-color': appearance?.body?.textColor || null,
|
|
2526
|
+
'--pdx-shell-body-padding': appearance?.body?.padding || null,
|
|
2527
|
+
'--pdx-shell-title-size': appearance?.typography?.titleSize || null,
|
|
2528
|
+
'--pdx-shell-title-weight': appearance?.typography?.titleWeight || null,
|
|
2529
|
+
'--pdx-shell-subtitle-size': appearance?.typography?.subtitleSize || null,
|
|
2530
|
+
};
|
|
2531
|
+
}
|
|
2532
|
+
previewShowHeader() {
|
|
2533
|
+
const raw = this.form.getRawValue();
|
|
2534
|
+
if (raw.kind === 'none')
|
|
2535
|
+
return false;
|
|
2536
|
+
if (raw.showHeader === 'true')
|
|
2537
|
+
return true;
|
|
2538
|
+
if (raw.showHeader === 'false')
|
|
2539
|
+
return false;
|
|
2540
|
+
return !!(raw.title || raw.subtitle || raw.icon);
|
|
2541
|
+
}
|
|
2542
|
+
previewTitle() {
|
|
2543
|
+
const title = this.editableText(this.form.controls.title.value).trim();
|
|
2544
|
+
return title || 'Titulo do card';
|
|
2545
|
+
}
|
|
2546
|
+
previewSubtitle() {
|
|
2547
|
+
const subtitle = this.editableText(this.form.controls.subtitle.value).trim();
|
|
2548
|
+
return subtitle || 'Subtitulo opcional';
|
|
2549
|
+
}
|
|
2550
|
+
buildPreviewAppearance() {
|
|
2551
|
+
const raw = this.form.getRawValue();
|
|
2552
|
+
const presetId = raw.preset || this.pagePreset || '';
|
|
2553
|
+
const base = presetId ? this.presets[presetId] : undefined;
|
|
2554
|
+
const override = this.buildAppearance(raw);
|
|
2555
|
+
return this.mergeAppearance(base, override);
|
|
2556
|
+
}
|
|
2557
|
+
mergeAppearance(base, override) {
|
|
2558
|
+
if (!base && !override)
|
|
2559
|
+
return undefined;
|
|
2560
|
+
const out = {};
|
|
2561
|
+
const mergeSection = (key) => {
|
|
2562
|
+
const a = (base && base[key]) || undefined;
|
|
2563
|
+
const b = (override && override[key]) || undefined;
|
|
2564
|
+
if (!a && !b)
|
|
2565
|
+
return;
|
|
2566
|
+
out[key] = { ...(a || {}), ...(b || {}) };
|
|
2567
|
+
};
|
|
2568
|
+
mergeSection('card');
|
|
2569
|
+
mergeSection('header');
|
|
2570
|
+
mergeSection('body');
|
|
2571
|
+
mergeSection('typography');
|
|
2572
|
+
return out;
|
|
2573
|
+
}
|
|
2574
|
+
togglePreviewCollapse() {
|
|
2575
|
+
this.previewCollapsed = !this.previewCollapsed;
|
|
2576
|
+
}
|
|
2577
|
+
togglePreviewExpand() {
|
|
2578
|
+
this.previewExpanded = !this.previewExpanded;
|
|
2579
|
+
}
|
|
2580
|
+
previewHeaderActions() {
|
|
2581
|
+
const actions = this.previewActions().filter((a) => (a.placement || 'header') === 'header');
|
|
2582
|
+
return actions.slice(0, 3);
|
|
2583
|
+
}
|
|
2584
|
+
previewOverflowCount() {
|
|
2585
|
+
const actions = this.previewActions().filter((a) => (a.placement || 'header') === 'header');
|
|
2586
|
+
return Math.max(0, actions.length - 3);
|
|
2587
|
+
}
|
|
2588
|
+
previewWindowActions() {
|
|
2589
|
+
return this.previewActions().filter((a) => (a.placement || 'header') === 'window');
|
|
2590
|
+
}
|
|
2591
|
+
normalizeAction(raw, source) {
|
|
2592
|
+
const action = { id: String(raw.id || '').trim() };
|
|
2593
|
+
const label = String(raw.label || '').trim();
|
|
2594
|
+
const icon = String(raw.icon || '').trim();
|
|
2595
|
+
const emit = String(raw.emit || '').trim();
|
|
2596
|
+
const tooltip = String(raw.tooltip || '').trim();
|
|
2597
|
+
const command = String(raw.command || '').trim();
|
|
2598
|
+
const normalizedLabel = this.preserveTextDescriptor(source?.label, label);
|
|
2599
|
+
const normalizedTooltip = this.preserveTextDescriptor(source?.tooltip, tooltip);
|
|
2600
|
+
if (normalizedLabel)
|
|
2601
|
+
action.label = normalizedLabel;
|
|
2602
|
+
if (icon)
|
|
2603
|
+
action.icon = icon;
|
|
2604
|
+
if (emit)
|
|
2605
|
+
action.emit = emit;
|
|
2606
|
+
if (normalizedTooltip)
|
|
2607
|
+
action.tooltip = normalizedTooltip;
|
|
2608
|
+
if (command)
|
|
2609
|
+
action.command = command;
|
|
2610
|
+
if (raw.variant && raw.variant !== 'text')
|
|
2611
|
+
action.variant = raw.variant;
|
|
2612
|
+
if (raw.placement && raw.placement !== 'header')
|
|
2613
|
+
action.placement = raw.placement;
|
|
2614
|
+
if (raw.visible === false)
|
|
2615
|
+
action.visible = false;
|
|
2616
|
+
if (raw.disabled === true)
|
|
2617
|
+
action.disabled = true;
|
|
2618
|
+
const payload = this.tryParsePayload(raw.payload);
|
|
2619
|
+
if (payload !== undefined)
|
|
2620
|
+
action.payload = payload;
|
|
2621
|
+
return action;
|
|
2622
|
+
}
|
|
2623
|
+
editableText(value) {
|
|
2624
|
+
if (typeof value === 'string')
|
|
2625
|
+
return value;
|
|
2626
|
+
return value?.text || value?.key || '';
|
|
2627
|
+
}
|
|
2628
|
+
preserveTextDescriptor(source, editedValue) {
|
|
2629
|
+
const edited = String(editedValue ?? '').trim();
|
|
2630
|
+
if (!edited)
|
|
2631
|
+
return undefined;
|
|
2632
|
+
if (source && typeof source === 'object') {
|
|
2633
|
+
const authoredText = this.editableText(source).trim();
|
|
2634
|
+
return edited === authoredText ? { ...source } : edited;
|
|
2635
|
+
}
|
|
2636
|
+
return edited;
|
|
2637
|
+
}
|
|
2638
|
+
tryParsePayload(raw) {
|
|
2639
|
+
const value = String(raw || '').trim();
|
|
2640
|
+
if (!value)
|
|
2641
|
+
return undefined;
|
|
2642
|
+
try {
|
|
2643
|
+
return JSON.parse(value);
|
|
2644
|
+
}
|
|
2645
|
+
catch {
|
|
2646
|
+
return value;
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
snapshotValue() {
|
|
2650
|
+
try {
|
|
2651
|
+
return JSON.stringify(this.buildResult());
|
|
2652
|
+
}
|
|
2653
|
+
catch {
|
|
2654
|
+
return '';
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
filteredAvailableActions() {
|
|
2658
|
+
const query = this.actionQuery.value.trim().toLowerCase();
|
|
2659
|
+
const scopes = new Set();
|
|
2660
|
+
if (this.showScopeShell)
|
|
2661
|
+
scopes.add('shell');
|
|
2662
|
+
if (this.showScopeAny)
|
|
2663
|
+
scopes.add('any');
|
|
2664
|
+
if (this.showScopeToolbar)
|
|
2665
|
+
scopes.add('toolbar');
|
|
2666
|
+
if (this.showScopeContext)
|
|
2667
|
+
scopes.add('context');
|
|
2668
|
+
return this.availableActions.filter((action) => {
|
|
2669
|
+
const scope = action.scope || 'any';
|
|
2670
|
+
if (!scopes.has(scope))
|
|
2671
|
+
return false;
|
|
2672
|
+
if (!query)
|
|
2673
|
+
return true;
|
|
2674
|
+
const hay = [
|
|
2675
|
+
action.label,
|
|
2676
|
+
action.id,
|
|
2677
|
+
action.description,
|
|
2678
|
+
action.emit,
|
|
2679
|
+
action.command,
|
|
2680
|
+
]
|
|
2681
|
+
.filter(Boolean)
|
|
2682
|
+
.join(' ')
|
|
2683
|
+
.toLowerCase();
|
|
2684
|
+
return hay.includes(query);
|
|
2685
|
+
});
|
|
2686
|
+
}
|
|
2687
|
+
isActionSelected(action) {
|
|
2688
|
+
return this.findActionIndex(action) >= 0;
|
|
2689
|
+
}
|
|
2690
|
+
toggleAvailableAction(action) {
|
|
2691
|
+
const idx = this.findActionIndex(action);
|
|
2692
|
+
if (idx >= 0) {
|
|
2693
|
+
this.removeAction(idx);
|
|
2694
|
+
return;
|
|
2695
|
+
}
|
|
2696
|
+
this.addAction({
|
|
2697
|
+
id: action.id,
|
|
2698
|
+
label: action.label,
|
|
2699
|
+
icon: action.icon,
|
|
2700
|
+
emit: action.emit,
|
|
2701
|
+
command: action.command,
|
|
2702
|
+
payload: action.payloadExample,
|
|
2703
|
+
});
|
|
2704
|
+
}
|
|
2705
|
+
scopeLabel(scope) {
|
|
2706
|
+
const value = scope || 'any';
|
|
2707
|
+
if (value === 'shell')
|
|
2708
|
+
return 'Shell';
|
|
2709
|
+
if (value === 'toolbar')
|
|
2710
|
+
return 'Toolbar';
|
|
2711
|
+
if (value === 'context')
|
|
2712
|
+
return 'Context';
|
|
2713
|
+
return 'Any';
|
|
2714
|
+
}
|
|
2715
|
+
stringifyPayload(payload) {
|
|
2716
|
+
if (payload === null)
|
|
2717
|
+
return 'null';
|
|
2718
|
+
if (payload === undefined)
|
|
2719
|
+
return 'undefined';
|
|
2720
|
+
if (typeof payload === 'string')
|
|
2721
|
+
return payload;
|
|
2722
|
+
try {
|
|
2723
|
+
return JSON.stringify(payload);
|
|
2724
|
+
}
|
|
2725
|
+
catch {
|
|
2726
|
+
return String(payload);
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
displayInputPath(path) {
|
|
2730
|
+
const trimmed = String(path || '').trim();
|
|
2731
|
+
if (!trimmed)
|
|
2732
|
+
return '';
|
|
2733
|
+
return trimmed.replace(/^inputs\./, '');
|
|
2734
|
+
}
|
|
2735
|
+
extractActionInput(actionValue) {
|
|
2736
|
+
const payload = this.tryParsePayload(actionValue?.payload);
|
|
2737
|
+
const input = typeof payload?.input === 'string' ? payload.input.trim() : '';
|
|
2738
|
+
return input;
|
|
2739
|
+
}
|
|
2740
|
+
showActionInputPath(actionValue) {
|
|
2741
|
+
const command = String(actionValue?.command || '').trim();
|
|
2742
|
+
if (command !== 'pdx:set-input')
|
|
2743
|
+
return false;
|
|
2744
|
+
return !!this.extractActionInput(actionValue);
|
|
2745
|
+
}
|
|
2746
|
+
currentSetInputValues() {
|
|
2747
|
+
const preset = this.setInputPresets.find((p) => p.input === this.setInputTarget.value);
|
|
2748
|
+
return preset?.values || [];
|
|
2749
|
+
}
|
|
2750
|
+
addSetInputAction() {
|
|
2751
|
+
const preset = this.setInputPresets.find((p) => p.input === this.setInputTarget.value);
|
|
2752
|
+
if (!preset)
|
|
2753
|
+
return;
|
|
2754
|
+
const selected = this.currentSetInputValues().find((v) => v.value === this.setInputValue.value);
|
|
2755
|
+
if (!selected)
|
|
2756
|
+
return;
|
|
2757
|
+
const label = `${preset.label}: ${selected.label}`;
|
|
2758
|
+
const payload = { input: preset.input, value: selected.value };
|
|
2759
|
+
this.addAction({
|
|
2760
|
+
id: `set-${preset.input}-${String(selected.value)}`,
|
|
2761
|
+
label,
|
|
2762
|
+
icon: selected.icon || preset.icon,
|
|
2763
|
+
command: 'pdx:set-input',
|
|
2764
|
+
payload,
|
|
2765
|
+
variant: 'text',
|
|
2766
|
+
placement: 'header',
|
|
2767
|
+
});
|
|
2768
|
+
}
|
|
2769
|
+
findActionIndex(action) {
|
|
2770
|
+
const values = this.actions.getRawValue();
|
|
2771
|
+
return values.findIndex((a) => {
|
|
2772
|
+
if (a.id !== action.id)
|
|
2773
|
+
return false;
|
|
2774
|
+
if (action.command && a.command)
|
|
2775
|
+
return a.command === action.command;
|
|
2776
|
+
if (action.emit && a.emit)
|
|
2777
|
+
return a.emit === action.emit;
|
|
2778
|
+
return true;
|
|
2779
|
+
});
|
|
2780
|
+
}
|
|
2781
|
+
previewActions() {
|
|
2782
|
+
return (this.actions.getRawValue() || [])
|
|
2783
|
+
.map((a) => this.normalizeAction(a))
|
|
2784
|
+
.filter((a) => a.id && a.visible !== false);
|
|
2785
|
+
}
|
|
2786
|
+
loadSetInputPresets(widgetType) {
|
|
2787
|
+
if (!widgetType) {
|
|
2788
|
+
this.setInputPresets = [];
|
|
2789
|
+
return;
|
|
2790
|
+
}
|
|
2791
|
+
this.setInputPresets = SET_INPUT_PRESETS[widgetType] || [];
|
|
2792
|
+
const first = this.setInputPresets[0];
|
|
2793
|
+
if (first) {
|
|
2794
|
+
this.setInputTarget.setValue(first.input, { emitEvent: false });
|
|
2795
|
+
const firstValue = first.values[0];
|
|
2796
|
+
if (firstValue)
|
|
2797
|
+
this.setInputValue.setValue(firstValue.value, { emitEvent: false });
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2800
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: WidgetShellEditorComponent, deps: [{ token: SETTINGS_PANEL_DATA, optional: true }, { token: i2$2.ComponentMetadataRegistry, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
2801
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: WidgetShellEditorComponent, isStandalone: true, selector: "praxis-widget-shell-editor", ngImport: i0, template: `
|
|
2802
|
+
<div class="shell-editor">
|
|
2803
|
+
<p class="shell-intro">
|
|
2804
|
+
Defina a identidade, a aparência e as ações do card. Use a prévia para conferir o resultado antes de salvar.
|
|
2805
|
+
</p>
|
|
2806
|
+
|
|
2807
|
+
<div class="shell-section">Geral</div>
|
|
2808
|
+
<div class="shell-grid">
|
|
2809
|
+
<mat-form-field appearance="outline">
|
|
2810
|
+
<mat-label>Tipo de card</mat-label>
|
|
2811
|
+
<mat-select [formControl]="form.controls.kind">
|
|
2812
|
+
<mat-option value="dashboard-card">Dashboard Card</mat-option>
|
|
2813
|
+
<mat-option value="none">Sem shell</mat-option>
|
|
2814
|
+
</mat-select>
|
|
2815
|
+
</mat-form-field>
|
|
2816
|
+
<mat-form-field appearance="outline">
|
|
2817
|
+
<mat-label>Preset</mat-label>
|
|
2818
|
+
<mat-select [formControl]="form.controls.preset">
|
|
2819
|
+
<mat-option value="">Nenhum</mat-option>
|
|
2820
|
+
@if (pagePreset) {
|
|
2821
|
+
<mat-option [value]="pagePreset">Usar preset da página ({{ pagePreset }})</mat-option>
|
|
2822
|
+
}
|
|
2823
|
+
@for (p of presetOptions; track p) {
|
|
2824
|
+
<mat-option [value]="p.id">{{ p.label }}</mat-option>
|
|
2825
|
+
}
|
|
2826
|
+
</mat-select>
|
|
2827
|
+
</mat-form-field>
|
|
2828
|
+
@if (!form.controls.preset.value && pagePreset) {
|
|
2829
|
+
<div class="shell-hint">
|
|
2830
|
+
Preset da página: {{ pagePreset }}
|
|
2831
|
+
</div>
|
|
2832
|
+
}
|
|
2833
|
+
@if (form.controls.preset.value) {
|
|
2834
|
+
<mat-checkbox [formControl]="form.controls.applyToAll">
|
|
2835
|
+
Aplicar preset como padrão da página
|
|
2836
|
+
</mat-checkbox>
|
|
2837
|
+
}
|
|
2838
|
+
<mat-form-field appearance="outline">
|
|
2839
|
+
<mat-label>Ícone</mat-label>
|
|
2840
|
+
<input matInput [formControl]="form.controls.icon" placeholder="ex: badge" />
|
|
2841
|
+
</mat-form-field>
|
|
2842
|
+
<mat-form-field appearance="outline">
|
|
2843
|
+
<mat-label>Título</mat-label>
|
|
2844
|
+
<input matInput [formControl]="form.controls.title" />
|
|
2845
|
+
</mat-form-field>
|
|
2846
|
+
<mat-form-field appearance="outline" class="shell-field--wide">
|
|
2847
|
+
<mat-label>Subtítulo</mat-label>
|
|
2848
|
+
<input matInput [formControl]="form.controls.subtitle" />
|
|
2849
|
+
</mat-form-field>
|
|
2850
|
+
<mat-form-field appearance="outline">
|
|
2851
|
+
<mat-label>Mostrar cabeçalho</mat-label>
|
|
2852
|
+
<mat-select [formControl]="form.controls.showHeader">
|
|
2853
|
+
<mat-option value="auto">Automático</mat-option>
|
|
2854
|
+
<mat-option value="true">Sempre</mat-option>
|
|
2855
|
+
<mat-option value="false">Nunca</mat-option>
|
|
2856
|
+
</mat-select>
|
|
2857
|
+
</mat-form-field>
|
|
2858
|
+
</div>
|
|
2859
|
+
|
|
2860
|
+
<div class="shell-section">Controles de janela</div>
|
|
2861
|
+
<div class="shell-flags">
|
|
2862
|
+
<mat-checkbox [formControl]="form.controls.collapsible">Permitir recolher</mat-checkbox>
|
|
2863
|
+
</div>
|
|
2864
|
+
|
|
2865
|
+
<mat-divider></mat-divider>
|
|
2866
|
+
|
|
2867
|
+
<div class="shell-section">Aparência</div>
|
|
2868
|
+
<div class="shell-grid">
|
|
2869
|
+
<mat-form-field appearance="outline">
|
|
2870
|
+
<mat-label>Fundo do card</mat-label>
|
|
2871
|
+
<input matInput [formControl]="form.controls.cardBg" placeholder="ex: #0b1220" />
|
|
2872
|
+
</mat-form-field>
|
|
2873
|
+
<mat-form-field appearance="outline">
|
|
2874
|
+
<mat-label>Cor da borda</mat-label>
|
|
2875
|
+
<input matInput [formControl]="form.controls.cardBorder" placeholder="ex: rgba(255,255,255,0.12)" />
|
|
2876
|
+
</mat-form-field>
|
|
2877
|
+
<mat-form-field appearance="outline">
|
|
2878
|
+
<mat-label>Raio da borda</mat-label>
|
|
2879
|
+
<input matInput [formControl]="form.controls.cardRadius" placeholder="ex: 14px" />
|
|
2880
|
+
</mat-form-field>
|
|
2881
|
+
<mat-form-field appearance="outline">
|
|
2882
|
+
<mat-label>Sombra</mat-label>
|
|
2883
|
+
<input matInput [formControl]="form.controls.cardShadow" placeholder="ex: 0 10px 30px rgba(0,0,0,0.2)" />
|
|
2884
|
+
</mat-form-field>
|
|
2885
|
+
<mat-form-field appearance="outline">
|
|
2886
|
+
<mat-label>Fundo do cabeçalho</mat-label>
|
|
2887
|
+
<input matInput [formControl]="form.controls.headerBg" placeholder="ex: linear-gradient(...)" />
|
|
2888
|
+
</mat-form-field>
|
|
2889
|
+
<mat-form-field appearance="outline">
|
|
2890
|
+
<mat-label>Borda do cabeçalho</mat-label>
|
|
2891
|
+
<input matInput [formControl]="form.controls.headerBorder" placeholder="ex: rgba(255,255,255,0.08)" />
|
|
2892
|
+
</mat-form-field>
|
|
2893
|
+
<mat-form-field appearance="outline">
|
|
2894
|
+
<mat-label>Cor do título</mat-label>
|
|
2895
|
+
<input matInput [formControl]="form.controls.titleColor" placeholder="ex: #e6edf3" />
|
|
2896
|
+
</mat-form-field>
|
|
2897
|
+
<mat-form-field appearance="outline">
|
|
2898
|
+
<mat-label>Cor do subtítulo</mat-label>
|
|
2899
|
+
<input matInput [formControl]="form.controls.subtitleColor" placeholder="ex: #9fb0c4" />
|
|
2900
|
+
</mat-form-field>
|
|
2901
|
+
<mat-form-field appearance="outline">
|
|
2902
|
+
<mat-label>Cor do ícone</mat-label>
|
|
2903
|
+
<input matInput [formControl]="form.controls.iconColor" placeholder="ex: #8ab4ff" />
|
|
2904
|
+
</mat-form-field>
|
|
2905
|
+
<mat-form-field appearance="outline">
|
|
2906
|
+
<mat-label>Fundo do corpo</mat-label>
|
|
2907
|
+
<input matInput [formControl]="form.controls.bodyBg" placeholder="ex: transparent" />
|
|
2908
|
+
</mat-form-field>
|
|
2909
|
+
<mat-form-field appearance="outline">
|
|
2910
|
+
<mat-label>Cor do texto do corpo</mat-label>
|
|
2911
|
+
<input matInput [formControl]="form.controls.bodyColor" placeholder="ex: #e6edf3" />
|
|
2912
|
+
</mat-form-field>
|
|
2913
|
+
<mat-form-field appearance="outline">
|
|
2914
|
+
<mat-label>Padding do corpo</mat-label>
|
|
2915
|
+
<input matInput [formControl]="form.controls.bodyPadding" placeholder="ex: 10px 12px 12px" />
|
|
2916
|
+
</mat-form-field>
|
|
2917
|
+
<mat-form-field appearance="outline">
|
|
2918
|
+
<mat-label>Tamanho do título</mat-label>
|
|
2919
|
+
<input matInput [formControl]="form.controls.titleSize" placeholder="ex: 14px" />
|
|
2920
|
+
</mat-form-field>
|
|
2921
|
+
<mat-form-field appearance="outline">
|
|
2922
|
+
<mat-label>Peso do título</mat-label>
|
|
2923
|
+
<input matInput [formControl]="form.controls.titleWeight" placeholder="ex: 600" />
|
|
2924
|
+
</mat-form-field>
|
|
2925
|
+
<mat-form-field appearance="outline">
|
|
2926
|
+
<mat-label>Tamanho do subtítulo</mat-label>
|
|
2927
|
+
<input matInput [formControl]="form.controls.subtitleSize" placeholder="ex: 12px" />
|
|
2928
|
+
</mat-form-field>
|
|
2929
|
+
</div>
|
|
2930
|
+
|
|
2931
|
+
<div class="shell-preview" [ngStyle]="previewVars()">
|
|
2932
|
+
<div class="shell-preview-card" [class.no-shell]="form.controls.kind.value === 'none'" [class.expanded]="previewExpanded">
|
|
2933
|
+
@if (previewShowHeader()) {
|
|
2934
|
+
<div class="shell-preview-header">
|
|
2935
|
+
<div class="shell-preview-title">
|
|
2936
|
+
@if (form.controls.icon.value) {
|
|
2937
|
+
<mat-icon [praxisIcon]="form.controls.icon.value"></mat-icon>
|
|
2938
|
+
}
|
|
2939
|
+
<div class="shell-preview-text">
|
|
2940
|
+
<div class="shell-preview-title-text">{{ previewTitle() }}</div>
|
|
2941
|
+
<div class="shell-preview-subtitle">{{ previewSubtitle() }}</div>
|
|
2942
|
+
</div>
|
|
2943
|
+
</div>
|
|
2944
|
+
<div class="shell-preview-actions">
|
|
2945
|
+
@for (action of previewHeaderActions(); track action.id) {
|
|
2946
|
+
<button
|
|
2947
|
+
type="button"
|
|
2948
|
+
[disabled]="action.disabled"
|
|
2949
|
+
[ngClass]="action.variant === 'outlined' ? 'pdx-preview-outlined' : 'pdx-preview-text'"
|
|
2950
|
+
mat-button
|
|
2951
|
+
>
|
|
2952
|
+
@if (action.icon) {
|
|
2953
|
+
<mat-icon [praxisIcon]="action.icon"></mat-icon>
|
|
2954
|
+
}
|
|
2955
|
+
<span class="pdx-preview-label">{{ action.label || action.id }}</span>
|
|
2956
|
+
</button>
|
|
2957
|
+
}
|
|
2958
|
+
@if (previewOverflowCount()) {
|
|
2959
|
+
<button
|
|
2960
|
+
praxisIconButton="more_horiz"
|
|
2961
|
+
size="compact"
|
|
2962
|
+
type="button"
|
|
2963
|
+
aria-label="Mais ações"
|
|
2964
|
+
></button>
|
|
2965
|
+
}
|
|
2966
|
+
@for (action of previewWindowActions(); track action.id) {
|
|
2967
|
+
@if (action.icon) {
|
|
2968
|
+
<button
|
|
2969
|
+
[praxisIconButton]="action.icon"
|
|
2970
|
+
size="compact"
|
|
2971
|
+
type="button"
|
|
2972
|
+
[disabled]="action.disabled"
|
|
2973
|
+
[attr.aria-label]="action.label || action.id"
|
|
2974
|
+
></button>
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
<button
|
|
2978
|
+
[praxisIconButton]="previewCollapsed ? 'unfold_more' : 'unfold_less'"
|
|
2979
|
+
size="compact"
|
|
2980
|
+
type="button"
|
|
2981
|
+
(click)="togglePreviewCollapse()"
|
|
2982
|
+
aria-label="Recolher"
|
|
2983
|
+
></button>
|
|
2984
|
+
<button
|
|
2985
|
+
[praxisIconButton]="previewExpanded ? 'close_fullscreen' : 'open_in_full'"
|
|
2986
|
+
size="compact"
|
|
2987
|
+
type="button"
|
|
2988
|
+
(click)="togglePreviewExpand()"
|
|
2989
|
+
aria-label="Expandir"
|
|
2990
|
+
></button>
|
|
2991
|
+
</div>
|
|
2992
|
+
</div>
|
|
2993
|
+
}
|
|
2994
|
+
<div class="shell-preview-body" [class.hidden]="previewCollapsed">Conteudo do widget</div>
|
|
2995
|
+
</div>
|
|
2996
|
+
</div>
|
|
2997
|
+
|
|
2998
|
+
<mat-divider></mat-divider>
|
|
2999
|
+
|
|
3000
|
+
@if (hasAvailableActions) {
|
|
3001
|
+
<div class="shell-section">Ações disponíveis</div>
|
|
3002
|
+
}
|
|
3003
|
+
@if (hasAvailableActions) {
|
|
3004
|
+
<div class="shell-available">
|
|
3005
|
+
<div class="shell-available-toolbar">
|
|
3006
|
+
<mat-form-field appearance="outline">
|
|
3007
|
+
<mat-label>Buscar ação</mat-label>
|
|
3008
|
+
<input matInput [formControl]="actionQuery" placeholder="ex: export, editar, submit" />
|
|
3009
|
+
</mat-form-field>
|
|
3010
|
+
<div class="shell-available-filters">
|
|
3011
|
+
<mat-checkbox [(ngModel)]="showScopeShell">Shell</mat-checkbox>
|
|
3012
|
+
<mat-checkbox [(ngModel)]="showScopeAny">Any</mat-checkbox>
|
|
3013
|
+
<mat-checkbox [(ngModel)]="showScopeToolbar">Toolbar</mat-checkbox>
|
|
3014
|
+
<mat-checkbox [(ngModel)]="showScopeContext">Context</mat-checkbox>
|
|
3015
|
+
</div>
|
|
3016
|
+
</div>
|
|
3017
|
+
<div class="shell-available-list">
|
|
3018
|
+
@for (action of filteredAvailableActions(); track action) {
|
|
3019
|
+
<div class="shell-available-item">
|
|
3020
|
+
<div class="shell-available-main">
|
|
3021
|
+
<div class="shell-available-title">
|
|
3022
|
+
@if (action.icon) {
|
|
3023
|
+
<mat-icon [praxisIcon]="action.icon"></mat-icon>
|
|
3024
|
+
}
|
|
3025
|
+
<div class="shell-available-text">
|
|
3026
|
+
<div class="shell-available-label">{{ action.label }}</div>
|
|
3027
|
+
<div class="shell-available-meta">
|
|
3028
|
+
<span class="shell-badge">{{ action.kind === 'command' ? 'Comando' : 'Ação' }}</span>
|
|
3029
|
+
<span class="shell-badge">{{ scopeLabel(action.scope) }}</span>
|
|
3030
|
+
<span class="shell-code">id: {{ action.id }}</span>
|
|
3031
|
+
@if (action.emit) {
|
|
3032
|
+
<span class="shell-code">emit: {{ action.emit }}</span>
|
|
3033
|
+
}
|
|
3034
|
+
@if (action.command) {
|
|
3035
|
+
<span class="shell-code">command: {{ action.command }}</span>
|
|
3036
|
+
}
|
|
3037
|
+
</div>
|
|
3038
|
+
</div>
|
|
3039
|
+
</div>
|
|
3040
|
+
@if (action.description) {
|
|
3041
|
+
<div class="shell-available-desc">{{ action.description }}</div>
|
|
3042
|
+
}
|
|
3043
|
+
@if (action.payloadExample !== undefined) {
|
|
3044
|
+
<div class="shell-available-payload">
|
|
3045
|
+
<span class="shell-code">payload: {{ stringifyPayload(action.payloadExample) }}</span>
|
|
3046
|
+
</div>
|
|
3047
|
+
}
|
|
3048
|
+
@if (action.scope === 'context') {
|
|
3049
|
+
<div class="shell-available-warning">
|
|
3050
|
+
Essa ação depende de item/linha selecionado; payload fixo pode não funcionar.
|
|
3051
|
+
</div>
|
|
3052
|
+
}
|
|
3053
|
+
</div>
|
|
3054
|
+
<div class="shell-available-actions">
|
|
3055
|
+
<button
|
|
3056
|
+
mat-stroked-button
|
|
3057
|
+
type="button"
|
|
3058
|
+
[color]="isActionSelected(action) ? 'warn' : 'primary'"
|
|
3059
|
+
(click)="toggleAvailableAction(action)"
|
|
3060
|
+
>
|
|
3061
|
+
{{ isActionSelected(action) ? 'Remover' : 'Adicionar' }}
|
|
3062
|
+
</button>
|
|
3063
|
+
</div>
|
|
3064
|
+
</div>
|
|
3065
|
+
}
|
|
3066
|
+
</div>
|
|
3067
|
+
</div>
|
|
3068
|
+
} @else {
|
|
3069
|
+
<div class="shell-empty">Nenhuma ação registrada para este componente.</div>
|
|
3070
|
+
}
|
|
3071
|
+
|
|
3072
|
+
@if (hasAvailableActions) {
|
|
3073
|
+
<mat-divider></mat-divider>
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
@if (setInputPresets.length) {
|
|
3077
|
+
<div class="shell-section">Ações rápidas (inputs)</div>
|
|
3078
|
+
}
|
|
3079
|
+
@if (setInputPresets.length) {
|
|
3080
|
+
<div class="shell-quick-inputs">
|
|
3081
|
+
<mat-form-field appearance="outline">
|
|
3082
|
+
<mat-label>Input</mat-label>
|
|
3083
|
+
<mat-select [formControl]="setInputTarget">
|
|
3084
|
+
@for (preset of setInputPresets; track preset) {
|
|
3085
|
+
<mat-option [value]="preset.input">
|
|
3086
|
+
@if (preset.icon) {
|
|
3087
|
+
<mat-icon [praxisIcon]="preset.icon"></mat-icon>
|
|
3088
|
+
}
|
|
3089
|
+
{{ preset.label }}
|
|
3090
|
+
</mat-option>
|
|
3091
|
+
}
|
|
3092
|
+
</mat-select>
|
|
3093
|
+
</mat-form-field>
|
|
3094
|
+
@if (setInputTarget.value) {
|
|
3095
|
+
<div class="shell-input-path">
|
|
3096
|
+
Input: {{ displayInputPath(setInputTarget.value) }}
|
|
3097
|
+
</div>
|
|
3098
|
+
}
|
|
3099
|
+
<mat-form-field appearance="outline">
|
|
3100
|
+
<mat-label>Valor</mat-label>
|
|
3101
|
+
<mat-select [formControl]="setInputValue">
|
|
3102
|
+
@for (option of currentSetInputValues(); track option) {
|
|
3103
|
+
<mat-option [value]="option.value">
|
|
3104
|
+
@if (option.icon) {
|
|
3105
|
+
<mat-icon [praxisIcon]="option.icon"></mat-icon>
|
|
3106
|
+
}
|
|
3107
|
+
{{ option.label }}
|
|
3108
|
+
</mat-option>
|
|
3109
|
+
}
|
|
3110
|
+
</mat-select>
|
|
3111
|
+
</mat-form-field>
|
|
3112
|
+
<button mat-flat-button color="primary" type="button" (click)="addSetInputAction()">
|
|
3113
|
+
Adicionar ação
|
|
3114
|
+
</button>
|
|
3115
|
+
</div>
|
|
3116
|
+
}
|
|
3117
|
+
|
|
3118
|
+
<div class="shell-section shell-actions-head">
|
|
3119
|
+
<div>Ações do cabeçalho</div>
|
|
3120
|
+
<button mat-flat-button color="primary" type="button" (click)="addAction()">Adicionar ação</button>
|
|
3121
|
+
</div>
|
|
3122
|
+
|
|
3123
|
+
@if (actions.controls.length) {
|
|
3124
|
+
<div class="shell-actions">
|
|
3125
|
+
@for (action of actions.controls; track action; let i = $index) {
|
|
3126
|
+
<div class="shell-action" [formGroup]="action">
|
|
3127
|
+
<div class="shell-action-row">
|
|
3128
|
+
<mat-form-field appearance="outline">
|
|
3129
|
+
<mat-label>ID</mat-label>
|
|
3130
|
+
<input matInput formControlName="id" />
|
|
3131
|
+
</mat-form-field>
|
|
3132
|
+
<mat-form-field appearance="outline">
|
|
3133
|
+
<mat-label>Label</mat-label>
|
|
3134
|
+
<input matInput formControlName="label" />
|
|
3135
|
+
</mat-form-field>
|
|
3136
|
+
<mat-form-field appearance="outline">
|
|
3137
|
+
<mat-label>Ícone</mat-label>
|
|
3138
|
+
<input matInput formControlName="icon" />
|
|
3139
|
+
</mat-form-field>
|
|
3140
|
+
</div>
|
|
3141
|
+
<div class="shell-action-row">
|
|
3142
|
+
<mat-form-field appearance="outline">
|
|
3143
|
+
<mat-label>Variante</mat-label>
|
|
3144
|
+
<mat-select formControlName="variant">
|
|
3145
|
+
<mat-option value="text">Texto</mat-option>
|
|
3146
|
+
<mat-option value="outlined">Outlined</mat-option>
|
|
3147
|
+
<mat-option value="icon">Ícone</mat-option>
|
|
3148
|
+
</mat-select>
|
|
3149
|
+
</mat-form-field>
|
|
3150
|
+
<mat-form-field appearance="outline">
|
|
3151
|
+
<mat-label>Posição</mat-label>
|
|
3152
|
+
<mat-select formControlName="placement">
|
|
3153
|
+
<mat-option value="header">Cabeçalho</mat-option>
|
|
3154
|
+
<mat-option value="window">Janela</mat-option>
|
|
3155
|
+
</mat-select>
|
|
3156
|
+
</mat-form-field>
|
|
3157
|
+
<mat-form-field appearance="outline">
|
|
3158
|
+
<mat-label>Emit</mat-label>
|
|
3159
|
+
<input matInput formControlName="emit" placeholder="ex: editar" />
|
|
3160
|
+
</mat-form-field>
|
|
3161
|
+
<mat-form-field appearance="outline">
|
|
3162
|
+
<mat-label>Tooltip</mat-label>
|
|
3163
|
+
<input matInput formControlName="tooltip" />
|
|
3164
|
+
</mat-form-field>
|
|
3165
|
+
</div>
|
|
3166
|
+
<div class="shell-action-row">
|
|
3167
|
+
<mat-form-field appearance="outline">
|
|
3168
|
+
<mat-label>Command</mat-label>
|
|
3169
|
+
<input matInput formControlName="command" placeholder="ex: add-item" />
|
|
3170
|
+
</mat-form-field>
|
|
3171
|
+
<mat-form-field appearance="outline">
|
|
3172
|
+
<mat-label>Payload (JSON)</mat-label>
|
|
3173
|
+
<textarea matInput rows="2" formControlName="payload" placeholder='ex: {"foo":"bar"}'></textarea>
|
|
3174
|
+
</mat-form-field>
|
|
3175
|
+
<mat-checkbox formControlName="visible">Visível</mat-checkbox>
|
|
3176
|
+
<mat-checkbox formControlName="disabled">Desabilitado</mat-checkbox>
|
|
3177
|
+
</div>
|
|
3178
|
+
@if (showActionInputPath(action.value)) {
|
|
3179
|
+
<div class="shell-action-hint">
|
|
3180
|
+
Input: {{ displayInputPath(extractActionInput(action.value)) }}
|
|
3181
|
+
</div>
|
|
3182
|
+
}
|
|
3183
|
+
<div class="shell-action-actions">
|
|
3184
|
+
<button mat-stroked-button color="warn" type="button" (click)="removeAction(i)">Remover</button>
|
|
3185
|
+
</div>
|
|
3186
|
+
</div>
|
|
3187
|
+
}
|
|
3188
|
+
</div>
|
|
3189
|
+
} @else {
|
|
3190
|
+
<div class="shell-empty">Nenhuma ação configurada.</div>
|
|
3191
|
+
}
|
|
3192
|
+
|
|
3193
|
+
</div>
|
|
3194
|
+
`, isInline: true, styles: [".shell-editor{display:grid;gap:20px;padding:12px 4px 20px}.shell-intro{margin:0;max-width:68ch;color:var(--md-sys-color-on-surface-variant);font-size:14px;line-height:1.5}.shell-section{margin:4px 0 -8px;color:var(--md-sys-color-on-surface);font-size:14px;font-weight:650;line-height:1.4}.shell-grid{display:grid;gap:12px 16px;grid-template-columns:repeat(2,minmax(0,1fr));align-items:start}.shell-field--wide{grid-column:1 / -1}.shell-flags{display:flex;gap:16px;align-items:center}.shell-actions-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.shell-available{display:grid;gap:12px}.shell-available-toolbar{display:grid;gap:12px;grid-template-columns:minmax(200px,1fr)}.shell-available-filters{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.shell-available-list{display:grid;gap:10px}.shell-available-item{display:grid;gap:8px;grid-template-columns:1fr auto;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;background:var(--md-sys-color-surface-container-low)}.shell-available-title{display:flex;align-items:center;gap:10px}.shell-available-text{display:grid;gap:4px}.shell-available-label{font-weight:600}.shell-available-meta{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-available-payload{font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-warning{font-size:11px;color:var(--md-sys-color-error)}.shell-available-actions{display:flex;align-items:flex-start;justify-content:flex-end}.shell-badge{padding:2px 6px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);font-size:10px}.shell-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.shell-actions{display:grid;gap:12px}.shell-action{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;display:grid;gap:8px}.shell-action-row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.shell-action-actions{display:flex;justify-content:flex-end}.shell-action-hint,.shell-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-hint{align-self:center;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-quick-inputs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));align-items:end}.shell-input-path{font-size:12px;color:var(--md-sys-color-on-surface-variant);align-self:center}.shell-editor .mat-mdc-form-field{width:100%}.shell-preview{border:1px dashed var(--md-sys-color-outline-variant);border-radius:12px;padding:12px}.shell-preview-card{background:var(--pdx-shell-card-bg, var(--md-sys-color-surface));border:1px solid var(--pdx-shell-card-border, var(--md-sys-color-outline-variant));border-radius:var(--pdx-shell-card-radius, 14px);box-shadow:var(--pdx-shell-card-shadow, var(--mat-elevation-level2));overflow:hidden}.shell-preview-card.no-shell{background:transparent;border:none;box-shadow:none}.shell-preview-card.expanded{box-shadow:var(--pdx-shell-card-shadow, 0 16px 34px rgba(0,0,0,.32));transform:scale(1.01)}.shell-preview-header{display:flex;align-items:center;gap:12px;padding:10px 12px 8px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.shell-preview-title{display:flex;align-items:center;gap:10px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.shell-preview-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.shell-preview-text{min-width:0}.shell-preview-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 14px);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-subtitle{font-size:var(--pdx-shell-subtitle-size, 12px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-actions{display:flex;align-items:center;gap:6px}.pdx-preview-text{padding:0 8px}.pdx-preview-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-preview-label{font-size:12px;font-weight:500}.shell-preview-body{padding:var(--pdx-shell-body-padding, 10px 12px 12px 12px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit);font-size:12px}.shell-preview-body.hidden{display:none}@media(max-width:640px){.shell-editor{padding-inline:0}.shell-grid{grid-template-columns:minmax(0,1fr)}.shell-field--wide{grid-column:auto}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5$1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i6.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3$1.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i5.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: MatSelectModule }, { kind: "component", type: i6$1.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$1.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3195
|
+
}
|
|
3196
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: WidgetShellEditorComponent, decorators: [{
|
|
3197
|
+
type: Component,
|
|
3198
|
+
args: [{ selector: 'praxis-widget-shell-editor', standalone: true, imports: [
|
|
3199
|
+
CommonModule,
|
|
3200
|
+
FormsModule,
|
|
3201
|
+
ReactiveFormsModule,
|
|
3202
|
+
MatButtonModule,
|
|
3203
|
+
MatCheckboxModule,
|
|
3204
|
+
MatDividerModule,
|
|
3205
|
+
MatFormFieldModule,
|
|
3206
|
+
MatIconModule,
|
|
3207
|
+
MatInputModule,
|
|
3208
|
+
MatSelectModule,
|
|
3209
|
+
PraxisIconButtonComponent,
|
|
3210
|
+
PraxisIconDirective,
|
|
3211
|
+
], template: `
|
|
3212
|
+
<div class="shell-editor">
|
|
3213
|
+
<p class="shell-intro">
|
|
3214
|
+
Defina a identidade, a aparência e as ações do card. Use a prévia para conferir o resultado antes de salvar.
|
|
3215
|
+
</p>
|
|
3216
|
+
|
|
3217
|
+
<div class="shell-section">Geral</div>
|
|
3218
|
+
<div class="shell-grid">
|
|
3219
|
+
<mat-form-field appearance="outline">
|
|
3220
|
+
<mat-label>Tipo de card</mat-label>
|
|
3221
|
+
<mat-select [formControl]="form.controls.kind">
|
|
3222
|
+
<mat-option value="dashboard-card">Dashboard Card</mat-option>
|
|
3223
|
+
<mat-option value="none">Sem shell</mat-option>
|
|
3224
|
+
</mat-select>
|
|
3225
|
+
</mat-form-field>
|
|
3226
|
+
<mat-form-field appearance="outline">
|
|
3227
|
+
<mat-label>Preset</mat-label>
|
|
3228
|
+
<mat-select [formControl]="form.controls.preset">
|
|
3229
|
+
<mat-option value="">Nenhum</mat-option>
|
|
3230
|
+
@if (pagePreset) {
|
|
3231
|
+
<mat-option [value]="pagePreset">Usar preset da página ({{ pagePreset }})</mat-option>
|
|
3232
|
+
}
|
|
3233
|
+
@for (p of presetOptions; track p) {
|
|
3234
|
+
<mat-option [value]="p.id">{{ p.label }}</mat-option>
|
|
3235
|
+
}
|
|
3236
|
+
</mat-select>
|
|
3237
|
+
</mat-form-field>
|
|
3238
|
+
@if (!form.controls.preset.value && pagePreset) {
|
|
3239
|
+
<div class="shell-hint">
|
|
3240
|
+
Preset da página: {{ pagePreset }}
|
|
3241
|
+
</div>
|
|
3242
|
+
}
|
|
3243
|
+
@if (form.controls.preset.value) {
|
|
3244
|
+
<mat-checkbox [formControl]="form.controls.applyToAll">
|
|
3245
|
+
Aplicar preset como padrão da página
|
|
3246
|
+
</mat-checkbox>
|
|
3247
|
+
}
|
|
3248
|
+
<mat-form-field appearance="outline">
|
|
3249
|
+
<mat-label>Ícone</mat-label>
|
|
3250
|
+
<input matInput [formControl]="form.controls.icon" placeholder="ex: badge" />
|
|
3251
|
+
</mat-form-field>
|
|
3252
|
+
<mat-form-field appearance="outline">
|
|
3253
|
+
<mat-label>Título</mat-label>
|
|
3254
|
+
<input matInput [formControl]="form.controls.title" />
|
|
3255
|
+
</mat-form-field>
|
|
3256
|
+
<mat-form-field appearance="outline" class="shell-field--wide">
|
|
3257
|
+
<mat-label>Subtítulo</mat-label>
|
|
3258
|
+
<input matInput [formControl]="form.controls.subtitle" />
|
|
3259
|
+
</mat-form-field>
|
|
3260
|
+
<mat-form-field appearance="outline">
|
|
3261
|
+
<mat-label>Mostrar cabeçalho</mat-label>
|
|
3262
|
+
<mat-select [formControl]="form.controls.showHeader">
|
|
3263
|
+
<mat-option value="auto">Automático</mat-option>
|
|
3264
|
+
<mat-option value="true">Sempre</mat-option>
|
|
3265
|
+
<mat-option value="false">Nunca</mat-option>
|
|
3266
|
+
</mat-select>
|
|
3267
|
+
</mat-form-field>
|
|
3268
|
+
</div>
|
|
3269
|
+
|
|
3270
|
+
<div class="shell-section">Controles de janela</div>
|
|
3271
|
+
<div class="shell-flags">
|
|
3272
|
+
<mat-checkbox [formControl]="form.controls.collapsible">Permitir recolher</mat-checkbox>
|
|
3273
|
+
</div>
|
|
3274
|
+
|
|
3275
|
+
<mat-divider></mat-divider>
|
|
3276
|
+
|
|
3277
|
+
<div class="shell-section">Aparência</div>
|
|
3278
|
+
<div class="shell-grid">
|
|
3279
|
+
<mat-form-field appearance="outline">
|
|
3280
|
+
<mat-label>Fundo do card</mat-label>
|
|
3281
|
+
<input matInput [formControl]="form.controls.cardBg" placeholder="ex: #0b1220" />
|
|
3282
|
+
</mat-form-field>
|
|
3283
|
+
<mat-form-field appearance="outline">
|
|
3284
|
+
<mat-label>Cor da borda</mat-label>
|
|
3285
|
+
<input matInput [formControl]="form.controls.cardBorder" placeholder="ex: rgba(255,255,255,0.12)" />
|
|
3286
|
+
</mat-form-field>
|
|
3287
|
+
<mat-form-field appearance="outline">
|
|
3288
|
+
<mat-label>Raio da borda</mat-label>
|
|
3289
|
+
<input matInput [formControl]="form.controls.cardRadius" placeholder="ex: 14px" />
|
|
3290
|
+
</mat-form-field>
|
|
3291
|
+
<mat-form-field appearance="outline">
|
|
3292
|
+
<mat-label>Sombra</mat-label>
|
|
3293
|
+
<input matInput [formControl]="form.controls.cardShadow" placeholder="ex: 0 10px 30px rgba(0,0,0,0.2)" />
|
|
3294
|
+
</mat-form-field>
|
|
3295
|
+
<mat-form-field appearance="outline">
|
|
3296
|
+
<mat-label>Fundo do cabeçalho</mat-label>
|
|
3297
|
+
<input matInput [formControl]="form.controls.headerBg" placeholder="ex: linear-gradient(...)" />
|
|
3298
|
+
</mat-form-field>
|
|
3299
|
+
<mat-form-field appearance="outline">
|
|
3300
|
+
<mat-label>Borda do cabeçalho</mat-label>
|
|
3301
|
+
<input matInput [formControl]="form.controls.headerBorder" placeholder="ex: rgba(255,255,255,0.08)" />
|
|
3302
|
+
</mat-form-field>
|
|
3303
|
+
<mat-form-field appearance="outline">
|
|
3304
|
+
<mat-label>Cor do título</mat-label>
|
|
3305
|
+
<input matInput [formControl]="form.controls.titleColor" placeholder="ex: #e6edf3" />
|
|
3306
|
+
</mat-form-field>
|
|
3307
|
+
<mat-form-field appearance="outline">
|
|
3308
|
+
<mat-label>Cor do subtítulo</mat-label>
|
|
3309
|
+
<input matInput [formControl]="form.controls.subtitleColor" placeholder="ex: #9fb0c4" />
|
|
3310
|
+
</mat-form-field>
|
|
3311
|
+
<mat-form-field appearance="outline">
|
|
3312
|
+
<mat-label>Cor do ícone</mat-label>
|
|
3313
|
+
<input matInput [formControl]="form.controls.iconColor" placeholder="ex: #8ab4ff" />
|
|
3314
|
+
</mat-form-field>
|
|
3315
|
+
<mat-form-field appearance="outline">
|
|
3316
|
+
<mat-label>Fundo do corpo</mat-label>
|
|
3317
|
+
<input matInput [formControl]="form.controls.bodyBg" placeholder="ex: transparent" />
|
|
3318
|
+
</mat-form-field>
|
|
3319
|
+
<mat-form-field appearance="outline">
|
|
3320
|
+
<mat-label>Cor do texto do corpo</mat-label>
|
|
3321
|
+
<input matInput [formControl]="form.controls.bodyColor" placeholder="ex: #e6edf3" />
|
|
3322
|
+
</mat-form-field>
|
|
3323
|
+
<mat-form-field appearance="outline">
|
|
3324
|
+
<mat-label>Padding do corpo</mat-label>
|
|
3325
|
+
<input matInput [formControl]="form.controls.bodyPadding" placeholder="ex: 10px 12px 12px" />
|
|
3326
|
+
</mat-form-field>
|
|
3327
|
+
<mat-form-field appearance="outline">
|
|
3328
|
+
<mat-label>Tamanho do título</mat-label>
|
|
3329
|
+
<input matInput [formControl]="form.controls.titleSize" placeholder="ex: 14px" />
|
|
3330
|
+
</mat-form-field>
|
|
3331
|
+
<mat-form-field appearance="outline">
|
|
3332
|
+
<mat-label>Peso do título</mat-label>
|
|
3333
|
+
<input matInput [formControl]="form.controls.titleWeight" placeholder="ex: 600" />
|
|
3334
|
+
</mat-form-field>
|
|
3335
|
+
<mat-form-field appearance="outline">
|
|
3336
|
+
<mat-label>Tamanho do subtítulo</mat-label>
|
|
3337
|
+
<input matInput [formControl]="form.controls.subtitleSize" placeholder="ex: 12px" />
|
|
3338
|
+
</mat-form-field>
|
|
3339
|
+
</div>
|
|
3340
|
+
|
|
3341
|
+
<div class="shell-preview" [ngStyle]="previewVars()">
|
|
3342
|
+
<div class="shell-preview-card" [class.no-shell]="form.controls.kind.value === 'none'" [class.expanded]="previewExpanded">
|
|
3343
|
+
@if (previewShowHeader()) {
|
|
3344
|
+
<div class="shell-preview-header">
|
|
3345
|
+
<div class="shell-preview-title">
|
|
3346
|
+
@if (form.controls.icon.value) {
|
|
3347
|
+
<mat-icon [praxisIcon]="form.controls.icon.value"></mat-icon>
|
|
3348
|
+
}
|
|
3349
|
+
<div class="shell-preview-text">
|
|
3350
|
+
<div class="shell-preview-title-text">{{ previewTitle() }}</div>
|
|
3351
|
+
<div class="shell-preview-subtitle">{{ previewSubtitle() }}</div>
|
|
3352
|
+
</div>
|
|
3353
|
+
</div>
|
|
3354
|
+
<div class="shell-preview-actions">
|
|
3355
|
+
@for (action of previewHeaderActions(); track action.id) {
|
|
3356
|
+
<button
|
|
3357
|
+
type="button"
|
|
3358
|
+
[disabled]="action.disabled"
|
|
3359
|
+
[ngClass]="action.variant === 'outlined' ? 'pdx-preview-outlined' : 'pdx-preview-text'"
|
|
3360
|
+
mat-button
|
|
3361
|
+
>
|
|
3362
|
+
@if (action.icon) {
|
|
3363
|
+
<mat-icon [praxisIcon]="action.icon"></mat-icon>
|
|
3364
|
+
}
|
|
3365
|
+
<span class="pdx-preview-label">{{ action.label || action.id }}</span>
|
|
3366
|
+
</button>
|
|
3367
|
+
}
|
|
3368
|
+
@if (previewOverflowCount()) {
|
|
3369
|
+
<button
|
|
3370
|
+
praxisIconButton="more_horiz"
|
|
3371
|
+
size="compact"
|
|
3372
|
+
type="button"
|
|
3373
|
+
aria-label="Mais ações"
|
|
3374
|
+
></button>
|
|
3375
|
+
}
|
|
3376
|
+
@for (action of previewWindowActions(); track action.id) {
|
|
3377
|
+
@if (action.icon) {
|
|
3378
|
+
<button
|
|
3379
|
+
[praxisIconButton]="action.icon"
|
|
3380
|
+
size="compact"
|
|
3381
|
+
type="button"
|
|
3382
|
+
[disabled]="action.disabled"
|
|
3383
|
+
[attr.aria-label]="action.label || action.id"
|
|
3384
|
+
></button>
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
<button
|
|
3388
|
+
[praxisIconButton]="previewCollapsed ? 'unfold_more' : 'unfold_less'"
|
|
3389
|
+
size="compact"
|
|
3390
|
+
type="button"
|
|
3391
|
+
(click)="togglePreviewCollapse()"
|
|
3392
|
+
aria-label="Recolher"
|
|
3393
|
+
></button>
|
|
3394
|
+
<button
|
|
3395
|
+
[praxisIconButton]="previewExpanded ? 'close_fullscreen' : 'open_in_full'"
|
|
3396
|
+
size="compact"
|
|
3397
|
+
type="button"
|
|
3398
|
+
(click)="togglePreviewExpand()"
|
|
3399
|
+
aria-label="Expandir"
|
|
3400
|
+
></button>
|
|
3401
|
+
</div>
|
|
3402
|
+
</div>
|
|
3403
|
+
}
|
|
3404
|
+
<div class="shell-preview-body" [class.hidden]="previewCollapsed">Conteudo do widget</div>
|
|
3405
|
+
</div>
|
|
3406
|
+
</div>
|
|
3407
|
+
|
|
3408
|
+
<mat-divider></mat-divider>
|
|
3409
|
+
|
|
3410
|
+
@if (hasAvailableActions) {
|
|
3411
|
+
<div class="shell-section">Ações disponíveis</div>
|
|
3412
|
+
}
|
|
3413
|
+
@if (hasAvailableActions) {
|
|
3414
|
+
<div class="shell-available">
|
|
3415
|
+
<div class="shell-available-toolbar">
|
|
3416
|
+
<mat-form-field appearance="outline">
|
|
3417
|
+
<mat-label>Buscar ação</mat-label>
|
|
3418
|
+
<input matInput [formControl]="actionQuery" placeholder="ex: export, editar, submit" />
|
|
3419
|
+
</mat-form-field>
|
|
3420
|
+
<div class="shell-available-filters">
|
|
3421
|
+
<mat-checkbox [(ngModel)]="showScopeShell">Shell</mat-checkbox>
|
|
3422
|
+
<mat-checkbox [(ngModel)]="showScopeAny">Any</mat-checkbox>
|
|
3423
|
+
<mat-checkbox [(ngModel)]="showScopeToolbar">Toolbar</mat-checkbox>
|
|
3424
|
+
<mat-checkbox [(ngModel)]="showScopeContext">Context</mat-checkbox>
|
|
3425
|
+
</div>
|
|
3426
|
+
</div>
|
|
3427
|
+
<div class="shell-available-list">
|
|
3428
|
+
@for (action of filteredAvailableActions(); track action) {
|
|
3429
|
+
<div class="shell-available-item">
|
|
3430
|
+
<div class="shell-available-main">
|
|
3431
|
+
<div class="shell-available-title">
|
|
3432
|
+
@if (action.icon) {
|
|
3433
|
+
<mat-icon [praxisIcon]="action.icon"></mat-icon>
|
|
3434
|
+
}
|
|
3435
|
+
<div class="shell-available-text">
|
|
3436
|
+
<div class="shell-available-label">{{ action.label }}</div>
|
|
3437
|
+
<div class="shell-available-meta">
|
|
3438
|
+
<span class="shell-badge">{{ action.kind === 'command' ? 'Comando' : 'Ação' }}</span>
|
|
3439
|
+
<span class="shell-badge">{{ scopeLabel(action.scope) }}</span>
|
|
3440
|
+
<span class="shell-code">id: {{ action.id }}</span>
|
|
3441
|
+
@if (action.emit) {
|
|
3442
|
+
<span class="shell-code">emit: {{ action.emit }}</span>
|
|
3443
|
+
}
|
|
3444
|
+
@if (action.command) {
|
|
3445
|
+
<span class="shell-code">command: {{ action.command }}</span>
|
|
3446
|
+
}
|
|
3447
|
+
</div>
|
|
3448
|
+
</div>
|
|
3449
|
+
</div>
|
|
3450
|
+
@if (action.description) {
|
|
3451
|
+
<div class="shell-available-desc">{{ action.description }}</div>
|
|
3452
|
+
}
|
|
3453
|
+
@if (action.payloadExample !== undefined) {
|
|
3454
|
+
<div class="shell-available-payload">
|
|
3455
|
+
<span class="shell-code">payload: {{ stringifyPayload(action.payloadExample) }}</span>
|
|
3456
|
+
</div>
|
|
3457
|
+
}
|
|
3458
|
+
@if (action.scope === 'context') {
|
|
3459
|
+
<div class="shell-available-warning">
|
|
3460
|
+
Essa ação depende de item/linha selecionado; payload fixo pode não funcionar.
|
|
3461
|
+
</div>
|
|
3462
|
+
}
|
|
3463
|
+
</div>
|
|
3464
|
+
<div class="shell-available-actions">
|
|
3465
|
+
<button
|
|
3466
|
+
mat-stroked-button
|
|
3467
|
+
type="button"
|
|
3468
|
+
[color]="isActionSelected(action) ? 'warn' : 'primary'"
|
|
3469
|
+
(click)="toggleAvailableAction(action)"
|
|
3470
|
+
>
|
|
3471
|
+
{{ isActionSelected(action) ? 'Remover' : 'Adicionar' }}
|
|
3472
|
+
</button>
|
|
3473
|
+
</div>
|
|
3474
|
+
</div>
|
|
3475
|
+
}
|
|
3476
|
+
</div>
|
|
3477
|
+
</div>
|
|
3478
|
+
} @else {
|
|
3479
|
+
<div class="shell-empty">Nenhuma ação registrada para este componente.</div>
|
|
3480
|
+
}
|
|
3481
|
+
|
|
3482
|
+
@if (hasAvailableActions) {
|
|
3483
|
+
<mat-divider></mat-divider>
|
|
3484
|
+
}
|
|
3485
|
+
|
|
3486
|
+
@if (setInputPresets.length) {
|
|
3487
|
+
<div class="shell-section">Ações rápidas (inputs)</div>
|
|
3488
|
+
}
|
|
3489
|
+
@if (setInputPresets.length) {
|
|
3490
|
+
<div class="shell-quick-inputs">
|
|
3491
|
+
<mat-form-field appearance="outline">
|
|
3492
|
+
<mat-label>Input</mat-label>
|
|
3493
|
+
<mat-select [formControl]="setInputTarget">
|
|
3494
|
+
@for (preset of setInputPresets; track preset) {
|
|
3495
|
+
<mat-option [value]="preset.input">
|
|
3496
|
+
@if (preset.icon) {
|
|
3497
|
+
<mat-icon [praxisIcon]="preset.icon"></mat-icon>
|
|
3498
|
+
}
|
|
3499
|
+
{{ preset.label }}
|
|
3500
|
+
</mat-option>
|
|
3501
|
+
}
|
|
3502
|
+
</mat-select>
|
|
3503
|
+
</mat-form-field>
|
|
3504
|
+
@if (setInputTarget.value) {
|
|
3505
|
+
<div class="shell-input-path">
|
|
3506
|
+
Input: {{ displayInputPath(setInputTarget.value) }}
|
|
3507
|
+
</div>
|
|
3508
|
+
}
|
|
3509
|
+
<mat-form-field appearance="outline">
|
|
3510
|
+
<mat-label>Valor</mat-label>
|
|
3511
|
+
<mat-select [formControl]="setInputValue">
|
|
3512
|
+
@for (option of currentSetInputValues(); track option) {
|
|
3513
|
+
<mat-option [value]="option.value">
|
|
3514
|
+
@if (option.icon) {
|
|
3515
|
+
<mat-icon [praxisIcon]="option.icon"></mat-icon>
|
|
3516
|
+
}
|
|
3517
|
+
{{ option.label }}
|
|
3518
|
+
</mat-option>
|
|
3519
|
+
}
|
|
3520
|
+
</mat-select>
|
|
3521
|
+
</mat-form-field>
|
|
3522
|
+
<button mat-flat-button color="primary" type="button" (click)="addSetInputAction()">
|
|
3523
|
+
Adicionar ação
|
|
3524
|
+
</button>
|
|
3525
|
+
</div>
|
|
3526
|
+
}
|
|
3527
|
+
|
|
3528
|
+
<div class="shell-section shell-actions-head">
|
|
3529
|
+
<div>Ações do cabeçalho</div>
|
|
3530
|
+
<button mat-flat-button color="primary" type="button" (click)="addAction()">Adicionar ação</button>
|
|
3531
|
+
</div>
|
|
3532
|
+
|
|
3533
|
+
@if (actions.controls.length) {
|
|
3534
|
+
<div class="shell-actions">
|
|
3535
|
+
@for (action of actions.controls; track action; let i = $index) {
|
|
3536
|
+
<div class="shell-action" [formGroup]="action">
|
|
3537
|
+
<div class="shell-action-row">
|
|
3538
|
+
<mat-form-field appearance="outline">
|
|
3539
|
+
<mat-label>ID</mat-label>
|
|
3540
|
+
<input matInput formControlName="id" />
|
|
3541
|
+
</mat-form-field>
|
|
3542
|
+
<mat-form-field appearance="outline">
|
|
3543
|
+
<mat-label>Label</mat-label>
|
|
3544
|
+
<input matInput formControlName="label" />
|
|
3545
|
+
</mat-form-field>
|
|
3546
|
+
<mat-form-field appearance="outline">
|
|
3547
|
+
<mat-label>Ícone</mat-label>
|
|
3548
|
+
<input matInput formControlName="icon" />
|
|
3549
|
+
</mat-form-field>
|
|
3550
|
+
</div>
|
|
3551
|
+
<div class="shell-action-row">
|
|
3552
|
+
<mat-form-field appearance="outline">
|
|
3553
|
+
<mat-label>Variante</mat-label>
|
|
3554
|
+
<mat-select formControlName="variant">
|
|
3555
|
+
<mat-option value="text">Texto</mat-option>
|
|
3556
|
+
<mat-option value="outlined">Outlined</mat-option>
|
|
3557
|
+
<mat-option value="icon">Ícone</mat-option>
|
|
3558
|
+
</mat-select>
|
|
3559
|
+
</mat-form-field>
|
|
3560
|
+
<mat-form-field appearance="outline">
|
|
3561
|
+
<mat-label>Posição</mat-label>
|
|
3562
|
+
<mat-select formControlName="placement">
|
|
3563
|
+
<mat-option value="header">Cabeçalho</mat-option>
|
|
3564
|
+
<mat-option value="window">Janela</mat-option>
|
|
3565
|
+
</mat-select>
|
|
3566
|
+
</mat-form-field>
|
|
3567
|
+
<mat-form-field appearance="outline">
|
|
3568
|
+
<mat-label>Emit</mat-label>
|
|
3569
|
+
<input matInput formControlName="emit" placeholder="ex: editar" />
|
|
3570
|
+
</mat-form-field>
|
|
3571
|
+
<mat-form-field appearance="outline">
|
|
3572
|
+
<mat-label>Tooltip</mat-label>
|
|
3573
|
+
<input matInput formControlName="tooltip" />
|
|
3574
|
+
</mat-form-field>
|
|
3575
|
+
</div>
|
|
3576
|
+
<div class="shell-action-row">
|
|
3577
|
+
<mat-form-field appearance="outline">
|
|
3578
|
+
<mat-label>Command</mat-label>
|
|
3579
|
+
<input matInput formControlName="command" placeholder="ex: add-item" />
|
|
3580
|
+
</mat-form-field>
|
|
3581
|
+
<mat-form-field appearance="outline">
|
|
3582
|
+
<mat-label>Payload (JSON)</mat-label>
|
|
3583
|
+
<textarea matInput rows="2" formControlName="payload" placeholder='ex: {"foo":"bar"}'></textarea>
|
|
3584
|
+
</mat-form-field>
|
|
3585
|
+
<mat-checkbox formControlName="visible">Visível</mat-checkbox>
|
|
3586
|
+
<mat-checkbox formControlName="disabled">Desabilitado</mat-checkbox>
|
|
3587
|
+
</div>
|
|
3588
|
+
@if (showActionInputPath(action.value)) {
|
|
3589
|
+
<div class="shell-action-hint">
|
|
3590
|
+
Input: {{ displayInputPath(extractActionInput(action.value)) }}
|
|
3591
|
+
</div>
|
|
3592
|
+
}
|
|
3593
|
+
<div class="shell-action-actions">
|
|
3594
|
+
<button mat-stroked-button color="warn" type="button" (click)="removeAction(i)">Remover</button>
|
|
3595
|
+
</div>
|
|
3596
|
+
</div>
|
|
3597
|
+
}
|
|
3598
|
+
</div>
|
|
3599
|
+
} @else {
|
|
3600
|
+
<div class="shell-empty">Nenhuma ação configurada.</div>
|
|
3601
|
+
}
|
|
3602
|
+
|
|
3603
|
+
</div>
|
|
3604
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".shell-editor{display:grid;gap:20px;padding:12px 4px 20px}.shell-intro{margin:0;max-width:68ch;color:var(--md-sys-color-on-surface-variant);font-size:14px;line-height:1.5}.shell-section{margin:4px 0 -8px;color:var(--md-sys-color-on-surface);font-size:14px;font-weight:650;line-height:1.4}.shell-grid{display:grid;gap:12px 16px;grid-template-columns:repeat(2,minmax(0,1fr));align-items:start}.shell-field--wide{grid-column:1 / -1}.shell-flags{display:flex;gap:16px;align-items:center}.shell-actions-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.shell-available{display:grid;gap:12px}.shell-available-toolbar{display:grid;gap:12px;grid-template-columns:minmax(200px,1fr)}.shell-available-filters{display:flex;gap:12px;align-items:center;flex-wrap:wrap}.shell-available-list{display:grid;gap:10px}.shell-available-item{display:grid;gap:8px;grid-template-columns:1fr auto;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;background:var(--md-sys-color-surface-container-low)}.shell-available-title{display:flex;align-items:center;gap:10px}.shell-available-text{display:grid;gap:4px}.shell-available-label{font-weight:600}.shell-available-meta{display:flex;gap:8px;flex-wrap:wrap;font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-available-payload{font-size:11px;color:var(--md-sys-color-on-surface-variant)}.shell-available-warning{font-size:11px;color:var(--md-sys-color-error)}.shell-available-actions{display:flex;align-items:flex-start;justify-content:flex-end}.shell-badge{padding:2px 6px;border-radius:999px;border:1px solid var(--md-sys-color-outline-variant);font-size:10px}.shell-code{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.shell-actions{display:grid;gap:12px}.shell-action{border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:12px;display:grid;gap:8px}.shell-action-row{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.shell-action-actions{display:flex;justify-content:flex-end}.shell-action-hint,.shell-empty{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-hint{align-self:center;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.shell-quick-inputs{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));align-items:end}.shell-input-path{font-size:12px;color:var(--md-sys-color-on-surface-variant);align-self:center}.shell-editor .mat-mdc-form-field{width:100%}.shell-preview{border:1px dashed var(--md-sys-color-outline-variant);border-radius:12px;padding:12px}.shell-preview-card{background:var(--pdx-shell-card-bg, var(--md-sys-color-surface));border:1px solid var(--pdx-shell-card-border, var(--md-sys-color-outline-variant));border-radius:var(--pdx-shell-card-radius, 14px);box-shadow:var(--pdx-shell-card-shadow, var(--mat-elevation-level2));overflow:hidden}.shell-preview-card.no-shell{background:transparent;border:none;box-shadow:none}.shell-preview-card.expanded{box-shadow:var(--pdx-shell-card-shadow, 0 16px 34px rgba(0,0,0,.32));transform:scale(1.01)}.shell-preview-header{display:flex;align-items:center;gap:12px;padding:10px 12px 8px;border-bottom:1px solid var(--pdx-shell-header-border, var(--md-sys-color-outline-variant));background:var(--pdx-shell-header-bg, var(--md-sys-color-surface-container))}.shell-preview-title{display:flex;align-items:center;gap:10px;min-width:0;flex:1;color:var(--pdx-shell-title-color, inherit)}.shell-preview-title mat-icon{color:var(--pdx-shell-icon-color, currentColor)}.shell-preview-text{min-width:0}.shell-preview-title-text{font-weight:var(--pdx-shell-title-weight, 600);font-size:var(--pdx-shell-title-size, 14px);line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-subtitle{font-size:var(--pdx-shell-subtitle-size, 12px);opacity:.75;color:var(--pdx-shell-subtitle-color, currentColor);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.shell-preview-actions{display:flex;align-items:center;gap:6px}.pdx-preview-text{padding:0 8px}.pdx-preview-outlined{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;padding:0 10px}.pdx-preview-label{font-size:12px;font-weight:500}.shell-preview-body{padding:var(--pdx-shell-body-padding, 10px 12px 12px 12px);background:var(--pdx-shell-body-bg, transparent);color:var(--pdx-shell-body-color, inherit);font-size:12px}.shell-preview-body.hidden{display:none}@media(max-width:640px){.shell-editor{padding-inline:0}.shell-grid{grid-template-columns:minmax(0,1fr)}.shell-field--wide{grid-column:auto}}\n"] }]
|
|
3605
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
3606
|
+
type: Optional
|
|
3607
|
+
}, {
|
|
3608
|
+
type: Inject,
|
|
3609
|
+
args: [SETTINGS_PANEL_DATA]
|
|
3610
|
+
}] }, { type: i2$2.ComponentMetadataRegistry, decorators: [{
|
|
3611
|
+
type: Optional
|
|
3612
|
+
}] }] });
|
|
3613
|
+
|
|
3614
|
+
function buildConnectionsViewerModel(page) {
|
|
3615
|
+
const widgets = page?.widgets ?? [];
|
|
3616
|
+
const links = page?.composition?.links ?? [];
|
|
3617
|
+
const counts = new Map();
|
|
3618
|
+
for (const widget of widgets) {
|
|
3619
|
+
counts.set(widget.key, { incoming: 0, outgoing: 0 });
|
|
3628
3620
|
}
|
|
3621
|
+
const edges = links.map((link) => {
|
|
3622
|
+
const fromWidgetId = link.from.kind === 'component-port' ? link.from.ref.widget : null;
|
|
3623
|
+
const toWidgetId = link.to.kind === 'component-port' ? link.to.ref.widget : null;
|
|
3624
|
+
const fromNestedPath = link.from.kind === 'component-port' && link.from.ref.nestedPath?.length
|
|
3625
|
+
? clone$2(link.from.ref.nestedPath)
|
|
3626
|
+
: null;
|
|
3627
|
+
const toNestedPath = link.to.kind === 'component-port' && link.to.ref.nestedPath?.length
|
|
3628
|
+
? clone$2(link.to.ref.nestedPath)
|
|
3629
|
+
: null;
|
|
3630
|
+
const toStatePath = link.to.kind === 'state' ? link.to.ref.path : null;
|
|
3631
|
+
const diagnosticReasons = [];
|
|
3632
|
+
if (fromWidgetId && !counts.has(fromWidgetId)) {
|
|
3633
|
+
diagnosticReasons.push('missing-source-widget');
|
|
3634
|
+
}
|
|
3635
|
+
if (toWidgetId && !counts.has(toWidgetId)) {
|
|
3636
|
+
diagnosticReasons.push('missing-target-widget');
|
|
3637
|
+
}
|
|
3638
|
+
if (fromWidgetId) {
|
|
3639
|
+
const current = counts.get(fromWidgetId) ?? { incoming: 0, outgoing: 0 };
|
|
3640
|
+
current.outgoing += 1;
|
|
3641
|
+
counts.set(fromWidgetId, current);
|
|
3642
|
+
}
|
|
3643
|
+
if (toWidgetId) {
|
|
3644
|
+
const current = counts.get(toWidgetId) ?? { incoming: 0, outgoing: 0 };
|
|
3645
|
+
current.incoming += 1;
|
|
3646
|
+
counts.set(toWidgetId, current);
|
|
3647
|
+
}
|
|
3648
|
+
return {
|
|
3649
|
+
id: link.id,
|
|
3650
|
+
fromKind: link.from.kind,
|
|
3651
|
+
fromWidgetId,
|
|
3652
|
+
fromEndpointId: link.from.kind === 'component-port'
|
|
3653
|
+
? buildComponentEndpointId(link.from.ref.widget, link.from.ref.nestedPath)
|
|
3654
|
+
: null,
|
|
3655
|
+
fromNestedPath,
|
|
3656
|
+
fromPort: link.from.kind === 'component-port' ? link.from.ref.port : null,
|
|
3657
|
+
toKind: link.to.kind,
|
|
3658
|
+
toWidgetId,
|
|
3659
|
+
toEndpointId: link.to.kind === 'component-port'
|
|
3660
|
+
? buildComponentEndpointId(link.to.ref.widget, link.to.ref.nestedPath)
|
|
3661
|
+
: null,
|
|
3662
|
+
toNestedPath,
|
|
3663
|
+
toPort: link.to.kind === 'component-port' ? link.to.ref.port : null,
|
|
3664
|
+
toStatePath,
|
|
3665
|
+
intent: link.intent,
|
|
3666
|
+
hasCondition: !!link.condition,
|
|
3667
|
+
hasTransform: !!link.transform?.steps?.length,
|
|
3668
|
+
hasPolicy: !!link.policy && Object.keys(link.policy).length > 0,
|
|
3669
|
+
hasDiagnostics: diagnosticReasons.length > 0,
|
|
3670
|
+
diagnosticReasons,
|
|
3671
|
+
link,
|
|
3672
|
+
};
|
|
3673
|
+
});
|
|
3674
|
+
const nodes = widgets.map((widget) => {
|
|
3675
|
+
const counter = counts.get(widget.key) ?? { incoming: 0, outgoing: 0 };
|
|
3676
|
+
return {
|
|
3677
|
+
widgetId: widget.key,
|
|
3678
|
+
componentType: widget.definition?.id ?? 'unknown',
|
|
3679
|
+
incomingCount: counter.incoming,
|
|
3680
|
+
outgoingCount: counter.outgoing,
|
|
3681
|
+
};
|
|
3682
|
+
});
|
|
3629
3683
|
return {
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3684
|
+
nodes,
|
|
3685
|
+
edges,
|
|
3686
|
+
totalLinks: edges.length,
|
|
3687
|
+
conditionLinks: edges.filter((edge) => edge.hasCondition).length,
|
|
3688
|
+
transformLinks: edges.filter((edge) => edge.hasTransform).length,
|
|
3689
|
+
policyLinks: edges.filter((edge) => edge.hasPolicy).length,
|
|
3690
|
+
diagnosticLinks: edges.filter((edge) => edge.hasDiagnostics).length,
|
|
3633
3691
|
};
|
|
3634
3692
|
}
|
|
3635
|
-
function
|
|
3636
|
-
|
|
3693
|
+
function buildComponentEndpointId(ownerWidgetKey, nestedPath) {
|
|
3694
|
+
if (!nestedPath?.length) {
|
|
3695
|
+
return ownerWidgetKey;
|
|
3696
|
+
}
|
|
3697
|
+
return `${ownerWidgetKey}${nestedPath
|
|
3698
|
+
.map((segment) => `/${formatPathSegment$1(segment)}`)
|
|
3699
|
+
.join('')}`;
|
|
3637
3700
|
}
|
|
3638
|
-
function
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3701
|
+
function formatPathSegment$1(segment) {
|
|
3702
|
+
if (segment.kind === 'widget') {
|
|
3703
|
+
const identity = segment.key
|
|
3704
|
+
|| segment.componentType
|
|
3705
|
+
|| (typeof segment.index === 'number' ? String(segment.index) : 'unknown');
|
|
3706
|
+
return `widget:${identity}`;
|
|
3707
|
+
}
|
|
3708
|
+
return [
|
|
3709
|
+
segment.kind,
|
|
3710
|
+
segment.id || segment.key || segment.index,
|
|
3711
|
+
].filter((part) => part !== undefined && part !== '').join(':');
|
|
3712
|
+
}
|
|
3713
|
+
function clone$2(value) {
|
|
3714
|
+
if (value == null || typeof value !== 'object')
|
|
3715
|
+
return value;
|
|
3716
|
+
return JSON.parse(JSON.stringify(value));
|
|
3643
3717
|
}
|
|
3644
3718
|
|
|
3645
3719
|
const CONNECTION_EDITOR_STATE_NODE_ID = '__page_state__';
|
|
@@ -20961,7 +21035,7 @@ class DynamicPageBuilderComponent {
|
|
|
20961
21035
|
}
|
|
20962
21036
|
runtimePage() {
|
|
20963
21037
|
const page = this.currentPage();
|
|
20964
|
-
if (!this.previewMode) {
|
|
21038
|
+
if (!this.previewMode && this.showSettings()) {
|
|
20965
21039
|
if (this.runtimeAuthoringPageCache?.source === page) {
|
|
20966
21040
|
return this.runtimeAuthoringPageCache.value;
|
|
20967
21041
|
}
|
|
@@ -20992,10 +21066,13 @@ class DynamicPageBuilderComponent {
|
|
|
20992
21066
|
return this.tx('builderMode.presentation', 'Presentation');
|
|
20993
21067
|
}
|
|
20994
21068
|
onRuntimePageChange(next) {
|
|
20995
|
-
const
|
|
20996
|
-
this.currentPage
|
|
20997
|
-
|
|
20998
|
-
|
|
21069
|
+
const canonical = this.toCanonicalPageFromAuthoringRuntime(next);
|
|
21070
|
+
if (JSON.stringify(canonical) === JSON.stringify(this.currentPage())) {
|
|
21071
|
+
return;
|
|
21072
|
+
}
|
|
21073
|
+
this.currentPage.set(canonical);
|
|
21074
|
+
this.clearSelectedWidgetIfMissing(canonical);
|
|
21075
|
+
this.pageChange.emit(canonical);
|
|
20999
21076
|
}
|
|
21000
21077
|
onRuntimeWidgetEvent(event) {
|
|
21001
21078
|
this.widgetEvent.emit(event);
|
|
@@ -23713,11 +23790,48 @@ class DynamicPageBuilderComponent {
|
|
|
23713
23790
|
});
|
|
23714
23791
|
return cloned;
|
|
23715
23792
|
}
|
|
23793
|
+
/**
|
|
23794
|
+
* Removes authoring-only inputs from a page emitted by the embedded runtime.
|
|
23795
|
+
*
|
|
23796
|
+
* The runtime must receive `enableCustomization=true` so nested components can
|
|
23797
|
+
* expose their editors, but that projection is not part of the authored page.
|
|
23798
|
+
* Restore the canonical value by widget key before publishing `pageChange` so
|
|
23799
|
+
* a presentation-only edit cannot accidentally persist authoring chrome.
|
|
23800
|
+
*/
|
|
23801
|
+
toCanonicalPageFromAuthoringRuntime(page) {
|
|
23802
|
+
const canonicalByKey = new Map((this.currentPage().widgets || []).map((widget) => [widget.key, widget]));
|
|
23803
|
+
const cloned = this.clonePage(page);
|
|
23804
|
+
cloned.widgets = (cloned.widgets || []).map((widget) => {
|
|
23805
|
+
const metadata = this.componentMetadata.get(widget.definition?.id);
|
|
23806
|
+
if (!metadata?.inputs?.some((input) => input.name === 'enableCustomization')) {
|
|
23807
|
+
return widget;
|
|
23808
|
+
}
|
|
23809
|
+
const canonicalInputs = canonicalByKey.get(widget.key)?.definition?.inputs;
|
|
23810
|
+
const inputs = { ...(widget.definition?.inputs || {}) };
|
|
23811
|
+
if (canonicalInputs && Object.prototype.hasOwnProperty.call(canonicalInputs, 'enableCustomization')) {
|
|
23812
|
+
inputs['enableCustomization'] = canonicalInputs['enableCustomization'];
|
|
23813
|
+
}
|
|
23814
|
+
else {
|
|
23815
|
+
delete inputs['enableCustomization'];
|
|
23816
|
+
}
|
|
23817
|
+
return {
|
|
23818
|
+
...widget,
|
|
23819
|
+
definition: {
|
|
23820
|
+
...widget.definition,
|
|
23821
|
+
inputs,
|
|
23822
|
+
},
|
|
23823
|
+
};
|
|
23824
|
+
});
|
|
23825
|
+
return cloned;
|
|
23826
|
+
}
|
|
23716
23827
|
toPresentationRuntimeWidget(widget) {
|
|
23717
|
-
const
|
|
23718
|
-
if (!inputs
|
|
23828
|
+
const metadata = this.componentMetadata.get(widget.definition?.id);
|
|
23829
|
+
if (!metadata?.inputs?.some((input) => input.name === 'enableCustomization')) {
|
|
23719
23830
|
return widget;
|
|
23720
23831
|
}
|
|
23832
|
+
const inputs = widget.definition?.inputs || {};
|
|
23833
|
+
if (inputs['enableCustomization'] === false)
|
|
23834
|
+
return widget;
|
|
23721
23835
|
return {
|
|
23722
23836
|
...widget,
|
|
23723
23837
|
definition: {
|
|
@@ -24959,6 +25073,11 @@ class DynamicPageBuilderComponent {
|
|
|
24959
25073
|
[previewActive]="isPreviewMode()"
|
|
24960
25074
|
[connectionMode]="showSettings() && connectionsViewerOpen()"
|
|
24961
25075
|
[modeLabel]="builderModeLabel()"
|
|
25076
|
+
[addLabel]="tx('toolbar.add', 'Inserir componente')"
|
|
25077
|
+
[saveLabel]="tx('toolbar.save', 'Salvar página')"
|
|
25078
|
+
[undoLabel]="tx('toolbar.undo', 'Desfazer')"
|
|
25079
|
+
[redoLabel]="tx('toolbar.redo', 'Refazer')"
|
|
25080
|
+
[settingsLabel]="tx('toolbar.settings', 'Configurações da página')"
|
|
24962
25081
|
[previewLabel]="tx('toolbar.preview', 'Pré-visualizar')"
|
|
24963
25082
|
[exitPreviewLabel]="tx('toolbar.exitPreview', 'Voltar para edição')"
|
|
24964
25083
|
(add)="onAddComponent()"
|
|
@@ -25036,7 +25155,7 @@ class DynamicPageBuilderComponent {
|
|
|
25036
25155
|
}
|
|
25037
25156
|
</praxis-floating-toolbar>
|
|
25038
25157
|
</div>
|
|
25039
|
-
`, isInline: true, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%;box-sizing:border-box}.builder-shell--bottom-toolbar{padding-block-end:calc(80px + env(safe-area-inset-bottom,0px))}.builder-shell:has(.pdx-shell.fullscreen) praxis-floating-toolbar{display:none}.builder-premium-readiness{display:grid;grid-template-columns:minmax(220px,.72fr) minmax(0,1.28fr);gap:12px;width:100%;margin:0 0 14px;padding:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 72%,transparent);border-radius:12px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 10%,transparent),transparent 36%),color-mix(in srgb,var(--md-sys-color-surface-container-lowest, #fff) 96%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);box-shadow:inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface, #1d1b20) 5%,transparent)}.builder-premium-readiness__header{display:flex;align-items:flex-start;gap:10px;min-width:0}.builder-premium-readiness__header strong{display:block;font-size:13px;line-height:1.25}.builder-premium-readiness__header p,.builder-premium-readiness__item p{margin:2px 0 0;color:var(--md-sys-color-on-surface-variant, #49454f);font-size:11px;line-height:1.35}.builder-premium-readiness__icon{color:var(--md-sys-color-primary, #6750a4);font-size:20px;line-height:1}.builder-premium-readiness__list{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:8px;margin:0;padding:0;list-style:none}.builder-premium-readiness__item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 64%,transparent);border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, #f7f2fa) 84%,transparent)}.builder-premium-readiness__item strong{display:block;font-size:12px;line-height:1.25}.builder-premium-readiness__action{appearance:none;display:inline-flex;align-items:center;justify-content:center;min-height:26px;margin-top:7px;padding:4px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 34%,transparent);border-radius:7px;background:color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 9%,var(--md-sys-color-surface, #fff));color:var(--md-sys-color-primary, #6750a4);cursor:pointer;font:inherit;font-size:11px;font-weight:700;line-height:1.2;text-align:left}.builder-premium-readiness__severity{width:8px;height:8px;margin-top:4px;border-radius:999px;background:var(--md-sys-color-primary, #6750a4)}.builder-premium-readiness__item[data-severity=warning] .builder-premium-readiness__severity{background:var(--praxis-warning, #b26a00)}.builder-premium-readiness__item[data-severity=error] .builder-premium-readiness__severity{background:var(--md-sys-color-error, #b3261e)}@media(max-width:760px){.builder-premium-readiness{grid-template-columns:1fr}}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent);border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 84%,transparent);color:var(--md-sys-color-primary);cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}.agentic-diagnostics-panel__health{display:grid;gap:8px;margin-bottom:12px}.agentic-diagnostics-panel__health h3,.agentic-diagnostics-panel__health p{margin:0}.agentic-diagnostics-panel__health h3{font-size:13px}.agentic-diagnostics-panel__health p{color:#4b5563;font-size:11px}.agentic-diagnostics-panel__metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:0}.agentic-diagnostics-panel__metrics div{padding:8px;border-radius:8px;background:#f3f4f6}.agentic-diagnostics-panel__metrics dt{color:#4b5563;font-size:10px}.agentic-diagnostics-panel__metrics dd{margin:3px 0 0;font-size:14px;font-weight:700}.agentic-diagnostics-panel__health-table{width:100%;border-collapse:collapse;font-size:10px}.agentic-diagnostics-panel__health-table caption{margin-bottom:4px;text-align:left;font-weight:700}.agentic-diagnostics-panel__health-table th,.agentic-diagnostics-panel__health-table td{padding:5px 4px;border-bottom:1px solid #e5e7eb;text-align:left}.agentic-diagnostics-panel__raw summary{margin-bottom:8px;cursor:pointer;font-size:11px;font-weight:700}@media(max-width:520px){.agentic-diagnostics-panel__metrics{grid-template-columns:repeat(2,minmax(0,1fr))}}praxis-ai-assistant-shell{position:fixed;inset:0;z-index:140;pointer-events:none}@media(min-width:1100px){.builder-shell--agentic-review-rail{box-sizing:border-box;padding-right:464px}}.builder-shell__agentic-toggle{position:relative}.builder-shell__agentic-toggle--open,.builder-shell__agentic-toggle--minimized{outline:2px solid rgba(96,165,250,.52);outline-offset:2px}.builder-shell__agentic-toggle--minimized:after{content:\"\";position:absolute;top:6px;right:6px;width:8px;height:8px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#34d399}.builder-shell__connections-toggle--open{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 52%,transparent);outline-offset:2px}.builder-shell__connections-toggle{position:relative}.builder-shell__connections-toggle--recommended:not(.builder-shell__connections-toggle--open){outline:2px solid rgba(34,211,238,.48);outline-offset:2px}.builder-shell__connections-toggle-badge{position:absolute;top:5px;right:5px;width:9px;height:9px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#22d3ee;box-shadow:0 0 0 3px #22d3ee2e}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,transparent);border-radius:12px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface-container-high) 76%),color-mix(in srgb,var(--md-sys-color-tertiary-container) 18%,var(--md-sys-color-surface-container) 82%));color:var(--md-sys-color-on-surface);box-shadow:0 18px 46px color-mix(in srgb,var(--md-sys-color-shadow, #000) 24%,transparent);overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:var(--md-sys-color-on-surface-variant);font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent);border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 74%,transparent);color:var(--md-sys-color-primary);font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:var(--md-sys-color-error);font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 72%,transparent)}.shared-rule-cockpit__facts dt{color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:var(--md-sys-color-on-surface);font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent);border-radius:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 58%,transparent)}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:var(--md-sys-color-on-surface);font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:var(--md-sys-color-on-surface-variant);font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 52%,transparent);border-radius:11px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent)}.shared-rule-cockpit__projection[data-status=ready]{border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 24%,transparent);background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 32%,var(--md-sys-color-surface-container-low) 68%)}.shared-rule-cockpit__projection span{color:var(--md-sys-color-primary);font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:var(--md-sys-color-on-surface);font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:var(--md-sys-color-on-surface-variant);font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent);border-radius:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 76%,transparent)}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:var(--md-sys-color-primary);font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:var(--md-sys-color-on-surface);font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:var(--md-sys-color-on-surface-variant);font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-secondary-container) 42%,transparent);color:var(--md-sys-color-on-secondary-container);font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 64%,transparent)}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.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: "component", type: DynamicWidgetPageComponent, selector: "praxis-dynamic-page", inputs: ["page", "context", "strictValidation", "enableCustomization", "showPageSettingsButton", "shellEditorComponent", "pageEditorComponent", "autoPersist", "pageIdentity", "componentInstanceId", "showWidgetAssistantButton"], outputs: ["pageChange", "widgetEvent", "widgetSelectionChange", "widgetAssistantRequested", "widgetDiagnosticsChange"] }, { kind: "component", type: FloatingToolbarComponent, selector: "praxis-floating-toolbar", inputs: ["visible", "canUndo", "canRedo", "showSave", "showPreview", "editingEnabled", "previewActive", "connectionMode", "modeLabel", "previewLabel", "exitPreviewLabel"], outputs: ["add", "undo", "redo", "settings", "preview", "save"] }, { kind: "component", type: ConnectionEditorComponent, selector: "praxis-connection-editor", inputs: ["open", "page"], outputs: ["pageChange", "focusWidget", "openPageSettings", "close"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "recommendedIntents", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "voiceInputMode", "voiceLanguage", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "recommendedIntent", "layoutChange"] }] });
|
|
25158
|
+
`, isInline: true, styles: [":host{display:block;position:relative;min-height:var(--pdx-page-builder-min-height, 420px)}.builder-shell{display:block;position:relative;min-height:inherit;height:100%;box-sizing:border-box}.builder-shell--bottom-toolbar{padding-block-end:calc(80px + env(safe-area-inset-bottom,0px))}.builder-shell:has(.pdx-shell.fullscreen) praxis-floating-toolbar{display:none}.builder-premium-readiness{display:grid;grid-template-columns:minmax(220px,.72fr) minmax(0,1.28fr);gap:12px;width:100%;margin:0 0 14px;padding:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 72%,transparent);border-radius:12px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 10%,transparent),transparent 36%),color-mix(in srgb,var(--md-sys-color-surface-container-lowest, #fff) 96%,transparent);color:var(--md-sys-color-on-surface, #1d1b20);box-shadow:inset 0 1px color-mix(in srgb,var(--md-sys-color-on-surface, #1d1b20) 5%,transparent)}.builder-premium-readiness__header{display:flex;align-items:flex-start;gap:10px;min-width:0}.builder-premium-readiness__header strong{display:block;font-size:13px;line-height:1.25}.builder-premium-readiness__header p,.builder-premium-readiness__item p{margin:2px 0 0;color:var(--md-sys-color-on-surface-variant, #49454f);font-size:11px;line-height:1.35}.builder-premium-readiness__icon{color:var(--md-sys-color-primary, #6750a4);font-size:20px;line-height:1}.builder-premium-readiness__list{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:8px;margin:0;padding:0;list-style:none}.builder-premium-readiness__item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:8px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 64%,transparent);border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low, #f7f2fa) 84%,transparent)}.builder-premium-readiness__item strong{display:block;font-size:12px;line-height:1.25}.builder-premium-readiness__action{appearance:none;display:inline-flex;align-items:center;justify-content:center;min-height:26px;margin-top:7px;padding:4px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 34%,transparent);border-radius:7px;background:color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 9%,var(--md-sys-color-surface, #fff));color:var(--md-sys-color-primary, #6750a4);cursor:pointer;font:inherit;font-size:11px;font-weight:700;line-height:1.2;text-align:left}.builder-premium-readiness__severity{width:8px;height:8px;margin-top:4px;border-radius:999px;background:var(--md-sys-color-primary, #6750a4)}.builder-premium-readiness__item[data-severity=warning] .builder-premium-readiness__severity{background:var(--praxis-warning, #b26a00)}.builder-premium-readiness__item[data-severity=error] .builder-premium-readiness__severity{background:var(--md-sys-color-error, #b3261e)}@media(max-width:760px){.builder-premium-readiness{grid-template-columns:1fr}}.agentic-diagnostics-panel{position:absolute;z-index:21;right:16px;width:min(520px,calc(100% - 32px));max-height:min(440px,calc(100% - 32px));overflow:auto;padding:12px;border:1px solid rgba(107,114,128,.28);border-radius:8px;background:#fffffff5;color:#111827;box-shadow:0 14px 36px #0000003d}.agentic-diagnostics-panel--collapsed{width:min(280px,calc(100% - 32px));max-height:58px;overflow:hidden;padding:10px 12px;pointer-events:auto}.agentic-diagnostics-panel__header{display:flex;align-items:center;justify-content:space-between;gap:12px;font-size:13px;font-weight:700}.agentic-diagnostics-panel__header-actions{display:flex;align-items:center;gap:8px}.agentic-diagnostics-panel__badge{padding:2px 6px;border:1px solid rgba(107,114,128,.28);border-radius:8px;font-size:11px;font-weight:600;color:#4b5563}.agentic-diagnostics-panel__toggle,.shared-rule-cockpit__toggle{appearance:none;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,transparent);border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 84%,transparent);color:var(--md-sys-color-primary);cursor:pointer;font-size:11px;font-weight:700;line-height:1;padding:6px 9px;white-space:nowrap}.agentic-diagnostics-panel__description{margin:8px 0 10px;color:#4b5563;font-size:12px;line-height:1.4}.agentic-diagnostics-panel pre{margin:0;white-space:pre-wrap;overflow-wrap:anywhere;font-size:11px;line-height:1.45;color:#1f2937}.agentic-diagnostics-panel__health{display:grid;gap:8px;margin-bottom:12px}.agentic-diagnostics-panel__health h3,.agentic-diagnostics-panel__health p{margin:0}.agentic-diagnostics-panel__health h3{font-size:13px}.agentic-diagnostics-panel__health p{color:#4b5563;font-size:11px}.agentic-diagnostics-panel__metrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:0}.agentic-diagnostics-panel__metrics div{padding:8px;border-radius:8px;background:#f3f4f6}.agentic-diagnostics-panel__metrics dt{color:#4b5563;font-size:10px}.agentic-diagnostics-panel__metrics dd{margin:3px 0 0;font-size:14px;font-weight:700}.agentic-diagnostics-panel__health-table{width:100%;border-collapse:collapse;font-size:10px}.agentic-diagnostics-panel__health-table caption{margin-bottom:4px;text-align:left;font-weight:700}.agentic-diagnostics-panel__health-table th,.agentic-diagnostics-panel__health-table td{padding:5px 4px;border-bottom:1px solid #e5e7eb;text-align:left}.agentic-diagnostics-panel__raw summary{margin-bottom:8px;cursor:pointer;font-size:11px;font-weight:700}@media(max-width:520px){.agentic-diagnostics-panel__metrics{grid-template-columns:repeat(2,minmax(0,1fr))}}praxis-ai-assistant-shell{position:fixed;inset:0;z-index:140;pointer-events:none}@media(min-width:1100px){.builder-shell--agentic-review-rail{box-sizing:border-box;padding-right:464px}}.builder-shell__agentic-toggle{position:relative}.builder-shell__agentic-toggle--open,.builder-shell__agentic-toggle--minimized{outline:2px solid rgba(96,165,250,.52);outline-offset:2px}.builder-shell__agentic-toggle--minimized:after{content:\"\";position:absolute;top:6px;right:6px;width:8px;height:8px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#34d399}.builder-shell__connections-toggle--open{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary, #6750a4) 52%,transparent);outline-offset:2px}.builder-shell__connections-toggle{position:relative}.builder-shell__connections-toggle--recommended:not(.builder-shell__connections-toggle--open){outline:2px solid rgba(34,211,238,.48);outline-offset:2px}.builder-shell__connections-toggle-badge{position:absolute;top:5px;right:5px;width:9px;height:9px;border:2px solid var(--md-sys-color-surface, #111827);border-radius:999px;background:#22d3ee;box-shadow:0 0 0 3px #22d3ee2e}.shared-rule-cockpit{position:absolute;z-index:120;left:16px;bottom:88px;width:min(720px,calc(100% - 32px));max-height:min(560px,calc(100vh - 140px));padding:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 24%,transparent);border-radius:12px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface-container-high) 76%),color-mix(in srgb,var(--md-sys-color-tertiary-container) 18%,var(--md-sys-color-surface-container) 82%));color:var(--md-sys-color-on-surface);box-shadow:0 18px 46px color-mix(in srgb,var(--md-sys-color-shadow, #000) 24%,transparent);overflow:auto;overscroll-behavior:contain}.shared-rule-cockpit--collapsed{width:min(360px,calc(100% - 32px));max-height:72px;overflow:hidden;padding:10px 12px}.shared-rule-cockpit__header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px}.shared-rule-cockpit__header-actions{display:flex;align-items:center;gap:8px}.shared-rule-cockpit__header div{display:grid;gap:2px}.shared-rule-cockpit__header strong{font-size:14px;line-height:1.2}.shared-rule-cockpit__header span{color:var(--md-sys-color-on-surface-variant);font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__badge{flex:0 0 auto;max-width:220px;padding:3px 8px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent);border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 74%,transparent);color:var(--md-sys-color-primary);font-size:11px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.shared-rule-cockpit__description,.shared-rule-cockpit__status,.shared-rule-cockpit__error{margin:10px 0 0;color:var(--md-sys-color-on-surface-variant);font-size:12px;line-height:1.45}.shared-rule-cockpit__error{color:var(--md-sys-color-error);font-weight:600}.shared-rule-cockpit__actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.shared-rule-cockpit__facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin:12px 0 0}.shared-rule-cockpit__facts div{min-width:0;padding:8px;border-radius:10px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 72%,transparent)}.shared-rule-cockpit__facts dt{color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}.shared-rule-cockpit__facts dd{margin:4px 0 0;color:var(--md-sys-color-on-surface);font-size:12px;overflow-wrap:anywhere}.shared-rule-cockpit__enforcement-matrix{display:grid;gap:10px;margin-top:12px;padding:10px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent);border-radius:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 58%,transparent)}.shared-rule-cockpit__matrix-header{display:flex;align-items:flex-start;justify-content:space-between;gap:10px}.shared-rule-cockpit__matrix-header div{display:grid;gap:2px}.shared-rule-cockpit__matrix-header strong{color:var(--md-sys-color-on-surface);font-size:12px}.shared-rule-cockpit__matrix-header span,.shared-rule-cockpit__matrix-source{color:var(--md-sys-color-on-surface-variant);font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-badge{flex:0 0 auto;padding:3px 8px;border-radius:999px;background:#16a34a1f;color:#166534;font-weight:800;white-space:nowrap}.shared-rule-cockpit__projection-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}.shared-rule-cockpit__projection{display:grid;gap:3px;min-width:0;padding:9px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 52%,transparent);border-radius:11px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent)}.shared-rule-cockpit__projection[data-status=ready]{border-color:color-mix(in srgb,var(--md-sys-color-tertiary) 24%,transparent);background:color-mix(in srgb,var(--md-sys-color-tertiary-container) 32%,var(--md-sys-color-surface-container-low) 68%)}.shared-rule-cockpit__projection span{color:var(--md-sys-color-primary);font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;overflow-wrap:anywhere}.shared-rule-cockpit__projection strong{color:var(--md-sys-color-on-surface);font-size:12px}.shared-rule-cockpit__projection small,.shared-rule-cockpit__projection em{color:var(--md-sys-color-on-surface-variant);font-size:11px;font-style:normal;overflow-wrap:anywhere}.shared-rule-cockpit__matrix-source{margin:0}.shared-rule-cockpit__timeline{display:grid;gap:8px;max-height:190px;margin:12px 0 0;padding:0;overflow:auto;list-style:none}.shared-rule-cockpit__timeline-item{display:grid;grid-template-columns:auto minmax(0,1fr);gap:10px;padding:10px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 12%,transparent);border-radius:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 76%,transparent)}.shared-rule-cockpit__timeline-icon{display:grid;width:24px;height:24px;place-items:center;border-radius:999px;background:#1e40af1a;color:var(--md-sys-color-primary);font-family:Material Icons;font-size:16px;line-height:1}.shared-rule-cockpit__timeline-item strong{color:var(--md-sys-color-on-surface);font-size:12px;line-height:1.35}.shared-rule-cockpit__timeline-item p,.shared-rule-cockpit__timeline-item small,.shared-rule-cockpit__timeline-item time,.shared-rule-cockpit__timeline-empty{display:block;margin:3px 0 0;color:var(--md-sys-color-on-surface-variant);font-size:11px;line-height:1.35;overflow-wrap:anywhere}.shared-rule-cockpit__timeline-badge{display:inline-flex;margin-left:6px;padding:2px 6px;border-radius:999px;background:color-mix(in srgb,var(--md-sys-color-secondary-container) 42%,transparent);color:var(--md-sys-color-on-secondary-container);font-size:10px;font-weight:700}.shared-rule-cockpit__timeline-empty{padding:10px;border-radius:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-lowest) 64%,transparent)}@media(max-width:720px){.shared-rule-cockpit{bottom:72px;max-height:calc(100vh - 112px)}.shared-rule-cockpit__facts,.shared-rule-cockpit__projection-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.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: i2.MatMiniFabButton, selector: "button[mat-mini-fab], a[mat-mini-fab], button[matMiniFab], a[matMiniFab]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i3.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: "component", type: DynamicWidgetPageComponent, selector: "praxis-dynamic-page", inputs: ["page", "context", "strictValidation", "enableCustomization", "showPageSettingsButton", "shellEditorComponent", "pageEditorComponent", "autoPersist", "pageIdentity", "componentInstanceId", "showWidgetAssistantButton"], outputs: ["pageChange", "widgetEvent", "widgetSelectionChange", "widgetAssistantRequested", "widgetDiagnosticsChange"] }, { kind: "component", type: FloatingToolbarComponent, selector: "praxis-floating-toolbar", inputs: ["visible", "canUndo", "canRedo", "showSave", "showPreview", "editingEnabled", "previewActive", "connectionMode", "modeLabel", "addLabel", "saveLabel", "undoLabel", "redoLabel", "settingsLabel", "previewLabel", "exitPreviewLabel"], outputs: ["add", "undo", "redo", "settings", "preview", "save"] }, { kind: "component", type: ConnectionEditorComponent, selector: "praxis-connection-editor", inputs: ["open", "page"], outputs: ["pageChange", "focusWidget", "openPageSettings", "close"] }, { kind: "component", type: PraxisAiAssistantShellComponent, selector: "praxis-ai-assistant-shell", inputs: ["labels", "mode", "state", "contextItems", "attachments", "messages", "quickReplies", "recommendedIntents", "prompt", "statusText", "errorText", "testIdPrefix", "panelTestId", "submitTestId", "applyTestId", "primaryAction", "secondaryActions", "governanceActions", "busy", "canSubmit", "canApply", "submitOnEnter", "showAttachAction", "enablePastedAttachments", "enableFileAttachments", "attachmentAccept", "attachmentMultiple", "voiceInputMode", "voiceLanguage", "draggable", "resizable", "minWidth", "minHeight", "margin", "layout"], outputs: ["promptChange", "submitPrompt", "apply", "retryTurn", "cancelTurn", "shellAction", "close", "attach", "attachmentsPasted", "attachmentsSelected", "removeAttachment", "messageAction", "editMessage", "resendMessage", "quickReply", "recommendedIntent", "layoutChange"] }] });
|
|
25040
25159
|
}
|
|
25041
25160
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: DynamicPageBuilderComponent, decorators: [{
|
|
25042
25161
|
type: Component,
|
|
@@ -25515,6 +25634,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
25515
25634
|
[previewActive]="isPreviewMode()"
|
|
25516
25635
|
[connectionMode]="showSettings() && connectionsViewerOpen()"
|
|
25517
25636
|
[modeLabel]="builderModeLabel()"
|
|
25637
|
+
[addLabel]="tx('toolbar.add', 'Inserir componente')"
|
|
25638
|
+
[saveLabel]="tx('toolbar.save', 'Salvar página')"
|
|
25639
|
+
[undoLabel]="tx('toolbar.undo', 'Desfazer')"
|
|
25640
|
+
[redoLabel]="tx('toolbar.redo', 'Refazer')"
|
|
25641
|
+
[settingsLabel]="tx('toolbar.settings', 'Configurações da página')"
|
|
25518
25642
|
[previewLabel]="tx('toolbar.preview', 'Pré-visualizar')"
|
|
25519
25643
|
[exitPreviewLabel]="tx('toolbar.exitPreview', 'Voltar para edição')"
|
|
25520
25644
|
(add)="onAddComponent()"
|