@praxisui/dynamic-form 3.0.0-beta.5 → 3.0.0-beta.7

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.
@@ -22,7 +22,7 @@ import { MatBadgeModule } from '@angular/material/badge';
22
22
  import { firstValueFrom, BehaviorSubject, Subject, debounceTime as debounceTime$1, takeUntil as takeUntil$1 } from 'rxjs';
23
23
  import { take, takeUntil, debounceTime, finalize, map } from 'rxjs/operators';
24
24
  import * as i1$2 from '@praxisui/core';
25
- import { PraxisIconDirective, RULE_PROPERTY_SCHEMA, FIELD_METADATA_CAPABILITIES, deepMerge, createDefaultFormConfig, normalizeFormConfig as normalizeFormConfig$1, ensureIds, ASYNC_CONFIG_STORAGE, migrateFormLayoutRule, LoggerService, createCorporateLoggerConfig, ConsoleLoggerSink, ResourceQuickConnectComponent, mapFieldDefinitionsToMetadata, syncWithServerMetadata, PRAXIS_LOADING_CTX, normalizeControlTypeKey, resolveSpan, resolveOffset, resolveOrder, resolveHidden, buildSchemaId, fetchWithETag, resolveControlTypeAlias, getTextTransformer, MemoryCacheAdapter, LocalStorageCacheAdapter, SchemaMetadataClient, CONNECTION_STORAGE, PRAXIS_LOADING_RENDERER, FORM_HOOKS_PRESETS, DynamicWidgetLoaderDirective, EmptyStateCardComponent, isValidFormConfig, ComponentMetadataRegistry, FieldControlType, GLOBAL_ACTION_CATALOG, GLOBAL_ACTION_SPEC_CATALOG, getGlobalActionCatalog, PRAXIS_GLOBAL_ACTION_CATALOG, getGlobalActionUiSchema } from '@praxisui/core';
25
+ import { PraxisIconDirective, RULE_PROPERTY_SCHEMA, FIELD_METADATA_CAPABILITIES, deepMerge, createDefaultFormConfig, normalizeFormConfig as normalizeFormConfig$1, ensureIds, ASYNC_CONFIG_STORAGE, migrateFormLayoutRule, LoggerService, createCorporateLoggerConfig, ConsoleLoggerSink, ResourceQuickConnectComponent, mapFieldDefinitionsToMetadata, syncWithServerMetadata, PRAXIS_LOADING_CTX, normalizeControlTypeKey, resolveSpan, resolveOffset, resolveOrder, resolveHidden, buildSchemaId, fetchWithETag, resolveControlTypeAlias, getTextTransformer, MemoryCacheAdapter, LocalStorageCacheAdapter, SchemaMetadataClient, CONNECTION_STORAGE, PRAXIS_LOADING_RENDERER, FORM_HOOKS_PRESETS, DynamicWidgetLoaderDirective, EmptyStateCardComponent, isValidFormConfig, ComponentMetadataRegistry, FieldControlType, GLOBAL_ACTION_CATALOG, PraxisI18nService, GLOBAL_ACTION_SPEC_CATALOG, getGlobalActionCatalog, PRAXIS_GLOBAL_ACTION_CATALOG, SURFACE_OPEN_I18N_NAMESPACE, getGlobalActionUiSchema, SurfaceOpenActionEditorComponent, providePraxisI18nConfig, SURFACE_OPEN_I18N_CONFIG } from '@praxisui/core';
26
26
  import * as i1 from '@praxisui/dynamic-fields';
27
27
  import { getControlTypeCatalog, ConfirmDialogComponent, DynamicFieldLoaderDirective } from '@praxisui/dynamic-fields';
28
28
  import { BaseAiAdapter, PraxisAiAssistantComponent } from '@praxisui/ai';
@@ -846,7 +846,7 @@ function generateRulePropertyWhenFalseCapabilities(targetType, properties) {
846
846
  return result;
847
847
  }
848
848
  const FORM_AI_CAPABILITIES = {
849
- version: 'v1.8', // Adds a semantic before-actions editorial slot.
849
+ version: 'v1.9', // Adds section header actions and richer section authoring affordances.
850
850
  enums: ENUMS$1,
851
851
  targets: [
852
852
  'praxis-dynamic-form',
@@ -1298,6 +1298,62 @@ const FORM_AI_CAPABILITIES = {
1298
1298
  valueKind: 'string',
1299
1299
  description: 'Texto de tooltip para o cabeçalho da seção.',
1300
1300
  },
1301
+ {
1302
+ path: 'sections[].headerActions',
1303
+ category: 'layout',
1304
+ valueKind: 'array',
1305
+ description: 'Lista de ações iconográficas renderizadas no canto direito do cabeçalho da seção.',
1306
+ safetyNotes: 'Prefira IDs estáveis porque essas ações podem ser alvo de regras e integrações do host.',
1307
+ },
1308
+ {
1309
+ path: 'sections[].headerActions[].id',
1310
+ category: 'layout',
1311
+ valueKind: 'string',
1312
+ description: 'ID estável da ação de cabeçalho da seção.',
1313
+ },
1314
+ {
1315
+ path: 'sections[].headerActions[].label',
1316
+ category: 'layout',
1317
+ valueKind: 'string',
1318
+ description: 'Label acessível usada em tooltip e aria-label da ação.',
1319
+ },
1320
+ {
1321
+ path: 'sections[].headerActions[].icon',
1322
+ category: 'layout',
1323
+ valueKind: 'string',
1324
+ description: 'Ícone renderizado na ação do cabeçalho da seção.',
1325
+ },
1326
+ {
1327
+ path: 'sections[].headerActions[].action',
1328
+ category: 'layout',
1329
+ valueKind: 'string',
1330
+ description: 'Nome opcional da ação emitida no customAction; se ausente, o runtime usa o ID.',
1331
+ },
1332
+ {
1333
+ path: 'sections[].headerActions[].tooltip',
1334
+ category: 'layout',
1335
+ valueKind: 'string',
1336
+ description: 'Tooltip opcional da ação; se ausente, o runtime usa a label.',
1337
+ },
1338
+ {
1339
+ path: 'sections[].headerActions[].color',
1340
+ category: 'appearance',
1341
+ valueKind: 'enum',
1342
+ allowedValues: ['primary', 'accent', 'warn', 'basic'],
1343
+ description: 'Tom visual da ação do cabeçalho da seção.',
1344
+ },
1345
+ {
1346
+ path: 'sections[].headerActions[].visible',
1347
+ category: 'layout',
1348
+ valueKind: 'boolean',
1349
+ description: 'Controla a visibilidade da ação do cabeçalho da seção.',
1350
+ },
1351
+ {
1352
+ path: 'sections[].headerActions[].disabled',
1353
+ category: 'layout',
1354
+ valueKind: 'boolean',
1355
+ description: 'Controla o estado desabilitado da ação do cabeçalho da seção.',
1356
+ },
1301
1357
  {
1302
1358
  path: 'sections[].className',
1303
1359
  category: 'appearance',
@@ -2645,6 +2701,15 @@ const TASK_PRESETS = {
2645
2701
  'sections[].descriptionColor',
2646
2702
  'sections[].headerAlign',
2647
2703
  'sections[].headerTooltip',
2704
+ 'sections[].headerActions',
2705
+ 'sections[].headerActions[].id',
2706
+ 'sections[].headerActions[].label',
2707
+ 'sections[].headerActions[].icon',
2708
+ 'sections[].headerActions[].action',
2709
+ 'sections[].headerActions[].tooltip',
2710
+ 'sections[].headerActions[].color',
2711
+ 'sections[].headerActions[].visible',
2712
+ 'sections[].headerActions[].disabled',
2648
2713
  'sections[].rows[].gap',
2649
2714
  'sections[].rows[].rowGap',
2650
2715
  'sections[].rows[].columns[].fields[]',
@@ -3648,11 +3713,13 @@ function sanitizeRuleEffect(rule) {
3648
3713
  }
3649
3714
  function normalizeTargets$1(rule) {
3650
3715
  const rawTargets = (rule.targets && rule.targets.length ? rule.targets : rule.targetFields) || [];
3651
- const detectedType = rawTargets.some((t) => t?.startsWith('section:')) ? 'section'
3652
- : rawTargets.some((t) => t?.startsWith('action:')) ? 'action'
3653
- : rawTargets.some((t) => t?.startsWith('row:')) ? 'row'
3654
- : rawTargets.some((t) => t?.startsWith('column:')) ? 'column'
3655
- : rule.targetType || 'field';
3716
+ const detectedType = rawTargets.some((t) => isScopedSectionHeaderActionTarget$1(t) || isUnscopedSectionHeaderActionTarget$1(t))
3717
+ ? 'action'
3718
+ : rawTargets.some((t) => t?.startsWith('section:')) ? 'section'
3719
+ : rawTargets.some((t) => t?.startsWith('action:')) ? 'action'
3720
+ : rawTargets.some((t) => t?.startsWith('row:')) ? 'row'
3721
+ : rawTargets.some((t) => t?.startsWith('column:')) ? 'column'
3722
+ : rule.targetType || 'field';
3656
3723
  const targets = rawTargets.map((t) => stripPrefix(t));
3657
3724
  const allowed = ['field', 'section', 'action', 'row', 'column'];
3658
3725
  const explicit = allowed.includes(rule.targetType)
@@ -3664,6 +3731,9 @@ function normalizeTargets$1(rule) {
3664
3731
  };
3665
3732
  }
3666
3733
  function stripPrefix(value) {
3734
+ if (isScopedSectionHeaderActionTarget$1(value) || isUnscopedSectionHeaderActionTarget$1(value)) {
3735
+ return value;
3736
+ }
3667
3737
  if (value?.startsWith('section:'))
3668
3738
  return value.substring('section:'.length);
3669
3739
  if (value?.startsWith('action:'))
@@ -3674,6 +3744,12 @@ function stripPrefix(value) {
3674
3744
  return value.substring('column:'.length);
3675
3745
  return value;
3676
3746
  }
3747
+ function isScopedSectionHeaderActionTarget$1(value) {
3748
+ return !!value && value.startsWith('section:') && value.includes(':header-action:');
3749
+ }
3750
+ function isUnscopedSectionHeaderActionTarget$1(value) {
3751
+ return !!value && value.startsWith('header-action:');
3752
+ }
3677
3753
  function coerceValue(def, value) {
3678
3754
  // null is treated as an explicit "remove override"
3679
3755
  if (value === null) {
@@ -6435,6 +6511,16 @@ class PraxisDynamicForm {
6435
6511
  const props = this.getSectionRuleProps(section);
6436
6512
  return props.headerTooltip ?? section.headerTooltip;
6437
6513
  }
6514
+ getSectionHeaderActions(section) {
6515
+ const props = this.getSectionRuleProps(section);
6516
+ const source = props.headerActions ?? section.headerActions;
6517
+ if (!Array.isArray(source))
6518
+ return [];
6519
+ return source
6520
+ .filter((action) => !!action && typeof action.id === 'string' && !!action.id.trim())
6521
+ .map((action) => this.applySectionHeaderActionOverrides(section, action))
6522
+ .filter((action) => action.visible !== false);
6523
+ }
6438
6524
  getSectionHeaderAlign(section) {
6439
6525
  const props = this.getSectionRuleProps(section);
6440
6526
  return props.headerAlign ?? section.headerAlign;
@@ -6454,6 +6540,100 @@ class PraxisDynamicForm {
6454
6540
  const gap = props.descriptionGapBottom ?? section.descriptionGapBottom;
6455
6541
  return gap ?? null;
6456
6542
  }
6543
+ getSectionHeaderActionColor(action) {
6544
+ const c = String(action.color || '').toLowerCase();
6545
+ switch (c) {
6546
+ case 'primary':
6547
+ return 'primary';
6548
+ case 'accent':
6549
+ case 'secondary':
6550
+ return 'accent';
6551
+ case 'warn':
6552
+ case 'danger':
6553
+ case 'error':
6554
+ return 'warn';
6555
+ default:
6556
+ return undefined;
6557
+ }
6558
+ }
6559
+ getSectionHeaderActionTooltip(action) {
6560
+ return action.tooltip || action.label;
6561
+ }
6562
+ isSectionHeaderActionDisabled(action) {
6563
+ return this.submitting || !!action.disabled || !!action.loading;
6564
+ }
6565
+ getSectionHeaderActionNgClass(action) {
6566
+ const className = action.className;
6567
+ const tone = String(action.color || 'basic').toLowerCase();
6568
+ return {
6569
+ ...(className ? { [className]: true } : {}),
6570
+ [`tone-${tone}`]: true,
6571
+ loading: !!action.loading,
6572
+ };
6573
+ }
6574
+ getSectionHeaderActionStyles(action) {
6575
+ return action.style && Object.keys(action.style).length ? action.style : null;
6576
+ }
6577
+ getSectionHeaderActionLoadingLabel(action) {
6578
+ return action.tooltip || action.label;
6579
+ }
6580
+ onSectionHeaderActionClick(section, action, event) {
6581
+ event.preventDefault();
6582
+ event.stopPropagation();
6583
+ if (this.isSectionHeaderActionDisabled(action))
6584
+ return;
6585
+ const actionId = this.getSectionHeaderActionEventId(action);
6586
+ if (!actionId)
6587
+ return;
6588
+ const confirmationMessage = this._getConfirmationMessageForAliases(...this.getSectionHeaderActionRuleKeys(section, action), actionId, action.id);
6589
+ const emitAction = () => {
6590
+ this.customAction.emit({
6591
+ actionId,
6592
+ formData: this.form.value,
6593
+ isValid: this.form.valid,
6594
+ source: 'section-header',
6595
+ ...(section.id ? { sectionId: section.id } : {}),
6596
+ });
6597
+ };
6598
+ if (confirmationMessage) {
6599
+ this._showConfirmationDialog(actionId, confirmationMessage, emitAction);
6600
+ }
6601
+ else {
6602
+ emitAction();
6603
+ }
6604
+ }
6605
+ applySectionHeaderActionOverrides(section, action) {
6606
+ const override = this.getSectionHeaderActionRuleKeys(section, action)
6607
+ .map((key) => (key ? this.actionRuleProps?.[key] : undefined))
6608
+ .find((candidate) => !!candidate);
6609
+ if (!override)
6610
+ return action;
6611
+ return {
6612
+ ...action,
6613
+ ...(override.label !== undefined ? { label: override.label } : {}),
6614
+ ...(override.icon !== undefined ? { icon: override.icon } : {}),
6615
+ ...(override.visible !== undefined ? { visible: override.visible } : {}),
6616
+ ...(override.disabled !== undefined ? { disabled: override.disabled } : {}),
6617
+ ...(override.loading !== undefined ? { loading: override.loading } : {}),
6618
+ ...(override.tooltip !== undefined ? { tooltip: override.tooltip } : {}),
6619
+ ...(override.color !== undefined ? { color: override.color } : {}),
6620
+ ...(override.className !== undefined ? { className: override.className } : {}),
6621
+ ...(override.style !== undefined ? { style: override.style } : {}),
6622
+ };
6623
+ }
6624
+ getSectionHeaderActionEventId(action) {
6625
+ return action.action?.trim() || action.id.trim();
6626
+ }
6627
+ getSectionHeaderActionRuleKeys(section, action) {
6628
+ const logicalId = this.getSectionHeaderActionEventId(action);
6629
+ const scopedKey = section.id && logicalId
6630
+ ? `section:${section.id}:header-action:${logicalId}`
6631
+ : undefined;
6632
+ const unscopedHeaderActionKey = logicalId
6633
+ ? `header-action:${logicalId}`
6634
+ : undefined;
6635
+ return [scopedKey, unscopedHeaderActionKey, logicalId, action.id?.trim()].filter((value) => !!value);
6636
+ }
6457
6637
  getRowRuleProps(row) {
6458
6638
  if (!row || !row.id)
6459
6639
  return {};
@@ -6931,14 +7111,23 @@ class PraxisDynamicForm {
6931
7111
  return Object.keys(styles).length ? styles : null;
6932
7112
  }
6933
7113
  _getConfirmationMessage(actionId) {
7114
+ return this._getConfirmationMessageForAliases(actionId);
7115
+ }
7116
+ _getConfirmationMessageForAliases(...actionIds) {
6934
7117
  const messages = this.config.messages;
6935
7118
  if (!messages)
6936
7119
  return undefined;
6937
- // Priority: customActions > confirmations
6938
- const customMessage = messages.customActions?.[actionId]?.confirmation;
6939
- if (customMessage)
6940
- return customMessage;
6941
- return messages.confirmations?.[actionId];
7120
+ for (const actionId of actionIds) {
7121
+ if (!actionId)
7122
+ continue;
7123
+ const customMessage = messages.customActions?.[actionId]?.confirmation;
7124
+ if (customMessage)
7125
+ return customMessage;
7126
+ const confirmation = messages.confirmations?.[actionId];
7127
+ if (confirmation)
7128
+ return confirmation;
7129
+ }
7130
+ return undefined;
6942
7131
  }
6943
7132
  _showConfirmationDialog(actionId, message, onConfirm) {
6944
7133
  const dialogRef = this.dialog.open(ConfirmDialogComponent, {
@@ -11054,7 +11243,7 @@ class PraxisDynamicForm {
11054
11243
  }
11055
11244
  }
11056
11245
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDynamicForm, deps: [{ token: i1$2.GenericCrudService }, { token: i1$3.FormBuilder }, { token: i0.ChangeDetectorRef }, { token: FormLayoutService }, { token: FormContextService }, { token: FormRulesService }, { token: i6$1.SettingsPanelService }, { token: i2.MatDialog }, { token: ASYNC_CONFIG_STORAGE }, { token: CONNECTION_STORAGE }, { token: i1$2.DynamicFormService }, { token: i8.MatSnackBar }, { token: CanvasStateService }, { token: DynamicFormLayoutService }, { token: i1$2.ErrorMessageService }, { token: i1$2.SchemaNormalizerService }, { token: i1$2.ComponentMetadataRegistry }, { token: i1$2.GlobalConfigService }, { token: i1$2.ComponentKeyService }, { token: i1$2.LoadingOrchestrator }, { token: PRAXIS_LOADING_RENDERER, optional: true }, { token: i11.Router, optional: true }, { token: i11.ActivatedRoute, optional: true }, { token: i1$2.FormHooksRegistry, optional: true }, { token: FORM_HOOKS_PRESETS, optional: true }, { token: i1$2.LoggerService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
11057
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: PraxisDynamicForm, isStandalone: true, selector: "praxis-dynamic-form", inputs: { resourcePath: "resourcePath", resourceId: "resourceId", editorialContext: "editorialContext", mode: "mode", config: "config", schemaSource: "schemaSource", enableCustomization: "enableCustomization", formId: "formId", componentInstanceId: "componentInstanceId", layout: "layout", backConfig: "backConfig", hooks: "hooks", removeEmptyContainersOnSave: "removeEmptyContainersOnSave", reactiveValidation: "reactiveValidation", reactiveValidationDebounceMs: "reactiveValidationDebounceMs", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", readonlyModeGlobal: "readonlyModeGlobal", disabledModeGlobal: "disabledModeGlobal", presentationModeGlobal: "presentationModeGlobal", visibleGlobal: "visibleGlobal", customEndpoints: "customEndpoints" }, outputs: { formSubmit: "formSubmit", formCancel: "formCancel", formReset: "formReset", configChange: "configChange", formReady: "formReady", valueChange: "valueChange", syncCompleted: "syncCompleted", initializationError: "initializationError", loadingStateChange: "loadingStateChange", enableCustomizationChange: "enableCustomizationChange", customAction: "customAction", actionConfirmation: "actionConfirmation", schemaStatusChange: "schemaStatusChange", fieldRenderError: "fieldRenderError", widgetEvent: "widgetEvent" }, viewQueries: [{ propertyName: "formHost", first: true, predicate: ["formHost"], descendants: true }, { propertyName: "fieldLoaders", predicate: DynamicFieldLoaderDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (isLoading) {\n<!-- Loading State -->\n<div class=\"form-loading\">\n <mat-progress-spinner diameter=\"40\"></mat-progress-spinner>\n <p>Carregando formul\u00E1rio...</p>\n</div>\n} @else if (initializationStatus === 'error') {\n<!-- Error State -->\n<div class=\"form-error\">\n <mat-icon color=\"warn\" [praxisIcon]=\"'error'\"></mat-icon>\n <h3>{{ getErrorTitle() }}</h3>\n <p>{{ currentErrorMessage }}</p>\n @if (isRecoverable) {\n <button mat-stroked-button (click)=\"retryInitialization()\">\n <mat-icon [praxisIcon]=\"'refresh'\"></mat-icon>\n Tentar Novamente\n </button>\n }\n <button mat-button (click)=\"showDetailedError()\" class=\"show-details\">\n Ver Detalhes T\u00E9cnicos\n </button>\n <!-- Permitir corre\u00E7\u00E3o do resourcePath diretamente do estado de erro -->\n <button mat-flat-button color=\"primary\" (click)=\"openQuickConnect()\" class=\"connect-action\">\n <mat-icon [praxisIcon]=\"'bolt'\"></mat-icon>\n Conectar a recurso\n </button>\n</div>\n} @else if (initializationStatus === 'success') {\n<!-- Inline banner for schema change (only when customization is enabled) -->\n@if (shouldShowOutdatedInline()) {\n<div class=\"pfx-form-info-banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"text\">O schema do servidor mudou. Reconciliar agora?</div>\n <div class=\"actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"openConfigEditor()\">\n <mat-icon [praxisIcon]=\"'sync'\"></mat-icon>\n Reconciliar\n </button>\n <button mat-button (click)=\"onSnoozeOutdated()\">Lembrar depois</button>\n <button mat-button (click)=\"onIgnoreOutdated()\">Ignorar</button>\n </div>\n</div>\n}\n\n<!-- Configuration Controls -->\n@if (shouldShowConfigControls && enableCustomization) {\n<div class=\"form-config-controls\">\n <praxis-ai-assistant [adapter]=\"aiAdapter\"></praxis-ai-assistant>\n <button type=\"button\" mat-icon-button (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configurar formul\u00E1rio'\">\n <mat-icon [praxisIcon]=\"'settings'\"></mat-icon>\n </button>\n <button type=\"button\" mat-icon-button (click)=\"disconnect()\" matTooltip=\"Desconectar da fonte de dados\"\n [disabled]=\"isLoading\">\n <mat-icon [praxisIcon]=\"'link_off'\"></mat-icon>\n </button>\n</div>\n}\n\n<!-- Form Content -->\n@if (!resourcePath && (!config.sections || config.sections.length === 0)) {\n<praxis-empty-state-card icon=\"link\" [title]=\"'Conecte o formul\u00E1rio \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para gerar automaticamente os campos do formul\u00E1rio.'\"\n [primaryAction]=\"{ label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) }\"></praxis-empty-state-card>\n}\n<form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\" [class.readonly-mode]=\"effectiveReadonly\"\n [class.editorial-visual-context]=\"hasEditorialVisualContext()\"\n [class.pfx-mounting]=\"isMounting\" [formGroup]=\"form\"\n [ngClass]=\"{\n 'pres-compact': presentationVars.compact,\n 'pres-label-left': presentationVars.labelPosition === 'left',\n 'pres-label-above': presentationVars.labelPosition === 'above'\n }\" [style.--pfx-pres-label-align]=\"presentationVars.labelAlign\"\n [style.--pfx-pres-label-size]=\"presentationVars.labelSize\"\n [style.--pfx-pres-label-width]=\"presentationVars.labelWidth\"\n [style.--pfx-pres-row-gap]=\"presentationVars.density === 'compact' ? '6px' : (presentationVars.density === 'cozy' ? '8px' : '10px')\"\n [style.--pfx-pres-row-padding]=\"presentationVars.density === 'compact' ? '2px 0' : (presentationVars.density === 'cozy' ? '6px 0' : '8px 0')\"\n [style.--pfx-pres-value-align]=\"presentationVars.valueAlign\"\n [style.--pfx-pres-value-size]=\"presentationVars.valueSize\"\n [style.--pdx-form-mount-duration]=\"getMountDurationVar()\"\n [style.--pdx-form-mount-offset]=\"getMountOffsetVar()\"\n [style.--pdx-form-mount-stagger]=\"getMountStaggerVar()\"\n class=\"praxis-dynamic-form\">\n <praxis-canvas-toolbar (editMetadata)=\"openSelectedElementEditor()\" (selectPath)=\"onSelectPath($event)\"\n (moveUp)=\"onToolbarMove('up')\" (moveDown)=\"onToolbarMove('down')\" (toggleReadonly)=\"onToolbarToggleReadonly()\"\n (toggleRequired)=\"onToolbarToggleRequired()\" (toggleHidden)=\"onToolbarToggleHidden()\"\n (toggleDisabled)=\"onToolbarToggleDisabled()\" (requestClose)=\"onToolbarRequestClose()\"\n *ngIf=\"enableCustomization && selectedElement\" [selectedElement]=\"selectedElement\"\n [style.transform]=\"toolbarTransform\"></praxis-canvas-toolbar>\n\n @if (formBlocksBefore.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before\" data-editorial-placement=\"before\">\n @for (block of formBlocksBefore; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('before', $event)\">\n </ng-container>\n }\n </section>\n }\n\n @if (actionPlacement === 'top' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"top\" [actions]=\"config.actions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"form.valid\" [submitError]=\"submitError\" [formId]=\"formId\" [actionOverrides]=\"actionRuleProps\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @for (section of config.sections; track (section.id ?? $index); let sectionIndex = $index;\n let last = $last) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n @if (isSectionVisible(section)) {\n <div #sectionEl class=\"form-section canvas-element\" data-canvas-type=\"section\" [attr.data-section-id]=\"section.id\"\n [attr.data-section-index]=\"sectionIndex\" (mouseenter)=\"onElementMouseEnter($event, 'section', section, sectionEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'section', section, sectionEl)\"\n [class.selected]=\"selectedElement?.domElement === sectionEl\"\n [class.hovered]=\"hoveredElement?.domElement === sectionEl && selectedElement?.domElement !== sectionEl\"\n [attr.data-section-appearance]=\"getSectionAppearance(section) || null\"\n [style.marginBottom.px]=\"!last ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n >\n <div class=\"section-heading-text\" [matTooltip]=\"getSectionHeaderTooltip(section) || null\"\n [matTooltipDisabled]=\"!getSectionHeaderTooltip(section)\">\n @if (getSectionStepLabel(section)) {\n <div class=\"section-step-label\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionStepLabel(section) }}\n </div>\n }\n @if (getSectionTitle(section)) {\n <h3 class=\"section-title\" [class.title-large]=\"getSectionTitleStyle(section) === 'titleLarge'\"\n [class.title-medium]=\"getSectionTitleStyle(section) === 'titleMedium'\"\n [class.title-small]=\"getSectionTitleStyle(section) === 'titleSmall'\"\n [class.headline-small]=\"getSectionTitleStyle(section) === 'headlineSmall'\"\n [style.marginBottom.px]=\"getSectionTitleGapBottom(section) ?? 20\" [style.color]=\"getSectionTitleColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [attr.id]=\"sectionPanelId(section, sectionIndex) + '-title'\">\n @let sectionHeaderVisual = getSectionHeaderVisual(section);\n @let sectionHeaderAvatarSize = getSectionHeaderAvatarSize(section);\n @if (sectionHeaderVisual.kind === 'icon') {\n <mat-icon class=\"section-title-icon\" aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.kind === 'image') {\n <img class=\"section-title-avatar section-title-avatar-image\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\"\n [src]=\"sectionHeaderVisual.src\" [alt]=\"sectionHeaderVisual.alt\" />\n }\n @if (sectionHeaderVisual.kind === 'initials') {\n <span class=\"section-title-avatar section-title-avatar-text\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n {{ sectionHeaderVisual.text }}\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n @if (sectionHeaderVisual.kind === 'placeholder') {\n <span class=\"section-title-avatar section-title-avatar-placeholder\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n @if (sectionHeaderVisual.icon) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.text) {\n <span>{{ sectionHeaderVisual.text }}</span>\n }\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n {{ getSectionTitle(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" mat-icon-button (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\n <mat-icon>edit</mat-icon>\n </button>\n }\n </h3>\n }\n @if (getSectionDescription(section)) {\n <p class=\"section-description\" [class.body-large]=\"getSectionDescriptionStyle(section) === 'bodyLarge'\"\n [class.body-medium]=\"getSectionDescriptionStyle(section) === 'bodyMedium'\"\n [class.body-small]=\"getSectionDescriptionStyle(section) === 'bodySmall'\"\n [style.marginBottom.px]=\"getSectionDescriptionGapBottom(section) ?? 8\" [style.color]=\"getSectionDescriptionColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionDescription(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" mat-icon-button\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\n <mat-icon>edit</mat-icon>\n </button>\n }\n </p>\n }\n </div>\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" mat-icon-button\n (click)=\"toggleSectionCollapse($event, section)\" [attr.aria-expanded]=\"!isSectionCollapsed(section)\"\n [attr.aria-controls]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-label]=\"isSectionCollapsed(section) ? 'Expandir se\u00E7\u00E3o' : 'Recolher se\u00E7\u00E3o'\">\n <mat-icon [praxisIcon]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\"></mat-icon>\n </button>\n }\n </div>\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-labelledby]=\"getSectionTitle(section) ? sectionPanelId(section, sectionIndex) + '-title' : null\">\n @if (!isSectionCollapsed(section)) {\n @for (row of section.rows; track (row.id ?? $index); let rowIndex = $index) {\n @if (isRowVisible(row)) {\n <div class=\"row-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n <div #rowEl class=\"form-row grid-12 canvas-element\" data-canvas-type=\"row\" [attr.data-row-index]=\"rowIndex\"\n [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\" [style.--pfx-grid-gap.px]=\"getRowGap(row)\"\n [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [style.--pfx-mount-index]=\"rowIndex\"\n [style.marginBottom.px]=\"rowIndex < section.rows.length - 1 ? (getRowRowGap(row) ?? null) : null\"\n [ngClass]=\"getRowClasses(row)\" [ngStyle]=\"getRowStyles(row)\"\n (mouseenter)=\"onElementMouseEnter($event, 'row', row, rowEl)\" (mouseleave)=\"onElementMouseLeave($event)\"\n (click)=\"onElementClick($event, 'row', row, rowEl)\" [class.selected]=\"selectedElement?.domElement === rowEl\"\n [class.hovered]=\"hoveredElement?.domElement === rowEl && selectedElement?.domElement !== rowEl\">\n @for (column of row.columns; track (column.id ?? $index); let colIndex = $index) {\n @if (isColumnVisible(column)) {\n <div class=\"column-drop-wrapper\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\">\n <div #colEl class=\"form-column canvas-element\" [ngClass]=\"getColumnClasses(column)\"\n [style.padding.px]=\"getColumnPadding(column)\" [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [ngStyle]=\"getColumnStyles(column)\" [attr.data-testid]=\"column.testId || null\"\n [attr.data-row-gap]=\"getRowRowGap(row)\" data-canvas-type=\"column\" [attr.data-column-index]=\"colIndex\"\n [attr.data-row-index]=\"rowIndex\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\"\n [attr.data-column-id]=\"column.id\" (mouseenter)=\"onElementMouseEnter($event, 'column', column, colEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'column', column, colEl)\"\n [class.selected]=\"selectedElement?.domElement === colEl\"\n [class.hovered]=\"hoveredElement?.domElement === colEl && selectedElement?.domElement !== colEl\">\n <ng-container dynamicFieldLoader [fields]=\"getColumnFields(column)\" [formGroup]=\"form\"\n [readonlyMode]=\"readonlyModeGlobal === null ? null : readonlyModeGlobal\"\n [disabledMode]=\"disabledModeGlobal === null ? null : disabledModeGlobal\"\n [presentationMode]=\"presentationForLoader\" [visible]=\"visibleGlobal === null ? null : visibleGlobal\"\n [canvasMode]=\"enableCustomization\" (canvasMouseEnter)=\"onFieldMouseEnter($event)\"\n (canvasMouseLeave)=\"onFieldMouseLeave($event)\" (canvasClick)=\"onFieldClick($event)\"\n (renderError)=\"onFieldRenderError($event)\">\n </ng-container>\n </div>\n </div>\n } }\n </div>\n </div>\n }\n }\n } @else {\n <div class=\"section-collapsed-placeholder\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'unfold_more'\"></mat-icon>\n <span>{{ getSectionCollapsedSummary(section) }}</span>\n </div>\n }\n @if (last && beforeActionsPlacement === 'insideLastSection' && formBlocksBeforeActions.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n @for (block of formBlocksBeforeActions; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('beforeActions', $event)\">\n </ng-container>\n }\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && last && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"config.actions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"form.valid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n </div>\n <!-- Overlay de bloqueio durante submiss\u00E3o -->\n @if (submitting) {\n <div class=\"form-blocking-overlay\" aria-live=\"polite\">\n <mat-progress-spinner diameter=\"40\" color=\"primary\"></mat-progress-spinner>\n <p>{{ config.messages?.loading?.submit || 'Salvando...' }}</p>\n </div>\n }\n </div>\n\n @if (enableCustomization && selectedElement?.domElement === sectionEl) {\n <div class=\"add-section-container\">\n <div class=\"add-section-line\"></div>\n <button mat-fab color=\"primary\" aria-label=\"Adicionar nova se\u00E7\u00E3o\" (click)=\"addNewSectionAfter(sectionIndex)\"\n matTooltip=\"Adicionar nova se\u00E7\u00E3o aqui\">\n <mat-icon [praxisIcon]=\"'add'\"></mat-icon>\n </button>\n <div class=\"add-section-line\"></div>\n </div>\n }\n }\n </div>\n }\n\n @if (beforeActionsPlacement !== 'insideLastSection' && formBlocksBeforeActions.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n @for (block of formBlocksBeforeActions; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('beforeActions', $event)\">\n </ng-container>\n }\n </section>\n }\n\n @if (actionPlacement === 'afterSections' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"afterSections\" [actions]=\"config.actions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"form.valid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @if (formBlocksAfter.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-after\" data-editorial-placement=\"after\">\n @for (block of formBlocksAfter; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('after', $event)\">\n </ng-container>\n }\n </section>\n }\n</form>\n@if (!enableCustomization && mode === 'view') {\n<div class=\"ai-floating-assistant\">\n <praxis-ai-assistant [adapter]=\"aiAdapter\"></praxis-ai-assistant>\n</div>\n}\n}\n", styles: ["@charset \"UTF-8\";.span-xs-1{grid-column:span 1}.span-xs-2{grid-column:span 2}.span-xs-3{grid-column:span 3}.span-xs-4{grid-column:span 4}.span-xs-5{grid-column:span 5}.span-xs-6{grid-column:span 6}.span-xs-7{grid-column:span 7}.span-xs-8{grid-column:span 8}.span-xs-9{grid-column:span 9}.span-xs-10{grid-column:span 10}.span-xs-11{grid-column:span 11}.span-xs-12{grid-column:span 12}.offset-xs-0{margin-left:0%}.offset-xs-1{margin-left:calc(1 / 12 * 100%)}.offset-xs-2{margin-left:calc(2 / 12 * 100%)}.offset-xs-3{margin-left:25%}.offset-xs-4{margin-left:calc(4 / 12 * 100%)}.offset-xs-5{margin-left:calc(5 / 12 * 100%)}.offset-xs-6{margin-left:50%}.offset-xs-7{margin-left:calc(7 / 12 * 100%)}.offset-xs-8{margin-left:calc(8 / 12 * 100%)}.offset-xs-9{margin-left:75%}.offset-xs-10{margin-left:calc(10 / 12 * 100%)}.offset-xs-11{margin-left:calc(11 / 12 * 100%)}.order-xs--12{order:-12}.order-xs--11{order:-11}.order-xs--10{order:-10}.order-xs--9{order:-9}.order-xs--8{order:-8}.order-xs--7{order:-7}.order-xs--6{order:-6}.order-xs--5{order:-5}.order-xs--4{order:-4}.order-xs--3{order:-3}.order-xs--2{order:-2}.order-xs--1{order:-1}.order-xs-0{order:0}.order-xs-1{order:1}.order-xs-2{order:2}.order-xs-3{order:3}.order-xs-4{order:4}.order-xs-5{order:5}.order-xs-6{order:6}.order-xs-7{order:7}.order-xs-8{order:8}.order-xs-9{order:9}.order-xs-10{order:10}.order-xs-11{order:11}.order-xs-12{order:12}.hidden-xs{display:none}@media(min-width:600px){.span-sm-1{grid-column:span 1}.span-sm-2{grid-column:span 2}.span-sm-3{grid-column:span 3}.span-sm-4{grid-column:span 4}.span-sm-5{grid-column:span 5}.span-sm-6{grid-column:span 6}.span-sm-7{grid-column:span 7}.span-sm-8{grid-column:span 8}.span-sm-9{grid-column:span 9}.span-sm-10{grid-column:span 10}.span-sm-11{grid-column:span 11}.span-sm-12{grid-column:span 12}.offset-sm-0{margin-left:0%}.offset-sm-1{margin-left:calc(1 / 12 * 100%)}.offset-sm-2{margin-left:calc(2 / 12 * 100%)}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:calc(4 / 12 * 100%)}.offset-sm-5{margin-left:calc(5 / 12 * 100%)}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:calc(7 / 12 * 100%)}.offset-sm-8{margin-left:calc(8 / 12 * 100%)}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:calc(10 / 12 * 100%)}.offset-sm-11{margin-left:calc(11 / 12 * 100%)}.order-sm--12{order:-12}.order-sm--11{order:-11}.order-sm--10{order:-10}.order-sm--9{order:-9}.order-sm--8{order:-8}.order-sm--7{order:-7}.order-sm--6{order:-6}.order-sm--5{order:-5}.order-sm--4{order:-4}.order-sm--3{order:-3}.order-sm--2{order:-2}.order-sm--1{order:-1}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.hidden-sm{display:none}}@media(min-width:900px){.span-md-1{grid-column:span 1}.span-md-2{grid-column:span 2}.span-md-3{grid-column:span 3}.span-md-4{grid-column:span 4}.span-md-5{grid-column:span 5}.span-md-6{grid-column:span 6}.span-md-7{grid-column:span 7}.span-md-8{grid-column:span 8}.span-md-9{grid-column:span 9}.span-md-10{grid-column:span 10}.span-md-11{grid-column:span 11}.span-md-12{grid-column:span 12}.offset-md-0{margin-left:0%}.offset-md-1{margin-left:calc(1 / 12 * 100%)}.offset-md-2{margin-left:calc(2 / 12 * 100%)}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:calc(4 / 12 * 100%)}.offset-md-5{margin-left:calc(5 / 12 * 100%)}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:calc(7 / 12 * 100%)}.offset-md-8{margin-left:calc(8 / 12 * 100%)}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:calc(10 / 12 * 100%)}.offset-md-11{margin-left:calc(11 / 12 * 100%)}.order-md--12{order:-12}.order-md--11{order:-11}.order-md--10{order:-10}.order-md--9{order:-9}.order-md--8{order:-8}.order-md--7{order:-7}.order-md--6{order:-6}.order-md--5{order:-5}.order-md--4{order:-4}.order-md--3{order:-3}.order-md--2{order:-2}.order-md--1{order:-1}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.hidden-md{display:none}}@media(min-width:1200px){.span-lg-1{grid-column:span 1}.span-lg-2{grid-column:span 2}.span-lg-3{grid-column:span 3}.span-lg-4{grid-column:span 4}.span-lg-5{grid-column:span 5}.span-lg-6{grid-column:span 6}.span-lg-7{grid-column:span 7}.span-lg-8{grid-column:span 8}.span-lg-9{grid-column:span 9}.span-lg-10{grid-column:span 10}.span-lg-11{grid-column:span 11}.span-lg-12{grid-column:span 12}.offset-lg-0{margin-left:0%}.offset-lg-1{margin-left:calc(1 / 12 * 100%)}.offset-lg-2{margin-left:calc(2 / 12 * 100%)}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:calc(4 / 12 * 100%)}.offset-lg-5{margin-left:calc(5 / 12 * 100%)}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:calc(7 / 12 * 100%)}.offset-lg-8{margin-left:calc(8 / 12 * 100%)}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:calc(10 / 12 * 100%)}.offset-lg-11{margin-left:calc(11 / 12 * 100%)}.order-lg--12{order:-12}.order-lg--11{order:-11}.order-lg--10{order:-10}.order-lg--9{order:-9}.order-lg--8{order:-8}.order-lg--7{order:-7}.order-lg--6{order:-6}.order-lg--5{order:-5}.order-lg--4{order:-4}.order-lg--3{order:-3}.order-lg--2{order:-2}.order-lg--1{order:-1}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.hidden-lg{display:none}}@media(min-width:1536px){.span-xl-1{grid-column:span 1}.span-xl-2{grid-column:span 2}.span-xl-3{grid-column:span 3}.span-xl-4{grid-column:span 4}.span-xl-5{grid-column:span 5}.span-xl-6{grid-column:span 6}.span-xl-7{grid-column:span 7}.span-xl-8{grid-column:span 8}.span-xl-9{grid-column:span 9}.span-xl-10{grid-column:span 10}.span-xl-11{grid-column:span 11}.span-xl-12{grid-column:span 12}.offset-xl-0{margin-left:0%}.offset-xl-1{margin-left:calc(1 / 12 * 100%)}.offset-xl-2{margin-left:calc(2 / 12 * 100%)}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:calc(4 / 12 * 100%)}.offset-xl-5{margin-left:calc(5 / 12 * 100%)}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:calc(7 / 12 * 100%)}.offset-xl-8{margin-left:calc(8 / 12 * 100%)}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:calc(10 / 12 * 100%)}.offset-xl-11{margin-left:calc(11 / 12 * 100%)}.order-xl--12{order:-12}.order-xl--11{order:-11}.order-xl--10{order:-10}.order-xl--9{order:-9}.order-xl--8{order:-8}.order-xl--7{order:-7}.order-xl--6{order:-6}.order-xl--5{order:-5}.order-xl--4{order:-4}.order-xl--3{order:-3}.order-xl--2{order:-2}.order-xl--1{order:-1}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.hidden-xl{display:none}}.canvas-mode-enabled{--canvas-hit: 14px}.canvas-mode-enabled .canvas-element{position:relative;z-index:0;border-radius:8px;outline:2px solid transparent;outline-offset:2px;transition:outline-color .2s ease,outline-style .2s ease}.canvas-mode-enabled .canvas-element:before{content:\"\";position:absolute;inset:calc(-1 * var(--canvas-hit));pointer-events:none;border-radius:inherit;background:transparent}.canvas-mode-enabled .canvas-element[data-canvas-type=section]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element[data-canvas-type=row]{--outline-color: var(--md-sys-color-secondary)}.canvas-mode-enabled .canvas-element[data-canvas-type=column],.canvas-mode-enabled .canvas-element[data-canvas-type=field]{--outline-color: var(--md-sys-color-tertiary)}.canvas-mode-enabled .canvas-element[data-canvas-type=actions]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element.hovered:not(.selected){outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:dashed}.canvas-mode-enabled .canvas-element.selected{outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:solid;box-shadow:0 0 0 2px var(--outline-color, var(--md-sys-color-primary))}.canvas-mode-enabled .canvas-element.hovered{z-index:1000}.canvas-mode-enabled .canvas-element.selected{z-index:2000}.section-drop-wrapper,.row-drop-wrapper,.column-drop-wrapper{display:contents}.add-section-container{display:flex;align-items:center;justify-content:center;padding:.5rem 0;margin:-.5rem 0;position:relative;z-index:500}.add-section-container .add-section-line{flex-grow:1;height:1px;background:repeating-linear-gradient(90deg,var(--md-sys-color-outline-variant),var(--md-sys-color-outline-variant) 4px,transparent 4px,transparent 8px)}.add-section-container button{margin:0 1rem;transform:scale(.85)}:host{display:block;position:relative}.form-config-controls{position:sticky;top:10px;margin-left:auto;margin-bottom:10px;display:flex;align-items:center;gap:.35rem;z-index:60;background:color-mix(in srgb,var(--md-sys-color-surface) 92%,transparent);padding:6px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);border-radius:999px;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 10px 22px #0f172a14;min-width:0;justify-content:flex-end;pointer-events:none;opacity:.88;transition:opacity .16s ease,box-shadow .16s ease,border-color .16s ease,transform .16s ease}.form-config-controls>*{pointer-events:auto}.praxis-dynamic-form:hover .form-config-controls,.praxis-dynamic-form:focus-within .form-config-controls{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant) 74%);box-shadow:0 14px 28px #0f172a1f;transform:translateY(-1px)}.form-config-controls .mat-icon-button{--mdc-icon-button-state-layer-size: 34px;width:34px;height:34px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);border:1px solid transparent}.form-config-controls .mat-icon-button:hover{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent)}.ai-floating-assistant{position:sticky;right:0;bottom:12px;margin-top:14px;margin-left:auto;width:fit-content;z-index:70;pointer-events:none}.ai-floating-assistant praxis-ai-assistant{pointer-events:auto;display:inline-flex}.ai-floating-assistant .ai-trigger-btn{box-shadow:0 12px 28px #0f172a24}.config-button{color:var(--md-sys-color-primary)}.form-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-on-surface);gap:1rem}.form-loading p{margin:0;font-size:.875rem;opacity:.7}.form-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-error);gap:1rem;border:1px solid var(--md-sys-color-error);border-radius:8px;background-color:var(--md-sys-color-error-container);margin:1rem;box-shadow:0 12px 30px #7f1d1d1f}.form-error h3{margin:0;color:var(--md-sys-color-on-error-container)}.form-error p{margin:0;color:var(--md-sys-color-on-error-container);opacity:.8}.form-error button{margin-top:.5rem}.pfx-form-info-banner{margin-bottom:14px;padding:12px 14px;border-radius:16px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant) 82%);background:color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface) 76%);color:var(--md-sys-color-on-surface);display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.pfx-form-info-banner .text{font-size:.92rem;line-height:1.5;font-weight:600}.pfx-form-info-banner .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.praxis-dynamic-form{display:flex;flex-direction:column;transition:all .3s ease;position:relative;font-family:inherit;font-size:inherit;color:inherit;--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--md-sys-color-surface-container) );--pfx-editorial-form-surface-muted: var(--md-sys-color-surface-container-low);--pfx-editorial-form-border: var( --pfx-form-stroke, var(--md-sys-color-outline-variant) );--pfx-editorial-form-text: var(--md-sys-color-on-surface);--pfx-editorial-form-text-muted: var(--md-sys-color-on-surface-variant);--pfx-editorial-form-field-surface: color-mix( in srgb, var(--pfx-editorial-form-surface-muted) 76%, var(--pfx-editorial-form-surface) 24% );--pfx-editorial-form-field-outline: color-mix( in srgb, var(--pfx-editorial-form-border) 88%, transparent );--pfx-editorial-form-accent: var(--md-sys-color-primary);--pfx-editorial-form-accent-text: var(--md-sys-color-on-primary);--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-field-radius: var(--pfx-form-field-radius, 4px);--pfx-editorial-form-border-width: 1px;--pfx-editorial-form-field-border-width: 1px;--pfx-editorial-form-shadow: none;--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-surface-flat: color-mix( in srgb, var(--pfx-editorial-form-surface) 78%, var(--pfx-editorial-form-surface-muted) 22% );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--pfx-form-label-strong: color-mix( in srgb, var(--pfx-editorial-form-text) 96%, white 4% );--pfx-form-label-muted: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 92%, var(--pfx-editorial-form-text) 8% );--pfx-form-field-surface-rest: color-mix( in srgb, var(--pfx-editorial-form-field-surface) 82%, var(--pfx-editorial-form-surface) 18% );--pfx-form-field-surface-focus: color-mix( in srgb, var(--pfx-editorial-form-accent) 4%, var(--pfx-form-field-surface-rest) 96% );--pfx-form-field-min-height: 48px;--pfx-form-section-padding: clamp(1.1rem, 1.8vw, 1.5rem);--pfx-form-section-gap: 22px;--pfx-form-footer-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 70%, var(--pfx-editorial-form-surface-muted) 30% );--pfx-form-footer-border: color-mix( in srgb, var(--pfx-editorial-form-border) 76%, transparent )}.praxis-dynamic-form.editorial-visual-context{font-family:var(--editorial-body-font-family, inherit);font-size:var(--editorial-body-size, 1rem);color:var(--editorial-text-primary, var(--md-sys-color-on-surface));--pfx-editorial-form-surface: var( --editorial-surface-primary, var(--pfx-form-section-surface, var(--md-sys-color-surface-container)) );--pfx-editorial-form-surface-muted: var( --editorial-surface-secondary, var(--md-sys-color-surface-container-low) );--pfx-editorial-form-border: var( --editorial-border-color, var(--pfx-form-stroke, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-text: var( --editorial-text-primary, var(--md-sys-color-on-surface) );--pfx-editorial-form-text-muted: var( --editorial-text-secondary, var(--md-sys-color-on-surface-variant) );--pfx-editorial-form-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--md-sys-color-primary)) );--pfx-editorial-form-accent-text: var( --editorial-cta-primary-text, var(--editorial-accent-contrast, var(--md-sys-color-on-primary)) );--pfx-editorial-form-radius: var(--editorial-card-radius, 18px);--pfx-editorial-form-field-radius: var( --editorial-field-radius, var(--editorial-card-radius, 14px) );--pfx-editorial-form-border-width: var(--editorial-card-border-width, 1px);--pfx-editorial-form-field-border-width: var(--editorial-field-border-width, 1px);--pfx-editorial-form-shadow: var(--editorial-card-shadow, none);--md-sys-color-surface: var( --pfx-editorial-form-surface, var(--md-sys-color-surface) );--md-sys-color-surface-container: var( --pfx-editorial-form-surface, var(--md-sys-color-surface-container) );--md-sys-color-surface-container-low: var( --pfx-editorial-form-surface-muted, var(--md-sys-color-surface-container-low) );--md-sys-color-surface-variant: var( --pfx-editorial-form-field-surface, var(--md-sys-color-surface-variant) );--md-sys-color-outline: var( --pfx-editorial-form-field-outline, var(--md-sys-color-outline) );--md-sys-color-outline-variant: var( --pfx-editorial-form-border, var(--md-sys-color-outline-variant) );--md-sys-color-on-surface: var( --pfx-editorial-form-text, var(--md-sys-color-on-surface) );--md-sys-color-on-surface-variant: var( --pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant) );--md-sys-color-primary: var( --pfx-editorial-form-accent, var(--md-sys-color-primary) );--md-sys-color-on-primary: var( --pfx-editorial-form-accent-text, var(--md-sys-color-on-primary) );--md-sys-color-on-surface-rgb: var( --editorial-text-primary-rgb, var(--md-sys-color-on-surface-rgb) );--mat-sys-on-surface: var( --pfx-editorial-form-text, var(--mat-sys-on-surface) );--mat-sys-on-surface-variant: var( --pfx-editorial-form-text-muted, var(--mat-sys-on-surface-variant) );--mat-sys-on-surface-rgb: var( --editorial-text-primary-rgb, var(--mat-sys-on-surface-rgb, var(--md-sys-color-on-surface-rgb)) );color:var(--pfx-editorial-form-text);color-scheme:light}.praxis-dynamic-form.presentation-mode .form-row,.praxis-dynamic-form.readonly-mode .form-row{gap:.5rem;margin-bottom:.5rem}.praxis-dynamic-form.presentation-mode .form-section,.praxis-dynamic-form.readonly-mode .form-section{padding:.75rem .875rem}.praxis-dynamic-form.pres-compact .form-row{gap:.35rem;margin-bottom:.35rem}.praxis-dynamic-form.pres-compact .form-section{padding:.5rem .75rem}.praxis-dynamic-form.pres-label-left .praxis-presentation{display:grid;grid-template-columns:var(--pfx-presentation-label-w, 220px) 1fr;align-items:baseline;column-gap:10px}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:right;margin-bottom:0}.form-section{border:1px solid var(--pfx-form-section-divider);border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);box-shadow:none;transition:all .2s ease;position:relative}.praxis-dynamic-form.editorial-visual-context .form-section{border:var(--pfx-editorial-form-border-width) solid var(--pfx-editorial-form-border)!important;background:var(--pfx-editorial-form-surface)!important;box-shadow:var(--editorial-card-shadow, none)}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{background-color:var(--pfx-editorial-form-surface)!important;background-image:linear-gradient(180deg,color-mix(in srgb,var(--editorial-accent, var(--md-sys-color-primary)) 6%,transparent) 0%,transparent 132px)!important;background-repeat:no-repeat!important}.section-drop-wrapper>.form-section{margin-bottom:var(--pfx-section-gap, 20px)}.section-drop-wrapper:last-of-type>.form-section{margin-bottom:0}.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections] .form-actions{margin-top:var(--pfx-actions-gap-top, var(--pfx-section-gap, 20px))}.section-title{margin:0 0 var(--pfx-section-title-mb, 12px) 0;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-size:var(--editorial-step-title-size, 1.12rem);font-weight:700;color:var(--pfx-form-label-strong)}.section-heading{display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding-bottom:18px;border-bottom:1px solid var(--pfx-form-section-divider)}.section-heading.align-center{flex-direction:column;align-items:center;text-align:center}.section-heading.align-center .section-heading-text{display:grid;justify-items:center}.section-step-label{display:inline-flex;align-items:center;min-height:24px;padding:0 10px;margin:0 0 8px;border-radius:999px;background:color-mix(in srgb,var(--pfx-editorial-form-accent) 10%,transparent);color:color-mix(in srgb,var(--pfx-editorial-form-accent) 84%,var(--pfx-form-label-strong) 16%);font-size:.72rem;font-weight:800;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));letter-spacing:.08em;text-transform:uppercase}.section-heading-text{flex:1 1 auto;min-width:0}.section-collapse-btn{margin-left:4px;color:var(--pfx-form-label-muted)}.section-title.title-large{font:var(--mdc-typography-title-large, 500 22px/28px system-ui)}.section-title.title-medium{font:var(--mdc-typography-title-medium, 500 16px/24px system-ui)}.section-title.title-small{font:var(--mdc-typography-title-small, 500 14px/20px system-ui)}.section-title.headline-small{font:var(--mdc-typography-headline-small, 600 24px/32px system-ui)}.section-title.title-large,.section-title.title-medium,.section-title.title-small,.section-title.headline-small{font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-weight:var(--editorial-title-weight, 600)}.section-description{margin:0;font-family:var(--editorial-body-font-family, inherit);font-size:.93rem;color:var(--pfx-form-label-muted);line-height:1.6}.section-description.body-large{font:var(--mdc-typography-body-large, 400 16px/24px system-ui)}.section-description.body-medium{font:var(--mdc-typography-body-medium, 400 14px/20px system-ui)}.section-description.body-small{font:var(--mdc-typography-body-small, 400 12px/16px system-ui)}.section-description.body-large,.section-description.body-medium,.section-description.body-small{font-family:var(--editorial-body-font-family, inherit);font-weight:var(--editorial-body-weight, 400)}.section-title.align-center,.section-description.align-center,.section-step-label.align-center{text-align:center}.form-section.section-appearance-plain{border-color:transparent;border-radius:0;padding:0;background:transparent}.form-section.section-appearance-plain .section-heading{margin-bottom:14px}.form-section.section-appearance-step{border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);border-color:var(--pfx-form-section-divider);box-shadow:none}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{border-radius:var(--editorial-card-radius, 20px);box-shadow:none}.form-section.section-appearance-step .section-heading{margin-bottom:22px;padding-bottom:16px;border-bottom:1px solid var(--pfx-form-section-divider)}.form-section.section-appearance-step .section-title{font:var(--mdc-typography-title-large, 700 22px/28px system-ui);color:var(--pfx-form-label-strong);margin-bottom:8px}.form-section.section-appearance-step .section-description{color:var(--pfx-form-label-muted);max-width:60ch}.form-section.section-appearance-step .section-step-label{min-height:24px;padding:0 10px;margin-bottom:10px;box-shadow:none}.form-section.section-appearance-step .section-heading.align-center .section-description{max-width:52ch}.form-section.section-appearance-step .section-body{display:grid;gap:8px;padding-top:0}.form-section.section-appearance-step .form-row{margin-bottom:var(--pfx-field-gap, 1rem)}.form-section.section-appearance-step .form-column{gap:var(--pfx-field-gap, 12px)}.form-section .form-editorial-blocks{display:grid;gap:16px}.form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{margin-top:24px;padding-top:18px;border-top:1px solid var(--pfx-form-section-divider)}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]{gap:18px}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]>*+*{margin-top:2px}.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections] .form-actions{margin-top:18px;padding-top:0}.praxis-dynamic-form>.form-editorial-blocks[data-editorial-placement=after]{margin-top:6px}:host-context(.mdc-theme-dark) .form-section.section-appearance-step,:host-context(.theme-dark) .form-section.section-appearance-step{border-color:color-mix(in srgb,var(--pfx-editorial-form-border) 82%,transparent);box-shadow:none}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-title,:host-context(.theme-dark) .form-section.section-appearance-step .section-title{color:color-mix(in srgb,var(--pfx-editorial-form-text) 96%,white)}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-description,:host-context(.theme-dark) .form-section.section-appearance-step .section-description{color:color-mix(in srgb,var(--pfx-editorial-form-text-muted) 86%,var(--pfx-editorial-form-text) 14%)}:host-context(.mdc-theme-dark) .section-step-label,:host-context(.theme-dark) .section-step-label{background:color-mix(in srgb,var(--md-sys-color-primary-container) 54%,transparent);color:color-mix(in srgb,var(--md-sys-color-primary) 88%,white)}:host-context(.mdc-theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions],:host-context(.theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{border-top-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 90%,transparent)}.inline-edit-btn{margin-left:6px;vertical-align:middle;--mdc-icon-button-size: 28px;--mdc-icon-button-icon-size: 16px}.inline-edit-btn mat-icon{font-size:16px;width:16px;height:16px}.section-body.collapsed{border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);border-radius:6px;padding:8px 10px}.section-collapsed-placeholder{display:flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.95rem}.section-collapsed-placeholder mat-icon{font-size:20px;width:20px;height:20px}.form-row{display:flex;gap:1.1rem;margin-bottom:var(--pfx-field-gap, 1.1rem);transition:all .2s ease;border-radius:6px;position:relative}.praxis-dynamic-form.pfx-mounting .form-row{opacity:0;transform:translateY(var(--pdx-form-mount-offset, 6px));animation:pdxFormMount var(--pdx-form-mount-duration, .16s) ease-out both;animation-delay:calc(var(--pfx-mount-index, 0) * var(--pdx-form-mount-stagger, 20ms))}@media(prefers-reduced-motion:reduce){.praxis-dynamic-form.pfx-mounting .form-row{animation:none;opacity:1;transform:none}}@keyframes pdxFormMount{to{opacity:1;transform:translateY(0)}}.praxis-dynamic-form .mat-mdc-form-field{width:100%;margin-bottom:var(--pfx-field-gap, 10px);font-family:inherit;--mdc-filled-text-field-container-color: var(--pfx-form-field-surface-rest);--mdc-filled-text-field-focus-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-active-indicator-color: var(--pfx-editorial-form-field-outline);--mdc-filled-text-field-hover-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-filled-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-caret-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-input-text-placeholder-color: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 82%, transparent );--mdc-outlined-text-field-outline-color: var(--pfx-editorial-form-field-outline);--mdc-outlined-text-field-hover-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-outlined-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-outlined-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-filled-text-field-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-filled-text-field-focus-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-outline-width: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-focus-outline-width: var(--pfx-editorial-form-field-border-width);--mat-select-enabled-trigger-text-color: var(--pfx-editorial-form-text);--mat-select-enabled-arrow-color: var(--pfx-form-label-muted);--mat-form-field-enabled-select-arrow-color: var(--pfx-form-label-muted);--mat-form-field-focus-select-arrow-color: var(--pfx-editorial-form-accent);--mat-form-field-hover-state-layer-opacity: 0;--mat-form-field-focus-state-layer-opacity: 0}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field{font-family:var(--editorial-body-font-family, inherit)}.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{background:var(--pfx-form-field-surface-rest);border-radius:var(--pfx-editorial-form-field-radius);min-height:var(--pfx-form-field-min-height);transition:background-color .16s ease,box-shadow .16s ease,border-color .16s ease}.praxis-dynamic-form.editorial-visual-context .mat-mdc-text-field-wrapper,.praxis-dynamic-form.editorial-visual-context .mdc-text-field,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--filled,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--outlined{background-color:var(--pfx-form-field-surface-rest)!important;background:var(--pfx-form-field-surface-rest)!important}.praxis-dynamic-form .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-form-label-muted)}.praxis-dynamic-form .mat-mdc-input-element,.praxis-dynamic-form .mat-mdc-select-value-text,.praxis-dynamic-form .mat-mdc-form-field-infix,.praxis-dynamic-form .mat-mdc-select-min-line{color:var(--pfx-editorial-form-text)}.praxis-dynamic-form .mat-mdc-form-field:hover .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field:hover .mdc-text-field,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mdc-text-field{background:var(--pfx-form-field-surface-focus)}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-value-text,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field-infix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-min-line,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input{color:var(--pfx-editorial-form-text)!important;-webkit-text-fill-color:var(--pfx-editorial-form-text)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-editorial-form-text-muted)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 68%,transparent)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element::placeholder,.praxis-dynamic-form.editorial-visual-context textarea.mat-mdc-input-element::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 58%,transparent)!important}.praxis-dynamic-form .mat-mdc-radio-button,.praxis-dynamic-form .mat-mdc-checkbox,.praxis-dynamic-form .mat-mdc-slide-toggle{--mdc-radio-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-checkmark-color: var(--pfx-editorial-form-accent-text);--mdc-checkbox-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-focus-state-layer-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-handle-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-track-color: color-mix(in srgb, var(--pfx-editorial-form-accent) 45%, #fff)}.praxis-dynamic-form [data-field-type=input],.praxis-dynamic-form [data-field-type=textarea],.praxis-dynamic-form [data-field-type=email],.praxis-dynamic-form [data-field-type=password],.praxis-dynamic-form [data-field-type=url],.praxis-dynamic-form [data-field-type=search],.praxis-dynamic-form [data-field-type=phone],.praxis-dynamic-form [data-field-type=numericTextBox],.praxis-dynamic-form [data-field-type=currency],.praxis-dynamic-form [data-field-type=cpfCnpj],.praxis-dynamic-form [data-field-type=date],.praxis-dynamic-form [data-field-type=dateInput],.praxis-dynamic-form [data-field-type=dateRange],.praxis-dynamic-form [data-field-type=dateTimeLocal],.praxis-dynamic-form [data-field-type=time],.praxis-dynamic-form [data-field-type=timePicker],.praxis-dynamic-form [data-field-type=timeRange],.praxis-dynamic-form [data-field-type=month],.praxis-dynamic-form [data-field-type=week],.praxis-dynamic-form [data-field-type=yearInput],.praxis-dynamic-form [data-field-type=select],.praxis-dynamic-form [data-field-type=multi-select],.praxis-dynamic-form [data-field-type=searchable-select],.praxis-dynamic-form [data-field-type=async-select],.praxis-dynamic-form [data-field-type=autocomplete],.praxis-dynamic-form [data-field-type=tree-select],.praxis-dynamic-form [data-field-type=multi-select-tree],.praxis-dynamic-form [data-field-type=priceRange],.praxis-dynamic-form [data-field-type=file-upload]{display:block;width:100%;min-width:0}.praxis-dynamic-form .mat-mdc-form-field-subscript-wrapper{min-height:var(--pfx-subscript-min-h, 22px)}.form-row:last-child{margin-bottom:0}.form-column{display:grid;align-content:start;gap:var(--pfx-field-gap, 10px);flex:1;min-width:0;transition:all .2s ease;border-radius:4px;position:relative}.form-row.grid-12{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.align-start{align-self:flex-start}.align-center{align-self:center}.align-end{align-self:flex-end}.align-stretch{align-self:stretch}.form-blocking-overlay{position:absolute;inset:0;background:transparent;color:var(--md-sys-color-on-surface);backdrop-filter:blur(2px) saturate(103%);-webkit-backdrop-filter:blur(2px) saturate(103%);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;z-index:10;pointer-events:all}@media(max-width:768px){.form-row{flex-direction:column;gap:.5rem}.form-section{padding:1rem}.section-heading{gap:10px;margin-bottom:16px;padding-bottom:14px}}.section-title{display:flex;align-items:center;gap:8px}.section-title .section-title-icon{font-size:1.25em;line-height:1}.section-title-avatar{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px));display:inline-flex;align-items:center;justify-content:center;width:var(--_pfx-form-section-avatar-size);height:var(--_pfx-form-section-avatar-size);border-radius:999px;flex:0 0 var(--_pfx-form-section-avatar-size);overflow:hidden}.section-title-avatar.size-sm{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-sm, 24px)}.section-title-avatar.size-md{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px))}.section-title-avatar.size-lg{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-lg, 40px)}.section-title-avatar-image{object-fit:cover;border:1px solid color-mix(in srgb,var(--pfx-form-section-divider) 72%,transparent);background:var(--pfx-form-section-surface-flat)}.section-title-avatar-text,.section-title-avatar-placeholder{background:color-mix(in srgb,var(--pfx-editorial-form-accent) 14%,var(--pfx-form-section-surface-flat));color:color-mix(in srgb,var(--pfx-editorial-form-accent) 82%,var(--pfx-form-label-strong) 18%);font-size:calc(var(--_pfx-form-section-avatar-size) * .41);font-weight:800;letter-spacing:.04em;text-transform:uppercase}.section-title-avatar-placeholder mat-icon{font-size:calc(var(--_pfx-form-section-avatar-size) * .5625);width:calc(var(--_pfx-form-section-avatar-size) * .5625);height:calc(var(--_pfx-form-section-avatar-size) * .5625);line-height:calc(var(--_pfx-form-section-avatar-size) * .5625)}.section-title-avatar-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent"], exportAs: ["dynamicWidgetLoader"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i15.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i17.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: CanvasToolbarComponent, selector: "praxis-canvas-toolbar", inputs: ["selectedElement"], outputs: ["editMetadata", "delete", "moveUp", "moveDown", "selectPath", "requestClose", "toggleReadonly", "toggleRequired", "toggleHidden", "toggleDisabled"] }, { kind: "component", type: PraxisFormActionsComponent, selector: "praxis-form-actions", inputs: ["actions", "editorialVisualContext", "isSubmitting", "formIsValid", "submitError", "formId", "actionOverrides"], outputs: ["action"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }, { kind: "component", type: PraxisAiAssistantComponent, selector: "praxis-ai-assistant", inputs: ["adapter", "riskPolicy", "allowManualPatchEdit"] }] });
11246
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: PraxisDynamicForm, isStandalone: true, selector: "praxis-dynamic-form", inputs: { resourcePath: "resourcePath", resourceId: "resourceId", editorialContext: "editorialContext", mode: "mode", config: "config", schemaSource: "schemaSource", enableCustomization: "enableCustomization", formId: "formId", componentInstanceId: "componentInstanceId", layout: "layout", backConfig: "backConfig", hooks: "hooks", removeEmptyContainersOnSave: "removeEmptyContainersOnSave", reactiveValidation: "reactiveValidation", reactiveValidationDebounceMs: "reactiveValidationDebounceMs", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", readonlyModeGlobal: "readonlyModeGlobal", disabledModeGlobal: "disabledModeGlobal", presentationModeGlobal: "presentationModeGlobal", visibleGlobal: "visibleGlobal", customEndpoints: "customEndpoints" }, outputs: { formSubmit: "formSubmit", formCancel: "formCancel", formReset: "formReset", configChange: "configChange", formReady: "formReady", valueChange: "valueChange", syncCompleted: "syncCompleted", initializationError: "initializationError", loadingStateChange: "loadingStateChange", enableCustomizationChange: "enableCustomizationChange", customAction: "customAction", actionConfirmation: "actionConfirmation", schemaStatusChange: "schemaStatusChange", fieldRenderError: "fieldRenderError", widgetEvent: "widgetEvent" }, viewQueries: [{ propertyName: "formHost", first: true, predicate: ["formHost"], descendants: true }, { propertyName: "fieldLoaders", predicate: DynamicFieldLoaderDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (isLoading) {\n<!-- Loading State -->\n<div class=\"form-loading\">\n <mat-progress-spinner diameter=\"40\"></mat-progress-spinner>\n <p>Carregando formul\u00E1rio...</p>\n</div>\n} @else if (initializationStatus === 'error') {\n<!-- Error State -->\n<div class=\"form-error\">\n <mat-icon color=\"warn\" [praxisIcon]=\"'error'\"></mat-icon>\n <h3>{{ getErrorTitle() }}</h3>\n <p>{{ currentErrorMessage }}</p>\n @if (isRecoverable) {\n <button mat-stroked-button (click)=\"retryInitialization()\">\n <mat-icon [praxisIcon]=\"'refresh'\"></mat-icon>\n Tentar Novamente\n </button>\n }\n <button mat-button (click)=\"showDetailedError()\" class=\"show-details\">\n Ver Detalhes T\u00E9cnicos\n </button>\n <!-- Permitir corre\u00E7\u00E3o do resourcePath diretamente do estado de erro -->\n <button mat-flat-button color=\"primary\" (click)=\"openQuickConnect()\" class=\"connect-action\">\n <mat-icon [praxisIcon]=\"'bolt'\"></mat-icon>\n Conectar a recurso\n </button>\n</div>\n} @else if (initializationStatus === 'success') {\n<!-- Inline banner for schema change (only when customization is enabled) -->\n@if (shouldShowOutdatedInline()) {\n<div class=\"pfx-form-info-banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"text\">O schema do servidor mudou. Reconciliar agora?</div>\n <div class=\"actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"openConfigEditor()\">\n <mat-icon [praxisIcon]=\"'sync'\"></mat-icon>\n Reconciliar\n </button>\n <button mat-button (click)=\"onSnoozeOutdated()\">Lembrar depois</button>\n <button mat-button (click)=\"onIgnoreOutdated()\">Ignorar</button>\n </div>\n</div>\n}\n\n<!-- Configuration Controls -->\n@if (shouldShowConfigControls && enableCustomization) {\n<div class=\"form-config-controls\">\n <praxis-ai-assistant [adapter]=\"aiAdapter\"></praxis-ai-assistant>\n <button type=\"button\" mat-icon-button (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configurar formul\u00E1rio'\">\n <mat-icon [praxisIcon]=\"'settings'\"></mat-icon>\n </button>\n <button type=\"button\" mat-icon-button (click)=\"disconnect()\" matTooltip=\"Desconectar da fonte de dados\"\n [disabled]=\"isLoading\">\n <mat-icon [praxisIcon]=\"'link_off'\"></mat-icon>\n </button>\n</div>\n}\n\n<!-- Form Content -->\n@if (!resourcePath && (!config.sections || config.sections.length === 0)) {\n<praxis-empty-state-card icon=\"link\" [title]=\"'Conecte o formul\u00E1rio \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para gerar automaticamente os campos do formul\u00E1rio.'\"\n [primaryAction]=\"{ label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) }\"></praxis-empty-state-card>\n}\n<form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\" [class.readonly-mode]=\"effectiveReadonly\"\n [class.editorial-visual-context]=\"hasEditorialVisualContext()\"\n [class.pfx-mounting]=\"isMounting\" [formGroup]=\"form\"\n [ngClass]=\"{\n 'pres-compact': presentationVars.compact,\n 'pres-label-left': presentationVars.labelPosition === 'left',\n 'pres-label-above': presentationVars.labelPosition === 'above'\n }\" [style.--pfx-pres-label-align]=\"presentationVars.labelAlign\"\n [style.--pfx-pres-label-size]=\"presentationVars.labelSize\"\n [style.--pfx-pres-label-width]=\"presentationVars.labelWidth\"\n [style.--pfx-pres-row-gap]=\"presentationVars.density === 'compact' ? '6px' : (presentationVars.density === 'cozy' ? '8px' : '10px')\"\n [style.--pfx-pres-row-padding]=\"presentationVars.density === 'compact' ? '2px 0' : (presentationVars.density === 'cozy' ? '6px 0' : '8px 0')\"\n [style.--pfx-pres-value-align]=\"presentationVars.valueAlign\"\n [style.--pfx-pres-value-size]=\"presentationVars.valueSize\"\n [style.--pdx-form-mount-duration]=\"getMountDurationVar()\"\n [style.--pdx-form-mount-offset]=\"getMountOffsetVar()\"\n [style.--pdx-form-mount-stagger]=\"getMountStaggerVar()\"\n class=\"praxis-dynamic-form\">\n <praxis-canvas-toolbar (editMetadata)=\"openSelectedElementEditor()\" (selectPath)=\"onSelectPath($event)\"\n (moveUp)=\"onToolbarMove('up')\" (moveDown)=\"onToolbarMove('down')\" (toggleReadonly)=\"onToolbarToggleReadonly()\"\n (toggleRequired)=\"onToolbarToggleRequired()\" (toggleHidden)=\"onToolbarToggleHidden()\"\n (toggleDisabled)=\"onToolbarToggleDisabled()\" (requestClose)=\"onToolbarRequestClose()\"\n *ngIf=\"enableCustomization && selectedElement\" [selectedElement]=\"selectedElement\"\n [style.transform]=\"toolbarTransform\"></praxis-canvas-toolbar>\n\n @if (formBlocksBefore.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before\" data-editorial-placement=\"before\">\n @for (block of formBlocksBefore; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('before', $event)\">\n </ng-container>\n }\n </section>\n }\n\n @if (actionPlacement === 'top' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"top\" [actions]=\"config.actions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"form.valid\" [submitError]=\"submitError\" [formId]=\"formId\" [actionOverrides]=\"actionRuleProps\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @for (section of config.sections; track (section.id ?? $index); let sectionIndex = $index;\n let last = $last) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n @if (isSectionVisible(section)) {\n <div #sectionEl class=\"form-section canvas-element\" data-canvas-type=\"section\" [attr.data-section-id]=\"section.id\"\n [attr.data-section-index]=\"sectionIndex\" (mouseenter)=\"onElementMouseEnter($event, 'section', section, sectionEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'section', section, sectionEl)\"\n [class.selected]=\"selectedElement?.domElement === sectionEl\"\n [class.hovered]=\"hoveredElement?.domElement === sectionEl && selectedElement?.domElement !== sectionEl\"\n [attr.data-section-appearance]=\"getSectionAppearance(section) || null\"\n [style.marginBottom.px]=\"!last ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n >\n <div class=\"section-heading-text\" [matTooltip]=\"getSectionHeaderTooltip(section) || null\"\n [matTooltipDisabled]=\"!getSectionHeaderTooltip(section)\">\n @if (getSectionStepLabel(section)) {\n <div class=\"section-step-label\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionStepLabel(section) }}\n </div>\n }\n @if (getSectionTitle(section)) {\n <h3 class=\"section-title\" [class.title-large]=\"getSectionTitleStyle(section) === 'titleLarge'\"\n [class.title-medium]=\"getSectionTitleStyle(section) === 'titleMedium'\"\n [class.title-small]=\"getSectionTitleStyle(section) === 'titleSmall'\"\n [class.headline-small]=\"getSectionTitleStyle(section) === 'headlineSmall'\"\n [style.marginBottom.px]=\"getSectionTitleGapBottom(section) ?? 20\" [style.color]=\"getSectionTitleColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [attr.id]=\"sectionPanelId(section, sectionIndex) + '-title'\">\n @let sectionHeaderVisual = getSectionHeaderVisual(section);\n @let sectionHeaderAvatarSize = getSectionHeaderAvatarSize(section);\n @if (sectionHeaderVisual.kind === 'icon') {\n <mat-icon class=\"section-title-icon\" aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.kind === 'image') {\n <img class=\"section-title-avatar section-title-avatar-image\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\"\n [src]=\"sectionHeaderVisual.src\" [alt]=\"sectionHeaderVisual.alt\" />\n }\n @if (sectionHeaderVisual.kind === 'initials') {\n <span class=\"section-title-avatar section-title-avatar-text\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n {{ sectionHeaderVisual.text }}\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n @if (sectionHeaderVisual.kind === 'placeholder') {\n <span class=\"section-title-avatar section-title-avatar-placeholder\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n @if (sectionHeaderVisual.icon) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.text) {\n <span>{{ sectionHeaderVisual.text }}</span>\n }\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n {{ getSectionTitle(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" mat-icon-button (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\n <mat-icon>edit</mat-icon>\n </button>\n }\n </h3>\n }\n @if (getSectionDescription(section)) {\n <p class=\"section-description\" [class.body-large]=\"getSectionDescriptionStyle(section) === 'bodyLarge'\"\n [class.body-medium]=\"getSectionDescriptionStyle(section) === 'bodyMedium'\"\n [class.body-small]=\"getSectionDescriptionStyle(section) === 'bodySmall'\"\n [style.marginBottom.px]=\"getSectionDescriptionGapBottom(section) ?? 8\" [style.color]=\"getSectionDescriptionColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionDescription(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" mat-icon-button\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\n <mat-icon>edit</mat-icon>\n </button>\n }\n </p>\n }\n </div>\n @if (getSectionHeaderActions(section).length) {\n <div class=\"section-heading-actions\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n @for (action of getSectionHeaderActions(section); track action.id) {\n <button\n type=\"button\"\n class=\"section-heading-action-btn\"\n mat-icon-button\n [color]=\"getSectionHeaderActionColor(action)\"\n [disabled]=\"isSectionHeaderActionDisabled(action)\"\n [matTooltip]=\"getSectionHeaderActionTooltip(action)\"\n [attr.aria-label]=\"action.label\"\n [attr.aria-busy]=\"action.loading ? 'true' : null\"\n [ngClass]=\"getSectionHeaderActionNgClass(action)\"\n [ngStyle]=\"getSectionHeaderActionStyles(action)\"\n (click)=\"onSectionHeaderActionClick(section, action, $event)\"\n >\n @if (action.loading) {\n <mat-progress-spinner diameter=\"16\" mode=\"indeterminate\"></mat-progress-spinner>\n <span class=\"section-heading-action-sr-only\">{{ getSectionHeaderActionLoadingLabel(action) }}</span>\n } @else {\n <mat-icon [praxisIcon]=\"action.icon\"></mat-icon>\n }\n </button>\n }\n </div>\n }\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" mat-icon-button\n (click)=\"toggleSectionCollapse($event, section)\" [attr.aria-expanded]=\"!isSectionCollapsed(section)\"\n [attr.aria-controls]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-label]=\"isSectionCollapsed(section) ? 'Expandir se\u00E7\u00E3o' : 'Recolher se\u00E7\u00E3o'\">\n <mat-icon [praxisIcon]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\"></mat-icon>\n </button>\n }\n </div>\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-labelledby]=\"getSectionTitle(section) ? sectionPanelId(section, sectionIndex) + '-title' : null\">\n @if (!isSectionCollapsed(section)) {\n @for (row of section.rows; track (row.id ?? $index); let rowIndex = $index) {\n @if (isRowVisible(row)) {\n <div class=\"row-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n <div #rowEl class=\"form-row grid-12 canvas-element\" data-canvas-type=\"row\" [attr.data-row-index]=\"rowIndex\"\n [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\" [style.--pfx-grid-gap.px]=\"getRowGap(row)\"\n [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [style.--pfx-mount-index]=\"rowIndex\"\n [style.marginBottom.px]=\"rowIndex < section.rows.length - 1 ? (getRowRowGap(row) ?? null) : null\"\n [ngClass]=\"getRowClasses(row)\" [ngStyle]=\"getRowStyles(row)\"\n (mouseenter)=\"onElementMouseEnter($event, 'row', row, rowEl)\" (mouseleave)=\"onElementMouseLeave($event)\"\n (click)=\"onElementClick($event, 'row', row, rowEl)\" [class.selected]=\"selectedElement?.domElement === rowEl\"\n [class.hovered]=\"hoveredElement?.domElement === rowEl && selectedElement?.domElement !== rowEl\">\n @for (column of row.columns; track (column.id ?? $index); let colIndex = $index) {\n @if (isColumnVisible(column)) {\n <div class=\"column-drop-wrapper\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\">\n <div #colEl class=\"form-column canvas-element\" [ngClass]=\"getColumnClasses(column)\"\n [style.padding.px]=\"getColumnPadding(column)\" [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [ngStyle]=\"getColumnStyles(column)\" [attr.data-testid]=\"column.testId || null\"\n [attr.data-row-gap]=\"getRowRowGap(row)\" data-canvas-type=\"column\" [attr.data-column-index]=\"colIndex\"\n [attr.data-row-index]=\"rowIndex\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\"\n [attr.data-column-id]=\"column.id\" (mouseenter)=\"onElementMouseEnter($event, 'column', column, colEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'column', column, colEl)\"\n [class.selected]=\"selectedElement?.domElement === colEl\"\n [class.hovered]=\"hoveredElement?.domElement === colEl && selectedElement?.domElement !== colEl\">\n <ng-container dynamicFieldLoader [fields]=\"getColumnFields(column)\" [formGroup]=\"form\"\n [readonlyMode]=\"readonlyModeGlobal === null ? null : readonlyModeGlobal\"\n [disabledMode]=\"disabledModeGlobal === null ? null : disabledModeGlobal\"\n [presentationMode]=\"presentationForLoader\" [visible]=\"visibleGlobal === null ? null : visibleGlobal\"\n [canvasMode]=\"enableCustomization\" (canvasMouseEnter)=\"onFieldMouseEnter($event)\"\n (canvasMouseLeave)=\"onFieldMouseLeave($event)\" (canvasClick)=\"onFieldClick($event)\"\n (renderError)=\"onFieldRenderError($event)\">\n </ng-container>\n </div>\n </div>\n } }\n </div>\n </div>\n }\n }\n } @else {\n <div class=\"section-collapsed-placeholder\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'unfold_more'\"></mat-icon>\n <span>{{ getSectionCollapsedSummary(section) }}</span>\n </div>\n }\n @if (last && beforeActionsPlacement === 'insideLastSection' && formBlocksBeforeActions.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n @for (block of formBlocksBeforeActions; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('beforeActions', $event)\">\n </ng-container>\n }\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && last && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"config.actions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"form.valid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n </div>\n <!-- Overlay de bloqueio durante submiss\u00E3o -->\n @if (submitting) {\n <div class=\"form-blocking-overlay\" aria-live=\"polite\">\n <mat-progress-spinner diameter=\"40\" color=\"primary\"></mat-progress-spinner>\n <p>{{ config.messages?.loading?.submit || 'Salvando...' }}</p>\n </div>\n }\n </div>\n\n @if (enableCustomization && selectedElement?.domElement === sectionEl) {\n <div class=\"add-section-container\">\n <div class=\"add-section-line\"></div>\n <button mat-fab color=\"primary\" aria-label=\"Adicionar nova se\u00E7\u00E3o\" (click)=\"addNewSectionAfter(sectionIndex)\"\n matTooltip=\"Adicionar nova se\u00E7\u00E3o aqui\">\n <mat-icon [praxisIcon]=\"'add'\"></mat-icon>\n </button>\n <div class=\"add-section-line\"></div>\n </div>\n }\n }\n </div>\n }\n\n @if (beforeActionsPlacement !== 'insideLastSection' && formBlocksBeforeActions.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n @for (block of formBlocksBeforeActions; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('beforeActions', $event)\">\n </ng-container>\n }\n </section>\n }\n\n @if (actionPlacement === 'afterSections' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"afterSections\" [actions]=\"config.actions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"form.valid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @if (formBlocksAfter.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-after\" data-editorial-placement=\"after\">\n @for (block of formBlocksAfter; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('after', $event)\">\n </ng-container>\n }\n </section>\n }\n</form>\n@if (!enableCustomization && mode === 'view') {\n<div class=\"ai-floating-assistant\">\n <praxis-ai-assistant [adapter]=\"aiAdapter\"></praxis-ai-assistant>\n</div>\n}\n}\n", styles: ["@charset \"UTF-8\";.span-xs-1{grid-column:span 1}.span-xs-2{grid-column:span 2}.span-xs-3{grid-column:span 3}.span-xs-4{grid-column:span 4}.span-xs-5{grid-column:span 5}.span-xs-6{grid-column:span 6}.span-xs-7{grid-column:span 7}.span-xs-8{grid-column:span 8}.span-xs-9{grid-column:span 9}.span-xs-10{grid-column:span 10}.span-xs-11{grid-column:span 11}.span-xs-12{grid-column:span 12}.offset-xs-0{margin-left:0%}.offset-xs-1{margin-left:calc(1 / 12 * 100%)}.offset-xs-2{margin-left:calc(2 / 12 * 100%)}.offset-xs-3{margin-left:25%}.offset-xs-4{margin-left:calc(4 / 12 * 100%)}.offset-xs-5{margin-left:calc(5 / 12 * 100%)}.offset-xs-6{margin-left:50%}.offset-xs-7{margin-left:calc(7 / 12 * 100%)}.offset-xs-8{margin-left:calc(8 / 12 * 100%)}.offset-xs-9{margin-left:75%}.offset-xs-10{margin-left:calc(10 / 12 * 100%)}.offset-xs-11{margin-left:calc(11 / 12 * 100%)}.order-xs--12{order:-12}.order-xs--11{order:-11}.order-xs--10{order:-10}.order-xs--9{order:-9}.order-xs--8{order:-8}.order-xs--7{order:-7}.order-xs--6{order:-6}.order-xs--5{order:-5}.order-xs--4{order:-4}.order-xs--3{order:-3}.order-xs--2{order:-2}.order-xs--1{order:-1}.order-xs-0{order:0}.order-xs-1{order:1}.order-xs-2{order:2}.order-xs-3{order:3}.order-xs-4{order:4}.order-xs-5{order:5}.order-xs-6{order:6}.order-xs-7{order:7}.order-xs-8{order:8}.order-xs-9{order:9}.order-xs-10{order:10}.order-xs-11{order:11}.order-xs-12{order:12}.hidden-xs{display:none}@media(min-width:600px){.span-sm-1{grid-column:span 1}.span-sm-2{grid-column:span 2}.span-sm-3{grid-column:span 3}.span-sm-4{grid-column:span 4}.span-sm-5{grid-column:span 5}.span-sm-6{grid-column:span 6}.span-sm-7{grid-column:span 7}.span-sm-8{grid-column:span 8}.span-sm-9{grid-column:span 9}.span-sm-10{grid-column:span 10}.span-sm-11{grid-column:span 11}.span-sm-12{grid-column:span 12}.offset-sm-0{margin-left:0%}.offset-sm-1{margin-left:calc(1 / 12 * 100%)}.offset-sm-2{margin-left:calc(2 / 12 * 100%)}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:calc(4 / 12 * 100%)}.offset-sm-5{margin-left:calc(5 / 12 * 100%)}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:calc(7 / 12 * 100%)}.offset-sm-8{margin-left:calc(8 / 12 * 100%)}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:calc(10 / 12 * 100%)}.offset-sm-11{margin-left:calc(11 / 12 * 100%)}.order-sm--12{order:-12}.order-sm--11{order:-11}.order-sm--10{order:-10}.order-sm--9{order:-9}.order-sm--8{order:-8}.order-sm--7{order:-7}.order-sm--6{order:-6}.order-sm--5{order:-5}.order-sm--4{order:-4}.order-sm--3{order:-3}.order-sm--2{order:-2}.order-sm--1{order:-1}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.hidden-sm{display:none}}@media(min-width:900px){.span-md-1{grid-column:span 1}.span-md-2{grid-column:span 2}.span-md-3{grid-column:span 3}.span-md-4{grid-column:span 4}.span-md-5{grid-column:span 5}.span-md-6{grid-column:span 6}.span-md-7{grid-column:span 7}.span-md-8{grid-column:span 8}.span-md-9{grid-column:span 9}.span-md-10{grid-column:span 10}.span-md-11{grid-column:span 11}.span-md-12{grid-column:span 12}.offset-md-0{margin-left:0%}.offset-md-1{margin-left:calc(1 / 12 * 100%)}.offset-md-2{margin-left:calc(2 / 12 * 100%)}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:calc(4 / 12 * 100%)}.offset-md-5{margin-left:calc(5 / 12 * 100%)}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:calc(7 / 12 * 100%)}.offset-md-8{margin-left:calc(8 / 12 * 100%)}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:calc(10 / 12 * 100%)}.offset-md-11{margin-left:calc(11 / 12 * 100%)}.order-md--12{order:-12}.order-md--11{order:-11}.order-md--10{order:-10}.order-md--9{order:-9}.order-md--8{order:-8}.order-md--7{order:-7}.order-md--6{order:-6}.order-md--5{order:-5}.order-md--4{order:-4}.order-md--3{order:-3}.order-md--2{order:-2}.order-md--1{order:-1}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.hidden-md{display:none}}@media(min-width:1200px){.span-lg-1{grid-column:span 1}.span-lg-2{grid-column:span 2}.span-lg-3{grid-column:span 3}.span-lg-4{grid-column:span 4}.span-lg-5{grid-column:span 5}.span-lg-6{grid-column:span 6}.span-lg-7{grid-column:span 7}.span-lg-8{grid-column:span 8}.span-lg-9{grid-column:span 9}.span-lg-10{grid-column:span 10}.span-lg-11{grid-column:span 11}.span-lg-12{grid-column:span 12}.offset-lg-0{margin-left:0%}.offset-lg-1{margin-left:calc(1 / 12 * 100%)}.offset-lg-2{margin-left:calc(2 / 12 * 100%)}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:calc(4 / 12 * 100%)}.offset-lg-5{margin-left:calc(5 / 12 * 100%)}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:calc(7 / 12 * 100%)}.offset-lg-8{margin-left:calc(8 / 12 * 100%)}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:calc(10 / 12 * 100%)}.offset-lg-11{margin-left:calc(11 / 12 * 100%)}.order-lg--12{order:-12}.order-lg--11{order:-11}.order-lg--10{order:-10}.order-lg--9{order:-9}.order-lg--8{order:-8}.order-lg--7{order:-7}.order-lg--6{order:-6}.order-lg--5{order:-5}.order-lg--4{order:-4}.order-lg--3{order:-3}.order-lg--2{order:-2}.order-lg--1{order:-1}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.hidden-lg{display:none}}@media(min-width:1536px){.span-xl-1{grid-column:span 1}.span-xl-2{grid-column:span 2}.span-xl-3{grid-column:span 3}.span-xl-4{grid-column:span 4}.span-xl-5{grid-column:span 5}.span-xl-6{grid-column:span 6}.span-xl-7{grid-column:span 7}.span-xl-8{grid-column:span 8}.span-xl-9{grid-column:span 9}.span-xl-10{grid-column:span 10}.span-xl-11{grid-column:span 11}.span-xl-12{grid-column:span 12}.offset-xl-0{margin-left:0%}.offset-xl-1{margin-left:calc(1 / 12 * 100%)}.offset-xl-2{margin-left:calc(2 / 12 * 100%)}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:calc(4 / 12 * 100%)}.offset-xl-5{margin-left:calc(5 / 12 * 100%)}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:calc(7 / 12 * 100%)}.offset-xl-8{margin-left:calc(8 / 12 * 100%)}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:calc(10 / 12 * 100%)}.offset-xl-11{margin-left:calc(11 / 12 * 100%)}.order-xl--12{order:-12}.order-xl--11{order:-11}.order-xl--10{order:-10}.order-xl--9{order:-9}.order-xl--8{order:-8}.order-xl--7{order:-7}.order-xl--6{order:-6}.order-xl--5{order:-5}.order-xl--4{order:-4}.order-xl--3{order:-3}.order-xl--2{order:-2}.order-xl--1{order:-1}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.hidden-xl{display:none}}.canvas-mode-enabled{--canvas-hit: 14px}.canvas-mode-enabled .canvas-element{position:relative;z-index:0;border-radius:8px;outline:2px solid transparent;outline-offset:2px;transition:outline-color .2s ease,outline-style .2s ease}.canvas-mode-enabled .canvas-element:before{content:\"\";position:absolute;inset:calc(-1 * var(--canvas-hit));pointer-events:none;border-radius:inherit;background:transparent}.canvas-mode-enabled .canvas-element[data-canvas-type=section]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element[data-canvas-type=row]{--outline-color: var(--md-sys-color-secondary)}.canvas-mode-enabled .canvas-element[data-canvas-type=column],.canvas-mode-enabled .canvas-element[data-canvas-type=field]{--outline-color: var(--md-sys-color-tertiary)}.canvas-mode-enabled .canvas-element[data-canvas-type=actions]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element.hovered:not(.selected){outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:dashed}.canvas-mode-enabled .canvas-element.selected{outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:solid;box-shadow:0 0 0 2px var(--outline-color, var(--md-sys-color-primary))}.canvas-mode-enabled .canvas-element.hovered{z-index:1000}.canvas-mode-enabled .canvas-element.selected{z-index:2000}.section-drop-wrapper,.row-drop-wrapper,.column-drop-wrapper{display:contents}.add-section-container{display:flex;align-items:center;justify-content:center;padding:.5rem 0;margin:-.5rem 0;position:relative;z-index:500}.add-section-container .add-section-line{flex-grow:1;height:1px;background:repeating-linear-gradient(90deg,var(--md-sys-color-outline-variant),var(--md-sys-color-outline-variant) 4px,transparent 4px,transparent 8px)}.add-section-container button{margin:0 1rem;transform:scale(.85)}:host{display:block;position:relative}.form-config-controls{position:sticky;top:10px;margin-left:auto;margin-bottom:10px;display:flex;align-items:center;gap:.35rem;z-index:60;background:color-mix(in srgb,var(--md-sys-color-surface) 92%,transparent);padding:6px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);border-radius:999px;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 10px 22px #0f172a14;min-width:0;justify-content:flex-end;pointer-events:none;opacity:.88;transition:opacity .16s ease,box-shadow .16s ease,border-color .16s ease,transform .16s ease}.form-config-controls>*{pointer-events:auto}.praxis-dynamic-form:hover .form-config-controls,.praxis-dynamic-form:focus-within .form-config-controls{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant) 74%);box-shadow:0 14px 28px #0f172a1f;transform:translateY(-1px)}.form-config-controls .mat-icon-button{--mdc-icon-button-state-layer-size: 34px;width:34px;height:34px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);border:1px solid transparent}.form-config-controls .mat-icon-button:hover{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent)}.ai-floating-assistant{position:sticky;right:0;bottom:12px;margin-top:14px;margin-left:auto;width:fit-content;z-index:70;pointer-events:none}.ai-floating-assistant praxis-ai-assistant{pointer-events:auto;display:inline-flex}.ai-floating-assistant .ai-trigger-btn{box-shadow:0 12px 28px #0f172a24}.config-button{color:var(--md-sys-color-primary)}.form-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-on-surface);gap:1rem}.form-loading p{margin:0;font-size:.875rem;opacity:.7}.form-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-error);gap:1rem;border:1px solid var(--md-sys-color-error);border-radius:8px;background-color:var(--md-sys-color-error-container);margin:1rem;box-shadow:0 12px 30px #7f1d1d1f}.form-error h3{margin:0;color:var(--md-sys-color-on-error-container)}.form-error p{margin:0;color:var(--md-sys-color-on-error-container);opacity:.8}.form-error button{margin-top:.5rem}.pfx-form-info-banner{margin-bottom:14px;padding:12px 14px;border-radius:16px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant) 82%);background:color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface) 76%);color:var(--md-sys-color-on-surface);display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.pfx-form-info-banner .text{font-size:.92rem;line-height:1.5;font-weight:600}.pfx-form-info-banner .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.praxis-dynamic-form{display:flex;flex-direction:column;transition:all .3s ease;position:relative;font-family:inherit;font-size:inherit;color:inherit;--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--md-sys-color-surface-container) );--pfx-editorial-form-surface-muted: var(--md-sys-color-surface-container-low);--pfx-editorial-form-border: var( --pfx-form-stroke, var(--md-sys-color-outline-variant) );--pfx-editorial-form-text: var(--md-sys-color-on-surface);--pfx-editorial-form-text-muted: var(--md-sys-color-on-surface-variant);--pfx-editorial-form-field-surface: color-mix( in srgb, var(--pfx-editorial-form-surface-muted) 76%, var(--pfx-editorial-form-surface) 24% );--pfx-editorial-form-field-outline: color-mix( in srgb, var(--pfx-editorial-form-border) 88%, transparent );--pfx-editorial-form-accent: var(--md-sys-color-primary);--pfx-editorial-form-accent-text: var(--md-sys-color-on-primary);--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-field-radius: var(--pfx-form-field-radius, 4px);--pfx-editorial-form-border-width: 1px;--pfx-editorial-form-field-border-width: 1px;--pfx-editorial-form-shadow: none;--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-surface-flat: color-mix( in srgb, var(--pfx-editorial-form-surface) 78%, var(--pfx-editorial-form-surface-muted) 22% );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--pfx-form-label-strong: color-mix( in srgb, var(--pfx-editorial-form-text) 96%, white 4% );--pfx-form-label-muted: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 92%, var(--pfx-editorial-form-text) 8% );--pfx-form-field-surface-rest: color-mix( in srgb, var(--pfx-editorial-form-field-surface) 82%, var(--pfx-editorial-form-surface) 18% );--pfx-form-field-surface-focus: color-mix( in srgb, var(--pfx-editorial-form-accent) 4%, var(--pfx-form-field-surface-rest) 96% );--pfx-form-field-min-height: 48px;--pfx-form-section-padding: clamp(1.1rem, 1.8vw, 1.5rem);--pfx-form-section-gap: 22px;--pfx-form-footer-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 70%, var(--pfx-editorial-form-surface-muted) 30% );--pfx-form-footer-border: color-mix( in srgb, var(--pfx-editorial-form-border) 76%, transparent )}.praxis-dynamic-form.editorial-visual-context{font-family:var(--editorial-body-font-family, inherit);font-size:var(--editorial-body-size, 1rem);color:var(--editorial-text-primary, var(--md-sys-color-on-surface));--pfx-editorial-form-surface: var( --editorial-surface-primary, var(--pfx-form-section-surface, var(--md-sys-color-surface-container)) );--pfx-editorial-form-surface-muted: var( --editorial-surface-secondary, var(--md-sys-color-surface-container-low) );--pfx-editorial-form-border: var( --editorial-border-color, var(--pfx-form-stroke, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-text: var( --editorial-text-primary, var(--md-sys-color-on-surface) );--pfx-editorial-form-text-muted: var( --editorial-text-secondary, var(--md-sys-color-on-surface-variant) );--pfx-editorial-form-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--md-sys-color-primary)) );--pfx-editorial-form-accent-text: var( --editorial-cta-primary-text, var(--editorial-accent-contrast, var(--md-sys-color-on-primary)) );--pfx-editorial-form-radius: var(--editorial-card-radius, 18px);--pfx-editorial-form-field-radius: var( --editorial-field-radius, var(--editorial-card-radius, 14px) );--pfx-editorial-form-border-width: var(--editorial-card-border-width, 1px);--pfx-editorial-form-field-border-width: var(--editorial-field-border-width, 1px);--pfx-editorial-form-shadow: var(--editorial-card-shadow, none);--md-sys-color-surface: var( --pfx-editorial-form-surface, var(--md-sys-color-surface) );--md-sys-color-surface-container: var( --pfx-editorial-form-surface, var(--md-sys-color-surface-container) );--md-sys-color-surface-container-low: var( --pfx-editorial-form-surface-muted, var(--md-sys-color-surface-container-low) );--md-sys-color-surface-variant: var( --pfx-editorial-form-field-surface, var(--md-sys-color-surface-variant) );--md-sys-color-outline: var( --pfx-editorial-form-field-outline, var(--md-sys-color-outline) );--md-sys-color-outline-variant: var( --pfx-editorial-form-border, var(--md-sys-color-outline-variant) );--md-sys-color-on-surface: var( --pfx-editorial-form-text, var(--md-sys-color-on-surface) );--md-sys-color-on-surface-variant: var( --pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant) );--md-sys-color-primary: var( --pfx-editorial-form-accent, var(--md-sys-color-primary) );--md-sys-color-on-primary: var( --pfx-editorial-form-accent-text, var(--md-sys-color-on-primary) );--md-sys-color-on-surface-rgb: var( --editorial-text-primary-rgb, var(--md-sys-color-on-surface-rgb) );--mat-sys-on-surface: var( --pfx-editorial-form-text, var(--mat-sys-on-surface) );--mat-sys-on-surface-variant: var( --pfx-editorial-form-text-muted, var(--mat-sys-on-surface-variant) );--mat-sys-on-surface-rgb: var( --editorial-text-primary-rgb, var(--mat-sys-on-surface-rgb, var(--md-sys-color-on-surface-rgb)) );color:var(--pfx-editorial-form-text);color-scheme:light}.praxis-dynamic-form.presentation-mode .form-row,.praxis-dynamic-form.readonly-mode .form-row{gap:.5rem;margin-bottom:.5rem}.praxis-dynamic-form.presentation-mode .form-section,.praxis-dynamic-form.readonly-mode .form-section{padding:.75rem .875rem}.praxis-dynamic-form.pres-compact .form-row{gap:.35rem;margin-bottom:.35rem}.praxis-dynamic-form.pres-compact .form-section{padding:.5rem .75rem}.praxis-dynamic-form.pres-label-left .praxis-presentation{display:grid;grid-template-columns:var(--pfx-presentation-label-w, 220px) 1fr;align-items:baseline;column-gap:10px}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:right;margin-bottom:0}.form-section{border:1px solid var(--pfx-form-section-divider);border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);box-shadow:none;transition:all .2s ease;position:relative}.praxis-dynamic-form.editorial-visual-context .form-section{border:var(--pfx-editorial-form-border-width) solid var(--pfx-editorial-form-border)!important;background:var(--pfx-editorial-form-surface)!important;box-shadow:var(--editorial-card-shadow, none)}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{background-color:var(--pfx-editorial-form-surface)!important;background-image:linear-gradient(180deg,color-mix(in srgb,var(--editorial-accent, var(--md-sys-color-primary)) 6%,transparent) 0%,transparent 132px)!important;background-repeat:no-repeat!important}.section-drop-wrapper>.form-section{margin-bottom:var(--pfx-section-gap, 20px)}.section-drop-wrapper:last-of-type>.form-section{margin-bottom:0}.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections] .form-actions{margin-top:var(--pfx-actions-gap-top, var(--pfx-section-gap, 20px))}.section-title{margin:0 0 var(--pfx-section-title-mb, 12px) 0;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-size:var(--editorial-step-title-size, 1.12rem);font-weight:700;color:var(--pfx-form-label-strong)}.section-heading{display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding-bottom:18px;border-bottom:1px solid var(--pfx-form-section-divider)}.section-heading.align-center{flex-direction:column;align-items:center;text-align:center}.section-heading.align-center .section-heading-text{display:grid;justify-items:center}.section-step-label{display:inline-flex;align-items:center;min-height:24px;padding:0 10px;margin:0 0 8px;border-radius:999px;background:color-mix(in srgb,var(--pfx-editorial-form-accent) 10%,transparent);color:color-mix(in srgb,var(--pfx-editorial-form-accent) 84%,var(--pfx-form-label-strong) 16%);font-size:.72rem;font-weight:800;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));letter-spacing:.08em;text-transform:uppercase}.section-heading-text{flex:1 1 auto;min-width:0}.section-heading-actions{display:inline-flex;align-items:center;align-self:flex-start;flex-wrap:wrap;gap:4px;margin-left:auto}.section-heading-actions.align-center{align-self:center;margin-left:0}.section-heading-action-btn{color:var(--pfx-form-label-muted)}.section-heading-action-btn .mat-mdc-progress-spinner,.section-heading-action-btn mat-progress-spinner{--mdc-circular-progress-active-indicator-color: currentColor}.section-heading-action-btn.loading{opacity:.72;pointer-events:none}.section-heading-action-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.section-collapse-btn{margin-left:4px;color:var(--pfx-form-label-muted)}.section-title.title-large{font:var(--mdc-typography-title-large, 500 22px/28px system-ui)}.section-title.title-medium{font:var(--mdc-typography-title-medium, 500 16px/24px system-ui)}.section-title.title-small{font:var(--mdc-typography-title-small, 500 14px/20px system-ui)}.section-title.headline-small{font:var(--mdc-typography-headline-small, 600 24px/32px system-ui)}.section-title.title-large,.section-title.title-medium,.section-title.title-small,.section-title.headline-small{font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-weight:var(--editorial-title-weight, 600)}.section-description{margin:0;font-family:var(--editorial-body-font-family, inherit);font-size:.93rem;color:var(--pfx-form-label-muted);line-height:1.6}.section-description.body-large{font:var(--mdc-typography-body-large, 400 16px/24px system-ui)}.section-description.body-medium{font:var(--mdc-typography-body-medium, 400 14px/20px system-ui)}.section-description.body-small{font:var(--mdc-typography-body-small, 400 12px/16px system-ui)}.section-description.body-large,.section-description.body-medium,.section-description.body-small{font-family:var(--editorial-body-font-family, inherit);font-weight:var(--editorial-body-weight, 400)}.section-title.align-center,.section-description.align-center,.section-step-label.align-center{text-align:center}.form-section.section-appearance-plain{border-color:transparent;border-radius:0;padding:0;background:transparent}.form-section.section-appearance-plain .section-heading{margin-bottom:14px}.form-section.section-appearance-step{border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);border-color:var(--pfx-form-section-divider);box-shadow:none}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{border-radius:var(--editorial-card-radius, 20px);box-shadow:none}.form-section.section-appearance-step .section-heading{margin-bottom:22px;padding-bottom:16px;border-bottom:1px solid var(--pfx-form-section-divider)}.form-section.section-appearance-step .section-title{font:var(--mdc-typography-title-large, 700 22px/28px system-ui);color:var(--pfx-form-label-strong);margin-bottom:8px}.form-section.section-appearance-step .section-description{color:var(--pfx-form-label-muted);max-width:60ch}.form-section.section-appearance-step .section-step-label{min-height:24px;padding:0 10px;margin-bottom:10px;box-shadow:none}.form-section.section-appearance-step .section-heading.align-center .section-description{max-width:52ch}.form-section.section-appearance-step .section-body{display:grid;gap:8px;padding-top:0}.form-section.section-appearance-step .form-row{margin-bottom:var(--pfx-field-gap, 1rem)}.form-section.section-appearance-step .form-column{gap:var(--pfx-field-gap, 12px)}.form-section .form-editorial-blocks{display:grid;gap:16px}.form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{margin-top:24px;padding-top:18px;border-top:1px solid var(--pfx-form-section-divider)}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]{gap:18px}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]>*+*{margin-top:2px}.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections] .form-actions{margin-top:18px;padding-top:0}.praxis-dynamic-form>.form-editorial-blocks[data-editorial-placement=after]{margin-top:6px}:host-context(.mdc-theme-dark) .form-section.section-appearance-step,:host-context(.theme-dark) .form-section.section-appearance-step{border-color:color-mix(in srgb,var(--pfx-editorial-form-border) 82%,transparent);box-shadow:none}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-title,:host-context(.theme-dark) .form-section.section-appearance-step .section-title{color:color-mix(in srgb,var(--pfx-editorial-form-text) 96%,white)}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-description,:host-context(.theme-dark) .form-section.section-appearance-step .section-description{color:color-mix(in srgb,var(--pfx-editorial-form-text-muted) 86%,var(--pfx-editorial-form-text) 14%)}:host-context(.mdc-theme-dark) .section-step-label,:host-context(.theme-dark) .section-step-label{background:color-mix(in srgb,var(--md-sys-color-primary-container) 54%,transparent);color:color-mix(in srgb,var(--md-sys-color-primary) 88%,white)}:host-context(.mdc-theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions],:host-context(.theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{border-top-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 90%,transparent)}.inline-edit-btn{margin-left:6px;vertical-align:middle;--mdc-icon-button-size: 28px;--mdc-icon-button-icon-size: 16px}.inline-edit-btn mat-icon{font-size:16px;width:16px;height:16px}.section-body.collapsed{border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);border-radius:6px;padding:8px 10px}.section-collapsed-placeholder{display:flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.95rem}.section-collapsed-placeholder mat-icon{font-size:20px;width:20px;height:20px}.form-row{display:flex;gap:1.1rem;margin-bottom:var(--pfx-field-gap, 1.1rem);transition:all .2s ease;border-radius:6px;position:relative}.praxis-dynamic-form.pfx-mounting .form-row{opacity:0;transform:translateY(var(--pdx-form-mount-offset, 6px));animation:pdxFormMount var(--pdx-form-mount-duration, .16s) ease-out both;animation-delay:calc(var(--pfx-mount-index, 0) * var(--pdx-form-mount-stagger, 20ms))}@media(prefers-reduced-motion:reduce){.praxis-dynamic-form.pfx-mounting .form-row{animation:none;opacity:1;transform:none}}@keyframes pdxFormMount{to{opacity:1;transform:translateY(0)}}.praxis-dynamic-form .mat-mdc-form-field{width:100%;margin-bottom:var(--pfx-field-gap, 10px);font-family:inherit;--mdc-filled-text-field-container-color: var(--pfx-form-field-surface-rest);--mdc-filled-text-field-focus-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-active-indicator-color: var(--pfx-editorial-form-field-outline);--mdc-filled-text-field-hover-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-filled-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-caret-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-input-text-placeholder-color: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 82%, transparent );--mdc-outlined-text-field-outline-color: var(--pfx-editorial-form-field-outline);--mdc-outlined-text-field-hover-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-outlined-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-outlined-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-filled-text-field-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-filled-text-field-focus-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-outline-width: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-focus-outline-width: var(--pfx-editorial-form-field-border-width);--mat-select-enabled-trigger-text-color: var(--pfx-editorial-form-text);--mat-select-enabled-arrow-color: var(--pfx-form-label-muted);--mat-form-field-enabled-select-arrow-color: var(--pfx-form-label-muted);--mat-form-field-focus-select-arrow-color: var(--pfx-editorial-form-accent);--mat-form-field-hover-state-layer-opacity: 0;--mat-form-field-focus-state-layer-opacity: 0}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field{font-family:var(--editorial-body-font-family, inherit)}.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{background:var(--pfx-form-field-surface-rest);border-radius:var(--pfx-editorial-form-field-radius);min-height:var(--pfx-form-field-min-height);transition:background-color .16s ease,box-shadow .16s ease,border-color .16s ease}.praxis-dynamic-form.editorial-visual-context .mat-mdc-text-field-wrapper,.praxis-dynamic-form.editorial-visual-context .mdc-text-field,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--filled,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--outlined{background-color:var(--pfx-form-field-surface-rest)!important;background:var(--pfx-form-field-surface-rest)!important}.praxis-dynamic-form .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-form-label-muted)}.praxis-dynamic-form .mat-mdc-input-element,.praxis-dynamic-form .mat-mdc-select-value-text,.praxis-dynamic-form .mat-mdc-form-field-infix,.praxis-dynamic-form .mat-mdc-select-min-line{color:var(--pfx-editorial-form-text)}.praxis-dynamic-form .mat-mdc-form-field:hover .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field:hover .mdc-text-field,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mdc-text-field{background:var(--pfx-form-field-surface-focus)}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-value-text,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field-infix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-min-line,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input{color:var(--pfx-editorial-form-text)!important;-webkit-text-fill-color:var(--pfx-editorial-form-text)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-editorial-form-text-muted)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 68%,transparent)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element::placeholder,.praxis-dynamic-form.editorial-visual-context textarea.mat-mdc-input-element::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 58%,transparent)!important}.praxis-dynamic-form .mat-mdc-radio-button,.praxis-dynamic-form .mat-mdc-checkbox,.praxis-dynamic-form .mat-mdc-slide-toggle{--mdc-radio-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-checkmark-color: var(--pfx-editorial-form-accent-text);--mdc-checkbox-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-focus-state-layer-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-handle-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-track-color: color-mix(in srgb, var(--pfx-editorial-form-accent) 45%, #fff)}.praxis-dynamic-form [data-field-type=input],.praxis-dynamic-form [data-field-type=textarea],.praxis-dynamic-form [data-field-type=email],.praxis-dynamic-form [data-field-type=password],.praxis-dynamic-form [data-field-type=url],.praxis-dynamic-form [data-field-type=search],.praxis-dynamic-form [data-field-type=phone],.praxis-dynamic-form [data-field-type=numericTextBox],.praxis-dynamic-form [data-field-type=currency],.praxis-dynamic-form [data-field-type=cpfCnpj],.praxis-dynamic-form [data-field-type=date],.praxis-dynamic-form [data-field-type=dateInput],.praxis-dynamic-form [data-field-type=dateRange],.praxis-dynamic-form [data-field-type=dateTimeLocal],.praxis-dynamic-form [data-field-type=time],.praxis-dynamic-form [data-field-type=timePicker],.praxis-dynamic-form [data-field-type=timeRange],.praxis-dynamic-form [data-field-type=month],.praxis-dynamic-form [data-field-type=week],.praxis-dynamic-form [data-field-type=yearInput],.praxis-dynamic-form [data-field-type=select],.praxis-dynamic-form [data-field-type=multi-select],.praxis-dynamic-form [data-field-type=searchable-select],.praxis-dynamic-form [data-field-type=async-select],.praxis-dynamic-form [data-field-type=autocomplete],.praxis-dynamic-form [data-field-type=tree-select],.praxis-dynamic-form [data-field-type=multi-select-tree],.praxis-dynamic-form [data-field-type=priceRange],.praxis-dynamic-form [data-field-type=file-upload]{display:block;width:100%;min-width:0}.praxis-dynamic-form .mat-mdc-form-field-subscript-wrapper{min-height:var(--pfx-subscript-min-h, 22px)}.form-row:last-child{margin-bottom:0}.form-column{display:grid;align-content:start;gap:var(--pfx-field-gap, 10px);flex:1;min-width:0;transition:all .2s ease;border-radius:4px;position:relative}.form-row.grid-12{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.align-start{align-self:flex-start}.align-center{align-self:center}.align-end{align-self:flex-end}.align-stretch{align-self:stretch}.form-blocking-overlay{position:absolute;inset:0;background:transparent;color:var(--md-sys-color-on-surface);backdrop-filter:blur(2px) saturate(103%);-webkit-backdrop-filter:blur(2px) saturate(103%);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;z-index:10;pointer-events:all}@media(max-width:768px){.form-row{flex-direction:column;gap:.5rem}.form-section{padding:1rem}.section-heading{gap:10px;margin-bottom:16px;padding-bottom:14px}}.section-title{display:flex;align-items:center;gap:8px}.section-title .section-title-icon{font-size:1.25em;line-height:1}.section-title-avatar{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px));display:inline-flex;align-items:center;justify-content:center;width:var(--_pfx-form-section-avatar-size);height:var(--_pfx-form-section-avatar-size);border-radius:999px;flex:0 0 var(--_pfx-form-section-avatar-size);overflow:hidden}.section-title-avatar.size-sm{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-sm, 24px)}.section-title-avatar.size-md{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px))}.section-title-avatar.size-lg{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-lg, 40px)}.section-title-avatar-image{object-fit:cover;border:1px solid color-mix(in srgb,var(--pfx-form-section-divider) 72%,transparent);background:var(--pfx-form-section-surface-flat)}.section-title-avatar-text,.section-title-avatar-placeholder{background:color-mix(in srgb,var(--pfx-editorial-form-accent) 14%,var(--pfx-form-section-surface-flat));color:color-mix(in srgb,var(--pfx-editorial-form-accent) 82%,var(--pfx-form-label-strong) 18%);font-size:calc(var(--_pfx-form-section-avatar-size) * .41);font-weight:800;letter-spacing:.04em;text-transform:uppercase}.section-title-avatar-placeholder mat-icon{font-size:calc(var(--_pfx-form-section-avatar-size) * .5625);width:calc(var(--_pfx-form-section-avatar-size) * .5625);height:calc(var(--_pfx-form-section-avatar-size) * .5625);line-height:calc(var(--_pfx-form-section-avatar-size) * .5625)}.section-title-avatar-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: DynamicFieldLoaderDirective, selector: "[dynamicFieldLoader]", inputs: ["fields", "formGroup", "enableExternalControlBinding", "itemTemplate", "debugTrace", "debugTraceLabel", "readonlyMode", "disabledMode", "presentationMode", "visible", "canvasMode"], outputs: ["componentsCreated", "fieldCreated", "fieldDestroyed", "renderError", "canvasMouseEnter", "canvasMouseLeave", "canvasClick"] }, { kind: "directive", type: DynamicWidgetLoaderDirective, selector: "[dynamicWidgetLoader]", inputs: ["dynamicWidgetLoader", "context", "strictValidation", "autoWireOutputs"], outputs: ["widgetEvent"], exportAs: ["dynamicWidgetLoader"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatFabButton, selector: "button[mat-fab], a[mat-fab], button[matFab], a[matFab]", inputs: ["extended"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i15.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatBadgeModule }, { kind: "directive", type: i17.MatBadge, selector: "[matBadge]", inputs: ["matBadgeColor", "matBadgeOverlap", "matBadgeDisabled", "matBadgePosition", "matBadge", "matBadgeDescription", "matBadgeSize", "matBadgeHidden"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: CanvasToolbarComponent, selector: "praxis-canvas-toolbar", inputs: ["selectedElement"], outputs: ["editMetadata", "delete", "moveUp", "moveDown", "selectPath", "requestClose", "toggleReadonly", "toggleRequired", "toggleHidden", "toggleDisabled"] }, { kind: "component", type: PraxisFormActionsComponent, selector: "praxis-form-actions", inputs: ["actions", "editorialVisualContext", "isSubmitting", "formIsValid", "submitError", "formId", "actionOverrides"], outputs: ["action"] }, { kind: "component", type: EmptyStateCardComponent, selector: "praxis-empty-state-card", inputs: ["icon", "title", "description", "primaryAction", "secondaryActions", "inline", "tone"] }, { kind: "component", type: PraxisAiAssistantComponent, selector: "praxis-ai-assistant", inputs: ["adapter", "riskPolicy", "allowManualPatchEdit"] }] });
11058
11247
  }
11059
11248
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDynamicForm, decorators: [{
11060
11249
  type: Component,
@@ -11075,7 +11264,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
11075
11264
  PraxisFormActionsComponent,
11076
11265
  EmptyStateCardComponent,
11077
11266
  PraxisAiAssistantComponent,
11078
- ], template: "@if (isLoading) {\n<!-- Loading State -->\n<div class=\"form-loading\">\n <mat-progress-spinner diameter=\"40\"></mat-progress-spinner>\n <p>Carregando formul\u00E1rio...</p>\n</div>\n} @else if (initializationStatus === 'error') {\n<!-- Error State -->\n<div class=\"form-error\">\n <mat-icon color=\"warn\" [praxisIcon]=\"'error'\"></mat-icon>\n <h3>{{ getErrorTitle() }}</h3>\n <p>{{ currentErrorMessage }}</p>\n @if (isRecoverable) {\n <button mat-stroked-button (click)=\"retryInitialization()\">\n <mat-icon [praxisIcon]=\"'refresh'\"></mat-icon>\n Tentar Novamente\n </button>\n }\n <button mat-button (click)=\"showDetailedError()\" class=\"show-details\">\n Ver Detalhes T\u00E9cnicos\n </button>\n <!-- Permitir corre\u00E7\u00E3o do resourcePath diretamente do estado de erro -->\n <button mat-flat-button color=\"primary\" (click)=\"openQuickConnect()\" class=\"connect-action\">\n <mat-icon [praxisIcon]=\"'bolt'\"></mat-icon>\n Conectar a recurso\n </button>\n</div>\n} @else if (initializationStatus === 'success') {\n<!-- Inline banner for schema change (only when customization is enabled) -->\n@if (shouldShowOutdatedInline()) {\n<div class=\"pfx-form-info-banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"text\">O schema do servidor mudou. Reconciliar agora?</div>\n <div class=\"actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"openConfigEditor()\">\n <mat-icon [praxisIcon]=\"'sync'\"></mat-icon>\n Reconciliar\n </button>\n <button mat-button (click)=\"onSnoozeOutdated()\">Lembrar depois</button>\n <button mat-button (click)=\"onIgnoreOutdated()\">Ignorar</button>\n </div>\n</div>\n}\n\n<!-- Configuration Controls -->\n@if (shouldShowConfigControls && enableCustomization) {\n<div class=\"form-config-controls\">\n <praxis-ai-assistant [adapter]=\"aiAdapter\"></praxis-ai-assistant>\n <button type=\"button\" mat-icon-button (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configurar formul\u00E1rio'\">\n <mat-icon [praxisIcon]=\"'settings'\"></mat-icon>\n </button>\n <button type=\"button\" mat-icon-button (click)=\"disconnect()\" matTooltip=\"Desconectar da fonte de dados\"\n [disabled]=\"isLoading\">\n <mat-icon [praxisIcon]=\"'link_off'\"></mat-icon>\n </button>\n</div>\n}\n\n<!-- Form Content -->\n@if (!resourcePath && (!config.sections || config.sections.length === 0)) {\n<praxis-empty-state-card icon=\"link\" [title]=\"'Conecte o formul\u00E1rio \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para gerar automaticamente os campos do formul\u00E1rio.'\"\n [primaryAction]=\"{ label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) }\"></praxis-empty-state-card>\n}\n<form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\" [class.readonly-mode]=\"effectiveReadonly\"\n [class.editorial-visual-context]=\"hasEditorialVisualContext()\"\n [class.pfx-mounting]=\"isMounting\" [formGroup]=\"form\"\n [ngClass]=\"{\n 'pres-compact': presentationVars.compact,\n 'pres-label-left': presentationVars.labelPosition === 'left',\n 'pres-label-above': presentationVars.labelPosition === 'above'\n }\" [style.--pfx-pres-label-align]=\"presentationVars.labelAlign\"\n [style.--pfx-pres-label-size]=\"presentationVars.labelSize\"\n [style.--pfx-pres-label-width]=\"presentationVars.labelWidth\"\n [style.--pfx-pres-row-gap]=\"presentationVars.density === 'compact' ? '6px' : (presentationVars.density === 'cozy' ? '8px' : '10px')\"\n [style.--pfx-pres-row-padding]=\"presentationVars.density === 'compact' ? '2px 0' : (presentationVars.density === 'cozy' ? '6px 0' : '8px 0')\"\n [style.--pfx-pres-value-align]=\"presentationVars.valueAlign\"\n [style.--pfx-pres-value-size]=\"presentationVars.valueSize\"\n [style.--pdx-form-mount-duration]=\"getMountDurationVar()\"\n [style.--pdx-form-mount-offset]=\"getMountOffsetVar()\"\n [style.--pdx-form-mount-stagger]=\"getMountStaggerVar()\"\n class=\"praxis-dynamic-form\">\n <praxis-canvas-toolbar (editMetadata)=\"openSelectedElementEditor()\" (selectPath)=\"onSelectPath($event)\"\n (moveUp)=\"onToolbarMove('up')\" (moveDown)=\"onToolbarMove('down')\" (toggleReadonly)=\"onToolbarToggleReadonly()\"\n (toggleRequired)=\"onToolbarToggleRequired()\" (toggleHidden)=\"onToolbarToggleHidden()\"\n (toggleDisabled)=\"onToolbarToggleDisabled()\" (requestClose)=\"onToolbarRequestClose()\"\n *ngIf=\"enableCustomization && selectedElement\" [selectedElement]=\"selectedElement\"\n [style.transform]=\"toolbarTransform\"></praxis-canvas-toolbar>\n\n @if (formBlocksBefore.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before\" data-editorial-placement=\"before\">\n @for (block of formBlocksBefore; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('before', $event)\">\n </ng-container>\n }\n </section>\n }\n\n @if (actionPlacement === 'top' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"top\" [actions]=\"config.actions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"form.valid\" [submitError]=\"submitError\" [formId]=\"formId\" [actionOverrides]=\"actionRuleProps\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @for (section of config.sections; track (section.id ?? $index); let sectionIndex = $index;\n let last = $last) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n @if (isSectionVisible(section)) {\n <div #sectionEl class=\"form-section canvas-element\" data-canvas-type=\"section\" [attr.data-section-id]=\"section.id\"\n [attr.data-section-index]=\"sectionIndex\" (mouseenter)=\"onElementMouseEnter($event, 'section', section, sectionEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'section', section, sectionEl)\"\n [class.selected]=\"selectedElement?.domElement === sectionEl\"\n [class.hovered]=\"hoveredElement?.domElement === sectionEl && selectedElement?.domElement !== sectionEl\"\n [attr.data-section-appearance]=\"getSectionAppearance(section) || null\"\n [style.marginBottom.px]=\"!last ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n >\n <div class=\"section-heading-text\" [matTooltip]=\"getSectionHeaderTooltip(section) || null\"\n [matTooltipDisabled]=\"!getSectionHeaderTooltip(section)\">\n @if (getSectionStepLabel(section)) {\n <div class=\"section-step-label\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionStepLabel(section) }}\n </div>\n }\n @if (getSectionTitle(section)) {\n <h3 class=\"section-title\" [class.title-large]=\"getSectionTitleStyle(section) === 'titleLarge'\"\n [class.title-medium]=\"getSectionTitleStyle(section) === 'titleMedium'\"\n [class.title-small]=\"getSectionTitleStyle(section) === 'titleSmall'\"\n [class.headline-small]=\"getSectionTitleStyle(section) === 'headlineSmall'\"\n [style.marginBottom.px]=\"getSectionTitleGapBottom(section) ?? 20\" [style.color]=\"getSectionTitleColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [attr.id]=\"sectionPanelId(section, sectionIndex) + '-title'\">\n @let sectionHeaderVisual = getSectionHeaderVisual(section);\n @let sectionHeaderAvatarSize = getSectionHeaderAvatarSize(section);\n @if (sectionHeaderVisual.kind === 'icon') {\n <mat-icon class=\"section-title-icon\" aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.kind === 'image') {\n <img class=\"section-title-avatar section-title-avatar-image\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\"\n [src]=\"sectionHeaderVisual.src\" [alt]=\"sectionHeaderVisual.alt\" />\n }\n @if (sectionHeaderVisual.kind === 'initials') {\n <span class=\"section-title-avatar section-title-avatar-text\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n {{ sectionHeaderVisual.text }}\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n @if (sectionHeaderVisual.kind === 'placeholder') {\n <span class=\"section-title-avatar section-title-avatar-placeholder\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n @if (sectionHeaderVisual.icon) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.text) {\n <span>{{ sectionHeaderVisual.text }}</span>\n }\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n {{ getSectionTitle(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" mat-icon-button (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\n <mat-icon>edit</mat-icon>\n </button>\n }\n </h3>\n }\n @if (getSectionDescription(section)) {\n <p class=\"section-description\" [class.body-large]=\"getSectionDescriptionStyle(section) === 'bodyLarge'\"\n [class.body-medium]=\"getSectionDescriptionStyle(section) === 'bodyMedium'\"\n [class.body-small]=\"getSectionDescriptionStyle(section) === 'bodySmall'\"\n [style.marginBottom.px]=\"getSectionDescriptionGapBottom(section) ?? 8\" [style.color]=\"getSectionDescriptionColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionDescription(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" mat-icon-button\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\n <mat-icon>edit</mat-icon>\n </button>\n }\n </p>\n }\n </div>\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" mat-icon-button\n (click)=\"toggleSectionCollapse($event, section)\" [attr.aria-expanded]=\"!isSectionCollapsed(section)\"\n [attr.aria-controls]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-label]=\"isSectionCollapsed(section) ? 'Expandir se\u00E7\u00E3o' : 'Recolher se\u00E7\u00E3o'\">\n <mat-icon [praxisIcon]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\"></mat-icon>\n </button>\n }\n </div>\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-labelledby]=\"getSectionTitle(section) ? sectionPanelId(section, sectionIndex) + '-title' : null\">\n @if (!isSectionCollapsed(section)) {\n @for (row of section.rows; track (row.id ?? $index); let rowIndex = $index) {\n @if (isRowVisible(row)) {\n <div class=\"row-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n <div #rowEl class=\"form-row grid-12 canvas-element\" data-canvas-type=\"row\" [attr.data-row-index]=\"rowIndex\"\n [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\" [style.--pfx-grid-gap.px]=\"getRowGap(row)\"\n [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [style.--pfx-mount-index]=\"rowIndex\"\n [style.marginBottom.px]=\"rowIndex < section.rows.length - 1 ? (getRowRowGap(row) ?? null) : null\"\n [ngClass]=\"getRowClasses(row)\" [ngStyle]=\"getRowStyles(row)\"\n (mouseenter)=\"onElementMouseEnter($event, 'row', row, rowEl)\" (mouseleave)=\"onElementMouseLeave($event)\"\n (click)=\"onElementClick($event, 'row', row, rowEl)\" [class.selected]=\"selectedElement?.domElement === rowEl\"\n [class.hovered]=\"hoveredElement?.domElement === rowEl && selectedElement?.domElement !== rowEl\">\n @for (column of row.columns; track (column.id ?? $index); let colIndex = $index) {\n @if (isColumnVisible(column)) {\n <div class=\"column-drop-wrapper\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\">\n <div #colEl class=\"form-column canvas-element\" [ngClass]=\"getColumnClasses(column)\"\n [style.padding.px]=\"getColumnPadding(column)\" [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [ngStyle]=\"getColumnStyles(column)\" [attr.data-testid]=\"column.testId || null\"\n [attr.data-row-gap]=\"getRowRowGap(row)\" data-canvas-type=\"column\" [attr.data-column-index]=\"colIndex\"\n [attr.data-row-index]=\"rowIndex\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\"\n [attr.data-column-id]=\"column.id\" (mouseenter)=\"onElementMouseEnter($event, 'column', column, colEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'column', column, colEl)\"\n [class.selected]=\"selectedElement?.domElement === colEl\"\n [class.hovered]=\"hoveredElement?.domElement === colEl && selectedElement?.domElement !== colEl\">\n <ng-container dynamicFieldLoader [fields]=\"getColumnFields(column)\" [formGroup]=\"form\"\n [readonlyMode]=\"readonlyModeGlobal === null ? null : readonlyModeGlobal\"\n [disabledMode]=\"disabledModeGlobal === null ? null : disabledModeGlobal\"\n [presentationMode]=\"presentationForLoader\" [visible]=\"visibleGlobal === null ? null : visibleGlobal\"\n [canvasMode]=\"enableCustomization\" (canvasMouseEnter)=\"onFieldMouseEnter($event)\"\n (canvasMouseLeave)=\"onFieldMouseLeave($event)\" (canvasClick)=\"onFieldClick($event)\"\n (renderError)=\"onFieldRenderError($event)\">\n </ng-container>\n </div>\n </div>\n } }\n </div>\n </div>\n }\n }\n } @else {\n <div class=\"section-collapsed-placeholder\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'unfold_more'\"></mat-icon>\n <span>{{ getSectionCollapsedSummary(section) }}</span>\n </div>\n }\n @if (last && beforeActionsPlacement === 'insideLastSection' && formBlocksBeforeActions.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n @for (block of formBlocksBeforeActions; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('beforeActions', $event)\">\n </ng-container>\n }\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && last && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"config.actions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"form.valid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n </div>\n <!-- Overlay de bloqueio durante submiss\u00E3o -->\n @if (submitting) {\n <div class=\"form-blocking-overlay\" aria-live=\"polite\">\n <mat-progress-spinner diameter=\"40\" color=\"primary\"></mat-progress-spinner>\n <p>{{ config.messages?.loading?.submit || 'Salvando...' }}</p>\n </div>\n }\n </div>\n\n @if (enableCustomization && selectedElement?.domElement === sectionEl) {\n <div class=\"add-section-container\">\n <div class=\"add-section-line\"></div>\n <button mat-fab color=\"primary\" aria-label=\"Adicionar nova se\u00E7\u00E3o\" (click)=\"addNewSectionAfter(sectionIndex)\"\n matTooltip=\"Adicionar nova se\u00E7\u00E3o aqui\">\n <mat-icon [praxisIcon]=\"'add'\"></mat-icon>\n </button>\n <div class=\"add-section-line\"></div>\n </div>\n }\n }\n </div>\n }\n\n @if (beforeActionsPlacement !== 'insideLastSection' && formBlocksBeforeActions.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n @for (block of formBlocksBeforeActions; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('beforeActions', $event)\">\n </ng-container>\n }\n </section>\n }\n\n @if (actionPlacement === 'afterSections' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"afterSections\" [actions]=\"config.actions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"form.valid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @if (formBlocksAfter.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-after\" data-editorial-placement=\"after\">\n @for (block of formBlocksAfter; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('after', $event)\">\n </ng-container>\n }\n </section>\n }\n</form>\n@if (!enableCustomization && mode === 'view') {\n<div class=\"ai-floating-assistant\">\n <praxis-ai-assistant [adapter]=\"aiAdapter\"></praxis-ai-assistant>\n</div>\n}\n}\n", styles: ["@charset \"UTF-8\";.span-xs-1{grid-column:span 1}.span-xs-2{grid-column:span 2}.span-xs-3{grid-column:span 3}.span-xs-4{grid-column:span 4}.span-xs-5{grid-column:span 5}.span-xs-6{grid-column:span 6}.span-xs-7{grid-column:span 7}.span-xs-8{grid-column:span 8}.span-xs-9{grid-column:span 9}.span-xs-10{grid-column:span 10}.span-xs-11{grid-column:span 11}.span-xs-12{grid-column:span 12}.offset-xs-0{margin-left:0%}.offset-xs-1{margin-left:calc(1 / 12 * 100%)}.offset-xs-2{margin-left:calc(2 / 12 * 100%)}.offset-xs-3{margin-left:25%}.offset-xs-4{margin-left:calc(4 / 12 * 100%)}.offset-xs-5{margin-left:calc(5 / 12 * 100%)}.offset-xs-6{margin-left:50%}.offset-xs-7{margin-left:calc(7 / 12 * 100%)}.offset-xs-8{margin-left:calc(8 / 12 * 100%)}.offset-xs-9{margin-left:75%}.offset-xs-10{margin-left:calc(10 / 12 * 100%)}.offset-xs-11{margin-left:calc(11 / 12 * 100%)}.order-xs--12{order:-12}.order-xs--11{order:-11}.order-xs--10{order:-10}.order-xs--9{order:-9}.order-xs--8{order:-8}.order-xs--7{order:-7}.order-xs--6{order:-6}.order-xs--5{order:-5}.order-xs--4{order:-4}.order-xs--3{order:-3}.order-xs--2{order:-2}.order-xs--1{order:-1}.order-xs-0{order:0}.order-xs-1{order:1}.order-xs-2{order:2}.order-xs-3{order:3}.order-xs-4{order:4}.order-xs-5{order:5}.order-xs-6{order:6}.order-xs-7{order:7}.order-xs-8{order:8}.order-xs-9{order:9}.order-xs-10{order:10}.order-xs-11{order:11}.order-xs-12{order:12}.hidden-xs{display:none}@media(min-width:600px){.span-sm-1{grid-column:span 1}.span-sm-2{grid-column:span 2}.span-sm-3{grid-column:span 3}.span-sm-4{grid-column:span 4}.span-sm-5{grid-column:span 5}.span-sm-6{grid-column:span 6}.span-sm-7{grid-column:span 7}.span-sm-8{grid-column:span 8}.span-sm-9{grid-column:span 9}.span-sm-10{grid-column:span 10}.span-sm-11{grid-column:span 11}.span-sm-12{grid-column:span 12}.offset-sm-0{margin-left:0%}.offset-sm-1{margin-left:calc(1 / 12 * 100%)}.offset-sm-2{margin-left:calc(2 / 12 * 100%)}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:calc(4 / 12 * 100%)}.offset-sm-5{margin-left:calc(5 / 12 * 100%)}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:calc(7 / 12 * 100%)}.offset-sm-8{margin-left:calc(8 / 12 * 100%)}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:calc(10 / 12 * 100%)}.offset-sm-11{margin-left:calc(11 / 12 * 100%)}.order-sm--12{order:-12}.order-sm--11{order:-11}.order-sm--10{order:-10}.order-sm--9{order:-9}.order-sm--8{order:-8}.order-sm--7{order:-7}.order-sm--6{order:-6}.order-sm--5{order:-5}.order-sm--4{order:-4}.order-sm--3{order:-3}.order-sm--2{order:-2}.order-sm--1{order:-1}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.hidden-sm{display:none}}@media(min-width:900px){.span-md-1{grid-column:span 1}.span-md-2{grid-column:span 2}.span-md-3{grid-column:span 3}.span-md-4{grid-column:span 4}.span-md-5{grid-column:span 5}.span-md-6{grid-column:span 6}.span-md-7{grid-column:span 7}.span-md-8{grid-column:span 8}.span-md-9{grid-column:span 9}.span-md-10{grid-column:span 10}.span-md-11{grid-column:span 11}.span-md-12{grid-column:span 12}.offset-md-0{margin-left:0%}.offset-md-1{margin-left:calc(1 / 12 * 100%)}.offset-md-2{margin-left:calc(2 / 12 * 100%)}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:calc(4 / 12 * 100%)}.offset-md-5{margin-left:calc(5 / 12 * 100%)}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:calc(7 / 12 * 100%)}.offset-md-8{margin-left:calc(8 / 12 * 100%)}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:calc(10 / 12 * 100%)}.offset-md-11{margin-left:calc(11 / 12 * 100%)}.order-md--12{order:-12}.order-md--11{order:-11}.order-md--10{order:-10}.order-md--9{order:-9}.order-md--8{order:-8}.order-md--7{order:-7}.order-md--6{order:-6}.order-md--5{order:-5}.order-md--4{order:-4}.order-md--3{order:-3}.order-md--2{order:-2}.order-md--1{order:-1}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.hidden-md{display:none}}@media(min-width:1200px){.span-lg-1{grid-column:span 1}.span-lg-2{grid-column:span 2}.span-lg-3{grid-column:span 3}.span-lg-4{grid-column:span 4}.span-lg-5{grid-column:span 5}.span-lg-6{grid-column:span 6}.span-lg-7{grid-column:span 7}.span-lg-8{grid-column:span 8}.span-lg-9{grid-column:span 9}.span-lg-10{grid-column:span 10}.span-lg-11{grid-column:span 11}.span-lg-12{grid-column:span 12}.offset-lg-0{margin-left:0%}.offset-lg-1{margin-left:calc(1 / 12 * 100%)}.offset-lg-2{margin-left:calc(2 / 12 * 100%)}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:calc(4 / 12 * 100%)}.offset-lg-5{margin-left:calc(5 / 12 * 100%)}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:calc(7 / 12 * 100%)}.offset-lg-8{margin-left:calc(8 / 12 * 100%)}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:calc(10 / 12 * 100%)}.offset-lg-11{margin-left:calc(11 / 12 * 100%)}.order-lg--12{order:-12}.order-lg--11{order:-11}.order-lg--10{order:-10}.order-lg--9{order:-9}.order-lg--8{order:-8}.order-lg--7{order:-7}.order-lg--6{order:-6}.order-lg--5{order:-5}.order-lg--4{order:-4}.order-lg--3{order:-3}.order-lg--2{order:-2}.order-lg--1{order:-1}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.hidden-lg{display:none}}@media(min-width:1536px){.span-xl-1{grid-column:span 1}.span-xl-2{grid-column:span 2}.span-xl-3{grid-column:span 3}.span-xl-4{grid-column:span 4}.span-xl-5{grid-column:span 5}.span-xl-6{grid-column:span 6}.span-xl-7{grid-column:span 7}.span-xl-8{grid-column:span 8}.span-xl-9{grid-column:span 9}.span-xl-10{grid-column:span 10}.span-xl-11{grid-column:span 11}.span-xl-12{grid-column:span 12}.offset-xl-0{margin-left:0%}.offset-xl-1{margin-left:calc(1 / 12 * 100%)}.offset-xl-2{margin-left:calc(2 / 12 * 100%)}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:calc(4 / 12 * 100%)}.offset-xl-5{margin-left:calc(5 / 12 * 100%)}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:calc(7 / 12 * 100%)}.offset-xl-8{margin-left:calc(8 / 12 * 100%)}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:calc(10 / 12 * 100%)}.offset-xl-11{margin-left:calc(11 / 12 * 100%)}.order-xl--12{order:-12}.order-xl--11{order:-11}.order-xl--10{order:-10}.order-xl--9{order:-9}.order-xl--8{order:-8}.order-xl--7{order:-7}.order-xl--6{order:-6}.order-xl--5{order:-5}.order-xl--4{order:-4}.order-xl--3{order:-3}.order-xl--2{order:-2}.order-xl--1{order:-1}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.hidden-xl{display:none}}.canvas-mode-enabled{--canvas-hit: 14px}.canvas-mode-enabled .canvas-element{position:relative;z-index:0;border-radius:8px;outline:2px solid transparent;outline-offset:2px;transition:outline-color .2s ease,outline-style .2s ease}.canvas-mode-enabled .canvas-element:before{content:\"\";position:absolute;inset:calc(-1 * var(--canvas-hit));pointer-events:none;border-radius:inherit;background:transparent}.canvas-mode-enabled .canvas-element[data-canvas-type=section]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element[data-canvas-type=row]{--outline-color: var(--md-sys-color-secondary)}.canvas-mode-enabled .canvas-element[data-canvas-type=column],.canvas-mode-enabled .canvas-element[data-canvas-type=field]{--outline-color: var(--md-sys-color-tertiary)}.canvas-mode-enabled .canvas-element[data-canvas-type=actions]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element.hovered:not(.selected){outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:dashed}.canvas-mode-enabled .canvas-element.selected{outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:solid;box-shadow:0 0 0 2px var(--outline-color, var(--md-sys-color-primary))}.canvas-mode-enabled .canvas-element.hovered{z-index:1000}.canvas-mode-enabled .canvas-element.selected{z-index:2000}.section-drop-wrapper,.row-drop-wrapper,.column-drop-wrapper{display:contents}.add-section-container{display:flex;align-items:center;justify-content:center;padding:.5rem 0;margin:-.5rem 0;position:relative;z-index:500}.add-section-container .add-section-line{flex-grow:1;height:1px;background:repeating-linear-gradient(90deg,var(--md-sys-color-outline-variant),var(--md-sys-color-outline-variant) 4px,transparent 4px,transparent 8px)}.add-section-container button{margin:0 1rem;transform:scale(.85)}:host{display:block;position:relative}.form-config-controls{position:sticky;top:10px;margin-left:auto;margin-bottom:10px;display:flex;align-items:center;gap:.35rem;z-index:60;background:color-mix(in srgb,var(--md-sys-color-surface) 92%,transparent);padding:6px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);border-radius:999px;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 10px 22px #0f172a14;min-width:0;justify-content:flex-end;pointer-events:none;opacity:.88;transition:opacity .16s ease,box-shadow .16s ease,border-color .16s ease,transform .16s ease}.form-config-controls>*{pointer-events:auto}.praxis-dynamic-form:hover .form-config-controls,.praxis-dynamic-form:focus-within .form-config-controls{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant) 74%);box-shadow:0 14px 28px #0f172a1f;transform:translateY(-1px)}.form-config-controls .mat-icon-button{--mdc-icon-button-state-layer-size: 34px;width:34px;height:34px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);border:1px solid transparent}.form-config-controls .mat-icon-button:hover{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent)}.ai-floating-assistant{position:sticky;right:0;bottom:12px;margin-top:14px;margin-left:auto;width:fit-content;z-index:70;pointer-events:none}.ai-floating-assistant praxis-ai-assistant{pointer-events:auto;display:inline-flex}.ai-floating-assistant .ai-trigger-btn{box-shadow:0 12px 28px #0f172a24}.config-button{color:var(--md-sys-color-primary)}.form-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-on-surface);gap:1rem}.form-loading p{margin:0;font-size:.875rem;opacity:.7}.form-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-error);gap:1rem;border:1px solid var(--md-sys-color-error);border-radius:8px;background-color:var(--md-sys-color-error-container);margin:1rem;box-shadow:0 12px 30px #7f1d1d1f}.form-error h3{margin:0;color:var(--md-sys-color-on-error-container)}.form-error p{margin:0;color:var(--md-sys-color-on-error-container);opacity:.8}.form-error button{margin-top:.5rem}.pfx-form-info-banner{margin-bottom:14px;padding:12px 14px;border-radius:16px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant) 82%);background:color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface) 76%);color:var(--md-sys-color-on-surface);display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.pfx-form-info-banner .text{font-size:.92rem;line-height:1.5;font-weight:600}.pfx-form-info-banner .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.praxis-dynamic-form{display:flex;flex-direction:column;transition:all .3s ease;position:relative;font-family:inherit;font-size:inherit;color:inherit;--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--md-sys-color-surface-container) );--pfx-editorial-form-surface-muted: var(--md-sys-color-surface-container-low);--pfx-editorial-form-border: var( --pfx-form-stroke, var(--md-sys-color-outline-variant) );--pfx-editorial-form-text: var(--md-sys-color-on-surface);--pfx-editorial-form-text-muted: var(--md-sys-color-on-surface-variant);--pfx-editorial-form-field-surface: color-mix( in srgb, var(--pfx-editorial-form-surface-muted) 76%, var(--pfx-editorial-form-surface) 24% );--pfx-editorial-form-field-outline: color-mix( in srgb, var(--pfx-editorial-form-border) 88%, transparent );--pfx-editorial-form-accent: var(--md-sys-color-primary);--pfx-editorial-form-accent-text: var(--md-sys-color-on-primary);--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-field-radius: var(--pfx-form-field-radius, 4px);--pfx-editorial-form-border-width: 1px;--pfx-editorial-form-field-border-width: 1px;--pfx-editorial-form-shadow: none;--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-surface-flat: color-mix( in srgb, var(--pfx-editorial-form-surface) 78%, var(--pfx-editorial-form-surface-muted) 22% );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--pfx-form-label-strong: color-mix( in srgb, var(--pfx-editorial-form-text) 96%, white 4% );--pfx-form-label-muted: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 92%, var(--pfx-editorial-form-text) 8% );--pfx-form-field-surface-rest: color-mix( in srgb, var(--pfx-editorial-form-field-surface) 82%, var(--pfx-editorial-form-surface) 18% );--pfx-form-field-surface-focus: color-mix( in srgb, var(--pfx-editorial-form-accent) 4%, var(--pfx-form-field-surface-rest) 96% );--pfx-form-field-min-height: 48px;--pfx-form-section-padding: clamp(1.1rem, 1.8vw, 1.5rem);--pfx-form-section-gap: 22px;--pfx-form-footer-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 70%, var(--pfx-editorial-form-surface-muted) 30% );--pfx-form-footer-border: color-mix( in srgb, var(--pfx-editorial-form-border) 76%, transparent )}.praxis-dynamic-form.editorial-visual-context{font-family:var(--editorial-body-font-family, inherit);font-size:var(--editorial-body-size, 1rem);color:var(--editorial-text-primary, var(--md-sys-color-on-surface));--pfx-editorial-form-surface: var( --editorial-surface-primary, var(--pfx-form-section-surface, var(--md-sys-color-surface-container)) );--pfx-editorial-form-surface-muted: var( --editorial-surface-secondary, var(--md-sys-color-surface-container-low) );--pfx-editorial-form-border: var( --editorial-border-color, var(--pfx-form-stroke, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-text: var( --editorial-text-primary, var(--md-sys-color-on-surface) );--pfx-editorial-form-text-muted: var( --editorial-text-secondary, var(--md-sys-color-on-surface-variant) );--pfx-editorial-form-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--md-sys-color-primary)) );--pfx-editorial-form-accent-text: var( --editorial-cta-primary-text, var(--editorial-accent-contrast, var(--md-sys-color-on-primary)) );--pfx-editorial-form-radius: var(--editorial-card-radius, 18px);--pfx-editorial-form-field-radius: var( --editorial-field-radius, var(--editorial-card-radius, 14px) );--pfx-editorial-form-border-width: var(--editorial-card-border-width, 1px);--pfx-editorial-form-field-border-width: var(--editorial-field-border-width, 1px);--pfx-editorial-form-shadow: var(--editorial-card-shadow, none);--md-sys-color-surface: var( --pfx-editorial-form-surface, var(--md-sys-color-surface) );--md-sys-color-surface-container: var( --pfx-editorial-form-surface, var(--md-sys-color-surface-container) );--md-sys-color-surface-container-low: var( --pfx-editorial-form-surface-muted, var(--md-sys-color-surface-container-low) );--md-sys-color-surface-variant: var( --pfx-editorial-form-field-surface, var(--md-sys-color-surface-variant) );--md-sys-color-outline: var( --pfx-editorial-form-field-outline, var(--md-sys-color-outline) );--md-sys-color-outline-variant: var( --pfx-editorial-form-border, var(--md-sys-color-outline-variant) );--md-sys-color-on-surface: var( --pfx-editorial-form-text, var(--md-sys-color-on-surface) );--md-sys-color-on-surface-variant: var( --pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant) );--md-sys-color-primary: var( --pfx-editorial-form-accent, var(--md-sys-color-primary) );--md-sys-color-on-primary: var( --pfx-editorial-form-accent-text, var(--md-sys-color-on-primary) );--md-sys-color-on-surface-rgb: var( --editorial-text-primary-rgb, var(--md-sys-color-on-surface-rgb) );--mat-sys-on-surface: var( --pfx-editorial-form-text, var(--mat-sys-on-surface) );--mat-sys-on-surface-variant: var( --pfx-editorial-form-text-muted, var(--mat-sys-on-surface-variant) );--mat-sys-on-surface-rgb: var( --editorial-text-primary-rgb, var(--mat-sys-on-surface-rgb, var(--md-sys-color-on-surface-rgb)) );color:var(--pfx-editorial-form-text);color-scheme:light}.praxis-dynamic-form.presentation-mode .form-row,.praxis-dynamic-form.readonly-mode .form-row{gap:.5rem;margin-bottom:.5rem}.praxis-dynamic-form.presentation-mode .form-section,.praxis-dynamic-form.readonly-mode .form-section{padding:.75rem .875rem}.praxis-dynamic-form.pres-compact .form-row{gap:.35rem;margin-bottom:.35rem}.praxis-dynamic-form.pres-compact .form-section{padding:.5rem .75rem}.praxis-dynamic-form.pres-label-left .praxis-presentation{display:grid;grid-template-columns:var(--pfx-presentation-label-w, 220px) 1fr;align-items:baseline;column-gap:10px}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:right;margin-bottom:0}.form-section{border:1px solid var(--pfx-form-section-divider);border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);box-shadow:none;transition:all .2s ease;position:relative}.praxis-dynamic-form.editorial-visual-context .form-section{border:var(--pfx-editorial-form-border-width) solid var(--pfx-editorial-form-border)!important;background:var(--pfx-editorial-form-surface)!important;box-shadow:var(--editorial-card-shadow, none)}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{background-color:var(--pfx-editorial-form-surface)!important;background-image:linear-gradient(180deg,color-mix(in srgb,var(--editorial-accent, var(--md-sys-color-primary)) 6%,transparent) 0%,transparent 132px)!important;background-repeat:no-repeat!important}.section-drop-wrapper>.form-section{margin-bottom:var(--pfx-section-gap, 20px)}.section-drop-wrapper:last-of-type>.form-section{margin-bottom:0}.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections] .form-actions{margin-top:var(--pfx-actions-gap-top, var(--pfx-section-gap, 20px))}.section-title{margin:0 0 var(--pfx-section-title-mb, 12px) 0;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-size:var(--editorial-step-title-size, 1.12rem);font-weight:700;color:var(--pfx-form-label-strong)}.section-heading{display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding-bottom:18px;border-bottom:1px solid var(--pfx-form-section-divider)}.section-heading.align-center{flex-direction:column;align-items:center;text-align:center}.section-heading.align-center .section-heading-text{display:grid;justify-items:center}.section-step-label{display:inline-flex;align-items:center;min-height:24px;padding:0 10px;margin:0 0 8px;border-radius:999px;background:color-mix(in srgb,var(--pfx-editorial-form-accent) 10%,transparent);color:color-mix(in srgb,var(--pfx-editorial-form-accent) 84%,var(--pfx-form-label-strong) 16%);font-size:.72rem;font-weight:800;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));letter-spacing:.08em;text-transform:uppercase}.section-heading-text{flex:1 1 auto;min-width:0}.section-collapse-btn{margin-left:4px;color:var(--pfx-form-label-muted)}.section-title.title-large{font:var(--mdc-typography-title-large, 500 22px/28px system-ui)}.section-title.title-medium{font:var(--mdc-typography-title-medium, 500 16px/24px system-ui)}.section-title.title-small{font:var(--mdc-typography-title-small, 500 14px/20px system-ui)}.section-title.headline-small{font:var(--mdc-typography-headline-small, 600 24px/32px system-ui)}.section-title.title-large,.section-title.title-medium,.section-title.title-small,.section-title.headline-small{font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-weight:var(--editorial-title-weight, 600)}.section-description{margin:0;font-family:var(--editorial-body-font-family, inherit);font-size:.93rem;color:var(--pfx-form-label-muted);line-height:1.6}.section-description.body-large{font:var(--mdc-typography-body-large, 400 16px/24px system-ui)}.section-description.body-medium{font:var(--mdc-typography-body-medium, 400 14px/20px system-ui)}.section-description.body-small{font:var(--mdc-typography-body-small, 400 12px/16px system-ui)}.section-description.body-large,.section-description.body-medium,.section-description.body-small{font-family:var(--editorial-body-font-family, inherit);font-weight:var(--editorial-body-weight, 400)}.section-title.align-center,.section-description.align-center,.section-step-label.align-center{text-align:center}.form-section.section-appearance-plain{border-color:transparent;border-radius:0;padding:0;background:transparent}.form-section.section-appearance-plain .section-heading{margin-bottom:14px}.form-section.section-appearance-step{border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);border-color:var(--pfx-form-section-divider);box-shadow:none}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{border-radius:var(--editorial-card-radius, 20px);box-shadow:none}.form-section.section-appearance-step .section-heading{margin-bottom:22px;padding-bottom:16px;border-bottom:1px solid var(--pfx-form-section-divider)}.form-section.section-appearance-step .section-title{font:var(--mdc-typography-title-large, 700 22px/28px system-ui);color:var(--pfx-form-label-strong);margin-bottom:8px}.form-section.section-appearance-step .section-description{color:var(--pfx-form-label-muted);max-width:60ch}.form-section.section-appearance-step .section-step-label{min-height:24px;padding:0 10px;margin-bottom:10px;box-shadow:none}.form-section.section-appearance-step .section-heading.align-center .section-description{max-width:52ch}.form-section.section-appearance-step .section-body{display:grid;gap:8px;padding-top:0}.form-section.section-appearance-step .form-row{margin-bottom:var(--pfx-field-gap, 1rem)}.form-section.section-appearance-step .form-column{gap:var(--pfx-field-gap, 12px)}.form-section .form-editorial-blocks{display:grid;gap:16px}.form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{margin-top:24px;padding-top:18px;border-top:1px solid var(--pfx-form-section-divider)}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]{gap:18px}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]>*+*{margin-top:2px}.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections] .form-actions{margin-top:18px;padding-top:0}.praxis-dynamic-form>.form-editorial-blocks[data-editorial-placement=after]{margin-top:6px}:host-context(.mdc-theme-dark) .form-section.section-appearance-step,:host-context(.theme-dark) .form-section.section-appearance-step{border-color:color-mix(in srgb,var(--pfx-editorial-form-border) 82%,transparent);box-shadow:none}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-title,:host-context(.theme-dark) .form-section.section-appearance-step .section-title{color:color-mix(in srgb,var(--pfx-editorial-form-text) 96%,white)}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-description,:host-context(.theme-dark) .form-section.section-appearance-step .section-description{color:color-mix(in srgb,var(--pfx-editorial-form-text-muted) 86%,var(--pfx-editorial-form-text) 14%)}:host-context(.mdc-theme-dark) .section-step-label,:host-context(.theme-dark) .section-step-label{background:color-mix(in srgb,var(--md-sys-color-primary-container) 54%,transparent);color:color-mix(in srgb,var(--md-sys-color-primary) 88%,white)}:host-context(.mdc-theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions],:host-context(.theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{border-top-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 90%,transparent)}.inline-edit-btn{margin-left:6px;vertical-align:middle;--mdc-icon-button-size: 28px;--mdc-icon-button-icon-size: 16px}.inline-edit-btn mat-icon{font-size:16px;width:16px;height:16px}.section-body.collapsed{border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);border-radius:6px;padding:8px 10px}.section-collapsed-placeholder{display:flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.95rem}.section-collapsed-placeholder mat-icon{font-size:20px;width:20px;height:20px}.form-row{display:flex;gap:1.1rem;margin-bottom:var(--pfx-field-gap, 1.1rem);transition:all .2s ease;border-radius:6px;position:relative}.praxis-dynamic-form.pfx-mounting .form-row{opacity:0;transform:translateY(var(--pdx-form-mount-offset, 6px));animation:pdxFormMount var(--pdx-form-mount-duration, .16s) ease-out both;animation-delay:calc(var(--pfx-mount-index, 0) * var(--pdx-form-mount-stagger, 20ms))}@media(prefers-reduced-motion:reduce){.praxis-dynamic-form.pfx-mounting .form-row{animation:none;opacity:1;transform:none}}@keyframes pdxFormMount{to{opacity:1;transform:translateY(0)}}.praxis-dynamic-form .mat-mdc-form-field{width:100%;margin-bottom:var(--pfx-field-gap, 10px);font-family:inherit;--mdc-filled-text-field-container-color: var(--pfx-form-field-surface-rest);--mdc-filled-text-field-focus-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-active-indicator-color: var(--pfx-editorial-form-field-outline);--mdc-filled-text-field-hover-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-filled-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-caret-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-input-text-placeholder-color: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 82%, transparent );--mdc-outlined-text-field-outline-color: var(--pfx-editorial-form-field-outline);--mdc-outlined-text-field-hover-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-outlined-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-outlined-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-filled-text-field-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-filled-text-field-focus-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-outline-width: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-focus-outline-width: var(--pfx-editorial-form-field-border-width);--mat-select-enabled-trigger-text-color: var(--pfx-editorial-form-text);--mat-select-enabled-arrow-color: var(--pfx-form-label-muted);--mat-form-field-enabled-select-arrow-color: var(--pfx-form-label-muted);--mat-form-field-focus-select-arrow-color: var(--pfx-editorial-form-accent);--mat-form-field-hover-state-layer-opacity: 0;--mat-form-field-focus-state-layer-opacity: 0}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field{font-family:var(--editorial-body-font-family, inherit)}.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{background:var(--pfx-form-field-surface-rest);border-radius:var(--pfx-editorial-form-field-radius);min-height:var(--pfx-form-field-min-height);transition:background-color .16s ease,box-shadow .16s ease,border-color .16s ease}.praxis-dynamic-form.editorial-visual-context .mat-mdc-text-field-wrapper,.praxis-dynamic-form.editorial-visual-context .mdc-text-field,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--filled,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--outlined{background-color:var(--pfx-form-field-surface-rest)!important;background:var(--pfx-form-field-surface-rest)!important}.praxis-dynamic-form .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-form-label-muted)}.praxis-dynamic-form .mat-mdc-input-element,.praxis-dynamic-form .mat-mdc-select-value-text,.praxis-dynamic-form .mat-mdc-form-field-infix,.praxis-dynamic-form .mat-mdc-select-min-line{color:var(--pfx-editorial-form-text)}.praxis-dynamic-form .mat-mdc-form-field:hover .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field:hover .mdc-text-field,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mdc-text-field{background:var(--pfx-form-field-surface-focus)}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-value-text,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field-infix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-min-line,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input{color:var(--pfx-editorial-form-text)!important;-webkit-text-fill-color:var(--pfx-editorial-form-text)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-editorial-form-text-muted)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 68%,transparent)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element::placeholder,.praxis-dynamic-form.editorial-visual-context textarea.mat-mdc-input-element::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 58%,transparent)!important}.praxis-dynamic-form .mat-mdc-radio-button,.praxis-dynamic-form .mat-mdc-checkbox,.praxis-dynamic-form .mat-mdc-slide-toggle{--mdc-radio-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-checkmark-color: var(--pfx-editorial-form-accent-text);--mdc-checkbox-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-focus-state-layer-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-handle-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-track-color: color-mix(in srgb, var(--pfx-editorial-form-accent) 45%, #fff)}.praxis-dynamic-form [data-field-type=input],.praxis-dynamic-form [data-field-type=textarea],.praxis-dynamic-form [data-field-type=email],.praxis-dynamic-form [data-field-type=password],.praxis-dynamic-form [data-field-type=url],.praxis-dynamic-form [data-field-type=search],.praxis-dynamic-form [data-field-type=phone],.praxis-dynamic-form [data-field-type=numericTextBox],.praxis-dynamic-form [data-field-type=currency],.praxis-dynamic-form [data-field-type=cpfCnpj],.praxis-dynamic-form [data-field-type=date],.praxis-dynamic-form [data-field-type=dateInput],.praxis-dynamic-form [data-field-type=dateRange],.praxis-dynamic-form [data-field-type=dateTimeLocal],.praxis-dynamic-form [data-field-type=time],.praxis-dynamic-form [data-field-type=timePicker],.praxis-dynamic-form [data-field-type=timeRange],.praxis-dynamic-form [data-field-type=month],.praxis-dynamic-form [data-field-type=week],.praxis-dynamic-form [data-field-type=yearInput],.praxis-dynamic-form [data-field-type=select],.praxis-dynamic-form [data-field-type=multi-select],.praxis-dynamic-form [data-field-type=searchable-select],.praxis-dynamic-form [data-field-type=async-select],.praxis-dynamic-form [data-field-type=autocomplete],.praxis-dynamic-form [data-field-type=tree-select],.praxis-dynamic-form [data-field-type=multi-select-tree],.praxis-dynamic-form [data-field-type=priceRange],.praxis-dynamic-form [data-field-type=file-upload]{display:block;width:100%;min-width:0}.praxis-dynamic-form .mat-mdc-form-field-subscript-wrapper{min-height:var(--pfx-subscript-min-h, 22px)}.form-row:last-child{margin-bottom:0}.form-column{display:grid;align-content:start;gap:var(--pfx-field-gap, 10px);flex:1;min-width:0;transition:all .2s ease;border-radius:4px;position:relative}.form-row.grid-12{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.align-start{align-self:flex-start}.align-center{align-self:center}.align-end{align-self:flex-end}.align-stretch{align-self:stretch}.form-blocking-overlay{position:absolute;inset:0;background:transparent;color:var(--md-sys-color-on-surface);backdrop-filter:blur(2px) saturate(103%);-webkit-backdrop-filter:blur(2px) saturate(103%);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;z-index:10;pointer-events:all}@media(max-width:768px){.form-row{flex-direction:column;gap:.5rem}.form-section{padding:1rem}.section-heading{gap:10px;margin-bottom:16px;padding-bottom:14px}}.section-title{display:flex;align-items:center;gap:8px}.section-title .section-title-icon{font-size:1.25em;line-height:1}.section-title-avatar{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px));display:inline-flex;align-items:center;justify-content:center;width:var(--_pfx-form-section-avatar-size);height:var(--_pfx-form-section-avatar-size);border-radius:999px;flex:0 0 var(--_pfx-form-section-avatar-size);overflow:hidden}.section-title-avatar.size-sm{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-sm, 24px)}.section-title-avatar.size-md{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px))}.section-title-avatar.size-lg{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-lg, 40px)}.section-title-avatar-image{object-fit:cover;border:1px solid color-mix(in srgb,var(--pfx-form-section-divider) 72%,transparent);background:var(--pfx-form-section-surface-flat)}.section-title-avatar-text,.section-title-avatar-placeholder{background:color-mix(in srgb,var(--pfx-editorial-form-accent) 14%,var(--pfx-form-section-surface-flat));color:color-mix(in srgb,var(--pfx-editorial-form-accent) 82%,var(--pfx-form-label-strong) 18%);font-size:calc(var(--_pfx-form-section-avatar-size) * .41);font-weight:800;letter-spacing:.04em;text-transform:uppercase}.section-title-avatar-placeholder mat-icon{font-size:calc(var(--_pfx-form-section-avatar-size) * .5625);width:calc(var(--_pfx-form-section-avatar-size) * .5625);height:calc(var(--_pfx-form-section-avatar-size) * .5625);line-height:calc(var(--_pfx-form-section-avatar-size) * .5625)}.section-title-avatar-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
11267
+ ], template: "@if (isLoading) {\n<!-- Loading State -->\n<div class=\"form-loading\">\n <mat-progress-spinner diameter=\"40\"></mat-progress-spinner>\n <p>Carregando formul\u00E1rio...</p>\n</div>\n} @else if (initializationStatus === 'error') {\n<!-- Error State -->\n<div class=\"form-error\">\n <mat-icon color=\"warn\" [praxisIcon]=\"'error'\"></mat-icon>\n <h3>{{ getErrorTitle() }}</h3>\n <p>{{ currentErrorMessage }}</p>\n @if (isRecoverable) {\n <button mat-stroked-button (click)=\"retryInitialization()\">\n <mat-icon [praxisIcon]=\"'refresh'\"></mat-icon>\n Tentar Novamente\n </button>\n }\n <button mat-button (click)=\"showDetailedError()\" class=\"show-details\">\n Ver Detalhes T\u00E9cnicos\n </button>\n <!-- Permitir corre\u00E7\u00E3o do resourcePath diretamente do estado de erro -->\n <button mat-flat-button color=\"primary\" (click)=\"openQuickConnect()\" class=\"connect-action\">\n <mat-icon [praxisIcon]=\"'bolt'\"></mat-icon>\n Conectar a recurso\n </button>\n</div>\n} @else if (initializationStatus === 'success') {\n<!-- Inline banner for schema change (only when customization is enabled) -->\n@if (shouldShowOutdatedInline()) {\n<div class=\"pfx-form-info-banner\" role=\"status\" aria-live=\"polite\">\n <div class=\"text\">O schema do servidor mudou. Reconciliar agora?</div>\n <div class=\"actions\">\n <button mat-stroked-button color=\"primary\" (click)=\"openConfigEditor()\">\n <mat-icon [praxisIcon]=\"'sync'\"></mat-icon>\n Reconciliar\n </button>\n <button mat-button (click)=\"onSnoozeOutdated()\">Lembrar depois</button>\n <button mat-button (click)=\"onIgnoreOutdated()\">Ignorar</button>\n </div>\n</div>\n}\n\n<!-- Configuration Controls -->\n@if (shouldShowConfigControls && enableCustomization) {\n<div class=\"form-config-controls\">\n <praxis-ai-assistant [adapter]=\"aiAdapter\"></praxis-ai-assistant>\n <button type=\"button\" mat-icon-button (click)=\"openConfigEditor()\" [disabled]=\"isLoading\" class=\"config-button\"\n [matBadge]=\"schemaOutdated ? '!' : ''\" [matBadgeHidden]=\"!schemaOutdated\" matBadgeColor=\"warn\" matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n [matTooltip]=\"schemaOutdated ? 'Schema do servidor mudou \u2014 Reconciliar' : 'Configurar formul\u00E1rio'\">\n <mat-icon [praxisIcon]=\"'settings'\"></mat-icon>\n </button>\n <button type=\"button\" mat-icon-button (click)=\"disconnect()\" matTooltip=\"Desconectar da fonte de dados\"\n [disabled]=\"isLoading\">\n <mat-icon [praxisIcon]=\"'link_off'\"></mat-icon>\n </button>\n</div>\n}\n\n<!-- Form Content -->\n@if (!resourcePath && (!config.sections || config.sections.length === 0)) {\n<praxis-empty-state-card icon=\"link\" [title]=\"'Conecte o formul\u00E1rio \u00E0 fonte de dados'\"\n [description]=\"'Informe a rota do recurso da API para gerar automaticamente os campos do formul\u00E1rio.'\"\n [primaryAction]=\"{ label: 'Conectar \u00E0 fonte de dados', icon: 'bolt', action: openQuickConnect.bind(this) }\"></praxis-empty-state-card>\n}\n<form #formHost (ngSubmit)=\"onSubmit()\" [attr.aria-busy]=\"submitting ? 'true' : null\"\n [attr.aria-label]=\"'Formul\u00E1rio ' + (config.metadata?.version || '')\" [class.canvas-mode-enabled]=\"enableCustomization\"\n [class.presentation-mode]=\"effectivePresentation\" [class.readonly-mode]=\"effectiveReadonly\"\n [class.editorial-visual-context]=\"hasEditorialVisualContext()\"\n [class.pfx-mounting]=\"isMounting\" [formGroup]=\"form\"\n [ngClass]=\"{\n 'pres-compact': presentationVars.compact,\n 'pres-label-left': presentationVars.labelPosition === 'left',\n 'pres-label-above': presentationVars.labelPosition === 'above'\n }\" [style.--pfx-pres-label-align]=\"presentationVars.labelAlign\"\n [style.--pfx-pres-label-size]=\"presentationVars.labelSize\"\n [style.--pfx-pres-label-width]=\"presentationVars.labelWidth\"\n [style.--pfx-pres-row-gap]=\"presentationVars.density === 'compact' ? '6px' : (presentationVars.density === 'cozy' ? '8px' : '10px')\"\n [style.--pfx-pres-row-padding]=\"presentationVars.density === 'compact' ? '2px 0' : (presentationVars.density === 'cozy' ? '6px 0' : '8px 0')\"\n [style.--pfx-pres-value-align]=\"presentationVars.valueAlign\"\n [style.--pfx-pres-value-size]=\"presentationVars.valueSize\"\n [style.--pdx-form-mount-duration]=\"getMountDurationVar()\"\n [style.--pdx-form-mount-offset]=\"getMountOffsetVar()\"\n [style.--pdx-form-mount-stagger]=\"getMountStaggerVar()\"\n class=\"praxis-dynamic-form\">\n <praxis-canvas-toolbar (editMetadata)=\"openSelectedElementEditor()\" (selectPath)=\"onSelectPath($event)\"\n (moveUp)=\"onToolbarMove('up')\" (moveDown)=\"onToolbarMove('down')\" (toggleReadonly)=\"onToolbarToggleReadonly()\"\n (toggleRequired)=\"onToolbarToggleRequired()\" (toggleHidden)=\"onToolbarToggleHidden()\"\n (toggleDisabled)=\"onToolbarToggleDisabled()\" (requestClose)=\"onToolbarRequestClose()\"\n *ngIf=\"enableCustomization && selectedElement\" [selectedElement]=\"selectedElement\"\n [style.transform]=\"toolbarTransform\"></praxis-canvas-toolbar>\n\n @if (formBlocksBefore.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before\" data-editorial-placement=\"before\">\n @for (block of formBlocksBefore; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('before', $event)\">\n </ng-container>\n }\n </section>\n }\n\n @if (actionPlacement === 'top' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"top\" [actions]=\"config.actions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"form.valid\" [submitError]=\"submitError\" [formId]=\"formId\" [actionOverrides]=\"actionRuleProps\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @for (section of config.sections; track (section.id ?? $index); let sectionIndex = $index;\n let last = $last) {\n <div class=\"section-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n @if (isSectionVisible(section)) {\n <div #sectionEl class=\"form-section canvas-element\" data-canvas-type=\"section\" [attr.data-section-id]=\"section.id\"\n [attr.data-section-index]=\"sectionIndex\" (mouseenter)=\"onElementMouseEnter($event, 'section', section, sectionEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'section', section, sectionEl)\"\n [class.selected]=\"selectedElement?.domElement === sectionEl\"\n [class.hovered]=\"hoveredElement?.domElement === sectionEl && selectedElement?.domElement !== sectionEl\"\n [attr.data-section-appearance]=\"getSectionAppearance(section) || null\"\n [style.marginBottom.px]=\"!last ? getSectionGapBottom(section) : null\" [ngClass]=\"getSectionClasses(section)\"\n [ngStyle]=\"getSectionStyles(section)\">\n <div\n class=\"section-heading\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [class.step-appearance]=\"getSectionAppearance(section) === 'step'\"\n >\n <div class=\"section-heading-text\" [matTooltip]=\"getSectionHeaderTooltip(section) || null\"\n [matTooltipDisabled]=\"!getSectionHeaderTooltip(section)\">\n @if (getSectionStepLabel(section)) {\n <div class=\"section-step-label\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionStepLabel(section) }}\n </div>\n }\n @if (getSectionTitle(section)) {\n <h3 class=\"section-title\" [class.title-large]=\"getSectionTitleStyle(section) === 'titleLarge'\"\n [class.title-medium]=\"getSectionTitleStyle(section) === 'titleMedium'\"\n [class.title-small]=\"getSectionTitleStyle(section) === 'titleSmall'\"\n [class.headline-small]=\"getSectionTitleStyle(section) === 'headlineSmall'\"\n [style.marginBottom.px]=\"getSectionTitleGapBottom(section) ?? 20\" [style.color]=\"getSectionTitleColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\"\n [attr.id]=\"sectionPanelId(section, sectionIndex) + '-title'\">\n @let sectionHeaderVisual = getSectionHeaderVisual(section);\n @let sectionHeaderAvatarSize = getSectionHeaderAvatarSize(section);\n @if (sectionHeaderVisual.kind === 'icon') {\n <mat-icon class=\"section-title-icon\" aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.kind === 'image') {\n <img class=\"section-title-avatar section-title-avatar-image\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\"\n [src]=\"sectionHeaderVisual.src\" [alt]=\"sectionHeaderVisual.alt\" />\n }\n @if (sectionHeaderVisual.kind === 'initials') {\n <span class=\"section-title-avatar section-title-avatar-text\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n {{ sectionHeaderVisual.text }}\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n @if (sectionHeaderVisual.kind === 'placeholder') {\n <span class=\"section-title-avatar section-title-avatar-placeholder\" [class.size-sm]=\"sectionHeaderAvatarSize === 'sm'\"\n [class.size-md]=\"sectionHeaderAvatarSize === 'md'\" [class.size-lg]=\"sectionHeaderAvatarSize === 'lg'\" aria-hidden=\"true\">\n @if (sectionHeaderVisual.icon) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"sectionHeaderVisual.icon\"></mat-icon>\n }\n @if (sectionHeaderVisual.text) {\n <span>{{ sectionHeaderVisual.text }}</span>\n }\n </span>\n @if (sectionHeaderVisual.ariaLabel) {\n <span class=\"section-title-avatar-sr-only\">{{ sectionHeaderVisual.ariaLabel }}</span>\n }\n }\n {{ getSectionTitle(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" mat-icon-button (click)=\"openSectionEditor(section, 'title')\"\n aria-label=\"Editar t\u00EDtulo da se\u00E7\u00E3o\" matTooltip=\"Editar t\u00EDtulo\">\n <mat-icon>edit</mat-icon>\n </button>\n }\n </h3>\n }\n @if (getSectionDescription(section)) {\n <p class=\"section-description\" [class.body-large]=\"getSectionDescriptionStyle(section) === 'bodyLarge'\"\n [class.body-medium]=\"getSectionDescriptionStyle(section) === 'bodyMedium'\"\n [class.body-small]=\"getSectionDescriptionStyle(section) === 'bodySmall'\"\n [style.marginBottom.px]=\"getSectionDescriptionGapBottom(section) ?? 8\" [style.color]=\"getSectionDescriptionColor(section) || null\"\n [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n {{ getSectionDescription(section) }}\n @if (enableCustomization) {\n <button type=\"button\" class=\"inline-edit-btn\" mat-icon-button\n (click)=\"openSectionEditor(section, 'description')\" aria-label=\"Editar descri\u00E7\u00E3o da se\u00E7\u00E3o\"\n matTooltip=\"Editar descri\u00E7\u00E3o\">\n <mat-icon>edit</mat-icon>\n </button>\n }\n </p>\n }\n </div>\n @if (getSectionHeaderActions(section).length) {\n <div class=\"section-heading-actions\" [class.align-center]=\"getSectionHeaderAlign(section) === 'center'\">\n @for (action of getSectionHeaderActions(section); track action.id) {\n <button\n type=\"button\"\n class=\"section-heading-action-btn\"\n mat-icon-button\n [color]=\"getSectionHeaderActionColor(action)\"\n [disabled]=\"isSectionHeaderActionDisabled(action)\"\n [matTooltip]=\"getSectionHeaderActionTooltip(action)\"\n [attr.aria-label]=\"action.label\"\n [attr.aria-busy]=\"action.loading ? 'true' : null\"\n [ngClass]=\"getSectionHeaderActionNgClass(action)\"\n [ngStyle]=\"getSectionHeaderActionStyles(action)\"\n (click)=\"onSectionHeaderActionClick(section, action, $event)\"\n >\n @if (action.loading) {\n <mat-progress-spinner diameter=\"16\" mode=\"indeterminate\"></mat-progress-spinner>\n <span class=\"section-heading-action-sr-only\">{{ getSectionHeaderActionLoadingLabel(action) }}</span>\n } @else {\n <mat-icon [praxisIcon]=\"action.icon\"></mat-icon>\n }\n </button>\n }\n </div>\n }\n @if (isSectionCollapsible(section)) {\n <button type=\"button\" class=\"section-collapse-btn\" mat-icon-button\n (click)=\"toggleSectionCollapse($event, section)\" [attr.aria-expanded]=\"!isSectionCollapsed(section)\"\n [attr.aria-controls]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-label]=\"isSectionCollapsed(section) ? 'Expandir se\u00E7\u00E3o' : 'Recolher se\u00E7\u00E3o'\">\n <mat-icon [praxisIcon]=\"isSectionCollapsed(section) ? 'expand_more' : 'expand_less'\"></mat-icon>\n </button>\n }\n </div>\n\n <div class=\"section-body\" [class.collapsed]=\"isSectionCollapsed(section)\"\n [attr.id]=\"sectionPanelId(section, sectionIndex)\"\n [attr.aria-labelledby]=\"getSectionTitle(section) ? sectionPanelId(section, sectionIndex) + '-title' : null\">\n @if (!isSectionCollapsed(section)) {\n @for (row of section.rows; track (row.id ?? $index); let rowIndex = $index) {\n @if (isRowVisible(row)) {\n <div class=\"row-drop-wrapper\" [attr.data-section-id]=\"section.id\">\n <div #rowEl class=\"form-row grid-12 canvas-element\" data-canvas-type=\"row\" [attr.data-row-index]=\"rowIndex\"\n [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\" [style.--pfx-grid-gap.px]=\"getRowGap(row)\"\n [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [style.--pfx-mount-index]=\"rowIndex\"\n [style.marginBottom.px]=\"rowIndex < section.rows.length - 1 ? (getRowRowGap(row) ?? null) : null\"\n [ngClass]=\"getRowClasses(row)\" [ngStyle]=\"getRowStyles(row)\"\n (mouseenter)=\"onElementMouseEnter($event, 'row', row, rowEl)\" (mouseleave)=\"onElementMouseLeave($event)\"\n (click)=\"onElementClick($event, 'row', row, rowEl)\" [class.selected]=\"selectedElement?.domElement === rowEl\"\n [class.hovered]=\"hoveredElement?.domElement === rowEl && selectedElement?.domElement !== rowEl\">\n @for (column of row.columns; track (column.id ?? $index); let colIndex = $index) {\n @if (isColumnVisible(column)) {\n <div class=\"column-drop-wrapper\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\">\n <div #colEl class=\"form-column canvas-element\" [ngClass]=\"getColumnClasses(column)\"\n [style.padding.px]=\"getColumnPadding(column)\" [style.--pfx-field-gap.px]=\"getRowRowGap(row)\"\n [ngStyle]=\"getColumnStyles(column)\" [attr.data-testid]=\"column.testId || null\"\n [attr.data-row-gap]=\"getRowRowGap(row)\" data-canvas-type=\"column\" [attr.data-column-index]=\"colIndex\"\n [attr.data-row-index]=\"rowIndex\" [attr.data-section-id]=\"section.id\" [attr.data-row-id]=\"row.id\"\n [attr.data-column-id]=\"column.id\" (mouseenter)=\"onElementMouseEnter($event, 'column', column, colEl)\"\n (mouseleave)=\"onElementMouseLeave($event)\" (click)=\"onElementClick($event, 'column', column, colEl)\"\n [class.selected]=\"selectedElement?.domElement === colEl\"\n [class.hovered]=\"hoveredElement?.domElement === colEl && selectedElement?.domElement !== colEl\">\n <ng-container dynamicFieldLoader [fields]=\"getColumnFields(column)\" [formGroup]=\"form\"\n [readonlyMode]=\"readonlyModeGlobal === null ? null : readonlyModeGlobal\"\n [disabledMode]=\"disabledModeGlobal === null ? null : disabledModeGlobal\"\n [presentationMode]=\"presentationForLoader\" [visible]=\"visibleGlobal === null ? null : visibleGlobal\"\n [canvasMode]=\"enableCustomization\" (canvasMouseEnter)=\"onFieldMouseEnter($event)\"\n (canvasMouseLeave)=\"onFieldMouseLeave($event)\" (canvasClick)=\"onFieldClick($event)\"\n (renderError)=\"onFieldRenderError($event)\">\n </ng-container>\n </div>\n </div>\n } }\n </div>\n </div>\n }\n }\n } @else {\n <div class=\"section-collapsed-placeholder\">\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"'unfold_more'\"></mat-icon>\n <span>{{ getSectionCollapsedSummary(section) }}</span>\n </div>\n }\n @if (last && beforeActionsPlacement === 'insideLastSection' && formBlocksBeforeActions.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n @for (block of formBlocksBeforeActions; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('beforeActions', $event)\">\n </ng-container>\n }\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && last && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"config.actions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"form.valid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n </div>\n <!-- Overlay de bloqueio durante submiss\u00E3o -->\n @if (submitting) {\n <div class=\"form-blocking-overlay\" aria-live=\"polite\">\n <mat-progress-spinner diameter=\"40\" color=\"primary\"></mat-progress-spinner>\n <p>{{ config.messages?.loading?.submit || 'Salvando...' }}</p>\n </div>\n }\n </div>\n\n @if (enableCustomization && selectedElement?.domElement === sectionEl) {\n <div class=\"add-section-container\">\n <div class=\"add-section-line\"></div>\n <button mat-fab color=\"primary\" aria-label=\"Adicionar nova se\u00E7\u00E3o\" (click)=\"addNewSectionAfter(sectionIndex)\"\n matTooltip=\"Adicionar nova se\u00E7\u00E3o aqui\">\n <mat-icon [praxisIcon]=\"'add'\"></mat-icon>\n </button>\n <div class=\"add-section-line\"></div>\n </div>\n }\n }\n </div>\n }\n\n @if (beforeActionsPlacement !== 'insideLastSection' && formBlocksBeforeActions.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n @for (block of formBlocksBeforeActions; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('beforeActions', $event)\">\n </ng-container>\n }\n </section>\n }\n\n @if (actionPlacement === 'afterSections' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"afterSections\" [actions]=\"config.actions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"form.valid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @if (formBlocksAfter.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-after\" data-editorial-placement=\"after\">\n @for (block of formBlocksAfter; track (block.id ?? $index)) {\n <ng-container\n [dynamicWidgetLoader]=\"block\"\n [context]=\"getEditorialWidgetContext()\"\n [strictValidation]=\"true\"\n [autoWireOutputs]=\"true\"\n (widgetEvent)=\"onEditorialWidgetEvent('after', $event)\">\n </ng-container>\n }\n </section>\n }\n</form>\n@if (!enableCustomization && mode === 'view') {\n<div class=\"ai-floating-assistant\">\n <praxis-ai-assistant [adapter]=\"aiAdapter\"></praxis-ai-assistant>\n</div>\n}\n}\n", styles: ["@charset \"UTF-8\";.span-xs-1{grid-column:span 1}.span-xs-2{grid-column:span 2}.span-xs-3{grid-column:span 3}.span-xs-4{grid-column:span 4}.span-xs-5{grid-column:span 5}.span-xs-6{grid-column:span 6}.span-xs-7{grid-column:span 7}.span-xs-8{grid-column:span 8}.span-xs-9{grid-column:span 9}.span-xs-10{grid-column:span 10}.span-xs-11{grid-column:span 11}.span-xs-12{grid-column:span 12}.offset-xs-0{margin-left:0%}.offset-xs-1{margin-left:calc(1 / 12 * 100%)}.offset-xs-2{margin-left:calc(2 / 12 * 100%)}.offset-xs-3{margin-left:25%}.offset-xs-4{margin-left:calc(4 / 12 * 100%)}.offset-xs-5{margin-left:calc(5 / 12 * 100%)}.offset-xs-6{margin-left:50%}.offset-xs-7{margin-left:calc(7 / 12 * 100%)}.offset-xs-8{margin-left:calc(8 / 12 * 100%)}.offset-xs-9{margin-left:75%}.offset-xs-10{margin-left:calc(10 / 12 * 100%)}.offset-xs-11{margin-left:calc(11 / 12 * 100%)}.order-xs--12{order:-12}.order-xs--11{order:-11}.order-xs--10{order:-10}.order-xs--9{order:-9}.order-xs--8{order:-8}.order-xs--7{order:-7}.order-xs--6{order:-6}.order-xs--5{order:-5}.order-xs--4{order:-4}.order-xs--3{order:-3}.order-xs--2{order:-2}.order-xs--1{order:-1}.order-xs-0{order:0}.order-xs-1{order:1}.order-xs-2{order:2}.order-xs-3{order:3}.order-xs-4{order:4}.order-xs-5{order:5}.order-xs-6{order:6}.order-xs-7{order:7}.order-xs-8{order:8}.order-xs-9{order:9}.order-xs-10{order:10}.order-xs-11{order:11}.order-xs-12{order:12}.hidden-xs{display:none}@media(min-width:600px){.span-sm-1{grid-column:span 1}.span-sm-2{grid-column:span 2}.span-sm-3{grid-column:span 3}.span-sm-4{grid-column:span 4}.span-sm-5{grid-column:span 5}.span-sm-6{grid-column:span 6}.span-sm-7{grid-column:span 7}.span-sm-8{grid-column:span 8}.span-sm-9{grid-column:span 9}.span-sm-10{grid-column:span 10}.span-sm-11{grid-column:span 11}.span-sm-12{grid-column:span 12}.offset-sm-0{margin-left:0%}.offset-sm-1{margin-left:calc(1 / 12 * 100%)}.offset-sm-2{margin-left:calc(2 / 12 * 100%)}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:calc(4 / 12 * 100%)}.offset-sm-5{margin-left:calc(5 / 12 * 100%)}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:calc(7 / 12 * 100%)}.offset-sm-8{margin-left:calc(8 / 12 * 100%)}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:calc(10 / 12 * 100%)}.offset-sm-11{margin-left:calc(11 / 12 * 100%)}.order-sm--12{order:-12}.order-sm--11{order:-11}.order-sm--10{order:-10}.order-sm--9{order:-9}.order-sm--8{order:-8}.order-sm--7{order:-7}.order-sm--6{order:-6}.order-sm--5{order:-5}.order-sm--4{order:-4}.order-sm--3{order:-3}.order-sm--2{order:-2}.order-sm--1{order:-1}.order-sm-0{order:0}.order-sm-1{order:1}.order-sm-2{order:2}.order-sm-3{order:3}.order-sm-4{order:4}.order-sm-5{order:5}.order-sm-6{order:6}.order-sm-7{order:7}.order-sm-8{order:8}.order-sm-9{order:9}.order-sm-10{order:10}.order-sm-11{order:11}.order-sm-12{order:12}.hidden-sm{display:none}}@media(min-width:900px){.span-md-1{grid-column:span 1}.span-md-2{grid-column:span 2}.span-md-3{grid-column:span 3}.span-md-4{grid-column:span 4}.span-md-5{grid-column:span 5}.span-md-6{grid-column:span 6}.span-md-7{grid-column:span 7}.span-md-8{grid-column:span 8}.span-md-9{grid-column:span 9}.span-md-10{grid-column:span 10}.span-md-11{grid-column:span 11}.span-md-12{grid-column:span 12}.offset-md-0{margin-left:0%}.offset-md-1{margin-left:calc(1 / 12 * 100%)}.offset-md-2{margin-left:calc(2 / 12 * 100%)}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:calc(4 / 12 * 100%)}.offset-md-5{margin-left:calc(5 / 12 * 100%)}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:calc(7 / 12 * 100%)}.offset-md-8{margin-left:calc(8 / 12 * 100%)}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:calc(10 / 12 * 100%)}.offset-md-11{margin-left:calc(11 / 12 * 100%)}.order-md--12{order:-12}.order-md--11{order:-11}.order-md--10{order:-10}.order-md--9{order:-9}.order-md--8{order:-8}.order-md--7{order:-7}.order-md--6{order:-6}.order-md--5{order:-5}.order-md--4{order:-4}.order-md--3{order:-3}.order-md--2{order:-2}.order-md--1{order:-1}.order-md-0{order:0}.order-md-1{order:1}.order-md-2{order:2}.order-md-3{order:3}.order-md-4{order:4}.order-md-5{order:5}.order-md-6{order:6}.order-md-7{order:7}.order-md-8{order:8}.order-md-9{order:9}.order-md-10{order:10}.order-md-11{order:11}.order-md-12{order:12}.hidden-md{display:none}}@media(min-width:1200px){.span-lg-1{grid-column:span 1}.span-lg-2{grid-column:span 2}.span-lg-3{grid-column:span 3}.span-lg-4{grid-column:span 4}.span-lg-5{grid-column:span 5}.span-lg-6{grid-column:span 6}.span-lg-7{grid-column:span 7}.span-lg-8{grid-column:span 8}.span-lg-9{grid-column:span 9}.span-lg-10{grid-column:span 10}.span-lg-11{grid-column:span 11}.span-lg-12{grid-column:span 12}.offset-lg-0{margin-left:0%}.offset-lg-1{margin-left:calc(1 / 12 * 100%)}.offset-lg-2{margin-left:calc(2 / 12 * 100%)}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:calc(4 / 12 * 100%)}.offset-lg-5{margin-left:calc(5 / 12 * 100%)}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:calc(7 / 12 * 100%)}.offset-lg-8{margin-left:calc(8 / 12 * 100%)}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:calc(10 / 12 * 100%)}.offset-lg-11{margin-left:calc(11 / 12 * 100%)}.order-lg--12{order:-12}.order-lg--11{order:-11}.order-lg--10{order:-10}.order-lg--9{order:-9}.order-lg--8{order:-8}.order-lg--7{order:-7}.order-lg--6{order:-6}.order-lg--5{order:-5}.order-lg--4{order:-4}.order-lg--3{order:-3}.order-lg--2{order:-2}.order-lg--1{order:-1}.order-lg-0{order:0}.order-lg-1{order:1}.order-lg-2{order:2}.order-lg-3{order:3}.order-lg-4{order:4}.order-lg-5{order:5}.order-lg-6{order:6}.order-lg-7{order:7}.order-lg-8{order:8}.order-lg-9{order:9}.order-lg-10{order:10}.order-lg-11{order:11}.order-lg-12{order:12}.hidden-lg{display:none}}@media(min-width:1536px){.span-xl-1{grid-column:span 1}.span-xl-2{grid-column:span 2}.span-xl-3{grid-column:span 3}.span-xl-4{grid-column:span 4}.span-xl-5{grid-column:span 5}.span-xl-6{grid-column:span 6}.span-xl-7{grid-column:span 7}.span-xl-8{grid-column:span 8}.span-xl-9{grid-column:span 9}.span-xl-10{grid-column:span 10}.span-xl-11{grid-column:span 11}.span-xl-12{grid-column:span 12}.offset-xl-0{margin-left:0%}.offset-xl-1{margin-left:calc(1 / 12 * 100%)}.offset-xl-2{margin-left:calc(2 / 12 * 100%)}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:calc(4 / 12 * 100%)}.offset-xl-5{margin-left:calc(5 / 12 * 100%)}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:calc(7 / 12 * 100%)}.offset-xl-8{margin-left:calc(8 / 12 * 100%)}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:calc(10 / 12 * 100%)}.offset-xl-11{margin-left:calc(11 / 12 * 100%)}.order-xl--12{order:-12}.order-xl--11{order:-11}.order-xl--10{order:-10}.order-xl--9{order:-9}.order-xl--8{order:-8}.order-xl--7{order:-7}.order-xl--6{order:-6}.order-xl--5{order:-5}.order-xl--4{order:-4}.order-xl--3{order:-3}.order-xl--2{order:-2}.order-xl--1{order:-1}.order-xl-0{order:0}.order-xl-1{order:1}.order-xl-2{order:2}.order-xl-3{order:3}.order-xl-4{order:4}.order-xl-5{order:5}.order-xl-6{order:6}.order-xl-7{order:7}.order-xl-8{order:8}.order-xl-9{order:9}.order-xl-10{order:10}.order-xl-11{order:11}.order-xl-12{order:12}.hidden-xl{display:none}}.canvas-mode-enabled{--canvas-hit: 14px}.canvas-mode-enabled .canvas-element{position:relative;z-index:0;border-radius:8px;outline:2px solid transparent;outline-offset:2px;transition:outline-color .2s ease,outline-style .2s ease}.canvas-mode-enabled .canvas-element:before{content:\"\";position:absolute;inset:calc(-1 * var(--canvas-hit));pointer-events:none;border-radius:inherit;background:transparent}.canvas-mode-enabled .canvas-element[data-canvas-type=section]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element[data-canvas-type=row]{--outline-color: var(--md-sys-color-secondary)}.canvas-mode-enabled .canvas-element[data-canvas-type=column],.canvas-mode-enabled .canvas-element[data-canvas-type=field]{--outline-color: var(--md-sys-color-tertiary)}.canvas-mode-enabled .canvas-element[data-canvas-type=actions]{--outline-color: var(--md-sys-color-primary)}.canvas-mode-enabled .canvas-element.hovered:not(.selected){outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:dashed}.canvas-mode-enabled .canvas-element.selected{outline-color:var(--outline-color, var(--md-sys-color-primary));outline-style:solid;box-shadow:0 0 0 2px var(--outline-color, var(--md-sys-color-primary))}.canvas-mode-enabled .canvas-element.hovered{z-index:1000}.canvas-mode-enabled .canvas-element.selected{z-index:2000}.section-drop-wrapper,.row-drop-wrapper,.column-drop-wrapper{display:contents}.add-section-container{display:flex;align-items:center;justify-content:center;padding:.5rem 0;margin:-.5rem 0;position:relative;z-index:500}.add-section-container .add-section-line{flex-grow:1;height:1px;background:repeating-linear-gradient(90deg,var(--md-sys-color-outline-variant),var(--md-sys-color-outline-variant) 4px,transparent 4px,transparent 8px)}.add-section-container button{margin:0 1rem;transform:scale(.85)}:host{display:block;position:relative}.form-config-controls{position:sticky;top:10px;margin-left:auto;margin-bottom:10px;display:flex;align-items:center;gap:.35rem;z-index:60;background:color-mix(in srgb,var(--md-sys-color-surface) 92%,transparent);padding:6px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline-variant) 82%,transparent);border-radius:999px;-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);box-shadow:0 10px 22px #0f172a14;min-width:0;justify-content:flex-end;pointer-events:none;opacity:.88;transition:opacity .16s ease,box-shadow .16s ease,border-color .16s ease,transform .16s ease}.form-config-controls>*{pointer-events:auto}.praxis-dynamic-form:hover .form-config-controls,.praxis-dynamic-form:focus-within .form-config-controls{opacity:1;border-color:color-mix(in srgb,var(--md-sys-color-primary) 26%,var(--md-sys-color-outline-variant) 74%);box-shadow:0 14px 28px #0f172a1f;transform:translateY(-1px)}.form-config-controls .mat-icon-button{--mdc-icon-button-state-layer-size: 34px;width:34px;height:34px;color:var(--md-sys-color-on-surface-variant);background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,transparent);border:1px solid transparent}.form-config-controls .mat-icon-button:hover{color:var(--md-sys-color-primary);background:var(--md-sys-color-primary-container);border-color:color-mix(in srgb,var(--md-sys-color-primary) 20%,transparent)}.ai-floating-assistant{position:sticky;right:0;bottom:12px;margin-top:14px;margin-left:auto;width:fit-content;z-index:70;pointer-events:none}.ai-floating-assistant praxis-ai-assistant{pointer-events:auto;display:inline-flex}.ai-floating-assistant .ai-trigger-btn{box-shadow:0 12px 28px #0f172a24}.config-button{color:var(--md-sys-color-primary)}.form-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-on-surface);gap:1rem}.form-loading p{margin:0;font-size:.875rem;opacity:.7}.form-error{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem;text-align:center;color:var(--md-sys-color-error);gap:1rem;border:1px solid var(--md-sys-color-error);border-radius:8px;background-color:var(--md-sys-color-error-container);margin:1rem;box-shadow:0 12px 30px #7f1d1d1f}.form-error h3{margin:0;color:var(--md-sys-color-on-error-container)}.form-error p{margin:0;color:var(--md-sys-color-on-error-container);opacity:.8}.form-error button{margin-top:.5rem}.pfx-form-info-banner{margin-bottom:14px;padding:12px 14px;border-radius:16px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 18%,var(--md-sys-color-outline-variant) 82%);background:color-mix(in srgb,var(--md-sys-color-primary-container) 24%,var(--md-sys-color-surface) 76%);color:var(--md-sys-color-on-surface);display:flex;align-items:flex-start;justify-content:space-between;gap:14px}.pfx-form-info-banner .text{font-size:.92rem;line-height:1.5;font-weight:600}.pfx-form-info-banner .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px}.praxis-dynamic-form{display:flex;flex-direction:column;transition:all .3s ease;position:relative;font-family:inherit;font-size:inherit;color:inherit;--pfx-editorial-form-surface: var( --pfx-form-section-surface, var(--md-sys-color-surface-container) );--pfx-editorial-form-surface-muted: var(--md-sys-color-surface-container-low);--pfx-editorial-form-border: var( --pfx-form-stroke, var(--md-sys-color-outline-variant) );--pfx-editorial-form-text: var(--md-sys-color-on-surface);--pfx-editorial-form-text-muted: var(--md-sys-color-on-surface-variant);--pfx-editorial-form-field-surface: color-mix( in srgb, var(--pfx-editorial-form-surface-muted) 76%, var(--pfx-editorial-form-surface) 24% );--pfx-editorial-form-field-outline: color-mix( in srgb, var(--pfx-editorial-form-border) 88%, transparent );--pfx-editorial-form-accent: var(--md-sys-color-primary);--pfx-editorial-form-accent-text: var(--md-sys-color-on-primary);--pfx-editorial-form-radius: var(--pfx-form-section-radius, 8px);--pfx-editorial-form-field-radius: var(--pfx-form-field-radius, 4px);--pfx-editorial-form-border-width: 1px;--pfx-editorial-form-field-border-width: 1px;--pfx-editorial-form-shadow: none;--pfx-form-shell-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 36%, transparent );--pfx-form-section-surface-flat: color-mix( in srgb, var(--pfx-editorial-form-surface) 78%, var(--pfx-editorial-form-surface-muted) 22% );--pfx-form-section-divider: color-mix( in srgb, var(--pfx-editorial-form-border) 68%, transparent );--pfx-form-label-strong: color-mix( in srgb, var(--pfx-editorial-form-text) 96%, white 4% );--pfx-form-label-muted: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 92%, var(--pfx-editorial-form-text) 8% );--pfx-form-field-surface-rest: color-mix( in srgb, var(--pfx-editorial-form-field-surface) 82%, var(--pfx-editorial-form-surface) 18% );--pfx-form-field-surface-focus: color-mix( in srgb, var(--pfx-editorial-form-accent) 4%, var(--pfx-form-field-surface-rest) 96% );--pfx-form-field-min-height: 48px;--pfx-form-section-padding: clamp(1.1rem, 1.8vw, 1.5rem);--pfx-form-section-gap: 22px;--pfx-form-footer-surface: color-mix( in srgb, var(--pfx-editorial-form-surface) 70%, var(--pfx-editorial-form-surface-muted) 30% );--pfx-form-footer-border: color-mix( in srgb, var(--pfx-editorial-form-border) 76%, transparent )}.praxis-dynamic-form.editorial-visual-context{font-family:var(--editorial-body-font-family, inherit);font-size:var(--editorial-body-size, 1rem);color:var(--editorial-text-primary, var(--md-sys-color-on-surface));--pfx-editorial-form-surface: var( --editorial-surface-primary, var(--pfx-form-section-surface, var(--md-sys-color-surface-container)) );--pfx-editorial-form-surface-muted: var( --editorial-surface-secondary, var(--md-sys-color-surface-container-low) );--pfx-editorial-form-border: var( --editorial-border-color, var(--pfx-form-stroke, var(--md-sys-color-outline-variant)) );--pfx-editorial-form-text: var( --editorial-text-primary, var(--md-sys-color-on-surface) );--pfx-editorial-form-text-muted: var( --editorial-text-secondary, var(--md-sys-color-on-surface-variant) );--pfx-editorial-form-accent: var( --editorial-cta-primary, var(--editorial-accent, var(--md-sys-color-primary)) );--pfx-editorial-form-accent-text: var( --editorial-cta-primary-text, var(--editorial-accent-contrast, var(--md-sys-color-on-primary)) );--pfx-editorial-form-radius: var(--editorial-card-radius, 18px);--pfx-editorial-form-field-radius: var( --editorial-field-radius, var(--editorial-card-radius, 14px) );--pfx-editorial-form-border-width: var(--editorial-card-border-width, 1px);--pfx-editorial-form-field-border-width: var(--editorial-field-border-width, 1px);--pfx-editorial-form-shadow: var(--editorial-card-shadow, none);--md-sys-color-surface: var( --pfx-editorial-form-surface, var(--md-sys-color-surface) );--md-sys-color-surface-container: var( --pfx-editorial-form-surface, var(--md-sys-color-surface-container) );--md-sys-color-surface-container-low: var( --pfx-editorial-form-surface-muted, var(--md-sys-color-surface-container-low) );--md-sys-color-surface-variant: var( --pfx-editorial-form-field-surface, var(--md-sys-color-surface-variant) );--md-sys-color-outline: var( --pfx-editorial-form-field-outline, var(--md-sys-color-outline) );--md-sys-color-outline-variant: var( --pfx-editorial-form-border, var(--md-sys-color-outline-variant) );--md-sys-color-on-surface: var( --pfx-editorial-form-text, var(--md-sys-color-on-surface) );--md-sys-color-on-surface-variant: var( --pfx-editorial-form-text-muted, var(--md-sys-color-on-surface-variant) );--md-sys-color-primary: var( --pfx-editorial-form-accent, var(--md-sys-color-primary) );--md-sys-color-on-primary: var( --pfx-editorial-form-accent-text, var(--md-sys-color-on-primary) );--md-sys-color-on-surface-rgb: var( --editorial-text-primary-rgb, var(--md-sys-color-on-surface-rgb) );--mat-sys-on-surface: var( --pfx-editorial-form-text, var(--mat-sys-on-surface) );--mat-sys-on-surface-variant: var( --pfx-editorial-form-text-muted, var(--mat-sys-on-surface-variant) );--mat-sys-on-surface-rgb: var( --editorial-text-primary-rgb, var(--mat-sys-on-surface-rgb, var(--md-sys-color-on-surface-rgb)) );color:var(--pfx-editorial-form-text);color-scheme:light}.praxis-dynamic-form.presentation-mode .form-row,.praxis-dynamic-form.readonly-mode .form-row{gap:.5rem;margin-bottom:.5rem}.praxis-dynamic-form.presentation-mode .form-section,.praxis-dynamic-form.readonly-mode .form-section{padding:.75rem .875rem}.praxis-dynamic-form.pres-compact .form-row{gap:.35rem;margin-bottom:.35rem}.praxis-dynamic-form.pres-compact .form-section{padding:.5rem .75rem}.praxis-dynamic-form.pres-label-left .praxis-presentation{display:grid;grid-template-columns:var(--pfx-presentation-label-w, 220px) 1fr;align-items:baseline;column-gap:10px}.praxis-dynamic-form.pres-label-left .praxis-presentation__label{text-align:right;margin-bottom:0}.form-section{border:1px solid var(--pfx-form-section-divider);border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);box-shadow:none;transition:all .2s ease;position:relative}.praxis-dynamic-form.editorial-visual-context .form-section{border:var(--pfx-editorial-form-border-width) solid var(--pfx-editorial-form-border)!important;background:var(--pfx-editorial-form-surface)!important;box-shadow:var(--editorial-card-shadow, none)}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{background-color:var(--pfx-editorial-form-surface)!important;background-image:linear-gradient(180deg,color-mix(in srgb,var(--editorial-accent, var(--md-sys-color-primary)) 6%,transparent) 0%,transparent 132px)!important;background-repeat:no-repeat!important}.section-drop-wrapper>.form-section{margin-bottom:var(--pfx-section-gap, 20px)}.section-drop-wrapper:last-of-type>.form-section{margin-bottom:0}.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections] .form-actions{margin-top:var(--pfx-actions-gap-top, var(--pfx-section-gap, 20px))}.section-title{margin:0 0 var(--pfx-section-title-mb, 12px) 0;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-size:var(--editorial-step-title-size, 1.12rem);font-weight:700;color:var(--pfx-form-label-strong)}.section-heading{display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding-bottom:18px;border-bottom:1px solid var(--pfx-form-section-divider)}.section-heading.align-center{flex-direction:column;align-items:center;text-align:center}.section-heading.align-center .section-heading-text{display:grid;justify-items:center}.section-step-label{display:inline-flex;align-items:center;min-height:24px;padding:0 10px;margin:0 0 8px;border-radius:999px;background:color-mix(in srgb,var(--pfx-editorial-form-accent) 10%,transparent);color:color-mix(in srgb,var(--pfx-editorial-form-accent) 84%,var(--pfx-form-label-strong) 16%);font-size:.72rem;font-weight:800;font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));letter-spacing:.08em;text-transform:uppercase}.section-heading-text{flex:1 1 auto;min-width:0}.section-heading-actions{display:inline-flex;align-items:center;align-self:flex-start;flex-wrap:wrap;gap:4px;margin-left:auto}.section-heading-actions.align-center{align-self:center;margin-left:0}.section-heading-action-btn{color:var(--pfx-form-label-muted)}.section-heading-action-btn .mat-mdc-progress-spinner,.section-heading-action-btn mat-progress-spinner{--mdc-circular-progress-active-indicator-color: currentColor}.section-heading-action-btn.loading{opacity:.72;pointer-events:none}.section-heading-action-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.section-collapse-btn{margin-left:4px;color:var(--pfx-form-label-muted)}.section-title.title-large{font:var(--mdc-typography-title-large, 500 22px/28px system-ui)}.section-title.title-medium{font:var(--mdc-typography-title-medium, 500 16px/24px system-ui)}.section-title.title-small{font:var(--mdc-typography-title-small, 500 14px/20px system-ui)}.section-title.headline-small{font:var(--mdc-typography-headline-small, 600 24px/32px system-ui)}.section-title.title-large,.section-title.title-medium,.section-title.title-small,.section-title.headline-small{font-family:var(--editorial-title-font-family, var(--editorial-body-font-family, inherit));font-weight:var(--editorial-title-weight, 600)}.section-description{margin:0;font-family:var(--editorial-body-font-family, inherit);font-size:.93rem;color:var(--pfx-form-label-muted);line-height:1.6}.section-description.body-large{font:var(--mdc-typography-body-large, 400 16px/24px system-ui)}.section-description.body-medium{font:var(--mdc-typography-body-medium, 400 14px/20px system-ui)}.section-description.body-small{font:var(--mdc-typography-body-small, 400 12px/16px system-ui)}.section-description.body-large,.section-description.body-medium,.section-description.body-small{font-family:var(--editorial-body-font-family, inherit);font-weight:var(--editorial-body-weight, 400)}.section-title.align-center,.section-description.align-center,.section-step-label.align-center{text-align:center}.form-section.section-appearance-plain{border-color:transparent;border-radius:0;padding:0;background:transparent}.form-section.section-appearance-plain .section-heading{margin-bottom:14px}.form-section.section-appearance-step{border-radius:var(--pfx-editorial-form-radius);padding:var(--pfx-form-section-padding);background:var(--pfx-form-section-surface-flat);border-color:var(--pfx-form-section-divider);box-shadow:none}.praxis-dynamic-form.editorial-visual-context .form-section.section-appearance-step{border-radius:var(--editorial-card-radius, 20px);box-shadow:none}.form-section.section-appearance-step .section-heading{margin-bottom:22px;padding-bottom:16px;border-bottom:1px solid var(--pfx-form-section-divider)}.form-section.section-appearance-step .section-title{font:var(--mdc-typography-title-large, 700 22px/28px system-ui);color:var(--pfx-form-label-strong);margin-bottom:8px}.form-section.section-appearance-step .section-description{color:var(--pfx-form-label-muted);max-width:60ch}.form-section.section-appearance-step .section-step-label{min-height:24px;padding:0 10px;margin-bottom:10px;box-shadow:none}.form-section.section-appearance-step .section-heading.align-center .section-description{max-width:52ch}.form-section.section-appearance-step .section-body{display:grid;gap:8px;padding-top:0}.form-section.section-appearance-step .form-row{margin-bottom:var(--pfx-field-gap, 1rem)}.form-section.section-appearance-step .form-column{gap:var(--pfx-field-gap, 12px)}.form-section .form-editorial-blocks{display:grid;gap:16px}.form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{margin-top:24px;padding-top:18px;border-top:1px solid var(--pfx-form-section-divider)}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]{gap:18px}.form-section.section-appearance-step .form-editorial-blocks[data-editorial-placement=beforeActions]>*+*{margin-top:2px}.praxis-dynamic-form>praxis-form-actions[data-actions-placement=afterSections] .form-actions{margin-top:18px;padding-top:0}.praxis-dynamic-form>.form-editorial-blocks[data-editorial-placement=after]{margin-top:6px}:host-context(.mdc-theme-dark) .form-section.section-appearance-step,:host-context(.theme-dark) .form-section.section-appearance-step{border-color:color-mix(in srgb,var(--pfx-editorial-form-border) 82%,transparent);box-shadow:none}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-title,:host-context(.theme-dark) .form-section.section-appearance-step .section-title{color:color-mix(in srgb,var(--pfx-editorial-form-text) 96%,white)}:host-context(.mdc-theme-dark) .form-section.section-appearance-step .section-description,:host-context(.theme-dark) .form-section.section-appearance-step .section-description{color:color-mix(in srgb,var(--pfx-editorial-form-text-muted) 86%,var(--pfx-editorial-form-text) 14%)}:host-context(.mdc-theme-dark) .section-step-label,:host-context(.theme-dark) .section-step-label{background:color-mix(in srgb,var(--md-sys-color-primary-container) 54%,transparent);color:color-mix(in srgb,var(--md-sys-color-primary) 88%,white)}:host-context(.mdc-theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions],:host-context(.theme-dark) .form-section .form-editorial-blocks[data-editorial-placement=beforeActions]{border-top-color:color-mix(in srgb,var(--md-sys-color-outline-variant) 90%,transparent)}.inline-edit-btn{margin-left:6px;vertical-align:middle;--mdc-icon-button-size: 28px;--mdc-icon-button-icon-size: 16px}.inline-edit-btn mat-icon{font-size:16px;width:16px;height:16px}.section-body.collapsed{border:1px dashed var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container-low);border-radius:6px;padding:8px 10px}.section-collapsed-placeholder{display:flex;align-items:center;gap:8px;color:var(--md-sys-color-on-surface-variant);font-size:.95rem}.section-collapsed-placeholder mat-icon{font-size:20px;width:20px;height:20px}.form-row{display:flex;gap:1.1rem;margin-bottom:var(--pfx-field-gap, 1.1rem);transition:all .2s ease;border-radius:6px;position:relative}.praxis-dynamic-form.pfx-mounting .form-row{opacity:0;transform:translateY(var(--pdx-form-mount-offset, 6px));animation:pdxFormMount var(--pdx-form-mount-duration, .16s) ease-out both;animation-delay:calc(var(--pfx-mount-index, 0) * var(--pdx-form-mount-stagger, 20ms))}@media(prefers-reduced-motion:reduce){.praxis-dynamic-form.pfx-mounting .form-row{animation:none;opacity:1;transform:none}}@keyframes pdxFormMount{to{opacity:1;transform:translateY(0)}}.praxis-dynamic-form .mat-mdc-form-field{width:100%;margin-bottom:var(--pfx-field-gap, 10px);font-family:inherit;--mdc-filled-text-field-container-color: var(--pfx-form-field-surface-rest);--mdc-filled-text-field-focus-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-active-indicator-color: var(--pfx-editorial-form-field-outline);--mdc-filled-text-field-hover-active-indicator-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-filled-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-caret-color: var(--pfx-editorial-form-accent);--mdc-filled-text-field-input-text-placeholder-color: color-mix( in srgb, var(--pfx-editorial-form-text-muted) 82%, transparent );--mdc-outlined-text-field-outline-color: var(--pfx-editorial-form-field-outline);--mdc-outlined-text-field-hover-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-outline-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-focus-label-text-color: var(--pfx-editorial-form-accent);--mdc-outlined-text-field-label-text-color: var(--pfx-form-label-muted);--mdc-outlined-text-field-input-text-color: var(--pfx-editorial-form-text);--mdc-filled-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-outlined-text-field-container-shape: var(--pfx-editorial-form-field-radius);--mdc-filled-text-field-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-filled-text-field-focus-active-indicator-height: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-outline-width: var(--pfx-editorial-form-field-border-width);--mdc-outlined-text-field-focus-outline-width: var(--pfx-editorial-form-field-border-width);--mat-select-enabled-trigger-text-color: var(--pfx-editorial-form-text);--mat-select-enabled-arrow-color: var(--pfx-form-label-muted);--mat-form-field-enabled-select-arrow-color: var(--pfx-form-label-muted);--mat-form-field-focus-select-arrow-color: var(--pfx-editorial-form-accent);--mat-form-field-hover-state-layer-opacity: 0;--mat-form-field-focus-state-layer-opacity: 0}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field{font-family:var(--editorial-body-font-family, inherit)}.praxis-dynamic-form .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mdc-text-field{background:var(--pfx-form-field-surface-rest);border-radius:var(--pfx-editorial-form-field-radius);min-height:var(--pfx-form-field-min-height);transition:background-color .16s ease,box-shadow .16s ease,border-color .16s ease}.praxis-dynamic-form.editorial-visual-context .mat-mdc-text-field-wrapper,.praxis-dynamic-form.editorial-visual-context .mdc-text-field,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--filled,.praxis-dynamic-form.editorial-visual-context .mdc-text-field--outlined{background-color:var(--pfx-form-field-surface-rest)!important;background:var(--pfx-form-field-surface-rest)!important}.praxis-dynamic-form .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-form-label-muted)}.praxis-dynamic-form .mat-mdc-input-element,.praxis-dynamic-form .mat-mdc-select-value-text,.praxis-dynamic-form .mat-mdc-form-field-infix,.praxis-dynamic-form .mat-mdc-select-min-line{color:var(--pfx-editorial-form-text)}.praxis-dynamic-form .mat-mdc-form-field:hover .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field:hover .mdc-text-field,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mat-mdc-text-field-wrapper,.praxis-dynamic-form .mat-mdc-form-field.mat-focused .mdc-text-field{background:var(--pfx-form-field-surface-focus)}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-value-text,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field-infix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-select-min-line,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input{color:var(--pfx-editorial-form-text)!important;-webkit-text-fill-color:var(--pfx-editorial-form-text)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-hint,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-error,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-required-marker,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-arrow,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-select-placeholder,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-suffix,.praxis-dynamic-form.editorial-visual-context .mat-mdc-form-field .mat-mdc-form-field-icon-prefix{color:var(--pfx-editorial-form-text-muted)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-floating-label,.praxis-dynamic-form.editorial-visual-context .mdc-text-field__input::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 68%,transparent)!important}.praxis-dynamic-form.editorial-visual-context .mat-mdc-input-element::placeholder,.praxis-dynamic-form.editorial-visual-context textarea.mat-mdc-input-element::placeholder{color:color-mix(in srgb,var(--pfx-editorial-form-text) 58%,transparent)!important}.praxis-dynamic-form .mat-mdc-radio-button,.praxis-dynamic-form .mat-mdc-checkbox,.praxis-dynamic-form .mat-mdc-slide-toggle{--mdc-radio-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-radio-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-checkmark-color: var(--pfx-editorial-form-accent-text);--mdc-checkbox-selected-focus-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-hover-icon-color: var(--pfx-editorial-form-accent);--mdc-checkbox-selected-icon-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-focus-state-layer-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-handle-color: var(--pfx-editorial-form-accent);--mdc-switch-selected-track-color: color-mix(in srgb, var(--pfx-editorial-form-accent) 45%, #fff)}.praxis-dynamic-form [data-field-type=input],.praxis-dynamic-form [data-field-type=textarea],.praxis-dynamic-form [data-field-type=email],.praxis-dynamic-form [data-field-type=password],.praxis-dynamic-form [data-field-type=url],.praxis-dynamic-form [data-field-type=search],.praxis-dynamic-form [data-field-type=phone],.praxis-dynamic-form [data-field-type=numericTextBox],.praxis-dynamic-form [data-field-type=currency],.praxis-dynamic-form [data-field-type=cpfCnpj],.praxis-dynamic-form [data-field-type=date],.praxis-dynamic-form [data-field-type=dateInput],.praxis-dynamic-form [data-field-type=dateRange],.praxis-dynamic-form [data-field-type=dateTimeLocal],.praxis-dynamic-form [data-field-type=time],.praxis-dynamic-form [data-field-type=timePicker],.praxis-dynamic-form [data-field-type=timeRange],.praxis-dynamic-form [data-field-type=month],.praxis-dynamic-form [data-field-type=week],.praxis-dynamic-form [data-field-type=yearInput],.praxis-dynamic-form [data-field-type=select],.praxis-dynamic-form [data-field-type=multi-select],.praxis-dynamic-form [data-field-type=searchable-select],.praxis-dynamic-form [data-field-type=async-select],.praxis-dynamic-form [data-field-type=autocomplete],.praxis-dynamic-form [data-field-type=tree-select],.praxis-dynamic-form [data-field-type=multi-select-tree],.praxis-dynamic-form [data-field-type=priceRange],.praxis-dynamic-form [data-field-type=file-upload]{display:block;width:100%;min-width:0}.praxis-dynamic-form .mat-mdc-form-field-subscript-wrapper{min-height:var(--pfx-subscript-min-h, 22px)}.form-row:last-child{margin-bottom:0}.form-column{display:grid;align-content:start;gap:var(--pfx-field-gap, 10px);flex:1;min-width:0;transition:all .2s ease;border-radius:4px;position:relative}.form-row.grid-12{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.align-start{align-self:flex-start}.align-center{align-self:center}.align-end{align-self:flex-end}.align-stretch{align-self:stretch}.form-blocking-overlay{position:absolute;inset:0;background:transparent;color:var(--md-sys-color-on-surface);backdrop-filter:blur(2px) saturate(103%);-webkit-backdrop-filter:blur(2px) saturate(103%);display:flex;align-items:center;justify-content:center;flex-direction:column;gap:12px;z-index:10;pointer-events:all}@media(max-width:768px){.form-row{flex-direction:column;gap:.5rem}.form-section{padding:1rem}.section-heading{gap:10px;margin-bottom:16px;padding-bottom:14px}}.section-title{display:flex;align-items:center;gap:8px}.section-title .section-title-icon{font-size:1.25em;line-height:1}.section-title-avatar{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px));display:inline-flex;align-items:center;justify-content:center;width:var(--_pfx-form-section-avatar-size);height:var(--_pfx-form-section-avatar-size);border-radius:999px;flex:0 0 var(--_pfx-form-section-avatar-size);overflow:hidden}.section-title-avatar.size-sm{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-sm, 24px)}.section-title-avatar.size-md{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px))}.section-title-avatar.size-lg{--_pfx-form-section-avatar-size: var(--pfx-form-section-avatar-size-lg, 40px)}.section-title-avatar-image{object-fit:cover;border:1px solid color-mix(in srgb,var(--pfx-form-section-divider) 72%,transparent);background:var(--pfx-form-section-surface-flat)}.section-title-avatar-text,.section-title-avatar-placeholder{background:color-mix(in srgb,var(--pfx-editorial-form-accent) 14%,var(--pfx-form-section-surface-flat));color:color-mix(in srgb,var(--pfx-editorial-form-accent) 82%,var(--pfx-form-label-strong) 18%);font-size:calc(var(--_pfx-form-section-avatar-size) * .41);font-weight:800;letter-spacing:.04em;text-transform:uppercase}.section-title-avatar-placeholder mat-icon{font-size:calc(var(--_pfx-form-section-avatar-size) * .5625);width:calc(var(--_pfx-form-section-avatar-size) * .5625);height:calc(var(--_pfx-form-section-avatar-size) * .5625);line-height:calc(var(--_pfx-form-section-avatar-size) * .5625)}.section-title-avatar-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n"] }]
11079
11268
  }], ctorParameters: () => [{ type: i1$2.GenericCrudService }, { type: i1$3.FormBuilder }, { type: i0.ChangeDetectorRef }, { type: FormLayoutService }, { type: FormContextService }, { type: FormRulesService }, { type: i6$1.SettingsPanelService }, { type: i2.MatDialog }, { type: undefined, decorators: [{
11080
11269
  type: Inject,
11081
11270
  args: [ASYNC_CONFIG_STORAGE]
@@ -13765,11 +13954,64 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
13765
13954
  type: Output
13766
13955
  }] } });
13767
13956
 
13957
+ const ACTIONS_EDITOR_I18N_NAMESPACE = 'praxisDynamicFormActionsEditor';
13958
+ const ACTIONS_EDITOR_I18N_CONFIG = {
13959
+ namespaces: {
13960
+ [ACTIONS_EDITOR_I18N_NAMESPACE]: {
13961
+ 'pt-BR': {
13962
+ 'custom.variant': 'Variante',
13963
+ 'custom.size': 'Tamanho',
13964
+ 'custom.size.small': 'Pequeno',
13965
+ 'custom.size.medium': 'Médio',
13966
+ 'custom.size.large': 'Grande',
13967
+ 'custom.tooltip': 'Tooltip',
13968
+ 'custom.shortcut': 'Atalho de Teclado',
13969
+ 'custom.shortcut.placeholder': 'Ex.: ctrl+shift+a',
13970
+ 'custom.className': 'Classe CSS',
13971
+ 'custom.disabled': 'Desabilitado',
13972
+ 'custom.loading': 'Loading',
13973
+ 'custom.style': 'Estilos do botão (JSON)',
13974
+ 'custom.style.placeholder': '{"borderRadius":"999px"}',
13975
+ 'custom.order.moveUp': 'Mover "{{label}}" para cima',
13976
+ 'custom.order.moveDown': 'Mover "{{label}}" para baixo',
13977
+ 'custom.order.moveUp.tooltip': 'Mover para cima',
13978
+ 'custom.order.moveDown.tooltip': 'Mover para baixo',
13979
+ 'custom.validation.invalidJson': 'JSON inválido.',
13980
+ 'custom.validation.objectJson': 'Informe um objeto JSON válido.',
13981
+ },
13982
+ 'en-US': {
13983
+ 'custom.variant': 'Variant',
13984
+ 'custom.size': 'Size',
13985
+ 'custom.size.small': 'Small',
13986
+ 'custom.size.medium': 'Medium',
13987
+ 'custom.size.large': 'Large',
13988
+ 'custom.tooltip': 'Tooltip',
13989
+ 'custom.shortcut': 'Keyboard shortcut',
13990
+ 'custom.shortcut.placeholder': 'Example: ctrl+shift+a',
13991
+ 'custom.className': 'CSS class',
13992
+ 'custom.disabled': 'Disabled',
13993
+ 'custom.loading': 'Loading',
13994
+ 'custom.style': 'Button styles (JSON)',
13995
+ 'custom.style.placeholder': '{"borderRadius":"999px"}',
13996
+ 'custom.order.moveUp': 'Move "{{label}}" up',
13997
+ 'custom.order.moveDown': 'Move "{{label}}" down',
13998
+ 'custom.order.moveUp.tooltip': 'Move up',
13999
+ 'custom.order.moveDown.tooltip': 'Move down',
14000
+ 'custom.validation.invalidJson': 'Invalid JSON.',
14001
+ 'custom.validation.objectJson': 'Provide a valid JSON object.',
14002
+ },
14003
+ },
14004
+ },
14005
+ };
14006
+
13768
14007
  let ActionsEditorComponent$1 = class ActionsEditorComponent {
13769
14008
  config;
13770
14009
  configChange = new EventEmitter();
13771
14010
  containerStylesText = '';
14011
+ customActionStyleTexts = new Map();
14012
+ customActionStyleErrors = new Map();
13772
14013
  globalActionCatalogSource = inject(GLOBAL_ACTION_CATALOG, { optional: true }) ?? [];
14014
+ i18n = inject(PraxisI18nService);
13773
14015
  legacyActionSpecs = GLOBAL_ACTION_SPEC_CATALOG;
13774
14016
  globalActionCatalog = this.buildGlobalActionCatalog();
13775
14017
  customActionValue = '__custom__';
@@ -13789,7 +14031,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
13789
14031
  onGapTopInput(val) {
13790
14032
  let num = Number(val);
13791
14033
  if (!isFinite(num)) {
13792
- // limpar volta ao padrão
14034
+ // limpar volta ao padrão
13793
14035
  const styles = { ...this.actions?.containerStyles };
13794
14036
  if (styles) {
13795
14037
  delete styles.marginTop;
@@ -13831,11 +14073,28 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
13831
14073
  }
13832
14074
  ngOnChanges() {
13833
14075
  this.syncContainerStylesText();
14076
+ this.syncCustomActionStyleTexts();
13834
14077
  }
13835
14078
  syncContainerStylesText() {
13836
14079
  const styles = this.config.actions?.containerStyles;
13837
14080
  this.containerStylesText = styles ? JSON.stringify(styles, null, 2) : '';
13838
14081
  }
14082
+ syncCustomActionStyleTexts() {
14083
+ const activeKeys = new Set();
14084
+ for (const [index, action] of (this.actions.custom || []).entries()) {
14085
+ const key = this.getCustomActionStyleKey(action, index);
14086
+ activeKeys.add(key);
14087
+ if (!this.customActionStyleTexts.has(key)) {
14088
+ this.customActionStyleTexts.set(key, this.stringifyJson(action.style));
14089
+ }
14090
+ }
14091
+ for (const key of Array.from(this.customActionStyleTexts.keys())) {
14092
+ if (!activeKeys.has(key)) {
14093
+ this.customActionStyleTexts.delete(key);
14094
+ this.customActionStyleErrors.delete(key);
14095
+ }
14096
+ }
14097
+ }
13839
14098
  getActionSpecById(id) {
13840
14099
  return this.globalActionCatalog.find((item) => item.id === id);
13841
14100
  }
@@ -13918,19 +14177,47 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
13918
14177
  }
13919
14178
  return Array.from(merged.values());
13920
14179
  }
14180
+ getActionCatalogLabel(spec) {
14181
+ if (spec?.id === 'surface.open') {
14182
+ return this.i18n.t('action.surfaceOpen.label', undefined, spec.label || '', SURFACE_OPEN_I18N_NAMESPACE);
14183
+ }
14184
+ return spec?.label || '';
14185
+ }
14186
+ tx(key, fallback, params) {
14187
+ return this.i18n.t(key, params, fallback, ACTIONS_EDITOR_I18N_NAMESPACE);
14188
+ }
14189
+ getCustomActionTitle(action) {
14190
+ return action.label || 'Novo Botão Customizado';
14191
+ }
14192
+ getMoveCustomActionAriaLabel(direction, action) {
14193
+ const key = direction === 'up' ? 'custom.order.moveUp' : 'custom.order.moveDown';
14194
+ const fallback = direction === 'up'
14195
+ ? `Mover "${this.getCustomActionTitle(action)}" para cima`
14196
+ : `Mover "${this.getCustomActionTitle(action)}" para baixo`;
14197
+ return this.tx(key, fallback, { label: this.getCustomActionTitle(action) });
14198
+ }
14199
+ getCustomStylePlaceholder() {
14200
+ return this.tx('custom.style.placeholder', '{"borderRadius":"999px"}');
14201
+ }
14202
+ getActionCatalogDescription(spec) {
14203
+ if (spec?.id === 'surface.open') {
14204
+ return this.i18n.t('action.surfaceOpen.description', undefined, spec.description || '', SURFACE_OPEN_I18N_NAMESPACE);
14205
+ }
14206
+ return spec?.description || '';
14207
+ }
13921
14208
  mapCatalogEntryToActionSpec(entry) {
13922
14209
  const hasPayloadSchema = !!entry.payloadSchema;
13923
14210
  return {
13924
14211
  id: entry.id,
13925
- label: entry.label,
13926
- description: entry.description || '',
14212
+ label: this.getActionCatalogLabel(entry),
14213
+ description: this.getActionCatalogDescription(entry),
13927
14214
  param: hasPayloadSchema
13928
14215
  ? {
13929
14216
  label: 'Payload (JSON opcional)',
13930
14217
  placeholder: entry.payloadSchema?.example
13931
14218
  ? JSON.stringify(entry.payloadSchema.example)
13932
14219
  : '{ }',
13933
- hint: 'Use JSON quando a ação global do app exigir payload estruturado.',
14220
+ hint: 'Use JSON quando a ação global do app exigir payload estruturado.',
13934
14221
  required: !!entry.payloadSchema?.required?.length,
13935
14222
  }
13936
14223
  : undefined,
@@ -13942,6 +14229,16 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
13942
14229
  return undefined;
13943
14230
  return getGlobalActionUiSchema(parsed.id);
13944
14231
  }
14232
+ getSurfaceOpenActionPayload(action) {
14233
+ const info = this.getActionParamInfo(action.action);
14234
+ const payload = info.isJson && info.json && typeof info.json === 'object' && !Array.isArray(info.json)
14235
+ ? info.json
14236
+ : undefined;
14237
+ return this.normalizeSurfaceOpenPayload(payload);
14238
+ }
14239
+ onSurfaceOpenActionPayloadChange(action, payload, index) {
14240
+ this.updateCustomAction(index, 'action', `surface.open:${JSON.stringify(this.normalizeSurfaceOpenPayload(payload))}`);
14241
+ }
13945
14242
  shouldShowGlobalActionField(action, field) {
13946
14243
  if (!field.dependsOnKey)
13947
14244
  return true;
@@ -14093,7 +14390,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14093
14390
  this.clearActionFieldError(action, field.key);
14094
14391
  }
14095
14392
  catch {
14096
- this.setActionFieldError(action, field.key, 'JSON inválido.');
14393
+ this.setActionFieldError(action, field.key, 'JSON inválido.');
14097
14394
  return;
14098
14395
  }
14099
14396
  }
@@ -14151,6 +14448,30 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14151
14448
  return '';
14152
14449
  }
14153
14450
  }
14451
+ normalizeSurfaceOpenPayload(payload) {
14452
+ return {
14453
+ presentation: payload?.presentation === 'drawer' ? 'drawer' : 'modal',
14454
+ title: payload?.title,
14455
+ subtitle: payload?.subtitle,
14456
+ icon: payload?.icon,
14457
+ size: payload?.size && Object.keys(payload.size).length
14458
+ ? { ...payload.size }
14459
+ : undefined,
14460
+ widget: {
14461
+ id: String(payload?.widget?.id || ''),
14462
+ inputs: { ...(payload?.widget?.inputs || {}) },
14463
+ bindingOrder: payload?.widget?.bindingOrder?.length
14464
+ ? [...payload.widget.bindingOrder]
14465
+ : undefined,
14466
+ },
14467
+ bindings: payload?.bindings?.length
14468
+ ? payload.bindings.map((binding) => ({ ...binding }))
14469
+ : [],
14470
+ context: payload?.context && typeof payload.context === 'object' && !Array.isArray(payload.context)
14471
+ ? { ...payload.context }
14472
+ : undefined,
14473
+ };
14474
+ }
14154
14475
  setActionFieldError(action, key, message) {
14155
14476
  const draftKey = this.getActionDraftKey(action);
14156
14477
  const errors = this.actionFieldErrors.get(draftKey) || {};
@@ -14479,11 +14800,14 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14479
14800
  },
14480
14801
  };
14481
14802
  this.configChange.emit(newConfig);
14803
+ if (key === 'style') {
14804
+ this.syncCustomActionStyleTexts();
14805
+ }
14482
14806
  }
14483
14807
  addCustomButton() {
14484
14808
  const newButton = {
14485
14809
  id: `custom_${Date.now()}`,
14486
- label: 'Novo Botão',
14810
+ label: 'Novo Botão',
14487
14811
  visible: true,
14488
14812
  color: 'basic',
14489
14813
  action: `custom_action_${Date.now()}`,
@@ -14498,6 +14822,38 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14498
14822
  };
14499
14823
  this.configChange.emit(newConfig);
14500
14824
  }
14825
+ canMoveCustomActionUp(index) {
14826
+ return index > 0;
14827
+ }
14828
+ canMoveCustomActionDown(index) {
14829
+ return index >= 0 && index < (this.actions.custom?.length || 0) - 1;
14830
+ }
14831
+ moveCustomActionUp(index) {
14832
+ this.reorderCustomAction(index, index - 1);
14833
+ }
14834
+ moveCustomActionDown(index) {
14835
+ this.reorderCustomAction(index, index + 1);
14836
+ }
14837
+ reorderCustomAction(fromIndex, toIndex) {
14838
+ const customActions = [...(this.actions.custom || [])];
14839
+ if (fromIndex < 0
14840
+ || toIndex < 0
14841
+ || fromIndex >= customActions.length
14842
+ || toIndex >= customActions.length
14843
+ || fromIndex === toIndex) {
14844
+ return;
14845
+ }
14846
+ const [moved] = customActions.splice(fromIndex, 1);
14847
+ customActions.splice(toIndex, 0, moved);
14848
+ const newConfig = {
14849
+ ...this.config,
14850
+ actions: {
14851
+ ...this.actions,
14852
+ custom: customActions,
14853
+ },
14854
+ };
14855
+ this.configChange.emit(newConfig);
14856
+ }
14501
14857
  removeCustomButton(index) {
14502
14858
  const customActions = [...(this.actions.custom || [])];
14503
14859
  customActions.splice(index, 1);
@@ -14549,12 +14905,70 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14549
14905
  // keep text; no update on parse error
14550
14906
  }
14551
14907
  }
14908
+ getCustomActionStyleText(action, index) {
14909
+ const key = this.getCustomActionStyleKey(action, index);
14910
+ if (this.customActionStyleTexts.has(key)) {
14911
+ return this.customActionStyleTexts.get(key) || '';
14912
+ }
14913
+ const text = this.stringifyJson(action.style);
14914
+ this.customActionStyleTexts.set(key, text);
14915
+ return text;
14916
+ }
14917
+ onCustomActionStyleTextChange(index, value) {
14918
+ const action = this.actions.custom?.[index];
14919
+ if (!action)
14920
+ return;
14921
+ const key = this.getCustomActionStyleKey(action, index);
14922
+ this.customActionStyleTexts.set(key, value);
14923
+ }
14924
+ applyCustomActionStyleText(action, index) {
14925
+ const key = this.getCustomActionStyleKey(action, index);
14926
+ const raw = (this.customActionStyleTexts.get(key) || '').trim();
14927
+ if (!raw) {
14928
+ this.customActionStyleErrors.delete(key);
14929
+ this.updateCustomAction(index, 'style', undefined);
14930
+ return;
14931
+ }
14932
+ try {
14933
+ const parsed = JSON.parse(raw);
14934
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
14935
+ this.customActionStyleErrors.set(key, this.tx('custom.validation.objectJson', 'Informe um objeto JSON válido.'));
14936
+ return;
14937
+ }
14938
+ this.customActionStyleErrors.delete(key);
14939
+ this.updateCustomAction(index, 'style', parsed);
14940
+ }
14941
+ catch {
14942
+ this.customActionStyleErrors.set(key, this.tx('custom.validation.invalidJson', 'JSON inválido.'));
14943
+ }
14944
+ }
14945
+ hasCustomActionStyleError(action, index) {
14946
+ const key = this.getCustomActionStyleKey(action, index);
14947
+ return this.customActionStyleErrors.has(key);
14948
+ }
14949
+ getCustomActionStyleError(action, index) {
14950
+ const key = this.getCustomActionStyleKey(action, index);
14951
+ return this.customActionStyleErrors.get(key) || '';
14952
+ }
14953
+ getCustomActionStyleKey(action, index) {
14954
+ return `custom:${action.id || action.action || action.label || `index-${index}`}`;
14955
+ }
14552
14956
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ActionsEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
14553
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: ActionsEditorComponent, isStandalone: true, selector: "praxis-actions-editor", inputs: { config: "config" }, outputs: { configChange: "configChange" }, usesOnChanges: true, ngImport: i0, template: `
14957
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: ActionsEditorComponent, isStandalone: true, selector: "praxis-actions-editor", inputs: { config: "config" }, outputs: { configChange: "configChange" }, providers: [
14958
+ providePraxisI18nConfig(SURFACE_OPEN_I18N_CONFIG),
14959
+ providePraxisI18nConfig(ACTIONS_EDITOR_I18N_CONFIG),
14960
+ ], usesOnChanges: true, ngImport: i0, template: `
14554
14961
  <ng-template #globalActionFields let-action let-index="index">
14555
14962
  @if (getGlobalActionSchema(action); as schema) {
14556
14963
  <div class="action-global-fields">
14557
- <div class="action-global-title">Configuração da ação global</div>
14964
+ <div class="action-global-title">Configuração da ação global</div>
14965
+ @if (schema.editorMode === 'surface-open') {
14966
+ <praxis-surface-open-action-editor
14967
+ [value]="getSurfaceOpenActionPayload(action)"
14968
+ hostKind="form"
14969
+ (valueChange)="onSurfaceOpenActionPayloadChange(action, $event, index)"
14970
+ ></praxis-surface-open-action-editor>
14971
+ } @else {
14558
14972
  <div class="action-global-grid">
14559
14973
  @for (field of schema.fields; track field.key) {
14560
14974
  @if (shouldShowGlobalActionField(action, field)) {
@@ -14562,7 +14976,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14562
14976
  <div class="action-section-title">Essencial</div>
14563
14977
  }
14564
14978
  @if (schema.id === 'showAlert' && field.key === 'title') {
14565
- <div class="action-section-title">Diálogo (opcional)</div>
14979
+ <div class="action-section-title">Diálogo (opcional)</div>
14566
14980
  }
14567
14981
  @if (field.type === 'toggle') {
14568
14982
  <mat-slide-toggle
@@ -14621,7 +15035,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14621
15035
  matSuffix
14622
15036
  type="button"
14623
15037
  class="help-icon-button"
14624
- matTooltip="Informe um JSON válido."
15038
+ matTooltip="Informe um JSON válido."
14625
15039
  >
14626
15040
  <mat-icon>help_outline</mat-icon>
14627
15041
  </button>
@@ -14680,23 +15094,24 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14680
15094
  }
14681
15095
  }
14682
15096
  </div>
15097
+ }
14683
15098
  </div>
14684
15099
  }
14685
15100
  </ng-template>
14686
15101
  <mat-tab-group>
14687
- <mat-tab label="Botões Padrão">
15102
+ <mat-tab label="Botões Padrão">
14688
15103
  <div class="editor-container">
14689
15104
  <mat-accordion multi>
14690
15105
  <mat-expansion-panel>
14691
15106
  <mat-expansion-panel-header>
14692
- Botão de Submeter (Submit)
15107
+ Botão de Submeter (Submit)
14693
15108
  </mat-expansion-panel-header>
14694
15109
  <ng-template matExpansionPanelContent>
14695
15110
  <div class="action-fields">
14696
15111
  <mat-slide-toggle
14697
15112
  [checked]="actions.submit.visible"
14698
15113
  (change)="updateAction('submit', 'visible', $event.checked)"
14699
- >Visível</mat-slide-toggle
15114
+ >Visível</mat-slide-toggle
14700
15115
  >
14701
15116
  <mat-form-field>
14702
15117
  <mat-label>Label</mat-label>
@@ -14713,7 +15128,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14713
15128
  />
14714
15129
  </mat-form-field>
14715
15130
  <mat-form-field>
14716
- <mat-labelcone</mat-label>
15131
+ <mat-label>Ícone</mat-label>
14717
15132
  <input
14718
15133
  matInput
14719
15134
  [value]="actions.submit.icon"
@@ -14775,14 +15190,14 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14775
15190
  <!-- Repetir para Cancel e Reset -->
14776
15191
  <mat-expansion-panel>
14777
15192
  <mat-expansion-panel-header>
14778
- Botão de Cancelar (Cancel)
15193
+ Botão de Cancelar (Cancel)
14779
15194
  </mat-expansion-panel-header>
14780
15195
  <ng-template matExpansionPanelContent>
14781
15196
  <div class="action-fields">
14782
15197
  <mat-slide-toggle
14783
15198
  [checked]="actions.cancel.visible"
14784
15199
  (change)="updateAction('cancel', 'visible', $event.checked)"
14785
- >Visível</mat-slide-toggle
15200
+ >Visível</mat-slide-toggle
14786
15201
  >
14787
15202
  <mat-form-field>
14788
15203
  <mat-label>Label</mat-label>
@@ -14799,7 +15214,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14799
15214
  />
14800
15215
  </mat-form-field>
14801
15216
  <mat-form-field>
14802
- <mat-labelcone</mat-label>
15217
+ <mat-label>Ícone</mat-label>
14803
15218
  <input
14804
15219
  matInput
14805
15220
  [value]="actions.cancel.icon"
@@ -14856,14 +15271,14 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14856
15271
  </mat-expansion-panel>
14857
15272
  <mat-expansion-panel>
14858
15273
  <mat-expansion-panel-header>
14859
- Botão de Limpar (Reset)
15274
+ Botão de Limpar (Reset)
14860
15275
  </mat-expansion-panel-header>
14861
15276
  <ng-template matExpansionPanelContent>
14862
15277
  <div class="action-fields">
14863
15278
  <mat-slide-toggle
14864
15279
  [checked]="actions.reset.visible"
14865
15280
  (change)="updateAction('reset', 'visible', $event.checked)"
14866
- >Visível</mat-slide-toggle
15281
+ >Visível</mat-slide-toggle
14867
15282
  >
14868
15283
  <mat-form-field>
14869
15284
  <mat-label>Label</mat-label>
@@ -14876,7 +15291,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14876
15291
  />
14877
15292
  </mat-form-field>
14878
15293
  <mat-form-field>
14879
- <mat-labelcone</mat-label>
15294
+ <mat-label>Ícone</mat-label>
14880
15295
  <input
14881
15296
  matInput
14882
15297
  [value]="actions.reset.icon"
@@ -14935,7 +15350,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14935
15350
  </div>
14936
15351
  </mat-tab>
14937
15352
 
14938
- <mat-tab label="Botões Customizados">
15353
+ <mat-tab label="Botões Customizados">
14939
15354
  <div class="editor-container">
14940
15355
  <button
14941
15356
  mat-stroked-button
@@ -14943,7 +15358,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14943
15358
  (click)="addCustomButton()"
14944
15359
  class="add-button"
14945
15360
  >
14946
- <mat-icon>add</mat-icon> Adicionar Botão
15361
+ <mat-icon>add</mat-icon> Adicionar Botão
14947
15362
  </button>
14948
15363
  <mat-accordion multi>
14949
15364
  @for (
@@ -14951,9 +15366,36 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14951
15366
  track customAction.id || customAction.action || $index;
14952
15367
  let i = $index
14953
15368
  ) {
14954
- <mat-expansion-panel>
15369
+ <div class="custom-action-panel-shell">
15370
+ <div class="custom-action-panel-toolbar">
15371
+ <div class="custom-action-order-controls">
15372
+ <button
15373
+ mat-icon-button
15374
+ type="button"
15375
+ [attr.aria-label]="getMoveCustomActionAriaLabel('up', customAction)"
15376
+ [matTooltip]="tx('custom.order.moveUp.tooltip', 'Mover para cima')"
15377
+ [disabled]="!canMoveCustomActionUp(i)"
15378
+ (click)="moveCustomActionUp(i)"
15379
+ >
15380
+ <mat-icon>arrow_upward</mat-icon>
15381
+ </button>
15382
+ <button
15383
+ mat-icon-button
15384
+ type="button"
15385
+ [attr.aria-label]="getMoveCustomActionAriaLabel('down', customAction)"
15386
+ [matTooltip]="tx('custom.order.moveDown.tooltip', 'Mover para baixo')"
15387
+ [disabled]="!canMoveCustomActionDown(i)"
15388
+ (click)="moveCustomActionDown(i)"
15389
+ >
15390
+ <mat-icon>arrow_downward</mat-icon>
15391
+ </button>
15392
+ </div>
15393
+ </div>
15394
+ <mat-expansion-panel>
14955
15395
  <mat-expansion-panel-header>
14956
- {{ customAction.label || 'Novo Botão Customizado' }}
15396
+ <mat-panel-title>
15397
+ {{ getCustomActionTitle(customAction) }}
15398
+ </mat-panel-title>
14957
15399
  </mat-expansion-panel-header>
14958
15400
  <ng-template matExpansionPanelContent>
14959
15401
  <div class="action-fields">
@@ -14962,10 +15404,10 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14962
15404
  (change)="
14963
15405
  updateCustomAction(i, 'visible', $event.checked)
14964
15406
  "
14965
- >Visível</mat-slide-toggle
15407
+ >Visível</mat-slide-toggle
14966
15408
  >
14967
15409
  <mat-form-field>
14968
- <mat-label>ID da Ação</mat-label>
15410
+ <mat-label>ID da Ação</mat-label>
14969
15411
  <input
14970
15412
  matInput
14971
15413
  [value]="customAction.id"
@@ -14976,7 +15418,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14976
15418
  />
14977
15419
  </mat-form-field>
14978
15420
  <mat-form-field>
14979
- <mat-label>Ação</mat-label>
15421
+ <mat-label>Ação</mat-label>
14980
15422
  <mat-select
14981
15423
  [value]="getCustomActionSelectValue(customAction.action)"
14982
15424
  (selectionChange)="onCustomActionSelectChange(i, $event.value)"
@@ -14984,7 +15426,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14984
15426
  <mat-option [value]="customActionValue">Customizada</mat-option>
14985
15427
  <mat-optgroup label="Acoes globais">
14986
15428
  @for (spec of globalActionCatalog; track spec.id) {
14987
- <mat-option [value]="spec.id">{{ spec.label }}</mat-option>
15429
+ <mat-option [value]="spec.id">{{ getActionCatalogLabel(spec) }}</mat-option>
14988
15430
  }
14989
15431
  </mat-optgroup>
14990
15432
  </mat-select>
@@ -14993,14 +15435,14 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
14993
15435
  matSuffix
14994
15436
  type="button"
14995
15437
  class="help-icon-button"
14996
- matTooltip="Ações globais exigem executor no app (ActionResolver). Customizadas emitem evento. Cor/posição afetam o botão."
15438
+ matTooltip="Ações globais exigem executor no app (ActionResolver). Customizadas só emitem evento. Cor/posição afetam o botão."
14997
15439
  >
14998
15440
  <mat-icon>help_outline</mat-icon>
14999
15441
  </button>
15000
15442
  </mat-form-field>
15001
15443
  @if (getCustomActionSelectValue(customAction.action) === customActionValue) {
15002
15444
  <mat-form-field>
15003
- <mat-label>Ação customizada</mat-label>
15445
+ <mat-label>Ação customizada</mat-label>
15004
15446
  <input
15005
15447
  matInput
15006
15448
  [value]="getCustomActionCustomValue(customAction.action)"
@@ -15018,7 +15460,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
15018
15460
  @if (getActionSpecById(getCustomActionSelectValue(customAction.action)); as actionSpec) {
15019
15461
  @if (actionSpec.param) {
15020
15462
  <mat-form-field>
15021
- <mat-label>{{ actionSpec.param.label || 'Parâmetro' }}</mat-label>
15463
+ <mat-label>{{ actionSpec.param.label || 'Parâmetro' }}</mat-label>
15022
15464
  <input
15023
15465
  matInput
15024
15466
  [value]="getCustomActionParam(customAction.action)"
@@ -15048,7 +15490,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
15048
15490
  />
15049
15491
  </mat-form-field>
15050
15492
  <mat-form-field>
15051
- <mat-labelcone</mat-label>
15493
+ <mat-label>Ícone</mat-label>
15052
15494
  <input
15053
15495
  matInput
15054
15496
  [value]="customAction.icon"
@@ -15062,7 +15504,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
15062
15504
  />
15063
15505
  </mat-form-field>
15064
15506
  <mat-form-field>
15065
- <mat-label>Cor do botão</mat-label>
15507
+ <mat-label>Cor do botão</mat-label>
15066
15508
  <mat-select
15067
15509
  [value]="customAction.color"
15068
15510
  (selectionChange)="
@@ -15075,17 +15517,118 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
15075
15517
  <mat-option value="basic">Basic</mat-option>
15076
15518
  </mat-select>
15077
15519
  </mat-form-field>
15520
+ <mat-form-field>
15521
+ <mat-label>{{ tx('custom.variant', 'Variante') }}</mat-label>
15522
+ <mat-select
15523
+ [value]="customAction.variant"
15524
+ (selectionChange)="
15525
+ updateCustomAction(i, 'variant', $event.value)
15526
+ "
15527
+ >
15528
+ <mat-option value="raised">Elevado (raised)</mat-option>
15529
+ <mat-option value="stroked">Contornado (stroked)</mat-option>
15530
+ <mat-option value="flat">Plano (flat)</mat-option>
15531
+ <mat-option value="fab">Flutuante (fab)</mat-option>
15532
+ </mat-select>
15533
+ </mat-form-field>
15534
+ <mat-form-field>
15535
+ <mat-label>{{ tx('custom.size', 'Tamanho') }}</mat-label>
15536
+ <mat-select
15537
+ [value]="customAction.size"
15538
+ (selectionChange)="
15539
+ updateCustomAction(i, 'size', $event.value)
15540
+ "
15541
+ >
15542
+ <mat-option value="small">{{ tx('custom.size.small', 'Pequeno') }}</mat-option>
15543
+ <mat-option value="medium">{{ tx('custom.size.medium', 'Médio') }}</mat-option>
15544
+ <mat-option value="large">{{ tx('custom.size.large', 'Grande') }}</mat-option>
15545
+ </mat-select>
15546
+ </mat-form-field>
15547
+ <mat-form-field>
15548
+ <mat-label>{{ tx('custom.tooltip', 'Tooltip') }}</mat-label>
15549
+ <input
15550
+ matInput
15551
+ [value]="customAction.tooltip"
15552
+ (input)="
15553
+ updateCustomAction(
15554
+ i,
15555
+ 'tooltip',
15556
+ $any($event.target).value
15557
+ )
15558
+ "
15559
+ />
15560
+ </mat-form-field>
15561
+ <mat-form-field>
15562
+ <mat-label>{{ tx('custom.shortcut', 'Atalho de Teclado') }}</mat-label>
15563
+ <input
15564
+ matInput
15565
+ [value]="customAction.shortcut"
15566
+ (input)="
15567
+ updateCustomAction(
15568
+ i,
15569
+ 'shortcut',
15570
+ $any($event.target).value
15571
+ )
15572
+ "
15573
+ [placeholder]="tx('custom.shortcut.placeholder', 'Ex.: ctrl+shift+a')"
15574
+ />
15575
+ </mat-form-field>
15576
+ <mat-form-field>
15577
+ <mat-label>{{ tx('custom.className', 'Classe CSS') }}</mat-label>
15578
+ <input
15579
+ matInput
15580
+ [value]="$any(customAction).className"
15581
+ (input)="
15582
+ updateCustomAction(
15583
+ i,
15584
+ 'className',
15585
+ $any($event.target).value
15586
+ )
15587
+ "
15588
+ />
15589
+ </mat-form-field>
15590
+ <mat-slide-toggle
15591
+ [checked]="!!customAction.disabled"
15592
+ (change)="
15593
+ updateCustomAction(i, 'disabled', $event.checked)
15594
+ "
15595
+ >
15596
+ {{ tx('custom.disabled', 'Desabilitado') }}
15597
+ </mat-slide-toggle>
15598
+ <mat-slide-toggle
15599
+ [checked]="!!customAction.loading"
15600
+ (change)="
15601
+ updateCustomAction(i, 'loading', $event.checked)
15602
+ "
15603
+ >
15604
+ {{ tx('custom.loading', 'Loading') }}
15605
+ </mat-slide-toggle>
15606
+ <mat-form-field class="w-100">
15607
+ <mat-label>{{ tx('custom.style', 'Estilos do botão (JSON)') }}</mat-label>
15608
+ <textarea
15609
+ matInput
15610
+ rows="4"
15611
+ [ngModel]="getCustomActionStyleText(customAction, i)"
15612
+ (ngModelChange)="onCustomActionStyleTextChange(i, $event)"
15613
+ (blur)="applyCustomActionStyleText(customAction, i)"
15614
+ [placeholder]="getCustomStylePlaceholder()"
15615
+ ></textarea>
15616
+ @if (hasCustomActionStyleError(customAction, i)) {
15617
+ <mat-error>{{ getCustomActionStyleError(customAction, i) }}</mat-error>
15618
+ }
15619
+ </mat-form-field>
15078
15620
  </div>
15079
15621
  <button
15080
15622
  mat-icon-button
15081
15623
  color="warn"
15082
15624
  (click)="removeCustomButton(i)"
15083
- matTooltip="Remover este botão"
15625
+ matTooltip="Remover este botão"
15084
15626
  >
15085
15627
  <mat-icon>delete</mat-icon>
15086
15628
  </button>
15087
15629
  </ng-template>
15088
15630
  </mat-expansion-panel>
15631
+ </div>
15089
15632
  }
15090
15633
  </mat-accordion>
15091
15634
  </div>
@@ -15094,19 +15637,19 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
15094
15637
  <mat-tab label="Layout">
15095
15638
  <div class="editor-container action-fields">
15096
15639
  <mat-form-field>
15097
- <mat-label>Posição estrutural</mat-label>
15640
+ <mat-label>Posição estrutural</mat-label>
15098
15641
  <mat-select [value]="actions.placement || 'afterSections'" (selectionChange)="updateLayout('placement', $event.value)">
15099
- <mat-option value="insideLastSection">Dentro da última seção</mat-option>
15100
- <mat-option value="afterSections">Após as seções</mat-option>
15101
- <mat-option value="top">Antes das seções</mat-option>
15642
+ <mat-option value="insideLastSection">Dentro da última seção</mat-option>
15643
+ <mat-option value="afterSections">Após as seções</mat-option>
15644
+ <mat-option value="top">Antes das seções</mat-option>
15102
15645
  </mat-select>
15103
15646
  </mat-form-field>
15104
15647
  <mat-form-field>
15105
- <mat-label>Espaço acima (px)</mat-label>
15106
- <input matInput type="number" [value]="getGapTopPx()" (input)="onGapTopInput($any($event.target).value)" placeholder="(padrão)" />
15648
+ <mat-label>Espaço acima (px)</mat-label>
15649
+ <input matInput type="number" [value]="getGapTopPx()" (input)="onGapTopInput($any($event.target).value)" placeholder="(padrão)" />
15107
15650
  </mat-form-field>
15108
15651
  <mat-form-field>
15109
- <mat-label>Alinhamento dos Botões</mat-label>
15652
+ <mat-label>Alinhamento dos Botões</mat-label>
15110
15653
  <mat-select
15111
15654
  [value]="actions.position"
15112
15655
  (selectionChange)="updateLayout('position', $event.value)"
@@ -15119,7 +15662,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
15119
15662
  </mat-select>
15120
15663
  </mat-form-field>
15121
15664
  <mat-form-field>
15122
- <mat-label>Orientação</mat-label>
15665
+ <mat-label>Orientação</mat-label>
15123
15666
  <mat-select
15124
15667
  [value]="actions.orientation"
15125
15668
  (selectionChange)="updateLayout('orientation', $event.value)"
@@ -15129,14 +15672,14 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
15129
15672
  </mat-select>
15130
15673
  </mat-form-field>
15131
15674
  <mat-form-field>
15132
- <mat-label>Espaçamento</mat-label>
15675
+ <mat-label>Espaçamento</mat-label>
15133
15676
  <mat-select
15134
15677
  [value]="actions.spacing"
15135
15678
  (selectionChange)="updateLayout('spacing', $event.value)"
15136
15679
  >
15137
15680
  <mat-option value="compact">Compacto</mat-option>
15138
15681
  <mat-option value="normal">Normal</mat-option>
15139
- <mat-option value="spacious">Espaçado</mat-option>
15682
+ <mat-option value="spacious">Espaçado</mat-option>
15140
15683
  </mat-select>
15141
15684
  </mat-form-field>
15142
15685
  <mat-slide-toggle
@@ -15155,11 +15698,11 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
15155
15698
  <mat-slide-toggle
15156
15699
  [checked]="actions.sticky"
15157
15700
  (change)="updateLayout('sticky', $event.checked)"
15158
- >Barra de Ações Fixa (Sticky)</mat-slide-toggle
15701
+ >Barra de Ações Fixa (Sticky)</mat-slide-toggle
15159
15702
  >
15160
15703
  <mat-expansion-panel>
15161
15704
  <mat-expansion-panel-header>
15162
- Configurações Mobile
15705
+ Configurações Mobile
15163
15706
  </mat-expansion-panel-header>
15164
15707
  <ng-template matExpansionPanelContent>
15165
15708
  <div class="action-fields">
@@ -15176,7 +15719,7 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
15176
15719
  updateLayoutMobile('position', $event.value)
15177
15720
  "
15178
15721
  >
15179
- <mat-option [value]="undefined">Padrão</mat-option>
15722
+ <mat-option [value]="undefined">Padrão</mat-option>
15180
15723
  <mat-option value="left">Esquerda</mat-option>
15181
15724
  <mat-option value="center">Centro</mat-option>
15182
15725
  <mat-option value="right">Direita</mat-option>
@@ -15184,14 +15727,14 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
15184
15727
  </mat-select>
15185
15728
  </mat-form-field>
15186
15729
  <mat-form-field>
15187
- <mat-label>Orientação (mobile)</mat-label>
15730
+ <mat-label>Orientação (mobile)</mat-label>
15188
15731
  <mat-select
15189
15732
  [value]="actions.mobile?.orientation"
15190
15733
  (selectionChange)="
15191
15734
  updateLayoutMobile('orientation', $event.value)
15192
15735
  "
15193
15736
  >
15194
- <mat-option [value]="undefined">Padrão</mat-option>
15737
+ <mat-option [value]="undefined">Padrão</mat-option>
15195
15738
  <mat-option value="horizontal">Horizontal</mat-option>
15196
15739
  <mat-option value="vertical">Vertical</mat-option>
15197
15740
  </mat-select>
@@ -15202,11 +15745,14 @@ let ActionsEditorComponent$1 = class ActionsEditorComponent {
15202
15745
  </div>
15203
15746
  </mat-tab>
15204
15747
  </mat-tab-group>
15205
- `, isInline: true, styles: [".editor-container{padding:16px;display:flex;flex-direction:column;gap:16px}.action-fields{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:16px;align-items:center}.action-global-fields{grid-column:1 / -1;padding:12px 14px;border:1px dashed var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));border-radius:10px;background:var(--md-sys-color-surface-container-low)}.action-global-title{font-size:12px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #9aa0a6);margin-bottom:10px}.action-global-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px 16px}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.action-global-fields .mat-mdc-form-field-icon-suffix{align-self:center}.action-section-title{width:100%;margin:10px 0 2px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #9aa0a6)}.add-button{margin-bottom:16px;align-self:flex-start}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$3.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i6$4.MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i3$1.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i3$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3$1.MatExpansionPanelContent, selector: "ng-template[matExpansionPanelContent]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] });
15748
+ `, isInline: true, styles: [".editor-container{padding:16px;display:flex;flex-direction:column;gap:16px}.action-fields{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:16px;align-items:center}.action-global-fields{grid-column:1 / -1;padding:12px 14px;border:1px dashed var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));border-radius:10px;background:var(--md-sys-color-surface-container-low)}.action-global-title{font-size:12px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #9aa0a6);margin-bottom:10px}.action-global-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px 16px}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.action-global-fields .mat-mdc-form-field-icon-suffix{align-self:center}.action-section-title{width:100%;margin:10px 0 2px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #9aa0a6)}.add-button{margin-bottom:16px;align-self:flex-start}.custom-action-panel-shell{display:grid;gap:8px}.custom-action-panel-toolbar{display:flex;justify-content:flex-end}.custom-action-order-controls{display:inline-flex;align-items:center;gap:4px;justify-content:flex-end}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$3.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i6$4.MatOptgroup, selector: "mat-optgroup", inputs: ["label", "disabled"], exportAs: ["matOptgroup"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i7$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i3$1.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i3$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i3$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i3$1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i3$1.MatExpansionPanelContent, selector: "ng-template[matExpansionPanelContent]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: SurfaceOpenActionEditorComponent, selector: "praxis-surface-open-action-editor", inputs: ["value", "hostKind"], outputs: ["valueChange"] }] });
15206
15749
  };
15207
15750
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: ActionsEditorComponent$1, decorators: [{
15208
15751
  type: Component,
15209
- args: [{ selector: 'praxis-actions-editor', standalone: true, imports: [
15752
+ args: [{ selector: 'praxis-actions-editor', standalone: true, providers: [
15753
+ providePraxisI18nConfig(SURFACE_OPEN_I18N_CONFIG),
15754
+ providePraxisI18nConfig(ACTIONS_EDITOR_I18N_CONFIG),
15755
+ ], imports: [
15210
15756
  CommonModule,
15211
15757
  FormsModule,
15212
15758
  MatFormFieldModule,
@@ -15218,11 +15764,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15218
15764
  MatIconModule,
15219
15765
  MatButtonModule,
15220
15766
  MatTooltipModule,
15767
+ SurfaceOpenActionEditorComponent,
15221
15768
  ], template: `
15222
15769
  <ng-template #globalActionFields let-action let-index="index">
15223
15770
  @if (getGlobalActionSchema(action); as schema) {
15224
15771
  <div class="action-global-fields">
15225
- <div class="action-global-title">Configuração da ação global</div>
15772
+ <div class="action-global-title">Configuração da ação global</div>
15773
+ @if (schema.editorMode === 'surface-open') {
15774
+ <praxis-surface-open-action-editor
15775
+ [value]="getSurfaceOpenActionPayload(action)"
15776
+ hostKind="form"
15777
+ (valueChange)="onSurfaceOpenActionPayloadChange(action, $event, index)"
15778
+ ></praxis-surface-open-action-editor>
15779
+ } @else {
15226
15780
  <div class="action-global-grid">
15227
15781
  @for (field of schema.fields; track field.key) {
15228
15782
  @if (shouldShowGlobalActionField(action, field)) {
@@ -15230,7 +15784,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15230
15784
  <div class="action-section-title">Essencial</div>
15231
15785
  }
15232
15786
  @if (schema.id === 'showAlert' && field.key === 'title') {
15233
- <div class="action-section-title">Diálogo (opcional)</div>
15787
+ <div class="action-section-title">Diálogo (opcional)</div>
15234
15788
  }
15235
15789
  @if (field.type === 'toggle') {
15236
15790
  <mat-slide-toggle
@@ -15289,7 +15843,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15289
15843
  matSuffix
15290
15844
  type="button"
15291
15845
  class="help-icon-button"
15292
- matTooltip="Informe um JSON válido."
15846
+ matTooltip="Informe um JSON válido."
15293
15847
  >
15294
15848
  <mat-icon>help_outline</mat-icon>
15295
15849
  </button>
@@ -15348,23 +15902,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15348
15902
  }
15349
15903
  }
15350
15904
  </div>
15905
+ }
15351
15906
  </div>
15352
15907
  }
15353
15908
  </ng-template>
15354
15909
  <mat-tab-group>
15355
- <mat-tab label="Botões Padrão">
15910
+ <mat-tab label="Botões Padrão">
15356
15911
  <div class="editor-container">
15357
15912
  <mat-accordion multi>
15358
15913
  <mat-expansion-panel>
15359
15914
  <mat-expansion-panel-header>
15360
- Botão de Submeter (Submit)
15915
+ Botão de Submeter (Submit)
15361
15916
  </mat-expansion-panel-header>
15362
15917
  <ng-template matExpansionPanelContent>
15363
15918
  <div class="action-fields">
15364
15919
  <mat-slide-toggle
15365
15920
  [checked]="actions.submit.visible"
15366
15921
  (change)="updateAction('submit', 'visible', $event.checked)"
15367
- >Visível</mat-slide-toggle
15922
+ >Visível</mat-slide-toggle
15368
15923
  >
15369
15924
  <mat-form-field>
15370
15925
  <mat-label>Label</mat-label>
@@ -15381,7 +15936,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15381
15936
  />
15382
15937
  </mat-form-field>
15383
15938
  <mat-form-field>
15384
- <mat-labelcone</mat-label>
15939
+ <mat-label>Ícone</mat-label>
15385
15940
  <input
15386
15941
  matInput
15387
15942
  [value]="actions.submit.icon"
@@ -15443,14 +15998,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15443
15998
  <!-- Repetir para Cancel e Reset -->
15444
15999
  <mat-expansion-panel>
15445
16000
  <mat-expansion-panel-header>
15446
- Botão de Cancelar (Cancel)
16001
+ Botão de Cancelar (Cancel)
15447
16002
  </mat-expansion-panel-header>
15448
16003
  <ng-template matExpansionPanelContent>
15449
16004
  <div class="action-fields">
15450
16005
  <mat-slide-toggle
15451
16006
  [checked]="actions.cancel.visible"
15452
16007
  (change)="updateAction('cancel', 'visible', $event.checked)"
15453
- >Visível</mat-slide-toggle
16008
+ >Visível</mat-slide-toggle
15454
16009
  >
15455
16010
  <mat-form-field>
15456
16011
  <mat-label>Label</mat-label>
@@ -15467,7 +16022,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15467
16022
  />
15468
16023
  </mat-form-field>
15469
16024
  <mat-form-field>
15470
- <mat-labelcone</mat-label>
16025
+ <mat-label>Ícone</mat-label>
15471
16026
  <input
15472
16027
  matInput
15473
16028
  [value]="actions.cancel.icon"
@@ -15524,14 +16079,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15524
16079
  </mat-expansion-panel>
15525
16080
  <mat-expansion-panel>
15526
16081
  <mat-expansion-panel-header>
15527
- Botão de Limpar (Reset)
16082
+ Botão de Limpar (Reset)
15528
16083
  </mat-expansion-panel-header>
15529
16084
  <ng-template matExpansionPanelContent>
15530
16085
  <div class="action-fields">
15531
16086
  <mat-slide-toggle
15532
16087
  [checked]="actions.reset.visible"
15533
16088
  (change)="updateAction('reset', 'visible', $event.checked)"
15534
- >Visível</mat-slide-toggle
16089
+ >Visível</mat-slide-toggle
15535
16090
  >
15536
16091
  <mat-form-field>
15537
16092
  <mat-label>Label</mat-label>
@@ -15544,7 +16099,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15544
16099
  />
15545
16100
  </mat-form-field>
15546
16101
  <mat-form-field>
15547
- <mat-labelcone</mat-label>
16102
+ <mat-label>Ícone</mat-label>
15548
16103
  <input
15549
16104
  matInput
15550
16105
  [value]="actions.reset.icon"
@@ -15603,7 +16158,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15603
16158
  </div>
15604
16159
  </mat-tab>
15605
16160
 
15606
- <mat-tab label="Botões Customizados">
16161
+ <mat-tab label="Botões Customizados">
15607
16162
  <div class="editor-container">
15608
16163
  <button
15609
16164
  mat-stroked-button
@@ -15611,7 +16166,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15611
16166
  (click)="addCustomButton()"
15612
16167
  class="add-button"
15613
16168
  >
15614
- <mat-icon>add</mat-icon> Adicionar Botão
16169
+ <mat-icon>add</mat-icon> Adicionar Botão
15615
16170
  </button>
15616
16171
  <mat-accordion multi>
15617
16172
  @for (
@@ -15619,9 +16174,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15619
16174
  track customAction.id || customAction.action || $index;
15620
16175
  let i = $index
15621
16176
  ) {
15622
- <mat-expansion-panel>
16177
+ <div class="custom-action-panel-shell">
16178
+ <div class="custom-action-panel-toolbar">
16179
+ <div class="custom-action-order-controls">
16180
+ <button
16181
+ mat-icon-button
16182
+ type="button"
16183
+ [attr.aria-label]="getMoveCustomActionAriaLabel('up', customAction)"
16184
+ [matTooltip]="tx('custom.order.moveUp.tooltip', 'Mover para cima')"
16185
+ [disabled]="!canMoveCustomActionUp(i)"
16186
+ (click)="moveCustomActionUp(i)"
16187
+ >
16188
+ <mat-icon>arrow_upward</mat-icon>
16189
+ </button>
16190
+ <button
16191
+ mat-icon-button
16192
+ type="button"
16193
+ [attr.aria-label]="getMoveCustomActionAriaLabel('down', customAction)"
16194
+ [matTooltip]="tx('custom.order.moveDown.tooltip', 'Mover para baixo')"
16195
+ [disabled]="!canMoveCustomActionDown(i)"
16196
+ (click)="moveCustomActionDown(i)"
16197
+ >
16198
+ <mat-icon>arrow_downward</mat-icon>
16199
+ </button>
16200
+ </div>
16201
+ </div>
16202
+ <mat-expansion-panel>
15623
16203
  <mat-expansion-panel-header>
15624
- {{ customAction.label || 'Novo Botão Customizado' }}
16204
+ <mat-panel-title>
16205
+ {{ getCustomActionTitle(customAction) }}
16206
+ </mat-panel-title>
15625
16207
  </mat-expansion-panel-header>
15626
16208
  <ng-template matExpansionPanelContent>
15627
16209
  <div class="action-fields">
@@ -15630,10 +16212,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15630
16212
  (change)="
15631
16213
  updateCustomAction(i, 'visible', $event.checked)
15632
16214
  "
15633
- >Visível</mat-slide-toggle
16215
+ >Visível</mat-slide-toggle
15634
16216
  >
15635
16217
  <mat-form-field>
15636
- <mat-label>ID da Ação</mat-label>
16218
+ <mat-label>ID da Ação</mat-label>
15637
16219
  <input
15638
16220
  matInput
15639
16221
  [value]="customAction.id"
@@ -15644,7 +16226,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15644
16226
  />
15645
16227
  </mat-form-field>
15646
16228
  <mat-form-field>
15647
- <mat-label>Ação</mat-label>
16229
+ <mat-label>Ação</mat-label>
15648
16230
  <mat-select
15649
16231
  [value]="getCustomActionSelectValue(customAction.action)"
15650
16232
  (selectionChange)="onCustomActionSelectChange(i, $event.value)"
@@ -15652,7 +16234,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15652
16234
  <mat-option [value]="customActionValue">Customizada</mat-option>
15653
16235
  <mat-optgroup label="Acoes globais">
15654
16236
  @for (spec of globalActionCatalog; track spec.id) {
15655
- <mat-option [value]="spec.id">{{ spec.label }}</mat-option>
16237
+ <mat-option [value]="spec.id">{{ getActionCatalogLabel(spec) }}</mat-option>
15656
16238
  }
15657
16239
  </mat-optgroup>
15658
16240
  </mat-select>
@@ -15661,14 +16243,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15661
16243
  matSuffix
15662
16244
  type="button"
15663
16245
  class="help-icon-button"
15664
- matTooltip="Ações globais exigem executor no app (ActionResolver). Customizadas emitem evento. Cor/posição afetam o botão."
16246
+ matTooltip="Ações globais exigem executor no app (ActionResolver). Customizadas só emitem evento. Cor/posição afetam o botão."
15665
16247
  >
15666
16248
  <mat-icon>help_outline</mat-icon>
15667
16249
  </button>
15668
16250
  </mat-form-field>
15669
16251
  @if (getCustomActionSelectValue(customAction.action) === customActionValue) {
15670
16252
  <mat-form-field>
15671
- <mat-label>Ação customizada</mat-label>
16253
+ <mat-label>Ação customizada</mat-label>
15672
16254
  <input
15673
16255
  matInput
15674
16256
  [value]="getCustomActionCustomValue(customAction.action)"
@@ -15686,7 +16268,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15686
16268
  @if (getActionSpecById(getCustomActionSelectValue(customAction.action)); as actionSpec) {
15687
16269
  @if (actionSpec.param) {
15688
16270
  <mat-form-field>
15689
- <mat-label>{{ actionSpec.param.label || 'Parâmetro' }}</mat-label>
16271
+ <mat-label>{{ actionSpec.param.label || 'Parâmetro' }}</mat-label>
15690
16272
  <input
15691
16273
  matInput
15692
16274
  [value]="getCustomActionParam(customAction.action)"
@@ -15716,7 +16298,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15716
16298
  />
15717
16299
  </mat-form-field>
15718
16300
  <mat-form-field>
15719
- <mat-labelcone</mat-label>
16301
+ <mat-label>Ícone</mat-label>
15720
16302
  <input
15721
16303
  matInput
15722
16304
  [value]="customAction.icon"
@@ -15730,7 +16312,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15730
16312
  />
15731
16313
  </mat-form-field>
15732
16314
  <mat-form-field>
15733
- <mat-label>Cor do botão</mat-label>
16315
+ <mat-label>Cor do botão</mat-label>
15734
16316
  <mat-select
15735
16317
  [value]="customAction.color"
15736
16318
  (selectionChange)="
@@ -15743,38 +16325,139 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15743
16325
  <mat-option value="basic">Basic</mat-option>
15744
16326
  </mat-select>
15745
16327
  </mat-form-field>
15746
- </div>
15747
- <button
15748
- mat-icon-button
15749
- color="warn"
15750
- (click)="removeCustomButton(i)"
15751
- matTooltip="Remover este botão"
15752
- >
15753
- <mat-icon>delete</mat-icon>
15754
- </button>
15755
- </ng-template>
15756
- </mat-expansion-panel>
15757
- }
15758
- </mat-accordion>
15759
- </div>
16328
+ <mat-form-field>
16329
+ <mat-label>{{ tx('custom.variant', 'Variante') }}</mat-label>
16330
+ <mat-select
16331
+ [value]="customAction.variant"
16332
+ (selectionChange)="
16333
+ updateCustomAction(i, 'variant', $event.value)
16334
+ "
16335
+ >
16336
+ <mat-option value="raised">Elevado (raised)</mat-option>
16337
+ <mat-option value="stroked">Contornado (stroked)</mat-option>
16338
+ <mat-option value="flat">Plano (flat)</mat-option>
16339
+ <mat-option value="fab">Flutuante (fab)</mat-option>
16340
+ </mat-select>
16341
+ </mat-form-field>
16342
+ <mat-form-field>
16343
+ <mat-label>{{ tx('custom.size', 'Tamanho') }}</mat-label>
16344
+ <mat-select
16345
+ [value]="customAction.size"
16346
+ (selectionChange)="
16347
+ updateCustomAction(i, 'size', $event.value)
16348
+ "
16349
+ >
16350
+ <mat-option value="small">{{ tx('custom.size.small', 'Pequeno') }}</mat-option>
16351
+ <mat-option value="medium">{{ tx('custom.size.medium', 'Médio') }}</mat-option>
16352
+ <mat-option value="large">{{ tx('custom.size.large', 'Grande') }}</mat-option>
16353
+ </mat-select>
16354
+ </mat-form-field>
16355
+ <mat-form-field>
16356
+ <mat-label>{{ tx('custom.tooltip', 'Tooltip') }}</mat-label>
16357
+ <input
16358
+ matInput
16359
+ [value]="customAction.tooltip"
16360
+ (input)="
16361
+ updateCustomAction(
16362
+ i,
16363
+ 'tooltip',
16364
+ $any($event.target).value
16365
+ )
16366
+ "
16367
+ />
16368
+ </mat-form-field>
16369
+ <mat-form-field>
16370
+ <mat-label>{{ tx('custom.shortcut', 'Atalho de Teclado') }}</mat-label>
16371
+ <input
16372
+ matInput
16373
+ [value]="customAction.shortcut"
16374
+ (input)="
16375
+ updateCustomAction(
16376
+ i,
16377
+ 'shortcut',
16378
+ $any($event.target).value
16379
+ )
16380
+ "
16381
+ [placeholder]="tx('custom.shortcut.placeholder', 'Ex.: ctrl+shift+a')"
16382
+ />
16383
+ </mat-form-field>
16384
+ <mat-form-field>
16385
+ <mat-label>{{ tx('custom.className', 'Classe CSS') }}</mat-label>
16386
+ <input
16387
+ matInput
16388
+ [value]="$any(customAction).className"
16389
+ (input)="
16390
+ updateCustomAction(
16391
+ i,
16392
+ 'className',
16393
+ $any($event.target).value
16394
+ )
16395
+ "
16396
+ />
16397
+ </mat-form-field>
16398
+ <mat-slide-toggle
16399
+ [checked]="!!customAction.disabled"
16400
+ (change)="
16401
+ updateCustomAction(i, 'disabled', $event.checked)
16402
+ "
16403
+ >
16404
+ {{ tx('custom.disabled', 'Desabilitado') }}
16405
+ </mat-slide-toggle>
16406
+ <mat-slide-toggle
16407
+ [checked]="!!customAction.loading"
16408
+ (change)="
16409
+ updateCustomAction(i, 'loading', $event.checked)
16410
+ "
16411
+ >
16412
+ {{ tx('custom.loading', 'Loading') }}
16413
+ </mat-slide-toggle>
16414
+ <mat-form-field class="w-100">
16415
+ <mat-label>{{ tx('custom.style', 'Estilos do botão (JSON)') }}</mat-label>
16416
+ <textarea
16417
+ matInput
16418
+ rows="4"
16419
+ [ngModel]="getCustomActionStyleText(customAction, i)"
16420
+ (ngModelChange)="onCustomActionStyleTextChange(i, $event)"
16421
+ (blur)="applyCustomActionStyleText(customAction, i)"
16422
+ [placeholder]="getCustomStylePlaceholder()"
16423
+ ></textarea>
16424
+ @if (hasCustomActionStyleError(customAction, i)) {
16425
+ <mat-error>{{ getCustomActionStyleError(customAction, i) }}</mat-error>
16426
+ }
16427
+ </mat-form-field>
16428
+ </div>
16429
+ <button
16430
+ mat-icon-button
16431
+ color="warn"
16432
+ (click)="removeCustomButton(i)"
16433
+ matTooltip="Remover este botão"
16434
+ >
16435
+ <mat-icon>delete</mat-icon>
16436
+ </button>
16437
+ </ng-template>
16438
+ </mat-expansion-panel>
16439
+ </div>
16440
+ }
16441
+ </mat-accordion>
16442
+ </div>
15760
16443
  </mat-tab>
15761
16444
 
15762
16445
  <mat-tab label="Layout">
15763
16446
  <div class="editor-container action-fields">
15764
16447
  <mat-form-field>
15765
- <mat-label>Posição estrutural</mat-label>
16448
+ <mat-label>Posição estrutural</mat-label>
15766
16449
  <mat-select [value]="actions.placement || 'afterSections'" (selectionChange)="updateLayout('placement', $event.value)">
15767
- <mat-option value="insideLastSection">Dentro da última seção</mat-option>
15768
- <mat-option value="afterSections">Após as seções</mat-option>
15769
- <mat-option value="top">Antes das seções</mat-option>
16450
+ <mat-option value="insideLastSection">Dentro da última seção</mat-option>
16451
+ <mat-option value="afterSections">Após as seções</mat-option>
16452
+ <mat-option value="top">Antes das seções</mat-option>
15770
16453
  </mat-select>
15771
16454
  </mat-form-field>
15772
16455
  <mat-form-field>
15773
- <mat-label>Espaço acima (px)</mat-label>
15774
- <input matInput type="number" [value]="getGapTopPx()" (input)="onGapTopInput($any($event.target).value)" placeholder="(padrão)" />
16456
+ <mat-label>Espaço acima (px)</mat-label>
16457
+ <input matInput type="number" [value]="getGapTopPx()" (input)="onGapTopInput($any($event.target).value)" placeholder="(padrão)" />
15775
16458
  </mat-form-field>
15776
16459
  <mat-form-field>
15777
- <mat-label>Alinhamento dos Botões</mat-label>
16460
+ <mat-label>Alinhamento dos Botões</mat-label>
15778
16461
  <mat-select
15779
16462
  [value]="actions.position"
15780
16463
  (selectionChange)="updateLayout('position', $event.value)"
@@ -15787,7 +16470,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15787
16470
  </mat-select>
15788
16471
  </mat-form-field>
15789
16472
  <mat-form-field>
15790
- <mat-label>Orientação</mat-label>
16473
+ <mat-label>Orientação</mat-label>
15791
16474
  <mat-select
15792
16475
  [value]="actions.orientation"
15793
16476
  (selectionChange)="updateLayout('orientation', $event.value)"
@@ -15797,14 +16480,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15797
16480
  </mat-select>
15798
16481
  </mat-form-field>
15799
16482
  <mat-form-field>
15800
- <mat-label>Espaçamento</mat-label>
16483
+ <mat-label>Espaçamento</mat-label>
15801
16484
  <mat-select
15802
16485
  [value]="actions.spacing"
15803
16486
  (selectionChange)="updateLayout('spacing', $event.value)"
15804
16487
  >
15805
16488
  <mat-option value="compact">Compacto</mat-option>
15806
16489
  <mat-option value="normal">Normal</mat-option>
15807
- <mat-option value="spacious">Espaçado</mat-option>
16490
+ <mat-option value="spacious">Espaçado</mat-option>
15808
16491
  </mat-select>
15809
16492
  </mat-form-field>
15810
16493
  <mat-slide-toggle
@@ -15823,11 +16506,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15823
16506
  <mat-slide-toggle
15824
16507
  [checked]="actions.sticky"
15825
16508
  (change)="updateLayout('sticky', $event.checked)"
15826
- >Barra de Ações Fixa (Sticky)</mat-slide-toggle
16509
+ >Barra de Ações Fixa (Sticky)</mat-slide-toggle
15827
16510
  >
15828
16511
  <mat-expansion-panel>
15829
16512
  <mat-expansion-panel-header>
15830
- Configurações Mobile
16513
+ Configurações Mobile
15831
16514
  </mat-expansion-panel-header>
15832
16515
  <ng-template matExpansionPanelContent>
15833
16516
  <div class="action-fields">
@@ -15844,7 +16527,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15844
16527
  updateLayoutMobile('position', $event.value)
15845
16528
  "
15846
16529
  >
15847
- <mat-option [value]="undefined">Padrão</mat-option>
16530
+ <mat-option [value]="undefined">Padrão</mat-option>
15848
16531
  <mat-option value="left">Esquerda</mat-option>
15849
16532
  <mat-option value="center">Centro</mat-option>
15850
16533
  <mat-option value="right">Direita</mat-option>
@@ -15852,14 +16535,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15852
16535
  </mat-select>
15853
16536
  </mat-form-field>
15854
16537
  <mat-form-field>
15855
- <mat-label>Orientação (mobile)</mat-label>
16538
+ <mat-label>Orientação (mobile)</mat-label>
15856
16539
  <mat-select
15857
16540
  [value]="actions.mobile?.orientation"
15858
16541
  (selectionChange)="
15859
16542
  updateLayoutMobile('orientation', $event.value)
15860
16543
  "
15861
16544
  >
15862
- <mat-option [value]="undefined">Padrão</mat-option>
16545
+ <mat-option [value]="undefined">Padrão</mat-option>
15863
16546
  <mat-option value="horizontal">Horizontal</mat-option>
15864
16547
  <mat-option value="vertical">Vertical</mat-option>
15865
16548
  </mat-select>
@@ -15870,7 +16553,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
15870
16553
  </div>
15871
16554
  </mat-tab>
15872
16555
  </mat-tab-group>
15873
- `, styles: [".editor-container{padding:16px;display:flex;flex-direction:column;gap:16px}.action-fields{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:16px;align-items:center}.action-global-fields{grid-column:1 / -1;padding:12px 14px;border:1px dashed var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));border-radius:10px;background:var(--md-sys-color-surface-container-low)}.action-global-title{font-size:12px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #9aa0a6);margin-bottom:10px}.action-global-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px 16px}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.action-global-fields .mat-mdc-form-field-icon-suffix{align-self:center}.action-section-title{width:100%;margin:10px 0 2px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #9aa0a6)}.add-button{margin-bottom:16px;align-self:flex-start}\n"] }]
16556
+ `, styles: [".editor-container{padding:16px;display:flex;flex-direction:column;gap:16px}.action-fields{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:16px;align-items:center}.action-global-fields{grid-column:1 / -1;padding:12px 14px;border:1px dashed var(--md-sys-color-outline-variant, rgba(255, 255, 255, .12));border-radius:10px;background:var(--md-sys-color-surface-container-low)}.action-global-title{font-size:12px;font-weight:600;letter-spacing:.02em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #9aa0a6);margin-bottom:10px}.action-global-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px 16px}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.action-global-fields .mat-mdc-form-field-icon-suffix{align-self:center}.action-section-title{width:100%;margin:10px 0 2px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--md-sys-color-on-surface-variant, #9aa0a6)}.add-button{margin-bottom:16px;align-self:flex-start}.custom-action-panel-shell{display:grid;gap:8px}.custom-action-panel-toolbar{display:flex;justify-content:flex-end}.custom-action-order-controls{display:inline-flex;align-items:center;gap:4px;justify-content:flex-end}\n"] }]
15874
16557
  }], propDecorators: { config: [{
15875
16558
  type: Input
15876
16559
  }], configChange: [{
@@ -16930,6 +17613,9 @@ function normalizeTargets(rawTargets, explicitTargetType) {
16930
17613
  };
16931
17614
  }
16932
17615
  function detectTarget(value) {
17616
+ if (isScopedSectionHeaderActionTarget(value) || isUnscopedSectionHeaderActionTarget(value)) {
17617
+ return { type: 'action', value };
17618
+ }
16933
17619
  if (value?.startsWith('section:')) {
16934
17620
  return { type: 'section', value: value.substring('section:'.length) };
16935
17621
  }
@@ -16945,6 +17631,10 @@ function detectTarget(value) {
16945
17631
  return { type: 'field', value };
16946
17632
  }
16947
17633
  function prefixTarget(targetType, value) {
17634
+ if (targetType === 'action' &&
17635
+ (isScopedSectionHeaderActionTarget(value) || isUnscopedSectionHeaderActionTarget(value))) {
17636
+ return value;
17637
+ }
16948
17638
  if (targetType === 'section')
16949
17639
  return `section:${value}`;
16950
17640
  if (targetType === 'action')
@@ -16955,6 +17645,12 @@ function prefixTarget(targetType, value) {
16955
17645
  return `column:${value}`;
16956
17646
  return value;
16957
17647
  }
17648
+ function isScopedSectionHeaderActionTarget(value) {
17649
+ return !!value && value.startsWith('section:') && value.includes(':header-action:');
17650
+ }
17651
+ function isUnscopedSectionHeaderActionTarget(value) {
17652
+ return !!value && value.startsWith('header-action:');
17653
+ }
16958
17654
  function parseSimpleCondition(condition) {
16959
17655
  const trimmed = condition.trim();
16960
17656
  const match = trimmed.match(/^(.+?)\s+(eq|equals|==|=|neq|notequals|!=|<>|lt|lessthan|<|lte|lessthanorequal|<=|gt|greaterthan|>|gte|greaterthanorequal|>=|contains|startswith|endswith|in)\s+(.+)$/iu);
@@ -17475,6 +18171,21 @@ class PraxisDynamicFormConfigEditor {
17475
18171
  });
17476
18172
  // Expose actions as rule targets (prefixed)
17477
18173
  const allActions = [];
18174
+ sections.forEach((section) => {
18175
+ (section.headerActions || []).forEach((action) => {
18176
+ const actionId = (action.action || action.id || '').trim();
18177
+ if (!actionId)
18178
+ return;
18179
+ const scopedActionId = section.id
18180
+ ? `section:${section.id}:header-action:${actionId}`
18181
+ : `header-action:${actionId}`;
18182
+ allActions.push({
18183
+ id: scopedActionId,
18184
+ label: action.label ||
18185
+ `${section.title || section.id} • ${actionId}`,
18186
+ });
18187
+ });
18188
+ });
17478
18189
  if (actions?.submit)
17479
18190
  allActions.push({ id: actions.submit.id || 'submit', label: actions.submit.label });
17480
18191
  if (actions?.cancel)
@@ -17994,7 +18705,7 @@ const PRAXIS_DYNAMIC_FORM_COMPONENT_METADATA = {
17994
18705
  name: 'config',
17995
18706
  type: 'FormConfig',
17996
18707
  label: 'Configuração',
17997
- description: 'Configuração completa do formulário (layout, metadados, ações, regras e headers de seção com `sectionHeader` para ícone/avatar dinâmico).',
18708
+ description: 'Configuração completa do formulário (layout, metadados, ações, regras e headers de seção com `sectionHeader` para ícone/avatar dinâmico e `headerActions` para ações contextuais).',
17998
18709
  },
17999
18710
  { name: 'schemaSource', type: "'resource' | 'filter'", default: 'resource', description: 'Fonte do schema de campos' },
18000
18711
  { name: 'enableCustomization', type: 'boolean', default: false, description: 'Habilita modo de customização do layout (canvas)' },
@@ -18079,9 +18790,10 @@ const PRAXIS_DYNAMIC_FORM_COMPONENT_METADATA = {
18079
18790
  formData: { type: 'object', description: 'Dados do formulário' },
18080
18791
  isValid: { type: 'boolean', description: 'Validade do formulário' },
18081
18792
  source: { type: 'string', description: 'Origem da ação' },
18793
+ sectionId: { type: 'string', description: 'ID da seção quando a ação veio do header de uma seção' },
18082
18794
  },
18083
18795
  required: ['actionId', 'formData', 'isValid', 'source'],
18084
- example: { actionId: 'save', formData: {}, isValid: true, source: 'button' },
18796
+ example: { actionId: 'help', formData: {}, isValid: true, source: 'section-header', sectionId: 'identification' },
18085
18797
  },
18086
18798
  scope: 'shell',
18087
18799
  },
@@ -18163,6 +18875,134 @@ function provideSettingsPanelDynamicForm() {
18163
18875
  return SETTINGS_PANEL_DYNAMIC_FORM_PROVIDER;
18164
18876
  }
18165
18877
 
18878
+ const SECTION_EDITOR_I18N_NAMESPACE = 'praxisDynamicFormSectionEditor';
18879
+ const SECTION_EDITOR_I18N_CONFIG = {
18880
+ namespaces: {
18881
+ [SECTION_EDITOR_I18N_NAMESPACE]: {
18882
+ 'pt-BR': {
18883
+ 'dynamicForm.sectionEditor.header.presets.title': 'Presets rápidos',
18884
+ 'dynamicForm.sectionEditor.header.presets.default': 'Padrão',
18885
+ 'dynamicForm.sectionEditor.header.presets.simple': 'Simples',
18886
+ 'dynamicForm.sectionEditor.header.presets.collapsible': 'Colapsável',
18887
+ 'dynamicForm.sectionEditor.header.fields.title': 'Título',
18888
+ 'dynamicForm.sectionEditor.header.fields.description': 'Descrição',
18889
+ 'dynamicForm.sectionEditor.header.fields.appearance': 'Aparência',
18890
+ 'dynamicForm.sectionEditor.header.fields.titleColor': 'Cor do título',
18891
+ 'dynamicForm.sectionEditor.header.fields.descriptionColor': 'Cor da descrição',
18892
+ 'dynamicForm.sectionEditor.header.fields.customColor': 'Cor personalizada (CSS)',
18893
+ 'dynamicForm.sectionEditor.header.fields.titleGapBottom': 'Gap do título (px)',
18894
+ 'dynamicForm.sectionEditor.header.fields.descriptionGapBottom': 'Gap da descrição (px)',
18895
+ 'dynamicForm.sectionEditor.header.fields.gapBottom': 'Gap abaixo da seção (px)',
18896
+ 'dynamicForm.sectionEditor.header.fields.collapsible': 'Colapsável',
18897
+ 'dynamicForm.sectionEditor.header.fields.collapsed': 'Iniciar recolhida',
18898
+ 'dynamicForm.sectionEditor.header.fields.headerTooltip': 'Tooltip do cabeçalho',
18899
+ 'dynamicForm.sectionEditor.header.placeholders.description': 'Resumo curto do conteúdo da seção',
18900
+ 'dynamicForm.sectionEditor.header.placeholders.customColor': 'ex.: #3366ff ou rgb(...)',
18901
+ 'dynamicForm.sectionEditor.header.placeholders.headerTooltip': 'Dica ao passar o mouse no título',
18902
+ 'dynamicForm.sectionEditor.header.options.titleColor.default': 'Padrão (on-surface)',
18903
+ 'dynamicForm.sectionEditor.header.options.titleColor.primary': 'Primária',
18904
+ 'dynamicForm.sectionEditor.header.options.titleColor.secondary': 'Secundária',
18905
+ 'dynamicForm.sectionEditor.header.options.descriptionColor.default': 'Padrão (on-surface-variant)',
18906
+ 'dynamicForm.sectionEditor.header.options.descriptionColor.primary': 'Primária',
18907
+ 'dynamicForm.sectionEditor.header.options.descriptionColor.secondary': 'Secundária',
18908
+ 'headerActions.title': 'Ações do cabeçalho',
18909
+ 'headerActions.description': 'Adicione ícones acionáveis no canto direito do cabeçalho da seção para affordances contextuais como ajuda, refresh ou drill-down.',
18910
+ 'headerActions.add': 'Adicionar ação',
18911
+ 'headerActions.empty': 'Nenhuma ação configurada para este cabeçalho.',
18912
+ 'headerActions.item': 'Ação {{index}}',
18913
+ 'headerActions.remove': 'Remover ação',
18914
+ 'headerActions.moveUp': 'Mover ação para cima',
18915
+ 'headerActions.moveDown': 'Mover ação para baixo',
18916
+ 'headerActions.fields.id': 'ID',
18917
+ 'headerActions.fields.label': 'Label acessível',
18918
+ 'headerActions.fields.icon': 'Ícone',
18919
+ 'headerActions.fields.action': 'Action emitida',
18920
+ 'headerActions.fields.tooltip': 'Tooltip',
18921
+ 'headerActions.fields.color': 'Cor',
18922
+ 'headerActions.fields.color.default': 'Padrão',
18923
+ 'headerActions.fields.color.basic': 'Basic',
18924
+ 'headerActions.fields.color.primary': 'Primária',
18925
+ 'headerActions.fields.color.accent': 'Accent',
18926
+ 'headerActions.fields.color.warn': 'Warn',
18927
+ 'headerActions.fields.visible': 'Visível',
18928
+ 'headerActions.fields.disabled': 'Desabilitada',
18929
+ 'headerActions.fields.loading': 'Loading',
18930
+ 'headerActions.fields.className': 'Classe CSS',
18931
+ 'headerActions.fields.style': 'Estilo (JSON)',
18932
+ 'headerActions.validation.invalidJson': 'JSON inválido.',
18933
+ 'headerActions.validation.objectJson': 'Informe um objeto JSON válido.',
18934
+ 'headerActions.placeholders.id': 'ex.: help',
18935
+ 'headerActions.placeholders.label': 'ex.: Ajuda da seção',
18936
+ 'headerActions.placeholders.icon': 'ex.: help_outline',
18937
+ 'headerActions.placeholders.action': 'Opcional. Se vazio, usa o ID',
18938
+ 'headerActions.placeholders.tooltip': 'Opcional. Se vazio, usa a label',
18939
+ 'headerActions.placeholders.className': 'ex.: section-help-action',
18940
+ 'headerActions.placeholders.style': '{"marginLeft":"4px"}',
18941
+ },
18942
+ 'en-US': {
18943
+ 'dynamicForm.sectionEditor.header.presets.title': 'Quick presets',
18944
+ 'dynamicForm.sectionEditor.header.presets.default': 'Default',
18945
+ 'dynamicForm.sectionEditor.header.presets.simple': 'Simple',
18946
+ 'dynamicForm.sectionEditor.header.presets.collapsible': 'Collapsible',
18947
+ 'dynamicForm.sectionEditor.header.fields.title': 'Title',
18948
+ 'dynamicForm.sectionEditor.header.fields.description': 'Description',
18949
+ 'dynamicForm.sectionEditor.header.fields.appearance': 'Appearance',
18950
+ 'dynamicForm.sectionEditor.header.fields.titleColor': 'Title color',
18951
+ 'dynamicForm.sectionEditor.header.fields.descriptionColor': 'Description color',
18952
+ 'dynamicForm.sectionEditor.header.fields.customColor': 'Custom color (CSS)',
18953
+ 'dynamicForm.sectionEditor.header.fields.titleGapBottom': 'Title gap (px)',
18954
+ 'dynamicForm.sectionEditor.header.fields.descriptionGapBottom': 'Description gap (px)',
18955
+ 'dynamicForm.sectionEditor.header.fields.gapBottom': 'Section bottom gap (px)',
18956
+ 'dynamicForm.sectionEditor.header.fields.collapsible': 'Collapsible',
18957
+ 'dynamicForm.sectionEditor.header.fields.collapsed': 'Start collapsed',
18958
+ 'dynamicForm.sectionEditor.header.fields.headerTooltip': 'Header tooltip',
18959
+ 'dynamicForm.sectionEditor.header.placeholders.description': 'Short summary of the section content',
18960
+ 'dynamicForm.sectionEditor.header.placeholders.customColor': 'e.g. #3366ff or rgb(...)',
18961
+ 'dynamicForm.sectionEditor.header.placeholders.headerTooltip': 'Hint shown when hovering the title',
18962
+ 'dynamicForm.sectionEditor.header.options.titleColor.default': 'Default (on-surface)',
18963
+ 'dynamicForm.sectionEditor.header.options.titleColor.primary': 'Primary',
18964
+ 'dynamicForm.sectionEditor.header.options.titleColor.secondary': 'Secondary',
18965
+ 'dynamicForm.sectionEditor.header.options.descriptionColor.default': 'Default (on-surface-variant)',
18966
+ 'dynamicForm.sectionEditor.header.options.descriptionColor.primary': 'Primary',
18967
+ 'dynamicForm.sectionEditor.header.options.descriptionColor.secondary': 'Secondary',
18968
+ 'headerActions.title': 'Header actions',
18969
+ 'headerActions.description': 'Add clickable icons to the right side of the section header for contextual affordances such as help, refresh or drill-down.',
18970
+ 'headerActions.add': 'Add action',
18971
+ 'headerActions.empty': 'No actions configured for this header.',
18972
+ 'headerActions.item': 'Action {{index}}',
18973
+ 'headerActions.remove': 'Remove action',
18974
+ 'headerActions.moveUp': 'Move action up',
18975
+ 'headerActions.moveDown': 'Move action down',
18976
+ 'headerActions.fields.id': 'ID',
18977
+ 'headerActions.fields.label': 'Accessible label',
18978
+ 'headerActions.fields.icon': 'Icon',
18979
+ 'headerActions.fields.action': 'Emitted action',
18980
+ 'headerActions.fields.tooltip': 'Tooltip',
18981
+ 'headerActions.fields.color': 'Color',
18982
+ 'headerActions.fields.color.default': 'Default',
18983
+ 'headerActions.fields.color.basic': 'Basic',
18984
+ 'headerActions.fields.color.primary': 'Primary',
18985
+ 'headerActions.fields.color.accent': 'Accent',
18986
+ 'headerActions.fields.color.warn': 'Warn',
18987
+ 'headerActions.fields.visible': 'Visible',
18988
+ 'headerActions.fields.disabled': 'Disabled',
18989
+ 'headerActions.fields.loading': 'Loading',
18990
+ 'headerActions.fields.className': 'CSS class',
18991
+ 'headerActions.fields.style': 'Style (JSON)',
18992
+ 'headerActions.validation.invalidJson': 'Invalid JSON.',
18993
+ 'headerActions.validation.objectJson': 'Provide a valid JSON object.',
18994
+ 'headerActions.placeholders.id': 'e.g. help',
18995
+ 'headerActions.placeholders.label': 'e.g. Section help',
18996
+ 'headerActions.placeholders.icon': 'e.g. help_outline',
18997
+ 'headerActions.placeholders.action': 'Optional. If empty, the ID is used',
18998
+ 'headerActions.placeholders.tooltip': 'Optional. If empty, the label is used',
18999
+ 'headerActions.placeholders.className': 'e.g. section-help-action',
19000
+ 'headerActions.placeholders.style': '{"marginLeft":"4px"}',
19001
+ },
19002
+ },
19003
+ },
19004
+ };
19005
+
18166
19006
  class SectionEditorComponent {
18167
19007
  fb;
18168
19008
  data;
@@ -18231,6 +19071,7 @@ class SectionEditorComponent {
18231
19071
  className: [this.section.className ?? ''],
18232
19072
  testId: [this.section.testId ?? ''],
18233
19073
  headerTooltip: [this.section.headerTooltip ?? ''],
19074
+ headerActions: this.fb.array((this.normalizeHeaderActions(this.section.headerActions) ?? []).map((action) => this.createHeaderActionGroup(action))),
18234
19075
  });
18235
19076
  this.syncCollapsedControlState(!!this.form.get('collapsible')?.value);
18236
19077
  this.form.valueChanges.pipe(takeUntil(this.destroy$)).subscribe(() => {
@@ -18262,6 +19103,12 @@ class SectionEditorComponent {
18262
19103
  getSettingsValue() {
18263
19104
  return this.normalizeSectionFormValue(this.form.getRawValue());
18264
19105
  }
19106
+ get headerActionsArray() {
19107
+ return this.form.get('headerActions');
19108
+ }
19109
+ getHeaderActionStylePlaceholder() {
19110
+ return this.tx('headerActions.placeholders.style', '{"marginLeft":"4px"}');
19111
+ }
18265
19112
  async pickIcon() {
18266
19113
  const current = this.form.value.icon;
18267
19114
  // Use dialog to avoid replacing the settings panel content.
@@ -18287,6 +19134,30 @@ class SectionEditorComponent {
18287
19134
  clearFallbackIcon() {
18288
19135
  this.form.get('sectionHeader.fallbackIcon')?.setValue('');
18289
19136
  }
19137
+ addHeaderAction() {
19138
+ this.headerActionsArray.push(this.createHeaderActionGroup({
19139
+ id: '',
19140
+ label: '',
19141
+ icon: '',
19142
+ visible: true,
19143
+ disabled: false,
19144
+ }));
19145
+ this.applyNormalizedFormValue();
19146
+ this.isDirty$.next(true);
19147
+ }
19148
+ removeHeaderAction(index) {
19149
+ if (index < 0 || index >= this.headerActionsArray.length)
19150
+ return;
19151
+ this.headerActionsArray.removeAt(index);
19152
+ this.applyNormalizedFormValue();
19153
+ this.isDirty$.next(true);
19154
+ }
19155
+ moveHeaderActionUp(index) {
19156
+ this.moveHeaderAction(index, index - 1);
19157
+ }
19158
+ moveHeaderActionDown(index) {
19159
+ this.moveHeaderAction(index, index + 1);
19160
+ }
18290
19161
  syncCollapsedControlState(canCollapse) {
18291
19162
  const collapsedControl = this.form.get('collapsed');
18292
19163
  if (!collapsedControl)
@@ -18379,8 +19250,8 @@ class SectionEditorComponent {
18379
19250
  trackFieldOption(index, field) {
18380
19251
  return field.value || String(index);
18381
19252
  }
18382
- tx(key, fallback) {
18383
- return this.i18n.t(key, undefined, fallback, 'praxis-dynamic-form');
19253
+ tx(key, fallback, params) {
19254
+ return this.i18n.t(key, params, fallback, SECTION_EDITOR_I18N_NAMESPACE);
18384
19255
  }
18385
19256
  applyNormalizedFormValue() {
18386
19257
  const normalized = this.normalizeSectionFormValue(this.form.getRawValue());
@@ -18406,6 +19277,7 @@ class SectionEditorComponent {
18406
19277
  'className',
18407
19278
  'testId',
18408
19279
  'headerTooltip',
19280
+ 'headerActions',
18409
19281
  ];
18410
19282
  for (const key of managedKeys) {
18411
19283
  const value = normalized[key];
@@ -18440,12 +19312,138 @@ class SectionEditorComponent {
18440
19312
  className: this.normalizeOptionalString(raw.className),
18441
19313
  testId: this.normalizeOptionalString(raw.testId),
18442
19314
  headerTooltip: this.normalizeOptionalString(raw.headerTooltip),
19315
+ headerActions: this.normalizeHeaderActions(raw.headerActions),
18443
19316
  };
18444
19317
  return normalized;
18445
19318
  }
18446
19319
  normalizeSectionHeader(raw) {
18447
19320
  return normalizeSectionHeaderConfig(raw);
18448
19321
  }
19322
+ createHeaderActionGroup(action) {
19323
+ return this.fb.group({
19324
+ id: [action?.id ?? ''],
19325
+ label: [action?.label ?? ''],
19326
+ icon: [action?.icon ?? ''],
19327
+ action: [action?.action ?? ''],
19328
+ tooltip: [action?.tooltip ?? ''],
19329
+ color: [action?.color ?? ''],
19330
+ visible: [action?.visible ?? true],
19331
+ disabled: [action?.disabled ?? false],
19332
+ loading: [action?.loading ?? false],
19333
+ className: [action?.className ?? ''],
19334
+ styleJson: [
19335
+ this.stringifyHeaderActionStyle(action?.style),
19336
+ this.headerActionStyleValidator,
19337
+ ],
19338
+ });
19339
+ }
19340
+ moveHeaderAction(fromIndex, toIndex) {
19341
+ if (fromIndex < 0 ||
19342
+ fromIndex >= this.headerActionsArray.length ||
19343
+ toIndex < 0 ||
19344
+ toIndex >= this.headerActionsArray.length ||
19345
+ fromIndex === toIndex) {
19346
+ return;
19347
+ }
19348
+ const control = this.headerActionsArray.at(fromIndex);
19349
+ this.headerActionsArray.removeAt(fromIndex);
19350
+ this.headerActionsArray.insert(toIndex, control);
19351
+ this.applyNormalizedFormValue();
19352
+ this.isDirty$.next(true);
19353
+ }
19354
+ normalizeHeaderActions(raw) {
19355
+ if (!Array.isArray(raw))
19356
+ return undefined;
19357
+ const normalized = [];
19358
+ raw.forEach((item) => {
19359
+ const id = this.normalizeOptionalString(item?.id);
19360
+ const icon = this.normalizeOptionalString(item?.icon);
19361
+ const label = this.normalizeOptionalString(item?.label) || id;
19362
+ if (!id || !icon || !label)
19363
+ return;
19364
+ const color = this.normalizeOptionalString(item?.color);
19365
+ const nextAction = {
19366
+ id,
19367
+ label,
19368
+ icon,
19369
+ };
19370
+ const action = this.normalizeOptionalString(item?.action);
19371
+ const tooltip = this.normalizeOptionalString(item?.tooltip);
19372
+ const normalizedColor = color === 'primary' ||
19373
+ color === 'accent' ||
19374
+ color === 'warn' ||
19375
+ color === 'basic'
19376
+ ? color
19377
+ : undefined;
19378
+ const className = this.normalizeOptionalString(item?.className);
19379
+ const style = this.parseHeaderActionStyle(item?.styleJson ?? item?.style);
19380
+ if (action !== undefined)
19381
+ nextAction.action = action;
19382
+ if (tooltip !== undefined)
19383
+ nextAction.tooltip = tooltip;
19384
+ if (normalizedColor !== undefined)
19385
+ nextAction.color = normalizedColor;
19386
+ if (item?.visible === false)
19387
+ nextAction.visible = false;
19388
+ if (item?.disabled === true)
19389
+ nextAction.disabled = true;
19390
+ if (item?.loading === true)
19391
+ nextAction.loading = true;
19392
+ if (className !== undefined)
19393
+ nextAction.className = className;
19394
+ if (style !== undefined)
19395
+ nextAction.style = style;
19396
+ normalized.push(nextAction);
19397
+ });
19398
+ return normalized.length ? normalized : undefined;
19399
+ }
19400
+ headerActionStyleValidator = (control) => {
19401
+ const rawValue = control.value;
19402
+ if (rawValue === null || rawValue === undefined || rawValue === '') {
19403
+ return null;
19404
+ }
19405
+ try {
19406
+ const parsed = typeof rawValue === 'string' ? JSON.parse(rawValue) : rawValue;
19407
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
19408
+ return { invalidObjectJson: true };
19409
+ }
19410
+ return null;
19411
+ }
19412
+ catch {
19413
+ return { invalidJson: true };
19414
+ }
19415
+ };
19416
+ stringifyHeaderActionStyle(value) {
19417
+ if (!value || !Object.keys(value).length)
19418
+ return '';
19419
+ try {
19420
+ return JSON.stringify(value, null, 2);
19421
+ }
19422
+ catch {
19423
+ return '';
19424
+ }
19425
+ }
19426
+ parseHeaderActionStyle(value) {
19427
+ if (value === null || value === undefined || value === '')
19428
+ return undefined;
19429
+ if (typeof value === 'object' && !Array.isArray(value)) {
19430
+ return Object.keys(value).length
19431
+ ? value
19432
+ : undefined;
19433
+ }
19434
+ if (typeof value !== 'string')
19435
+ return undefined;
19436
+ try {
19437
+ const parsed = JSON.parse(value);
19438
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
19439
+ return undefined;
19440
+ }
19441
+ return Object.keys(parsed).length ? parsed : undefined;
19442
+ }
19443
+ catch {
19444
+ return undefined;
19445
+ }
19446
+ }
18449
19447
  normalizeOptionalString(value) {
18450
19448
  if (typeof value !== 'string')
18451
19449
  return undefined;
@@ -18459,7 +19457,7 @@ class SectionEditorComponent {
18459
19457
  return Number.isFinite(numeric) ? numeric : undefined;
18460
19458
  }
18461
19459
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: SectionEditorComponent, deps: [{ token: i1$3.FormBuilder }, { token: SETTINGS_PANEL_DATA }, { token: i1$2.IconPickerService }, { token: i1$2.PraxisI18nService }], target: i0.ɵɵFactoryTarget.Component });
18462
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: SectionEditorComponent, isStandalone: true, selector: "praxis-section-editor", inputs: { focusTarget: "focusTarget", fieldMetadata: "fieldMetadata" }, viewQueries: [{ propertyName: "titleInput", first: true, predicate: ["titleInput"], descendants: true }, { propertyName: "descriptionInput", first: true, predicate: ["descriptionInput"], descendants: true }], ngImport: i0, template: `
19460
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: SectionEditorComponent, isStandalone: true, selector: "praxis-section-editor", inputs: { focusTarget: "focusTarget", fieldMetadata: "fieldMetadata" }, providers: [providePraxisI18nConfig(SECTION_EDITOR_I18N_CONFIG)], viewQueries: [{ propertyName: "titleInput", first: true, predicate: ["titleInput"], descendants: true }, { propertyName: "descriptionInput", first: true, predicate: ["descriptionInput"], descendants: true }], ngImport: i0, template: `
18463
19461
  <div class="editor-container" *ngIf="form">
18464
19462
  <mat-tab-group>
18465
19463
  <mat-tab [label]="tx('dynamicForm.sectionEditor.tabs.header', 'Cabeçalho')">
@@ -18469,15 +19467,15 @@ class SectionEditorComponent {
18469
19467
  </div>
18470
19468
  <form [formGroup]="form" class="stack">
18471
19469
  <div class="preset-row">
18472
- <span class="preset-title">Presets rápidos</span>
18473
- <button mat-stroked-button type="button" (click)="applyPreset('default')">Padrão</button>
18474
- <button mat-stroked-button type="button" (click)="applyPreset('simple')">Simples</button>
18475
- <button mat-stroked-button type="button" (click)="applyPreset('collapsible')">Colapsável</button>
19470
+ <span class="preset-title">{{ tx('dynamicForm.sectionEditor.header.presets.title', 'Presets rápidos') }}</span>
19471
+ <button mat-stroked-button type="button" (click)="applyPreset('default')">{{ tx('dynamicForm.sectionEditor.header.presets.default', 'Padrão') }}</button>
19472
+ <button mat-stroked-button type="button" (click)="applyPreset('simple')">{{ tx('dynamicForm.sectionEditor.header.presets.simple', 'Simples') }}</button>
19473
+ <button mat-stroked-button type="button" (click)="applyPreset('collapsible')">{{ tx('dynamicForm.sectionEditor.header.presets.collapsible', 'Colapsável') }}</button>
18476
19474
  </div>
18477
19475
 
18478
19476
  <div class="row-2">
18479
19477
  <mat-form-field appearance="fill">
18480
- <mat-label>Título</mat-label>
19478
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.title', 'Título') }}</mat-label>
18481
19479
  <input matInput #titleInput formControlName="title" />
18482
19480
  </mat-form-field>
18483
19481
 
@@ -18523,13 +19521,13 @@ class SectionEditorComponent {
18523
19521
  </div>
18524
19522
 
18525
19523
  <mat-form-field appearance="fill">
18526
- <mat-label>Descrição</mat-label>
18527
- <textarea matInput #descriptionInput formControlName="description" placeholder="Resumo curto do conteúdo da seção"></textarea>
19524
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.description', 'Descrição') }}</mat-label>
19525
+ <textarea matInput #descriptionInput formControlName="description" [placeholder]="tx('dynamicForm.sectionEditor.header.placeholders.description', 'Resumo curto do conteúdo da seção')"></textarea>
18528
19526
  </mat-form-field>
18529
19527
 
18530
19528
  <div class="row-3">
18531
19529
  <mat-form-field appearance="fill">
18532
- <mat-label>Aparência</mat-label>
19530
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.appearance', 'Aparência') }}</mat-label>
18533
19531
  <mat-select formControlName="appearance">
18534
19532
  <mat-option value="card">Card</mat-option>
18535
19533
  <mat-option value="plain">Plain</mat-option>
@@ -18572,40 +19570,40 @@ class SectionEditorComponent {
18572
19570
  <mat-divider></mat-divider>
18573
19571
  <div class="row-3">
18574
19572
  <mat-form-field appearance="fill">
18575
- <mat-label>Cor do título</mat-label>
19573
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.titleColor', 'Cor do título') }}</mat-label>
18576
19574
  <mat-select formControlName="titleColor">
18577
- <mat-option value="">Padrão (on-surface)</mat-option>
18578
- <mat-option value="var(--md-sys-color-primary)">Primária</mat-option>
18579
- <mat-option value="var(--md-sys-color-secondary)">Secundária</mat-option>
19575
+ <mat-option value="">{{ tx('dynamicForm.sectionEditor.header.options.titleColor.default', 'Padrão (on-surface)') }}</mat-option>
19576
+ <mat-option value="var(--md-sys-color-primary)">{{ tx('dynamicForm.sectionEditor.header.options.titleColor.primary', 'Primária') }}</mat-option>
19577
+ <mat-option value="var(--md-sys-color-secondary)">{{ tx('dynamicForm.sectionEditor.header.options.titleColor.secondary', 'Secundária') }}</mat-option>
18580
19578
  <mat-option value="var(--md-sys-color-on-surface-variant)">On surface variant</mat-option>
18581
19579
  </mat-select>
18582
19580
  </mat-form-field>
18583
19581
  <mat-form-field appearance="fill">
18584
- <mat-label>Cor da descrição</mat-label>
19582
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.descriptionColor', 'Cor da descrição') }}</mat-label>
18585
19583
  <mat-select formControlName="descriptionColor">
18586
- <mat-option value="">Padrão (on-surface-variant)</mat-option>
18587
- <mat-option value="var(--md-sys-color-primary)">Primária</mat-option>
18588
- <mat-option value="var(--md-sys-color-secondary)">Secundária</mat-option>
19584
+ <mat-option value="">{{ tx('dynamicForm.sectionEditor.header.options.descriptionColor.default', 'Padrão (on-surface-variant)') }}</mat-option>
19585
+ <mat-option value="var(--md-sys-color-primary)">{{ tx('dynamicForm.sectionEditor.header.options.descriptionColor.primary', 'Primária') }}</mat-option>
19586
+ <mat-option value="var(--md-sys-color-secondary)">{{ tx('dynamicForm.sectionEditor.header.options.descriptionColor.secondary', 'Secundária') }}</mat-option>
18589
19587
  <mat-option value="var(--md-sys-color-on-surface)">On surface</mat-option>
18590
19588
  </mat-select>
18591
19589
  </mat-form-field>
18592
19590
  <mat-form-field appearance="fill">
18593
- <mat-label>Cor personalizada (CSS)</mat-label>
18594
- <input matInput placeholder="ex.: #3366ff ou rgb(...)" (input)="setCustomColors($any($event.target).value)" />
19591
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.customColor', 'Cor personalizada (CSS)') }}</mat-label>
19592
+ <input matInput [placeholder]="tx('dynamicForm.sectionEditor.header.placeholders.customColor', 'ex.: #3366ff ou rgb(...)')" (input)="setCustomColors($any($event.target).value)" />
18595
19593
  </mat-form-field>
18596
19594
  </div>
18597
19595
 
18598
19596
  <div class="row-3">
18599
19597
  <mat-form-field appearance="fill">
18600
- <mat-label>Gap do título (px)</mat-label>
19598
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.titleGapBottom', 'Gap do título (px)') }}</mat-label>
18601
19599
  <input matInput type="number" formControlName="titleGapBottom" min="0" />
18602
19600
  </mat-form-field>
18603
19601
  <mat-form-field appearance="fill">
18604
- <mat-label>Gap da descrição (px)</mat-label>
19602
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.descriptionGapBottom', 'Gap da descrição (px)') }}</mat-label>
18605
19603
  <input matInput type="number" formControlName="descriptionGapBottom" min="0" />
18606
19604
  </mat-form-field>
18607
19605
  <mat-form-field appearance="fill">
18608
- <mat-label>Gap abaixo da seção (px)</mat-label>
19606
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.gapBottom', 'Gap abaixo da seção (px)') }}</mat-label>
18609
19607
  <input matInput type="number" min="0" formControlName="gapBottom" />
18610
19608
  </mat-form-field>
18611
19609
  </div>
@@ -18613,19 +19611,148 @@ class SectionEditorComponent {
18613
19611
  <mat-divider></mat-divider>
18614
19612
  <div class="row-2">
18615
19613
  <mat-slide-toggle formControlName="collapsible">
18616
- Colapsável
19614
+ {{ tx('dynamicForm.sectionEditor.header.fields.collapsible', 'Colapsável') }}
18617
19615
  </mat-slide-toggle>
18618
19616
 
18619
19617
  <mat-slide-toggle formControlName="collapsed">
18620
- Iniciar recolhida
19618
+ {{ tx('dynamicForm.sectionEditor.header.fields.collapsed', 'Iniciar recolhida') }}
18621
19619
  </mat-slide-toggle>
18622
19620
  </div>
18623
19621
 
18624
19622
  <mat-form-field appearance="fill">
18625
- <mat-label>Tooltip do cabeçalho</mat-label>
18626
- <input matInput formControlName="headerTooltip" placeholder="Dica ao passar o mouse no título" />
19623
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.headerTooltip', 'Tooltip do cabeçalho') }}</mat-label>
19624
+ <input matInput formControlName="headerTooltip" [placeholder]="tx('dynamicForm.sectionEditor.header.placeholders.headerTooltip', 'Dica ao passar o mouse no título')" />
18627
19625
  </mat-form-field>
18628
19626
 
19627
+ <mat-divider></mat-divider>
19628
+ <div class="inline-section-header">
19629
+ <div>
19630
+ <div class="inline-section-title">{{ tx('headerActions.title', 'Ações do cabeçalho') }}</div>
19631
+ <p class="inline-section-description">
19632
+ {{ tx('headerActions.description', 'Adicione ícones acionáveis no canto direito do cabeçalho da seção para affordances contextuais como ajuda, refresh ou drill-down.') }}
19633
+ </p>
19634
+ </div>
19635
+ <button mat-stroked-button type="button" (click)="addHeaderAction()">
19636
+ {{ tx('headerActions.add', 'Adicionar ação') }}
19637
+ </button>
19638
+ </div>
19639
+
19640
+ @if (!headerActionsArray.length) {
19641
+ <p class="empty-inline-state">
19642
+ {{ tx('headerActions.empty', 'Nenhuma ação configurada para este cabeçalho.') }}
19643
+ </p>
19644
+ }
19645
+
19646
+ <div class="header-actions-list" formArrayName="headerActions">
19647
+ <div class="header-action-card" *ngFor="let actionGroup of headerActionsArray.controls; let index = index" [formGroupName]="index">
19648
+ <div class="header-action-toolbar">
19649
+ <div class="header-action-title">
19650
+ {{ tx('headerActions.item', 'Ação {{index}}', { index: index + 1 }) }}
19651
+ </div>
19652
+ <div class="header-action-toolbar-buttons">
19653
+ <button
19654
+ mat-icon-button
19655
+ type="button"
19656
+ (click)="moveHeaderActionUp(index)"
19657
+ [disabled]="index === 0"
19658
+ [attr.aria-label]="tx('headerActions.moveUp', 'Mover ação para cima')"
19659
+ >
19660
+ <mat-icon [praxisIcon]="'arrow_upward'"></mat-icon>
19661
+ </button>
19662
+ <button
19663
+ mat-icon-button
19664
+ type="button"
19665
+ (click)="moveHeaderActionDown(index)"
19666
+ [disabled]="index === headerActionsArray.length - 1"
19667
+ [attr.aria-label]="tx('headerActions.moveDown', 'Mover ação para baixo')"
19668
+ >
19669
+ <mat-icon [praxisIcon]="'arrow_downward'"></mat-icon>
19670
+ </button>
19671
+ <button
19672
+ mat-icon-button
19673
+ type="button"
19674
+ color="warn"
19675
+ (click)="removeHeaderAction(index)"
19676
+ [attr.aria-label]="tx('headerActions.remove', 'Remover ação')"
19677
+ >
19678
+ <mat-icon [praxisIcon]="'delete'"></mat-icon>
19679
+ </button>
19680
+ </div>
19681
+ </div>
19682
+
19683
+ <div class="row-3">
19684
+ <mat-form-field appearance="fill">
19685
+ <mat-label>{{ tx('headerActions.fields.id', 'ID') }}</mat-label>
19686
+ <input matInput formControlName="id" [placeholder]="tx('headerActions.placeholders.id', 'ex.: help')" />
19687
+ </mat-form-field>
19688
+
19689
+ <mat-form-field appearance="fill">
19690
+ <mat-label>{{ tx('headerActions.fields.label', 'Label acessível') }}</mat-label>
19691
+ <input matInput formControlName="label" [placeholder]="tx('headerActions.placeholders.label', 'ex.: Ajuda da seção')" />
19692
+ </mat-form-field>
19693
+
19694
+ <mat-form-field appearance="fill">
19695
+ <mat-label>{{ tx('headerActions.fields.icon', 'Ícone') }}</mat-label>
19696
+ <input matInput formControlName="icon" [placeholder]="tx('headerActions.placeholders.icon', 'ex.: help_outline')" />
19697
+ </mat-form-field>
19698
+ </div>
19699
+
19700
+ <div class="row-3">
19701
+ <mat-form-field appearance="fill">
19702
+ <mat-label>{{ tx('headerActions.fields.action', 'Action emitida') }}</mat-label>
19703
+ <input matInput formControlName="action" [placeholder]="tx('headerActions.placeholders.action', 'Opcional. Se vazio, usa o ID')" />
19704
+ </mat-form-field>
19705
+
19706
+ <mat-form-field appearance="fill">
19707
+ <mat-label>{{ tx('headerActions.fields.tooltip', 'Tooltip') }}</mat-label>
19708
+ <input matInput formControlName="tooltip" [placeholder]="tx('headerActions.placeholders.tooltip', 'Opcional. Se vazio, usa a label')" />
19709
+ </mat-form-field>
19710
+
19711
+ <mat-form-field appearance="fill">
19712
+ <mat-label>{{ tx('headerActions.fields.color', 'Cor') }}</mat-label>
19713
+ <mat-select formControlName="color">
19714
+ <mat-option value="">{{ tx('headerActions.fields.color.default', 'Padrão') }}</mat-option>
19715
+ <mat-option value="basic">{{ tx('headerActions.fields.color.basic', 'Basic') }}</mat-option>
19716
+ <mat-option value="primary">{{ tx('headerActions.fields.color.primary', 'Primária') }}</mat-option>
19717
+ <mat-option value="accent">{{ tx('headerActions.fields.color.accent', 'Accent') }}</mat-option>
19718
+ <mat-option value="warn">{{ tx('headerActions.fields.color.warn', 'Warn') }}</mat-option>
19719
+ </mat-select>
19720
+ </mat-form-field>
19721
+ </div>
19722
+
19723
+ <div class="row-2">
19724
+ <mat-form-field appearance="fill">
19725
+ <mat-label>{{ tx('headerActions.fields.className', 'Classe CSS') }}</mat-label>
19726
+ <input matInput formControlName="className" [placeholder]="tx('headerActions.placeholders.className', 'ex.: section-help-action')" />
19727
+ </mat-form-field>
19728
+
19729
+ <mat-form-field appearance="fill">
19730
+ <mat-label>{{ tx('headerActions.fields.style', 'Estilo (JSON)') }}</mat-label>
19731
+ <textarea matInput rows="3" formControlName="styleJson" [placeholder]="getHeaderActionStylePlaceholder()"></textarea>
19732
+ @if (actionGroup.get('styleJson')?.hasError('invalidJson')) {
19733
+ <mat-error>{{ tx('headerActions.validation.invalidJson', 'JSON inválido.') }}</mat-error>
19734
+ } @else if (actionGroup.get('styleJson')?.hasError('invalidObjectJson')) {
19735
+ <mat-error>{{ tx('headerActions.validation.objectJson', 'Informe um objeto JSON válido.') }}</mat-error>
19736
+ }
19737
+ </mat-form-field>
19738
+ </div>
19739
+
19740
+ <div class="row-3">
19741
+ <mat-slide-toggle formControlName="visible">
19742
+ {{ tx('headerActions.fields.visible', 'Visível') }}
19743
+ </mat-slide-toggle>
19744
+
19745
+ <mat-slide-toggle formControlName="disabled">
19746
+ {{ tx('headerActions.fields.disabled', 'Desabilitada') }}
19747
+ </mat-slide-toggle>
19748
+
19749
+ <mat-slide-toggle formControlName="loading">
19750
+ {{ tx('headerActions.fields.loading', 'Loading') }}
19751
+ </mat-slide-toggle>
19752
+ </div>
19753
+ </div>
19754
+ </div>
19755
+
18629
19756
  <div class="row-2">
18630
19757
  <mat-form-field appearance="fill">
18631
19758
  <mat-label>Classe CSS</mat-label>
@@ -18775,11 +19902,11 @@ class SectionEditorComponent {
18775
19902
  </mat-tab>
18776
19903
  </mat-tab-group>
18777
19904
  </div>
18778
- `, isInline: true, styles: [".editor-container{padding:16px}.preset-row{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:12px}.preset-title{font-weight:600;color:var(--md-sys-color-on-surface-variant)}.bp-group{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0}.stack{display:flex;flex-direction:column;gap:12px}.row-2,.row-3{display:grid;gap:10px;align-items:start}.row-2{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.row-3{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}mat-form-field{width:100%;margin-bottom:12px}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.avatar-guidance{border-radius:12px;padding:12px 14px;background:color-mix(in srgb,var(--md-sys-color-primary) 6%,white);border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent)}.avatar-guidance p{margin:0 0 6px;font-size:12px;line-height:1.5;color:var(--md-sys-color-on-surface-variant)}.avatar-guidance p:last-child{margin-bottom:0}.tips p{margin:0 0 6px;font-size:13px;color:var(--md-sys-color-on-surface-variant)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$3.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i7$2.MatTabContent, selector: "[matTabContent]" }, { kind: "component", type: i7$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$3.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i11$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }] });
19905
+ `, isInline: true, styles: [".editor-container{padding:16px}.preset-row{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:12px}.preset-title{font-weight:600;color:var(--md-sys-color-on-surface-variant)}.bp-group{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0}.inline-section-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap}.inline-section-title{font-size:14px;font-weight:700;color:var(--md-sys-color-on-surface)}.inline-section-description{margin:4px 0 0;font-size:12px;line-height:1.5;color:var(--md-sys-color-on-surface-variant);max-width:72ch}.empty-inline-state{margin:0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.header-actions-list{display:flex;flex-direction:column;gap:12px}.header-action-card{border:1px solid var(--md-sys-color-outline-variant);border-radius:14px;padding:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,white 18%)}.header-action-toolbar{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.header-action-title{font-size:13px;font-weight:700;color:var(--md-sys-color-on-surface)}.header-action-toolbar-buttons{display:inline-flex;align-items:center;gap:4px}.stack{display:flex;flex-direction:column;gap:12px}.row-2,.row-3{display:grid;gap:10px;align-items:start}.row-2{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.row-3{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}mat-form-field{width:100%;margin-bottom:12px}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.avatar-guidance{border-radius:12px;padding:12px 14px;background:color-mix(in srgb,var(--md-sys-color-primary) 6%,white);border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent)}.avatar-guidance p{margin:0 0 6px;font-size:12px;line-height:1.5;color:var(--md-sys-color-on-surface-variant)}.avatar-guidance p:last-child{margin-bottom:0}.tips p{margin:0 0 6px;font-size:13px;color:var(--md-sys-color-on-surface-variant)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1$3.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1$3.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i3.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i3.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i7$2.MatTabContent, selector: "[matTabContent]" }, { kind: "component", type: i7$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i7$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i6$3.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i11$1.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i6$4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6$4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }] });
18779
19906
  }
18780
19907
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: SectionEditorComponent, decorators: [{
18781
19908
  type: Component,
18782
- args: [{ selector: 'praxis-section-editor', standalone: true, imports: [
19909
+ args: [{ selector: 'praxis-section-editor', standalone: true, providers: [providePraxisI18nConfig(SECTION_EDITOR_I18N_CONFIG)], imports: [
18783
19910
  CommonModule,
18784
19911
  ReactiveFormsModule,
18785
19912
  MatFormFieldModule,
@@ -18803,15 +19930,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
18803
19930
  </div>
18804
19931
  <form [formGroup]="form" class="stack">
18805
19932
  <div class="preset-row">
18806
- <span class="preset-title">Presets rápidos</span>
18807
- <button mat-stroked-button type="button" (click)="applyPreset('default')">Padrão</button>
18808
- <button mat-stroked-button type="button" (click)="applyPreset('simple')">Simples</button>
18809
- <button mat-stroked-button type="button" (click)="applyPreset('collapsible')">Colapsável</button>
19933
+ <span class="preset-title">{{ tx('dynamicForm.sectionEditor.header.presets.title', 'Presets rápidos') }}</span>
19934
+ <button mat-stroked-button type="button" (click)="applyPreset('default')">{{ tx('dynamicForm.sectionEditor.header.presets.default', 'Padrão') }}</button>
19935
+ <button mat-stroked-button type="button" (click)="applyPreset('simple')">{{ tx('dynamicForm.sectionEditor.header.presets.simple', 'Simples') }}</button>
19936
+ <button mat-stroked-button type="button" (click)="applyPreset('collapsible')">{{ tx('dynamicForm.sectionEditor.header.presets.collapsible', 'Colapsável') }}</button>
18810
19937
  </div>
18811
19938
 
18812
19939
  <div class="row-2">
18813
19940
  <mat-form-field appearance="fill">
18814
- <mat-label>Título</mat-label>
19941
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.title', 'Título') }}</mat-label>
18815
19942
  <input matInput #titleInput formControlName="title" />
18816
19943
  </mat-form-field>
18817
19944
 
@@ -18857,13 +19984,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
18857
19984
  </div>
18858
19985
 
18859
19986
  <mat-form-field appearance="fill">
18860
- <mat-label>Descrição</mat-label>
18861
- <textarea matInput #descriptionInput formControlName="description" placeholder="Resumo curto do conteúdo da seção"></textarea>
19987
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.description', 'Descrição') }}</mat-label>
19988
+ <textarea matInput #descriptionInput formControlName="description" [placeholder]="tx('dynamicForm.sectionEditor.header.placeholders.description', 'Resumo curto do conteúdo da seção')"></textarea>
18862
19989
  </mat-form-field>
18863
19990
 
18864
19991
  <div class="row-3">
18865
19992
  <mat-form-field appearance="fill">
18866
- <mat-label>Aparência</mat-label>
19993
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.appearance', 'Aparência') }}</mat-label>
18867
19994
  <mat-select formControlName="appearance">
18868
19995
  <mat-option value="card">Card</mat-option>
18869
19996
  <mat-option value="plain">Plain</mat-option>
@@ -18906,40 +20033,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
18906
20033
  <mat-divider></mat-divider>
18907
20034
  <div class="row-3">
18908
20035
  <mat-form-field appearance="fill">
18909
- <mat-label>Cor do título</mat-label>
20036
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.titleColor', 'Cor do título') }}</mat-label>
18910
20037
  <mat-select formControlName="titleColor">
18911
- <mat-option value="">Padrão (on-surface)</mat-option>
18912
- <mat-option value="var(--md-sys-color-primary)">Primária</mat-option>
18913
- <mat-option value="var(--md-sys-color-secondary)">Secundária</mat-option>
20038
+ <mat-option value="">{{ tx('dynamicForm.sectionEditor.header.options.titleColor.default', 'Padrão (on-surface)') }}</mat-option>
20039
+ <mat-option value="var(--md-sys-color-primary)">{{ tx('dynamicForm.sectionEditor.header.options.titleColor.primary', 'Primária') }}</mat-option>
20040
+ <mat-option value="var(--md-sys-color-secondary)">{{ tx('dynamicForm.sectionEditor.header.options.titleColor.secondary', 'Secundária') }}</mat-option>
18914
20041
  <mat-option value="var(--md-sys-color-on-surface-variant)">On surface variant</mat-option>
18915
20042
  </mat-select>
18916
20043
  </mat-form-field>
18917
20044
  <mat-form-field appearance="fill">
18918
- <mat-label>Cor da descrição</mat-label>
20045
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.descriptionColor', 'Cor da descrição') }}</mat-label>
18919
20046
  <mat-select formControlName="descriptionColor">
18920
- <mat-option value="">Padrão (on-surface-variant)</mat-option>
18921
- <mat-option value="var(--md-sys-color-primary)">Primária</mat-option>
18922
- <mat-option value="var(--md-sys-color-secondary)">Secundária</mat-option>
20047
+ <mat-option value="">{{ tx('dynamicForm.sectionEditor.header.options.descriptionColor.default', 'Padrão (on-surface-variant)') }}</mat-option>
20048
+ <mat-option value="var(--md-sys-color-primary)">{{ tx('dynamicForm.sectionEditor.header.options.descriptionColor.primary', 'Primária') }}</mat-option>
20049
+ <mat-option value="var(--md-sys-color-secondary)">{{ tx('dynamicForm.sectionEditor.header.options.descriptionColor.secondary', 'Secundária') }}</mat-option>
18923
20050
  <mat-option value="var(--md-sys-color-on-surface)">On surface</mat-option>
18924
20051
  </mat-select>
18925
20052
  </mat-form-field>
18926
20053
  <mat-form-field appearance="fill">
18927
- <mat-label>Cor personalizada (CSS)</mat-label>
18928
- <input matInput placeholder="ex.: #3366ff ou rgb(...)" (input)="setCustomColors($any($event.target).value)" />
20054
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.customColor', 'Cor personalizada (CSS)') }}</mat-label>
20055
+ <input matInput [placeholder]="tx('dynamicForm.sectionEditor.header.placeholders.customColor', 'ex.: #3366ff ou rgb(...)')" (input)="setCustomColors($any($event.target).value)" />
18929
20056
  </mat-form-field>
18930
20057
  </div>
18931
20058
 
18932
20059
  <div class="row-3">
18933
20060
  <mat-form-field appearance="fill">
18934
- <mat-label>Gap do título (px)</mat-label>
20061
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.titleGapBottom', 'Gap do título (px)') }}</mat-label>
18935
20062
  <input matInput type="number" formControlName="titleGapBottom" min="0" />
18936
20063
  </mat-form-field>
18937
20064
  <mat-form-field appearance="fill">
18938
- <mat-label>Gap da descrição (px)</mat-label>
20065
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.descriptionGapBottom', 'Gap da descrição (px)') }}</mat-label>
18939
20066
  <input matInput type="number" formControlName="descriptionGapBottom" min="0" />
18940
20067
  </mat-form-field>
18941
20068
  <mat-form-field appearance="fill">
18942
- <mat-label>Gap abaixo da seção (px)</mat-label>
20069
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.gapBottom', 'Gap abaixo da seção (px)') }}</mat-label>
18943
20070
  <input matInput type="number" min="0" formControlName="gapBottom" />
18944
20071
  </mat-form-field>
18945
20072
  </div>
@@ -18947,19 +20074,148 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
18947
20074
  <mat-divider></mat-divider>
18948
20075
  <div class="row-2">
18949
20076
  <mat-slide-toggle formControlName="collapsible">
18950
- Colapsável
20077
+ {{ tx('dynamicForm.sectionEditor.header.fields.collapsible', 'Colapsável') }}
18951
20078
  </mat-slide-toggle>
18952
20079
 
18953
20080
  <mat-slide-toggle formControlName="collapsed">
18954
- Iniciar recolhida
20081
+ {{ tx('dynamicForm.sectionEditor.header.fields.collapsed', 'Iniciar recolhida') }}
18955
20082
  </mat-slide-toggle>
18956
20083
  </div>
18957
20084
 
18958
20085
  <mat-form-field appearance="fill">
18959
- <mat-label>Tooltip do cabeçalho</mat-label>
18960
- <input matInput formControlName="headerTooltip" placeholder="Dica ao passar o mouse no título" />
20086
+ <mat-label>{{ tx('dynamicForm.sectionEditor.header.fields.headerTooltip', 'Tooltip do cabeçalho') }}</mat-label>
20087
+ <input matInput formControlName="headerTooltip" [placeholder]="tx('dynamicForm.sectionEditor.header.placeholders.headerTooltip', 'Dica ao passar o mouse no título')" />
18961
20088
  </mat-form-field>
18962
20089
 
20090
+ <mat-divider></mat-divider>
20091
+ <div class="inline-section-header">
20092
+ <div>
20093
+ <div class="inline-section-title">{{ tx('headerActions.title', 'Ações do cabeçalho') }}</div>
20094
+ <p class="inline-section-description">
20095
+ {{ tx('headerActions.description', 'Adicione ícones acionáveis no canto direito do cabeçalho da seção para affordances contextuais como ajuda, refresh ou drill-down.') }}
20096
+ </p>
20097
+ </div>
20098
+ <button mat-stroked-button type="button" (click)="addHeaderAction()">
20099
+ {{ tx('headerActions.add', 'Adicionar ação') }}
20100
+ </button>
20101
+ </div>
20102
+
20103
+ @if (!headerActionsArray.length) {
20104
+ <p class="empty-inline-state">
20105
+ {{ tx('headerActions.empty', 'Nenhuma ação configurada para este cabeçalho.') }}
20106
+ </p>
20107
+ }
20108
+
20109
+ <div class="header-actions-list" formArrayName="headerActions">
20110
+ <div class="header-action-card" *ngFor="let actionGroup of headerActionsArray.controls; let index = index" [formGroupName]="index">
20111
+ <div class="header-action-toolbar">
20112
+ <div class="header-action-title">
20113
+ {{ tx('headerActions.item', 'Ação {{index}}', { index: index + 1 }) }}
20114
+ </div>
20115
+ <div class="header-action-toolbar-buttons">
20116
+ <button
20117
+ mat-icon-button
20118
+ type="button"
20119
+ (click)="moveHeaderActionUp(index)"
20120
+ [disabled]="index === 0"
20121
+ [attr.aria-label]="tx('headerActions.moveUp', 'Mover ação para cima')"
20122
+ >
20123
+ <mat-icon [praxisIcon]="'arrow_upward'"></mat-icon>
20124
+ </button>
20125
+ <button
20126
+ mat-icon-button
20127
+ type="button"
20128
+ (click)="moveHeaderActionDown(index)"
20129
+ [disabled]="index === headerActionsArray.length - 1"
20130
+ [attr.aria-label]="tx('headerActions.moveDown', 'Mover ação para baixo')"
20131
+ >
20132
+ <mat-icon [praxisIcon]="'arrow_downward'"></mat-icon>
20133
+ </button>
20134
+ <button
20135
+ mat-icon-button
20136
+ type="button"
20137
+ color="warn"
20138
+ (click)="removeHeaderAction(index)"
20139
+ [attr.aria-label]="tx('headerActions.remove', 'Remover ação')"
20140
+ >
20141
+ <mat-icon [praxisIcon]="'delete'"></mat-icon>
20142
+ </button>
20143
+ </div>
20144
+ </div>
20145
+
20146
+ <div class="row-3">
20147
+ <mat-form-field appearance="fill">
20148
+ <mat-label>{{ tx('headerActions.fields.id', 'ID') }}</mat-label>
20149
+ <input matInput formControlName="id" [placeholder]="tx('headerActions.placeholders.id', 'ex.: help')" />
20150
+ </mat-form-field>
20151
+
20152
+ <mat-form-field appearance="fill">
20153
+ <mat-label>{{ tx('headerActions.fields.label', 'Label acessível') }}</mat-label>
20154
+ <input matInput formControlName="label" [placeholder]="tx('headerActions.placeholders.label', 'ex.: Ajuda da seção')" />
20155
+ </mat-form-field>
20156
+
20157
+ <mat-form-field appearance="fill">
20158
+ <mat-label>{{ tx('headerActions.fields.icon', 'Ícone') }}</mat-label>
20159
+ <input matInput formControlName="icon" [placeholder]="tx('headerActions.placeholders.icon', 'ex.: help_outline')" />
20160
+ </mat-form-field>
20161
+ </div>
20162
+
20163
+ <div class="row-3">
20164
+ <mat-form-field appearance="fill">
20165
+ <mat-label>{{ tx('headerActions.fields.action', 'Action emitida') }}</mat-label>
20166
+ <input matInput formControlName="action" [placeholder]="tx('headerActions.placeholders.action', 'Opcional. Se vazio, usa o ID')" />
20167
+ </mat-form-field>
20168
+
20169
+ <mat-form-field appearance="fill">
20170
+ <mat-label>{{ tx('headerActions.fields.tooltip', 'Tooltip') }}</mat-label>
20171
+ <input matInput formControlName="tooltip" [placeholder]="tx('headerActions.placeholders.tooltip', 'Opcional. Se vazio, usa a label')" />
20172
+ </mat-form-field>
20173
+
20174
+ <mat-form-field appearance="fill">
20175
+ <mat-label>{{ tx('headerActions.fields.color', 'Cor') }}</mat-label>
20176
+ <mat-select formControlName="color">
20177
+ <mat-option value="">{{ tx('headerActions.fields.color.default', 'Padrão') }}</mat-option>
20178
+ <mat-option value="basic">{{ tx('headerActions.fields.color.basic', 'Basic') }}</mat-option>
20179
+ <mat-option value="primary">{{ tx('headerActions.fields.color.primary', 'Primária') }}</mat-option>
20180
+ <mat-option value="accent">{{ tx('headerActions.fields.color.accent', 'Accent') }}</mat-option>
20181
+ <mat-option value="warn">{{ tx('headerActions.fields.color.warn', 'Warn') }}</mat-option>
20182
+ </mat-select>
20183
+ </mat-form-field>
20184
+ </div>
20185
+
20186
+ <div class="row-2">
20187
+ <mat-form-field appearance="fill">
20188
+ <mat-label>{{ tx('headerActions.fields.className', 'Classe CSS') }}</mat-label>
20189
+ <input matInput formControlName="className" [placeholder]="tx('headerActions.placeholders.className', 'ex.: section-help-action')" />
20190
+ </mat-form-field>
20191
+
20192
+ <mat-form-field appearance="fill">
20193
+ <mat-label>{{ tx('headerActions.fields.style', 'Estilo (JSON)') }}</mat-label>
20194
+ <textarea matInput rows="3" formControlName="styleJson" [placeholder]="getHeaderActionStylePlaceholder()"></textarea>
20195
+ @if (actionGroup.get('styleJson')?.hasError('invalidJson')) {
20196
+ <mat-error>{{ tx('headerActions.validation.invalidJson', 'JSON inválido.') }}</mat-error>
20197
+ } @else if (actionGroup.get('styleJson')?.hasError('invalidObjectJson')) {
20198
+ <mat-error>{{ tx('headerActions.validation.objectJson', 'Informe um objeto JSON válido.') }}</mat-error>
20199
+ }
20200
+ </mat-form-field>
20201
+ </div>
20202
+
20203
+ <div class="row-3">
20204
+ <mat-slide-toggle formControlName="visible">
20205
+ {{ tx('headerActions.fields.visible', 'Visível') }}
20206
+ </mat-slide-toggle>
20207
+
20208
+ <mat-slide-toggle formControlName="disabled">
20209
+ {{ tx('headerActions.fields.disabled', 'Desabilitada') }}
20210
+ </mat-slide-toggle>
20211
+
20212
+ <mat-slide-toggle formControlName="loading">
20213
+ {{ tx('headerActions.fields.loading', 'Loading') }}
20214
+ </mat-slide-toggle>
20215
+ </div>
20216
+ </div>
20217
+ </div>
20218
+
18963
20219
  <div class="row-2">
18964
20220
  <mat-form-field appearance="fill">
18965
20221
  <mat-label>Classe CSS</mat-label>
@@ -19109,7 +20365,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
19109
20365
  </mat-tab>
19110
20366
  </mat-tab-group>
19111
20367
  </div>
19112
- `, styles: [".editor-container{padding:16px}.preset-row{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:12px}.preset-title{font-weight:600;color:var(--md-sys-color-on-surface-variant)}.bp-group{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0}.stack{display:flex;flex-direction:column;gap:12px}.row-2,.row-3{display:grid;gap:10px;align-items:start}.row-2{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.row-3{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}mat-form-field{width:100%;margin-bottom:12px}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.avatar-guidance{border-radius:12px;padding:12px 14px;background:color-mix(in srgb,var(--md-sys-color-primary) 6%,white);border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent)}.avatar-guidance p{margin:0 0 6px;font-size:12px;line-height:1.5;color:var(--md-sys-color-on-surface-variant)}.avatar-guidance p:last-child{margin-bottom:0}.tips p{margin:0 0 6px;font-size:13px;color:var(--md-sys-color-on-surface-variant)}\n"] }]
20368
+ `, styles: [".editor-container{padding:16px}.preset-row{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:12px}.preset-title{font-weight:600;color:var(--md-sys-color-on-surface-variant)}.bp-group{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0}.inline-section-header{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap}.inline-section-title{font-size:14px;font-weight:700;color:var(--md-sys-color-on-surface)}.inline-section-description{margin:4px 0 0;font-size:12px;line-height:1.5;color:var(--md-sys-color-on-surface-variant);max-width:72ch}.empty-inline-state{margin:0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.header-actions-list{display:flex;flex-direction:column;gap:12px}.header-action-card{border:1px solid var(--md-sys-color-outline-variant);border-radius:14px;padding:12px;background:color-mix(in srgb,var(--md-sys-color-surface-container-low) 82%,white 18%)}.header-action-toolbar{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.header-action-title{font-size:13px;font-weight:700;color:var(--md-sys-color-on-surface)}.header-action-toolbar-buttons{display:inline-flex;align-items:center;gap:4px}.stack{display:flex;flex-direction:column;gap:12px}.row-2,.row-3{display:grid;gap:10px;align-items:start}.row-2{grid-template-columns:repeat(auto-fit,minmax(220px,1fr))}.row-3{grid-template-columns:repeat(auto-fit,minmax(180px,1fr))}mat-form-field{width:100%;margin-bottom:12px}.help-icon-button{--mdc-icon-button-state-layer-size: 28px;--mdc-icon-button-icon-size: 18px;width:28px;height:28px;padding:0;display:inline-flex;align-items:center;justify-content:center;vertical-align:middle}.help-icon-button mat-icon{font-size:18px;line-height:18px;width:18px;height:18px}.avatar-guidance{border-radius:12px;padding:12px 14px;background:color-mix(in srgb,var(--md-sys-color-primary) 6%,white);border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,transparent)}.avatar-guidance p{margin:0 0 6px;font-size:12px;line-height:1.5;color:var(--md-sys-color-on-surface-variant)}.avatar-guidance p:last-child{margin-bottom:0}.tips p{margin:0 0 6px;font-size:13px;color:var(--md-sys-color-on-surface-variant)}\n"] }]
19113
20369
  }], ctorParameters: () => [{ type: i1$3.FormBuilder }, { type: undefined, decorators: [{
19114
20370
  type: Inject,
19115
20371
  args: [SETTINGS_PANEL_DATA]