@praxisui/dynamic-form 8.0.0-beta.11 → 8.0.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -12
- package/fesm2022/praxisui-dynamic-form.mjs +1289 -141
- package/index.d.ts +168 -6
- package/package.json +6 -6
|
@@ -23,16 +23,16 @@ import { MatBadgeModule } from '@angular/material/badge';
|
|
|
23
23
|
import { firstValueFrom, BehaviorSubject, Subject, throwError, debounceTime as debounceTime$1, takeUntil as takeUntil$1 } from 'rxjs';
|
|
24
24
|
import { map, take, takeUntil, timeout, tap, debounceTime, finalize } from 'rxjs/operators';
|
|
25
25
|
import * as i1$2 from '@praxisui/core';
|
|
26
|
-
import { PraxisI18nService, PraxisIconDirective, providePraxisI18nConfig, RULE_PROPERTY_SCHEMA, FIELD_METADATA_CAPABILITIES, deepMerge, createDefaultFormConfig, normalizeFormConfig as normalizeFormConfig$1, ensureIds, createEmptyRichContentDocument, ASYNC_CONFIG_STORAGE, migrateFormLayoutRule, LoggerService, createCorporateLoggerConfig, ConsoleLoggerSink, ResourceQuickConnectComponent, composeHeadersWithVersion, buildApiUrl, mapFieldDefinitionsToMetadata, reconcileFormConfig, syncWithServerMetadata, PRAXIS_LOADING_CTX, normalizeControlTypeKey, resolveSpan, resolveOffset, resolveOrder, resolveHidden, buildSchemaId, fetchWithETag, resolveControlTypeAlias, getTextTransformer, MemoryCacheAdapter, LocalStorageCacheAdapter, SchemaMetadataClient, CONNECTION_STORAGE, API_URL, PRAXIS_LOADING_RENDERER, FORM_HOOKS_PRESETS, EmptyStateCardComponent, isValidFormConfig, ComponentMetadataRegistry, FieldControlType, isRequiredGlobalActionPayloadMissing, GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_ACTION_CATALOG, getGlobalActionCatalog, SURFACE_OPEN_I18N_NAMESPACE, getGlobalActionUiSchema, getRequiredGlobalActionPayloadKeys, hasMeaningfulGlobalActionPayloadValue, SurfaceOpenActionEditorComponent, SURFACE_OPEN_I18N_CONFIG, validateGlobalActionRefs, PraxisJsonLogicService } from '@praxisui/core';
|
|
26
|
+
import { PraxisI18nService, PraxisIconDirective, providePraxisI18nConfig, RULE_PROPERTY_SCHEMA, FIELD_METADATA_CAPABILITIES, deepMerge, createDefaultFormConfig, normalizeFormConfig as normalizeFormConfig$1, ensureIds, createEmptyRichContentDocument, ASYNC_CONFIG_STORAGE, migrateFormLayoutRule, normalizeFormLayoutItems, createFieldLayoutItem, getFormLayoutFieldNames, LoggerService, createCorporateLoggerConfig, ConsoleLoggerSink, ResourceQuickConnectComponent, composeHeadersWithVersion, buildApiUrl, mapFieldDefinitionsToMetadata, reconcileFormConfig, syncWithServerMetadata, PRAXIS_LOADING_CTX, normalizeControlTypeKey, getFormColumnFieldNames, resolveSpan, resolveOffset, resolveOrder, resolveHidden, buildSchemaId, fetchWithETag, resolveControlTypeAlias, getTextTransformer, MemoryCacheAdapter, LocalStorageCacheAdapter, SchemaMetadataClient, CONNECTION_STORAGE, API_URL, PRAXIS_LOADING_RENDERER, FORM_HOOKS_PRESETS, EmptyStateCardComponent, isValidFormConfig, ComponentMetadataRegistry, FieldControlType, isRequiredGlobalActionPayloadMissing, GLOBAL_ACTION_CATALOG, PRAXIS_GLOBAL_ACTION_CATALOG, getGlobalActionCatalog, SURFACE_OPEN_I18N_NAMESPACE, getGlobalActionUiSchema, getRequiredGlobalActionPayloadKeys, hasMeaningfulGlobalActionPayloadValue, SurfaceOpenActionEditorComponent, SURFACE_OPEN_I18N_CONFIG, validateGlobalActionRefs, PraxisJsonLogicService } from '@praxisui/core';
|
|
27
27
|
import * as i1 from '@praxisui/dynamic-fields';
|
|
28
28
|
import { getControlTypeCatalog, ConfirmDialogComponent, DynamicFieldLoaderDirective } from '@praxisui/dynamic-fields';
|
|
29
29
|
import { BaseAiAdapter, PraxisAiAssistantComponent } from '@praxisui/ai';
|
|
30
|
-
import { PraxisRichContent } from '@praxisui/rich-content';
|
|
30
|
+
import { PraxisRichContent, PraxisRichContentConfigEditor } from '@praxisui/rich-content';
|
|
31
31
|
import * as i6 from '@angular/material/menu';
|
|
32
32
|
import { MatMenuModule } from '@angular/material/menu';
|
|
33
33
|
import { produce } from 'immer';
|
|
34
34
|
import * as i7 from '@praxisui/settings-panel';
|
|
35
|
-
import { SETTINGS_PANEL_DATA, GLOBAL_CONFIG_DYNAMIC_FORM_COMPONENT } from '@praxisui/settings-panel';
|
|
35
|
+
import { SettingsPanelService, SETTINGS_PANEL_DATA, GLOBAL_CONFIG_DYNAMIC_FORM_COMPONENT } from '@praxisui/settings-panel';
|
|
36
36
|
import * as i12 from '@angular/router';
|
|
37
37
|
import * as i7$3 from '@angular/material/tabs';
|
|
38
38
|
import { MatTabsModule } from '@angular/material/tabs';
|
|
@@ -1157,7 +1157,7 @@ function generateRulePropertyWhenFalseCapabilities(targetType, properties) {
|
|
|
1157
1157
|
return result;
|
|
1158
1158
|
}
|
|
1159
1159
|
const FORM_AI_CAPABILITIES = {
|
|
1160
|
-
version: 'v1.
|
|
1160
|
+
version: 'v1.11', // Publishes column layout items and visual block authoring paths.
|
|
1161
1161
|
enums: ENUMS$1,
|
|
1162
1162
|
targets: [
|
|
1163
1163
|
'praxis-dynamic-form',
|
|
@@ -1177,7 +1177,8 @@ const FORM_AI_CAPABILITIES = {
|
|
|
1177
1177
|
'Este catálogo foca em configurações de alto nÃvel (macro) do formulário e regras.',
|
|
1178
1178
|
'Detalhes de propriedades internas de campos individuais devem ser tratados em catálogos de microcomponentes.',
|
|
1179
1179
|
'Referencie campos pelo name em fieldMetadata[].name.',
|
|
1180
|
-
'Para hierarquia do layout use sections[].rows[].columns[].
|
|
1180
|
+
'Para hierarquia do layout use sections[].rows[].columns[].items como contrato canônico ordenado; items kind:"field" referenciam fieldMetadata e items kind:"richContent" são blocos visuais fora do payload.',
|
|
1181
|
+
'sections[].rows[].columns[].fields permanece como projeção/migração de campos; não use fields para criar blocos visuais.',
|
|
1181
1182
|
'POLICY: Ao alterar arrays de layout (sections, rows, columns), o patch deve ser tratado como merge/append, não replace total.',
|
|
1182
1183
|
'Condições booleanas declarativas devem usar Json Logic canônico. Funções, handlers e hooks continuam exigindo revisão de segurança ou wiring pelo host.',
|
|
1183
1184
|
'Regras condicionais devem usar JSON Logic canônico em rules.condition. Não utilize JS puro nem string ad hoc.',
|
|
@@ -1726,18 +1727,71 @@ const FORM_AI_CAPABILITIES = {
|
|
|
1726
1727
|
path: 'sections[].rows[].columns[].fields',
|
|
1727
1728
|
category: 'layout',
|
|
1728
1729
|
valueKind: 'array',
|
|
1729
|
-
description: '
|
|
1730
|
+
description: 'Projeção legada/derivada dos itens kind:"field" dentro da coluna.',
|
|
1730
1731
|
critical: true,
|
|
1731
1732
|
intentExamples: ['mover campo para a primeira coluna', 'reordenar campos na coluna'],
|
|
1732
|
-
safetyNotes: '
|
|
1733
|
+
safetyNotes: 'Use sections[].rows[].columns[].items para patches novos. fields não suporta blocos visuais.',
|
|
1733
1734
|
},
|
|
1734
1735
|
{
|
|
1735
1736
|
path: 'sections[].rows[].columns[].fields[]',
|
|
1736
1737
|
category: 'layout',
|
|
1737
1738
|
valueKind: 'string',
|
|
1738
|
-
description: 'Nome do campo dentro da coluna.',
|
|
1739
|
+
description: 'Nome do campo dentro da projeção legada/derivada da coluna.',
|
|
1739
1740
|
critical: true,
|
|
1740
|
-
safetyNotes: 'Apenas nomes de campos
|
|
1741
|
+
safetyNotes: 'Apenas nomes de campos. Para ordem mista entre campos e blocos visuais, use items[].',
|
|
1742
|
+
},
|
|
1743
|
+
{
|
|
1744
|
+
path: 'sections[].rows[].columns[].items',
|
|
1745
|
+
category: 'layout',
|
|
1746
|
+
valueKind: 'array',
|
|
1747
|
+
description: 'Lista canônica ordenada de itens da coluna: campos e blocos visuais.',
|
|
1748
|
+
critical: true,
|
|
1749
|
+
intentExamples: ['adicionar bloco visual na coluna', 'mover texto entre campos', 'reordenar campo e aviso visual'],
|
|
1750
|
+
safetyNotes: 'Itens kind:"field" devem apontar para fieldMetadata[].name. Itens kind:"richContent" não entram no payload de submit.',
|
|
1751
|
+
},
|
|
1752
|
+
{
|
|
1753
|
+
path: 'sections[].rows[].columns[].items[].kind',
|
|
1754
|
+
category: 'layout',
|
|
1755
|
+
valueKind: 'enum',
|
|
1756
|
+
allowedValues: ['field', 'richContent'],
|
|
1757
|
+
description: 'Tipo do item de layout da coluna.',
|
|
1758
|
+
critical: true,
|
|
1759
|
+
},
|
|
1760
|
+
{
|
|
1761
|
+
path: 'sections[].rows[].columns[].items[].id',
|
|
1762
|
+
category: 'layout',
|
|
1763
|
+
valueKind: 'string',
|
|
1764
|
+
description: 'ID estável do item de layout dentro do formulário.',
|
|
1765
|
+
critical: true,
|
|
1766
|
+
safetyNotes: 'Use IDs estáveis para mover/atualizar/remover itens; não use Ãndice como identidade.',
|
|
1767
|
+
},
|
|
1768
|
+
{
|
|
1769
|
+
path: 'sections[].rows[].columns[].items[].fieldName',
|
|
1770
|
+
category: 'layout',
|
|
1771
|
+
valueKind: 'string',
|
|
1772
|
+
description: 'Nome do campo quando kind é "field".',
|
|
1773
|
+
critical: true,
|
|
1774
|
+
safetyNotes: 'Deve existir em fieldMetadata[].name.',
|
|
1775
|
+
},
|
|
1776
|
+
{
|
|
1777
|
+
path: 'sections[].rows[].columns[].items[].document',
|
|
1778
|
+
category: 'editorial',
|
|
1779
|
+
valueKind: 'object',
|
|
1780
|
+
description: 'RichContentDocument do bloco visual quando kind é "richContent".',
|
|
1781
|
+
safetyNotes: 'Não participa do formData nem do payload HTTP de submissão.',
|
|
1782
|
+
},
|
|
1783
|
+
{
|
|
1784
|
+
path: 'sections[].rows[].columns[].items[].layout',
|
|
1785
|
+
category: 'editorial',
|
|
1786
|
+
valueKind: 'enum',
|
|
1787
|
+
allowedValues: ['block', 'inline'],
|
|
1788
|
+
description: 'Modo de renderização do bloco visual richContent dentro da coluna.',
|
|
1789
|
+
},
|
|
1790
|
+
{
|
|
1791
|
+
path: 'sections[].rows[].columns[].items[].rootClassName',
|
|
1792
|
+
category: 'appearance',
|
|
1793
|
+
valueKind: 'string',
|
|
1794
|
+
description: 'Classe CSS opcional aplicada ao bloco visual richContent.',
|
|
1741
1795
|
},
|
|
1742
1796
|
{
|
|
1743
1797
|
path: 'sections[].rows[].columns[].span.xs',
|
|
@@ -3020,6 +3074,13 @@ const TASK_PRESETS = {
|
|
|
3020
3074
|
'sections[].headerActions[].disabled',
|
|
3021
3075
|
'sections[].rows[].gap',
|
|
3022
3076
|
'sections[].rows[].rowGap',
|
|
3077
|
+
'sections[].rows[].columns[].items[]',
|
|
3078
|
+
'sections[].rows[].columns[].items[].kind',
|
|
3079
|
+
'sections[].rows[].columns[].items[].id',
|
|
3080
|
+
'sections[].rows[].columns[].items[].fieldName',
|
|
3081
|
+
'sections[].rows[].columns[].items[].document',
|
|
3082
|
+
'sections[].rows[].columns[].items[].layout',
|
|
3083
|
+
'sections[].rows[].columns[].items[].rootClassName',
|
|
3023
3084
|
'sections[].rows[].columns[].fields[]',
|
|
3024
3085
|
'sections[].rows[].columns[].span.*',
|
|
3025
3086
|
'sections[].rows[].columns[].offset.*',
|
|
@@ -4347,18 +4408,18 @@ class DynamicFormLayoutService {
|
|
|
4347
4408
|
this.changesSubject.next({ timestamp: Date.now(), op, config });
|
|
4348
4409
|
}
|
|
4349
4410
|
normalizeConfig(config) {
|
|
4350
|
-
return produce(config, (draft) => {
|
|
4411
|
+
return ensureIds(produce(config, (draft) => {
|
|
4351
4412
|
draft.sections = draft.sections || [];
|
|
4352
4413
|
draft.sections.forEach((section) => {
|
|
4353
4414
|
section.rows = section.rows || [];
|
|
4354
4415
|
section.rows.forEach((row) => {
|
|
4355
4416
|
row.columns = row.columns || [];
|
|
4356
4417
|
row.columns.forEach((col) => {
|
|
4357
|
-
|
|
4418
|
+
this.applyLayoutItemsToColumn(col, normalizeFormLayoutItems(col));
|
|
4358
4419
|
});
|
|
4359
4420
|
});
|
|
4360
4421
|
});
|
|
4361
|
-
});
|
|
4422
|
+
}));
|
|
4362
4423
|
}
|
|
4363
4424
|
validateConfig(config) {
|
|
4364
4425
|
const errors = [];
|
|
@@ -4373,11 +4434,23 @@ class DynamicFormLayoutService {
|
|
|
4373
4434
|
return;
|
|
4374
4435
|
}
|
|
4375
4436
|
row.columns.forEach((col, cIdx) => {
|
|
4376
|
-
|
|
4377
|
-
|
|
4437
|
+
const rawItems = col.items;
|
|
4438
|
+
if (Array.isArray(rawItems)) {
|
|
4439
|
+
rawItems.forEach((item, itemIdx) => {
|
|
4440
|
+
if (item?.kind === 'field' && !item.fieldName) {
|
|
4441
|
+
errors.push(`field item at section[${sIdx}].row[${rIdx}].column[${cIdx}].item[${itemIdx}] missing fieldName`);
|
|
4442
|
+
}
|
|
4443
|
+
else if (item?.kind === 'richContent' && !item.document) {
|
|
4444
|
+
errors.push(`richContent item at section[${sIdx}].row[${rIdx}].column[${cIdx}].item[${itemIdx}] missing document`);
|
|
4445
|
+
}
|
|
4446
|
+
else if (item?.kind !== 'field' && item?.kind !== 'richContent') {
|
|
4447
|
+
errors.push(`layout item at section[${sIdx}].row[${rIdx}].column[${cIdx}].item[${itemIdx}] has invalid kind`);
|
|
4448
|
+
}
|
|
4449
|
+
});
|
|
4378
4450
|
return;
|
|
4379
4451
|
}
|
|
4380
|
-
col.fields.
|
|
4452
|
+
const fields = Array.isArray(col.fields) ? col.fields : [];
|
|
4453
|
+
fields.forEach((field, fIdx) => {
|
|
4381
4454
|
const name = typeof field === 'string' ? field : field?.name;
|
|
4382
4455
|
if (!name) {
|
|
4383
4456
|
errors.push(`field at section[${sIdx}].row[${rIdx}].column[${cIdx}].field[${fIdx}] missing name`);
|
|
@@ -4641,11 +4714,15 @@ class DynamicFormLayoutService {
|
|
|
4641
4714
|
// Objetivo: 2 campos por linha em telas md+ (6/12 cada) e 1 por linha em xs/sm (12/12)
|
|
4642
4715
|
const perRow = Math.max(1, fieldsPerRow || 2);
|
|
4643
4716
|
const base = Math.max(1, Math.floor(12 / perRow));
|
|
4644
|
-
const columns = rowFields.map((field) =>
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4717
|
+
const columns = rowFields.map((field, index) => {
|
|
4718
|
+
const items = [createFieldLayoutItem(field.name, index)];
|
|
4719
|
+
return {
|
|
4720
|
+
id: this.genId('col'),
|
|
4721
|
+
items,
|
|
4722
|
+
fields: getFormLayoutFieldNames(items),
|
|
4723
|
+
span: { xs: 12, sm: 12, md: base, lg: base, xl: base },
|
|
4724
|
+
};
|
|
4725
|
+
});
|
|
4649
4726
|
rows.push({ id: this.genId('row'), columns });
|
|
4650
4727
|
}
|
|
4651
4728
|
return rows;
|
|
@@ -4671,6 +4748,89 @@ class DynamicFormLayoutService {
|
|
|
4671
4748
|
this.emit(op, next);
|
|
4672
4749
|
return { config: next, op };
|
|
4673
4750
|
}
|
|
4751
|
+
getFieldName(field) {
|
|
4752
|
+
if (typeof field === 'string')
|
|
4753
|
+
return field;
|
|
4754
|
+
if (field && typeof field === 'object') {
|
|
4755
|
+
const name = field.name;
|
|
4756
|
+
return typeof name === 'string' ? name : null;
|
|
4757
|
+
}
|
|
4758
|
+
return null;
|
|
4759
|
+
}
|
|
4760
|
+
findFieldLayoutItemIndex(items, fieldName, fieldIndex) {
|
|
4761
|
+
let visibleFieldIndex = 0;
|
|
4762
|
+
for (let index = 0; index < items.length; index++) {
|
|
4763
|
+
const item = items[index];
|
|
4764
|
+
if (item.kind !== 'field')
|
|
4765
|
+
continue;
|
|
4766
|
+
if (fieldIndex !== undefined && visibleFieldIndex === fieldIndex) {
|
|
4767
|
+
return index;
|
|
4768
|
+
}
|
|
4769
|
+
if (fieldIndex === undefined && fieldName && item.fieldName === fieldName) {
|
|
4770
|
+
return index;
|
|
4771
|
+
}
|
|
4772
|
+
visibleFieldIndex++;
|
|
4773
|
+
}
|
|
4774
|
+
return fieldName
|
|
4775
|
+
? items.findIndex((item) => item.kind === 'field' && item.fieldName === fieldName)
|
|
4776
|
+
: -1;
|
|
4777
|
+
}
|
|
4778
|
+
getLayoutInsertIndexForFieldIndex(items, fieldIndex) {
|
|
4779
|
+
let visibleFieldIndex = 0;
|
|
4780
|
+
for (let index = 0; index < items.length; index++) {
|
|
4781
|
+
if (items[index].kind !== 'field')
|
|
4782
|
+
continue;
|
|
4783
|
+
if (visibleFieldIndex === fieldIndex)
|
|
4784
|
+
return index;
|
|
4785
|
+
visibleFieldIndex++;
|
|
4786
|
+
}
|
|
4787
|
+
return items.length;
|
|
4788
|
+
}
|
|
4789
|
+
applyLayoutItemsToColumn(column, items) {
|
|
4790
|
+
column.items = items;
|
|
4791
|
+
column.fields = getFormLayoutFieldNames(items);
|
|
4792
|
+
}
|
|
4793
|
+
insertFieldLayoutItem(column, field, fieldIndex) {
|
|
4794
|
+
const fieldName = this.getFieldName(field);
|
|
4795
|
+
if (!fieldName)
|
|
4796
|
+
return;
|
|
4797
|
+
const items = normalizeFormLayoutItems(column);
|
|
4798
|
+
const layoutIndex = this.getLayoutInsertIndexForFieldIndex(items, fieldIndex);
|
|
4799
|
+
items.splice(layoutIndex, 0, createFieldLayoutItem(fieldName, fieldIndex));
|
|
4800
|
+
this.applyLayoutItemsToColumn(column, items);
|
|
4801
|
+
}
|
|
4802
|
+
removeFieldLayoutItem(column, fieldIndex) {
|
|
4803
|
+
const items = normalizeFormLayoutItems(column);
|
|
4804
|
+
const layoutIndex = this.findFieldLayoutItemIndex(items, null, fieldIndex);
|
|
4805
|
+
if (layoutIndex >= 0) {
|
|
4806
|
+
items.splice(layoutIndex, 1);
|
|
4807
|
+
}
|
|
4808
|
+
this.applyLayoutItemsToColumn(column, items);
|
|
4809
|
+
}
|
|
4810
|
+
hasLayoutItems(column) {
|
|
4811
|
+
return normalizeFormLayoutItems(column).length > 0;
|
|
4812
|
+
}
|
|
4813
|
+
moveFieldLayoutItem(sourceColumn, destinationColumn, movedField, fromFieldIndex, toFieldIndex) {
|
|
4814
|
+
const fieldName = this.getFieldName(movedField);
|
|
4815
|
+
if (!fieldName)
|
|
4816
|
+
return;
|
|
4817
|
+
const sourceItems = normalizeFormLayoutItems(sourceColumn);
|
|
4818
|
+
const sourceItemIndex = this.findFieldLayoutItemIndex(sourceItems, fieldName, fromFieldIndex);
|
|
4819
|
+
const [movedItem] = sourceItemIndex >= 0
|
|
4820
|
+
? sourceItems.splice(sourceItemIndex, 1)
|
|
4821
|
+
: [createFieldLayoutItem(fieldName, toFieldIndex)];
|
|
4822
|
+
if (sourceColumn === destinationColumn) {
|
|
4823
|
+
const destinationIndex = this.getLayoutInsertIndexForFieldIndex(sourceItems, toFieldIndex);
|
|
4824
|
+
sourceItems.splice(destinationIndex, 0, movedItem);
|
|
4825
|
+
this.applyLayoutItemsToColumn(sourceColumn, sourceItems);
|
|
4826
|
+
return;
|
|
4827
|
+
}
|
|
4828
|
+
const destinationItems = normalizeFormLayoutItems(destinationColumn);
|
|
4829
|
+
const destinationIndex = this.getLayoutInsertIndexForFieldIndex(destinationItems, toFieldIndex);
|
|
4830
|
+
destinationItems.splice(destinationIndex, 0, movedItem);
|
|
4831
|
+
this.applyLayoutItemsToColumn(sourceColumn, sourceItems);
|
|
4832
|
+
this.applyLayoutItemsToColumn(destinationColumn, destinationItems);
|
|
4833
|
+
}
|
|
4674
4834
|
moveSection(config, fromIndex, toIndex) {
|
|
4675
4835
|
const op = { type: 'moveSection', fromIndex, toIndex };
|
|
4676
4836
|
if (fromIndex === toIndex) {
|
|
@@ -4858,12 +5018,12 @@ class DynamicFormLayoutService {
|
|
|
4858
5018
|
columnId: dstCols[to.colIndex].id,
|
|
4859
5019
|
};
|
|
4860
5020
|
return this.mutate(config, op, (draft) => {
|
|
4861
|
-
const
|
|
4862
|
-
.columns[from.colIndex]
|
|
4863
|
-
const
|
|
4864
|
-
const
|
|
4865
|
-
|
|
4866
|
-
if (policy === 'pruneEmptyContainers' &&
|
|
5021
|
+
const srcColumn = draft.sections[from.sectionIndex].rows[from.rowIndex]
|
|
5022
|
+
.columns[from.colIndex];
|
|
5023
|
+
const dstColumn = draft.sections[to.sectionIndex].rows[to.rowIndex].columns[to.colIndex];
|
|
5024
|
+
const moved = srcColumn.fields[from.fieldIndex];
|
|
5025
|
+
this.moveFieldLayoutItem(srcColumn, dstColumn, moved, from.fieldIndex, to.toFieldIndex);
|
|
5026
|
+
if (policy === 'pruneEmptyContainers' && !this.hasLayoutItems(srcColumn)) {
|
|
4867
5027
|
draft.sections[from.sectionIndex].rows[from.rowIndex].columns.splice(from.colIndex, 1);
|
|
4868
5028
|
pruned.push('column');
|
|
4869
5029
|
const draftRow = draft.sections[from.sectionIndex].rows[from.rowIndex];
|
|
@@ -4892,8 +5052,8 @@ class DynamicFormLayoutService {
|
|
|
4892
5052
|
this.assertIndex(atIdx, fields.length, 'atIdx', true);
|
|
4893
5053
|
const op = { type: 'insertField', target, field, atIdx };
|
|
4894
5054
|
return this.mutate(config, op, (draft) => {
|
|
4895
|
-
const
|
|
4896
|
-
|
|
5055
|
+
const draftColumn = draft.sections[target.sectionIndex].rows[target.rowIndex].columns[target.colIndex];
|
|
5056
|
+
this.insertFieldLayoutItem(draftColumn, field, atIdx);
|
|
4897
5057
|
});
|
|
4898
5058
|
}
|
|
4899
5059
|
removeField(config, secIdx, rowIdx, colIdx, fieldIndex, options = {}) {
|
|
@@ -4928,10 +5088,9 @@ class DynamicFormLayoutService {
|
|
|
4928
5088
|
};
|
|
4929
5089
|
const pruned = [];
|
|
4930
5090
|
return this.mutate(config, op, (draft) => {
|
|
4931
|
-
const
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
if (policy === 'pruneEmptyContainers' && draftFields.length === 0) {
|
|
5091
|
+
const draftColumn = draft.sections[secIdx].rows[rowIdx].columns[colIdx];
|
|
5092
|
+
this.removeFieldLayoutItem(draftColumn, fieldIndex);
|
|
5093
|
+
if (policy === 'pruneEmptyContainers' && !this.hasLayoutItems(draftColumn)) {
|
|
4935
5094
|
draft.sections[secIdx].rows[rowIdx].columns.splice(colIdx, 1);
|
|
4936
5095
|
pruned.push('column');
|
|
4937
5096
|
if (draft.sections[secIdx].rows[rowIdx].columns.length === 0) {
|
|
@@ -5135,13 +5294,13 @@ class DynamicFormLayoutService {
|
|
|
5135
5294
|
this.assertIndex(to.toIndex, dstFields.length, 'to.toIndex', true);
|
|
5136
5295
|
const pruned = [];
|
|
5137
5296
|
return this.mutate(config, op, (draft) => {
|
|
5138
|
-
const
|
|
5139
|
-
.columns[fromPath.colIndex]
|
|
5140
|
-
const
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
if (policy === 'pruneEmptyContainers' &&
|
|
5297
|
+
const srcColumn = draft.sections[fromPath.sectionIndex].rows[fromPath.rowIndex]
|
|
5298
|
+
.columns[fromPath.colIndex];
|
|
5299
|
+
const dstColumn = draft.sections[toPath.sectionIndex].rows[toPath.rowIndex]
|
|
5300
|
+
.columns[toPath.colIndex];
|
|
5301
|
+
const moved = srcColumn.fields[fromPath.fieldIndex];
|
|
5302
|
+
this.moveFieldLayoutItem(srcColumn, dstColumn, moved, fromPath.fieldIndex, to.toIndex);
|
|
5303
|
+
if (policy === 'pruneEmptyContainers' && !this.hasLayoutItems(srcColumn)) {
|
|
5145
5304
|
draft.sections[fromPath.sectionIndex].rows[fromPath.rowIndex].columns.splice(fromPath.colIndex, 1);
|
|
5146
5305
|
pruned.push('column');
|
|
5147
5306
|
const draftRow = draft.sections[fromPath.sectionIndex].rows[fromPath.rowIndex];
|
|
@@ -5167,9 +5326,159 @@ class DynamicFormLayoutService {
|
|
|
5167
5326
|
this.assertIndex(index, fields.length, 'atIndex', true);
|
|
5168
5327
|
const op = { type: 'insertField', target, field, atIndex: index };
|
|
5169
5328
|
return this.mutate(config, op, (draft) => {
|
|
5170
|
-
const
|
|
5171
|
-
.columns[path.colIndex]
|
|
5172
|
-
|
|
5329
|
+
const draftColumn = draft.sections[path.sectionIndex].rows[path.rowIndex]
|
|
5330
|
+
.columns[path.colIndex];
|
|
5331
|
+
this.insertFieldLayoutItem(draftColumn, field, index);
|
|
5332
|
+
});
|
|
5333
|
+
}
|
|
5334
|
+
insertLayoutItemById(config, target, item, atIndex) {
|
|
5335
|
+
const path = this.resolvePathByIds(config, target);
|
|
5336
|
+
const column = config.sections[path.sectionIndex].rows[path.rowIndex].columns[path.colIndex];
|
|
5337
|
+
const items = normalizeFormLayoutItems(column);
|
|
5338
|
+
const index = atIndex ?? items.length;
|
|
5339
|
+
this.assertIndex(index, items.length, 'atIndex', true);
|
|
5340
|
+
const op = {
|
|
5341
|
+
type: 'insertLayoutItem',
|
|
5342
|
+
target,
|
|
5343
|
+
itemId: item.id,
|
|
5344
|
+
atIndex: index,
|
|
5345
|
+
};
|
|
5346
|
+
return this.mutate(config, op, (draft) => {
|
|
5347
|
+
const draftColumn = draft.sections[path.sectionIndex].rows[path.rowIndex].columns[path.colIndex];
|
|
5348
|
+
const draftItems = normalizeFormLayoutItems(draftColumn);
|
|
5349
|
+
draftItems.splice(index, 0, item);
|
|
5350
|
+
this.applyLayoutItemsToColumn(draftColumn, draftItems);
|
|
5351
|
+
});
|
|
5352
|
+
}
|
|
5353
|
+
moveLayoutItemById(config, from, to, options = {}) {
|
|
5354
|
+
const fromPath = this.resolvePathByIds(config, from);
|
|
5355
|
+
const toPath = this.resolvePathByIds(config, to);
|
|
5356
|
+
const sourceColumn = config.sections[fromPath.sectionIndex].rows[fromPath.rowIndex].columns[fromPath.colIndex];
|
|
5357
|
+
const sourceItems = normalizeFormLayoutItems(sourceColumn);
|
|
5358
|
+
const fromIndex = sourceItems.findIndex((item) => item.id === from.itemId);
|
|
5359
|
+
if (fromIndex < 0) {
|
|
5360
|
+
throw new Error(`itemId not found: ${from.itemId}`);
|
|
5361
|
+
}
|
|
5362
|
+
const destinationColumn = config.sections[toPath.sectionIndex].rows[toPath.rowIndex].columns[toPath.colIndex];
|
|
5363
|
+
const destinationLength = from.sectionId === to.sectionId &&
|
|
5364
|
+
from.rowId === to.rowId &&
|
|
5365
|
+
from.columnId === to.columnId
|
|
5366
|
+
? sourceItems.length - 1
|
|
5367
|
+
: normalizeFormLayoutItems(destinationColumn).length;
|
|
5368
|
+
this.assertIndex(to.toIndex, destinationLength, 'to.toIndex', true);
|
|
5369
|
+
const policy = options.policy ?? 'keepEmptyContainers';
|
|
5370
|
+
const op = {
|
|
5371
|
+
type: 'moveLayoutItem',
|
|
5372
|
+
correlationId: options.correlationId,
|
|
5373
|
+
origin: options.origin,
|
|
5374
|
+
from: {
|
|
5375
|
+
sectionId: from.sectionId,
|
|
5376
|
+
rowId: from.rowId,
|
|
5377
|
+
columnId: from.columnId,
|
|
5378
|
+
itemId: from.itemId,
|
|
5379
|
+
},
|
|
5380
|
+
to: {
|
|
5381
|
+
sectionId: to.sectionId,
|
|
5382
|
+
rowId: to.rowId,
|
|
5383
|
+
columnId: to.columnId,
|
|
5384
|
+
toIndex: to.toIndex,
|
|
5385
|
+
},
|
|
5386
|
+
policy,
|
|
5387
|
+
};
|
|
5388
|
+
const pruned = [];
|
|
5389
|
+
return this.mutate(config, op, (draft) => {
|
|
5390
|
+
const draftSourceColumn = draft.sections[fromPath.sectionIndex].rows[fromPath.rowIndex].columns[fromPath.colIndex];
|
|
5391
|
+
const draftSourceItems = normalizeFormLayoutItems(draftSourceColumn);
|
|
5392
|
+
const draftFromIndex = draftSourceItems.findIndex((item) => item.id === from.itemId);
|
|
5393
|
+
const [movedItem] = draftSourceItems.splice(draftFromIndex, 1);
|
|
5394
|
+
if (from.sectionId === to.sectionId &&
|
|
5395
|
+
from.rowId === to.rowId &&
|
|
5396
|
+
from.columnId === to.columnId) {
|
|
5397
|
+
draftSourceItems.splice(to.toIndex, 0, movedItem);
|
|
5398
|
+
this.applyLayoutItemsToColumn(draftSourceColumn, draftSourceItems);
|
|
5399
|
+
}
|
|
5400
|
+
else {
|
|
5401
|
+
const draftDestinationColumn = draft.sections[toPath.sectionIndex].rows[toPath.rowIndex].columns[toPath.colIndex];
|
|
5402
|
+
const draftDestinationItems = normalizeFormLayoutItems(draftDestinationColumn);
|
|
5403
|
+
draftDestinationItems.splice(to.toIndex, 0, movedItem);
|
|
5404
|
+
this.applyLayoutItemsToColumn(draftSourceColumn, draftSourceItems);
|
|
5405
|
+
this.applyLayoutItemsToColumn(draftDestinationColumn, draftDestinationItems);
|
|
5406
|
+
}
|
|
5407
|
+
if (policy === 'pruneEmptyContainers' &&
|
|
5408
|
+
!this.hasLayoutItems(draftSourceColumn)) {
|
|
5409
|
+
draft.sections[fromPath.sectionIndex].rows[fromPath.rowIndex].columns.splice(fromPath.colIndex, 1);
|
|
5410
|
+
pruned.push('column');
|
|
5411
|
+
const draftRow = draft.sections[fromPath.sectionIndex].rows[fromPath.rowIndex];
|
|
5412
|
+
if (draftRow.columns.length === 0) {
|
|
5413
|
+
draft.sections[fromPath.sectionIndex].rows.splice(fromPath.rowIndex, 1);
|
|
5414
|
+
pruned.push('row');
|
|
5415
|
+
if (draft.sections[fromPath.sectionIndex].rows.length === 0) {
|
|
5416
|
+
draft.sections.splice(fromPath.sectionIndex, 1);
|
|
5417
|
+
pruned.push('section');
|
|
5418
|
+
}
|
|
5419
|
+
}
|
|
5420
|
+
}
|
|
5421
|
+
if (pruned.length) {
|
|
5422
|
+
op.meta = { ...(op.meta || {}), pruned };
|
|
5423
|
+
}
|
|
5424
|
+
});
|
|
5425
|
+
}
|
|
5426
|
+
updateLayoutItemById(config, target, item) {
|
|
5427
|
+
const path = this.resolvePathByIds(config, target);
|
|
5428
|
+
const column = config.sections[path.sectionIndex].rows[path.rowIndex].columns[path.colIndex];
|
|
5429
|
+
const itemIndex = normalizeFormLayoutItems(column).findIndex((candidate) => candidate.id === target.itemId);
|
|
5430
|
+
if (itemIndex < 0) {
|
|
5431
|
+
throw new Error(`itemId not found: ${target.itemId}`);
|
|
5432
|
+
}
|
|
5433
|
+
const op = {
|
|
5434
|
+
type: 'updateLayoutItem',
|
|
5435
|
+
target,
|
|
5436
|
+
itemId: target.itemId,
|
|
5437
|
+
};
|
|
5438
|
+
return this.mutate(config, op, (draft) => {
|
|
5439
|
+
const draftColumn = draft.sections[path.sectionIndex].rows[path.rowIndex].columns[path.colIndex];
|
|
5440
|
+
const items = normalizeFormLayoutItems(draftColumn);
|
|
5441
|
+
items[itemIndex] = { ...item, id: target.itemId };
|
|
5442
|
+
this.applyLayoutItemsToColumn(draftColumn, items);
|
|
5443
|
+
});
|
|
5444
|
+
}
|
|
5445
|
+
removeLayoutItemById(config, sectionId, rowId, columnId, itemId, options = {}) {
|
|
5446
|
+
const path = this.resolvePathByIds(config, { sectionId, rowId, columnId });
|
|
5447
|
+
const column = config.sections[path.sectionIndex].rows[path.rowIndex].columns[path.colIndex];
|
|
5448
|
+
const itemIndex = normalizeFormLayoutItems(column).findIndex((item) => item.id === itemId);
|
|
5449
|
+
if (itemIndex < 0) {
|
|
5450
|
+
throw new Error(`itemId not found: ${itemId}`);
|
|
5451
|
+
}
|
|
5452
|
+
const policy = options.policy ?? 'keepEmptyContainers';
|
|
5453
|
+
const op = {
|
|
5454
|
+
type: 'removeLayoutItem',
|
|
5455
|
+
correlationId: options.correlationId,
|
|
5456
|
+
origin: options.origin,
|
|
5457
|
+
from: { sectionId, rowId, columnId, itemId },
|
|
5458
|
+
policy,
|
|
5459
|
+
};
|
|
5460
|
+
const pruned = [];
|
|
5461
|
+
return this.mutate(config, op, (draft) => {
|
|
5462
|
+
const draftColumn = draft.sections[path.sectionIndex].rows[path.rowIndex].columns[path.colIndex];
|
|
5463
|
+
const items = normalizeFormLayoutItems(draftColumn);
|
|
5464
|
+
items.splice(itemIndex, 1);
|
|
5465
|
+
this.applyLayoutItemsToColumn(draftColumn, items);
|
|
5466
|
+
if (policy === 'pruneEmptyContainers' && !this.hasLayoutItems(draftColumn)) {
|
|
5467
|
+
draft.sections[path.sectionIndex].rows[path.rowIndex].columns.splice(path.colIndex, 1);
|
|
5468
|
+
pruned.push('column');
|
|
5469
|
+
const row = draft.sections[path.sectionIndex].rows[path.rowIndex];
|
|
5470
|
+
if (row.columns.length === 0) {
|
|
5471
|
+
draft.sections[path.sectionIndex].rows.splice(path.rowIndex, 1);
|
|
5472
|
+
pruned.push('row');
|
|
5473
|
+
if (draft.sections[path.sectionIndex].rows.length === 0) {
|
|
5474
|
+
draft.sections.splice(path.sectionIndex, 1);
|
|
5475
|
+
pruned.push('section');
|
|
5476
|
+
}
|
|
5477
|
+
}
|
|
5478
|
+
}
|
|
5479
|
+
if (pruned.length) {
|
|
5480
|
+
op.meta = { ...(op.meta || {}), pruned };
|
|
5481
|
+
}
|
|
5173
5482
|
});
|
|
5174
5483
|
}
|
|
5175
5484
|
removeFieldById(config, sectionId, rowId, columnId, fieldName, options = {}) {
|
|
@@ -5198,10 +5507,10 @@ class DynamicFormLayoutService {
|
|
|
5198
5507
|
};
|
|
5199
5508
|
const pruned = [];
|
|
5200
5509
|
return this.mutate(config, op, (draft) => {
|
|
5201
|
-
const
|
|
5202
|
-
.columns[path.colIndex]
|
|
5203
|
-
|
|
5204
|
-
if (policy === 'pruneEmptyContainers' &&
|
|
5510
|
+
const column = draft.sections[path.sectionIndex].rows[path.rowIndex]
|
|
5511
|
+
.columns[path.colIndex];
|
|
5512
|
+
this.removeFieldLayoutItem(column, path.fieldIndex);
|
|
5513
|
+
if (policy === 'pruneEmptyContainers' && !this.hasLayoutItems(column)) {
|
|
5205
5514
|
draft.sections[path.sectionIndex].rows[path.rowIndex].columns.splice(path.colIndex, 1);
|
|
5206
5515
|
pruned.push('column');
|
|
5207
5516
|
const row = draft.sections[path.sectionIndex].rows[path.rowIndex];
|
|
@@ -5228,7 +5537,7 @@ class DynamicFormLayoutService {
|
|
|
5228
5537
|
const pruned = this.mutate(config, op, (draft) => {
|
|
5229
5538
|
draft.sections = (draft.sections || []).filter((section) => {
|
|
5230
5539
|
section.rows = (section.rows || []).filter((row) => {
|
|
5231
|
-
row.columns = (row.columns || []).filter((col) => col
|
|
5540
|
+
row.columns = (row.columns || []).filter((col) => this.hasLayoutItems(col));
|
|
5232
5541
|
return row.columns.length > 0;
|
|
5233
5542
|
});
|
|
5234
5543
|
return section.rows.length > 0;
|
|
@@ -7495,7 +7804,7 @@ class PraxisDynamicForm {
|
|
|
7495
7804
|
return true;
|
|
7496
7805
|
}
|
|
7497
7806
|
if (Array.isArray(row.columns) && row.columns.length > 0) {
|
|
7498
|
-
const columnsWithFields = row.columns.filter((column) =>
|
|
7807
|
+
const columnsWithFields = row.columns.filter((column) => getFormColumnFieldNames(column).length > 0);
|
|
7499
7808
|
if (columnsWithFields.length === 0) {
|
|
7500
7809
|
return true;
|
|
7501
7810
|
}
|
|
@@ -7513,7 +7822,7 @@ class PraxisDynamicForm {
|
|
|
7513
7822
|
}
|
|
7514
7823
|
getRowClasses(row) {
|
|
7515
7824
|
const props = this.getRowRuleProps(row);
|
|
7516
|
-
const key = row?.id || JSON.stringify(row?.columns?.map((column) => column.id || column
|
|
7825
|
+
const key = row?.id || JSON.stringify(row?.columns?.map((column) => column.id || this.getColumnItemsSignature(column)) || []);
|
|
7517
7826
|
const signature = String(props.className || '');
|
|
7518
7827
|
const cached = this.rowClassesCache.get(key);
|
|
7519
7828
|
if (cached?.signature === signature) {
|
|
@@ -7527,7 +7836,7 @@ class PraxisDynamicForm {
|
|
|
7527
7836
|
}
|
|
7528
7837
|
getRowStyles(row) {
|
|
7529
7838
|
const props = this.getRowRuleProps(row);
|
|
7530
|
-
const key = row?.id || JSON.stringify(row?.columns?.map((column) => column.id || column
|
|
7839
|
+
const key = row?.id || JSON.stringify(row?.columns?.map((column) => column.id || this.getColumnItemsSignature(column)) || []);
|
|
7531
7840
|
const signature = JSON.stringify(props.style || {});
|
|
7532
7841
|
const cached = this.rowStylesCache.get(key);
|
|
7533
7842
|
if (cached?.signature === signature) {
|
|
@@ -7886,15 +8195,56 @@ class PraxisDynamicForm {
|
|
|
7886
8195
|
const rows = section?.rows || [];
|
|
7887
8196
|
const fieldCount = rows.reduce((acc, row) => {
|
|
7888
8197
|
const cols = row?.columns || [];
|
|
7889
|
-
const colFields = cols.reduce((cAcc, col) => cAcc + (
|
|
8198
|
+
const colFields = cols.reduce((cAcc, col) => cAcc + getFormColumnFieldNames(col).length, 0);
|
|
7890
8199
|
return acc + colFields;
|
|
7891
8200
|
}, 0);
|
|
7892
8201
|
const rowLabel = rows.length === 1 ? 'linha' : 'linhas';
|
|
7893
8202
|
const fieldLabel = fieldCount === 1 ? 'campo' : 'campos';
|
|
7894
8203
|
return `${rows.length} ${rowLabel}, ${fieldCount} ${fieldLabel}`;
|
|
7895
8204
|
}
|
|
8205
|
+
getColumnItems(column) {
|
|
8206
|
+
return normalizeFormLayoutItems(column);
|
|
8207
|
+
}
|
|
8208
|
+
getColumnRenderItems(column) {
|
|
8209
|
+
const renderItems = [];
|
|
8210
|
+
let fieldBatch = [];
|
|
8211
|
+
const flushFieldBatch = () => {
|
|
8212
|
+
if (!fieldBatch.length)
|
|
8213
|
+
return;
|
|
8214
|
+
const batchItems = fieldBatch;
|
|
8215
|
+
fieldBatch = [];
|
|
8216
|
+
const id = `${column.id || 'column'}:fields:${renderItems.length}:${batchItems
|
|
8217
|
+
.map((item) => item.id)
|
|
8218
|
+
.join(',')}`;
|
|
8219
|
+
renderItems.push({
|
|
8220
|
+
kind: 'fields',
|
|
8221
|
+
id,
|
|
8222
|
+
fields: this.getColumnFields({ id, items: batchItems }),
|
|
8223
|
+
});
|
|
8224
|
+
};
|
|
8225
|
+
for (const item of this.getColumnItems(column)) {
|
|
8226
|
+
if (item.kind === 'field') {
|
|
8227
|
+
fieldBatch.push(item);
|
|
8228
|
+
continue;
|
|
8229
|
+
}
|
|
8230
|
+
flushFieldBatch();
|
|
8231
|
+
const document = this.getRichContentLayoutItemDocument(item);
|
|
8232
|
+
if (!document)
|
|
8233
|
+
continue;
|
|
8234
|
+
renderItems.push({
|
|
8235
|
+
kind: 'richContent',
|
|
8236
|
+
id: `${column.id || 'column'}:${item.id}`,
|
|
8237
|
+
document,
|
|
8238
|
+
layout: this.getRichContentLayoutItemLayout(item),
|
|
8239
|
+
rootClassName: item.kind === 'richContent' ? item.rootClassName ?? null : null,
|
|
8240
|
+
});
|
|
8241
|
+
}
|
|
8242
|
+
flushFieldBatch();
|
|
8243
|
+
return renderItems;
|
|
8244
|
+
}
|
|
7896
8245
|
getColumnFields(column) {
|
|
7897
|
-
const
|
|
8246
|
+
const fieldNames = getFormColumnFieldNames(column);
|
|
8247
|
+
const key = column.id || JSON.stringify(fieldNames);
|
|
7898
8248
|
const signature = this.getColumnFieldsSignature(column);
|
|
7899
8249
|
const cached = this.columnFieldsCache.get(key);
|
|
7900
8250
|
if (cached?.signature === signature) {
|
|
@@ -7903,7 +8253,7 @@ class PraxisDynamicForm {
|
|
|
7903
8253
|
const fieldMetadata = this.config.fieldMetadata || [];
|
|
7904
8254
|
const byName = new Map(fieldMetadata.map((f) => [f.name, f]));
|
|
7905
8255
|
const ordered = [];
|
|
7906
|
-
for (const name of
|
|
8256
|
+
for (const name of fieldNames) {
|
|
7907
8257
|
if (this.fieldVisibility[name] === false)
|
|
7908
8258
|
continue;
|
|
7909
8259
|
const meta = byName.get(name);
|
|
@@ -7929,8 +8279,16 @@ class PraxisDynamicForm {
|
|
|
7929
8279
|
this.columnFieldsCache.set(key, { signature, value: ordered });
|
|
7930
8280
|
return ordered;
|
|
7931
8281
|
}
|
|
8282
|
+
getRichContentLayoutItemDocument(item) {
|
|
8283
|
+
return item.kind === 'richContent' && item.document?.kind === 'praxis.rich-content'
|
|
8284
|
+
? item.document
|
|
8285
|
+
: null;
|
|
8286
|
+
}
|
|
8287
|
+
getRichContentLayoutItemLayout(item) {
|
|
8288
|
+
return item.kind === 'richContent' ? item.layout ?? 'block' : 'block';
|
|
8289
|
+
}
|
|
7932
8290
|
getColumnFieldsSignature(column) {
|
|
7933
|
-
return column
|
|
8291
|
+
return getFormColumnFieldNames(column)
|
|
7934
8292
|
.map((name) => {
|
|
7935
8293
|
const visible = this.fieldVisibility[name] === false ? '0' : '1';
|
|
7936
8294
|
const overrides = this.fieldRuleProps[name];
|
|
@@ -7939,6 +8297,17 @@ class PraxisDynamicForm {
|
|
|
7939
8297
|
})
|
|
7940
8298
|
.join('|');
|
|
7941
8299
|
}
|
|
8300
|
+
getColumnItemsSignature(column) {
|
|
8301
|
+
return normalizeFormLayoutItems(column)
|
|
8302
|
+
.map((item) => {
|
|
8303
|
+
if (item.kind === 'field') {
|
|
8304
|
+
return `field:${item.id}:${item.fieldName}`;
|
|
8305
|
+
}
|
|
8306
|
+
const nodeCount = item.document?.nodes?.length ?? 0;
|
|
8307
|
+
return `richContent:${item.id}:${item.layout ?? 'block'}:${nodeCount}`;
|
|
8308
|
+
})
|
|
8309
|
+
.join('|');
|
|
8310
|
+
}
|
|
7942
8311
|
getColumnRuleProps(column) {
|
|
7943
8312
|
if (!column || !column.id)
|
|
7944
8313
|
return {};
|
|
@@ -8138,8 +8507,12 @@ class PraxisDynamicForm {
|
|
|
8138
8507
|
return !this.isResponsiveHiddenActive(props.hidden);
|
|
8139
8508
|
}
|
|
8140
8509
|
}
|
|
8510
|
+
const items = this.getColumnItems(column);
|
|
8511
|
+
if (items.some((item) => item.kind === 'richContent')) {
|
|
8512
|
+
return true;
|
|
8513
|
+
}
|
|
8141
8514
|
// A column is visible if at least one of its fields is visible.
|
|
8142
|
-
return
|
|
8515
|
+
return getFormLayoutFieldNames(items).some((fieldName) => this.fieldVisibility[fieldName]);
|
|
8143
8516
|
}
|
|
8144
8517
|
isResponsiveHiddenActive(hidden) {
|
|
8145
8518
|
if (!hidden || typeof hidden !== 'object' || Array.isArray(hidden)) {
|
|
@@ -12282,7 +12655,7 @@ class PraxisDynamicForm {
|
|
|
12282
12655
|
}
|
|
12283
12656
|
}
|
|
12284
12657
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDynamicForm, deps: [{ token: i1$2.GenericCrudService }, { token: i2.HttpClient }, { token: i1$3.FormBuilder }, { token: i0.ChangeDetectorRef }, { token: FormLayoutService }, { token: FormContextService }, { token: FormRulesService }, { token: i7.SettingsPanelService }, { token: i2$1.MatDialog }, { token: ASYNC_CONFIG_STORAGE }, { token: CONNECTION_STORAGE }, { token: i1$2.DynamicFormService }, { token: i9$1.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: i0.NgZone }, { token: API_URL }, { token: PRAXIS_LOADING_RENDERER, optional: true }, { token: i12.Router, optional: true }, { token: i12.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 });
|
|
12285
|
-
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", initialValue: "initialValue", editorialContext: "editorialContext", mode: "mode", config: "config", actions: "actions", schemaSource: "schemaSource", schemaUrl: "schemaUrl", submitUrl: "submitUrl", submitMethod: "submitMethod", responseSchemaUrl: "responseSchemaUrl", apiEndpointKey: "apiEndpointKey", apiUrlEntry: "apiUrlEntry", 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" }, providers: [providePraxisI18nConfig(PRAXIS_DYNAMIC_FORM_I18N_CONFIG)], 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\" role=\"status\" aria-live=\"polite\" aria-label=\"Carregando formul\u00E1rio\">\n <div class=\"form-loading-header\">\n <mat-progress-spinner diameter=\"32\"></mat-progress-spinner>\n <div class=\"form-loading-copy\">\n <p class=\"form-loading-title\">Carregando formul\u00E1rio...</p>\n <p class=\"form-loading-subtitle\">Preparando campos e op\u00E7\u00F5es do cadastro.</p>\n </div>\n </div>\n <div class=\"form-loading-skeleton\" aria-hidden=\"true\">\n <span class=\"form-loading-line form-loading-line-title\"></span>\n <span class=\"form-loading-line\"></span>\n <span class=\"form-loading-line form-loading-line-short\"></span>\n <span class=\"form-loading-field\"></span>\n <span class=\"form-loading-field form-loading-field-wide\"></span>\n </div>\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?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before\" data-editorial-placement=\"before\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'top' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"top\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\" [actionOverrides]=\"actionRuleProps\"\n [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\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 [enableExternalControlBinding]=\"true\"\n [readonlyMode]=\"readonlyModeGlobal === null ? null : readonlyModeGlobal\"\n [disabledMode]=\"effectiveDisabledMode\"\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?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && last && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"effectiveActions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [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?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'afterSections' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"afterSections\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @if (formBlocksAfter?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-after\" data-editorial-placement=\"after\">\n <praxis-rich-content\n [document]=\"formBlocksAfterDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\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:var(--praxis-layer-authoring-hover, 300)}.canvas-mode-enabled .canvas-element.selected{z-index:var(--praxis-layer-authoring-selected, 320)}.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:var(--praxis-layer-authoring-insert, 280)}.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:stretch;justify-content:center;padding:1.25rem;text-align:left;color:var(--md-sys-color-on-surface);gap:1rem;min-height:220px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,var(--md-sys-color-outline-variant) 86%);border-radius:8px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent),transparent 42%),color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,var(--md-sys-color-surface) 22%);box-shadow:0 12px 28px #0f172a14}.form-loading-header{display:flex;align-items:center;gap:.85rem}.form-loading-copy{min-width:0}.form-loading p{margin:0}.form-loading-title{font-weight:700;color:var(--md-sys-color-on-surface)}.form-loading-subtitle{margin-top:.2rem;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.form-loading-skeleton{display:grid;gap:.7rem}.form-loading-line,.form-loading-field{display:block;overflow:hidden;position:relative;border-radius:6px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 74%,var(--md-sys-color-primary) 6%)}.form-loading-line:after,.form-loading-field:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 16%,white 18%),transparent);animation:form-loading-shimmer 1.4s ease-in-out infinite}.form-loading-line{height:12px}.form-loading-line-title{width:min(42%,240px)}.form-loading-line-short{width:min(64%,360px)}.form-loading-field{height:44px}.form-loading-field-wide{height:72px}@keyframes form-loading-shimmer{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.form-loading-line:after,.form-loading-field:after{animation:none;transform:none;opacity:.28}}.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: "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: i16.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: i18.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", "invalidRequiredFieldLabels", "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"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"] }] });
|
|
12658
|
+
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", initialValue: "initialValue", editorialContext: "editorialContext", mode: "mode", config: "config", actions: "actions", schemaSource: "schemaSource", schemaUrl: "schemaUrl", submitUrl: "submitUrl", submitMethod: "submitMethod", responseSchemaUrl: "responseSchemaUrl", apiEndpointKey: "apiEndpointKey", apiUrlEntry: "apiUrlEntry", 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" }, providers: [providePraxisI18nConfig(PRAXIS_DYNAMIC_FORM_I18N_CONFIG)], 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\" role=\"status\" aria-live=\"polite\" aria-label=\"Carregando formul\u00E1rio\">\n <div class=\"form-loading-header\">\n <mat-progress-spinner diameter=\"32\"></mat-progress-spinner>\n <div class=\"form-loading-copy\">\n <p class=\"form-loading-title\">Carregando formul\u00E1rio...</p>\n <p class=\"form-loading-subtitle\">Preparando campos e op\u00E7\u00F5es do cadastro.</p>\n </div>\n </div>\n <div class=\"form-loading-skeleton\" aria-hidden=\"true\">\n <span class=\"form-loading-line form-loading-line-title\"></span>\n <span class=\"form-loading-line\"></span>\n <span class=\"form-loading-line form-loading-line-short\"></span>\n <span class=\"form-loading-field\"></span>\n <span class=\"form-loading-field form-loading-field-wide\"></span>\n </div>\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?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before\" data-editorial-placement=\"before\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'top' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"top\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\" [actionOverrides]=\"actionRuleProps\"\n [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\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 @for (renderItem of getColumnRenderItems(column); track renderItem.id) {\n @if (renderItem.kind === 'fields') {\n <ng-container dynamicFieldLoader [fields]=\"renderItem.fields\" [formGroup]=\"form\"\n [enableExternalControlBinding]=\"true\"\n [readonlyMode]=\"readonlyModeGlobal === null ? null : readonlyModeGlobal\"\n [disabledMode]=\"effectiveDisabledMode\"\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 } @else {\n <praxis-rich-content\n class=\"form-layout-rich-content\"\n [document]=\"renderItem.document\"\n [layout]=\"renderItem.layout\"\n [rootClassName]=\"renderItem.rootClassName || ''\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n }\n }\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?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && last && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"effectiveActions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [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?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'afterSections' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"afterSections\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @if (formBlocksAfter?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-after\" data-editorial-placement=\"after\">\n <praxis-rich-content\n [document]=\"formBlocksAfterDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\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:var(--praxis-layer-authoring-hover, 300)}.canvas-mode-enabled .canvas-element.selected{z-index:var(--praxis-layer-authoring-selected, 320)}.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:var(--praxis-layer-authoring-insert, 280)}.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:stretch;justify-content:center;padding:1.25rem;text-align:left;color:var(--md-sys-color-on-surface);gap:1rem;min-height:220px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,var(--md-sys-color-outline-variant) 86%);border-radius:8px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent),transparent 42%),color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,var(--md-sys-color-surface) 22%);box-shadow:0 12px 28px #0f172a14}.form-loading-header{display:flex;align-items:center;gap:.85rem}.form-loading-copy{min-width:0}.form-loading p{margin:0}.form-loading-title{font-weight:700;color:var(--md-sys-color-on-surface)}.form-loading-subtitle{margin-top:.2rem;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.form-loading-skeleton{display:grid;gap:.7rem}.form-loading-line,.form-loading-field{display:block;overflow:hidden;position:relative;border-radius:6px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 74%,var(--md-sys-color-primary) 6%)}.form-loading-line:after,.form-loading-field:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 16%,white 18%),transparent);animation:form-loading-shimmer 1.4s ease-in-out infinite}.form-loading-line{height:12px}.form-loading-line-title{width:min(42%,240px)}.form-loading-line-short{width:min(64%,360px)}.form-loading-field{height:44px}.form-loading-field-wide{height:72px}@keyframes form-loading-shimmer{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.form-loading-line:after,.form-loading-field:after{animation:none;transform:none;opacity:.28}}.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: "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: i16.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: i18.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", "invalidRequiredFieldLabels", "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"] }, { kind: "component", type: PraxisRichContent, selector: "praxis-rich-content", inputs: ["document", "nodes", "context", "hostCapabilities", "layout", "rootClassName"] }] });
|
|
12286
12659
|
}
|
|
12287
12660
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: PraxisDynamicForm, decorators: [{
|
|
12288
12661
|
type: Component,
|
|
@@ -12303,7 +12676,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
12303
12676
|
EmptyStateCardComponent,
|
|
12304
12677
|
PraxisAiAssistantComponent,
|
|
12305
12678
|
PraxisRichContent,
|
|
12306
|
-
], template: "@if (isLoading) {\n<!-- Loading State -->\n<div class=\"form-loading\" role=\"status\" aria-live=\"polite\" aria-label=\"Carregando formul\u00E1rio\">\n <div class=\"form-loading-header\">\n <mat-progress-spinner diameter=\"32\"></mat-progress-spinner>\n <div class=\"form-loading-copy\">\n <p class=\"form-loading-title\">Carregando formul\u00E1rio...</p>\n <p class=\"form-loading-subtitle\">Preparando campos e op\u00E7\u00F5es do cadastro.</p>\n </div>\n </div>\n <div class=\"form-loading-skeleton\" aria-hidden=\"true\">\n <span class=\"form-loading-line form-loading-line-title\"></span>\n <span class=\"form-loading-line\"></span>\n <span class=\"form-loading-line form-loading-line-short\"></span>\n <span class=\"form-loading-field\"></span>\n <span class=\"form-loading-field form-loading-field-wide\"></span>\n </div>\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?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before\" data-editorial-placement=\"before\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'top' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"top\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\" [actionOverrides]=\"actionRuleProps\"\n [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\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 [enableExternalControlBinding]=\"true\"\n [readonlyMode]=\"readonlyModeGlobal === null ? null : readonlyModeGlobal\"\n [disabledMode]=\"effectiveDisabledMode\"\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?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && last && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"effectiveActions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [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?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'afterSections' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"afterSections\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @if (formBlocksAfter?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-after\" data-editorial-placement=\"after\">\n <praxis-rich-content\n [document]=\"formBlocksAfterDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\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:var(--praxis-layer-authoring-hover, 300)}.canvas-mode-enabled .canvas-element.selected{z-index:var(--praxis-layer-authoring-selected, 320)}.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:var(--praxis-layer-authoring-insert, 280)}.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:stretch;justify-content:center;padding:1.25rem;text-align:left;color:var(--md-sys-color-on-surface);gap:1rem;min-height:220px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,var(--md-sys-color-outline-variant) 86%);border-radius:8px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent),transparent 42%),color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,var(--md-sys-color-surface) 22%);box-shadow:0 12px 28px #0f172a14}.form-loading-header{display:flex;align-items:center;gap:.85rem}.form-loading-copy{min-width:0}.form-loading p{margin:0}.form-loading-title{font-weight:700;color:var(--md-sys-color-on-surface)}.form-loading-subtitle{margin-top:.2rem;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.form-loading-skeleton{display:grid;gap:.7rem}.form-loading-line,.form-loading-field{display:block;overflow:hidden;position:relative;border-radius:6px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 74%,var(--md-sys-color-primary) 6%)}.form-loading-line:after,.form-loading-field:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 16%,white 18%),transparent);animation:form-loading-shimmer 1.4s ease-in-out infinite}.form-loading-line{height:12px}.form-loading-line-title{width:min(42%,240px)}.form-loading-line-short{width:min(64%,360px)}.form-loading-field{height:44px}.form-loading-field-wide{height:72px}@keyframes form-loading-shimmer{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.form-loading-line:after,.form-loading-field:after{animation:none;transform:none;opacity:.28}}.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"] }]
|
|
12679
|
+
], template: "@if (isLoading) {\n<!-- Loading State -->\n<div class=\"form-loading\" role=\"status\" aria-live=\"polite\" aria-label=\"Carregando formul\u00E1rio\">\n <div class=\"form-loading-header\">\n <mat-progress-spinner diameter=\"32\"></mat-progress-spinner>\n <div class=\"form-loading-copy\">\n <p class=\"form-loading-title\">Carregando formul\u00E1rio...</p>\n <p class=\"form-loading-subtitle\">Preparando campos e op\u00E7\u00F5es do cadastro.</p>\n </div>\n </div>\n <div class=\"form-loading-skeleton\" aria-hidden=\"true\">\n <span class=\"form-loading-line form-loading-line-title\"></span>\n <span class=\"form-loading-line\"></span>\n <span class=\"form-loading-line form-loading-line-short\"></span>\n <span class=\"form-loading-field\"></span>\n <span class=\"form-loading-field form-loading-field-wide\"></span>\n </div>\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?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before\" data-editorial-placement=\"before\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'top' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"top\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\" [actionOverrides]=\"actionRuleProps\"\n [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\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 @for (renderItem of getColumnRenderItems(column); track renderItem.id) {\n @if (renderItem.kind === 'fields') {\n <ng-container dynamicFieldLoader [fields]=\"renderItem.fields\" [formGroup]=\"form\"\n [enableExternalControlBinding]=\"true\"\n [readonlyMode]=\"readonlyModeGlobal === null ? null : readonlyModeGlobal\"\n [disabledMode]=\"effectiveDisabledMode\"\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 } @else {\n <praxis-rich-content\n class=\"form-layout-rich-content\"\n [document]=\"renderItem.document\"\n [layout]=\"renderItem.layout\"\n [rootClassName]=\"renderItem.rootClassName || ''\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n }\n }\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?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n </section>\n }\n @if (actionPlacement === 'insideLastSection' && last && !(effectivePresentation\n || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"insideLastSection\" [actions]=\"effectiveActions\"\n [isSubmitting]=\"submitting\" [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [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?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-before-actions\" data-editorial-placement=\"beforeActions\">\n <praxis-rich-content\n [document]=\"formBlocksBeforeActionsDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\n </section>\n }\n\n @if (actionPlacement === 'afterSections' && !(effectivePresentation || effectiveReadonly)) {\n <praxis-form-actions data-actions-placement=\"afterSections\" [actions]=\"effectiveActions\" [isSubmitting]=\"submitting\"\n [formIsValid]=\"effectiveFormIsValid\" [submitError]=\"submitError\" [formId]=\"formId\"\n [actionOverrides]=\"actionRuleProps\" [invalidRequiredFieldLabels]=\"invalidRequiredFieldLabels\"\n [editorialVisualContext]=\"hasEditorialVisualContext()\"\n (action)=\"onFormAction($event)\"></praxis-form-actions>\n }\n\n @if (formBlocksAfter?.nodes?.length) {\n <section class=\"form-editorial-blocks form-editorial-blocks-after\" data-editorial-placement=\"after\">\n <praxis-rich-content\n [document]=\"formBlocksAfterDocument\"\n [context]=\"getEditorialRichContentContext()\"\n ></praxis-rich-content>\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:var(--praxis-layer-authoring-hover, 300)}.canvas-mode-enabled .canvas-element.selected{z-index:var(--praxis-layer-authoring-selected, 320)}.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:var(--praxis-layer-authoring-insert, 280)}.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:stretch;justify-content:center;padding:1.25rem;text-align:left;color:var(--md-sys-color-on-surface);gap:1rem;min-height:220px;border:1px solid color-mix(in srgb,var(--md-sys-color-primary) 14%,var(--md-sys-color-outline-variant) 86%);border-radius:8px;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-primary) 8%,transparent),transparent 42%),color-mix(in srgb,var(--md-sys-color-surface-container-low) 78%,var(--md-sys-color-surface) 22%);box-shadow:0 12px 28px #0f172a14}.form-loading-header{display:flex;align-items:center;gap:.85rem}.form-loading-copy{min-width:0}.form-loading p{margin:0}.form-loading-title{font-weight:700;color:var(--md-sys-color-on-surface)}.form-loading-subtitle{margin-top:.2rem;font-size:.875rem;color:var(--md-sys-color-on-surface-variant)}.form-loading-skeleton{display:grid;gap:.7rem}.form-loading-line,.form-loading-field{display:block;overflow:hidden;position:relative;border-radius:6px;background:color-mix(in srgb,var(--md-sys-color-surface-container-high) 74%,var(--md-sys-color-primary) 6%)}.form-loading-line:after,.form-loading-field:after{content:\"\";position:absolute;inset:0;transform:translate(-100%);background:linear-gradient(90deg,transparent,color-mix(in srgb,var(--md-sys-color-primary) 16%,white 18%),transparent);animation:form-loading-shimmer 1.4s ease-in-out infinite}.form-loading-line{height:12px}.form-loading-line-title{width:min(42%,240px)}.form-loading-line-short{width:min(64%,360px)}.form-loading-field{height:44px}.form-loading-field-wide{height:72px}@keyframes form-loading-shimmer{to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.form-loading-line:after,.form-loading-field:after{animation:none;transform:none;opacity:.28}}.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"] }]
|
|
12307
12680
|
}], ctorParameters: () => [{ type: i1$2.GenericCrudService }, { type: i2.HttpClient }, { type: i1$3.FormBuilder }, { type: i0.ChangeDetectorRef }, { type: FormLayoutService }, { type: FormContextService }, { type: FormRulesService }, { type: i7.SettingsPanelService }, { type: i2$1.MatDialog }, { type: undefined, decorators: [{
|
|
12308
12681
|
type: Inject,
|
|
12309
12682
|
args: [ASYNC_CONFIG_STORAGE]
|
|
@@ -13110,9 +13483,123 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
13110
13483
|
type: Input
|
|
13111
13484
|
}] } });
|
|
13112
13485
|
|
|
13486
|
+
const LAYOUT_EDITOR_I18N_NAMESPACE = 'praxisDynamicFormLayoutEditor';
|
|
13487
|
+
const LAYOUT_EDITOR_DEFAULT_COPY = {
|
|
13488
|
+
'apiFields.heading': 'Campos da API',
|
|
13489
|
+
'apiFields.hint': 'Campos do fieldMetadata ainda não alocados no layout.',
|
|
13490
|
+
'apiFields.addAction': 'Adicionar campo da API',
|
|
13491
|
+
'apiFields.empty': 'Nenhum campo da API disponível',
|
|
13492
|
+
'apiFields.addTooltip': 'Adicionar campo existente da API nesta coluna',
|
|
13493
|
+
'visualBlock.label': 'Bloco visual',
|
|
13494
|
+
'visualBlock.addAction': 'Adicionar bloco visual',
|
|
13495
|
+
'visualBlock.addTooltip': 'Adicionar texto ou bloco visual nesta coluna',
|
|
13496
|
+
'visualBlock.editTitle': 'Editar bloco visual',
|
|
13497
|
+
'visualBlock.editAction': 'Editar bloco visual',
|
|
13498
|
+
'visualBlock.removeAction': 'Remover bloco visual',
|
|
13499
|
+
'visualBlock.moveUp': 'Mover bloco visual para cima',
|
|
13500
|
+
'visualBlock.moveDown': 'Mover bloco visual para baixo',
|
|
13501
|
+
'visualBlock.movePreviousColumn': 'Mover bloco visual para a coluna anterior',
|
|
13502
|
+
'visualBlock.moveNextColumn': 'Mover bloco visual para a próxima coluna',
|
|
13503
|
+
'visualBlock.preset.text': 'Texto',
|
|
13504
|
+
'visualBlock.preset.notice': 'Aviso',
|
|
13505
|
+
'visualBlock.preset.divider': 'Separador',
|
|
13506
|
+
'visualBlock.preset.infoCard': 'Card informativo',
|
|
13507
|
+
'visualBlock.preset.text.default': 'Novo texto',
|
|
13508
|
+
'visualBlock.preset.notice.default': 'Revise as informações antes de continuar.',
|
|
13509
|
+
'visualBlock.preset.divider.default': 'Separador',
|
|
13510
|
+
'visualBlock.preset.infoCard.title': 'Informação importante',
|
|
13511
|
+
'visualBlock.preset.infoCard.body': 'Use este espaço para orientar o preenchimento.',
|
|
13512
|
+
};
|
|
13513
|
+
const LAYOUT_EDITOR_I18N_CONFIG = {
|
|
13514
|
+
namespaces: {
|
|
13515
|
+
[LAYOUT_EDITOR_I18N_NAMESPACE]: {
|
|
13516
|
+
'pt-BR': LAYOUT_EDITOR_DEFAULT_COPY,
|
|
13517
|
+
'en-US': {
|
|
13518
|
+
'apiFields.heading': 'API fields',
|
|
13519
|
+
'apiFields.hint': 'fieldMetadata fields not yet allocated in the layout.',
|
|
13520
|
+
'apiFields.addAction': 'Add API field',
|
|
13521
|
+
'apiFields.empty': 'No API field available',
|
|
13522
|
+
'apiFields.addTooltip': 'Add an existing API field to this column',
|
|
13523
|
+
'visualBlock.label': 'Visual block',
|
|
13524
|
+
'visualBlock.addAction': 'Add visual block',
|
|
13525
|
+
'visualBlock.addTooltip': 'Add text or a visual block to this column',
|
|
13526
|
+
'visualBlock.editTitle': 'Edit visual block',
|
|
13527
|
+
'visualBlock.editAction': 'Edit visual block',
|
|
13528
|
+
'visualBlock.removeAction': 'Remove visual block',
|
|
13529
|
+
'visualBlock.moveUp': 'Move visual block up',
|
|
13530
|
+
'visualBlock.moveDown': 'Move visual block down',
|
|
13531
|
+
'visualBlock.movePreviousColumn': 'Move visual block to the previous column',
|
|
13532
|
+
'visualBlock.moveNextColumn': 'Move visual block to the next column',
|
|
13533
|
+
'visualBlock.preset.text': 'Text',
|
|
13534
|
+
'visualBlock.preset.notice': 'Notice',
|
|
13535
|
+
'visualBlock.preset.divider': 'Divider',
|
|
13536
|
+
'visualBlock.preset.infoCard': 'Info card',
|
|
13537
|
+
'visualBlock.preset.text.default': 'New text',
|
|
13538
|
+
'visualBlock.preset.notice.default': 'Review the information before continuing.',
|
|
13539
|
+
'visualBlock.preset.divider.default': 'Divider',
|
|
13540
|
+
'visualBlock.preset.infoCard.title': 'Important information',
|
|
13541
|
+
'visualBlock.preset.infoCard.body': 'Use this space to guide completion.',
|
|
13542
|
+
},
|
|
13543
|
+
},
|
|
13544
|
+
},
|
|
13545
|
+
};
|
|
13546
|
+
|
|
13547
|
+
const VISUAL_BLOCK_PRESETS = [
|
|
13548
|
+
{ id: 'text', labelKey: 'visualBlock.preset.text', icon: 'short_text' },
|
|
13549
|
+
{ id: 'notice', labelKey: 'visualBlock.preset.notice', icon: 'error_outline' },
|
|
13550
|
+
{ id: 'divider', labelKey: 'visualBlock.preset.divider', icon: 'horizontal_rule' },
|
|
13551
|
+
{ id: 'infoCard', labelKey: 'visualBlock.preset.infoCard', icon: 'info' },
|
|
13552
|
+
];
|
|
13553
|
+
function createVisualBlockItemFromPreset(presetId, id, copy) {
|
|
13554
|
+
return {
|
|
13555
|
+
kind: 'richContent',
|
|
13556
|
+
id,
|
|
13557
|
+
document: createVisualBlockDocument(presetId, copy),
|
|
13558
|
+
layout: 'block',
|
|
13559
|
+
};
|
|
13560
|
+
}
|
|
13561
|
+
function createVisualBlockDocument(presetId, copy) {
|
|
13562
|
+
return {
|
|
13563
|
+
kind: 'praxis.rich-content',
|
|
13564
|
+
version: '1.0.0',
|
|
13565
|
+
nodes: [createPresetNode(presetId, copy)],
|
|
13566
|
+
};
|
|
13567
|
+
}
|
|
13568
|
+
function createPresetNode(presetId, copy) {
|
|
13569
|
+
switch (presetId) {
|
|
13570
|
+
case 'notice':
|
|
13571
|
+
return {
|
|
13572
|
+
type: 'compose',
|
|
13573
|
+
direction: 'row',
|
|
13574
|
+
gap: 'sm',
|
|
13575
|
+
className: 'praxis-rich-content-notice',
|
|
13576
|
+
items: [
|
|
13577
|
+
{ type: 'icon', icon: 'error_outline', ariaLabel: copy.notice },
|
|
13578
|
+
{ type: 'text', text: copy.notice },
|
|
13579
|
+
],
|
|
13580
|
+
};
|
|
13581
|
+
case 'divider':
|
|
13582
|
+
return {
|
|
13583
|
+
type: 'text',
|
|
13584
|
+
text: copy.divider,
|
|
13585
|
+
className: 'praxis-rich-content-divider',
|
|
13586
|
+
};
|
|
13587
|
+
case 'infoCard':
|
|
13588
|
+
return {
|
|
13589
|
+
type: 'card',
|
|
13590
|
+
title: copy.infoCardTitle,
|
|
13591
|
+
content: [{ type: 'text', text: copy.infoCardBody }],
|
|
13592
|
+
};
|
|
13593
|
+
case 'text':
|
|
13594
|
+
default:
|
|
13595
|
+
return { type: 'text', text: copy.text };
|
|
13596
|
+
}
|
|
13597
|
+
}
|
|
13598
|
+
|
|
13113
13599
|
class RowConfiguratorComponent {
|
|
13114
13600
|
row;
|
|
13115
13601
|
fieldMetadata = [];
|
|
13602
|
+
availableFields = [];
|
|
13116
13603
|
sectionIndex;
|
|
13117
13604
|
rowIndex;
|
|
13118
13605
|
isLastRow = false;
|
|
@@ -13125,9 +13612,17 @@ class RowConfiguratorComponent {
|
|
|
13125
13612
|
remove = new EventEmitter();
|
|
13126
13613
|
applyRowGapAll = new EventEmitter();
|
|
13127
13614
|
fieldDrop = new EventEmitter();
|
|
13615
|
+
addVisualBlock = new EventEmitter();
|
|
13616
|
+
addApiField = new EventEmitter();
|
|
13617
|
+
editVisualBlock = new EventEmitter();
|
|
13618
|
+
moveVisualBlock = new EventEmitter();
|
|
13619
|
+
moveVisualBlockToColumn = new EventEmitter();
|
|
13620
|
+
removeVisualBlock = new EventEmitter();
|
|
13128
13621
|
select = new EventEmitter();
|
|
13129
13622
|
// Debounced dropzone highlight
|
|
13130
13623
|
activeDropIndex = null;
|
|
13624
|
+
visualBlockPresets = VISUAL_BLOCK_PRESETS;
|
|
13625
|
+
i18n = inject(PraxisI18nService);
|
|
13131
13626
|
hoverTimer = null;
|
|
13132
13627
|
breakpoints = ['xs', 'sm', 'md', 'lg', 'xl'];
|
|
13133
13628
|
previewBreakpoint = 'md';
|
|
@@ -13174,6 +13669,107 @@ class RowConfiguratorComponent {
|
|
|
13174
13669
|
controlType: FieldControlType.INPUT,
|
|
13175
13670
|
});
|
|
13176
13671
|
}
|
|
13672
|
+
getColumnLayoutItems(column) {
|
|
13673
|
+
return normalizeFormLayoutItems(column);
|
|
13674
|
+
}
|
|
13675
|
+
hasColumnContent(column) {
|
|
13676
|
+
return this.getColumnLayoutItems(column).length > 0;
|
|
13677
|
+
}
|
|
13678
|
+
getVisualBlockLabel(item) {
|
|
13679
|
+
if (item.kind !== 'richContent')
|
|
13680
|
+
return '';
|
|
13681
|
+
return this.findRichContentLabel(item.document?.nodes) || this.t('visualBlock.label');
|
|
13682
|
+
}
|
|
13683
|
+
findRichContentLabel(nodes) {
|
|
13684
|
+
if (!Array.isArray(nodes))
|
|
13685
|
+
return null;
|
|
13686
|
+
for (const node of nodes) {
|
|
13687
|
+
const label = this.findRichNodeLabel(node);
|
|
13688
|
+
if (label)
|
|
13689
|
+
return label;
|
|
13690
|
+
}
|
|
13691
|
+
return null;
|
|
13692
|
+
}
|
|
13693
|
+
findRichNodeLabel(node) {
|
|
13694
|
+
if (!node || typeof node !== 'object')
|
|
13695
|
+
return null;
|
|
13696
|
+
const richNode = node;
|
|
13697
|
+
for (const value of [richNode.text, richNode.label, richNode.title, richNode.subtitle]) {
|
|
13698
|
+
if (typeof value === 'string' && value.trim())
|
|
13699
|
+
return value.trim();
|
|
13700
|
+
}
|
|
13701
|
+
for (const nested of [richNode.items, richNode.content, richNode.trailing]) {
|
|
13702
|
+
const label = this.findRichContentLabel(nested);
|
|
13703
|
+
if (label)
|
|
13704
|
+
return label;
|
|
13705
|
+
}
|
|
13706
|
+
return this.findRichNodeLabel(richNode.avatar) || this.findRichNodeLabel(richNode.meta);
|
|
13707
|
+
}
|
|
13708
|
+
t(key, params) {
|
|
13709
|
+
return this.i18n.t(key, params, LAYOUT_EDITOR_DEFAULT_COPY[key] ?? key, LAYOUT_EDITOR_I18N_NAMESPACE);
|
|
13710
|
+
}
|
|
13711
|
+
getFieldLabel(field) {
|
|
13712
|
+
return field.label || field.name;
|
|
13713
|
+
}
|
|
13714
|
+
selectVisualBlock(columnIndex, item, event) {
|
|
13715
|
+
event.stopPropagation();
|
|
13716
|
+
if (item.kind !== 'richContent')
|
|
13717
|
+
return;
|
|
13718
|
+
this.select.emit({
|
|
13719
|
+
type: 'visualBlock',
|
|
13720
|
+
sectionIndex: this.sectionIndex,
|
|
13721
|
+
rowIndex: this.rowIndex,
|
|
13722
|
+
columnIndex,
|
|
13723
|
+
itemId: item.id,
|
|
13724
|
+
});
|
|
13725
|
+
}
|
|
13726
|
+
openVisualBlockEditor(columnIndex, item, event) {
|
|
13727
|
+
this.selectVisualBlock(columnIndex, item, event);
|
|
13728
|
+
if (item.kind !== 'richContent')
|
|
13729
|
+
return;
|
|
13730
|
+
this.editVisualBlock.emit({
|
|
13731
|
+
rowIndex: this.rowIndex,
|
|
13732
|
+
columnIndex,
|
|
13733
|
+
itemId: item.id,
|
|
13734
|
+
});
|
|
13735
|
+
}
|
|
13736
|
+
moveVisualBlockItem(columnIndex, item, direction, event) {
|
|
13737
|
+
this.selectVisualBlock(columnIndex, item, event);
|
|
13738
|
+
if (item.kind !== 'richContent')
|
|
13739
|
+
return;
|
|
13740
|
+
this.moveVisualBlock.emit({
|
|
13741
|
+
rowIndex: this.rowIndex,
|
|
13742
|
+
columnIndex,
|
|
13743
|
+
itemId: item.id,
|
|
13744
|
+
direction,
|
|
13745
|
+
});
|
|
13746
|
+
}
|
|
13747
|
+
canMoveVisualBlockToColumn(columnIndex, direction) {
|
|
13748
|
+
const targetColumnIndex = columnIndex + direction;
|
|
13749
|
+
return targetColumnIndex >= 0 && targetColumnIndex < (this.row?.columns?.length ?? 0);
|
|
13750
|
+
}
|
|
13751
|
+
moveVisualBlockToAdjacentColumn(columnIndex, item, direction, event) {
|
|
13752
|
+
this.selectVisualBlock(columnIndex, item, event);
|
|
13753
|
+
if (item.kind !== 'richContent' || !this.canMoveVisualBlockToColumn(columnIndex, direction)) {
|
|
13754
|
+
return;
|
|
13755
|
+
}
|
|
13756
|
+
this.moveVisualBlockToColumn.emit({
|
|
13757
|
+
rowIndex: this.rowIndex,
|
|
13758
|
+
columnIndex,
|
|
13759
|
+
targetColumnIndex: columnIndex + direction,
|
|
13760
|
+
itemId: item.id,
|
|
13761
|
+
});
|
|
13762
|
+
}
|
|
13763
|
+
removeVisualBlockItem(columnIndex, item, event) {
|
|
13764
|
+
this.selectVisualBlock(columnIndex, item, event);
|
|
13765
|
+
if (item.kind !== 'richContent')
|
|
13766
|
+
return;
|
|
13767
|
+
this.removeVisualBlock.emit({
|
|
13768
|
+
rowIndex: this.rowIndex,
|
|
13769
|
+
columnIndex,
|
|
13770
|
+
itemId: item.id,
|
|
13771
|
+
});
|
|
13772
|
+
}
|
|
13177
13773
|
drop(event) {
|
|
13178
13774
|
this.fieldDrop.emit(event);
|
|
13179
13775
|
}
|
|
@@ -13293,13 +13889,30 @@ class RowConfiguratorComponent {
|
|
|
13293
13889
|
this.rowChange.emit(updated);
|
|
13294
13890
|
}
|
|
13295
13891
|
clearColumn(index) {
|
|
13296
|
-
if (!confirm('Tem certeza que deseja remover
|
|
13892
|
+
if (!confirm('Tem certeza que deseja remover todo o conteudo desta coluna?'))
|
|
13297
13893
|
return;
|
|
13298
13894
|
const updated = produce(this.row, (draft) => {
|
|
13299
13895
|
draft.columns[index].fields = [];
|
|
13896
|
+
draft.columns[index].items = [];
|
|
13300
13897
|
});
|
|
13301
13898
|
this.rowChange.emit(updated);
|
|
13302
13899
|
}
|
|
13900
|
+
addVisualBlockToColumn(index, presetId) {
|
|
13901
|
+
this.addVisualBlock.emit({
|
|
13902
|
+
rowIndex: this.rowIndex,
|
|
13903
|
+
columnIndex: index,
|
|
13904
|
+
presetId,
|
|
13905
|
+
});
|
|
13906
|
+
}
|
|
13907
|
+
addApiFieldToColumn(index, fieldName) {
|
|
13908
|
+
if (!fieldName)
|
|
13909
|
+
return;
|
|
13910
|
+
this.addApiField.emit({
|
|
13911
|
+
rowIndex: this.rowIndex,
|
|
13912
|
+
columnIndex: index,
|
|
13913
|
+
fieldName,
|
|
13914
|
+
});
|
|
13915
|
+
}
|
|
13303
13916
|
addFieldToColumn(index) {
|
|
13304
13917
|
if (!this.fieldMetadata || this.fieldMetadata.length === 0)
|
|
13305
13918
|
return;
|
|
@@ -13502,7 +14115,7 @@ class RowConfiguratorComponent {
|
|
|
13502
14115
|
return null;
|
|
13503
14116
|
}
|
|
13504
14117
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: RowConfiguratorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13505
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: RowConfiguratorComponent, isStandalone: true, selector: "praxis-row-configurator", inputs: { row: "row", fieldMetadata: "fieldMetadata", sectionIndex: "sectionIndex", rowIndex: "rowIndex", isLastRow: "isLastRow", selected: "selected", availableFieldsListId: "availableFieldsListId", connectedDropListIds: "connectedDropListIds", gapGlobal: "gapGlobal" }, outputs: { rowChange: "rowChange", remove: "remove", applyRowGapAll: "applyRowGapAll", fieldDrop: "fieldDrop", select: "select" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"row-meta\" *ngIf=\"row\">\n <div class=\"bp-toggle\" role=\"group\" aria-label=\"Breakpoint de visualiza\u00E7\u00E3o\">\n <button\n *ngFor=\"let bp of breakpoints\"\n type=\"button\"\n mat-stroked-button\n class=\"bp-toggle__btn\"\n [class.active]=\"previewBreakpoint === bp\"\n (click)=\"previewBreakpoint = bp\"\n >\n {{ bp }}\n </button>\n </div>\n <div class=\"gap-controls\">\n <div class=\"gap-chip\" *ngIf=\"hasMultipleColumns()\" matTooltip=\"Gap entre colunas (px)\"\n aria-label=\"Gap entre colunas\">\n <span class=\"chip-title\">Colunas</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('gap', -2)\"\n aria-label=\"Reduzir gap de colunas\">\n <mat-icon>remove</mat-icon>\n </button>\n <input class=\"gap-chip__input\" type=\"number\" min=\"0\" [ngModel]=\"row.gap ?? gapGlobal\"\n (ngModelChange)=\"updateRowGap('gap', $event)\" aria-label=\"Valor do gap entre colunas\" />\n <span class=\"gap-chip__suffix\">px</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('gap', 2)\"\n aria-label=\"Aumentar gap de colunas\">\n <mat-icon>add</mat-icon>\n </button>\n </div>\n <div class=\"gap-chip\" matTooltip=\"Gap abaixo da linha (px)\" aria-label=\"Gap abaixo da linha\">\n <span class=\"chip-title\">Linha</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('rowGap', -2)\"\n aria-label=\"Reduzir espa\u00E7o entre campos da linha\" matTooltip=\"Reduz o espa\u00E7o entre campos desta linha\">\n <mat-icon>remove</mat-icon>\n </button>\n <input class=\"gap-chip__input\" type=\"number\" min=\"0\" [ngModel]=\"row.rowGap ?? 0\"\n (ngModelChange)=\"updateRowGap('rowGap', $event)\" aria-label=\"Espa\u00E7o entre campos desta linha\" />\n <span class=\"gap-chip__suffix\">px</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('rowGap', 2)\"\n aria-label=\"Aumentar espa\u00E7o entre campos da linha\" matTooltip=\"Aumenta o espa\u00E7o entre campos desta linha\">\n <mat-icon>add</mat-icon>\n </button>\n <button mat-icon-button class=\"gap-chip__btn\" [matMenuTriggerFor]=\"rowGapMenu\"\n matTooltip=\"Mais op\u00E7\u00F5es para aplicar este espa\u00E7o\" aria-label=\"Mais op\u00E7\u00F5es de aplica\u00E7\u00E3o\">\n <mat-icon>done_all</mat-icon>\n </button>\n <mat-menu #rowGapMenu=\"matMenu\">\n <button mat-menu-item (click)=\"applyRowGapToAll()\">\n <mat-icon>done_all</mat-icon>\n <span>Aplicar em todas as linhas da se\u00E7\u00E3o</span>\n </button>\n <button mat-menu-item (click)=\"clearRowGap()\">\n <mat-icon>undo</mat-icon>\n <span>Voltar ao padr\u00E3o</span>\n </button>\n </mat-menu>\n </div>\n <div class=\"gap-pill\" aria-label=\"Resumo de espa\u00E7amentos\">\n Campos: {{ (row.rowGap ?? 'padr\u00E3o') }}px \u00B7 Colunas: {{ (row.gap ?? gapGlobal) }}px\n </div>\n <div class=\"row-actions-meta\">\n <button mat-icon-button [matMenuTriggerFor]=\"rowMenu\" (click)=\"openRowMenu()\" matTooltip=\"Op\u00E7\u00F5es da linha\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <mat-menu #rowMenu=\"matMenu\" (closed)=\"onMenuClosed()\">\n <ng-container *ngIf=\"menuContext?.type === 'column'; else rowMenuContent\">\n <button mat-menu-item (click)=\"toggleHidden(menuContext!.columnIndex!)\">\n <mat-icon>{{ getHiddenFor(row.columns[menuContext!.columnIndex!]) ? 'visibility' : 'visibility_off'\n }}</mat-icon>\n <span>{{ getHiddenFor(row.columns[menuContext!.columnIndex!]) ? 'Mostrar neste breakpoint' : 'Ocultar neste\n breakpoint' }}</span>\n </button>\n <button mat-menu-item (click)=\"removeColumn(menuContext!.columnIndex!)\">\n <mat-icon color=\"warn\">delete</mat-icon>\n <span>Remover coluna</span>\n </button>\n </ng-container>\n <ng-template #rowMenuContent>\n <div mat-menu-item disabled>Presets de colunas</div>\n <button mat-menu-item (click)=\"applyPreset([12])\"><mat-icon>view_column</mat-icon><span>1/1</span></button>\n <button mat-menu-item (click)=\"applyPreset([6,6])\"><mat-icon>view_column</mat-icon><span>1/2 \u2014\n 1/2</span></button>\n <button mat-menu-item (click)=\"applyPreset([4,8])\"><mat-icon>view_column</mat-icon><span>1/3 \u2014\n 2/3</span></button>\n <button mat-menu-item (click)=\"applyPreset([8,4])\"><mat-icon>view_column</mat-icon><span>2/3 \u2014\n 1/3</span></button>\n <button mat-menu-item (click)=\"applyPreset([4,4,4])\"><mat-icon>view_column</mat-icon><span>1/3 \u2014 1/3 \u2014\n 1/3</span></button>\n <button mat-menu-item (click)=\"applyPreset([3,3,3,3])\"><mat-icon>view_column</mat-icon><span>1/4 \u2014 1/4 \u2014 1/4 \u2014\n 1/4</span></button>\n <button mat-menu-item (click)=\"addColumn()\"><mat-icon>add</mat-icon><span>Adicionar coluna</span></button>\n <button mat-menu-item (click)=\"removeRow()\"><mat-icon>delete</mat-icon><span>Remover linha</span></button>\n </ng-template>\n </mat-menu>\n </div>\n </div>\n <div class=\"span-warning\" *ngIf=\"getSpanTotal(previewBreakpoint) !== 12\">\n <mat-icon color=\"warn\">warning</mat-icon>\n Soma de spans = {{ getSpanTotal(previewBreakpoint) }} (ideal: 12)\n </div>\n</div>\n\n<div class=\"row-container\" [style.marginBottom.px]=\"!isLastRow ? (row.rowGap || null) : null\">\n <ng-container *ngIf=\"row.columns.length > 0; else emptyRow\">\n <div class=\"row grid-12\" cdkDropListGroup (click)=\"selectRow()\" [class.selected]=\"isRowSelected()\" tabindex=\"0\"\n role=\"button\" [attr.aria-label]=\"'Linha ' + (rowIndex + 1)\" [attr.aria-selected]=\"isRowSelected()\"\n [style.--pfx-grid-gap.px]=\"row.gap || null\" [style.--px-row-field-gap.px]=\"row.rowGap ?? null\">\n <div class=\"row-label\" aria-hidden=\"true\">Linha {{ rowIndex + 1 }}</div>\n <div *ngFor=\"let column of row.columns; let i = index\" class=\"column\" [id]=\"getColumnId(i)\" cdkDropList\n [cdkDropListData]=\"column.fields\" [cdkDropListConnectedTo]=\"connectedColumns(i)\"\n (cdkDropListDropped)=\"drop($event)\" (cdkDropListEntered)=\"onDropEnter(i)\" (cdkDropListExited)=\"onDropExit(i)\"\n (click)=\"selectColumn(i, $event)\" [class.drop-active]=\"activeDropIndex === i\"\n [class.selected]=\"isColumnSelected(i)\" [ngClass]=\"getColumnClassList(column)\"\n [style.grid-column]=\"'span ' + getSpanFor(column)\" tabindex=\"0\" role=\"button\"\n [attr.aria-label]=\"'Coluna ' + (i + 1) + ' de Linha ' + (rowIndex + 1) + '; Largura ' + getSpanFor(column)\"\n [attr.aria-selected]=\"isColumnSelected(i)\">\n <div class=\"column-header\">\n <div class=\"column-status-pill\" [matMenuTriggerFor]=\"columnSettingsMenu\"\n matTooltip=\"Clique para ajustar largura e offset\" [class.active]=\"isColumnSelected(i)\">\n <span class=\"status-bp\">{{ previewBreakpoint }}</span>\n <span class=\"status-divider\">\u00B7</span>\n <span class=\"status-span\">\n <mat-icon>view_column</mat-icon>\n {{ getSpanFor(column) }}/12\n </span>\n <span class=\"status-divider\">\u00B7</span>\n <span class=\"status-offset\">\n off {{ getOffsetFor(column) }}\n </span>\n <span class=\"status-hidden\" *ngIf=\"getHiddenFor(column)\">\n <mat-icon>visibility_off</mat-icon>\n </span>\n </div>\n\n <div class=\"column-actions\">\n <button mat-icon-button class=\"action-btn\" [matMenuTriggerFor]=\"columnOverflowMenu\"\n (click)=\"$event.stopPropagation()\" matTooltip=\"Op\u00E7\u00F5es da coluna\">\n <mat-icon>more_vert</mat-icon>\n </button>\n </div>\n </div>\n\n <mat-menu #columnSettingsMenu=\"matMenu\" class=\"column-settings-popover\">\n <div class=\"popover-content\" (click)=\"$event.stopPropagation()\">\n <div class=\"control-group\" *ngIf=\"getSuggestedSpan(i) as suggested\">\n <button mat-flat-button color=\"primary\" (click)=\"setSpan(i, suggested)\"\n matTooltip=\"Ajustar largura para completar 12 colunas\">\n <mat-icon>auto_fix_high</mat-icon>\n Ajustar para {{ suggested }} (Total 12)\n </button>\n </div>\n <div class=\"control-group\">\n <label>Largura ({{ previewBreakpoint }})</label>\n <div class=\"control-row\">\n <button mat-icon-button (click)=\"adjustSpan(i, -1)\"><mat-icon>remove</mat-icon></button>\n <span class=\"value-display\">{{ getSpanFor(column) }} / 12</span>\n <button mat-icon-button (click)=\"adjustSpan(i, 1)\"><mat-icon>add</mat-icon></button>\n </div>\n </div>\n <div class=\"control-group\">\n <label>Offset ({{ previewBreakpoint }})</label>\n <div class=\"control-row\">\n <button mat-icon-button (click)=\"adjustOffset(i, -1)\"><mat-icon>chevron_left</mat-icon></button>\n <span class=\"value-display\">{{ getOffsetFor(column) }}</span>\n <button mat-icon-button (click)=\"adjustOffset(i, 1)\"><mat-icon>chevron_right</mat-icon></button>\n </div>\n </div>\n <div class=\"control-group\">\n <button mat-stroked-button (click)=\"toggleHidden(i)\" [color]=\"getHiddenFor(column) ? 'warn' : ''\">\n <mat-icon>{{ getHiddenFor(column) ? 'visibility' : 'visibility_off' }}</mat-icon>\n {{ getHiddenFor(column) ? 'Mostrar' : 'Ocultar' }}\n </button>\n </div>\n </div>\n </mat-menu>\n\n <mat-menu #columnOverflowMenu=\"matMenu\">\n <button mat-menu-item (click)=\"openColumnConfig(i)\" matTooltip=\"Abrir painel de configura\u00E7\u00E3o completa\">\n <mat-icon>tune</mat-icon>\n <span>Configurar coluna</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"moveColumn(i, -1)\" [disabled]=\"i === 0\"\n matTooltip=\"Mover coluna para a esquerda\">\n <mat-icon>arrow_back</mat-icon>\n <span>Mover para esquerda</span>\n </button>\n <button mat-menu-item (click)=\"moveColumn(i, 1)\" [disabled]=\"i === row.columns.length - 1\"\n matTooltip=\"Mover coluna para a direita\">\n <mat-icon>arrow_forward</mat-icon>\n <span>Mover para direita</span>\n </button>\n\n <button mat-menu-item (click)=\"clearColumn(i)\" [disabled]=\"column.fields.length === 0\"\n matTooltip=\"Remover todos os campos desta coluna\">\n <mat-icon>backspace</mat-icon>\n <span>Limpar conte\u00FAdo</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"removeColumn(i)\" matTooltip=\"Excluir esta coluna\">\n <mat-icon color=\"warn\">delete</mat-icon>\n <span>Remover coluna</span>\n </button>\n </mat-menu>\n <div class=\"column-content\">\n <div class=\"hidden-overlay\" *ngIf=\"getHiddenFor(column)\">\n <mat-icon aria-hidden=\"true\">visibility_off</mat-icon>\n <span>Oculta em {{ previewBreakpoint }}</span>\n </div>\n <ng-container *ngIf=\"column.fields.length > 0; else emptyColumn\">\n <div *ngFor=\"let fieldName of column.fields\" (click)=\"selectField(fieldName, $event)\"\n [class.selected]=\"isFieldSelected(fieldName)\">\n <praxis-field-configurator [field]=\"getFieldByName(fieldName)\"></praxis-field-configurator>\n </div>\n </ng-container>\n <ng-template #emptyColumn>\n <div class=\"column-placeholder\">\n <span>Coluna vazia \u2014 solte um campo ou remova.</span>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n </ng-container>\n <ng-template #emptyRow>\n <div class=\"row-empty-placeholder\">\n <span>Linha vazia \u2014 crie colunas ou remova.</span>\n <div class=\"row-placeholder-actions\">\n <button mat-stroked-button (click)=\"addColumn()\" matTooltip=\"Adicionar coluna\">\n <mat-icon>add</mat-icon> Adicionar coluna\n </button>\n <button mat-stroked-button color=\"warn\" (click)=\"removeRow()\" matTooltip=\"Remover linha\">\n <mat-icon>delete</mat-icon> Remover linha\n </button>\n </div>\n </div>\n </ng-template>\n</div>\n", styles: [".row-meta{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap}.bp-toggle{display:inline-flex;gap:4px;align-items:center}.bp-toggle__btn{min-width:34px;height:30px;line-height:30px;padding:0 8px;text-transform:uppercase}.bp-toggle__btn.active{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.gap-controls{display:flex;gap:8px;flex-wrap:wrap;align-items:center}.gap-chip{display:inline-flex;align-items:center;gap:2px;padding:0 4px;height:32px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-variant)}.gap-chip__btn{width:24px;height:24px;line-height:24px;min-width:0;padding:0;--mdc-icon-button-size: 24px;--mdc-icon-button-state-layer-size: 24px}.gap-chip .mat-mdc-button-touch-target{width:24px;height:24px}.gap-chip mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.gap-chip__input{width:42px;border:none;background:transparent;color:var(--md-sys-color-on-surface);font:var(--mdc-typography-body-medium, 600 13px/18px system-ui);text-align:center;outline:none;-moz-appearance:textfield}.gap-chip__input::-webkit-outer-spin-button,.gap-chip__input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.gap-chip__suffix{color:var(--md-sys-color-on-surface-variant);font:var(--mdc-typography-label-medium, 500 12px/16px system-ui)}.gap-pill{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border-radius:12px;background:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);font:var(--mdc-typography-label-medium, 500 12px/16px system-ui)}.chip-title{font:var(--mdc-typography-label-medium, 600 12px/16px system-ui);color:var(--md-sys-color-on-surface-variant);text-transform:uppercase;letter-spacing:.03em}.span-warning{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-error);background:var(--md-sys-color-error-container);border:1px solid var(--md-sys-color-error);border-radius:6px;padding:4px 8px}.row-container{position:relative;display:flex;align-items:stretch}.row{display:flex;flex-grow:1;position:relative;padding-right:0;border-radius:6px;transition:box-shadow .2s ease;gap:var(--pfx-grid-gap, 12px)}.row:focus{outline:none;box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row:focus-visible{box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row.grid-12{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.row.selected{box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row-label{position:absolute;left:-4px;top:-10px;transform:translateY(-100%);background:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;padding:2px 6px;font-size:11px;opacity:0;transition:opacity .15s ease;pointer-events:none}.row:hover .row-label,.row.selected .row-label{opacity:1}.row-actions-meta{margin-left:auto}.column{position:relative;flex:1;display:flex;flex-direction:column;border:1px dashed var(--md-sys-color-outline-variant);margin:0;background:var(--md-sys-color-surface-container);transition:background-color .2s ease,border-color .2s ease;border-radius:8px;overflow:hidden}.column-header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px;background:var(--md-sys-color-surface-variant);border-bottom:1px solid var(--md-sys-color-outline-variant);min-height:36px}.column-content{flex:1;display:grid;align-content:start;gap:var(--px-row-field-gap, 6px);padding:8px}.column-status-pill{display:inline-flex;align-items:center;gap:6px;padding:2px 8px;border-radius:12px;background:var(--md-sys-color-surface);border:1px solid var(--md-sys-color-outline-variant);cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none}.column-status-pill:hover,.column-status-pill.active{background:var(--md-sys-color-surface-variant);border-color:var(--md-sys-color-outline)}.status-bp{font-weight:700;text-transform:uppercase;font-size:11px;color:var(--md-sys-color-primary)}.status-divider{color:var(--md-sys-color-outline-variant)}.status-span,.status-offset{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--md-sys-color-on-surface)}.status-span mat-icon{font-size:14px;width:14px;height:14px}.status-hidden{color:var(--md-sys-color-error);display:flex;align-items:center}.status-hidden mat-icon{font-size:14px;width:14px;height:14px}.column-actions{display:flex;align-items:center;opacity:0;transition:opacity .2s ease}.column:hover .column-actions,.column.selected .column-actions,.column-actions:focus-within{opacity:1}.action-btn{width:24px;height:24px;line-height:24px;padding:0}.action-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.popover-content{padding:12px;display:flex;flex-direction:column;gap:12px;min-width:200px}.control-group{display:flex;flex-direction:column;gap:4px}.control-group label{font-size:11px;color:var(--md-sys-color-on-surface-variant);text-transform:uppercase;font-weight:600}.control-row{display:flex;align-items:center;justify-content:space-between;background:var(--md-sys-color-surface-container-high);border-radius:8px;padding:2px}.value-display{font-weight:600;font-size:13px}.row.grid-12 .column{flex:unset}.column>div{margin:0}.column:focus{outline:none;box-shadow:0 0 0 2px var(--md-sys-color-primary)}.column:focus-visible{box-shadow:0 0 0 2px var(--md-sys-color-primary)}.column.drop-active{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-surface-variant)}.column.selected{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px var(--md-sys-color-primary)}.column.cdk-drop-list-receiving{animation:columnHighlight .3s ease-in-out}@keyframes columnHighlight{0%{box-shadow:0 0 0 2px var(--md-sys-color-primary)}to{box-shadow:none}}.field-selected-highlight.selected .field-item,.selected>.field-item{border-color:var(--md-sys-color-primary)!important;box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row-empty-placeholder{flex:1;border:1px dashed var(--md-sys-color-outline-variant);margin:0;padding:16px;text-align:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container)}.row-placeholder-actions{margin-top:8px;display:flex;gap:8px;justify-content:center}.hidden-overlay{position:absolute;inset:0;background:var(--md-sys-color-surface-container-low);border:1px dashed var(--md-sys-color-outline);display:flex;align-items:center;justify-content:center;gap:6px;color:var(--md-sys-color-on-surface-variant);z-index:2;pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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: DragDropModule }, { kind: "directive", type: i2$2.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i2$2.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "component", type: FieldConfiguratorComponent, selector: "praxis-field-configurator", inputs: ["field"] }, { 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.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.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i6.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i6.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i6.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }] });
|
|
14118
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: RowConfiguratorComponent, isStandalone: true, selector: "praxis-row-configurator", inputs: { row: "row", fieldMetadata: "fieldMetadata", availableFields: "availableFields", sectionIndex: "sectionIndex", rowIndex: "rowIndex", isLastRow: "isLastRow", selected: "selected", availableFieldsListId: "availableFieldsListId", connectedDropListIds: "connectedDropListIds", gapGlobal: "gapGlobal" }, outputs: { rowChange: "rowChange", remove: "remove", applyRowGapAll: "applyRowGapAll", fieldDrop: "fieldDrop", addVisualBlock: "addVisualBlock", addApiField: "addApiField", editVisualBlock: "editVisualBlock", moveVisualBlock: "moveVisualBlock", moveVisualBlockToColumn: "moveVisualBlockToColumn", removeVisualBlock: "removeVisualBlock", select: "select" }, providers: [providePraxisI18nConfig(LAYOUT_EDITOR_I18N_CONFIG)], usesOnChanges: true, ngImport: i0, template: "<div class=\"row-meta\" *ngIf=\"row\">\n <div class=\"bp-toggle\" role=\"group\" aria-label=\"Breakpoint de visualiza\u00E7\u00E3o\">\n <button\n *ngFor=\"let bp of breakpoints\"\n type=\"button\"\n mat-stroked-button\n class=\"bp-toggle__btn\"\n [class.active]=\"previewBreakpoint === bp\"\n (click)=\"previewBreakpoint = bp\"\n >\n {{ bp }}\n </button>\n </div>\n <div class=\"gap-controls\">\n <div class=\"gap-chip\" *ngIf=\"hasMultipleColumns()\" matTooltip=\"Gap entre colunas (px)\"\n aria-label=\"Gap entre colunas\">\n <span class=\"chip-title\">Colunas</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('gap', -2)\"\n aria-label=\"Reduzir gap de colunas\">\n <mat-icon>remove</mat-icon>\n </button>\n <input class=\"gap-chip__input\" type=\"number\" min=\"0\" [ngModel]=\"row.gap ?? gapGlobal\"\n (ngModelChange)=\"updateRowGap('gap', $event)\" aria-label=\"Valor do gap entre colunas\" />\n <span class=\"gap-chip__suffix\">px</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('gap', 2)\"\n aria-label=\"Aumentar gap de colunas\">\n <mat-icon>add</mat-icon>\n </button>\n </div>\n <div class=\"gap-chip\" matTooltip=\"Gap abaixo da linha (px)\" aria-label=\"Gap abaixo da linha\">\n <span class=\"chip-title\">Linha</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('rowGap', -2)\"\n aria-label=\"Reduzir espa\u00E7o entre campos da linha\" matTooltip=\"Reduz o espa\u00E7o entre campos desta linha\">\n <mat-icon>remove</mat-icon>\n </button>\n <input class=\"gap-chip__input\" type=\"number\" min=\"0\" [ngModel]=\"row.rowGap ?? 0\"\n (ngModelChange)=\"updateRowGap('rowGap', $event)\" aria-label=\"Espa\u00E7o entre campos desta linha\" />\n <span class=\"gap-chip__suffix\">px</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('rowGap', 2)\"\n aria-label=\"Aumentar espa\u00E7o entre campos da linha\" matTooltip=\"Aumenta o espa\u00E7o entre campos desta linha\">\n <mat-icon>add</mat-icon>\n </button>\n <button mat-icon-button class=\"gap-chip__btn\" [matMenuTriggerFor]=\"rowGapMenu\"\n matTooltip=\"Mais op\u00E7\u00F5es para aplicar este espa\u00E7o\" aria-label=\"Mais op\u00E7\u00F5es de aplica\u00E7\u00E3o\">\n <mat-icon>done_all</mat-icon>\n </button>\n <mat-menu #rowGapMenu=\"matMenu\">\n <button mat-menu-item (click)=\"applyRowGapToAll()\">\n <mat-icon>done_all</mat-icon>\n <span>Aplicar em todas as linhas da se\u00E7\u00E3o</span>\n </button>\n <button mat-menu-item (click)=\"clearRowGap()\">\n <mat-icon>undo</mat-icon>\n <span>Voltar ao padr\u00E3o</span>\n </button>\n </mat-menu>\n </div>\n <div class=\"gap-pill\" aria-label=\"Resumo de espa\u00E7amentos\">\n Campos: {{ (row.rowGap ?? 'padr\u00E3o') }}px \u00B7 Colunas: {{ (row.gap ?? gapGlobal) }}px\n </div>\n <div class=\"row-actions-meta\">\n <button mat-icon-button [matMenuTriggerFor]=\"rowMenu\" (click)=\"openRowMenu()\" matTooltip=\"Op\u00E7\u00F5es da linha\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <mat-menu #rowMenu=\"matMenu\" (closed)=\"onMenuClosed()\">\n <ng-container *ngIf=\"menuContext?.type === 'column'; else rowMenuContent\">\n <button mat-menu-item (click)=\"toggleHidden(menuContext!.columnIndex!)\">\n <mat-icon>{{ getHiddenFor(row.columns[menuContext!.columnIndex!]) ? 'visibility' : 'visibility_off'\n }}</mat-icon>\n <span>{{ getHiddenFor(row.columns[menuContext!.columnIndex!]) ? 'Mostrar neste breakpoint' : 'Ocultar neste\n breakpoint' }}</span>\n </button>\n <button mat-menu-item (click)=\"removeColumn(menuContext!.columnIndex!)\">\n <mat-icon color=\"warn\">delete</mat-icon>\n <span>Remover coluna</span>\n </button>\n </ng-container>\n <ng-template #rowMenuContent>\n <div mat-menu-item disabled>Presets de colunas</div>\n <button mat-menu-item (click)=\"applyPreset([12])\"><mat-icon>view_column</mat-icon><span>1/1</span></button>\n <button mat-menu-item (click)=\"applyPreset([6,6])\"><mat-icon>view_column</mat-icon><span>1/2 \u2014\n 1/2</span></button>\n <button mat-menu-item (click)=\"applyPreset([4,8])\"><mat-icon>view_column</mat-icon><span>1/3 \u2014\n 2/3</span></button>\n <button mat-menu-item (click)=\"applyPreset([8,4])\"><mat-icon>view_column</mat-icon><span>2/3 \u2014\n 1/3</span></button>\n <button mat-menu-item (click)=\"applyPreset([4,4,4])\"><mat-icon>view_column</mat-icon><span>1/3 \u2014 1/3 \u2014\n 1/3</span></button>\n <button mat-menu-item (click)=\"applyPreset([3,3,3,3])\"><mat-icon>view_column</mat-icon><span>1/4 \u2014 1/4 \u2014 1/4 \u2014\n 1/4</span></button>\n <button mat-menu-item (click)=\"addColumn()\"><mat-icon>add</mat-icon><span>Adicionar coluna</span></button>\n <button mat-menu-item (click)=\"removeRow()\"><mat-icon>delete</mat-icon><span>Remover linha</span></button>\n </ng-template>\n </mat-menu>\n </div>\n </div>\n <div class=\"span-warning\" *ngIf=\"getSpanTotal(previewBreakpoint) !== 12\">\n <mat-icon color=\"warn\">warning</mat-icon>\n Soma de spans = {{ getSpanTotal(previewBreakpoint) }} (ideal: 12)\n </div>\n</div>\n\n<div class=\"row-container\" [style.marginBottom.px]=\"!isLastRow ? (row.rowGap || null) : null\">\n <ng-container *ngIf=\"row.columns.length > 0; else emptyRow\">\n <div class=\"row grid-12\" cdkDropListGroup (click)=\"selectRow()\" [class.selected]=\"isRowSelected()\" tabindex=\"0\"\n role=\"button\" [attr.aria-label]=\"'Linha ' + (rowIndex + 1)\" [attr.aria-selected]=\"isRowSelected()\"\n [style.--pfx-grid-gap.px]=\"row.gap || null\" [style.--px-row-field-gap.px]=\"row.rowGap ?? null\">\n <div class=\"row-label\" aria-hidden=\"true\">Linha {{ rowIndex + 1 }}</div>\n <div *ngFor=\"let column of row.columns; let i = index\" class=\"column\" [id]=\"getColumnId(i)\" cdkDropList\n [cdkDropListData]=\"column.fields\" [cdkDropListConnectedTo]=\"connectedColumns(i)\"\n (cdkDropListDropped)=\"drop($event)\" (cdkDropListEntered)=\"onDropEnter(i)\" (cdkDropListExited)=\"onDropExit(i)\"\n (click)=\"selectColumn(i, $event)\" [class.drop-active]=\"activeDropIndex === i\"\n [class.selected]=\"isColumnSelected(i)\" [ngClass]=\"getColumnClassList(column)\"\n [style.grid-column]=\"'span ' + getSpanFor(column)\" tabindex=\"0\" role=\"button\"\n [attr.aria-label]=\"'Coluna ' + (i + 1) + ' de Linha ' + (rowIndex + 1) + '; Largura ' + getSpanFor(column)\"\n [attr.aria-selected]=\"isColumnSelected(i)\">\n <div class=\"column-header\">\n <div class=\"column-status-pill\" [matMenuTriggerFor]=\"columnSettingsMenu\"\n matTooltip=\"Clique para ajustar largura e offset\" [class.active]=\"isColumnSelected(i)\">\n <span class=\"status-bp\">{{ previewBreakpoint }}</span>\n <span class=\"status-divider\">\u00B7</span>\n <span class=\"status-span\">\n <mat-icon>view_column</mat-icon>\n {{ getSpanFor(column) }}/12\n </span>\n <span class=\"status-divider\">\u00B7</span>\n <span class=\"status-offset\">\n off {{ getOffsetFor(column) }}\n </span>\n <span class=\"status-hidden\" *ngIf=\"getHiddenFor(column)\">\n <mat-icon>visibility_off</mat-icon>\n </span>\n </div>\n\n <div class=\"column-actions\">\n <button mat-icon-button class=\"action-btn\" [matMenuTriggerFor]=\"columnOverflowMenu\"\n (click)=\"$event.stopPropagation()\" matTooltip=\"Op\u00E7\u00F5es da coluna\">\n <mat-icon>more_vert</mat-icon>\n </button>\n </div>\n </div>\n\n <mat-menu #columnSettingsMenu=\"matMenu\" class=\"column-settings-popover\">\n <div class=\"popover-content\" (click)=\"$event.stopPropagation()\">\n <div class=\"control-group\" *ngIf=\"getSuggestedSpan(i) as suggested\">\n <button mat-flat-button color=\"primary\" (click)=\"setSpan(i, suggested)\"\n matTooltip=\"Ajustar largura para completar 12 colunas\">\n <mat-icon>auto_fix_high</mat-icon>\n Ajustar para {{ suggested }} (Total 12)\n </button>\n </div>\n <div class=\"control-group\">\n <label>Largura ({{ previewBreakpoint }})</label>\n <div class=\"control-row\">\n <button mat-icon-button (click)=\"adjustSpan(i, -1)\"><mat-icon>remove</mat-icon></button>\n <span class=\"value-display\">{{ getSpanFor(column) }} / 12</span>\n <button mat-icon-button (click)=\"adjustSpan(i, 1)\"><mat-icon>add</mat-icon></button>\n </div>\n </div>\n <div class=\"control-group\">\n <label>Offset ({{ previewBreakpoint }})</label>\n <div class=\"control-row\">\n <button mat-icon-button (click)=\"adjustOffset(i, -1)\"><mat-icon>chevron_left</mat-icon></button>\n <span class=\"value-display\">{{ getOffsetFor(column) }}</span>\n <button mat-icon-button (click)=\"adjustOffset(i, 1)\"><mat-icon>chevron_right</mat-icon></button>\n </div>\n </div>\n <div class=\"control-group\">\n <button mat-stroked-button (click)=\"toggleHidden(i)\" [color]=\"getHiddenFor(column) ? 'warn' : ''\">\n <mat-icon>{{ getHiddenFor(column) ? 'visibility' : 'visibility_off' }}</mat-icon>\n {{ getHiddenFor(column) ? 'Mostrar' : 'Ocultar' }}\n </button>\n </div>\n </div>\n </mat-menu>\n\n <mat-menu #columnOverflowMenu=\"matMenu\">\n <button mat-menu-item (click)=\"openColumnConfig(i)\" matTooltip=\"Abrir painel de configura\u00E7\u00E3o completa\">\n <mat-icon>tune</mat-icon>\n <span>Configurar coluna</span>\n </button>\n <button mat-menu-item [matMenuTriggerFor]=\"apiFieldMenu\" [matTooltip]=\"t('apiFields.addTooltip')\">\n <mat-icon>input</mat-icon>\n <span>{{ t('apiFields.addAction') }}</span>\n </button>\n <mat-menu #apiFieldMenu=\"matMenu\">\n <button\n mat-menu-item\n *ngFor=\"let field of availableFields\"\n (click)=\"addApiFieldToColumn(i, field.name)\"\n >\n <mat-icon>short_text</mat-icon>\n <span>{{ getFieldLabel(field) }}</span>\n </button>\n <button mat-menu-item disabled *ngIf=\"!availableFields.length\">\n <span>{{ t('apiFields.empty') }}</span>\n </button>\n </mat-menu>\n <button mat-menu-item [matMenuTriggerFor]=\"visualBlockPresetMenu\" [matTooltip]=\"t('visualBlock.addTooltip')\">\n <mat-icon>notes</mat-icon>\n <span>{{ t('visualBlock.addAction') }}</span>\n </button>\n <mat-menu #visualBlockPresetMenu=\"matMenu\">\n <button\n mat-menu-item\n *ngFor=\"let preset of visualBlockPresets\"\n (click)=\"addVisualBlockToColumn(i, preset.id)\"\n >\n <mat-icon>{{ preset.icon }}</mat-icon>\n <span>{{ t(preset.labelKey) }}</span>\n </button>\n </mat-menu>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"moveColumn(i, -1)\" [disabled]=\"i === 0\"\n matTooltip=\"Mover coluna para a esquerda\">\n <mat-icon>arrow_back</mat-icon>\n <span>Mover para esquerda</span>\n </button>\n <button mat-menu-item (click)=\"moveColumn(i, 1)\" [disabled]=\"i === row.columns.length - 1\"\n matTooltip=\"Mover coluna para a direita\">\n <mat-icon>arrow_forward</mat-icon>\n <span>Mover para direita</span>\n </button>\n\n <button mat-menu-item (click)=\"clearColumn(i)\" [disabled]=\"!hasColumnContent(column)\"\n matTooltip=\"Remover todo o conte\u00C3\u00BAdo desta coluna\">\n <mat-icon>backspace</mat-icon>\n <span>Limpar conte\u00FAdo</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"removeColumn(i)\" matTooltip=\"Excluir esta coluna\">\n <mat-icon color=\"warn\">delete</mat-icon>\n <span>Remover coluna</span>\n </button>\n </mat-menu>\n <div class=\"column-content\">\n <div class=\"hidden-overlay\" *ngIf=\"getHiddenFor(column)\">\n <mat-icon aria-hidden=\"true\">visibility_off</mat-icon>\n <span>Oculta em {{ previewBreakpoint }}</span>\n </div>\n <ng-container *ngIf=\"hasColumnContent(column); else emptyColumn\">\n <ng-container *ngFor=\"let item of getColumnLayoutItems(column); let itemIndex = index\">\n <div *ngIf=\"item.kind === 'field'; else visualBlockItem\" (click)=\"selectField(item.fieldName, $event)\"\n [class.selected]=\"isFieldSelected(item.fieldName)\">\n <praxis-field-configurator [field]=\"getFieldByName(item.fieldName)\"></praxis-field-configurator>\n </div>\n <ng-template #visualBlockItem>\n <div\n class=\"visual-block-preview\"\n *ngIf=\"item.kind === 'richContent'\"\n role=\"button\"\n tabindex=\"0\"\n [class.selected]=\"selected?.type === 'visualBlock' && selected?.itemId === item.id\"\n (click)=\"selectVisualBlock(i, item, $event)\"\n (dblclick)=\"openVisualBlockEditor(i, item, $event)\"\n >\n <mat-icon aria-hidden=\"true\">notes</mat-icon>\n <span>{{ getVisualBlockLabel(item) }}</span>\n <span class=\"visual-block-preview__actions\">\n <button\n mat-icon-button\n class=\"visual-block-preview__action\"\n type=\"button\"\n [matTooltip]=\"t('visualBlock.moveUp')\"\n [attr.aria-label]=\"t('visualBlock.moveUp')\"\n [disabled]=\"itemIndex === 0\"\n (click)=\"moveVisualBlockItem(i, item, -1, $event)\"\n >\n <mat-icon>arrow_upward</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"visual-block-preview__action\"\n type=\"button\"\n [matTooltip]=\"t('visualBlock.moveDown')\"\n [attr.aria-label]=\"t('visualBlock.moveDown')\"\n [disabled]=\"itemIndex === getColumnLayoutItems(column).length - 1\"\n (click)=\"moveVisualBlockItem(i, item, 1, $event)\"\n >\n <mat-icon>arrow_downward</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"visual-block-preview__action\"\n type=\"button\"\n [matTooltip]=\"t('visualBlock.movePreviousColumn')\"\n [attr.aria-label]=\"t('visualBlock.movePreviousColumn')\"\n [disabled]=\"!canMoveVisualBlockToColumn(i, -1)\"\n (click)=\"moveVisualBlockToAdjacentColumn(i, item, -1, $event)\"\n >\n <mat-icon>arrow_back</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"visual-block-preview__action\"\n type=\"button\"\n [matTooltip]=\"t('visualBlock.moveNextColumn')\"\n [attr.aria-label]=\"t('visualBlock.moveNextColumn')\"\n [disabled]=\"!canMoveVisualBlockToColumn(i, 1)\"\n (click)=\"moveVisualBlockToAdjacentColumn(i, item, 1, $event)\"\n >\n <mat-icon>arrow_forward</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"visual-block-preview__action\"\n type=\"button\"\n [matTooltip]=\"t('visualBlock.editAction')\"\n [attr.aria-label]=\"t('visualBlock.editAction')\"\n (click)=\"openVisualBlockEditor(i, item, $event)\"\n >\n <mat-icon>edit</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"visual-block-preview__action\"\n type=\"button\"\n color=\"warn\"\n [matTooltip]=\"t('visualBlock.removeAction')\"\n [attr.aria-label]=\"t('visualBlock.removeAction')\"\n (click)=\"removeVisualBlockItem(i, item, $event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </span>\n </div>\n </ng-template>\n </ng-container>\n </ng-container>\n <ng-template #emptyColumn>\n <div class=\"column-placeholder\">\n <span>Coluna vazia \u2014 solte um campo ou remova.</span>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n </ng-container>\n <ng-template #emptyRow>\n <div class=\"row-empty-placeholder\">\n <span>Linha vazia \u2014 crie colunas ou remova.</span>\n <div class=\"row-placeholder-actions\">\n <button mat-stroked-button (click)=\"addColumn()\" matTooltip=\"Adicionar coluna\">\n <mat-icon>add</mat-icon> Adicionar coluna\n </button>\n <button mat-stroked-button color=\"warn\" (click)=\"removeRow()\" matTooltip=\"Remover linha\">\n <mat-icon>delete</mat-icon> Remover linha\n </button>\n </div>\n </div>\n </ng-template>\n</div>\n", styles: [".row-meta{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap}.bp-toggle{display:inline-flex;gap:4px;align-items:center}.bp-toggle__btn{min-width:34px;height:30px;line-height:30px;padding:0 8px;text-transform:uppercase}.bp-toggle__btn.active{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.gap-controls{display:flex;gap:8px;flex-wrap:wrap;align-items:center}.gap-chip{display:inline-flex;align-items:center;gap:2px;padding:0 4px;height:32px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-variant)}.gap-chip__btn{width:24px;height:24px;line-height:24px;min-width:0;padding:0;--mdc-icon-button-size: 24px;--mdc-icon-button-state-layer-size: 24px}.gap-chip .mat-mdc-button-touch-target{width:24px;height:24px}.gap-chip mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.gap-chip__input{width:42px;border:none;background:transparent;color:var(--md-sys-color-on-surface);font:var(--mdc-typography-body-medium, 600 13px/18px system-ui);text-align:center;outline:none;-moz-appearance:textfield}.gap-chip__input::-webkit-outer-spin-button,.gap-chip__input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.gap-chip__suffix{color:var(--md-sys-color-on-surface-variant);font:var(--mdc-typography-label-medium, 500 12px/16px system-ui)}.gap-pill{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border-radius:12px;background:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);font:var(--mdc-typography-label-medium, 500 12px/16px system-ui)}.chip-title{font:var(--mdc-typography-label-medium, 600 12px/16px system-ui);color:var(--md-sys-color-on-surface-variant);text-transform:uppercase;letter-spacing:.03em}.span-warning{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-error);background:var(--md-sys-color-error-container);border:1px solid var(--md-sys-color-error);border-radius:6px;padding:4px 8px}.row-container{position:relative;display:flex;align-items:stretch}.row{display:flex;flex-grow:1;position:relative;padding-right:0;border-radius:6px;transition:box-shadow .2s ease;gap:var(--pfx-grid-gap, 12px)}.row:focus{outline:none;box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row:focus-visible{box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row.grid-12{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.row.selected{box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row-label{position:absolute;left:-4px;top:-10px;transform:translateY(-100%);background:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;padding:2px 6px;font-size:11px;opacity:0;transition:opacity .15s ease;pointer-events:none}.row:hover .row-label,.row.selected .row-label{opacity:1}.row-actions-meta{margin-left:auto}.column{position:relative;flex:1;display:flex;flex-direction:column;border:1px dashed var(--md-sys-color-outline-variant);margin:0;background:var(--md-sys-color-surface-container);transition:background-color .2s ease,border-color .2s ease;border-radius:8px;overflow:hidden}.column-header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px;background:var(--md-sys-color-surface-variant);border-bottom:1px solid var(--md-sys-color-outline-variant);min-height:36px}.column-content{flex:1;display:grid;align-content:start;gap:var(--px-row-field-gap, 6px);padding:8px}.column-status-pill{display:inline-flex;align-items:center;gap:6px;padding:2px 8px;border-radius:12px;background:var(--md-sys-color-surface);border:1px solid var(--md-sys-color-outline-variant);cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none}.column-status-pill:hover,.column-status-pill.active{background:var(--md-sys-color-surface-variant);border-color:var(--md-sys-color-outline)}.status-bp{font-weight:700;text-transform:uppercase;font-size:11px;color:var(--md-sys-color-primary)}.status-divider{color:var(--md-sys-color-outline-variant)}.status-span,.status-offset{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--md-sys-color-on-surface)}.status-span mat-icon{font-size:14px;width:14px;height:14px}.status-hidden{color:var(--md-sys-color-error);display:flex;align-items:center}.status-hidden mat-icon{font-size:14px;width:14px;height:14px}.column-actions{display:flex;align-items:center;opacity:0;transition:opacity .2s ease}.column:hover .column-actions,.column.selected .column-actions,.column-actions:focus-within{opacity:1}.action-btn{width:24px;height:24px;line-height:24px;padding:0}.action-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.popover-content{padding:12px;display:flex;flex-direction:column;gap:12px;min-width:200px}.control-group{display:flex;flex-direction:column;gap:4px}.control-group label{font-size:11px;color:var(--md-sys-color-on-surface-variant);text-transform:uppercase;font-weight:600}.control-row{display:flex;align-items:center;justify-content:space-between;background:var(--md-sys-color-surface-container-high);border-radius:8px;padding:2px}.value-display{font-weight:600;font-size:13px}.row.grid-12 .column{flex:unset}.column>div{margin:0}.column:focus{outline:none;box-shadow:0 0 0 2px var(--md-sys-color-primary)}.column:focus-visible{box-shadow:0 0 0 2px var(--md-sys-color-primary)}.column.drop-active{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-surface-variant)}.column.selected{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px var(--md-sys-color-primary)}.column.cdk-drop-list-receiving{animation:columnHighlight .3s ease-in-out}@keyframes columnHighlight{0%{box-shadow:0 0 0 2px var(--md-sys-color-primary)}to{box-shadow:none}}.field-selected-highlight.selected .field-item,.selected>.field-item{border-color:var(--md-sys-color-primary)!important;box-shadow:0 0 0 2px var(--md-sys-color-primary)}.visual-block-preview{display:flex;align-items:center;gap:8px;min-height:36px;padding:8px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface-variant);font-size:13px;cursor:pointer}.visual-block-preview.selected{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px var(--md-sys-color-primary)}.visual-block-preview mat-icon{font-size:18px;width:18px;height:18px}.visual-block-preview__actions{margin-left:auto;display:inline-flex;align-items:center;gap:2px}.visual-block-preview__action{width:28px;height:28px;--mdc-icon-button-size: 28px;--mdc-icon-button-state-layer-size: 28px}.row-empty-placeholder{flex:1;border:1px dashed var(--md-sys-color-outline-variant);margin:0;padding:16px;text-align:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container)}.row-placeholder-actions{margin-top:8px;display:flex;gap:8px;justify-content:center}.hidden-overlay{position:absolute;inset:0;background:var(--md-sys-color-surface-container-low);border:1px dashed var(--md-sys-color-outline);display:flex;align-items:center;justify-content:center;gap:6px;color:var(--md-sys-color-on-surface-variant);z-index:2;pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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: DragDropModule }, { kind: "directive", type: i2$2.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i2$2.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "component", type: FieldConfiguratorComponent, selector: "praxis-field-configurator", inputs: ["field"] }, { 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.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.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i6.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i6.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i6.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }] });
|
|
13506
14119
|
}
|
|
13507
14120
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: RowConfiguratorComponent, decorators: [{
|
|
13508
14121
|
type: Component,
|
|
@@ -13516,11 +14129,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
13516
14129
|
MatTooltipModule,
|
|
13517
14130
|
MatMenuModule,
|
|
13518
14131
|
MatDividerModule,
|
|
13519
|
-
], template: "<div class=\"row-meta\" *ngIf=\"row\">\n <div class=\"bp-toggle\" role=\"group\" aria-label=\"Breakpoint de visualiza\u00E7\u00E3o\">\n <button\n *ngFor=\"let bp of breakpoints\"\n type=\"button\"\n mat-stroked-button\n class=\"bp-toggle__btn\"\n [class.active]=\"previewBreakpoint === bp\"\n (click)=\"previewBreakpoint = bp\"\n >\n {{ bp }}\n </button>\n </div>\n <div class=\"gap-controls\">\n <div class=\"gap-chip\" *ngIf=\"hasMultipleColumns()\" matTooltip=\"Gap entre colunas (px)\"\n aria-label=\"Gap entre colunas\">\n <span class=\"chip-title\">Colunas</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('gap', -2)\"\n aria-label=\"Reduzir gap de colunas\">\n <mat-icon>remove</mat-icon>\n </button>\n <input class=\"gap-chip__input\" type=\"number\" min=\"0\" [ngModel]=\"row.gap ?? gapGlobal\"\n (ngModelChange)=\"updateRowGap('gap', $event)\" aria-label=\"Valor do gap entre colunas\" />\n <span class=\"gap-chip__suffix\">px</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('gap', 2)\"\n aria-label=\"Aumentar gap de colunas\">\n <mat-icon>add</mat-icon>\n </button>\n </div>\n <div class=\"gap-chip\" matTooltip=\"Gap abaixo da linha (px)\" aria-label=\"Gap abaixo da linha\">\n <span class=\"chip-title\">Linha</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('rowGap', -2)\"\n aria-label=\"Reduzir espa\u00E7o entre campos da linha\" matTooltip=\"Reduz o espa\u00E7o entre campos desta linha\">\n <mat-icon>remove</mat-icon>\n </button>\n <input class=\"gap-chip__input\" type=\"number\" min=\"0\" [ngModel]=\"row.rowGap ?? 0\"\n (ngModelChange)=\"updateRowGap('rowGap', $event)\" aria-label=\"Espa\u00E7o entre campos desta linha\" />\n <span class=\"gap-chip__suffix\">px</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('rowGap', 2)\"\n aria-label=\"Aumentar espa\u00E7o entre campos da linha\" matTooltip=\"Aumenta o espa\u00E7o entre campos desta linha\">\n <mat-icon>add</mat-icon>\n </button>\n <button mat-icon-button class=\"gap-chip__btn\" [matMenuTriggerFor]=\"rowGapMenu\"\n matTooltip=\"Mais op\u00E7\u00F5es para aplicar este espa\u00E7o\" aria-label=\"Mais op\u00E7\u00F5es de aplica\u00E7\u00E3o\">\n <mat-icon>done_all</mat-icon>\n </button>\n <mat-menu #rowGapMenu=\"matMenu\">\n <button mat-menu-item (click)=\"applyRowGapToAll()\">\n <mat-icon>done_all</mat-icon>\n <span>Aplicar em todas as linhas da se\u00E7\u00E3o</span>\n </button>\n <button mat-menu-item (click)=\"clearRowGap()\">\n <mat-icon>undo</mat-icon>\n <span>Voltar ao padr\u00E3o</span>\n </button>\n </mat-menu>\n </div>\n <div class=\"gap-pill\" aria-label=\"Resumo de espa\u00E7amentos\">\n Campos: {{ (row.rowGap ?? 'padr\u00E3o') }}px \u00B7 Colunas: {{ (row.gap ?? gapGlobal) }}px\n </div>\n <div class=\"row-actions-meta\">\n <button mat-icon-button [matMenuTriggerFor]=\"rowMenu\" (click)=\"openRowMenu()\" matTooltip=\"Op\u00E7\u00F5es da linha\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <mat-menu #rowMenu=\"matMenu\" (closed)=\"onMenuClosed()\">\n <ng-container *ngIf=\"menuContext?.type === 'column'; else rowMenuContent\">\n <button mat-menu-item (click)=\"toggleHidden(menuContext!.columnIndex!)\">\n <mat-icon>{{ getHiddenFor(row.columns[menuContext!.columnIndex!]) ? 'visibility' : 'visibility_off'\n }}</mat-icon>\n <span>{{ getHiddenFor(row.columns[menuContext!.columnIndex!]) ? 'Mostrar neste breakpoint' : 'Ocultar neste\n breakpoint' }}</span>\n </button>\n <button mat-menu-item (click)=\"removeColumn(menuContext!.columnIndex!)\">\n <mat-icon color=\"warn\">delete</mat-icon>\n <span>Remover coluna</span>\n </button>\n </ng-container>\n <ng-template #rowMenuContent>\n <div mat-menu-item disabled>Presets de colunas</div>\n <button mat-menu-item (click)=\"applyPreset([12])\"><mat-icon>view_column</mat-icon><span>1/1</span></button>\n <button mat-menu-item (click)=\"applyPreset([6,6])\"><mat-icon>view_column</mat-icon><span>1/2 \u2014\n 1/2</span></button>\n <button mat-menu-item (click)=\"applyPreset([4,8])\"><mat-icon>view_column</mat-icon><span>1/3 \u2014\n 2/3</span></button>\n <button mat-menu-item (click)=\"applyPreset([8,4])\"><mat-icon>view_column</mat-icon><span>2/3 \u2014\n 1/3</span></button>\n <button mat-menu-item (click)=\"applyPreset([4,4,4])\"><mat-icon>view_column</mat-icon><span>1/3 \u2014 1/3 \u2014\n 1/3</span></button>\n <button mat-menu-item (click)=\"applyPreset([3,3,3,3])\"><mat-icon>view_column</mat-icon><span>1/4 \u2014 1/4 \u2014 1/4 \u2014\n 1/4</span></button>\n <button mat-menu-item (click)=\"addColumn()\"><mat-icon>add</mat-icon><span>Adicionar coluna</span></button>\n <button mat-menu-item (click)=\"removeRow()\"><mat-icon>delete</mat-icon><span>Remover linha</span></button>\n </ng-template>\n </mat-menu>\n </div>\n </div>\n <div class=\"span-warning\" *ngIf=\"getSpanTotal(previewBreakpoint) !== 12\">\n <mat-icon color=\"warn\">warning</mat-icon>\n Soma de spans = {{ getSpanTotal(previewBreakpoint) }} (ideal: 12)\n </div>\n</div>\n\n<div class=\"row-container\" [style.marginBottom.px]=\"!isLastRow ? (row.rowGap || null) : null\">\n <ng-container *ngIf=\"row.columns.length > 0; else emptyRow\">\n <div class=\"row grid-12\" cdkDropListGroup (click)=\"selectRow()\" [class.selected]=\"isRowSelected()\" tabindex=\"0\"\n role=\"button\" [attr.aria-label]=\"'Linha ' + (rowIndex + 1)\" [attr.aria-selected]=\"isRowSelected()\"\n [style.--pfx-grid-gap.px]=\"row.gap || null\" [style.--px-row-field-gap.px]=\"row.rowGap ?? null\">\n <div class=\"row-label\" aria-hidden=\"true\">Linha {{ rowIndex + 1 }}</div>\n <div *ngFor=\"let column of row.columns; let i = index\" class=\"column\" [id]=\"getColumnId(i)\" cdkDropList\n [cdkDropListData]=\"column.fields\" [cdkDropListConnectedTo]=\"connectedColumns(i)\"\n (cdkDropListDropped)=\"drop($event)\" (cdkDropListEntered)=\"onDropEnter(i)\" (cdkDropListExited)=\"onDropExit(i)\"\n (click)=\"selectColumn(i, $event)\" [class.drop-active]=\"activeDropIndex === i\"\n [class.selected]=\"isColumnSelected(i)\" [ngClass]=\"getColumnClassList(column)\"\n [style.grid-column]=\"'span ' + getSpanFor(column)\" tabindex=\"0\" role=\"button\"\n [attr.aria-label]=\"'Coluna ' + (i + 1) + ' de Linha ' + (rowIndex + 1) + '; Largura ' + getSpanFor(column)\"\n [attr.aria-selected]=\"isColumnSelected(i)\">\n <div class=\"column-header\">\n <div class=\"column-status-pill\" [matMenuTriggerFor]=\"columnSettingsMenu\"\n matTooltip=\"Clique para ajustar largura e offset\" [class.active]=\"isColumnSelected(i)\">\n <span class=\"status-bp\">{{ previewBreakpoint }}</span>\n <span class=\"status-divider\">\u00B7</span>\n <span class=\"status-span\">\n <mat-icon>view_column</mat-icon>\n {{ getSpanFor(column) }}/12\n </span>\n <span class=\"status-divider\">\u00B7</span>\n <span class=\"status-offset\">\n off {{ getOffsetFor(column) }}\n </span>\n <span class=\"status-hidden\" *ngIf=\"getHiddenFor(column)\">\n <mat-icon>visibility_off</mat-icon>\n </span>\n </div>\n\n <div class=\"column-actions\">\n <button mat-icon-button class=\"action-btn\" [matMenuTriggerFor]=\"columnOverflowMenu\"\n (click)=\"$event.stopPropagation()\" matTooltip=\"Op\u00E7\u00F5es da coluna\">\n <mat-icon>more_vert</mat-icon>\n </button>\n </div>\n </div>\n\n <mat-menu #columnSettingsMenu=\"matMenu\" class=\"column-settings-popover\">\n <div class=\"popover-content\" (click)=\"$event.stopPropagation()\">\n <div class=\"control-group\" *ngIf=\"getSuggestedSpan(i) as suggested\">\n <button mat-flat-button color=\"primary\" (click)=\"setSpan(i, suggested)\"\n matTooltip=\"Ajustar largura para completar 12 colunas\">\n <mat-icon>auto_fix_high</mat-icon>\n Ajustar para {{ suggested }} (Total 12)\n </button>\n </div>\n <div class=\"control-group\">\n <label>Largura ({{ previewBreakpoint }})</label>\n <div class=\"control-row\">\n <button mat-icon-button (click)=\"adjustSpan(i, -1)\"><mat-icon>remove</mat-icon></button>\n <span class=\"value-display\">{{ getSpanFor(column) }} / 12</span>\n <button mat-icon-button (click)=\"adjustSpan(i, 1)\"><mat-icon>add</mat-icon></button>\n </div>\n </div>\n <div class=\"control-group\">\n <label>Offset ({{ previewBreakpoint }})</label>\n <div class=\"control-row\">\n <button mat-icon-button (click)=\"adjustOffset(i, -1)\"><mat-icon>chevron_left</mat-icon></button>\n <span class=\"value-display\">{{ getOffsetFor(column) }}</span>\n <button mat-icon-button (click)=\"adjustOffset(i, 1)\"><mat-icon>chevron_right</mat-icon></button>\n </div>\n </div>\n <div class=\"control-group\">\n <button mat-stroked-button (click)=\"toggleHidden(i)\" [color]=\"getHiddenFor(column) ? 'warn' : ''\">\n <mat-icon>{{ getHiddenFor(column) ? 'visibility' : 'visibility_off' }}</mat-icon>\n {{ getHiddenFor(column) ? 'Mostrar' : 'Ocultar' }}\n </button>\n </div>\n </div>\n </mat-menu>\n\n <mat-menu #columnOverflowMenu=\"matMenu\">\n <button mat-menu-item (click)=\"openColumnConfig(i)\" matTooltip=\"Abrir painel de configura\u00E7\u00E3o completa\">\n <mat-icon>tune</mat-icon>\n <span>Configurar coluna</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"moveColumn(i, -1)\" [disabled]=\"i === 0\"\n matTooltip=\"Mover coluna para a esquerda\">\n <mat-icon>arrow_back</mat-icon>\n <span>Mover para esquerda</span>\n </button>\n <button mat-menu-item (click)=\"moveColumn(i, 1)\" [disabled]=\"i === row.columns.length - 1\"\n matTooltip=\"Mover coluna para a direita\">\n <mat-icon>arrow_forward</mat-icon>\n <span>Mover para direita</span>\n </button>\n\n <button mat-menu-item (click)=\"clearColumn(i)\" [disabled]=\"column.fields.length === 0\"\n matTooltip=\"Remover todos os campos desta coluna\">\n <mat-icon>backspace</mat-icon>\n <span>Limpar conte\u00FAdo</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"removeColumn(i)\" matTooltip=\"Excluir esta coluna\">\n <mat-icon color=\"warn\">delete</mat-icon>\n <span>Remover coluna</span>\n </button>\n </mat-menu>\n <div class=\"column-content\">\n <div class=\"hidden-overlay\" *ngIf=\"getHiddenFor(column)\">\n <mat-icon aria-hidden=\"true\">visibility_off</mat-icon>\n <span>Oculta em {{ previewBreakpoint }}</span>\n </div>\n <ng-container *ngIf=\"column.fields.length > 0; else emptyColumn\">\n <div *ngFor=\"let fieldName of column.fields\" (click)=\"selectField(fieldName, $event)\"\n [class.selected]=\"isFieldSelected(fieldName)\">\n <praxis-field-configurator [field]=\"getFieldByName(fieldName)\"></praxis-field-configurator>\n </div>\n </ng-container>\n <ng-template #emptyColumn>\n <div class=\"column-placeholder\">\n <span>Coluna vazia \u2014 solte um campo ou remova.</span>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n </ng-container>\n <ng-template #emptyRow>\n <div class=\"row-empty-placeholder\">\n <span>Linha vazia \u2014 crie colunas ou remova.</span>\n <div class=\"row-placeholder-actions\">\n <button mat-stroked-button (click)=\"addColumn()\" matTooltip=\"Adicionar coluna\">\n <mat-icon>add</mat-icon> Adicionar coluna\n </button>\n <button mat-stroked-button color=\"warn\" (click)=\"removeRow()\" matTooltip=\"Remover linha\">\n <mat-icon>delete</mat-icon> Remover linha\n </button>\n </div>\n </div>\n </ng-template>\n</div>\n", styles: [".row-meta{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap}.bp-toggle{display:inline-flex;gap:4px;align-items:center}.bp-toggle__btn{min-width:34px;height:30px;line-height:30px;padding:0 8px;text-transform:uppercase}.bp-toggle__btn.active{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.gap-controls{display:flex;gap:8px;flex-wrap:wrap;align-items:center}.gap-chip{display:inline-flex;align-items:center;gap:2px;padding:0 4px;height:32px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-variant)}.gap-chip__btn{width:24px;height:24px;line-height:24px;min-width:0;padding:0;--mdc-icon-button-size: 24px;--mdc-icon-button-state-layer-size: 24px}.gap-chip .mat-mdc-button-touch-target{width:24px;height:24px}.gap-chip mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.gap-chip__input{width:42px;border:none;background:transparent;color:var(--md-sys-color-on-surface);font:var(--mdc-typography-body-medium, 600 13px/18px system-ui);text-align:center;outline:none;-moz-appearance:textfield}.gap-chip__input::-webkit-outer-spin-button,.gap-chip__input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.gap-chip__suffix{color:var(--md-sys-color-on-surface-variant);font:var(--mdc-typography-label-medium, 500 12px/16px system-ui)}.gap-pill{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border-radius:12px;background:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);font:var(--mdc-typography-label-medium, 500 12px/16px system-ui)}.chip-title{font:var(--mdc-typography-label-medium, 600 12px/16px system-ui);color:var(--md-sys-color-on-surface-variant);text-transform:uppercase;letter-spacing:.03em}.span-warning{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-error);background:var(--md-sys-color-error-container);border:1px solid var(--md-sys-color-error);border-radius:6px;padding:4px 8px}.row-container{position:relative;display:flex;align-items:stretch}.row{display:flex;flex-grow:1;position:relative;padding-right:0;border-radius:6px;transition:box-shadow .2s ease;gap:var(--pfx-grid-gap, 12px)}.row:focus{outline:none;box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row:focus-visible{box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row.grid-12{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.row.selected{box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row-label{position:absolute;left:-4px;top:-10px;transform:translateY(-100%);background:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;padding:2px 6px;font-size:11px;opacity:0;transition:opacity .15s ease;pointer-events:none}.row:hover .row-label,.row.selected .row-label{opacity:1}.row-actions-meta{margin-left:auto}.column{position:relative;flex:1;display:flex;flex-direction:column;border:1px dashed var(--md-sys-color-outline-variant);margin:0;background:var(--md-sys-color-surface-container);transition:background-color .2s ease,border-color .2s ease;border-radius:8px;overflow:hidden}.column-header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px;background:var(--md-sys-color-surface-variant);border-bottom:1px solid var(--md-sys-color-outline-variant);min-height:36px}.column-content{flex:1;display:grid;align-content:start;gap:var(--px-row-field-gap, 6px);padding:8px}.column-status-pill{display:inline-flex;align-items:center;gap:6px;padding:2px 8px;border-radius:12px;background:var(--md-sys-color-surface);border:1px solid var(--md-sys-color-outline-variant);cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none}.column-status-pill:hover,.column-status-pill.active{background:var(--md-sys-color-surface-variant);border-color:var(--md-sys-color-outline)}.status-bp{font-weight:700;text-transform:uppercase;font-size:11px;color:var(--md-sys-color-primary)}.status-divider{color:var(--md-sys-color-outline-variant)}.status-span,.status-offset{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--md-sys-color-on-surface)}.status-span mat-icon{font-size:14px;width:14px;height:14px}.status-hidden{color:var(--md-sys-color-error);display:flex;align-items:center}.status-hidden mat-icon{font-size:14px;width:14px;height:14px}.column-actions{display:flex;align-items:center;opacity:0;transition:opacity .2s ease}.column:hover .column-actions,.column.selected .column-actions,.column-actions:focus-within{opacity:1}.action-btn{width:24px;height:24px;line-height:24px;padding:0}.action-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.popover-content{padding:12px;display:flex;flex-direction:column;gap:12px;min-width:200px}.control-group{display:flex;flex-direction:column;gap:4px}.control-group label{font-size:11px;color:var(--md-sys-color-on-surface-variant);text-transform:uppercase;font-weight:600}.control-row{display:flex;align-items:center;justify-content:space-between;background:var(--md-sys-color-surface-container-high);border-radius:8px;padding:2px}.value-display{font-weight:600;font-size:13px}.row.grid-12 .column{flex:unset}.column>div{margin:0}.column:focus{outline:none;box-shadow:0 0 0 2px var(--md-sys-color-primary)}.column:focus-visible{box-shadow:0 0 0 2px var(--md-sys-color-primary)}.column.drop-active{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-surface-variant)}.column.selected{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px var(--md-sys-color-primary)}.column.cdk-drop-list-receiving{animation:columnHighlight .3s ease-in-out}@keyframes columnHighlight{0%{box-shadow:0 0 0 2px var(--md-sys-color-primary)}to{box-shadow:none}}.field-selected-highlight.selected .field-item,.selected>.field-item{border-color:var(--md-sys-color-primary)!important;box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row-empty-placeholder{flex:1;border:1px dashed var(--md-sys-color-outline-variant);margin:0;padding:16px;text-align:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container)}.row-placeholder-actions{margin-top:8px;display:flex;gap:8px;justify-content:center}.hidden-overlay{position:absolute;inset:0;background:var(--md-sys-color-surface-container-low);border:1px dashed var(--md-sys-color-outline);display:flex;align-items:center;justify-content:center;gap:6px;color:var(--md-sys-color-on-surface-variant);z-index:2;pointer-events:none}\n"] }]
|
|
14132
|
+
], providers: [providePraxisI18nConfig(LAYOUT_EDITOR_I18N_CONFIG)], template: "<div class=\"row-meta\" *ngIf=\"row\">\n <div class=\"bp-toggle\" role=\"group\" aria-label=\"Breakpoint de visualiza\u00E7\u00E3o\">\n <button\n *ngFor=\"let bp of breakpoints\"\n type=\"button\"\n mat-stroked-button\n class=\"bp-toggle__btn\"\n [class.active]=\"previewBreakpoint === bp\"\n (click)=\"previewBreakpoint = bp\"\n >\n {{ bp }}\n </button>\n </div>\n <div class=\"gap-controls\">\n <div class=\"gap-chip\" *ngIf=\"hasMultipleColumns()\" matTooltip=\"Gap entre colunas (px)\"\n aria-label=\"Gap entre colunas\">\n <span class=\"chip-title\">Colunas</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('gap', -2)\"\n aria-label=\"Reduzir gap de colunas\">\n <mat-icon>remove</mat-icon>\n </button>\n <input class=\"gap-chip__input\" type=\"number\" min=\"0\" [ngModel]=\"row.gap ?? gapGlobal\"\n (ngModelChange)=\"updateRowGap('gap', $event)\" aria-label=\"Valor do gap entre colunas\" />\n <span class=\"gap-chip__suffix\">px</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('gap', 2)\"\n aria-label=\"Aumentar gap de colunas\">\n <mat-icon>add</mat-icon>\n </button>\n </div>\n <div class=\"gap-chip\" matTooltip=\"Gap abaixo da linha (px)\" aria-label=\"Gap abaixo da linha\">\n <span class=\"chip-title\">Linha</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('rowGap', -2)\"\n aria-label=\"Reduzir espa\u00E7o entre campos da linha\" matTooltip=\"Reduz o espa\u00E7o entre campos desta linha\">\n <mat-icon>remove</mat-icon>\n </button>\n <input class=\"gap-chip__input\" type=\"number\" min=\"0\" [ngModel]=\"row.rowGap ?? 0\"\n (ngModelChange)=\"updateRowGap('rowGap', $event)\" aria-label=\"Espa\u00E7o entre campos desta linha\" />\n <span class=\"gap-chip__suffix\">px</span>\n <button mat-icon-button class=\"gap-chip__btn\" (click)=\"adjustRowGapDelta('rowGap', 2)\"\n aria-label=\"Aumentar espa\u00E7o entre campos da linha\" matTooltip=\"Aumenta o espa\u00E7o entre campos desta linha\">\n <mat-icon>add</mat-icon>\n </button>\n <button mat-icon-button class=\"gap-chip__btn\" [matMenuTriggerFor]=\"rowGapMenu\"\n matTooltip=\"Mais op\u00E7\u00F5es para aplicar este espa\u00E7o\" aria-label=\"Mais op\u00E7\u00F5es de aplica\u00E7\u00E3o\">\n <mat-icon>done_all</mat-icon>\n </button>\n <mat-menu #rowGapMenu=\"matMenu\">\n <button mat-menu-item (click)=\"applyRowGapToAll()\">\n <mat-icon>done_all</mat-icon>\n <span>Aplicar em todas as linhas da se\u00E7\u00E3o</span>\n </button>\n <button mat-menu-item (click)=\"clearRowGap()\">\n <mat-icon>undo</mat-icon>\n <span>Voltar ao padr\u00E3o</span>\n </button>\n </mat-menu>\n </div>\n <div class=\"gap-pill\" aria-label=\"Resumo de espa\u00E7amentos\">\n Campos: {{ (row.rowGap ?? 'padr\u00E3o') }}px \u00B7 Colunas: {{ (row.gap ?? gapGlobal) }}px\n </div>\n <div class=\"row-actions-meta\">\n <button mat-icon-button [matMenuTriggerFor]=\"rowMenu\" (click)=\"openRowMenu()\" matTooltip=\"Op\u00E7\u00F5es da linha\">\n <mat-icon>more_vert</mat-icon>\n </button>\n <mat-menu #rowMenu=\"matMenu\" (closed)=\"onMenuClosed()\">\n <ng-container *ngIf=\"menuContext?.type === 'column'; else rowMenuContent\">\n <button mat-menu-item (click)=\"toggleHidden(menuContext!.columnIndex!)\">\n <mat-icon>{{ getHiddenFor(row.columns[menuContext!.columnIndex!]) ? 'visibility' : 'visibility_off'\n }}</mat-icon>\n <span>{{ getHiddenFor(row.columns[menuContext!.columnIndex!]) ? 'Mostrar neste breakpoint' : 'Ocultar neste\n breakpoint' }}</span>\n </button>\n <button mat-menu-item (click)=\"removeColumn(menuContext!.columnIndex!)\">\n <mat-icon color=\"warn\">delete</mat-icon>\n <span>Remover coluna</span>\n </button>\n </ng-container>\n <ng-template #rowMenuContent>\n <div mat-menu-item disabled>Presets de colunas</div>\n <button mat-menu-item (click)=\"applyPreset([12])\"><mat-icon>view_column</mat-icon><span>1/1</span></button>\n <button mat-menu-item (click)=\"applyPreset([6,6])\"><mat-icon>view_column</mat-icon><span>1/2 \u2014\n 1/2</span></button>\n <button mat-menu-item (click)=\"applyPreset([4,8])\"><mat-icon>view_column</mat-icon><span>1/3 \u2014\n 2/3</span></button>\n <button mat-menu-item (click)=\"applyPreset([8,4])\"><mat-icon>view_column</mat-icon><span>2/3 \u2014\n 1/3</span></button>\n <button mat-menu-item (click)=\"applyPreset([4,4,4])\"><mat-icon>view_column</mat-icon><span>1/3 \u2014 1/3 \u2014\n 1/3</span></button>\n <button mat-menu-item (click)=\"applyPreset([3,3,3,3])\"><mat-icon>view_column</mat-icon><span>1/4 \u2014 1/4 \u2014 1/4 \u2014\n 1/4</span></button>\n <button mat-menu-item (click)=\"addColumn()\"><mat-icon>add</mat-icon><span>Adicionar coluna</span></button>\n <button mat-menu-item (click)=\"removeRow()\"><mat-icon>delete</mat-icon><span>Remover linha</span></button>\n </ng-template>\n </mat-menu>\n </div>\n </div>\n <div class=\"span-warning\" *ngIf=\"getSpanTotal(previewBreakpoint) !== 12\">\n <mat-icon color=\"warn\">warning</mat-icon>\n Soma de spans = {{ getSpanTotal(previewBreakpoint) }} (ideal: 12)\n </div>\n</div>\n\n<div class=\"row-container\" [style.marginBottom.px]=\"!isLastRow ? (row.rowGap || null) : null\">\n <ng-container *ngIf=\"row.columns.length > 0; else emptyRow\">\n <div class=\"row grid-12\" cdkDropListGroup (click)=\"selectRow()\" [class.selected]=\"isRowSelected()\" tabindex=\"0\"\n role=\"button\" [attr.aria-label]=\"'Linha ' + (rowIndex + 1)\" [attr.aria-selected]=\"isRowSelected()\"\n [style.--pfx-grid-gap.px]=\"row.gap || null\" [style.--px-row-field-gap.px]=\"row.rowGap ?? null\">\n <div class=\"row-label\" aria-hidden=\"true\">Linha {{ rowIndex + 1 }}</div>\n <div *ngFor=\"let column of row.columns; let i = index\" class=\"column\" [id]=\"getColumnId(i)\" cdkDropList\n [cdkDropListData]=\"column.fields\" [cdkDropListConnectedTo]=\"connectedColumns(i)\"\n (cdkDropListDropped)=\"drop($event)\" (cdkDropListEntered)=\"onDropEnter(i)\" (cdkDropListExited)=\"onDropExit(i)\"\n (click)=\"selectColumn(i, $event)\" [class.drop-active]=\"activeDropIndex === i\"\n [class.selected]=\"isColumnSelected(i)\" [ngClass]=\"getColumnClassList(column)\"\n [style.grid-column]=\"'span ' + getSpanFor(column)\" tabindex=\"0\" role=\"button\"\n [attr.aria-label]=\"'Coluna ' + (i + 1) + ' de Linha ' + (rowIndex + 1) + '; Largura ' + getSpanFor(column)\"\n [attr.aria-selected]=\"isColumnSelected(i)\">\n <div class=\"column-header\">\n <div class=\"column-status-pill\" [matMenuTriggerFor]=\"columnSettingsMenu\"\n matTooltip=\"Clique para ajustar largura e offset\" [class.active]=\"isColumnSelected(i)\">\n <span class=\"status-bp\">{{ previewBreakpoint }}</span>\n <span class=\"status-divider\">\u00B7</span>\n <span class=\"status-span\">\n <mat-icon>view_column</mat-icon>\n {{ getSpanFor(column) }}/12\n </span>\n <span class=\"status-divider\">\u00B7</span>\n <span class=\"status-offset\">\n off {{ getOffsetFor(column) }}\n </span>\n <span class=\"status-hidden\" *ngIf=\"getHiddenFor(column)\">\n <mat-icon>visibility_off</mat-icon>\n </span>\n </div>\n\n <div class=\"column-actions\">\n <button mat-icon-button class=\"action-btn\" [matMenuTriggerFor]=\"columnOverflowMenu\"\n (click)=\"$event.stopPropagation()\" matTooltip=\"Op\u00E7\u00F5es da coluna\">\n <mat-icon>more_vert</mat-icon>\n </button>\n </div>\n </div>\n\n <mat-menu #columnSettingsMenu=\"matMenu\" class=\"column-settings-popover\">\n <div class=\"popover-content\" (click)=\"$event.stopPropagation()\">\n <div class=\"control-group\" *ngIf=\"getSuggestedSpan(i) as suggested\">\n <button mat-flat-button color=\"primary\" (click)=\"setSpan(i, suggested)\"\n matTooltip=\"Ajustar largura para completar 12 colunas\">\n <mat-icon>auto_fix_high</mat-icon>\n Ajustar para {{ suggested }} (Total 12)\n </button>\n </div>\n <div class=\"control-group\">\n <label>Largura ({{ previewBreakpoint }})</label>\n <div class=\"control-row\">\n <button mat-icon-button (click)=\"adjustSpan(i, -1)\"><mat-icon>remove</mat-icon></button>\n <span class=\"value-display\">{{ getSpanFor(column) }} / 12</span>\n <button mat-icon-button (click)=\"adjustSpan(i, 1)\"><mat-icon>add</mat-icon></button>\n </div>\n </div>\n <div class=\"control-group\">\n <label>Offset ({{ previewBreakpoint }})</label>\n <div class=\"control-row\">\n <button mat-icon-button (click)=\"adjustOffset(i, -1)\"><mat-icon>chevron_left</mat-icon></button>\n <span class=\"value-display\">{{ getOffsetFor(column) }}</span>\n <button mat-icon-button (click)=\"adjustOffset(i, 1)\"><mat-icon>chevron_right</mat-icon></button>\n </div>\n </div>\n <div class=\"control-group\">\n <button mat-stroked-button (click)=\"toggleHidden(i)\" [color]=\"getHiddenFor(column) ? 'warn' : ''\">\n <mat-icon>{{ getHiddenFor(column) ? 'visibility' : 'visibility_off' }}</mat-icon>\n {{ getHiddenFor(column) ? 'Mostrar' : 'Ocultar' }}\n </button>\n </div>\n </div>\n </mat-menu>\n\n <mat-menu #columnOverflowMenu=\"matMenu\">\n <button mat-menu-item (click)=\"openColumnConfig(i)\" matTooltip=\"Abrir painel de configura\u00E7\u00E3o completa\">\n <mat-icon>tune</mat-icon>\n <span>Configurar coluna</span>\n </button>\n <button mat-menu-item [matMenuTriggerFor]=\"apiFieldMenu\" [matTooltip]=\"t('apiFields.addTooltip')\">\n <mat-icon>input</mat-icon>\n <span>{{ t('apiFields.addAction') }}</span>\n </button>\n <mat-menu #apiFieldMenu=\"matMenu\">\n <button\n mat-menu-item\n *ngFor=\"let field of availableFields\"\n (click)=\"addApiFieldToColumn(i, field.name)\"\n >\n <mat-icon>short_text</mat-icon>\n <span>{{ getFieldLabel(field) }}</span>\n </button>\n <button mat-menu-item disabled *ngIf=\"!availableFields.length\">\n <span>{{ t('apiFields.empty') }}</span>\n </button>\n </mat-menu>\n <button mat-menu-item [matMenuTriggerFor]=\"visualBlockPresetMenu\" [matTooltip]=\"t('visualBlock.addTooltip')\">\n <mat-icon>notes</mat-icon>\n <span>{{ t('visualBlock.addAction') }}</span>\n </button>\n <mat-menu #visualBlockPresetMenu=\"matMenu\">\n <button\n mat-menu-item\n *ngFor=\"let preset of visualBlockPresets\"\n (click)=\"addVisualBlockToColumn(i, preset.id)\"\n >\n <mat-icon>{{ preset.icon }}</mat-icon>\n <span>{{ t(preset.labelKey) }}</span>\n </button>\n </mat-menu>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"moveColumn(i, -1)\" [disabled]=\"i === 0\"\n matTooltip=\"Mover coluna para a esquerda\">\n <mat-icon>arrow_back</mat-icon>\n <span>Mover para esquerda</span>\n </button>\n <button mat-menu-item (click)=\"moveColumn(i, 1)\" [disabled]=\"i === row.columns.length - 1\"\n matTooltip=\"Mover coluna para a direita\">\n <mat-icon>arrow_forward</mat-icon>\n <span>Mover para direita</span>\n </button>\n\n <button mat-menu-item (click)=\"clearColumn(i)\" [disabled]=\"!hasColumnContent(column)\"\n matTooltip=\"Remover todo o conte\u00C3\u00BAdo desta coluna\">\n <mat-icon>backspace</mat-icon>\n <span>Limpar conte\u00FAdo</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"removeColumn(i)\" matTooltip=\"Excluir esta coluna\">\n <mat-icon color=\"warn\">delete</mat-icon>\n <span>Remover coluna</span>\n </button>\n </mat-menu>\n <div class=\"column-content\">\n <div class=\"hidden-overlay\" *ngIf=\"getHiddenFor(column)\">\n <mat-icon aria-hidden=\"true\">visibility_off</mat-icon>\n <span>Oculta em {{ previewBreakpoint }}</span>\n </div>\n <ng-container *ngIf=\"hasColumnContent(column); else emptyColumn\">\n <ng-container *ngFor=\"let item of getColumnLayoutItems(column); let itemIndex = index\">\n <div *ngIf=\"item.kind === 'field'; else visualBlockItem\" (click)=\"selectField(item.fieldName, $event)\"\n [class.selected]=\"isFieldSelected(item.fieldName)\">\n <praxis-field-configurator [field]=\"getFieldByName(item.fieldName)\"></praxis-field-configurator>\n </div>\n <ng-template #visualBlockItem>\n <div\n class=\"visual-block-preview\"\n *ngIf=\"item.kind === 'richContent'\"\n role=\"button\"\n tabindex=\"0\"\n [class.selected]=\"selected?.type === 'visualBlock' && selected?.itemId === item.id\"\n (click)=\"selectVisualBlock(i, item, $event)\"\n (dblclick)=\"openVisualBlockEditor(i, item, $event)\"\n >\n <mat-icon aria-hidden=\"true\">notes</mat-icon>\n <span>{{ getVisualBlockLabel(item) }}</span>\n <span class=\"visual-block-preview__actions\">\n <button\n mat-icon-button\n class=\"visual-block-preview__action\"\n type=\"button\"\n [matTooltip]=\"t('visualBlock.moveUp')\"\n [attr.aria-label]=\"t('visualBlock.moveUp')\"\n [disabled]=\"itemIndex === 0\"\n (click)=\"moveVisualBlockItem(i, item, -1, $event)\"\n >\n <mat-icon>arrow_upward</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"visual-block-preview__action\"\n type=\"button\"\n [matTooltip]=\"t('visualBlock.moveDown')\"\n [attr.aria-label]=\"t('visualBlock.moveDown')\"\n [disabled]=\"itemIndex === getColumnLayoutItems(column).length - 1\"\n (click)=\"moveVisualBlockItem(i, item, 1, $event)\"\n >\n <mat-icon>arrow_downward</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"visual-block-preview__action\"\n type=\"button\"\n [matTooltip]=\"t('visualBlock.movePreviousColumn')\"\n [attr.aria-label]=\"t('visualBlock.movePreviousColumn')\"\n [disabled]=\"!canMoveVisualBlockToColumn(i, -1)\"\n (click)=\"moveVisualBlockToAdjacentColumn(i, item, -1, $event)\"\n >\n <mat-icon>arrow_back</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"visual-block-preview__action\"\n type=\"button\"\n [matTooltip]=\"t('visualBlock.moveNextColumn')\"\n [attr.aria-label]=\"t('visualBlock.moveNextColumn')\"\n [disabled]=\"!canMoveVisualBlockToColumn(i, 1)\"\n (click)=\"moveVisualBlockToAdjacentColumn(i, item, 1, $event)\"\n >\n <mat-icon>arrow_forward</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"visual-block-preview__action\"\n type=\"button\"\n [matTooltip]=\"t('visualBlock.editAction')\"\n [attr.aria-label]=\"t('visualBlock.editAction')\"\n (click)=\"openVisualBlockEditor(i, item, $event)\"\n >\n <mat-icon>edit</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"visual-block-preview__action\"\n type=\"button\"\n color=\"warn\"\n [matTooltip]=\"t('visualBlock.removeAction')\"\n [attr.aria-label]=\"t('visualBlock.removeAction')\"\n (click)=\"removeVisualBlockItem(i, item, $event)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </span>\n </div>\n </ng-template>\n </ng-container>\n </ng-container>\n <ng-template #emptyColumn>\n <div class=\"column-placeholder\">\n <span>Coluna vazia \u2014 solte um campo ou remova.</span>\n </div>\n </ng-template>\n </div>\n </div>\n </div>\n </ng-container>\n <ng-template #emptyRow>\n <div class=\"row-empty-placeholder\">\n <span>Linha vazia \u2014 crie colunas ou remova.</span>\n <div class=\"row-placeholder-actions\">\n <button mat-stroked-button (click)=\"addColumn()\" matTooltip=\"Adicionar coluna\">\n <mat-icon>add</mat-icon> Adicionar coluna\n </button>\n <button mat-stroked-button color=\"warn\" (click)=\"removeRow()\" matTooltip=\"Remover linha\">\n <mat-icon>delete</mat-icon> Remover linha\n </button>\n </div>\n </div>\n </ng-template>\n</div>\n", styles: [".row-meta{display:flex;align-items:center;gap:8px;margin-bottom:8px;flex-wrap:wrap}.bp-toggle{display:inline-flex;gap:4px;align-items:center}.bp-toggle__btn{min-width:34px;height:30px;line-height:30px;padding:0 8px;text-transform:uppercase}.bp-toggle__btn.active{background:var(--md-sys-color-primary-container);color:var(--md-sys-color-on-primary-container)}.gap-controls{display:flex;gap:8px;flex-wrap:wrap;align-items:center}.gap-chip{display:inline-flex;align-items:center;gap:2px;padding:0 4px;height:32px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-variant)}.gap-chip__btn{width:24px;height:24px;line-height:24px;min-width:0;padding:0;--mdc-icon-button-size: 24px;--mdc-icon-button-state-layer-size: 24px}.gap-chip .mat-mdc-button-touch-target{width:24px;height:24px}.gap-chip mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.gap-chip__input{width:42px;border:none;background:transparent;color:var(--md-sys-color-on-surface);font:var(--mdc-typography-body-medium, 600 13px/18px system-ui);text-align:center;outline:none;-moz-appearance:textfield}.gap-chip__input::-webkit-outer-spin-button,.gap-chip__input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.gap-chip__suffix{color:var(--md-sys-color-on-surface-variant);font:var(--mdc-typography-label-medium, 500 12px/16px system-ui)}.gap-pill{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border-radius:12px;background:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);font:var(--mdc-typography-label-medium, 500 12px/16px system-ui)}.chip-title{font:var(--mdc-typography-label-medium, 600 12px/16px system-ui);color:var(--md-sys-color-on-surface-variant);text-transform:uppercase;letter-spacing:.03em}.span-warning{display:inline-flex;align-items:center;gap:6px;color:var(--md-sys-color-on-error);background:var(--md-sys-color-error-container);border:1px solid var(--md-sys-color-error);border-radius:6px;padding:4px 8px}.row-container{position:relative;display:flex;align-items:stretch}.row{display:flex;flex-grow:1;position:relative;padding-right:0;border-radius:6px;transition:box-shadow .2s ease;gap:var(--pfx-grid-gap, 12px)}.row:focus{outline:none;box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row:focus-visible{box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row.grid-12{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:var(--pfx-grid-gap, 16px)}.row.selected{box-shadow:0 0 0 2px var(--md-sys-color-primary)}.row-label{position:absolute;left:-4px;top:-10px;transform:translateY(-100%);background:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);border:1px solid var(--md-sys-color-outline-variant);border-radius:10px;padding:2px 6px;font-size:11px;opacity:0;transition:opacity .15s ease;pointer-events:none}.row:hover .row-label,.row.selected .row-label{opacity:1}.row-actions-meta{margin-left:auto}.column{position:relative;flex:1;display:flex;flex-direction:column;border:1px dashed var(--md-sys-color-outline-variant);margin:0;background:var(--md-sys-color-surface-container);transition:background-color .2s ease,border-color .2s ease;border-radius:8px;overflow:hidden}.column-header{display:flex;align-items:center;justify-content:space-between;padding:4px 8px;background:var(--md-sys-color-surface-variant);border-bottom:1px solid var(--md-sys-color-outline-variant);min-height:36px}.column-content{flex:1;display:grid;align-content:start;gap:var(--px-row-field-gap, 6px);padding:8px}.column-status-pill{display:inline-flex;align-items:center;gap:6px;padding:2px 8px;border-radius:12px;background:var(--md-sys-color-surface);border:1px solid var(--md-sys-color-outline-variant);cursor:pointer;transition:all .2s ease;-webkit-user-select:none;user-select:none}.column-status-pill:hover,.column-status-pill.active{background:var(--md-sys-color-surface-variant);border-color:var(--md-sys-color-outline)}.status-bp{font-weight:700;text-transform:uppercase;font-size:11px;color:var(--md-sys-color-primary)}.status-divider{color:var(--md-sys-color-outline-variant)}.status-span,.status-offset{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--md-sys-color-on-surface)}.status-span mat-icon{font-size:14px;width:14px;height:14px}.status-hidden{color:var(--md-sys-color-error);display:flex;align-items:center}.status-hidden mat-icon{font-size:14px;width:14px;height:14px}.column-actions{display:flex;align-items:center;opacity:0;transition:opacity .2s ease}.column:hover .column-actions,.column.selected .column-actions,.column-actions:focus-within{opacity:1}.action-btn{width:24px;height:24px;line-height:24px;padding:0}.action-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.popover-content{padding:12px;display:flex;flex-direction:column;gap:12px;min-width:200px}.control-group{display:flex;flex-direction:column;gap:4px}.control-group label{font-size:11px;color:var(--md-sys-color-on-surface-variant);text-transform:uppercase;font-weight:600}.control-row{display:flex;align-items:center;justify-content:space-between;background:var(--md-sys-color-surface-container-high);border-radius:8px;padding:2px}.value-display{font-weight:600;font-size:13px}.row.grid-12 .column{flex:unset}.column>div{margin:0}.column:focus{outline:none;box-shadow:0 0 0 2px var(--md-sys-color-primary)}.column:focus-visible{box-shadow:0 0 0 2px var(--md-sys-color-primary)}.column.drop-active{border-color:var(--md-sys-color-primary);background:var(--md-sys-color-surface-variant)}.column.selected{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px var(--md-sys-color-primary)}.column.cdk-drop-list-receiving{animation:columnHighlight .3s ease-in-out}@keyframes columnHighlight{0%{box-shadow:0 0 0 2px var(--md-sys-color-primary)}to{box-shadow:none}}.field-selected-highlight.selected .field-item,.selected>.field-item{border-color:var(--md-sys-color-primary)!important;box-shadow:0 0 0 2px var(--md-sys-color-primary)}.visual-block-preview{display:flex;align-items:center;gap:8px;min-height:36px;padding:8px;border:1px dashed var(--md-sys-color-outline-variant);border-radius:6px;background:var(--md-sys-color-surface);color:var(--md-sys-color-on-surface-variant);font-size:13px;cursor:pointer}.visual-block-preview.selected{border-color:var(--md-sys-color-primary);box-shadow:0 0 0 2px var(--md-sys-color-primary)}.visual-block-preview mat-icon{font-size:18px;width:18px;height:18px}.visual-block-preview__actions{margin-left:auto;display:inline-flex;align-items:center;gap:2px}.visual-block-preview__action{width:28px;height:28px;--mdc-icon-button-size: 28px;--mdc-icon-button-state-layer-size: 28px}.row-empty-placeholder{flex:1;border:1px dashed var(--md-sys-color-outline-variant);margin:0;padding:16px;text-align:center;color:var(--md-sys-color-on-surface-variant);background:var(--md-sys-color-surface-container)}.row-placeholder-actions{margin-top:8px;display:flex;gap:8px;justify-content:center}.hidden-overlay{position:absolute;inset:0;background:var(--md-sys-color-surface-container-low);border:1px dashed var(--md-sys-color-outline);display:flex;align-items:center;justify-content:center;gap:6px;color:var(--md-sys-color-on-surface-variant);z-index:2;pointer-events:none}\n"] }]
|
|
13520
14133
|
}], propDecorators: { row: [{
|
|
13521
14134
|
type: Input
|
|
13522
14135
|
}], fieldMetadata: [{
|
|
13523
14136
|
type: Input
|
|
14137
|
+
}], availableFields: [{
|
|
14138
|
+
type: Input
|
|
13524
14139
|
}], sectionIndex: [{
|
|
13525
14140
|
type: Input
|
|
13526
14141
|
}], rowIndex: [{
|
|
@@ -13543,6 +14158,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
13543
14158
|
type: Output
|
|
13544
14159
|
}], fieldDrop: [{
|
|
13545
14160
|
type: Output
|
|
14161
|
+
}], addVisualBlock: [{
|
|
14162
|
+
type: Output
|
|
14163
|
+
}], addApiField: [{
|
|
14164
|
+
type: Output
|
|
14165
|
+
}], editVisualBlock: [{
|
|
14166
|
+
type: Output
|
|
14167
|
+
}], moveVisualBlock: [{
|
|
14168
|
+
type: Output
|
|
14169
|
+
}], moveVisualBlockToColumn: [{
|
|
14170
|
+
type: Output
|
|
14171
|
+
}], removeVisualBlock: [{
|
|
14172
|
+
type: Output
|
|
13546
14173
|
}], select: [{
|
|
13547
14174
|
type: Output
|
|
13548
14175
|
}] } });
|
|
@@ -13812,6 +14439,7 @@ class SectionConfiguratorComponent {
|
|
|
13812
14439
|
sectionIndex;
|
|
13813
14440
|
allSections = [];
|
|
13814
14441
|
fieldMetadata = [];
|
|
14442
|
+
availableFields = [];
|
|
13815
14443
|
selected = null;
|
|
13816
14444
|
availableFieldsListId = 'available-fields-list';
|
|
13817
14445
|
columnDropListIds = [];
|
|
@@ -13821,6 +14449,12 @@ class SectionConfiguratorComponent {
|
|
|
13821
14449
|
remove = new EventEmitter();
|
|
13822
14450
|
select = new EventEmitter();
|
|
13823
14451
|
fieldDrop = new EventEmitter();
|
|
14452
|
+
addVisualBlock = new EventEmitter();
|
|
14453
|
+
addApiField = new EventEmitter();
|
|
14454
|
+
editVisualBlock = new EventEmitter();
|
|
14455
|
+
moveVisualBlock = new EventEmitter();
|
|
14456
|
+
moveVisualBlockToColumn = new EventEmitter();
|
|
14457
|
+
removeVisualBlock = new EventEmitter();
|
|
13824
14458
|
isHovered = false;
|
|
13825
14459
|
isCollapsed = false;
|
|
13826
14460
|
constructor(dialog, presetRegistry, settingsPanel) {
|
|
@@ -13895,6 +14529,56 @@ class SectionConfiguratorComponent {
|
|
|
13895
14529
|
onFieldDrop(event, rowIndex) {
|
|
13896
14530
|
this.fieldDrop.emit({ event, sectionIndex: this.sectionIndex, rowIndex });
|
|
13897
14531
|
}
|
|
14532
|
+
onAddVisualBlock(event) {
|
|
14533
|
+
this.addVisualBlock.emit({
|
|
14534
|
+
sectionIndex: this.sectionIndex,
|
|
14535
|
+
rowIndex: event.rowIndex,
|
|
14536
|
+
columnIndex: event.columnIndex,
|
|
14537
|
+
presetId: event.presetId,
|
|
14538
|
+
});
|
|
14539
|
+
}
|
|
14540
|
+
onAddApiField(event) {
|
|
14541
|
+
this.addApiField.emit({
|
|
14542
|
+
sectionIndex: this.sectionIndex,
|
|
14543
|
+
rowIndex: event.rowIndex,
|
|
14544
|
+
columnIndex: event.columnIndex,
|
|
14545
|
+
fieldName: event.fieldName,
|
|
14546
|
+
});
|
|
14547
|
+
}
|
|
14548
|
+
onEditVisualBlock(event) {
|
|
14549
|
+
this.editVisualBlock.emit({
|
|
14550
|
+
sectionIndex: this.sectionIndex,
|
|
14551
|
+
rowIndex: event.rowIndex,
|
|
14552
|
+
columnIndex: event.columnIndex,
|
|
14553
|
+
itemId: event.itemId,
|
|
14554
|
+
});
|
|
14555
|
+
}
|
|
14556
|
+
onMoveVisualBlock(event) {
|
|
14557
|
+
this.moveVisualBlock.emit({
|
|
14558
|
+
sectionIndex: this.sectionIndex,
|
|
14559
|
+
rowIndex: event.rowIndex,
|
|
14560
|
+
columnIndex: event.columnIndex,
|
|
14561
|
+
itemId: event.itemId,
|
|
14562
|
+
direction: event.direction,
|
|
14563
|
+
});
|
|
14564
|
+
}
|
|
14565
|
+
onMoveVisualBlockToColumn(event) {
|
|
14566
|
+
this.moveVisualBlockToColumn.emit({
|
|
14567
|
+
sectionIndex: this.sectionIndex,
|
|
14568
|
+
rowIndex: event.rowIndex,
|
|
14569
|
+
columnIndex: event.columnIndex,
|
|
14570
|
+
targetColumnIndex: event.targetColumnIndex,
|
|
14571
|
+
itemId: event.itemId,
|
|
14572
|
+
});
|
|
14573
|
+
}
|
|
14574
|
+
onRemoveVisualBlock(event) {
|
|
14575
|
+
this.removeVisualBlock.emit({
|
|
14576
|
+
sectionIndex: this.sectionIndex,
|
|
14577
|
+
rowIndex: event.rowIndex,
|
|
14578
|
+
columnIndex: event.columnIndex,
|
|
14579
|
+
itemId: event.itemId,
|
|
14580
|
+
});
|
|
14581
|
+
}
|
|
13898
14582
|
onRemoveSection() {
|
|
13899
14583
|
this.remove.emit();
|
|
13900
14584
|
}
|
|
@@ -14050,7 +14734,7 @@ class SectionConfiguratorComponent {
|
|
|
14050
14734
|
this.applyStyleToAll.emit(patch);
|
|
14051
14735
|
}
|
|
14052
14736
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: SectionConfiguratorComponent, deps: [{ token: i2$1.MatDialog }, { token: SectionPresetRegistry }, { token: i7.SettingsPanelService }], target: i0.ɵɵFactoryTarget.Component });
|
|
14053
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: SectionConfiguratorComponent, isStandalone: true, selector: "praxis-section-configurator", inputs: { section: "section", sectionIndex: "sectionIndex", allSections: "allSections", fieldMetadata: "fieldMetadata", selected: "selected", availableFieldsListId: "availableFieldsListId", columnDropListIds: "columnDropListIds", gapGlobal: "gapGlobal" }, outputs: { sectionChange: "sectionChange", applyStyleToAll: "applyStyleToAll", remove: "remove", select: "select", fieldDrop: "fieldDrop" }, ngImport: i0, template: "<mat-card\n class=\"section-card\"\n cdkDrag\n (mouseenter)=\"onMouseEnter()\"\n (mouseleave)=\"onMouseLeave()\"\n [class.hovered]=\"isHovered\"\n [class.selected]=\"isThisSectionSelected()\"\n [class.collapsed]=\"isCollapsed\"\n (click)=\"onSelectSection()\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'Se\u00E7\u00E3o ' + (sectionIndex + 1)\"\n [attr.aria-selected]=\"isThisSectionSelected()\"\n>\n <mat-card-header class=\"section-header\">\n <mat-card-title class=\"title-wrapper\">\n <div class=\"section-heading\">\n @let headerPreview = getSectionHeaderPreview();\n @let headerAvatarSize = getSectionHeaderAvatarSize();\n @if (headerPreview.kind === 'icon') {\n <mat-icon class=\"section-heading__icon\" aria-hidden=\"true\" [praxisIcon]=\"headerPreview.icon\"></mat-icon>\n }\n @if (headerPreview.kind === 'initials') {\n <span class=\"section-heading__avatar section-heading__avatar--text\" [class.size-sm]=\"headerAvatarSize === 'sm'\"\n [class.size-md]=\"headerAvatarSize === 'md'\" [class.size-lg]=\"headerAvatarSize === 'lg'\"\n [matTooltip]=\"headerPreview.tooltip || ''\" [matTooltipDisabled]=\"!headerPreview.tooltip\">\n {{ headerPreview.text }}\n </span>\n }\n @if (headerPreview.kind === 'placeholder') {\n <span class=\"section-heading__avatar section-heading__avatar--placeholder\" [class.size-sm]=\"headerAvatarSize === 'sm'\"\n [class.size-md]=\"headerAvatarSize === 'md'\" [class.size-lg]=\"headerAvatarSize === 'lg'\"\n [matTooltip]=\"headerPreview.tooltip || ''\" [matTooltipDisabled]=\"!headerPreview.tooltip\">\n @if (headerPreview.icon) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"headerPreview.icon\"></mat-icon>\n }\n </span>\n }\n <div class=\"section-heading__text\">\n <span class=\"section-name\">{{ section.title || 'Sem t\u00EDtulo' }}</span>\n <span class=\"section-desc\" *ngIf=\"section.description\">{{ section.description }}</span>\n </div>\n </div>\n <button\n mat-icon-button\n type=\"button\"\n color=\"primary\"\n class=\"section-editor-trigger\"\n (click)=\"openAdvancedEditor($event)\"\n matTooltip=\"Para editar o t\u00EDtulo, use o editor completo da se\u00E7\u00E3o\"\n aria-label=\"Abrir editor da se\u00E7\u00E3o\"\n >\n <mat-icon>open_in_new</mat-icon>\n </button>\n </mat-card-title>\n <div class=\"section-header-actions\">\n <button\n mat-icon-button\n class=\"section-collapse-btn\"\n type=\"button\"\n (click)=\"toggleCollapsed($event)\"\n [attr.aria-expanded]=\"!isCollapsed\"\n [attr.aria-label]=\"isCollapsed ? 'Expandir se\u00E7\u00E3o' : 'Colapsar se\u00E7\u00E3o'\"\n [matTooltip]=\"isCollapsed ? 'Expandir se\u00E7\u00E3o' : 'Colapsar se\u00E7\u00E3o'\"\n >\n <mat-icon>{{ isCollapsed ? 'unfold_more' : 'unfold_less' }}</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"section-menu-btn\"\n [matMenuTriggerFor]=\"sectionMenu\"\n aria-label=\"Mais a\u00E7\u00F5es da se\u00E7\u00E3o\"\n matTooltip=\"Mais a\u00E7\u00F5es\"\n >\n <mat-icon [praxisIcon]=\"'more_vert'\"></mat-icon>\n </button>\n </div>\n <mat-menu #sectionMenu=\"matMenu\">\n <button mat-menu-item (click)=\"openSectionPresets()\">\n <mat-icon [praxisIcon]=\"'view_quilt'\"></mat-icon>\n <span>Presets de se\u00E7\u00E3o\u2026</span>\n </button>\n <button mat-menu-item (click)=\"applyCurrentStyleToAll()\">\n <mat-icon [praxisIcon]=\"'format_paint'\"></mat-icon>\n <span>Aplicar estilo desta se\u00E7\u00E3o a todas</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item *ngIf=\"section.description == null\" (click)=\"section.description = ''; onSectionUpdated()\">\n <mat-icon [praxisIcon]=\"'note_add'\"></mat-icon>\n <span>Adicionar descri\u00E7\u00E3o</span>\n </button>\n <button mat-menu-item *ngIf=\"section.description != null\" (click)=\"section.description = undefined; onSectionUpdated()\">\n <mat-icon [praxisIcon]=\"'backspace'\"></mat-icon>\n <span>Remover descri\u00E7\u00E3o</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"onRemoveSection()\">\n <mat-icon [praxisIcon]=\"'delete'\"></mat-icon>\n <span>Remover se\u00E7\u00E3o</span>\n </button>\n </mat-menu>\n </mat-card-header>\n <mat-card-content [attr.aria-hidden]=\"isCollapsed\">\n <ng-container *ngIf=\"isThisSectionSelected(); else linhasTitle\">\n <div class=\"section-breadcrumbs\" (click)=\"$event.stopPropagation()\">\n <button\n type=\"button\"\n class=\"crumb as-button\"\n data-crumb=\"layout\"\n [attr.aria-label]=\"'Voltar ao Layout'\"\n disabled\n >\n Layout\n </button>\n <span class=\"sep\">\u203A</span>\n <button\n type=\"button\"\n class=\"crumb as-button crumb-section\"\n data-crumb=\"section\"\n (click)=\"onSelectSectionFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Selecionar Se\u00E7\u00E3o ' + (sectionIndex + 1)\"\n >\n Se\u00E7\u00E3o {{ sectionIndex + 1 }}\n </button>\n <ng-container *ngIf=\"selected?.rowIndex != null\">\n <span class=\"sep\">\u203A</span>\n <button\n type=\"button\"\n class=\"crumb as-button crumb-row\"\n data-crumb=\"row\"\n (click)=\"onSelectRowFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Selecionar Linha ' + (selected!.rowIndex! + 1)\"\n >\n Linha {{ selected!.rowIndex! + 1 }}\n </button>\n </ng-container>\n <ng-container *ngIf=\"selected?.columnIndex != null\">\n <span class=\"sep\">\u203A</span>\n <button\n type=\"button\"\n class=\"crumb as-button crumb-column\"\n data-crumb=\"column\"\n (click)=\"onSelectColumnFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Selecionar Coluna ' + (selected!.columnIndex! + 1)\"\n >\n Coluna {{ selected!.columnIndex! + 1 }}\n </button>\n </ng-container>\n <ng-container *ngIf=\"selected?.fieldName\">\n <span class=\"sep\">\u203A</span>\n <span class=\"crumb active\">{{ selected!.fieldName }}</span>\n </ng-container>\n <button\n *ngIf=\"selected\"\n type=\"button\"\n class=\"crumb as-button crumb-clear\"\n data-crumb=\"clear\"\n (click)=\"onClearSelectionFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Limpar sele\u00E7\u00E3o'\"\n >\n Limpar\n </button>\n </div>\n </ng-container>\n <ng-template #linhasTitle>\n <h5>Linhas</h5>\n </ng-template>\n <div\n class=\"row-list\"\n cdkDropList\n [cdkDropListData]=\"section.rows\"\n (cdkDropListDropped)=\"dropRow($event)\"\n >\n <praxis-row-configurator\n *ngFor=\"let row of section.rows; let i = index\"\n class=\"row-item\"\n [row]=\"row\"\n [fieldMetadata]=\"fieldMetadata\"\n [sectionIndex]=\"sectionIndex\"\n [rowIndex]=\"i\"\n [isLastRow]=\"i === section.rows.length - 1\"\n [selected]=\"selected\"\n [availableFieldsListId]=\"availableFieldsListId\"\n [connectedDropListIds]=\"columnDropListIds\"\n [gapGlobal]=\"gapGlobal\"\n (rowChange)=\"onRowUpdated(i, $event)\"\n (applyRowGapAll)=\"onApplyRowGapAll($event)\"\n (remove)=\"removeRow(i)\"\n (select)=\"select.emit($event)\"\n (fieldDrop)=\"onFieldDrop($event, i)\"\n cdkDrag\n ></praxis-row-configurator>\n </div>\n <div class=\"section-actions\" aria-label=\"A\u00E7\u00F5es da se\u00E7\u00E3o\">\n <button\n class=\"fab-add-row\"\n mat-fab\n color=\"primary\"\n (click)=\"addRow()\"\n matTooltip=\"Adicionar linha\"\n aria-label=\"Adicionar linha\"\n >\n <mat-icon>add</mat-icon>\n </button>\n </div>\n </mat-card-content>\n</mat-card>\n", styles: ["@charset \"UTF-8\";.section-card{background:var(--md-sys-color-surface, var(--sicoob-bg-elev-1));margin-bottom:16px;transition:border-color .2s ease;border:1px solid transparent}.section-card.hovered{border-color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-card.selected{border-color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)));box-shadow:0 0 0 2px var(--md-sys-color-primary)}.section-card:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)));outline-offset:2px}.section-card .mat-mdc-card-content{padding-bottom:var(--px-editor-section-gap, 16px)}.section-breadcrumbs{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin:4px 0 8px;display:flex;align-items:center;gap:6px}.section-breadcrumbs .as-button{background:transparent;border:none;padding:0 2px;color:inherit;font:inherit;cursor:pointer;border-radius:4px}.section-breadcrumbs .as-button:hover{color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-breadcrumbs .as-button:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)));outline-offset:2px}.section-breadcrumbs .crumb-clear{margin-left:6px;opacity:.85}.section-breadcrumbs .crumb.active{color:var(--md-sys-color-on-surface);font-weight:600}.section-breadcrumbs .sep{opacity:.6}.section-header{display:flex;justify-content:space-between;align-items:center;gap:12px;min-height:56px}.title-wrapper{display:flex;align-items:center;gap:8px;width:100%;min-width:0;flex:1 1 auto}.section-heading{display:flex;align-items:center;gap:10px;min-width:0}.section-heading__icon{color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-heading__avatar{--_pfx-layout-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-layout-section-avatar-size);height:var(--_pfx-layout-section-avatar-size);border-radius:999px;flex:0 0 var(--_pfx-layout-section-avatar-size);overflow:hidden}.section-heading__avatar.size-sm{--_pfx-layout-section-avatar-size: var(--pfx-form-section-avatar-size-sm, 24px)}.section-heading__avatar.size-md{--_pfx-layout-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px))}.section-heading__avatar.size-lg{--_pfx-layout-section-avatar-size: var(--pfx-form-section-avatar-size-lg, 40px)}.section-heading__avatar--text,.section-heading__avatar--placeholder{background:color-mix(in srgb,var(--pfx-editorial-form-accent, var(--md-sys-color-primary, var(--sicoob-primary-default))) 14%,var(--pfx-form-section-surface-flat, var(--md-sys-color-surface, var(--sicoob-bg-elev-1))));color:color-mix(in srgb,var(--pfx-editorial-form-accent, var(--md-sys-color-primary, var(--sicoob-primary-default))) 82%,var(--pfx-form-label-strong, var(--md-sys-color-on-surface, var(--sicoob-text-default))) 18%);font-size:calc(var(--_pfx-layout-section-avatar-size) * .41);font-weight:800;letter-spacing:.04em;text-transform:uppercase}.section-heading__avatar--placeholder mat-icon{font-size:calc(var(--_pfx-layout-section-avatar-size) * .5625);width:calc(var(--_pfx-layout-section-avatar-size) * .5625);height:calc(var(--_pfx-layout-section-avatar-size) * .5625);line-height:calc(var(--_pfx-layout-section-avatar-size) * .5625)}.section-heading__text{display:flex;flex-direction:column;align-items:flex-start;min-width:0}.section-heading .section-name{font-weight:600;color:var(--md-sys-color-on-surface);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-heading .section-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-editor-trigger{margin-left:auto}.section-header-actions{display:inline-flex;align-items:center;gap:4px;flex-shrink:0}.section-header-actions .mat-mdc-icon-button{width:36px;height:36px;padding:6px}.add-row-button{margin-top:8px}.row-item{animation:fadeIn .3s ease}@keyframes fadeIn{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}.section-card:hover{border-color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-card.collapsed .mat-mdc-card-content{display:none}:host ::ng-deep .section-card .mat-mdc-card-header{padding:8px 12px}:host ::ng-deep .section-card .mat-mdc-card-title{margin:0}:host ::ng-deep .section-card .mat-mdc-card-content{padding:0 12px 12px}.section-actions{position:relative;margin-top:12px;padding-top:16px;border-top:1px solid var(--md-sys-color-outline-variant, var(--md-sys-color-outline-variant, var(--sicoob-stroke-medium)));min-height:28px}.row-list{border-top:1px solid var(--px-editor-separator-color, var(--md-sys-color-outline-variant));padding-top:12px;margin-top:8px}.fab-add-row{position:absolute;top:-15px;left:50%;transform:translate(-50%,calc(-50% - var(--pfx-divider-w, 1px)));z-index:2;--pfx-fab-size: var(--pfx-fab-size-row, 32px);--pfx-fab-icon: var(--pfx-fab-icon-row, 18px);width:var(--pfx-fab-size);height:var(--pfx-fab-size);border-radius:50%}.fab-add-row.mat-mdc-fab{width:var(--pfx-fab-size);height:var(--pfx-fab-size);padding:0}.fab-add-row .mat-mdc-button-touch-target,.fab-add-row .mat-mdc-button-persistent-ripple,.fab-add-row .mat-mdc-button-ripple{width:var(--pfx-fab-size);height:var(--pfx-fab-size)}.fab-add-row mat-icon{font-size:var(--pfx-fab-icon);width:var(--pfx-fab-icon);height:var(--pfx-fab-icon)}\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: DragDropModule }, { kind: "directive", type: i2$2.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i2$2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: RowConfiguratorComponent, selector: "praxis-row-configurator", inputs: ["row", "fieldMetadata", "sectionIndex", "rowIndex", "isLastRow", "selected", "availableFieldsListId", "connectedDropListIds", "gapGlobal"], outputs: ["rowChange", "remove", "applyRowGapAll", "fieldDrop", "select"] }, { kind: "ngmodule", type: MatButtonModule }, { 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: 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: MatCardModule }, { kind: "component", type: i8.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i8.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i8.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i8.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i6.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i6.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i6.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }] });
|
|
14737
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: SectionConfiguratorComponent, isStandalone: true, selector: "praxis-section-configurator", inputs: { section: "section", sectionIndex: "sectionIndex", allSections: "allSections", fieldMetadata: "fieldMetadata", availableFields: "availableFields", selected: "selected", availableFieldsListId: "availableFieldsListId", columnDropListIds: "columnDropListIds", gapGlobal: "gapGlobal" }, outputs: { sectionChange: "sectionChange", applyStyleToAll: "applyStyleToAll", remove: "remove", select: "select", fieldDrop: "fieldDrop", addVisualBlock: "addVisualBlock", addApiField: "addApiField", editVisualBlock: "editVisualBlock", moveVisualBlock: "moveVisualBlock", moveVisualBlockToColumn: "moveVisualBlockToColumn", removeVisualBlock: "removeVisualBlock" }, ngImport: i0, template: "<mat-card\n class=\"section-card\"\n cdkDrag\n (mouseenter)=\"onMouseEnter()\"\n (mouseleave)=\"onMouseLeave()\"\n [class.hovered]=\"isHovered\"\n [class.selected]=\"isThisSectionSelected()\"\n [class.collapsed]=\"isCollapsed\"\n (click)=\"onSelectSection()\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'Se\u00E7\u00E3o ' + (sectionIndex + 1)\"\n [attr.aria-selected]=\"isThisSectionSelected()\"\n>\n <mat-card-header class=\"section-header\">\n <mat-card-title class=\"title-wrapper\">\n <div class=\"section-heading\">\n @let headerPreview = getSectionHeaderPreview();\n @let headerAvatarSize = getSectionHeaderAvatarSize();\n @if (headerPreview.kind === 'icon') {\n <mat-icon class=\"section-heading__icon\" aria-hidden=\"true\" [praxisIcon]=\"headerPreview.icon\"></mat-icon>\n }\n @if (headerPreview.kind === 'initials') {\n <span class=\"section-heading__avatar section-heading__avatar--text\" [class.size-sm]=\"headerAvatarSize === 'sm'\"\n [class.size-md]=\"headerAvatarSize === 'md'\" [class.size-lg]=\"headerAvatarSize === 'lg'\"\n [matTooltip]=\"headerPreview.tooltip || ''\" [matTooltipDisabled]=\"!headerPreview.tooltip\">\n {{ headerPreview.text }}\n </span>\n }\n @if (headerPreview.kind === 'placeholder') {\n <span class=\"section-heading__avatar section-heading__avatar--placeholder\" [class.size-sm]=\"headerAvatarSize === 'sm'\"\n [class.size-md]=\"headerAvatarSize === 'md'\" [class.size-lg]=\"headerAvatarSize === 'lg'\"\n [matTooltip]=\"headerPreview.tooltip || ''\" [matTooltipDisabled]=\"!headerPreview.tooltip\">\n @if (headerPreview.icon) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"headerPreview.icon\"></mat-icon>\n }\n </span>\n }\n <div class=\"section-heading__text\">\n <span class=\"section-name\">{{ section.title || 'Sem t\u00EDtulo' }}</span>\n <span class=\"section-desc\" *ngIf=\"section.description\">{{ section.description }}</span>\n </div>\n </div>\n <button\n mat-icon-button\n type=\"button\"\n color=\"primary\"\n class=\"section-editor-trigger\"\n (click)=\"openAdvancedEditor($event)\"\n matTooltip=\"Para editar o t\u00EDtulo, use o editor completo da se\u00E7\u00E3o\"\n aria-label=\"Abrir editor da se\u00E7\u00E3o\"\n >\n <mat-icon>open_in_new</mat-icon>\n </button>\n </mat-card-title>\n <div class=\"section-header-actions\">\n <button\n mat-icon-button\n class=\"section-collapse-btn\"\n type=\"button\"\n (click)=\"toggleCollapsed($event)\"\n [attr.aria-expanded]=\"!isCollapsed\"\n [attr.aria-label]=\"isCollapsed ? 'Expandir se\u00E7\u00E3o' : 'Colapsar se\u00E7\u00E3o'\"\n [matTooltip]=\"isCollapsed ? 'Expandir se\u00E7\u00E3o' : 'Colapsar se\u00E7\u00E3o'\"\n >\n <mat-icon>{{ isCollapsed ? 'unfold_more' : 'unfold_less' }}</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"section-menu-btn\"\n [matMenuTriggerFor]=\"sectionMenu\"\n aria-label=\"Mais a\u00E7\u00F5es da se\u00E7\u00E3o\"\n matTooltip=\"Mais a\u00E7\u00F5es\"\n >\n <mat-icon [praxisIcon]=\"'more_vert'\"></mat-icon>\n </button>\n </div>\n <mat-menu #sectionMenu=\"matMenu\">\n <button mat-menu-item (click)=\"openSectionPresets()\">\n <mat-icon [praxisIcon]=\"'view_quilt'\"></mat-icon>\n <span>Presets de se\u00E7\u00E3o\u2026</span>\n </button>\n <button mat-menu-item (click)=\"applyCurrentStyleToAll()\">\n <mat-icon [praxisIcon]=\"'format_paint'\"></mat-icon>\n <span>Aplicar estilo desta se\u00E7\u00E3o a todas</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item *ngIf=\"section.description == null\" (click)=\"section.description = ''; onSectionUpdated()\">\n <mat-icon [praxisIcon]=\"'note_add'\"></mat-icon>\n <span>Adicionar descri\u00E7\u00E3o</span>\n </button>\n <button mat-menu-item *ngIf=\"section.description != null\" (click)=\"section.description = undefined; onSectionUpdated()\">\n <mat-icon [praxisIcon]=\"'backspace'\"></mat-icon>\n <span>Remover descri\u00E7\u00E3o</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"onRemoveSection()\">\n <mat-icon [praxisIcon]=\"'delete'\"></mat-icon>\n <span>Remover se\u00E7\u00E3o</span>\n </button>\n </mat-menu>\n </mat-card-header>\n <mat-card-content [attr.aria-hidden]=\"isCollapsed\">\n <ng-container *ngIf=\"isThisSectionSelected(); else linhasTitle\">\n <div class=\"section-breadcrumbs\" (click)=\"$event.stopPropagation()\">\n <button\n type=\"button\"\n class=\"crumb as-button\"\n data-crumb=\"layout\"\n [attr.aria-label]=\"'Voltar ao Layout'\"\n disabled\n >\n Layout\n </button>\n <span class=\"sep\">\u203A</span>\n <button\n type=\"button\"\n class=\"crumb as-button crumb-section\"\n data-crumb=\"section\"\n (click)=\"onSelectSectionFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Selecionar Se\u00E7\u00E3o ' + (sectionIndex + 1)\"\n >\n Se\u00E7\u00E3o {{ sectionIndex + 1 }}\n </button>\n <ng-container *ngIf=\"selected?.rowIndex != null\">\n <span class=\"sep\">\u203A</span>\n <button\n type=\"button\"\n class=\"crumb as-button crumb-row\"\n data-crumb=\"row\"\n (click)=\"onSelectRowFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Selecionar Linha ' + (selected!.rowIndex! + 1)\"\n >\n Linha {{ selected!.rowIndex! + 1 }}\n </button>\n </ng-container>\n <ng-container *ngIf=\"selected?.columnIndex != null\">\n <span class=\"sep\">\u203A</span>\n <button\n type=\"button\"\n class=\"crumb as-button crumb-column\"\n data-crumb=\"column\"\n (click)=\"onSelectColumnFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Selecionar Coluna ' + (selected!.columnIndex! + 1)\"\n >\n Coluna {{ selected!.columnIndex! + 1 }}\n </button>\n </ng-container>\n <ng-container *ngIf=\"selected?.fieldName\">\n <span class=\"sep\">\u203A</span>\n <span class=\"crumb active\">{{ selected!.fieldName }}</span>\n </ng-container>\n <button\n *ngIf=\"selected\"\n type=\"button\"\n class=\"crumb as-button crumb-clear\"\n data-crumb=\"clear\"\n (click)=\"onClearSelectionFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Limpar sele\u00E7\u00E3o'\"\n >\n Limpar\n </button>\n </div>\n </ng-container>\n <ng-template #linhasTitle>\n <h5>Linhas</h5>\n </ng-template>\n <div\n class=\"row-list\"\n cdkDropList\n [cdkDropListData]=\"section.rows\"\n (cdkDropListDropped)=\"dropRow($event)\"\n >\n <praxis-row-configurator\n *ngFor=\"let row of section.rows; let i = index\"\n class=\"row-item\"\n [row]=\"row\"\n [fieldMetadata]=\"fieldMetadata\"\n [availableFields]=\"availableFields\"\n [sectionIndex]=\"sectionIndex\"\n [rowIndex]=\"i\"\n [isLastRow]=\"i === section.rows.length - 1\"\n [selected]=\"selected\"\n [availableFieldsListId]=\"availableFieldsListId\"\n [connectedDropListIds]=\"columnDropListIds\"\n [gapGlobal]=\"gapGlobal\"\n (rowChange)=\"onRowUpdated(i, $event)\"\n (applyRowGapAll)=\"onApplyRowGapAll($event)\"\n (remove)=\"removeRow(i)\"\n (select)=\"select.emit($event)\"\n (fieldDrop)=\"onFieldDrop($event, i)\"\n (addVisualBlock)=\"onAddVisualBlock($event)\"\n (addApiField)=\"onAddApiField($event)\"\n (editVisualBlock)=\"onEditVisualBlock($event)\"\n (moveVisualBlock)=\"onMoveVisualBlock($event)\"\n (moveVisualBlockToColumn)=\"onMoveVisualBlockToColumn($event)\"\n (removeVisualBlock)=\"onRemoveVisualBlock($event)\"\n cdkDrag\n ></praxis-row-configurator>\n </div>\n <div class=\"section-actions\" aria-label=\"A\u00E7\u00F5es da se\u00E7\u00E3o\">\n <button\n class=\"fab-add-row\"\n mat-fab\n color=\"primary\"\n (click)=\"addRow()\"\n matTooltip=\"Adicionar linha\"\n aria-label=\"Adicionar linha\"\n >\n <mat-icon>add</mat-icon>\n </button>\n </div>\n </mat-card-content>\n</mat-card>\n", styles: ["@charset \"UTF-8\";.section-card{background:var(--md-sys-color-surface, var(--sicoob-bg-elev-1));margin-bottom:16px;transition:border-color .2s ease;border:1px solid transparent}.section-card.hovered{border-color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-card.selected{border-color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)));box-shadow:0 0 0 2px var(--md-sys-color-primary)}.section-card:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)));outline-offset:2px}.section-card .mat-mdc-card-content{padding-bottom:var(--px-editor-section-gap, 16px)}.section-breadcrumbs{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin:4px 0 8px;display:flex;align-items:center;gap:6px}.section-breadcrumbs .as-button{background:transparent;border:none;padding:0 2px;color:inherit;font:inherit;cursor:pointer;border-radius:4px}.section-breadcrumbs .as-button:hover{color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-breadcrumbs .as-button:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)));outline-offset:2px}.section-breadcrumbs .crumb-clear{margin-left:6px;opacity:.85}.section-breadcrumbs .crumb.active{color:var(--md-sys-color-on-surface);font-weight:600}.section-breadcrumbs .sep{opacity:.6}.section-header{display:flex;justify-content:space-between;align-items:center;gap:12px;min-height:56px}.title-wrapper{display:flex;align-items:center;gap:8px;width:100%;min-width:0;flex:1 1 auto}.section-heading{display:flex;align-items:center;gap:10px;min-width:0}.section-heading__icon{color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-heading__avatar{--_pfx-layout-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-layout-section-avatar-size);height:var(--_pfx-layout-section-avatar-size);border-radius:999px;flex:0 0 var(--_pfx-layout-section-avatar-size);overflow:hidden}.section-heading__avatar.size-sm{--_pfx-layout-section-avatar-size: var(--pfx-form-section-avatar-size-sm, 24px)}.section-heading__avatar.size-md{--_pfx-layout-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px))}.section-heading__avatar.size-lg{--_pfx-layout-section-avatar-size: var(--pfx-form-section-avatar-size-lg, 40px)}.section-heading__avatar--text,.section-heading__avatar--placeholder{background:color-mix(in srgb,var(--pfx-editorial-form-accent, var(--md-sys-color-primary, var(--sicoob-primary-default))) 14%,var(--pfx-form-section-surface-flat, var(--md-sys-color-surface, var(--sicoob-bg-elev-1))));color:color-mix(in srgb,var(--pfx-editorial-form-accent, var(--md-sys-color-primary, var(--sicoob-primary-default))) 82%,var(--pfx-form-label-strong, var(--md-sys-color-on-surface, var(--sicoob-text-default))) 18%);font-size:calc(var(--_pfx-layout-section-avatar-size) * .41);font-weight:800;letter-spacing:.04em;text-transform:uppercase}.section-heading__avatar--placeholder mat-icon{font-size:calc(var(--_pfx-layout-section-avatar-size) * .5625);width:calc(var(--_pfx-layout-section-avatar-size) * .5625);height:calc(var(--_pfx-layout-section-avatar-size) * .5625);line-height:calc(var(--_pfx-layout-section-avatar-size) * .5625)}.section-heading__text{display:flex;flex-direction:column;align-items:flex-start;min-width:0}.section-heading .section-name{font-weight:600;color:var(--md-sys-color-on-surface);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-heading .section-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-editor-trigger{margin-left:auto}.section-header-actions{display:inline-flex;align-items:center;gap:4px;flex-shrink:0}.section-header-actions .mat-mdc-icon-button{width:36px;height:36px;padding:6px}.add-row-button{margin-top:8px}.row-item{animation:fadeIn .3s ease}@keyframes fadeIn{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}.section-card:hover{border-color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-card.collapsed .mat-mdc-card-content{display:none}:host ::ng-deep .section-card .mat-mdc-card-header{padding:8px 12px}:host ::ng-deep .section-card .mat-mdc-card-title{margin:0}:host ::ng-deep .section-card .mat-mdc-card-content{padding:0 12px 12px}.section-actions{position:relative;margin-top:12px;padding-top:16px;border-top:1px solid var(--md-sys-color-outline-variant, var(--md-sys-color-outline-variant, var(--sicoob-stroke-medium)));min-height:28px}.row-list{border-top:1px solid var(--px-editor-separator-color, var(--md-sys-color-outline-variant));padding-top:12px;margin-top:8px}.fab-add-row{position:absolute;top:-15px;left:50%;transform:translate(-50%,calc(-50% - var(--pfx-divider-w, 1px)));z-index:2;--pfx-fab-size: var(--pfx-fab-size-row, 32px);--pfx-fab-icon: var(--pfx-fab-icon-row, 18px);width:var(--pfx-fab-size);height:var(--pfx-fab-size);border-radius:50%}.fab-add-row.mat-mdc-fab{width:var(--pfx-fab-size);height:var(--pfx-fab-size);padding:0}.fab-add-row .mat-mdc-button-touch-target,.fab-add-row .mat-mdc-button-persistent-ripple,.fab-add-row .mat-mdc-button-ripple{width:var(--pfx-fab-size);height:var(--pfx-fab-size)}.fab-add-row mat-icon{font-size:var(--pfx-fab-icon);width:var(--pfx-fab-icon);height:var(--pfx-fab-icon)}\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: DragDropModule }, { kind: "directive", type: i2$2.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i2$2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: RowConfiguratorComponent, selector: "praxis-row-configurator", inputs: ["row", "fieldMetadata", "availableFields", "sectionIndex", "rowIndex", "isLastRow", "selected", "availableFieldsListId", "connectedDropListIds", "gapGlobal"], outputs: ["rowChange", "remove", "applyRowGapAll", "fieldDrop", "addVisualBlock", "addApiField", "editVisualBlock", "moveVisualBlock", "moveVisualBlockToColumn", "removeVisualBlock", "select"] }, { kind: "ngmodule", type: MatButtonModule }, { 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: 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: MatCardModule }, { kind: "component", type: i8.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i8.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i8.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i8.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i9.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i6.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i6.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i6.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "component", type: i11.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }] });
|
|
14054
14738
|
}
|
|
14055
14739
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: SectionConfiguratorComponent, decorators: [{
|
|
14056
14740
|
type: Component,
|
|
@@ -14066,7 +14750,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14066
14750
|
MatDialogModule,
|
|
14067
14751
|
MatMenuModule,
|
|
14068
14752
|
MatDividerModule,
|
|
14069
|
-
], template: "<mat-card\n class=\"section-card\"\n cdkDrag\n (mouseenter)=\"onMouseEnter()\"\n (mouseleave)=\"onMouseLeave()\"\n [class.hovered]=\"isHovered\"\n [class.selected]=\"isThisSectionSelected()\"\n [class.collapsed]=\"isCollapsed\"\n (click)=\"onSelectSection()\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'Se\u00E7\u00E3o ' + (sectionIndex + 1)\"\n [attr.aria-selected]=\"isThisSectionSelected()\"\n>\n <mat-card-header class=\"section-header\">\n <mat-card-title class=\"title-wrapper\">\n <div class=\"section-heading\">\n @let headerPreview = getSectionHeaderPreview();\n @let headerAvatarSize = getSectionHeaderAvatarSize();\n @if (headerPreview.kind === 'icon') {\n <mat-icon class=\"section-heading__icon\" aria-hidden=\"true\" [praxisIcon]=\"headerPreview.icon\"></mat-icon>\n }\n @if (headerPreview.kind === 'initials') {\n <span class=\"section-heading__avatar section-heading__avatar--text\" [class.size-sm]=\"headerAvatarSize === 'sm'\"\n [class.size-md]=\"headerAvatarSize === 'md'\" [class.size-lg]=\"headerAvatarSize === 'lg'\"\n [matTooltip]=\"headerPreview.tooltip || ''\" [matTooltipDisabled]=\"!headerPreview.tooltip\">\n {{ headerPreview.text }}\n </span>\n }\n @if (headerPreview.kind === 'placeholder') {\n <span class=\"section-heading__avatar section-heading__avatar--placeholder\" [class.size-sm]=\"headerAvatarSize === 'sm'\"\n [class.size-md]=\"headerAvatarSize === 'md'\" [class.size-lg]=\"headerAvatarSize === 'lg'\"\n [matTooltip]=\"headerPreview.tooltip || ''\" [matTooltipDisabled]=\"!headerPreview.tooltip\">\n @if (headerPreview.icon) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"headerPreview.icon\"></mat-icon>\n }\n </span>\n }\n <div class=\"section-heading__text\">\n <span class=\"section-name\">{{ section.title || 'Sem t\u00EDtulo' }}</span>\n <span class=\"section-desc\" *ngIf=\"section.description\">{{ section.description }}</span>\n </div>\n </div>\n <button\n mat-icon-button\n type=\"button\"\n color=\"primary\"\n class=\"section-editor-trigger\"\n (click)=\"openAdvancedEditor($event)\"\n matTooltip=\"Para editar o t\u00EDtulo, use o editor completo da se\u00E7\u00E3o\"\n aria-label=\"Abrir editor da se\u00E7\u00E3o\"\n >\n <mat-icon>open_in_new</mat-icon>\n </button>\n </mat-card-title>\n <div class=\"section-header-actions\">\n <button\n mat-icon-button\n class=\"section-collapse-btn\"\n type=\"button\"\n (click)=\"toggleCollapsed($event)\"\n [attr.aria-expanded]=\"!isCollapsed\"\n [attr.aria-label]=\"isCollapsed ? 'Expandir se\u00E7\u00E3o' : 'Colapsar se\u00E7\u00E3o'\"\n [matTooltip]=\"isCollapsed ? 'Expandir se\u00E7\u00E3o' : 'Colapsar se\u00E7\u00E3o'\"\n >\n <mat-icon>{{ isCollapsed ? 'unfold_more' : 'unfold_less' }}</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"section-menu-btn\"\n [matMenuTriggerFor]=\"sectionMenu\"\n aria-label=\"Mais a\u00E7\u00F5es da se\u00E7\u00E3o\"\n matTooltip=\"Mais a\u00E7\u00F5es\"\n >\n <mat-icon [praxisIcon]=\"'more_vert'\"></mat-icon>\n </button>\n </div>\n <mat-menu #sectionMenu=\"matMenu\">\n <button mat-menu-item (click)=\"openSectionPresets()\">\n <mat-icon [praxisIcon]=\"'view_quilt'\"></mat-icon>\n <span>Presets de se\u00E7\u00E3o\u2026</span>\n </button>\n <button mat-menu-item (click)=\"applyCurrentStyleToAll()\">\n <mat-icon [praxisIcon]=\"'format_paint'\"></mat-icon>\n <span>Aplicar estilo desta se\u00E7\u00E3o a todas</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item *ngIf=\"section.description == null\" (click)=\"section.description = ''; onSectionUpdated()\">\n <mat-icon [praxisIcon]=\"'note_add'\"></mat-icon>\n <span>Adicionar descri\u00E7\u00E3o</span>\n </button>\n <button mat-menu-item *ngIf=\"section.description != null\" (click)=\"section.description = undefined; onSectionUpdated()\">\n <mat-icon [praxisIcon]=\"'backspace'\"></mat-icon>\n <span>Remover descri\u00E7\u00E3o</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"onRemoveSection()\">\n <mat-icon [praxisIcon]=\"'delete'\"></mat-icon>\n <span>Remover se\u00E7\u00E3o</span>\n </button>\n </mat-menu>\n </mat-card-header>\n <mat-card-content [attr.aria-hidden]=\"isCollapsed\">\n <ng-container *ngIf=\"isThisSectionSelected(); else linhasTitle\">\n <div class=\"section-breadcrumbs\" (click)=\"$event.stopPropagation()\">\n <button\n type=\"button\"\n class=\"crumb as-button\"\n data-crumb=\"layout\"\n [attr.aria-label]=\"'Voltar ao Layout'\"\n disabled\n >\n Layout\n </button>\n <span class=\"sep\">\u203A</span>\n <button\n type=\"button\"\n class=\"crumb as-button crumb-section\"\n data-crumb=\"section\"\n (click)=\"onSelectSectionFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Selecionar Se\u00E7\u00E3o ' + (sectionIndex + 1)\"\n >\n Se\u00E7\u00E3o {{ sectionIndex + 1 }}\n </button>\n <ng-container *ngIf=\"selected?.rowIndex != null\">\n <span class=\"sep\">\u203A</span>\n <button\n type=\"button\"\n class=\"crumb as-button crumb-row\"\n data-crumb=\"row\"\n (click)=\"onSelectRowFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Selecionar Linha ' + (selected!.rowIndex! + 1)\"\n >\n Linha {{ selected!.rowIndex! + 1 }}\n </button>\n </ng-container>\n <ng-container *ngIf=\"selected?.columnIndex != null\">\n <span class=\"sep\">\u203A</span>\n <button\n type=\"button\"\n class=\"crumb as-button crumb-column\"\n data-crumb=\"column\"\n (click)=\"onSelectColumnFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Selecionar Coluna ' + (selected!.columnIndex! + 1)\"\n >\n Coluna {{ selected!.columnIndex! + 1 }}\n </button>\n </ng-container>\n <ng-container *ngIf=\"selected?.fieldName\">\n <span class=\"sep\">\u203A</span>\n <span class=\"crumb active\">{{ selected!.fieldName }}</span>\n </ng-container>\n <button\n *ngIf=\"selected\"\n type=\"button\"\n class=\"crumb as-button crumb-clear\"\n data-crumb=\"clear\"\n (click)=\"onClearSelectionFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Limpar sele\u00E7\u00E3o'\"\n >\n Limpar\n </button>\n </div>\n </ng-container>\n <ng-template #linhasTitle>\n <h5>Linhas</h5>\n </ng-template>\n <div\n class=\"row-list\"\n cdkDropList\n [cdkDropListData]=\"section.rows\"\n (cdkDropListDropped)=\"dropRow($event)\"\n >\n <praxis-row-configurator\n *ngFor=\"let row of section.rows; let i = index\"\n class=\"row-item\"\n [row]=\"row\"\n [fieldMetadata]=\"fieldMetadata\"\n [sectionIndex]=\"sectionIndex\"\n [rowIndex]=\"i\"\n [isLastRow]=\"i === section.rows.length - 1\"\n [selected]=\"selected\"\n [availableFieldsListId]=\"availableFieldsListId\"\n [connectedDropListIds]=\"columnDropListIds\"\n [gapGlobal]=\"gapGlobal\"\n (rowChange)=\"onRowUpdated(i, $event)\"\n (applyRowGapAll)=\"onApplyRowGapAll($event)\"\n (remove)=\"removeRow(i)\"\n (select)=\"select.emit($event)\"\n (fieldDrop)=\"onFieldDrop($event, i)\"\n cdkDrag\n ></praxis-row-configurator>\n </div>\n <div class=\"section-actions\" aria-label=\"A\u00E7\u00F5es da se\u00E7\u00E3o\">\n <button\n class=\"fab-add-row\"\n mat-fab\n color=\"primary\"\n (click)=\"addRow()\"\n matTooltip=\"Adicionar linha\"\n aria-label=\"Adicionar linha\"\n >\n <mat-icon>add</mat-icon>\n </button>\n </div>\n </mat-card-content>\n</mat-card>\n", styles: ["@charset \"UTF-8\";.section-card{background:var(--md-sys-color-surface, var(--sicoob-bg-elev-1));margin-bottom:16px;transition:border-color .2s ease;border:1px solid transparent}.section-card.hovered{border-color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-card.selected{border-color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)));box-shadow:0 0 0 2px var(--md-sys-color-primary)}.section-card:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)));outline-offset:2px}.section-card .mat-mdc-card-content{padding-bottom:var(--px-editor-section-gap, 16px)}.section-breadcrumbs{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin:4px 0 8px;display:flex;align-items:center;gap:6px}.section-breadcrumbs .as-button{background:transparent;border:none;padding:0 2px;color:inherit;font:inherit;cursor:pointer;border-radius:4px}.section-breadcrumbs .as-button:hover{color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-breadcrumbs .as-button:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)));outline-offset:2px}.section-breadcrumbs .crumb-clear{margin-left:6px;opacity:.85}.section-breadcrumbs .crumb.active{color:var(--md-sys-color-on-surface);font-weight:600}.section-breadcrumbs .sep{opacity:.6}.section-header{display:flex;justify-content:space-between;align-items:center;gap:12px;min-height:56px}.title-wrapper{display:flex;align-items:center;gap:8px;width:100%;min-width:0;flex:1 1 auto}.section-heading{display:flex;align-items:center;gap:10px;min-width:0}.section-heading__icon{color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-heading__avatar{--_pfx-layout-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-layout-section-avatar-size);height:var(--_pfx-layout-section-avatar-size);border-radius:999px;flex:0 0 var(--_pfx-layout-section-avatar-size);overflow:hidden}.section-heading__avatar.size-sm{--_pfx-layout-section-avatar-size: var(--pfx-form-section-avatar-size-sm, 24px)}.section-heading__avatar.size-md{--_pfx-layout-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px))}.section-heading__avatar.size-lg{--_pfx-layout-section-avatar-size: var(--pfx-form-section-avatar-size-lg, 40px)}.section-heading__avatar--text,.section-heading__avatar--placeholder{background:color-mix(in srgb,var(--pfx-editorial-form-accent, var(--md-sys-color-primary, var(--sicoob-primary-default))) 14%,var(--pfx-form-section-surface-flat, var(--md-sys-color-surface, var(--sicoob-bg-elev-1))));color:color-mix(in srgb,var(--pfx-editorial-form-accent, var(--md-sys-color-primary, var(--sicoob-primary-default))) 82%,var(--pfx-form-label-strong, var(--md-sys-color-on-surface, var(--sicoob-text-default))) 18%);font-size:calc(var(--_pfx-layout-section-avatar-size) * .41);font-weight:800;letter-spacing:.04em;text-transform:uppercase}.section-heading__avatar--placeholder mat-icon{font-size:calc(var(--_pfx-layout-section-avatar-size) * .5625);width:calc(var(--_pfx-layout-section-avatar-size) * .5625);height:calc(var(--_pfx-layout-section-avatar-size) * .5625);line-height:calc(var(--_pfx-layout-section-avatar-size) * .5625)}.section-heading__text{display:flex;flex-direction:column;align-items:flex-start;min-width:0}.section-heading .section-name{font-weight:600;color:var(--md-sys-color-on-surface);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-heading .section-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-editor-trigger{margin-left:auto}.section-header-actions{display:inline-flex;align-items:center;gap:4px;flex-shrink:0}.section-header-actions .mat-mdc-icon-button{width:36px;height:36px;padding:6px}.add-row-button{margin-top:8px}.row-item{animation:fadeIn .3s ease}@keyframes fadeIn{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}.section-card:hover{border-color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-card.collapsed .mat-mdc-card-content{display:none}:host ::ng-deep .section-card .mat-mdc-card-header{padding:8px 12px}:host ::ng-deep .section-card .mat-mdc-card-title{margin:0}:host ::ng-deep .section-card .mat-mdc-card-content{padding:0 12px 12px}.section-actions{position:relative;margin-top:12px;padding-top:16px;border-top:1px solid var(--md-sys-color-outline-variant, var(--md-sys-color-outline-variant, var(--sicoob-stroke-medium)));min-height:28px}.row-list{border-top:1px solid var(--px-editor-separator-color, var(--md-sys-color-outline-variant));padding-top:12px;margin-top:8px}.fab-add-row{position:absolute;top:-15px;left:50%;transform:translate(-50%,calc(-50% - var(--pfx-divider-w, 1px)));z-index:2;--pfx-fab-size: var(--pfx-fab-size-row, 32px);--pfx-fab-icon: var(--pfx-fab-icon-row, 18px);width:var(--pfx-fab-size);height:var(--pfx-fab-size);border-radius:50%}.fab-add-row.mat-mdc-fab{width:var(--pfx-fab-size);height:var(--pfx-fab-size);padding:0}.fab-add-row .mat-mdc-button-touch-target,.fab-add-row .mat-mdc-button-persistent-ripple,.fab-add-row .mat-mdc-button-ripple{width:var(--pfx-fab-size);height:var(--pfx-fab-size)}.fab-add-row mat-icon{font-size:var(--pfx-fab-icon);width:var(--pfx-fab-icon);height:var(--pfx-fab-icon)}\n"] }]
|
|
14753
|
+
], template: "<mat-card\n class=\"section-card\"\n cdkDrag\n (mouseenter)=\"onMouseEnter()\"\n (mouseleave)=\"onMouseLeave()\"\n [class.hovered]=\"isHovered\"\n [class.selected]=\"isThisSectionSelected()\"\n [class.collapsed]=\"isCollapsed\"\n (click)=\"onSelectSection()\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'Se\u00E7\u00E3o ' + (sectionIndex + 1)\"\n [attr.aria-selected]=\"isThisSectionSelected()\"\n>\n <mat-card-header class=\"section-header\">\n <mat-card-title class=\"title-wrapper\">\n <div class=\"section-heading\">\n @let headerPreview = getSectionHeaderPreview();\n @let headerAvatarSize = getSectionHeaderAvatarSize();\n @if (headerPreview.kind === 'icon') {\n <mat-icon class=\"section-heading__icon\" aria-hidden=\"true\" [praxisIcon]=\"headerPreview.icon\"></mat-icon>\n }\n @if (headerPreview.kind === 'initials') {\n <span class=\"section-heading__avatar section-heading__avatar--text\" [class.size-sm]=\"headerAvatarSize === 'sm'\"\n [class.size-md]=\"headerAvatarSize === 'md'\" [class.size-lg]=\"headerAvatarSize === 'lg'\"\n [matTooltip]=\"headerPreview.tooltip || ''\" [matTooltipDisabled]=\"!headerPreview.tooltip\">\n {{ headerPreview.text }}\n </span>\n }\n @if (headerPreview.kind === 'placeholder') {\n <span class=\"section-heading__avatar section-heading__avatar--placeholder\" [class.size-sm]=\"headerAvatarSize === 'sm'\"\n [class.size-md]=\"headerAvatarSize === 'md'\" [class.size-lg]=\"headerAvatarSize === 'lg'\"\n [matTooltip]=\"headerPreview.tooltip || ''\" [matTooltipDisabled]=\"!headerPreview.tooltip\">\n @if (headerPreview.icon) {\n <mat-icon aria-hidden=\"true\" [praxisIcon]=\"headerPreview.icon\"></mat-icon>\n }\n </span>\n }\n <div class=\"section-heading__text\">\n <span class=\"section-name\">{{ section.title || 'Sem t\u00EDtulo' }}</span>\n <span class=\"section-desc\" *ngIf=\"section.description\">{{ section.description }}</span>\n </div>\n </div>\n <button\n mat-icon-button\n type=\"button\"\n color=\"primary\"\n class=\"section-editor-trigger\"\n (click)=\"openAdvancedEditor($event)\"\n matTooltip=\"Para editar o t\u00EDtulo, use o editor completo da se\u00E7\u00E3o\"\n aria-label=\"Abrir editor da se\u00E7\u00E3o\"\n >\n <mat-icon>open_in_new</mat-icon>\n </button>\n </mat-card-title>\n <div class=\"section-header-actions\">\n <button\n mat-icon-button\n class=\"section-collapse-btn\"\n type=\"button\"\n (click)=\"toggleCollapsed($event)\"\n [attr.aria-expanded]=\"!isCollapsed\"\n [attr.aria-label]=\"isCollapsed ? 'Expandir se\u00E7\u00E3o' : 'Colapsar se\u00E7\u00E3o'\"\n [matTooltip]=\"isCollapsed ? 'Expandir se\u00E7\u00E3o' : 'Colapsar se\u00E7\u00E3o'\"\n >\n <mat-icon>{{ isCollapsed ? 'unfold_more' : 'unfold_less' }}</mat-icon>\n </button>\n <button\n mat-icon-button\n class=\"section-menu-btn\"\n [matMenuTriggerFor]=\"sectionMenu\"\n aria-label=\"Mais a\u00E7\u00F5es da se\u00E7\u00E3o\"\n matTooltip=\"Mais a\u00E7\u00F5es\"\n >\n <mat-icon [praxisIcon]=\"'more_vert'\"></mat-icon>\n </button>\n </div>\n <mat-menu #sectionMenu=\"matMenu\">\n <button mat-menu-item (click)=\"openSectionPresets()\">\n <mat-icon [praxisIcon]=\"'view_quilt'\"></mat-icon>\n <span>Presets de se\u00E7\u00E3o\u2026</span>\n </button>\n <button mat-menu-item (click)=\"applyCurrentStyleToAll()\">\n <mat-icon [praxisIcon]=\"'format_paint'\"></mat-icon>\n <span>Aplicar estilo desta se\u00E7\u00E3o a todas</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item *ngIf=\"section.description == null\" (click)=\"section.description = ''; onSectionUpdated()\">\n <mat-icon [praxisIcon]=\"'note_add'\"></mat-icon>\n <span>Adicionar descri\u00E7\u00E3o</span>\n </button>\n <button mat-menu-item *ngIf=\"section.description != null\" (click)=\"section.description = undefined; onSectionUpdated()\">\n <mat-icon [praxisIcon]=\"'backspace'\"></mat-icon>\n <span>Remover descri\u00E7\u00E3o</span>\n </button>\n <mat-divider></mat-divider>\n <button mat-menu-item (click)=\"onRemoveSection()\">\n <mat-icon [praxisIcon]=\"'delete'\"></mat-icon>\n <span>Remover se\u00E7\u00E3o</span>\n </button>\n </mat-menu>\n </mat-card-header>\n <mat-card-content [attr.aria-hidden]=\"isCollapsed\">\n <ng-container *ngIf=\"isThisSectionSelected(); else linhasTitle\">\n <div class=\"section-breadcrumbs\" (click)=\"$event.stopPropagation()\">\n <button\n type=\"button\"\n class=\"crumb as-button\"\n data-crumb=\"layout\"\n [attr.aria-label]=\"'Voltar ao Layout'\"\n disabled\n >\n Layout\n </button>\n <span class=\"sep\">\u203A</span>\n <button\n type=\"button\"\n class=\"crumb as-button crumb-section\"\n data-crumb=\"section\"\n (click)=\"onSelectSectionFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Selecionar Se\u00E7\u00E3o ' + (sectionIndex + 1)\"\n >\n Se\u00E7\u00E3o {{ sectionIndex + 1 }}\n </button>\n <ng-container *ngIf=\"selected?.rowIndex != null\">\n <span class=\"sep\">\u203A</span>\n <button\n type=\"button\"\n class=\"crumb as-button crumb-row\"\n data-crumb=\"row\"\n (click)=\"onSelectRowFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Selecionar Linha ' + (selected!.rowIndex! + 1)\"\n >\n Linha {{ selected!.rowIndex! + 1 }}\n </button>\n </ng-container>\n <ng-container *ngIf=\"selected?.columnIndex != null\">\n <span class=\"sep\">\u203A</span>\n <button\n type=\"button\"\n class=\"crumb as-button crumb-column\"\n data-crumb=\"column\"\n (click)=\"onSelectColumnFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Selecionar Coluna ' + (selected!.columnIndex! + 1)\"\n >\n Coluna {{ selected!.columnIndex! + 1 }}\n </button>\n </ng-container>\n <ng-container *ngIf=\"selected?.fieldName\">\n <span class=\"sep\">\u203A</span>\n <span class=\"crumb active\">{{ selected!.fieldName }}</span>\n </ng-container>\n <button\n *ngIf=\"selected\"\n type=\"button\"\n class=\"crumb as-button crumb-clear\"\n data-crumb=\"clear\"\n (click)=\"onClearSelectionFromBreadcrumb($event)\"\n [attr.aria-label]=\"'Limpar sele\u00E7\u00E3o'\"\n >\n Limpar\n </button>\n </div>\n </ng-container>\n <ng-template #linhasTitle>\n <h5>Linhas</h5>\n </ng-template>\n <div\n class=\"row-list\"\n cdkDropList\n [cdkDropListData]=\"section.rows\"\n (cdkDropListDropped)=\"dropRow($event)\"\n >\n <praxis-row-configurator\n *ngFor=\"let row of section.rows; let i = index\"\n class=\"row-item\"\n [row]=\"row\"\n [fieldMetadata]=\"fieldMetadata\"\n [availableFields]=\"availableFields\"\n [sectionIndex]=\"sectionIndex\"\n [rowIndex]=\"i\"\n [isLastRow]=\"i === section.rows.length - 1\"\n [selected]=\"selected\"\n [availableFieldsListId]=\"availableFieldsListId\"\n [connectedDropListIds]=\"columnDropListIds\"\n [gapGlobal]=\"gapGlobal\"\n (rowChange)=\"onRowUpdated(i, $event)\"\n (applyRowGapAll)=\"onApplyRowGapAll($event)\"\n (remove)=\"removeRow(i)\"\n (select)=\"select.emit($event)\"\n (fieldDrop)=\"onFieldDrop($event, i)\"\n (addVisualBlock)=\"onAddVisualBlock($event)\"\n (addApiField)=\"onAddApiField($event)\"\n (editVisualBlock)=\"onEditVisualBlock($event)\"\n (moveVisualBlock)=\"onMoveVisualBlock($event)\"\n (moveVisualBlockToColumn)=\"onMoveVisualBlockToColumn($event)\"\n (removeVisualBlock)=\"onRemoveVisualBlock($event)\"\n cdkDrag\n ></praxis-row-configurator>\n </div>\n <div class=\"section-actions\" aria-label=\"A\u00E7\u00F5es da se\u00E7\u00E3o\">\n <button\n class=\"fab-add-row\"\n mat-fab\n color=\"primary\"\n (click)=\"addRow()\"\n matTooltip=\"Adicionar linha\"\n aria-label=\"Adicionar linha\"\n >\n <mat-icon>add</mat-icon>\n </button>\n </div>\n </mat-card-content>\n</mat-card>\n", styles: ["@charset \"UTF-8\";.section-card{background:var(--md-sys-color-surface, var(--sicoob-bg-elev-1));margin-bottom:16px;transition:border-color .2s ease;border:1px solid transparent}.section-card.hovered{border-color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-card.selected{border-color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)));box-shadow:0 0 0 2px var(--md-sys-color-primary)}.section-card:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)));outline-offset:2px}.section-card .mat-mdc-card-content{padding-bottom:var(--px-editor-section-gap, 16px)}.section-breadcrumbs{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin:4px 0 8px;display:flex;align-items:center;gap:6px}.section-breadcrumbs .as-button{background:transparent;border:none;padding:0 2px;color:inherit;font:inherit;cursor:pointer;border-radius:4px}.section-breadcrumbs .as-button:hover{color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-breadcrumbs .as-button:focus-visible{outline:2px solid var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)));outline-offset:2px}.section-breadcrumbs .crumb-clear{margin-left:6px;opacity:.85}.section-breadcrumbs .crumb.active{color:var(--md-sys-color-on-surface);font-weight:600}.section-breadcrumbs .sep{opacity:.6}.section-header{display:flex;justify-content:space-between;align-items:center;gap:12px;min-height:56px}.title-wrapper{display:flex;align-items:center;gap:8px;width:100%;min-width:0;flex:1 1 auto}.section-heading{display:flex;align-items:center;gap:10px;min-width:0}.section-heading__icon{color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-heading__avatar{--_pfx-layout-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-layout-section-avatar-size);height:var(--_pfx-layout-section-avatar-size);border-radius:999px;flex:0 0 var(--_pfx-layout-section-avatar-size);overflow:hidden}.section-heading__avatar.size-sm{--_pfx-layout-section-avatar-size: var(--pfx-form-section-avatar-size-sm, 24px)}.section-heading__avatar.size-md{--_pfx-layout-section-avatar-size: var(--pfx-form-section-avatar-size-md, var(--pfx-form-section-avatar-size, 32px))}.section-heading__avatar.size-lg{--_pfx-layout-section-avatar-size: var(--pfx-form-section-avatar-size-lg, 40px)}.section-heading__avatar--text,.section-heading__avatar--placeholder{background:color-mix(in srgb,var(--pfx-editorial-form-accent, var(--md-sys-color-primary, var(--sicoob-primary-default))) 14%,var(--pfx-form-section-surface-flat, var(--md-sys-color-surface, var(--sicoob-bg-elev-1))));color:color-mix(in srgb,var(--pfx-editorial-form-accent, var(--md-sys-color-primary, var(--sicoob-primary-default))) 82%,var(--pfx-form-label-strong, var(--md-sys-color-on-surface, var(--sicoob-text-default))) 18%);font-size:calc(var(--_pfx-layout-section-avatar-size) * .41);font-weight:800;letter-spacing:.04em;text-transform:uppercase}.section-heading__avatar--placeholder mat-icon{font-size:calc(var(--_pfx-layout-section-avatar-size) * .5625);width:calc(var(--_pfx-layout-section-avatar-size) * .5625);height:calc(var(--_pfx-layout-section-avatar-size) * .5625);line-height:calc(var(--_pfx-layout-section-avatar-size) * .5625)}.section-heading__text{display:flex;flex-direction:column;align-items:flex-start;min-width:0}.section-heading .section-name{font-weight:600;color:var(--md-sys-color-on-surface);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-heading .section-desc{font-size:12px;color:var(--md-sys-color-on-surface-variant);margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.section-editor-trigger{margin-left:auto}.section-header-actions{display:inline-flex;align-items:center;gap:4px;flex-shrink:0}.section-header-actions .mat-mdc-icon-button{width:36px;height:36px;padding:6px}.add-row-button{margin-top:8px}.row-item{animation:fadeIn .3s ease}@keyframes fadeIn{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:none}}.section-card:hover{border-color:var(--md-sys-color-primary, var(--md-sys-color-primary, var(--sicoob-primary-default)))}.section-card.collapsed .mat-mdc-card-content{display:none}:host ::ng-deep .section-card .mat-mdc-card-header{padding:8px 12px}:host ::ng-deep .section-card .mat-mdc-card-title{margin:0}:host ::ng-deep .section-card .mat-mdc-card-content{padding:0 12px 12px}.section-actions{position:relative;margin-top:12px;padding-top:16px;border-top:1px solid var(--md-sys-color-outline-variant, var(--md-sys-color-outline-variant, var(--sicoob-stroke-medium)));min-height:28px}.row-list{border-top:1px solid var(--px-editor-separator-color, var(--md-sys-color-outline-variant));padding-top:12px;margin-top:8px}.fab-add-row{position:absolute;top:-15px;left:50%;transform:translate(-50%,calc(-50% - var(--pfx-divider-w, 1px)));z-index:2;--pfx-fab-size: var(--pfx-fab-size-row, 32px);--pfx-fab-icon: var(--pfx-fab-icon-row, 18px);width:var(--pfx-fab-size);height:var(--pfx-fab-size);border-radius:50%}.fab-add-row.mat-mdc-fab{width:var(--pfx-fab-size);height:var(--pfx-fab-size);padding:0}.fab-add-row .mat-mdc-button-touch-target,.fab-add-row .mat-mdc-button-persistent-ripple,.fab-add-row .mat-mdc-button-ripple{width:var(--pfx-fab-size);height:var(--pfx-fab-size)}.fab-add-row mat-icon{font-size:var(--pfx-fab-icon);width:var(--pfx-fab-icon);height:var(--pfx-fab-icon)}\n"] }]
|
|
14070
14754
|
}], ctorParameters: () => [{ type: i2$1.MatDialog }, { type: SectionPresetRegistry }, { type: i7.SettingsPanelService }], propDecorators: { section: [{
|
|
14071
14755
|
type: Input
|
|
14072
14756
|
}], sectionIndex: [{
|
|
@@ -14075,6 +14759,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14075
14759
|
type: Input
|
|
14076
14760
|
}], fieldMetadata: [{
|
|
14077
14761
|
type: Input
|
|
14762
|
+
}], availableFields: [{
|
|
14763
|
+
type: Input
|
|
14078
14764
|
}], selected: [{
|
|
14079
14765
|
type: Input
|
|
14080
14766
|
}], availableFieldsListId: [{
|
|
@@ -14093,6 +14779,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14093
14779
|
type: Output
|
|
14094
14780
|
}], fieldDrop: [{
|
|
14095
14781
|
type: Output
|
|
14782
|
+
}], addVisualBlock: [{
|
|
14783
|
+
type: Output
|
|
14784
|
+
}], addApiField: [{
|
|
14785
|
+
type: Output
|
|
14786
|
+
}], editVisualBlock: [{
|
|
14787
|
+
type: Output
|
|
14788
|
+
}], moveVisualBlock: [{
|
|
14789
|
+
type: Output
|
|
14790
|
+
}], moveVisualBlockToColumn: [{
|
|
14791
|
+
type: Output
|
|
14792
|
+
}], removeVisualBlock: [{
|
|
14793
|
+
type: Output
|
|
14096
14794
|
}] } });
|
|
14097
14795
|
|
|
14098
14796
|
/** Tokens for theme colors used across the layout editor. */
|
|
@@ -14141,6 +14839,10 @@ class LayoutEditorComponent {
|
|
|
14141
14839
|
configChange = new EventEmitter();
|
|
14142
14840
|
paletteCollapsed = false;
|
|
14143
14841
|
prefs = inject(LayoutPrefsService);
|
|
14842
|
+
layoutService = inject(DynamicFormLayoutService);
|
|
14843
|
+
settingsPanel = inject(SettingsPanelService);
|
|
14844
|
+
i18n = inject(PraxisI18nService);
|
|
14845
|
+
visualBlockIdSequence = 0;
|
|
14144
14846
|
colorTokens = LayoutColorToken;
|
|
14145
14847
|
selected = null;
|
|
14146
14848
|
// Global default for section gap (inherited when not customized)
|
|
@@ -14214,12 +14916,15 @@ class LayoutEditorComponent {
|
|
|
14214
14916
|
this.config.sections.forEach((s) => {
|
|
14215
14917
|
s.rows.forEach((r) => {
|
|
14216
14918
|
r.columns.forEach((c) => {
|
|
14217
|
-
c.
|
|
14919
|
+
getFormColumnFieldNames(c).forEach((fieldName) => placedFieldNames.add(fieldName));
|
|
14218
14920
|
});
|
|
14219
14921
|
});
|
|
14220
14922
|
});
|
|
14221
14923
|
return visibleFields.filter((f) => !placedFieldNames.has(f.name));
|
|
14222
14924
|
}
|
|
14925
|
+
t(key, params) {
|
|
14926
|
+
return this.i18n.t(key, params, LAYOUT_EDITOR_DEFAULT_COPY[key] ?? key, LAYOUT_EDITOR_I18N_NAMESPACE);
|
|
14927
|
+
}
|
|
14223
14928
|
get columnDropListIds() {
|
|
14224
14929
|
const ids = [];
|
|
14225
14930
|
this.config.sections.forEach((section, sIdx) => {
|
|
@@ -14264,42 +14969,72 @@ class LayoutEditorComponent {
|
|
|
14264
14969
|
dropField({ event }) {
|
|
14265
14970
|
const prevPos = this.parseColumnId(event.previousContainer.id);
|
|
14266
14971
|
const currentPos = this.parseColumnId(event.container.id);
|
|
14267
|
-
|
|
14268
|
-
|
|
14269
|
-
|
|
14270
|
-
|
|
14271
|
-
|
|
14272
|
-
|
|
14273
|
-
|
|
14274
|
-
|
|
14275
|
-
|
|
14276
|
-
|
|
14277
|
-
|
|
14278
|
-
|
|
14279
|
-
|
|
14280
|
-
|
|
14281
|
-
|
|
14282
|
-
|
|
14283
|
-
|
|
14284
|
-
|
|
14285
|
-
|
|
14286
|
-
|
|
14287
|
-
|
|
14288
|
-
|
|
14289
|
-
|
|
14290
|
-
|
|
14291
|
-
|
|
14292
|
-
|
|
14293
|
-
|
|
14294
|
-
|
|
14295
|
-
|
|
14296
|
-
|
|
14297
|
-
|
|
14298
|
-
|
|
14299
|
-
|
|
14300
|
-
this.config = newConfig;
|
|
14972
|
+
let nextConfig = this.layoutService.normalizeConfig(this.config);
|
|
14973
|
+
if (event.previousContainer.id === 'available-fields-list') {
|
|
14974
|
+
if (!currentPos)
|
|
14975
|
+
return;
|
|
14976
|
+
const field = (event.item?.data ??
|
|
14977
|
+
event.previousContainer.data?.[event.previousIndex]);
|
|
14978
|
+
if (!field?.name)
|
|
14979
|
+
return;
|
|
14980
|
+
const target = this.getColumnTargetByIndex(nextConfig, currentPos);
|
|
14981
|
+
if (!target)
|
|
14982
|
+
return;
|
|
14983
|
+
nextConfig = this.layoutService.insertFieldById(nextConfig, target, field.name, event.currentIndex).config;
|
|
14984
|
+
}
|
|
14985
|
+
else if (event.container.id === 'available-fields-list') {
|
|
14986
|
+
if (!prevPos)
|
|
14987
|
+
return;
|
|
14988
|
+
const source = this.getColumnTargetByIndex(nextConfig, prevPos);
|
|
14989
|
+
const fieldName = nextConfig.sections[prevPos.sectionIndex].rows[prevPos.rowIndex]
|
|
14990
|
+
.columns[prevPos.columnIndex].fields?.[event.previousIndex];
|
|
14991
|
+
if (!source || !fieldName)
|
|
14992
|
+
return;
|
|
14993
|
+
nextConfig = this.layoutService.removeFieldById(nextConfig, source.sectionId, source.rowId, source.columnId, fieldName).config;
|
|
14994
|
+
}
|
|
14995
|
+
else if (prevPos && currentPos) {
|
|
14996
|
+
const source = this.getColumnTargetByIndex(nextConfig, prevPos);
|
|
14997
|
+
const target = this.getColumnTargetByIndex(nextConfig, currentPos);
|
|
14998
|
+
const fieldName = nextConfig.sections[prevPos.sectionIndex].rows[prevPos.rowIndex]
|
|
14999
|
+
.columns[prevPos.columnIndex].fields?.[event.previousIndex];
|
|
15000
|
+
if (!source || !target || !fieldName)
|
|
15001
|
+
return;
|
|
15002
|
+
nextConfig = this.layoutService.moveFieldById(nextConfig, { ...source, fieldName }, { ...target, toIndex: event.currentIndex }).config;
|
|
15003
|
+
}
|
|
15004
|
+
this.config = nextConfig;
|
|
14301
15005
|
this.configChange.emit(this.config);
|
|
14302
15006
|
}
|
|
15007
|
+
getColumnTargetByIndex(config, pos) {
|
|
15008
|
+
const section = config.sections[pos.sectionIndex];
|
|
15009
|
+
const row = section?.rows?.[pos.rowIndex];
|
|
15010
|
+
const column = row?.columns?.[pos.columnIndex];
|
|
15011
|
+
if (!section?.id || !row?.id || !column?.id)
|
|
15012
|
+
return null;
|
|
15013
|
+
return {
|
|
15014
|
+
sectionId: section.id,
|
|
15015
|
+
rowId: row.id,
|
|
15016
|
+
columnId: column.id,
|
|
15017
|
+
};
|
|
15018
|
+
}
|
|
15019
|
+
getLayoutItemTargetByIndex(config, event) {
|
|
15020
|
+
const section = config.sections[event.sectionIndex];
|
|
15021
|
+
const row = section?.rows?.[event.rowIndex];
|
|
15022
|
+
const column = row?.columns?.[event.columnIndex];
|
|
15023
|
+
if (!section?.id || !row?.id || !column?.id) {
|
|
15024
|
+
return null;
|
|
15025
|
+
}
|
|
15026
|
+
const itemIndex = column.items?.findIndex((item) => item.id === event.itemId) ?? -1;
|
|
15027
|
+
if (itemIndex < 0 || column.items?.[itemIndex]?.kind !== 'richContent') {
|
|
15028
|
+
return null;
|
|
15029
|
+
}
|
|
15030
|
+
return {
|
|
15031
|
+
...event,
|
|
15032
|
+
sectionId: section.id,
|
|
15033
|
+
rowId: row.id,
|
|
15034
|
+
columnId: column.id,
|
|
15035
|
+
itemIndex,
|
|
15036
|
+
};
|
|
15037
|
+
}
|
|
14303
15038
|
dropSection(event) {
|
|
14304
15039
|
const sections = [...this.config.sections];
|
|
14305
15040
|
if (event.previousContainer === event.container) {
|
|
@@ -14341,6 +15076,178 @@ class LayoutEditorComponent {
|
|
|
14341
15076
|
catch { }
|
|
14342
15077
|
this.emitNewConfig({ sections });
|
|
14343
15078
|
}
|
|
15079
|
+
addVisualBlockToColumn(event) {
|
|
15080
|
+
const normalized = this.layoutService.normalizeConfig(this.config);
|
|
15081
|
+
const section = normalized.sections[event.sectionIndex];
|
|
15082
|
+
const row = section?.rows?.[event.rowIndex];
|
|
15083
|
+
const column = row?.columns?.[event.columnIndex];
|
|
15084
|
+
if (!section?.id || !row?.id || !column?.id) {
|
|
15085
|
+
return;
|
|
15086
|
+
}
|
|
15087
|
+
const item = createVisualBlockItemFromPreset(event.presetId, this.createVisualBlockItemId(), {
|
|
15088
|
+
text: this.t('visualBlock.preset.text.default'),
|
|
15089
|
+
notice: this.t('visualBlock.preset.notice.default'),
|
|
15090
|
+
divider: this.t('visualBlock.preset.divider.default'),
|
|
15091
|
+
infoCardTitle: this.t('visualBlock.preset.infoCard.title'),
|
|
15092
|
+
infoCardBody: this.t('visualBlock.preset.infoCard.body'),
|
|
15093
|
+
});
|
|
15094
|
+
const result = this.layoutService.insertLayoutItemById(normalized, {
|
|
15095
|
+
sectionId: section.id,
|
|
15096
|
+
rowId: row.id,
|
|
15097
|
+
columnId: column.id,
|
|
15098
|
+
}, item);
|
|
15099
|
+
this.config = result.config;
|
|
15100
|
+
this.selected = {
|
|
15101
|
+
type: 'visualBlock',
|
|
15102
|
+
sectionIndex: event.sectionIndex,
|
|
15103
|
+
rowIndex: event.rowIndex,
|
|
15104
|
+
columnIndex: event.columnIndex,
|
|
15105
|
+
itemId: item.id,
|
|
15106
|
+
};
|
|
15107
|
+
this.configChange.emit(this.config);
|
|
15108
|
+
}
|
|
15109
|
+
createVisualBlockItemId() {
|
|
15110
|
+
this.visualBlockIdSequence += 1;
|
|
15111
|
+
const entropy = Math.random().toString(36).slice(2, 9);
|
|
15112
|
+
return `rich-content-${Date.now()}-${this.visualBlockIdSequence}-${entropy}`;
|
|
15113
|
+
}
|
|
15114
|
+
addApiFieldToColumn(event) {
|
|
15115
|
+
if (!event.fieldName)
|
|
15116
|
+
return;
|
|
15117
|
+
if (!this.availableFields.some((field) => field.name === event.fieldName)) {
|
|
15118
|
+
return;
|
|
15119
|
+
}
|
|
15120
|
+
const normalized = this.layoutService.normalizeConfig(this.config);
|
|
15121
|
+
const target = this.getColumnTargetByIndex(normalized, event);
|
|
15122
|
+
if (!target) {
|
|
15123
|
+
return;
|
|
15124
|
+
}
|
|
15125
|
+
const result = this.layoutService.insertFieldById(normalized, target, event.fieldName);
|
|
15126
|
+
this.config = result.config;
|
|
15127
|
+
this.selected = {
|
|
15128
|
+
type: 'field',
|
|
15129
|
+
sectionIndex: event.sectionIndex,
|
|
15130
|
+
rowIndex: event.rowIndex,
|
|
15131
|
+
columnIndex: event.columnIndex,
|
|
15132
|
+
fieldName: event.fieldName,
|
|
15133
|
+
};
|
|
15134
|
+
this.configChange.emit(this.config);
|
|
15135
|
+
}
|
|
15136
|
+
openVisualBlockEditor(event) {
|
|
15137
|
+
const normalized = this.layoutService.normalizeConfig(this.config);
|
|
15138
|
+
const section = normalized.sections[event.sectionIndex];
|
|
15139
|
+
const row = section?.rows?.[event.rowIndex];
|
|
15140
|
+
const column = row?.columns?.[event.columnIndex];
|
|
15141
|
+
const item = column?.items?.find((candidate) => candidate.id === event.itemId);
|
|
15142
|
+
if (!section?.id || !row?.id || !column?.id || item?.kind !== 'richContent') {
|
|
15143
|
+
return;
|
|
15144
|
+
}
|
|
15145
|
+
const ref = this.settingsPanel.open({
|
|
15146
|
+
id: `layout.richContent.${section.id}.${row.id}.${column.id}.${item.id}`,
|
|
15147
|
+
title: this.t('visualBlock.editTitle'),
|
|
15148
|
+
titleIcon: 'notes',
|
|
15149
|
+
content: {
|
|
15150
|
+
component: PraxisRichContentConfigEditor,
|
|
15151
|
+
inputs: {
|
|
15152
|
+
inputs: {
|
|
15153
|
+
document: item.document,
|
|
15154
|
+
layout: item.layout ?? 'block',
|
|
15155
|
+
rootClassName: item.rootClassName ?? null,
|
|
15156
|
+
},
|
|
15157
|
+
},
|
|
15158
|
+
},
|
|
15159
|
+
});
|
|
15160
|
+
const applyValue = (value) => {
|
|
15161
|
+
if (!value?.inputs?.document)
|
|
15162
|
+
return;
|
|
15163
|
+
const currentConfig = this.layoutService.normalizeConfig(this.config);
|
|
15164
|
+
const currentColumn = currentConfig.sections
|
|
15165
|
+
.find((candidate) => candidate.id === section.id)
|
|
15166
|
+
?.rows?.find((candidate) => candidate.id === row.id)
|
|
15167
|
+
?.columns?.find((candidate) => candidate.id === column.id);
|
|
15168
|
+
const currentItem = currentColumn?.items?.find((candidate) => candidate.id === item.id);
|
|
15169
|
+
if (currentItem?.kind !== 'richContent')
|
|
15170
|
+
return;
|
|
15171
|
+
const result = this.layoutService.updateLayoutItemById(currentConfig, {
|
|
15172
|
+
sectionId: section.id,
|
|
15173
|
+
rowId: row.id,
|
|
15174
|
+
columnId: column.id,
|
|
15175
|
+
itemId: item.id,
|
|
15176
|
+
}, {
|
|
15177
|
+
...currentItem,
|
|
15178
|
+
document: value.inputs.document,
|
|
15179
|
+
layout: value.inputs.layout ?? 'block',
|
|
15180
|
+
rootClassName: value.inputs.rootClassName ?? null,
|
|
15181
|
+
});
|
|
15182
|
+
this.config = result.config;
|
|
15183
|
+
this.configChange.emit(this.config);
|
|
15184
|
+
};
|
|
15185
|
+
ref.applied$?.subscribe(applyValue);
|
|
15186
|
+
ref.saved$?.subscribe(applyValue);
|
|
15187
|
+
}
|
|
15188
|
+
moveVisualBlock(event) {
|
|
15189
|
+
const normalized = this.layoutService.normalizeConfig(this.config);
|
|
15190
|
+
const target = this.getLayoutItemTargetByIndex(normalized, event);
|
|
15191
|
+
if (!target) {
|
|
15192
|
+
return;
|
|
15193
|
+
}
|
|
15194
|
+
const toIndex = target.itemIndex + event.direction;
|
|
15195
|
+
const itemCount = normalized.sections[event.sectionIndex].rows[event.rowIndex]
|
|
15196
|
+
.columns[event.columnIndex].items?.length ?? 0;
|
|
15197
|
+
if (toIndex < 0 || toIndex >= itemCount) {
|
|
15198
|
+
return;
|
|
15199
|
+
}
|
|
15200
|
+
const result = this.layoutService.moveLayoutItemById(normalized, {
|
|
15201
|
+
sectionId: target.sectionId,
|
|
15202
|
+
rowId: target.rowId,
|
|
15203
|
+
columnId: target.columnId,
|
|
15204
|
+
itemId: event.itemId,
|
|
15205
|
+
}, {
|
|
15206
|
+
sectionId: target.sectionId,
|
|
15207
|
+
rowId: target.rowId,
|
|
15208
|
+
columnId: target.columnId,
|
|
15209
|
+
toIndex,
|
|
15210
|
+
}, { policy: 'keepEmptyContainers' });
|
|
15211
|
+
this.config = result.config;
|
|
15212
|
+
this.configChange.emit(this.config);
|
|
15213
|
+
}
|
|
15214
|
+
moveVisualBlockToColumn(event) {
|
|
15215
|
+
const normalized = this.layoutService.normalizeConfig(this.config);
|
|
15216
|
+
const source = this.getLayoutItemTargetByIndex(normalized, event);
|
|
15217
|
+
const target = this.getColumnTargetByIndex(normalized, {
|
|
15218
|
+
sectionIndex: event.sectionIndex,
|
|
15219
|
+
rowIndex: event.rowIndex,
|
|
15220
|
+
columnIndex: event.targetColumnIndex,
|
|
15221
|
+
});
|
|
15222
|
+
const targetColumn = normalized.sections[event.sectionIndex]?.rows?.[event.rowIndex]
|
|
15223
|
+
?.columns?.[event.targetColumnIndex];
|
|
15224
|
+
if (!source || !target || !targetColumn) {
|
|
15225
|
+
return;
|
|
15226
|
+
}
|
|
15227
|
+
const result = this.layoutService.moveLayoutItemById(normalized, {
|
|
15228
|
+
sectionId: source.sectionId,
|
|
15229
|
+
rowId: source.rowId,
|
|
15230
|
+
columnId: source.columnId,
|
|
15231
|
+
itemId: event.itemId,
|
|
15232
|
+
}, {
|
|
15233
|
+
sectionId: target.sectionId,
|
|
15234
|
+
rowId: target.rowId,
|
|
15235
|
+
columnId: target.columnId,
|
|
15236
|
+
toIndex: targetColumn.items?.length ?? 0,
|
|
15237
|
+
}, { policy: 'keepEmptyContainers' });
|
|
15238
|
+
this.config = result.config;
|
|
15239
|
+
this.configChange.emit(this.config);
|
|
15240
|
+
}
|
|
15241
|
+
removeVisualBlock(event) {
|
|
15242
|
+
const normalized = this.layoutService.normalizeConfig(this.config);
|
|
15243
|
+
const target = this.getLayoutItemTargetByIndex(normalized, event);
|
|
15244
|
+
if (!target) {
|
|
15245
|
+
return;
|
|
15246
|
+
}
|
|
15247
|
+
const result = this.layoutService.removeLayoutItemById(normalized, target.sectionId, target.rowId, target.columnId, event.itemId, { policy: 'keepEmptyContainers' });
|
|
15248
|
+
this.config = result.config;
|
|
15249
|
+
this.configChange.emit(this.config);
|
|
15250
|
+
}
|
|
14344
15251
|
emitNewConfig(configChanges) {
|
|
14345
15252
|
const newConfig = {
|
|
14346
15253
|
...this.config,
|
|
@@ -14357,7 +15264,7 @@ class LayoutEditorComponent {
|
|
|
14357
15264
|
return s.id ?? index;
|
|
14358
15265
|
}
|
|
14359
15266
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: LayoutEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14360
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: LayoutEditorComponent, isStandalone: true, selector: "praxis-layout-editor", inputs: { config: "config" }, outputs: { configChange: "configChange", select: "select" }, host: { listeners: { "document:keydown": "handleKeydown($event)" } }, ngImport: i0, template: `
|
|
15267
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.17", type: LayoutEditorComponent, isStandalone: true, selector: "praxis-layout-editor", inputs: { config: "config" }, outputs: { configChange: "configChange", select: "select" }, host: { listeners: { "document:keydown": "handleKeydown($event)" } }, providers: [providePraxisI18nConfig(LAYOUT_EDITOR_I18N_CONFIG)], ngImport: i0, template: `
|
|
14361
15268
|
<div class="layout-editor-wrapper"
|
|
14362
15269
|
cdkDropListGroup
|
|
14363
15270
|
[class.no-available-fields]="!availableFields.length"
|
|
@@ -14446,8 +15353,8 @@ class LayoutEditorComponent {
|
|
|
14446
15353
|
>
|
|
14447
15354
|
<mat-icon>chevron_right</mat-icon>
|
|
14448
15355
|
</button>
|
|
14449
|
-
<h4>
|
|
14450
|
-
<small class="available-fields__hint">
|
|
15356
|
+
<h4>{{ t('apiFields.heading') }}</h4>
|
|
15357
|
+
<small class="available-fields__hint">{{ t('apiFields.hint') }}</small>
|
|
14451
15358
|
<div
|
|
14452
15359
|
cdkDropList
|
|
14453
15360
|
id="available-fields-list"
|
|
@@ -14472,8 +15379,12 @@ class LayoutEditorComponent {
|
|
|
14472
15379
|
<mat-icon>chevron_left</mat-icon>
|
|
14473
15380
|
</button>
|
|
14474
15381
|
<div class="layout-canvas">
|
|
14475
|
-
<div
|
|
14476
|
-
|
|
15382
|
+
<div
|
|
15383
|
+
class="no-fields-chip"
|
|
15384
|
+
data-testid="layout-editor-api-fields-empty"
|
|
15385
|
+
*ngIf="!availableFields.length"
|
|
15386
|
+
>
|
|
15387
|
+
{{ t('apiFields.empty') }}
|
|
14477
15388
|
</div>
|
|
14478
15389
|
<div
|
|
14479
15390
|
cdkDropList
|
|
@@ -14487,6 +15398,7 @@ class LayoutEditorComponent {
|
|
|
14487
15398
|
[sectionIndex]="i"
|
|
14488
15399
|
[allSections]="config.sections"
|
|
14489
15400
|
[fieldMetadata]="config.fieldMetadata || []"
|
|
15401
|
+
[availableFields]="availableFields"
|
|
14490
15402
|
[selected]="selected"
|
|
14491
15403
|
[gapGlobal]="gapGlobal || 16"
|
|
14492
15404
|
[availableFieldsListId]="
|
|
@@ -14498,6 +15410,12 @@ class LayoutEditorComponent {
|
|
|
14498
15410
|
(sectionChange)="onSectionUpdated(i, $event)"
|
|
14499
15411
|
(applyStyleToAll)="onApplyStyleToAll($event)"
|
|
14500
15412
|
(fieldDrop)="dropField($event)"
|
|
15413
|
+
(addVisualBlock)="addVisualBlockToColumn($event)"
|
|
15414
|
+
(addApiField)="addApiFieldToColumn($event)"
|
|
15415
|
+
(editVisualBlock)="openVisualBlockEditor($event)"
|
|
15416
|
+
(moveVisualBlock)="moveVisualBlock($event)"
|
|
15417
|
+
(moveVisualBlockToColumn)="moveVisualBlockToColumn($event)"
|
|
15418
|
+
(removeVisualBlock)="removeVisualBlock($event)"
|
|
14501
15419
|
cdkDrag
|
|
14502
15420
|
></praxis-section-configurator>
|
|
14503
15421
|
</div>
|
|
@@ -14515,7 +15433,7 @@ class LayoutEditorComponent {
|
|
|
14515
15433
|
</div>
|
|
14516
15434
|
</div>
|
|
14517
15435
|
</div>
|
|
14518
|
-
`, isInline: true, styles: [".layout-editor-wrapper{display:flex;flex-wrap:wrap;gap:16px}.layout-editor-wrapper.no-available-fields{gap:0}.editor-toolbar{position:sticky;top:0;z-index:3;display:flex;gap:16px;align-items:center;min-height:56px;background:var(--md-sys-color-surface-container);border-bottom:1px solid var(--md-sys-color-outline-variant);box-shadow:var(--md-sys-elevation-level1, var(--md-sys-elevation-level1));padding:0 12px;margin:0 0 var(--px-editor-section-gap, 16px) 0}.editor-toolbar .title-block{display:flex;flex-direction:column;justify-content:center;gap:2px}.editor-toolbar .toolbar-title{font:var(--mdc-typography-title-small, 600 15px/20px system-ui);color:var(--md-sys-color-on-surface)}.editor-toolbar .toolbar-subtitle{font:var(--mdc-typography-body-small, 400 12px/16px system-ui);color:var(--md-sys-color-on-surface-variant)}.editor-toolbar .spacer{flex:1 1 auto}.editor-toolbar .toolbar-group{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}.editor-toolbar .gap-group{align-items:center}.editor-toolbar .group-label{font:var(--mdc-typography-label-medium, 500 12px/16px system-ui);color:var(--md-sys-color-on-surface-variant)}.editor-toolbar .gap-group{align-items:center;gap:10px}.editor-toolbar .density-control{display:flex;align-items:center;gap:8px}.editor-toolbar .density-label{font:var(--mdc-typography-label-medium, 500 12px/16px system-ui);opacity:.9}.editor-toolbar .density-toggle,.editor-toolbar .toggle-icons-group{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;overflow:hidden;background:var(--md-sys-color-surface-container-low)}.editor-toolbar .density-toggle .mat-button-toggle,.editor-toolbar .toggle-icons-group .mat-button-toggle{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant)}.editor-toolbar .density-toggle .mat-button-toggle+.mat-button-toggle,.editor-toolbar .toggle-icons-group .mat-button-toggle+.mat-button-toggle{border-left:1px solid var(--md-sys-color-outline-variant)}.editor-toolbar .density-toggle .mat-button-toggle-button,.toggle-icons-group .mat-button-toggle-button{height:32px}.editor-toolbar .density-toggle .mat-icon,.toggle-icons-group .mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.editor-toolbar .density-toggle .mat-icon,.editor-toolbar .toggle-icons-group .mat-icon{color:inherit}.gap-chip{display:inline-flex;align-items:center;gap:2px;padding:0 4px;height:32px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-variant)}.gap-chip__btn{width:24px;height:24px;line-height:24px;min-width:0;padding:0;--mdc-icon-button-size: 24px;--mdc-icon-button-state-layer-size: 24px}.gap-chip .mat-mdc-button-touch-target{width:24px;height:24px}.gap-chip mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.gap-chip__input{width:42px;border:none;background:transparent;color:var(--md-sys-color-on-surface);font:var(--mdc-typography-body-medium, 600 13px/18px system-ui);text-align:center;outline:none;-moz-appearance:textfield}.gap-chip__input::-webkit-outer-spin-button,.gap-chip__input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.gap-chip__suffix{color:var(--md-sys-color-on-surface-variant);font:var(--mdc-typography-label-medium, 500 12px/16px system-ui)}.pill{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border-radius:12px;background:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);font-size:12px}.pill.subtle{background:transparent;color:var(--md-sys-color-on-surface-variant);padding-left:0}.available-fields{width:250px;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:10px;background:var(--md-sys-color-surface)}.collapse-toggle{float:right}.available-fields__hint{display:block;margin-bottom:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px}.no-fields-chip{position:absolute;top:8px;right:8px;padding:4px 8px;border:1px dashed var(--md-sys-color-outline);border-radius:16px;color:var(--md-sys-color-outline);font-size:12px;background:var(--md-sys-color-surface);pointer-events:none}.layout-canvas{flex-grow:1;overflow:visible;max-height:none;position:relative}.field-list{min-height:100px}.section-list{display:flex;flex-direction:column;gap:var(--pfx-section-gap, 20px)}.add-section-container{position:relative;padding-top:16px;margin-top:12px;border-top:1px solid var(--md-sys-color-outline-variant);min-height:28px}.fab-add-section{position:absolute;top:-30px;left:50%;transform:translate(-50%,calc(-50% - var(--pfx-divider-w, 1px)));z-index:2;--pfx-fab-size: var(--pfx-fab-size-section, 32px);--pfx-fab-icon: var(--pfx-fab-icon-section, 18px);width:var(--pfx-fab-size);height:var(--pfx-fab-size);border-radius:50%}.fab-add-section mat-icon{font-size:var(--pfx-fab-icon);width:var(--pfx-fab-icon);height:var(--pfx-fab-icon)}.fab-add-section.mat-mdc-fab{width:var(--pfx-fab-size);height:var(--pfx-fab-size);padding:0}.fab-add-section .mat-mdc-button-touch-target,.fab-add-section .mat-mdc-button-persistent-ripple,.fab-add-section .mat-mdc-button-ripple{width:var(--pfx-fab-size);height:var(--pfx-fab-size)}.cdk-drag-placeholder{opacity:.3;transition:opacity .2s ease}:host ::ng-deep .mdc-text-field--filled{--mdc-filled-text-field-container-color: var(--md-sys-color-surface-container)}:host ::ng-deep .mdc-text-field__input::placeholder{color:var(--md-sys-color-on-surface-variant)!important;opacity:.95}:host ::ng-deep .mat-mdc-form-field-subscript-wrapper,:host ::ng-deep .mat-mdc-hint{color:var(--md-sys-color-on-surface-variant)!important}:host ::ng-deep .mdc-text-field--disabled .mdc-text-field__input,:host ::ng-deep .mat-mdc-select-disabled .mat-mdc-select-value{color:var(--md-sys-color-on-surface-variant)!important}:host ::ng-deep .mat-button-toggle-checked{background:var(--md-sys-color-primary-container)!important;color:var(--md-sys-color-on-primary-container)!important}:host ::ng-deep .editor-toolbar .mat-button-toggle-appearance-standard{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .editor-toolbar .mat-button-toggle-appearance-standard:hover{background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface)}:host ::ng-deep .editor-toolbar .mat-button-toggle-checked:hover{background:var(--md-sys-color-primary-container)!important;color:var(--md-sys-color-on-primary-container)!important}:host{--px-editor-section-gap: 16px;--pfx-grid-gap: 12px;--pfx-section-gap: var(--px-editor-section-gap)}@media(min-width:960px){:host{--px-editor-section-gap: 20px;--pfx-grid-gap: 16px}}@media(min-width:1280px){:host{--px-editor-section-gap: 24px;--pfx-grid-gap: 20px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i2$2.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i2$2.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i2$2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "component", type: SectionConfiguratorComponent, selector: "praxis-section-configurator", inputs: ["section", "sectionIndex", "allSections", "fieldMetadata", "selected", "availableFieldsListId", "columnDropListIds", "gapGlobal"], outputs: ["sectionChange", "applyStyleToAll", "remove", "select", "fieldDrop"] }, { kind: "component", type: FieldConfiguratorComponent, selector: "praxis-field-configurator", inputs: ["field"] }, { kind: "ngmodule", type: MatButtonModule }, { 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: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: MatToolbarModule }, { kind: "component", type: i6$1.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i7$2.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i7$2.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: 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.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.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
15436
|
+
`, isInline: true, styles: [".layout-editor-wrapper{display:flex;flex-wrap:wrap;gap:16px}.layout-editor-wrapper.no-available-fields{gap:0}.editor-toolbar{position:sticky;top:0;z-index:3;display:flex;gap:16px;align-items:center;min-height:56px;background:var(--md-sys-color-surface-container);border-bottom:1px solid var(--md-sys-color-outline-variant);box-shadow:var(--md-sys-elevation-level1, var(--md-sys-elevation-level1));padding:0 12px;margin:0 0 var(--px-editor-section-gap, 16px) 0}.editor-toolbar .title-block{display:flex;flex-direction:column;justify-content:center;gap:2px}.editor-toolbar .toolbar-title{font:var(--mdc-typography-title-small, 600 15px/20px system-ui);color:var(--md-sys-color-on-surface)}.editor-toolbar .toolbar-subtitle{font:var(--mdc-typography-body-small, 400 12px/16px system-ui);color:var(--md-sys-color-on-surface-variant)}.editor-toolbar .spacer{flex:1 1 auto}.editor-toolbar .toolbar-group{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}.editor-toolbar .gap-group{align-items:center}.editor-toolbar .group-label{font:var(--mdc-typography-label-medium, 500 12px/16px system-ui);color:var(--md-sys-color-on-surface-variant)}.editor-toolbar .gap-group{align-items:center;gap:10px}.editor-toolbar .density-control{display:flex;align-items:center;gap:8px}.editor-toolbar .density-label{font:var(--mdc-typography-label-medium, 500 12px/16px system-ui);opacity:.9}.editor-toolbar .density-toggle,.editor-toolbar .toggle-icons-group{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;overflow:hidden;background:var(--md-sys-color-surface-container-low)}.editor-toolbar .density-toggle .mat-button-toggle,.editor-toolbar .toggle-icons-group .mat-button-toggle{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant)}.editor-toolbar .density-toggle .mat-button-toggle+.mat-button-toggle,.editor-toolbar .toggle-icons-group .mat-button-toggle+.mat-button-toggle{border-left:1px solid var(--md-sys-color-outline-variant)}.editor-toolbar .density-toggle .mat-button-toggle-button,.toggle-icons-group .mat-button-toggle-button{height:32px}.editor-toolbar .density-toggle .mat-icon,.toggle-icons-group .mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.editor-toolbar .density-toggle .mat-icon,.editor-toolbar .toggle-icons-group .mat-icon{color:inherit}.gap-chip{display:inline-flex;align-items:center;gap:2px;padding:0 4px;height:32px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-variant)}.gap-chip__btn{width:24px;height:24px;line-height:24px;min-width:0;padding:0;--mdc-icon-button-size: 24px;--mdc-icon-button-state-layer-size: 24px}.gap-chip .mat-mdc-button-touch-target{width:24px;height:24px}.gap-chip mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.gap-chip__input{width:42px;border:none;background:transparent;color:var(--md-sys-color-on-surface);font:var(--mdc-typography-body-medium, 600 13px/18px system-ui);text-align:center;outline:none;-moz-appearance:textfield}.gap-chip__input::-webkit-outer-spin-button,.gap-chip__input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.gap-chip__suffix{color:var(--md-sys-color-on-surface-variant);font:var(--mdc-typography-label-medium, 500 12px/16px system-ui)}.pill{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border-radius:12px;background:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);font-size:12px}.pill.subtle{background:transparent;color:var(--md-sys-color-on-surface-variant);padding-left:0}.available-fields{width:250px;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:10px;background:var(--md-sys-color-surface)}.collapse-toggle{float:right}.available-fields__hint{display:block;margin-bottom:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px}.no-fields-chip{position:absolute;top:8px;right:8px;padding:4px 8px;border:1px dashed var(--md-sys-color-outline);border-radius:16px;color:var(--md-sys-color-outline);font-size:12px;background:var(--md-sys-color-surface);pointer-events:none}.layout-canvas{flex-grow:1;overflow:visible;max-height:none;position:relative}.field-list{min-height:100px}.section-list{display:flex;flex-direction:column;gap:var(--pfx-section-gap, 20px)}.add-section-container{position:relative;padding-top:16px;margin-top:12px;border-top:1px solid var(--md-sys-color-outline-variant);min-height:28px}.fab-add-section{position:absolute;top:-30px;left:50%;transform:translate(-50%,calc(-50% - var(--pfx-divider-w, 1px)));z-index:2;--pfx-fab-size: var(--pfx-fab-size-section, 32px);--pfx-fab-icon: var(--pfx-fab-icon-section, 18px);width:var(--pfx-fab-size);height:var(--pfx-fab-size);border-radius:50%}.fab-add-section mat-icon{font-size:var(--pfx-fab-icon);width:var(--pfx-fab-icon);height:var(--pfx-fab-icon)}.fab-add-section.mat-mdc-fab{width:var(--pfx-fab-size);height:var(--pfx-fab-size);padding:0}.fab-add-section .mat-mdc-button-touch-target,.fab-add-section .mat-mdc-button-persistent-ripple,.fab-add-section .mat-mdc-button-ripple{width:var(--pfx-fab-size);height:var(--pfx-fab-size)}.cdk-drag-placeholder{opacity:.3;transition:opacity .2s ease}:host ::ng-deep .mdc-text-field--filled{--mdc-filled-text-field-container-color: var(--md-sys-color-surface-container)}:host ::ng-deep .mdc-text-field__input::placeholder{color:var(--md-sys-color-on-surface-variant)!important;opacity:.95}:host ::ng-deep .mat-mdc-form-field-subscript-wrapper,:host ::ng-deep .mat-mdc-hint{color:var(--md-sys-color-on-surface-variant)!important}:host ::ng-deep .mdc-text-field--disabled .mdc-text-field__input,:host ::ng-deep .mat-mdc-select-disabled .mat-mdc-select-value{color:var(--md-sys-color-on-surface-variant)!important}:host ::ng-deep .mat-button-toggle-checked{background:var(--md-sys-color-primary-container)!important;color:var(--md-sys-color-on-primary-container)!important}:host ::ng-deep .editor-toolbar .mat-button-toggle-appearance-standard{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .editor-toolbar .mat-button-toggle-appearance-standard:hover{background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface)}:host ::ng-deep .editor-toolbar .mat-button-toggle-checked:hover{background:var(--md-sys-color-primary-container)!important;color:var(--md-sys-color-on-primary-container)!important}:host{--px-editor-section-gap: 16px;--pfx-grid-gap: 12px;--pfx-section-gap: var(--px-editor-section-gap)}@media(min-width:960px){:host{--px-editor-section-gap: 20px;--pfx-grid-gap: 16px}}@media(min-width:1280px){:host{--px-editor-section-gap: 24px;--pfx-grid-gap: 20px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i2$2.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i2$2.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i2$2.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "component", type: SectionConfiguratorComponent, selector: "praxis-section-configurator", inputs: ["section", "sectionIndex", "allSections", "fieldMetadata", "availableFields", "selected", "availableFieldsListId", "columnDropListIds", "gapGlobal"], outputs: ["sectionChange", "applyStyleToAll", "remove", "select", "fieldDrop", "addVisualBlock", "addApiField", "editVisualBlock", "moveVisualBlock", "moveVisualBlockToColumn", "removeVisualBlock"] }, { kind: "component", type: FieldConfiguratorComponent, selector: "praxis-field-configurator", inputs: ["field"] }, { kind: "ngmodule", type: MatButtonModule }, { 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: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: MatToolbarModule }, { kind: "component", type: i6$1.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i7$2.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i7$2.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: 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.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.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
|
|
14519
15437
|
}
|
|
14520
15438
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: LayoutEditorComponent, decorators: [{
|
|
14521
15439
|
type: Component,
|
|
@@ -14620,8 +15538,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14620
15538
|
>
|
|
14621
15539
|
<mat-icon>chevron_right</mat-icon>
|
|
14622
15540
|
</button>
|
|
14623
|
-
<h4>
|
|
14624
|
-
<small class="available-fields__hint">
|
|
15541
|
+
<h4>{{ t('apiFields.heading') }}</h4>
|
|
15542
|
+
<small class="available-fields__hint">{{ t('apiFields.hint') }}</small>
|
|
14625
15543
|
<div
|
|
14626
15544
|
cdkDropList
|
|
14627
15545
|
id="available-fields-list"
|
|
@@ -14646,8 +15564,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14646
15564
|
<mat-icon>chevron_left</mat-icon>
|
|
14647
15565
|
</button>
|
|
14648
15566
|
<div class="layout-canvas">
|
|
14649
|
-
<div
|
|
14650
|
-
|
|
15567
|
+
<div
|
|
15568
|
+
class="no-fields-chip"
|
|
15569
|
+
data-testid="layout-editor-api-fields-empty"
|
|
15570
|
+
*ngIf="!availableFields.length"
|
|
15571
|
+
>
|
|
15572
|
+
{{ t('apiFields.empty') }}
|
|
14651
15573
|
</div>
|
|
14652
15574
|
<div
|
|
14653
15575
|
cdkDropList
|
|
@@ -14661,6 +15583,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14661
15583
|
[sectionIndex]="i"
|
|
14662
15584
|
[allSections]="config.sections"
|
|
14663
15585
|
[fieldMetadata]="config.fieldMetadata || []"
|
|
15586
|
+
[availableFields]="availableFields"
|
|
14664
15587
|
[selected]="selected"
|
|
14665
15588
|
[gapGlobal]="gapGlobal || 16"
|
|
14666
15589
|
[availableFieldsListId]="
|
|
@@ -14672,6 +15595,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14672
15595
|
(sectionChange)="onSectionUpdated(i, $event)"
|
|
14673
15596
|
(applyStyleToAll)="onApplyStyleToAll($event)"
|
|
14674
15597
|
(fieldDrop)="dropField($event)"
|
|
15598
|
+
(addVisualBlock)="addVisualBlockToColumn($event)"
|
|
15599
|
+
(addApiField)="addApiFieldToColumn($event)"
|
|
15600
|
+
(editVisualBlock)="openVisualBlockEditor($event)"
|
|
15601
|
+
(moveVisualBlock)="moveVisualBlock($event)"
|
|
15602
|
+
(moveVisualBlockToColumn)="moveVisualBlockToColumn($event)"
|
|
15603
|
+
(removeVisualBlock)="removeVisualBlock($event)"
|
|
14675
15604
|
cdkDrag
|
|
14676
15605
|
></praxis-section-configurator>
|
|
14677
15606
|
</div>
|
|
@@ -14689,7 +15618,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14689
15618
|
</div>
|
|
14690
15619
|
</div>
|
|
14691
15620
|
</div>
|
|
14692
|
-
`, styles: [".layout-editor-wrapper{display:flex;flex-wrap:wrap;gap:16px}.layout-editor-wrapper.no-available-fields{gap:0}.editor-toolbar{position:sticky;top:0;z-index:3;display:flex;gap:16px;align-items:center;min-height:56px;background:var(--md-sys-color-surface-container);border-bottom:1px solid var(--md-sys-color-outline-variant);box-shadow:var(--md-sys-elevation-level1, var(--md-sys-elevation-level1));padding:0 12px;margin:0 0 var(--px-editor-section-gap, 16px) 0}.editor-toolbar .title-block{display:flex;flex-direction:column;justify-content:center;gap:2px}.editor-toolbar .toolbar-title{font:var(--mdc-typography-title-small, 600 15px/20px system-ui);color:var(--md-sys-color-on-surface)}.editor-toolbar .toolbar-subtitle{font:var(--mdc-typography-body-small, 400 12px/16px system-ui);color:var(--md-sys-color-on-surface-variant)}.editor-toolbar .spacer{flex:1 1 auto}.editor-toolbar .toolbar-group{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}.editor-toolbar .gap-group{align-items:center}.editor-toolbar .group-label{font:var(--mdc-typography-label-medium, 500 12px/16px system-ui);color:var(--md-sys-color-on-surface-variant)}.editor-toolbar .gap-group{align-items:center;gap:10px}.editor-toolbar .density-control{display:flex;align-items:center;gap:8px}.editor-toolbar .density-label{font:var(--mdc-typography-label-medium, 500 12px/16px system-ui);opacity:.9}.editor-toolbar .density-toggle,.editor-toolbar .toggle-icons-group{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;overflow:hidden;background:var(--md-sys-color-surface-container-low)}.editor-toolbar .density-toggle .mat-button-toggle,.editor-toolbar .toggle-icons-group .mat-button-toggle{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant)}.editor-toolbar .density-toggle .mat-button-toggle+.mat-button-toggle,.editor-toolbar .toggle-icons-group .mat-button-toggle+.mat-button-toggle{border-left:1px solid var(--md-sys-color-outline-variant)}.editor-toolbar .density-toggle .mat-button-toggle-button,.toggle-icons-group .mat-button-toggle-button{height:32px}.editor-toolbar .density-toggle .mat-icon,.toggle-icons-group .mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.editor-toolbar .density-toggle .mat-icon,.editor-toolbar .toggle-icons-group .mat-icon{color:inherit}.gap-chip{display:inline-flex;align-items:center;gap:2px;padding:0 4px;height:32px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-variant)}.gap-chip__btn{width:24px;height:24px;line-height:24px;min-width:0;padding:0;--mdc-icon-button-size: 24px;--mdc-icon-button-state-layer-size: 24px}.gap-chip .mat-mdc-button-touch-target{width:24px;height:24px}.gap-chip mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.gap-chip__input{width:42px;border:none;background:transparent;color:var(--md-sys-color-on-surface);font:var(--mdc-typography-body-medium, 600 13px/18px system-ui);text-align:center;outline:none;-moz-appearance:textfield}.gap-chip__input::-webkit-outer-spin-button,.gap-chip__input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.gap-chip__suffix{color:var(--md-sys-color-on-surface-variant);font:var(--mdc-typography-label-medium, 500 12px/16px system-ui)}.pill{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border-radius:12px;background:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);font-size:12px}.pill.subtle{background:transparent;color:var(--md-sys-color-on-surface-variant);padding-left:0}.available-fields{width:250px;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:10px;background:var(--md-sys-color-surface)}.collapse-toggle{float:right}.available-fields__hint{display:block;margin-bottom:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px}.no-fields-chip{position:absolute;top:8px;right:8px;padding:4px 8px;border:1px dashed var(--md-sys-color-outline);border-radius:16px;color:var(--md-sys-color-outline);font-size:12px;background:var(--md-sys-color-surface);pointer-events:none}.layout-canvas{flex-grow:1;overflow:visible;max-height:none;position:relative}.field-list{min-height:100px}.section-list{display:flex;flex-direction:column;gap:var(--pfx-section-gap, 20px)}.add-section-container{position:relative;padding-top:16px;margin-top:12px;border-top:1px solid var(--md-sys-color-outline-variant);min-height:28px}.fab-add-section{position:absolute;top:-30px;left:50%;transform:translate(-50%,calc(-50% - var(--pfx-divider-w, 1px)));z-index:2;--pfx-fab-size: var(--pfx-fab-size-section, 32px);--pfx-fab-icon: var(--pfx-fab-icon-section, 18px);width:var(--pfx-fab-size);height:var(--pfx-fab-size);border-radius:50%}.fab-add-section mat-icon{font-size:var(--pfx-fab-icon);width:var(--pfx-fab-icon);height:var(--pfx-fab-icon)}.fab-add-section.mat-mdc-fab{width:var(--pfx-fab-size);height:var(--pfx-fab-size);padding:0}.fab-add-section .mat-mdc-button-touch-target,.fab-add-section .mat-mdc-button-persistent-ripple,.fab-add-section .mat-mdc-button-ripple{width:var(--pfx-fab-size);height:var(--pfx-fab-size)}.cdk-drag-placeholder{opacity:.3;transition:opacity .2s ease}:host ::ng-deep .mdc-text-field--filled{--mdc-filled-text-field-container-color: var(--md-sys-color-surface-container)}:host ::ng-deep .mdc-text-field__input::placeholder{color:var(--md-sys-color-on-surface-variant)!important;opacity:.95}:host ::ng-deep .mat-mdc-form-field-subscript-wrapper,:host ::ng-deep .mat-mdc-hint{color:var(--md-sys-color-on-surface-variant)!important}:host ::ng-deep .mdc-text-field--disabled .mdc-text-field__input,:host ::ng-deep .mat-mdc-select-disabled .mat-mdc-select-value{color:var(--md-sys-color-on-surface-variant)!important}:host ::ng-deep .mat-button-toggle-checked{background:var(--md-sys-color-primary-container)!important;color:var(--md-sys-color-on-primary-container)!important}:host ::ng-deep .editor-toolbar .mat-button-toggle-appearance-standard{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .editor-toolbar .mat-button-toggle-appearance-standard:hover{background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface)}:host ::ng-deep .editor-toolbar .mat-button-toggle-checked:hover{background:var(--md-sys-color-primary-container)!important;color:var(--md-sys-color-on-primary-container)!important}:host{--px-editor-section-gap: 16px;--pfx-grid-gap: 12px;--pfx-section-gap: var(--px-editor-section-gap)}@media(min-width:960px){:host{--px-editor-section-gap: 20px;--pfx-grid-gap: 16px}}@media(min-width:1280px){:host{--px-editor-section-gap: 24px;--pfx-grid-gap: 20px}}\n"] }]
|
|
15621
|
+
`, providers: [providePraxisI18nConfig(LAYOUT_EDITOR_I18N_CONFIG)], styles: [".layout-editor-wrapper{display:flex;flex-wrap:wrap;gap:16px}.layout-editor-wrapper.no-available-fields{gap:0}.editor-toolbar{position:sticky;top:0;z-index:3;display:flex;gap:16px;align-items:center;min-height:56px;background:var(--md-sys-color-surface-container);border-bottom:1px solid var(--md-sys-color-outline-variant);box-shadow:var(--md-sys-elevation-level1, var(--md-sys-elevation-level1));padding:0 12px;margin:0 0 var(--px-editor-section-gap, 16px) 0}.editor-toolbar .title-block{display:flex;flex-direction:column;justify-content:center;gap:2px}.editor-toolbar .toolbar-title{font:var(--mdc-typography-title-small, 600 15px/20px system-ui);color:var(--md-sys-color-on-surface)}.editor-toolbar .toolbar-subtitle{font:var(--mdc-typography-body-small, 400 12px/16px system-ui);color:var(--md-sys-color-on-surface-variant)}.editor-toolbar .spacer{flex:1 1 auto}.editor-toolbar .toolbar-group{display:inline-flex;align-items:center;gap:8px;flex-wrap:wrap}.editor-toolbar .gap-group{align-items:center}.editor-toolbar .group-label{font:var(--mdc-typography-label-medium, 500 12px/16px system-ui);color:var(--md-sys-color-on-surface-variant)}.editor-toolbar .gap-group{align-items:center;gap:10px}.editor-toolbar .density-control{display:flex;align-items:center;gap:8px}.editor-toolbar .density-label{font:var(--mdc-typography-label-medium, 500 12px/16px system-ui);opacity:.9}.editor-toolbar .density-toggle,.editor-toolbar .toggle-icons-group{border:1px solid var(--md-sys-color-outline-variant);border-radius:999px;overflow:hidden;background:var(--md-sys-color-surface-container-low)}.editor-toolbar .density-toggle .mat-button-toggle,.editor-toolbar .toggle-icons-group .mat-button-toggle{background:var(--md-sys-color-surface-container-low);color:var(--md-sys-color-on-surface-variant)}.editor-toolbar .density-toggle .mat-button-toggle+.mat-button-toggle,.editor-toolbar .toggle-icons-group .mat-button-toggle+.mat-button-toggle{border-left:1px solid var(--md-sys-color-outline-variant)}.editor-toolbar .density-toggle .mat-button-toggle-button,.toggle-icons-group .mat-button-toggle-button{height:32px}.editor-toolbar .density-toggle .mat-icon,.toggle-icons-group .mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.editor-toolbar .density-toggle .mat-icon,.editor-toolbar .toggle-icons-group .mat-icon{color:inherit}.gap-chip{display:inline-flex;align-items:center;gap:2px;padding:0 4px;height:32px;border-radius:8px;border:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-variant)}.gap-chip__btn{width:24px;height:24px;line-height:24px;min-width:0;padding:0;--mdc-icon-button-size: 24px;--mdc-icon-button-state-layer-size: 24px}.gap-chip .mat-mdc-button-touch-target{width:24px;height:24px}.gap-chip mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.gap-chip__input{width:42px;border:none;background:transparent;color:var(--md-sys-color-on-surface);font:var(--mdc-typography-body-medium, 600 13px/18px system-ui);text-align:center;outline:none;-moz-appearance:textfield}.gap-chip__input::-webkit-outer-spin-button,.gap-chip__input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.gap-chip__suffix{color:var(--md-sys-color-on-surface-variant);font:var(--mdc-typography-label-medium, 500 12px/16px system-ui)}.pill{display:inline-flex;align-items:center;gap:6px;padding:4px 8px;border-radius:12px;background:var(--md-sys-color-surface-variant);color:var(--md-sys-color-on-surface-variant);font-size:12px}.pill.subtle{background:transparent;color:var(--md-sys-color-on-surface-variant);padding-left:0}.available-fields{width:250px;border:1px solid var(--md-sys-color-outline-variant);border-radius:12px;padding:10px;background:var(--md-sys-color-surface)}.collapse-toggle{float:right}.available-fields__hint{display:block;margin-bottom:8px;color:var(--md-sys-color-on-surface-variant);font-size:12px}.no-fields-chip{position:absolute;top:8px;right:8px;padding:4px 8px;border:1px dashed var(--md-sys-color-outline);border-radius:16px;color:var(--md-sys-color-outline);font-size:12px;background:var(--md-sys-color-surface);pointer-events:none}.layout-canvas{flex-grow:1;overflow:visible;max-height:none;position:relative}.field-list{min-height:100px}.section-list{display:flex;flex-direction:column;gap:var(--pfx-section-gap, 20px)}.add-section-container{position:relative;padding-top:16px;margin-top:12px;border-top:1px solid var(--md-sys-color-outline-variant);min-height:28px}.fab-add-section{position:absolute;top:-30px;left:50%;transform:translate(-50%,calc(-50% - var(--pfx-divider-w, 1px)));z-index:2;--pfx-fab-size: var(--pfx-fab-size-section, 32px);--pfx-fab-icon: var(--pfx-fab-icon-section, 18px);width:var(--pfx-fab-size);height:var(--pfx-fab-size);border-radius:50%}.fab-add-section mat-icon{font-size:var(--pfx-fab-icon);width:var(--pfx-fab-icon);height:var(--pfx-fab-icon)}.fab-add-section.mat-mdc-fab{width:var(--pfx-fab-size);height:var(--pfx-fab-size);padding:0}.fab-add-section .mat-mdc-button-touch-target,.fab-add-section .mat-mdc-button-persistent-ripple,.fab-add-section .mat-mdc-button-ripple{width:var(--pfx-fab-size);height:var(--pfx-fab-size)}.cdk-drag-placeholder{opacity:.3;transition:opacity .2s ease}:host ::ng-deep .mdc-text-field--filled{--mdc-filled-text-field-container-color: var(--md-sys-color-surface-container)}:host ::ng-deep .mdc-text-field__input::placeholder{color:var(--md-sys-color-on-surface-variant)!important;opacity:.95}:host ::ng-deep .mat-mdc-form-field-subscript-wrapper,:host ::ng-deep .mat-mdc-hint{color:var(--md-sys-color-on-surface-variant)!important}:host ::ng-deep .mdc-text-field--disabled .mdc-text-field__input,:host ::ng-deep .mat-mdc-select-disabled .mat-mdc-select-value{color:var(--md-sys-color-on-surface-variant)!important}:host ::ng-deep .mat-button-toggle-checked{background:var(--md-sys-color-primary-container)!important;color:var(--md-sys-color-on-primary-container)!important}:host ::ng-deep .editor-toolbar .mat-button-toggle-appearance-standard{color:var(--md-sys-color-on-surface-variant)}:host ::ng-deep .editor-toolbar .mat-button-toggle-appearance-standard:hover{background:var(--md-sys-color-surface-container-high);color:var(--md-sys-color-on-surface)}:host ::ng-deep .editor-toolbar .mat-button-toggle-checked:hover{background:var(--md-sys-color-primary-container)!important;color:var(--md-sys-color-on-primary-container)!important}:host{--px-editor-section-gap: 16px;--pfx-grid-gap: 12px;--pfx-section-gap: var(--px-editor-section-gap)}@media(min-width:960px){:host{--px-editor-section-gap: 20px;--pfx-grid-gap: 16px}}@media(min-width:1280px){:host{--px-editor-section-gap: 24px;--pfx-grid-gap: 20px}}\n"] }]
|
|
14693
15622
|
}], propDecorators: { config: [{
|
|
14694
15623
|
type: Input
|
|
14695
15624
|
}], configChange: [{
|
|
@@ -19919,7 +20848,8 @@ class PraxisFilterForm {
|
|
|
19919
20848
|
}
|
|
19920
20849
|
getColumnFields(column) {
|
|
19921
20850
|
const metas = this.fieldMetadata;
|
|
19922
|
-
|
|
20851
|
+
const fieldNames = new Set(getFormColumnFieldNames(column));
|
|
20852
|
+
return metas.filter((m) => fieldNames.has(m.name));
|
|
19923
20853
|
}
|
|
19924
20854
|
get fieldMetadata() {
|
|
19925
20855
|
return this.config?.fieldMetadata || [];
|
|
@@ -24045,7 +24975,7 @@ const FORM_COMPONENT_AI_CAPABILITIES = {
|
|
|
24045
24975
|
* Manifesto de authoring canônico para o componente praxis-dynamic-form.
|
|
24046
24976
|
* Este arquivo define as operações permitidas pela IA para editar formulários.
|
|
24047
24977
|
*
|
|
24048
|
-
* @version 1.
|
|
24978
|
+
* @version 1.5.0
|
|
24049
24979
|
* @status COMPLIANT - Alinhado com contrato v2, gate de aceitação e semântica local/schema-backed.
|
|
24050
24980
|
*/
|
|
24051
24981
|
const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
@@ -24053,7 +24983,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24053
24983
|
componentId: 'praxis-dynamic-form',
|
|
24054
24984
|
ownerPackage: '@praxisui/dynamic-form',
|
|
24055
24985
|
configSchemaId: 'FormConfig',
|
|
24056
|
-
manifestVersion: '1.
|
|
24986
|
+
manifestVersion: '1.5.0',
|
|
24057
24987
|
runtimeInputs: [
|
|
24058
24988
|
{ name: 'config', type: 'FormConfig', description: 'Configuração completa do formulário' },
|
|
24059
24989
|
{ name: 'resourcePath', type: 'string', description: 'Caminho do recurso (API)' },
|
|
@@ -24076,6 +25006,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24076
25006
|
* Usado conceitualmente por layout.field.move; declarado como target para futuras ops
|
|
24077
25007
|
* de reposicionamento granular (ex: layout.placement.swap).
|
|
24078
25008
|
*/
|
|
25009
|
+
{ kind: 'visualBlock', resolver: 'layout-item-by-id', description: 'Blocos visuais richContent em sections[].rows[].columns[].items[]; não participam do payload de submissão' },
|
|
24079
25010
|
{ kind: 'layoutPlacement', resolver: 'layout-placement-by-field', description: 'Posicionamento de campo no layout; target para ops de reposicionamento' },
|
|
24080
25011
|
{ kind: 'formAction', resolver: 'action-by-id-or-label', description: 'Ações da toolbar (submit, cancel, reset)' },
|
|
24081
25012
|
{ kind: 'formRule', resolver: 'rule-by-id-or-name', description: 'Regras de visibilidade e validação' },
|
|
@@ -24102,7 +25033,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24102
25033
|
effects: [{ kind: 'merge-by-key', path: 'fieldMetadata[]', key: 'name' }],
|
|
24103
25034
|
validators: ['field-exists'],
|
|
24104
25035
|
affectedPaths: ['fieldMetadata[].label'],
|
|
24105
|
-
submissionImpact:
|
|
25036
|
+
submissionImpact: 'visual-only',
|
|
24106
25037
|
preconditions: ['config-initialized', 'target-exists']
|
|
24107
25038
|
},
|
|
24108
25039
|
{
|
|
@@ -24119,7 +25050,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24119
25050
|
effects: [{ kind: 'merge-by-key', path: 'fieldMetadata[]', key: 'name' }],
|
|
24120
25051
|
validators: ['field-exists'],
|
|
24121
25052
|
affectedPaths: ['fieldMetadata[].placeholder'],
|
|
24122
|
-
submissionImpact:
|
|
25053
|
+
submissionImpact: 'visual-only',
|
|
24123
25054
|
preconditions: ['config-initialized', 'target-exists']
|
|
24124
25055
|
},
|
|
24125
25056
|
{
|
|
@@ -24136,7 +25067,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24136
25067
|
effects: [{ kind: 'merge-by-key', path: 'fieldMetadata[]', key: 'name' }],
|
|
24137
25068
|
validators: ['field-exists'],
|
|
24138
25069
|
affectedPaths: ['fieldMetadata[].required'],
|
|
24139
|
-
submissionImpact:
|
|
25070
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
24140
25071
|
preconditions: ['config-initialized', 'target-exists']
|
|
24141
25072
|
},
|
|
24142
25073
|
{
|
|
@@ -24153,7 +25084,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24153
25084
|
effects: [{ kind: 'merge-by-key', path: 'fieldMetadata[]', key: 'name' }],
|
|
24154
25085
|
validators: ['field-exists'],
|
|
24155
25086
|
affectedPaths: ['fieldMetadata[].readOnly'],
|
|
24156
|
-
submissionImpact:
|
|
25087
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
24157
25088
|
preconditions: ['config-initialized', 'target-exists']
|
|
24158
25089
|
},
|
|
24159
25090
|
{
|
|
@@ -24170,7 +25101,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24170
25101
|
effects: [{ kind: 'merge-by-key', path: 'fieldMetadata[]', key: 'name' }],
|
|
24171
25102
|
validators: ['field-exists'],
|
|
24172
25103
|
affectedPaths: ['fieldMetadata[].disabled'],
|
|
24173
|
-
submissionImpact:
|
|
25104
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
24174
25105
|
preconditions: ['config-initialized', 'target-exists']
|
|
24175
25106
|
},
|
|
24176
25107
|
{
|
|
@@ -24187,7 +25118,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24187
25118
|
effects: [{ kind: 'merge-by-key', path: 'fieldMetadata[]', key: 'name' }],
|
|
24188
25119
|
validators: ['field-exists'],
|
|
24189
25120
|
affectedPaths: ['fieldMetadata[].hidden'],
|
|
24190
|
-
submissionImpact:
|
|
25121
|
+
submissionImpact: 'visual-only',
|
|
24191
25122
|
preconditions: ['config-initialized', 'target-exists']
|
|
24192
25123
|
},
|
|
24193
25124
|
{
|
|
@@ -24206,7 +25137,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24206
25137
|
requiresConfirmation: true,
|
|
24207
25138
|
validators: ['field-exists', 'control-type-compatible'],
|
|
24208
25139
|
affectedPaths: ['fieldMetadata[].controlType'],
|
|
24209
|
-
submissionImpact:
|
|
25140
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
24210
25141
|
preconditions: ['config-initialized', 'target-exists']
|
|
24211
25142
|
},
|
|
24212
25143
|
{
|
|
@@ -24241,7 +25172,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24241
25172
|
effects: [{ kind: 'merge-by-key', path: 'fieldMetadata[]', key: 'name' }],
|
|
24242
25173
|
validators: ['field-exists', 'option-source-valid'],
|
|
24243
25174
|
affectedPaths: ['fieldMetadata[].optionSource'],
|
|
24244
|
-
submissionImpact:
|
|
25175
|
+
submissionImpact: 'affects-remote-binding',
|
|
24245
25176
|
preconditions: ['config-initialized', 'target-exists']
|
|
24246
25177
|
},
|
|
24247
25178
|
// ─── LOCAL FIELD OPERATIONS ───────────────────────────────────────────────
|
|
@@ -24279,7 +25210,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24279
25210
|
effects: [{ kind: 'append-unique', path: 'fieldMetadata[]', key: 'name' }],
|
|
24280
25211
|
validators: ['field-name-unique', 'local-schema-name-no-collision'],
|
|
24281
25212
|
affectedPaths: ['fieldMetadata[]'],
|
|
24282
|
-
submissionImpact:
|
|
25213
|
+
submissionImpact: 'affects-submission',
|
|
24283
25214
|
preconditions: ['config-initialized']
|
|
24284
25215
|
},
|
|
24285
25216
|
{
|
|
@@ -24299,8 +25230,8 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24299
25230
|
kind: 'compile-domain-patch',
|
|
24300
25231
|
handler: 'form-layout-field-cleanup',
|
|
24301
25232
|
handlerContract: {
|
|
24302
|
-
reads: ['fieldMetadata[].name', 'sections[].rows[].columns[].fields'],
|
|
24303
|
-
writes: ['sections[].rows[].columns[].fields'],
|
|
25233
|
+
reads: ['fieldMetadata[].name', 'sections[].rows[].columns[].items', 'sections[].rows[].columns[].fields'],
|
|
25234
|
+
writes: ['sections[].rows[].columns[].items', 'sections[].rows[].columns[].fields'],
|
|
24304
25235
|
identityKeys: ['fieldMetadata[].name', 'sections[].id', 'sections[].rows[].id', 'sections[].rows[].columns[].id'],
|
|
24305
25236
|
inputSchema: { type: 'object', required: ['target.name'], properties: { 'target.name': { type: 'string' } } },
|
|
24306
25237
|
failureModes: ['target-field-not-found', 'target-field-not-local', 'layout-reference-conflict'],
|
|
@@ -24311,8 +25242,8 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24311
25242
|
destructive: true,
|
|
24312
25243
|
requiresConfirmation: true,
|
|
24313
25244
|
validators: ['field-exists', 'field-is-local'],
|
|
24314
|
-
affectedPaths: ['fieldMetadata[]', 'sections[].rows[].columns[].fields'],
|
|
24315
|
-
submissionImpact:
|
|
25245
|
+
affectedPaths: ['fieldMetadata[]', 'sections[].rows[].columns[].items', 'sections[].rows[].columns[].fields'],
|
|
25246
|
+
submissionImpact: 'affects-submission',
|
|
24316
25247
|
preconditions: ['config-initialized', 'target-exists']
|
|
24317
25248
|
},
|
|
24318
25249
|
{
|
|
@@ -24331,7 +25262,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24331
25262
|
effects: [{ kind: 'merge-by-key', path: 'fieldMetadata[]', key: 'name' }],
|
|
24332
25263
|
validators: ['field-exists', 'field-is-local', 'editor-round-trip-preserve'],
|
|
24333
25264
|
affectedPaths: ['fieldMetadata[].submitPolicy'],
|
|
24334
|
-
submissionImpact:
|
|
25265
|
+
submissionImpact: 'affects-submission',
|
|
24335
25266
|
preconditions: ['config-initialized', 'target-exists']
|
|
24336
25267
|
},
|
|
24337
25268
|
// ─── LAYOUT OPERATIONS ────────────────────────────────────────────────────
|
|
@@ -24354,7 +25285,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24354
25285
|
effects: [{ kind: 'append-unique', path: 'sections[]', key: 'id' }],
|
|
24355
25286
|
validators: ['section-id-unique'],
|
|
24356
25287
|
affectedPaths: ['sections[]'],
|
|
24357
|
-
submissionImpact:
|
|
25288
|
+
submissionImpact: 'visual-only',
|
|
24358
25289
|
preconditions: ['config-initialized']
|
|
24359
25290
|
},
|
|
24360
25291
|
{
|
|
@@ -24375,7 +25306,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24375
25306
|
kind: 'compile-domain-patch',
|
|
24376
25307
|
handler: 'form-layout-section-cleanup',
|
|
24377
25308
|
handlerContract: {
|
|
24378
|
-
reads: ['sections[].id', 'sections[].rows[].id', 'sections[].rows[].columns[].id', 'sections[].rows[].columns[].fields'],
|
|
25309
|
+
reads: ['sections[].id', 'sections[].rows[].id', 'sections[].rows[].columns[].id', 'sections[].rows[].columns[].items', 'sections[].rows[].columns[].fields'],
|
|
24379
25310
|
writes: ['sections[]'],
|
|
24380
25311
|
identityKeys: ['sections[].id'],
|
|
24381
25312
|
inputSchema: { type: 'object', required: ['target.id'], properties: { 'target.id': { type: 'string' } } },
|
|
@@ -24387,8 +25318,8 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24387
25318
|
destructive: true,
|
|
24388
25319
|
requiresConfirmation: true,
|
|
24389
25320
|
validators: ['section-exists'],
|
|
24390
|
-
affectedPaths: ['sections[]', 'sections[].rows[]', 'sections[].rows[].columns[]', 'sections[].rows[].columns[].fields'],
|
|
24391
|
-
submissionImpact:
|
|
25321
|
+
affectedPaths: ['sections[]', 'sections[].rows[]', 'sections[].rows[].columns[]', 'sections[].rows[].columns[].items', 'sections[].rows[].columns[].fields'],
|
|
25322
|
+
submissionImpact: 'visual-only',
|
|
24392
25323
|
preconditions: ['config-initialized', 'target-exists']
|
|
24393
25324
|
},
|
|
24394
25325
|
{
|
|
@@ -24408,7 +25339,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24408
25339
|
effects: [{ kind: 'append-unique', path: 'sections[].rows[]', key: 'id' }],
|
|
24409
25340
|
validators: ['section-exists', 'row-id-unique-in-section'],
|
|
24410
25341
|
affectedPaths: ['sections[].rows[]'],
|
|
24411
|
-
submissionImpact:
|
|
25342
|
+
submissionImpact: 'visual-only',
|
|
24412
25343
|
preconditions: ['config-initialized', 'target-exists']
|
|
24413
25344
|
},
|
|
24414
25345
|
{
|
|
@@ -24428,7 +25359,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24428
25359
|
effects: [{ kind: 'append-unique', path: 'sections[].rows[].columns[]', key: 'id' }],
|
|
24429
25360
|
validators: ['row-exists', 'column-id-unique-in-row'],
|
|
24430
25361
|
affectedPaths: ['sections[].rows[].columns[]'],
|
|
24431
|
-
submissionImpact:
|
|
25362
|
+
submissionImpact: 'visual-only',
|
|
24432
25363
|
preconditions: ['config-initialized', 'target-exists']
|
|
24433
25364
|
},
|
|
24434
25365
|
{
|
|
@@ -24456,9 +25387,10 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24456
25387
|
'sections[].id',
|
|
24457
25388
|
'sections[].rows[].id',
|
|
24458
25389
|
'sections[].rows[].columns[].id',
|
|
25390
|
+
'sections[].rows[].columns[].items',
|
|
24459
25391
|
'sections[].rows[].columns[].fields'
|
|
24460
25392
|
],
|
|
24461
|
-
writes: ['sections[].rows[].columns[].fields'],
|
|
25393
|
+
writes: ['sections[].rows[].columns[].items', 'sections[].rows[].columns[].fields'],
|
|
24462
25394
|
identityKeys: ['fieldMetadata[].name', 'sections[].id', 'sections[].rows[].id', 'sections[].rows[].columns[].id'],
|
|
24463
25395
|
inputSchema: {
|
|
24464
25396
|
type: 'object',
|
|
@@ -24476,11 +25408,184 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24476
25408
|
}
|
|
24477
25409
|
}],
|
|
24478
25410
|
validators: ['field-exists', 'layout-target-exists', 'no-index-as-identity', 'field-exists-in-layout'],
|
|
24479
|
-
affectedPaths: ['sections[].rows[].columns[].fields'],
|
|
24480
|
-
submissionImpact:
|
|
25411
|
+
affectedPaths: ['sections[].rows[].columns[].items', 'sections[].rows[].columns[].fields'],
|
|
25412
|
+
submissionImpact: 'visual-only',
|
|
24481
25413
|
preconditions: ['config-initialized', 'target-exists']
|
|
24482
25414
|
},
|
|
24483
25415
|
// ─── RULE OPERATIONS ──────────────────────────────────────────────────────
|
|
25416
|
+
{
|
|
25417
|
+
operationId: 'layout.visualBlock.add',
|
|
25418
|
+
title: 'Adicionar bloco visual',
|
|
25419
|
+
scope: 'column',
|
|
25420
|
+
targetKind: 'column',
|
|
25421
|
+
target: { kind: 'column', resolver: 'column-by-id-in-row', ambiguityPolicy: 'fail', required: true },
|
|
25422
|
+
inputSchema: {
|
|
25423
|
+
type: 'object',
|
|
25424
|
+
required: ['id', 'document'],
|
|
25425
|
+
properties: {
|
|
25426
|
+
id: { type: 'string' },
|
|
25427
|
+
document: {
|
|
25428
|
+
type: 'object',
|
|
25429
|
+
required: ['kind', 'version', 'nodes'],
|
|
25430
|
+
properties: {
|
|
25431
|
+
kind: { const: 'praxis.rich-content' },
|
|
25432
|
+
version: { type: 'string' },
|
|
25433
|
+
nodes: { type: 'array' }
|
|
25434
|
+
}
|
|
25435
|
+
},
|
|
25436
|
+
layout: { enum: ['block', 'inline'], default: 'block' },
|
|
25437
|
+
rootClassName: { type: ['string', 'null'] },
|
|
25438
|
+
index: { type: 'number' }
|
|
25439
|
+
}
|
|
25440
|
+
},
|
|
25441
|
+
effects: [{
|
|
25442
|
+
kind: 'compile-domain-patch',
|
|
25443
|
+
handler: 'form-layout-visual-block-add',
|
|
25444
|
+
handlerContract: {
|
|
25445
|
+
reads: ['sections[].id', 'sections[].rows[].id', 'sections[].rows[].columns[].id', 'sections[].rows[].columns[].items'],
|
|
25446
|
+
writes: ['sections[].rows[].columns[].items'],
|
|
25447
|
+
identityKeys: ['sections[].id', 'sections[].rows[].id', 'sections[].rows[].columns[].id', 'sections[].rows[].columns[].items[].id'],
|
|
25448
|
+
inputSchema: {
|
|
25449
|
+
type: 'object',
|
|
25450
|
+
required: ['target.sectionId', 'target.rowId', 'target.columnId', 'id', 'document'],
|
|
25451
|
+
properties: {
|
|
25452
|
+
'target.sectionId': { type: 'string' },
|
|
25453
|
+
'target.rowId': { type: 'string' },
|
|
25454
|
+
'target.columnId': { type: 'string' },
|
|
25455
|
+
id: { type: 'string' },
|
|
25456
|
+
document: { type: 'object' },
|
|
25457
|
+
layout: { enum: ['block', 'inline'] },
|
|
25458
|
+
rootClassName: { type: ['string', 'null'] },
|
|
25459
|
+
index: { type: 'number' }
|
|
25460
|
+
}
|
|
25461
|
+
},
|
|
25462
|
+
failureModes: ['target-layout-location-not-found', 'duplicate-visual-block-id', 'invalid-rich-content-document'],
|
|
25463
|
+
description: 'Adds a richContent layout item into sections[].rows[].columns[].items[] by stable section, row, and column ids.'
|
|
25464
|
+
}
|
|
25465
|
+
}],
|
|
25466
|
+
validators: ['layout-target-exists', 'visual-block-id-unique', 'rich-content-document-valid'],
|
|
25467
|
+
affectedPaths: ['sections[].rows[].columns[].items'],
|
|
25468
|
+
submissionImpact: 'visual-only',
|
|
25469
|
+
preconditions: ['config-initialized', 'target-exists']
|
|
25470
|
+
},
|
|
25471
|
+
{
|
|
25472
|
+
operationId: 'layout.visualBlock.update',
|
|
25473
|
+
title: 'Atualizar bloco visual',
|
|
25474
|
+
scope: 'layout',
|
|
25475
|
+
targetKind: 'visualBlock',
|
|
25476
|
+
target: { kind: 'visualBlock', resolver: 'layout-item-by-id', ambiguityPolicy: 'fail', required: true },
|
|
25477
|
+
inputSchema: {
|
|
25478
|
+
type: 'object',
|
|
25479
|
+
minProperties: 1,
|
|
25480
|
+
properties: {
|
|
25481
|
+
document: {
|
|
25482
|
+
type: 'object',
|
|
25483
|
+
required: ['kind', 'version', 'nodes'],
|
|
25484
|
+
properties: {
|
|
25485
|
+
kind: { const: 'praxis.rich-content' },
|
|
25486
|
+
version: { type: 'string' },
|
|
25487
|
+
nodes: { type: 'array' }
|
|
25488
|
+
}
|
|
25489
|
+
},
|
|
25490
|
+
layout: { enum: ['block', 'inline'] },
|
|
25491
|
+
rootClassName: { type: ['string', 'null'] }
|
|
25492
|
+
}
|
|
25493
|
+
},
|
|
25494
|
+
effects: [{
|
|
25495
|
+
kind: 'compile-domain-patch',
|
|
25496
|
+
handler: 'form-layout-visual-block-update',
|
|
25497
|
+
handlerContract: {
|
|
25498
|
+
reads: ['sections[].rows[].columns[].items[].id'],
|
|
25499
|
+
writes: ['sections[].rows[].columns[].items'],
|
|
25500
|
+
identityKeys: ['sections[].id', 'sections[].rows[].id', 'sections[].rows[].columns[].id', 'sections[].rows[].columns[].items[].id'],
|
|
25501
|
+
inputSchema: {
|
|
25502
|
+
type: 'object',
|
|
25503
|
+
required: ['target.itemId'],
|
|
25504
|
+
properties: {
|
|
25505
|
+
'target.itemId': { type: 'string' },
|
|
25506
|
+
document: { type: 'object' },
|
|
25507
|
+
layout: { enum: ['block', 'inline'] },
|
|
25508
|
+
rootClassName: { type: ['string', 'null'] }
|
|
25509
|
+
}
|
|
25510
|
+
},
|
|
25511
|
+
failureModes: ['target-visual-block-not-found', 'invalid-rich-content-document'],
|
|
25512
|
+
description: 'Updates a richContent layout item by stable layout item id without touching fieldMetadata or form submit payload.'
|
|
25513
|
+
}
|
|
25514
|
+
}],
|
|
25515
|
+
validators: ['visual-block-exists', 'rich-content-document-valid', 'editor-round-trip-preserve'],
|
|
25516
|
+
affectedPaths: ['sections[].rows[].columns[].items'],
|
|
25517
|
+
submissionImpact: 'visual-only',
|
|
25518
|
+
preconditions: ['config-initialized', 'target-exists']
|
|
25519
|
+
},
|
|
25520
|
+
{
|
|
25521
|
+
operationId: 'layout.visualBlock.move',
|
|
25522
|
+
title: 'Mover bloco visual',
|
|
25523
|
+
scope: 'layout',
|
|
25524
|
+
targetKind: 'visualBlock',
|
|
25525
|
+
target: { kind: 'visualBlock', resolver: 'layout-item-by-id', ambiguityPolicy: 'fail', required: true },
|
|
25526
|
+
inputSchema: {
|
|
25527
|
+
type: 'object',
|
|
25528
|
+
required: ['targetSectionId', 'targetRowId', 'targetColumnId'],
|
|
25529
|
+
properties: {
|
|
25530
|
+
targetSectionId: { type: 'string' },
|
|
25531
|
+
targetRowId: { type: 'string' },
|
|
25532
|
+
targetColumnId: { type: 'string' },
|
|
25533
|
+
index: { type: 'number' }
|
|
25534
|
+
}
|
|
25535
|
+
},
|
|
25536
|
+
effects: [{
|
|
25537
|
+
kind: 'compile-domain-patch',
|
|
25538
|
+
handler: 'form-layout-visual-block-move',
|
|
25539
|
+
handlerContract: {
|
|
25540
|
+
reads: ['sections[].id', 'sections[].rows[].id', 'sections[].rows[].columns[].id', 'sections[].rows[].columns[].items[].id'],
|
|
25541
|
+
writes: ['sections[].rows[].columns[].items'],
|
|
25542
|
+
identityKeys: ['sections[].id', 'sections[].rows[].id', 'sections[].rows[].columns[].id', 'sections[].rows[].columns[].items[].id'],
|
|
25543
|
+
inputSchema: {
|
|
25544
|
+
type: 'object',
|
|
25545
|
+
required: ['target.itemId', 'targetSectionId', 'targetRowId', 'targetColumnId'],
|
|
25546
|
+
properties: {
|
|
25547
|
+
'target.itemId': { type: 'string' },
|
|
25548
|
+
targetSectionId: { type: 'string' },
|
|
25549
|
+
targetRowId: { type: 'string' },
|
|
25550
|
+
targetColumnId: { type: 'string' },
|
|
25551
|
+
index: { type: 'number' }
|
|
25552
|
+
}
|
|
25553
|
+
},
|
|
25554
|
+
failureModes: ['target-visual-block-not-found', 'target-layout-location-not-found', 'ambiguous-visual-block-target'],
|
|
25555
|
+
description: 'Moves a richContent layout item by stable item, section, row, and column ids; index is insertion position only.'
|
|
25556
|
+
}
|
|
25557
|
+
}],
|
|
25558
|
+
validators: ['visual-block-exists', 'layout-target-exists', 'no-index-as-identity'],
|
|
25559
|
+
affectedPaths: ['sections[].rows[].columns[].items'],
|
|
25560
|
+
submissionImpact: 'visual-only',
|
|
25561
|
+
preconditions: ['config-initialized', 'target-exists']
|
|
25562
|
+
},
|
|
25563
|
+
{
|
|
25564
|
+
operationId: 'layout.visualBlock.remove',
|
|
25565
|
+
title: 'Remover bloco visual',
|
|
25566
|
+
scope: 'layout',
|
|
25567
|
+
targetKind: 'visualBlock',
|
|
25568
|
+
target: { kind: 'visualBlock', resolver: 'layout-item-by-id', ambiguityPolicy: 'fail', required: true },
|
|
25569
|
+
inputSchema: { type: 'object', properties: {} },
|
|
25570
|
+
effects: [{
|
|
25571
|
+
kind: 'compile-domain-patch',
|
|
25572
|
+
handler: 'form-layout-visual-block-remove',
|
|
25573
|
+
handlerContract: {
|
|
25574
|
+
reads: ['sections[].rows[].columns[].items[].id'],
|
|
25575
|
+
writes: ['sections[].rows[].columns[].items'],
|
|
25576
|
+
identityKeys: ['sections[].id', 'sections[].rows[].id', 'sections[].rows[].columns[].id', 'sections[].rows[].columns[].items[].id'],
|
|
25577
|
+
inputSchema: { type: 'object', required: ['target.itemId'], properties: { 'target.itemId': { type: 'string' } } },
|
|
25578
|
+
failureModes: ['target-visual-block-not-found', 'ambiguous-visual-block-target'],
|
|
25579
|
+
description: 'Removes a richContent layout item from sections[].rows[].columns[].items[] without touching fieldMetadata or form submit payload.'
|
|
25580
|
+
}
|
|
25581
|
+
}],
|
|
25582
|
+
destructive: true,
|
|
25583
|
+
requiresConfirmation: true,
|
|
25584
|
+
validators: ['visual-block-exists'],
|
|
25585
|
+
affectedPaths: ['sections[].rows[].columns[].items'],
|
|
25586
|
+
submissionImpact: 'visual-only',
|
|
25587
|
+
preconditions: ['config-initialized', 'target-exists']
|
|
25588
|
+
},
|
|
24484
25589
|
{
|
|
24485
25590
|
operationId: 'rule.visibility.add',
|
|
24486
25591
|
title: 'Adicionar regra de visibilidade',
|
|
@@ -24503,7 +25608,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24503
25608
|
effects: [{ kind: 'append-unique', path: 'formRules[]', key: 'id' }],
|
|
24504
25609
|
validators: ['rule-id-unique', 'rule-target-refs-exist', 'json-logic-valid'],
|
|
24505
25610
|
affectedPaths: ['formRules[]'],
|
|
24506
|
-
submissionImpact:
|
|
25611
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
24507
25612
|
preconditions: ['config-initialized']
|
|
24508
25613
|
},
|
|
24509
25614
|
{
|
|
@@ -24534,7 +25639,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24534
25639
|
effects: [{ kind: 'append-unique', path: 'formRules[]', key: 'id' }],
|
|
24535
25640
|
validators: ['rule-id-unique', 'rule-target-refs-exist', 'json-logic-valid'],
|
|
24536
25641
|
affectedPaths: ['formRules[]'],
|
|
24537
|
-
submissionImpact:
|
|
25642
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
24538
25643
|
preconditions: ['config-initialized']
|
|
24539
25644
|
},
|
|
24540
25645
|
{
|
|
@@ -24549,7 +25654,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24549
25654
|
requiresConfirmation: true,
|
|
24550
25655
|
validators: ['rule-exists'],
|
|
24551
25656
|
affectedPaths: ['formRules[]'],
|
|
24552
|
-
submissionImpact:
|
|
25657
|
+
submissionImpact: 'affects-schema-backed-data',
|
|
24553
25658
|
preconditions: ['config-initialized', 'target-exists']
|
|
24554
25659
|
},
|
|
24555
25660
|
// ─── ACTION OPERATIONS ────────────────────────────────────────────────────
|
|
@@ -24572,7 +25677,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24572
25677
|
effects: [{ kind: 'merge-object', path: 'actions.submit' }],
|
|
24573
25678
|
validators: ['editor-round-trip-preserve'],
|
|
24574
25679
|
affectedPaths: ['actions.submit'],
|
|
24575
|
-
submissionImpact:
|
|
25680
|
+
submissionImpact: 'affects-submission',
|
|
24576
25681
|
preconditions: ['config-initialized']
|
|
24577
25682
|
},
|
|
24578
25683
|
{
|
|
@@ -24595,7 +25700,7 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24595
25700
|
effects: [{ kind: 'merge-object', path: 'actions.cancel' }],
|
|
24596
25701
|
validators: ['editor-round-trip-preserve'],
|
|
24597
25702
|
affectedPaths: ['actions.cancel'],
|
|
24598
|
-
submissionImpact:
|
|
25703
|
+
submissionImpact: 'config-only',
|
|
24599
25704
|
preconditions: ['config-initialized']
|
|
24600
25705
|
},
|
|
24601
25706
|
{
|
|
@@ -24618,9 +25723,9 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24618
25723
|
effects: [{ kind: 'merge-object', path: 'actions.reset' }],
|
|
24619
25724
|
validators: ['editor-round-trip-preserve'],
|
|
24620
25725
|
affectedPaths: ['actions.reset'],
|
|
24621
|
-
submissionImpact:
|
|
25726
|
+
submissionImpact: 'config-only',
|
|
24622
25727
|
preconditions: ['config-initialized']
|
|
24623
|
-
}
|
|
25728
|
+
},
|
|
24624
25729
|
],
|
|
24625
25730
|
validators: [
|
|
24626
25731
|
{
|
|
@@ -24736,12 +25841,31 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24736
25841
|
level: 'error',
|
|
24737
25842
|
code: 'DF019',
|
|
24738
25843
|
description: 'Edição não deve corromper propriedades críticas para o round-trip do editor. Aplicado após operações que afetam submitPolicy ou source de campos locais.'
|
|
25844
|
+
},
|
|
25845
|
+
{
|
|
25846
|
+
validatorId: 'visual-block-exists',
|
|
25847
|
+
level: 'error',
|
|
25848
|
+
code: 'DF020',
|
|
25849
|
+
description: 'O bloco visual alvo deve existir como item kind:"richContent" em sections[].rows[].columns[].items[].'
|
|
25850
|
+
},
|
|
25851
|
+
{
|
|
25852
|
+
validatorId: 'visual-block-id-unique',
|
|
25853
|
+
level: 'error',
|
|
25854
|
+
code: 'DF021',
|
|
25855
|
+
description: 'IDs de blocos visuais devem ser unicos entre os itens de layout do formulario.'
|
|
25856
|
+
},
|
|
25857
|
+
{
|
|
25858
|
+
validatorId: 'rich-content-document-valid',
|
|
25859
|
+
level: 'error',
|
|
25860
|
+
code: 'DF022',
|
|
25861
|
+
description: 'O document do bloco visual deve seguir o contrato RichContentDocument canonico.'
|
|
24739
25862
|
}
|
|
24740
25863
|
],
|
|
24741
25864
|
roundTripRequirements: [
|
|
24742
25865
|
'strip-undefined',
|
|
24743
25866
|
'normalize-json-logic',
|
|
24744
25867
|
'stable-field-order',
|
|
25868
|
+
'preserve-column-layout-items',
|
|
24745
25869
|
'preserve-local-field-source',
|
|
24746
25870
|
'preserve-section-row-column-ids'
|
|
24747
25871
|
],
|
|
@@ -24776,6 +25900,30 @@ const PRAXIS_DYNAMIC_FORM_AUTHORING_MANIFEST = {
|
|
|
24776
25900
|
params: { targetSectionId: 'secao-contato', targetRowId: 'row-1', targetColumnId: 'col-1' },
|
|
24777
25901
|
isPositive: true
|
|
24778
25902
|
},
|
|
25903
|
+
{
|
|
25904
|
+
id: 'add-visual-block',
|
|
25905
|
+
request: 'Adicionar um aviso visual antes dos campos de contato',
|
|
25906
|
+
operationId: 'layout.visualBlock.add',
|
|
25907
|
+
target: 'col-contato',
|
|
25908
|
+
params: {
|
|
25909
|
+
id: 'aviso-contato',
|
|
25910
|
+
document: {
|
|
25911
|
+
kind: 'praxis.rich-content',
|
|
25912
|
+
version: '1.0.0',
|
|
25913
|
+
nodes: [{ type: 'text', text: 'Confira os dados antes de salvar.' }]
|
|
25914
|
+
},
|
|
25915
|
+
layout: 'block'
|
|
25916
|
+
},
|
|
25917
|
+
isPositive: true
|
|
25918
|
+
},
|
|
25919
|
+
{
|
|
25920
|
+
id: 'move-visual-block',
|
|
25921
|
+
request: 'Mover o aviso visual para a segunda coluna da secao de contato',
|
|
25922
|
+
operationId: 'layout.visualBlock.move',
|
|
25923
|
+
target: 'aviso-contato',
|
|
25924
|
+
params: { targetSectionId: 'secao-contato', targetRowId: 'row-1', targetColumnId: 'col-2' },
|
|
25925
|
+
isPositive: true
|
|
25926
|
+
},
|
|
24779
25927
|
{
|
|
24780
25928
|
id: 'add-visibility-rule',
|
|
24781
25929
|
request: 'Ocultar o campo cpf quando o tipo de pessoa for jurídica',
|