@praxisui/editorial-forms 1.0.0-beta.61 → 1.0.0-beta.64

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.
@@ -1,8 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { makeEnvironmentProviders, InjectionToken, inject, input, output, signal, computed, effect, ChangeDetectionStrategy, Component, reflectComponentType, Input } from '@angular/core';
3
- import * as i1 from '@angular/common';
4
- import { CommonModule, NgComponentOutlet } from '@angular/common';
5
- import { DynamicWidgetLoaderDirective } from '@praxisui/core';
2
+ import { makeEnvironmentProviders, InjectionToken, inject, DestroyRef, viewChild, ViewContainerRef, input, output, signal, computed, effect, ChangeDetectionStrategy, Component, reflectComponentType, Input } from '@angular/core';
3
+ import { CommonModule } from '@angular/common';
4
+ import { PraxisI18nService, PraxisIconDirective, DynamicWidgetLoaderDirective, providePraxisI18n } from '@praxisui/core';
5
+ import * as i1 from '@angular/material/icon';
6
+ import { MatIconModule } from '@angular/material/icon';
6
7
 
7
8
  /**
8
9
  * Root provider entrypoint for the editorial runtime package.
@@ -173,16 +174,23 @@ function resolveEditorialDataBlockAdapter(adapters, context) {
173
174
  }
174
175
 
175
176
  class EditorialDataCollectionBlockOutletComponent {
177
+ i18n = inject(PraxisI18nService);
176
178
  adapters = inject(EDITORIAL_DATA_BLOCK_ADAPTER, {
177
179
  optional: true,
178
180
  }) ?? [];
181
+ destroyRef = inject(DestroyRef);
179
182
  adapterRegistry = new EditorialDataBlockAdapterRegistry(this.adapters);
183
+ adapterHost = viewChild('adapterHost', ...(ngDevMode ? [{ debugName: "adapterHost", read: ViewContainerRef }] : [{ read: ViewContainerRef }]));
180
184
  loadVersion = 0;
181
185
  lastAdapterEventSignature = null;
186
+ componentRef = null;
187
+ renderedComponentType = null;
188
+ componentOutputSubscriptions = [];
182
189
  block = input.required(...(ngDevMode ? [{ debugName: "block" }] : []));
183
190
  runtimeContext = input(null, ...(ngDevMode ? [{ debugName: "runtimeContext" }] : []));
184
191
  solution = input(null, ...(ngDevMode ? [{ debugName: "solution" }] : []));
185
192
  instance = input(null, ...(ngDevMode ? [{ debugName: "instance" }] : []));
193
+ runtimeContextChange = output();
186
194
  operationalEvent = output();
187
195
  resolvedComponent = signal(null, ...(ngDevMode ? [{ debugName: "resolvedComponent" }] : []));
188
196
  state = signal({ kind: 'idle' }, ...(ngDevMode ? [{ debugName: "state" }] : []));
@@ -231,23 +239,42 @@ class EditorialDataCollectionBlockOutletComponent {
231
239
  return errorState.message;
232
240
  }
233
241
  if (snapshotState?.readiness === 'invalid') {
234
- return `O bloco "${block.formBlockId}" foi materializado com estado invalido. Revise formBlockId, formConfigRef e a configuracao editorial herdada.`;
242
+ return this.t('dataCollection.fallback.invalid', 'O bloco "{formBlockId}" foi materializado com estado invalido. Revise formBlockId, formConfigRef e a configuracao editorial herdada.', { formBlockId: block.formBlockId });
235
243
  }
236
244
  if (snapshotState?.readiness === 'missingConfig') {
237
- return `O bloco "${block.formBlockId}" nao encontrou configuracao de coleta. Chave consultada: ${snapshotState.resolvedFormConfigLookupKey ?? 'nenhuma chave candidata'}.`;
245
+ return this.t('dataCollection.fallback.missingConfig', 'O bloco "{formBlockId}" nao encontrou configuracao de coleta. Chave consultada: {lookupKey}.', {
246
+ formBlockId: block.formBlockId,
247
+ lookupKey: snapshotState.resolvedFormConfigLookupKey ?? 'nenhuma chave candidata',
248
+ });
238
249
  }
239
250
  if (adapterResolution.status === 'incompatible') {
240
- return `O bloco "${block.formBlockId}" encontrou adapters registrados (${adapterResolution.adapterIds.join(', ')}), mas nenhum declarou compatibilidade para esta coleta.`;
251
+ return this.t('dataCollection.fallback.incompatible', 'O bloco "{formBlockId}" encontrou adapters registrados ({adapterIds}), mas nenhum declarou compatibilidade para esta coleta.', {
252
+ formBlockId: block.formBlockId,
253
+ adapterIds: adapterResolution.adapterIds.join(', ') || 'nenhum',
254
+ });
241
255
  }
242
256
  if (!resolution.formConfig && adapterResolution.status === 'missing') {
243
- return `O bloco "${block.formBlockId}" nao encontrou configuracao de coleta nem adaptador registrado. Verifique o provider do host e a materializacao do FormConfig editorial.`;
257
+ return this.t('dataCollection.fallback.missingAdapter', 'O bloco "{formBlockId}" nao encontrou configuracao de coleta nem adaptador registrado. Verifique o provider do host e a materializacao do FormConfig editorial.', { formBlockId: block.formBlockId });
244
258
  }
245
259
  if (!resolution.formConfig) {
246
- return `O bloco "${block.formBlockId}" encontrou um adaptador, mas nao encontrou FormConfig em ${resolution.lookupKey ?? 'nenhuma chave conhecida'}.`;
260
+ return this.t('dataCollection.fallback.adapterWithoutConfig', 'O bloco "{formBlockId}" encontrou um adaptador, mas nao encontrou FormConfig em {lookupKey}.', {
261
+ formBlockId: block.formBlockId,
262
+ lookupKey: resolution.lookupKey ?? 'nenhuma chave conhecida',
263
+ });
247
264
  }
248
- return `Existe configuracao para "${block.formBlockId}" (${resolution.source}), mas nenhum adaptador de coleta foi registrado para materializar a engine.`;
265
+ return this.t('dataCollection.fallback.unresolvedEngine', 'Existe configuracao para "{formBlockId}" ({source}), mas nenhum adaptador de coleta foi registrado para materializar a engine.', {
266
+ formBlockId: block.formBlockId,
267
+ source: resolution.source,
268
+ });
249
269
  }, ...(ngDevMode ? [{ debugName: "fallbackMessage" }] : []));
270
+ effectiveSurface = computed(() => this.block().surface === 'plain' ? 'plain' : 'card', ...(ngDevMode ? [{ debugName: "effectiveSurface" }] : []));
271
+ showBlockTitle = computed(() => Boolean(this.block().title) && !this.shouldHideBlockTitle(), ...(ngDevMode ? [{ debugName: "showBlockTitle" }] : []));
272
+ showBlockDescription = computed(() => Boolean(this.block().description) && !this.shouldHideBlockDescription(), ...(ngDevMode ? [{ debugName: "showBlockDescription" }] : []));
273
+ showBlockHeader = computed(() => this.showBlockTitle() || this.showBlockDescription(), ...(ngDevMode ? [{ debugName: "showBlockHeader" }] : []));
250
274
  constructor() {
275
+ this.destroyRef.onDestroy(() => {
276
+ this.destroyRenderedComponent();
277
+ });
251
278
  effect(() => {
252
279
  const context = this.adapterContext();
253
280
  const resolution = this.resolution();
@@ -261,9 +288,9 @@ class EditorialDataCollectionBlockOutletComponent {
261
288
  if (adapterResolution.status === 'incompatible') {
262
289
  this.state.set({
263
290
  kind: 'error',
264
- title: 'Adaptador incompatível',
265
- message: `Nenhum adaptador registrado aceitou o bloco "${context.block.formBlockId}".`,
266
- details: `Adapters disponiveis: ${adapterResolution.adapterIds.join(', ') || 'nenhum'}.`,
291
+ title: this.t('dataCollection.error.incompatibleTitle', 'Adaptador incompatível'),
292
+ message: this.t('dataCollection.error.incompatibleMessage', 'Nenhum adaptador registrado aceitou o bloco "{formBlockId}".', { formBlockId: context.block.formBlockId }),
293
+ details: this.t('dataCollection.error.availableAdapters', 'Adapters disponiveis: {adapterIds}.', { adapterIds: adapterResolution.adapterIds.join(', ') || 'nenhum' }),
267
294
  });
268
295
  }
269
296
  return;
@@ -272,9 +299,9 @@ class EditorialDataCollectionBlockOutletComponent {
272
299
  this.resolvedComponent.set(null);
273
300
  this.state.set({
274
301
  kind: 'error',
275
- title: 'Configuracao de coleta ausente',
276
- message: `O bloco "${context.block.formBlockId}" nao possui FormConfig resolvido para a engine de coleta.`,
277
- details: `Origem consultada: ${resolution.lookupKey ?? 'nenhuma chave candidata'}.`,
302
+ title: this.t('dataCollection.error.missingConfigTitle', 'Configuracao de coleta ausente'),
303
+ message: this.t('dataCollection.error.missingConfigMessage', 'O bloco "{formBlockId}" nao possui FormConfig resolvido para a engine de coleta.', { formBlockId: context.block.formBlockId }),
304
+ details: this.t('dataCollection.error.lookupSource', 'Origem consultada: {lookupKey}.', { lookupKey: resolution.lookupKey ?? 'nenhuma chave candidata' }),
278
305
  });
279
306
  return;
280
307
  }
@@ -282,12 +309,12 @@ class EditorialDataCollectionBlockOutletComponent {
282
309
  const component = adapter.component ?? null;
283
310
  if (!component) {
284
311
  this.resolvedComponent.set(null);
285
- this.emitAdapterResolutionEvent('invalid', adapter, 'Registre um componente compatível ou implemente resolveComponent().');
312
+ this.emitAdapterResolutionEvent('invalid', adapter, this.t('dataCollection.error.adapterRegistrationHint', 'Registre um componente compatível ou implemente resolveComponent().'));
286
313
  this.state.set({
287
314
  kind: 'error',
288
- title: 'Adaptador incompleto',
289
- message: `O adaptador "${adapter.displayName ?? adapter.adapterId}" nao expôs um componente de coleta.`,
290
- details: 'Registre um componente compatível ou implemente resolveComponent().',
315
+ title: this.t('dataCollection.error.incompleteAdapterTitle', 'Adaptador incompleto'),
316
+ message: this.t('dataCollection.error.incompleteAdapterMessage', 'O adaptador "{adapterName}" nao expôs um componente de coleta.', { adapterName: adapter.displayName ?? adapter.adapterId }),
317
+ details: this.t('dataCollection.error.adapterRegistrationHint', 'Registre um componente compatível ou implemente resolveComponent().'),
291
318
  });
292
319
  return;
293
320
  }
@@ -296,10 +323,26 @@ class EditorialDataCollectionBlockOutletComponent {
296
323
  }
297
324
  this.state.set({
298
325
  kind: 'loading',
299
- message: `Carregando a engine de coleta para "${context.block.formBlockId}"...`,
326
+ message: this.t('dataCollection.loadingMessage', 'Carregando a engine de coleta para "{formBlockId}"...', { formBlockId: context.block.formBlockId }),
300
327
  });
301
328
  void this.loadAdapterComponent(adapter, context, requestVersion);
302
329
  });
330
+ effect(() => {
331
+ const component = this.adapterComponent();
332
+ const host = this.adapterHost();
333
+ if (!host || !component) {
334
+ this.destroyRenderedComponent();
335
+ return;
336
+ }
337
+ if (this.renderedComponentType !== component) {
338
+ this.destroyRenderedComponent();
339
+ host.clear();
340
+ this.componentRef = host.createComponent(component);
341
+ this.renderedComponentType = component;
342
+ this.bindComponentOutputs(this.componentRef);
343
+ }
344
+ this.applyComponentInputs();
345
+ });
303
346
  }
304
347
  async loadAdapterComponent(adapter, context, requestVersion) {
305
348
  try {
@@ -313,9 +356,12 @@ class EditorialDataCollectionBlockOutletComponent {
313
356
  this.resolvedComponent.set(null);
314
357
  this.state.set({
315
358
  kind: 'error',
316
- title: 'Falha ao carregar a engine',
317
- message: `O adaptador "${adapter.displayName ?? adapter.adapterId}" falhou ao preparar a coleta do bloco "${context.block.formBlockId}".`,
318
- details: 'Valide o provider opcional do host e a disponibilidade do componente compatível.',
359
+ title: this.t('dataCollection.error.loadFailureTitle', 'Falha ao carregar a engine'),
360
+ message: this.t('dataCollection.error.loadFailureMessage', 'O adaptador "{adapterName}" falhou ao preparar a coleta do bloco "{formBlockId}".', {
361
+ adapterName: adapter.displayName ?? adapter.adapterId,
362
+ formBlockId: context.block.formBlockId,
363
+ }),
364
+ details: this.t('dataCollection.error.loadFailureDetails', 'Valide o provider opcional do host e a disponibilidade do componente compatível.'),
319
365
  });
320
366
  }
321
367
  }
@@ -327,9 +373,12 @@ class EditorialDataCollectionBlockOutletComponent {
327
373
  this.resolvedComponent.set(null);
328
374
  this.state.set({
329
375
  kind: 'error',
330
- title: 'Componente nao resolvido',
331
- message: `O adaptador "${adapter.displayName ?? adapter.adapterId}" nao retornou um componente para o bloco "${context.block.formBlockId}".`,
332
- details: 'Implemente component ou resolveComponent() com um componente Angular compatível.',
376
+ title: this.t('dataCollection.error.unresolvedComponentTitle', 'Componente nao resolvido'),
377
+ message: this.t('dataCollection.error.unresolvedComponentMessage', 'O adaptador "{adapterName}" nao retornou um componente para o bloco "{formBlockId}".', {
378
+ adapterName: adapter.displayName ?? adapter.adapterId,
379
+ formBlockId: context.block.formBlockId,
380
+ }),
381
+ details: this.t('dataCollection.error.unresolvedComponentDetails', 'Implemente component ou resolveComponent() com um componente Angular compatível.'),
333
382
  });
334
383
  return;
335
384
  }
@@ -339,8 +388,11 @@ class EditorialDataCollectionBlockOutletComponent {
339
388
  this.emitAdapterResolutionEvent('invalid', adapter, validation.reason);
340
389
  this.state.set({
341
390
  kind: 'error',
342
- title: 'Componente incompatível',
343
- message: `O adaptador "${adapter.displayName ?? adapter.adapterId}" retornou um componente incompatível para "${context.block.formBlockId}".`,
391
+ title: this.t('dataCollection.error.invalidComponentTitle', 'Componente incompatível'),
392
+ message: this.t('dataCollection.error.invalidComponentMessage', 'O adaptador "{adapterName}" retornou um componente incompatível para "{formBlockId}".', {
393
+ adapterName: adapter.displayName ?? adapter.adapterId,
394
+ formBlockId: context.block.formBlockId,
395
+ }),
344
396
  details: validation.reason,
345
397
  });
346
398
  return;
@@ -408,98 +460,854 @@ class EditorialDataCollectionBlockOutletComponent {
408
460
  },
409
461
  });
410
462
  }
463
+ applyComponentInputs() {
464
+ if (!this.componentRef) {
465
+ return;
466
+ }
467
+ const inputs = {
468
+ block: this.block(),
469
+ runtimeContext: this.runtimeContext(),
470
+ solution: this.solution(),
471
+ instance: this.instance(),
472
+ resolvedFormConfig: this.resolution().formConfig,
473
+ ...(this.adapter()?.buildInputs?.(this.adapterContext()) ?? {}),
474
+ };
475
+ for (const [key, value] of Object.entries(inputs)) {
476
+ this.componentRef.setInput(key, value);
477
+ }
478
+ }
479
+ bindComponentOutputs(componentRef) {
480
+ this.componentOutputSubscriptions = [];
481
+ const instance = componentRef.instance;
482
+ const valueChange = instance['valueChange'];
483
+ if (!isSubscribableOutput(valueChange)) {
484
+ return;
485
+ }
486
+ this.componentOutputSubscriptions.push(valueChange.subscribe((event) => {
487
+ const payload = extractFormDataChangeEvent(event);
488
+ if (!payload) {
489
+ return;
490
+ }
491
+ this.runtimeContextChange.emit(this.mergeFormDataIntoRuntimeContext(payload));
492
+ }));
493
+ }
494
+ mergeFormDataIntoRuntimeContext(payload) {
495
+ const runtimeContext = this.runtimeContext();
496
+ const currentFormData = readRuntimeFormData(runtimeContext);
497
+ const nextFormData = payload.mode === 'replace'
498
+ ? { ...payload.formData }
499
+ : { ...currentFormData, ...payload.formData };
500
+ for (const key of payload.removedKeys ?? []) {
501
+ delete nextFormData[key];
502
+ }
503
+ return {
504
+ ...(runtimeContext ?? {}),
505
+ formData: nextFormData,
506
+ };
507
+ }
508
+ destroyRenderedComponent() {
509
+ for (const subscription of this.componentOutputSubscriptions) {
510
+ subscription.unsubscribe();
511
+ }
512
+ this.componentOutputSubscriptions = [];
513
+ this.componentRef?.destroy();
514
+ this.componentRef = null;
515
+ this.renderedComponentType = null;
516
+ }
517
+ t(key, fallback, params) {
518
+ return this.i18n.t(`praxis.editorialForms.${key}`, params, fallback);
519
+ }
520
+ shouldHideBlockTitle() {
521
+ if (this.effectiveSurface() !== 'plain') {
522
+ return false;
523
+ }
524
+ const section = this.getSingleResolvedSection();
525
+ return !!section && areEquivalentCopy(this.block().title, section.title);
526
+ }
527
+ shouldHideBlockDescription() {
528
+ if (this.effectiveSurface() !== 'plain') {
529
+ return false;
530
+ }
531
+ const section = this.getSingleResolvedSection();
532
+ return !!section && areEquivalentCopy(this.block().description, section.description);
533
+ }
534
+ getSingleResolvedSection() {
535
+ const sections = this.resolution().formConfig?.sections ?? [];
536
+ if (sections.length !== 1) {
537
+ return null;
538
+ }
539
+ const [section] = sections;
540
+ return section ?? null;
541
+ }
411
542
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialDataCollectionBlockOutletComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
412
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialDataCollectionBlockOutletComponent, isStandalone: true, selector: "praxis-editorial-data-collection-block-outlet", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: true, transformFunction: null }, runtimeContext: { classPropertyName: "runtimeContext", publicName: "runtimeContext", isSignal: true, isRequired: false, transformFunction: null }, solution: { classPropertyName: "solution", publicName: "solution", isSignal: true, isRequired: false, transformFunction: null }, instance: { classPropertyName: "instance", publicName: "instance", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { operationalEvent: "operationalEvent" }, ngImport: i0, template: `
413
- <section class="block-card data-block">
414
- @if (block().title) {
415
- <h3>{{ block().title }}</h3>
543
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialDataCollectionBlockOutletComponent, isStandalone: true, selector: "praxis-editorial-data-collection-block-outlet", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: true, transformFunction: null }, runtimeContext: { classPropertyName: "runtimeContext", publicName: "runtimeContext", isSignal: true, isRequired: false, transformFunction: null }, solution: { classPropertyName: "solution", publicName: "solution", isSignal: true, isRequired: false, transformFunction: null }, instance: { classPropertyName: "instance", publicName: "instance", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { runtimeContextChange: "runtimeContextChange", operationalEvent: "operationalEvent" }, viewQueries: [{ propertyName: "adapterHost", first: true, predicate: ["adapterHost"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: `
544
+ <section
545
+ class="data-block"
546
+ [class.block-card]="effectiveSurface() === 'card'"
547
+ [class.block-plain]="effectiveSurface() === 'plain'"
548
+ [attr.data-surface]="effectiveSurface()"
549
+ >
550
+ @if (showBlockHeader()) {
551
+ <header class="block-header">
552
+ @if (showBlockTitle()) {
553
+ <h3 class="block-title">{{ block().title }}</h3>
554
+ }
555
+
556
+ @if (showBlockDescription()) {
557
+ <p class="description">{{ block().description }}</p>
558
+ }
559
+ </header>
416
560
  }
417
561
 
418
- @if (block().description) {
419
- <p class="description">{{ block().description }}</p>
562
+ <div class="block-body">
563
+ @if (adapterComponent(); as adapterComponent) {
564
+ <ng-template #adapterHost></ng-template>
565
+ } @else if (loadingState(); as loadingState) {
566
+ <div class="feedback status" role="status" aria-live="polite" aria-atomic="true">
567
+ <strong>{{ t('dataCollection.loadingTitle', 'Preparando coleta') }}</strong>
568
+ <p>{{ loadingState.message }}</p>
569
+ </div>
570
+ } @else if (errorState(); as errorState) {
571
+ <div class="feedback error" role="alert" aria-live="assertive" aria-atomic="true">
572
+ <strong>{{ errorState.title }}</strong>
573
+ <p>{{ errorState.message }}</p>
574
+ @if (errorState.details) {
575
+ <p class="details">{{ errorState.details }}</p>
576
+ }
577
+ </div>
578
+ } @else {
579
+ <div class="feedback status" role="status" aria-live="polite" aria-atomic="true">
580
+ <strong>{{ t('dataCollection.unavailableTitle', 'Coleta nao disponivel') }}</strong>
581
+ <p>{{ fallbackMessage() }}</p>
582
+ </div>
583
+ }
584
+ </div>
585
+ </section>
586
+ `, isInline: true, styles: [":host{display:block;color:var(--editorial-text-primary, var(--md-sys-color-on-surface, #1b1b1f))}.data-block{display:grid;gap:16px;font-family:var(--editorial-body-font-family, inherit)}.block-card{display:grid;gap:16px;padding:clamp(18px,2vw,24px);border-radius:var(--editorial-card-radius, 18px);background:var(--editorial-surface-secondary, var(--md-sys-color-surface-container-low, #f7f2fa));border:var(--editorial-card-border-width, 1px) solid color-mix(in srgb,var(--editorial-border-color, var(--md-sys-color-outline-variant, #cac4d0)) 65%,transparent);box-shadow:var(--editorial-card-shadow, none)}.block-plain{padding:0;border:0;background:transparent;box-shadow:none;gap:0}.block-header{display:grid;gap:8px}.block-plain .block-header{margin-bottom:16px;padding-bottom:4px}.block-body{min-width:0}h3,p{margin:0}.block-title{font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-size:var(--editorial-step-title-size, 1.15rem);line-height:1.15;color:var(--editorial-text-primary, var(--md-sys-color-on-surface, #1b1b1f))}.description,.feedback{color:var(--editorial-text-secondary, var(--md-sys-color-on-surface-variant, #49454f));font-size:var(--editorial-body-size, .95rem);line-height:1.55}.feedback{display:grid;gap:6px;padding:12px 14px;border-radius:var(--editorial-card-radius, 14px);border:var(--editorial-card-border-width, 1px) solid color-mix(in srgb,var(--editorial-border-color, var(--md-sys-color-outline-variant, #cac4d0)) 70%,transparent);background:color-mix(in srgb,var(--editorial-surface-primary, var(--md-sys-color-surface, #fff)) 94%,var(--editorial-surface-secondary, var(--md-sys-color-surface-container-low, #f7f2fa)) 6%)}.feedback strong{color:var(--editorial-text-primary, var(--md-sys-color-on-surface, #1b1b1f));font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit))}.error{border-color:color-mix(in srgb,var(--md-sys-color-error, #b3261e) 50%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container, #f9dedc) 35%,var(--md-sys-color-surface, #fff))}.details{font-size:.9rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
587
+ }
588
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialDataCollectionBlockOutletComponent, decorators: [{
589
+ type: Component,
590
+ args: [{ selector: 'praxis-editorial-data-collection-block-outlet', standalone: true, imports: [CommonModule], template: `
591
+ <section
592
+ class="data-block"
593
+ [class.block-card]="effectiveSurface() === 'card'"
594
+ [class.block-plain]="effectiveSurface() === 'plain'"
595
+ [attr.data-surface]="effectiveSurface()"
596
+ >
597
+ @if (showBlockHeader()) {
598
+ <header class="block-header">
599
+ @if (showBlockTitle()) {
600
+ <h3 class="block-title">{{ block().title }}</h3>
601
+ }
602
+
603
+ @if (showBlockDescription()) {
604
+ <p class="description">{{ block().description }}</p>
605
+ }
606
+ </header>
420
607
  }
421
608
 
422
- @if (adapterComponent(); as adapterComponent) {
423
- <ng-container
424
- *ngComponentOutlet="adapterComponent; inputs: adapterInputs()"
425
- />
426
- } @else if (loadingState(); as loadingState) {
427
- <div class="feedback status" role="status" aria-live="polite" aria-atomic="true">
428
- <strong>Preparando coleta</strong>
429
- <p>{{ loadingState.message }}</p>
609
+ <div class="block-body">
610
+ @if (adapterComponent(); as adapterComponent) {
611
+ <ng-template #adapterHost></ng-template>
612
+ } @else if (loadingState(); as loadingState) {
613
+ <div class="feedback status" role="status" aria-live="polite" aria-atomic="true">
614
+ <strong>{{ t('dataCollection.loadingTitle', 'Preparando coleta') }}</strong>
615
+ <p>{{ loadingState.message }}</p>
616
+ </div>
617
+ } @else if (errorState(); as errorState) {
618
+ <div class="feedback error" role="alert" aria-live="assertive" aria-atomic="true">
619
+ <strong>{{ errorState.title }}</strong>
620
+ <p>{{ errorState.message }}</p>
621
+ @if (errorState.details) {
622
+ <p class="details">{{ errorState.details }}</p>
623
+ }
624
+ </div>
625
+ } @else {
626
+ <div class="feedback status" role="status" aria-live="polite" aria-atomic="true">
627
+ <strong>{{ t('dataCollection.unavailableTitle', 'Coleta nao disponivel') }}</strong>
628
+ <p>{{ fallbackMessage() }}</p>
629
+ </div>
630
+ }
631
+ </div>
632
+ </section>
633
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;color:var(--editorial-text-primary, var(--md-sys-color-on-surface, #1b1b1f))}.data-block{display:grid;gap:16px;font-family:var(--editorial-body-font-family, inherit)}.block-card{display:grid;gap:16px;padding:clamp(18px,2vw,24px);border-radius:var(--editorial-card-radius, 18px);background:var(--editorial-surface-secondary, var(--md-sys-color-surface-container-low, #f7f2fa));border:var(--editorial-card-border-width, 1px) solid color-mix(in srgb,var(--editorial-border-color, var(--md-sys-color-outline-variant, #cac4d0)) 65%,transparent);box-shadow:var(--editorial-card-shadow, none)}.block-plain{padding:0;border:0;background:transparent;box-shadow:none;gap:0}.block-header{display:grid;gap:8px}.block-plain .block-header{margin-bottom:16px;padding-bottom:4px}.block-body{min-width:0}h3,p{margin:0}.block-title{font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-size:var(--editorial-step-title-size, 1.15rem);line-height:1.15;color:var(--editorial-text-primary, var(--md-sys-color-on-surface, #1b1b1f))}.description,.feedback{color:var(--editorial-text-secondary, var(--md-sys-color-on-surface-variant, #49454f));font-size:var(--editorial-body-size, .95rem);line-height:1.55}.feedback{display:grid;gap:6px;padding:12px 14px;border-radius:var(--editorial-card-radius, 14px);border:var(--editorial-card-border-width, 1px) solid color-mix(in srgb,var(--editorial-border-color, var(--md-sys-color-outline-variant, #cac4d0)) 70%,transparent);background:color-mix(in srgb,var(--editorial-surface-primary, var(--md-sys-color-surface, #fff)) 94%,var(--editorial-surface-secondary, var(--md-sys-color-surface-container-low, #f7f2fa)) 6%)}.feedback strong{color:var(--editorial-text-primary, var(--md-sys-color-on-surface, #1b1b1f));font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit))}.error{border-color:color-mix(in srgb,var(--md-sys-color-error, #b3261e) 50%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container, #f9dedc) 35%,var(--md-sys-color-surface, #fff))}.details{font-size:.9rem}\n"] }]
634
+ }], ctorParameters: () => [], propDecorators: { adapterHost: [{ type: i0.ViewChild, args: ['adapterHost', { ...{ read: ViewContainerRef }, isSignal: true }] }], block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: true }] }], runtimeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "runtimeContext", required: false }] }], solution: [{ type: i0.Input, args: [{ isSignal: true, alias: "solution", required: false }] }], instance: [{ type: i0.Input, args: [{ isSignal: true, alias: "instance", required: false }] }], runtimeContextChange: [{ type: i0.Output, args: ["runtimeContextChange"] }], operationalEvent: [{ type: i0.Output, args: ["operationalEvent"] }] } });
635
+ function isSubscribableOutput(candidate) {
636
+ return !!candidate && typeof candidate === 'object' && typeof candidate.subscribe === 'function';
637
+ }
638
+ function extractFormDataChangeEvent(event) {
639
+ if (!event || typeof event !== 'object') {
640
+ return null;
641
+ }
642
+ const formData = event.formData;
643
+ if (!formData || typeof formData !== 'object' || Array.isArray(formData)) {
644
+ return null;
645
+ }
646
+ const mode = event.mode;
647
+ const removedKeys = event.removedKeys;
648
+ return {
649
+ formData: { ...formData },
650
+ mode: mode === 'replace' ? 'replace' : 'merge',
651
+ removedKeys: Array.isArray(removedKeys)
652
+ ? removedKeys.filter((item) => typeof item === 'string')
653
+ : undefined,
654
+ };
655
+ }
656
+ function readRuntimeFormData(runtimeContext) {
657
+ const formData = runtimeContext?.['formData'];
658
+ if (!formData || typeof formData !== 'object' || Array.isArray(formData)) {
659
+ return {};
660
+ }
661
+ return formData;
662
+ }
663
+ function isResolvedDataCollectionBlock(block) {
664
+ return 'dataCollectionState' in block;
665
+ }
666
+ function areEquivalentCopy(left, right) {
667
+ if (!left || !right) {
668
+ return false;
669
+ }
670
+ return normalizeComparableCopy(left) === normalizeComparableCopy(right);
671
+ }
672
+ function normalizeComparableCopy(value) {
673
+ return value.trim().replace(/\s+/g, ' ').toLocaleLowerCase();
674
+ }
675
+
676
+ class EditorialIntroHeroBlockComponent {
677
+ block = input.required(...(ngDevMode ? [{ debugName: "block" }] : []));
678
+ actionTriggered = output();
679
+ triggerAction(action) {
680
+ this.actionTriggered.emit(action.actionId);
681
+ }
682
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialIntroHeroBlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
683
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialIntroHeroBlockComponent, isStandalone: true, selector: "praxis-editorial-intro-hero-block", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { actionTriggered: "actionTriggered" }, ngImport: i0, template: `
684
+ <section class="intro-hero" [attr.data-align]="block().align ?? 'center'">
685
+ @if (block().icon?.name) {
686
+ <div class="hero-icon"><mat-icon aria-hidden="true" [praxisIcon]="block().icon?.name"></mat-icon></div>
687
+ }
688
+ <div class="hero-copy">
689
+ <h3>{{ block().title }}</h3>
690
+ @if (block().subtitle) {
691
+ <p class="subtitle">{{ block().subtitle }}</p>
692
+ }
693
+ @if (block().description) {
694
+ <p class="description">{{ block().description }}</p>
695
+ }
696
+ </div>
697
+
698
+ @if (block().highlightItems?.length) {
699
+ <div class="hero-highlights">
700
+ @for (item of block().highlightItems; track item.id) {
701
+ <article class="highlight-card">
702
+ @if (item.icon?.name) {
703
+ <mat-icon class="highlight-icon" aria-hidden="true" [praxisIcon]="item.icon?.name"></mat-icon>
704
+ }
705
+ <strong>{{ item.title }}</strong>
706
+ @if (item.description) {
707
+ <p>{{ item.description }}</p>
708
+ }
709
+ </article>
710
+ }
430
711
  </div>
431
- } @else if (errorState(); as errorState) {
432
- <div class="feedback error" role="alert" aria-live="assertive" aria-atomic="true">
433
- <strong>{{ errorState.title }}</strong>
434
- <p>{{ errorState.message }}</p>
435
- @if (errorState.details) {
436
- <p class="details">{{ errorState.details }}</p>
712
+ }
713
+
714
+ @if (block().primaryAction || block().secondaryAction) {
715
+ <div class="hero-actions">
716
+ @if (block().primaryAction; as action) {
717
+ <button
718
+ type="button"
719
+ class="hero-action primary"
720
+ [attr.data-appearance]="action.appearance ?? 'primary'"
721
+ (click)="triggerAction(action)"
722
+ >
723
+ @if (action.icon?.name) {
724
+ <mat-icon aria-hidden="true" [praxisIcon]="action.icon?.name"></mat-icon>
725
+ }
726
+ <span>{{ action.label }}</span>
727
+ </button>
728
+ }
729
+ @if (block().secondaryAction; as action) {
730
+ <button
731
+ type="button"
732
+ class="hero-action secondary"
733
+ [attr.data-appearance]="action.appearance ?? 'secondary'"
734
+ (click)="triggerAction(action)"
735
+ >
736
+ @if (action.icon?.name) {
737
+ <mat-icon aria-hidden="true" [praxisIcon]="action.icon?.name"></mat-icon>
738
+ }
739
+ <span>{{ action.label }}</span>
740
+ </button>
437
741
  }
438
742
  </div>
439
- } @else {
440
- <div class="feedback status" role="status" aria-live="polite" aria-atomic="true">
441
- <strong>Coleta nao disponivel</strong>
442
- <p>{{ fallbackMessage() }}</p>
743
+ }
744
+ </section>
745
+ `, isInline: true, styles: [".intro-hero{display:grid;gap:18px;text-align:center}.intro-hero[data-align=left]{text-align:left}.hero-icon{width:64px;height:64px;border-radius:18px;background:color-mix(in srgb,var(--editorial-accent, #264a8a) 18%,#fff);color:var(--editorial-accent, #264a8a);display:grid;place-items:center;justify-self:center;font-weight:700}.hero-icon mat-icon,.highlight-icon{width:22px;height:22px;font-size:22px;line-height:22px}.intro-hero[data-align=left] .hero-icon{justify-self:start}.hero-copy{display:grid;gap:10px}.hero-copy h3,.hero-copy p{margin:0}.hero-copy h3{font-size:var(--editorial-hero-title-size, 1.75rem);line-height:1.15}.subtitle,.description{font-size:var(--editorial-body-size, 1rem);color:var(--editorial-text-secondary, #7b8aa0)}.hero-highlights{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}.hero-actions{display:flex;flex-wrap:wrap;justify-content:center;gap:12px}.intro-hero[data-align=left] .hero-actions{justify-content:flex-start}.hero-action{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:44px;padding:0 20px;border-radius:var(--editorial-button-radius, var(--editorial-card-radius, 18px));border:1px solid transparent;cursor:pointer;font:inherit;font-weight:600;transition:background-color .12s ease,color .12s ease,border-color .12s ease,box-shadow .12s ease}.hero-action mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.hero-action.primary{background:var(--editorial-cta-primary, var(--editorial-accent, #264a8a));color:var(--editorial-cta-primary-text, #fff);box-shadow:var(--editorial-card-shadow, none)}.hero-action.secondary{background:color-mix(in srgb,var(--editorial-accent, #264a8a) 8%,#fff);border-color:color-mix(in srgb,var(--editorial-accent, #264a8a) 20%,transparent);color:var(--editorial-accent, #264a8a)}.highlight-card{display:grid;gap:6px;padding:14px;border-radius:var(--editorial-card-radius, 18px);background:var(--editorial-surface-primary, #fff);border:1px solid var(--editorial-border-color, #d9deea);box-shadow:var(--editorial-card-shadow, none)}.highlight-card p{margin:0;color:var(--editorial-text-secondary, #7b8aa0)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
746
+ }
747
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialIntroHeroBlockComponent, decorators: [{
748
+ type: Component,
749
+ args: [{ selector: 'praxis-editorial-intro-hero-block', standalone: true, imports: [CommonModule, MatIconModule, PraxisIconDirective], template: `
750
+ <section class="intro-hero" [attr.data-align]="block().align ?? 'center'">
751
+ @if (block().icon?.name) {
752
+ <div class="hero-icon"><mat-icon aria-hidden="true" [praxisIcon]="block().icon?.name"></mat-icon></div>
753
+ }
754
+ <div class="hero-copy">
755
+ <h3>{{ block().title }}</h3>
756
+ @if (block().subtitle) {
757
+ <p class="subtitle">{{ block().subtitle }}</p>
758
+ }
759
+ @if (block().description) {
760
+ <p class="description">{{ block().description }}</p>
761
+ }
762
+ </div>
763
+
764
+ @if (block().highlightItems?.length) {
765
+ <div class="hero-highlights">
766
+ @for (item of block().highlightItems; track item.id) {
767
+ <article class="highlight-card">
768
+ @if (item.icon?.name) {
769
+ <mat-icon class="highlight-icon" aria-hidden="true" [praxisIcon]="item.icon?.name"></mat-icon>
770
+ }
771
+ <strong>{{ item.title }}</strong>
772
+ @if (item.description) {
773
+ <p>{{ item.description }}</p>
774
+ }
775
+ </article>
776
+ }
443
777
  </div>
444
778
  }
779
+
780
+ @if (block().primaryAction || block().secondaryAction) {
781
+ <div class="hero-actions">
782
+ @if (block().primaryAction; as action) {
783
+ <button
784
+ type="button"
785
+ class="hero-action primary"
786
+ [attr.data-appearance]="action.appearance ?? 'primary'"
787
+ (click)="triggerAction(action)"
788
+ >
789
+ @if (action.icon?.name) {
790
+ <mat-icon aria-hidden="true" [praxisIcon]="action.icon?.name"></mat-icon>
791
+ }
792
+ <span>{{ action.label }}</span>
793
+ </button>
794
+ }
795
+ @if (block().secondaryAction; as action) {
796
+ <button
797
+ type="button"
798
+ class="hero-action secondary"
799
+ [attr.data-appearance]="action.appearance ?? 'secondary'"
800
+ (click)="triggerAction(action)"
801
+ >
802
+ @if (action.icon?.name) {
803
+ <mat-icon aria-hidden="true" [praxisIcon]="action.icon?.name"></mat-icon>
804
+ }
805
+ <span>{{ action.label }}</span>
806
+ </button>
807
+ }
808
+ </div>
809
+ }
810
+ </section>
811
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".intro-hero{display:grid;gap:18px;text-align:center}.intro-hero[data-align=left]{text-align:left}.hero-icon{width:64px;height:64px;border-radius:18px;background:color-mix(in srgb,var(--editorial-accent, #264a8a) 18%,#fff);color:var(--editorial-accent, #264a8a);display:grid;place-items:center;justify-self:center;font-weight:700}.hero-icon mat-icon,.highlight-icon{width:22px;height:22px;font-size:22px;line-height:22px}.intro-hero[data-align=left] .hero-icon{justify-self:start}.hero-copy{display:grid;gap:10px}.hero-copy h3,.hero-copy p{margin:0}.hero-copy h3{font-size:var(--editorial-hero-title-size, 1.75rem);line-height:1.15}.subtitle,.description{font-size:var(--editorial-body-size, 1rem);color:var(--editorial-text-secondary, #7b8aa0)}.hero-highlights{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px}.hero-actions{display:flex;flex-wrap:wrap;justify-content:center;gap:12px}.intro-hero[data-align=left] .hero-actions{justify-content:flex-start}.hero-action{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:44px;padding:0 20px;border-radius:var(--editorial-button-radius, var(--editorial-card-radius, 18px));border:1px solid transparent;cursor:pointer;font:inherit;font-weight:600;transition:background-color .12s ease,color .12s ease,border-color .12s ease,box-shadow .12s ease}.hero-action mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.hero-action.primary{background:var(--editorial-cta-primary, var(--editorial-accent, #264a8a));color:var(--editorial-cta-primary-text, #fff);box-shadow:var(--editorial-card-shadow, none)}.hero-action.secondary{background:color-mix(in srgb,var(--editorial-accent, #264a8a) 8%,#fff);border-color:color-mix(in srgb,var(--editorial-accent, #264a8a) 20%,transparent);color:var(--editorial-accent, #264a8a)}.highlight-card{display:grid;gap:6px;padding:14px;border-radius:var(--editorial-card-radius, 18px);background:var(--editorial-surface-primary, #fff);border:1px solid var(--editorial-border-color, #d9deea);box-shadow:var(--editorial-card-shadow, none)}.highlight-card p{margin:0;color:var(--editorial-text-secondary, #7b8aa0)}\n"] }]
812
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: true }] }], actionTriggered: [{ type: i0.Output, args: ["actionTriggered"] }] } });
813
+
814
+ class EditorialReviewSectionsBlockComponent {
815
+ i18n = inject(PraxisI18nService);
816
+ block = input.required(...(ngDevMode ? [{ debugName: "block" }] : []));
817
+ runtimeContext = input(null, ...(ngDevMode ? [{ debugName: "runtimeContext" }] : []));
818
+ visibleFields(fields) {
819
+ return fields.filter((field) => {
820
+ if (!field.hideWhenEmpty) {
821
+ return true;
822
+ }
823
+ return this.readValue(field) != null && this.readValue(field) !== '';
824
+ });
825
+ }
826
+ resolveValue(field) {
827
+ const value = this.readValue(field);
828
+ if (value == null || value === '') {
829
+ return this.t('review.empty', '-');
830
+ }
831
+ return this.formatValue(value, field.format);
832
+ }
833
+ readValue(field) {
834
+ return getValueAtPath(this.runtimeContext() ?? {}, field.valuePath);
835
+ }
836
+ formatValue(value, format) {
837
+ switch (format) {
838
+ case 'date':
839
+ return this.formatDateValue(value);
840
+ case 'phone':
841
+ return this.formatPhoneValue(value);
842
+ case 'email':
843
+ return String(value);
844
+ case 'boolean':
845
+ return this.formatBooleanValue(value);
846
+ case 'list':
847
+ return this.formatListValue(value);
848
+ case 'text':
849
+ default:
850
+ if (Array.isArray(value)) {
851
+ return this.formatListValue(value);
852
+ }
853
+ if (typeof value === 'boolean') {
854
+ return this.formatBooleanValue(value);
855
+ }
856
+ return String(value);
857
+ }
858
+ }
859
+ formatDateValue(value) {
860
+ if (value == null || value === '') {
861
+ return this.t('review.empty', '-');
862
+ }
863
+ return this.i18n.formatDate(value);
864
+ }
865
+ formatPhoneValue(value) {
866
+ const raw = String(value ?? '').trim();
867
+ if (!raw) {
868
+ return this.t('review.empty', '-');
869
+ }
870
+ const digits = raw.replace(/\D+/g, '');
871
+ if (digits.length === 11) {
872
+ return `(${digits.slice(0, 2)}) ${digits.slice(2, 7)}-${digits.slice(7)}`;
873
+ }
874
+ if (digits.length === 10) {
875
+ return `(${digits.slice(0, 2)}) ${digits.slice(2, 6)}-${digits.slice(6)}`;
876
+ }
877
+ if (digits.length > 11) {
878
+ return `+${digits}`;
879
+ }
880
+ return raw;
881
+ }
882
+ formatBooleanValue(value) {
883
+ return value
884
+ ? this.t('review.boolean.true', 'Sim')
885
+ : this.t('review.boolean.false', 'Nao');
886
+ }
887
+ formatListValue(value) {
888
+ if (!Array.isArray(value)) {
889
+ return String(value);
890
+ }
891
+ return value.map((item) => String(item)).join(', ');
892
+ }
893
+ t(key, fallback) {
894
+ return this.i18n.t(`praxis.editorialForms.${key}`, undefined, fallback);
895
+ }
896
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialReviewSectionsBlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
897
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialReviewSectionsBlockComponent, isStandalone: true, selector: "praxis-editorial-review-sections-block", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: true, transformFunction: null }, runtimeContext: { classPropertyName: "runtimeContext", publicName: "runtimeContext", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
898
+ <section class="review-sections">
899
+ @if (block().title) {
900
+ <header class="review-header">
901
+ <h3>{{ block().title }}</h3>
902
+ @if (block().description) {
903
+ <p>{{ block().description }}</p>
904
+ }
905
+ </header>
906
+ }
907
+
908
+ <div class="review-sections-grid">
909
+ @for (section of block().sections; track section.id) {
910
+ <article class="review-section">
911
+ <header class="review-section-header">
912
+ @if (section.icon?.name) {
913
+ <mat-icon class="section-icon" aria-hidden="true" [praxisIcon]="section.icon?.name"></mat-icon>
914
+ }
915
+ <h4>{{ section.title }}</h4>
916
+ </header>
917
+ <dl class="review-grid">
918
+ @for (field of visibleFields(section.fields); track field.key) {
919
+ <div>
920
+ <dt>{{ field.label }}</dt>
921
+ <dd>{{ resolveValue(field) }}</dd>
922
+ </div>
923
+ }
924
+ </dl>
925
+ </article>
926
+ }
927
+ </div>
445
928
  </section>
446
- `, isInline: true, styles: [":host{display:block}.block-card{display:grid;gap:12px;padding:18px;border-radius:18px;background:var(--md-sys-color-surface-container-low, #f7f2fa);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent)}h3,p{margin:0}.description,.feedback{color:var(--md-sys-color-on-surface-variant, #49454f)}.feedback{display:grid;gap:6px;padding:12px 14px;border-radius:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent);background:var(--md-sys-color-surface, #fff)}.feedback strong{color:var(--md-sys-color-on-surface, #1b1b1f)}.error{border-color:color-mix(in srgb,var(--md-sys-color-error, #b3261e) 50%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container, #f9dedc) 35%,var(--md-sys-color-surface, #fff))}.details{font-size:.9rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
929
+ `, isInline: true, styles: [".review-sections,.review-header{display:grid;gap:10px}.review-header h3,.review-header p,.review-section h4{margin:0}.review-header p{color:var(--editorial-text-secondary, #7b8aa0)}.review-sections-grid{display:grid;gap:14px}.review-section{display:grid;gap:12px;padding:18px;border-radius:var(--editorial-card-radius, 18px);border:1px solid var(--editorial-border-color, #d9deea);background:var(--editorial-surface-primary, #fff);box-shadow:var(--editorial-card-shadow, none)}.review-section-header{display:inline-flex;align-items:center;gap:10px}.section-icon{display:grid;place-items:center;width:18px;height:18px;color:var(--editorial-accent, #264a8a);font-size:18px;line-height:18px}.review-grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:0}.review-grid dt{margin-bottom:4px;color:var(--editorial-text-secondary, #7b8aa0);font-size:.82rem}.review-grid dd{margin:0;font-weight:600;color:var(--editorial-text-primary, #24324a)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
447
930
  }
448
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialDataCollectionBlockOutletComponent, decorators: [{
931
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialReviewSectionsBlockComponent, decorators: [{
449
932
  type: Component,
450
- args: [{ selector: 'praxis-editorial-data-collection-block-outlet', standalone: true, imports: [CommonModule, NgComponentOutlet], template: `
451
- <section class="block-card data-block">
933
+ args: [{ selector: 'praxis-editorial-review-sections-block', standalone: true, imports: [CommonModule, MatIconModule, PraxisIconDirective], template: `
934
+ <section class="review-sections">
452
935
  @if (block().title) {
453
- <h3>{{ block().title }}</h3>
936
+ <header class="review-header">
937
+ <h3>{{ block().title }}</h3>
938
+ @if (block().description) {
939
+ <p>{{ block().description }}</p>
940
+ }
941
+ </header>
454
942
  }
455
943
 
456
- @if (block().description) {
457
- <p class="description">{{ block().description }}</p>
944
+ <div class="review-sections-grid">
945
+ @for (section of block().sections; track section.id) {
946
+ <article class="review-section">
947
+ <header class="review-section-header">
948
+ @if (section.icon?.name) {
949
+ <mat-icon class="section-icon" aria-hidden="true" [praxisIcon]="section.icon?.name"></mat-icon>
950
+ }
951
+ <h4>{{ section.title }}</h4>
952
+ </header>
953
+ <dl class="review-grid">
954
+ @for (field of visibleFields(section.fields); track field.key) {
955
+ <div>
956
+ <dt>{{ field.label }}</dt>
957
+ <dd>{{ resolveValue(field) }}</dd>
958
+ </div>
959
+ }
960
+ </dl>
961
+ </article>
962
+ }
963
+ </div>
964
+ </section>
965
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".review-sections,.review-header{display:grid;gap:10px}.review-header h3,.review-header p,.review-section h4{margin:0}.review-header p{color:var(--editorial-text-secondary, #7b8aa0)}.review-sections-grid{display:grid;gap:14px}.review-section{display:grid;gap:12px;padding:18px;border-radius:var(--editorial-card-radius, 18px);border:1px solid var(--editorial-border-color, #d9deea);background:var(--editorial-surface-primary, #fff);box-shadow:var(--editorial-card-shadow, none)}.review-section-header{display:inline-flex;align-items:center;gap:10px}.section-icon{display:grid;place-items:center;width:18px;height:18px;color:var(--editorial-accent, #264a8a);font-size:18px;line-height:18px}.review-grid{display:grid;gap:10px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));margin:0}.review-grid dt{margin-bottom:4px;color:var(--editorial-text-secondary, #7b8aa0);font-size:.82rem}.review-grid dd{margin:0;font-weight:600;color:var(--editorial-text-primary, #24324a)}\n"] }]
966
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: true }] }], runtimeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "runtimeContext", required: false }] }] } });
967
+
968
+ class EditorialSelectionCardsBlockComponent {
969
+ i18n = inject(PraxisI18nService);
970
+ block = input.required(...(ngDevMode ? [{ debugName: "block" }] : []));
971
+ runtimeContext = input(null, ...(ngDevMode ? [{ debugName: "runtimeContext" }] : []));
972
+ runtimeContextChange = output();
973
+ valueChange = output();
974
+ groupId = computed(() => `selection-group-${this.block().blockId}`, ...(ngDevMode ? [{ debugName: "groupId" }] : []));
975
+ gridTemplateColumns = computed(() => {
976
+ const columns = this.block().columns ?? 2;
977
+ return `repeat(${columns}, minmax(0, 1fr))`;
978
+ }, ...(ngDevMode ? [{ debugName: "gridTemplateColumns" }] : []));
979
+ groupAriaLabel = computed(() => this.block().title
980
+ || this.t('selection.group.label', 'Grupo de selecao'), ...(ngDevMode ? [{ debugName: "groupAriaLabel" }] : []));
981
+ isSelected(value) {
982
+ const currentValue = this.currentValue();
983
+ if (Array.isArray(currentValue)) {
984
+ return currentValue.includes(value);
985
+ }
986
+ return currentValue === value;
987
+ }
988
+ toggleValue(value) {
989
+ const field = this.block().field;
990
+ if (this.block().selectionMode === 'single') {
991
+ const currentValue = this.currentValue();
992
+ const nextValue = currentValue === value ? null : value;
993
+ this.runtimeContextChange.emit(this.buildNextRuntimeContext(field, nextValue));
994
+ this.valueChange.emit({ field, value: nextValue });
995
+ return;
996
+ }
997
+ const currentValue = this.currentValue();
998
+ const current = Array.isArray(currentValue) ? [...currentValue] : [];
999
+ const index = current.indexOf(value);
1000
+ if (index >= 0) {
1001
+ current.splice(index, 1);
1002
+ }
1003
+ else {
1004
+ current.push(value);
1005
+ }
1006
+ this.runtimeContextChange.emit(this.buildNextRuntimeContext(field, current));
1007
+ this.valueChange.emit({ field, value: current });
1008
+ }
1009
+ itemTabIndex(value) {
1010
+ if (this.block().selectionMode !== 'single') {
1011
+ return 0;
1012
+ }
1013
+ const currentValue = this.currentValue();
1014
+ if (currentValue === value) {
1015
+ return 0;
1016
+ }
1017
+ const firstValue = this.enabledItemValues()[0];
1018
+ return firstValue === value && currentValue == null ? 0 : -1;
1019
+ }
1020
+ handleKeydown(event, value) {
1021
+ if (event.key === ' ' || event.key === 'Enter') {
1022
+ event.preventDefault();
1023
+ this.toggleValue(value);
1024
+ return;
1025
+ }
1026
+ if (!['ArrowRight', 'ArrowDown', 'ArrowLeft', 'ArrowUp'].includes(event.key)) {
1027
+ return;
1028
+ }
1029
+ const enabledValues = this.enabledItemValues();
1030
+ const currentIndex = enabledValues.indexOf(value);
1031
+ if (currentIndex < 0) {
1032
+ return;
1033
+ }
1034
+ event.preventDefault();
1035
+ const nextIndex = event.key === 'ArrowRight' || event.key === 'ArrowDown'
1036
+ ? (currentIndex + 1) % enabledValues.length
1037
+ : (currentIndex - 1 + enabledValues.length) % enabledValues.length;
1038
+ const nextValue = enabledValues[nextIndex];
1039
+ this.focusItem(nextValue);
1040
+ if (this.block().selectionMode === 'single') {
1041
+ this.toggleValue(nextValue);
1042
+ }
1043
+ }
1044
+ buildItemAriaLabel(label, value) {
1045
+ const selected = this.isSelected(value)
1046
+ ? this.t('selection.state.selected', 'selecionado')
1047
+ : this.t('selection.state.unselected', 'nao selecionado');
1048
+ return `${label}, ${selected}`;
1049
+ }
1050
+ currentValue() {
1051
+ const formData = this.readFormData();
1052
+ const value = formData[this.block().field];
1053
+ if (Array.isArray(value)) {
1054
+ return value.filter((item) => typeof item === 'string');
1055
+ }
1056
+ return typeof value === 'string' ? value : null;
1057
+ }
1058
+ buildNextRuntimeContext(field, value) {
1059
+ const context = this.runtimeContext();
1060
+ const nextContext = context ? { ...context } : {};
1061
+ const formData = this.cloneFormData();
1062
+ if (value == null) {
1063
+ delete formData[field];
1064
+ }
1065
+ else {
1066
+ formData[field] = value;
1067
+ }
1068
+ nextContext['formData'] = formData;
1069
+ return nextContext;
1070
+ }
1071
+ readFormData() {
1072
+ const context = this.runtimeContext();
1073
+ if (!context) {
1074
+ return {};
1075
+ }
1076
+ const existing = context['formData'];
1077
+ if (existing && typeof existing === 'object' && !Array.isArray(existing)) {
1078
+ return existing;
1079
+ }
1080
+ return {};
1081
+ }
1082
+ cloneFormData() {
1083
+ return { ...this.readFormData() };
1084
+ }
1085
+ enabledItemValues() {
1086
+ return this.block().items
1087
+ .filter((item) => !item.disabled)
1088
+ .map((item) => item.value);
1089
+ }
1090
+ focusItem(value) {
1091
+ const container = document.getElementById(this.groupId());
1092
+ const buttons = container?.querySelectorAll('.selection-card');
1093
+ const targetIndex = this.block().items.findIndex((candidate) => candidate.value === value);
1094
+ const element = targetIndex >= 0 ? buttons?.[targetIndex] : null;
1095
+ element?.focus();
1096
+ }
1097
+ t(key, fallback) {
1098
+ return this.i18n.t(`praxis.editorialForms.${key}`, undefined, fallback);
1099
+ }
1100
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialSelectionCardsBlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1101
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialSelectionCardsBlockComponent, isStandalone: true, selector: "praxis-editorial-selection-cards-block", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: true, transformFunction: null }, runtimeContext: { classPropertyName: "runtimeContext", publicName: "runtimeContext", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { runtimeContextChange: "runtimeContextChange", valueChange: "valueChange" }, ngImport: i0, template: `
1102
+ <section class="selection-block">
1103
+ @if (block().title) {
1104
+ <header class="selection-header">
1105
+ <h3>{{ block().title }}</h3>
1106
+ @if (block().description) {
1107
+ <p>{{ block().description }}</p>
1108
+ }
1109
+ </header>
458
1110
  }
459
1111
 
460
- @if (adapterComponent(); as adapterComponent) {
461
- <ng-container
462
- *ngComponentOutlet="adapterComponent; inputs: adapterInputs()"
463
- />
464
- } @else if (loadingState(); as loadingState) {
465
- <div class="feedback status" role="status" aria-live="polite" aria-atomic="true">
466
- <strong>Preparando coleta</strong>
467
- <p>{{ loadingState.message }}</p>
468
- </div>
469
- } @else if (errorState(); as errorState) {
470
- <div class="feedback error" role="alert" aria-live="assertive" aria-atomic="true">
471
- <strong>{{ errorState.title }}</strong>
472
- <p>{{ errorState.message }}</p>
473
- @if (errorState.details) {
474
- <p class="details">{{ errorState.details }}</p>
1112
+ <div
1113
+ class="selection-grid"
1114
+ [attr.data-icon-position]="block().style?.iconPosition ?? 'left'"
1115
+ [style.grid-template-columns]="gridTemplateColumns()"
1116
+ [attr.id]="groupId()"
1117
+ [attr.role]="block().selectionMode === 'single' ? 'radiogroup' : 'group'"
1118
+ [attr.aria-label]="groupAriaLabel()"
1119
+ >
1120
+ @for (item of block().items; track item.id) {
1121
+ <button
1122
+ type="button"
1123
+ class="selection-card"
1124
+ [class.selected]="isSelected(item.value)"
1125
+ [attr.data-variant]="block().style?.variant ?? 'default'"
1126
+ [attr.data-tone]="item.tone ?? 'default'"
1127
+ [disabled]="item.disabled"
1128
+ [attr.role]="block().selectionMode === 'single' ? 'radio' : 'checkbox'"
1129
+ [attr.aria-checked]="isSelected(item.value)"
1130
+ [attr.aria-disabled]="item.disabled ? 'true' : null"
1131
+ [attr.tabindex]="itemTabIndex(item.value)"
1132
+ [attr.aria-label]="buildItemAriaLabel(item.label, item.value)"
1133
+ (click)="toggleValue(item.value)"
1134
+ (keydown)="handleKeydown($event, item.value)"
1135
+ >
1136
+ <span class="selection-leading">
1137
+ @if (item.icon?.name) {
1138
+ <mat-icon class="selection-icon" aria-hidden="true" [praxisIcon]="item.icon?.name"></mat-icon>
1139
+ }
1140
+ <span class="selection-copy">
1141
+ <strong>{{ item.label }}</strong>
1142
+ @if (item.description) {
1143
+ <span>{{ item.description }}</span>
1144
+ }
1145
+ </span>
1146
+ </span>
1147
+ @if (block().style?.showCheckmark ?? true) {
1148
+ <span class="selection-check" aria-hidden="true">
1149
+ @if (isSelected(item.value)) {
1150
+ <mat-icon aria-hidden="true" praxisIcon="check"></mat-icon>
1151
+ }
1152
+ </span>
1153
+ }
1154
+ </button>
1155
+ }
1156
+ </div>
1157
+ </section>
1158
+ `, isInline: true, styles: [".selection-block,.selection-header{display:grid;gap:10px}.selection-header h3,.selection-header p{margin:0}.selection-header p{color:var(--editorial-text-secondary, #7b8aa0)}.selection-grid{display:grid;gap:14px}.selection-card{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;min-height:72px;padding:16px;border-radius:var(--editorial-card-radius, 18px);border:1px solid var(--editorial-border-color, #d9deea);background:var(--editorial-surface-primary, #fff);color:var(--editorial-text-primary, #24324a);box-shadow:var(--editorial-card-shadow, none);cursor:pointer;text-align:left;transition:background-color .12s ease,border-color .12s ease,box-shadow .12s ease,transform .12s ease}.selection-card:hover:not([disabled]){transform:translateY(-1px)}.selection-card.selected{border-color:var(--editorial-accent, #264a8a);box-shadow:0 0 0 2px color-mix(in srgb,var(--editorial-accent, #264a8a) 22%,transparent);background:color-mix(in srgb,var(--editorial-accent, #264a8a) 8%,#fff)}.selection-card[data-variant=accent]{background:color-mix(in srgb,var(--editorial-accent, #264a8a) 4%,#fff);border-color:color-mix(in srgb,var(--editorial-accent, #264a8a) 18%,transparent)}.selection-card[data-variant=outline]{box-shadow:none;background:transparent}.selection-card[data-tone=accent] .selection-icon{background:color-mix(in srgb,var(--editorial-accent, #264a8a) 18%,#fff);color:var(--editorial-accent, #264a8a)}.selection-card[data-tone=muted] .selection-icon{background:var(--editorial-surface-secondary, #eef2f8);color:var(--editorial-text-secondary, #7b8aa0)}.selection-card[disabled]{opacity:.5;cursor:not-allowed}.selection-leading{display:inline-flex;align-items:center;gap:12px;min-width:0;flex:1 1 auto}.selection-grid[data-icon-position=top] .selection-card{flex-direction:column;align-items:stretch}.selection-grid[data-icon-position=top] .selection-leading{display:grid;gap:10px}.selection-grid[data-icon-position=top] .selection-check{align-self:flex-end}.selection-icon,.selection-check{display:grid;place-items:center;width:28px;height:28px;border-radius:999px;background:color-mix(in srgb,var(--editorial-accent, #264a8a) 14%,#fff);color:var(--editorial-accent, #264a8a);font-size:.75rem;font-weight:700;flex:0 0 auto}.selection-icon,.selection-check mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.selection-copy{display:grid;gap:4px;min-width:0}.selection-copy span{color:var(--editorial-text-secondary, #7b8aa0);font-size:.9rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1159
+ }
1160
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialSelectionCardsBlockComponent, decorators: [{
1161
+ type: Component,
1162
+ args: [{ selector: 'praxis-editorial-selection-cards-block', standalone: true, imports: [CommonModule, MatIconModule, PraxisIconDirective], template: `
1163
+ <section class="selection-block">
1164
+ @if (block().title) {
1165
+ <header class="selection-header">
1166
+ <h3>{{ block().title }}</h3>
1167
+ @if (block().description) {
1168
+ <p>{{ block().description }}</p>
475
1169
  }
476
- </div>
477
- } @else {
478
- <div class="feedback status" role="status" aria-live="polite" aria-atomic="true">
479
- <strong>Coleta nao disponivel</strong>
480
- <p>{{ fallbackMessage() }}</p>
481
- </div>
1170
+ </header>
482
1171
  }
1172
+
1173
+ <div
1174
+ class="selection-grid"
1175
+ [attr.data-icon-position]="block().style?.iconPosition ?? 'left'"
1176
+ [style.grid-template-columns]="gridTemplateColumns()"
1177
+ [attr.id]="groupId()"
1178
+ [attr.role]="block().selectionMode === 'single' ? 'radiogroup' : 'group'"
1179
+ [attr.aria-label]="groupAriaLabel()"
1180
+ >
1181
+ @for (item of block().items; track item.id) {
1182
+ <button
1183
+ type="button"
1184
+ class="selection-card"
1185
+ [class.selected]="isSelected(item.value)"
1186
+ [attr.data-variant]="block().style?.variant ?? 'default'"
1187
+ [attr.data-tone]="item.tone ?? 'default'"
1188
+ [disabled]="item.disabled"
1189
+ [attr.role]="block().selectionMode === 'single' ? 'radio' : 'checkbox'"
1190
+ [attr.aria-checked]="isSelected(item.value)"
1191
+ [attr.aria-disabled]="item.disabled ? 'true' : null"
1192
+ [attr.tabindex]="itemTabIndex(item.value)"
1193
+ [attr.aria-label]="buildItemAriaLabel(item.label, item.value)"
1194
+ (click)="toggleValue(item.value)"
1195
+ (keydown)="handleKeydown($event, item.value)"
1196
+ >
1197
+ <span class="selection-leading">
1198
+ @if (item.icon?.name) {
1199
+ <mat-icon class="selection-icon" aria-hidden="true" [praxisIcon]="item.icon?.name"></mat-icon>
1200
+ }
1201
+ <span class="selection-copy">
1202
+ <strong>{{ item.label }}</strong>
1203
+ @if (item.description) {
1204
+ <span>{{ item.description }}</span>
1205
+ }
1206
+ </span>
1207
+ </span>
1208
+ @if (block().style?.showCheckmark ?? true) {
1209
+ <span class="selection-check" aria-hidden="true">
1210
+ @if (isSelected(item.value)) {
1211
+ <mat-icon aria-hidden="true" praxisIcon="check"></mat-icon>
1212
+ }
1213
+ </span>
1214
+ }
1215
+ </button>
1216
+ }
1217
+ </div>
483
1218
  </section>
484
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.block-card{display:grid;gap:12px;padding:18px;border-radius:18px;background:var(--md-sys-color-surface-container-low, #f7f2fa);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent)}h3,p{margin:0}.description,.feedback{color:var(--md-sys-color-on-surface-variant, #49454f)}.feedback{display:grid;gap:6px;padding:12px 14px;border-radius:14px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent);background:var(--md-sys-color-surface, #fff)}.feedback strong{color:var(--md-sys-color-on-surface, #1b1b1f)}.error{border-color:color-mix(in srgb,var(--md-sys-color-error, #b3261e) 50%,transparent);background:color-mix(in srgb,var(--md-sys-color-error-container, #f9dedc) 35%,var(--md-sys-color-surface, #fff))}.details{font-size:.9rem}\n"] }]
485
- }], ctorParameters: () => [], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: true }] }], runtimeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "runtimeContext", required: false }] }], solution: [{ type: i0.Input, args: [{ isSignal: true, alias: "solution", required: false }] }], instance: [{ type: i0.Input, args: [{ isSignal: true, alias: "instance", required: false }] }], operationalEvent: [{ type: i0.Output, args: ["operationalEvent"] }] } });
486
- function isResolvedDataCollectionBlock(block) {
487
- return 'dataCollectionState' in block;
1219
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".selection-block,.selection-header{display:grid;gap:10px}.selection-header h3,.selection-header p{margin:0}.selection-header p{color:var(--editorial-text-secondary, #7b8aa0)}.selection-grid{display:grid;gap:14px}.selection-card{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;min-height:72px;padding:16px;border-radius:var(--editorial-card-radius, 18px);border:1px solid var(--editorial-border-color, #d9deea);background:var(--editorial-surface-primary, #fff);color:var(--editorial-text-primary, #24324a);box-shadow:var(--editorial-card-shadow, none);cursor:pointer;text-align:left;transition:background-color .12s ease,border-color .12s ease,box-shadow .12s ease,transform .12s ease}.selection-card:hover:not([disabled]){transform:translateY(-1px)}.selection-card.selected{border-color:var(--editorial-accent, #264a8a);box-shadow:0 0 0 2px color-mix(in srgb,var(--editorial-accent, #264a8a) 22%,transparent);background:color-mix(in srgb,var(--editorial-accent, #264a8a) 8%,#fff)}.selection-card[data-variant=accent]{background:color-mix(in srgb,var(--editorial-accent, #264a8a) 4%,#fff);border-color:color-mix(in srgb,var(--editorial-accent, #264a8a) 18%,transparent)}.selection-card[data-variant=outline]{box-shadow:none;background:transparent}.selection-card[data-tone=accent] .selection-icon{background:color-mix(in srgb,var(--editorial-accent, #264a8a) 18%,#fff);color:var(--editorial-accent, #264a8a)}.selection-card[data-tone=muted] .selection-icon{background:var(--editorial-surface-secondary, #eef2f8);color:var(--editorial-text-secondary, #7b8aa0)}.selection-card[disabled]{opacity:.5;cursor:not-allowed}.selection-leading{display:inline-flex;align-items:center;gap:12px;min-width:0;flex:1 1 auto}.selection-grid[data-icon-position=top] .selection-card{flex-direction:column;align-items:stretch}.selection-grid[data-icon-position=top] .selection-leading{display:grid;gap:10px}.selection-grid[data-icon-position=top] .selection-check{align-self:flex-end}.selection-icon,.selection-check{display:grid;place-items:center;width:28px;height:28px;border-radius:999px;background:color-mix(in srgb,var(--editorial-accent, #264a8a) 14%,#fff);color:var(--editorial-accent, #264a8a);font-size:.75rem;font-weight:700;flex:0 0 auto}.selection-icon,.selection-check mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.selection-copy{display:grid;gap:4px;min-width:0}.selection-copy span{color:var(--editorial-text-secondary, #7b8aa0);font-size:.9rem}\n"] }]
1220
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: true }] }], runtimeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "runtimeContext", required: false }] }], runtimeContextChange: [{ type: i0.Output, args: ["runtimeContextChange"] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
1221
+
1222
+ class EditorialSuccessPanelBlockComponent {
1223
+ block = input.required(...(ngDevMode ? [{ debugName: "block" }] : []));
1224
+ actionTriggered = output();
1225
+ triggerAction(action) {
1226
+ this.actionTriggered.emit(action.actionId);
1227
+ }
1228
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialSuccessPanelBlockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1229
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialSuccessPanelBlockComponent, isStandalone: true, selector: "praxis-editorial-success-panel-block", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { actionTriggered: "actionTriggered" }, ngImport: i0, template: `
1230
+ <section class="success-panel" [attr.data-tone]="block().tone ?? 'success'">
1231
+ @if (block().icon?.name) {
1232
+ <div class="success-icon"><mat-icon aria-hidden="true" [praxisIcon]="block().icon?.name"></mat-icon></div>
1233
+ }
1234
+ <h3>{{ block().title }}</h3>
1235
+ @if (block().description) {
1236
+ <p>{{ block().description }}</p>
1237
+ }
1238
+ @if (block().secondaryMessage) {
1239
+ <p class="secondary-message">{{ block().secondaryMessage }}</p>
1240
+ }
1241
+ @if (block().nextSteps?.length) {
1242
+ <ul>
1243
+ @for (item of block().nextSteps; track item) {
1244
+ <li>{{ item }}</li>
1245
+ }
1246
+ </ul>
1247
+ }
1248
+ @if (block().primaryAction; as action) {
1249
+ <button type="button" class="success-action" (click)="triggerAction(action)">
1250
+ @if (action.icon?.name) {
1251
+ <mat-icon aria-hidden="true" [praxisIcon]="action.icon?.name"></mat-icon>
1252
+ }
1253
+ <span>{{ action.label }}</span>
1254
+ </button>
1255
+ }
1256
+ </section>
1257
+ `, isInline: true, styles: [".success-panel{display:grid;gap:12px;text-align:center;padding:20px;border-radius:var(--editorial-card-radius, 18px);background:color-mix(in srgb,var(--editorial-success, #35b37e) 10%,#fff);border:1px solid color-mix(in srgb,var(--editorial-success, #35b37e) 32%,transparent);box-shadow:var(--editorial-card-shadow, none)}.success-panel[data-tone=accent]{background:color-mix(in srgb,var(--editorial-accent, #264a8a) 10%,#fff);border-color:color-mix(in srgb,var(--editorial-accent, #264a8a) 24%,transparent)}.success-panel[data-tone=neutral]{background:var(--editorial-surface-primary, #fff);border-color:var(--editorial-border-color, #d9deea)}.success-panel h3,.success-panel p,.success-panel ul{margin:0}.success-panel ul{padding-left:20px;text-align:left}.secondary-message{color:var(--editorial-text-secondary, #7b8aa0);font-size:var(--editorial-body-size, 1rem)}.success-icon{display:grid;place-items:center;width:48px;height:48px;border-radius:999px;background:var(--editorial-success, #35b37e);color:#fff;justify-self:center;font-weight:700}.success-panel[data-tone=accent] .success-icon{background:var(--editorial-accent, #264a8a)}.success-panel[data-tone=neutral] .success-icon{background:var(--editorial-surface-secondary, #eef2f8);color:var(--editorial-text-primary, #24324a)}.success-icon mat-icon{width:20px;height:20px;font-size:20px;line-height:20px}.success-action{justify-self:center;display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:44px;padding:0 20px;border:0;border-radius:var(--editorial-button-radius, var(--editorial-card-radius, 18px));background:var(--editorial-cta-primary, var(--editorial-success, #35b37e));color:var(--editorial-cta-primary-text, #fff);box-shadow:var(--editorial-card-shadow, none);cursor:pointer;font:inherit;font-weight:600}.success-action mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
488
1258
  }
1259
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialSuccessPanelBlockComponent, decorators: [{
1260
+ type: Component,
1261
+ args: [{ selector: 'praxis-editorial-success-panel-block', standalone: true, imports: [CommonModule, MatIconModule, PraxisIconDirective], template: `
1262
+ <section class="success-panel" [attr.data-tone]="block().tone ?? 'success'">
1263
+ @if (block().icon?.name) {
1264
+ <div class="success-icon"><mat-icon aria-hidden="true" [praxisIcon]="block().icon?.name"></mat-icon></div>
1265
+ }
1266
+ <h3>{{ block().title }}</h3>
1267
+ @if (block().description) {
1268
+ <p>{{ block().description }}</p>
1269
+ }
1270
+ @if (block().secondaryMessage) {
1271
+ <p class="secondary-message">{{ block().secondaryMessage }}</p>
1272
+ }
1273
+ @if (block().nextSteps?.length) {
1274
+ <ul>
1275
+ @for (item of block().nextSteps; track item) {
1276
+ <li>{{ item }}</li>
1277
+ }
1278
+ </ul>
1279
+ }
1280
+ @if (block().primaryAction; as action) {
1281
+ <button type="button" class="success-action" (click)="triggerAction(action)">
1282
+ @if (action.icon?.name) {
1283
+ <mat-icon aria-hidden="true" [praxisIcon]="action.icon?.name"></mat-icon>
1284
+ }
1285
+ <span>{{ action.label }}</span>
1286
+ </button>
1287
+ }
1288
+ </section>
1289
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".success-panel{display:grid;gap:12px;text-align:center;padding:20px;border-radius:var(--editorial-card-radius, 18px);background:color-mix(in srgb,var(--editorial-success, #35b37e) 10%,#fff);border:1px solid color-mix(in srgb,var(--editorial-success, #35b37e) 32%,transparent);box-shadow:var(--editorial-card-shadow, none)}.success-panel[data-tone=accent]{background:color-mix(in srgb,var(--editorial-accent, #264a8a) 10%,#fff);border-color:color-mix(in srgb,var(--editorial-accent, #264a8a) 24%,transparent)}.success-panel[data-tone=neutral]{background:var(--editorial-surface-primary, #fff);border-color:var(--editorial-border-color, #d9deea)}.success-panel h3,.success-panel p,.success-panel ul{margin:0}.success-panel ul{padding-left:20px;text-align:left}.secondary-message{color:var(--editorial-text-secondary, #7b8aa0);font-size:var(--editorial-body-size, 1rem)}.success-icon{display:grid;place-items:center;width:48px;height:48px;border-radius:999px;background:var(--editorial-success, #35b37e);color:#fff;justify-self:center;font-weight:700}.success-panel[data-tone=accent] .success-icon{background:var(--editorial-accent, #264a8a)}.success-panel[data-tone=neutral] .success-icon{background:var(--editorial-surface-secondary, #eef2f8);color:var(--editorial-text-primary, #24324a)}.success-icon mat-icon{width:20px;height:20px;font-size:20px;line-height:20px}.success-action{justify-self:center;display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:44px;padding:0 20px;border:0;border-radius:var(--editorial-button-radius, var(--editorial-card-radius, 18px));background:var(--editorial-cta-primary, var(--editorial-success, #35b37e));color:var(--editorial-cta-primary-text, #fff);box-shadow:var(--editorial-card-shadow, none);cursor:pointer;font:inherit;font-weight:600}.success-action mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}\n"] }]
1290
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: true }] }], actionTriggered: [{ type: i0.Output, args: ["actionTriggered"] }] } });
489
1291
 
490
1292
  class EditorialBlockRendererComponent {
491
1293
  block = input.required(...(ngDevMode ? [{ debugName: "block" }] : []));
492
1294
  runtimeContext = input(null, ...(ngDevMode ? [{ debugName: "runtimeContext" }] : []));
493
1295
  solution = input(null, ...(ngDevMode ? [{ debugName: "solution" }] : []));
494
1296
  instance = input(null, ...(ngDevMode ? [{ debugName: "instance" }] : []));
1297
+ runtimeContextChange = output();
495
1298
  operationalEvent = output();
1299
+ blockAction = output();
1300
+ introHero = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "introHero" }] : []));
496
1301
  hero = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "hero" }] : []));
497
1302
  richText = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "richText" }] : []));
498
1303
  policyList = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "policyList" }] : []));
499
1304
  timeline = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "timeline" }] : []));
500
1305
  review = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "review" }] : []));
1306
+ reviewSections = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "reviewSections" }] : []));
501
1307
  contextSummary = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "contextSummary" }] : []));
1308
+ selectionCards = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "selectionCards" }] : []));
502
1309
  infoCards = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "infoCards" }] : []));
1310
+ successPanel = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "successPanel" }] : []));
503
1311
  faq = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "faq" }] : []));
504
1312
  dataCollection = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "dataCollection" }] : []));
505
1313
  customWidget = computed(() => this.block(), ...(ngDevMode ? [{ debugName: "customWidget" }] : []));
@@ -518,8 +1326,14 @@ class EditorialBlockRendererComponent {
518
1326
  return valuePath ? `${contextPath}.${valuePath}` : contextPath;
519
1327
  }
520
1328
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialBlockRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
521
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialBlockRendererComponent, isStandalone: true, selector: "praxis-editorial-block-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: true, transformFunction: null }, runtimeContext: { classPropertyName: "runtimeContext", publicName: "runtimeContext", isSignal: true, isRequired: false, transformFunction: null }, solution: { classPropertyName: "solution", publicName: "solution", isSignal: true, isRequired: false, transformFunction: null }, instance: { classPropertyName: "instance", publicName: "instance", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { operationalEvent: "operationalEvent" }, ngImport: i0, template: `
1329
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialBlockRendererComponent, isStandalone: true, selector: "praxis-editorial-block-renderer", inputs: { block: { classPropertyName: "block", publicName: "block", isSignal: true, isRequired: true, transformFunction: null }, runtimeContext: { classPropertyName: "runtimeContext", publicName: "runtimeContext", isSignal: true, isRequired: false, transformFunction: null }, solution: { classPropertyName: "solution", publicName: "solution", isSignal: true, isRequired: false, transformFunction: null }, instance: { classPropertyName: "instance", publicName: "instance", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { runtimeContextChange: "runtimeContextChange", operationalEvent: "operationalEvent", blockAction: "blockAction" }, ngImport: i0, template: `
522
1330
  @switch (block().kind) {
1331
+ @case ('introHero') {
1332
+ <praxis-editorial-intro-hero-block
1333
+ [block]="introHero()"
1334
+ (actionTriggered)="blockAction.emit({ blockId: introHero().blockId, actionId: $event })"
1335
+ />
1336
+ }
523
1337
  @case ('hero') {
524
1338
  <section class="block-card hero-block">
525
1339
  @if (hero().subtitle) {
@@ -601,6 +1415,12 @@ class EditorialBlockRendererComponent {
601
1415
  </dl>
602
1416
  </section>
603
1417
  }
1418
+ @case ('reviewSections') {
1419
+ <praxis-editorial-review-sections-block
1420
+ [block]="reviewSections()"
1421
+ [runtimeContext]="runtimeContext()"
1422
+ />
1423
+ }
604
1424
  @case ('contextSummary') {
605
1425
  <section class="block-card">
606
1426
  @if (contextSummary().title) {
@@ -616,6 +1436,13 @@ class EditorialBlockRendererComponent {
616
1436
  </dl>
617
1437
  </section>
618
1438
  }
1439
+ @case ('selectionCards') {
1440
+ <praxis-editorial-selection-cards-block
1441
+ [block]="selectionCards()"
1442
+ [runtimeContext]="runtimeContext()"
1443
+ (runtimeContextChange)="runtimeContextChange.emit($event)"
1444
+ />
1445
+ }
619
1446
  @case ('infoCards') {
620
1447
  <section class="block-card">
621
1448
  <div class="cards-grid">
@@ -630,6 +1457,12 @@ class EditorialBlockRendererComponent {
630
1457
  </div>
631
1458
  </section>
632
1459
  }
1460
+ @case ('successPanel') {
1461
+ <praxis-editorial-success-panel-block
1462
+ [block]="successPanel()"
1463
+ (actionTriggered)="blockAction.emit({ blockId: successPanel().blockId, actionId: $event })"
1464
+ />
1465
+ }
633
1466
  @case ('faqAccordion') {
634
1467
  <section class="block-card stack-sm">
635
1468
  @for (item of faq().items; track item.id) {
@@ -646,6 +1479,7 @@ class EditorialBlockRendererComponent {
646
1479
  [runtimeContext]="runtimeContext()"
647
1480
  [solution]="solution()"
648
1481
  [instance]="instance()"
1482
+ (runtimeContextChange)="runtimeContextChange.emit($event)"
649
1483
  (operationalEvent)="operationalEvent.emit($event)"
650
1484
  />
651
1485
  }
@@ -666,7 +1500,7 @@ class EditorialBlockRendererComponent {
666
1500
  />
667
1501
  }
668
1502
  }
669
- `, isInline: true, styles: [":host{display:block}.block-card{display:grid;gap:12px;padding:18px;border-radius:18px;background:var(--md-sys-color-surface-container-low, #f7f2fa);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent)}.eyebrow{margin:0;font-size:.8rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-primary, #6750a4)}h3,p,ul,ol,dl{margin:0}.description,.content,.timeline-item span,.policy-item p,.info-card p,.faq-item p{color:var(--md-sys-color-on-surface-variant, #49454f)}.hero-block h3 span{color:var(--md-sys-color-primary, #6750a4)}.review-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.review-grid dt{margin-bottom:4px;font-size:.78rem;color:var(--md-sys-color-on-surface-variant, #49454f)}.review-grid dd{margin:0;font-weight:600}.list-reset{list-style:none;padding:0;margin:0}.stack-sm{display:grid;gap:10px}.timeline{display:grid;gap:12px;padding-left:18px;margin:0}.timeline-item{display:grid;gap:4px}.policy-item,.faq-item,.info-card{padding:12px;border-radius:14px;background:var(--md-sys-color-surface, #fff)}.cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px}.notice-block{border-left:4px solid var(--md-sys-color-primary, #6750a4)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent"], exportAs: ["dynamicWidgetLoader"] }, { kind: "component", type: EditorialDataCollectionBlockOutletComponent, selector: "praxis-editorial-data-collection-block-outlet", inputs: ["block", "runtimeContext", "solution", "instance"], outputs: ["operationalEvent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1503
+ `, isInline: true, styles: [":host{display:block}.block-card{display:grid;gap:12px;padding:18px;border-radius:18px;background:var(--md-sys-color-surface-container-low, #f7f2fa);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent)}.eyebrow{margin:0;font-size:.8rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-primary, #6750a4)}h3,p,ul,ol,dl{margin:0}.description,.content,.timeline-item span,.policy-item p,.info-card p,.faq-item p{color:var(--md-sys-color-on-surface-variant, #49454f)}.hero-block h3 span{color:var(--md-sys-color-primary, #6750a4)}.review-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.review-grid dt{margin-bottom:4px;font-size:.78rem;color:var(--md-sys-color-on-surface-variant, #49454f)}.review-grid dd{margin:0;font-weight:600}.list-reset{list-style:none;padding:0;margin:0}.stack-sm{display:grid;gap:10px}.timeline{display:grid;gap:12px;padding-left:18px;margin:0}.timeline-item{display:grid;gap:4px}.policy-item,.faq-item,.info-card{padding:12px;border-radius:14px;background:var(--md-sys-color-surface, #fff)}.cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px}.notice-block{border-left:4px solid var(--md-sys-color-primary, #6750a4)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent"], exportAs: ["dynamicWidgetLoader"] }, { kind: "component", type: EditorialDataCollectionBlockOutletComponent, selector: "praxis-editorial-data-collection-block-outlet", inputs: ["block", "runtimeContext", "solution", "instance"], outputs: ["runtimeContextChange", "operationalEvent"] }, { kind: "component", type: EditorialIntroHeroBlockComponent, selector: "praxis-editorial-intro-hero-block", inputs: ["block"], outputs: ["actionTriggered"] }, { kind: "component", type: EditorialSelectionCardsBlockComponent, selector: "praxis-editorial-selection-cards-block", inputs: ["block", "runtimeContext"], outputs: ["runtimeContextChange", "valueChange"] }, { kind: "component", type: EditorialReviewSectionsBlockComponent, selector: "praxis-editorial-review-sections-block", inputs: ["block", "runtimeContext"] }, { kind: "component", type: EditorialSuccessPanelBlockComponent, selector: "praxis-editorial-success-panel-block", inputs: ["block"], outputs: ["actionTriggered"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
670
1504
  }
671
1505
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialBlockRendererComponent, decorators: [{
672
1506
  type: Component,
@@ -674,8 +1508,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
674
1508
  CommonModule,
675
1509
  DynamicWidgetLoaderDirective,
676
1510
  EditorialDataCollectionBlockOutletComponent,
1511
+ EditorialIntroHeroBlockComponent,
1512
+ EditorialSelectionCardsBlockComponent,
1513
+ EditorialReviewSectionsBlockComponent,
1514
+ EditorialSuccessPanelBlockComponent,
677
1515
  ], template: `
678
1516
  @switch (block().kind) {
1517
+ @case ('introHero') {
1518
+ <praxis-editorial-intro-hero-block
1519
+ [block]="introHero()"
1520
+ (actionTriggered)="blockAction.emit({ blockId: introHero().blockId, actionId: $event })"
1521
+ />
1522
+ }
679
1523
  @case ('hero') {
680
1524
  <section class="block-card hero-block">
681
1525
  @if (hero().subtitle) {
@@ -757,6 +1601,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
757
1601
  </dl>
758
1602
  </section>
759
1603
  }
1604
+ @case ('reviewSections') {
1605
+ <praxis-editorial-review-sections-block
1606
+ [block]="reviewSections()"
1607
+ [runtimeContext]="runtimeContext()"
1608
+ />
1609
+ }
760
1610
  @case ('contextSummary') {
761
1611
  <section class="block-card">
762
1612
  @if (contextSummary().title) {
@@ -772,6 +1622,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
772
1622
  </dl>
773
1623
  </section>
774
1624
  }
1625
+ @case ('selectionCards') {
1626
+ <praxis-editorial-selection-cards-block
1627
+ [block]="selectionCards()"
1628
+ [runtimeContext]="runtimeContext()"
1629
+ (runtimeContextChange)="runtimeContextChange.emit($event)"
1630
+ />
1631
+ }
775
1632
  @case ('infoCards') {
776
1633
  <section class="block-card">
777
1634
  <div class="cards-grid">
@@ -786,6 +1643,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
786
1643
  </div>
787
1644
  </section>
788
1645
  }
1646
+ @case ('successPanel') {
1647
+ <praxis-editorial-success-panel-block
1648
+ [block]="successPanel()"
1649
+ (actionTriggered)="blockAction.emit({ blockId: successPanel().blockId, actionId: $event })"
1650
+ />
1651
+ }
789
1652
  @case ('faqAccordion') {
790
1653
  <section class="block-card stack-sm">
791
1654
  @for (item of faq().items; track item.id) {
@@ -802,6 +1665,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
802
1665
  [runtimeContext]="runtimeContext()"
803
1666
  [solution]="solution()"
804
1667
  [instance]="instance()"
1668
+ (runtimeContextChange)="runtimeContextChange.emit($event)"
805
1669
  (operationalEvent)="operationalEvent.emit($event)"
806
1670
  />
807
1671
  }
@@ -823,17 +1687,239 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
823
1687
  }
824
1688
  }
825
1689
  `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.block-card{display:grid;gap:12px;padding:18px;border-radius:18px;background:var(--md-sys-color-surface-container-low, #f7f2fa);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent)}.eyebrow{margin:0;font-size:.8rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:var(--md-sys-color-primary, #6750a4)}h3,p,ul,ol,dl{margin:0}.description,.content,.timeline-item span,.policy-item p,.info-card p,.faq-item p{color:var(--md-sys-color-on-surface-variant, #49454f)}.hero-block h3 span{color:var(--md-sys-color-primary, #6750a4)}.review-grid{display:grid;gap:12px;grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}.review-grid dt{margin-bottom:4px;font-size:.78rem;color:var(--md-sys-color-on-surface-variant, #49454f)}.review-grid dd{margin:0;font-weight:600}.list-reset{list-style:none;padding:0;margin:0}.stack-sm{display:grid;gap:10px}.timeline{display:grid;gap:12px;padding-left:18px;margin:0}.timeline-item{display:grid;gap:4px}.policy-item,.faq-item,.info-card{padding:12px;border-radius:14px;background:var(--md-sys-color-surface, #fff)}.cards-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px}.notice-block{border-left:4px solid var(--md-sys-color-primary, #6750a4)}\n"] }]
826
- }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: true }] }], runtimeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "runtimeContext", required: false }] }], solution: [{ type: i0.Input, args: [{ isSignal: true, alias: "solution", required: false }] }], instance: [{ type: i0.Input, args: [{ isSignal: true, alias: "instance", required: false }] }], operationalEvent: [{ type: i0.Output, args: ["operationalEvent"] }] } });
1690
+ }], propDecorators: { block: [{ type: i0.Input, args: [{ isSignal: true, alias: "block", required: true }] }], runtimeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "runtimeContext", required: false }] }], solution: [{ type: i0.Input, args: [{ isSignal: true, alias: "solution", required: false }] }], instance: [{ type: i0.Input, args: [{ isSignal: true, alias: "instance", required: false }] }], runtimeContextChange: [{ type: i0.Output, args: ["runtimeContextChange"] }], operationalEvent: [{ type: i0.Output, args: ["operationalEvent"] }], blockAction: [{ type: i0.Output, args: ["blockAction"] }] } });
1691
+
1692
+ function resolveRuntimeOrientation(layout, stepper, compactViewport = false) {
1693
+ if (compactViewport && layout?.responsive?.mobileOrientation) {
1694
+ return layout.responsive.mobileOrientation;
1695
+ }
1696
+ return stepper?.orientation ?? layout?.orientation ?? 'horizontal';
1697
+ }
1698
+ function resolveShellVariant(layout) {
1699
+ return layout?.shellVariant ?? 'corporate-wizard';
1700
+ }
1701
+ function resolveDensity(layout) {
1702
+ return layout?.density ?? 'comfortable';
1703
+ }
1704
+ function buildRuntimeLayoutCss(layout) {
1705
+ if (!layout) {
1706
+ return '';
1707
+ }
1708
+ return [
1709
+ layout.maxWidth ? `max-width:${layout.maxWidth};width:100%;margin-inline:auto` : '',
1710
+ layout.spacing?.pagePadding ? `--editorial-page-padding:${layout.spacing.pagePadding}` : '',
1711
+ layout.spacing?.shellPadding ? `--editorial-shell-padding:${layout.spacing.shellPadding}` : '',
1712
+ layout.spacing?.blockGap ? `--editorial-block-gap:${layout.spacing.blockGap}` : '',
1713
+ layout.spacing?.sectionGap ? `--editorial-section-gap:${layout.spacing.sectionGap}` : '',
1714
+ layout.spacing?.actionGap ? `--editorial-action-gap:${layout.spacing.actionGap}` : '',
1715
+ ].filter(Boolean).join(';');
1716
+ }
1717
+ function getStepDisplayState(step, steps, activeStepId, isBlocked) {
1718
+ if (step.stepId === activeStepId && isBlocked) {
1719
+ return 'blocked';
1720
+ }
1721
+ if (step.stepId === activeStepId) {
1722
+ return 'active';
1723
+ }
1724
+ const activeIndex = steps.findIndex((item) => item.stepId === activeStepId);
1725
+ const stepIndex = steps.findIndex((item) => item.stepId === step.stepId);
1726
+ if (activeIndex >= 0 && stepIndex >= 0 && stepIndex < activeIndex) {
1727
+ return 'completed';
1728
+ }
1729
+ return 'pending';
1730
+ }
1731
+
1732
+ class EditorialStepperComponent {
1733
+ i18n = inject(PraxisI18nService);
1734
+ steps = input.required(...(ngDevMode ? [{ debugName: "steps" }] : []));
1735
+ activeStepId = input(null, ...(ngDevMode ? [{ debugName: "activeStepId" }] : []));
1736
+ config = input(null, ...(ngDevMode ? [{ debugName: "config" }] : []));
1737
+ orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : []));
1738
+ progressionBlocked = input(false, ...(ngDevMode ? [{ debugName: "progressionBlocked" }] : []));
1739
+ isStepSelectionBlocked = input(() => false, ...(ngDevMode ? [{ debugName: "isStepSelectionBlocked" }] : []));
1740
+ stepSelected = output();
1741
+ effectiveOrientation = computed(() => this.config()?.orientation ?? this.orientation(), ...(ngDevMode ? [{ debugName: "effectiveOrientation" }] : []));
1742
+ stepperVariant = computed(() => this.config()?.variant ?? 'icon-label', ...(ngDevMode ? [{ debugName: "stepperVariant" }] : []));
1743
+ stepperAriaLabel = computed(() => this.t('stepper.ariaLabel', 'Etapas da jornada'), ...(ngDevMode ? [{ debugName: "stepperAriaLabel" }] : []));
1744
+ stepState(step) {
1745
+ return getStepDisplayState(step, this.steps(), this.activeStepId(), this.progressionBlocked());
1746
+ }
1747
+ stepNumber(step) {
1748
+ return this.steps().findIndex((item) => item.stepId === step.stepId) + 1;
1749
+ }
1750
+ isSelectionBlocked(stepId) {
1751
+ if (this.config()?.allowStepJump) {
1752
+ return false;
1753
+ }
1754
+ return this.isStepSelectionBlocked()(stepId);
1755
+ }
1756
+ onStepClick(stepId) {
1757
+ if (this.isSelectionBlocked(stepId)) {
1758
+ return;
1759
+ }
1760
+ this.stepSelected.emit(stepId);
1761
+ }
1762
+ connectorState(step) {
1763
+ const state = this.stepState(step);
1764
+ if (state === 'completed') {
1765
+ return 'completed';
1766
+ }
1767
+ if (state === 'active') {
1768
+ return 'active';
1769
+ }
1770
+ if (state === 'blocked') {
1771
+ return 'blocked';
1772
+ }
1773
+ return 'pending';
1774
+ }
1775
+ buildStepAriaLabel(step) {
1776
+ const state = this.stepState(step);
1777
+ const status = state === 'completed'
1778
+ ? this.t('stepper.state.completed', 'concluida')
1779
+ : state === 'active'
1780
+ ? this.t('stepper.state.active', 'etapa atual')
1781
+ : state === 'blocked'
1782
+ ? this.t('stepper.state.blocked', 'bloqueada')
1783
+ : this.t('stepper.state.pending', 'pendente');
1784
+ return `${this.stepNumber(step)}. ${step.label}, ${status}`;
1785
+ }
1786
+ t(key, fallback) {
1787
+ return this.i18n.t(`praxis.editorialForms.${key}`, undefined, fallback);
1788
+ }
1789
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialStepperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1790
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialStepperComponent, isStandalone: true, selector: "praxis-editorial-stepper", inputs: { steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: true, transformFunction: null }, activeStepId: { classPropertyName: "activeStepId", publicName: "activeStepId", isSignal: true, isRequired: false, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, progressionBlocked: { classPropertyName: "progressionBlocked", publicName: "progressionBlocked", isSignal: true, isRequired: false, transformFunction: null }, isStepSelectionBlocked: { classPropertyName: "isStepSelectionBlocked", publicName: "isStepSelectionBlocked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { stepSelected: "stepSelected" }, ngImport: i0, template: `
1791
+ <ol
1792
+ class="steps-nav"
1793
+ [class.vertical]="effectiveOrientation() === 'vertical'"
1794
+ [class.horizontal]="effectiveOrientation() === 'horizontal'"
1795
+ [attr.data-variant]="stepperVariant()"
1796
+ [attr.data-align]="config()?.align ?? 'start'"
1797
+ [attr.data-size]="config()?.size ?? 'md'"
1798
+ [attr.aria-label]="stepperAriaLabel()"
1799
+ >
1800
+ @for (step of steps(); track step.stepId; let last = $last) {
1801
+ <li
1802
+ class="stepper-item"
1803
+ [attr.data-state]="stepState(step)"
1804
+ [attr.aria-posinset]="stepNumber(step)"
1805
+ [attr.aria-setsize]="steps().length"
1806
+ >
1807
+ <button
1808
+ type="button"
1809
+ class="step-chip"
1810
+ [class.active]="activeStepId() === step.stepId"
1811
+ [class.completed]="stepState(step) === 'completed'"
1812
+ [class.blocked]="stepState(step) === 'blocked'"
1813
+ [disabled]="isSelectionBlocked(step.stepId)"
1814
+ [attr.data-state]="stepState(step)"
1815
+ [attr.aria-current]="activeStepId() === step.stepId ? 'step' : null"
1816
+ [attr.aria-label]="buildStepAriaLabel(step)"
1817
+ (click)="onStepClick(step.stepId)"
1818
+ >
1819
+ <span class="step-icon" aria-hidden="true">
1820
+ @if (stepState(step) === 'completed') {
1821
+ <mat-icon aria-hidden="true" praxisIcon="check"></mat-icon>
1822
+ } @else if (step.icon?.name) {
1823
+ <mat-icon aria-hidden="true" [praxisIcon]="step.icon?.name"></mat-icon>
1824
+ } @else {
1825
+ <span>{{ stepNumber(step) }}</span>
1826
+ }
1827
+ </span>
1828
+ @if ((config()?.showLabels ?? true) !== false) {
1829
+ <span class="step-copy">
1830
+ <span class="step-label">{{ step.label }}</span>
1831
+ @if ((config()?.showDescriptions ?? false) && step.description) {
1832
+ <span class="step-description">{{ step.description }}</span>
1833
+ }
1834
+ </span>
1835
+ }
1836
+ </button>
1837
+ @if ((config()?.showConnectors ?? true) && !last) {
1838
+ <span
1839
+ class="step-connector"
1840
+ [attr.data-state]="connectorState(step)"
1841
+ [attr.data-style]="config()?.connectorStyle ?? 'solid'"
1842
+ ></span>
1843
+ }
1844
+ </li>
1845
+ }
1846
+ </ol>
1847
+ `, isInline: true, styles: [":host{display:block}.steps-nav{--step-indicator-size: 42px;--step-copy-padding-block: 12px;--step-copy-padding-inline: 14px;--step-copy-width: minmax(0, 176px);--step-gap: 16px;--step-connector-offset: 26px;--step-connector-size: 4px;display:flex;align-items:flex-start;gap:var(--step-gap);list-style:none;padding:0;margin:0;width:100%}.steps-nav.horizontal[data-align=center]{justify-content:center}.steps-nav.horizontal[data-align=space-between]{justify-content:space-between}.steps-nav.horizontal[data-align=space-between] .stepper-item{flex:1 1 0}.steps-nav.horizontal[data-align=start] .stepper-item,.steps-nav.horizontal[data-align=center] .stepper-item{flex:0 1 196px}.steps-nav.vertical{flex-direction:column;gap:14px}.stepper-item{display:flex;align-items:flex-start;gap:var(--step-gap);min-width:0}.steps-nav.vertical .stepper-item{align-items:stretch;flex-direction:column;gap:10px}.step-chip{position:relative;display:inline-flex;flex-direction:column;align-items:center;gap:12px;width:100%;min-width:0;padding:0;border:0;background:transparent;color:var(--editorial-text-primary, #24324a);cursor:pointer;text-align:center;transition:transform .18s ease,opacity .18s ease}.step-chip:hover:not([disabled]){transform:translateY(-1px)}.step-chip:focus-visible{outline:3px solid var(--editorial-step-active, var(--editorial-accent, #264a8a));outline:3px solid color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 32%,white);outline-offset:6px;border-radius:calc(var(--editorial-card-radius, 22px) + 4px)}.steps-nav[data-size=sm]{--step-indicator-size: 34px;--step-copy-padding-block: 9px;--step-copy-padding-inline: 12px;--step-copy-width: minmax(0, 132px);--step-gap: 12px;--step-connector-offset: 21px}.steps-nav[data-size=lg]{--step-indicator-size: 52px;--step-copy-padding-block: 15px;--step-copy-padding-inline: 18px;--step-copy-width: minmax(0, 220px);--step-gap: 20px;--step-connector-offset: 32px}.step-chip[disabled]{opacity:.72;cursor:not-allowed;transform:none}.step-icon{display:inline-flex;align-items:center;justify-content:center;width:var(--step-indicator-size);height:var(--step-indicator-size);border-radius:999px;border:1px solid var(--editorial-border-color, #d9deea);border:1px solid color-mix(in srgb,var(--editorial-border-color, #d9deea) 74%,white);background:var(--editorial-step-pending, #eef1f7);background:radial-gradient(circle at 30% 30%,color-mix(in srgb,var(--editorial-surface-primary, #fff) 86%,white),color-mix(in srgb,var(--editorial-step-pending, #eef1f7) 92%,white));color:var(--editorial-text-secondary, #7b8aa0);font-size:.82rem;font-weight:700;flex:0 0 auto;box-shadow:inset 0 1px #ffffffeb,0 10px 22px #14274414;transition:background .18s ease,color .18s ease,box-shadow .18s ease,border-color .18s ease}.step-icon mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.steps-nav[data-size=lg] .step-icon mat-icon{width:22px;height:22px;font-size:22px;line-height:22px}.step-chip.active .step-icon{border-color:var(--editorial-step-active, var(--editorial-accent, #264a8a));background:var(--editorial-step-active, var(--editorial-accent, #264a8a));border-color:color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 62%,white);color:var(--editorial-accent-contrast, #fff);box-shadow:0 0 0 var(--editorial-active-step-border-width, 2px) color-mix(in srgb,var(--editorial-accent, #264a8a) 20%,transparent),0 16px 28px color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 22%,transparent)}.step-chip.completed .step-icon{border-color:var(--editorial-step-completed, var(--editorial-success, #35b37e));background:var(--editorial-step-completed, var(--editorial-success, #35b37e));border-color:color-mix(in srgb,var(--editorial-step-completed, var(--editorial-success, #35b37e)) 66%,white);color:#fff;box-shadow:0 14px 24px color-mix(in srgb,var(--editorial-step-completed, var(--editorial-success, #35b37e)) 20%,transparent)}.step-chip.blocked .step-icon{border-color:var(--editorial-step-blocked, var(--editorial-warning, #f28c38));background:var(--editorial-step-blocked, var(--editorial-warning, #f28c38));border-color:color-mix(in srgb,var(--editorial-step-blocked, var(--editorial-warning, #f28c38)) 66%,white);color:#fff;box-shadow:0 14px 24px color-mix(in srgb,var(--editorial-step-blocked, var(--editorial-warning, #f28c38)) 18%,transparent)}.step-copy{display:grid;gap:4px;min-width:0;width:var(--step-copy-width);padding:var(--step-copy-padding-block) var(--step-copy-padding-inline);border-radius:calc(var(--editorial-card-radius, 22px) - 4px);border:1px solid var(--editorial-border-color, #d9deea);border:1px solid color-mix(in srgb,var(--editorial-border-color, #d9deea) 92%,white);background:var(--editorial-surface-primary, #fff);background:linear-gradient(180deg,color-mix(in srgb,var(--editorial-surface-primary, #fff) 96%,white),color-mix(in srgb,var(--editorial-surface-secondary, #f6f8fc) 74%,white));box-shadow:0 16px 32px #14274414;transition:border-color .18s ease,background .18s ease,box-shadow .18s ease}.step-chip.active .step-copy{border-color:var(--editorial-step-active, var(--editorial-accent, #264a8a));background:var(--editorial-surface-primary, #fff);border-color:color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 32%,var(--editorial-border-color, #d9deea));background:linear-gradient(180deg,color-mix(in srgb,var(--editorial-surface-primary, #fff) 90%,white),color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 8%,var(--editorial-surface-primary, #fff)));box-shadow:0 18px 36px #1427441a,0 0 0 1px color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 12%,transparent)}.step-chip.completed .step-copy{border-color:var(--editorial-step-completed, var(--editorial-success, #35b37e));background:var(--editorial-surface-primary, #fff);border-color:color-mix(in srgb,var(--editorial-step-completed, var(--editorial-success, #35b37e)) 34%,var(--editorial-border-color, #d9deea));background:linear-gradient(180deg,color-mix(in srgb,var(--editorial-surface-primary, #fff) 88%,white),color-mix(in srgb,var(--editorial-step-completed, var(--editorial-success, #35b37e)) 8%,var(--editorial-surface-primary, #fff)))}.step-chip.blocked .step-copy{border-color:var(--editorial-step-blocked, var(--editorial-warning, #f28c38));background:var(--editorial-surface-primary, #fff);border-color:color-mix(in srgb,var(--editorial-step-blocked, var(--editorial-warning, #f28c38)) 38%,var(--editorial-border-color, #d9deea));background:linear-gradient(180deg,color-mix(in srgb,var(--editorial-surface-primary, #fff) 90%,white),color-mix(in srgb,var(--editorial-step-blocked, var(--editorial-warning, #f28c38)) 10%,var(--editorial-surface-primary, #fff)))}.step-label{font-weight:700;line-height:1.25;white-space:normal}.step-description{color:var(--editorial-text-secondary, #7b8aa0);font-size:.85rem;line-height:1.35}.step-connector{display:block;flex:1 1 auto;align-self:flex-start;min-width:40px;margin-top:var(--step-connector-offset);height:var(--step-connector-size);background:var(--editorial-connector, #8fd8c0);background:linear-gradient(90deg,color-mix(in srgb,var(--editorial-border-color, #d9deea) 58%,white),color-mix(in srgb,var(--editorial-connector, #8fd8c0) 72%,white));border-radius:999px;opacity:.92}.steps-nav.vertical .step-connector{width:var(--step-connector-size);min-width:var(--step-connector-size);min-height:28px;margin-top:0;margin-left:calc((var(--step-indicator-size) / 2) - (var(--step-connector-size) / 2));height:32px}.step-connector[data-style=dashed]{background:repeating-linear-gradient(90deg,var(--editorial-connector, #8fd8c0) 0 8px,transparent 8px 14px)}.steps-nav.vertical .step-connector[data-style=dashed]{background:repeating-linear-gradient(180deg,var(--editorial-connector, #8fd8c0) 0 8px,transparent 8px 14px)}.step-connector[data-style=soft]{height:8px;background:var(--editorial-connector, #8fd8c0);background:linear-gradient(90deg,color-mix(in srgb,var(--editorial-connector, #8fd8c0) 24%,transparent),color-mix(in srgb,var(--editorial-connector, #8fd8c0) 88%,white) 55%,color-mix(in srgb,var(--editorial-connector, #8fd8c0) 24%,transparent))}.steps-nav.vertical .step-connector[data-style=soft]{width:8px;min-width:8px;height:32px;background:var(--editorial-connector, #8fd8c0);background:linear-gradient(180deg,color-mix(in srgb,var(--editorial-connector, #8fd8c0) 24%,transparent),color-mix(in srgb,var(--editorial-connector, #8fd8c0) 88%,white) 55%,color-mix(in srgb,var(--editorial-connector, #8fd8c0) 24%,transparent))}.step-connector[data-state=completed]{background:var(--editorial-step-completed, var(--editorial-success, #35b37e));background:linear-gradient(90deg,color-mix(in srgb,var(--editorial-step-completed, var(--editorial-success, #35b37e)) 92%,white),color-mix(in srgb,var(--editorial-connector, #8fd8c0) 82%,white))}.step-connector[data-state=active]{background:var(--editorial-step-active, var(--editorial-accent, #264a8a));background:linear-gradient(90deg,color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 86%,white),color-mix(in srgb,var(--editorial-connector, #8fd8c0) 84%,white) 60%,color-mix(in srgb,var(--editorial-border-color, #d9deea) 48%,white))}.step-connector[data-state=blocked]{background:var(--editorial-step-blocked, var(--editorial-warning, #f28c38));background:linear-gradient(90deg,color-mix(in srgb,var(--editorial-step-blocked, var(--editorial-warning, #f28c38)) 78%,white),color-mix(in srgb,var(--editorial-border-color, #d9deea) 48%,white))}.steps-nav[data-variant=simple] .step-copy,.steps-nav[data-variant=simple] .step-description,.steps-nav[data-variant=icon] .step-description{display:none}.steps-nav[data-variant=simple] .step-chip,.steps-nav[data-variant=icon] .step-chip{gap:8px}.steps-nav.horizontal[data-variant=simple] .stepper-item,.steps-nav.horizontal[data-variant=icon] .stepper-item{align-items:center}.steps-nav[data-variant=rich] .step-copy{border-radius:var(--editorial-card-radius, 22px);box-shadow:0 20px 36px #14274417,0 0 0 1px #ffffff8c}.steps-nav.horizontal[data-variant=rich] .step-chip{align-items:stretch}.steps-nav.horizontal[data-variant=rich] .step-copy{text-align:left}.steps-nav.vertical .step-chip{flex-direction:row;align-items:center;justify-content:flex-start;text-align:left;gap:14px}.steps-nav.vertical .step-copy{width:100%}@media(max-width:860px){.steps-nav.horizontal{flex-direction:column;gap:12px}.steps-nav.horizontal .stepper-item{flex:none}.steps-nav.horizontal .step-chip{flex-direction:row;align-items:center;justify-content:flex-start;text-align:left}.steps-nav.horizontal .step-copy{width:100%}.steps-nav.horizontal .step-connector{width:var(--step-connector-size);min-width:var(--step-connector-size);min-height:24px;margin-top:0;margin-left:calc((var(--step-indicator-size) / 2) - (var(--step-connector-size) / 2));height:24px}.steps-nav.horizontal .step-connector[data-style=dashed]{background:repeating-linear-gradient(180deg,var(--editorial-connector, #8fd8c0) 0 8px,transparent 8px 14px)}.steps-nav.horizontal .step-connector[data-style=soft]{width:8px;min-width:8px;height:24px;background:var(--editorial-connector, #8fd8c0);background:linear-gradient(180deg,color-mix(in srgb,var(--editorial-connector, #8fd8c0) 24%,transparent),color-mix(in srgb,var(--editorial-connector, #8fd8c0) 88%,white) 55%,color-mix(in srgb,var(--editorial-connector, #8fd8c0) 24%,transparent))}}@media(prefers-reduced-motion:reduce){.step-chip,.step-icon,.step-copy{transition:none}.step-chip:hover:not([disabled]){transform:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1848
+ }
1849
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialStepperComponent, decorators: [{
1850
+ type: Component,
1851
+ args: [{ selector: 'praxis-editorial-stepper', standalone: true, imports: [CommonModule, MatIconModule, PraxisIconDirective], template: `
1852
+ <ol
1853
+ class="steps-nav"
1854
+ [class.vertical]="effectiveOrientation() === 'vertical'"
1855
+ [class.horizontal]="effectiveOrientation() === 'horizontal'"
1856
+ [attr.data-variant]="stepperVariant()"
1857
+ [attr.data-align]="config()?.align ?? 'start'"
1858
+ [attr.data-size]="config()?.size ?? 'md'"
1859
+ [attr.aria-label]="stepperAriaLabel()"
1860
+ >
1861
+ @for (step of steps(); track step.stepId; let last = $last) {
1862
+ <li
1863
+ class="stepper-item"
1864
+ [attr.data-state]="stepState(step)"
1865
+ [attr.aria-posinset]="stepNumber(step)"
1866
+ [attr.aria-setsize]="steps().length"
1867
+ >
1868
+ <button
1869
+ type="button"
1870
+ class="step-chip"
1871
+ [class.active]="activeStepId() === step.stepId"
1872
+ [class.completed]="stepState(step) === 'completed'"
1873
+ [class.blocked]="stepState(step) === 'blocked'"
1874
+ [disabled]="isSelectionBlocked(step.stepId)"
1875
+ [attr.data-state]="stepState(step)"
1876
+ [attr.aria-current]="activeStepId() === step.stepId ? 'step' : null"
1877
+ [attr.aria-label]="buildStepAriaLabel(step)"
1878
+ (click)="onStepClick(step.stepId)"
1879
+ >
1880
+ <span class="step-icon" aria-hidden="true">
1881
+ @if (stepState(step) === 'completed') {
1882
+ <mat-icon aria-hidden="true" praxisIcon="check"></mat-icon>
1883
+ } @else if (step.icon?.name) {
1884
+ <mat-icon aria-hidden="true" [praxisIcon]="step.icon?.name"></mat-icon>
1885
+ } @else {
1886
+ <span>{{ stepNumber(step) }}</span>
1887
+ }
1888
+ </span>
1889
+ @if ((config()?.showLabels ?? true) !== false) {
1890
+ <span class="step-copy">
1891
+ <span class="step-label">{{ step.label }}</span>
1892
+ @if ((config()?.showDescriptions ?? false) && step.description) {
1893
+ <span class="step-description">{{ step.description }}</span>
1894
+ }
1895
+ </span>
1896
+ }
1897
+ </button>
1898
+ @if ((config()?.showConnectors ?? true) && !last) {
1899
+ <span
1900
+ class="step-connector"
1901
+ [attr.data-state]="connectorState(step)"
1902
+ [attr.data-style]="config()?.connectorStyle ?? 'solid'"
1903
+ ></span>
1904
+ }
1905
+ </li>
1906
+ }
1907
+ </ol>
1908
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.steps-nav{--step-indicator-size: 42px;--step-copy-padding-block: 12px;--step-copy-padding-inline: 14px;--step-copy-width: minmax(0, 176px);--step-gap: 16px;--step-connector-offset: 26px;--step-connector-size: 4px;display:flex;align-items:flex-start;gap:var(--step-gap);list-style:none;padding:0;margin:0;width:100%}.steps-nav.horizontal[data-align=center]{justify-content:center}.steps-nav.horizontal[data-align=space-between]{justify-content:space-between}.steps-nav.horizontal[data-align=space-between] .stepper-item{flex:1 1 0}.steps-nav.horizontal[data-align=start] .stepper-item,.steps-nav.horizontal[data-align=center] .stepper-item{flex:0 1 196px}.steps-nav.vertical{flex-direction:column;gap:14px}.stepper-item{display:flex;align-items:flex-start;gap:var(--step-gap);min-width:0}.steps-nav.vertical .stepper-item{align-items:stretch;flex-direction:column;gap:10px}.step-chip{position:relative;display:inline-flex;flex-direction:column;align-items:center;gap:12px;width:100%;min-width:0;padding:0;border:0;background:transparent;color:var(--editorial-text-primary, #24324a);cursor:pointer;text-align:center;transition:transform .18s ease,opacity .18s ease}.step-chip:hover:not([disabled]){transform:translateY(-1px)}.step-chip:focus-visible{outline:3px solid var(--editorial-step-active, var(--editorial-accent, #264a8a));outline:3px solid color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 32%,white);outline-offset:6px;border-radius:calc(var(--editorial-card-radius, 22px) + 4px)}.steps-nav[data-size=sm]{--step-indicator-size: 34px;--step-copy-padding-block: 9px;--step-copy-padding-inline: 12px;--step-copy-width: minmax(0, 132px);--step-gap: 12px;--step-connector-offset: 21px}.steps-nav[data-size=lg]{--step-indicator-size: 52px;--step-copy-padding-block: 15px;--step-copy-padding-inline: 18px;--step-copy-width: minmax(0, 220px);--step-gap: 20px;--step-connector-offset: 32px}.step-chip[disabled]{opacity:.72;cursor:not-allowed;transform:none}.step-icon{display:inline-flex;align-items:center;justify-content:center;width:var(--step-indicator-size);height:var(--step-indicator-size);border-radius:999px;border:1px solid var(--editorial-border-color, #d9deea);border:1px solid color-mix(in srgb,var(--editorial-border-color, #d9deea) 74%,white);background:var(--editorial-step-pending, #eef1f7);background:radial-gradient(circle at 30% 30%,color-mix(in srgb,var(--editorial-surface-primary, #fff) 86%,white),color-mix(in srgb,var(--editorial-step-pending, #eef1f7) 92%,white));color:var(--editorial-text-secondary, #7b8aa0);font-size:.82rem;font-weight:700;flex:0 0 auto;box-shadow:inset 0 1px #ffffffeb,0 10px 22px #14274414;transition:background .18s ease,color .18s ease,box-shadow .18s ease,border-color .18s ease}.step-icon mat-icon{width:18px;height:18px;font-size:18px;line-height:18px}.steps-nav[data-size=lg] .step-icon mat-icon{width:22px;height:22px;font-size:22px;line-height:22px}.step-chip.active .step-icon{border-color:var(--editorial-step-active, var(--editorial-accent, #264a8a));background:var(--editorial-step-active, var(--editorial-accent, #264a8a));border-color:color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 62%,white);color:var(--editorial-accent-contrast, #fff);box-shadow:0 0 0 var(--editorial-active-step-border-width, 2px) color-mix(in srgb,var(--editorial-accent, #264a8a) 20%,transparent),0 16px 28px color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 22%,transparent)}.step-chip.completed .step-icon{border-color:var(--editorial-step-completed, var(--editorial-success, #35b37e));background:var(--editorial-step-completed, var(--editorial-success, #35b37e));border-color:color-mix(in srgb,var(--editorial-step-completed, var(--editorial-success, #35b37e)) 66%,white);color:#fff;box-shadow:0 14px 24px color-mix(in srgb,var(--editorial-step-completed, var(--editorial-success, #35b37e)) 20%,transparent)}.step-chip.blocked .step-icon{border-color:var(--editorial-step-blocked, var(--editorial-warning, #f28c38));background:var(--editorial-step-blocked, var(--editorial-warning, #f28c38));border-color:color-mix(in srgb,var(--editorial-step-blocked, var(--editorial-warning, #f28c38)) 66%,white);color:#fff;box-shadow:0 14px 24px color-mix(in srgb,var(--editorial-step-blocked, var(--editorial-warning, #f28c38)) 18%,transparent)}.step-copy{display:grid;gap:4px;min-width:0;width:var(--step-copy-width);padding:var(--step-copy-padding-block) var(--step-copy-padding-inline);border-radius:calc(var(--editorial-card-radius, 22px) - 4px);border:1px solid var(--editorial-border-color, #d9deea);border:1px solid color-mix(in srgb,var(--editorial-border-color, #d9deea) 92%,white);background:var(--editorial-surface-primary, #fff);background:linear-gradient(180deg,color-mix(in srgb,var(--editorial-surface-primary, #fff) 96%,white),color-mix(in srgb,var(--editorial-surface-secondary, #f6f8fc) 74%,white));box-shadow:0 16px 32px #14274414;transition:border-color .18s ease,background .18s ease,box-shadow .18s ease}.step-chip.active .step-copy{border-color:var(--editorial-step-active, var(--editorial-accent, #264a8a));background:var(--editorial-surface-primary, #fff);border-color:color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 32%,var(--editorial-border-color, #d9deea));background:linear-gradient(180deg,color-mix(in srgb,var(--editorial-surface-primary, #fff) 90%,white),color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 8%,var(--editorial-surface-primary, #fff)));box-shadow:0 18px 36px #1427441a,0 0 0 1px color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 12%,transparent)}.step-chip.completed .step-copy{border-color:var(--editorial-step-completed, var(--editorial-success, #35b37e));background:var(--editorial-surface-primary, #fff);border-color:color-mix(in srgb,var(--editorial-step-completed, var(--editorial-success, #35b37e)) 34%,var(--editorial-border-color, #d9deea));background:linear-gradient(180deg,color-mix(in srgb,var(--editorial-surface-primary, #fff) 88%,white),color-mix(in srgb,var(--editorial-step-completed, var(--editorial-success, #35b37e)) 8%,var(--editorial-surface-primary, #fff)))}.step-chip.blocked .step-copy{border-color:var(--editorial-step-blocked, var(--editorial-warning, #f28c38));background:var(--editorial-surface-primary, #fff);border-color:color-mix(in srgb,var(--editorial-step-blocked, var(--editorial-warning, #f28c38)) 38%,var(--editorial-border-color, #d9deea));background:linear-gradient(180deg,color-mix(in srgb,var(--editorial-surface-primary, #fff) 90%,white),color-mix(in srgb,var(--editorial-step-blocked, var(--editorial-warning, #f28c38)) 10%,var(--editorial-surface-primary, #fff)))}.step-label{font-weight:700;line-height:1.25;white-space:normal}.step-description{color:var(--editorial-text-secondary, #7b8aa0);font-size:.85rem;line-height:1.35}.step-connector{display:block;flex:1 1 auto;align-self:flex-start;min-width:40px;margin-top:var(--step-connector-offset);height:var(--step-connector-size);background:var(--editorial-connector, #8fd8c0);background:linear-gradient(90deg,color-mix(in srgb,var(--editorial-border-color, #d9deea) 58%,white),color-mix(in srgb,var(--editorial-connector, #8fd8c0) 72%,white));border-radius:999px;opacity:.92}.steps-nav.vertical .step-connector{width:var(--step-connector-size);min-width:var(--step-connector-size);min-height:28px;margin-top:0;margin-left:calc((var(--step-indicator-size) / 2) - (var(--step-connector-size) / 2));height:32px}.step-connector[data-style=dashed]{background:repeating-linear-gradient(90deg,var(--editorial-connector, #8fd8c0) 0 8px,transparent 8px 14px)}.steps-nav.vertical .step-connector[data-style=dashed]{background:repeating-linear-gradient(180deg,var(--editorial-connector, #8fd8c0) 0 8px,transparent 8px 14px)}.step-connector[data-style=soft]{height:8px;background:var(--editorial-connector, #8fd8c0);background:linear-gradient(90deg,color-mix(in srgb,var(--editorial-connector, #8fd8c0) 24%,transparent),color-mix(in srgb,var(--editorial-connector, #8fd8c0) 88%,white) 55%,color-mix(in srgb,var(--editorial-connector, #8fd8c0) 24%,transparent))}.steps-nav.vertical .step-connector[data-style=soft]{width:8px;min-width:8px;height:32px;background:var(--editorial-connector, #8fd8c0);background:linear-gradient(180deg,color-mix(in srgb,var(--editorial-connector, #8fd8c0) 24%,transparent),color-mix(in srgb,var(--editorial-connector, #8fd8c0) 88%,white) 55%,color-mix(in srgb,var(--editorial-connector, #8fd8c0) 24%,transparent))}.step-connector[data-state=completed]{background:var(--editorial-step-completed, var(--editorial-success, #35b37e));background:linear-gradient(90deg,color-mix(in srgb,var(--editorial-step-completed, var(--editorial-success, #35b37e)) 92%,white),color-mix(in srgb,var(--editorial-connector, #8fd8c0) 82%,white))}.step-connector[data-state=active]{background:var(--editorial-step-active, var(--editorial-accent, #264a8a));background:linear-gradient(90deg,color-mix(in srgb,var(--editorial-step-active, var(--editorial-accent, #264a8a)) 86%,white),color-mix(in srgb,var(--editorial-connector, #8fd8c0) 84%,white) 60%,color-mix(in srgb,var(--editorial-border-color, #d9deea) 48%,white))}.step-connector[data-state=blocked]{background:var(--editorial-step-blocked, var(--editorial-warning, #f28c38));background:linear-gradient(90deg,color-mix(in srgb,var(--editorial-step-blocked, var(--editorial-warning, #f28c38)) 78%,white),color-mix(in srgb,var(--editorial-border-color, #d9deea) 48%,white))}.steps-nav[data-variant=simple] .step-copy,.steps-nav[data-variant=simple] .step-description,.steps-nav[data-variant=icon] .step-description{display:none}.steps-nav[data-variant=simple] .step-chip,.steps-nav[data-variant=icon] .step-chip{gap:8px}.steps-nav.horizontal[data-variant=simple] .stepper-item,.steps-nav.horizontal[data-variant=icon] .stepper-item{align-items:center}.steps-nav[data-variant=rich] .step-copy{border-radius:var(--editorial-card-radius, 22px);box-shadow:0 20px 36px #14274417,0 0 0 1px #ffffff8c}.steps-nav.horizontal[data-variant=rich] .step-chip{align-items:stretch}.steps-nav.horizontal[data-variant=rich] .step-copy{text-align:left}.steps-nav.vertical .step-chip{flex-direction:row;align-items:center;justify-content:flex-start;text-align:left;gap:14px}.steps-nav.vertical .step-copy{width:100%}@media(max-width:860px){.steps-nav.horizontal{flex-direction:column;gap:12px}.steps-nav.horizontal .stepper-item{flex:none}.steps-nav.horizontal .step-chip{flex-direction:row;align-items:center;justify-content:flex-start;text-align:left}.steps-nav.horizontal .step-copy{width:100%}.steps-nav.horizontal .step-connector{width:var(--step-connector-size);min-width:var(--step-connector-size);min-height:24px;margin-top:0;margin-left:calc((var(--step-indicator-size) / 2) - (var(--step-connector-size) / 2));height:24px}.steps-nav.horizontal .step-connector[data-style=dashed]{background:repeating-linear-gradient(180deg,var(--editorial-connector, #8fd8c0) 0 8px,transparent 8px 14px)}.steps-nav.horizontal .step-connector[data-style=soft]{width:8px;min-width:8px;height:24px;background:var(--editorial-connector, #8fd8c0);background:linear-gradient(180deg,color-mix(in srgb,var(--editorial-connector, #8fd8c0) 24%,transparent),color-mix(in srgb,var(--editorial-connector, #8fd8c0) 88%,white) 55%,color-mix(in srgb,var(--editorial-connector, #8fd8c0) 24%,transparent))}}@media(prefers-reduced-motion:reduce){.step-chip,.step-icon,.step-copy{transition:none}.step-chip:hover:not([disabled]){transform:none}}\n"] }]
1909
+ }], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], activeStepId: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeStepId", required: false }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], progressionBlocked: [{ type: i0.Input, args: [{ isSignal: true, alias: "progressionBlocked", required: false }] }], isStepSelectionBlocked: [{ type: i0.Input, args: [{ isSignal: true, alias: "isStepSelectionBlocked", required: false }] }], stepSelected: [{ type: i0.Output, args: ["stepSelected"] }] } });
827
1910
 
828
1911
  function resolveEditorialRuntimeSnapshot(input) {
829
1912
  const diagnostics = [];
830
1913
  const solution = input.solution;
831
1914
  const instance = input.instance;
832
1915
  const context = mergeContext(instance?.context ?? {}, instance?.overrides?.contextPatch ?? {}, input.runtimeContext ?? {});
1916
+ const runtimeProblemType = solution?.problemType ?? instance?.template.problemType ?? null;
833
1917
  const effectiveThemePreset = resolveEffectiveThemePreset(solution, instance, diagnostics);
834
- const effectiveCompliancePresets = resolveEffectiveCompliancePresets(solution, instance, diagnostics);
1918
+ const effectiveCompliancePresets = resolveEffectiveCompliancePresets(solution, instance, runtimeProblemType, diagnostics);
835
1919
  validateContextContract(solution?.contextContract ?? [], context, diagnostics);
836
1920
  validateComplianceContext(effectiveCompliancePresets, context, diagnostics);
1921
+ validateComplianceRequirements(effectiveCompliancePresets, context, diagnostics);
1922
+ diagnoseUnsupportedPresentationConfig(solution?.presentation ?? null, diagnostics);
837
1923
  const journeys = mergeJourneys(solution, instance, diagnostics);
838
1924
  applyCompliancePresetBlocks(journeys, effectiveCompliancePresets, solution, instance);
839
1925
  applyJourneyOverrides(journeys, instance?.overrides?.journeyOverrides ?? [], diagnostics, instance);
@@ -855,6 +1941,7 @@ function resolveEditorialRuntimeSnapshot(input) {
855
1941
  description: solution?.description ?? null,
856
1942
  problemType: solution?.problemType ?? instance?.template.problemType ?? null,
857
1943
  context,
1944
+ presentation: resolveEffectivePresentation(solution?.presentation ?? null, effectiveThemePreset),
858
1945
  effectiveThemePreset,
859
1946
  effectiveCompliancePresets,
860
1947
  journeys,
@@ -885,13 +1972,13 @@ function resolveEffectiveThemePreset(solution, instance, diagnostics) {
885
1972
  }
886
1973
  return resolved;
887
1974
  }
888
- function resolveEffectiveCompliancePresets(solution, instance, diagnostics) {
1975
+ function resolveEffectiveCompliancePresets(solution, instance, runtimeProblemType, diagnostics) {
889
1976
  if (instance?.selectedCompliancePresets?.length) {
890
- return instance.selectedCompliancePresets;
1977
+ return filterCompliancePresetsByProblemType(instance.selectedCompliancePresets, runtimeProblemType, diagnostics);
891
1978
  }
892
1979
  const requestedPresetIds = instance?.overrides?.compliancePresetIds;
893
1980
  if (!requestedPresetIds?.length) {
894
- return solution?.compliancePresets ?? [];
1981
+ return filterCompliancePresetsByProblemType(solution?.compliancePresets ?? [], runtimeProblemType, diagnostics);
895
1982
  }
896
1983
  const resolved = [];
897
1984
  for (const presetId of requestedPresetIds) {
@@ -908,7 +1995,7 @@ function resolveEffectiveCompliancePresets(solution, instance, diagnostics) {
908
1995
  }
909
1996
  resolved.push(preset);
910
1997
  }
911
- return resolved;
1998
+ return filterCompliancePresetsByProblemType(resolved, runtimeProblemType, diagnostics);
912
1999
  }
913
2000
  function validateContextContract(contract, context, diagnostics) {
914
2001
  for (const field of contract) {
@@ -945,6 +2032,40 @@ function validateComplianceContext(presets, context, diagnostics) {
945
2032
  }
946
2033
  }
947
2034
  }
2035
+ function validateComplianceRequirements(presets, context, diagnostics) {
2036
+ for (const preset of presets) {
2037
+ for (const key of preset.requiredEvidenceKeys ?? []) {
2038
+ const value = resolveComplianceValue(context, key);
2039
+ if (value != null && value !== '' && (!Array.isArray(value) || value.length > 0)) {
2040
+ continue;
2041
+ }
2042
+ diagnostics.push({
2043
+ code: 'compliance-evidence-missing',
2044
+ severity: 'error',
2045
+ message: `Compliance preset "${preset.presetId}" requer a evidência "${key}".`,
2046
+ scopeKind: 'global',
2047
+ path: `compliancePreset:${preset.presetId}:evidence:${key}`,
2048
+ });
2049
+ }
2050
+ for (const key of preset.requiredAcceptances ?? []) {
2051
+ const value = resolveComplianceValue(context, key);
2052
+ const accepted = value === true
2053
+ || value === 'true'
2054
+ || value === 'accepted'
2055
+ || value === 'ACCEPTED';
2056
+ if (accepted) {
2057
+ continue;
2058
+ }
2059
+ diagnostics.push({
2060
+ code: 'compliance-acceptance-missing',
2061
+ severity: 'error',
2062
+ message: `Compliance preset "${preset.presetId}" requer o aceite "${key}".`,
2063
+ scopeKind: 'global',
2064
+ path: `compliancePreset:${preset.presetId}:acceptance:${key}`,
2065
+ });
2066
+ }
2067
+ }
2068
+ }
948
2069
  function mergeJourneys(solution, instance, diagnostics) {
949
2070
  const resolvedJourneys = new Map();
950
2071
  const order = [];
@@ -990,6 +2111,11 @@ function createResolvedStep(step, source, instance) {
990
2111
  stepId: step.stepId,
991
2112
  label: step.label,
992
2113
  description: step.description,
2114
+ kind: step.kind,
2115
+ icon: step.icon,
2116
+ visual: step.visual,
2117
+ optional: step.optional,
2118
+ editableFromReview: step.editableFromReview,
993
2119
  blocks: step.blocks.map((block) => createResolvedBlock(block, {
994
2120
  ...source,
995
2121
  blockId: block.blockId,
@@ -1058,6 +2184,11 @@ function mergeJourney(base, override, source, diagnostics, instance) {
1058
2184
  stepId: step.stepId,
1059
2185
  label: step.label || existing.label,
1060
2186
  description: step.description ?? existing.description,
2187
+ kind: step.kind ?? existing.kind,
2188
+ icon: step.icon ?? existing.icon,
2189
+ visual: step.visual ?? existing.visual,
2190
+ optional: step.optional ?? existing.optional,
2191
+ editableFromReview: step.editableFromReview ?? existing.editableFromReview,
1061
2192
  blocks: mergedBlocks,
1062
2193
  });
1063
2194
  }
@@ -1089,6 +2220,111 @@ function applyCompliancePresetBlocks(journeys, presets, solution, instance) {
1089
2220
  }
1090
2221
  }
1091
2222
  }
2223
+ function filterCompliancePresetsByProblemType(presets, runtimeProblemType, diagnostics) {
2224
+ if (!runtimeProblemType) {
2225
+ return presets;
2226
+ }
2227
+ return presets.filter((preset) => {
2228
+ if (!preset.problemTypes?.length || preset.problemTypes.includes(runtimeProblemType)) {
2229
+ return true;
2230
+ }
2231
+ diagnostics.push({
2232
+ code: 'compliance-preset-problem-type-mismatch',
2233
+ severity: 'warning',
2234
+ message: `Compliance preset "${preset.presetId}" nao se aplica ao problemType "${runtimeProblemType}".`,
2235
+ scopeKind: 'global',
2236
+ path: `compliancePreset:${preset.presetId}:problemType`,
2237
+ });
2238
+ return false;
2239
+ });
2240
+ }
2241
+ function resolveComplianceValue(context, key) {
2242
+ const direct = getValueAtPath(context, key);
2243
+ if (direct != null && direct !== '') {
2244
+ return direct;
2245
+ }
2246
+ return getValueAtPath(context, `formData.${key}`);
2247
+ }
2248
+ function resolveEffectivePresentation(basePresentation, themePreset) {
2249
+ if (!basePresentation && !themePreset) {
2250
+ return null;
2251
+ }
2252
+ const layout = {
2253
+ ...(basePresentation?.layout ?? {}),
2254
+ };
2255
+ if (themePreset?.maxWidth != null && !layout.maxWidth) {
2256
+ layout.maxWidth = String(themePreset.maxWidth);
2257
+ }
2258
+ if (themePreset?.pageSpacing != null) {
2259
+ layout.spacing = {
2260
+ ...(layout.spacing ?? {}),
2261
+ pagePadding: layout.spacing?.pagePadding ?? String(themePreset.pageSpacing),
2262
+ };
2263
+ }
2264
+ if (themePreset?.shellVariant && !layout.shellVariant) {
2265
+ layout.shellVariant = mapThemeShellVariant(themePreset.shellVariant);
2266
+ }
2267
+ const theme = {
2268
+ ...(basePresentation?.theme ?? {}),
2269
+ color: {
2270
+ ...(basePresentation?.theme?.color ?? {}),
2271
+ pageBackground: basePresentation?.theme?.color?.pageBackground ?? themePreset?.background,
2272
+ },
2273
+ };
2274
+ return {
2275
+ ...(basePresentation ?? {}),
2276
+ layout,
2277
+ theme,
2278
+ };
2279
+ }
2280
+ function diagnoseUnsupportedPresentationConfig(presentation, diagnostics) {
2281
+ if (!presentation) {
2282
+ return;
2283
+ }
2284
+ const unsupportedEntries = [];
2285
+ if (presentation.layout?.contentAlign) {
2286
+ unsupportedEntries.push({
2287
+ path: 'presentation.layout.contentAlign',
2288
+ reason: 'contentAlign ainda nao afeta o shell do runtime.',
2289
+ });
2290
+ }
2291
+ if (presentation.layout?.responsive?.tabletOrientation) {
2292
+ unsupportedEntries.push({
2293
+ path: 'presentation.layout.responsive.tabletOrientation',
2294
+ reason: 'tabletOrientation ainda nao possui comportamento responsivo dedicado.',
2295
+ });
2296
+ }
2297
+ if (presentation.motion) {
2298
+ unsupportedEntries.push({
2299
+ path: 'presentation.motion',
2300
+ reason: 'motion ainda nao possui integracao operacional no renderer do runtime.',
2301
+ });
2302
+ }
2303
+ for (const entry of unsupportedEntries) {
2304
+ diagnostics.push({
2305
+ code: 'presentation-config-unsupported',
2306
+ severity: 'warning',
2307
+ message: `Configuracao de presentation ignorada em "${entry.path}". ${entry.reason}`,
2308
+ scopeKind: 'global',
2309
+ path: entry.path,
2310
+ });
2311
+ }
2312
+ }
2313
+ function mapThemeShellVariant(shellVariant) {
2314
+ if (shellVariant === 'wizard') {
2315
+ return 'corporate-wizard';
2316
+ }
2317
+ if (shellVariant === 'split') {
2318
+ return 'sidebar-journey';
2319
+ }
2320
+ if (shellVariant === 'plain') {
2321
+ return 'compliance-flow';
2322
+ }
2323
+ if (shellVariant === 'card') {
2324
+ return 'compact-form';
2325
+ }
2326
+ return 'editorial-rich';
2327
+ }
1092
2328
  function applyJourneyOverrides(journeys, overrides, diagnostics, instance) {
1093
2329
  for (const journeyOverride of overrides) {
1094
2330
  const journey = journeys.find((candidate) => candidate.journeyId === journeyOverride.journeyId);
@@ -1352,7 +2588,7 @@ function buildDataCollectionState(block, instance) {
1352
2588
  resolvedFormConfigSource: resolution.source,
1353
2589
  resolvedFormConfigLookupKey: resolution.lookupKey,
1354
2590
  hasResolvedFormConfig,
1355
- expectedAdapter: 'required',
2591
+ expectedAdapter: 'optional',
1356
2592
  readiness,
1357
2593
  };
1358
2594
  }
@@ -1474,7 +2710,105 @@ function deriveRuntimeFallbackState(snapshot, scope = {}) {
1474
2710
  };
1475
2711
  }
1476
2712
 
2713
+ function buildRuntimeCssVars(theme) {
2714
+ if (!theme) {
2715
+ return '';
2716
+ }
2717
+ const vars = [
2718
+ ['--editorial-page-background', theme.color?.pageBackground],
2719
+ ['--editorial-surface-primary', theme.color?.surfacePrimary],
2720
+ ['--editorial-surface-secondary', theme.color?.surfaceSecondary],
2721
+ ['--editorial-border-color', theme.color?.border],
2722
+ ['--editorial-text-primary', theme.color?.textPrimary],
2723
+ ['--editorial-text-secondary', theme.color?.textSecondary],
2724
+ ['--editorial-accent', theme.color?.accent],
2725
+ ['--editorial-accent-contrast', theme.color?.accentContrast],
2726
+ ['--editorial-success', theme.color?.success],
2727
+ ['--editorial-warning', theme.color?.warning],
2728
+ ['--editorial-danger', theme.color?.danger],
2729
+ ['--editorial-muted', theme.color?.muted],
2730
+ ['--editorial-step-active', theme.color?.stepActive],
2731
+ ['--editorial-step-completed', theme.color?.stepCompleted],
2732
+ ['--editorial-step-pending', theme.color?.stepPending],
2733
+ ['--editorial-step-blocked', theme.color?.stepBlocked],
2734
+ ['--editorial-connector', theme.color?.connector],
2735
+ ['--editorial-cta-primary', theme.color?.ctaPrimary],
2736
+ ['--editorial-cta-primary-text', theme.color?.ctaPrimaryText],
2737
+ ['--editorial-cta-secondary', theme.color?.ctaSecondary],
2738
+ ['--editorial-cta-secondary-text', theme.color?.ctaSecondaryText],
2739
+ ['--editorial-shell-radius', theme.radius?.shell],
2740
+ ['--editorial-card-radius', theme.radius?.card],
2741
+ ['--editorial-button-radius', theme.radius?.button],
2742
+ ['--editorial-field-radius', theme.radius?.field],
2743
+ ['--editorial-step-radius', theme.radius?.step],
2744
+ ['--editorial-shell-shadow', theme.shadow?.shell],
2745
+ ['--editorial-card-shadow', theme.shadow?.card],
2746
+ ['--editorial-floating-shadow', theme.shadow?.floating],
2747
+ ['--editorial-shell-border-width', theme.borderWidth?.shell],
2748
+ ['--editorial-card-border-width', theme.borderWidth?.card],
2749
+ ['--editorial-field-border-width', theme.borderWidth?.field],
2750
+ ['--editorial-active-step-border-width', theme.borderWidth?.activeStep],
2751
+ ['--editorial-title-font-family', theme.typography?.titleFontFamily],
2752
+ ['--editorial-body-font-family', theme.typography?.bodyFontFamily],
2753
+ ['--editorial-title-weight', stringifyToken(theme.typography?.titleWeight)],
2754
+ ['--editorial-body-weight', stringifyToken(theme.typography?.bodyWeight)],
2755
+ ['--editorial-hero-title-size', theme.typography?.heroTitleSize],
2756
+ ['--editorial-step-title-size', theme.typography?.stepTitleSize],
2757
+ ['--editorial-body-size', theme.typography?.bodySize],
2758
+ ['--editorial-caption-size', theme.typography?.captionSize],
2759
+ ];
2760
+ const textPrimaryRgb = toRgbTuple(theme.color?.textPrimary);
2761
+ const textSecondaryRgb = toRgbTuple(theme.color?.textSecondary);
2762
+ const surfacePrimaryRgb = toRgbTuple(theme.color?.surfacePrimary);
2763
+ const surfaceSecondaryRgb = toRgbTuple(theme.color?.surfaceSecondary);
2764
+ if (textPrimaryRgb) {
2765
+ vars.push(['--editorial-text-primary-rgb', textPrimaryRgb]);
2766
+ }
2767
+ if (textSecondaryRgb) {
2768
+ vars.push(['--editorial-text-secondary-rgb', textSecondaryRgb]);
2769
+ }
2770
+ if (surfacePrimaryRgb) {
2771
+ vars.push(['--editorial-surface-primary-rgb', surfacePrimaryRgb]);
2772
+ }
2773
+ if (surfaceSecondaryRgb) {
2774
+ vars.push(['--editorial-surface-secondary-rgb', surfaceSecondaryRgb]);
2775
+ }
2776
+ return vars
2777
+ .filter(([, value]) => Boolean(value))
2778
+ .map(([key, value]) => `${key}:${value}`)
2779
+ .join(';');
2780
+ }
2781
+ function stringifyToken(value) {
2782
+ if (value === undefined || value === null || value === '') {
2783
+ return undefined;
2784
+ }
2785
+ return String(value);
2786
+ }
2787
+ function toRgbTuple(value) {
2788
+ if (!value) {
2789
+ return undefined;
2790
+ }
2791
+ const normalized = value.trim();
2792
+ const hex = normalized.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
2793
+ if (hex) {
2794
+ const raw = hex[1];
2795
+ const expanded = raw.length === 3
2796
+ ? raw.split('').map((char) => `${char}${char}`).join('')
2797
+ : raw;
2798
+ const r = parseInt(expanded.slice(0, 2), 16);
2799
+ const g = parseInt(expanded.slice(2, 4), 16);
2800
+ const b = parseInt(expanded.slice(4, 6), 16);
2801
+ return `${r}, ${g}, ${b}`;
2802
+ }
2803
+ const rgb = normalized.match(/^rgba?\(\s*(\d{1,3})[\s,]+(\d{1,3})[\s,]+(\d{1,3})(?:[\s,\/]+[\d.]+)?\s*\)$/i);
2804
+ if (rgb) {
2805
+ return `${rgb[1]}, ${rgb[2]}, ${rgb[3]}`;
2806
+ }
2807
+ return undefined;
2808
+ }
2809
+
1477
2810
  class EditorialFormRuntimeComponent {
2811
+ i18n = inject(PraxisI18nService);
1478
2812
  solution = input(null, ...(ngDevMode ? [{ debugName: "solution" }] : []));
1479
2813
  instance = input(null, ...(ngDevMode ? [{ debugName: "instance" }] : []));
1480
2814
  runtimeContext = input(null, ...(ngDevMode ? [{ debugName: "runtimeContext" }] : []));
@@ -1485,12 +2819,14 @@ class EditorialFormRuntimeComponent {
1485
2819
  state = new EditorialRuntimeState();
1486
2820
  solutionState = signal(null, ...(ngDevMode ? [{ debugName: "solutionState" }] : []));
1487
2821
  instanceState = signal(null, ...(ngDevMode ? [{ debugName: "instanceState" }] : []));
2822
+ runtimeContextState = signal(null, ...(ngDevMode ? [{ debugName: "runtimeContextState" }] : []));
2823
+ compactViewport = signal(false, ...(ngDevMode ? [{ debugName: "compactViewport" }] : []));
1488
2824
  lastSnapshotSignature = null;
1489
2825
  lastDiagnosticsSignature = null;
1490
2826
  lastFallbackSignature = null;
1491
2827
  lastBlockingSignature = null;
1492
2828
  lastOverrideConflictSignature = null;
1493
- runtime = this.state.connect(this.solutionState, this.instanceState, this.runtimeContext);
2829
+ runtime = this.state.connect(this.solutionState, this.instanceState, this.runtimeContextState);
1494
2830
  snapshot = computed(() => this.runtime.snapshot(), ...(ngDevMode ? [{ debugName: "snapshot" }] : []));
1495
2831
  resolvedHostConfig = computed(() => ({
1496
2832
  ...DEFAULT_EDITORIAL_RUNTIME_HOST_CONFIG,
@@ -1515,28 +2851,38 @@ class EditorialFormRuntimeComponent {
1515
2851
  activeStepHasErrors = computed(() => this.activeStepDiagnostics().some((item) => item.severity === 'error'), ...(ngDevMode ? [{ debugName: "activeStepHasErrors" }] : []));
1516
2852
  activeStepHasWarnings = computed(() => this.activeStepDiagnostics().some((item) => item.severity === 'warning'), ...(ngDevMode ? [{ debugName: "activeStepHasWarnings" }] : []));
1517
2853
  diagnosticsMessage = computed(() => this.fallbackState().mode === 'blocked'
1518
- ? 'Existem inconsistencias bloqueadoras que impedem a progressao segura do fluxo editorial.'
2854
+ ? this.t('runtime.diagnostics.message.blocked', 'Existem inconsistencias bloqueadoras que impedem a progressao segura do fluxo editorial.')
1519
2855
  : this.fallbackState().mode === 'degraded'
1520
- ? 'O runtime esta operando de forma degradada e requer atencao operacional.'
2856
+ ? this.t('runtime.diagnostics.message.degraded', 'O runtime esta operando de forma degradada e requer atencao operacional.')
1521
2857
  : this.runtimeDiagnostics().hasErrors
1522
- ? 'Existem inconsistencias que podem comprometer a experiencia editorial.'
1523
- : 'Existem avisos operacionais para revisar nesta instancia editorial.', ...(ngDevMode ? [{ debugName: "diagnosticsMessage" }] : []));
2858
+ ? this.t('runtime.diagnostics.message.error', 'Existem inconsistencias que podem comprometer a experiencia editorial.')
2859
+ : this.t('runtime.diagnostics.message.warning', 'Existem avisos operacionais para revisar nesta instancia editorial.'), ...(ngDevMode ? [{ debugName: "diagnosticsMessage" }] : []));
1524
2860
  activeGlobalDiagnostics = computed(() => this.globalDiagnostics().filter((item) => item.severity === 'error'), ...(ngDevMode ? [{ debugName: "activeGlobalDiagnostics" }] : []));
1525
2861
  visibleBlocks = computed(() => getVisibleBlocks(this.activeStep()?.blocks, this.resolvedContext()), ...(ngDevMode ? [{ debugName: "visibleBlocks" }] : []));
1526
2862
  runtimeTitle = computed(() => this.snapshot().title, ...(ngDevMode ? [{ debugName: "runtimeTitle" }] : []));
1527
2863
  runtimeDescription = computed(() => this.snapshot().description, ...(ngDevMode ? [{ debugName: "runtimeDescription" }] : []));
1528
2864
  runtimeEyebrow = computed(() => this.snapshot().problemType, ...(ngDevMode ? [{ debugName: "runtimeEyebrow" }] : []));
2865
+ presentation = computed(() => this.snapshot().presentation, ...(ngDevMode ? [{ debugName: "presentation" }] : []));
2866
+ runtimeCssVars = computed(() => buildRuntimeCssVars(this.presentation()?.theme), ...(ngDevMode ? [{ debugName: "runtimeCssVars" }] : []));
2867
+ runtimeLayoutCss = computed(() => buildRuntimeLayoutCss(this.presentation()?.layout), ...(ngDevMode ? [{ debugName: "runtimeLayoutCss" }] : []));
2868
+ runtimeStyleAttr = computed(() => [this.runtimeCssVars(), this.runtimeLayoutCss()].filter(Boolean).join(';'), ...(ngDevMode ? [{ debugName: "runtimeStyleAttr" }] : []));
2869
+ effectiveOrientation = computed(() => resolveRuntimeOrientation(this.presentation()?.layout, this.presentation()?.stepper, this.compactViewport()), ...(ngDevMode ? [{ debugName: "effectiveOrientation" }] : []));
2870
+ shellVariant = computed(() => resolveShellVariant(this.presentation()?.layout), ...(ngDevMode ? [{ debugName: "shellVariant" }] : []));
2871
+ effectiveDensity = computed(() => resolveDensity(this.presentation()?.layout), ...(ngDevMode ? [{ debugName: "effectiveDensity" }] : []));
2872
+ stepperConfig = computed(() => this.presentation()?.stepper ?? null, ...(ngDevMode ? [{ debugName: "stepperConfig" }] : []));
2873
+ stepperVisible = computed(() => this.stepperConfig()?.visible !== false, ...(ngDevMode ? [{ debugName: "stepperVisible" }] : []));
2874
+ stepSelectionBlocker = (stepId) => this.isStepSelectionBlocked(stepId);
1529
2875
  fallbackLabel = computed(() => {
1530
2876
  if (this.fallbackState().mode === 'blocked') {
1531
- return 'Runtime bloqueado';
2877
+ return this.t('runtime.fallback.blocked', 'Runtime bloqueado');
1532
2878
  }
1533
2879
  if (this.fallbackState().mode === 'degraded') {
1534
- return 'Runtime degradado';
2880
+ return this.t('runtime.fallback.degraded', 'Runtime degradado');
1535
2881
  }
1536
2882
  if (this.fallbackState().mode === 'warning') {
1537
- return 'Runtime com aviso';
2883
+ return this.t('runtime.fallback.warning', 'Runtime com aviso');
1538
2884
  }
1539
- return 'Runtime saudavel';
2885
+ return this.t('runtime.fallback.healthy', 'Runtime saudavel');
1540
2886
  }, ...(ngDevMode ? [{ debugName: "fallbackLabel" }] : []));
1541
2887
  currentStepIndex = computed(() => {
1542
2888
  const journey = this.activeJourney();
@@ -1555,6 +2901,25 @@ class EditorialFormRuntimeComponent {
1555
2901
  effect(() => {
1556
2902
  this.solutionState.set(this.solution());
1557
2903
  this.instanceState.set(this.instance());
2904
+ this.runtimeContextState.set(this.runtimeContext());
2905
+ });
2906
+ effect((onCleanup) => {
2907
+ const breakpoint = this.presentation()?.layout?.responsive?.collapseStepperBelow;
2908
+ if (typeof window === 'undefined' || typeof window.matchMedia !== 'function' || !breakpoint) {
2909
+ this.compactViewport.set(false);
2910
+ return;
2911
+ }
2912
+ const media = window.matchMedia(`(max-width: ${breakpoint})`);
2913
+ const sync = () => this.compactViewport.set(media.matches);
2914
+ sync();
2915
+ const listener = () => sync();
2916
+ if (typeof media.addEventListener === 'function') {
2917
+ media.addEventListener('change', listener);
2918
+ onCleanup(() => media.removeEventListener('change', listener));
2919
+ return;
2920
+ }
2921
+ media.addListener(listener);
2922
+ onCleanup(() => media.removeListener(listener));
1558
2923
  });
1559
2924
  effect(() => {
1560
2925
  const snapshot = this.snapshot();
@@ -1684,6 +3049,18 @@ class EditorialFormRuntimeComponent {
1684
3049
  this.state.selectStep(next.stepId);
1685
3050
  }
1686
3051
  }
3052
+ handleBlockAction(action) {
3053
+ if (action.actionId === 'next-step') {
3054
+ this.goToNextStep();
3055
+ return;
3056
+ }
3057
+ if (action.actionId === 'previous-step') {
3058
+ this.goToPreviousStep();
3059
+ }
3060
+ }
3061
+ updateRuntimeContext(nextContext) {
3062
+ this.runtimeContextState.set(nextContext);
3063
+ }
1687
3064
  journeyErrorCount(journeyId) {
1688
3065
  return this.countDiagnostics((item) => item.journeyId === journeyId && item.severity === 'error');
1689
3066
  }
@@ -1698,20 +3075,22 @@ class EditorialFormRuntimeComponent {
1698
3075
  }
1699
3076
  formatDiagnosticSeverity(item) {
1700
3077
  if (item.severity === 'error') {
1701
- return 'Erro';
3078
+ return this.t('runtime.diagnostics.severity.error', 'Erro');
1702
3079
  }
1703
3080
  if (item.severity === 'warning') {
1704
- return 'Aviso';
3081
+ return this.t('runtime.diagnostics.severity.warning', 'Aviso');
1705
3082
  }
1706
- return 'Info';
3083
+ return this.t('runtime.diagnostics.severity.info', 'Info');
1707
3084
  }
1708
3085
  formatDiagnosticScope(item) {
1709
3086
  const parts = [
1710
- item.scopeKind === 'global' ? 'Escopo: runtime global' : null,
1711
- formatScopeLabel('Jornada', item.journeyLabel, item.journeyId),
1712
- formatScopeLabel('Etapa', item.stepLabel, item.stepId),
1713
- formatScopeLabel('Bloco', item.blockLabel, item.blockId),
1714
- item.path ? `Path: ${item.path}` : null,
3087
+ item.scopeKind === 'global'
3088
+ ? this.t('runtime.scope.global', 'Escopo: runtime global')
3089
+ : null,
3090
+ formatScopeLabel(this.t('runtime.scope.journey', 'Jornada'), item.journeyLabel, item.journeyId),
3091
+ formatScopeLabel(this.t('runtime.scope.step', 'Etapa'), item.stepLabel, item.stepId),
3092
+ formatScopeLabel(this.t('runtime.scope.block', 'Bloco'), item.blockLabel, item.blockId),
3093
+ item.path ? `${this.t('runtime.scope.path', 'Path')}: ${item.path}` : null,
1715
3094
  ].filter((value) => Boolean(value));
1716
3095
  return parts.join(' | ');
1717
3096
  }
@@ -1730,13 +3109,16 @@ class EditorialFormRuntimeComponent {
1730
3109
  if (stepId === activeStepId) {
1731
3110
  return false;
1732
3111
  }
3112
+ if (this.stepperConfig()?.allowStepJump === false) {
3113
+ return true;
3114
+ }
1733
3115
  return this.isForwardNavigationBlocked();
1734
3116
  }
1735
3117
  navigationBlockingMessage() {
1736
3118
  if (this.activeGlobalDiagnostics().length) {
1737
- return 'A navegacao de avanço foi bloqueada porque o runtime possui erro global que precisa ser corrigido antes de continuar.';
3119
+ return this.t('runtime.navigation.globalBlocked', 'A navegacao de avanço foi bloqueada porque o runtime possui erro global que precisa ser corrigido antes de continuar.');
1738
3120
  }
1739
- return 'A navegacao de avanço foi bloqueada porque a etapa atual possui erro estrutural.';
3121
+ return this.t('runtime.navigation.stepBlocked', 'A navegacao de avanço foi bloqueada porque a etapa atual possui erro estrutural.');
1740
3122
  }
1741
3123
  countDiagnostics(predicate) {
1742
3124
  return this.diagnosticItems().filter(predicate).length;
@@ -1751,9 +3133,21 @@ class EditorialFormRuntimeComponent {
1751
3133
  }
1752
3134
  this.operationalEvent.emit(event);
1753
3135
  }
3136
+ t(key, fallback, params) {
3137
+ return this.i18n.t(`praxis.editorialForms.${key}`, params, fallback);
3138
+ }
1754
3139
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialFormRuntimeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1755
3140
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: EditorialFormRuntimeComponent, isStandalone: true, selector: "praxis-editorial-form-runtime", inputs: { solution: { classPropertyName: "solution", publicName: "solution", isSignal: true, isRequired: false, transformFunction: null }, instance: { classPropertyName: "instance", publicName: "instance", isSignal: true, isRequired: false, transformFunction: null }, runtimeContext: { classPropertyName: "runtimeContext", publicName: "runtimeContext", isSignal: true, isRequired: false, transformFunction: null }, hostConfig: { classPropertyName: "hostConfig", publicName: "hostConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { snapshotChange: "snapshotChange", fallbackChange: "fallbackChange", operationalEvent: "operationalEvent" }, ngImport: i0, template: `
1756
- <section class="editorial-runtime">
3141
+ <section
3142
+ class="editorial-runtime"
3143
+ [class.orientation-horizontal]="effectiveOrientation() === 'horizontal'"
3144
+ [class.orientation-vertical]="effectiveOrientation() === 'vertical'"
3145
+ [class.density-compact]="effectiveDensity() === 'compact'"
3146
+ [class.density-comfortable]="effectiveDensity() === 'comfortable'"
3147
+ [class.density-relaxed]="effectiveDensity() === 'relaxed'"
3148
+ [attr.data-shell-variant]="shellVariant()"
3149
+ [style]="runtimeStyleAttr()"
3150
+ >
1757
3151
  @if (runtimeDiagnostics().items.length) {
1758
3152
  <section
1759
3153
  class="diagnostics-panel"
@@ -1763,18 +3157,26 @@ class EditorialFormRuntimeComponent {
1763
3157
  [attr.aria-live]="runtimeDiagnostics().hasErrors ? 'assertive' : 'polite'"
1764
3158
  aria-atomic="true"
1765
3159
  >
1766
- <h2>Diagnosticos do runtime</h2>
3160
+ <h2>{{ t('runtime.diagnostics.title', 'Diagnosticos do runtime') }}</h2>
1767
3161
  <p>{{ diagnosticsMessage() }}</p>
1768
- <div class="diagnostics-summary" aria-label="Resumo de severidade">
1769
- <span class="summary-pill error">Erros: {{ diagnosticsErrorCount() }}</span>
1770
- <span class="summary-pill warning">Avisos: {{ diagnosticsWarningCount() }}</span>
1771
- <span class="summary-pill info">Infos: {{ diagnosticsInfoCount() }}</span>
3162
+ <div
3163
+ class="diagnostics-summary"
3164
+ [attr.aria-label]="t('runtime.diagnostics.severitySummary', 'Resumo de severidade')"
3165
+ >
3166
+ <span class="summary-pill error">{{ t('runtime.diagnostics.errorsCount', 'Erros: {count}', { count: diagnosticsErrorCount() }) }}</span>
3167
+ <span class="summary-pill warning">{{ t('runtime.diagnostics.warningsCount', 'Avisos: {count}', { count: diagnosticsWarningCount() }) }}</span>
3168
+ <span class="summary-pill info">{{ t('runtime.diagnostics.infoCount', 'Infos: {count}', { count: diagnosticsInfoCount() }) }}</span>
1772
3169
  </div>
1773
3170
  <details class="diagnostics-details">
1774
- <summary>Ver detalhes ({{ diagnosticItems().length }})</summary>
3171
+ <summary>
3172
+ {{ t('runtime.diagnostics.details', 'Ver detalhes ({count})', { count: diagnosticItems().length }) }}
3173
+ </summary>
1775
3174
  @if (globalDiagnostics().length) {
1776
- <section class="diagnostic-group global" aria-label="Erros globais do runtime">
1777
- <h3>Erros globais do runtime</h3>
3175
+ <section
3176
+ class="diagnostic-group global"
3177
+ [attr.aria-label]="t('runtime.diagnostics.globalErrors', 'Erros globais do runtime')"
3178
+ >
3179
+ <h3>{{ t('runtime.diagnostics.globalErrors', 'Erros globais do runtime') }}</h3>
1778
3180
  <ul class="diagnostics-list">
1779
3181
  @for (item of globalDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
1780
3182
  <li>
@@ -1818,7 +3220,10 @@ class EditorialFormRuntimeComponent {
1818
3220
  </header>
1819
3221
 
1820
3222
  @if (journeys().length > 1) {
1821
- <nav class="journey-tabs" aria-label="Jornadas editoriais">
3223
+ <nav
3224
+ class="journey-tabs"
3225
+ [attr.aria-label]="t('runtime.journeys.ariaLabel', 'Jornadas editoriais')"
3226
+ >
1822
3227
  @for (journey of journeys(); track journey.journeyId) {
1823
3228
  <button
1824
3229
  type="button"
@@ -1830,11 +3235,17 @@ class EditorialFormRuntimeComponent {
1830
3235
  >
1831
3236
  {{ journey.label }}
1832
3237
  @if (journeyErrorCount(journey.journeyId)) {
1833
- <span class="status-badge error" aria-label="Jornada com erros">
3238
+ <span
3239
+ class="status-badge error"
3240
+ [attr.aria-label]="t('runtime.journeys.errors', 'Jornada com erros')"
3241
+ >
1834
3242
  {{ journeyErrorCount(journey.journeyId) }}
1835
3243
  </span>
1836
3244
  } @else if (journeyWarningCount(journey.journeyId)) {
1837
- <span class="status-badge warning" aria-label="Jornada com avisos">
3245
+ <span
3246
+ class="status-badge warning"
3247
+ [attr.aria-label]="t('runtime.journeys.warnings', 'Jornada com avisos')"
3248
+ >
1838
3249
  {{ journeyWarningCount(journey.journeyId) }}
1839
3250
  </span>
1840
3251
  }
@@ -1852,32 +3263,16 @@ class EditorialFormRuntimeComponent {
1852
3263
  }
1853
3264
  </header>
1854
3265
 
1855
- @if (journey.steps.length > 1) {
1856
- <ol class="steps-nav" aria-label="Etapas da jornada">
1857
- @for (step of journey.steps; track step.stepId) {
1858
- <li>
1859
- <button
1860
- type="button"
1861
- class="step-chip"
1862
- [class.active]="activeStep()?.stepId === step.stepId"
1863
- [disabled]="isStepSelectionBlocked(step.stepId)"
1864
- [attr.aria-describedby]="isStepSelectionBlocked(step.stepId) ? 'navigation-blocking-note' : null"
1865
- (click)="selectStep(step.stepId)"
1866
- >
1867
- {{ step.label }}
1868
- @if (stepErrorCount(step.stepId)) {
1869
- <span class="status-badge error" aria-label="Etapa com erros">
1870
- {{ stepErrorCount(step.stepId) }}
1871
- </span>
1872
- } @else if (stepWarningCount(step.stepId)) {
1873
- <span class="status-badge warning" aria-label="Etapa com avisos">
1874
- {{ stepWarningCount(step.stepId) }}
1875
- </span>
1876
- }
1877
- </button>
1878
- </li>
1879
- }
1880
- </ol>
3266
+ @if (journey.steps.length > 1 && stepperVisible()) {
3267
+ <praxis-editorial-stepper
3268
+ [steps]="journey.steps"
3269
+ [activeStepId]="activeStep()?.stepId ?? null"
3270
+ [config]="stepperConfig()"
3271
+ [orientation]="effectiveOrientation()"
3272
+ [progressionBlocked]="isForwardNavigationBlocked()"
3273
+ [isStepSelectionBlocked]="stepSelectionBlocker"
3274
+ (stepSelected)="selectStep($event)"
3275
+ />
1881
3276
  }
1882
3277
 
1883
3278
  @if (activeStep(); as step) {
@@ -1894,7 +3289,12 @@ class EditorialFormRuntimeComponent {
1894
3289
  }
1895
3290
  </div>
1896
3291
  <div class="step-counter">
1897
- Etapa {{ currentStepIndex() + 1 }} de {{ journey.steps.length }}
3292
+ {{
3293
+ t('runtime.step.counter', 'Etapa {current} de {total}', {
3294
+ current: currentStepIndex() + 1,
3295
+ total: journey.steps.length,
3296
+ })
3297
+ }}
1898
3298
  </div>
1899
3299
  </header>
1900
3300
 
@@ -1907,7 +3307,7 @@ class EditorialFormRuntimeComponent {
1907
3307
  [attr.aria-live]="activeStepHasErrors() ? 'assertive' : 'polite'"
1908
3308
  aria-atomic="true"
1909
3309
  >
1910
- <h4>Situacao desta etapa</h4>
3310
+ <h4>{{ t('runtime.step.statusTitle', 'Situacao desta etapa') }}</h4>
1911
3311
  <ul class="diagnostics-list contextual">
1912
3312
  @for (item of activeStepDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
1913
3313
  <li>
@@ -1929,7 +3329,7 @@ class EditorialFormRuntimeComponent {
1929
3329
  aria-live="assertive"
1930
3330
  aria-atomic="true"
1931
3331
  >
1932
- <h4>Erro global do runtime</h4>
3332
+ <h4>{{ t('runtime.step.globalErrorTitle', 'Erro global do runtime') }}</h4>
1933
3333
  <ul class="diagnostics-list contextual">
1934
3334
  @for (item of activeGlobalDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
1935
3335
  <li>
@@ -1951,6 +3351,8 @@ class EditorialFormRuntimeComponent {
1951
3351
  [runtimeContext]="resolvedContext()"
1952
3352
  [solution]="solution()"
1953
3353
  [instance]="instance()"
3354
+ (runtimeContextChange)="updateRuntimeContext($event)"
3355
+ (blockAction)="handleBlockAction($event)"
1954
3356
  (operationalEvent)="emitOperationalEvent($event)"
1955
3357
  />
1956
3358
  }
@@ -1958,16 +3360,26 @@ class EditorialFormRuntimeComponent {
1958
3360
 
1959
3361
  @if (journey.steps.length > 1) {
1960
3362
  <footer class="step-actions">
1961
- <button type="button" (click)="goToPreviousStep()" [disabled]="!hasPreviousStep()">
1962
- Etapa anterior
3363
+ <button
3364
+ type="button"
3365
+ class="secondary"
3366
+ (click)="goToPreviousStep()"
3367
+ [disabled]="!hasPreviousStep()"
3368
+ >
3369
+ {{ t('runtime.actions.previous', 'Etapa anterior') }}
1963
3370
  </button>
1964
3371
  <button
1965
3372
  type="button"
3373
+ class="primary"
1966
3374
  (click)="goToNextStep()"
1967
3375
  [disabled]="!hasNextStep() || isForwardNavigationBlocked()"
1968
3376
  [attr.aria-describedby]="isForwardNavigationBlocked() ? 'navigation-blocking-note' : null"
1969
3377
  >
1970
- {{ isForwardNavigationBlocked() ? 'Corrija os erros para avancar' : 'Proxima etapa' }}
3378
+ {{
3379
+ isForwardNavigationBlocked()
3380
+ ? t('runtime.actions.nextBlocked', 'Corrija os erros para avancar')
3381
+ : t('runtime.actions.next', 'Proxima etapa')
3382
+ }}
1971
3383
  </button>
1972
3384
  </footer>
1973
3385
  @if (isForwardNavigationBlocked()) {
@@ -1981,23 +3393,36 @@ class EditorialFormRuntimeComponent {
1981
3393
  </section>
1982
3394
  } @else {
1983
3395
  <section class="empty-state">
1984
- <h2>Editorial runtime sem jornada</h2>
1985
- <p>Nenhuma jornada editorial foi resolvida para o estado atual.</p>
3396
+ <h2>{{ t('runtime.empty.noJourneyTitle', 'Editorial runtime sem jornada') }}</h2>
3397
+ <p>
3398
+ {{ t('runtime.empty.noJourneyDescription', 'Nenhuma jornada editorial foi resolvida para o estado atual.') }}
3399
+ </p>
1986
3400
  </section>
1987
3401
  }
1988
3402
  } @else {
1989
3403
  <section class="empty-state">
1990
- <h2>Editorial runtime vazio</h2>
1991
- <p>Forneca uma solution ou instance editorial para materializar a jornada.</p>
3404
+ <h2>{{ t('runtime.empty.noSolutionTitle', 'Editorial runtime vazio') }}</h2>
3405
+ <p>
3406
+ {{ t('runtime.empty.noSolutionDescription', 'Forneca uma solution ou instance editorial para materializar a jornada.') }}
3407
+ </p>
1992
3408
  </section>
1993
3409
  }
1994
3410
  </section>
1995
- `, isInline: true, styles: [":host{display:block}.editorial-runtime{display:grid;gap:24px;padding:24px;color:var(--md-sys-color-on-surface, #1b1b1f);background:var(--md-sys-color-surface, #fdf8fd)}.runtime-header,.journey-card,.empty-state,.diagnostics-panel{border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent);border-radius:20px;background:var(--md-sys-color-surface-container-low, #f7f2fa);padding:20px}.diagnostics-panel{display:grid;gap:10px}.diagnostics-panel.warning{border-color:color-mix(in srgb,#b26a00 55%,var(--md-sys-color-outline-variant, #cac4d0));background:color-mix(in srgb,#fff4de 78%,var(--md-sys-color-surface-container-low, #f7f2fa))}.diagnostics-panel.error{border-color:color-mix(in srgb,#b3261e 60%,var(--md-sys-color-outline-variant, #cac4d0));background:color-mix(in srgb,#fde7e9 78%,var(--md-sys-color-surface-container-low, #f7f2fa))}.diagnostics-list{margin:0;padding-left:18px;display:grid;gap:8px}.diagnostics-summary{display:flex;flex-wrap:wrap;gap:8px}.summary-pill{display:inline-flex;align-items:center;min-height:32px;padding:6px 10px;border-radius:999px;font-size:.85rem;border:1px solid transparent;background:color-mix(in srgb,var(--md-sys-color-surface, #fff) 85%,transparent)}.summary-pill.error{border-color:color-mix(in srgb,#b3261e 45%,transparent)}.summary-pill.warning{border-color:color-mix(in srgb,#b26a00 45%,transparent)}.summary-pill.info{border-color:color-mix(in srgb,#00639b 45%,transparent)}.status-badge{display:inline-flex;align-items:center;justify-content:center;min-width:22px;min-height:22px;padding:0 6px;border-radius:999px;font-size:.75rem;font-weight:700;background:var(--md-sys-color-surface, #fff)}.status-badge.error{color:#8c1d18;background:#fde7e9}.status-badge.warning{color:#7a4b00;background:#fff4de}.diagnostics-details summary{cursor:pointer;font-weight:600}.diagnostic-group{display:grid;gap:8px;padding:12px 0}.diagnostic-group.global{border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent);margin-bottom:12px}.step-panel.error{border-left:4px solid #b3261e}.step-panel.warning{border-left:4px solid #b26a00}.step-diagnostics{display:grid;gap:8px;padding:14px 16px;border-radius:16px}.step-diagnostics.error{background:#fde7e9;color:#5b1210}.step-diagnostics.warning{background:#fff4de;color:#6b4300}.step-diagnostics.global{background:#fde7e9;color:#5b1210;border:1px solid color-mix(in srgb,#b3261e 35%,transparent)}.diagnostics-list.contextual{padding-left:16px}.diagnostic-location{display:block;margin-top:4px;font-size:.82rem;opacity:.85}.step-blocking-note{font-size:.9rem;color:#8c1d18}.eyebrow{margin:0 0 8px;text-transform:uppercase;letter-spacing:.08em;font-size:.75rem;color:var(--md-sys-color-primary, #6750a4);font-weight:700}.runtime-state-pill{justify-self:start;display:inline-flex;align-items:center;min-height:30px;padding:4px 10px;border-radius:999px;font-size:.8rem;font-weight:700;background:color-mix(in srgb,var(--md-sys-color-surface, #fff) 88%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent)}.runtime-state-pill[data-mode=warning]{color:#7a4b00;background:#fff4de}.runtime-state-pill[data-mode=degraded]{color:#8c1d18;background:#fde7e9}.runtime-state-pill[data-mode=blocked]{color:#8c1d18;background:#fde7e9;border-color:color-mix(in srgb,#b3261e 55%,transparent)}h1,h2,h3,p{margin:0}.runtime-header,.journey-card,.journey-header,.step-panel{display:grid;gap:12px}.description,.journey-header p,.step-header p,.step-counter,.empty-state p{color:var(--md-sys-color-on-surface-variant, #49454f)}.journey-tabs,.steps-nav,.step-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center}.steps-nav{list-style:none;padding:0;margin:0}.journey-tab,.step-chip,.step-actions button{display:inline-flex;align-items:center;justify-content:center;min-height:42px;padding:10px 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 75%,transparent);background:var(--md-sys-color-surface, #fff);color:inherit;cursor:pointer}.journey-tab.active,.step-chip.active{background:var(--md-sys-color-primary, #6750a4);color:var(--md-sys-color-on-primary, #fff)}.step-header{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between}.block-stack{display:grid;gap:16px}.step-actions button[disabled]{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: EditorialBlockRendererComponent, selector: "praxis-editorial-block-renderer", inputs: ["block", "runtimeContext", "solution", "instance"], outputs: ["operationalEvent"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3411
+ `, isInline: true, styles: [":host{display:block}.editorial-runtime{display:grid;gap:24px;padding:var(--editorial-page-padding, 24px);color:var(--editorial-text-primary, var(--md-sys-color-on-surface, #1b1b1f));background:var(--editorial-page-background, var(--md-sys-color-surface, #fdf8fd));font-family:var(--editorial-body-font-family, inherit)}.runtime-header,.journey-card,.empty-state,.diagnostics-panel{border:var(--editorial-shell-border-width, 1px) solid color-mix(in srgb,var(--editorial-border-color, var(--md-sys-color-outline-variant, #cac4d0)) 70%,transparent);border-radius:var(--editorial-shell-radius, 20px);background:var(--editorial-surface-secondary, var(--md-sys-color-surface-container-low, #f7f2fa));padding:var(--editorial-shell-padding, 20px);box-shadow:var(--editorial-shell-shadow, none)}.diagnostics-panel{display:grid;gap:10px}.diagnostics-panel.warning{border-color:color-mix(in srgb,#b26a00 55%,var(--md-sys-color-outline-variant, #cac4d0));background:color-mix(in srgb,#fff4de 78%,var(--md-sys-color-surface-container-low, #f7f2fa))}.diagnostics-panel.error{border-color:color-mix(in srgb,#b3261e 60%,var(--md-sys-color-outline-variant, #cac4d0));background:color-mix(in srgb,#fde7e9 78%,var(--md-sys-color-surface-container-low, #f7f2fa))}.diagnostics-list{margin:0;padding-left:18px;display:grid;gap:8px}.diagnostics-summary{display:flex;flex-wrap:wrap;gap:8px}.summary-pill{display:inline-flex;align-items:center;min-height:32px;padding:6px 10px;border-radius:999px;font-size:.85rem;border:1px solid transparent;background:color-mix(in srgb,var(--md-sys-color-surface, #fff) 85%,transparent)}.summary-pill.error{border-color:color-mix(in srgb,#b3261e 45%,transparent)}.summary-pill.warning{border-color:color-mix(in srgb,#b26a00 45%,transparent)}.summary-pill.info{border-color:color-mix(in srgb,#00639b 45%,transparent)}.status-badge{display:inline-flex;align-items:center;justify-content:center;min-width:22px;min-height:22px;padding:0 6px;border-radius:999px;font-size:.75rem;font-weight:700;background:var(--md-sys-color-surface, #fff)}.status-badge.error{color:#8c1d18;background:#fde7e9}.status-badge.warning{color:#7a4b00;background:#fff4de}.diagnostics-details summary{cursor:pointer;font-weight:600}.diagnostic-group{display:grid;gap:8px;padding:12px 0}.diagnostic-group.global{border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent);margin-bottom:12px}.step-panel.error{border-left:4px solid #b3261e}.step-panel.warning{border-left:4px solid #b26a00}.step-diagnostics{display:grid;gap:8px;padding:14px 16px;border-radius:16px}.step-diagnostics.error{background:#fde7e9;color:#5b1210}.step-diagnostics.warning{background:#fff4de;color:#6b4300}.step-diagnostics.global{background:#fde7e9;color:#5b1210;border:1px solid color-mix(in srgb,#b3261e 35%,transparent)}.diagnostics-list.contextual{padding-left:16px}.diagnostic-location{display:block;margin-top:4px;font-size:.82rem;opacity:.85}.step-blocking-note{font-size:.9rem;color:#8c1d18}.eyebrow{margin:0 0 8px;text-transform:uppercase;letter-spacing:.08em;font-size:var(--editorial-caption-size, .75rem);color:var(--editorial-accent, var(--md-sys-color-primary, #6750a4));font-weight:700}.runtime-state-pill{justify-self:start;display:inline-flex;align-items:center;min-height:30px;padding:4px 10px;border-radius:999px;font-size:.8rem;font-weight:700;background:color-mix(in srgb,var(--md-sys-color-surface, #fff) 88%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent)}.runtime-state-pill[data-mode=warning]{color:#7a4b00;background:#fff4de}.runtime-state-pill[data-mode=degraded]{color:#8c1d18;background:#fde7e9}.runtime-state-pill[data-mode=blocked]{color:#8c1d18;background:#fde7e9;border-color:color-mix(in srgb,#b3261e 55%,transparent)}h1,h2,h3,p{margin:0}h1{font-size:var(--editorial-hero-title-size, 2rem);line-height:1.1}.step-header h3{font-size:var(--editorial-step-title-size, 1.25rem);line-height:1.2}.runtime-header,.journey-card,.journey-header,.step-panel{display:grid;gap:12px}.editorial-runtime[data-shell-variant=sidebar-journey] .journey-card,.orientation-vertical .journey-card{grid-template-columns:minmax(220px,280px) minmax(0,1fr);align-items:start}.description,.journey-header p,.step-header p,.step-counter,.empty-state p{font-size:var(--editorial-body-size, 1rem);color:var(--editorial-text-secondary, var(--md-sys-color-on-surface-variant, #49454f))}.journey-tabs,.step-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center}.journey-tab,.step-actions button{display:inline-flex;align-items:center;justify-content:center;min-height:42px;padding:10px 12px;border-radius:var(--editorial-button-radius, 999px);border:1px solid color-mix(in srgb,var(--editorial-border-color, var(--md-sys-color-outline-variant, #cac4d0)) 75%,transparent);background:var(--editorial-surface-primary, var(--md-sys-color-surface, #fff));color:inherit;box-shadow:var(--editorial-card-shadow, none);cursor:pointer}.journey-tab.active,.step-actions button.primary{background:var(--editorial-cta-primary, var(--editorial-accent, var(--md-sys-color-primary, #6750a4)));color:var(--editorial-cta-primary-text, var(--editorial-accent-contrast, var(--md-sys-color-on-primary, #fff)));border-color:transparent}.step-actions button.secondary{color:var(--editorial-cta-primary, var(--editorial-accent, var(--md-sys-color-primary, #6750a4)))}.step-header{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between}.block-stack{display:grid;gap:var(--editorial-block-gap, 16px)}.step-actions button[disabled]{opacity:.5;cursor:not-allowed}.density-compact{--editorial-page-padding: 16px;--editorial-shell-padding: 16px;--editorial-block-gap: 12px}.density-comfortable{--editorial-page-padding: 24px;--editorial-shell-padding: 20px;--editorial-block-gap: 16px}.density-relaxed{--editorial-page-padding: 32px;--editorial-shell-padding: 28px;--editorial-block-gap: 20px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: EditorialBlockRendererComponent, selector: "praxis-editorial-block-renderer", inputs: ["block", "runtimeContext", "solution", "instance"], outputs: ["runtimeContextChange", "operationalEvent", "blockAction"] }, { kind: "component", type: EditorialStepperComponent, selector: "praxis-editorial-stepper", inputs: ["steps", "activeStepId", "config", "orientation", "progressionBlocked", "isStepSelectionBlocked"], outputs: ["stepSelected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1996
3412
  }
1997
3413
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: EditorialFormRuntimeComponent, decorators: [{
1998
3414
  type: Component,
1999
- args: [{ selector: 'praxis-editorial-form-runtime', standalone: true, imports: [CommonModule, EditorialBlockRendererComponent], template: `
2000
- <section class="editorial-runtime">
3415
+ args: [{ selector: 'praxis-editorial-form-runtime', standalone: true, imports: [CommonModule, EditorialBlockRendererComponent, EditorialStepperComponent], template: `
3416
+ <section
3417
+ class="editorial-runtime"
3418
+ [class.orientation-horizontal]="effectiveOrientation() === 'horizontal'"
3419
+ [class.orientation-vertical]="effectiveOrientation() === 'vertical'"
3420
+ [class.density-compact]="effectiveDensity() === 'compact'"
3421
+ [class.density-comfortable]="effectiveDensity() === 'comfortable'"
3422
+ [class.density-relaxed]="effectiveDensity() === 'relaxed'"
3423
+ [attr.data-shell-variant]="shellVariant()"
3424
+ [style]="runtimeStyleAttr()"
3425
+ >
2001
3426
  @if (runtimeDiagnostics().items.length) {
2002
3427
  <section
2003
3428
  class="diagnostics-panel"
@@ -2007,18 +3432,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
2007
3432
  [attr.aria-live]="runtimeDiagnostics().hasErrors ? 'assertive' : 'polite'"
2008
3433
  aria-atomic="true"
2009
3434
  >
2010
- <h2>Diagnosticos do runtime</h2>
3435
+ <h2>{{ t('runtime.diagnostics.title', 'Diagnosticos do runtime') }}</h2>
2011
3436
  <p>{{ diagnosticsMessage() }}</p>
2012
- <div class="diagnostics-summary" aria-label="Resumo de severidade">
2013
- <span class="summary-pill error">Erros: {{ diagnosticsErrorCount() }}</span>
2014
- <span class="summary-pill warning">Avisos: {{ diagnosticsWarningCount() }}</span>
2015
- <span class="summary-pill info">Infos: {{ diagnosticsInfoCount() }}</span>
3437
+ <div
3438
+ class="diagnostics-summary"
3439
+ [attr.aria-label]="t('runtime.diagnostics.severitySummary', 'Resumo de severidade')"
3440
+ >
3441
+ <span class="summary-pill error">{{ t('runtime.diagnostics.errorsCount', 'Erros: {count}', { count: diagnosticsErrorCount() }) }}</span>
3442
+ <span class="summary-pill warning">{{ t('runtime.diagnostics.warningsCount', 'Avisos: {count}', { count: diagnosticsWarningCount() }) }}</span>
3443
+ <span class="summary-pill info">{{ t('runtime.diagnostics.infoCount', 'Infos: {count}', { count: diagnosticsInfoCount() }) }}</span>
2016
3444
  </div>
2017
3445
  <details class="diagnostics-details">
2018
- <summary>Ver detalhes ({{ diagnosticItems().length }})</summary>
3446
+ <summary>
3447
+ {{ t('runtime.diagnostics.details', 'Ver detalhes ({count})', { count: diagnosticItems().length }) }}
3448
+ </summary>
2019
3449
  @if (globalDiagnostics().length) {
2020
- <section class="diagnostic-group global" aria-label="Erros globais do runtime">
2021
- <h3>Erros globais do runtime</h3>
3450
+ <section
3451
+ class="diagnostic-group global"
3452
+ [attr.aria-label]="t('runtime.diagnostics.globalErrors', 'Erros globais do runtime')"
3453
+ >
3454
+ <h3>{{ t('runtime.diagnostics.globalErrors', 'Erros globais do runtime') }}</h3>
2022
3455
  <ul class="diagnostics-list">
2023
3456
  @for (item of globalDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
2024
3457
  <li>
@@ -2062,7 +3495,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
2062
3495
  </header>
2063
3496
 
2064
3497
  @if (journeys().length > 1) {
2065
- <nav class="journey-tabs" aria-label="Jornadas editoriais">
3498
+ <nav
3499
+ class="journey-tabs"
3500
+ [attr.aria-label]="t('runtime.journeys.ariaLabel', 'Jornadas editoriais')"
3501
+ >
2066
3502
  @for (journey of journeys(); track journey.journeyId) {
2067
3503
  <button
2068
3504
  type="button"
@@ -2074,11 +3510,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
2074
3510
  >
2075
3511
  {{ journey.label }}
2076
3512
  @if (journeyErrorCount(journey.journeyId)) {
2077
- <span class="status-badge error" aria-label="Jornada com erros">
3513
+ <span
3514
+ class="status-badge error"
3515
+ [attr.aria-label]="t('runtime.journeys.errors', 'Jornada com erros')"
3516
+ >
2078
3517
  {{ journeyErrorCount(journey.journeyId) }}
2079
3518
  </span>
2080
3519
  } @else if (journeyWarningCount(journey.journeyId)) {
2081
- <span class="status-badge warning" aria-label="Jornada com avisos">
3520
+ <span
3521
+ class="status-badge warning"
3522
+ [attr.aria-label]="t('runtime.journeys.warnings', 'Jornada com avisos')"
3523
+ >
2082
3524
  {{ journeyWarningCount(journey.journeyId) }}
2083
3525
  </span>
2084
3526
  }
@@ -2096,32 +3538,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
2096
3538
  }
2097
3539
  </header>
2098
3540
 
2099
- @if (journey.steps.length > 1) {
2100
- <ol class="steps-nav" aria-label="Etapas da jornada">
2101
- @for (step of journey.steps; track step.stepId) {
2102
- <li>
2103
- <button
2104
- type="button"
2105
- class="step-chip"
2106
- [class.active]="activeStep()?.stepId === step.stepId"
2107
- [disabled]="isStepSelectionBlocked(step.stepId)"
2108
- [attr.aria-describedby]="isStepSelectionBlocked(step.stepId) ? 'navigation-blocking-note' : null"
2109
- (click)="selectStep(step.stepId)"
2110
- >
2111
- {{ step.label }}
2112
- @if (stepErrorCount(step.stepId)) {
2113
- <span class="status-badge error" aria-label="Etapa com erros">
2114
- {{ stepErrorCount(step.stepId) }}
2115
- </span>
2116
- } @else if (stepWarningCount(step.stepId)) {
2117
- <span class="status-badge warning" aria-label="Etapa com avisos">
2118
- {{ stepWarningCount(step.stepId) }}
2119
- </span>
2120
- }
2121
- </button>
2122
- </li>
2123
- }
2124
- </ol>
3541
+ @if (journey.steps.length > 1 && stepperVisible()) {
3542
+ <praxis-editorial-stepper
3543
+ [steps]="journey.steps"
3544
+ [activeStepId]="activeStep()?.stepId ?? null"
3545
+ [config]="stepperConfig()"
3546
+ [orientation]="effectiveOrientation()"
3547
+ [progressionBlocked]="isForwardNavigationBlocked()"
3548
+ [isStepSelectionBlocked]="stepSelectionBlocker"
3549
+ (stepSelected)="selectStep($event)"
3550
+ />
2125
3551
  }
2126
3552
 
2127
3553
  @if (activeStep(); as step) {
@@ -2138,7 +3564,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
2138
3564
  }
2139
3565
  </div>
2140
3566
  <div class="step-counter">
2141
- Etapa {{ currentStepIndex() + 1 }} de {{ journey.steps.length }}
3567
+ {{
3568
+ t('runtime.step.counter', 'Etapa {current} de {total}', {
3569
+ current: currentStepIndex() + 1,
3570
+ total: journey.steps.length,
3571
+ })
3572
+ }}
2142
3573
  </div>
2143
3574
  </header>
2144
3575
 
@@ -2151,7 +3582,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
2151
3582
  [attr.aria-live]="activeStepHasErrors() ? 'assertive' : 'polite'"
2152
3583
  aria-atomic="true"
2153
3584
  >
2154
- <h4>Situacao desta etapa</h4>
3585
+ <h4>{{ t('runtime.step.statusTitle', 'Situacao desta etapa') }}</h4>
2155
3586
  <ul class="diagnostics-list contextual">
2156
3587
  @for (item of activeStepDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
2157
3588
  <li>
@@ -2173,7 +3604,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
2173
3604
  aria-live="assertive"
2174
3605
  aria-atomic="true"
2175
3606
  >
2176
- <h4>Erro global do runtime</h4>
3607
+ <h4>{{ t('runtime.step.globalErrorTitle', 'Erro global do runtime') }}</h4>
2177
3608
  <ul class="diagnostics-list contextual">
2178
3609
  @for (item of activeGlobalDiagnostics(); track item.code + ':' + (item.path ?? $index)) {
2179
3610
  <li>
@@ -2195,6 +3626,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
2195
3626
  [runtimeContext]="resolvedContext()"
2196
3627
  [solution]="solution()"
2197
3628
  [instance]="instance()"
3629
+ (runtimeContextChange)="updateRuntimeContext($event)"
3630
+ (blockAction)="handleBlockAction($event)"
2198
3631
  (operationalEvent)="emitOperationalEvent($event)"
2199
3632
  />
2200
3633
  }
@@ -2202,16 +3635,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
2202
3635
 
2203
3636
  @if (journey.steps.length > 1) {
2204
3637
  <footer class="step-actions">
2205
- <button type="button" (click)="goToPreviousStep()" [disabled]="!hasPreviousStep()">
2206
- Etapa anterior
3638
+ <button
3639
+ type="button"
3640
+ class="secondary"
3641
+ (click)="goToPreviousStep()"
3642
+ [disabled]="!hasPreviousStep()"
3643
+ >
3644
+ {{ t('runtime.actions.previous', 'Etapa anterior') }}
2207
3645
  </button>
2208
3646
  <button
2209
3647
  type="button"
3648
+ class="primary"
2210
3649
  (click)="goToNextStep()"
2211
3650
  [disabled]="!hasNextStep() || isForwardNavigationBlocked()"
2212
3651
  [attr.aria-describedby]="isForwardNavigationBlocked() ? 'navigation-blocking-note' : null"
2213
3652
  >
2214
- {{ isForwardNavigationBlocked() ? 'Corrija os erros para avancar' : 'Proxima etapa' }}
3653
+ {{
3654
+ isForwardNavigationBlocked()
3655
+ ? t('runtime.actions.nextBlocked', 'Corrija os erros para avancar')
3656
+ : t('runtime.actions.next', 'Proxima etapa')
3657
+ }}
2215
3658
  </button>
2216
3659
  </footer>
2217
3660
  @if (isForwardNavigationBlocked()) {
@@ -2225,28 +3668,45 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
2225
3668
  </section>
2226
3669
  } @else {
2227
3670
  <section class="empty-state">
2228
- <h2>Editorial runtime sem jornada</h2>
2229
- <p>Nenhuma jornada editorial foi resolvida para o estado atual.</p>
3671
+ <h2>{{ t('runtime.empty.noJourneyTitle', 'Editorial runtime sem jornada') }}</h2>
3672
+ <p>
3673
+ {{ t('runtime.empty.noJourneyDescription', 'Nenhuma jornada editorial foi resolvida para o estado atual.') }}
3674
+ </p>
2230
3675
  </section>
2231
3676
  }
2232
3677
  } @else {
2233
3678
  <section class="empty-state">
2234
- <h2>Editorial runtime vazio</h2>
2235
- <p>Forneca uma solution ou instance editorial para materializar a jornada.</p>
3679
+ <h2>{{ t('runtime.empty.noSolutionTitle', 'Editorial runtime vazio') }}</h2>
3680
+ <p>
3681
+ {{ t('runtime.empty.noSolutionDescription', 'Forneca uma solution ou instance editorial para materializar a jornada.') }}
3682
+ </p>
2236
3683
  </section>
2237
3684
  }
2238
3685
  </section>
2239
- `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.editorial-runtime{display:grid;gap:24px;padding:24px;color:var(--md-sys-color-on-surface, #1b1b1f);background:var(--md-sys-color-surface, #fdf8fd)}.runtime-header,.journey-card,.empty-state,.diagnostics-panel{border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent);border-radius:20px;background:var(--md-sys-color-surface-container-low, #f7f2fa);padding:20px}.diagnostics-panel{display:grid;gap:10px}.diagnostics-panel.warning{border-color:color-mix(in srgb,#b26a00 55%,var(--md-sys-color-outline-variant, #cac4d0));background:color-mix(in srgb,#fff4de 78%,var(--md-sys-color-surface-container-low, #f7f2fa))}.diagnostics-panel.error{border-color:color-mix(in srgb,#b3261e 60%,var(--md-sys-color-outline-variant, #cac4d0));background:color-mix(in srgb,#fde7e9 78%,var(--md-sys-color-surface-container-low, #f7f2fa))}.diagnostics-list{margin:0;padding-left:18px;display:grid;gap:8px}.diagnostics-summary{display:flex;flex-wrap:wrap;gap:8px}.summary-pill{display:inline-flex;align-items:center;min-height:32px;padding:6px 10px;border-radius:999px;font-size:.85rem;border:1px solid transparent;background:color-mix(in srgb,var(--md-sys-color-surface, #fff) 85%,transparent)}.summary-pill.error{border-color:color-mix(in srgb,#b3261e 45%,transparent)}.summary-pill.warning{border-color:color-mix(in srgb,#b26a00 45%,transparent)}.summary-pill.info{border-color:color-mix(in srgb,#00639b 45%,transparent)}.status-badge{display:inline-flex;align-items:center;justify-content:center;min-width:22px;min-height:22px;padding:0 6px;border-radius:999px;font-size:.75rem;font-weight:700;background:var(--md-sys-color-surface, #fff)}.status-badge.error{color:#8c1d18;background:#fde7e9}.status-badge.warning{color:#7a4b00;background:#fff4de}.diagnostics-details summary{cursor:pointer;font-weight:600}.diagnostic-group{display:grid;gap:8px;padding:12px 0}.diagnostic-group.global{border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent);margin-bottom:12px}.step-panel.error{border-left:4px solid #b3261e}.step-panel.warning{border-left:4px solid #b26a00}.step-diagnostics{display:grid;gap:8px;padding:14px 16px;border-radius:16px}.step-diagnostics.error{background:#fde7e9;color:#5b1210}.step-diagnostics.warning{background:#fff4de;color:#6b4300}.step-diagnostics.global{background:#fde7e9;color:#5b1210;border:1px solid color-mix(in srgb,#b3261e 35%,transparent)}.diagnostics-list.contextual{padding-left:16px}.diagnostic-location{display:block;margin-top:4px;font-size:.82rem;opacity:.85}.step-blocking-note{font-size:.9rem;color:#8c1d18}.eyebrow{margin:0 0 8px;text-transform:uppercase;letter-spacing:.08em;font-size:.75rem;color:var(--md-sys-color-primary, #6750a4);font-weight:700}.runtime-state-pill{justify-self:start;display:inline-flex;align-items:center;min-height:30px;padding:4px 10px;border-radius:999px;font-size:.8rem;font-weight:700;background:color-mix(in srgb,var(--md-sys-color-surface, #fff) 88%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent)}.runtime-state-pill[data-mode=warning]{color:#7a4b00;background:#fff4de}.runtime-state-pill[data-mode=degraded]{color:#8c1d18;background:#fde7e9}.runtime-state-pill[data-mode=blocked]{color:#8c1d18;background:#fde7e9;border-color:color-mix(in srgb,#b3261e 55%,transparent)}h1,h2,h3,p{margin:0}.runtime-header,.journey-card,.journey-header,.step-panel{display:grid;gap:12px}.description,.journey-header p,.step-header p,.step-counter,.empty-state p{color:var(--md-sys-color-on-surface-variant, #49454f)}.journey-tabs,.steps-nav,.step-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center}.steps-nav{list-style:none;padding:0;margin:0}.journey-tab,.step-chip,.step-actions button{display:inline-flex;align-items:center;justify-content:center;min-height:42px;padding:10px 12px;border-radius:999px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 75%,transparent);background:var(--md-sys-color-surface, #fff);color:inherit;cursor:pointer}.journey-tab.active,.step-chip.active{background:var(--md-sys-color-primary, #6750a4);color:var(--md-sys-color-on-primary, #fff)}.step-header{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between}.block-stack{display:grid;gap:16px}.step-actions button[disabled]{opacity:.5;cursor:not-allowed}\n"] }]
3686
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block}.editorial-runtime{display:grid;gap:24px;padding:var(--editorial-page-padding, 24px);color:var(--editorial-text-primary, var(--md-sys-color-on-surface, #1b1b1f));background:var(--editorial-page-background, var(--md-sys-color-surface, #fdf8fd));font-family:var(--editorial-body-font-family, inherit)}.runtime-header,.journey-card,.empty-state,.diagnostics-panel{border:var(--editorial-shell-border-width, 1px) solid color-mix(in srgb,var(--editorial-border-color, var(--md-sys-color-outline-variant, #cac4d0)) 70%,transparent);border-radius:var(--editorial-shell-radius, 20px);background:var(--editorial-surface-secondary, var(--md-sys-color-surface-container-low, #f7f2fa));padding:var(--editorial-shell-padding, 20px);box-shadow:var(--editorial-shell-shadow, none)}.diagnostics-panel{display:grid;gap:10px}.diagnostics-panel.warning{border-color:color-mix(in srgb,#b26a00 55%,var(--md-sys-color-outline-variant, #cac4d0));background:color-mix(in srgb,#fff4de 78%,var(--md-sys-color-surface-container-low, #f7f2fa))}.diagnostics-panel.error{border-color:color-mix(in srgb,#b3261e 60%,var(--md-sys-color-outline-variant, #cac4d0));background:color-mix(in srgb,#fde7e9 78%,var(--md-sys-color-surface-container-low, #f7f2fa))}.diagnostics-list{margin:0;padding-left:18px;display:grid;gap:8px}.diagnostics-summary{display:flex;flex-wrap:wrap;gap:8px}.summary-pill{display:inline-flex;align-items:center;min-height:32px;padding:6px 10px;border-radius:999px;font-size:.85rem;border:1px solid transparent;background:color-mix(in srgb,var(--md-sys-color-surface, #fff) 85%,transparent)}.summary-pill.error{border-color:color-mix(in srgb,#b3261e 45%,transparent)}.summary-pill.warning{border-color:color-mix(in srgb,#b26a00 45%,transparent)}.summary-pill.info{border-color:color-mix(in srgb,#00639b 45%,transparent)}.status-badge{display:inline-flex;align-items:center;justify-content:center;min-width:22px;min-height:22px;padding:0 6px;border-radius:999px;font-size:.75rem;font-weight:700;background:var(--md-sys-color-surface, #fff)}.status-badge.error{color:#8c1d18;background:#fde7e9}.status-badge.warning{color:#7a4b00;background:#fff4de}.diagnostics-details summary{cursor:pointer;font-weight:600}.diagnostic-group{display:grid;gap:8px;padding:12px 0}.diagnostic-group.global{border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 65%,transparent);margin-bottom:12px}.step-panel.error{border-left:4px solid #b3261e}.step-panel.warning{border-left:4px solid #b26a00}.step-diagnostics{display:grid;gap:8px;padding:14px 16px;border-radius:16px}.step-diagnostics.error{background:#fde7e9;color:#5b1210}.step-diagnostics.warning{background:#fff4de;color:#6b4300}.step-diagnostics.global{background:#fde7e9;color:#5b1210;border:1px solid color-mix(in srgb,#b3261e 35%,transparent)}.diagnostics-list.contextual{padding-left:16px}.diagnostic-location{display:block;margin-top:4px;font-size:.82rem;opacity:.85}.step-blocking-note{font-size:.9rem;color:#8c1d18}.eyebrow{margin:0 0 8px;text-transform:uppercase;letter-spacing:.08em;font-size:var(--editorial-caption-size, .75rem);color:var(--editorial-accent, var(--md-sys-color-primary, #6750a4));font-weight:700}.runtime-state-pill{justify-self:start;display:inline-flex;align-items:center;min-height:30px;padding:4px 10px;border-radius:999px;font-size:.8rem;font-weight:700;background:color-mix(in srgb,var(--md-sys-color-surface, #fff) 88%,transparent);border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant, #cac4d0) 70%,transparent)}.runtime-state-pill[data-mode=warning]{color:#7a4b00;background:#fff4de}.runtime-state-pill[data-mode=degraded]{color:#8c1d18;background:#fde7e9}.runtime-state-pill[data-mode=blocked]{color:#8c1d18;background:#fde7e9;border-color:color-mix(in srgb,#b3261e 55%,transparent)}h1,h2,h3,p{margin:0}h1{font-size:var(--editorial-hero-title-size, 2rem);line-height:1.1}.step-header h3{font-size:var(--editorial-step-title-size, 1.25rem);line-height:1.2}.runtime-header,.journey-card,.journey-header,.step-panel{display:grid;gap:12px}.editorial-runtime[data-shell-variant=sidebar-journey] .journey-card,.orientation-vertical .journey-card{grid-template-columns:minmax(220px,280px) minmax(0,1fr);align-items:start}.description,.journey-header p,.step-header p,.step-counter,.empty-state p{font-size:var(--editorial-body-size, 1rem);color:var(--editorial-text-secondary, var(--md-sys-color-on-surface-variant, #49454f))}.journey-tabs,.step-actions{display:flex;flex-wrap:wrap;gap:10px;align-items:center}.journey-tab,.step-actions button{display:inline-flex;align-items:center;justify-content:center;min-height:42px;padding:10px 12px;border-radius:var(--editorial-button-radius, 999px);border:1px solid color-mix(in srgb,var(--editorial-border-color, var(--md-sys-color-outline-variant, #cac4d0)) 75%,transparent);background:var(--editorial-surface-primary, var(--md-sys-color-surface, #fff));color:inherit;box-shadow:var(--editorial-card-shadow, none);cursor:pointer}.journey-tab.active,.step-actions button.primary{background:var(--editorial-cta-primary, var(--editorial-accent, var(--md-sys-color-primary, #6750a4)));color:var(--editorial-cta-primary-text, var(--editorial-accent-contrast, var(--md-sys-color-on-primary, #fff)));border-color:transparent}.step-actions button.secondary{color:var(--editorial-cta-primary, var(--editorial-accent, var(--md-sys-color-primary, #6750a4)))}.step-header{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between}.block-stack{display:grid;gap:var(--editorial-block-gap, 16px)}.step-actions button[disabled]{opacity:.5;cursor:not-allowed}.density-compact{--editorial-page-padding: 16px;--editorial-shell-padding: 16px;--editorial-block-gap: 12px}.density-comfortable{--editorial-page-padding: 24px;--editorial-shell-padding: 20px;--editorial-block-gap: 16px}.density-relaxed{--editorial-page-padding: 32px;--editorial-shell-padding: 28px;--editorial-block-gap: 20px}\n"] }]
2240
3687
  }], ctorParameters: () => [], propDecorators: { solution: [{ type: i0.Input, args: [{ isSignal: true, alias: "solution", required: false }] }], instance: [{ type: i0.Input, args: [{ isSignal: true, alias: "instance", required: false }] }], runtimeContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "runtimeContext", required: false }] }], hostConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "hostConfig", required: false }] }], snapshotChange: [{ type: i0.Output, args: ["snapshotChange"] }], fallbackChange: [{ type: i0.Output, args: ["fallbackChange"] }], operationalEvent: [{ type: i0.Output, args: ["operationalEvent"] }] } });
2241
3688
  function buildSnapshotSignature(snapshot) {
2242
- return [
2243
- snapshot.solutionId ?? '',
2244
- snapshot.instanceId ?? '',
2245
- snapshot.journeys.length,
2246
- snapshot.diagnostics.items.length,
2247
- snapshot.diagnostics.hasErrors,
2248
- snapshot.diagnostics.hasWarnings,
2249
- ].join(':');
3689
+ return stableSerializeForSignature(snapshot);
3690
+ }
3691
+ function stableSerializeForSignature(value) {
3692
+ if (value == null) {
3693
+ return String(value);
3694
+ }
3695
+ if (typeof value === 'string'
3696
+ || typeof value === 'number'
3697
+ || typeof value === 'boolean') {
3698
+ return JSON.stringify(value);
3699
+ }
3700
+ if (Array.isArray(value)) {
3701
+ return `[${value.map((item) => stableSerializeForSignature(item)).join(',')}]`;
3702
+ }
3703
+ if (typeof value === 'object') {
3704
+ const entries = Object.entries(value)
3705
+ .sort(([left], [right]) => left.localeCompare(right))
3706
+ .map(([key, entryValue]) => `${JSON.stringify(key)}:${stableSerializeForSignature(entryValue)}`);
3707
+ return `{${entries.join(',')}}`;
3708
+ }
3709
+ return JSON.stringify(String(value));
2250
3710
  }
2251
3711
  function dedupeDiagnostics(items) {
2252
3712
  const seen = new Set();
@@ -2357,6 +3817,192 @@ function provideEditorialDynamicFormAdapter(options) {
2357
3817
  return provideEditorialDataBlockAdapter(createEditorialDynamicFormAdapter(options));
2358
3818
  }
2359
3819
 
3820
+ const PRAXIS_EDITORIAL_FORMS_EN_US = {
3821
+ 'praxis.editorialForms.runtime.diagnostics.title': 'Runtime diagnostics',
3822
+ 'praxis.editorialForms.runtime.diagnostics.severitySummary': 'Severity summary',
3823
+ 'praxis.editorialForms.runtime.diagnostics.globalErrors': 'Global runtime errors',
3824
+ 'praxis.editorialForms.runtime.diagnostics.details': 'View details ({count})',
3825
+ 'praxis.editorialForms.runtime.journeys.ariaLabel': 'Editorial journeys',
3826
+ 'praxis.editorialForms.runtime.journeys.errors': 'Journey has errors',
3827
+ 'praxis.editorialForms.runtime.journeys.warnings': 'Journey has warnings',
3828
+ 'praxis.editorialForms.runtime.step.counter': 'Step {current} of {total}',
3829
+ 'praxis.editorialForms.runtime.step.statusTitle': 'Current step status',
3830
+ 'praxis.editorialForms.runtime.step.globalErrorTitle': 'Global runtime error',
3831
+ 'praxis.editorialForms.runtime.actions.previous': 'Previous step',
3832
+ 'praxis.editorialForms.runtime.actions.next': 'Next step',
3833
+ 'praxis.editorialForms.runtime.actions.nextBlocked': 'Fix the errors to continue',
3834
+ 'praxis.editorialForms.runtime.empty.noJourneyTitle': 'Editorial runtime without journey',
3835
+ 'praxis.editorialForms.runtime.empty.noJourneyDescription': 'No editorial journey was resolved for the current state.',
3836
+ 'praxis.editorialForms.runtime.empty.noSolutionTitle': 'Empty editorial runtime',
3837
+ 'praxis.editorialForms.runtime.empty.noSolutionDescription': 'Provide an editorial solution or instance to materialize the journey.',
3838
+ 'praxis.editorialForms.runtime.fallback.blocked': 'Runtime blocked',
3839
+ 'praxis.editorialForms.runtime.fallback.degraded': 'Runtime degraded',
3840
+ 'praxis.editorialForms.runtime.fallback.warning': 'Runtime warning',
3841
+ 'praxis.editorialForms.runtime.fallback.healthy': 'Runtime healthy',
3842
+ 'praxis.editorialForms.runtime.navigation.globalBlocked': 'Forward navigation was blocked because the runtime has a global error that must be fixed before continuing.',
3843
+ 'praxis.editorialForms.runtime.navigation.stepBlocked': 'Forward navigation was blocked because the current step has a structural error.',
3844
+ 'praxis.editorialForms.runtime.diagnostics.severity.error': 'Error',
3845
+ 'praxis.editorialForms.runtime.diagnostics.severity.warning': 'Warning',
3846
+ 'praxis.editorialForms.runtime.diagnostics.severity.info': 'Info',
3847
+ 'praxis.editorialForms.runtime.diagnostics.errorsCount': 'Errors: {count}',
3848
+ 'praxis.editorialForms.runtime.diagnostics.warningsCount': 'Warnings: {count}',
3849
+ 'praxis.editorialForms.runtime.diagnostics.infoCount': 'Info: {count}',
3850
+ 'praxis.editorialForms.runtime.diagnostics.message.blocked': 'Blocking inconsistencies prevent the editorial flow from progressing safely.',
3851
+ 'praxis.editorialForms.runtime.diagnostics.message.degraded': 'The runtime is operating in a degraded mode and requires operational attention.',
3852
+ 'praxis.editorialForms.runtime.diagnostics.message.error': 'There are inconsistencies that may compromise the editorial experience.',
3853
+ 'praxis.editorialForms.runtime.diagnostics.message.warning': 'There are operational warnings to review for this editorial instance.',
3854
+ 'praxis.editorialForms.runtime.scope.global': 'Scope: global runtime',
3855
+ 'praxis.editorialForms.runtime.scope.journey': 'Journey',
3856
+ 'praxis.editorialForms.runtime.scope.step': 'Step',
3857
+ 'praxis.editorialForms.runtime.scope.block': 'Block',
3858
+ 'praxis.editorialForms.runtime.scope.path': 'Path',
3859
+ 'praxis.editorialForms.stepper.ariaLabel': 'Journey steps',
3860
+ 'praxis.editorialForms.stepper.state.completed': 'completed',
3861
+ 'praxis.editorialForms.stepper.state.active': 'current step',
3862
+ 'praxis.editorialForms.stepper.state.blocked': 'blocked',
3863
+ 'praxis.editorialForms.stepper.state.pending': 'pending',
3864
+ 'praxis.editorialForms.selection.state.selected': 'selected',
3865
+ 'praxis.editorialForms.selection.state.unselected': 'not selected',
3866
+ 'praxis.editorialForms.selection.group.label': 'Selection group',
3867
+ 'praxis.editorialForms.review.empty': '-',
3868
+ 'praxis.editorialForms.review.boolean.true': 'Yes',
3869
+ 'praxis.editorialForms.review.boolean.false': 'No',
3870
+ 'praxis.editorialForms.dataCollection.loadingTitle': 'Preparing data collection',
3871
+ 'praxis.editorialForms.dataCollection.unavailableTitle': 'Data collection unavailable',
3872
+ 'praxis.editorialForms.dataCollection.error.incompatibleTitle': 'Incompatible adapter',
3873
+ 'praxis.editorialForms.dataCollection.error.missingConfigTitle': 'Missing data collection configuration',
3874
+ 'praxis.editorialForms.dataCollection.error.incompleteAdapterTitle': 'Incomplete adapter',
3875
+ 'praxis.editorialForms.dataCollection.error.loadFailureTitle': 'Failed to load engine',
3876
+ 'praxis.editorialForms.dataCollection.error.unresolvedComponentTitle': 'Component not resolved',
3877
+ 'praxis.editorialForms.dataCollection.error.invalidComponentTitle': 'Incompatible component',
3878
+ 'praxis.editorialForms.dataCollection.fallback.invalid': 'Block "{formBlockId}" was materialized with an invalid state. Review formBlockId, formConfigRef and inherited editorial configuration.',
3879
+ 'praxis.editorialForms.dataCollection.fallback.missingConfig': 'Block "{formBlockId}" did not find data collection configuration. Lookup key checked: {lookupKey}.',
3880
+ 'praxis.editorialForms.dataCollection.fallback.incompatible': 'Block "{formBlockId}" found registered adapters ({adapterIds}), but none declared compatibility for this data collection.',
3881
+ 'praxis.editorialForms.dataCollection.fallback.missingAdapter': 'Block "{formBlockId}" did not find data collection configuration nor a registered adapter. Check the host provider and editorial FormConfig materialization.',
3882
+ 'praxis.editorialForms.dataCollection.fallback.adapterWithoutConfig': 'Block "{formBlockId}" found an adapter, but did not find FormConfig at {lookupKey}.',
3883
+ 'praxis.editorialForms.dataCollection.fallback.unresolvedEngine': 'Configuration exists for "{formBlockId}" ({source}), but no data collection adapter was registered to materialize the engine.',
3884
+ 'praxis.editorialForms.dataCollection.error.incompatibleMessage': 'No registered adapter accepted block "{formBlockId}".',
3885
+ 'praxis.editorialForms.dataCollection.error.availableAdapters': 'Available adapters: {adapterIds}.',
3886
+ 'praxis.editorialForms.dataCollection.error.missingConfigMessage': 'Block "{formBlockId}" has no resolved FormConfig for the data collection engine.',
3887
+ 'praxis.editorialForms.dataCollection.error.lookupSource': 'Lookup source: {lookupKey}.',
3888
+ 'praxis.editorialForms.dataCollection.error.adapterRegistrationHint': 'Register a compatible component or implement resolveComponent().',
3889
+ 'praxis.editorialForms.dataCollection.error.incompleteAdapterMessage': 'Adapter "{adapterName}" did not expose a data collection component.',
3890
+ 'praxis.editorialForms.dataCollection.loadingMessage': 'Loading the data collection engine for "{formBlockId}"...',
3891
+ 'praxis.editorialForms.dataCollection.error.loadFailureMessage': 'Adapter "{adapterName}" failed while preparing block "{formBlockId}".',
3892
+ 'praxis.editorialForms.dataCollection.error.loadFailureDetails': 'Validate the optional host provider and the availability of a compatible component.',
3893
+ 'praxis.editorialForms.dataCollection.error.unresolvedComponentMessage': 'Adapter "{adapterName}" did not return a component for block "{formBlockId}".',
3894
+ 'praxis.editorialForms.dataCollection.error.unresolvedComponentDetails': 'Implement component or resolveComponent() with a compatible Angular component.',
3895
+ 'praxis.editorialForms.dataCollection.error.invalidComponentMessage': 'Adapter "{adapterName}" returned an incompatible component for "{formBlockId}".',
3896
+ };
3897
+
3898
+ const PRAXIS_EDITORIAL_FORMS_PT_BR = {
3899
+ 'praxis.editorialForms.runtime.diagnostics.title': 'Diagnosticos do runtime',
3900
+ 'praxis.editorialForms.runtime.diagnostics.severitySummary': 'Resumo de severidade',
3901
+ 'praxis.editorialForms.runtime.diagnostics.globalErrors': 'Erros globais do runtime',
3902
+ 'praxis.editorialForms.runtime.diagnostics.details': 'Ver detalhes ({count})',
3903
+ 'praxis.editorialForms.runtime.journeys.ariaLabel': 'Jornadas editoriais',
3904
+ 'praxis.editorialForms.runtime.journeys.errors': 'Jornada com erros',
3905
+ 'praxis.editorialForms.runtime.journeys.warnings': 'Jornada com avisos',
3906
+ 'praxis.editorialForms.runtime.step.counter': 'Etapa {current} de {total}',
3907
+ 'praxis.editorialForms.runtime.step.statusTitle': 'Situacao desta etapa',
3908
+ 'praxis.editorialForms.runtime.step.globalErrorTitle': 'Erro global do runtime',
3909
+ 'praxis.editorialForms.runtime.actions.previous': 'Etapa anterior',
3910
+ 'praxis.editorialForms.runtime.actions.next': 'Proxima etapa',
3911
+ 'praxis.editorialForms.runtime.actions.nextBlocked': 'Corrija os erros para avancar',
3912
+ 'praxis.editorialForms.runtime.empty.noJourneyTitle': 'Editorial runtime sem jornada',
3913
+ 'praxis.editorialForms.runtime.empty.noJourneyDescription': 'Nenhuma jornada editorial foi resolvida para o estado atual.',
3914
+ 'praxis.editorialForms.runtime.empty.noSolutionTitle': 'Editorial runtime vazio',
3915
+ 'praxis.editorialForms.runtime.empty.noSolutionDescription': 'Forneca uma solution ou instance editorial para materializar a jornada.',
3916
+ 'praxis.editorialForms.runtime.fallback.blocked': 'Runtime bloqueado',
3917
+ 'praxis.editorialForms.runtime.fallback.degraded': 'Runtime degradado',
3918
+ 'praxis.editorialForms.runtime.fallback.warning': 'Runtime com aviso',
3919
+ 'praxis.editorialForms.runtime.fallback.healthy': 'Runtime saudavel',
3920
+ 'praxis.editorialForms.runtime.navigation.globalBlocked': 'A navegacao de avanço foi bloqueada porque o runtime possui erro global que precisa ser corrigido antes de continuar.',
3921
+ 'praxis.editorialForms.runtime.navigation.stepBlocked': 'A navegacao de avanço foi bloqueada porque a etapa atual possui erro estrutural.',
3922
+ 'praxis.editorialForms.runtime.diagnostics.severity.error': 'Erro',
3923
+ 'praxis.editorialForms.runtime.diagnostics.severity.warning': 'Aviso',
3924
+ 'praxis.editorialForms.runtime.diagnostics.severity.info': 'Info',
3925
+ 'praxis.editorialForms.runtime.diagnostics.errorsCount': 'Erros: {count}',
3926
+ 'praxis.editorialForms.runtime.diagnostics.warningsCount': 'Avisos: {count}',
3927
+ 'praxis.editorialForms.runtime.diagnostics.infoCount': 'Infos: {count}',
3928
+ 'praxis.editorialForms.runtime.diagnostics.message.blocked': 'Existem inconsistencias bloqueadoras que impedem a progressao segura do fluxo editorial.',
3929
+ 'praxis.editorialForms.runtime.diagnostics.message.degraded': 'O runtime esta operando de forma degradada e requer atencao operacional.',
3930
+ 'praxis.editorialForms.runtime.diagnostics.message.error': 'Existem inconsistencias que podem comprometer a experiencia editorial.',
3931
+ 'praxis.editorialForms.runtime.diagnostics.message.warning': 'Existem avisos operacionais para revisar nesta instancia editorial.',
3932
+ 'praxis.editorialForms.runtime.scope.global': 'Escopo: runtime global',
3933
+ 'praxis.editorialForms.runtime.scope.journey': 'Jornada',
3934
+ 'praxis.editorialForms.runtime.scope.step': 'Etapa',
3935
+ 'praxis.editorialForms.runtime.scope.block': 'Bloco',
3936
+ 'praxis.editorialForms.runtime.scope.path': 'Path',
3937
+ 'praxis.editorialForms.stepper.ariaLabel': 'Etapas da jornada',
3938
+ 'praxis.editorialForms.stepper.state.completed': 'concluida',
3939
+ 'praxis.editorialForms.stepper.state.active': 'etapa atual',
3940
+ 'praxis.editorialForms.stepper.state.blocked': 'bloqueada',
3941
+ 'praxis.editorialForms.stepper.state.pending': 'pendente',
3942
+ 'praxis.editorialForms.selection.state.selected': 'selecionado',
3943
+ 'praxis.editorialForms.selection.state.unselected': 'nao selecionado',
3944
+ 'praxis.editorialForms.selection.group.label': 'Grupo de selecao',
3945
+ 'praxis.editorialForms.review.empty': '-',
3946
+ 'praxis.editorialForms.review.boolean.true': 'Sim',
3947
+ 'praxis.editorialForms.review.boolean.false': 'Nao',
3948
+ 'praxis.editorialForms.dataCollection.loadingTitle': 'Preparando coleta',
3949
+ 'praxis.editorialForms.dataCollection.unavailableTitle': 'Coleta nao disponivel',
3950
+ 'praxis.editorialForms.dataCollection.error.incompatibleTitle': 'Adaptador incompatível',
3951
+ 'praxis.editorialForms.dataCollection.error.missingConfigTitle': 'Configuracao de coleta ausente',
3952
+ 'praxis.editorialForms.dataCollection.error.incompleteAdapterTitle': 'Adaptador incompleto',
3953
+ 'praxis.editorialForms.dataCollection.error.loadFailureTitle': 'Falha ao carregar a engine',
3954
+ 'praxis.editorialForms.dataCollection.error.unresolvedComponentTitle': 'Componente nao resolvido',
3955
+ 'praxis.editorialForms.dataCollection.error.invalidComponentTitle': 'Componente incompatível',
3956
+ 'praxis.editorialForms.dataCollection.fallback.invalid': 'O bloco "{formBlockId}" foi materializado com estado invalido. Revise formBlockId, formConfigRef e a configuracao editorial herdada.',
3957
+ 'praxis.editorialForms.dataCollection.fallback.missingConfig': 'O bloco "{formBlockId}" nao encontrou configuracao de coleta. Chave consultada: {lookupKey}.',
3958
+ 'praxis.editorialForms.dataCollection.fallback.incompatible': 'O bloco "{formBlockId}" encontrou adapters registrados ({adapterIds}), mas nenhum declarou compatibilidade para esta coleta.',
3959
+ 'praxis.editorialForms.dataCollection.fallback.missingAdapter': 'O bloco "{formBlockId}" nao encontrou configuracao de coleta nem adaptador registrado. Verifique o provider do host e a materializacao do FormConfig editorial.',
3960
+ 'praxis.editorialForms.dataCollection.fallback.adapterWithoutConfig': 'O bloco "{formBlockId}" encontrou um adaptador, mas nao encontrou FormConfig em {lookupKey}.',
3961
+ 'praxis.editorialForms.dataCollection.fallback.unresolvedEngine': 'Existe configuracao para "{formBlockId}" ({source}), mas nenhum adaptador de coleta foi registrado para materializar a engine.',
3962
+ 'praxis.editorialForms.dataCollection.error.incompatibleMessage': 'Nenhum adaptador registrado aceitou o bloco "{formBlockId}".',
3963
+ 'praxis.editorialForms.dataCollection.error.availableAdapters': 'Adapters disponiveis: {adapterIds}.',
3964
+ 'praxis.editorialForms.dataCollection.error.missingConfigMessage': 'O bloco "{formBlockId}" nao possui FormConfig resolvido para a engine de coleta.',
3965
+ 'praxis.editorialForms.dataCollection.error.lookupSource': 'Origem consultada: {lookupKey}.',
3966
+ 'praxis.editorialForms.dataCollection.error.adapterRegistrationHint': 'Registre um componente compatível ou implemente resolveComponent().',
3967
+ 'praxis.editorialForms.dataCollection.error.incompleteAdapterMessage': 'O adaptador "{adapterName}" nao expôs um componente de coleta.',
3968
+ 'praxis.editorialForms.dataCollection.loadingMessage': 'Carregando a engine de coleta para "{formBlockId}"...',
3969
+ 'praxis.editorialForms.dataCollection.error.loadFailureMessage': 'O adaptador "{adapterName}" falhou ao preparar a coleta do bloco "{formBlockId}".',
3970
+ 'praxis.editorialForms.dataCollection.error.loadFailureDetails': 'Valide o provider opcional do host e a disponibilidade do componente compatível.',
3971
+ 'praxis.editorialForms.dataCollection.error.unresolvedComponentMessage': 'O adaptador "{adapterName}" nao retornou um componente para o bloco "{formBlockId}".',
3972
+ 'praxis.editorialForms.dataCollection.error.unresolvedComponentDetails': 'Implemente component ou resolveComponent() com um componente Angular compatível.',
3973
+ 'praxis.editorialForms.dataCollection.error.invalidComponentMessage': 'O adaptador "{adapterName}" retornou um componente incompatível para "{formBlockId}".',
3974
+ };
3975
+
3976
+ function createPraxisEditorialFormsI18nConfig(options = {}) {
3977
+ const dictionaries = {
3978
+ 'pt-BR': {
3979
+ ...PRAXIS_EDITORIAL_FORMS_PT_BR,
3980
+ ...(options.dictionaries?.['pt-BR'] ?? {}),
3981
+ },
3982
+ 'en-US': {
3983
+ ...PRAXIS_EDITORIAL_FORMS_EN_US,
3984
+ ...(options.dictionaries?.['en-US'] ?? {}),
3985
+ },
3986
+ };
3987
+ for (const [locale, dictionary] of Object.entries(options.dictionaries ?? {})) {
3988
+ if (locale === 'pt-BR' || locale === 'en-US') {
3989
+ continue;
3990
+ }
3991
+ dictionaries[locale] = {
3992
+ ...(dictionaries[locale] ?? {}),
3993
+ ...dictionary,
3994
+ };
3995
+ }
3996
+ return {
3997
+ locale: options.locale,
3998
+ fallbackLocale: options.fallbackLocale ?? 'pt-BR',
3999
+ dictionaries,
4000
+ };
4001
+ }
4002
+ function providePraxisEditorialFormsI18n(options = {}) {
4003
+ return providePraxisI18n(createPraxisEditorialFormsI18nConfig(options));
4004
+ }
4005
+
2360
4006
  class HarnessDataEngineComponent {
2361
4007
  config;
2362
4008
  formId;
@@ -2607,5 +4253,5 @@ function getHarnessDataEngineComponent() {
2607
4253
  * Generated bundle index. Do not edit.
2608
4254
  */
2609
4255
 
2610
- export { DEFAULT_EDITORIAL_RUNTIME_HOST_CONFIG, EDITORIAL_DATA_BLOCK_ADAPTER, EditorialBlockRendererComponent, EditorialDataBlockAdapterRegistry, EditorialDataCollectionBlockOutletComponent, EditorialFormRuntimeComponent, EditorialRuntimeState, HarnessDataEngineComponent, createEditorialDynamicFormAdapter, createEditorialRuntimeHarnessCatalog, deriveRuntimeFallbackState, getHarnessDataEngineComponent, getValueAtPath, getVisibleBlocks, isBlockVisible, matchesVisibilityRule, provideEditorialDataBlockAdapter, provideEditorialDynamicFormAdapter, providePraxisEditorialForms, resolveActiveJourney, resolveActiveStep, resolveEditorialDataBlockAdapter, resolveEditorialDataBlockFormConfig, resolveEditorialDataBlockFormConfigDetails, resolveEditorialRuntimeSnapshot };
4256
+ export { DEFAULT_EDITORIAL_RUNTIME_HOST_CONFIG, EDITORIAL_DATA_BLOCK_ADAPTER, EditorialBlockRendererComponent, EditorialDataBlockAdapterRegistry, EditorialDataCollectionBlockOutletComponent, EditorialFormRuntimeComponent, EditorialIntroHeroBlockComponent, EditorialReviewSectionsBlockComponent, EditorialRuntimeState, EditorialSelectionCardsBlockComponent, EditorialStepperComponent, EditorialSuccessPanelBlockComponent, HarnessDataEngineComponent, PRAXIS_EDITORIAL_FORMS_EN_US, PRAXIS_EDITORIAL_FORMS_PT_BR, buildRuntimeCssVars, buildRuntimeLayoutCss, createEditorialDynamicFormAdapter, createEditorialRuntimeHarnessCatalog, createPraxisEditorialFormsI18nConfig, deriveRuntimeFallbackState, getHarnessDataEngineComponent, getStepDisplayState, getValueAtPath, getVisibleBlocks, isBlockVisible, matchesVisibilityRule, provideEditorialDataBlockAdapter, provideEditorialDynamicFormAdapter, providePraxisEditorialForms, providePraxisEditorialFormsI18n, resolveActiveJourney, resolveActiveStep, resolveDensity, resolveEditorialDataBlockAdapter, resolveEditorialDataBlockFormConfig, resolveEditorialDataBlockFormConfigDetails, resolveEditorialRuntimeSnapshot, resolveRuntimeOrientation, resolveShellVariant };
2611
4257
  //# sourceMappingURL=praxisui-editorial-forms.mjs.map