@praxisui/stepper 6.0.0-beta.0 → 8.0.0-beta.0
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 +13 -3
- package/fesm2022/praxisui-stepper.mjs +251 -921
- package/index.d.ts +15 -24
- package/package.json +8 -7
|
@@ -9,7 +9,7 @@ import * as i6 from '@angular/material/button';
|
|
|
9
9
|
import { MatButtonModule } from '@angular/material/button';
|
|
10
10
|
import * as i5$1 from '@angular/material/icon';
|
|
11
11
|
import { MatIconModule } from '@angular/material/icon';
|
|
12
|
-
import { providePraxisI18n, PraxisI18nService, IconPickerService, PraxisIconDirective, deepMerge, ASYNC_CONFIG_STORAGE, ComponentKeyService, LoggerService, DynamicWidgetLoaderDirective, EmptyStateCardComponent, EDITORIAL_WIDGET_TAG, ComponentMetadataRegistry, createCorporateLoggerConfig, ConsoleLoggerSink, CONFIG_STORAGE } from '@praxisui/core';
|
|
12
|
+
import { providePraxisI18n, PraxisI18nService, IconPickerService, createEmptyRichContentDocument, PraxisIconDirective, deepMerge, ASYNC_CONFIG_STORAGE, ComponentKeyService, LoggerService, DynamicWidgetLoaderDirective, EmptyStateCardComponent, EDITORIAL_WIDGET_TAG, ComponentMetadataRegistry, createCorporateLoggerConfig, ConsoleLoggerSink, CONFIG_STORAGE } from '@praxisui/core';
|
|
13
13
|
import * as i2 from '@angular/forms';
|
|
14
14
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
15
15
|
import { PraxisDynamicFormConfigEditor, PraxisDynamicForm } from '@praxisui/dynamic-form';
|
|
@@ -26,9 +26,7 @@ import * as i9 from '@angular/material/tooltip';
|
|
|
26
26
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
27
27
|
import * as i1 from '@angular/material/dialog';
|
|
28
28
|
import { MAT_DIALOG_DATA, MatDialogModule, MatDialog } from '@angular/material/dialog';
|
|
29
|
-
import * as i10 from '@angular/material/
|
|
30
|
-
import { MatMenuModule } from '@angular/material/menu';
|
|
31
|
-
import * as i11 from '@angular/material/tabs';
|
|
29
|
+
import * as i10 from '@angular/material/tabs';
|
|
32
30
|
import { MatTabsModule } from '@angular/material/tabs';
|
|
33
31
|
import { BehaviorSubject } from 'rxjs';
|
|
34
32
|
import { PraxisListConfigEditor } from '@praxisui/list';
|
|
@@ -37,6 +35,7 @@ import { ComponentPaletteDialogComponent } from '@praxisui/page-builder';
|
|
|
37
35
|
import * as i5 from '@angular/material/checkbox';
|
|
38
36
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
39
37
|
import { BaseAiAdapter, PraxisAiAssistantComponent } from '@praxisui/ai';
|
|
38
|
+
import { PraxisRichContent } from '@praxisui/rich-content';
|
|
40
39
|
import { take } from 'rxjs/operators';
|
|
41
40
|
import * as i1$2 from '@angular/material/card';
|
|
42
41
|
import { MatCardModule } from '@angular/material/card';
|
|
@@ -138,376 +137,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
138
137
|
args: [MAT_DIALOG_DATA]
|
|
139
138
|
}] }] });
|
|
140
139
|
|
|
141
|
-
class WizardWidgetConfigDialogComponent {
|
|
142
|
-
ref;
|
|
143
|
-
wizardWidgetId;
|
|
144
|
-
dialogTitle;
|
|
145
|
-
model;
|
|
146
|
-
originalInputs;
|
|
147
|
-
constructor(ref, data) {
|
|
148
|
-
this.ref = ref;
|
|
149
|
-
const id = (data?.widgetId || '');
|
|
150
|
-
this.wizardWidgetId = this.isWizardWidgetId(id) ? id : null;
|
|
151
|
-
this.originalInputs = { ...(data?.inputs || {}) };
|
|
152
|
-
this.model = this.buildDraft(this.originalInputs);
|
|
153
|
-
this.dialogTitle = this.resolveTitle(this.wizardWidgetId);
|
|
154
|
-
}
|
|
155
|
-
get benefits() {
|
|
156
|
-
if (!Array.isArray(this.model.items))
|
|
157
|
-
this.model.items = [];
|
|
158
|
-
return this.model.items;
|
|
159
|
-
}
|
|
160
|
-
addBenefit() {
|
|
161
|
-
this.benefits.push({ title: '', text: '', icon: '' });
|
|
162
|
-
}
|
|
163
|
-
removeBenefit(index) {
|
|
164
|
-
this.benefits.splice(index, 1);
|
|
165
|
-
}
|
|
166
|
-
get statusMessage() {
|
|
167
|
-
switch (this.wizardWidgetId) {
|
|
168
|
-
case 'praxis-wizard-content':
|
|
169
|
-
return {
|
|
170
|
-
title: 'Legado em deprecação',
|
|
171
|
-
body: 'Este bloco continua suportado para compatibilidade, mas novo authoring deve preferir widget:rich-text-block. O shape atual do wizard segue válido neste ciclo.',
|
|
172
|
-
};
|
|
173
|
-
case 'praxis-wizard-inline-notice':
|
|
174
|
-
return {
|
|
175
|
-
title: 'Semântica em aberto',
|
|
176
|
-
body: 'Este bloco permanece ativo no wizard até a definição final entre legal-notice e um eventual info-callout compartilhado.',
|
|
177
|
-
};
|
|
178
|
-
case 'praxis-wizard-benefits':
|
|
179
|
-
return {
|
|
180
|
-
title: 'Mantido temporariamente',
|
|
181
|
-
body: 'Ainda não existe equivalente canônico compartilhado para este grid no backlog editorial atual.',
|
|
182
|
-
};
|
|
183
|
-
case 'praxis-wizard-divider':
|
|
184
|
-
return {
|
|
185
|
-
title: 'Mantido temporariamente',
|
|
186
|
-
body: 'Este divisor continua como bloco legado do wizard enquanto não houver equivalente compartilhado priorizado.',
|
|
187
|
-
};
|
|
188
|
-
default:
|
|
189
|
-
return null;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
cancel() {
|
|
193
|
-
this.ref.close();
|
|
194
|
-
}
|
|
195
|
-
save() {
|
|
196
|
-
const next = { ...this.originalInputs, ...this.buildInputsForWidget() };
|
|
197
|
-
if (typeof next.blockId === 'string') {
|
|
198
|
-
next.blockId = next.blockId.trim();
|
|
199
|
-
}
|
|
200
|
-
if (!next.blockId)
|
|
201
|
-
delete next.blockId;
|
|
202
|
-
this.ref.close({ inputs: next });
|
|
203
|
-
}
|
|
204
|
-
isWizardWidgetId(value) {
|
|
205
|
-
return (value === 'praxis-wizard-benefits'
|
|
206
|
-
|| value === 'praxis-wizard-content'
|
|
207
|
-
|| value === 'praxis-wizard-inline-notice'
|
|
208
|
-
|| value === 'praxis-wizard-divider');
|
|
209
|
-
}
|
|
210
|
-
resolveTitle(id) {
|
|
211
|
-
switch (id) {
|
|
212
|
-
case 'praxis-wizard-benefits':
|
|
213
|
-
return 'Editar grade de benefícios';
|
|
214
|
-
case 'praxis-wizard-content':
|
|
215
|
-
return 'Editar bloco de conteúdo';
|
|
216
|
-
case 'praxis-wizard-inline-notice':
|
|
217
|
-
return 'Editar aviso inline';
|
|
218
|
-
case 'praxis-wizard-divider':
|
|
219
|
-
return 'Editar divisor';
|
|
220
|
-
default:
|
|
221
|
-
return 'Editar Widget do Wizard';
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
buildDraft(inputs) {
|
|
225
|
-
return {
|
|
226
|
-
blockId: inputs.blockId || '',
|
|
227
|
-
title: inputs.title || '',
|
|
228
|
-
subtitle: inputs.subtitle || '',
|
|
229
|
-
text: inputs.text || '',
|
|
230
|
-
caption: inputs.caption || '',
|
|
231
|
-
tone: inputs.tone || 'neutral',
|
|
232
|
-
label: inputs.label || '',
|
|
233
|
-
columns: Number.isFinite(Number(inputs.columns)) ? Number(inputs.columns) : 4,
|
|
234
|
-
boxed: !!inputs.boxed,
|
|
235
|
-
items: Array.isArray(inputs.items)
|
|
236
|
-
? inputs.items.map((item) => ({ icon: item?.icon || '', title: item?.title || '', text: item?.text || '' }))
|
|
237
|
-
: [],
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
buildInputsForWidget() {
|
|
241
|
-
if (!this.wizardWidgetId)
|
|
242
|
-
return { ...this.model };
|
|
243
|
-
const base = {};
|
|
244
|
-
if (this.model.blockId?.trim())
|
|
245
|
-
base.blockId = this.model.blockId.trim();
|
|
246
|
-
switch (this.wizardWidgetId) {
|
|
247
|
-
case 'praxis-wizard-inline-notice':
|
|
248
|
-
base.text = this.model.text || '';
|
|
249
|
-
base.tone = this.model.tone || 'neutral';
|
|
250
|
-
return base;
|
|
251
|
-
case 'praxis-wizard-content':
|
|
252
|
-
base.title = this.model.title || '';
|
|
253
|
-
base.subtitle = this.model.subtitle || '';
|
|
254
|
-
base.text = this.model.text || '';
|
|
255
|
-
base.caption = this.model.caption || '';
|
|
256
|
-
return base;
|
|
257
|
-
case 'praxis-wizard-divider':
|
|
258
|
-
base.label = this.model.label || '';
|
|
259
|
-
return base;
|
|
260
|
-
case 'praxis-wizard-benefits':
|
|
261
|
-
base.title = this.model.title || '';
|
|
262
|
-
base.columns = this.safeColumns(this.model.columns);
|
|
263
|
-
base.boxed = !!this.model.boxed;
|
|
264
|
-
base.items = this.benefits
|
|
265
|
-
.map((item) => ({
|
|
266
|
-
icon: item.icon || '',
|
|
267
|
-
title: item.title || '',
|
|
268
|
-
text: item.text || '',
|
|
269
|
-
}))
|
|
270
|
-
.filter((item) => item.title || item.text || item.icon);
|
|
271
|
-
return base;
|
|
272
|
-
default:
|
|
273
|
-
return base;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
safeColumns(value) {
|
|
277
|
-
const parsed = Number(value);
|
|
278
|
-
if (!Number.isFinite(parsed) || parsed < 1)
|
|
279
|
-
return 1;
|
|
280
|
-
return Math.floor(parsed);
|
|
281
|
-
}
|
|
282
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: WizardWidgetConfigDialogComponent, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
283
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: WizardWidgetConfigDialogComponent, isStandalone: true, selector: "praxis-wizard-widget-config-dialog", ngImport: i0, template: `
|
|
284
|
-
<h2 mat-dialog-title>{{ dialogTitle }}</h2>
|
|
285
|
-
|
|
286
|
-
<div mat-dialog-content class="dialog-grid">
|
|
287
|
-
<div class="status-banner" *ngIf="statusMessage as status">
|
|
288
|
-
<strong>{{ status.title }}</strong>
|
|
289
|
-
<span>{{ status.body }}</span>
|
|
290
|
-
</div>
|
|
291
|
-
|
|
292
|
-
<ng-container [ngSwitch]="wizardWidgetId">
|
|
293
|
-
<ng-container *ngSwitchCase="'praxis-wizard-inline-notice'">
|
|
294
|
-
<mat-form-field appearance="outline" class="full">
|
|
295
|
-
<mat-label>Texto</mat-label>
|
|
296
|
-
<input matInput [(ngModel)]="model.text" placeholder="Mensagem do aviso" />
|
|
297
|
-
</mat-form-field>
|
|
298
|
-
<mat-form-field appearance="outline">
|
|
299
|
-
<mat-label>Tom</mat-label>
|
|
300
|
-
<select matNativeControl [(ngModel)]="model.tone">
|
|
301
|
-
<option value="neutral">Neutro</option>
|
|
302
|
-
<option value="info">Informativo</option>
|
|
303
|
-
<option value="warning">Atenção</option>
|
|
304
|
-
</select>
|
|
305
|
-
</mat-form-field>
|
|
306
|
-
</ng-container>
|
|
307
|
-
|
|
308
|
-
<ng-container *ngSwitchCase="'praxis-wizard-content'">
|
|
309
|
-
<mat-form-field appearance="outline">
|
|
310
|
-
<mat-label>Título</mat-label>
|
|
311
|
-
<input matInput [(ngModel)]="model.title" />
|
|
312
|
-
</mat-form-field>
|
|
313
|
-
<mat-form-field appearance="outline">
|
|
314
|
-
<mat-label>Subtítulo</mat-label>
|
|
315
|
-
<input matInput [(ngModel)]="model.subtitle" />
|
|
316
|
-
</mat-form-field>
|
|
317
|
-
<mat-form-field appearance="outline" class="full">
|
|
318
|
-
<mat-label>Texto</mat-label>
|
|
319
|
-
<input matInput [(ngModel)]="model.text" />
|
|
320
|
-
</mat-form-field>
|
|
321
|
-
<mat-form-field appearance="outline" class="full">
|
|
322
|
-
<mat-label>Legenda</mat-label>
|
|
323
|
-
<input matInput [(ngModel)]="model.caption" />
|
|
324
|
-
</mat-form-field>
|
|
325
|
-
</ng-container>
|
|
326
|
-
|
|
327
|
-
<ng-container *ngSwitchCase="'praxis-wizard-divider'">
|
|
328
|
-
<mat-form-field appearance="outline" class="full">
|
|
329
|
-
<mat-label>Rótulo</mat-label>
|
|
330
|
-
<input matInput [(ngModel)]="model.label" placeholder="Opcional" />
|
|
331
|
-
</mat-form-field>
|
|
332
|
-
</ng-container>
|
|
333
|
-
|
|
334
|
-
<ng-container *ngSwitchCase="'praxis-wizard-benefits'">
|
|
335
|
-
<mat-form-field appearance="outline">
|
|
336
|
-
<mat-label>Título</mat-label>
|
|
337
|
-
<input matInput [(ngModel)]="model.title" />
|
|
338
|
-
</mat-form-field>
|
|
339
|
-
<mat-form-field appearance="outline">
|
|
340
|
-
<mat-label>Colunas</mat-label>
|
|
341
|
-
<input matInput type="number" min="1" [(ngModel)]="model.columns" />
|
|
342
|
-
</mat-form-field>
|
|
343
|
-
<mat-checkbox [(ngModel)]="model.boxed">Cards com contorno</mat-checkbox>
|
|
344
|
-
|
|
345
|
-
<div class="benefits">
|
|
346
|
-
<div class="benefits-head">
|
|
347
|
-
<strong>Itens de benefício</strong>
|
|
348
|
-
<button mat-stroked-button type="button" (click)="addBenefit()">Adicionar item</button>
|
|
349
|
-
</div>
|
|
350
|
-
<div class="benefit-card" *ngFor="let item of benefits; let i = index">
|
|
351
|
-
<div class="benefit-head">
|
|
352
|
-
<span>Item {{ i + 1 }}</span>
|
|
353
|
-
<button mat-button color="warn" type="button" (click)="removeBenefit(i)">Remover</button>
|
|
354
|
-
</div>
|
|
355
|
-
<mat-form-field appearance="outline">
|
|
356
|
-
<mat-label>Ícone</mat-label>
|
|
357
|
-
<input matInput [(ngModel)]="item.icon" placeholder="Ex.: info" />
|
|
358
|
-
</mat-form-field>
|
|
359
|
-
<mat-form-field appearance="outline">
|
|
360
|
-
<mat-label>Título</mat-label>
|
|
361
|
-
<input matInput [(ngModel)]="item.title" />
|
|
362
|
-
</mat-form-field>
|
|
363
|
-
<mat-form-field appearance="outline" class="full">
|
|
364
|
-
<mat-label>Texto</mat-label>
|
|
365
|
-
<input matInput [(ngModel)]="item.text" />
|
|
366
|
-
</mat-form-field>
|
|
367
|
-
</div>
|
|
368
|
-
</div>
|
|
369
|
-
</ng-container>
|
|
370
|
-
</ng-container>
|
|
371
|
-
|
|
372
|
-
<details class="advanced full">
|
|
373
|
-
<summary>Avançado</summary>
|
|
374
|
-
<div class="advanced-body">
|
|
375
|
-
<mat-form-field appearance="outline" class="full">
|
|
376
|
-
<mat-label>Block ID legado (avançado)</mat-label>
|
|
377
|
-
<input matInput [(ngModel)]="model.blockId" placeholder="Ex.: ft-edit-wizard:access:block:hero" />
|
|
378
|
-
<mat-hint>Identificador operacional legado do wizard para telemetria/E2E e compatibilidade com editor/adapter. No modelo convergido, instanceId será a convenção editorial preferencial.</mat-hint>
|
|
379
|
-
</mat-form-field>
|
|
380
|
-
</div>
|
|
381
|
-
</details>
|
|
382
|
-
</div>
|
|
383
|
-
|
|
384
|
-
<div mat-dialog-actions align="end">
|
|
385
|
-
<button mat-button type="button" (click)="cancel()">Cancelar</button>
|
|
386
|
-
<button mat-flat-button color="primary" type="button" (click)="save()">Salvar</button>
|
|
387
|
-
</div>
|
|
388
|
-
`, isInline: true, styles: [".dialog-grid{display:grid;gap:12px;min-width:min(760px,92vw)}.full{grid-column:1 / -1}.status-banner{display:grid;gap:4px;padding:10px 12px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant);font-size:12px}.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.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { 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"] }] });
|
|
389
|
-
}
|
|
390
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: WizardWidgetConfigDialogComponent, decorators: [{
|
|
391
|
-
type: Component,
|
|
392
|
-
args: [{ selector: 'praxis-wizard-widget-config-dialog', standalone: true, imports: [
|
|
393
|
-
CommonModule,
|
|
394
|
-
FormsModule,
|
|
395
|
-
MatDialogModule,
|
|
396
|
-
MatFormFieldModule,
|
|
397
|
-
MatInputModule,
|
|
398
|
-
MatCheckboxModule,
|
|
399
|
-
MatButtonModule,
|
|
400
|
-
], template: `
|
|
401
|
-
<h2 mat-dialog-title>{{ dialogTitle }}</h2>
|
|
402
|
-
|
|
403
|
-
<div mat-dialog-content class="dialog-grid">
|
|
404
|
-
<div class="status-banner" *ngIf="statusMessage as status">
|
|
405
|
-
<strong>{{ status.title }}</strong>
|
|
406
|
-
<span>{{ status.body }}</span>
|
|
407
|
-
</div>
|
|
408
|
-
|
|
409
|
-
<ng-container [ngSwitch]="wizardWidgetId">
|
|
410
|
-
<ng-container *ngSwitchCase="'praxis-wizard-inline-notice'">
|
|
411
|
-
<mat-form-field appearance="outline" class="full">
|
|
412
|
-
<mat-label>Texto</mat-label>
|
|
413
|
-
<input matInput [(ngModel)]="model.text" placeholder="Mensagem do aviso" />
|
|
414
|
-
</mat-form-field>
|
|
415
|
-
<mat-form-field appearance="outline">
|
|
416
|
-
<mat-label>Tom</mat-label>
|
|
417
|
-
<select matNativeControl [(ngModel)]="model.tone">
|
|
418
|
-
<option value="neutral">Neutro</option>
|
|
419
|
-
<option value="info">Informativo</option>
|
|
420
|
-
<option value="warning">Atenção</option>
|
|
421
|
-
</select>
|
|
422
|
-
</mat-form-field>
|
|
423
|
-
</ng-container>
|
|
424
|
-
|
|
425
|
-
<ng-container *ngSwitchCase="'praxis-wizard-content'">
|
|
426
|
-
<mat-form-field appearance="outline">
|
|
427
|
-
<mat-label>Título</mat-label>
|
|
428
|
-
<input matInput [(ngModel)]="model.title" />
|
|
429
|
-
</mat-form-field>
|
|
430
|
-
<mat-form-field appearance="outline">
|
|
431
|
-
<mat-label>Subtítulo</mat-label>
|
|
432
|
-
<input matInput [(ngModel)]="model.subtitle" />
|
|
433
|
-
</mat-form-field>
|
|
434
|
-
<mat-form-field appearance="outline" class="full">
|
|
435
|
-
<mat-label>Texto</mat-label>
|
|
436
|
-
<input matInput [(ngModel)]="model.text" />
|
|
437
|
-
</mat-form-field>
|
|
438
|
-
<mat-form-field appearance="outline" class="full">
|
|
439
|
-
<mat-label>Legenda</mat-label>
|
|
440
|
-
<input matInput [(ngModel)]="model.caption" />
|
|
441
|
-
</mat-form-field>
|
|
442
|
-
</ng-container>
|
|
443
|
-
|
|
444
|
-
<ng-container *ngSwitchCase="'praxis-wizard-divider'">
|
|
445
|
-
<mat-form-field appearance="outline" class="full">
|
|
446
|
-
<mat-label>Rótulo</mat-label>
|
|
447
|
-
<input matInput [(ngModel)]="model.label" placeholder="Opcional" />
|
|
448
|
-
</mat-form-field>
|
|
449
|
-
</ng-container>
|
|
450
|
-
|
|
451
|
-
<ng-container *ngSwitchCase="'praxis-wizard-benefits'">
|
|
452
|
-
<mat-form-field appearance="outline">
|
|
453
|
-
<mat-label>Título</mat-label>
|
|
454
|
-
<input matInput [(ngModel)]="model.title" />
|
|
455
|
-
</mat-form-field>
|
|
456
|
-
<mat-form-field appearance="outline">
|
|
457
|
-
<mat-label>Colunas</mat-label>
|
|
458
|
-
<input matInput type="number" min="1" [(ngModel)]="model.columns" />
|
|
459
|
-
</mat-form-field>
|
|
460
|
-
<mat-checkbox [(ngModel)]="model.boxed">Cards com contorno</mat-checkbox>
|
|
461
|
-
|
|
462
|
-
<div class="benefits">
|
|
463
|
-
<div class="benefits-head">
|
|
464
|
-
<strong>Itens de benefício</strong>
|
|
465
|
-
<button mat-stroked-button type="button" (click)="addBenefit()">Adicionar item</button>
|
|
466
|
-
</div>
|
|
467
|
-
<div class="benefit-card" *ngFor="let item of benefits; let i = index">
|
|
468
|
-
<div class="benefit-head">
|
|
469
|
-
<span>Item {{ i + 1 }}</span>
|
|
470
|
-
<button mat-button color="warn" type="button" (click)="removeBenefit(i)">Remover</button>
|
|
471
|
-
</div>
|
|
472
|
-
<mat-form-field appearance="outline">
|
|
473
|
-
<mat-label>Ícone</mat-label>
|
|
474
|
-
<input matInput [(ngModel)]="item.icon" placeholder="Ex.: info" />
|
|
475
|
-
</mat-form-field>
|
|
476
|
-
<mat-form-field appearance="outline">
|
|
477
|
-
<mat-label>Título</mat-label>
|
|
478
|
-
<input matInput [(ngModel)]="item.title" />
|
|
479
|
-
</mat-form-field>
|
|
480
|
-
<mat-form-field appearance="outline" class="full">
|
|
481
|
-
<mat-label>Texto</mat-label>
|
|
482
|
-
<input matInput [(ngModel)]="item.text" />
|
|
483
|
-
</mat-form-field>
|
|
484
|
-
</div>
|
|
485
|
-
</div>
|
|
486
|
-
</ng-container>
|
|
487
|
-
</ng-container>
|
|
488
|
-
|
|
489
|
-
<details class="advanced full">
|
|
490
|
-
<summary>Avançado</summary>
|
|
491
|
-
<div class="advanced-body">
|
|
492
|
-
<mat-form-field appearance="outline" class="full">
|
|
493
|
-
<mat-label>Block ID legado (avançado)</mat-label>
|
|
494
|
-
<input matInput [(ngModel)]="model.blockId" placeholder="Ex.: ft-edit-wizard:access:block:hero" />
|
|
495
|
-
<mat-hint>Identificador operacional legado do wizard para telemetria/E2E e compatibilidade com editor/adapter. No modelo convergido, instanceId será a convenção editorial preferencial.</mat-hint>
|
|
496
|
-
</mat-form-field>
|
|
497
|
-
</div>
|
|
498
|
-
</details>
|
|
499
|
-
</div>
|
|
500
|
-
|
|
501
|
-
<div mat-dialog-actions align="end">
|
|
502
|
-
<button mat-button type="button" (click)="cancel()">Cancelar</button>
|
|
503
|
-
<button mat-flat-button color="primary" type="button" (click)="save()">Salvar</button>
|
|
504
|
-
</div>
|
|
505
|
-
`, styles: [".dialog-grid{display:grid;gap:12px;min-width:min(760px,92vw)}.full{grid-column:1 / -1}.status-banner{display:grid;gap:4px;padding:10px 12px;border-radius:10px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant);font-size:12px}.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"] }]
|
|
506
|
-
}], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
|
|
507
|
-
type: Inject,
|
|
508
|
-
args: [MAT_DIALOG_DATA]
|
|
509
|
-
}] }] });
|
|
510
|
-
|
|
511
140
|
const PRAXIS_STEPPER_EN_US = {
|
|
512
141
|
'praxis.stepper.editor.tabs.general': 'General',
|
|
513
142
|
'praxis.stepper.editor.tabs.steps': 'Steps',
|
|
@@ -709,7 +338,7 @@ const PRAXIS_STEPPER_EN_US = {
|
|
|
709
338
|
'praxis.stepper.editor.summary.noContent': 'No content',
|
|
710
339
|
'praxis.stepper.editor.summary.labelPrefix': 'Label: {{label}}',
|
|
711
340
|
'praxis.stepper.editor.summary.dividerNoLabel': 'Divider without label',
|
|
712
|
-
'praxis.stepper.editor.status.contentLegacy': 'Deprecated legacy: new authoring should prefer
|
|
341
|
+
'praxis.stepper.editor.status.contentLegacy': 'Deprecated legacy: new authoring should prefer step rich content documents. This block remains supported only for existing configurations.',
|
|
713
342
|
'praxis.stepper.editor.status.noticeCurrent': 'Kept in the current cycle: final semantics are still being defined between legal-notice and info-callout.',
|
|
714
343
|
'praxis.stepper.editor.status.benefitsTemporary': 'Temporarily kept: still no canonical equivalent in the editorial backlog.',
|
|
715
344
|
'praxis.stepper.editor.status.dividerTemporary': 'Temporarily kept: legacy separator without a prioritized shared equivalent.',
|
|
@@ -920,7 +549,7 @@ const PRAXIS_STEPPER_PT_BR = {
|
|
|
920
549
|
'praxis.stepper.editor.summary.noContent': 'Sem conteúdo',
|
|
921
550
|
'praxis.stepper.editor.summary.labelPrefix': 'Rótulo: {{label}}',
|
|
922
551
|
'praxis.stepper.editor.summary.dividerNoLabel': 'Divisor sem rótulo',
|
|
923
|
-
'praxis.stepper.editor.status.contentLegacy': 'Legado em depreciação: novas criações devem preferir
|
|
552
|
+
'praxis.stepper.editor.status.contentLegacy': 'Legado em depreciação: novas criações devem preferir documentos de rich content da etapa. O bloco continua suportado apenas para configurações existentes.',
|
|
924
553
|
'praxis.stepper.editor.status.noticeCurrent': 'Mantido no ciclo atual: semântica final ainda em definição entre aviso-legal (legal-notice) e destaque-informativo (info-callout).',
|
|
925
554
|
'praxis.stepper.editor.status.benefitsTemporary': 'Mantido temporariamente: ainda sem equivalente canônico no backlog editorial.',
|
|
926
555
|
'praxis.stepper.editor.status.dividerTemporary': 'Mantido temporariamente: separador legado sem equivalente compartilhado priorizado.',
|
|
@@ -1268,150 +897,78 @@ class PraxisStepperConfigEditor {
|
|
|
1268
897
|
}
|
|
1269
898
|
ensureWidgets() { const s = this.activeStep; if (!s.widgets)
|
|
1270
899
|
s.widgets = []; return s.widgets; }
|
|
1271
|
-
ensureWidgetsBeforeForm() { const s = this.activeStep; if (!s.widgetsBeforeForm)
|
|
1272
|
-
s.widgetsBeforeForm = []; return s.widgetsBeforeForm; }
|
|
1273
900
|
displayWidgetName(w) {
|
|
1274
901
|
switch (w.id) {
|
|
1275
902
|
case 'praxis-list': return this.tx('editor.widgets.listSelection', 'List (selection)');
|
|
1276
903
|
case 'pdx-material-searchable-select': return this.tx('editor.widgets.searchableSelection', 'Searchable selection');
|
|
1277
904
|
case 'praxis-files-upload': return this.tx('editor.widgets.fileUpload', 'File upload');
|
|
1278
905
|
case 'praxis-dynamic-form': return this.tx('editor.widgets.form', 'Form');
|
|
1279
|
-
case 'praxis-wizard-benefits': return this.tx('editor.widgets.benefits', 'Benefits grid');
|
|
1280
|
-
case 'praxis-wizard-content': return this.tx('editor.widgets.content', 'Content block');
|
|
1281
|
-
case 'praxis-wizard-inline-notice': return this.tx('editor.widgets.notice', 'Inline notice');
|
|
1282
|
-
case 'praxis-wizard-divider': return this.tx('editor.widgets.divider', 'Divider');
|
|
1283
906
|
default: return w.inputs?.title || w.inputs?.label || this.tx('editor.widgets.default', 'Widget');
|
|
1284
907
|
}
|
|
1285
908
|
}
|
|
1286
|
-
editorialBeforeWidgets(step) {
|
|
1287
|
-
return (step.widgetsBeforeForm || []).filter((w) => this.isWizardWidgetId(w.id));
|
|
1288
|
-
}
|
|
1289
|
-
editorialAfterWidgets(step) {
|
|
1290
|
-
return (step.widgets || []).filter((w) => this.isWizardWidgetId(w.id));
|
|
1291
|
-
}
|
|
1292
909
|
advancedWidgets(step) {
|
|
1293
|
-
return
|
|
1294
|
-
}
|
|
1295
|
-
widgetBlockId(w) {
|
|
1296
|
-
const blockId = String(w.inputs?.blockId || '').trim();
|
|
1297
|
-
return blockId || null;
|
|
1298
|
-
}
|
|
1299
|
-
editorialWidgetSummary(w) {
|
|
1300
|
-
const inputs = w.inputs || {};
|
|
1301
|
-
const shorten = (value, max = 72) => {
|
|
1302
|
-
const text = (value || '').trim();
|
|
1303
|
-
if (!text)
|
|
1304
|
-
return '';
|
|
1305
|
-
return text.length > max ? `${text.slice(0, max - 3)}...` : text;
|
|
1306
|
-
};
|
|
1307
|
-
switch (w.id) {
|
|
1308
|
-
case 'praxis-wizard-benefits': {
|
|
1309
|
-
const count = Array.isArray(inputs.items) ? inputs.items.length : 0;
|
|
1310
|
-
const cols = Number.isFinite(Number(inputs.columns)) ? Number(inputs.columns) : 4;
|
|
1311
|
-
return this.tx('editor.summary.itemsColumns', '{{count}} item(s) • {{cols}} column(s)')
|
|
1312
|
-
.replace('{{count}}', `${count}`)
|
|
1313
|
-
.replace('{{cols}}', `${cols}`);
|
|
1314
|
-
}
|
|
1315
|
-
case 'praxis-wizard-content': {
|
|
1316
|
-
const text = shorten(inputs.title || inputs.subtitle || inputs.text || inputs.caption, 90);
|
|
1317
|
-
return text || this.tx('editor.summary.noContent', 'No content');
|
|
1318
|
-
}
|
|
1319
|
-
case 'praxis-wizard-inline-notice': {
|
|
1320
|
-
const tone = this.toneLabel(inputs.tone);
|
|
1321
|
-
const text = shorten(inputs.text, 90);
|
|
1322
|
-
return text ? `${tone} • ${text}` : tone;
|
|
1323
|
-
}
|
|
1324
|
-
case 'praxis-wizard-divider':
|
|
1325
|
-
return inputs.label
|
|
1326
|
-
? this.tx('editor.summary.labelPrefix', 'Label: {{label}}').replace('{{label}}', inputs.label)
|
|
1327
|
-
: this.tx('editor.summary.dividerNoLabel', 'Divider without label');
|
|
1328
|
-
default:
|
|
1329
|
-
return '';
|
|
1330
|
-
}
|
|
910
|
+
return step.widgets || [];
|
|
1331
911
|
}
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
case 'praxis-wizard-content':
|
|
1335
|
-
return this.tx('editor.status.contentLegacy', 'Deprecated legacy: new authoring should prefer widget:rich-text-block. This block remains supported for compatibility in this cycle.');
|
|
1336
|
-
case 'praxis-wizard-inline-notice':
|
|
1337
|
-
return this.tx('editor.status.noticeCurrent', 'Kept in the current cycle: final semantics are still being defined between legal-notice and info-callout.');
|
|
1338
|
-
case 'praxis-wizard-benefits':
|
|
1339
|
-
return this.tx('editor.status.benefitsTemporary', 'Temporarily kept: still no canonical equivalent in the editorial backlog.');
|
|
1340
|
-
case 'praxis-wizard-divider':
|
|
1341
|
-
return this.tx('editor.status.dividerTemporary', 'Temporarily kept: legacy separator without a prioritized shared equivalent.');
|
|
1342
|
-
default:
|
|
1343
|
-
return this.tx('editor.status.editorialWidget', 'Wizard editorial widget.');
|
|
1344
|
-
}
|
|
912
|
+
richContentNodeCount(document) {
|
|
913
|
+
return Array.isArray(document?.nodes) ? document.nodes.length : 0;
|
|
1345
914
|
}
|
|
1346
|
-
|
|
1347
|
-
const
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
const wd = {
|
|
1355
|
-
id,
|
|
1356
|
-
inputs: { ...defaults, ...result.inputs },
|
|
1357
|
-
};
|
|
915
|
+
richContentJson(step, zone) {
|
|
916
|
+
const document = zone === 'before' ? step.stepBlocksBeforeForm : step.stepBlocksAfterForm;
|
|
917
|
+
return JSON.stringify(document ?? createEmptyRichContentDocument(), null, 2);
|
|
918
|
+
}
|
|
919
|
+
setRichContentJson(step, zone, value) {
|
|
920
|
+
try {
|
|
921
|
+
const parsed = JSON.parse(value || '{}');
|
|
922
|
+
const next = this.normalizeRichContentDocument(parsed);
|
|
1358
923
|
if (zone === 'before')
|
|
1359
|
-
|
|
924
|
+
step.stepBlocksBeforeForm = next;
|
|
1360
925
|
else
|
|
1361
|
-
|
|
926
|
+
step.stepBlocksAfterForm = next;
|
|
927
|
+
this.isValid$.next(true);
|
|
1362
928
|
this.markDirty();
|
|
1363
|
-
}
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
if (!step)
|
|
1368
|
-
return;
|
|
1369
|
-
const list = this.ensureWidgetsBeforeForm();
|
|
1370
|
-
this.reorderSubset(list, (w) => this.isWizardWidgetId(w.id), ev.previousIndex, ev.currentIndex);
|
|
1371
|
-
this.markDirty();
|
|
1372
|
-
}
|
|
1373
|
-
dropEditorialAfter(ev) {
|
|
1374
|
-
const step = this.activeStep;
|
|
1375
|
-
if (!step)
|
|
1376
|
-
return;
|
|
1377
|
-
const list = this.ensureWidgets();
|
|
1378
|
-
this.reorderSubset(list, (w) => this.isWizardWidgetId(w.id), ev.previousIndex, ev.currentIndex);
|
|
1379
|
-
this.markDirty();
|
|
929
|
+
}
|
|
930
|
+
catch {
|
|
931
|
+
this.isValid$.next(false);
|
|
932
|
+
}
|
|
1380
933
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
934
|
+
seedRichContent(step, zone) {
|
|
935
|
+
const label = step.label || this.tx('editor.defaults.newStep', 'New step');
|
|
936
|
+
const document = {
|
|
937
|
+
kind: 'praxis.rich-content',
|
|
938
|
+
version: '1.0.0',
|
|
939
|
+
nodes: [
|
|
940
|
+
{
|
|
941
|
+
type: 'card',
|
|
942
|
+
title: zone === 'before'
|
|
943
|
+
? this.tx('editor.steps.seedBeforeTitle', 'Step context')
|
|
944
|
+
: this.tx('editor.steps.seedAfterTitle', 'Follow-up'),
|
|
945
|
+
content: [
|
|
946
|
+
{ type: 'text', text: label },
|
|
947
|
+
{ type: 'badge', label: zone === 'before' ? 'before' : 'after' },
|
|
948
|
+
],
|
|
949
|
+
},
|
|
950
|
+
],
|
|
951
|
+
};
|
|
952
|
+
if (zone === 'before')
|
|
953
|
+
step.stepBlocksBeforeForm = document;
|
|
954
|
+
else
|
|
955
|
+
step.stepBlocksAfterForm = document;
|
|
1391
956
|
this.markDirty();
|
|
1392
957
|
}
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
return;
|
|
1397
|
-
const clone = JSON.parse(JSON.stringify(w));
|
|
1398
|
-
const inputs = (clone.inputs = { ...(clone.inputs || {}) });
|
|
1399
|
-
inputs.blockId = this.nextEditorialBlockId(step, w.id, zone);
|
|
1400
|
-
const list = zone === 'before' ? this.ensureWidgetsBeforeForm() : this.ensureWidgets();
|
|
1401
|
-
const idx = list.indexOf(w);
|
|
1402
|
-
if (idx >= 0)
|
|
1403
|
-
list.splice(idx + 1, 0, clone);
|
|
958
|
+
clearRichContent(step, zone) {
|
|
959
|
+
if (zone === 'before')
|
|
960
|
+
step.stepBlocksBeforeForm = null;
|
|
1404
961
|
else
|
|
1405
|
-
|
|
962
|
+
step.stepBlocksAfterForm = null;
|
|
1406
963
|
this.markDirty();
|
|
1407
964
|
}
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
965
|
+
normalizeRichContentDocument(document) {
|
|
966
|
+
return {
|
|
967
|
+
kind: 'praxis.rich-content',
|
|
968
|
+
version: '1.0.0',
|
|
969
|
+
context: document.context,
|
|
970
|
+
nodes: Array.isArray(document.nodes) ? document.nodes : [],
|
|
971
|
+
};
|
|
1415
972
|
}
|
|
1416
973
|
removeAdvancedWidget(w) {
|
|
1417
974
|
const widgets = this.ensureWidgets();
|
|
@@ -1435,98 +992,7 @@ class PraxisStepperConfigEditor {
|
|
|
1435
992
|
return (w.id === 'praxis-dynamic-form'
|
|
1436
993
|
|| w.id === 'praxis-list'
|
|
1437
994
|
|| w.id === 'pdx-material-searchable-select'
|
|
1438
|
-
|| w.id === 'praxis-files-upload'
|
|
1439
|
-
|| this.isWizardWidgetId(w.id));
|
|
1440
|
-
}
|
|
1441
|
-
defaultEditorialInputs(id, step, zone) {
|
|
1442
|
-
const blockId = this.nextEditorialBlockId(step, id, zone);
|
|
1443
|
-
switch (id) {
|
|
1444
|
-
case 'praxis-wizard-benefits':
|
|
1445
|
-
return {
|
|
1446
|
-
blockId,
|
|
1447
|
-
title: '',
|
|
1448
|
-
columns: 4,
|
|
1449
|
-
boxed: true,
|
|
1450
|
-
items: [{ icon: '', title: this.tx('editor.defaults.newBenefit', 'New benefit'), text: '' }],
|
|
1451
|
-
};
|
|
1452
|
-
case 'praxis-wizard-content':
|
|
1453
|
-
return {
|
|
1454
|
-
blockId,
|
|
1455
|
-
title: '',
|
|
1456
|
-
subtitle: '',
|
|
1457
|
-
text: '',
|
|
1458
|
-
caption: '',
|
|
1459
|
-
};
|
|
1460
|
-
case 'praxis-wizard-inline-notice':
|
|
1461
|
-
return {
|
|
1462
|
-
blockId,
|
|
1463
|
-
text: '',
|
|
1464
|
-
tone: 'neutral',
|
|
1465
|
-
};
|
|
1466
|
-
case 'praxis-wizard-divider':
|
|
1467
|
-
return {
|
|
1468
|
-
blockId,
|
|
1469
|
-
label: '',
|
|
1470
|
-
};
|
|
1471
|
-
default:
|
|
1472
|
-
return { blockId };
|
|
1473
|
-
}
|
|
1474
|
-
}
|
|
1475
|
-
nextEditorialBlockId(step, id, zone) {
|
|
1476
|
-
const stepPart = this.normalizeBlockIdPart(step.id || `step-${this.activeIndex + 1}`);
|
|
1477
|
-
const kind = id.replace('praxis-wizard-', '');
|
|
1478
|
-
const prefix = `${stepPart}:${zone}:${kind}:`;
|
|
1479
|
-
const used = new Set();
|
|
1480
|
-
let max = 0;
|
|
1481
|
-
const allWidgets = [...(step.widgetsBeforeForm || []), ...(step.widgets || [])];
|
|
1482
|
-
allWidgets.forEach((widget) => {
|
|
1483
|
-
const blockId = String(widget.inputs?.blockId || '').trim();
|
|
1484
|
-
if (!blockId.startsWith(prefix))
|
|
1485
|
-
return;
|
|
1486
|
-
used.add(blockId);
|
|
1487
|
-
const suffix = Number(blockId.slice(prefix.length));
|
|
1488
|
-
if (Number.isFinite(suffix)) {
|
|
1489
|
-
max = Math.max(max, suffix);
|
|
1490
|
-
}
|
|
1491
|
-
});
|
|
1492
|
-
let nextIdx = Math.max(1, max + 1);
|
|
1493
|
-
let candidate = `${prefix}${nextIdx}`;
|
|
1494
|
-
while (used.has(candidate)) {
|
|
1495
|
-
nextIdx += 1;
|
|
1496
|
-
candidate = `${prefix}${nextIdx}`;
|
|
1497
|
-
}
|
|
1498
|
-
return candidate;
|
|
1499
|
-
}
|
|
1500
|
-
normalizeBlockIdPart(value) {
|
|
1501
|
-
const normalized = (value || '')
|
|
1502
|
-
.trim()
|
|
1503
|
-
.toLowerCase()
|
|
1504
|
-
.replace(/\s+/g, '-')
|
|
1505
|
-
.replace(/[^a-z0-9:_-]/g, '');
|
|
1506
|
-
return normalized || `step-${this.activeIndex + 1}`;
|
|
1507
|
-
}
|
|
1508
|
-
toneLabel(value) {
|
|
1509
|
-
switch (value) {
|
|
1510
|
-
case 'info': return this.tx('editor.tone.info', 'Informational');
|
|
1511
|
-
case 'warning': return this.tx('editor.tone.warning', 'Warning');
|
|
1512
|
-
default: return this.tx('editor.tone.neutral', 'Neutral');
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
|
-
reorderSubset(list, pick, fromSubsetIndex, toSubsetIndex) {
|
|
1516
|
-
const subsetIndices = [];
|
|
1517
|
-
list.forEach((item, index) => {
|
|
1518
|
-
if (pick(item))
|
|
1519
|
-
subsetIndices.push(index);
|
|
1520
|
-
});
|
|
1521
|
-
const fromReal = subsetIndices[fromSubsetIndex];
|
|
1522
|
-
const toReal = subsetIndices[toSubsetIndex];
|
|
1523
|
-
if (fromReal == null || toReal == null)
|
|
1524
|
-
return;
|
|
1525
|
-
const [moved] = list.splice(fromReal, 1);
|
|
1526
|
-
let insertAt = toReal;
|
|
1527
|
-
if (fromReal < toReal)
|
|
1528
|
-
insertAt -= 1;
|
|
1529
|
-
list.splice(insertAt, 0, moved);
|
|
995
|
+
|| w.id === 'praxis-files-upload');
|
|
1530
996
|
}
|
|
1531
997
|
// ------- Main form -------
|
|
1532
998
|
addMainForm() {
|
|
@@ -1700,44 +1166,11 @@ class PraxisStepperConfigEditor {
|
|
|
1700
1166
|
ref.saved$.subscribe(apply);
|
|
1701
1167
|
break;
|
|
1702
1168
|
}
|
|
1703
|
-
case 'praxis-wizard-benefits':
|
|
1704
|
-
case 'praxis-wizard-content':
|
|
1705
|
-
case 'praxis-wizard-inline-notice':
|
|
1706
|
-
case 'praxis-wizard-divider': {
|
|
1707
|
-
this.openWizardWidgetEditor(w);
|
|
1708
|
-
break;
|
|
1709
|
-
}
|
|
1710
1169
|
default:
|
|
1711
1170
|
// No editor available
|
|
1712
1171
|
break;
|
|
1713
1172
|
}
|
|
1714
1173
|
}
|
|
1715
|
-
openWizardWidgetEditor(w) {
|
|
1716
|
-
if (!this.isWizardWidgetId(w.id))
|
|
1717
|
-
return;
|
|
1718
|
-
this.openWizardWidgetDialog(w.id, { ...(w.inputs || {}) }).subscribe((result) => {
|
|
1719
|
-
if (!result?.inputs)
|
|
1720
|
-
return;
|
|
1721
|
-
w.inputs = { ...(w.inputs || {}), ...result.inputs };
|
|
1722
|
-
this.markDirty();
|
|
1723
|
-
});
|
|
1724
|
-
}
|
|
1725
|
-
openWizardWidgetDialog(widgetId, inputs) {
|
|
1726
|
-
const dialogRef = this.dialog.open(WizardWidgetConfigDialogComponent, {
|
|
1727
|
-
width: '760px',
|
|
1728
|
-
data: {
|
|
1729
|
-
widgetId,
|
|
1730
|
-
inputs: { ...inputs },
|
|
1731
|
-
},
|
|
1732
|
-
});
|
|
1733
|
-
return dialogRef.afterClosed();
|
|
1734
|
-
}
|
|
1735
|
-
isWizardWidgetId(id) {
|
|
1736
|
-
return (id === 'praxis-wizard-benefits'
|
|
1737
|
-
|| id === 'praxis-wizard-content'
|
|
1738
|
-
|| id === 'praxis-wizard-inline-notice'
|
|
1739
|
-
|| id === 'praxis-wizard-divider');
|
|
1740
|
-
}
|
|
1741
1174
|
// SettingsValueProvider
|
|
1742
1175
|
getSettingsValue() { return this.config; }
|
|
1743
1176
|
onSave() { return this.getSettingsValue(); }
|
|
@@ -1970,114 +1403,52 @@ class PraxisStepperConfigEditor {
|
|
|
1970
1403
|
<div class="zone-head">
|
|
1971
1404
|
<div class="zone-title">{{ tx('editor.steps.zoneBefore', 'Before form') }}</div>
|
|
1972
1405
|
<div class="zone-actions">
|
|
1973
|
-
<span class="zone-count">{{
|
|
1974
|
-
<button mat-stroked-button
|
|
1975
|
-
<mat-icon [praxisIcon]="'
|
|
1976
|
-
{{ tx('editor.steps.
|
|
1406
|
+
<span class="zone-count">{{ richContentNodeCount(step.stepBlocksBeforeForm) }}</span>
|
|
1407
|
+
<button mat-stroked-button type="button" (click)="seedRichContent(step, 'before')">
|
|
1408
|
+
<mat-icon [praxisIcon]="'auto_awesome'"></mat-icon>
|
|
1409
|
+
{{ tx('editor.steps.seedRichContent', 'Seed') }}
|
|
1977
1410
|
</button>
|
|
1978
|
-
<mat-menu #beforeEditorialMenu="matMenu">
|
|
1979
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-benefits', 'before')">
|
|
1980
|
-
<mat-icon [praxisIcon]="'view_module'"></mat-icon>
|
|
1981
|
-
{{ tx('editor.steps.widgetBenefits', 'Benefits grid') }}
|
|
1982
|
-
</button>
|
|
1983
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-content', 'before')">
|
|
1984
|
-
<mat-icon [praxisIcon]="'article'"></mat-icon>
|
|
1985
|
-
{{ tx('editor.steps.widgetContent', 'Content block') }}
|
|
1986
|
-
</button>
|
|
1987
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-inline-notice', 'before')">
|
|
1988
|
-
<mat-icon [praxisIcon]="'info'"></mat-icon>
|
|
1989
|
-
{{ tx('editor.steps.widgetNotice', 'Inline notice') }}
|
|
1990
|
-
</button>
|
|
1991
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-divider', 'before')">
|
|
1992
|
-
<mat-icon [praxisIcon]="'horizontal_rule'"></mat-icon>
|
|
1993
|
-
{{ tx('editor.steps.widgetDivider', 'Divider') }}
|
|
1994
|
-
</button>
|
|
1995
|
-
</mat-menu>
|
|
1996
|
-
</div>
|
|
1997
|
-
</div>
|
|
1998
|
-
<div cdkDropList (cdkDropListDropped)="dropEditorialBefore($event)" class="widget-list">
|
|
1999
|
-
<div class="widget-item editorial-item" *ngFor="let w of editorialBeforeWidgets(step)" cdkDrag>
|
|
2000
|
-
<div class="drag-handle" cdkDragHandle><mat-icon [praxisIcon]="'drag_indicator'"></mat-icon></div>
|
|
2001
|
-
<div class="info">
|
|
2002
|
-
<div class="name">{{ displayWidgetName(w) }}</div>
|
|
2003
|
-
<div class="sub">{{ editorialWidgetSummary(w) }}</div>
|
|
2004
|
-
<div class="meta">{{ editorialWidgetStatus(w) }}</div>
|
|
2005
|
-
<div class="meta" *ngIf="widgetBlockId(w) as blockId">ID: {{ blockId }}</div>
|
|
2006
|
-
</div>
|
|
2007
|
-
<div class="actions">
|
|
2008
|
-
<button mat-icon-button (click)="editWidget(w)" [matTooltip]="tx('editor.steps.editBlock', 'Edit block')">
|
|
2009
|
-
<mat-icon [praxisIcon]="'tune'"></mat-icon>
|
|
2010
|
-
</button>
|
|
2011
|
-
<button mat-icon-button (click)="moveEditorialWidget(w, 'before', 'after')" [matTooltip]="tx('editor.steps.moveAfter', 'Move after the form')">
|
|
2012
|
-
<mat-icon [praxisIcon]="'south'"></mat-icon>
|
|
2013
|
-
</button>
|
|
2014
|
-
<button mat-icon-button (click)="duplicateEditorialWidget(w, 'before')" [matTooltip]="tx('editor.steps.duplicateBlock', 'Duplicate block')">
|
|
2015
|
-
<mat-icon [praxisIcon]="'content_copy'"></mat-icon>
|
|
2016
|
-
</button>
|
|
2017
|
-
<button mat-icon-button color="warn" (click)="removeEditorialWidget(w, 'before')" [matTooltip]="tx('editor.steps.removeBlock', 'Remove block')">
|
|
2018
|
-
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
2019
|
-
</button>
|
|
2020
|
-
</div>
|
|
2021
1411
|
</div>
|
|
2022
|
-
<div class="empty" *ngIf="!editorialBeforeWidgets(step).length">{{ tx('editor.steps.emptyZone', 'No blocks in this zone.') }}</div>
|
|
2023
1412
|
</div>
|
|
1413
|
+
<mat-form-field appearance="outline" class="w-full rich-content-json">
|
|
1414
|
+
<mat-label>{{ tx('editor.steps.richContentDocument', 'RichContentDocument JSON') }}</mat-label>
|
|
1415
|
+
<textarea
|
|
1416
|
+
matInput
|
|
1417
|
+
rows="12"
|
|
1418
|
+
[ngModel]="richContentJson(step, 'before')"
|
|
1419
|
+
(ngModelChange)="setRichContentJson(step, 'before', $event)"
|
|
1420
|
+
></textarea>
|
|
1421
|
+
</mat-form-field>
|
|
1422
|
+
<button mat-button color="warn" type="button" (click)="clearRichContent(step, 'before')">
|
|
1423
|
+
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
1424
|
+
{{ tx('editor.steps.clearZone', 'Clear zone') }}
|
|
1425
|
+
</button>
|
|
2024
1426
|
</div>
|
|
2025
1427
|
|
|
2026
1428
|
<div class="zone-column">
|
|
2027
1429
|
<div class="zone-head">
|
|
2028
1430
|
<div class="zone-title">{{ tx('editor.steps.zoneAfter', 'After form') }}</div>
|
|
2029
1431
|
<div class="zone-actions">
|
|
2030
|
-
<span class="zone-count">{{
|
|
2031
|
-
<button mat-stroked-button
|
|
2032
|
-
<mat-icon [praxisIcon]="'
|
|
2033
|
-
{{ tx('editor.steps.
|
|
1432
|
+
<span class="zone-count">{{ richContentNodeCount(step.stepBlocksAfterForm) }}</span>
|
|
1433
|
+
<button mat-stroked-button type="button" (click)="seedRichContent(step, 'after')">
|
|
1434
|
+
<mat-icon [praxisIcon]="'auto_awesome'"></mat-icon>
|
|
1435
|
+
{{ tx('editor.steps.seedRichContent', 'Seed') }}
|
|
2034
1436
|
</button>
|
|
2035
|
-
<mat-menu #afterEditorialMenu="matMenu">
|
|
2036
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-benefits', 'after')">
|
|
2037
|
-
<mat-icon [praxisIcon]="'view_module'"></mat-icon>
|
|
2038
|
-
{{ tx('editor.steps.widgetBenefits', 'Benefits grid') }}
|
|
2039
|
-
</button>
|
|
2040
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-content', 'after')">
|
|
2041
|
-
<mat-icon [praxisIcon]="'article'"></mat-icon>
|
|
2042
|
-
{{ tx('editor.steps.widgetContent', 'Content block') }}
|
|
2043
|
-
</button>
|
|
2044
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-inline-notice', 'after')">
|
|
2045
|
-
<mat-icon [praxisIcon]="'info'"></mat-icon>
|
|
2046
|
-
{{ tx('editor.steps.widgetNotice', 'Inline notice') }}
|
|
2047
|
-
</button>
|
|
2048
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-divider', 'after')">
|
|
2049
|
-
<mat-icon [praxisIcon]="'horizontal_rule'"></mat-icon>
|
|
2050
|
-
{{ tx('editor.steps.widgetDivider', 'Divider') }}
|
|
2051
|
-
</button>
|
|
2052
|
-
</mat-menu>
|
|
2053
1437
|
</div>
|
|
2054
1438
|
</div>
|
|
2055
|
-
<
|
|
2056
|
-
<
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
<button mat-icon-button (click)="moveEditorialWidget(w, 'after', 'before')" [matTooltip]="tx('editor.steps.moveBefore', 'Move before the form')">
|
|
2069
|
-
<mat-icon [praxisIcon]="'north'"></mat-icon>
|
|
2070
|
-
</button>
|
|
2071
|
-
<button mat-icon-button (click)="duplicateEditorialWidget(w, 'after')" [matTooltip]="tx('editor.steps.duplicateBlock', 'Duplicate block')">
|
|
2072
|
-
<mat-icon [praxisIcon]="'content_copy'"></mat-icon>
|
|
2073
|
-
</button>
|
|
2074
|
-
<button mat-icon-button color="warn" (click)="removeEditorialWidget(w, 'after')" [matTooltip]="tx('editor.steps.removeBlock', 'Remove block')">
|
|
2075
|
-
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
2076
|
-
</button>
|
|
2077
|
-
</div>
|
|
2078
|
-
</div>
|
|
2079
|
-
<div class="empty" *ngIf="!editorialAfterWidgets(step).length">{{ tx('editor.steps.emptyZone', 'No blocks in this zone.') }}</div>
|
|
2080
|
-
</div>
|
|
1439
|
+
<mat-form-field appearance="outline" class="w-full rich-content-json">
|
|
1440
|
+
<mat-label>{{ tx('editor.steps.richContentDocument', 'RichContentDocument JSON') }}</mat-label>
|
|
1441
|
+
<textarea
|
|
1442
|
+
matInput
|
|
1443
|
+
rows="12"
|
|
1444
|
+
[ngModel]="richContentJson(step, 'after')"
|
|
1445
|
+
(ngModelChange)="setRichContentJson(step, 'after', $event)"
|
|
1446
|
+
></textarea>
|
|
1447
|
+
</mat-form-field>
|
|
1448
|
+
<button mat-button color="warn" type="button" (click)="clearRichContent(step, 'after')">
|
|
1449
|
+
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
1450
|
+
{{ tx('editor.steps.clearZone', 'Clear zone') }}
|
|
1451
|
+
</button>
|
|
2081
1452
|
</div>
|
|
2082
1453
|
</div>
|
|
2083
1454
|
</div>
|
|
@@ -2409,7 +1780,7 @@ class PraxisStepperConfigEditor {
|
|
|
2409
1780
|
</mat-tab>
|
|
2410
1781
|
</mat-tab-group>
|
|
2411
1782
|
</div>
|
|
2412
|
-
`, 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:16px;display:grid;gap:16px;background:var(--md-sys-color-surface);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 78%,transparent);border-radius:16px}.help{color:var(--md-sys-color-on-surface-variant);font-size:13px}.editor-intro{display:flex;justify-content:space-between;gap:16px;align-items:flex-start;padding:4px 2px 2px}.editor-intro-copy{display:grid;gap:6px;max-width:760px}.eyebrow{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant);font-weight:600}.editor-title{font-size:22px;line-height:1.15;font-weight:650;color:var(--md-sys-color-on-surface)}.editor-subtitle{max-width:72ch;color:var(--md-sys-color-on-surface-variant);line-height:1.45;font-size:14px}.editor-intro-meta{display:flex;gap:8px;align-items:flex-start}.meta-pill{display:grid;gap:2px;min-width:88px;padding:10px 12px;border-radius:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);background:var(--md-sys-color-surface-container-low)}.meta-label{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--md-sys-color-on-surface-variant)}.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}.settings-group{display:grid;gap:14px;padding:2px 0 4px}.settings-group+.settings-group,.settings-group+.disclosure,.disclosure+.settings-group{padding-top:18px;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 60%,transparent)}.group-head{display:grid;gap:4px;max-width:72ch}.inline-actions-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;align-items:start}.inline-action-item{display:grid;gap:8px;align-content:start;min-width:0}.pdx-steps{display:grid;gap:12px;padding:4px 0 2px}.steps-workspace{display:grid;grid-template-columns:minmax(260px,320px) minmax(0,1fr);gap:24px;align-items:start}.pdx-steps-header{display:flex;justify-content:space-between;align-items:center;gap:16px}.pdx-step-list{display:grid;gap:10px}.pdx-step-item{display:grid;grid-template-columns:20px 1fr auto;gap:10px;align-items:start;padding:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 68%,transparent);border-radius:14px;background:var(--md-sys-color-surface);cursor:pointer;outline:none}.pdx-step-item.active{border-color:color-mix(in srgb,var(--md-sys-color-primary) 55%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 26%,var(--md-sys-color-surface));box-shadow:none}.pdx-step-item:focus-visible{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent)}.drag-handle{display:flex;align-items:center;color:var(--md-sys-color-on-surface-variant)}.step-summary{display:grid;gap:8px;min-width:0}.step-summary-head{display:grid;gap:2px}.step-summary-index{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--md-sys-color-on-surface-variant);font-weight:600}.step-summary-title{font-size:15px;line-height:1.3;font-weight:600;color:var(--md-sys-color-on-surface)}.step-summary-sub{font-size:12px;color:var(--md-sys-color-on-surface-variant);font-family:var(--md-ref-typeface-plain, monospace);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.step-summary-flags{display:flex;gap:6px;flex-wrap:wrap}.summary-chip{display:inline-flex;align-items:center;min-height:22px;padding:0 8px;border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:600}.summary-chip-warn{background:color-mix(in srgb,var(--md-sys-color-error-container) 60%,transparent);color:var(--md-sys-color-on-error-container)}.pdx-active-step{display:grid;gap:18px;min-width:0}.pdx-active-step .hdr{display:flex;gap:12px;align-items:flex-start;justify-content:space-between}.active-step-head{display:grid;gap:4px}.pdx-content-editor{display:grid;gap:16px}.section{display:grid;gap:12px;padding:0;border:none;border-radius:0;background:transparent}.section-body{display:grid;gap:12px}.section-title{font-weight:600;font-size:15px;color:var(--md-sys-color-on-surface)}.section-subtitle{font-size:13px;color:var(--md-sys-color-on-surface-variant);line-height:1.45}.section-head{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap}.editorial-section{padding-bottom:6px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 68%,transparent)}.detail-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.field-span-2{grid-column:span 2}.toggle-group{display:flex;gap:10px;flex-wrap:wrap;padding-top:4px}.disclosure{padding:0 0 12px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 62%,transparent)}.disclosure summary{list-style:none;display:flex;justify-content:space-between;align-items:baseline;gap:16px;cursor:pointer;padding:0;position:relative}.disclosure summary::-webkit-details-marker{display:none}.disclosure summary:after{content:\"expand_more\";font-family:Material Icons;font-size:18px;color:var(--md-sys-color-on-surface-variant);transition:transform .16s ease}.disclosure[open] summary:after{transform:rotate(180deg)}.disclosure summary:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 58%,transparent);outline-offset:4px;border-radius:8px}.disclosure-body{padding-top:12px}.widget-list{display:grid;gap:8px}.widget-item{display:grid;grid-template-columns:20px 1fr auto;align-items:start;gap:12px;padding:10px 0;border:none;border-radius:0;background:transparent;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 56%,transparent)}.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);line-height:1.45}.widget-item .info .meta{margin-top:2px;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:2px;flex-wrap:nowrap;justify-content:flex-end;align-items:flex-start;opacity:.92}.editorial-item{align-items:start}.editorial-item .actions{justify-content:flex-end}.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(220px,1fr));gap:8px;margin-bottom:4px}.cta-row-item{display:grid;gap:10px;padding:12px 0;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 56%,transparent)}.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-column{display:grid;gap:10px;min-width:0}.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-column+.zone-column{padding-left:16px;border-left:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 56%,transparent)}.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}.form-row-card{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:10px 0;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 56%,transparent)}.form-row-main{display:flex;align-items:center;gap:12px;min-width:0}.form-row-actions{display:flex;gap:4px;flex-wrap:wrap;justify-content:flex-end}.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}.cta-row-item .cta-head{display:grid;grid-template-columns:20px 1fr;align-items:start;gap:10px}.cta-row-item .cta-title{font-weight:600;color:var(--md-sys-color-on-surface)}.cta-row-item .cta-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant);line-height:1.45;margin-top:2px}.cta-row-item .cta-actions{display:flex;gap:8px;align-items:center}.widget-item:last-child,.cta-row-item:last-child,.form-row-card:last-child{border-bottom:none}@media(max-width:900px){.editor-intro{flex-direction:column}.steps-workspace{grid-template-columns:1fr;gap:20px}.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-end}.form-row-card{flex-direction:column;align-items:flex-start}.form-row-actions{justify-content:flex-start}.zone-column+.zone-column{padding-left:0;border-left:none;padding-top:12px;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 56%,transparent)}}@media(max-width:640px){.tab-pad{padding:14px}.editor-title{font-size:20px}.pdx-active-step .hdr{align-items:flex-start;flex-direction:column}.detail-grid{grid-template-columns:1fr}.field-span-2{grid-column:auto}.toggle-group{flex-direction:column;align-items:flex-start}.zone-head{align-items:flex-start;flex-direction:column}.zone-actions,.widget-item .actions{justify-content:flex-start}.disclosure summary{flex-direction:column;align-items: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: "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: MatDialogModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i10.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: i10.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i10.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: i11.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i11.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"] }] });
|
|
1783
|
+
`, 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:16px;display:grid;gap:16px;background:var(--md-sys-color-surface);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 78%,transparent);border-radius:16px}.help{color:var(--md-sys-color-on-surface-variant);font-size:13px}.editor-intro{display:flex;justify-content:space-between;gap:16px;align-items:flex-start;padding:4px 2px 2px}.editor-intro-copy{display:grid;gap:6px;max-width:760px}.eyebrow{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant);font-weight:600}.editor-title{font-size:22px;line-height:1.15;font-weight:650;color:var(--md-sys-color-on-surface)}.editor-subtitle{max-width:72ch;color:var(--md-sys-color-on-surface-variant);line-height:1.45;font-size:14px}.editor-intro-meta{display:flex;gap:8px;align-items:flex-start}.meta-pill{display:grid;gap:2px;min-width:88px;padding:10px 12px;border-radius:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 70%,transparent);background:var(--md-sys-color-surface-container-low)}.meta-label{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--md-sys-color-on-surface-variant)}.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}.settings-group{display:grid;gap:14px;padding:2px 0 4px}.settings-group+.settings-group,.settings-group+.disclosure,.disclosure+.settings-group{padding-top:18px;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 60%,transparent)}.group-head{display:grid;gap:4px;max-width:72ch}.inline-actions-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;align-items:start}.inline-action-item{display:grid;gap:8px;align-content:start;min-width:0}.pdx-steps{display:grid;gap:12px;padding:4px 0 2px}.steps-workspace{display:grid;grid-template-columns:minmax(260px,320px) minmax(0,1fr);gap:24px;align-items:start}.pdx-steps-header{display:flex;justify-content:space-between;align-items:center;gap:16px}.pdx-step-list{display:grid;gap:10px}.pdx-step-item{display:grid;grid-template-columns:20px 1fr auto;gap:10px;align-items:start;padding:12px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 68%,transparent);border-radius:14px;background:var(--md-sys-color-surface);cursor:pointer;outline:none}.pdx-step-item.active{border-color:color-mix(in srgb,var(--md-sys-color-primary) 55%,var(--md-sys-color-outline-variant));background:color-mix(in srgb,var(--md-sys-color-primary-container) 26%,var(--md-sys-color-surface));box-shadow:none}.pdx-step-item:focus-visible{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--md-sys-color-primary) 22%,transparent)}.drag-handle{display:flex;align-items:center;color:var(--md-sys-color-on-surface-variant)}.step-summary{display:grid;gap:8px;min-width:0}.step-summary-head{display:grid;gap:2px}.step-summary-index{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--md-sys-color-on-surface-variant);font-weight:600}.step-summary-title{font-size:15px;line-height:1.3;font-weight:600;color:var(--md-sys-color-on-surface)}.step-summary-sub{font-size:12px;color:var(--md-sys-color-on-surface-variant);font-family:var(--md-ref-typeface-plain, monospace);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.step-summary-flags{display:flex;gap:6px;flex-wrap:wrap}.summary-chip{display:inline-flex;align-items:center;min-height:22px;padding:0 8px;border-radius:999px;background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface-variant);font-size:11px;font-weight:600}.summary-chip-warn{background:color-mix(in srgb,var(--md-sys-color-error-container) 60%,transparent);color:var(--md-sys-color-on-error-container)}.pdx-active-step{display:grid;gap:18px;min-width:0}.pdx-active-step .hdr{display:flex;gap:12px;align-items:flex-start;justify-content:space-between}.active-step-head{display:grid;gap:4px}.pdx-content-editor{display:grid;gap:16px}.section{display:grid;gap:12px;padding:0;border:none;border-radius:0;background:transparent}.section-body{display:grid;gap:12px}.section-title{font-weight:600;font-size:15px;color:var(--md-sys-color-on-surface)}.section-subtitle{font-size:13px;color:var(--md-sys-color-on-surface-variant);line-height:1.45}.section-head{display:flex;gap:12px;align-items:center;justify-content:space-between;flex-wrap:wrap}.editorial-section{padding-bottom:6px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 68%,transparent)}.detail-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.field-span-2{grid-column:span 2}.toggle-group{display:flex;gap:10px;flex-wrap:wrap;padding-top:4px}.disclosure{padding:0 0 12px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 62%,transparent)}.disclosure summary{list-style:none;display:flex;justify-content:space-between;align-items:baseline;gap:16px;cursor:pointer;padding:0;position:relative}.disclosure summary::-webkit-details-marker{display:none}.disclosure summary:after{content:\"expand_more\";font-family:Material Icons;font-size:18px;color:var(--md-sys-color-on-surface-variant);transition:transform .16s ease}.disclosure[open] summary:after{transform:rotate(180deg)}.disclosure summary:focus-visible{outline:2px solid color-mix(in srgb,var(--md-sys-color-primary) 58%,transparent);outline-offset:4px;border-radius:8px}.disclosure-body{padding-top:12px}.widget-list{display:grid;gap:8px}.widget-item{display:grid;grid-template-columns:20px 1fr auto;align-items:start;gap:12px;padding:10px 0;border:none;border-radius:0;background:transparent;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 56%,transparent)}.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);line-height:1.45}.widget-item .info .meta{margin-top:2px;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:2px;flex-wrap:nowrap;justify-content:flex-end;align-items:flex-start;opacity:.92}.editorial-item{align-items:start}.editorial-item .actions{justify-content:flex-end}.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(220px,1fr));gap:8px;margin-bottom:4px}.cta-row-item{display:grid;gap:10px;padding:12px 0;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 56%,transparent)}.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-column{display:grid;gap:10px;min-width:0}.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-column+.zone-column{padding-left:16px;border-left:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 56%,transparent)}.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}.form-row-card{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:10px 0;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 56%,transparent)}.form-row-main{display:flex;align-items:center;gap:12px;min-width:0}.form-row-actions{display:flex;gap:4px;flex-wrap:wrap;justify-content:flex-end}.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}.cta-row-item .cta-head{display:grid;grid-template-columns:20px 1fr;align-items:start;gap:10px}.cta-row-item .cta-title{font-weight:600;color:var(--md-sys-color-on-surface)}.cta-row-item .cta-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant);line-height:1.45;margin-top:2px}.cta-row-item .cta-actions{display:flex;gap:8px;align-items:center}.widget-item:last-child,.cta-row-item:last-child,.form-row-card:last-child{border-bottom:none}@media(max-width:900px){.editor-intro{flex-direction:column}.steps-workspace{grid-template-columns:1fr;gap:20px}.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-end}.form-row-card{flex-direction:column;align-items:flex-start}.form-row-actions{justify-content:flex-start}.zone-column+.zone-column{padding-left:0;border-left:none;padding-top:12px;border-top:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 56%,transparent)}}@media(max-width:640px){.tab-pad{padding:14px}.editor-title{font-size:20px}.pdx-active-step .hdr{align-items:flex-start;flex-direction:column}.detail-grid{grid-template-columns:1fr}.field-span-2{grid-column:auto}.toggle-group{flex-direction:column;align-items:flex-start}.zone-head{align-items:flex-start;flex-direction:column}.zone-actions,.widget-item .actions{justify-content:flex-start}.disclosure summary{flex-direction:column;align-items: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: "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: MatDialogModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i10.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i10.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"] }] });
|
|
2413
1784
|
}
|
|
2414
1785
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisStepperConfigEditor, decorators: [{
|
|
2415
1786
|
type: Component,
|
|
@@ -2425,7 +1796,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2425
1796
|
DragDropModule,
|
|
2426
1797
|
MatTooltipModule,
|
|
2427
1798
|
MatDialogModule,
|
|
2428
|
-
MatMenuModule,
|
|
2429
1799
|
MatTabsModule,
|
|
2430
1800
|
], providers: [providePraxisStepperI18n()], template: `
|
|
2431
1801
|
<div class="pdx-editor">
|
|
@@ -2644,114 +2014,52 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
2644
2014
|
<div class="zone-head">
|
|
2645
2015
|
<div class="zone-title">{{ tx('editor.steps.zoneBefore', 'Before form') }}</div>
|
|
2646
2016
|
<div class="zone-actions">
|
|
2647
|
-
<span class="zone-count">{{
|
|
2648
|
-
<button mat-stroked-button
|
|
2649
|
-
<mat-icon [praxisIcon]="'
|
|
2650
|
-
{{ tx('editor.steps.
|
|
2017
|
+
<span class="zone-count">{{ richContentNodeCount(step.stepBlocksBeforeForm) }}</span>
|
|
2018
|
+
<button mat-stroked-button type="button" (click)="seedRichContent(step, 'before')">
|
|
2019
|
+
<mat-icon [praxisIcon]="'auto_awesome'"></mat-icon>
|
|
2020
|
+
{{ tx('editor.steps.seedRichContent', 'Seed') }}
|
|
2651
2021
|
</button>
|
|
2652
|
-
<mat-menu #beforeEditorialMenu="matMenu">
|
|
2653
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-benefits', 'before')">
|
|
2654
|
-
<mat-icon [praxisIcon]="'view_module'"></mat-icon>
|
|
2655
|
-
{{ tx('editor.steps.widgetBenefits', 'Benefits grid') }}
|
|
2656
|
-
</button>
|
|
2657
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-content', 'before')">
|
|
2658
|
-
<mat-icon [praxisIcon]="'article'"></mat-icon>
|
|
2659
|
-
{{ tx('editor.steps.widgetContent', 'Content block') }}
|
|
2660
|
-
</button>
|
|
2661
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-inline-notice', 'before')">
|
|
2662
|
-
<mat-icon [praxisIcon]="'info'"></mat-icon>
|
|
2663
|
-
{{ tx('editor.steps.widgetNotice', 'Inline notice') }}
|
|
2664
|
-
</button>
|
|
2665
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-divider', 'before')">
|
|
2666
|
-
<mat-icon [praxisIcon]="'horizontal_rule'"></mat-icon>
|
|
2667
|
-
{{ tx('editor.steps.widgetDivider', 'Divider') }}
|
|
2668
|
-
</button>
|
|
2669
|
-
</mat-menu>
|
|
2670
2022
|
</div>
|
|
2671
2023
|
</div>
|
|
2672
|
-
<
|
|
2673
|
-
<
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
<button mat-icon-button (click)="moveEditorialWidget(w, 'before', 'after')" [matTooltip]="tx('editor.steps.moveAfter', 'Move after the form')">
|
|
2686
|
-
<mat-icon [praxisIcon]="'south'"></mat-icon>
|
|
2687
|
-
</button>
|
|
2688
|
-
<button mat-icon-button (click)="duplicateEditorialWidget(w, 'before')" [matTooltip]="tx('editor.steps.duplicateBlock', 'Duplicate block')">
|
|
2689
|
-
<mat-icon [praxisIcon]="'content_copy'"></mat-icon>
|
|
2690
|
-
</button>
|
|
2691
|
-
<button mat-icon-button color="warn" (click)="removeEditorialWidget(w, 'before')" [matTooltip]="tx('editor.steps.removeBlock', 'Remove block')">
|
|
2692
|
-
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
2693
|
-
</button>
|
|
2694
|
-
</div>
|
|
2695
|
-
</div>
|
|
2696
|
-
<div class="empty" *ngIf="!editorialBeforeWidgets(step).length">{{ tx('editor.steps.emptyZone', 'No blocks in this zone.') }}</div>
|
|
2697
|
-
</div>
|
|
2024
|
+
<mat-form-field appearance="outline" class="w-full rich-content-json">
|
|
2025
|
+
<mat-label>{{ tx('editor.steps.richContentDocument', 'RichContentDocument JSON') }}</mat-label>
|
|
2026
|
+
<textarea
|
|
2027
|
+
matInput
|
|
2028
|
+
rows="12"
|
|
2029
|
+
[ngModel]="richContentJson(step, 'before')"
|
|
2030
|
+
(ngModelChange)="setRichContentJson(step, 'before', $event)"
|
|
2031
|
+
></textarea>
|
|
2032
|
+
</mat-form-field>
|
|
2033
|
+
<button mat-button color="warn" type="button" (click)="clearRichContent(step, 'before')">
|
|
2034
|
+
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
2035
|
+
{{ tx('editor.steps.clearZone', 'Clear zone') }}
|
|
2036
|
+
</button>
|
|
2698
2037
|
</div>
|
|
2699
2038
|
|
|
2700
2039
|
<div class="zone-column">
|
|
2701
2040
|
<div class="zone-head">
|
|
2702
2041
|
<div class="zone-title">{{ tx('editor.steps.zoneAfter', 'After form') }}</div>
|
|
2703
2042
|
<div class="zone-actions">
|
|
2704
|
-
<span class="zone-count">{{
|
|
2705
|
-
<button mat-stroked-button
|
|
2706
|
-
<mat-icon [praxisIcon]="'
|
|
2707
|
-
{{ tx('editor.steps.
|
|
2043
|
+
<span class="zone-count">{{ richContentNodeCount(step.stepBlocksAfterForm) }}</span>
|
|
2044
|
+
<button mat-stroked-button type="button" (click)="seedRichContent(step, 'after')">
|
|
2045
|
+
<mat-icon [praxisIcon]="'auto_awesome'"></mat-icon>
|
|
2046
|
+
{{ tx('editor.steps.seedRichContent', 'Seed') }}
|
|
2708
2047
|
</button>
|
|
2709
|
-
<mat-menu #afterEditorialMenu="matMenu">
|
|
2710
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-benefits', 'after')">
|
|
2711
|
-
<mat-icon [praxisIcon]="'view_module'"></mat-icon>
|
|
2712
|
-
{{ tx('editor.steps.widgetBenefits', 'Benefits grid') }}
|
|
2713
|
-
</button>
|
|
2714
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-content', 'after')">
|
|
2715
|
-
<mat-icon [praxisIcon]="'article'"></mat-icon>
|
|
2716
|
-
{{ tx('editor.steps.widgetContent', 'Content block') }}
|
|
2717
|
-
</button>
|
|
2718
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-inline-notice', 'after')">
|
|
2719
|
-
<mat-icon [praxisIcon]="'info'"></mat-icon>
|
|
2720
|
-
{{ tx('editor.steps.widgetNotice', 'Inline notice') }}
|
|
2721
|
-
</button>
|
|
2722
|
-
<button mat-menu-item (click)="addEditorialWidget('praxis-wizard-divider', 'after')">
|
|
2723
|
-
<mat-icon [praxisIcon]="'horizontal_rule'"></mat-icon>
|
|
2724
|
-
{{ tx('editor.steps.widgetDivider', 'Divider') }}
|
|
2725
|
-
</button>
|
|
2726
|
-
</mat-menu>
|
|
2727
|
-
</div>
|
|
2728
|
-
</div>
|
|
2729
|
-
<div cdkDropList (cdkDropListDropped)="dropEditorialAfter($event)" class="widget-list">
|
|
2730
|
-
<div class="widget-item editorial-item" *ngFor="let w of editorialAfterWidgets(step)" cdkDrag>
|
|
2731
|
-
<div class="drag-handle" cdkDragHandle><mat-icon [praxisIcon]="'drag_indicator'"></mat-icon></div>
|
|
2732
|
-
<div class="info">
|
|
2733
|
-
<div class="name">{{ displayWidgetName(w) }}</div>
|
|
2734
|
-
<div class="sub">{{ editorialWidgetSummary(w) }}</div>
|
|
2735
|
-
<div class="meta">{{ editorialWidgetStatus(w) }}</div>
|
|
2736
|
-
<div class="meta" *ngIf="widgetBlockId(w) as blockId">ID: {{ blockId }}</div>
|
|
2737
|
-
</div>
|
|
2738
|
-
<div class="actions">
|
|
2739
|
-
<button mat-icon-button (click)="editWidget(w)" [matTooltip]="tx('editor.steps.editBlock', 'Edit block')">
|
|
2740
|
-
<mat-icon [praxisIcon]="'tune'"></mat-icon>
|
|
2741
|
-
</button>
|
|
2742
|
-
<button mat-icon-button (click)="moveEditorialWidget(w, 'after', 'before')" [matTooltip]="tx('editor.steps.moveBefore', 'Move before the form')">
|
|
2743
|
-
<mat-icon [praxisIcon]="'north'"></mat-icon>
|
|
2744
|
-
</button>
|
|
2745
|
-
<button mat-icon-button (click)="duplicateEditorialWidget(w, 'after')" [matTooltip]="tx('editor.steps.duplicateBlock', 'Duplicate block')">
|
|
2746
|
-
<mat-icon [praxisIcon]="'content_copy'"></mat-icon>
|
|
2747
|
-
</button>
|
|
2748
|
-
<button mat-icon-button color="warn" (click)="removeEditorialWidget(w, 'after')" [matTooltip]="tx('editor.steps.removeBlock', 'Remove block')">
|
|
2749
|
-
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
2750
|
-
</button>
|
|
2751
|
-
</div>
|
|
2752
2048
|
</div>
|
|
2753
|
-
<div class="empty" *ngIf="!editorialAfterWidgets(step).length">{{ tx('editor.steps.emptyZone', 'No blocks in this zone.') }}</div>
|
|
2754
2049
|
</div>
|
|
2050
|
+
<mat-form-field appearance="outline" class="w-full rich-content-json">
|
|
2051
|
+
<mat-label>{{ tx('editor.steps.richContentDocument', 'RichContentDocument JSON') }}</mat-label>
|
|
2052
|
+
<textarea
|
|
2053
|
+
matInput
|
|
2054
|
+
rows="12"
|
|
2055
|
+
[ngModel]="richContentJson(step, 'after')"
|
|
2056
|
+
(ngModelChange)="setRichContentJson(step, 'after', $event)"
|
|
2057
|
+
></textarea>
|
|
2058
|
+
</mat-form-field>
|
|
2059
|
+
<button mat-button color="warn" type="button" (click)="clearRichContent(step, 'after')">
|
|
2060
|
+
<mat-icon [praxisIcon]="'delete'"></mat-icon>
|
|
2061
|
+
{{ tx('editor.steps.clearZone', 'Clear zone') }}
|
|
2062
|
+
</button>
|
|
2755
2063
|
</div>
|
|
2756
2064
|
</div>
|
|
2757
2065
|
</div>
|
|
@@ -3187,22 +2495,20 @@ const CAPS = [
|
|
|
3187
2495
|
{ path: 'steps[].form.mode', category: 'steps', valueKind: 'enum', allowedValues: ENUMS['formMode'], description: 'Form mode.' },
|
|
3188
2496
|
{ path: 'steps[].form.config', category: 'steps', valueKind: 'object', description: 'FormConfig for Dynamic Form.', safetyNotes: 'Use the form catalog for nested paths and FieldMetadata details.' },
|
|
3189
2497
|
{ path: 'steps[].form.config.editorialContext', category: 'steps', valueKind: 'object', description: 'Contexto editorial compartilhado entre blocos hospedados pelo Dynamic Form da etapa.' },
|
|
3190
|
-
{ path: 'steps[].form.config.formBlocksBefore', category: 'steps', valueKind: '
|
|
3191
|
-
{ path: 'steps[].form.config.formBlocksBeforeActions', category: 'steps', valueKind: '
|
|
3192
|
-
{ path: 'steps[].form.config.formBlocksAfter', category: 'steps', valueKind: '
|
|
2498
|
+
{ path: 'steps[].form.config.formBlocksBefore', category: 'steps', valueKind: 'object', description: 'RichContentDocument hospedado antes do formulario da etapa.' },
|
|
2499
|
+
{ path: 'steps[].form.config.formBlocksBeforeActions', category: 'steps', valueKind: 'object', description: 'RichContentDocument hospedado depois das secoes e antes da area principal de acoes do formulario da etapa.' },
|
|
2500
|
+
{ path: 'steps[].form.config.formBlocksAfter', category: 'steps', valueKind: 'object', description: 'RichContentDocument hospedado depois do formulario inteiro da etapa.' },
|
|
3193
2501
|
{ path: 'steps[].form.schemaSource', category: 'steps', valueKind: 'enum', allowedValues: ENUMS['schemaSource'], description: 'Schema source for Dynamic Form.' },
|
|
3194
2502
|
{ path: 'steps[].form.formId', category: 'steps', valueKind: 'string', description: 'Form id for Dynamic Form.' },
|
|
3195
|
-
{ path: 'steps[].
|
|
3196
|
-
{ path: 'steps[].
|
|
3197
|
-
{ path: 'steps[].widgets
|
|
3198
|
-
{ path: 'steps[].widgets[]
|
|
3199
|
-
{ path: 'steps[].widgets[].
|
|
3200
|
-
{ path: 'steps[].widgets[].
|
|
3201
|
-
{ path: 'steps[].widgets[].bindingOrder', category: 'steps', valueKind: 'array', description: 'Explicit input binding order.' },
|
|
3202
|
-
{ path: 'steps[].widgets[].bindingOrder[]', category: 'steps', valueKind: 'string', description: 'Input name applied first.' },
|
|
2503
|
+
{ path: 'steps[].stepBlocksBeforeForm', category: 'steps', valueKind: 'object', description: 'RichContentDocument rendered before the step form.' },
|
|
2504
|
+
{ path: 'steps[].stepBlocksAfterForm', category: 'steps', valueKind: 'object', description: 'RichContentDocument rendered after the step form.' },
|
|
2505
|
+
{ path: 'steps[].widgets', category: 'steps', valueKind: 'array', description: 'Advanced host-owned WidgetDefinition list rendered after canonical rich content.', safetyNotes: 'Use only for embedded components that cannot be represented as RichContentDocument.' },
|
|
2506
|
+
{ path: 'steps[].widgets[]', category: 'steps', valueKind: 'object', description: 'Advanced WidgetDefinition item.' },
|
|
2507
|
+
{ path: 'steps[].widgets[].id', category: 'steps', valueKind: 'enum', allowedValues: ENUMS['widgetId'], description: 'Component registry id for advanced widget.', safetyNotes: 'Use ids registered in ComponentMetadataRegistry. Do not use widgets for step editorial copy/cards.' },
|
|
2508
|
+
{ path: 'steps[].widgets[].inputs', category: 'steps', valueKind: 'object', description: 'Inputs bound into the advanced widget instance.' },
|
|
3203
2509
|
];
|
|
3204
2510
|
const STEPPER_AI_CAPABILITIES = {
|
|
3205
|
-
version: 'v1.
|
|
2511
|
+
version: 'v1.5',
|
|
3206
2512
|
enums: ENUMS,
|
|
3207
2513
|
targets: [
|
|
3208
2514
|
'praxis-stepper',
|
|
@@ -3214,8 +2520,9 @@ const STEPPER_AI_CAPABILITIES = {
|
|
|
3214
2520
|
notes: [
|
|
3215
2521
|
'steps[] should be merged by id or label to avoid replacing all steps.',
|
|
3216
2522
|
'steps[].form.config uses FormConfig (see form catalog) and may include sections/actions/fieldMetadata.',
|
|
3217
|
-
'steps[].form.config tambem pode usar a surface editorial do dynamic-form: formBlocksBefore, formBlocksBeforeActions, formBlocksAfter e editorialContext.',
|
|
3218
|
-
'steps[].
|
|
2523
|
+
'steps[].form.config tambem pode usar a surface editorial do dynamic-form: formBlocksBefore, formBlocksBeforeActions, formBlocksAfter e editorialContext como RichContentDocument.',
|
|
2524
|
+
'Use steps[].stepBlocksBeforeForm and steps[].stepBlocksAfterForm for editorial step content; both are RichContentDocument surfaces rendered by @praxisui/rich-content.',
|
|
2525
|
+
'steps[].widgets is reserved for advanced embedded components that do not have a canonical rich-content representation.',
|
|
3219
2526
|
'appearance.tokens is a free-form map; host may validate/sanitize.',
|
|
3220
2527
|
'When editing steps[].form.config.fieldMetadata, use FieldMetadata base if no controlType catalog exists.',
|
|
3221
2528
|
],
|
|
@@ -3379,6 +2686,7 @@ class PraxisStepper {
|
|
|
3379
2686
|
return undefined;
|
|
3380
2687
|
} })();
|
|
3381
2688
|
warnedMissingId = false;
|
|
2689
|
+
emptyStepRichContentDocument = createEmptyRichContentDocument();
|
|
3382
2690
|
animationDone = new EventEmitter();
|
|
3383
2691
|
aiAdapter = new StepperAiAdapter(this);
|
|
3384
2692
|
// Computed getters
|
|
@@ -3519,9 +2827,25 @@ class PraxisStepper {
|
|
|
3519
2827
|
}
|
|
3520
2828
|
isStepEmpty(step) {
|
|
3521
2829
|
const hasForm = !!step.form;
|
|
3522
|
-
const
|
|
2830
|
+
const hasBlocksBefore = this.hasRichContent(step.stepBlocksBeforeForm);
|
|
2831
|
+
const hasBlocksAfter = this.hasRichContent(step.stepBlocksAfterForm);
|
|
3523
2832
|
const hasWidgets = Array.isArray(step.widgets) && step.widgets.length > 0;
|
|
3524
|
-
return !hasForm && !hasWidgets && !
|
|
2833
|
+
return !hasForm && !hasWidgets && !hasBlocksBefore && !hasBlocksAfter;
|
|
2834
|
+
}
|
|
2835
|
+
hasRichContent(document) {
|
|
2836
|
+
return Array.isArray(document?.nodes) && document.nodes.length > 0;
|
|
2837
|
+
}
|
|
2838
|
+
getStepRichContentContext(stepIndex) {
|
|
2839
|
+
const step = this.steps()[stepIndex];
|
|
2840
|
+
return {
|
|
2841
|
+
step: (step ?? {}),
|
|
2842
|
+
stepIndex,
|
|
2843
|
+
stepper: {
|
|
2844
|
+
stepperId: this.stepperId,
|
|
2845
|
+
selectedIndex: this.selectedIndexComputed(),
|
|
2846
|
+
},
|
|
2847
|
+
...(this.stepperContext ?? {}),
|
|
2848
|
+
};
|
|
3525
2849
|
}
|
|
3526
2850
|
openEditor() {
|
|
3527
2851
|
const cfg = this._config() || { steps: [], orientation: 'horizontal', headerPosition: 'top', linear: false };
|
|
@@ -3784,12 +3108,12 @@ class PraxisStepper {
|
|
|
3784
3108
|
<ng-template #plainLabel>{{ step.label }}</ng-template>
|
|
3785
3109
|
</ng-template>
|
|
3786
3110
|
<div [class]="contentClassList()">
|
|
3787
|
-
<
|
|
3788
|
-
|
|
3789
|
-
[
|
|
3790
|
-
[
|
|
3791
|
-
|
|
3792
|
-
|
|
3111
|
+
<praxis-rich-content
|
|
3112
|
+
*ngIf="hasRichContent(step.stepBlocksBeforeForm)"
|
|
3113
|
+
[document]="step.stepBlocksBeforeForm || emptyStepRichContentDocument"
|
|
3114
|
+
[context]="getStepRichContentContext(i)"
|
|
3115
|
+
rootClassName="pdx-step-rich-content pdx-step-rich-content--before"
|
|
3116
|
+
></praxis-rich-content>
|
|
3793
3117
|
<praxis-dynamic-form *ngIf="step.form as f"
|
|
3794
3118
|
[resourcePath]="f.resourcePath"
|
|
3795
3119
|
[resourceId]="$any(f.resourceId)"
|
|
@@ -3800,6 +3124,12 @@ class PraxisStepper {
|
|
|
3800
3124
|
(formReady)="onFormReady(i, $event)"
|
|
3801
3125
|
(valueChange)="onFormValueChange(i, $event)"
|
|
3802
3126
|
></praxis-dynamic-form>
|
|
3127
|
+
<praxis-rich-content
|
|
3128
|
+
*ngIf="hasRichContent(step.stepBlocksAfterForm)"
|
|
3129
|
+
[document]="step.stepBlocksAfterForm || emptyStepRichContentDocument"
|
|
3130
|
+
[context]="getStepRichContentContext(i)"
|
|
3131
|
+
rootClassName="pdx-step-rich-content pdx-step-rich-content--after"
|
|
3132
|
+
></praxis-rich-content>
|
|
3803
3133
|
<ng-container *ngFor="let wd of step.widgets || []"
|
|
3804
3134
|
[dynamicWidgetLoader]="wd"
|
|
3805
3135
|
[context]="stepperContext"
|
|
@@ -3881,11 +3211,11 @@ class PraxisStepper {
|
|
|
3881
3211
|
>
|
|
3882
3212
|
<mat-icon fontIcon="edit"></mat-icon>
|
|
3883
3213
|
</button>
|
|
3884
|
-
`, 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.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;--mat-stepper-header-hover-state-layer-color: color-mix( in srgb, var(--md-sys-color-on-surface) 8%, transparent );--mat-stepper-header-focus-state-layer-color: transparent;--mat-stepper-header-hover-state-layer-shape: 14px;--mat-stepper-header-focus-state-layer-shape: 14px}::ng-deep .pdx-stepper-ft-light .mat-step-header{margin:0}::ng-deep .pdx-stepper-ft-light .mat-step-header .mat-step-header-ripple{display:none}::ng-deep .ft-stepper{background:transparent}.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", "editorialContext", "mode", "config", "schemaSource", "schemaUrl", "submitUrl", "submitMethod", "responseSchemaUrl", "apiEndpointKey", "apiUrlEntry", "enableCustomization", "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", "enableCustomizationChange", "customAction", "actionConfirmation", "schemaStatusChange", "fieldRenderError"
|
|
3214
|
+
`, 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.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;--mat-stepper-header-hover-state-layer-color: color-mix( in srgb, var(--md-sys-color-on-surface) 8%, transparent );--mat-stepper-header-focus-state-layer-color: transparent;--mat-stepper-header-hover-state-layer-shape: 14px;--mat-stepper-header-focus-state-layer-shape: 14px}::ng-deep .pdx-stepper-ft-light .mat-step-header{margin:0}::ng-deep .pdx-stepper-ft-light .mat-step-header .mat-step-header-ripple{display:none}::ng-deep .ft-stepper{background:transparent}.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", "initialValue", "editorialContext", "mode", "config", "schemaSource", "schemaUrl", "submitUrl", "submitMethod", "responseSchemaUrl", "apiEndpointKey", "apiUrlEntry", "enableCustomization", "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", "enableCustomizationChange", "customAction", "actionConfirmation", "schemaStatusChange", "fieldRenderError"] }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "ownerWidgetKey", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent", "widgetDiagnostic"], 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"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3885
3215
|
}
|
|
3886
3216
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisStepper, decorators: [{
|
|
3887
3217
|
type: Component,
|
|
3888
|
-
args: [{ selector: 'praxis-stepper', standalone: true, imports: [CommonModule, ReactiveFormsModule, MatStepperModule, MatButtonModule, MatIconModule, PraxisIconDirective, PraxisDynamicForm, DynamicWidgetLoaderDirective, EmptyStateCardComponent, PraxisAiAssistantComponent], host: {
|
|
3218
|
+
args: [{ selector: 'praxis-stepper', standalone: true, imports: [CommonModule, ReactiveFormsModule, MatStepperModule, MatButtonModule, MatIconModule, PraxisIconDirective, PraxisDynamicForm, DynamicWidgetLoaderDirective, EmptyStateCardComponent, PraxisAiAssistantComponent, PraxisRichContent], host: {
|
|
3889
3219
|
'[class]': 'densityClass()'
|
|
3890
3220
|
}, template: `
|
|
3891
3221
|
<div class="stepper-ai-assistant" *ngIf="enableCustomization">
|
|
@@ -3942,12 +3272,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
3942
3272
|
<ng-template #plainLabel>{{ step.label }}</ng-template>
|
|
3943
3273
|
</ng-template>
|
|
3944
3274
|
<div [class]="contentClassList()">
|
|
3945
|
-
<
|
|
3946
|
-
|
|
3947
|
-
[
|
|
3948
|
-
[
|
|
3949
|
-
|
|
3950
|
-
|
|
3275
|
+
<praxis-rich-content
|
|
3276
|
+
*ngIf="hasRichContent(step.stepBlocksBeforeForm)"
|
|
3277
|
+
[document]="step.stepBlocksBeforeForm || emptyStepRichContentDocument"
|
|
3278
|
+
[context]="getStepRichContentContext(i)"
|
|
3279
|
+
rootClassName="pdx-step-rich-content pdx-step-rich-content--before"
|
|
3280
|
+
></praxis-rich-content>
|
|
3951
3281
|
<praxis-dynamic-form *ngIf="step.form as f"
|
|
3952
3282
|
[resourcePath]="f.resourcePath"
|
|
3953
3283
|
[resourceId]="$any(f.resourceId)"
|
|
@@ -3958,6 +3288,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
3958
3288
|
(formReady)="onFormReady(i, $event)"
|
|
3959
3289
|
(valueChange)="onFormValueChange(i, $event)"
|
|
3960
3290
|
></praxis-dynamic-form>
|
|
3291
|
+
<praxis-rich-content
|
|
3292
|
+
*ngIf="hasRichContent(step.stepBlocksAfterForm)"
|
|
3293
|
+
[document]="step.stepBlocksAfterForm || emptyStepRichContentDocument"
|
|
3294
|
+
[context]="getStepRichContentContext(i)"
|
|
3295
|
+
rootClassName="pdx-step-rich-content pdx-step-rich-content--after"
|
|
3296
|
+
></praxis-rich-content>
|
|
3961
3297
|
<ng-container *ngFor="let wd of step.widgets || []"
|
|
3962
3298
|
[dynamicWidgetLoader]="wd"
|
|
3963
3299
|
[context]="stepperContext"
|
|
@@ -4346,7 +3682,7 @@ const PRAXIS_WIZARD_CONTENT_METADATA = {
|
|
|
4346
3682
|
selector: 'praxis-wizard-content-block',
|
|
4347
3683
|
component: PraxisWizardContentBlockComponent,
|
|
4348
3684
|
friendlyName: 'Wizard Content Block',
|
|
4349
|
-
description: 'Bloco editorial legado do wizard com título/subtítulo/texto. Está formalmente em deprecação para novo authoring e converge para
|
|
3685
|
+
description: 'Bloco editorial legado do wizard com título/subtítulo/texto. Está formalmente em deprecação para novo authoring e converge para RichContentDocument em stepBlocksBeforeForm/stepBlocksAfterForm, mas continua suportado para leitura e edição de configurações existentes neste ciclo.',
|
|
4350
3686
|
icon: 'article',
|
|
4351
3687
|
inputs: [
|
|
4352
3688
|
{ name: 'blockId', type: 'string', label: 'Block ID legado', description: 'Identificador operacional legado do wizard, usado hoje para telemetria/e2e e compatibilidade com editor/adapter.' },
|
|
@@ -4695,23 +4031,6 @@ const FT_WIZARD_JSON = `{
|
|
|
4695
4031
|
}`;
|
|
4696
4032
|
const FT_WIZARD_CONFIG = JSON.parse(FT_WIZARD_JSON);
|
|
4697
4033
|
|
|
4698
|
-
const defaultCardSkin = {
|
|
4699
|
-
type: 'elevated',
|
|
4700
|
-
radius: '12px',
|
|
4701
|
-
border: '1px solid var(--md-sys-color-outline-variant, #e0e0e0)',
|
|
4702
|
-
shadow: '0 1px 2px rgba(0,0,0,0.06)',
|
|
4703
|
-
};
|
|
4704
|
-
const defaultCardLayout = {
|
|
4705
|
-
variant: 'cards',
|
|
4706
|
-
density: 'comfortable',
|
|
4707
|
-
lines: 2,
|
|
4708
|
-
model: 'standard',
|
|
4709
|
-
dividers: 'none',
|
|
4710
|
-
};
|
|
4711
|
-
const defaultCardTemplating = {
|
|
4712
|
-
primary: { type: 'text', expr: '${item.title}', class: 'ft-card-title' },
|
|
4713
|
-
secondary: { type: 'text', expr: '${item.description}', class: 'ft-card-desc' },
|
|
4714
|
-
};
|
|
4715
4034
|
function buildStepperConfig(wizard) {
|
|
4716
4035
|
const steps = wizard.steps.map((step) => buildStep(step, wizard.id));
|
|
4717
4036
|
return {
|
|
@@ -4733,19 +4052,17 @@ function buildStepperConfig(wizard) {
|
|
|
4733
4052
|
}
|
|
4734
4053
|
function buildStep(step, wizardId) {
|
|
4735
4054
|
const blocks = buildBlocks(mergeBlocks(step), wizardId, step.id);
|
|
4736
|
-
const
|
|
4055
|
+
const beforeNodes = [
|
|
4737
4056
|
...blocks.before,
|
|
4738
|
-
...(step
|
|
4057
|
+
...buildCardNodes(step),
|
|
4739
4058
|
];
|
|
4740
|
-
const widgetsBeforeForm = beforeWidgets.length ? beforeWidgets : undefined;
|
|
4741
|
-
const widgetsAfterForm = blocks.after.length ? blocks.after : undefined;
|
|
4742
4059
|
return {
|
|
4743
4060
|
id: step.id,
|
|
4744
4061
|
label: step.label,
|
|
4745
4062
|
description: step.subtitle || step.description,
|
|
4746
4063
|
optional: step.optional,
|
|
4747
|
-
|
|
4748
|
-
|
|
4064
|
+
stepBlocksBeforeForm: toDocument(beforeNodes),
|
|
4065
|
+
stepBlocksAfterForm: toDocument(blocks.after),
|
|
4749
4066
|
form: step.form
|
|
4750
4067
|
? {
|
|
4751
4068
|
formId: step.form.formId || `${wizardId}:${step.id}`,
|
|
@@ -4755,22 +4072,16 @@ function buildStep(step, wizardId) {
|
|
|
4755
4072
|
: undefined,
|
|
4756
4073
|
};
|
|
4757
4074
|
}
|
|
4758
|
-
function
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
id: 'praxis-list',
|
|
4769
|
-
inputs: {
|
|
4770
|
-
listId: cfg.id,
|
|
4771
|
-
config: cfg,
|
|
4772
|
-
},
|
|
4773
|
-
};
|
|
4075
|
+
function buildCardNodes(step) {
|
|
4076
|
+
return (step.cards ?? []).map((card, index) => ({
|
|
4077
|
+
type: 'card',
|
|
4078
|
+
id: `${step.id}:card:${index}`,
|
|
4079
|
+
title: card.title,
|
|
4080
|
+
content: [
|
|
4081
|
+
...(card.icon ? [{ type: 'icon', icon: card.icon, ariaLabel: card.title }] : []),
|
|
4082
|
+
...(card.description ? [{ type: 'text', text: card.description }] : []),
|
|
4083
|
+
],
|
|
4084
|
+
}));
|
|
4774
4085
|
}
|
|
4775
4086
|
function mergeBlocks(step) {
|
|
4776
4087
|
const out = [];
|
|
@@ -4800,7 +4111,7 @@ function buildBlocks(blocks, wizardId, stepId) {
|
|
|
4800
4111
|
const after = [];
|
|
4801
4112
|
blocks.forEach((block, index) => {
|
|
4802
4113
|
const placement = block.placement ?? 'beforeForm';
|
|
4803
|
-
const def =
|
|
4114
|
+
const def = toRichNode(block, wizardId, stepId, index);
|
|
4804
4115
|
if (!def)
|
|
4805
4116
|
return;
|
|
4806
4117
|
if (placement === 'afterForm')
|
|
@@ -4816,57 +4127,76 @@ function resolveBlockRuntimeId(block, wizardId, stepId, index) {
|
|
|
4816
4127
|
? `${wizardId}:${stepId}:block:${explicitId}`
|
|
4817
4128
|
: `${wizardId}:${stepId}:block:${index}`;
|
|
4818
4129
|
}
|
|
4819
|
-
function
|
|
4130
|
+
function toRichNode(block, wizardId, stepId, index) {
|
|
4820
4131
|
const baseId = resolveBlockRuntimeId(block, wizardId, stepId, index);
|
|
4821
4132
|
switch (block.type) {
|
|
4822
4133
|
case 'benefitsGrid':
|
|
4823
4134
|
return {
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4135
|
+
type: 'card',
|
|
4136
|
+
id: baseId,
|
|
4137
|
+
title: block.title,
|
|
4138
|
+
className: block.boxed === false ? 'pdx-wizard-benefits pdx-wizard-benefits--plain' : 'pdx-wizard-benefits',
|
|
4139
|
+
content: block.items.flatMap((item, itemIndex) => {
|
|
4140
|
+
const nodes = [
|
|
4141
|
+
{ type: 'text', text: item.title, id: `${baseId}:title:${itemIndex}` },
|
|
4142
|
+
];
|
|
4143
|
+
if (item.icon) {
|
|
4144
|
+
nodes.unshift({ type: 'icon', icon: item.icon, ariaLabel: item.title, id: `${baseId}:icon:${itemIndex}` });
|
|
4145
|
+
}
|
|
4146
|
+
if (item.text) {
|
|
4147
|
+
nodes.push({ type: 'text', text: item.text, id: `${baseId}:text:${itemIndex}` });
|
|
4148
|
+
}
|
|
4149
|
+
return nodes;
|
|
4150
|
+
}),
|
|
4832
4151
|
};
|
|
4833
4152
|
case 'contentBlock':
|
|
4834
4153
|
return {
|
|
4835
|
-
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
4840
|
-
contentFormat: 'plain',
|
|
4841
|
-
content: joinContentParts(block.text, block.caption),
|
|
4842
|
-
},
|
|
4154
|
+
type: 'card',
|
|
4155
|
+
id: baseId,
|
|
4156
|
+
title: block.title,
|
|
4157
|
+
subtitle: block.subtitle,
|
|
4158
|
+
content: textNodes(baseId, block.text, block.caption),
|
|
4843
4159
|
};
|
|
4844
4160
|
case 'inlineNotice':
|
|
4845
4161
|
return {
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
tone: block.tone,
|
|
4851
|
-
|
|
4162
|
+
type: 'compose',
|
|
4163
|
+
id: baseId,
|
|
4164
|
+
gap: 'sm',
|
|
4165
|
+
items: [
|
|
4166
|
+
{ type: 'icon', icon: block.tone === 'warning' ? 'warning' : 'info', ariaLabel: block.tone ?? 'info' },
|
|
4167
|
+
{ type: 'text', text: block.text },
|
|
4168
|
+
],
|
|
4852
4169
|
};
|
|
4853
4170
|
case 'divider':
|
|
4854
4171
|
return {
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
},
|
|
4172
|
+
type: 'text',
|
|
4173
|
+
id: baseId,
|
|
4174
|
+
text: block.label ?? '',
|
|
4175
|
+
className: 'pdx-wizard-divider',
|
|
4860
4176
|
};
|
|
4861
4177
|
default:
|
|
4862
4178
|
return null;
|
|
4863
4179
|
}
|
|
4864
4180
|
}
|
|
4865
|
-
function
|
|
4866
|
-
|
|
4181
|
+
function textNodes(baseId, text, caption) {
|
|
4182
|
+
return [text, caption]
|
|
4867
4183
|
.map((value) => (typeof value === 'string' ? value.trim() : ''))
|
|
4868
|
-
.filter(Boolean)
|
|
4869
|
-
|
|
4184
|
+
.filter(Boolean)
|
|
4185
|
+
.map((value, index) => ({
|
|
4186
|
+
type: 'text',
|
|
4187
|
+
id: `${baseId}:text:${index}`,
|
|
4188
|
+
text: value,
|
|
4189
|
+
}));
|
|
4190
|
+
}
|
|
4191
|
+
function toDocument(nodes) {
|
|
4192
|
+
if (!nodes.length) {
|
|
4193
|
+
return null;
|
|
4194
|
+
}
|
|
4195
|
+
return {
|
|
4196
|
+
kind: 'praxis.rich-content',
|
|
4197
|
+
version: '1.0.0',
|
|
4198
|
+
nodes,
|
|
4199
|
+
};
|
|
4870
4200
|
}
|
|
4871
4201
|
|
|
4872
4202
|
class PraxisWizardCtaBarComponent {
|