@praxisui/stepper 1.0.0-beta.29 → 1.0.0-beta.40
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 +71 -4
- package/fesm2022/praxisui-stepper.mjs +2895 -118
- package/fesm2022/praxisui-stepper.mjs.map +1 -1
- package/index.d.ts +261 -7
- package/package.json +7 -7
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import * as i1$1 from '@angular/common';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { Inject, Component, inject, signal, EventEmitter, computed, TemplateRef, Output, Input, ContentChild, ChangeDetectionStrategy, ENVIRONMENT_INITIALIZER } from '@angular/core';
|
|
4
|
+
import { Inject, Component, inject, signal, EventEmitter, computed, TemplateRef, Output, Input, ContentChild, ChangeDetectionStrategy, ENVIRONMENT_INITIALIZER, isDevMode, ElementRef, Renderer2, effect, ViewChild } from '@angular/core';
|
|
5
|
+
import { ActivatedRoute } from '@angular/router';
|
|
5
6
|
import * as i2$1 from '@angular/material/stepper';
|
|
6
7
|
import { MatStepperModule } from '@angular/material/stepper';
|
|
7
8
|
import * as i6 from '@angular/material/button';
|
|
8
9
|
import { MatButtonModule } from '@angular/material/button';
|
|
9
10
|
import * as i5$1 from '@angular/material/icon';
|
|
10
11
|
import { MatIconModule } from '@angular/material/icon';
|
|
11
|
-
import { IconPickerService, PraxisIconDirective, DynamicWidgetLoaderDirective, EmptyStateCardComponent, ComponentMetadataRegistry } from '@praxisui/core';
|
|
12
|
+
import { IconPickerService, PraxisIconDirective, deepMerge, ASYNC_CONFIG_STORAGE, ComponentKeyService, LoggerService, DynamicWidgetLoaderDirective, EmptyStateCardComponent, ComponentMetadataRegistry, createCorporateLoggerConfig, ConsoleLoggerSink, CONFIG_STORAGE } from '@praxisui/core';
|
|
12
13
|
import * as i2 from '@angular/forms';
|
|
13
14
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
14
15
|
import { PraxisDynamicFormConfigEditor, PraxisDynamicForm } from '@praxisui/dynamic-form';
|
|
@@ -30,7 +31,9 @@ import * as i11 from '@angular/material/button-toggle';
|
|
|
30
31
|
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
|
31
32
|
import * as i1 from '@angular/material/dialog';
|
|
32
33
|
import { MAT_DIALOG_DATA, MatDialogModule, MatDialog } from '@angular/material/dialog';
|
|
33
|
-
import * as i12 from '@angular/material/
|
|
34
|
+
import * as i12 from '@angular/material/menu';
|
|
35
|
+
import { MatMenuModule } from '@angular/material/menu';
|
|
36
|
+
import * as i13 from '@angular/material/tabs';
|
|
34
37
|
import { MatTabsModule } from '@angular/material/tabs';
|
|
35
38
|
import { BehaviorSubject } from 'rxjs';
|
|
36
39
|
import { PraxisListConfigEditor } from '@praxisui/list';
|
|
@@ -38,6 +41,8 @@ import { PraxisFilesUploadConfigEditor } from '@praxisui/files-upload';
|
|
|
38
41
|
import { ComponentPaletteDialogComponent } from '@praxisui/page-builder';
|
|
39
42
|
import * as i5 from '@angular/material/checkbox';
|
|
40
43
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
44
|
+
import { BaseAiAdapter, PraxisAiAssistantComponent } from '@praxisui/ai';
|
|
45
|
+
import { take } from 'rxjs/operators';
|
|
41
46
|
|
|
42
47
|
class SelectQuickConfigDialogComponent {
|
|
43
48
|
ref;
|
|
@@ -136,6 +141,340 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
136
141
|
args: [MAT_DIALOG_DATA]
|
|
137
142
|
}] }] });
|
|
138
143
|
|
|
144
|
+
class WizardWidgetConfigDialogComponent {
|
|
145
|
+
ref;
|
|
146
|
+
wizardWidgetId;
|
|
147
|
+
dialogTitle;
|
|
148
|
+
model;
|
|
149
|
+
originalInputs;
|
|
150
|
+
constructor(ref, data) {
|
|
151
|
+
this.ref = ref;
|
|
152
|
+
const id = (data?.widgetId || '');
|
|
153
|
+
this.wizardWidgetId = this.isWizardWidgetId(id) ? id : null;
|
|
154
|
+
this.originalInputs = { ...(data?.inputs || {}) };
|
|
155
|
+
this.model = this.buildDraft(this.originalInputs);
|
|
156
|
+
this.dialogTitle = this.resolveTitle(this.wizardWidgetId);
|
|
157
|
+
}
|
|
158
|
+
get benefits() {
|
|
159
|
+
if (!Array.isArray(this.model.items))
|
|
160
|
+
this.model.items = [];
|
|
161
|
+
return this.model.items;
|
|
162
|
+
}
|
|
163
|
+
addBenefit() {
|
|
164
|
+
this.benefits.push({ title: '', text: '', icon: '' });
|
|
165
|
+
}
|
|
166
|
+
removeBenefit(index) {
|
|
167
|
+
this.benefits.splice(index, 1);
|
|
168
|
+
}
|
|
169
|
+
cancel() {
|
|
170
|
+
this.ref.close();
|
|
171
|
+
}
|
|
172
|
+
save() {
|
|
173
|
+
const next = { ...this.originalInputs, ...this.buildInputsForWidget() };
|
|
174
|
+
if (typeof next.blockId === 'string') {
|
|
175
|
+
next.blockId = next.blockId.trim();
|
|
176
|
+
}
|
|
177
|
+
if (!next.blockId)
|
|
178
|
+
delete next.blockId;
|
|
179
|
+
this.ref.close({ inputs: next });
|
|
180
|
+
}
|
|
181
|
+
isWizardWidgetId(value) {
|
|
182
|
+
return (value === 'praxis-wizard-benefits'
|
|
183
|
+
|| value === 'praxis-wizard-content'
|
|
184
|
+
|| value === 'praxis-wizard-inline-notice'
|
|
185
|
+
|| value === 'praxis-wizard-divider');
|
|
186
|
+
}
|
|
187
|
+
resolveTitle(id) {
|
|
188
|
+
switch (id) {
|
|
189
|
+
case 'praxis-wizard-benefits':
|
|
190
|
+
return 'Editar grade de benefícios';
|
|
191
|
+
case 'praxis-wizard-content':
|
|
192
|
+
return 'Editar bloco de conteúdo';
|
|
193
|
+
case 'praxis-wizard-inline-notice':
|
|
194
|
+
return 'Editar aviso inline';
|
|
195
|
+
case 'praxis-wizard-divider':
|
|
196
|
+
return 'Editar divisor';
|
|
197
|
+
default:
|
|
198
|
+
return 'Editar Widget do Wizard';
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
buildDraft(inputs) {
|
|
202
|
+
return {
|
|
203
|
+
blockId: inputs.blockId || '',
|
|
204
|
+
title: inputs.title || '',
|
|
205
|
+
subtitle: inputs.subtitle || '',
|
|
206
|
+
text: inputs.text || '',
|
|
207
|
+
caption: inputs.caption || '',
|
|
208
|
+
tone: inputs.tone || 'neutral',
|
|
209
|
+
label: inputs.label || '',
|
|
210
|
+
columns: Number.isFinite(Number(inputs.columns)) ? Number(inputs.columns) : 4,
|
|
211
|
+
boxed: !!inputs.boxed,
|
|
212
|
+
items: Array.isArray(inputs.items)
|
|
213
|
+
? inputs.items.map((item) => ({ icon: item?.icon || '', title: item?.title || '', text: item?.text || '' }))
|
|
214
|
+
: [],
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
buildInputsForWidget() {
|
|
218
|
+
if (!this.wizardWidgetId)
|
|
219
|
+
return { ...this.model };
|
|
220
|
+
const base = {};
|
|
221
|
+
if (this.model.blockId?.trim())
|
|
222
|
+
base.blockId = this.model.blockId.trim();
|
|
223
|
+
switch (this.wizardWidgetId) {
|
|
224
|
+
case 'praxis-wizard-inline-notice':
|
|
225
|
+
base.text = this.model.text || '';
|
|
226
|
+
base.tone = this.model.tone || 'neutral';
|
|
227
|
+
return base;
|
|
228
|
+
case 'praxis-wizard-content':
|
|
229
|
+
base.title = this.model.title || '';
|
|
230
|
+
base.subtitle = this.model.subtitle || '';
|
|
231
|
+
base.text = this.model.text || '';
|
|
232
|
+
base.caption = this.model.caption || '';
|
|
233
|
+
return base;
|
|
234
|
+
case 'praxis-wizard-divider':
|
|
235
|
+
base.label = this.model.label || '';
|
|
236
|
+
return base;
|
|
237
|
+
case 'praxis-wizard-benefits':
|
|
238
|
+
base.title = this.model.title || '';
|
|
239
|
+
base.columns = this.safeColumns(this.model.columns);
|
|
240
|
+
base.boxed = !!this.model.boxed;
|
|
241
|
+
base.items = this.benefits
|
|
242
|
+
.map((item) => ({
|
|
243
|
+
icon: item.icon || '',
|
|
244
|
+
title: item.title || '',
|
|
245
|
+
text: item.text || '',
|
|
246
|
+
}))
|
|
247
|
+
.filter((item) => item.title || item.text || item.icon);
|
|
248
|
+
return base;
|
|
249
|
+
default:
|
|
250
|
+
return base;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
safeColumns(value) {
|
|
254
|
+
const parsed = Number(value);
|
|
255
|
+
if (!Number.isFinite(parsed) || parsed < 1)
|
|
256
|
+
return 1;
|
|
257
|
+
return Math.floor(parsed);
|
|
258
|
+
}
|
|
259
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: WizardWidgetConfigDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
260
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: WizardWidgetConfigDialogComponent, isStandalone: true, selector: "praxis-wizard-widget-config-dialog", ngImport: i0, template: `
|
|
261
|
+
<h2 mat-dialog-title>{{ dialogTitle }}</h2>
|
|
262
|
+
|
|
263
|
+
<div mat-dialog-content class="dialog-grid">
|
|
264
|
+
<ng-container [ngSwitch]="wizardWidgetId">
|
|
265
|
+
<ng-container *ngSwitchCase="'praxis-wizard-inline-notice'">
|
|
266
|
+
<mat-form-field appearance="outline" class="full">
|
|
267
|
+
<mat-label>Texto</mat-label>
|
|
268
|
+
<input matInput [(ngModel)]="model.text" placeholder="Mensagem do aviso" />
|
|
269
|
+
</mat-form-field>
|
|
270
|
+
<mat-form-field appearance="outline">
|
|
271
|
+
<mat-label>Tom</mat-label>
|
|
272
|
+
<select matNativeControl [(ngModel)]="model.tone">
|
|
273
|
+
<option value="neutral">Neutro</option>
|
|
274
|
+
<option value="info">Informativo</option>
|
|
275
|
+
<option value="warning">Atenção</option>
|
|
276
|
+
</select>
|
|
277
|
+
</mat-form-field>
|
|
278
|
+
</ng-container>
|
|
279
|
+
|
|
280
|
+
<ng-container *ngSwitchCase="'praxis-wizard-content'">
|
|
281
|
+
<mat-form-field appearance="outline">
|
|
282
|
+
<mat-label>Título</mat-label>
|
|
283
|
+
<input matInput [(ngModel)]="model.title" />
|
|
284
|
+
</mat-form-field>
|
|
285
|
+
<mat-form-field appearance="outline">
|
|
286
|
+
<mat-label>Subtítulo</mat-label>
|
|
287
|
+
<input matInput [(ngModel)]="model.subtitle" />
|
|
288
|
+
</mat-form-field>
|
|
289
|
+
<mat-form-field appearance="outline" class="full">
|
|
290
|
+
<mat-label>Texto</mat-label>
|
|
291
|
+
<input matInput [(ngModel)]="model.text" />
|
|
292
|
+
</mat-form-field>
|
|
293
|
+
<mat-form-field appearance="outline" class="full">
|
|
294
|
+
<mat-label>Legenda</mat-label>
|
|
295
|
+
<input matInput [(ngModel)]="model.caption" />
|
|
296
|
+
</mat-form-field>
|
|
297
|
+
</ng-container>
|
|
298
|
+
|
|
299
|
+
<ng-container *ngSwitchCase="'praxis-wizard-divider'">
|
|
300
|
+
<mat-form-field appearance="outline" class="full">
|
|
301
|
+
<mat-label>Rótulo</mat-label>
|
|
302
|
+
<input matInput [(ngModel)]="model.label" placeholder="Opcional" />
|
|
303
|
+
</mat-form-field>
|
|
304
|
+
</ng-container>
|
|
305
|
+
|
|
306
|
+
<ng-container *ngSwitchCase="'praxis-wizard-benefits'">
|
|
307
|
+
<mat-form-field appearance="outline">
|
|
308
|
+
<mat-label>Título</mat-label>
|
|
309
|
+
<input matInput [(ngModel)]="model.title" />
|
|
310
|
+
</mat-form-field>
|
|
311
|
+
<mat-form-field appearance="outline">
|
|
312
|
+
<mat-label>Colunas</mat-label>
|
|
313
|
+
<input matInput type="number" min="1" [(ngModel)]="model.columns" />
|
|
314
|
+
</mat-form-field>
|
|
315
|
+
<mat-checkbox [(ngModel)]="model.boxed">Cards com contorno</mat-checkbox>
|
|
316
|
+
|
|
317
|
+
<div class="benefits">
|
|
318
|
+
<div class="benefits-head">
|
|
319
|
+
<strong>Itens de benefício</strong>
|
|
320
|
+
<button mat-stroked-button type="button" (click)="addBenefit()">Adicionar item</button>
|
|
321
|
+
</div>
|
|
322
|
+
<div class="benefit-card" *ngFor="let item of benefits; let i = index">
|
|
323
|
+
<div class="benefit-head">
|
|
324
|
+
<span>Item {{ i + 1 }}</span>
|
|
325
|
+
<button mat-button color="warn" type="button" (click)="removeBenefit(i)">Remover</button>
|
|
326
|
+
</div>
|
|
327
|
+
<mat-form-field appearance="outline">
|
|
328
|
+
<mat-label>Ícone</mat-label>
|
|
329
|
+
<input matInput [(ngModel)]="item.icon" placeholder="Ex.: info" />
|
|
330
|
+
</mat-form-field>
|
|
331
|
+
<mat-form-field appearance="outline">
|
|
332
|
+
<mat-label>Título</mat-label>
|
|
333
|
+
<input matInput [(ngModel)]="item.title" />
|
|
334
|
+
</mat-form-field>
|
|
335
|
+
<mat-form-field appearance="outline" class="full">
|
|
336
|
+
<mat-label>Texto</mat-label>
|
|
337
|
+
<input matInput [(ngModel)]="item.text" />
|
|
338
|
+
</mat-form-field>
|
|
339
|
+
</div>
|
|
340
|
+
</div>
|
|
341
|
+
</ng-container>
|
|
342
|
+
</ng-container>
|
|
343
|
+
|
|
344
|
+
<details class="advanced full">
|
|
345
|
+
<summary>Avançado</summary>
|
|
346
|
+
<div class="advanced-body">
|
|
347
|
+
<mat-form-field appearance="outline" class="full">
|
|
348
|
+
<mat-label>ID estável (avançado)</mat-label>
|
|
349
|
+
<input matInput [(ngModel)]="model.blockId" placeholder="Ex.: ft-edit-wizard:access:block:hero" />
|
|
350
|
+
<mat-hint>Use como chave estável de telemetria/E2E. Evite alterar após publicar.</mat-hint>
|
|
351
|
+
</mat-form-field>
|
|
352
|
+
</div>
|
|
353
|
+
</details>
|
|
354
|
+
</div>
|
|
355
|
+
|
|
356
|
+
<div mat-dialog-actions align="end">
|
|
357
|
+
<button mat-button type="button" (click)="cancel()">Cancelar</button>
|
|
358
|
+
<button mat-flat-button color="primary" type="button" (click)="save()">Salvar</button>
|
|
359
|
+
</div>
|
|
360
|
+
`, isInline: true, styles: [".dialog-grid{display:grid;gap:12px;min-width:min(760px,92vw)}.full{grid-column:1 / -1}.benefits{display:grid;gap:10px;border-top:1px solid var(--md-sys-color-outline-variant);padding-top:8px}.benefits-head{display:flex;justify-content:space-between;align-items:center;gap:8px}.benefit-card{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));padding:10px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest)}.benefit-head{grid-column:1 / -1;display:flex;align-items:center;justify-content:space-between;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.advanced{border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);padding:8px 10px;background:var(--md-sys-color-surface-container-lowest)}.advanced>summary{cursor:pointer;font-weight:600;list-style:none}.advanced>summary::-webkit-details-marker{display:none}.advanced-body{margin-top:10px;display:grid;gap:8px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatDialogModule }, { 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.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i5.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: MatButtonModule }, { kind: "component", type: i6.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"] }] });
|
|
361
|
+
}
|
|
362
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: WizardWidgetConfigDialogComponent, decorators: [{
|
|
363
|
+
type: Component,
|
|
364
|
+
args: [{ selector: 'praxis-wizard-widget-config-dialog', standalone: true, imports: [
|
|
365
|
+
CommonModule,
|
|
366
|
+
FormsModule,
|
|
367
|
+
MatDialogModule,
|
|
368
|
+
MatFormFieldModule,
|
|
369
|
+
MatInputModule,
|
|
370
|
+
MatCheckboxModule,
|
|
371
|
+
MatButtonModule,
|
|
372
|
+
], template: `
|
|
373
|
+
<h2 mat-dialog-title>{{ dialogTitle }}</h2>
|
|
374
|
+
|
|
375
|
+
<div mat-dialog-content class="dialog-grid">
|
|
376
|
+
<ng-container [ngSwitch]="wizardWidgetId">
|
|
377
|
+
<ng-container *ngSwitchCase="'praxis-wizard-inline-notice'">
|
|
378
|
+
<mat-form-field appearance="outline" class="full">
|
|
379
|
+
<mat-label>Texto</mat-label>
|
|
380
|
+
<input matInput [(ngModel)]="model.text" placeholder="Mensagem do aviso" />
|
|
381
|
+
</mat-form-field>
|
|
382
|
+
<mat-form-field appearance="outline">
|
|
383
|
+
<mat-label>Tom</mat-label>
|
|
384
|
+
<select matNativeControl [(ngModel)]="model.tone">
|
|
385
|
+
<option value="neutral">Neutro</option>
|
|
386
|
+
<option value="info">Informativo</option>
|
|
387
|
+
<option value="warning">Atenção</option>
|
|
388
|
+
</select>
|
|
389
|
+
</mat-form-field>
|
|
390
|
+
</ng-container>
|
|
391
|
+
|
|
392
|
+
<ng-container *ngSwitchCase="'praxis-wizard-content'">
|
|
393
|
+
<mat-form-field appearance="outline">
|
|
394
|
+
<mat-label>Título</mat-label>
|
|
395
|
+
<input matInput [(ngModel)]="model.title" />
|
|
396
|
+
</mat-form-field>
|
|
397
|
+
<mat-form-field appearance="outline">
|
|
398
|
+
<mat-label>Subtítulo</mat-label>
|
|
399
|
+
<input matInput [(ngModel)]="model.subtitle" />
|
|
400
|
+
</mat-form-field>
|
|
401
|
+
<mat-form-field appearance="outline" class="full">
|
|
402
|
+
<mat-label>Texto</mat-label>
|
|
403
|
+
<input matInput [(ngModel)]="model.text" />
|
|
404
|
+
</mat-form-field>
|
|
405
|
+
<mat-form-field appearance="outline" class="full">
|
|
406
|
+
<mat-label>Legenda</mat-label>
|
|
407
|
+
<input matInput [(ngModel)]="model.caption" />
|
|
408
|
+
</mat-form-field>
|
|
409
|
+
</ng-container>
|
|
410
|
+
|
|
411
|
+
<ng-container *ngSwitchCase="'praxis-wizard-divider'">
|
|
412
|
+
<mat-form-field appearance="outline" class="full">
|
|
413
|
+
<mat-label>Rótulo</mat-label>
|
|
414
|
+
<input matInput [(ngModel)]="model.label" placeholder="Opcional" />
|
|
415
|
+
</mat-form-field>
|
|
416
|
+
</ng-container>
|
|
417
|
+
|
|
418
|
+
<ng-container *ngSwitchCase="'praxis-wizard-benefits'">
|
|
419
|
+
<mat-form-field appearance="outline">
|
|
420
|
+
<mat-label>Título</mat-label>
|
|
421
|
+
<input matInput [(ngModel)]="model.title" />
|
|
422
|
+
</mat-form-field>
|
|
423
|
+
<mat-form-field appearance="outline">
|
|
424
|
+
<mat-label>Colunas</mat-label>
|
|
425
|
+
<input matInput type="number" min="1" [(ngModel)]="model.columns" />
|
|
426
|
+
</mat-form-field>
|
|
427
|
+
<mat-checkbox [(ngModel)]="model.boxed">Cards com contorno</mat-checkbox>
|
|
428
|
+
|
|
429
|
+
<div class="benefits">
|
|
430
|
+
<div class="benefits-head">
|
|
431
|
+
<strong>Itens de benefício</strong>
|
|
432
|
+
<button mat-stroked-button type="button" (click)="addBenefit()">Adicionar item</button>
|
|
433
|
+
</div>
|
|
434
|
+
<div class="benefit-card" *ngFor="let item of benefits; let i = index">
|
|
435
|
+
<div class="benefit-head">
|
|
436
|
+
<span>Item {{ i + 1 }}</span>
|
|
437
|
+
<button mat-button color="warn" type="button" (click)="removeBenefit(i)">Remover</button>
|
|
438
|
+
</div>
|
|
439
|
+
<mat-form-field appearance="outline">
|
|
440
|
+
<mat-label>Ícone</mat-label>
|
|
441
|
+
<input matInput [(ngModel)]="item.icon" placeholder="Ex.: info" />
|
|
442
|
+
</mat-form-field>
|
|
443
|
+
<mat-form-field appearance="outline">
|
|
444
|
+
<mat-label>Título</mat-label>
|
|
445
|
+
<input matInput [(ngModel)]="item.title" />
|
|
446
|
+
</mat-form-field>
|
|
447
|
+
<mat-form-field appearance="outline" class="full">
|
|
448
|
+
<mat-label>Texto</mat-label>
|
|
449
|
+
<input matInput [(ngModel)]="item.text" />
|
|
450
|
+
</mat-form-field>
|
|
451
|
+
</div>
|
|
452
|
+
</div>
|
|
453
|
+
</ng-container>
|
|
454
|
+
</ng-container>
|
|
455
|
+
|
|
456
|
+
<details class="advanced full">
|
|
457
|
+
<summary>Avançado</summary>
|
|
458
|
+
<div class="advanced-body">
|
|
459
|
+
<mat-form-field appearance="outline" class="full">
|
|
460
|
+
<mat-label>ID estável (avançado)</mat-label>
|
|
461
|
+
<input matInput [(ngModel)]="model.blockId" placeholder="Ex.: ft-edit-wizard:access:block:hero" />
|
|
462
|
+
<mat-hint>Use como chave estável de telemetria/E2E. Evite alterar após publicar.</mat-hint>
|
|
463
|
+
</mat-form-field>
|
|
464
|
+
</div>
|
|
465
|
+
</details>
|
|
466
|
+
</div>
|
|
467
|
+
|
|
468
|
+
<div mat-dialog-actions align="end">
|
|
469
|
+
<button mat-button type="button" (click)="cancel()">Cancelar</button>
|
|
470
|
+
<button mat-flat-button color="primary" type="button" (click)="save()">Salvar</button>
|
|
471
|
+
</div>
|
|
472
|
+
`, styles: [".dialog-grid{display:grid;gap:12px;min-width:min(760px,92vw)}.full{grid-column:1 / -1}.benefits{display:grid;gap:10px;border-top:1px solid var(--md-sys-color-outline-variant);padding-top:8px}.benefits-head{display:flex;justify-content:space-between;align-items:center;gap:8px}.benefit-card{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));padding:10px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-lowest)}.benefit-head{grid-column:1 / -1;display:flex;align-items:center;justify-content:space-between;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.advanced{border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);padding:8px 10px;background:var(--md-sys-color-surface-container-lowest)}.advanced>summary{cursor:pointer;font-weight:600;list-style:none}.advanced>summary::-webkit-details-marker{display:none}.advanced-body{margin-top:10px;display:grid;gap:8px}\n"] }]
|
|
473
|
+
}], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
|
|
474
|
+
type: Inject,
|
|
475
|
+
args: [MAT_DIALOG_DATA]
|
|
476
|
+
}] }] });
|
|
477
|
+
|
|
139
478
|
class PraxisStepperConfigEditor {
|
|
140
479
|
config = { steps: [], orientation: 'horizontal', headerPosition: 'top', linear: false };
|
|
141
480
|
activeIndex = 0;
|
|
@@ -236,8 +575,8 @@ class PraxisStepperConfigEditor {
|
|
|
236
575
|
'container-color': 'var(--md-sys-color-surface-container)',
|
|
237
576
|
'header-label-text-color': 'var(--md-sys-color-primary)',
|
|
238
577
|
'header-selected-state-icon-background-color': 'var(--md-sys-color-primary)',
|
|
239
|
-
'header-selected-state-icon-foreground-color': '
|
|
240
|
-
'line-color': '
|
|
578
|
+
'header-selected-state-icon-foreground-color': 'var(--md-sys-color-on-primary)',
|
|
579
|
+
'line-color': 'var(--md-sys-color-primary)',
|
|
241
580
|
},
|
|
242
581
|
neutral: {
|
|
243
582
|
'container-color': 'var(--md-sys-color-surface)',
|
|
@@ -245,11 +584,11 @@ class PraxisStepperConfigEditor {
|
|
|
245
584
|
'line-color': 'var(--md-sys-color-outline-variant)',
|
|
246
585
|
},
|
|
247
586
|
'high-contrast': {
|
|
248
|
-
'container-color': '
|
|
249
|
-
'header-label-text-color': '
|
|
250
|
-
'header-selected-state-icon-background-color': 'var(--md-sys-color-on-
|
|
251
|
-
'header-selected-state-icon-foreground-color': '
|
|
252
|
-
'line-color': '
|
|
587
|
+
'container-color': 'var(--md-sys-color-surface)',
|
|
588
|
+
'header-label-text-color': 'var(--md-sys-color-on-surface)',
|
|
589
|
+
'header-selected-state-icon-background-color': 'var(--md-sys-color-on-surface)',
|
|
590
|
+
'header-selected-state-icon-foreground-color': 'var(--md-sys-color-surface)',
|
|
591
|
+
'line-color': 'var(--md-sys-color-on-surface)',
|
|
253
592
|
},
|
|
254
593
|
};
|
|
255
594
|
const preset = presets[id] || {};
|
|
@@ -371,15 +710,141 @@ class PraxisStepperConfigEditor {
|
|
|
371
710
|
get activeStep() { return this.config.steps?.[this.activeIndex] || null; }
|
|
372
711
|
ensureWidgets() { const s = this.activeStep; if (!s.widgets)
|
|
373
712
|
s.widgets = []; return s.widgets; }
|
|
713
|
+
ensureWidgetsBeforeForm() { const s = this.activeStep; if (!s.widgetsBeforeForm)
|
|
714
|
+
s.widgetsBeforeForm = []; return s.widgetsBeforeForm; }
|
|
374
715
|
displayWidgetName(w) {
|
|
375
716
|
switch (w.id) {
|
|
376
717
|
case 'praxis-list': return 'Lista (seleção)';
|
|
377
|
-
case 'pdx-material-searchable-select': return '
|
|
718
|
+
case 'pdx-material-searchable-select': return 'Seleção com busca';
|
|
378
719
|
case 'praxis-files-upload': return 'Upload de arquivos';
|
|
379
720
|
case 'praxis-dynamic-form': return 'Formulário';
|
|
721
|
+
case 'praxis-wizard-benefits': return 'Grade de benefícios';
|
|
722
|
+
case 'praxis-wizard-content': return 'Bloco de conteúdo';
|
|
723
|
+
case 'praxis-wizard-inline-notice': return 'Aviso inline';
|
|
724
|
+
case 'praxis-wizard-divider': return 'Divisor';
|
|
380
725
|
default: return w.inputs?.title || w.inputs?.label || 'Widget';
|
|
381
726
|
}
|
|
382
727
|
}
|
|
728
|
+
editorialBeforeWidgets(step) {
|
|
729
|
+
return (step.widgetsBeforeForm || []).filter((w) => this.isWizardWidgetId(w.id));
|
|
730
|
+
}
|
|
731
|
+
editorialAfterWidgets(step) {
|
|
732
|
+
return (step.widgets || []).filter((w) => this.isWizardWidgetId(w.id));
|
|
733
|
+
}
|
|
734
|
+
advancedWidgets(step) {
|
|
735
|
+
return (step.widgets || []).filter((w) => !this.isWizardWidgetId(w.id));
|
|
736
|
+
}
|
|
737
|
+
widgetBlockId(w) {
|
|
738
|
+
const blockId = String(w.inputs?.blockId || '').trim();
|
|
739
|
+
return blockId || null;
|
|
740
|
+
}
|
|
741
|
+
editorialWidgetSummary(w) {
|
|
742
|
+
const inputs = w.inputs || {};
|
|
743
|
+
const shorten = (value, max = 72) => {
|
|
744
|
+
const text = (value || '').trim();
|
|
745
|
+
if (!text)
|
|
746
|
+
return '';
|
|
747
|
+
return text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
748
|
+
};
|
|
749
|
+
switch (w.id) {
|
|
750
|
+
case 'praxis-wizard-benefits': {
|
|
751
|
+
const count = Array.isArray(inputs.items) ? inputs.items.length : 0;
|
|
752
|
+
const cols = Number.isFinite(Number(inputs.columns)) ? Number(inputs.columns) : 4;
|
|
753
|
+
return `${count} item(ns) • ${cols} coluna(s)`;
|
|
754
|
+
}
|
|
755
|
+
case 'praxis-wizard-content': {
|
|
756
|
+
const text = shorten(inputs.title || inputs.subtitle || inputs.text || inputs.caption, 90);
|
|
757
|
+
return text || 'Sem conteúdo';
|
|
758
|
+
}
|
|
759
|
+
case 'praxis-wizard-inline-notice': {
|
|
760
|
+
const tone = this.toneLabel(inputs.tone);
|
|
761
|
+
const text = shorten(inputs.text, 90);
|
|
762
|
+
return text ? `${tone} • ${text}` : tone;
|
|
763
|
+
}
|
|
764
|
+
case 'praxis-wizard-divider':
|
|
765
|
+
return inputs.label ? `Rótulo: ${inputs.label}` : 'Divisor sem rótulo';
|
|
766
|
+
default:
|
|
767
|
+
return '';
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
addEditorialWidget(id, zone = 'before') {
|
|
771
|
+
const step = this.activeStep;
|
|
772
|
+
if (!step)
|
|
773
|
+
return;
|
|
774
|
+
const defaults = this.defaultEditorialInputs(id, step, zone);
|
|
775
|
+
this.openWizardWidgetDialog(id, defaults).subscribe((result) => {
|
|
776
|
+
if (!result?.inputs)
|
|
777
|
+
return;
|
|
778
|
+
const wd = {
|
|
779
|
+
id,
|
|
780
|
+
inputs: { ...defaults, ...result.inputs },
|
|
781
|
+
};
|
|
782
|
+
if (zone === 'before')
|
|
783
|
+
this.ensureWidgetsBeforeForm().push(wd);
|
|
784
|
+
else
|
|
785
|
+
this.ensureWidgets().push(wd);
|
|
786
|
+
this.markDirty();
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
dropEditorialBefore(ev) {
|
|
790
|
+
const step = this.activeStep;
|
|
791
|
+
if (!step)
|
|
792
|
+
return;
|
|
793
|
+
const list = this.ensureWidgetsBeforeForm();
|
|
794
|
+
this.reorderSubset(list, (w) => this.isWizardWidgetId(w.id), ev.previousIndex, ev.currentIndex);
|
|
795
|
+
this.markDirty();
|
|
796
|
+
}
|
|
797
|
+
dropEditorialAfter(ev) {
|
|
798
|
+
const step = this.activeStep;
|
|
799
|
+
if (!step)
|
|
800
|
+
return;
|
|
801
|
+
const list = this.ensureWidgets();
|
|
802
|
+
this.reorderSubset(list, (w) => this.isWizardWidgetId(w.id), ev.previousIndex, ev.currentIndex);
|
|
803
|
+
this.markDirty();
|
|
804
|
+
}
|
|
805
|
+
moveEditorialWidget(w, from, to) {
|
|
806
|
+
if (from === to)
|
|
807
|
+
return;
|
|
808
|
+
const fromList = from === 'before' ? this.ensureWidgetsBeforeForm() : this.ensureWidgets();
|
|
809
|
+
const toList = to === 'before' ? this.ensureWidgetsBeforeForm() : this.ensureWidgets();
|
|
810
|
+
const idx = fromList.indexOf(w);
|
|
811
|
+
if (idx < 0)
|
|
812
|
+
return;
|
|
813
|
+
fromList.splice(idx, 1);
|
|
814
|
+
toList.push(w);
|
|
815
|
+
this.markDirty();
|
|
816
|
+
}
|
|
817
|
+
duplicateEditorialWidget(w, zone) {
|
|
818
|
+
const step = this.activeStep;
|
|
819
|
+
if (!step || !this.isWizardWidgetId(w.id))
|
|
820
|
+
return;
|
|
821
|
+
const clone = JSON.parse(JSON.stringify(w));
|
|
822
|
+
const inputs = (clone.inputs = { ...(clone.inputs || {}) });
|
|
823
|
+
inputs.blockId = this.nextEditorialBlockId(step, w.id, zone);
|
|
824
|
+
const list = zone === 'before' ? this.ensureWidgetsBeforeForm() : this.ensureWidgets();
|
|
825
|
+
const idx = list.indexOf(w);
|
|
826
|
+
if (idx >= 0)
|
|
827
|
+
list.splice(idx + 1, 0, clone);
|
|
828
|
+
else
|
|
829
|
+
list.push(clone);
|
|
830
|
+
this.markDirty();
|
|
831
|
+
}
|
|
832
|
+
removeEditorialWidget(w, zone) {
|
|
833
|
+
const list = zone === 'before' ? this.ensureWidgetsBeforeForm() : this.ensureWidgets();
|
|
834
|
+
const idx = list.indexOf(w);
|
|
835
|
+
if (idx < 0)
|
|
836
|
+
return;
|
|
837
|
+
list.splice(idx, 1);
|
|
838
|
+
this.markDirty();
|
|
839
|
+
}
|
|
840
|
+
removeAdvancedWidget(w) {
|
|
841
|
+
const widgets = this.ensureWidgets();
|
|
842
|
+
const idx = widgets.indexOf(w);
|
|
843
|
+
if (idx < 0)
|
|
844
|
+
return;
|
|
845
|
+
widgets.splice(idx, 1);
|
|
846
|
+
this.markDirty();
|
|
847
|
+
}
|
|
383
848
|
dropWidget(ev) {
|
|
384
849
|
const arr = this.ensureWidgets();
|
|
385
850
|
moveItemInArray(arr, ev.previousIndex, ev.currentIndex);
|
|
@@ -390,6 +855,103 @@ class PraxisStepperConfigEditor {
|
|
|
390
855
|
arr.splice(idx, 1);
|
|
391
856
|
this.markDirty();
|
|
392
857
|
}
|
|
858
|
+
canEditWidget(w) {
|
|
859
|
+
return (w.id === 'praxis-dynamic-form'
|
|
860
|
+
|| w.id === 'praxis-list'
|
|
861
|
+
|| w.id === 'pdx-material-searchable-select'
|
|
862
|
+
|| w.id === 'praxis-files-upload'
|
|
863
|
+
|| this.isWizardWidgetId(w.id));
|
|
864
|
+
}
|
|
865
|
+
defaultEditorialInputs(id, step, zone) {
|
|
866
|
+
const blockId = this.nextEditorialBlockId(step, id, zone);
|
|
867
|
+
switch (id) {
|
|
868
|
+
case 'praxis-wizard-benefits':
|
|
869
|
+
return {
|
|
870
|
+
blockId,
|
|
871
|
+
title: '',
|
|
872
|
+
columns: 4,
|
|
873
|
+
boxed: true,
|
|
874
|
+
items: [{ icon: '', title: 'Novo benefício', text: '' }],
|
|
875
|
+
};
|
|
876
|
+
case 'praxis-wizard-content':
|
|
877
|
+
return {
|
|
878
|
+
blockId,
|
|
879
|
+
title: '',
|
|
880
|
+
subtitle: '',
|
|
881
|
+
text: '',
|
|
882
|
+
caption: '',
|
|
883
|
+
};
|
|
884
|
+
case 'praxis-wizard-inline-notice':
|
|
885
|
+
return {
|
|
886
|
+
blockId,
|
|
887
|
+
text: '',
|
|
888
|
+
tone: 'neutral',
|
|
889
|
+
};
|
|
890
|
+
case 'praxis-wizard-divider':
|
|
891
|
+
return {
|
|
892
|
+
blockId,
|
|
893
|
+
label: '',
|
|
894
|
+
};
|
|
895
|
+
default:
|
|
896
|
+
return { blockId };
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
nextEditorialBlockId(step, id, zone) {
|
|
900
|
+
const stepPart = this.normalizeBlockIdPart(step.id || `step-${this.activeIndex + 1}`);
|
|
901
|
+
const kind = id.replace('praxis-wizard-', '');
|
|
902
|
+
const prefix = `${stepPart}:${zone}:${kind}:`;
|
|
903
|
+
const used = new Set();
|
|
904
|
+
let max = 0;
|
|
905
|
+
const allWidgets = [...(step.widgetsBeforeForm || []), ...(step.widgets || [])];
|
|
906
|
+
allWidgets.forEach((widget) => {
|
|
907
|
+
const blockId = String(widget.inputs?.blockId || '').trim();
|
|
908
|
+
if (!blockId.startsWith(prefix))
|
|
909
|
+
return;
|
|
910
|
+
used.add(blockId);
|
|
911
|
+
const suffix = Number(blockId.slice(prefix.length));
|
|
912
|
+
if (Number.isFinite(suffix)) {
|
|
913
|
+
max = Math.max(max, suffix);
|
|
914
|
+
}
|
|
915
|
+
});
|
|
916
|
+
let nextIdx = Math.max(1, max + 1);
|
|
917
|
+
let candidate = `${prefix}${nextIdx}`;
|
|
918
|
+
while (used.has(candidate)) {
|
|
919
|
+
nextIdx += 1;
|
|
920
|
+
candidate = `${prefix}${nextIdx}`;
|
|
921
|
+
}
|
|
922
|
+
return candidate;
|
|
923
|
+
}
|
|
924
|
+
normalizeBlockIdPart(value) {
|
|
925
|
+
const normalized = (value || '')
|
|
926
|
+
.trim()
|
|
927
|
+
.toLowerCase()
|
|
928
|
+
.replace(/\s+/g, '-')
|
|
929
|
+
.replace(/[^a-z0-9:_-]/g, '');
|
|
930
|
+
return normalized || `step-${this.activeIndex + 1}`;
|
|
931
|
+
}
|
|
932
|
+
toneLabel(value) {
|
|
933
|
+
switch (value) {
|
|
934
|
+
case 'info': return 'Informativo';
|
|
935
|
+
case 'warning': return 'Atenção';
|
|
936
|
+
default: return 'Neutro';
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
reorderSubset(list, pick, fromSubsetIndex, toSubsetIndex) {
|
|
940
|
+
const subsetIndices = [];
|
|
941
|
+
list.forEach((item, index) => {
|
|
942
|
+
if (pick(item))
|
|
943
|
+
subsetIndices.push(index);
|
|
944
|
+
});
|
|
945
|
+
const fromReal = subsetIndices[fromSubsetIndex];
|
|
946
|
+
const toReal = subsetIndices[toSubsetIndex];
|
|
947
|
+
if (fromReal == null || toReal == null)
|
|
948
|
+
return;
|
|
949
|
+
const [moved] = list.splice(fromReal, 1);
|
|
950
|
+
let insertAt = toReal;
|
|
951
|
+
if (fromReal < toReal)
|
|
952
|
+
insertAt -= 1;
|
|
953
|
+
list.splice(insertAt, 0, moved);
|
|
954
|
+
}
|
|
393
955
|
// ------- Main form -------
|
|
394
956
|
addMainForm() {
|
|
395
957
|
const step = this.activeStep;
|
|
@@ -422,7 +984,7 @@ class PraxisStepperConfigEditor {
|
|
|
422
984
|
const ref = this.settings.open({ id: `stepper:list:${step.id || this.activeIndex}`, title: 'Configurar Lista (seleção)', content: { component: PraxisListConfigEditor, inputs: { config: current, listId: step.id || 'list' } } });
|
|
423
985
|
const apply = (val) => {
|
|
424
986
|
const cfg = (val && (val.config || val)) || current;
|
|
425
|
-
const wd = { id: 'praxis-list', inputs: { config: cfg } };
|
|
987
|
+
const wd = { id: 'praxis-list', inputs: { config: cfg, listId: `${step.id || 'step'}-list-${Date.now()}` } };
|
|
426
988
|
const arr = this.ensureWidgets();
|
|
427
989
|
arr.push(wd);
|
|
428
990
|
this.markDirty();
|
|
@@ -460,7 +1022,7 @@ class PraxisStepperConfigEditor {
|
|
|
460
1022
|
return;
|
|
461
1023
|
const ref = this.settings.open({ id: `stepper:upload:${step.id || this.activeIndex}`, title: 'Configurar Upload de Arquivos', content: { component: PraxisFilesUploadConfigEditor, inputs: {} } });
|
|
462
1024
|
const apply = (cfg) => {
|
|
463
|
-
const wd = { id: 'praxis-files-upload', inputs: { config: cfg,
|
|
1025
|
+
const wd = { id: 'praxis-files-upload', inputs: { config: cfg, filesUploadId: `${step.id || 'step'}-upload-${Date.now()}` } };
|
|
464
1026
|
this.ensureWidgets().push(wd);
|
|
465
1027
|
this.markDirty();
|
|
466
1028
|
};
|
|
@@ -498,7 +1060,7 @@ class PraxisStepperConfigEditor {
|
|
|
498
1060
|
if (!step)
|
|
499
1061
|
return;
|
|
500
1062
|
const cfg = { mode: 'tree', selection: { mode: 'single' } };
|
|
501
|
-
const wd = { id: 'praxis-list', inputs: { config: cfg } };
|
|
1063
|
+
const wd = { id: 'praxis-list', inputs: { config: cfg, listId: `${step.id || 'step'}-list-${Date.now()}` } };
|
|
502
1064
|
this.ensureWidgets().push(wd);
|
|
503
1065
|
this.markDirty();
|
|
504
1066
|
}
|
|
@@ -521,7 +1083,7 @@ class PraxisStepperConfigEditor {
|
|
|
521
1083
|
ref.applied$.subscribe(apply);
|
|
522
1084
|
ref.saved$.subscribe(apply);
|
|
523
1085
|
}
|
|
524
|
-
editWidget(w
|
|
1086
|
+
editWidget(w) {
|
|
525
1087
|
switch (w.id) {
|
|
526
1088
|
case 'praxis-dynamic-form':
|
|
527
1089
|
// treat as embedded form
|
|
@@ -562,11 +1124,44 @@ class PraxisStepperConfigEditor {
|
|
|
562
1124
|
ref.saved$.subscribe(apply);
|
|
563
1125
|
break;
|
|
564
1126
|
}
|
|
1127
|
+
case 'praxis-wizard-benefits':
|
|
1128
|
+
case 'praxis-wizard-content':
|
|
1129
|
+
case 'praxis-wizard-inline-notice':
|
|
1130
|
+
case 'praxis-wizard-divider': {
|
|
1131
|
+
this.openWizardWidgetEditor(w);
|
|
1132
|
+
break;
|
|
1133
|
+
}
|
|
565
1134
|
default:
|
|
566
1135
|
// No editor available
|
|
567
1136
|
break;
|
|
568
1137
|
}
|
|
569
1138
|
}
|
|
1139
|
+
openWizardWidgetEditor(w) {
|
|
1140
|
+
if (!this.isWizardWidgetId(w.id))
|
|
1141
|
+
return;
|
|
1142
|
+
this.openWizardWidgetDialog(w.id, { ...(w.inputs || {}) }).subscribe((result) => {
|
|
1143
|
+
if (!result?.inputs)
|
|
1144
|
+
return;
|
|
1145
|
+
w.inputs = { ...(w.inputs || {}), ...result.inputs };
|
|
1146
|
+
this.markDirty();
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
openWizardWidgetDialog(widgetId, inputs) {
|
|
1150
|
+
const dialogRef = this.dialog.open(WizardWidgetConfigDialogComponent, {
|
|
1151
|
+
width: '760px',
|
|
1152
|
+
data: {
|
|
1153
|
+
widgetId,
|
|
1154
|
+
inputs: { ...inputs },
|
|
1155
|
+
},
|
|
1156
|
+
});
|
|
1157
|
+
return dialogRef.afterClosed();
|
|
1158
|
+
}
|
|
1159
|
+
isWizardWidgetId(id) {
|
|
1160
|
+
return (id === 'praxis-wizard-benefits'
|
|
1161
|
+
|| id === 'praxis-wizard-content'
|
|
1162
|
+
|| id === 'praxis-wizard-inline-notice'
|
|
1163
|
+
|| id === 'praxis-wizard-divider');
|
|
1164
|
+
}
|
|
570
1165
|
// SettingsValueProvider
|
|
571
1166
|
getSettingsValue() { return this.config; }
|
|
572
1167
|
onSave() { return this.getSettingsValue(); }
|
|
@@ -595,7 +1190,16 @@ class PraxisStepperConfigEditor {
|
|
|
595
1190
|
<option value="horizontal">Horizontal</option>
|
|
596
1191
|
<option value="vertical">Vertical</option>
|
|
597
1192
|
</select>
|
|
598
|
-
<
|
|
1193
|
+
<button
|
|
1194
|
+
mat-icon-button
|
|
1195
|
+
matSuffix
|
|
1196
|
+
class="help-icon-button"
|
|
1197
|
+
type="button"
|
|
1198
|
+
[matTooltip]="'Horizontal: cabeçalho no topo • Vertical: lista à esquerda'"
|
|
1199
|
+
matTooltipPosition="above"
|
|
1200
|
+
>
|
|
1201
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1202
|
+
</button>
|
|
599
1203
|
</mat-form-field>
|
|
600
1204
|
<mat-form-field appearance="outline">
|
|
601
1205
|
<mat-label>Posição dos títulos</mat-label>
|
|
@@ -603,7 +1207,16 @@ class PraxisStepperConfigEditor {
|
|
|
603
1207
|
<option value="top">Acima</option>
|
|
604
1208
|
<option value="bottom">Abaixo</option>
|
|
605
1209
|
</select>
|
|
606
|
-
<
|
|
1210
|
+
<button
|
|
1211
|
+
mat-icon-button
|
|
1212
|
+
matSuffix
|
|
1213
|
+
class="help-icon-button"
|
|
1214
|
+
type="button"
|
|
1215
|
+
[matTooltip]="'Válido na orientação horizontal'"
|
|
1216
|
+
matTooltipPosition="above"
|
|
1217
|
+
>
|
|
1218
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1219
|
+
</button>
|
|
607
1220
|
</mat-form-field>
|
|
608
1221
|
<mat-form-field appearance="outline">
|
|
609
1222
|
<mat-label>Posição do rótulo</mat-label>
|
|
@@ -611,7 +1224,16 @@ class PraxisStepperConfigEditor {
|
|
|
611
1224
|
<option value="end">Ao lado</option>
|
|
612
1225
|
<option value="bottom">Abaixo</option>
|
|
613
1226
|
</select>
|
|
614
|
-
<
|
|
1227
|
+
<button
|
|
1228
|
+
mat-icon-button
|
|
1229
|
+
matSuffix
|
|
1230
|
+
class="help-icon-button"
|
|
1231
|
+
type="button"
|
|
1232
|
+
[matTooltip]="'Como o texto aparece no cabeçalho'"
|
|
1233
|
+
matTooltipPosition="above"
|
|
1234
|
+
>
|
|
1235
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1236
|
+
</button>
|
|
615
1237
|
</mat-form-field>
|
|
616
1238
|
<mat-form-field appearance="outline">
|
|
617
1239
|
<mat-label>Cor</mat-label>
|
|
@@ -621,17 +1243,44 @@ class PraxisStepperConfigEditor {
|
|
|
621
1243
|
<option value="accent">Acento</option>
|
|
622
1244
|
<option value="warn">Alerta</option>
|
|
623
1245
|
</select>
|
|
624
|
-
<
|
|
1246
|
+
<button
|
|
1247
|
+
mat-icon-button
|
|
1248
|
+
matSuffix
|
|
1249
|
+
class="help-icon-button"
|
|
1250
|
+
type="button"
|
|
1251
|
+
[matTooltip]="'Aplicável a temas Material 2 (M2)'"
|
|
1252
|
+
matTooltipPosition="above"
|
|
1253
|
+
>
|
|
1254
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1255
|
+
</button>
|
|
625
1256
|
</mat-form-field>
|
|
626
1257
|
<mat-form-field appearance="outline">
|
|
627
1258
|
<mat-label>Duração da animação</mat-label>
|
|
628
1259
|
<input matInput [(ngModel)]="config.animationDuration" (ngModelChange)="markDirty()" placeholder="Ex.: 300ms" />
|
|
629
|
-
<
|
|
1260
|
+
<button
|
|
1261
|
+
mat-icon-button
|
|
1262
|
+
matSuffix
|
|
1263
|
+
class="help-icon-button"
|
|
1264
|
+
type="button"
|
|
1265
|
+
[matTooltip]="'Tempo da transição entre etapas'"
|
|
1266
|
+
matTooltipPosition="above"
|
|
1267
|
+
>
|
|
1268
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1269
|
+
</button>
|
|
630
1270
|
</mat-form-field>
|
|
631
1271
|
<mat-form-field appearance="outline">
|
|
632
1272
|
<mat-label>Etapa selecionada</mat-label>
|
|
633
1273
|
<input matInput type="number" [(ngModel)]="config.selectedIndex" (ngModelChange)="markDirty()" />
|
|
634
|
-
<
|
|
1274
|
+
<button
|
|
1275
|
+
mat-icon-button
|
|
1276
|
+
matSuffix
|
|
1277
|
+
class="help-icon-button"
|
|
1278
|
+
type="button"
|
|
1279
|
+
[matTooltip]="'Índice inicia em 0 (primeira etapa)'"
|
|
1280
|
+
matTooltipPosition="above"
|
|
1281
|
+
>
|
|
1282
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1283
|
+
</button>
|
|
635
1284
|
</mat-form-field>
|
|
636
1285
|
<mat-form-field appearance="outline">
|
|
637
1286
|
<mat-label>Densidade</mat-label>
|
|
@@ -640,22 +1289,58 @@ class PraxisStepperConfigEditor {
|
|
|
640
1289
|
<option value="comfortable">Confortável</option>
|
|
641
1290
|
<option value="compact">Compacta</option>
|
|
642
1291
|
</select>
|
|
643
|
-
<
|
|
1292
|
+
<button
|
|
1293
|
+
mat-icon-button
|
|
1294
|
+
matSuffix
|
|
1295
|
+
class="help-icon-button"
|
|
1296
|
+
type="button"
|
|
1297
|
+
[matTooltip]="'Controla espaçamentos e alturas'"
|
|
1298
|
+
matTooltipPosition="above"
|
|
1299
|
+
>
|
|
1300
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1301
|
+
</button>
|
|
644
1302
|
</mat-form-field>
|
|
645
1303
|
<mat-form-field appearance="outline" class="w-full">
|
|
646
1304
|
<mat-label>Classe do stepper (opcional)</mat-label>
|
|
647
1305
|
<input matInput [(ngModel)]="config.stepperClass" (ngModelChange)="markDirty()" placeholder="Ex.: meu-stepper" />
|
|
648
|
-
<
|
|
1306
|
+
<button
|
|
1307
|
+
mat-icon-button
|
|
1308
|
+
matSuffix
|
|
1309
|
+
class="help-icon-button"
|
|
1310
|
+
type="button"
|
|
1311
|
+
[matTooltip]="'Permite estilizar com CSS escopado'"
|
|
1312
|
+
matTooltipPosition="above"
|
|
1313
|
+
>
|
|
1314
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1315
|
+
</button>
|
|
649
1316
|
</mat-form-field>
|
|
650
1317
|
<mat-form-field appearance="outline" class="w-full">
|
|
651
1318
|
<mat-label>Classe do cabeçalho (opcional)</mat-label>
|
|
652
1319
|
<input matInput [(ngModel)]="config.headerClass" (ngModelChange)="markDirty()" placeholder="Ex.: stepper-header" />
|
|
653
|
-
<
|
|
1320
|
+
<button
|
|
1321
|
+
mat-icon-button
|
|
1322
|
+
matSuffix
|
|
1323
|
+
class="help-icon-button"
|
|
1324
|
+
type="button"
|
|
1325
|
+
[matTooltip]="'Use para ajustes finos de aparência'"
|
|
1326
|
+
matTooltipPosition="above"
|
|
1327
|
+
>
|
|
1328
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1329
|
+
</button>
|
|
654
1330
|
</mat-form-field>
|
|
655
1331
|
<mat-form-field appearance="outline" class="w-full">
|
|
656
1332
|
<mat-label>Classe do conteúdo (opcional)</mat-label>
|
|
657
1333
|
<input matInput [(ngModel)]="config.contentClass" (ngModelChange)="markDirty()" placeholder="Ex.: stepper-content" />
|
|
658
|
-
<
|
|
1334
|
+
<button
|
|
1335
|
+
mat-icon-button
|
|
1336
|
+
matSuffix
|
|
1337
|
+
class="help-icon-button"
|
|
1338
|
+
type="button"
|
|
1339
|
+
[matTooltip]="'Aplica uma classe à área de conteúdo'"
|
|
1340
|
+
matTooltipPosition="above"
|
|
1341
|
+
>
|
|
1342
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1343
|
+
</button>
|
|
659
1344
|
</mat-form-field>
|
|
660
1345
|
</div>
|
|
661
1346
|
<div class="pdx-toggles">
|
|
@@ -677,35 +1362,89 @@ class PraxisStepperConfigEditor {
|
|
|
677
1362
|
<div class="pdx-step-item" *ngFor="let s of config.steps; let i = index" cdkDrag [class.active]="activeIndex === i" (click)="setActive(i)">
|
|
678
1363
|
<div class="drag-handle" cdkDragHandle><mat-icon [praxisIcon]="'drag_indicator'"></mat-icon></div>
|
|
679
1364
|
<div class="pdx-fields">
|
|
680
|
-
<mat-form-field appearance="outline"
|
|
1365
|
+
<mat-form-field appearance="outline" class="min-180">
|
|
681
1366
|
<mat-label>Título da etapa</mat-label>
|
|
682
1367
|
<input matInput [(ngModel)]="s.label" (ngModelChange)="markDirty()" />
|
|
683
|
-
<
|
|
1368
|
+
<button
|
|
1369
|
+
mat-icon-button
|
|
1370
|
+
matSuffix
|
|
1371
|
+
class="help-icon-button"
|
|
1372
|
+
type="button"
|
|
1373
|
+
[matTooltip]="'Como aparecerá no cabeçalho'"
|
|
1374
|
+
matTooltipPosition="above"
|
|
1375
|
+
>
|
|
1376
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1377
|
+
</button>
|
|
684
1378
|
</mat-form-field>
|
|
685
1379
|
<mat-form-field appearance="outline">
|
|
686
1380
|
<mat-label>Identificador (opcional)</mat-label>
|
|
687
1381
|
<input matInput [(ngModel)]="s.id" (ngModelChange)="markDirty()" />
|
|
688
|
-
<
|
|
1382
|
+
<button
|
|
1383
|
+
mat-icon-button
|
|
1384
|
+
matSuffix
|
|
1385
|
+
class="help-icon-button"
|
|
1386
|
+
type="button"
|
|
1387
|
+
[matTooltip]="'Útil para automações'"
|
|
1388
|
+
matTooltipPosition="above"
|
|
1389
|
+
>
|
|
1390
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1391
|
+
</button>
|
|
689
1392
|
</mat-form-field>
|
|
690
1393
|
<mat-form-field appearance="outline">
|
|
691
1394
|
<mat-label>Texto alternativo (acessibilidade)</mat-label>
|
|
692
1395
|
<input matInput [(ngModel)]="s.ariaLabel" (ngModelChange)="markDirty()" />
|
|
693
|
-
<
|
|
1396
|
+
<button
|
|
1397
|
+
mat-icon-button
|
|
1398
|
+
matSuffix
|
|
1399
|
+
class="help-icon-button"
|
|
1400
|
+
type="button"
|
|
1401
|
+
[matTooltip]="'Lido por leitores de tela'"
|
|
1402
|
+
matTooltipPosition="above"
|
|
1403
|
+
>
|
|
1404
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1405
|
+
</button>
|
|
694
1406
|
</mat-form-field>
|
|
695
1407
|
<mat-form-field appearance="outline">
|
|
696
1408
|
<mat-label>ID que descreve (opcional)</mat-label>
|
|
697
1409
|
<input matInput [(ngModel)]="s.ariaLabelledby" (ngModelChange)="markDirty()" />
|
|
698
|
-
<
|
|
1410
|
+
<button
|
|
1411
|
+
mat-icon-button
|
|
1412
|
+
matSuffix
|
|
1413
|
+
class="help-icon-button"
|
|
1414
|
+
type="button"
|
|
1415
|
+
[matTooltip]="'ID de um elemento que descreve a etapa'"
|
|
1416
|
+
matTooltipPosition="above"
|
|
1417
|
+
>
|
|
1418
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1419
|
+
</button>
|
|
699
1420
|
</mat-form-field>
|
|
700
1421
|
<mat-form-field appearance="outline">
|
|
701
1422
|
<mat-label>Ícone/estado do marcador</mat-label>
|
|
702
1423
|
<input matInput [(ngModel)]="s.state" (ngModelChange)="markDirty()" placeholder="Ex.: number, done, edit" />
|
|
703
|
-
<
|
|
1424
|
+
<button
|
|
1425
|
+
mat-icon-button
|
|
1426
|
+
matSuffix
|
|
1427
|
+
class="help-icon-button"
|
|
1428
|
+
type="button"
|
|
1429
|
+
[matTooltip]="'Controla o ícone do passo (quando aplicável)'"
|
|
1430
|
+
matTooltipPosition="above"
|
|
1431
|
+
>
|
|
1432
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1433
|
+
</button>
|
|
704
1434
|
</mat-form-field>
|
|
705
1435
|
<mat-form-field appearance="outline">
|
|
706
1436
|
<mat-label>Mensagem de erro</mat-label>
|
|
707
1437
|
<input matInput [(ngModel)]="s.errorMessage" (ngModelChange)="markDirty()" />
|
|
708
|
-
<
|
|
1438
|
+
<button
|
|
1439
|
+
mat-icon-button
|
|
1440
|
+
matSuffix
|
|
1441
|
+
class="help-icon-button"
|
|
1442
|
+
type="button"
|
|
1443
|
+
[matTooltip]="'Mostrada quando há erro na etapa'"
|
|
1444
|
+
matTooltipPosition="above"
|
|
1445
|
+
>
|
|
1446
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1447
|
+
</button>
|
|
709
1448
|
</mat-form-field>
|
|
710
1449
|
<div class="pdx-flag-group">
|
|
711
1450
|
<mat-slide-toggle [(ngModel)]="s.optional" (ngModelChange)="markDirty()">Etapa opcional</mat-slide-toggle>
|
|
@@ -732,8 +1471,139 @@ class PraxisStepperConfigEditor {
|
|
|
732
1471
|
</div>
|
|
733
1472
|
|
|
734
1473
|
<div class="pdx-content-editor">
|
|
1474
|
+
<div class="section editorial-section">
|
|
1475
|
+
<div class="section-head">
|
|
1476
|
+
<div>
|
|
1477
|
+
<div class="section-title">Conteúdo editorial</div>
|
|
1478
|
+
<div class="section-subtitle">Organize os blocos narrativos da etapa antes ou depois do formulário.</div>
|
|
1479
|
+
</div>
|
|
1480
|
+
</div>
|
|
1481
|
+
|
|
1482
|
+
<div class="zone-grid">
|
|
1483
|
+
<div class="zone-card">
|
|
1484
|
+
<div class="zone-head">
|
|
1485
|
+
<div class="zone-title">Antes do formulário</div>
|
|
1486
|
+
<div class="zone-actions">
|
|
1487
|
+
<span class="zone-count">{{ editorialBeforeWidgets(step).length }}</span>
|
|
1488
|
+
<button mat-stroked-button [matMenuTriggerFor]="beforeEditorialMenu">
|
|
1489
|
+
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
1490
|
+
Adicionar
|
|
1491
|
+
</button>
|
|
1492
|
+
<mat-menu #beforeEditorialMenu="matMenu">
|
|
1493
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-benefits', 'before')">
|
|
1494
|
+
<mat-icon [praxisIcon]="'view_module'"></mat-icon>
|
|
1495
|
+
Grade de benefícios
|
|
1496
|
+
</button>
|
|
1497
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-content', 'before')">
|
|
1498
|
+
<mat-icon [praxisIcon]="'article'"></mat-icon>
|
|
1499
|
+
Bloco de conteúdo
|
|
1500
|
+
</button>
|
|
1501
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-inline-notice', 'before')">
|
|
1502
|
+
<mat-icon [praxisIcon]="'info'"></mat-icon>
|
|
1503
|
+
Aviso inline
|
|
1504
|
+
</button>
|
|
1505
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-divider', 'before')">
|
|
1506
|
+
<mat-icon [praxisIcon]="'horizontal_rule'"></mat-icon>
|
|
1507
|
+
Divisor
|
|
1508
|
+
</button>
|
|
1509
|
+
</mat-menu>
|
|
1510
|
+
</div>
|
|
1511
|
+
</div>
|
|
1512
|
+
<div cdkDropList (cdkDropListDropped)="dropEditorialBefore($event)" class="widget-list">
|
|
1513
|
+
<div class="widget-item editorial-item" *ngFor="let w of editorialBeforeWidgets(step)" cdkDrag>
|
|
1514
|
+
<div class="drag-handle" cdkDragHandle><mat-icon [praxisIcon]="'drag_indicator'"></mat-icon></div>
|
|
1515
|
+
<div class="info">
|
|
1516
|
+
<div class="name">{{ displayWidgetName(w) }}</div>
|
|
1517
|
+
<div class="sub">{{ editorialWidgetSummary(w) }}</div>
|
|
1518
|
+
<div class="meta" *ngIf="widgetBlockId(w) as blockId">ID: {{ blockId }}</div>
|
|
1519
|
+
</div>
|
|
1520
|
+
<div class="actions">
|
|
1521
|
+
<button mat-button (click)="editWidget(w)">
|
|
1522
|
+
<mat-icon [praxisIcon]="'tune'"></mat-icon>
|
|
1523
|
+
Editar
|
|
1524
|
+
</button>
|
|
1525
|
+
<button mat-button (click)="moveEditorialWidget(w, 'before', 'after')">
|
|
1526
|
+
<mat-icon [praxisIcon]="'arrow_downward'"></mat-icon>
|
|
1527
|
+
Mover para depois
|
|
1528
|
+
</button>
|
|
1529
|
+
<button mat-button (click)="duplicateEditorialWidget(w, 'before')">
|
|
1530
|
+
<mat-icon [praxisIcon]="'content_copy'"></mat-icon>
|
|
1531
|
+
Duplicar
|
|
1532
|
+
</button>
|
|
1533
|
+
<button mat-button color="warn" (click)="removeEditorialWidget(w, 'before')">
|
|
1534
|
+
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
1535
|
+
Remover
|
|
1536
|
+
</button>
|
|
1537
|
+
</div>
|
|
1538
|
+
</div>
|
|
1539
|
+
<div class="empty" *ngIf="!editorialBeforeWidgets(step).length">Nenhum bloco nesta zona.</div>
|
|
1540
|
+
</div>
|
|
1541
|
+
</div>
|
|
1542
|
+
|
|
1543
|
+
<div class="zone-card">
|
|
1544
|
+
<div class="zone-head">
|
|
1545
|
+
<div class="zone-title">Depois do formulário</div>
|
|
1546
|
+
<div class="zone-actions">
|
|
1547
|
+
<span class="zone-count">{{ editorialAfterWidgets(step).length }}</span>
|
|
1548
|
+
<button mat-stroked-button [matMenuTriggerFor]="afterEditorialMenu">
|
|
1549
|
+
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
1550
|
+
Adicionar
|
|
1551
|
+
</button>
|
|
1552
|
+
<mat-menu #afterEditorialMenu="matMenu">
|
|
1553
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-benefits', 'after')">
|
|
1554
|
+
<mat-icon [praxisIcon]="'view_module'"></mat-icon>
|
|
1555
|
+
Grade de benefícios
|
|
1556
|
+
</button>
|
|
1557
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-content', 'after')">
|
|
1558
|
+
<mat-icon [praxisIcon]="'article'"></mat-icon>
|
|
1559
|
+
Bloco de conteúdo
|
|
1560
|
+
</button>
|
|
1561
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-inline-notice', 'after')">
|
|
1562
|
+
<mat-icon [praxisIcon]="'info'"></mat-icon>
|
|
1563
|
+
Aviso inline
|
|
1564
|
+
</button>
|
|
1565
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-divider', 'after')">
|
|
1566
|
+
<mat-icon [praxisIcon]="'horizontal_rule'"></mat-icon>
|
|
1567
|
+
Divisor
|
|
1568
|
+
</button>
|
|
1569
|
+
</mat-menu>
|
|
1570
|
+
</div>
|
|
1571
|
+
</div>
|
|
1572
|
+
<div cdkDropList (cdkDropListDropped)="dropEditorialAfter($event)" class="widget-list">
|
|
1573
|
+
<div class="widget-item editorial-item" *ngFor="let w of editorialAfterWidgets(step)" cdkDrag>
|
|
1574
|
+
<div class="drag-handle" cdkDragHandle><mat-icon [praxisIcon]="'drag_indicator'"></mat-icon></div>
|
|
1575
|
+
<div class="info">
|
|
1576
|
+
<div class="name">{{ displayWidgetName(w) }}</div>
|
|
1577
|
+
<div class="sub">{{ editorialWidgetSummary(w) }}</div>
|
|
1578
|
+
<div class="meta" *ngIf="widgetBlockId(w) as blockId">ID: {{ blockId }}</div>
|
|
1579
|
+
</div>
|
|
1580
|
+
<div class="actions">
|
|
1581
|
+
<button mat-button (click)="editWidget(w)">
|
|
1582
|
+
<mat-icon [praxisIcon]="'tune'"></mat-icon>
|
|
1583
|
+
Editar
|
|
1584
|
+
</button>
|
|
1585
|
+
<button mat-button (click)="moveEditorialWidget(w, 'after', 'before')">
|
|
1586
|
+
<mat-icon [praxisIcon]="'arrow_upward'"></mat-icon>
|
|
1587
|
+
Mover para antes
|
|
1588
|
+
</button>
|
|
1589
|
+
<button mat-button (click)="duplicateEditorialWidget(w, 'after')">
|
|
1590
|
+
<mat-icon [praxisIcon]="'content_copy'"></mat-icon>
|
|
1591
|
+
Duplicar
|
|
1592
|
+
</button>
|
|
1593
|
+
<button mat-button color="warn" (click)="removeEditorialWidget(w, 'after')">
|
|
1594
|
+
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
1595
|
+
Remover
|
|
1596
|
+
</button>
|
|
1597
|
+
</div>
|
|
1598
|
+
</div>
|
|
1599
|
+
<div class="empty" *ngIf="!editorialAfterWidgets(step).length">Nenhum bloco nesta zona.</div>
|
|
1600
|
+
</div>
|
|
1601
|
+
</div>
|
|
1602
|
+
</div>
|
|
1603
|
+
</div>
|
|
1604
|
+
|
|
735
1605
|
<div class="section">
|
|
736
|
-
<div class="section-title">Formulário
|
|
1606
|
+
<div class="section-title">Formulário da etapa</div>
|
|
737
1607
|
<div class="section-body">
|
|
738
1608
|
<ng-container *ngIf="step.form; else addFormBtn">
|
|
739
1609
|
<mat-card appearance="outlined" class="mini-card">
|
|
@@ -755,22 +1625,18 @@ class PraxisStepperConfigEditor {
|
|
|
755
1625
|
</div>
|
|
756
1626
|
|
|
757
1627
|
<div class="section">
|
|
758
|
-
<div class="section-
|
|
1628
|
+
<div class="section-head">
|
|
1629
|
+
<div>
|
|
1630
|
+
<div class="section-title">Componentes avançados</div>
|
|
1631
|
+
<div class="section-subtitle">Use para cenários de seleção e integrações específicas.</div>
|
|
1632
|
+
</div>
|
|
1633
|
+
<button mat-stroked-button (click)="openMoreComponents()">
|
|
1634
|
+
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
1635
|
+
Mais componentes
|
|
1636
|
+
</button>
|
|
1637
|
+
</div>
|
|
759
1638
|
<div class="section-body">
|
|
760
1639
|
<div class="cta-grid">
|
|
761
|
-
<div class="cta-card mat-elevation-z2">
|
|
762
|
-
<div class="cta-head">
|
|
763
|
-
<mat-icon [praxisIcon]="'dynamic_form'"></mat-icon>
|
|
764
|
-
<div class="cta-title">Formulário dinâmico</div>
|
|
765
|
-
</div>
|
|
766
|
-
<div class="cta-desc">Crie campos e validações personalizadas nesta etapa.</div>
|
|
767
|
-
<div class="cta-actions">
|
|
768
|
-
<button mat-flat-button color="primary" (click)="addMainForm()">
|
|
769
|
-
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
770
|
-
Inserir formulário
|
|
771
|
-
</button>
|
|
772
|
-
</div>
|
|
773
|
-
</div>
|
|
774
1640
|
<div class="cta-card mat-elevation-z2">
|
|
775
1641
|
<div class="cta-head">
|
|
776
1642
|
<mat-icon [praxisIcon]="'account_tree'"></mat-icon>
|
|
@@ -797,20 +1663,53 @@ class PraxisStepperConfigEditor {
|
|
|
797
1663
|
</button>
|
|
798
1664
|
</div>
|
|
799
1665
|
</div>
|
|
1666
|
+
<div class="cta-card mat-elevation-z2">
|
|
1667
|
+
<div class="cta-head">
|
|
1668
|
+
<mat-icon [praxisIcon]="'search'"></mat-icon>
|
|
1669
|
+
<div class="cta-title">Seleção com busca</div>
|
|
1670
|
+
</div>
|
|
1671
|
+
<div class="cta-desc">Campo de seleção com busca remota/local.</div>
|
|
1672
|
+
<div class="cta-actions">
|
|
1673
|
+
<button mat-stroked-button (click)="addSearchableSelect()">
|
|
1674
|
+
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
1675
|
+
Inserir seletor
|
|
1676
|
+
</button>
|
|
1677
|
+
</div>
|
|
1678
|
+
</div>
|
|
1679
|
+
<div class="cta-card mat-elevation-z2">
|
|
1680
|
+
<div class="cta-head">
|
|
1681
|
+
<mat-icon [praxisIcon]="'upload_file'"></mat-icon>
|
|
1682
|
+
<div class="cta-title">Upload de arquivos</div>
|
|
1683
|
+
</div>
|
|
1684
|
+
<div class="cta-desc">Anexe documentos com validação de upload.</div>
|
|
1685
|
+
<div class="cta-actions">
|
|
1686
|
+
<button mat-stroked-button (click)="addFilesUpload()">
|
|
1687
|
+
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
1688
|
+
Inserir upload
|
|
1689
|
+
</button>
|
|
1690
|
+
</div>
|
|
1691
|
+
</div>
|
|
800
1692
|
</div>
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
1693
|
+
|
|
1694
|
+
<div class="widget-list advanced-list">
|
|
1695
|
+
<div class="widget-item" *ngFor="let w of advancedWidgets(step)">
|
|
1696
|
+
<div class="drag-handle"><mat-icon [praxisIcon]="'extension'"></mat-icon></div>
|
|
804
1697
|
<div class="info">
|
|
805
1698
|
<div class="name">{{ displayWidgetName(w) }}</div>
|
|
806
1699
|
<div class="sub">{{ w.id }}</div>
|
|
807
1700
|
</div>
|
|
808
1701
|
<div class="actions">
|
|
809
|
-
<button mat-button (click)="editWidget(w
|
|
810
|
-
|
|
1702
|
+
<button mat-button (click)="editWidget(w)" [disabled]="!canEditWidget(w)">
|
|
1703
|
+
<mat-icon [praxisIcon]="'tune'"></mat-icon>
|
|
1704
|
+
Editar
|
|
1705
|
+
</button>
|
|
1706
|
+
<button mat-button color="warn" (click)="removeAdvancedWidget(w)">
|
|
1707
|
+
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
1708
|
+
Remover
|
|
1709
|
+
</button>
|
|
811
1710
|
</div>
|
|
812
1711
|
</div>
|
|
813
|
-
<div class="empty" *ngIf="!step.
|
|
1712
|
+
<div class="empty" *ngIf="!advancedWidgets(step).length">Nenhum componente avançado adicionado.</div>
|
|
814
1713
|
</div>
|
|
815
1714
|
</div>
|
|
816
1715
|
</div>
|
|
@@ -898,12 +1797,30 @@ class PraxisStepperConfigEditor {
|
|
|
898
1797
|
<mat-form-field appearance="outline">
|
|
899
1798
|
<mat-label>Altura do cabeçalho (px)</mat-label>
|
|
900
1799
|
<input matInput type="number" [ngModel]="headerHeightPx" (ngModelChange)="setHeaderHeightPx($event)" placeholder="Ex.: 48" />
|
|
901
|
-
<
|
|
1800
|
+
<button
|
|
1801
|
+
mat-icon-button
|
|
1802
|
+
matSuffix
|
|
1803
|
+
class="help-icon-button"
|
|
1804
|
+
type="button"
|
|
1805
|
+
[matTooltip]="'Altura do item do cabeçalho'"
|
|
1806
|
+
matTooltipPosition="above"
|
|
1807
|
+
>
|
|
1808
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1809
|
+
</button>
|
|
902
1810
|
</mat-form-field>
|
|
903
1811
|
<mat-form-field appearance="outline">
|
|
904
1812
|
<mat-label>Tamanho do texto (px)</mat-label>
|
|
905
1813
|
<input matInput type="number" [ngModel]="headerLabelTextSizePx" (ngModelChange)="setHeaderLabelTextSizePx($event)" placeholder="Ex.: 14" />
|
|
906
|
-
<
|
|
1814
|
+
<button
|
|
1815
|
+
mat-icon-button
|
|
1816
|
+
matSuffix
|
|
1817
|
+
class="help-icon-button"
|
|
1818
|
+
type="button"
|
|
1819
|
+
[matTooltip]="'Tamanho do título da etapa'"
|
|
1820
|
+
matTooltipPosition="above"
|
|
1821
|
+
>
|
|
1822
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1823
|
+
</button>
|
|
907
1824
|
</mat-form-field>
|
|
908
1825
|
<mat-form-field appearance="outline">
|
|
909
1826
|
<mat-label>Peso do texto</mat-label>
|
|
@@ -920,7 +1837,16 @@ class PraxisStepperConfigEditor {
|
|
|
920
1837
|
<mat-form-field appearance="outline" class="w-full">
|
|
921
1838
|
<mat-label>Classe de tema (opcional)</mat-label>
|
|
922
1839
|
<input matInput [(ngModel)]="appearance.themeClass" (ngModelChange)="onAppearanceChange()" placeholder="Ex.: theme-stepper-custom" />
|
|
923
|
-
<
|
|
1840
|
+
<button
|
|
1841
|
+
mat-icon-button
|
|
1842
|
+
matSuffix
|
|
1843
|
+
class="help-icon-button"
|
|
1844
|
+
type="button"
|
|
1845
|
+
[matTooltip]="'Aplica as cores apenas dentro desse seletor'"
|
|
1846
|
+
matTooltipPosition="above"
|
|
1847
|
+
>
|
|
1848
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1849
|
+
</button>
|
|
924
1850
|
</mat-form-field>
|
|
925
1851
|
<mat-form-field appearance="outline">
|
|
926
1852
|
<mat-label>Conjunto de ícones</mat-label>
|
|
@@ -930,7 +1856,16 @@ class PraxisStepperConfigEditor {
|
|
|
930
1856
|
<option value="material-symbols-rounded">Material Symbols (Rounded)</option>
|
|
931
1857
|
<option value="material-symbols-sharp">Material Symbols (Sharp)</option>
|
|
932
1858
|
</select>
|
|
933
|
-
<
|
|
1859
|
+
<button
|
|
1860
|
+
mat-icon-button
|
|
1861
|
+
matSuffix
|
|
1862
|
+
class="help-icon-button"
|
|
1863
|
+
type="button"
|
|
1864
|
+
[matTooltip]="'Selecione se usar ícones do Material Symbols'"
|
|
1865
|
+
matTooltipPosition="above"
|
|
1866
|
+
>
|
|
1867
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1868
|
+
</button>
|
|
934
1869
|
</mat-form-field>
|
|
935
1870
|
</div>
|
|
936
1871
|
<div class="icons-grid">
|
|
@@ -991,7 +1926,7 @@ class PraxisStepperConfigEditor {
|
|
|
991
1926
|
</mat-tab>
|
|
992
1927
|
</mat-tab-group>
|
|
993
1928
|
</div>
|
|
994
|
-
`, isInline: true, styles: [".pdx-editor{display:grid;gap:16px}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-toggles{display:flex;gap:12px;flex-wrap:wrap}.tab-pad{padding:12px 4px;display:grid;gap:12px}.help{color:#000000b3;font-size:13px}.quick-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-bottom:6px}.icons-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin:8px 0}.icon-item{display:grid;gap:6px;align-content:start}.icons-hint{margin-top:4px}.pdx-steps{display:grid;gap:8px}.pdx-steps-header{display:flex;justify-content:space-between;align-items:center}.pdx-step-list{display:grid;gap:8px}.pdx-step-item{display:grid;grid-template-columns:24px 1fr auto;gap:8px;align-items:start;padding:8px;border:1px solid rgba(0,0,0,.12);border-radius:8px;cursor:pointer}.pdx-step-item.active{border-color:color-mix(in oklab,var(--md-sys-color-primary) 40%,rgba(0,0,0,.12));box-shadow:var(--mat-elevation-transition),var(--mat-elevation-level2, 0 2px 6px rgba(0,0,0,.12))}.drag-handle{display:flex;align-items:center;color:#0000008a}.pdx-fields{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.pdx-flag-group{display:flex;gap:10px;align-items:center}.pdx-active-step{display:grid;gap:12px;padding-top:8px;border-top:1px dashed rgba(0,0,0,.12)}.pdx-active-step .hdr{display:flex;gap:12px;align-items:center;justify-content:space-between}.pdx-content-editor{display:grid;gap:16px}.section{display:grid;gap:8px}.section-title{font-weight:600;opacity:.85}.mini-card{display:block}.widget-list{display:grid;gap:8px}.widget-item{display:grid;grid-template-columns:24px 1fr auto;align-items:center;gap:8px;padding:8px;border:1px solid rgba(0,0,0,.12);border-radius:8px}.widget-item .info .name{font-weight:600}.widget-item .info .sub{font-size:12px;opacity:.7}.widget-item .actions{display:flex;gap:8px}.cta-row{display:flex;gap:8px;align-items:center}.spacer{flex:1 1 auto}.muted{color:#0009}.cta-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px;margin-bottom:8px}.cta-card{display:grid;gap:8px;padding:12px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant, rgba(0,0,0,.12));background:var(--md-sys-color-surface)}.cta-card .cta-head{display:flex;align-items:center;gap:8px}.cta-card .cta-title{font-weight:600}.cta-card .cta-desc{font-size:12px;opacity:.78}.cta-card .cta-actions{display:flex;gap:8px;align-items:center}.tokens-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px;margin:8px 0}.token-item{display:contents}.pdx-appearance{margin-top:8px;display:grid;gap:8px}.pdx-appearance-actions{display:flex;gap:8px;flex-wrap:wrap}.code-card{margin-top:8px}.code-head{font-weight:600;margin-bottom:4px}.code{white-space:pre;overflow:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i8.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i8.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i8.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i10.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i10.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i10.MatCardAvatar, selector: "[mat-card-avatar], [matCardAvatar]" }, { kind: "component", type: i10.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i10.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i10.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i11.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i11.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i12.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i12.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }] });
|
|
1929
|
+
`, isInline: true, styles: [".pdx-editor{display:grid;gap:16px}.pdx-editor .mat-mdc-form-field{width:100%}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-toggles{display:flex;gap:12px;flex-wrap:wrap}.tab-pad{padding:12px;display:grid;gap:12px;background:var(--md-sys-color-surface);border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.help{color:var(--md-sys-color-on-surface-variant);font-size:13px}.quick-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-bottom:6px}.icons-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin:8px 0}.icon-item{display:grid;gap:6px;align-content:start}.icons-hint{margin-top:4px}.pdx-steps{display:grid;gap:8px}.pdx-steps-header{display:flex;justify-content:space-between;align-items:center}.pdx-step-list{display:grid;gap:8px}.pdx-step-item{display:grid;grid-template-columns:24px 1fr auto;gap:8px;align-items:start;padding:8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface);cursor:pointer}.pdx-step-item.active{border-color:var(--md-sys-color-primary);box-shadow:var(--mat-elevation-level2)}.drag-handle{display:flex;align-items:center;color:var(--md-sys-color-on-surface-variant)}.pdx-fields{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.pdx-flag-group{display:flex;gap:10px;align-items:center}.pdx-active-step{display:grid;gap:12px;padding-top:8px;border-top:1px dashed var(--md-sys-color-outline-variant)}.pdx-active-step .hdr{display:flex;gap:12px;align-items:center;justify-content:space-between}.pdx-content-editor{display:grid;gap:16px}.section{display:grid;gap:8px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container-lowest)}.section-body{display:grid;gap:8px}.section-title{font-weight:600;opacity:.85}.section-subtitle{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.section-head{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap}.editorial-section{background:var(--md-sys-color-surface-container-low);border-color:var(--md-sys-color-primary)}.mini-card{display:block}.widget-list{display:grid;gap:8px}.widget-item{display:grid;grid-template-columns:24px 1fr auto;align-items:center;gap:8px;padding:8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface)}.widget-item .info{display:grid;gap:2px;min-width:0}.widget-item .info .name{font-weight:600}.widget-item .info .sub{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.widget-item .info .meta{font-size:11px;color:var(--md-sys-color-on-surface-variant);font-family:var(--md-ref-typeface-plain, monospace);opacity:.85}.widget-item .actions{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}.editorial-item{align-items:start}.editorial-item .actions{justify-content:flex-start}.cta-row{display:flex;gap:8px;align-items:center}.spacer{flex:1 1 auto}.muted{color:var(--md-sys-color-on-surface-variant)}.cta-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px;margin-bottom:8px}.cta-card{display:grid;gap:8px;padding:12px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.cta-card .cta-head{display:flex;align-items:center;gap:8px}.cta-card .cta-title{font-weight:600}.cta-card .cta-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.cta-card .cta-actions{display:flex;gap:8px;align-items:center}.tokens-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px;margin:8px 0}.token-item{display:contents}.pdx-appearance{margin-top:8px;display:grid;gap:8px}.pdx-appearance-actions{display:flex;gap:8px;flex-wrap:wrap}.zone-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px}.zone-card{display:grid;gap:8px;padding:12px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.zone-head{display:flex;align-items:center;justify-content:space-between;gap:8px}.zone-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}.zone-title{font-weight:600}.zone-count{font-size:12px;padding:2px 8px;border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface)}.advanced-list{margin-top:4px}.code-card{margin-top:8px}.code-head{font-weight:600;margin-bottom:4px}.code{white-space:pre;overflow:auto;background:var(--md-sys-color-surface-container-highest)}.w-full{grid-column:1 / -1}.min-180{min-width:180px}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}@media(max-width:900px){.pdx-step-item{grid-template-columns:20px 1fr}.pdx-actions{grid-column:1 / -1;justify-self:end}.widget-item{grid-template-columns:20px 1fr}.widget-item .actions{grid-column:1 / -1;justify-content:flex-start}}@media(max-width:640px){.pdx-active-step .hdr{align-items:flex-start;flex-direction:column}.pdx-flag-group{flex-direction:column;align-items:flex-start}.zone-head{align-items:flex-start;flex-direction:column}.zone-actions{justify-content:flex-start}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i7.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i8.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i8.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i8.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i10.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i10.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i10.MatCardAvatar, selector: "[mat-card-avatar], [matCardAvatar]" }, { kind: "component", type: i10.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i10.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i10.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i11.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i11.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i12.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i12.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i12.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i13.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i13.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }] });
|
|
995
1930
|
}
|
|
996
1931
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisStepperConfigEditor, decorators: [{
|
|
997
1932
|
type: Component,
|
|
@@ -1010,6 +1945,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1010
1945
|
MatCardModule,
|
|
1011
1946
|
MatButtonToggleModule,
|
|
1012
1947
|
MatDialogModule,
|
|
1948
|
+
MatMenuModule,
|
|
1013
1949
|
MatTabsModule,
|
|
1014
1950
|
], template: `
|
|
1015
1951
|
<div class="pdx-editor">
|
|
@@ -1024,7 +1960,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1024
1960
|
<option value="horizontal">Horizontal</option>
|
|
1025
1961
|
<option value="vertical">Vertical</option>
|
|
1026
1962
|
</select>
|
|
1027
|
-
<
|
|
1963
|
+
<button
|
|
1964
|
+
mat-icon-button
|
|
1965
|
+
matSuffix
|
|
1966
|
+
class="help-icon-button"
|
|
1967
|
+
type="button"
|
|
1968
|
+
[matTooltip]="'Horizontal: cabeçalho no topo • Vertical: lista à esquerda'"
|
|
1969
|
+
matTooltipPosition="above"
|
|
1970
|
+
>
|
|
1971
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1972
|
+
</button>
|
|
1028
1973
|
</mat-form-field>
|
|
1029
1974
|
<mat-form-field appearance="outline">
|
|
1030
1975
|
<mat-label>Posição dos títulos</mat-label>
|
|
@@ -1032,7 +1977,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1032
1977
|
<option value="top">Acima</option>
|
|
1033
1978
|
<option value="bottom">Abaixo</option>
|
|
1034
1979
|
</select>
|
|
1035
|
-
<
|
|
1980
|
+
<button
|
|
1981
|
+
mat-icon-button
|
|
1982
|
+
matSuffix
|
|
1983
|
+
class="help-icon-button"
|
|
1984
|
+
type="button"
|
|
1985
|
+
[matTooltip]="'Válido na orientação horizontal'"
|
|
1986
|
+
matTooltipPosition="above"
|
|
1987
|
+
>
|
|
1988
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
1989
|
+
</button>
|
|
1036
1990
|
</mat-form-field>
|
|
1037
1991
|
<mat-form-field appearance="outline">
|
|
1038
1992
|
<mat-label>Posição do rótulo</mat-label>
|
|
@@ -1040,7 +1994,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1040
1994
|
<option value="end">Ao lado</option>
|
|
1041
1995
|
<option value="bottom">Abaixo</option>
|
|
1042
1996
|
</select>
|
|
1043
|
-
<
|
|
1997
|
+
<button
|
|
1998
|
+
mat-icon-button
|
|
1999
|
+
matSuffix
|
|
2000
|
+
class="help-icon-button"
|
|
2001
|
+
type="button"
|
|
2002
|
+
[matTooltip]="'Como o texto aparece no cabeçalho'"
|
|
2003
|
+
matTooltipPosition="above"
|
|
2004
|
+
>
|
|
2005
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2006
|
+
</button>
|
|
1044
2007
|
</mat-form-field>
|
|
1045
2008
|
<mat-form-field appearance="outline">
|
|
1046
2009
|
<mat-label>Cor</mat-label>
|
|
@@ -1050,17 +2013,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1050
2013
|
<option value="accent">Acento</option>
|
|
1051
2014
|
<option value="warn">Alerta</option>
|
|
1052
2015
|
</select>
|
|
1053
|
-
<
|
|
2016
|
+
<button
|
|
2017
|
+
mat-icon-button
|
|
2018
|
+
matSuffix
|
|
2019
|
+
class="help-icon-button"
|
|
2020
|
+
type="button"
|
|
2021
|
+
[matTooltip]="'Aplicável a temas Material 2 (M2)'"
|
|
2022
|
+
matTooltipPosition="above"
|
|
2023
|
+
>
|
|
2024
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2025
|
+
</button>
|
|
1054
2026
|
</mat-form-field>
|
|
1055
2027
|
<mat-form-field appearance="outline">
|
|
1056
2028
|
<mat-label>Duração da animação</mat-label>
|
|
1057
2029
|
<input matInput [(ngModel)]="config.animationDuration" (ngModelChange)="markDirty()" placeholder="Ex.: 300ms" />
|
|
1058
|
-
<
|
|
2030
|
+
<button
|
|
2031
|
+
mat-icon-button
|
|
2032
|
+
matSuffix
|
|
2033
|
+
class="help-icon-button"
|
|
2034
|
+
type="button"
|
|
2035
|
+
[matTooltip]="'Tempo da transição entre etapas'"
|
|
2036
|
+
matTooltipPosition="above"
|
|
2037
|
+
>
|
|
2038
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2039
|
+
</button>
|
|
1059
2040
|
</mat-form-field>
|
|
1060
2041
|
<mat-form-field appearance="outline">
|
|
1061
2042
|
<mat-label>Etapa selecionada</mat-label>
|
|
1062
2043
|
<input matInput type="number" [(ngModel)]="config.selectedIndex" (ngModelChange)="markDirty()" />
|
|
1063
|
-
<
|
|
2044
|
+
<button
|
|
2045
|
+
mat-icon-button
|
|
2046
|
+
matSuffix
|
|
2047
|
+
class="help-icon-button"
|
|
2048
|
+
type="button"
|
|
2049
|
+
[matTooltip]="'Índice inicia em 0 (primeira etapa)'"
|
|
2050
|
+
matTooltipPosition="above"
|
|
2051
|
+
>
|
|
2052
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2053
|
+
</button>
|
|
1064
2054
|
</mat-form-field>
|
|
1065
2055
|
<mat-form-field appearance="outline">
|
|
1066
2056
|
<mat-label>Densidade</mat-label>
|
|
@@ -1069,22 +2059,58 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1069
2059
|
<option value="comfortable">Confortável</option>
|
|
1070
2060
|
<option value="compact">Compacta</option>
|
|
1071
2061
|
</select>
|
|
1072
|
-
<
|
|
2062
|
+
<button
|
|
2063
|
+
mat-icon-button
|
|
2064
|
+
matSuffix
|
|
2065
|
+
class="help-icon-button"
|
|
2066
|
+
type="button"
|
|
2067
|
+
[matTooltip]="'Controla espaçamentos e alturas'"
|
|
2068
|
+
matTooltipPosition="above"
|
|
2069
|
+
>
|
|
2070
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2071
|
+
</button>
|
|
1073
2072
|
</mat-form-field>
|
|
1074
2073
|
<mat-form-field appearance="outline" class="w-full">
|
|
1075
2074
|
<mat-label>Classe do stepper (opcional)</mat-label>
|
|
1076
2075
|
<input matInput [(ngModel)]="config.stepperClass" (ngModelChange)="markDirty()" placeholder="Ex.: meu-stepper" />
|
|
1077
|
-
<
|
|
2076
|
+
<button
|
|
2077
|
+
mat-icon-button
|
|
2078
|
+
matSuffix
|
|
2079
|
+
class="help-icon-button"
|
|
2080
|
+
type="button"
|
|
2081
|
+
[matTooltip]="'Permite estilizar com CSS escopado'"
|
|
2082
|
+
matTooltipPosition="above"
|
|
2083
|
+
>
|
|
2084
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2085
|
+
</button>
|
|
1078
2086
|
</mat-form-field>
|
|
1079
2087
|
<mat-form-field appearance="outline" class="w-full">
|
|
1080
2088
|
<mat-label>Classe do cabeçalho (opcional)</mat-label>
|
|
1081
2089
|
<input matInput [(ngModel)]="config.headerClass" (ngModelChange)="markDirty()" placeholder="Ex.: stepper-header" />
|
|
1082
|
-
<
|
|
2090
|
+
<button
|
|
2091
|
+
mat-icon-button
|
|
2092
|
+
matSuffix
|
|
2093
|
+
class="help-icon-button"
|
|
2094
|
+
type="button"
|
|
2095
|
+
[matTooltip]="'Use para ajustes finos de aparência'"
|
|
2096
|
+
matTooltipPosition="above"
|
|
2097
|
+
>
|
|
2098
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2099
|
+
</button>
|
|
1083
2100
|
</mat-form-field>
|
|
1084
2101
|
<mat-form-field appearance="outline" class="w-full">
|
|
1085
2102
|
<mat-label>Classe do conteúdo (opcional)</mat-label>
|
|
1086
2103
|
<input matInput [(ngModel)]="config.contentClass" (ngModelChange)="markDirty()" placeholder="Ex.: stepper-content" />
|
|
1087
|
-
<
|
|
2104
|
+
<button
|
|
2105
|
+
mat-icon-button
|
|
2106
|
+
matSuffix
|
|
2107
|
+
class="help-icon-button"
|
|
2108
|
+
type="button"
|
|
2109
|
+
[matTooltip]="'Aplica uma classe à área de conteúdo'"
|
|
2110
|
+
matTooltipPosition="above"
|
|
2111
|
+
>
|
|
2112
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2113
|
+
</button>
|
|
1088
2114
|
</mat-form-field>
|
|
1089
2115
|
</div>
|
|
1090
2116
|
<div class="pdx-toggles">
|
|
@@ -1106,35 +2132,89 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1106
2132
|
<div class="pdx-step-item" *ngFor="let s of config.steps; let i = index" cdkDrag [class.active]="activeIndex === i" (click)="setActive(i)">
|
|
1107
2133
|
<div class="drag-handle" cdkDragHandle><mat-icon [praxisIcon]="'drag_indicator'"></mat-icon></div>
|
|
1108
2134
|
<div class="pdx-fields">
|
|
1109
|
-
<mat-form-field appearance="outline"
|
|
2135
|
+
<mat-form-field appearance="outline" class="min-180">
|
|
1110
2136
|
<mat-label>Título da etapa</mat-label>
|
|
1111
2137
|
<input matInput [(ngModel)]="s.label" (ngModelChange)="markDirty()" />
|
|
1112
|
-
<
|
|
2138
|
+
<button
|
|
2139
|
+
mat-icon-button
|
|
2140
|
+
matSuffix
|
|
2141
|
+
class="help-icon-button"
|
|
2142
|
+
type="button"
|
|
2143
|
+
[matTooltip]="'Como aparecerá no cabeçalho'"
|
|
2144
|
+
matTooltipPosition="above"
|
|
2145
|
+
>
|
|
2146
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2147
|
+
</button>
|
|
1113
2148
|
</mat-form-field>
|
|
1114
2149
|
<mat-form-field appearance="outline">
|
|
1115
2150
|
<mat-label>Identificador (opcional)</mat-label>
|
|
1116
2151
|
<input matInput [(ngModel)]="s.id" (ngModelChange)="markDirty()" />
|
|
1117
|
-
<
|
|
2152
|
+
<button
|
|
2153
|
+
mat-icon-button
|
|
2154
|
+
matSuffix
|
|
2155
|
+
class="help-icon-button"
|
|
2156
|
+
type="button"
|
|
2157
|
+
[matTooltip]="'Útil para automações'"
|
|
2158
|
+
matTooltipPosition="above"
|
|
2159
|
+
>
|
|
2160
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2161
|
+
</button>
|
|
1118
2162
|
</mat-form-field>
|
|
1119
2163
|
<mat-form-field appearance="outline">
|
|
1120
2164
|
<mat-label>Texto alternativo (acessibilidade)</mat-label>
|
|
1121
2165
|
<input matInput [(ngModel)]="s.ariaLabel" (ngModelChange)="markDirty()" />
|
|
1122
|
-
<
|
|
2166
|
+
<button
|
|
2167
|
+
mat-icon-button
|
|
2168
|
+
matSuffix
|
|
2169
|
+
class="help-icon-button"
|
|
2170
|
+
type="button"
|
|
2171
|
+
[matTooltip]="'Lido por leitores de tela'"
|
|
2172
|
+
matTooltipPosition="above"
|
|
2173
|
+
>
|
|
2174
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2175
|
+
</button>
|
|
1123
2176
|
</mat-form-field>
|
|
1124
2177
|
<mat-form-field appearance="outline">
|
|
1125
2178
|
<mat-label>ID que descreve (opcional)</mat-label>
|
|
1126
2179
|
<input matInput [(ngModel)]="s.ariaLabelledby" (ngModelChange)="markDirty()" />
|
|
1127
|
-
<
|
|
2180
|
+
<button
|
|
2181
|
+
mat-icon-button
|
|
2182
|
+
matSuffix
|
|
2183
|
+
class="help-icon-button"
|
|
2184
|
+
type="button"
|
|
2185
|
+
[matTooltip]="'ID de um elemento que descreve a etapa'"
|
|
2186
|
+
matTooltipPosition="above"
|
|
2187
|
+
>
|
|
2188
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2189
|
+
</button>
|
|
1128
2190
|
</mat-form-field>
|
|
1129
2191
|
<mat-form-field appearance="outline">
|
|
1130
2192
|
<mat-label>Ícone/estado do marcador</mat-label>
|
|
1131
2193
|
<input matInput [(ngModel)]="s.state" (ngModelChange)="markDirty()" placeholder="Ex.: number, done, edit" />
|
|
1132
|
-
<
|
|
2194
|
+
<button
|
|
2195
|
+
mat-icon-button
|
|
2196
|
+
matSuffix
|
|
2197
|
+
class="help-icon-button"
|
|
2198
|
+
type="button"
|
|
2199
|
+
[matTooltip]="'Controla o ícone do passo (quando aplicável)'"
|
|
2200
|
+
matTooltipPosition="above"
|
|
2201
|
+
>
|
|
2202
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2203
|
+
</button>
|
|
1133
2204
|
</mat-form-field>
|
|
1134
2205
|
<mat-form-field appearance="outline">
|
|
1135
2206
|
<mat-label>Mensagem de erro</mat-label>
|
|
1136
2207
|
<input matInput [(ngModel)]="s.errorMessage" (ngModelChange)="markDirty()" />
|
|
1137
|
-
<
|
|
2208
|
+
<button
|
|
2209
|
+
mat-icon-button
|
|
2210
|
+
matSuffix
|
|
2211
|
+
class="help-icon-button"
|
|
2212
|
+
type="button"
|
|
2213
|
+
[matTooltip]="'Mostrada quando há erro na etapa'"
|
|
2214
|
+
matTooltipPosition="above"
|
|
2215
|
+
>
|
|
2216
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2217
|
+
</button>
|
|
1138
2218
|
</mat-form-field>
|
|
1139
2219
|
<div class="pdx-flag-group">
|
|
1140
2220
|
<mat-slide-toggle [(ngModel)]="s.optional" (ngModelChange)="markDirty()">Etapa opcional</mat-slide-toggle>
|
|
@@ -1161,8 +2241,139 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1161
2241
|
</div>
|
|
1162
2242
|
|
|
1163
2243
|
<div class="pdx-content-editor">
|
|
2244
|
+
<div class="section editorial-section">
|
|
2245
|
+
<div class="section-head">
|
|
2246
|
+
<div>
|
|
2247
|
+
<div class="section-title">Conteúdo editorial</div>
|
|
2248
|
+
<div class="section-subtitle">Organize os blocos narrativos da etapa antes ou depois do formulário.</div>
|
|
2249
|
+
</div>
|
|
2250
|
+
</div>
|
|
2251
|
+
|
|
2252
|
+
<div class="zone-grid">
|
|
2253
|
+
<div class="zone-card">
|
|
2254
|
+
<div class="zone-head">
|
|
2255
|
+
<div class="zone-title">Antes do formulário</div>
|
|
2256
|
+
<div class="zone-actions">
|
|
2257
|
+
<span class="zone-count">{{ editorialBeforeWidgets(step).length }}</span>
|
|
2258
|
+
<button mat-stroked-button [matMenuTriggerFor]="beforeEditorialMenu">
|
|
2259
|
+
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
2260
|
+
Adicionar
|
|
2261
|
+
</button>
|
|
2262
|
+
<mat-menu #beforeEditorialMenu="matMenu">
|
|
2263
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-benefits', 'before')">
|
|
2264
|
+
<mat-icon [praxisIcon]="'view_module'"></mat-icon>
|
|
2265
|
+
Grade de benefícios
|
|
2266
|
+
</button>
|
|
2267
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-content', 'before')">
|
|
2268
|
+
<mat-icon [praxisIcon]="'article'"></mat-icon>
|
|
2269
|
+
Bloco de conteúdo
|
|
2270
|
+
</button>
|
|
2271
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-inline-notice', 'before')">
|
|
2272
|
+
<mat-icon [praxisIcon]="'info'"></mat-icon>
|
|
2273
|
+
Aviso inline
|
|
2274
|
+
</button>
|
|
2275
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-divider', 'before')">
|
|
2276
|
+
<mat-icon [praxisIcon]="'horizontal_rule'"></mat-icon>
|
|
2277
|
+
Divisor
|
|
2278
|
+
</button>
|
|
2279
|
+
</mat-menu>
|
|
2280
|
+
</div>
|
|
2281
|
+
</div>
|
|
2282
|
+
<div cdkDropList (cdkDropListDropped)="dropEditorialBefore($event)" class="widget-list">
|
|
2283
|
+
<div class="widget-item editorial-item" *ngFor="let w of editorialBeforeWidgets(step)" cdkDrag>
|
|
2284
|
+
<div class="drag-handle" cdkDragHandle><mat-icon [praxisIcon]="'drag_indicator'"></mat-icon></div>
|
|
2285
|
+
<div class="info">
|
|
2286
|
+
<div class="name">{{ displayWidgetName(w) }}</div>
|
|
2287
|
+
<div class="sub">{{ editorialWidgetSummary(w) }}</div>
|
|
2288
|
+
<div class="meta" *ngIf="widgetBlockId(w) as blockId">ID: {{ blockId }}</div>
|
|
2289
|
+
</div>
|
|
2290
|
+
<div class="actions">
|
|
2291
|
+
<button mat-button (click)="editWidget(w)">
|
|
2292
|
+
<mat-icon [praxisIcon]="'tune'"></mat-icon>
|
|
2293
|
+
Editar
|
|
2294
|
+
</button>
|
|
2295
|
+
<button mat-button (click)="moveEditorialWidget(w, 'before', 'after')">
|
|
2296
|
+
<mat-icon [praxisIcon]="'arrow_downward'"></mat-icon>
|
|
2297
|
+
Mover para depois
|
|
2298
|
+
</button>
|
|
2299
|
+
<button mat-button (click)="duplicateEditorialWidget(w, 'before')">
|
|
2300
|
+
<mat-icon [praxisIcon]="'content_copy'"></mat-icon>
|
|
2301
|
+
Duplicar
|
|
2302
|
+
</button>
|
|
2303
|
+
<button mat-button color="warn" (click)="removeEditorialWidget(w, 'before')">
|
|
2304
|
+
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
2305
|
+
Remover
|
|
2306
|
+
</button>
|
|
2307
|
+
</div>
|
|
2308
|
+
</div>
|
|
2309
|
+
<div class="empty" *ngIf="!editorialBeforeWidgets(step).length">Nenhum bloco nesta zona.</div>
|
|
2310
|
+
</div>
|
|
2311
|
+
</div>
|
|
2312
|
+
|
|
2313
|
+
<div class="zone-card">
|
|
2314
|
+
<div class="zone-head">
|
|
2315
|
+
<div class="zone-title">Depois do formulário</div>
|
|
2316
|
+
<div class="zone-actions">
|
|
2317
|
+
<span class="zone-count">{{ editorialAfterWidgets(step).length }}</span>
|
|
2318
|
+
<button mat-stroked-button [matMenuTriggerFor]="afterEditorialMenu">
|
|
2319
|
+
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
2320
|
+
Adicionar
|
|
2321
|
+
</button>
|
|
2322
|
+
<mat-menu #afterEditorialMenu="matMenu">
|
|
2323
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-benefits', 'after')">
|
|
2324
|
+
<mat-icon [praxisIcon]="'view_module'"></mat-icon>
|
|
2325
|
+
Grade de benefícios
|
|
2326
|
+
</button>
|
|
2327
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-content', 'after')">
|
|
2328
|
+
<mat-icon [praxisIcon]="'article'"></mat-icon>
|
|
2329
|
+
Bloco de conteúdo
|
|
2330
|
+
</button>
|
|
2331
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-inline-notice', 'after')">
|
|
2332
|
+
<mat-icon [praxisIcon]="'info'"></mat-icon>
|
|
2333
|
+
Aviso inline
|
|
2334
|
+
</button>
|
|
2335
|
+
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-divider', 'after')">
|
|
2336
|
+
<mat-icon [praxisIcon]="'horizontal_rule'"></mat-icon>
|
|
2337
|
+
Divisor
|
|
2338
|
+
</button>
|
|
2339
|
+
</mat-menu>
|
|
2340
|
+
</div>
|
|
2341
|
+
</div>
|
|
2342
|
+
<div cdkDropList (cdkDropListDropped)="dropEditorialAfter($event)" class="widget-list">
|
|
2343
|
+
<div class="widget-item editorial-item" *ngFor="let w of editorialAfterWidgets(step)" cdkDrag>
|
|
2344
|
+
<div class="drag-handle" cdkDragHandle><mat-icon [praxisIcon]="'drag_indicator'"></mat-icon></div>
|
|
2345
|
+
<div class="info">
|
|
2346
|
+
<div class="name">{{ displayWidgetName(w) }}</div>
|
|
2347
|
+
<div class="sub">{{ editorialWidgetSummary(w) }}</div>
|
|
2348
|
+
<div class="meta" *ngIf="widgetBlockId(w) as blockId">ID: {{ blockId }}</div>
|
|
2349
|
+
</div>
|
|
2350
|
+
<div class="actions">
|
|
2351
|
+
<button mat-button (click)="editWidget(w)">
|
|
2352
|
+
<mat-icon [praxisIcon]="'tune'"></mat-icon>
|
|
2353
|
+
Editar
|
|
2354
|
+
</button>
|
|
2355
|
+
<button mat-button (click)="moveEditorialWidget(w, 'after', 'before')">
|
|
2356
|
+
<mat-icon [praxisIcon]="'arrow_upward'"></mat-icon>
|
|
2357
|
+
Mover para antes
|
|
2358
|
+
</button>
|
|
2359
|
+
<button mat-button (click)="duplicateEditorialWidget(w, 'after')">
|
|
2360
|
+
<mat-icon [praxisIcon]="'content_copy'"></mat-icon>
|
|
2361
|
+
Duplicar
|
|
2362
|
+
</button>
|
|
2363
|
+
<button mat-button color="warn" (click)="removeEditorialWidget(w, 'after')">
|
|
2364
|
+
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
2365
|
+
Remover
|
|
2366
|
+
</button>
|
|
2367
|
+
</div>
|
|
2368
|
+
</div>
|
|
2369
|
+
<div class="empty" *ngIf="!editorialAfterWidgets(step).length">Nenhum bloco nesta zona.</div>
|
|
2370
|
+
</div>
|
|
2371
|
+
</div>
|
|
2372
|
+
</div>
|
|
2373
|
+
</div>
|
|
2374
|
+
|
|
1164
2375
|
<div class="section">
|
|
1165
|
-
<div class="section-title">Formulário
|
|
2376
|
+
<div class="section-title">Formulário da etapa</div>
|
|
1166
2377
|
<div class="section-body">
|
|
1167
2378
|
<ng-container *ngIf="step.form; else addFormBtn">
|
|
1168
2379
|
<mat-card appearance="outlined" class="mini-card">
|
|
@@ -1184,62 +2395,91 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1184
2395
|
</div>
|
|
1185
2396
|
|
|
1186
2397
|
<div class="section">
|
|
1187
|
-
<div class="section-
|
|
2398
|
+
<div class="section-head">
|
|
2399
|
+
<div>
|
|
2400
|
+
<div class="section-title">Componentes avançados</div>
|
|
2401
|
+
<div class="section-subtitle">Use para cenários de seleção e integrações específicas.</div>
|
|
2402
|
+
</div>
|
|
2403
|
+
<button mat-stroked-button (click)="openMoreComponents()">
|
|
2404
|
+
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
2405
|
+
Mais componentes
|
|
2406
|
+
</button>
|
|
2407
|
+
</div>
|
|
1188
2408
|
<div class="section-body">
|
|
1189
2409
|
<div class="cta-grid">
|
|
1190
2410
|
<div class="cta-card mat-elevation-z2">
|
|
1191
2411
|
<div class="cta-head">
|
|
1192
|
-
<mat-icon [praxisIcon]="'
|
|
1193
|
-
<div class="cta-title">
|
|
2412
|
+
<mat-icon [praxisIcon]="'account_tree'"></mat-icon>
|
|
2413
|
+
<div class="cta-title">Lista em árvore</div>
|
|
1194
2414
|
</div>
|
|
1195
|
-
<div class="cta-desc">
|
|
2415
|
+
<div class="cta-desc">Exiba dados hierárquicos com seleção simples.</div>
|
|
1196
2416
|
<div class="cta-actions">
|
|
1197
|
-
<button mat-
|
|
2417
|
+
<button mat-stroked-button (click)="addTreeList()">
|
|
1198
2418
|
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
1199
|
-
Inserir
|
|
2419
|
+
Inserir árvore
|
|
1200
2420
|
</button>
|
|
1201
2421
|
</div>
|
|
1202
2422
|
</div>
|
|
1203
2423
|
<div class="cta-card mat-elevation-z2">
|
|
1204
2424
|
<div class="cta-head">
|
|
1205
|
-
<mat-icon [praxisIcon]="'
|
|
1206
|
-
<div class="cta-title">
|
|
2425
|
+
<mat-icon [praxisIcon]="'swap_horiz'"></mat-icon>
|
|
2426
|
+
<div class="cta-title">Transferência de itens</div>
|
|
1207
2427
|
</div>
|
|
1208
|
-
<div class="cta-desc">
|
|
2428
|
+
<div class="cta-desc">Mover itens entre listas (ideal para múltipla seleção).</div>
|
|
1209
2429
|
<div class="cta-actions">
|
|
1210
|
-
<button mat-stroked-button (click)="
|
|
2430
|
+
<button mat-stroked-button (click)="addTransferListQuick()">
|
|
1211
2431
|
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
1212
|
-
Inserir
|
|
2432
|
+
Inserir transferência
|
|
1213
2433
|
</button>
|
|
1214
2434
|
</div>
|
|
1215
2435
|
</div>
|
|
1216
2436
|
<div class="cta-card mat-elevation-z2">
|
|
1217
2437
|
<div class="cta-head">
|
|
1218
|
-
<mat-icon [praxisIcon]="'
|
|
1219
|
-
<div class="cta-title">
|
|
2438
|
+
<mat-icon [praxisIcon]="'search'"></mat-icon>
|
|
2439
|
+
<div class="cta-title">Seleção com busca</div>
|
|
1220
2440
|
</div>
|
|
1221
|
-
<div class="cta-desc">
|
|
2441
|
+
<div class="cta-desc">Campo de seleção com busca remota/local.</div>
|
|
1222
2442
|
<div class="cta-actions">
|
|
1223
|
-
<button mat-stroked-button (click)="
|
|
2443
|
+
<button mat-stroked-button (click)="addSearchableSelect()">
|
|
1224
2444
|
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
1225
|
-
Inserir
|
|
2445
|
+
Inserir seletor
|
|
2446
|
+
</button>
|
|
2447
|
+
</div>
|
|
2448
|
+
</div>
|
|
2449
|
+
<div class="cta-card mat-elevation-z2">
|
|
2450
|
+
<div class="cta-head">
|
|
2451
|
+
<mat-icon [praxisIcon]="'upload_file'"></mat-icon>
|
|
2452
|
+
<div class="cta-title">Upload de arquivos</div>
|
|
2453
|
+
</div>
|
|
2454
|
+
<div class="cta-desc">Anexe documentos com validação de upload.</div>
|
|
2455
|
+
<div class="cta-actions">
|
|
2456
|
+
<button mat-stroked-button (click)="addFilesUpload()">
|
|
2457
|
+
<mat-icon [praxisIcon]="'add'"></mat-icon>
|
|
2458
|
+
Inserir upload
|
|
1226
2459
|
</button>
|
|
1227
2460
|
</div>
|
|
1228
2461
|
</div>
|
|
1229
2462
|
</div>
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
2463
|
+
|
|
2464
|
+
<div class="widget-list advanced-list">
|
|
2465
|
+
<div class="widget-item" *ngFor="let w of advancedWidgets(step)">
|
|
2466
|
+
<div class="drag-handle"><mat-icon [praxisIcon]="'extension'"></mat-icon></div>
|
|
1233
2467
|
<div class="info">
|
|
1234
2468
|
<div class="name">{{ displayWidgetName(w) }}</div>
|
|
1235
2469
|
<div class="sub">{{ w.id }}</div>
|
|
1236
2470
|
</div>
|
|
1237
2471
|
<div class="actions">
|
|
1238
|
-
<button mat-button (click)="editWidget(w
|
|
1239
|
-
|
|
2472
|
+
<button mat-button (click)="editWidget(w)" [disabled]="!canEditWidget(w)">
|
|
2473
|
+
<mat-icon [praxisIcon]="'tune'"></mat-icon>
|
|
2474
|
+
Editar
|
|
2475
|
+
</button>
|
|
2476
|
+
<button mat-button color="warn" (click)="removeAdvancedWidget(w)">
|
|
2477
|
+
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
2478
|
+
Remover
|
|
2479
|
+
</button>
|
|
1240
2480
|
</div>
|
|
1241
2481
|
</div>
|
|
1242
|
-
<div class="empty" *ngIf="!step.
|
|
2482
|
+
<div class="empty" *ngIf="!advancedWidgets(step).length">Nenhum componente avançado adicionado.</div>
|
|
1243
2483
|
</div>
|
|
1244
2484
|
</div>
|
|
1245
2485
|
</div>
|
|
@@ -1327,12 +2567,30 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1327
2567
|
<mat-form-field appearance="outline">
|
|
1328
2568
|
<mat-label>Altura do cabeçalho (px)</mat-label>
|
|
1329
2569
|
<input matInput type="number" [ngModel]="headerHeightPx" (ngModelChange)="setHeaderHeightPx($event)" placeholder="Ex.: 48" />
|
|
1330
|
-
<
|
|
2570
|
+
<button
|
|
2571
|
+
mat-icon-button
|
|
2572
|
+
matSuffix
|
|
2573
|
+
class="help-icon-button"
|
|
2574
|
+
type="button"
|
|
2575
|
+
[matTooltip]="'Altura do item do cabeçalho'"
|
|
2576
|
+
matTooltipPosition="above"
|
|
2577
|
+
>
|
|
2578
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2579
|
+
</button>
|
|
1331
2580
|
</mat-form-field>
|
|
1332
2581
|
<mat-form-field appearance="outline">
|
|
1333
2582
|
<mat-label>Tamanho do texto (px)</mat-label>
|
|
1334
2583
|
<input matInput type="number" [ngModel]="headerLabelTextSizePx" (ngModelChange)="setHeaderLabelTextSizePx($event)" placeholder="Ex.: 14" />
|
|
1335
|
-
<
|
|
2584
|
+
<button
|
|
2585
|
+
mat-icon-button
|
|
2586
|
+
matSuffix
|
|
2587
|
+
class="help-icon-button"
|
|
2588
|
+
type="button"
|
|
2589
|
+
[matTooltip]="'Tamanho do título da etapa'"
|
|
2590
|
+
matTooltipPosition="above"
|
|
2591
|
+
>
|
|
2592
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2593
|
+
</button>
|
|
1336
2594
|
</mat-form-field>
|
|
1337
2595
|
<mat-form-field appearance="outline">
|
|
1338
2596
|
<mat-label>Peso do texto</mat-label>
|
|
@@ -1349,7 +2607,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1349
2607
|
<mat-form-field appearance="outline" class="w-full">
|
|
1350
2608
|
<mat-label>Classe de tema (opcional)</mat-label>
|
|
1351
2609
|
<input matInput [(ngModel)]="appearance.themeClass" (ngModelChange)="onAppearanceChange()" placeholder="Ex.: theme-stepper-custom" />
|
|
1352
|
-
<
|
|
2610
|
+
<button
|
|
2611
|
+
mat-icon-button
|
|
2612
|
+
matSuffix
|
|
2613
|
+
class="help-icon-button"
|
|
2614
|
+
type="button"
|
|
2615
|
+
[matTooltip]="'Aplica as cores apenas dentro desse seletor'"
|
|
2616
|
+
matTooltipPosition="above"
|
|
2617
|
+
>
|
|
2618
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2619
|
+
</button>
|
|
1353
2620
|
</mat-form-field>
|
|
1354
2621
|
<mat-form-field appearance="outline">
|
|
1355
2622
|
<mat-label>Conjunto de ícones</mat-label>
|
|
@@ -1359,7 +2626,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1359
2626
|
<option value="material-symbols-rounded">Material Symbols (Rounded)</option>
|
|
1360
2627
|
<option value="material-symbols-sharp">Material Symbols (Sharp)</option>
|
|
1361
2628
|
</select>
|
|
1362
|
-
<
|
|
2629
|
+
<button
|
|
2630
|
+
mat-icon-button
|
|
2631
|
+
matSuffix
|
|
2632
|
+
class="help-icon-button"
|
|
2633
|
+
type="button"
|
|
2634
|
+
[matTooltip]="'Selecione se usar ícones do Material Symbols'"
|
|
2635
|
+
matTooltipPosition="above"
|
|
2636
|
+
>
|
|
2637
|
+
<mat-icon [praxisIcon]="'help_outline'"></mat-icon>
|
|
2638
|
+
</button>
|
|
1363
2639
|
</mat-form-field>
|
|
1364
2640
|
</div>
|
|
1365
2641
|
<div class="icons-grid">
|
|
@@ -1420,12 +2696,225 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1420
2696
|
</mat-tab>
|
|
1421
2697
|
</mat-tab-group>
|
|
1422
2698
|
</div>
|
|
1423
|
-
`, styles: [".pdx-editor{display:grid;gap:16px}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-toggles{display:flex;gap:12px;flex-wrap:wrap}.tab-pad{padding:12px
|
|
2699
|
+
`, styles: [".pdx-editor{display:grid;gap:16px}.pdx-editor .mat-mdc-form-field{width:100%}.pdx-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px}.pdx-toggles{display:flex;gap:12px;flex-wrap:wrap}.tab-pad{padding:12px;display:grid;gap:12px;background:var(--md-sys-color-surface);border:1px solid var(--md-sys-color-outline-variant);border-radius:12px}.help{color:var(--md-sys-color-on-surface-variant);font-size:13px}.quick-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin-bottom:6px}.icons-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px;margin:8px 0}.icon-item{display:grid;gap:6px;align-content:start}.icons-hint{margin-top:4px}.pdx-steps{display:grid;gap:8px}.pdx-steps-header{display:flex;justify-content:space-between;align-items:center}.pdx-step-list{display:grid;gap:8px}.pdx-step-item{display:grid;grid-template-columns:24px 1fr auto;gap:8px;align-items:start;padding:8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;background:var(--md-sys-color-surface);cursor:pointer}.pdx-step-item.active{border-color:var(--md-sys-color-primary);box-shadow:var(--mat-elevation-level2)}.drag-handle{display:flex;align-items:center;color:var(--md-sys-color-on-surface-variant)}.pdx-fields{display:grid;gap:8px;grid-template-columns:repeat(auto-fit,minmax(160px,1fr))}.pdx-flag-group{display:flex;gap:10px;align-items:center}.pdx-active-step{display:grid;gap:12px;padding-top:8px;border-top:1px dashed var(--md-sys-color-outline-variant)}.pdx-active-step .hdr{display:flex;gap:12px;align-items:center;justify-content:space-between}.pdx-content-editor{display:grid;gap:16px}.section{display:grid;gap:8px;padding:12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;background:var(--md-sys-color-surface-container-lowest)}.section-body{display:grid;gap:8px}.section-title{font-weight:600;opacity:.85}.section-subtitle{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.section-head{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap}.editorial-section{background:var(--md-sys-color-surface-container-low);border-color:var(--md-sys-color-primary)}.mini-card{display:block}.widget-list{display:grid;gap:8px}.widget-item{display:grid;grid-template-columns:24px 1fr auto;align-items:center;gap:8px;padding:8px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface)}.widget-item .info{display:grid;gap:2px;min-width:0}.widget-item .info .name{font-weight:600}.widget-item .info .sub{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.widget-item .info .meta{font-size:11px;color:var(--md-sys-color-on-surface-variant);font-family:var(--md-ref-typeface-plain, monospace);opacity:.85}.widget-item .actions{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}.editorial-item{align-items:start}.editorial-item .actions{justify-content:flex-start}.cta-row{display:flex;gap:8px;align-items:center}.spacer{flex:1 1 auto}.muted{color:var(--md-sys-color-on-surface-variant)}.cta-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:12px;margin-bottom:8px}.cta-card{display:grid;gap:8px;padding:12px;border-radius:12px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.cta-card .cta-head{display:flex;align-items:center;gap:8px}.cta-card .cta-title{font-weight:600}.cta-card .cta-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant)}.cta-card .cta-actions{display:flex;gap:8px;align-items:center}.tokens-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px;margin:8px 0}.token-item{display:contents}.pdx-appearance{margin-top:8px;display:grid;gap:8px}.pdx-appearance-actions{display:flex;gap:8px;flex-wrap:wrap}.zone-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px}.zone-card{display:grid;gap:8px;padding:12px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface)}.zone-head{display:flex;align-items:center;justify-content:space-between;gap:8px}.zone-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}.zone-title{font-weight:600}.zone-count{font-size:12px;padding:2px 8px;border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface)}.advanced-list{margin-top:4px}.code-card{margin-top:8px}.code-head{font-weight:600;margin-bottom:4px}.code{white-space:pre;overflow:auto;background:var(--md-sys-color-surface-container-highest)}.w-full{grid-column:1 / -1}.min-180{min-width:180px}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;margin-right:-4px}.help-icon-button mat-icon{font-size:18px;width:18px;height:18px}.mat-mdc-form-field-icon-suffix{align-self:center}@media(max-width:900px){.pdx-step-item{grid-template-columns:20px 1fr}.pdx-actions{grid-column:1 / -1;justify-self:end}.widget-item{grid-template-columns:20px 1fr}.widget-item .actions{grid-column:1 / -1;justify-content:flex-start}}@media(max-width:640px){.pdx-active-step .hdr{align-items:flex-start;flex-direction:column}.pdx-flag-group{flex-direction:column;align-items:flex-start}.zone-head{align-items:flex-start;flex-direction:column}.zone-actions{justify-content:flex-start}}\n"] }]
|
|
1424
2700
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
1425
2701
|
type: Inject,
|
|
1426
2702
|
args: [SETTINGS_PANEL_DATA]
|
|
1427
2703
|
}] }] });
|
|
1428
2704
|
|
|
2705
|
+
/**
|
|
2706
|
+
* Capabilities catalog for Praxis Stepper (StepperMetadata).
|
|
2707
|
+
* Paths follow StepperMetadata shape (patch merged at config root).
|
|
2708
|
+
*/
|
|
2709
|
+
const ENUMS = {
|
|
2710
|
+
orientation: ['horizontal', 'vertical'],
|
|
2711
|
+
headerPosition: ['top', 'bottom'],
|
|
2712
|
+
labelPosition: ['bottom', 'end'],
|
|
2713
|
+
density: ['default', 'comfortable', 'compact'],
|
|
2714
|
+
matColor: ['primary', 'accent', 'warn'],
|
|
2715
|
+
navVariant: ['basic', 'flat', 'stroked', 'raised'],
|
|
2716
|
+
navAlign: ['start', 'center', 'end', 'space-between'],
|
|
2717
|
+
formMode: ['create', 'edit', 'view'],
|
|
2718
|
+
schemaSource: ['resource', 'filter'],
|
|
2719
|
+
iconsSet: ['material-symbols-outlined', 'material-symbols-rounded', 'material-symbols-sharp'],
|
|
2720
|
+
widgetId: ['praxis-dynamic-form', 'praxis-list', 'pdx-material-searchable-select', 'praxis-files-upload'],
|
|
2721
|
+
stepperTokenKey: [
|
|
2722
|
+
'container-color',
|
|
2723
|
+
'line-color',
|
|
2724
|
+
'header-label-text-color',
|
|
2725
|
+
'header-optional-label-text-color',
|
|
2726
|
+
'header-icon-foreground-color',
|
|
2727
|
+
'header-icon-background-color',
|
|
2728
|
+
'header-done-state-icon-background-color',
|
|
2729
|
+
'header-done-state-icon-foreground-color',
|
|
2730
|
+
'header-edit-state-icon-background-color',
|
|
2731
|
+
'header-edit-state-icon-foreground-color',
|
|
2732
|
+
'header-error-state-icon-background-color',
|
|
2733
|
+
'header-error-state-icon-foreground-color',
|
|
2734
|
+
'header-error-state-label-text-color',
|
|
2735
|
+
'header-focus-state-layer-color',
|
|
2736
|
+
'header-hover-state-layer-color',
|
|
2737
|
+
'header-label-text-font',
|
|
2738
|
+
'header-label-text-size',
|
|
2739
|
+
'header-label-text-weight',
|
|
2740
|
+
'header-selected-state-label-text-size',
|
|
2741
|
+
'header-selected-state-label-text-weight',
|
|
2742
|
+
'container-text-font',
|
|
2743
|
+
'header-height',
|
|
2744
|
+
'header-focus-state-layer-shape',
|
|
2745
|
+
'header-hover-state-layer-shape',
|
|
2746
|
+
'header-selected-state-icon-background-color',
|
|
2747
|
+
'header-selected-state-icon-foreground-color',
|
|
2748
|
+
'header-selected-state-label-text-color',
|
|
2749
|
+
],
|
|
2750
|
+
};
|
|
2751
|
+
const CAPS = [
|
|
2752
|
+
{ path: 'orientation', category: 'layout', valueKind: 'enum', allowedValues: ENUMS.orientation, description: 'Orientation of the stepper.' },
|
|
2753
|
+
{ path: 'linear', category: 'behavior', valueKind: 'boolean', description: 'Require sequential completion of steps.' },
|
|
2754
|
+
{ path: 'headerPosition', category: 'layout', valueKind: 'enum', allowedValues: ENUMS.headerPosition, description: 'Header position (vertical only).' },
|
|
2755
|
+
{ path: 'labelPosition', category: 'layout', valueKind: 'enum', allowedValues: ENUMS.labelPosition, description: 'Label position for horizontal stepper.' },
|
|
2756
|
+
{ path: 'color', category: 'appearance', valueKind: 'enum', allowedValues: ENUMS.matColor, description: 'Material color palette.' },
|
|
2757
|
+
{ path: 'disableRipple', category: 'behavior', valueKind: 'boolean', description: 'Disable ripple for headers.' },
|
|
2758
|
+
{ path: 'animationDuration', category: 'behavior', valueKind: 'string', description: 'Animation duration, e.g. 300ms.' },
|
|
2759
|
+
{ path: 'selectedIndex', category: 'behavior', valueKind: 'number', description: 'Current step index.' },
|
|
2760
|
+
{ path: 'density', category: 'appearance', valueKind: 'enum', allowedValues: ENUMS.density, description: 'Density preset.' },
|
|
2761
|
+
{ path: 'stepperClass', category: 'appearance', valueKind: 'string', description: 'CSS class for stepper root.' },
|
|
2762
|
+
{ path: 'headerClass', category: 'appearance', valueKind: 'string', description: 'CSS class for header.' },
|
|
2763
|
+
{ path: 'contentClass', category: 'appearance', valueKind: 'string', description: 'CSS class for content area.' },
|
|
2764
|
+
{ path: 'appearance', category: 'appearance', valueKind: 'object', description: 'Appearance settings.' },
|
|
2765
|
+
{ path: 'appearance.themeClass', category: 'appearance', valueKind: 'string', description: 'Theme CSS class for root.' },
|
|
2766
|
+
{ path: 'appearance.tokens', category: 'appearance', valueKind: 'object', description: 'Token map for theme overrides.' },
|
|
2767
|
+
{ path: 'appearance.tokens.[token]', category: 'appearance', valueKind: 'string', allowedValues: ENUMS.stepperTokenKey, description: 'Token value (CSS value or var).', safetyNotes: 'Token keys follow mat.stepper-overrides.' },
|
|
2768
|
+
{ path: 'appearance.icons', category: 'appearance', valueKind: 'object', description: 'Stepper icon overrides.' },
|
|
2769
|
+
{ path: 'appearance.icons.number', category: 'appearance', valueKind: 'string', description: 'Icon for number state.' },
|
|
2770
|
+
{ path: 'appearance.icons.done', category: 'appearance', valueKind: 'string', description: 'Icon for done state.' },
|
|
2771
|
+
{ path: 'appearance.icons.edit', category: 'appearance', valueKind: 'string', description: 'Icon for edit state.' },
|
|
2772
|
+
{ path: 'appearance.icons.error', category: 'appearance', valueKind: 'string', description: 'Icon for error state.' },
|
|
2773
|
+
{ path: 'appearance.iconsSet', category: 'appearance', valueKind: 'enum', allowedValues: ENUMS.iconsSet, description: 'Icon set class name (Material Symbols).' },
|
|
2774
|
+
{ path: 'navigation', category: 'navigation', valueKind: 'object', description: 'Footer navigation config.' },
|
|
2775
|
+
{ path: 'navigation.visible', category: 'navigation', valueKind: 'boolean', description: 'Show navigation buttons.' },
|
|
2776
|
+
{ path: 'navigation.prevLabel', category: 'navigation', valueKind: 'string', description: 'Previous button label.' },
|
|
2777
|
+
{ path: 'navigation.nextLabel', category: 'navigation', valueKind: 'string', description: 'Next button label.' },
|
|
2778
|
+
{ path: 'navigation.prevIcon', category: 'navigation', valueKind: 'string', description: 'Previous button icon.' },
|
|
2779
|
+
{ path: 'navigation.nextIcon', category: 'navigation', valueKind: 'string', description: 'Next button icon.' },
|
|
2780
|
+
{ path: 'navigation.variant', category: 'navigation', valueKind: 'enum', allowedValues: ENUMS.navVariant, description: 'Button variant.' },
|
|
2781
|
+
{ path: 'navigation.color', category: 'navigation', valueKind: 'enum', allowedValues: ENUMS.matColor, description: 'Button color.' },
|
|
2782
|
+
{ path: 'navigation.align', category: 'navigation', valueKind: 'enum', allowedValues: ENUMS.navAlign, description: 'Navigation alignment.' },
|
|
2783
|
+
{ path: 'steps', category: 'steps', valueKind: 'array', description: 'Step definitions.' },
|
|
2784
|
+
{ path: 'steps[]', category: 'steps', valueKind: 'object', description: 'Step definition.' },
|
|
2785
|
+
{ path: 'steps[].id', category: 'steps', valueKind: 'string', description: 'Step id.' },
|
|
2786
|
+
{ path: 'steps[].label', category: 'steps', valueKind: 'string', description: 'Step label.' },
|
|
2787
|
+
{ path: 'steps[].description', category: 'steps', valueKind: 'string', description: 'Step description.' },
|
|
2788
|
+
{ path: 'steps[].optional', category: 'steps', valueKind: 'boolean', description: 'Mark step as optional.' },
|
|
2789
|
+
{ path: 'steps[].editable', category: 'steps', valueKind: 'boolean', description: 'Allow editing completed steps.' },
|
|
2790
|
+
{ path: 'steps[].completed', category: 'steps', valueKind: 'boolean', description: 'Force completed state.' },
|
|
2791
|
+
{ path: 'steps[].hasError', category: 'steps', valueKind: 'boolean', description: 'Force error state.' },
|
|
2792
|
+
{ path: 'steps[].stateIcon', category: 'steps', valueKind: 'string', description: 'Custom state icon key.' },
|
|
2793
|
+
{ path: 'steps[].state', category: 'steps', valueKind: 'string', description: 'Custom state name for matStepperIcon.' },
|
|
2794
|
+
{ path: 'steps[].errorMessage', category: 'steps', valueKind: 'string', description: 'Error message shown in header.' },
|
|
2795
|
+
{ path: 'steps[].ariaLabel', category: 'accessibility', valueKind: 'string', description: 'ARIA label for step header.' },
|
|
2796
|
+
{ path: 'steps[].ariaLabelledby', category: 'accessibility', valueKind: 'string', description: 'ARIA labelledby for step header.' },
|
|
2797
|
+
{ path: 'steps[].form', category: 'steps', valueKind: 'object', description: 'Optional Dynamic Form config for step.' },
|
|
2798
|
+
{ path: 'steps[].form.resourcePath', category: 'steps', valueKind: 'string', description: 'Resource path for Dynamic Form.' },
|
|
2799
|
+
{ path: 'steps[].form.resourceId', category: 'steps', valueKind: 'string', description: 'Resource id for Dynamic Form (string or number).', example: '123', safetyNotes: 'Accepts string or number.' },
|
|
2800
|
+
{ path: 'steps[].form.mode', category: 'steps', valueKind: 'enum', allowedValues: ENUMS.formMode, description: 'Form mode.' },
|
|
2801
|
+
{ path: 'steps[].form.config', category: 'steps', valueKind: 'object', description: 'FormConfig for Dynamic Form.', safetyNotes: 'Use the form catalog for nested paths and FieldMetadata details.' },
|
|
2802
|
+
{ path: 'steps[].form.schemaSource', category: 'steps', valueKind: 'enum', allowedValues: ENUMS.schemaSource, description: 'Schema source for Dynamic Form.' },
|
|
2803
|
+
{ path: 'steps[].form.formId', category: 'steps', valueKind: 'string', description: 'Form id for Dynamic Form.' },
|
|
2804
|
+
{ path: 'steps[].widgets', category: 'steps', valueKind: 'array', description: 'WidgetDefinition list for step content.' },
|
|
2805
|
+
{ path: 'steps[].widgets[]', category: 'steps', valueKind: 'object', description: 'WidgetDefinition item.' },
|
|
2806
|
+
{ path: 'steps[].widgets[].id', category: 'steps', valueKind: 'enum', allowedValues: ENUMS.widgetId, description: 'Component registry id for widget.', safetyNotes: 'Use ids registered in ComponentMetadataRegistry.' },
|
|
2807
|
+
{ path: 'steps[].widgets[].inputs', category: 'steps', valueKind: 'object', description: 'Inputs bound into the widget instance.' },
|
|
2808
|
+
{ path: 'steps[].widgets[].outputs', category: 'steps', valueKind: 'object', description: 'Outputs mapped to actions.' },
|
|
2809
|
+
{ path: 'steps[].widgets[].outputs.[outputName]', category: 'steps', valueKind: 'object', description: 'Output action mapping (ActionDefinition or "emit").', safetyNotes: 'Use string "emit" to forward the output without mapping.' },
|
|
2810
|
+
{ path: 'steps[].widgets[].bindingOrder', category: 'steps', valueKind: 'array', description: 'Explicit input binding order.' },
|
|
2811
|
+
{ path: 'steps[].widgets[].bindingOrder[]', category: 'steps', valueKind: 'string', description: 'Input name applied first.' },
|
|
2812
|
+
];
|
|
2813
|
+
const STEPPER_AI_CAPABILITIES = {
|
|
2814
|
+
version: 'v1.2',
|
|
2815
|
+
enums: ENUMS,
|
|
2816
|
+
targets: [
|
|
2817
|
+
'praxis-stepper',
|
|
2818
|
+
'mat-stepper',
|
|
2819
|
+
'stepper',
|
|
2820
|
+
'praxis-stepper-config-editor',
|
|
2821
|
+
'praxis-select-quick-config-dialog',
|
|
2822
|
+
],
|
|
2823
|
+
notes: [
|
|
2824
|
+
'steps[] should be merged by id or label to avoid replacing all steps.',
|
|
2825
|
+
'steps[].form.config uses FormConfig (see form catalog) and may include sections/actions/fieldMetadata.',
|
|
2826
|
+
'steps[].widgets[].id must be a ComponentMetadataRegistry id (see component-registry catalog).',
|
|
2827
|
+
'appearance.tokens is a free-form map; host may validate/sanitize.',
|
|
2828
|
+
'When editing steps[].form.config.fieldMetadata, use FieldMetadata base if no controlType catalog exists.',
|
|
2829
|
+
],
|
|
2830
|
+
capabilities: CAPS,
|
|
2831
|
+
};
|
|
2832
|
+
|
|
2833
|
+
class StepperAiAdapter extends BaseAiAdapter {
|
|
2834
|
+
stepper;
|
|
2835
|
+
componentName = 'Praxis Stepper';
|
|
2836
|
+
constructor(stepper) {
|
|
2837
|
+
super();
|
|
2838
|
+
this.stepper = stepper;
|
|
2839
|
+
}
|
|
2840
|
+
getCurrentConfig() {
|
|
2841
|
+
const current = this.stepper._config?.() ?? { steps: [] };
|
|
2842
|
+
return this.cloneConfig(current);
|
|
2843
|
+
}
|
|
2844
|
+
getCapabilities() {
|
|
2845
|
+
return STEPPER_AI_CAPABILITIES.capabilities;
|
|
2846
|
+
}
|
|
2847
|
+
getRuntimeState() {
|
|
2848
|
+
const cfg = this.stepper._config?.();
|
|
2849
|
+
const steps = cfg?.steps || [];
|
|
2850
|
+
return {
|
|
2851
|
+
stepsCount: steps.length,
|
|
2852
|
+
selectedIndex: this.stepper.selectedIndexComputed?.() ?? 0,
|
|
2853
|
+
linear: !!cfg?.linear,
|
|
2854
|
+
orientation: cfg?.orientation || 'horizontal',
|
|
2855
|
+
hasForms: steps.some((s) => !!s.form),
|
|
2856
|
+
};
|
|
2857
|
+
}
|
|
2858
|
+
createSnapshot() {
|
|
2859
|
+
return this.getCurrentConfig();
|
|
2860
|
+
}
|
|
2861
|
+
async restoreSnapshot(snapshot) {
|
|
2862
|
+
if (!snapshot)
|
|
2863
|
+
return;
|
|
2864
|
+
this.applyConfig(this.cloneConfig(snapshot));
|
|
2865
|
+
}
|
|
2866
|
+
async applyPatch(patch) {
|
|
2867
|
+
try {
|
|
2868
|
+
const current = this.getCurrentConfig();
|
|
2869
|
+
const next = this.smartMergeStepperConfig(current, patch);
|
|
2870
|
+
this.applyConfig(next);
|
|
2871
|
+
return { success: true };
|
|
2872
|
+
}
|
|
2873
|
+
catch (error) {
|
|
2874
|
+
const message = error instanceof Error ? error.message : 'Unknown error applying patch';
|
|
2875
|
+
return { success: false, error: message };
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
applyConfig(config) {
|
|
2879
|
+
const apply = this.stepper.applyConfigFromAdapter;
|
|
2880
|
+
if (typeof apply === 'function') {
|
|
2881
|
+
apply.call(this.stepper, config);
|
|
2882
|
+
return;
|
|
2883
|
+
}
|
|
2884
|
+
this.stepper.config = config;
|
|
2885
|
+
}
|
|
2886
|
+
smartMergeStepperConfig(base, patch) {
|
|
2887
|
+
const result = deepMerge(base, patch);
|
|
2888
|
+
if (patch.steps && Array.isArray(patch.steps)) {
|
|
2889
|
+
const merged = this.mergeByKey(base.steps || [], patch.steps, (s) => s.id || s.label || '');
|
|
2890
|
+
result.steps = merged;
|
|
2891
|
+
}
|
|
2892
|
+
return result;
|
|
2893
|
+
}
|
|
2894
|
+
mergeByKey(baseArr, patchArr, keyFn) {
|
|
2895
|
+
const merged = baseArr.map((orig) => {
|
|
2896
|
+
const key = keyFn(orig);
|
|
2897
|
+
const match = key ? patchArr.find((p) => keyFn(p) === key) : undefined;
|
|
2898
|
+
return match ? deepMerge(orig, match) : orig;
|
|
2899
|
+
});
|
|
2900
|
+
patchArr.forEach((item) => {
|
|
2901
|
+
const key = keyFn(item);
|
|
2902
|
+
if (!key || !baseArr.find((o) => keyFn(o) === key)) {
|
|
2903
|
+
merged.push(item);
|
|
2904
|
+
}
|
|
2905
|
+
});
|
|
2906
|
+
return merged;
|
|
2907
|
+
}
|
|
2908
|
+
cloneConfig(config) {
|
|
2909
|
+
try {
|
|
2910
|
+
return structuredClone(config);
|
|
2911
|
+
}
|
|
2912
|
+
catch {
|
|
2913
|
+
return JSON.parse(JSON.stringify(config));
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
|
|
1429
2918
|
class PraxisStepper {
|
|
1430
2919
|
// Templates projetados
|
|
1431
2920
|
stepLabelTpl;
|
|
@@ -1438,6 +2927,8 @@ class PraxisStepper {
|
|
|
1438
2927
|
primaryCta = { label: 'Configurar Stepper', icon: 'tune', color: 'primary', action: () => this.openEditor() };
|
|
1439
2928
|
secondaryCtas = [{ label: 'Adicionar etapa inicial', icon: 'add', action: () => this.addFirstStep() }];
|
|
1440
2929
|
// API de entrada
|
|
2930
|
+
stepperId;
|
|
2931
|
+
componentInstanceId;
|
|
1441
2932
|
set config(c) {
|
|
1442
2933
|
let next = null;
|
|
1443
2934
|
if (typeof c === 'string') {
|
|
@@ -1454,6 +2945,7 @@ class PraxisStepper {
|
|
|
1454
2945
|
this._config.set(next);
|
|
1455
2946
|
if (next?.selectedIndex != null)
|
|
1456
2947
|
this._selectedIndex.set(next.selectedIndex);
|
|
2948
|
+
this.persistConfig(next);
|
|
1457
2949
|
}
|
|
1458
2950
|
set selectedIndexInput(i) {
|
|
1459
2951
|
if (i != null)
|
|
@@ -1476,9 +2968,22 @@ class PraxisStepper {
|
|
|
1476
2968
|
// Emissões
|
|
1477
2969
|
selectedIndexChange = new EventEmitter();
|
|
1478
2970
|
widgetEvent = new EventEmitter();
|
|
2971
|
+
stepFormReady = new EventEmitter();
|
|
2972
|
+
stepFormValueChange = new EventEmitter();
|
|
1479
2973
|
stepperContext;
|
|
1480
2974
|
settings = inject(SettingsPanelService);
|
|
2975
|
+
storage = inject(ASYNC_CONFIG_STORAGE);
|
|
2976
|
+
componentKeys = inject(ComponentKeyService);
|
|
2977
|
+
logger = inject(LoggerService);
|
|
2978
|
+
route = (() => { try {
|
|
2979
|
+
return inject(ActivatedRoute);
|
|
2980
|
+
}
|
|
2981
|
+
catch {
|
|
2982
|
+
return undefined;
|
|
2983
|
+
} })();
|
|
2984
|
+
warnedMissingId = false;
|
|
1481
2985
|
animationDone = new EventEmitter();
|
|
2986
|
+
aiAdapter = new StepperAiAdapter(this);
|
|
1482
2987
|
// Computed getters
|
|
1483
2988
|
steps = computed(() => this._config()?.steps || [], ...(ngDevMode ? [{ debugName: "steps" }] : []));
|
|
1484
2989
|
orientation = computed(() => this._config()?.orientation || 'horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : []));
|
|
@@ -1500,6 +3005,21 @@ class PraxisStepper {
|
|
|
1500
3005
|
navNextLabel = () => this.nav()?.nextLabel || 'Próximo';
|
|
1501
3006
|
navPrevIcon = () => this.nav()?.prevIcon;
|
|
1502
3007
|
navNextIcon = () => this.nav()?.nextIcon;
|
|
3008
|
+
stepperClassList = () => {
|
|
3009
|
+
const cfg = this._config();
|
|
3010
|
+
return [
|
|
3011
|
+
'praxis-stepper',
|
|
3012
|
+
cfg?.stepperClass,
|
|
3013
|
+
cfg?.headerClass,
|
|
3014
|
+
cfg?.appearance?.themeClass,
|
|
3015
|
+
cfg?.appearance?.preset === 'ft-light' ? 'pdx-stepper-ft-light' : null,
|
|
3016
|
+
].filter(Boolean).join(' ');
|
|
3017
|
+
};
|
|
3018
|
+
contentClassList = () => {
|
|
3019
|
+
const cfg = this._config();
|
|
3020
|
+
return ['pdx-step-content', cfg?.contentClass].filter(Boolean).join(' ');
|
|
3021
|
+
};
|
|
3022
|
+
navActionsClass = () => `pdx-step-actions ${this.navAlignClass()}`;
|
|
1503
3023
|
navAlignClass = () => {
|
|
1504
3024
|
const a = this.nav()?.align || 'end';
|
|
1505
3025
|
switch (a) {
|
|
@@ -1562,9 +3082,19 @@ class PraxisStepper {
|
|
|
1562
3082
|
onFormReady(stepIndex, ev) {
|
|
1563
3083
|
this._formGroups.set(stepIndex, ev.formGroup);
|
|
1564
3084
|
this._formValidity.set(stepIndex, ev.formGroup.valid);
|
|
3085
|
+
this.stepFormReady.emit({
|
|
3086
|
+
stepIndex,
|
|
3087
|
+
stepId: this.steps()[stepIndex]?.id,
|
|
3088
|
+
event: ev,
|
|
3089
|
+
});
|
|
1565
3090
|
}
|
|
1566
3091
|
onFormValueChange(stepIndex, ev) {
|
|
1567
3092
|
this._formValidity.set(stepIndex, ev.isValid);
|
|
3093
|
+
this.stepFormValueChange.emit({
|
|
3094
|
+
stepIndex,
|
|
3095
|
+
stepId: this.steps()[stepIndex]?.id,
|
|
3096
|
+
event: ev,
|
|
3097
|
+
});
|
|
1568
3098
|
}
|
|
1569
3099
|
formGroupFor(i) {
|
|
1570
3100
|
return this._formGroups.get(i);
|
|
@@ -1586,13 +3116,15 @@ class PraxisStepper {
|
|
|
1586
3116
|
}
|
|
1587
3117
|
isStepEmpty(step) {
|
|
1588
3118
|
const hasForm = !!step.form;
|
|
3119
|
+
const hasWidgetsBefore = Array.isArray(step.widgetsBeforeForm) && step.widgetsBeforeForm.length > 0;
|
|
1589
3120
|
const hasWidgets = Array.isArray(step.widgets) && step.widgets.length > 0;
|
|
1590
|
-
return !hasForm && !hasWidgets;
|
|
3121
|
+
return !hasForm && !hasWidgets && !hasWidgetsBefore;
|
|
1591
3122
|
}
|
|
1592
3123
|
openEditor() {
|
|
1593
3124
|
const cfg = this._config() || { steps: [], orientation: 'horizontal', headerPosition: 'top', linear: false };
|
|
3125
|
+
const key = this.storageKey() || this.stepperId || 'default';
|
|
1594
3126
|
const ref = this.settings.open({
|
|
1595
|
-
id:
|
|
3127
|
+
id: `praxis-stepper-editor:${key}`,
|
|
1596
3128
|
title: 'Configurar Stepper',
|
|
1597
3129
|
content: { component: PraxisStepperConfigEditor, inputs: { config: cfg } },
|
|
1598
3130
|
});
|
|
@@ -1605,11 +3137,19 @@ class PraxisStepper {
|
|
|
1605
3137
|
// Clamp selection after changes
|
|
1606
3138
|
const sel = typeof cloned.selectedIndex === 'number' ? cloned.selectedIndex : this._selectedIndex();
|
|
1607
3139
|
this._selectedIndex.set(this.clampIndex(sel));
|
|
3140
|
+
this.persistConfig(cloned);
|
|
1608
3141
|
}
|
|
1609
3142
|
};
|
|
1610
3143
|
ref.applied$.subscribe(apply);
|
|
1611
3144
|
ref.saved$.subscribe(apply);
|
|
1612
3145
|
}
|
|
3146
|
+
applyConfigFromAdapter(next) {
|
|
3147
|
+
const cloned = JSON.parse(JSON.stringify(next));
|
|
3148
|
+
this._config.set(cloned);
|
|
3149
|
+
const sel = typeof cloned.selectedIndex === 'number' ? cloned.selectedIndex : this._selectedIndex();
|
|
3150
|
+
this._selectedIndex.set(this.clampIndex(sel));
|
|
3151
|
+
this.persistConfig(cloned);
|
|
3152
|
+
}
|
|
1613
3153
|
// CTA helpers
|
|
1614
3154
|
addFirstStep() {
|
|
1615
3155
|
const current = this._config() || { steps: [], orientation: 'horizontal', headerPosition: 'top', linear: false };
|
|
@@ -1624,11 +3164,17 @@ class PraxisStepper {
|
|
|
1624
3164
|
this._config.set(next);
|
|
1625
3165
|
// Seleciona a primeira etapa
|
|
1626
3166
|
this._selectedIndex.set(0);
|
|
3167
|
+
this.persistConfig(next);
|
|
1627
3168
|
}
|
|
1628
3169
|
// Navegação com validação remota opcional
|
|
1629
3170
|
async onNext(i) {
|
|
1630
3171
|
// Em modo linear, bloquear quando inválido
|
|
1631
3172
|
if (this.linear() && this._formValidity.get(i) === false) {
|
|
3173
|
+
const fg = this._formGroups.get(i);
|
|
3174
|
+
if (fg) {
|
|
3175
|
+
fg.markAllAsTouched();
|
|
3176
|
+
fg.updateValueAndValidity({ emitEvent: true });
|
|
3177
|
+
}
|
|
1632
3178
|
return;
|
|
1633
3179
|
}
|
|
1634
3180
|
const step = this.steps()[i];
|
|
@@ -1667,8 +3213,63 @@ class PraxisStepper {
|
|
|
1667
3213
|
}
|
|
1668
3214
|
fg.updateValueAndValidity({ emitEvent: true });
|
|
1669
3215
|
}
|
|
3216
|
+
persistConfig(config) {
|
|
3217
|
+
const key = this.storageKey();
|
|
3218
|
+
if (!key || !config)
|
|
3219
|
+
return;
|
|
3220
|
+
this.storage.saveConfig(key, config).pipe(take(1)).subscribe({ error: () => { } });
|
|
3221
|
+
}
|
|
3222
|
+
storageKey() {
|
|
3223
|
+
const id = this.componentKeyId();
|
|
3224
|
+
return id ? `stepper-config:${id}` : null;
|
|
3225
|
+
}
|
|
3226
|
+
componentKeyId() {
|
|
3227
|
+
const key = this.componentKeys.buildComponentId({
|
|
3228
|
+
componentType: 'praxis-stepper',
|
|
3229
|
+
componentId: this.stepperId,
|
|
3230
|
+
instanceKey: this.componentInstanceId,
|
|
3231
|
+
componentRef: this,
|
|
3232
|
+
route: this.route,
|
|
3233
|
+
requireComponentId: true,
|
|
3234
|
+
});
|
|
3235
|
+
if (!key)
|
|
3236
|
+
this.warnMissingId();
|
|
3237
|
+
return key;
|
|
3238
|
+
}
|
|
3239
|
+
warnMissingId() {
|
|
3240
|
+
if (this.warnedMissingId)
|
|
3241
|
+
return;
|
|
3242
|
+
this.warnedMissingId = true;
|
|
3243
|
+
this.logger.warnOnce('[PraxisStepper] stepperId is required for config persistence.', {
|
|
3244
|
+
context: {
|
|
3245
|
+
lib: 'praxis-stepper',
|
|
3246
|
+
component: 'PraxisStepper',
|
|
3247
|
+
},
|
|
3248
|
+
data: {
|
|
3249
|
+
stepperId: this.stepperId,
|
|
3250
|
+
componentInstanceId: this.componentInstanceId,
|
|
3251
|
+
},
|
|
3252
|
+
dedupeKey: 'praxis-stepper:missing-stepper-id',
|
|
3253
|
+
});
|
|
3254
|
+
}
|
|
3255
|
+
ngOnInit() {
|
|
3256
|
+
const key = this.storageKey();
|
|
3257
|
+
if (!key)
|
|
3258
|
+
return;
|
|
3259
|
+
this.storage.loadConfig(key).pipe(take(1)).subscribe((stored) => {
|
|
3260
|
+
if (!stored)
|
|
3261
|
+
return;
|
|
3262
|
+
const cloned = JSON.parse(JSON.stringify(stored));
|
|
3263
|
+
this._config.set(cloned);
|
|
3264
|
+
const sel = typeof cloned.selectedIndex === 'number' ? cloned.selectedIndex : this._selectedIndex();
|
|
3265
|
+
this._selectedIndex.set(this.clampIndex(sel));
|
|
3266
|
+
});
|
|
3267
|
+
}
|
|
1670
3268
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisStepper, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1671
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: PraxisStepper, isStandalone: true, selector: "praxis-stepper", inputs: { config: "config", selectedIndexInput: "selectedIndexInput", selectedIndex: "selectedIndex", disableRippleInput: "disableRippleInput", editModeEnabled: "editModeEnabled", labelPosition: "labelPosition", color: "color", serverValidate: "serverValidate", stepperContext: "stepperContext" }, outputs: { selectedIndexChange: "selectedIndexChange", widgetEvent: "widgetEvent", animationDone: "animationDone", selectionChange: "selectionChange" }, queries: [{ propertyName: "stepLabelTpl", first: true, predicate: ["stepLabelTpl"], descendants: true, read: TemplateRef }], ngImport: i0, template: `
|
|
3269
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: PraxisStepper, isStandalone: true, selector: "praxis-stepper", inputs: { stepperId: "stepperId", componentInstanceId: "componentInstanceId", config: "config", selectedIndexInput: "selectedIndexInput", selectedIndex: "selectedIndex", disableRippleInput: "disableRippleInput", editModeEnabled: "editModeEnabled", labelPosition: "labelPosition", color: "color", serverValidate: "serverValidate", stepperContext: "stepperContext" }, outputs: { selectedIndexChange: "selectedIndexChange", widgetEvent: "widgetEvent", stepFormReady: "stepFormReady", stepFormValueChange: "stepFormValueChange", animationDone: "animationDone", selectionChange: "selectionChange" }, host: { properties: { "class": "densityClass()" } }, queries: [{ propertyName: "stepLabelTpl", first: true, predicate: ["stepLabelTpl"], descendants: true, read: TemplateRef }], ngImport: i0, template: `
|
|
3270
|
+
<div class="stepper-ai-assistant" *ngIf="editModeEnabled">
|
|
3271
|
+
<praxis-ai-assistant [adapter]="aiAdapter"></praxis-ai-assistant>
|
|
3272
|
+
</div>
|
|
1672
3273
|
<ng-container *ngIf="steps().length > 0; else emptyState">
|
|
1673
3274
|
<mat-stepper
|
|
1674
3275
|
[linear]="linear()"
|
|
@@ -1681,8 +3282,7 @@ class PraxisStepper {
|
|
|
1681
3282
|
[selectedIndex]="selectedIndexComputed()"
|
|
1682
3283
|
(selectionChange)="onSelectionChange($event)"
|
|
1683
3284
|
(animationDone)="onAnimationDone()"
|
|
1684
|
-
class="
|
|
1685
|
-
[ngClass]="[densityClass(), _config()?.stepperClass || '']"
|
|
3285
|
+
[class]="stepperClassList()"
|
|
1686
3286
|
>
|
|
1687
3287
|
<!-- Projeção de ícones customizados do header: <ng-template matStepperIcon="done"> ... </ng-template> -->
|
|
1688
3288
|
<ng-content></ng-content>
|
|
@@ -1719,7 +3319,13 @@ class PraxisStepper {
|
|
|
1719
3319
|
></ng-container>
|
|
1720
3320
|
<ng-template #plainLabel>{{ step.label }}</ng-template>
|
|
1721
3321
|
</ng-template>
|
|
1722
|
-
<div class
|
|
3322
|
+
<div [class]="contentClassList()">
|
|
3323
|
+
<ng-container *ngFor="let wd of step.widgetsBeforeForm || []"
|
|
3324
|
+
[dynamicWidgetLoader]="wd"
|
|
3325
|
+
[context]="stepperContext"
|
|
3326
|
+
[strictValidation]="true"
|
|
3327
|
+
[autoWireOutputs]="true"
|
|
3328
|
+
(widgetEvent)="onChildWidgetEvent(i, wd, $event)"></ng-container>
|
|
1723
3329
|
<praxis-dynamic-form *ngIf="step.form as f"
|
|
1724
3330
|
[resourcePath]="f.resourcePath"
|
|
1725
3331
|
[resourceId]="$any(f.resourceId)"
|
|
@@ -1746,7 +3352,7 @@ class PraxisStepper {
|
|
|
1746
3352
|
></praxis-empty-state-card>
|
|
1747
3353
|
</ng-container>
|
|
1748
3354
|
</div>
|
|
1749
|
-
<div
|
|
3355
|
+
<div *ngIf="navVisible()" [class]="navActionsClass()">
|
|
1750
3356
|
<!-- PREV button (hidden on first step) -->
|
|
1751
3357
|
<ng-container *ngIf="selectedIndexComputed() > 0">
|
|
1752
3358
|
<ng-container [ngSwitch]="navVariant()">
|
|
@@ -1811,11 +3417,16 @@ class PraxisStepper {
|
|
|
1811
3417
|
>
|
|
1812
3418
|
<mat-icon fontIcon="edit"></mat-icon>
|
|
1813
3419
|
</button>
|
|
1814
|
-
`, isInline: true, styles: [":host{display:block;position:relative}.praxis-stepper{width:100
|
|
3420
|
+
`, isInline: true, styles: [":host{display:block;position:relative}.praxis-stepper{width:100%;background:var(--md-sys-color-surface);border:1px solid var(--md-sys-color-outline-variant);border-radius:16px;padding:12px;box-shadow:var(--mat-elevation-level1)}.praxis-stepper.pdx-stepper-ft-light{background:transparent;border:none;border-radius:0;padding:0;box-shadow:none}:host(.density-compact) ::ng-deep .mat-step-header{min-height:36px}:host(.density-compact) .pdx-step-actions{padding-top:4px;gap:6px}:host(.density-comfortable) ::ng-deep .mat-step-header{min-height:44px}.pdx-step-content{padding:12px 4px 8px;color:var(--md-sys-color-on-surface)}.pdx-step-actions{display:flex;gap:8px;padding-top:8px}::ng-deep .praxis-stepper .mat-step-header{border-radius:999px;margin:4px 0;color:var(--md-sys-color-on-surface)}::ng-deep .praxis-stepper .mat-step-label{color:var(--md-sys-color-on-surface)}::ng-deep .praxis-stepper .mat-step-label.mat-step-label-selected{color:var(--md-sys-color-on-surface);font-weight:600}::ng-deep .praxis-stepper .mat-step-header:hover{background:var(--md-sys-color-primary-container)}::ng-deep .praxis-stepper .mat-step-header.cdk-keyboard-focused,::ng-deep .praxis-stepper .mat-step-header.cdk-program-focused{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}::ng-deep .praxis-stepper .mat-step-icon{background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface)}::ng-deep .praxis-stepper .mat-step-icon-selected{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}::ng-deep .praxis-stepper .mat-step-icon-state-done{background:var(--md-sys-color-tertiary);color:var(--md-sys-color-on-tertiary)}::ng-deep .praxis-stepper .mat-step-icon-state-error{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}::ng-deep .praxis-stepper .mat-stepper-horizontal-line{border-top-color:var(--md-sys-color-outline-variant)}::ng-deep .praxis-stepper .mat-stepper-vertical-line:before{border-left-color:var(--md-sys-color-outline-variant)}::ng-deep .pdx-stepper-ft-light .mat-stepper-horizontal{background:transparent}::ng-deep .pdx-stepper-ft-light .mat-horizontal-stepper-header-container{margin-bottom:14px;justify-content:flex-start;align-items:center}::ng-deep .pdx-stepper-ft-light .mat-step-header{min-height:28px;font-size:.75rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}::ng-deep .pdx-stepper-ft-light .mat-step-label.mat-step-label-active,::ng-deep .pdx-stepper-ft-light .mat-step-label.mat-step-label-selected{color:var(--md-sys-color-on-surface);font-weight:600}::ng-deep .pdx-stepper-ft-light .mat-step-icon{height:16px;width:16px;font-size:9px;background:transparent;border:1px solid var(--md-sys-color-outline-variant);color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}::ng-deep .pdx-stepper-ft-light .mat-step-icon .mat-icon{display:none}::ng-deep .pdx-stepper-ft-light .mat-step-icon-content{font-weight:600;font-size:9px;line-height:1}::ng-deep .pdx-stepper-ft-light .mat-step-icon-state-done,::ng-deep .pdx-stepper-ft-light .mat-step-icon-selected{background:var(--praxis-wizard-accent, var(--md-sys-color-primary, currentColor));border-color:var(--praxis-wizard-accent, var(--md-sys-color-primary, currentColor));color:var(--praxis-wizard-accent-on, var(--md-sys-color-on-primary, #ffffff))}::ng-deep .pdx-stepper-ft-light .mat-stepper-horizontal-line{border-top-color:var(--md-sys-color-outline-variant);border-top-width:1px;margin:0 8px;flex:1 1 0}::ng-deep .pdx-stepper-ft-light .mat-step-header{padding:0 6px;flex:0 0 auto}::ng-deep .pdx-stepper-ft-light .mat-step-header.cdk-keyboard-focused,::ng-deep .pdx-stepper-ft-light .mat-step-header.cdk-program-focused,::ng-deep .pdx-stepper-ft-light .mat-step-header.cdk-focused,::ng-deep .pdx-stepper-ft-light .mat-step-header.cdk-mouse-focused{outline:none;box-shadow:none;background:transparent}::ng-deep .pdx-stepper-ft-light .mat-step-header:hover{background:transparent}::ng-deep .ft-stepper{background:transparent}::ng-deep .ft-stepper .mat-horizontal-stepper-header-container{margin-bottom:16px}::ng-deep .ft-stepper .mat-step-header{font-size:.8rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}::ng-deep .ft-stepper .mat-step-label.mat-step-label-active,::ng-deep .ft-stepper .mat-step-label.mat-step-label-selected{color:var(--md-sys-color-on-surface);font-weight:600}::ng-deep .ft-stepper .mat-step-icon{height:22px;width:22px;font-size:11px;background:var(--praxis-wizard-card-bg, var(--md-sys-color-surface));border:2px solid var(--md-sys-color-outline-variant);color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}::ng-deep .ft-stepper .mat-step-icon-state-done,::ng-deep .ft-stepper .mat-step-icon-selected{background:var(--praxis-wizard-accent, var(--md-sys-color-primary, currentColor));border-color:var(--praxis-wizard-accent, var(--md-sys-color-primary, currentColor));color:var(--praxis-wizard-accent-on, var(--md-sys-color-on-primary, #ffffff))}::ng-deep .ft-stepper .mat-stepper-horizontal-line{border-top-color:var(--md-sys-color-outline-variant)}.ft-stepper-content{padding:0}.ft-stepper-content .form-section{border:none;padding:0;background:transparent}.nav-align-start{justify-content:flex-start}.nav-align-center{justify-content:center}.nav-align-end{justify-content:flex-end}.nav-align-space-between{justify-content:space-between}.edit-fab{position:absolute;right:12px;bottom:12px;z-index:2}.stepper-ai-assistant{position:absolute;right:12px;bottom:72px;z-index:3}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1$1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: MatStepperModule }, { kind: "component", type: i2$1.MatStep, selector: "mat-step", inputs: ["color"], exportAs: ["matStep"] }, { kind: "directive", type: i2$1.MatStepLabel, selector: "[matStepLabel]" }, { kind: "component", type: i2$1.MatStepper, selector: "mat-stepper, mat-vertical-stepper, mat-horizontal-stepper, [matStepper]", inputs: ["disableRipple", "color", "labelPosition", "headerPosition", "animationDuration"], outputs: ["animationDone"], exportAs: ["matStepper", "matVerticalStepper", "matHorizontalStepper"] }, { kind: "directive", type: i2$1.MatStepperIcon, selector: "ng-template[matStepperIcon]", inputs: ["matStepperIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: PraxisDynamicForm, selector: "praxis-dynamic-form", inputs: ["resourcePath", "resourceId", "mode", "config", "schemaSource", "editModeEnabled", "formId", "componentInstanceId", "layout", "backConfig", "hooks", "removeEmptyContainersOnSave", "reactiveValidation", "reactiveValidationDebounceMs", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "readonlyModeGlobal", "disabledModeGlobal", "presentationModeGlobal", "visibleGlobal", "customEndpoints"], outputs: ["formSubmit", "formCancel", "formReset", "configChange", "formReady", "valueChange", "syncCompleted", "initializationError", "loadingStateChange", "editModeEnabledChange", "customAction", "actionConfirmation", "schemaStatusChange", "fieldRenderError"] }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent"], exportAs: ["dynamicWidgetLoader"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }, { kind: "component", type: PraxisAiAssistantComponent, selector: "praxis-ai-assistant", inputs: ["adapter", "riskPolicy", "allowManualPatchEdit"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1815
3421
|
}
|
|
1816
3422
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisStepper, decorators: [{
|
|
1817
3423
|
type: Component,
|
|
1818
|
-
args: [{ selector: 'praxis-stepper', standalone: true, imports: [CommonModule, ReactiveFormsModule, MatStepperModule, MatButtonModule, MatIconModule, PraxisIconDirective, PraxisDynamicForm, DynamicWidgetLoaderDirective, EmptyStateCardComponent],
|
|
3424
|
+
args: [{ selector: 'praxis-stepper', standalone: true, imports: [CommonModule, ReactiveFormsModule, MatStepperModule, MatButtonModule, MatIconModule, PraxisIconDirective, PraxisDynamicForm, DynamicWidgetLoaderDirective, EmptyStateCardComponent, PraxisAiAssistantComponent], host: {
|
|
3425
|
+
'[class]': 'densityClass()'
|
|
3426
|
+
}, template: `
|
|
3427
|
+
<div class="stepper-ai-assistant" *ngIf="editModeEnabled">
|
|
3428
|
+
<praxis-ai-assistant [adapter]="aiAdapter"></praxis-ai-assistant>
|
|
3429
|
+
</div>
|
|
1819
3430
|
<ng-container *ngIf="steps().length > 0; else emptyState">
|
|
1820
3431
|
<mat-stepper
|
|
1821
3432
|
[linear]="linear()"
|
|
@@ -1828,8 +3439,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1828
3439
|
[selectedIndex]="selectedIndexComputed()"
|
|
1829
3440
|
(selectionChange)="onSelectionChange($event)"
|
|
1830
3441
|
(animationDone)="onAnimationDone()"
|
|
1831
|
-
class="
|
|
1832
|
-
[ngClass]="[densityClass(), _config()?.stepperClass || '']"
|
|
3442
|
+
[class]="stepperClassList()"
|
|
1833
3443
|
>
|
|
1834
3444
|
<!-- Projeção de ícones customizados do header: <ng-template matStepperIcon="done"> ... </ng-template> -->
|
|
1835
3445
|
<ng-content></ng-content>
|
|
@@ -1866,7 +3476,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1866
3476
|
></ng-container>
|
|
1867
3477
|
<ng-template #plainLabel>{{ step.label }}</ng-template>
|
|
1868
3478
|
</ng-template>
|
|
1869
|
-
<div class
|
|
3479
|
+
<div [class]="contentClassList()">
|
|
3480
|
+
<ng-container *ngFor="let wd of step.widgetsBeforeForm || []"
|
|
3481
|
+
[dynamicWidgetLoader]="wd"
|
|
3482
|
+
[context]="stepperContext"
|
|
3483
|
+
[strictValidation]="true"
|
|
3484
|
+
[autoWireOutputs]="true"
|
|
3485
|
+
(widgetEvent)="onChildWidgetEvent(i, wd, $event)"></ng-container>
|
|
1870
3486
|
<praxis-dynamic-form *ngIf="step.form as f"
|
|
1871
3487
|
[resourcePath]="f.resourcePath"
|
|
1872
3488
|
[resourceId]="$any(f.resourceId)"
|
|
@@ -1893,7 +3509,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1893
3509
|
></praxis-empty-state-card>
|
|
1894
3510
|
</ng-container>
|
|
1895
3511
|
</div>
|
|
1896
|
-
<div
|
|
3512
|
+
<div *ngIf="navVisible()" [class]="navActionsClass()">
|
|
1897
3513
|
<!-- PREV button (hidden on first step) -->
|
|
1898
3514
|
<ng-container *ngIf="selectedIndexComputed() > 0">
|
|
1899
3515
|
<ng-container [ngSwitch]="navVariant()">
|
|
@@ -1958,10 +3574,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1958
3574
|
>
|
|
1959
3575
|
<mat-icon fontIcon="edit"></mat-icon>
|
|
1960
3576
|
</button>
|
|
1961
|
-
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;position:relative}.praxis-stepper{width:100
|
|
3577
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;position:relative}.praxis-stepper{width:100%;background:var(--md-sys-color-surface);border:1px solid var(--md-sys-color-outline-variant);border-radius:16px;padding:12px;box-shadow:var(--mat-elevation-level1)}.praxis-stepper.pdx-stepper-ft-light{background:transparent;border:none;border-radius:0;padding:0;box-shadow:none}:host(.density-compact) ::ng-deep .mat-step-header{min-height:36px}:host(.density-compact) .pdx-step-actions{padding-top:4px;gap:6px}:host(.density-comfortable) ::ng-deep .mat-step-header{min-height:44px}.pdx-step-content{padding:12px 4px 8px;color:var(--md-sys-color-on-surface)}.pdx-step-actions{display:flex;gap:8px;padding-top:8px}::ng-deep .praxis-stepper .mat-step-header{border-radius:999px;margin:4px 0;color:var(--md-sys-color-on-surface)}::ng-deep .praxis-stepper .mat-step-label{color:var(--md-sys-color-on-surface)}::ng-deep .praxis-stepper .mat-step-label.mat-step-label-selected{color:var(--md-sys-color-on-surface);font-weight:600}::ng-deep .praxis-stepper .mat-step-header:hover{background:var(--md-sys-color-primary-container)}::ng-deep .praxis-stepper .mat-step-header.cdk-keyboard-focused,::ng-deep .praxis-stepper .mat-step-header.cdk-program-focused{outline:2px solid var(--md-sys-color-primary);outline-offset:2px}::ng-deep .praxis-stepper .mat-step-icon{background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface)}::ng-deep .praxis-stepper .mat-step-icon-selected{background:var(--md-sys-color-primary);color:var(--md-sys-color-on-primary)}::ng-deep .praxis-stepper .mat-step-icon-state-done{background:var(--md-sys-color-tertiary);color:var(--md-sys-color-on-tertiary)}::ng-deep .praxis-stepper .mat-step-icon-state-error{background:var(--md-sys-color-error);color:var(--md-sys-color-on-error)}::ng-deep .praxis-stepper .mat-stepper-horizontal-line{border-top-color:var(--md-sys-color-outline-variant)}::ng-deep .praxis-stepper .mat-stepper-vertical-line:before{border-left-color:var(--md-sys-color-outline-variant)}::ng-deep .pdx-stepper-ft-light .mat-stepper-horizontal{background:transparent}::ng-deep .pdx-stepper-ft-light .mat-horizontal-stepper-header-container{margin-bottom:14px;justify-content:flex-start;align-items:center}::ng-deep .pdx-stepper-ft-light .mat-step-header{min-height:28px;font-size:.75rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}::ng-deep .pdx-stepper-ft-light .mat-step-label.mat-step-label-active,::ng-deep .pdx-stepper-ft-light .mat-step-label.mat-step-label-selected{color:var(--md-sys-color-on-surface);font-weight:600}::ng-deep .pdx-stepper-ft-light .mat-step-icon{height:16px;width:16px;font-size:9px;background:transparent;border:1px solid var(--md-sys-color-outline-variant);color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}::ng-deep .pdx-stepper-ft-light .mat-step-icon .mat-icon{display:none}::ng-deep .pdx-stepper-ft-light .mat-step-icon-content{font-weight:600;font-size:9px;line-height:1}::ng-deep .pdx-stepper-ft-light .mat-step-icon-state-done,::ng-deep .pdx-stepper-ft-light .mat-step-icon-selected{background:var(--praxis-wizard-accent, var(--md-sys-color-primary, currentColor));border-color:var(--praxis-wizard-accent, var(--md-sys-color-primary, currentColor));color:var(--praxis-wizard-accent-on, var(--md-sys-color-on-primary, #ffffff))}::ng-deep .pdx-stepper-ft-light .mat-stepper-horizontal-line{border-top-color:var(--md-sys-color-outline-variant);border-top-width:1px;margin:0 8px;flex:1 1 0}::ng-deep .pdx-stepper-ft-light .mat-step-header{padding:0 6px;flex:0 0 auto}::ng-deep .pdx-stepper-ft-light .mat-step-header.cdk-keyboard-focused,::ng-deep .pdx-stepper-ft-light .mat-step-header.cdk-program-focused,::ng-deep .pdx-stepper-ft-light .mat-step-header.cdk-focused,::ng-deep .pdx-stepper-ft-light .mat-step-header.cdk-mouse-focused{outline:none;box-shadow:none;background:transparent}::ng-deep .pdx-stepper-ft-light .mat-step-header:hover{background:transparent}::ng-deep .ft-stepper{background:transparent}::ng-deep .ft-stepper .mat-horizontal-stepper-header-container{margin-bottom:16px}::ng-deep .ft-stepper .mat-step-header{font-size:.8rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}::ng-deep .ft-stepper .mat-step-label.mat-step-label-active,::ng-deep .ft-stepper .mat-step-label.mat-step-label-selected{color:var(--md-sys-color-on-surface);font-weight:600}::ng-deep .ft-stepper .mat-step-icon{height:22px;width:22px;font-size:11px;background:var(--praxis-wizard-card-bg, var(--md-sys-color-surface));border:2px solid var(--md-sys-color-outline-variant);color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}::ng-deep .ft-stepper .mat-step-icon-state-done,::ng-deep .ft-stepper .mat-step-icon-selected{background:var(--praxis-wizard-accent, var(--md-sys-color-primary, currentColor));border-color:var(--praxis-wizard-accent, var(--md-sys-color-primary, currentColor));color:var(--praxis-wizard-accent-on, var(--md-sys-color-on-primary, #ffffff))}::ng-deep .ft-stepper .mat-stepper-horizontal-line{border-top-color:var(--md-sys-color-outline-variant)}.ft-stepper-content{padding:0}.ft-stepper-content .form-section{border:none;padding:0;background:transparent}.nav-align-start{justify-content:flex-start}.nav-align-center{justify-content:center}.nav-align-end{justify-content:flex-end}.nav-align-space-between{justify-content:space-between}.edit-fab{position:absolute;right:12px;bottom:12px;z-index:2}.stepper-ai-assistant{position:absolute;right:12px;bottom:72px;z-index:3}\n"] }]
|
|
1962
3578
|
}], propDecorators: { stepLabelTpl: [{
|
|
1963
3579
|
type: ContentChild,
|
|
1964
3580
|
args: ['stepLabelTpl', { read: TemplateRef }]
|
|
3581
|
+
}], stepperId: [{
|
|
3582
|
+
type: Input,
|
|
3583
|
+
args: [{ required: true }]
|
|
3584
|
+
}], componentInstanceId: [{
|
|
3585
|
+
type: Input
|
|
1965
3586
|
}], config: [{
|
|
1966
3587
|
type: Input
|
|
1967
3588
|
}], selectedIndexInput: [{
|
|
@@ -1982,6 +3603,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1982
3603
|
type: Output
|
|
1983
3604
|
}], widgetEvent: [{
|
|
1984
3605
|
type: Output
|
|
3606
|
+
}], stepFormReady: [{
|
|
3607
|
+
type: Output
|
|
3608
|
+
}], stepFormValueChange: [{
|
|
3609
|
+
type: Output
|
|
1985
3610
|
}], stepperContext: [{
|
|
1986
3611
|
type: Input
|
|
1987
3612
|
}], animationDone: [{
|
|
@@ -1990,6 +3615,178 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
1990
3615
|
type: Output
|
|
1991
3616
|
}] } });
|
|
1992
3617
|
|
|
3618
|
+
class PraxisWizardBenefitsGridComponent {
|
|
3619
|
+
blockId;
|
|
3620
|
+
title;
|
|
3621
|
+
items = [];
|
|
3622
|
+
columns;
|
|
3623
|
+
boxed = true;
|
|
3624
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisWizardBenefitsGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3625
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: PraxisWizardBenefitsGridComponent, isStandalone: true, selector: "praxis-wizard-benefits-grid", inputs: { blockId: "blockId", title: "title", items: "items", columns: "columns", boxed: "boxed" }, host: { properties: { "attr.data-block-id": "blockId || null" } }, ngImport: i0, template: `
|
|
3626
|
+
<section class="pwx-benefits">
|
|
3627
|
+
@if (title) {
|
|
3628
|
+
<h3 class="pwx-benefits-title">{{ title }}</h3>
|
|
3629
|
+
}
|
|
3630
|
+
<div class="pwx-benefits-grid" [class.is-boxed]="boxed" [style.--pwx-columns]="columns || 4">
|
|
3631
|
+
<div class="pwx-benefit" *ngFor="let item of items">
|
|
3632
|
+
<div class="pwx-benefit-icon" *ngIf="item.icon">
|
|
3633
|
+
<mat-icon [fontIcon]="item.icon"></mat-icon>
|
|
3634
|
+
</div>
|
|
3635
|
+
<div class="pwx-benefit-body">
|
|
3636
|
+
<div class="pwx-benefit-title">{{ item.title }}</div>
|
|
3637
|
+
<div class="pwx-benefit-text" *ngIf="item.text">{{ item.text }}</div>
|
|
3638
|
+
</div>
|
|
3639
|
+
</div>
|
|
3640
|
+
</div>
|
|
3641
|
+
</section>
|
|
3642
|
+
`, isInline: true, styles: [":host{display:block}.pwx-benefits{display:flex;flex-direction:column;gap:10px}.pwx-benefits-title{margin:0;font-size:.9rem;font-weight:600;color:var(--md-sys-color-on-surface);letter-spacing:.02em;display:flex;align-items:center;gap:12px}.pwx-benefits-title:before,.pwx-benefits-title:after{content:\"\";height:1px;flex:1;background:var(--md-sys-color-outline-variant)}.pwx-benefits-grid{display:grid;grid-template-columns:repeat(var(--pwx-columns),minmax(0,1fr));gap:14px 18px}.pwx-benefits-grid.is-boxed{padding:10px 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface)}.pwx-benefit{display:flex;gap:10px;align-items:flex-start}.pwx-benefit-icon{width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center;color:var(--praxis-wizard-accent, var(--md-sys-color-primary))}.pwx-benefit-title{font-weight:600;font-size:.88rem;color:var(--md-sys-color-on-surface)}.pwx-benefit-text{font-size:.82rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant));line-height:1.35}@media(max-width:720px){.pwx-benefits-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:480px){.pwx-benefits-grid{grid-template-columns:1fr}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3643
|
+
}
|
|
3644
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisWizardBenefitsGridComponent, decorators: [{
|
|
3645
|
+
type: Component,
|
|
3646
|
+
args: [{ selector: 'praxis-wizard-benefits-grid', standalone: true, host: {
|
|
3647
|
+
'[attr.data-block-id]': 'blockId || null',
|
|
3648
|
+
}, imports: [CommonModule, MatIconModule], template: `
|
|
3649
|
+
<section class="pwx-benefits">
|
|
3650
|
+
@if (title) {
|
|
3651
|
+
<h3 class="pwx-benefits-title">{{ title }}</h3>
|
|
3652
|
+
}
|
|
3653
|
+
<div class="pwx-benefits-grid" [class.is-boxed]="boxed" [style.--pwx-columns]="columns || 4">
|
|
3654
|
+
<div class="pwx-benefit" *ngFor="let item of items">
|
|
3655
|
+
<div class="pwx-benefit-icon" *ngIf="item.icon">
|
|
3656
|
+
<mat-icon [fontIcon]="item.icon"></mat-icon>
|
|
3657
|
+
</div>
|
|
3658
|
+
<div class="pwx-benefit-body">
|
|
3659
|
+
<div class="pwx-benefit-title">{{ item.title }}</div>
|
|
3660
|
+
<div class="pwx-benefit-text" *ngIf="item.text">{{ item.text }}</div>
|
|
3661
|
+
</div>
|
|
3662
|
+
</div>
|
|
3663
|
+
</div>
|
|
3664
|
+
</section>
|
|
3665
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.pwx-benefits{display:flex;flex-direction:column;gap:10px}.pwx-benefits-title{margin:0;font-size:.9rem;font-weight:600;color:var(--md-sys-color-on-surface);letter-spacing:.02em;display:flex;align-items:center;gap:12px}.pwx-benefits-title:before,.pwx-benefits-title:after{content:\"\";height:1px;flex:1;background:var(--md-sys-color-outline-variant)}.pwx-benefits-grid{display:grid;grid-template-columns:repeat(var(--pwx-columns),minmax(0,1fr));gap:14px 18px}.pwx-benefits-grid.is-boxed{padding:10px 12px;border:1px solid var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface)}.pwx-benefit{display:flex;gap:10px;align-items:flex-start}.pwx-benefit-icon{width:18px;height:18px;display:inline-flex;align-items:center;justify-content:center;color:var(--praxis-wizard-accent, var(--md-sys-color-primary))}.pwx-benefit-title{font-weight:600;font-size:.88rem;color:var(--md-sys-color-on-surface)}.pwx-benefit-text{font-size:.82rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant));line-height:1.35}@media(max-width:720px){.pwx-benefits-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:480px){.pwx-benefits-grid{grid-template-columns:1fr}}\n"] }]
|
|
3666
|
+
}], propDecorators: { blockId: [{
|
|
3667
|
+
type: Input
|
|
3668
|
+
}], title: [{
|
|
3669
|
+
type: Input
|
|
3670
|
+
}], items: [{
|
|
3671
|
+
type: Input
|
|
3672
|
+
}], columns: [{
|
|
3673
|
+
type: Input
|
|
3674
|
+
}], boxed: [{
|
|
3675
|
+
type: Input
|
|
3676
|
+
}] } });
|
|
3677
|
+
|
|
3678
|
+
class PraxisWizardContentBlockComponent {
|
|
3679
|
+
blockId;
|
|
3680
|
+
title;
|
|
3681
|
+
subtitle;
|
|
3682
|
+
text;
|
|
3683
|
+
caption;
|
|
3684
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisWizardContentBlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3685
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: PraxisWizardContentBlockComponent, isStandalone: true, selector: "praxis-wizard-content-block", inputs: { blockId: "blockId", title: "title", subtitle: "subtitle", text: "text", caption: "caption" }, host: { properties: { "attr.data-block-id": "blockId || null" } }, ngImport: i0, template: `
|
|
3686
|
+
<section class="pwx-content">
|
|
3687
|
+
@if (title) {
|
|
3688
|
+
<h3 class="pwx-content-title">{{ title }}</h3>
|
|
3689
|
+
}
|
|
3690
|
+
@if (subtitle) {
|
|
3691
|
+
<div class="pwx-content-subtitle">{{ subtitle }}</div>
|
|
3692
|
+
}
|
|
3693
|
+
@if (text) {
|
|
3694
|
+
<p class="pwx-content-text">{{ text }}</p>
|
|
3695
|
+
}
|
|
3696
|
+
@if (caption) {
|
|
3697
|
+
<div class="pwx-content-caption">{{ caption }}</div>
|
|
3698
|
+
}
|
|
3699
|
+
</section>
|
|
3700
|
+
`, isInline: true, styles: [":host{display:block}.pwx-content{display:flex;flex-direction:column;gap:6px}.pwx-content-title{margin:0;font-size:1.05rem;font-weight:600;color:var(--md-sys-color-on-surface)}.pwx-content-subtitle{font-size:.95rem;color:var(--md-sys-color-on-surface)}.pwx-content-text{margin:0;font-size:.88rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}.pwx-content-caption{font-size:.78rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3701
|
+
}
|
|
3702
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisWizardContentBlockComponent, decorators: [{
|
|
3703
|
+
type: Component,
|
|
3704
|
+
args: [{ selector: 'praxis-wizard-content-block', standalone: true, host: {
|
|
3705
|
+
'[attr.data-block-id]': 'blockId || null',
|
|
3706
|
+
}, imports: [CommonModule], template: `
|
|
3707
|
+
<section class="pwx-content">
|
|
3708
|
+
@if (title) {
|
|
3709
|
+
<h3 class="pwx-content-title">{{ title }}</h3>
|
|
3710
|
+
}
|
|
3711
|
+
@if (subtitle) {
|
|
3712
|
+
<div class="pwx-content-subtitle">{{ subtitle }}</div>
|
|
3713
|
+
}
|
|
3714
|
+
@if (text) {
|
|
3715
|
+
<p class="pwx-content-text">{{ text }}</p>
|
|
3716
|
+
}
|
|
3717
|
+
@if (caption) {
|
|
3718
|
+
<div class="pwx-content-caption">{{ caption }}</div>
|
|
3719
|
+
}
|
|
3720
|
+
</section>
|
|
3721
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.pwx-content{display:flex;flex-direction:column;gap:6px}.pwx-content-title{margin:0;font-size:1.05rem;font-weight:600;color:var(--md-sys-color-on-surface)}.pwx-content-subtitle{font-size:.95rem;color:var(--md-sys-color-on-surface)}.pwx-content-text{margin:0;font-size:.88rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}.pwx-content-caption{font-size:.78rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}\n"] }]
|
|
3722
|
+
}], propDecorators: { blockId: [{
|
|
3723
|
+
type: Input
|
|
3724
|
+
}], title: [{
|
|
3725
|
+
type: Input
|
|
3726
|
+
}], subtitle: [{
|
|
3727
|
+
type: Input
|
|
3728
|
+
}], text: [{
|
|
3729
|
+
type: Input
|
|
3730
|
+
}], caption: [{
|
|
3731
|
+
type: Input
|
|
3732
|
+
}] } });
|
|
3733
|
+
|
|
3734
|
+
class PraxisWizardInlineNoticeComponent {
|
|
3735
|
+
blockId;
|
|
3736
|
+
text = '';
|
|
3737
|
+
tone = 'neutral';
|
|
3738
|
+
get toneClass() {
|
|
3739
|
+
return this.tone !== 'neutral' ? this.tone : '';
|
|
3740
|
+
}
|
|
3741
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisWizardInlineNoticeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3742
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: PraxisWizardInlineNoticeComponent, isStandalone: true, selector: "praxis-wizard-inline-notice", inputs: { blockId: "blockId", text: "text", tone: "tone" }, host: { properties: { "attr.data-block-id": "blockId || null" } }, ngImport: i0, template: `
|
|
3743
|
+
<div class="pwx-inline" [ngClass]="toneClass">
|
|
3744
|
+
{{ text }}
|
|
3745
|
+
</div>
|
|
3746
|
+
`, isInline: true, styles: [":host{display:block}.pwx-inline{font-size:.82rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant));line-height:1.4}.pwx-inline.info{color:var(--md-sys-color-on-surface)}.pwx-inline.warning{color:var(--md-sys-color-error)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3747
|
+
}
|
|
3748
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisWizardInlineNoticeComponent, decorators: [{
|
|
3749
|
+
type: Component,
|
|
3750
|
+
args: [{ selector: 'praxis-wizard-inline-notice', standalone: true, host: {
|
|
3751
|
+
'[attr.data-block-id]': 'blockId || null',
|
|
3752
|
+
}, imports: [CommonModule], template: `
|
|
3753
|
+
<div class="pwx-inline" [ngClass]="toneClass">
|
|
3754
|
+
{{ text }}
|
|
3755
|
+
</div>
|
|
3756
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.pwx-inline{font-size:.82rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant));line-height:1.4}.pwx-inline.info{color:var(--md-sys-color-on-surface)}.pwx-inline.warning{color:var(--md-sys-color-error)}\n"] }]
|
|
3757
|
+
}], propDecorators: { blockId: [{
|
|
3758
|
+
type: Input
|
|
3759
|
+
}], text: [{
|
|
3760
|
+
type: Input
|
|
3761
|
+
}], tone: [{
|
|
3762
|
+
type: Input
|
|
3763
|
+
}] } });
|
|
3764
|
+
|
|
3765
|
+
class PraxisWizardDividerComponent {
|
|
3766
|
+
blockId;
|
|
3767
|
+
label;
|
|
3768
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisWizardDividerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3769
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: PraxisWizardDividerComponent, isStandalone: true, selector: "praxis-wizard-divider", inputs: { blockId: "blockId", label: "label" }, host: { properties: { "attr.data-block-id": "blockId || null" } }, ngImport: i0, template: `
|
|
3770
|
+
<div class="pwx-divider">
|
|
3771
|
+
<span *ngIf="label" class="pwx-divider-label">{{ label }}</span>
|
|
3772
|
+
</div>
|
|
3773
|
+
`, isInline: true, styles: [":host{display:block}.pwx-divider{position:relative;height:1px;background:var(--praxis-wizard-divider, var(--md-sys-color-outline-variant));margin:16px 0}.pwx-divider-label{position:absolute;top:-.65rem;left:50%;transform:translate(-50%);padding:0 8px;font-size:.75rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant));background:var(--praxis-wizard-card-bg, var(--md-sys-color-surface))}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3774
|
+
}
|
|
3775
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisWizardDividerComponent, decorators: [{
|
|
3776
|
+
type: Component,
|
|
3777
|
+
args: [{ selector: 'praxis-wizard-divider', standalone: true, host: {
|
|
3778
|
+
'[attr.data-block-id]': 'blockId || null',
|
|
3779
|
+
}, imports: [CommonModule], template: `
|
|
3780
|
+
<div class="pwx-divider">
|
|
3781
|
+
<span *ngIf="label" class="pwx-divider-label">{{ label }}</span>
|
|
3782
|
+
</div>
|
|
3783
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.pwx-divider{position:relative;height:1px;background:var(--praxis-wizard-divider, var(--md-sys-color-outline-variant));margin:16px 0}.pwx-divider-label{position:absolute;top:-.65rem;left:50%;transform:translate(-50%);padding:0 8px;font-size:.75rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant));background:var(--praxis-wizard-card-bg, var(--md-sys-color-surface))}\n"] }]
|
|
3784
|
+
}], propDecorators: { blockId: [{
|
|
3785
|
+
type: Input
|
|
3786
|
+
}], label: [{
|
|
3787
|
+
type: Input
|
|
3788
|
+
}] } });
|
|
3789
|
+
|
|
1993
3790
|
const PRAXIS_STEPPER_COMPONENT_METADATA = {
|
|
1994
3791
|
id: 'praxis-stepper',
|
|
1995
3792
|
selector: 'praxis-stepper',
|
|
@@ -1998,10 +3795,13 @@ const PRAXIS_STEPPER_COMPONENT_METADATA = {
|
|
|
1998
3795
|
description: 'Stepper configurável (horizontal/vertical/linear) com passos e conteúdo dinâmico.',
|
|
1999
3796
|
icon: 'format_list_numbered',
|
|
2000
3797
|
inputs: [
|
|
3798
|
+
{ name: 'stepperId', type: 'string', label: 'ID do Stepper', description: 'Identificador para persistência (obrigatório)' },
|
|
3799
|
+
{ name: 'componentInstanceId', type: 'string', label: 'ID da instância', description: 'Identificador opcional para múltiplas instâncias na mesma rota' },
|
|
2001
3800
|
{ name: 'config', type: 'StepperMetadata', label: 'Configuração', description: 'Configuração JSON com passos e opções' },
|
|
2002
3801
|
{ name: 'selectedIndex', type: 'number', label: '[(selectedIndex)] Índice selecionado' },
|
|
2003
3802
|
{ name: 'selectedIndexInput', type: 'number', label: 'Índice selecionado (legacy)' },
|
|
2004
3803
|
{ name: 'disableRippleInput', type: 'boolean', default: false, label: 'Desabilitar ripple' },
|
|
3804
|
+
{ name: 'editModeEnabled', type: 'boolean', default: false, label: 'Modo de edição', description: 'Exibe controles de edição e assistente AI no runtime' },
|
|
2005
3805
|
{ name: 'labelPosition', type: "'bottom' | 'end'", label: 'Posição do rótulo (horizontal)' },
|
|
2006
3806
|
{ name: 'color', type: 'ThemePalette', label: 'Cor (M2)' },
|
|
2007
3807
|
{ name: 'appearance', type: '{ themeClass?: string; tokens?: Record<string,string>; icons?: { number?: string; done?: string; edit?: string; error?: string }; iconsSet?: string }', label: 'Aparência (tokens, themeClass, ícones, conjunto)' },
|
|
@@ -2010,6 +3810,7 @@ const PRAXIS_STEPPER_COMPONENT_METADATA = {
|
|
|
2010
3810
|
{ name: 'stepperClass', type: 'string', label: 'Classe CSS (stepper)' },
|
|
2011
3811
|
{ name: 'headerClass', type: 'string', label: 'Classe CSS (header)' },
|
|
2012
3812
|
{ name: 'contentClass', type: 'string', label: 'Classe CSS (conteúdo)' },
|
|
3813
|
+
{ name: 'stepperContext', type: 'Record<string, any>', label: 'Contexto', description: 'Contexto compartilhado para widgets internos' },
|
|
2013
3814
|
{ name: 'navigation', type: "{ visible?: boolean; prevLabel?: string; nextLabel?: string; prevIcon?: string; nextIcon?: string; variant?: 'basic'|'flat'|'stroked'|'raised'; color?: ThemePalette; align?: 'start'|'center'|'end'|'space-between' }", label: 'Navegação (botões)'
|
|
2014
3815
|
},
|
|
2015
3816
|
],
|
|
@@ -2018,22 +3819,998 @@ const PRAXIS_STEPPER_COMPONENT_METADATA = {
|
|
|
2018
3819
|
{ name: 'selectedIndexChange', type: 'number', label: 'Índice selecionado (change)' },
|
|
2019
3820
|
{ name: 'animationDone', type: 'void', label: 'Animação concluída' },
|
|
2020
3821
|
{ name: 'widgetEvent', type: '{ stepId?: string; stepIndex?: number; sourceId: string; output?: string; payload?: any }', label: 'Evento interno' },
|
|
3822
|
+
{ name: 'stepFormReady', type: '{ stepId?: string; stepIndex: number; event: FormReadyEvent }', label: 'Form ready (por etapa)' },
|
|
3823
|
+
{ name: 'stepFormValueChange', type: '{ stepId?: string; stepIndex: number; event: FormValueChangeEvent }', label: 'Form value change (por etapa)' },
|
|
3824
|
+
],
|
|
3825
|
+
actions: [
|
|
3826
|
+
{
|
|
3827
|
+
id: 'select-step',
|
|
3828
|
+
label: 'Selecionar etapa',
|
|
3829
|
+
icon: 'flag',
|
|
3830
|
+
description: 'Emite alteração do índice selecionado',
|
|
3831
|
+
emit: 'selectedIndexChange',
|
|
3832
|
+
payloadSchema: {
|
|
3833
|
+
type: 'number',
|
|
3834
|
+
example: 0,
|
|
3835
|
+
},
|
|
3836
|
+
scope: 'any',
|
|
3837
|
+
},
|
|
3838
|
+
{
|
|
3839
|
+
id: 'step-change',
|
|
3840
|
+
label: 'Troca de etapa',
|
|
3841
|
+
icon: 'swap_vert',
|
|
3842
|
+
description: 'Emite evento ao trocar de etapa',
|
|
3843
|
+
emit: 'selectionChange',
|
|
3844
|
+
payloadSchema: {
|
|
3845
|
+
type: 'object',
|
|
3846
|
+
properties: {
|
|
3847
|
+
selectedIndex: { type: 'number', description: 'Índice selecionado' },
|
|
3848
|
+
previouslySelectedIndex: { type: 'number', description: 'Índice anterior' },
|
|
3849
|
+
},
|
|
3850
|
+
required: ['selectedIndex'],
|
|
3851
|
+
example: { selectedIndex: 1, previouslySelectedIndex: 0 },
|
|
3852
|
+
},
|
|
3853
|
+
scope: 'any',
|
|
3854
|
+
},
|
|
2021
3855
|
],
|
|
2022
3856
|
tags: ['widget', 'container', 'stepper', 'configurable'],
|
|
2023
3857
|
lib: '@praxisui/stepper',
|
|
2024
3858
|
layoutHints: { recommendedCols: 8, recommendedRows: 6, minCols: 4, minRows: 4 },
|
|
2025
3859
|
};
|
|
3860
|
+
const PRAXIS_WIZARD_BENEFITS_METADATA = {
|
|
3861
|
+
id: 'praxis-wizard-benefits',
|
|
3862
|
+
selector: 'praxis-wizard-benefits-grid',
|
|
3863
|
+
component: PraxisWizardBenefitsGridComponent,
|
|
3864
|
+
friendlyName: 'Wizard Benefits Grid',
|
|
3865
|
+
description: 'Grid de benefícios com ícones/títulos/texto (uso editorial).',
|
|
3866
|
+
icon: 'view_module',
|
|
3867
|
+
inputs: [
|
|
3868
|
+
{ name: 'blockId', type: 'string', label: 'ID estável (avançado)', description: 'Chave estável para telemetria/e2e.' },
|
|
3869
|
+
{ name: 'title', type: 'string', label: 'Título' },
|
|
3870
|
+
{ name: 'items', type: 'Array<{ icon?: string; title: string; text?: string }>', label: 'Itens' },
|
|
3871
|
+
{ name: 'columns', type: 'number', label: 'Colunas' },
|
|
3872
|
+
{ name: 'boxed', type: 'boolean', label: 'Boxed' },
|
|
3873
|
+
],
|
|
3874
|
+
outputs: [],
|
|
3875
|
+
tags: ['widget', 'wizard', 'content', 'benefits'],
|
|
3876
|
+
lib: '@praxisui/stepper',
|
|
3877
|
+
};
|
|
3878
|
+
const PRAXIS_WIZARD_CONTENT_METADATA = {
|
|
3879
|
+
id: 'praxis-wizard-content',
|
|
3880
|
+
selector: 'praxis-wizard-content-block',
|
|
3881
|
+
component: PraxisWizardContentBlockComponent,
|
|
3882
|
+
friendlyName: 'Wizard Content Block',
|
|
3883
|
+
description: 'Bloco editorial com título/subtítulo/texto.',
|
|
3884
|
+
icon: 'article',
|
|
3885
|
+
inputs: [
|
|
3886
|
+
{ name: 'blockId', type: 'string', label: 'ID estável (avançado)', description: 'Chave estável para telemetria/e2e.' },
|
|
3887
|
+
{ name: 'title', type: 'string', label: 'Título' },
|
|
3888
|
+
{ name: 'subtitle', type: 'string', label: 'Subtítulo' },
|
|
3889
|
+
{ name: 'text', type: 'string', label: 'Texto' },
|
|
3890
|
+
{ name: 'caption', type: 'string', label: 'Legenda' },
|
|
3891
|
+
],
|
|
3892
|
+
outputs: [],
|
|
3893
|
+
tags: ['widget', 'wizard', 'content'],
|
|
3894
|
+
lib: '@praxisui/stepper',
|
|
3895
|
+
};
|
|
3896
|
+
const PRAXIS_WIZARD_NOTICE_METADATA = {
|
|
3897
|
+
id: 'praxis-wizard-inline-notice',
|
|
3898
|
+
selector: 'praxis-wizard-inline-notice',
|
|
3899
|
+
component: PraxisWizardInlineNoticeComponent,
|
|
3900
|
+
friendlyName: 'Wizard Inline Notice',
|
|
3901
|
+
description: 'Texto legal/nota inline para wizards.',
|
|
3902
|
+
icon: 'info',
|
|
3903
|
+
inputs: [
|
|
3904
|
+
{ name: 'blockId', type: 'string', label: 'ID estável (avançado)', description: 'Chave estável para telemetria/e2e.' },
|
|
3905
|
+
{ name: 'text', type: 'string', label: 'Texto' },
|
|
3906
|
+
{ name: 'tone', type: "'neutral' | 'info' | 'warning'", label: 'Tom' },
|
|
3907
|
+
],
|
|
3908
|
+
outputs: [],
|
|
3909
|
+
tags: ['widget', 'wizard', 'notice'],
|
|
3910
|
+
lib: '@praxisui/stepper',
|
|
3911
|
+
};
|
|
3912
|
+
const PRAXIS_WIZARD_DIVIDER_METADATA = {
|
|
3913
|
+
id: 'praxis-wizard-divider',
|
|
3914
|
+
selector: 'praxis-wizard-divider',
|
|
3915
|
+
component: PraxisWizardDividerComponent,
|
|
3916
|
+
friendlyName: 'Wizard Divider',
|
|
3917
|
+
description: 'Separador visual para fluxo.',
|
|
3918
|
+
icon: 'horizontal_rule',
|
|
3919
|
+
inputs: [
|
|
3920
|
+
{ name: 'blockId', type: 'string', label: 'ID estável (avançado)', description: 'Chave estável para telemetria/e2e.' },
|
|
3921
|
+
{ name: 'label', type: 'string', label: 'Rótulo' },
|
|
3922
|
+
],
|
|
3923
|
+
outputs: [],
|
|
3924
|
+
tags: ['widget', 'wizard', 'divider'],
|
|
3925
|
+
lib: '@praxisui/stepper',
|
|
3926
|
+
};
|
|
2026
3927
|
function providePraxisStepperMetadata() {
|
|
2027
3928
|
return {
|
|
2028
3929
|
provide: ENVIRONMENT_INITIALIZER,
|
|
2029
3930
|
multi: true,
|
|
2030
3931
|
useFactory: (registry) => () => {
|
|
2031
3932
|
registry.register(PRAXIS_STEPPER_COMPONENT_METADATA);
|
|
3933
|
+
registry.register(PRAXIS_WIZARD_BENEFITS_METADATA);
|
|
3934
|
+
registry.register(PRAXIS_WIZARD_CONTENT_METADATA);
|
|
3935
|
+
registry.register(PRAXIS_WIZARD_NOTICE_METADATA);
|
|
3936
|
+
registry.register(PRAXIS_WIZARD_DIVIDER_METADATA);
|
|
2032
3937
|
},
|
|
2033
3938
|
deps: [ComponentMetadataRegistry],
|
|
2034
3939
|
};
|
|
2035
3940
|
}
|
|
2036
3941
|
|
|
3942
|
+
const FT_WIZARD_JSON = `{
|
|
3943
|
+
"id": "ft-edit-wizard",
|
|
3944
|
+
"brand": "FINANCIAL TIMES",
|
|
3945
|
+
"progress": {
|
|
3946
|
+
"variant": "line",
|
|
3947
|
+
"showLabels": true,
|
|
3948
|
+
"labelPosition": "bottom"
|
|
3949
|
+
},
|
|
3950
|
+
"cta": {
|
|
3951
|
+
"label": "Continue",
|
|
3952
|
+
"action": "next",
|
|
3953
|
+
"secondaryLabel": "Back",
|
|
3954
|
+
"secondaryAction": "prev",
|
|
3955
|
+
"sticky": true
|
|
3956
|
+
},
|
|
3957
|
+
"preferences": {
|
|
3958
|
+
"stepId": "preferences",
|
|
3959
|
+
"storageKey": "praxis:ft-wizard",
|
|
3960
|
+
"persistFields": ["topStories", "invitesOffers", "recommendations"]
|
|
3961
|
+
},
|
|
3962
|
+
"theme": {
|
|
3963
|
+
"praxis-wizard-card-bg": "#fff1e5",
|
|
3964
|
+
"md-sys-color-surface": "#fff1e5",
|
|
3965
|
+
"md-sys-color-on-surface": "#33302e",
|
|
3966
|
+
"praxis-wizard-accent": "#0d7680",
|
|
3967
|
+
"praxis-wizard-border": "#cfcfcf",
|
|
3968
|
+
"md-sys-color-outline-variant": "#cfcfcf",
|
|
3969
|
+
"ft-font-head": "\\\"Financier Display\\\", Georgia, serif",
|
|
3970
|
+
"ft-font-body": "\\\"Metric\\\", \\\"Helvetica Neue\\\", Helvetica, Arial, sans-serif",
|
|
3971
|
+
"ft-radius": "0",
|
|
3972
|
+
"ft-shadow": "none",
|
|
3973
|
+
"ft-header-border": "1px solid #cfcfcf"
|
|
3974
|
+
},
|
|
3975
|
+
"steps": [
|
|
3976
|
+
{
|
|
3977
|
+
"id": "access",
|
|
3978
|
+
"label": "Access",
|
|
3979
|
+
"title": "Create an FT Edit account",
|
|
3980
|
+
"subtitle": "Get access in a couple of steps and upgrade later for the full FT experience.",
|
|
3981
|
+
"zones": {
|
|
3982
|
+
"intro": [
|
|
3983
|
+
{
|
|
3984
|
+
"type": "benefitsGrid",
|
|
3985
|
+
"title": "Why register?",
|
|
3986
|
+
"columns": 4,
|
|
3987
|
+
"boxed": true,
|
|
3988
|
+
"items": [
|
|
3989
|
+
{
|
|
3990
|
+
"icon": "format_quote",
|
|
3991
|
+
"title": "Beyond the headlines",
|
|
3992
|
+
"text": "Insightful news, thought-provoking opinion and fascinating features."
|
|
3993
|
+
},
|
|
3994
|
+
{
|
|
3995
|
+
"icon": "edit_note",
|
|
3996
|
+
"title": "Curated daily editions",
|
|
3997
|
+
"text": "Eight fresh articles a day chosen for you by our senior editors."
|
|
3998
|
+
},
|
|
3999
|
+
{
|
|
4000
|
+
"icon": "bookmarks",
|
|
4001
|
+
"title": "Never miss a great story",
|
|
4002
|
+
"text": "Explore previous editions from the past week."
|
|
4003
|
+
},
|
|
4004
|
+
{
|
|
4005
|
+
"icon": "mail",
|
|
4006
|
+
"title": "Receive the FT Edit newsletter",
|
|
4007
|
+
"text": "A daily round-up delivered straight to your inbox."
|
|
4008
|
+
}
|
|
4009
|
+
]
|
|
4010
|
+
}
|
|
4011
|
+
],
|
|
4012
|
+
"footer": [
|
|
4013
|
+
{
|
|
4014
|
+
"type": "inlineNotice",
|
|
4015
|
+
"text": "For more information about how we use your data, please refer to our privacy and cookie policies."
|
|
4016
|
+
}
|
|
4017
|
+
]
|
|
4018
|
+
},
|
|
4019
|
+
"cta": {
|
|
4020
|
+
"label": "Register with email",
|
|
4021
|
+
"action": "next"
|
|
4022
|
+
},
|
|
4023
|
+
"form": {
|
|
4024
|
+
"config": {
|
|
4025
|
+
"sections": [
|
|
4026
|
+
{
|
|
4027
|
+
"id": "access-section",
|
|
4028
|
+
"rows": [
|
|
4029
|
+
{
|
|
4030
|
+
"columns": [
|
|
4031
|
+
{
|
|
4032
|
+
"fields": ["confirmAge", "editNewsletter"]
|
|
4033
|
+
}
|
|
4034
|
+
]
|
|
4035
|
+
}
|
|
4036
|
+
]
|
|
4037
|
+
}
|
|
4038
|
+
],
|
|
4039
|
+
"fieldMetadata": [
|
|
4040
|
+
{
|
|
4041
|
+
"name": "confirmAge",
|
|
4042
|
+
"label": "",
|
|
4043
|
+
"controlType": "checkbox",
|
|
4044
|
+
"required": true,
|
|
4045
|
+
"layout": "horizontal",
|
|
4046
|
+
"options": [
|
|
4047
|
+
{
|
|
4048
|
+
"label": "I confirm I am 16+ years old and agree to the Terms & Conditions.",
|
|
4049
|
+
"value": true
|
|
4050
|
+
}
|
|
4051
|
+
]
|
|
4052
|
+
},
|
|
4053
|
+
{
|
|
4054
|
+
"name": "editNewsletter",
|
|
4055
|
+
"label": "FT Edit newsletter",
|
|
4056
|
+
"controlType": "toggle",
|
|
4057
|
+
"defaultValue": true,
|
|
4058
|
+
"hint": "All new members also start receiving our daily FT Edit newsletter."
|
|
4059
|
+
}
|
|
4060
|
+
],
|
|
4061
|
+
"actions": {
|
|
4062
|
+
"submit": { "visible": false, "label": "Submit" },
|
|
4063
|
+
"cancel": { "visible": false, "label": "Cancel" },
|
|
4064
|
+
"reset": { "visible": false, "label": "Reset" }
|
|
4065
|
+
}
|
|
4066
|
+
}
|
|
4067
|
+
}
|
|
4068
|
+
},
|
|
4069
|
+
{
|
|
4070
|
+
"id": "account",
|
|
4071
|
+
"label": "Account",
|
|
4072
|
+
"title": "Create an FT Edit account",
|
|
4073
|
+
"subtitle": "This address will be used to create your account.",
|
|
4074
|
+
"zones": {
|
|
4075
|
+
"intro": [
|
|
4076
|
+
{
|
|
4077
|
+
"type": "inlineNotice",
|
|
4078
|
+
"text": "All new members also start receiving our daily FT Edit newsletter.",
|
|
4079
|
+
"tone": "info"
|
|
4080
|
+
}
|
|
4081
|
+
],
|
|
4082
|
+
"footer": [
|
|
4083
|
+
{
|
|
4084
|
+
"type": "inlineNotice",
|
|
4085
|
+
"text": "We will send you service messages about your account, security or legal notifications."
|
|
4086
|
+
}
|
|
4087
|
+
]
|
|
4088
|
+
},
|
|
4089
|
+
"form": {
|
|
4090
|
+
"config": {
|
|
4091
|
+
"sections": [
|
|
4092
|
+
{
|
|
4093
|
+
"id": "account-section",
|
|
4094
|
+
"rows": [
|
|
4095
|
+
{
|
|
4096
|
+
"columns": [
|
|
4097
|
+
{ "fields": ["email", "password"] },
|
|
4098
|
+
{ "fields": ["newsletterOptIn"] }
|
|
4099
|
+
]
|
|
4100
|
+
}
|
|
4101
|
+
]
|
|
4102
|
+
}
|
|
4103
|
+
],
|
|
4104
|
+
"fieldMetadata": [
|
|
4105
|
+
{
|
|
4106
|
+
"name": "email",
|
|
4107
|
+
"label": "Email address",
|
|
4108
|
+
"controlType": "email",
|
|
4109
|
+
"required": true,
|
|
4110
|
+
"placeholder": "Enter your email address"
|
|
4111
|
+
},
|
|
4112
|
+
{
|
|
4113
|
+
"name": "password",
|
|
4114
|
+
"label": "Password",
|
|
4115
|
+
"controlType": "password",
|
|
4116
|
+
"required": true,
|
|
4117
|
+
"placeholder": "Enter a password",
|
|
4118
|
+
"hint": "Use 8 or more characters. You can use letters, numbers or symbols.",
|
|
4119
|
+
"validators": {
|
|
4120
|
+
"minLength": 8
|
|
4121
|
+
},
|
|
4122
|
+
"revealToggle": {
|
|
4123
|
+
"enabled": true,
|
|
4124
|
+
"style": "text",
|
|
4125
|
+
"showLabel": "Show password",
|
|
4126
|
+
"hideLabel": "Hide password",
|
|
4127
|
+
"ariaLabel": "Toggle password visibility"
|
|
4128
|
+
}
|
|
4129
|
+
},
|
|
4130
|
+
{
|
|
4131
|
+
"name": "newsletterOptIn",
|
|
4132
|
+
"label": "Stay up to date",
|
|
4133
|
+
"controlType": "toggle",
|
|
4134
|
+
"defaultValue": true,
|
|
4135
|
+
"hint": "All new members also start receiving our daily FT Edit newsletter."
|
|
4136
|
+
}
|
|
4137
|
+
],
|
|
4138
|
+
"actions": {
|
|
4139
|
+
"submit": { "visible": false, "label": "Submit" },
|
|
4140
|
+
"cancel": { "visible": false, "label": "Cancel" },
|
|
4141
|
+
"reset": { "visible": false, "label": "Reset" }
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4144
|
+
}
|
|
4145
|
+
},
|
|
4146
|
+
{
|
|
4147
|
+
"id": "preferences",
|
|
4148
|
+
"label": "Preferences",
|
|
4149
|
+
"title": "Stay up to date",
|
|
4150
|
+
"subtitle": "You can update these any time in your Contact Preferences.",
|
|
4151
|
+
"description": "We will send you service messages about your account, security or legal notifications.",
|
|
4152
|
+
"zones": {
|
|
4153
|
+
"footer": [
|
|
4154
|
+
{
|
|
4155
|
+
"type": "divider"
|
|
4156
|
+
},
|
|
4157
|
+
{
|
|
4158
|
+
"type": "inlineNotice",
|
|
4159
|
+
"text": "We will send you service messages about your account, security or legal notifications."
|
|
4160
|
+
}
|
|
4161
|
+
]
|
|
4162
|
+
},
|
|
4163
|
+
"cta": {
|
|
4164
|
+
"label": "Create an FT Edit account",
|
|
4165
|
+
"action": "submit",
|
|
4166
|
+
"secondaryLabel": "Back",
|
|
4167
|
+
"secondaryAction": "prev"
|
|
4168
|
+
},
|
|
4169
|
+
"form": {
|
|
4170
|
+
"config": {
|
|
4171
|
+
"sections": [
|
|
4172
|
+
{
|
|
4173
|
+
"id": "prefs-section",
|
|
4174
|
+
"rows": [
|
|
4175
|
+
{
|
|
4176
|
+
"columns": [
|
|
4177
|
+
{ "fields": ["topStories"] },
|
|
4178
|
+
{ "fields": ["invitesOffers"] },
|
|
4179
|
+
{ "fields": ["recommendations"] }
|
|
4180
|
+
]
|
|
4181
|
+
}
|
|
4182
|
+
]
|
|
4183
|
+
}
|
|
4184
|
+
],
|
|
4185
|
+
"fieldMetadata": [
|
|
4186
|
+
{
|
|
4187
|
+
"name": "topStories",
|
|
4188
|
+
"label": "Top stories & features",
|
|
4189
|
+
"controlType": "toggle",
|
|
4190
|
+
"defaultValue": true,
|
|
4191
|
+
"hint": "Get the most from the Financial Times with personalised special reports, recommended reads and latest feature announcements."
|
|
4192
|
+
},
|
|
4193
|
+
{
|
|
4194
|
+
"name": "invitesOffers",
|
|
4195
|
+
"label": "Invites & offers from the FT",
|
|
4196
|
+
"controlType": "toggle",
|
|
4197
|
+
"defaultValue": true,
|
|
4198
|
+
"hint": "Receive exclusive personalised event invitations, carefully-curated offers and promotions from the Financial Times."
|
|
4199
|
+
},
|
|
4200
|
+
{
|
|
4201
|
+
"name": "recommendations",
|
|
4202
|
+
"label": "Personal recommendations",
|
|
4203
|
+
"controlType": "toggle",
|
|
4204
|
+
"defaultValue": false,
|
|
4205
|
+
"hint": "Tailored reading lists based on what you follow."
|
|
4206
|
+
}
|
|
4207
|
+
],
|
|
4208
|
+
"actions": {
|
|
4209
|
+
"submit": { "visible": false, "label": "Submit" },
|
|
4210
|
+
"cancel": { "visible": false, "label": "Cancel" },
|
|
4211
|
+
"reset": { "visible": false, "label": "Reset" }
|
|
4212
|
+
}
|
|
4213
|
+
}
|
|
4214
|
+
}
|
|
4215
|
+
}
|
|
4216
|
+
]
|
|
4217
|
+
}`;
|
|
4218
|
+
const FT_WIZARD_CONFIG = JSON.parse(FT_WIZARD_JSON);
|
|
4219
|
+
|
|
4220
|
+
const defaultCardSkin = {
|
|
4221
|
+
type: 'elevated',
|
|
4222
|
+
radius: '12px',
|
|
4223
|
+
border: '1px solid var(--md-sys-color-outline-variant, #e0e0e0)',
|
|
4224
|
+
shadow: '0 1px 2px rgba(0,0,0,0.06)',
|
|
4225
|
+
};
|
|
4226
|
+
const defaultCardLayout = {
|
|
4227
|
+
variant: 'cards',
|
|
4228
|
+
density: 'comfortable',
|
|
4229
|
+
lines: 2,
|
|
4230
|
+
model: 'standard',
|
|
4231
|
+
dividers: 'none',
|
|
4232
|
+
};
|
|
4233
|
+
const defaultCardTemplating = {
|
|
4234
|
+
primary: { type: 'text', expr: '${item.title}', class: 'ft-card-title' },
|
|
4235
|
+
secondary: { type: 'text', expr: '${item.description}', class: 'ft-card-desc' },
|
|
4236
|
+
};
|
|
4237
|
+
function buildStepperConfig(wizard) {
|
|
4238
|
+
const steps = wizard.steps.map((step) => buildStep(step, wizard.id));
|
|
4239
|
+
return {
|
|
4240
|
+
orientation: 'horizontal',
|
|
4241
|
+
linear: true,
|
|
4242
|
+
headerPosition: 'top',
|
|
4243
|
+
labelPosition: wizard.progress?.labelPosition ?? 'bottom',
|
|
4244
|
+
density: 'compact',
|
|
4245
|
+
stepperClass: 'ft-stepper',
|
|
4246
|
+
headerClass: 'ft-stepper-header',
|
|
4247
|
+
contentClass: 'ft-stepper-content',
|
|
4248
|
+
appearance: {
|
|
4249
|
+
preset: 'ft-light',
|
|
4250
|
+
},
|
|
4251
|
+
navigation: { visible: false },
|
|
4252
|
+
steps,
|
|
4253
|
+
};
|
|
4254
|
+
}
|
|
4255
|
+
function buildStep(step, wizardId) {
|
|
4256
|
+
const blocks = buildBlocks(mergeBlocks(step), wizardId, step.id);
|
|
4257
|
+
const beforeWidgets = [
|
|
4258
|
+
...blocks.before,
|
|
4259
|
+
...(step.cards?.length ? [buildCardsWidget(step, wizardId)] : []),
|
|
4260
|
+
];
|
|
4261
|
+
const widgetsBeforeForm = beforeWidgets.length ? beforeWidgets : undefined;
|
|
4262
|
+
const widgetsAfterForm = blocks.after.length ? blocks.after : undefined;
|
|
4263
|
+
return {
|
|
4264
|
+
id: step.id,
|
|
4265
|
+
label: step.label,
|
|
4266
|
+
description: step.subtitle || step.description,
|
|
4267
|
+
optional: step.optional,
|
|
4268
|
+
widgetsBeforeForm,
|
|
4269
|
+
widgets: widgetsAfterForm,
|
|
4270
|
+
form: step.form
|
|
4271
|
+
? {
|
|
4272
|
+
formId: step.form.formId || `${wizardId}:${step.id}`,
|
|
4273
|
+
config: step.form.config,
|
|
4274
|
+
mode: 'create',
|
|
4275
|
+
}
|
|
4276
|
+
: undefined,
|
|
4277
|
+
};
|
|
4278
|
+
}
|
|
4279
|
+
function buildCardsWidget(step, wizardId) {
|
|
4280
|
+
const cfg = {
|
|
4281
|
+
id: `${wizardId}:${step.id}:cards`,
|
|
4282
|
+
dataSource: { data: step.cards || [] },
|
|
4283
|
+
layout: { ...defaultCardLayout },
|
|
4284
|
+
skin: { ...defaultCardSkin },
|
|
4285
|
+
templating: { ...defaultCardTemplating },
|
|
4286
|
+
ui: { showSearch: false, showSort: false, showRange: false },
|
|
4287
|
+
};
|
|
4288
|
+
return {
|
|
4289
|
+
id: 'praxis-list',
|
|
4290
|
+
inputs: {
|
|
4291
|
+
listId: cfg.id,
|
|
4292
|
+
config: cfg,
|
|
4293
|
+
},
|
|
4294
|
+
};
|
|
4295
|
+
}
|
|
4296
|
+
function mergeBlocks(step) {
|
|
4297
|
+
const out = [];
|
|
4298
|
+
const hasZones = !!(step.zones?.intro?.length || step.zones?.body?.length || step.zones?.footer?.length);
|
|
4299
|
+
if (hasZones) {
|
|
4300
|
+
// Contrato atual: `zones` é o modelo canônico e substitui `blocks` legado
|
|
4301
|
+
// quando ambos coexistem no payload, evitando renderização duplicada.
|
|
4302
|
+
if (step.zones?.intro?.length) {
|
|
4303
|
+
out.push(...step.zones.intro.map((b) => ({ ...b, placement: 'beforeForm' })));
|
|
4304
|
+
}
|
|
4305
|
+
if (step.zones?.body?.length) {
|
|
4306
|
+
out.push(...step.zones.body.map((b) => ({ ...b, placement: 'beforeForm' })));
|
|
4307
|
+
}
|
|
4308
|
+
if (step.zones?.footer?.length) {
|
|
4309
|
+
out.push(...step.zones.footer.map((b) => ({ ...b, placement: 'afterForm' })));
|
|
4310
|
+
}
|
|
4311
|
+
return out;
|
|
4312
|
+
}
|
|
4313
|
+
if (step.blocks?.length)
|
|
4314
|
+
out.push(...step.blocks);
|
|
4315
|
+
return out.length ? out : undefined;
|
|
4316
|
+
}
|
|
4317
|
+
function buildBlocks(blocks, wizardId, stepId) {
|
|
4318
|
+
if (!blocks || blocks.length === 0)
|
|
4319
|
+
return { before: [], after: [] };
|
|
4320
|
+
const before = [];
|
|
4321
|
+
const after = [];
|
|
4322
|
+
blocks.forEach((block, index) => {
|
|
4323
|
+
const placement = block.placement ?? 'beforeForm';
|
|
4324
|
+
const def = toWidget(block, wizardId, stepId, index);
|
|
4325
|
+
if (!def)
|
|
4326
|
+
return;
|
|
4327
|
+
if (placement === 'afterForm')
|
|
4328
|
+
after.push(def);
|
|
4329
|
+
else
|
|
4330
|
+
before.push(def);
|
|
4331
|
+
});
|
|
4332
|
+
return { before, after };
|
|
4333
|
+
}
|
|
4334
|
+
function resolveBlockRuntimeId(block, wizardId, stepId, index) {
|
|
4335
|
+
const explicitId = typeof block.id === 'string' ? block.id.trim() : '';
|
|
4336
|
+
return explicitId
|
|
4337
|
+
? `${wizardId}:${stepId}:block:${explicitId}`
|
|
4338
|
+
: `${wizardId}:${stepId}:block:${index}`;
|
|
4339
|
+
}
|
|
4340
|
+
function toWidget(block, wizardId, stepId, index) {
|
|
4341
|
+
const baseId = resolveBlockRuntimeId(block, wizardId, stepId, index);
|
|
4342
|
+
switch (block.type) {
|
|
4343
|
+
case 'benefitsGrid':
|
|
4344
|
+
return {
|
|
4345
|
+
id: 'praxis-wizard-benefits',
|
|
4346
|
+
inputs: {
|
|
4347
|
+
blockId: baseId,
|
|
4348
|
+
title: block.title,
|
|
4349
|
+
items: block.items,
|
|
4350
|
+
columns: block.columns,
|
|
4351
|
+
boxed: block.boxed,
|
|
4352
|
+
},
|
|
4353
|
+
};
|
|
4354
|
+
case 'contentBlock':
|
|
4355
|
+
return {
|
|
4356
|
+
id: 'praxis-wizard-content',
|
|
4357
|
+
inputs: {
|
|
4358
|
+
blockId: baseId,
|
|
4359
|
+
title: block.title,
|
|
4360
|
+
subtitle: block.subtitle,
|
|
4361
|
+
text: block.text,
|
|
4362
|
+
caption: block.caption,
|
|
4363
|
+
},
|
|
4364
|
+
};
|
|
4365
|
+
case 'inlineNotice':
|
|
4366
|
+
return {
|
|
4367
|
+
id: 'praxis-wizard-inline-notice',
|
|
4368
|
+
inputs: {
|
|
4369
|
+
blockId: baseId,
|
|
4370
|
+
text: block.text,
|
|
4371
|
+
tone: block.tone,
|
|
4372
|
+
},
|
|
4373
|
+
};
|
|
4374
|
+
case 'divider':
|
|
4375
|
+
return {
|
|
4376
|
+
id: 'praxis-wizard-divider',
|
|
4377
|
+
inputs: {
|
|
4378
|
+
blockId: baseId,
|
|
4379
|
+
label: block.label ?? '',
|
|
4380
|
+
},
|
|
4381
|
+
};
|
|
4382
|
+
default:
|
|
4383
|
+
return null;
|
|
4384
|
+
}
|
|
4385
|
+
}
|
|
4386
|
+
|
|
4387
|
+
class PraxisWizardCtaBarComponent {
|
|
4388
|
+
primaryLabel = 'Continue';
|
|
4389
|
+
primaryDisabled = false;
|
|
4390
|
+
secondaryLabel = 'Back';
|
|
4391
|
+
showSecondary = false;
|
|
4392
|
+
sticky = false;
|
|
4393
|
+
primaryClick = new EventEmitter();
|
|
4394
|
+
secondaryClick = new EventEmitter();
|
|
4395
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisWizardCtaBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4396
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: PraxisWizardCtaBarComponent, isStandalone: true, selector: "praxis-wizard-cta-bar", inputs: { primaryLabel: "primaryLabel", primaryDisabled: "primaryDisabled", secondaryLabel: "secondaryLabel", showSecondary: "showSecondary", sticky: "sticky" }, outputs: { primaryClick: "primaryClick", secondaryClick: "secondaryClick" }, ngImport: i0, template: `
|
|
4397
|
+
<div class="pwx-cta" [class.is-sticky]="sticky" [class.has-secondary]="showSecondary">
|
|
4398
|
+
<button
|
|
4399
|
+
*ngIf="showSecondary"
|
|
4400
|
+
mat-button
|
|
4401
|
+
type="button"
|
|
4402
|
+
class="pwx-cta-secondary"
|
|
4403
|
+
(click)="secondaryClick.emit()"
|
|
4404
|
+
[attr.aria-label]="secondaryLabel"
|
|
4405
|
+
>
|
|
4406
|
+
{{ secondaryLabel }}
|
|
4407
|
+
</button>
|
|
4408
|
+
<button
|
|
4409
|
+
mat-flat-button
|
|
4410
|
+
color="primary"
|
|
4411
|
+
type="button"
|
|
4412
|
+
class="pwx-cta-primary"
|
|
4413
|
+
[disabled]="primaryDisabled"
|
|
4414
|
+
(click)="primaryClick.emit()"
|
|
4415
|
+
[attr.aria-label]="primaryLabel"
|
|
4416
|
+
>
|
|
4417
|
+
{{ primaryLabel }}
|
|
4418
|
+
</button>
|
|
4419
|
+
</div>
|
|
4420
|
+
`, isInline: true, styles: [":host{display:block}.pwx-cta{display:flex;justify-content:flex-end;align-items:center;gap:12px;padding-top:16px}.pwx-cta:not(.has-secondary){justify-content:center}.pwx-cta.is-sticky{position:sticky;bottom:0;background:var(--praxis-wizard-card-bg, var(--md-sys-color-surface));padding:12px 0 8px;border-top:1px solid var(--praxis-wizard-border, var(--md-sys-color-outline-variant))}.pwx-cta.has-secondary .pwx-cta-primary{min-width:200px}.pwx-cta-primary{min-width:240px;height:36px;border-radius:4px;font-weight:600;text-transform:none;padding:0 18px}.pwx-cta-secondary{color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant));text-transform:none;font-weight:500;padding:0 4px;min-width:auto}@media(max-width:600px){.pwx-cta{flex-direction:column;align-items:stretch}.pwx-cta-primary{width:100%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i6.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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4421
|
+
}
|
|
4422
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisWizardCtaBarComponent, decorators: [{
|
|
4423
|
+
type: Component,
|
|
4424
|
+
args: [{ selector: 'praxis-wizard-cta-bar', standalone: true, imports: [CommonModule, MatButtonModule], template: `
|
|
4425
|
+
<div class="pwx-cta" [class.is-sticky]="sticky" [class.has-secondary]="showSecondary">
|
|
4426
|
+
<button
|
|
4427
|
+
*ngIf="showSecondary"
|
|
4428
|
+
mat-button
|
|
4429
|
+
type="button"
|
|
4430
|
+
class="pwx-cta-secondary"
|
|
4431
|
+
(click)="secondaryClick.emit()"
|
|
4432
|
+
[attr.aria-label]="secondaryLabel"
|
|
4433
|
+
>
|
|
4434
|
+
{{ secondaryLabel }}
|
|
4435
|
+
</button>
|
|
4436
|
+
<button
|
|
4437
|
+
mat-flat-button
|
|
4438
|
+
color="primary"
|
|
4439
|
+
type="button"
|
|
4440
|
+
class="pwx-cta-primary"
|
|
4441
|
+
[disabled]="primaryDisabled"
|
|
4442
|
+
(click)="primaryClick.emit()"
|
|
4443
|
+
[attr.aria-label]="primaryLabel"
|
|
4444
|
+
>
|
|
4445
|
+
{{ primaryLabel }}
|
|
4446
|
+
</button>
|
|
4447
|
+
</div>
|
|
4448
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.pwx-cta{display:flex;justify-content:flex-end;align-items:center;gap:12px;padding-top:16px}.pwx-cta:not(.has-secondary){justify-content:center}.pwx-cta.is-sticky{position:sticky;bottom:0;background:var(--praxis-wizard-card-bg, var(--md-sys-color-surface));padding:12px 0 8px;border-top:1px solid var(--praxis-wizard-border, var(--md-sys-color-outline-variant))}.pwx-cta.has-secondary .pwx-cta-primary{min-width:200px}.pwx-cta-primary{min-width:240px;height:36px;border-radius:4px;font-weight:600;text-transform:none;padding:0 18px}.pwx-cta-secondary{color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant));text-transform:none;font-weight:500;padding:0 4px;min-width:auto}@media(max-width:600px){.pwx-cta{flex-direction:column;align-items:stretch}.pwx-cta-primary{width:100%}}\n"] }]
|
|
4449
|
+
}], propDecorators: { primaryLabel: [{
|
|
4450
|
+
type: Input
|
|
4451
|
+
}], primaryDisabled: [{
|
|
4452
|
+
type: Input
|
|
4453
|
+
}], secondaryLabel: [{
|
|
4454
|
+
type: Input
|
|
4455
|
+
}], showSecondary: [{
|
|
4456
|
+
type: Input
|
|
4457
|
+
}], sticky: [{
|
|
4458
|
+
type: Input
|
|
4459
|
+
}], primaryClick: [{
|
|
4460
|
+
type: Output
|
|
4461
|
+
}], secondaryClick: [{
|
|
4462
|
+
type: Output
|
|
4463
|
+
}] } });
|
|
4464
|
+
|
|
4465
|
+
const PRAXIS_WIZARD_LOGGER = new LoggerService(createCorporateLoggerConfig(isDevMode() ? 'dev' : 'prod'), [new ConsoleLoggerSink()]);
|
|
4466
|
+
function logWizardConfigIssue(message) {
|
|
4467
|
+
PRAXIS_WIZARD_LOGGER.warnOnce(`[PraxisWizard] ${message}`, {
|
|
4468
|
+
context: {
|
|
4469
|
+
lib: 'praxis-stepper',
|
|
4470
|
+
component: 'PraxisWizardFormComponent',
|
|
4471
|
+
},
|
|
4472
|
+
dedupeKey: `praxis-wizard:config:${message}`,
|
|
4473
|
+
});
|
|
4474
|
+
}
|
|
4475
|
+
function validateWizardConfig(cfg) {
|
|
4476
|
+
if (!cfg)
|
|
4477
|
+
return null;
|
|
4478
|
+
const errors = [];
|
|
4479
|
+
if (!cfg.id)
|
|
4480
|
+
errors.push('config.id is required.');
|
|
4481
|
+
if (!cfg.steps || cfg.steps.length === 0)
|
|
4482
|
+
errors.push('config.steps must have at least one step.');
|
|
4483
|
+
cfg.steps?.forEach((step, idx) => {
|
|
4484
|
+
if (!step.id)
|
|
4485
|
+
errors.push(`steps[${idx}].id is required.`);
|
|
4486
|
+
if (!step.label)
|
|
4487
|
+
errors.push(`steps[${idx}].label is required.`);
|
|
4488
|
+
const hasZones = !!(step.zones?.intro?.length || step.zones?.body?.length || step.zones?.footer?.length);
|
|
4489
|
+
const hasBlocks = !!(step.blocks && step.blocks.length > 0);
|
|
4490
|
+
if (hasZones && hasBlocks) {
|
|
4491
|
+
errors.push(`steps[${idx}] cannot use both 'zones' and 'blocks'.`);
|
|
4492
|
+
}
|
|
4493
|
+
});
|
|
4494
|
+
if (errors.length) {
|
|
4495
|
+
errors.forEach((err) => logWizardConfigIssue(err));
|
|
4496
|
+
if (isDevMode()) {
|
|
4497
|
+
throw new Error(`[PraxisWizard] Invalid configuration:\\n${errors.join('\\n')}`);
|
|
4498
|
+
}
|
|
4499
|
+
}
|
|
4500
|
+
return cfg;
|
|
4501
|
+
}
|
|
4502
|
+
class PraxisWizardFormComponent {
|
|
4503
|
+
el = inject(ElementRef);
|
|
4504
|
+
renderer = inject(Renderer2);
|
|
4505
|
+
storage = inject(CONFIG_STORAGE);
|
|
4506
|
+
constructor() {
|
|
4507
|
+
effect(() => {
|
|
4508
|
+
const cfg = this.wizard();
|
|
4509
|
+
const theme = cfg?.theme;
|
|
4510
|
+
if (theme) {
|
|
4511
|
+
Object.entries(theme).forEach(([key, value]) => {
|
|
4512
|
+
this.renderer.setStyle(this.el.nativeElement, `--${key}`, value);
|
|
4513
|
+
});
|
|
4514
|
+
}
|
|
4515
|
+
});
|
|
4516
|
+
}
|
|
4517
|
+
stepper;
|
|
4518
|
+
wizardId;
|
|
4519
|
+
editModeEnabled = false;
|
|
4520
|
+
set config(cfg) {
|
|
4521
|
+
if (!cfg) {
|
|
4522
|
+
this._config.set(null);
|
|
4523
|
+
return;
|
|
4524
|
+
}
|
|
4525
|
+
if (typeof cfg === 'string') {
|
|
4526
|
+
try {
|
|
4527
|
+
this._config.set(validateWizardConfig(JSON.parse(cfg)));
|
|
4528
|
+
}
|
|
4529
|
+
catch {
|
|
4530
|
+
this._config.set(null);
|
|
4531
|
+
}
|
|
4532
|
+
return;
|
|
4533
|
+
}
|
|
4534
|
+
this._config.set(validateWizardConfig(cfg));
|
|
4535
|
+
}
|
|
4536
|
+
submit = new EventEmitter();
|
|
4537
|
+
_config = signal(null, ...(ngDevMode ? [{ debugName: "_config" }] : []));
|
|
4538
|
+
persistedState = signal(null, ...(ngDevMode ? [{ debugName: "persistedState" }] : []));
|
|
4539
|
+
selectedIndex = signal(0, ...(ngDevMode ? [{ debugName: "selectedIndex" }] : []));
|
|
4540
|
+
wizard = computed(() => {
|
|
4541
|
+
const cfg = this._config();
|
|
4542
|
+
if (!cfg)
|
|
4543
|
+
return null;
|
|
4544
|
+
const persisted = this.persistedState()?.preferences;
|
|
4545
|
+
if (!persisted)
|
|
4546
|
+
return cfg;
|
|
4547
|
+
return applyPreferenceDefaults(cfg, persisted);
|
|
4548
|
+
}, ...(ngDevMode ? [{ debugName: "wizard" }] : []));
|
|
4549
|
+
stepperConfig = computed(() => {
|
|
4550
|
+
const cfg = this.wizard();
|
|
4551
|
+
return cfg ? buildStepperConfig(cfg) : null;
|
|
4552
|
+
}, ...(ngDevMode ? [{ debugName: "stepperConfig" }] : []));
|
|
4553
|
+
activeStep = computed(() => {
|
|
4554
|
+
const w = this.wizard();
|
|
4555
|
+
return w?.steps?.[this.selectedIndex()] || null;
|
|
4556
|
+
}, ...(ngDevMode ? [{ debugName: "activeStep" }] : []));
|
|
4557
|
+
wizardBrand = computed(() => this.wizard()?.brand || 'FINANCIAL TIMES', ...(ngDevMode ? [{ debugName: "wizardBrand" }] : []));
|
|
4558
|
+
activeTitle = computed(() => this.activeStep()?.title || this.wizard()?.title || '', ...(ngDevMode ? [{ debugName: "activeTitle" }] : []));
|
|
4559
|
+
activeSubtitle = computed(() => this.activeStep()?.subtitle || this.wizard()?.subtitle || '', ...(ngDevMode ? [{ debugName: "activeSubtitle" }] : []));
|
|
4560
|
+
activeDescription = computed(() => this.activeStep()?.description || this.wizard()?.description || '', ...(ngDevMode ? [{ debugName: "activeDescription" }] : []));
|
|
4561
|
+
resolvedCta = computed(() => {
|
|
4562
|
+
const stepCta = this.activeStep()?.cta;
|
|
4563
|
+
const globalCta = this.wizard()?.cta;
|
|
4564
|
+
return { ...(globalCta || {}), ...(stepCta || {}) };
|
|
4565
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedCta" }] : []));
|
|
4566
|
+
primaryLabel = computed(() => this.resolvedCta().label ?? 'Continue', ...(ngDevMode ? [{ debugName: "primaryLabel" }] : []));
|
|
4567
|
+
primaryAction = computed(() => this.resolvedCta().action ?? 'next', ...(ngDevMode ? [{ debugName: "primaryAction" }] : []));
|
|
4568
|
+
secondaryLabel = computed(() => this.resolvedCta().secondaryLabel ?? 'Back', ...(ngDevMode ? [{ debugName: "secondaryLabel" }] : []));
|
|
4569
|
+
secondaryAction = computed(() => this.resolvedCta().secondaryAction ?? 'prev', ...(ngDevMode ? [{ debugName: "secondaryAction" }] : []));
|
|
4570
|
+
showSecondaryAction() {
|
|
4571
|
+
const action = this.secondaryAction();
|
|
4572
|
+
if (action === 'cancel')
|
|
4573
|
+
return true;
|
|
4574
|
+
return action === 'prev' && this.selectedIndex() > 0;
|
|
4575
|
+
}
|
|
4576
|
+
isPrimaryDisabled() {
|
|
4577
|
+
const action = this.primaryAction();
|
|
4578
|
+
if (action === 'next')
|
|
4579
|
+
return !!this.stepper?.isNextDisabled(this.selectedIndex());
|
|
4580
|
+
if (action === 'submit')
|
|
4581
|
+
return !!this.stepper?.isNextDisabled(this.selectedIndex());
|
|
4582
|
+
return false;
|
|
4583
|
+
}
|
|
4584
|
+
onPrimaryAction() {
|
|
4585
|
+
this.focusPrimaryAction();
|
|
4586
|
+
const action = this.primaryAction();
|
|
4587
|
+
if (action === 'next') {
|
|
4588
|
+
this.stepper?.next();
|
|
4589
|
+
return;
|
|
4590
|
+
}
|
|
4591
|
+
if (action === 'submit') {
|
|
4592
|
+
this.submit.emit({ wizardId: this.wizardId, values: this.collectValues() });
|
|
4593
|
+
return;
|
|
4594
|
+
}
|
|
4595
|
+
}
|
|
4596
|
+
onSecondaryAction() {
|
|
4597
|
+
this.focusSecondaryAction();
|
|
4598
|
+
if (this.secondaryAction() === 'prev') {
|
|
4599
|
+
this.stepper?.prev();
|
|
4600
|
+
return;
|
|
4601
|
+
}
|
|
4602
|
+
if (this.secondaryAction() === 'cancel') {
|
|
4603
|
+
this.resetProgress();
|
|
4604
|
+
}
|
|
4605
|
+
}
|
|
4606
|
+
onSelectedIndexChange(idx) {
|
|
4607
|
+
this.selectedIndex.set(idx);
|
|
4608
|
+
this.persistState();
|
|
4609
|
+
}
|
|
4610
|
+
onStepFormValueChange(ev) {
|
|
4611
|
+
const wizard = this.wizard();
|
|
4612
|
+
if (!wizard?.preferences)
|
|
4613
|
+
return;
|
|
4614
|
+
const prefStepId = wizard.preferences.stepId;
|
|
4615
|
+
if (!prefStepId || prefStepId !== ev.stepId)
|
|
4616
|
+
return;
|
|
4617
|
+
const values = pickPreferenceValues(ev.event?.formData, wizard.preferences.persistFields);
|
|
4618
|
+
this.persistState({ preferences: values });
|
|
4619
|
+
}
|
|
4620
|
+
ngOnInit() {
|
|
4621
|
+
this.loadPersistedState();
|
|
4622
|
+
}
|
|
4623
|
+
collectValues() {
|
|
4624
|
+
const values = {};
|
|
4625
|
+
const steps = this.wizard()?.steps || [];
|
|
4626
|
+
steps.forEach((step, idx) => {
|
|
4627
|
+
const form = this.stepper?.formGroupFor(idx);
|
|
4628
|
+
if (form)
|
|
4629
|
+
values[step.id] = form.getRawValue();
|
|
4630
|
+
});
|
|
4631
|
+
return values;
|
|
4632
|
+
}
|
|
4633
|
+
loadPersistedState() {
|
|
4634
|
+
if (!this.storageKey())
|
|
4635
|
+
return;
|
|
4636
|
+
const stored = this.storage.loadConfig(this.storageKey());
|
|
4637
|
+
if (!stored)
|
|
4638
|
+
return;
|
|
4639
|
+
this.persistedState.set(stored);
|
|
4640
|
+
if (typeof stored.selectedIndex === 'number') {
|
|
4641
|
+
this.selectedIndex.set(stored.selectedIndex);
|
|
4642
|
+
}
|
|
4643
|
+
}
|
|
4644
|
+
persistState(partial) {
|
|
4645
|
+
if (!this.storageKey())
|
|
4646
|
+
return;
|
|
4647
|
+
const next = {
|
|
4648
|
+
selectedIndex: this.selectedIndex(),
|
|
4649
|
+
preferences: this.persistedState()?.preferences,
|
|
4650
|
+
...partial,
|
|
4651
|
+
};
|
|
4652
|
+
this.persistedState.set(next);
|
|
4653
|
+
this.storage.saveConfig(this.storageKey(), next);
|
|
4654
|
+
}
|
|
4655
|
+
storageKey() {
|
|
4656
|
+
const cfg = this.wizard();
|
|
4657
|
+
const base = cfg?.preferences?.storageKey || `praxis:wizard:${cfg?.id || this.wizardId}`;
|
|
4658
|
+
return `${base}:state`;
|
|
4659
|
+
}
|
|
4660
|
+
resetProgress() {
|
|
4661
|
+
const key = this.storageKey();
|
|
4662
|
+
if (key)
|
|
4663
|
+
this.storage.clearConfig(key);
|
|
4664
|
+
this.persistedState.set(null);
|
|
4665
|
+
this.selectedIndex.set(0);
|
|
4666
|
+
this.stepper?.reset();
|
|
4667
|
+
}
|
|
4668
|
+
focusPrimaryAction() {
|
|
4669
|
+
if (typeof document === 'undefined')
|
|
4670
|
+
return;
|
|
4671
|
+
const host = document.querySelector(`[data-wizard-id="${this.wizardId}"]`) || document;
|
|
4672
|
+
const el = host.querySelector('.pwx-cta-primary');
|
|
4673
|
+
el?.focus();
|
|
4674
|
+
}
|
|
4675
|
+
focusSecondaryAction() {
|
|
4676
|
+
if (typeof document === 'undefined')
|
|
4677
|
+
return;
|
|
4678
|
+
const host = document.querySelector(`[data-wizard-id="${this.wizardId}"]`) || document;
|
|
4679
|
+
const el = host.querySelector('.pwx-cta-secondary');
|
|
4680
|
+
el?.focus();
|
|
4681
|
+
}
|
|
4682
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisWizardFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4683
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: PraxisWizardFormComponent, isStandalone: true, selector: "praxis-wizard-form", inputs: { wizardId: "wizardId", editModeEnabled: "editModeEnabled", config: "config" }, outputs: { submit: "submit" }, viewQueries: [{ propertyName: "stepper", first: true, predicate: ["stepper"], descendants: true, static: true }], ngImport: i0, template: `
|
|
4684
|
+
<section class="ft-wizard-shell" [attr.data-wizard-id]="wizardId">
|
|
4685
|
+
<div class="ft-wizard-header">
|
|
4686
|
+
<div class="ft-brand">{{ wizardBrand() }}</div>
|
|
4687
|
+
</div>
|
|
4688
|
+
|
|
4689
|
+
<mat-card class="ft-wizard-card">
|
|
4690
|
+
<div class="ft-card-header">
|
|
4691
|
+
<h2>{{ activeTitle() }}</h2>
|
|
4692
|
+
@if (activeSubtitle()) {
|
|
4693
|
+
<p>{{ activeSubtitle() }}</p>
|
|
4694
|
+
}
|
|
4695
|
+
@if (activeDescription()) {
|
|
4696
|
+
<p class="ft-card-description">{{ activeDescription() }}</p>
|
|
4697
|
+
}
|
|
4698
|
+
</div>
|
|
4699
|
+
|
|
4700
|
+
<praxis-stepper
|
|
4701
|
+
#stepper
|
|
4702
|
+
[stepperId]="wizardId"
|
|
4703
|
+
[config]="stepperConfig()"
|
|
4704
|
+
[selectedIndex]="selectedIndex()"
|
|
4705
|
+
[editModeEnabled]="editModeEnabled"
|
|
4706
|
+
(selectedIndexChange)="onSelectedIndexChange($event)"
|
|
4707
|
+
(stepFormValueChange)="onStepFormValueChange($event)"
|
|
4708
|
+
></praxis-stepper>
|
|
4709
|
+
|
|
4710
|
+
<praxis-wizard-cta-bar
|
|
4711
|
+
[primaryLabel]="primaryLabel()"
|
|
4712
|
+
[primaryDisabled]="isPrimaryDisabled()"
|
|
4713
|
+
[secondaryLabel]="secondaryLabel()"
|
|
4714
|
+
[showSecondary]="showSecondaryAction()"
|
|
4715
|
+
[sticky]="resolvedCta().sticky ?? false"
|
|
4716
|
+
(primaryClick)="onPrimaryAction()"
|
|
4717
|
+
(secondaryClick)="onSecondaryAction()"
|
|
4718
|
+
></praxis-wizard-cta-bar>
|
|
4719
|
+
</mat-card>
|
|
4720
|
+
</section>
|
|
4721
|
+
`, isInline: true, styles: [":host{display:block;min-height:100vh;background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface);font-family:\"Source Sans 3\",Segoe UI,system-ui,-apple-system,sans-serif;--praxis-wizard-accent: var(--md-sys-color-primary);--praxis-wizard-accent-on: var(--md-sys-color-on-primary);--praxis-wizard-muted: var(--md-sys-color-on-surface-variant);--praxis-wizard-card-bg: var(--md-sys-color-surface);--praxis-wizard-border: var(--md-sys-color-outline-variant);--pfx-section-gap: 12px;--pfx-form-section-surface: var(--md-sys-color-surface);--pfx-form-stroke: var(--md-sys-color-outline-variant)}.ft-wizard-shell{max-width:700px;margin:0 auto;padding:28px 16px 64px;display:flex;flex-direction:column;gap:12px}.ft-wizard-header{text-align:center;border-bottom:var(--ft-header-border, none);padding-bottom:var(--ft-header-spacing, 0px);margin-bottom:var(--ft-header-spacing, 0px)}.ft-brand{font-family:Iowan Old Style,Palatino Linotype,Book Antiqua,Palatino,serif;letter-spacing:.22em;font-size:17px;text-transform:uppercase;color:var(--md-sys-color-on-surface)}.ft-wizard-card{padding:20px 22px 16px;border-radius:var(--ft-radius, 10px);box-shadow:var(--ft-shadow, 0 6px 16px rgba(33, 24, 16, .05));border:1px solid var(--praxis-wizard-border);background:var(--praxis-wizard-card-bg)}:host ::ng-deep .ft-stepper{background:transparent}:host ::ng-deep .ft-stepper .mat-stepper-horizontal{background:transparent}:host ::ng-deep .ft-stepper-content{padding-bottom:12px}:host ::ng-deep .ft-stepper-content .form-section{border-radius:var(--ft-radius, 6px);background:var(--pfx-form-section-surface);border-color:var(--pfx-form-stroke)!important;padding:10px 12px;box-shadow:var(--ft-shadow, none)!important}:host ::ng-deep .ft-stepper-content .form-section:focus-within{border-color:var(--pfx-form-stroke);box-shadow:none}:host ::ng-deep .ft-stepper-content .mat-mdc-form-field{width:100%;--mdc-outlined-text-field-container-height: 40px;--mdc-outlined-text-field-container-shape: var(--ft-radius, 4px);--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-focus-outline-color: var(--praxis-wizard-accent)}.ft-card-header h2{margin:0;font-family:var(--ft-font-head, inherit);font-size:1.32rem;font-weight:600;color:var(--md-sys-color-on-surface)}:host ::ng-deep .ft-stepper-content .mat-mdc-form-field-infix{min-height:40px;padding-top:8px;padding-bottom:6px}:host ::ng-deep .ft-stepper-content .mat-mdc-form-field-subscript-wrapper{margin-top:4px}:host ::ng-deep .ft-stepper-content .mat-mdc-floating-label,:host ::ng-deep .ft-stepper-content .mat-mdc-form-field-label{font-size:.88rem}:host ::ng-deep .ft-stepper-content .mat-mdc-form-field-hint,:host ::ng-deep .ft-stepper-content .mat-mdc-form-field-error{font-size:.78rem}:host ::ng-deep .ft-stepper-content .mat-mdc-checkbox,:host ::ng-deep .ft-stepper-content .mat-mdc-slide-toggle{margin:4px 0}:host ::ng-deep .ft-stepper-content .mat-mdc-slide-toggle .mdc-form-field,:host ::ng-deep .ft-stepper-content .mat-mdc-checkbox .mdc-form-field{gap:10px}:host ::ng-deep .ft-stepper-content .pdx-checkbox-group-wrapper{display:flex;flex-direction:column;gap:6px}:host ::ng-deep .ft-stepper-content .pdx-checkbox-label{font-size:.82rem;font-weight:600;color:var(--md-sys-color-on-surface);margin-bottom:2px}:host ::ng-deep .ft-stepper-content .pdx-checkbox-options{display:flex;flex-direction:column;gap:4px}:host ::ng-deep .ft-stepper-content .pdx-checkbox-options.pdx-checkbox-horizontal{flex-direction:row;flex-wrap:wrap;gap:12px}:host ::ng-deep .ft-stepper-content .pdx-slide-toggle-wrapper{min-height:40px;padding:2px 0}:host ::ng-deep .ft-stepper-content .mat-mdc-slide-toggle{--mdc-switch-handle-height: 16px;--mdc-switch-handle-width: 16px;--mdc-switch-track-height: 20px;--mdc-switch-track-width: 36px}:host ::ng-deep .ft-stepper-content .pdx-slide-toggle-wrapper mat-slide-toggle{justify-content:space-between}:host ::ng-deep .ft-stepper-content .pdx-hint,:host ::ng-deep .ft-stepper-content .pdx-error{font-size:.78rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}.ft-card-header{display:flex;flex-direction:column;gap:6px;margin-bottom:6px}:host ::ng-deep .ft-stepper .mat-horizontal-stepper-header-container{margin-bottom:6px}.ft-card-header h2{margin:0;font-size:1.32rem;font-weight:600;color:var(--md-sys-color-on-surface)}.ft-card-header p{margin:0;color:var(--praxis-wizard-muted);font-size:.88rem}.ft-card-description{font-size:.84rem}.ft-card-description{color:var(--praxis-wizard-muted);font-size:.88rem}:host ::ng-deep .ft-card-title{font-weight:600;color:var(--md-sys-color-on-surface)}:host ::ng-deep .ft-card-desc{color:var(--praxis-wizard-muted);font-size:.84rem}@media(max-width:600px){.ft-wizard-shell{padding:22px 12px 48px}.ft-wizard-card{padding:16px 14px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i10.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: PraxisStepper, selector: "praxis-stepper", inputs: ["stepperId", "componentInstanceId", "config", "selectedIndexInput", "selectedIndex", "disableRippleInput", "editModeEnabled", "labelPosition", "color", "serverValidate", "stepperContext"], outputs: ["selectedIndexChange", "widgetEvent", "stepFormReady", "stepFormValueChange", "animationDone", "selectionChange"] }, { kind: "component", type: PraxisWizardCtaBarComponent, selector: "praxis-wizard-cta-bar", inputs: ["primaryLabel", "primaryDisabled", "secondaryLabel", "showSecondary", "sticky"], outputs: ["primaryClick", "secondaryClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
4722
|
+
}
|
|
4723
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: PraxisWizardFormComponent, decorators: [{
|
|
4724
|
+
type: Component,
|
|
4725
|
+
args: [{ selector: 'praxis-wizard-form', standalone: true, imports: [CommonModule, MatCardModule, MatIconModule, PraxisStepper, PraxisWizardCtaBarComponent], template: `
|
|
4726
|
+
<section class="ft-wizard-shell" [attr.data-wizard-id]="wizardId">
|
|
4727
|
+
<div class="ft-wizard-header">
|
|
4728
|
+
<div class="ft-brand">{{ wizardBrand() }}</div>
|
|
4729
|
+
</div>
|
|
4730
|
+
|
|
4731
|
+
<mat-card class="ft-wizard-card">
|
|
4732
|
+
<div class="ft-card-header">
|
|
4733
|
+
<h2>{{ activeTitle() }}</h2>
|
|
4734
|
+
@if (activeSubtitle()) {
|
|
4735
|
+
<p>{{ activeSubtitle() }}</p>
|
|
4736
|
+
}
|
|
4737
|
+
@if (activeDescription()) {
|
|
4738
|
+
<p class="ft-card-description">{{ activeDescription() }}</p>
|
|
4739
|
+
}
|
|
4740
|
+
</div>
|
|
4741
|
+
|
|
4742
|
+
<praxis-stepper
|
|
4743
|
+
#stepper
|
|
4744
|
+
[stepperId]="wizardId"
|
|
4745
|
+
[config]="stepperConfig()"
|
|
4746
|
+
[selectedIndex]="selectedIndex()"
|
|
4747
|
+
[editModeEnabled]="editModeEnabled"
|
|
4748
|
+
(selectedIndexChange)="onSelectedIndexChange($event)"
|
|
4749
|
+
(stepFormValueChange)="onStepFormValueChange($event)"
|
|
4750
|
+
></praxis-stepper>
|
|
4751
|
+
|
|
4752
|
+
<praxis-wizard-cta-bar
|
|
4753
|
+
[primaryLabel]="primaryLabel()"
|
|
4754
|
+
[primaryDisabled]="isPrimaryDisabled()"
|
|
4755
|
+
[secondaryLabel]="secondaryLabel()"
|
|
4756
|
+
[showSecondary]="showSecondaryAction()"
|
|
4757
|
+
[sticky]="resolvedCta().sticky ?? false"
|
|
4758
|
+
(primaryClick)="onPrimaryAction()"
|
|
4759
|
+
(secondaryClick)="onSecondaryAction()"
|
|
4760
|
+
></praxis-wizard-cta-bar>
|
|
4761
|
+
</mat-card>
|
|
4762
|
+
</section>
|
|
4763
|
+
`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;min-height:100vh;background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface);font-family:\"Source Sans 3\",Segoe UI,system-ui,-apple-system,sans-serif;--praxis-wizard-accent: var(--md-sys-color-primary);--praxis-wizard-accent-on: var(--md-sys-color-on-primary);--praxis-wizard-muted: var(--md-sys-color-on-surface-variant);--praxis-wizard-card-bg: var(--md-sys-color-surface);--praxis-wizard-border: var(--md-sys-color-outline-variant);--pfx-section-gap: 12px;--pfx-form-section-surface: var(--md-sys-color-surface);--pfx-form-stroke: var(--md-sys-color-outline-variant)}.ft-wizard-shell{max-width:700px;margin:0 auto;padding:28px 16px 64px;display:flex;flex-direction:column;gap:12px}.ft-wizard-header{text-align:center;border-bottom:var(--ft-header-border, none);padding-bottom:var(--ft-header-spacing, 0px);margin-bottom:var(--ft-header-spacing, 0px)}.ft-brand{font-family:Iowan Old Style,Palatino Linotype,Book Antiqua,Palatino,serif;letter-spacing:.22em;font-size:17px;text-transform:uppercase;color:var(--md-sys-color-on-surface)}.ft-wizard-card{padding:20px 22px 16px;border-radius:var(--ft-radius, 10px);box-shadow:var(--ft-shadow, 0 6px 16px rgba(33, 24, 16, .05));border:1px solid var(--praxis-wizard-border);background:var(--praxis-wizard-card-bg)}:host ::ng-deep .ft-stepper{background:transparent}:host ::ng-deep .ft-stepper .mat-stepper-horizontal{background:transparent}:host ::ng-deep .ft-stepper-content{padding-bottom:12px}:host ::ng-deep .ft-stepper-content .form-section{border-radius:var(--ft-radius, 6px);background:var(--pfx-form-section-surface);border-color:var(--pfx-form-stroke)!important;padding:10px 12px;box-shadow:var(--ft-shadow, none)!important}:host ::ng-deep .ft-stepper-content .form-section:focus-within{border-color:var(--pfx-form-stroke);box-shadow:none}:host ::ng-deep .ft-stepper-content .mat-mdc-form-field{width:100%;--mdc-outlined-text-field-container-height: 40px;--mdc-outlined-text-field-container-shape: var(--ft-radius, 4px);--mdc-outlined-text-field-outline-color: var(--md-sys-color-outline-variant);--mdc-outlined-text-field-focus-outline-color: var(--praxis-wizard-accent)}.ft-card-header h2{margin:0;font-family:var(--ft-font-head, inherit);font-size:1.32rem;font-weight:600;color:var(--md-sys-color-on-surface)}:host ::ng-deep .ft-stepper-content .mat-mdc-form-field-infix{min-height:40px;padding-top:8px;padding-bottom:6px}:host ::ng-deep .ft-stepper-content .mat-mdc-form-field-subscript-wrapper{margin-top:4px}:host ::ng-deep .ft-stepper-content .mat-mdc-floating-label,:host ::ng-deep .ft-stepper-content .mat-mdc-form-field-label{font-size:.88rem}:host ::ng-deep .ft-stepper-content .mat-mdc-form-field-hint,:host ::ng-deep .ft-stepper-content .mat-mdc-form-field-error{font-size:.78rem}:host ::ng-deep .ft-stepper-content .mat-mdc-checkbox,:host ::ng-deep .ft-stepper-content .mat-mdc-slide-toggle{margin:4px 0}:host ::ng-deep .ft-stepper-content .mat-mdc-slide-toggle .mdc-form-field,:host ::ng-deep .ft-stepper-content .mat-mdc-checkbox .mdc-form-field{gap:10px}:host ::ng-deep .ft-stepper-content .pdx-checkbox-group-wrapper{display:flex;flex-direction:column;gap:6px}:host ::ng-deep .ft-stepper-content .pdx-checkbox-label{font-size:.82rem;font-weight:600;color:var(--md-sys-color-on-surface);margin-bottom:2px}:host ::ng-deep .ft-stepper-content .pdx-checkbox-options{display:flex;flex-direction:column;gap:4px}:host ::ng-deep .ft-stepper-content .pdx-checkbox-options.pdx-checkbox-horizontal{flex-direction:row;flex-wrap:wrap;gap:12px}:host ::ng-deep .ft-stepper-content .pdx-slide-toggle-wrapper{min-height:40px;padding:2px 0}:host ::ng-deep .ft-stepper-content .mat-mdc-slide-toggle{--mdc-switch-handle-height: 16px;--mdc-switch-handle-width: 16px;--mdc-switch-track-height: 20px;--mdc-switch-track-width: 36px}:host ::ng-deep .ft-stepper-content .pdx-slide-toggle-wrapper mat-slide-toggle{justify-content:space-between}:host ::ng-deep .ft-stepper-content .pdx-hint,:host ::ng-deep .ft-stepper-content .pdx-error{font-size:.78rem;color:var(--praxis-wizard-muted, var(--md-sys-color-on-surface-variant))}.ft-card-header{display:flex;flex-direction:column;gap:6px;margin-bottom:6px}:host ::ng-deep .ft-stepper .mat-horizontal-stepper-header-container{margin-bottom:6px}.ft-card-header h2{margin:0;font-size:1.32rem;font-weight:600;color:var(--md-sys-color-on-surface)}.ft-card-header p{margin:0;color:var(--praxis-wizard-muted);font-size:.88rem}.ft-card-description{font-size:.84rem}.ft-card-description{color:var(--praxis-wizard-muted);font-size:.88rem}:host ::ng-deep .ft-card-title{font-weight:600;color:var(--md-sys-color-on-surface)}:host ::ng-deep .ft-card-desc{color:var(--praxis-wizard-muted);font-size:.84rem}@media(max-width:600px){.ft-wizard-shell{padding:22px 12px 48px}.ft-wizard-card{padding:16px 14px}}\n"] }]
|
|
4764
|
+
}], ctorParameters: () => [], propDecorators: { stepper: [{
|
|
4765
|
+
type: ViewChild,
|
|
4766
|
+
args: ['stepper', { static: true }]
|
|
4767
|
+
}], wizardId: [{
|
|
4768
|
+
type: Input,
|
|
4769
|
+
args: [{ required: true }]
|
|
4770
|
+
}], editModeEnabled: [{
|
|
4771
|
+
type: Input
|
|
4772
|
+
}], config: [{
|
|
4773
|
+
type: Input
|
|
4774
|
+
}], submit: [{
|
|
4775
|
+
type: Output
|
|
4776
|
+
}] } });
|
|
4777
|
+
function pickPreferenceValues(value, fields) {
|
|
4778
|
+
if (!value || !fields || fields.length === 0)
|
|
4779
|
+
return value || {};
|
|
4780
|
+
const out = {};
|
|
4781
|
+
fields.forEach((key) => {
|
|
4782
|
+
if (Object.prototype.hasOwnProperty.call(value, key))
|
|
4783
|
+
out[key] = value[key];
|
|
4784
|
+
});
|
|
4785
|
+
return out;
|
|
4786
|
+
}
|
|
4787
|
+
function applyPreferenceDefaults(cfg, values) {
|
|
4788
|
+
const pref = cfg.preferences;
|
|
4789
|
+
if (!pref?.stepId || !values)
|
|
4790
|
+
return cfg;
|
|
4791
|
+
const steps = cfg.steps.map((step) => {
|
|
4792
|
+
if (step.id !== pref.stepId || !step.form?.config?.fieldMetadata)
|
|
4793
|
+
return step;
|
|
4794
|
+
const fieldMetadata = step.form.config.fieldMetadata.map((meta) => {
|
|
4795
|
+
if (meta.name && Object.prototype.hasOwnProperty.call(values, meta.name)) {
|
|
4796
|
+
return { ...meta, defaultValue: values[meta.name] };
|
|
4797
|
+
}
|
|
4798
|
+
return meta;
|
|
4799
|
+
});
|
|
4800
|
+
return {
|
|
4801
|
+
...step,
|
|
4802
|
+
form: {
|
|
4803
|
+
...step.form,
|
|
4804
|
+
config: {
|
|
4805
|
+
...step.form.config,
|
|
4806
|
+
fieldMetadata,
|
|
4807
|
+
},
|
|
4808
|
+
},
|
|
4809
|
+
};
|
|
4810
|
+
});
|
|
4811
|
+
return { ...cfg, steps };
|
|
4812
|
+
}
|
|
4813
|
+
|
|
2037
4814
|
/*
|
|
2038
4815
|
* Public API Surface of praxis-stepper
|
|
2039
4816
|
*/
|
|
@@ -2042,5 +4819,5 @@ function providePraxisStepperMetadata() {
|
|
|
2042
4819
|
* Generated bundle index. Do not edit.
|
|
2043
4820
|
*/
|
|
2044
4821
|
|
|
2045
|
-
export { PRAXIS_STEPPER_COMPONENT_METADATA, PraxisStepper, PraxisStepperConfigEditor, providePraxisStepperMetadata };
|
|
4822
|
+
export { FT_WIZARD_CONFIG, FT_WIZARD_JSON, PRAXIS_STEPPER_COMPONENT_METADATA, PRAXIS_WIZARD_BENEFITS_METADATA, PRAXIS_WIZARD_CONTENT_METADATA, PRAXIS_WIZARD_DIVIDER_METADATA, PRAXIS_WIZARD_NOTICE_METADATA, PraxisStepper, PraxisStepperConfigEditor, PraxisWizardFormComponent, STEPPER_AI_CAPABILITIES, providePraxisStepperMetadata };
|
|
2046
4823
|
//# sourceMappingURL=praxisui-stepper.mjs.map
|